wip: switch to synchronized handling during testing

This commit is contained in:
punchready 2021-06-08 16:04:46 +02:00
parent afc413507a
commit 805e8e5f9e
4 changed files with 73 additions and 14 deletions

View File

@ -21,6 +21,8 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class LobbyConnection implements Runnable { public class LobbyConnection implements Runnable {
private static boolean synchronous = false;
public final String gameID; public final String gameID;
public LobbyConnectionState state = LobbyConnectionState.Waiting; public LobbyConnectionState state = LobbyConnectionState.Waiting;
@ -127,6 +129,11 @@ public class LobbyConnection implements Runnable {
public void handleMessage(Participant participant, Request[] requests) { public void handleMessage(Participant participant, Request[] requests) {
if(synchronous) {
lobby.receiveRequests(requests, participant);
return;
}
try { try {
this.requestQueue.put(Tuple.of(participant, requests)); this.requestQueue.put(Tuple.of(participant, requests));
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
@ -151,6 +158,11 @@ public class LobbyConnection implements Runnable {
} }
public void runSynchronous() {
synchronous = true;
run();
}
@Override @Override
public void run() { public void run() {
state = LobbyConnectionState.Started; state = LobbyConnectionState.Started;
@ -161,7 +173,11 @@ public class LobbyConnection implements Runnable {
spectator.state = ParticipantState.Playing; spectator.state = ParticipantState.Playing;
} }
if(!synchronous) {
Logger.info("Starting Lobby thread for lobby '{}'", gameID); Logger.info("Starting Lobby thread for lobby '{}'", gameID);
}else {
Logger.info("Starting Lobby in main thread for lobby '{}'", gameID);
}
sendGameStructure(true, true, true); sendGameStructure(true, true, true);
@ -175,6 +191,10 @@ public class LobbyConnection implements Runnable {
selection.get(player2.id) selection.get(player2.id)
); );
if(synchronous) {
return;
}
while (state == LobbyConnectionState.Started) { while (state == LobbyConnectionState.Started) {
Tuple<Participant, Request[]> currentRequests = pollQueueAsync(); Tuple<Participant, Request[]> currentRequests = pollQueueAsync();

View File

@ -4,11 +4,14 @@ import org.tinylog.Logger;
import uulm.teamname.marvelous.server.Server; import uulm.teamname.marvelous.server.Server;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.Future;
/** /**
* Class meant for running lobbies. It manages said lobbies, creates threads for it, and moves it into an executor * Class meant for running lobbies. It manages said lobbies, creates threads for it, and moves it into an executor
*/ */
public class LobbyRunner { public class LobbyRunner {
private static boolean synchronous = false;
private static LobbyRunner instance; private static LobbyRunner instance;
static LobbyRunner getInstance() { static LobbyRunner getInstance() {
@ -31,16 +34,16 @@ public class LobbyRunner {
synchronized (activeLobbies) { synchronized (activeLobbies) {
if (activeLobbies.containsKey(connection)) { if (activeLobbies.containsKey(connection)) {
Logger.warn("Already active lobby was started again. This is probably a bug."); Logger.warn("Already active lobby was started again. This is probably a bug.");
} else if (!canAddLobby()) {
Logger.warn("Scheduling lobby to be started while max lobbies is reached. This might be a bug.");
Thread lobbyThread = new Thread(connection, "Lobby-" + connection.gameID);
activeLobbies.put(connection, lobbyThread);
lobbyThread.start();
} else { } else {
if(!synchronous) {
Logger.trace("Executing LobbyThread 'Lobby-{}'...", connection.gameID); Logger.trace("Executing LobbyThread 'Lobby-{}'...", connection.gameID);
Thread lobbyThread = new Thread(connection, "Lobby-" + connection.gameID); Thread lobbyThread = new Thread(connection, "Lobby-" + connection.gameID);
activeLobbies.put(connection, lobbyThread); activeLobbies.put(connection, lobbyThread);
lobbyThread.start(); lobbyThread.start();
}else {
Logger.trace("Executing Lobby 'Lobby-{}'...", connection.gameID);
connection.runSynchronous();
}
} }
} }
} }

View File

@ -1,7 +1,9 @@
package uulm.teamname.marvelous.server; package uulm.teamname.marvelous.server;
import uulm.teamname.marvelous.gamelibrary.config.*; import uulm.teamname.marvelous.gamelibrary.config.*;
import uulm.teamname.marvelous.server.lobbymanager.LobbyRunner;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
@ -26,6 +28,12 @@ public class BaseGameLogicTest {
partyConfig.timeStoneCD = 7; partyConfig.timeStoneCD = 7;
partyConfig.mindStoneDMG = 3; partyConfig.mindStoneDMG = 3;
partyConfig.maxRoundTime = 1000;
partyConfig.maxGameTime = 1000;
partyConfig.maxAnimationTime = 1000;
partyConfig.maxResponseTime = 1000;
partyConfig.maxPauseTime = 1000;
characterConfig.characters = new CharacterProperties[24]; characterConfig.characters = new CharacterProperties[24];
for(int i = 0; i < characterConfig.characters.length; i++) { for(int i = 0; i < characterConfig.characters.length; i++) {
characterConfig.characters[i] = generateCharacter(i); characterConfig.characters[i] = generateCharacter(i);
@ -78,4 +86,16 @@ public class BaseGameLogicTest {
return props; return props;
} }
static void setPrivateFinalBoolean(Class c, String name, boolean value) throws NoSuchFieldException, IllegalAccessException {
Field field = LobbyRunner.class.getDeclaredField(name);
field.setAccessible(true);
//this is broken somehow
//Field modifiersField = Field.class.getDeclaredField("modifiers");
//modifiersField.setAccessible(true);
//modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, value);
}
} }

View File

@ -12,7 +12,9 @@ import uulm.teamname.marvelous.gamelibrary.messages.client.CharacterSelectionMes
import uulm.teamname.marvelous.gamelibrary.messages.client.HelloServerMessage; import uulm.teamname.marvelous.gamelibrary.messages.client.HelloServerMessage;
import uulm.teamname.marvelous.gamelibrary.messages.client.PlayerReadyMessage; import uulm.teamname.marvelous.gamelibrary.messages.client.PlayerReadyMessage;
import uulm.teamname.marvelous.gamelibrary.messages.server.*; import uulm.teamname.marvelous.gamelibrary.messages.server.*;
import uulm.teamname.marvelous.server.lobbymanager.LobbyConnection;
import uulm.teamname.marvelous.server.lobbymanager.LobbyManager; import uulm.teamname.marvelous.server.lobbymanager.LobbyManager;
import uulm.teamname.marvelous.server.lobbymanager.LobbyRunner;
import uulm.teamname.marvelous.server.netconnector.UserManager; import uulm.teamname.marvelous.server.netconnector.UserManager;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -29,7 +31,7 @@ class MarvelousServerTest extends BaseGameLogicTest {
private static JSON json; private static JSON json;
@BeforeAll @BeforeAll
static void start() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { static void start() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Constructor<UserManager> um = UserManager.class.getDeclaredConstructor(); Constructor<UserManager> um = UserManager.class.getDeclaredConstructor();
um.setAccessible(true); um.setAccessible(true);
um.newInstance(); um.newInstance();
@ -41,6 +43,9 @@ class MarvelousServerTest extends BaseGameLogicTest {
generate(); generate();
setPrivateFinalBoolean(LobbyConnection.class, "synchronous", true);
setPrivateFinalBoolean(LobbyRunner.class, "synchronous", true);
serverMock.when(Server::getMaxLobbies).thenReturn(10); serverMock.when(Server::getMaxLobbies).thenReturn(10);
serverMock.when(Server::getPartyConfig).thenReturn(partyConfig); serverMock.when(Server::getPartyConfig).thenReturn(partyConfig);
serverMock.when(Server::getScenarioConfig).thenReturn(scenarioConfig); serverMock.when(Server::getScenarioConfig).thenReturn(scenarioConfig);
@ -66,6 +71,11 @@ class MarvelousServerTest extends BaseGameLogicTest {
WebSocket s1 = mock(WebSocket.class); WebSocket s1 = mock(WebSocket.class);
WebSocket s2 = mock(WebSocket.class); WebSocket s2 = mock(WebSocket.class);
when(p1.getResourceDescriptor()).thenReturn("/");
when(p2.getResourceDescriptor()).thenReturn("/");
when(s1.getResourceDescriptor()).thenReturn("/");
when(s2.getResourceDescriptor()).thenReturn("/");
m.connectUser(p1); m.connectUser(p1);
ensureHandshake(m, p1, "Player 1", "1234", false); ensureHandshake(m, p1, "Player 1", "1234", false);
@ -83,14 +93,14 @@ class MarvelousServerTest extends BaseGameLogicTest {
ensureSpectatorReady(m, s1, true, RoleEnum.SPECTATOR); ensureSpectatorReady(m, s1, true, RoleEnum.SPECTATOR);
//these are broken right now because Server doesn't get mocked in lobby threads //these are broken right now because Server doesn't get mocked in lobby threads
/*
ensureCharacterSelection(m, p1, false); ensureCharacterSelection(m, p1, false);
ensureCharacterSelection(m, p2, true); ensureCharacterSelection(m, p2, true);
ensureReceived(p1, new GameStructureMessage()); ensureReceived(p1, new GameStructureMessage());
ensureReceived(p2, new GameStructureMessage()); ensureReceived(p2, new GameStructureMessage());
ensureReceived(s1, new GameStructureMessage()); ensureReceived(s1, new GameStructureMessage());
*/
System.out.println("hi");
} }
private void ensureHandshake(UserManager m, WebSocket c, String name, String deviceID, boolean runningGame) { private void ensureHandshake(UserManager m, WebSocket c, String name, String deviceID, boolean runningGame) {
@ -179,7 +189,13 @@ class MarvelousServerTest extends BaseGameLogicTest {
for(Field field: expected.getClass().getDeclaredFields()) { for(Field field: expected.getClass().getDeclaredFields()) {
try { try {
Object value = field.get(expected); Object value = field.get(expected);
if(value != null && !value.equals(field.get(message))) { Object actualValue;
try {
actualValue = field.get(message);
}catch(IllegalArgumentException e) {
throw new IllegalArgumentException("[TEST] Response message expected to be '" + expected.getClass().getName() + "' but was '" + message.getClass().getName() + "'");
}
if(value != null && !value.equals(actualValue)) {
throw new IllegalArgumentException("[TEST] Field " + field.getName() + " expected to be '" + value + "' but was '" + field.get(message) + "'"); throw new IllegalArgumentException("[TEST] Field " + field.getName() + " expected to be '" + value + "' but was '" + field.get(message) + "'");
} }
}catch(IllegalAccessException ignore) { } }catch(IllegalAccessException ignore) { }