From a2c2e9faf68aab5fb89e1ce4872d16e09a1f39fa Mon Sep 17 00:00:00 2001 From: Jaime Freire <5436581+jaimefreire@users.noreply.github.com> Date: Wed, 3 Jan 2024 18:41:25 +0100 Subject: [PATCH] Tests, fixes; working version --- .../chat/participant/Participant.java | 80 ++++++++++++------- .../chat/participant/ParticipantProtocol.java | 4 + .../social_altruism/chat/potroom/PotRoom.java | 7 +- .../chat/potroom/SessionProtocol.java | 19 +++-- src/main/resources/log4j.xml | 2 +- .../chat/CaseStudiesTests.java | 58 ++++++++++++++ ...QuickStartTest.java => ProtocolTests.java} | 48 ++++++++--- 7 files changed, 166 insertions(+), 52 deletions(-) create mode 100644 src/test/java/dev/freireservices/social_altruism/chat/CaseStudiesTests.java rename src/test/java/dev/freireservices/social_altruism/chat/{PotQuickStartTest.java => ProtocolTests.java} (68%) diff --git a/src/main/java/dev/freireservices/social_altruism/chat/participant/Participant.java b/src/main/java/dev/freireservices/social_altruism/chat/participant/Participant.java index 4ecd0f4..e2bf7fe 100644 --- a/src/main/java/dev/freireservices/social_altruism/chat/participant/Participant.java +++ b/src/main/java/dev/freireservices/social_altruism/chat/participant/Participant.java @@ -12,8 +12,8 @@ import lombok.Getter; import lombok.Setter; import java.security.SecureRandom; +import java.time.Duration; import java.util.List; -import java.util.concurrent.TimeUnit; import static dev.freireservices.social_altruism.chat.participant.ParticipantType.JUSTICIERO; import static dev.freireservices.social_altruism.chat.participant.ParticipantType.SANTO; @@ -59,23 +59,48 @@ public class Participant { } private Behavior behavior() { + return uninitialized(); + } + + private Behavior uninitialized() { return Behaviors.receive(ParticipantMessage.class) - .onMessage(SessionStarted.class, this::onSessionStarted) .onMessage(SessionDenied.class, this::onSessionDenied) - .onMessage(SessionGranted.class, this::onSessionGranted) + .onMessage(SessionGranted.class, x -> + { + onSessionGranted(x); + return readyToStart(); + }) + .build(); + } + + private Behavior readyToStart() { + return Behaviors.receive(ParticipantMessage.class) + .onMessage(SessionStarted.class, + x -> { + onSessionStarted(x); + return started(); + } + ) + .build(); + } + + private Behavior started() { + return Behaviors.receive(ParticipantMessage.class) .onMessage(PotReturned.class, this::onPotReturned) .onMessage(SessionEnded.class, this::onSessionEnded) .build(); } + private Behavior onSessionEnded(SessionEnded sessionEnded) { context.getLog().info("Session ended for user {}", context.getSelf().path().name()); - try { - TimeUnit.SECONDS.sleep(1); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + + context.getLog().info("Session ended for user: Stats: {}. Earned {} coins, profit {} %" + , context.getSelf().path().name() + , getParticipantCoins() - getInitialCoins() + , (getParticipantCoins() - getInitialCoins()) + ); return Behaviors.stopped(); } @@ -85,32 +110,33 @@ public class Participant { return Behaviors.stopped(); } - private Behavior onSessionGranted( + private void onSessionGranted( SessionGranted message) { + context.getLog().info("Session granted message received for {} ", context.getSelf().path().name()); setChatRoom(message.chatRoom()); setSession(message.session()); - return Behaviors.same(); } - private Behavior onSessionStarted( + private void onSessionStarted( SessionStarted startSession) { + context.getLog().info("Session started for {} with {} participants", context.getSelf().path().name(), startSession.participants().size()); resetCurrentTurn(); setParticipants(startSession.participants()); setTotalTurns(startSession.totalTurns()); - playTurn(startSession.replyTo()); - context.getLog().info("Session started for {} with {} participants", context.getSelf().path().name(), startSession.participants().size()); - return Behaviors.same(); + playTurnWithSmallDelay(startSession.replyTo()); } - private void playTurn(ActorRef replyTo) { + private void playTurnWithSmallDelay(ActorRef replyTo) { if (getParticipantCoins() > 0 && getCurrentTurn() < getTotalTurns()) { - replyTo.tell(new SessionProtocol.PlayTurn( + context.scheduleOnce(Duration.ofSeconds(5), replyTo, - context.getSelf(), - participants, - getCurrentTurn(), - getParticipationForCurrentTurn() - )); + new SessionProtocol.PlayTurn( + replyTo, + context.getSelf(), + participants, + getCurrentTurn(), + getParticipationForCurrentTurn()) + ); } } @@ -141,12 +167,7 @@ public class Participant { // Still game? if (getParticipantCoins() > 1) { - try { - TimeUnit.SECONDS.sleep(5); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - playTurn(potReturned.session()); + playTurnWithSmallDelay(potReturned.session()); } else { context .getLog() @@ -160,7 +181,10 @@ public class Participant { context.getLog().info("END GAME"); context.getLog().info("---------"); context.getLog().info("END GAME"); - return Behaviors.stopped(); + + context.stop(context.getSelf()); + Behaviors.stopped(); + } adjustBehaviour(potReturned); return Behaviors.same(); diff --git a/src/main/java/dev/freireservices/social_altruism/chat/participant/ParticipantProtocol.java b/src/main/java/dev/freireservices/social_altruism/chat/participant/ParticipantProtocol.java index 7db134e..2981c01 100644 --- a/src/main/java/dev/freireservices/social_altruism/chat/participant/ParticipantProtocol.java +++ b/src/main/java/dev/freireservices/social_altruism/chat/participant/ParticipantProtocol.java @@ -10,6 +10,10 @@ public class ParticipantProtocol { public interface ParticipantMessage { } + enum Timeout implements ParticipantMessage { + INSTANCE + } + public record SessionGranted( ActorRef chatRoom, ActorRef session diff --git a/src/main/java/dev/freireservices/social_altruism/chat/potroom/PotRoom.java b/src/main/java/dev/freireservices/social_altruism/chat/potroom/PotRoom.java index 78b4783..98aa831 100644 --- a/src/main/java/dev/freireservices/social_altruism/chat/potroom/PotRoom.java +++ b/src/main/java/dev/freireservices/social_altruism/chat/potroom/PotRoom.java @@ -4,7 +4,6 @@ import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.Behaviors; -import dev.freireservices.social_altruism.chat.participant.ParticipantProtocol.*; import dev.freireservices.social_altruism.chat.potroom.PotRoomProtocol.EnterPot; import dev.freireservices.social_altruism.chat.potroom.PotRoomProtocol.PotRoomMessage; import dev.freireservices.social_altruism.chat.potroom.SessionProtocol.SessionMessage; @@ -54,9 +53,10 @@ public class PotRoom { Session.create(participants, totalTurns), URLEncoder.encode(enterPot.replyTo().path().name(), UTF_8)); - participant.tell(new SessionGranted(chatRoom, session.narrow())); // Communicate session start and share pot info with all participants + //Fishy, probably could spare one.. + participants.forEach(p -> p.tell(new SessionGranted(chatRoom, session.narrow()))); participants.forEach(p -> p.tell(new SessionStarted(chatRoom, session, participants, totalTurns))); return createPotBehaviour(chatRoom); @@ -89,6 +89,7 @@ public class PotRoom { public static Behavior create(int numberOfParticipants, int totalTurns) { return Behaviors.setup( - ctx -> new PotRoom(ctx, numberOfParticipants, totalTurns).createPotBehaviour(ctx.getSelf())); + ctx -> new PotRoom(ctx, numberOfParticipants, totalTurns) + .createPotBehaviour(ctx.getSelf())); } } diff --git a/src/main/java/dev/freireservices/social_altruism/chat/potroom/SessionProtocol.java b/src/main/java/dev/freireservices/social_altruism/chat/potroom/SessionProtocol.java index 99d398a..00253d3 100644 --- a/src/main/java/dev/freireservices/social_altruism/chat/potroom/SessionProtocol.java +++ b/src/main/java/dev/freireservices/social_altruism/chat/potroom/SessionProtocol.java @@ -20,16 +20,6 @@ public class SessionProtocol { implements SessionMessage { } - public record ShareReturnPotWithParticipants( - ActorRef session, - List> participants, - double returnedAmount) implements SessionMessage { - } - - - public record EndSession() implements SessionMessage { } - - public record PlayTurn( ActorRef session, @@ -40,4 +30,13 @@ public class SessionProtocol { implements SessionMessage { } + public record ShareReturnPotWithParticipants( + ActorRef session, + List> participants, + double returnedAmount) implements SessionMessage { + } + + + public record EndSession() implements SessionMessage { } + } \ No newline at end of file diff --git a/src/main/resources/log4j.xml b/src/main/resources/log4j.xml index 45b90ad..c6b1322 100644 --- a/src/main/resources/log4j.xml +++ b/src/main/resources/log4j.xml @@ -1,7 +1,7 @@ + xmlns:log4j='http://jakarta.apache.org/log4j/'> diff --git a/src/test/java/dev/freireservices/social_altruism/chat/CaseStudiesTests.java b/src/test/java/dev/freireservices/social_altruism/chat/CaseStudiesTests.java new file mode 100644 index 0000000..11a1c0b --- /dev/null +++ b/src/test/java/dev/freireservices/social_altruism/chat/CaseStudiesTests.java @@ -0,0 +1,58 @@ +package dev.freireservices.social_altruism.chat; + +import akka.actor.testkit.typed.javadsl.ActorTestKit; +import akka.actor.testkit.typed.javadsl.BehaviorTestKit; +import akka.actor.testkit.typed.javadsl.TestProbe; +import akka.actor.typed.ActorRef; +import dev.freireservices.social_altruism.chat.participant.Participant; +import dev.freireservices.social_altruism.chat.participant.ParticipantProtocol; +import dev.freireservices.social_altruism.chat.participant.ParticipantProtocol.ParticipantMessage; +import dev.freireservices.social_altruism.chat.potroom.PotRoom; +import dev.freireservices.social_altruism.chat.potroom.PotRoomProtocol; +import org.junit.Test; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +import static dev.freireservices.social_altruism.chat.participant.ParticipantType.*; + +public class CaseStudiesTests { + public static final int INITIAL_COINS = 100; + public static final int TOTAL_PARTICIPANTS = 3; + public static final int TOTAL_TURNS = 10; + + @Test + public void testCooperation() { + + final ActorTestKit testKit = ActorTestKit.create(); + var potRoom = PotRoom.create(TOTAL_PARTICIPANTS, TOTAL_TURNS); + + ActorRef chatRoomTest = + testKit.spawn(potRoom, "potRoom"); + + ActorRef p1 = + testKit.spawn(Participant.create(INITIAL_COINS, PICARO), "PICARO-1"); + + ActorRef p2 = + testKit.spawn(Participant.create(INITIAL_COINS, JUSTICIERO), "JUSTICIERO-1"); + + ActorRef p3 = + testKit.spawn(Participant.create(INITIAL_COINS, SANTO), "SANTO-1"); + + + + + + // Enter POT + chatRoomTest.tell(new PotRoomProtocol.EnterPot(p1)); + chatRoomTest.tell(new PotRoomProtocol.EnterPot(p2)); + chatRoomTest.tell(new PotRoomProtocol.EnterPot(p3)); + + try { + TimeUnit.MINUTES.sleep(3); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + } +} diff --git a/src/test/java/dev/freireservices/social_altruism/chat/PotQuickStartTest.java b/src/test/java/dev/freireservices/social_altruism/chat/ProtocolTests.java similarity index 68% rename from src/test/java/dev/freireservices/social_altruism/chat/PotQuickStartTest.java rename to src/test/java/dev/freireservices/social_altruism/chat/ProtocolTests.java index 0cb662a..4b7adf0 100644 --- a/src/test/java/dev/freireservices/social_altruism/chat/PotQuickStartTest.java +++ b/src/test/java/dev/freireservices/social_altruism/chat/ProtocolTests.java @@ -2,7 +2,6 @@ package dev.freireservices.social_altruism.chat; import akka.actor.testkit.typed.javadsl.ActorTestKit; import akka.actor.testkit.typed.javadsl.BehaviorTestKit; -import akka.actor.testkit.typed.javadsl.BehaviorTestKit$; import akka.actor.testkit.typed.javadsl.TestProbe; import akka.actor.typed.ActorRef; import dev.freireservices.social_altruism.chat.participant.Participant; @@ -16,13 +15,12 @@ import java.time.Duration; import static dev.freireservices.social_altruism.chat.participant.ParticipantType.*; -public class PotQuickStartTest { +public class ProtocolTests { public static final int INITIAL_COINS = 100; public static final int TOTAL_PARTICIPANTS = 4; @Test - // FIXME - Improve or delete.. - public void testCooperationCaseOne() { + public void testSessionStartedOnJoinParticipants() { final ActorTestKit testKit = ActorTestKit.create(); @@ -57,8 +55,25 @@ public class PotQuickStartTest { } + @Test - public void testActorGetsUserDenied() { + public void testActorGetsSessionGranted() { + final ActorTestKit testKit = ActorTestKit.create(); + TestProbe testProbe = + testKit.createTestProbe("TestProbe"); + + ActorRef chatRoomTest = + testKit.spawn(PotRoom.create(1, 1), "chatRoom"); + + chatRoomTest.tell(new PotRoomProtocol.EnterPot(testProbe.ref())); + + testProbe.expectMessageClass(ParticipantProtocol.SessionGranted.class, Duration.ofSeconds(10)); + + // #assert + } + + @Test + public void testActorGetsSessionDenied() { final ActorTestKit testKit = ActorTestKit.create(); TestProbe testProbe = testKit.createTestProbe("TestProbe"); @@ -67,13 +82,26 @@ public class PotQuickStartTest { testKit.spawn(PotRoom.create(2, 1), "chatRoom"); chatRoomTest.tell(new PotRoomProtocol.EnterPot(testProbe.ref())); - - testProbe.expectMessageClass(ParticipantProtocol.SessionGranted.class, Duration.ofSeconds(10)); - chatRoomTest.tell(new PotRoomProtocol.EnterPot(testProbe.ref())); - testProbe.expectMessage( - Duration.ofSeconds(10), new ParticipantProtocol.SessionDenied("Can only enter a pot once")); + testProbe.expectMessageClass(ParticipantProtocol.SessionDenied.class, Duration.ofSeconds(5)); + + // #assert + } + + @Test + public void testMultipleSessions() { + final ActorTestKit testKit = ActorTestKit.create(); + TestProbe testProbe = + testKit.createTestProbe("TestProbe"); + + ActorRef chatRoomTest = + testKit.spawn(PotRoom.create(2, 1), "chatRoom"); + + chatRoomTest.tell(new PotRoomProtocol.EnterPot(testProbe.ref())); + chatRoomTest.tell(new PotRoomProtocol.EnterPot(testProbe.ref())); + + testProbe.expectMessageClass(ParticipantProtocol.SessionDenied.class, Duration.ofSeconds(5)); // #assert }