package games.strategy.engine.message.unifiedmessenger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import games.strategy.debug.ClientLogger;
import games.strategy.engine.message.ChannelMessenger;
import games.strategy.engine.message.IChannelSubscribor;
import games.strategy.engine.message.RemoteName;
import games.strategy.engine.message.UnifiedMessengerHub;
import games.strategy.net.ClientMessenger;
import games.strategy.net.IMessenger;
import games.strategy.net.IServerMessenger;
import games.strategy.net.MacFinder;
import games.strategy.net.ServerMessenger;
import games.strategy.test.TestUtil;
import games.strategy.util.ThreadUtil;
public class ChannelMessengerTest {
private IServerMessenger serverMessenger;
private IMessenger clientMessenger;
private static int SERVER_PORT = -1;
private ChannelMessenger serverChannelMessenger;
private ChannelMessenger clientChannelMessenger;
private UnifiedMessengerHub unifiedMessengerHub;
@Before
public void setUp() throws IOException {
SERVER_PORT = TestUtil.getUniquePort();
serverMessenger = new ServerMessenger("Server", SERVER_PORT);
serverMessenger.setAcceptNewConnections(true);
final String mac = MacFinder.getHashedMacAddress();
clientMessenger = new ClientMessenger("localhost", SERVER_PORT, "client1", mac);
final UnifiedMessenger unifiedMessenger = new UnifiedMessenger(serverMessenger);
unifiedMessengerHub = unifiedMessenger.getHub();
serverChannelMessenger = new ChannelMessenger(unifiedMessenger);
clientChannelMessenger = new ChannelMessenger(new UnifiedMessenger(clientMessenger));
}
@After
public void tearDown() {
try {
if (serverMessenger != null) {
serverMessenger.shutDown();
}
} catch (final Exception e) {
ClientLogger.logQuietly(e);
}
try {
if (clientMessenger != null) {
clientMessenger.shutDown();
}
} catch (final Exception e) {
ClientLogger.logQuietly(e);
}
}
@Test
public void testLocalCall() {
final RemoteName descriptor = new RemoteName(IChannelBase.class, "testLocalCall");
serverChannelMessenger.registerChannelSubscriber(new ChannelSubscribor(), descriptor);
final IChannelBase subscribor = (IChannelBase) serverChannelMessenger.getChannelBroadcastor(descriptor);
subscribor.testNoParams();
subscribor.testPrimitives(1, (short) 0, 1, (byte) 1, true, (float) 1.0);
subscribor.testString("a");
}
@Test
public void testRemoteCall() {
final RemoteName testRemote = new RemoteName(IChannelBase.class, "testRemote");
final ChannelSubscribor subscribor1 = new ChannelSubscribor();
serverChannelMessenger.registerChannelSubscriber(subscribor1, testRemote);
assertHasChannel(testRemote, unifiedMessengerHub);
final IChannelBase channelTest = (IChannelBase) clientChannelMessenger.getChannelBroadcastor(testRemote);
channelTest.testNoParams();
assertCallCountIs(subscribor1, 1);
channelTest.testString("a");
assertCallCountIs(subscribor1, 2);
channelTest.testPrimitives(1, (short) 0, 1, (byte) 1, true, (float) 1.0);
assertCallCountIs(subscribor1, 3);
channelTest.testArray(null, null, null, null, null, null);
assertCallCountIs(subscribor1, 4);
}
@Test
public void testMultipleClients() throws Exception {
// set up the client and server
// so that the client has 1 subscribor, and the server knows about it
final RemoteName test = new RemoteName(IChannelBase.class, "test");
final ChannelSubscribor client1Subscribor = new ChannelSubscribor();
clientChannelMessenger.registerChannelSubscriber(client1Subscribor, test);
assertHasChannel(test, unifiedMessengerHub);
assertEquals(1, clientChannelMessenger.getUnifiedMessenger().getLocalEndPointCount(test));
// add a new client
final String mac = MacFinder.getHashedMacAddress();
final ClientMessenger clientMessenger2 = new ClientMessenger("localhost", SERVER_PORT, "client2", mac);
final ChannelMessenger client2 = new ChannelMessenger(new UnifiedMessenger(clientMessenger2));
((IChannelBase) client2.getChannelBroadcastor(test)).testString("a");
assertCallCountIs(client1Subscribor, 1);
}
@Test
public void testMultipleChannels() {
final RemoteName testRemote2 = new RemoteName(IChannelBase.class, "testRemote2");
final RemoteName testRemote3 = new RemoteName(IChannelBase.class, "testRemote3");
final ChannelSubscribor subscribor2 = new ChannelSubscribor();
clientChannelMessenger.registerChannelSubscriber(subscribor2, testRemote2);
final ChannelSubscribor subscribor3 = new ChannelSubscribor();
clientChannelMessenger.registerChannelSubscriber(subscribor3, testRemote3);
assertHasChannel(testRemote2, unifiedMessengerHub);
assertHasChannel(testRemote3, unifiedMessengerHub);
final IChannelBase channelTest2 = (IChannelBase) serverChannelMessenger.getChannelBroadcastor(testRemote2);
channelTest2.testNoParams();
assertCallCountIs(subscribor2, 1);
final IChannelBase channelTest3 = (IChannelBase) serverChannelMessenger.getChannelBroadcastor(testRemote3);
channelTest3.testNoParams();
assertCallCountIs(subscribor3, 1);
}
private void assertHasChannel(final RemoteName descriptor, final UnifiedMessengerHub hub) {
int waitCount = 0;
while (waitCount < 10 && !hub.hasImplementors(descriptor.getName())) {
ThreadUtil.sleep(100);
waitCount++;
}
assertTrue(hub.hasImplementors(descriptor.getName()));
}
private static void assertCallCountIs(final ChannelSubscribor subscribor, final int expected) {
// since the method call happens in a seperate thread,
// wait for the call to go through, but dont wait too long
int waitCount = 0;
while (waitCount < 20 && expected != subscribor.getCallCount()) {
ThreadUtil.sleep(50);
waitCount++;
}
assertEquals(expected, subscribor.getCallCount());
}
private interface IChannelBase extends IChannelSubscribor {
void testNoParams();
void testPrimitives(int a, short b, long c, byte d, boolean e, float f);
void testString(String a);
void testArray(int[] ints, short[] shorts, byte[] bytes, boolean[] bools, float[] floats, Object[] objects);
}
private static class ChannelSubscribor implements IChannelBase {
private int callCount = 0;
private synchronized void incrementCount() {
callCount++;
}
public synchronized int getCallCount() {
return callCount;
}
@Override
public void testNoParams() {
incrementCount();
}
@Override
public void testPrimitives(final int a, final short b, final long c, final byte d, final boolean e, final float f) {
incrementCount();
}
@Override
public void testString(final String a) {
incrementCount();
}
@Override
public void testArray(final int[] ints, final short[] shorts, final byte[] bytes, final boolean[] bools,
final float[] floats, final Object[] objects) {
incrementCount();
}
}
}