Tests, fixes; working version

This commit is contained in:
Jaime Freire 2024-01-03 18:41:25 +01:00
parent c8a7f22a45
commit a2c2e9faf6
7 changed files with 166 additions and 52 deletions

View File

@ -12,8 +12,8 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.time.Duration;
import java.util.List; 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.JUSTICIERO;
import static dev.freireservices.social_altruism.chat.participant.ParticipantType.SANTO; import static dev.freireservices.social_altruism.chat.participant.ParticipantType.SANTO;
@ -59,23 +59,48 @@ public class Participant {
} }
private Behavior<ParticipantMessage> behavior() { private Behavior<ParticipantMessage> behavior() {
return uninitialized();
}
private Behavior<ParticipantMessage> uninitialized() {
return Behaviors.receive(ParticipantMessage.class) return Behaviors.receive(ParticipantMessage.class)
.onMessage(SessionStarted.class, this::onSessionStarted)
.onMessage(SessionDenied.class, this::onSessionDenied) .onMessage(SessionDenied.class, this::onSessionDenied)
.onMessage(SessionGranted.class, this::onSessionGranted) .onMessage(SessionGranted.class, x ->
{
onSessionGranted(x);
return readyToStart();
})
.build();
}
private Behavior<ParticipantMessage> readyToStart() {
return Behaviors.receive(ParticipantMessage.class)
.onMessage(SessionStarted.class,
x -> {
onSessionStarted(x);
return started();
}
)
.build();
}
private Behavior<ParticipantMessage> started() {
return Behaviors.receive(ParticipantMessage.class)
.onMessage(PotReturned.class, this::onPotReturned) .onMessage(PotReturned.class, this::onPotReturned)
.onMessage(SessionEnded.class, this::onSessionEnded) .onMessage(SessionEnded.class, this::onSessionEnded)
.build(); .build();
} }
private Behavior<ParticipantMessage> onSessionEnded(SessionEnded sessionEnded) { private Behavior<ParticipantMessage> onSessionEnded(SessionEnded sessionEnded) {
context.getLog().info("Session ended for user {}", context.getSelf().path().name()); context.getLog().info("Session ended for user {}", context.getSelf().path().name());
try {
TimeUnit.SECONDS.sleep(1); context.getLog().info("Session ended for user: Stats: {}. Earned {} coins, profit {} %"
} catch (InterruptedException e) { , context.getSelf().path().name()
throw new RuntimeException(e); , getParticipantCoins() - getInitialCoins()
} , (getParticipantCoins() - getInitialCoins())
);
return Behaviors.stopped(); return Behaviors.stopped();
} }
@ -85,32 +110,33 @@ public class Participant {
return Behaviors.stopped(); return Behaviors.stopped();
} }
private Behavior<ParticipantMessage> onSessionGranted( private void onSessionGranted(
SessionGranted message) { SessionGranted message) {
context.getLog().info("Session granted message received for {} ", context.getSelf().path().name());
setChatRoom(message.chatRoom()); setChatRoom(message.chatRoom());
setSession(message.session()); setSession(message.session());
return Behaviors.same();
} }
private Behavior<ParticipantMessage> onSessionStarted( private void onSessionStarted(
SessionStarted startSession) { SessionStarted startSession) {
context.getLog().info("Session started for {} with {} participants", context.getSelf().path().name(), startSession.participants().size());
resetCurrentTurn(); resetCurrentTurn();
setParticipants(startSession.participants()); setParticipants(startSession.participants());
setTotalTurns(startSession.totalTurns()); setTotalTurns(startSession.totalTurns());
playTurn(startSession.replyTo()); playTurnWithSmallDelay(startSession.replyTo());
context.getLog().info("Session started for {} with {} participants", context.getSelf().path().name(), startSession.participants().size());
return Behaviors.same();
} }
private void playTurn(ActorRef<SessionMessage> replyTo) { private void playTurnWithSmallDelay(ActorRef<SessionMessage> replyTo) {
if (getParticipantCoins() > 0 && getCurrentTurn() < getTotalTurns()) { if (getParticipantCoins() > 0 && getCurrentTurn() < getTotalTurns()) {
replyTo.tell(new SessionProtocol.PlayTurn( context.scheduleOnce(Duration.ofSeconds(5),
replyTo, replyTo,
context.getSelf(), new SessionProtocol.PlayTurn(
participants, replyTo,
getCurrentTurn(), context.getSelf(),
getParticipationForCurrentTurn() participants,
)); getCurrentTurn(),
getParticipationForCurrentTurn())
);
} }
} }
@ -141,12 +167,7 @@ public class Participant {
// Still game? // Still game?
if (getParticipantCoins() > 1) { if (getParticipantCoins() > 1) {
try { playTurnWithSmallDelay(potReturned.session());
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
playTurn(potReturned.session());
} else { } else {
context context
.getLog() .getLog()
@ -160,7 +181,10 @@ public class Participant {
context.getLog().info("END GAME"); context.getLog().info("END GAME");
context.getLog().info("---------"); context.getLog().info("---------");
context.getLog().info("END GAME"); context.getLog().info("END GAME");
return Behaviors.stopped();
context.stop(context.getSelf());
Behaviors.stopped();
} }
adjustBehaviour(potReturned); adjustBehaviour(potReturned);
return Behaviors.same(); return Behaviors.same();

View File

@ -10,6 +10,10 @@ public class ParticipantProtocol {
public interface ParticipantMessage { public interface ParticipantMessage {
} }
enum Timeout implements ParticipantMessage {
INSTANCE
}
public record SessionGranted( public record SessionGranted(
ActorRef<PotRoomMessage> chatRoom, ActorRef<PotRoomMessage> chatRoom,
ActorRef<SessionMessage> session ActorRef<SessionMessage> session

View File

@ -4,7 +4,6 @@ import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior; import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.ActorContext; import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Behaviors; 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.EnterPot;
import dev.freireservices.social_altruism.chat.potroom.PotRoomProtocol.PotRoomMessage; import dev.freireservices.social_altruism.chat.potroom.PotRoomProtocol.PotRoomMessage;
import dev.freireservices.social_altruism.chat.potroom.SessionProtocol.SessionMessage; import dev.freireservices.social_altruism.chat.potroom.SessionProtocol.SessionMessage;
@ -54,9 +53,10 @@ public class PotRoom {
Session.create(participants, totalTurns), Session.create(participants, totalTurns),
URLEncoder.encode(enterPot.replyTo().path().name(), UTF_8)); 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 // 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))); participants.forEach(p -> p.tell(new SessionStarted(chatRoom, session, participants, totalTurns)));
return createPotBehaviour(chatRoom); return createPotBehaviour(chatRoom);
@ -89,6 +89,7 @@ public class PotRoom {
public static Behavior<PotRoomMessage> create(int numberOfParticipants, int totalTurns) { public static Behavior<PotRoomMessage> create(int numberOfParticipants, int totalTurns) {
return Behaviors.setup( return Behaviors.setup(
ctx -> new PotRoom(ctx, numberOfParticipants, totalTurns).createPotBehaviour(ctx.getSelf())); ctx -> new PotRoom(ctx, numberOfParticipants, totalTurns)
.createPotBehaviour(ctx.getSelf()));
} }
} }

View File

@ -20,16 +20,6 @@ public class SessionProtocol {
implements SessionMessage { implements SessionMessage {
} }
public record ShareReturnPotWithParticipants(
ActorRef<SessionMessage> session,
List<ActorRef<ParticipantMessage>> participants,
double returnedAmount) implements SessionMessage {
}
public record EndSession() implements SessionMessage { }
public record PlayTurn( public record PlayTurn(
ActorRef<SessionMessage> session, ActorRef<SessionMessage> session,
@ -40,4 +30,13 @@ public class SessionProtocol {
implements SessionMessage { implements SessionMessage {
} }
public record ShareReturnPotWithParticipants(
ActorRef<SessionMessage> session,
List<ActorRef<ParticipantMessage>> participants,
double returnedAmount) implements SessionMessage {
}
public record EndSession() implements SessionMessage { }
} }

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true" <log4j:configuration debug="true"
xmlns:log4j='https://jakarta.apache.org/log4j/'> xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="console" class="org.apache.log4j.ConsoleAppender"> <appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout"> <layout class="org.apache.log4j.PatternLayout">

View File

@ -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<PotRoomProtocol.PotRoomMessage> chatRoomTest =
testKit.spawn(potRoom, "potRoom");
ActorRef<ParticipantMessage> p1 =
testKit.spawn(Participant.create(INITIAL_COINS, PICARO), "PICARO-1");
ActorRef<ParticipantMessage> p2 =
testKit.spawn(Participant.create(INITIAL_COINS, JUSTICIERO), "JUSTICIERO-1");
ActorRef<ParticipantMessage> 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);
}
}
}

View File

@ -2,7 +2,6 @@ package dev.freireservices.social_altruism.chat;
import akka.actor.testkit.typed.javadsl.ActorTestKit; 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.BehaviorTestKit$;
import akka.actor.testkit.typed.javadsl.TestProbe; import akka.actor.testkit.typed.javadsl.TestProbe;
import akka.actor.typed.ActorRef; import akka.actor.typed.ActorRef;
import dev.freireservices.social_altruism.chat.participant.Participant; 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.*; 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 INITIAL_COINS = 100;
public static final int TOTAL_PARTICIPANTS = 4; public static final int TOTAL_PARTICIPANTS = 4;
@Test @Test
// FIXME - Improve or delete.. public void testSessionStartedOnJoinParticipants() {
public void testCooperationCaseOne() {
final ActorTestKit testKit = ActorTestKit.create(); final ActorTestKit testKit = ActorTestKit.create();
@ -57,8 +55,25 @@ public class PotQuickStartTest {
} }
@Test @Test
public void testActorGetsUserDenied() { public void testActorGetsSessionGranted() {
final ActorTestKit testKit = ActorTestKit.create();
TestProbe<ParticipantMessage> testProbe =
testKit.createTestProbe("TestProbe");
ActorRef<PotRoomProtocol.PotRoomMessage> 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(); final ActorTestKit testKit = ActorTestKit.create();
TestProbe<ParticipantMessage> testProbe = TestProbe<ParticipantMessage> testProbe =
testKit.createTestProbe("TestProbe"); testKit.createTestProbe("TestProbe");
@ -67,13 +82,26 @@ public class PotQuickStartTest {
testKit.spawn(PotRoom.create(2, 1), "chatRoom"); testKit.spawn(PotRoom.create(2, 1), "chatRoom");
chatRoomTest.tell(new PotRoomProtocol.EnterPot(testProbe.ref())); chatRoomTest.tell(new PotRoomProtocol.EnterPot(testProbe.ref()));
testProbe.expectMessageClass(ParticipantProtocol.SessionGranted.class, Duration.ofSeconds(10));
chatRoomTest.tell(new PotRoomProtocol.EnterPot(testProbe.ref())); chatRoomTest.tell(new PotRoomProtocol.EnterPot(testProbe.ref()));
testProbe.expectMessage( testProbe.expectMessageClass(ParticipantProtocol.SessionDenied.class, Duration.ofSeconds(5));
Duration.ofSeconds(10), new ParticipantProtocol.SessionDenied("Can only enter a pot once"));
// #assert
}
@Test
public void testMultipleSessions() {
final ActorTestKit testKit = ActorTestKit.create();
TestProbe<ParticipantMessage> testProbe =
testKit.createTestProbe("TestProbe");
ActorRef<PotRoomProtocol.PotRoomMessage> 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 // #assert
} }