diff --git a/README.md b/README.md index 2e29896..1219df9 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,11 @@ Install scala, sbt, and java-17 - Uses a custom actor for maintianing shared memory (Peterson Tournament Shared Mem Actor) - Bakery Algorithm - Uses a custom actor for maintianing shared memory (Bakery Shared Mem Actor) - - TODO: if node is already requesting, then it should not be able to request again - +- Test and Set Lock Algorithm + - Uses a custom actor for maintianing shared memory (Test and Set Shared Mem Actor) +- Test and Test and Set Lock Algorithm + - Uses a custom actor for maintianing shared memory (Test and Test and Set Shared Mem Actor) + ### [Simulation Plan](./mutexsimplan.json) 1. Ricart Agarwal @@ -47,9 +50,17 @@ Install scala, sbt, and java-17 6. Peterson's Algorithm (Tournament for N Processes) 8 Processes 7. Peterson's Algorithm (Two Process) 8. Bakery Algorithm +9. Test and Set Lock Algorithm +10. Test and Test and Set Lock Algorithm + ## Telemetry ### [Mutex](./mutexsimplan.json) -![Mutex Telemetry](./assets/mutexsimplanrun.png) \ No newline at end of file +![Mutex Telemetry](./assets/mutexsimplanrun.png) + +## Testing + +- Test cases for all algorithms (Integration Testing Based on Log Analysis). Directory [`src/test/scala/com/distcomp/mutex`](src/test/scala/com/distcomp/mutex). +- Test cases for Shared Memory Actors (Unit Testing checks for correctness of shared memory) Directory [`src/test/scala/com/distcomp/sharedmemory`](src/test/scala/com/distcomp/sharedmemory). \ No newline at end of file diff --git a/assets/mutextests.png b/assets/mutextests.png new file mode 100644 index 0000000..02060ca Binary files /dev/null and b/assets/mutextests.png differ diff --git a/mutexsimplan.json b/mutexsimplan.json index d64e7bc..9f943b9 100644 --- a/mutexsimplan.json +++ b/mutexsimplan.json @@ -109,6 +109,33 @@ "additional": 0, "kill": 1 } + }, + { + "dotFilePath": "ExampleNetwork.dot", + "isDirected": true, + "createRing": true, + "createClique": false, + "createBinTree": false, + "enableFailureDetector": false, + "algorithm": "test-and-set", + "additionalParameters": { + "initiators": 5, + "additional": 0, + "kill": 1 + } + },{ + "dotFilePath": "ExampleNetwork.dot", + "isDirected": true, + "createRing": true, + "createClique": false, + "createBinTree": false, + "enableFailureDetector": false, + "algorithm": "test-and-test-and-set", + "additionalParameters": { + "initiators": 5, + "additional": 0, + "kill": 1 + } } ] } diff --git a/src/test/scala/com/distcomp/AkkaQuickstartSpec.scala b/src/test/scala/com/distcomp/AkkaQuickstartSpec.scala deleted file mode 100644 index 100056c..0000000 --- a/src/test/scala/com/distcomp/AkkaQuickstartSpec.scala +++ /dev/null @@ -1,25 +0,0 @@ -////#full-example -//package com.distcomp -// -//import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit -//import com.distcomp.Greeter.Greet -//import com.distcomp.Greeter.Greeted -//import org.scalatest.wordspec.AnyWordSpecLike -// -////#definition -//class AkkaQuickstartSpec extends ScalaTestWithActorTestKit with AnyWordSpecLike { -////#definition -// -// "A Greeter" must { -// //#test -// "reply to greeted" in { -// val replyProbe = createTestProbe[Greeted]() -// val underTest = spawn(Greeter()) -// underTest ! Greet("Santa", replyProbe.ref) -// replyProbe.expectMessage(Greeted("Santa", underTest.ref)) -// } -// //#test -// } -// -//} -////#full-example diff --git a/src/test/scala/com/distcomp/sharedmemory/BakerySMTest.scala b/src/test/scala/com/distcomp/sharedmemory/BakerySMTest.scala new file mode 100644 index 0000000..c652c75 --- /dev/null +++ b/src/test/scala/com/distcomp/sharedmemory/BakerySMTest.scala @@ -0,0 +1,52 @@ +//#full-example +package com.distcomp.sharedmemory + +import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit +import com.distcomp.common.BakeryProtocol._ +import com.distcomp.common.Message +import com.distcomp.utils.DummyNodeActor +import org.scalatest.wordspec.AnyWordSpecLike + +//#definition +class BakerySMTest extends ScalaTestWithActorTestKit with AnyWordSpecLike { +//#definition + + "A BakerySharedMemoryActor" must { + val replyProbe = createTestProbe[Message]() + + val nodeIds: List[Int] = List(1,2,3,4,5,6) + + val nodeSet = nodeIds.map(id => spawn(DummyNodeActor(), s"Dummy Node $id")).toSet + + val finalSet = nodeSet + replyProbe.ref + + val underTest = spawn(BakerySharedMemActor(finalSet)) + + //#test + "must read numbers successfully" in { + underTest ! ReadNumbers(replyProbe.ref) + replyProbe.expectMessage(ReadNumbersReply(finalSet.map(node => node -> 0).toMap)) + } + + "must set choosing, numbers and read responses properly" in { + underTest ! SetChoosing(replyProbe.ref, true) + + replyProbe.expectMessage(SetChoosingReply(true)) + + underTest ! SetNumber(replyProbe.ref, 3) + + underTest ! GetChoosingAndNumber(replyProbe.ref) + + val choosingBefore = finalSet.map(node => node -> false).toMap + val numbersBefore = finalSet.map(node => node -> 0).toMap + + val choosingAfter = choosingBefore.updated(replyProbe.ref, true) + val numbersAfter = numbersBefore.updated(replyProbe.ref, 3) + + replyProbe.expectMessage(GetChoosingAndNumberReply(choosingAfter, numbersAfter)) + + } + //#test + } +} +//#full-example diff --git a/src/test/scala/com/distcomp/sharedmemory/PetersonTournamentSMTest.scala b/src/test/scala/com/distcomp/sharedmemory/PetersonTournamentSMTest.scala new file mode 100644 index 0000000..50b4bde --- /dev/null +++ b/src/test/scala/com/distcomp/sharedmemory/PetersonTournamentSMTest.scala @@ -0,0 +1,41 @@ +//#full-example +package com.distcomp.sharedmemory + +import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit +import com.distcomp.common.Message +import com.distcomp.common.PetersonTournamentProtocol._ +import com.distcomp.utils.DummyNodeActor +import org.scalatest.wordspec.AnyWordSpecLike + +//#definition +class PetersonTournamentSMTest extends ScalaTestWithActorTestKit with AnyWordSpecLike { +//#definition + + "A PetersonTournamentSharedMemoryActor" must { + val replyProbe = createTestProbe[Message]() + + val nodeIds: List[Int] = List(1,2,3,4,5,6) + + val nodeSet = nodeIds.map(id => spawn(DummyNodeActor(), s"Dummy Node $id")).toSet + + val underTest = spawn(PetersonTournamentSharedMemActor(nodeSet)) + + //#test + "must reply on read flag and turn" in { + underTest ! ReadFlagAndTurnTournament(replyProbe.ref, 3, 0) + replyProbe.expectMessage(ReadFlagAndTurnTournamentReply(false, -1, 3)) + } + + "must set flag and turn for a node" in { + underTest ! SetFlagTournament(3,0, true) + underTest ! SetTurnTournament(3,0) + underTest ! ReadFlagAndTurnTournament(replyProbe.ref, 3, 0) + + replyProbe.expectMessage(ReadFlagAndTurnTournamentReply(true, 0, 3)) + + + } + //#test + } +} +//#full-example diff --git a/src/test/scala/com/distcomp/sharedmemory/TASSMTest.scala b/src/test/scala/com/distcomp/sharedmemory/TASSMTest.scala new file mode 100644 index 0000000..e3eb9a9 --- /dev/null +++ b/src/test/scala/com/distcomp/sharedmemory/TASSMTest.scala @@ -0,0 +1,49 @@ +//#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.TestAndSetSharedMemProtocol.{ReadLockRequest, ReadLockResponse, SetLockRequest, SetLockResponse, UnlockRequest} +import com.distcomp.utils.DummyNodeActor +import org.scalatest.wordspec.AnyWordSpecLike + +//#definition +class TASSMTest extends ScalaTestWithActorTestKit with AnyWordSpecLike { +//#definition + + + + "A TestAndSetSharedMemoryActor" must { + val replyProbe = createTestProbe[Message]() + + val underTest = spawn(TestAndSetSharedMemActor()) + + //#test + "must read lock request properly" in { + underTest ! ReadLockRequest(replyProbe.ref) + replyProbe.expectMessage(ReadLockResponse(underTest,false)) + } + + "must set lock properly" in { + underTest ! SetLockRequest(replyProbe.ref) + // lock was false, so the response should be false but lock is set to true + replyProbe.expectMessage(SetLockResponse(false)) + + underTest ! ReadLockRequest(replyProbe.ref) + replyProbe.expectMessage(ReadLockResponse(underTest,true)) + } + + "must unlock and read lock request properly" in { + underTest ! UnlockRequest + underTest ! ReadLockRequest(replyProbe.ref) + replyProbe.expectMessage(ReadLockResponse(underTest,false)) + } + + + + //#test + } + +} +//#full-example