From 08af8055177397f2e211f38ad735edc379211d2f Mon Sep 17 00:00:00 2001 From: Kaushal <50149591+Kaushal1011@users.noreply.github.com> Date: Sun, 21 Apr 2024 21:33:02 -0500 Subject: [PATCH] mutex algo simulations and tests done :tada: :white_check_mark: :chart_with_upwards_trend: --- README.md | 17 +++++- assets/mutextests.png | Bin 0 -> 36660 bytes mutexsimplan.json | 27 +++++++++ .../com/distcomp/AkkaQuickstartSpec.scala | 25 --------- .../distcomp/sharedmemory/BakerySMTest.scala | 52 ++++++++++++++++++ .../PetersonTournamentSMTest.scala | 41 ++++++++++++++ .../com/distcomp/sharedmemory/TASSMTest.scala | 49 +++++++++++++++++ 7 files changed, 183 insertions(+), 28 deletions(-) create mode 100644 assets/mutextests.png delete mode 100644 src/test/scala/com/distcomp/AkkaQuickstartSpec.scala create mode 100644 src/test/scala/com/distcomp/sharedmemory/BakerySMTest.scala create mode 100644 src/test/scala/com/distcomp/sharedmemory/PetersonTournamentSMTest.scala create mode 100644 src/test/scala/com/distcomp/sharedmemory/TASSMTest.scala 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 0000000000000000000000000000000000000000..02060cabdabcc20d6947e7fc03eccb03769075c5 GIT binary patch literal 36660 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 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