Skip to content

Commit

Permalink
test written using akka testing framework for actor message 🔧
Browse files Browse the repository at this point in the history
  • Loading branch information
Kaushal1011 committed Apr 22, 2024
1 parent 3484b2d commit d5b7b96
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 36 deletions.
4 changes: 0 additions & 4 deletions src/main/scala/com/distcomp/mutex/AgrawalElAbbadi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,6 @@ object AgrawalElAbbadi {
newQuorumQueue.head ! PermissionRequest(context.self)
active(context.self.path.name, parent, tree, simulator, failureDetector, timestamp, failedNodes, heartbeatRunner, permissionGivenTo, newQuorumQueue)

case null :: null :: Nil=> // No children, empty or "null" children
context.self ! EnterCriticalSection
active(context.self.path.name, parent, tree, simulator, failureDetector, timestamp, failedNodes, heartbeatRunner, permissionGivenTo, List.empty)

case null => // Should not occur, but safe
context.self ! EnterCriticalSection
active(context.self.path.name, parent, tree, simulator, failureDetector, timestamp, failedNodes, heartbeatRunner, permissionGivenTo, List.empty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ object TestAndSetSharedMemActor {
case ReadLockRequest(from) =>
from ! ReadLockResponse(context.self, bool)
Behaviors.same
case _ =>
Behaviors.same
}

}
Expand Down
18 changes: 18 additions & 0 deletions src/test/resources/mutex/AgarAbbadiPlan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"steps": [
{
"dotFilePath": "ExampleNetwork.dot",
"isDirected": false,
"createRing": false,
"createClique": false,
"createBinTree": true,
"enableFailureDetector": true,
"algorithm": "agrawal-elabbadi",
"additionalParameters": {
"initiators": 7,
"additional": 0,
"kill": 1
}
}
]
}
88 changes: 88 additions & 0 deletions src/test/scala/com/distcomp/mutex/AgarwalElAbbadiTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.distcomp.mutex

import akka.actor.testkit.typed.scaladsl.ActorTestKit
import com.distcomp.utils.LoggingTestUtils._
import com.distcomp.utils.SimSetup
import com.typesafe.config.{Config, ConfigFactory}
import org.scalatest.wordspec.AnyWordSpecLike

import java.io.PrintWriter


class AgarwalElAbbadiTest extends AnyWordSpecLike {
val config: Config = ConfigFactory.load("logback-test")
val testKit: ActorTestKit = ActorTestKit("MyTestSystem", config)

val clearTests: Unit = new PrintWriter("test-logs.txt").close()
val mutexTestFile: String = getClass.getResource("/mutex/AgarAbbadiPlan.json").getPath

val initiators: Int = SimSetup.getInitiators(mutexTestFile)

// We will initialize logs once and use it across different tests
lazy val logs: List[String] = SimSetup(mutexTestFile)

def afterAll(): Unit = {
testKit.shutdownTestKit()
}

"A simulation" should {
"finish in time and extract logs" in {
// Check if logs are extracted correctly by verifying non-empty and specific content
assert(logs.nonEmpty, "Log file should not be empty")
}

"have all nodes ready message in logs" in {
// Directly use logs which will be lazily evaluated the first time they are accessed
assert(logs.exists(_.contains("All nodes are ready")), "Logs should contain a ready message")
}

"have initialisation message in logs" in {
// Directly use logs which will be lazily evaluated the first time they are accessed
assert(logs.exists(_.contains("Setting edges for")), "Logs should contain an initialisation message")
}

"have failure detector initiated with all heartbeats" in {
assert(logs.exists(_.contains("Received initial heartbeats from all nodes, starting periodic failure check.")), "Logs should contain a message indicating that the failure detector has been initiated with all heartbeats")
}

"have nodes in binary tree topology" in {
assert(logs.exists(_.contains("Binary Tree Network Topology (Comlete)")), "Logs should contain a message indicating that the nodes are in a binary tree topology")
}

"have permission grant logs" in {
assert(logs.exists(_.contains("has granted permission")), "Logs should contain a message indicating that permission has been granted")
}

"have permission denied logs" in {
assert(logs.exists(_.contains("has been denied permission")), "Logs should contain a message indicating that permission has been denied")
}

"have permission request logs" in {
assert(logs.exists(_.contains("requesting permission")), "Logs should contain a message indicating that permission has been requested")
}

"have nodes releasing critical section" in {
assert(logs.exists(_.contains("released critical section")), "Logs should contain a message indicating that a node has released the critical section")
}

"have the correct number of initiators" in {
val initiatorCounts =getInitiatorCounts(logs)

assert(initiatorCounts == initiators, "Initiator counts should match")
}

"have the correct nodes entering and exiting" in {
val (initiators, enters, exits) = extractInitiatorsEntersAndExits(logs)

assert(initiators == enters, "Initiators should match enters")
assert(initiators == exits, "Initiators should match exits")
}

"have the same node exiting and entering" in {
assert(verifyExitFollowedByEnterSameNode(logs), "Node should exit and enter in the same order")
}


}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//#full-example
package com.distcomp.sharedmemory

import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
import com.distcomp.common.Message
import com.distcomp.common.PetersonTwoProcess._
import com.distcomp.common.PetersonTwoProcess.ReadFlagAndTurnReply
import org.scalatest.wordspec.AnyWordSpecLike
import com.distcomp.utils.DummyNodeActor

//#definition
class PetersonTwoProcessSMTest extends ScalaTestWithActorTestKit with AnyWordSpecLike {
//#definition



"A PetersonTwoProcSharedMemoryActor" must {
val replyProbe = createTestProbe[Message]()

val nodeIds: List[Int] = List(1,2)

val nodeSet = nodeIds.map(id => spawn(DummyNodeActor(), s"Dummy Node $id")).toSet

val underTest = spawn(PetersonSharedMemActor(nodeSet))

//#test
"must reply on read flag and turn" in {
underTest ! ReadFlagAndTurn(replyProbe.ref, nodeSet.head)
replyProbe.expectMessage(ReadFlagAndTurnReply(false, None))
}

"must set flag and turn for a node" in {
underTest ! SetFlag(nodeSet.head, true)
underTest ! SetTurn(nodeSet.head)
underTest ! ReadFlagAndTurn(replyProbe.ref, nodeSet.head)

replyProbe.expectMessage(ReadFlagAndTurnReply(true, Some(nodeSet.head)))


}



//#test
}

}
//#full-example
14 changes: 14 additions & 0 deletions src/test/scala/com/distcomp/utils/DummyNodeActor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.distcomp.utils
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.Behaviors
import com.distcomp.common.Message

object DummyNodeActor {

def apply(): Behavior[Message] = {
Behaviors.receiveMessage {
case _ =>
Behaviors.same
}
}
}
16 changes: 8 additions & 8 deletions src/test/scala/com/distcomp/utils/LoggingTestUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ object LoggingTestUtils {
val initiatorCounts = logs
.filter(_.contains("starting critical section request"))

println(s"${initiatorCounts}")
// println(s"${initiatorCounts}")

println(s"Initiator counts: ${initiatorCounts.length}")
// println(s"Initiator counts: ${initiatorCounts.length}")

initiatorCounts.length
}
Expand All @@ -24,19 +24,19 @@ object LoggingTestUtils {
.filter(_.contains("starting critical section request"))
.map(extractNodeName).toSet

println(s"Initiators: ${initiators}")
// println(s"Initiators: ${initiators}")

val enters = logs
.filter(_.contains("entering critical section"))
.map(extractNodeName).toSet

println(s"Enters: ${enters}")
// println(s"Enters: ${enters}")

val exits = logs
.filter(_.contains("exiting critical section"))
.map(extractNodeName).toSet

println(s"Exits: ${exits}")
// println(s"Exits: ${exits}")

(initiators, enters, exits)
}
Expand All @@ -47,17 +47,17 @@ object LoggingTestUtils {
.map(extractNodeName)


println(s"Enters: ${enters}")
// println(s"Enters: ${enters}")

val exits = logs
.filter(_.contains("exiting critical section"))
.map(extractNodeName)

println(s"Exits: ${exits}")
// println(s"Exits: ${exits}")

val enterExitPairs = enters.zip(exits)

println(s"Enter exit pairs: ${enterExitPairs}")
// println(s"Enter exit pairs: ${enterExitPairs}")

enterExitPairs.forall{ case (enter, exit) => enter == exit }
}
Expand Down

0 comments on commit d5b7b96

Please sign in to comment.