package games.strategy.engine.chat; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; import games.strategy.debug.ClientLogger; import games.strategy.engine.lobby.server.NullModeratorController; import games.strategy.engine.message.ChannelMessenger; import games.strategy.engine.message.RemoteMessenger; import games.strategy.engine.message.unifiedmessenger.UnifiedMessenger; import games.strategy.net.ClientMessenger; import games.strategy.net.IMessenger; import games.strategy.net.INode; import games.strategy.net.IServerMessenger; import games.strategy.net.MacFinder; import games.strategy.net.ServerMessenger; import games.strategy.sound.SoundPath; import games.strategy.test.TestUtil; import games.strategy.util.ThreadUtil; public class ChatTest { private static int SERVER_PORT = -1; private IServerMessenger serverMessenger; private IMessenger client1Messenger; private IMessenger client2Messenger; UnifiedMessenger serverUnifiedMessenger; RemoteMessenger serverRemoteMessenger; ChannelMessenger serverChannelMessenger; UnifiedMessenger client1UnifiedMessenger; RemoteMessenger client1RemoteMessenger; ChannelMessenger client1ChannelMessenger; UnifiedMessenger client2UnifiedMessenger; RemoteMessenger client2RemoteMessenger; ChannelMessenger client2ChannelMessenger; TestChatListener serverChatListener; TestChatListener client1ChatListener; TestChatListener client2ChatListener; NullModeratorController serverModeratorController; @Before public void setUp() throws IOException { SERVER_PORT = TestUtil.getUniquePort(); serverMessenger = new ServerMessenger("Server", SERVER_PORT); serverMessenger.setAcceptNewConnections(true); final String mac = MacFinder.getHashedMacAddress(); client1Messenger = new ClientMessenger("localhost", SERVER_PORT, "client1", mac); client2Messenger = new ClientMessenger("localhost", SERVER_PORT, "client2", mac); serverUnifiedMessenger = new UnifiedMessenger(serverMessenger); serverRemoteMessenger = new RemoteMessenger(serverUnifiedMessenger); serverChannelMessenger = new ChannelMessenger(serverUnifiedMessenger); client1UnifiedMessenger = new UnifiedMessenger(client1Messenger); client1RemoteMessenger = new RemoteMessenger(client1UnifiedMessenger); client1ChannelMessenger = new ChannelMessenger(client1UnifiedMessenger); client2UnifiedMessenger = new UnifiedMessenger(client2Messenger); client2RemoteMessenger = new RemoteMessenger(client2UnifiedMessenger); client2ChannelMessenger = new ChannelMessenger(client2UnifiedMessenger); serverModeratorController = new NullModeratorController(serverMessenger, null); serverModeratorController.register(serverRemoteMessenger); serverChatListener = new TestChatListener(); client1ChatListener = new TestChatListener(); client2ChatListener = new TestChatListener(); } @After public void tearDown() { try { if (serverMessenger != null) { serverMessenger.shutDown(); } } catch (final Exception e) { ClientLogger.logQuietly(e); } try { if (client1Messenger != null) { client1Messenger.shutDown(); } } catch (final Exception e) { ClientLogger.logQuietly(e); } try { if (client2Messenger != null) { client2Messenger.shutDown(); } } catch (final Exception e) { ClientLogger.logQuietly(e); } } @Test public void testAll() throws Exception { // this is a rather big and ugly unit test // its just that the chat is so hard to set up // and we really need to test it working with sockets // rather than some mocked up implementation final ChatController controller = new ChatController("c", serverMessenger, serverRemoteMessenger, serverChannelMessenger, serverModeratorController); final Chat server = new Chat(serverMessenger, "c", serverChannelMessenger, serverRemoteMessenger, Chat.CHAT_SOUND_PROFILE.NO_SOUND); server.addChatListener(serverChatListener); final Chat client1 = new Chat(client1Messenger, "c", client1ChannelMessenger, client1RemoteMessenger, Chat.CHAT_SOUND_PROFILE.NO_SOUND); client1.addChatListener(client1ChatListener); final Chat client2 = new Chat(client2Messenger, "c", client2ChannelMessenger, client2RemoteMessenger, Chat.CHAT_SOUND_PROFILE.NO_SOUND); client2.addChatListener(client2ChatListener); // we need to wait for all the messages to write for (int i = 0; i < 10; i++) { try { assertEquals(client1ChatListener.players.size(), 3); assertEquals(client2ChatListener.players.size(), 3); assertEquals(serverChatListener.players.size(), 3); break; } catch (final AssertionError e) { ThreadUtil.sleep(25); } } assertEquals(client1ChatListener.players.size(), 3); assertEquals(client2ChatListener.players.size(), 3); assertEquals(serverChatListener.players.size(), 3); // send 50 messages, each client sending messages on a different thread. final int messageCount = 50; final Runnable client2Send = new Runnable() { @Override public void run() { for (int i = 0; i < messageCount; i++) { client2.sendMessage("Test", false); } } }; final Thread clientThread = new Thread(client2Send); clientThread.start(); final Runnable serverSend = new Runnable() { @Override public void run() { for (int i = 0; i < messageCount; i++) { server.sendMessage("Test", false); } } }; final Thread serverThread = new Thread(serverSend); serverThread.start(); for (int i = 0; i < messageCount; i++) { client1.sendMessage("Test", false); } serverThread.join(); clientThread.join(); // we need to wait for all the messages to write for (int i = 0; i < 10; i++) { try { assertEquals(client1ChatListener.messages.size(), 3 * messageCount); assertEquals(client2ChatListener.messages.size(), 3 * messageCount); assertEquals(serverChatListener.messages.size(), 3 * messageCount); break; } catch (final AssertionError afe) { ThreadUtil.sleep(25); } } assertEquals(client1ChatListener.messages.size(), 3 * messageCount); assertEquals(client2ChatListener.messages.size(), 3 * messageCount); assertEquals(serverChatListener.messages.size(), 3 * messageCount); client1.shutdown(); client2.shutdown(); // we need to wait for all the messages to write for (int i = 0; i < 10; i++) { try { assertEquals(serverChatListener.players.size(), 1); break; } catch (final AssertionError e) { ThreadUtil.sleep(25); } } assertEquals(serverChatListener.players.size(), 1); controller.deactivate(); for (int i = 0; i < 10; i++) { try { assertEquals(serverChatListener.players.size(), 0); break; } catch (final AssertionError afe) { ThreadUtil.sleep(25); } } assertEquals(serverChatListener.players.size(), 0); } private static class TestChatListener implements IChatListener { public List<INode> players; public List<String> messages = new ArrayList<>(); @Override public void updatePlayerList(final Collection<INode> players) { synchronized (this) { this.players = new ArrayList<>(players); } } @Override public void addMessageWithSound(final String message, final String from, final boolean thirdperson, final String sound) { synchronized (this) { messages.add(message); } } @Override public void addMessage(final String message, final String from, final boolean thirdperson) { addMessageWithSound(message, from, thirdperson, SoundPath.CLIP_CHAT_MESSAGE); } @Override public void addStatusMessage(final String message) {} } }