package eu.hgross.blaubot.test; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import java.net.UnknownHostException; import java.util.HashSet; import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import eu.hgross.blaubot.core.Blaubot; import eu.hgross.blaubot.core.IBlaubotDevice; import eu.hgross.blaubot.core.LifecycleListenerAdapter; import eu.hgross.blaubot.util.Log; /** * Tests the lifecycle listener */ public class LifecycleListenerTest { private static final int CONNECTIVITY_TEST_TIMEOUT = 150000; private static final int MAX_STOPPING_TIMEOUT_FOR_ALL_INSTANCES = 30000; private static final long WAIT_TIME_BETWEEN_TESTS = 1000; // sleep time between tests to let the os close the sockets private static final int NUMBER_OF_BLAUBOT_INSTANCES = 3; // min 3! private static final int STARTING_PORT_FOR_BLAUBOT_INSTANCES = 17171; private UUID blaubotTestUUID = UUID.fromString("fc7eaac6-ac62-11e4-89d3-123b93f75cba"); private List<Blaubot> instances; @BeforeClass public static void setUpClass() { Log.LOG_LEVEL = Log.LogLevel.ERRORS; } @Before public void setUp() throws UnknownHostException { // HashSet<String> uniqueDeviceIdStrings = BlaubotJunitHelper.createEthernetUniqueDeviceIdStringsFromFirstLocalIpAddress(NUMBER_OF_BLAUBOT_INSTANCES, STARTING_PORT_FOR_BLAUBOT_INSTANCES); HashSet<String> uniqueDeviceIdStrings = BlaubotJunitHelper.createEthernetUniqueDeviceIdStringsFromLoopbackInterface(NUMBER_OF_BLAUBOT_INSTANCES, STARTING_PORT_FOR_BLAUBOT_INSTANCES); this.instances = BlaubotJunitHelper.setUpEthernetBlaubotInstancesFromUniqueIdSet(uniqueDeviceIdStrings, blaubotTestUUID, BlaubotJunitHelper.EthernetBeaconType.FIXED_DEVICE_SET); } @After public void cleanUp() throws UnknownHostException, InterruptedException { BlaubotJunitHelper.stopBlaubotInstances(instances, MAX_STOPPING_TIMEOUT_FOR_ALL_INSTANCES); this.instances.clear(); Thread.sleep(WAIT_TIME_BETWEEN_TESTS); } @Test(timeout=CONNECTIVITY_TEST_TIMEOUT * 4) /** * This is what we do: * Create 3 blaubot instances and check this states: * - State1: start instance1 and instance2; assert that we get 2 onConnected and a onDeviceJoined for both * - State2: then start a third and assert that we get 1 onConnected, 2 ondDeviceJoined with the third's uniqueDeviceId and one onDeviceJoined for instance1, and instance2 * - State3: stop instance3 and assert that we get 2 onDeviceLeft() and one onDisconnected() * - State4: stop instance2 and assert that we get 2 onDeviceLeft and two onDisconnected (kingdom is no more after timeout) */ public void testLifeCycle() throws InterruptedException { // assert that we have 3 instances Assert.assertEquals(3, instances.size()); final Blaubot device1 = instances.get(0); final Blaubot device2 = instances.get(1); final Blaubot device3 = instances.get(2); class EventCounterLifecycleListener extends LifecycleListenerAdapter { AtomicInteger onDeviceJoinedForDevice1Count = new AtomicInteger(0); AtomicInteger onDeviceJoinedForDevice2Count = new AtomicInteger(0); AtomicInteger onDeviceJoinedForDevice3Count = new AtomicInteger(0); AtomicInteger onDeviceLeftForDevice1Count = new AtomicInteger(0); AtomicInteger onDeviceLeftForDevice2Count = new AtomicInteger(0); AtomicInteger onDeviceLeftForDevice3Count = new AtomicInteger(0); AtomicInteger onConnectedCount = new AtomicInteger(0); AtomicInteger onDisconnectedCount = new AtomicInteger(0); @Override public void onConnected() { onConnectedCount.incrementAndGet(); } @Override public void onDisconnected() { onDisconnectedCount.incrementAndGet(); } @Override public void onDeviceJoined(IBlaubotDevice blaubotDevice) { if (blaubotDevice.getUniqueDeviceID().equals(device1.getOwnDevice().getUniqueDeviceID())) { onDeviceJoinedForDevice1Count.incrementAndGet(); } else if (blaubotDevice.getUniqueDeviceID().equals(device2.getOwnDevice().getUniqueDeviceID())) { onDeviceJoinedForDevice2Count.incrementAndGet(); } else if (blaubotDevice.getUniqueDeviceID().equals(device3.getOwnDevice().getUniqueDeviceID())) { onDeviceJoinedForDevice3Count.incrementAndGet(); } } @Override public void onDeviceLeft(IBlaubotDevice blaubotDevice) { if (blaubotDevice.getUniqueDeviceID().equals(device1.getOwnDevice().getUniqueDeviceID())) { onDeviceLeftForDevice1Count.incrementAndGet(); } else if (blaubotDevice.getUniqueDeviceID().equals(device2.getOwnDevice().getUniqueDeviceID())) { onDeviceLeftForDevice2Count.incrementAndGet(); } else if (blaubotDevice.getUniqueDeviceID().equals(device3.getOwnDevice().getUniqueDeviceID())) { onDeviceLeftForDevice3Count.incrementAndGet(); } } @Override public String toString() { final StringBuffer sb = new StringBuffer("EventCounterLifecycleListener{"); sb.append("onDeviceJoinedForDevice1Count=").append(onDeviceJoinedForDevice1Count); sb.append(", onDeviceJoinedForDevice2Count=").append(onDeviceJoinedForDevice2Count); sb.append(", onDeviceJoinedForDevice3Count=").append(onDeviceJoinedForDevice3Count); sb.append(", onDeviceLeftForDevice1Count=").append(onDeviceLeftForDevice1Count); sb.append(", onDeviceLeftForDevice2Count=").append(onDeviceLeftForDevice2Count); sb.append(", onDeviceLeftForDevice3Count=").append(onDeviceLeftForDevice3Count); sb.append(", onConnectedCount=").append(onConnectedCount); sb.append(", onDisconnectedCount=").append(onDisconnectedCount); sb.append('}'); return sb.toString(); } } EventCounterLifecycleListener state1 = new EventCounterLifecycleListener(); EventCounterLifecycleListener state2 = new EventCounterLifecycleListener(); EventCounterLifecycleListener state3 = new EventCounterLifecycleListener(); EventCounterLifecycleListener state4 = new EventCounterLifecycleListener(); // attach listener for state1 for (Blaubot b : instances) { b.addLifecycleListener(state1); } // start and await that we have a kingdom of two Assert.assertTrue("The blaubot instances could not form a kingdom fast enough. States: " + BlaubotJunitHelper.createBlaubotCensusString(device1, device2), BlaubotJunitHelper.blockUntilWeHaveOneKingdom(CONNECTIVITY_TEST_TIMEOUT, device1, device2)); // give it some time Thread.sleep(2000); // check condition boolean state1Condition = state1.onDeviceJoinedForDevice1Count.get() == 1 && state1.onDeviceJoinedForDevice2Count.get() == 1 && state1.onDeviceJoinedForDevice3Count.get() == 0 && state1.onDeviceLeftForDevice1Count.get() == 0 && state1.onDeviceLeftForDevice2Count.get() == 0 && state1.onDeviceLeftForDevice3Count.get() == 0 && state1.onConnectedCount.get() == 2 && state1.onDisconnectedCount.get() == 0; Assert.assertTrue("State 1 condition not met: " + state1, state1Condition); // attach state 2 listener and start instance 3 for (Blaubot b : instances) { b.addLifecycleListener(state2); } // start instance 3 and await join to kingdom Assert.assertTrue("The blaubot instances could not form a kingdom fast enough. States: " + BlaubotJunitHelper.createBlaubotCensusString(device1, device2, device3), BlaubotJunitHelper.blockUntilWeHaveOneKingdom(CONNECTIVITY_TEST_TIMEOUT, device1, device2, device3)); // give it some time Thread.sleep(2000); // check condition boolean state2Condition = state2.onDeviceJoinedForDevice1Count.get() == 1 && state2.onDeviceJoinedForDevice2Count.get() == 1 && state2.onDeviceJoinedForDevice3Count.get() == 2 && state2.onDeviceLeftForDevice1Count.get() == 0 && state2.onDeviceLeftForDevice2Count.get() == 0 && state2.onDeviceLeftForDevice3Count.get() == 0 && state2.onConnectedCount.get() == 1 && state2.onDisconnectedCount.get() == 0; Assert.assertTrue("State 2 condition not met: " + state2, state2Condition); // attach state 3 listener and stop instance 3 for (Blaubot b : instances) { b.addLifecycleListener(state3); } device3.stopBlaubot(); // give it some time Thread.sleep(2000); // check condition boolean state3Condition = state3.onDeviceJoinedForDevice1Count.get() == 0 && state3.onDeviceJoinedForDevice2Count.get() == 0 && state3.onDeviceJoinedForDevice3Count.get() == 0 && state3.onDeviceLeftForDevice1Count.get() == 1 && state3.onDeviceLeftForDevice2Count.get() == 1 && state3.onDeviceLeftForDevice3Count.get() == 2 && state3.onConnectedCount.get() == 0 && state3.onDisconnectedCount.get() == 1; Assert.assertTrue("State 3 condition not met: " + state3, state3Condition); // State4: stop instance2 and assert that we get 2 onDeviceLeft and one 2 onDisconnected for (Blaubot b : instances) { b.addLifecycleListener(state4); } device2.stopBlaubot(); // give it some time Thread.sleep((device1.getAdapters().get(0).getConnectionStateMachineConfig().getKingWithoutPeasantsTimeout() * 2)); // check condition boolean state4Condition = state4.onDeviceJoinedForDevice1Count.get() == 0 && state4.onDeviceJoinedForDevice2Count.get() == 0 && state4.onDeviceJoinedForDevice3Count.get() == 0 && state4.onDeviceLeftForDevice1Count.get() == 1 && // device 2 should receive this event state4.onDeviceLeftForDevice2Count.get() == 1 && // device 1 should receive this event state4.onDeviceLeftForDevice3Count.get() == 0 && state4.onConnectedCount.get() == 0 && state4.onDisconnectedCount.get() == 2; // device 2 should receive this event Assert.assertTrue("State 4 condition not met: " + state4, state4Condition); } }