package jReto.integration;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import jReto.meta.PeerConfiguration;
import jReto.module.dummy.DummyModule;
import jReto.module.dummy.DummyNetworkInterface;
import jReto.util.RunLoop;
import org.junit.Test;
import de.tum.in.www1.jReto.LocalPeer;
import de.tum.in.www1.jReto.util.CountDown;
public class DiscoveryTest {
/**
* Test discovery with various configurations.
* */
@Test(timeout=1000000)
public void testPeerDiscoveryDirect() {
this.testPeerDiscovery(PeerConfiguration.directNeighborConfiguration());
}
@Test(timeout=1000)
public void testPeerDiscovery2Hop() {
this.testPeerDiscovery(PeerConfiguration.twoHopRoutedConfiguration());
}
@Test(timeout=1000)
public void testPeerDiscovery4Hop() {
this.testPeerDiscovery(PeerConfiguration.fourHopRoutedConfiguration());
}
@Test(timeout=1000)
public void testPeerDiscoveryNontrivial() {
this.testPeerDiscovery(PeerConfiguration.nontrivial2HopNetworkConfiguration());
}
@Test(timeout=1000)
public void testPeerDiscoveryDisconnectedPeers() {
this.testPeerDiscovery(PeerConfiguration.configurationWithDisconnectedPeers());
}
public void testPeerDiscovery(final PeerConfiguration configuration) {
final Set<UUID> reachablePeerIdentifiers = new HashSet<>();
for (LocalPeer reachablePeer : configuration.reachablePeers) {
reachablePeerIdentifiers.add(reachablePeer.getUniqueIdentifier());
}
final Set<UUID> discoveredIdentifiers = new HashSet<>();
discoveredIdentifiers.add(configuration.peer1.getUniqueIdentifier());
final CountDown peerCountDown = new CountDown((reachablePeerIdentifiers.size()-1) * 2, new Runnable() {
@Override
public void run() {
assertTrue("Not all peers were discovered. Discovered: "+discoveredIdentifiers+", Discoverable: "+reachablePeerIdentifiers, discoveredIdentifiers.equals(reachablePeerIdentifiers));
configuration.runloop.stop();
}
});
for (LocalPeer peer : configuration.participatingPeers) {
if (peer == configuration.peer1) {
peer.start(discoveredPeer -> {
assertTrue("Incorrect peer name discovered: "+peer.getUniqueIdentifier()+", reachable are: "+reachablePeerIdentifiers, reachablePeerIdentifiers.contains(peer.getUniqueIdentifier()));
assertTrue("Incorrect peer discovered: Peers should not discover themselves.", !discoveredPeer.getUniqueIdentifier().equals(configuration.peer1.getUniqueIdentifier()));
discoveredIdentifiers.add(discoveredPeer.getUniqueIdentifier());
peerCountDown.countDown();
}, removedPeer -> {});
} else if (peer == configuration.peer2) {
peer.start(discoveredPeer -> {
assertTrue("Incorrect peer name discovered: "+peer.getUniqueIdentifier()+", reachable are: "+reachablePeerIdentifiers, reachablePeerIdentifiers.contains(peer.getUniqueIdentifier()));
assertTrue("Incorrect peer discovered: Peers should not discover themselves.", !discoveredPeer.getUniqueIdentifier().equals(configuration.peer2.getUniqueIdentifier()));
peerCountDown.countDown();
}, removedPeer -> {});
} else {
peer.start(discoveredPeer -> {}, removedPeer -> {});
}
}
configuration.runloop.start();
}
/**
* Test removal with various configurations.
* */
@Test(timeout=1000)
public void testPeerRemovalDirect() {
this.testPeerRemoval(PeerConfiguration.directNeighborConfiguration());
}
@Test(timeout=1000)
public void testPeerRemoval2Hop() {
this.testPeerRemoval(PeerConfiguration.twoHopRoutedConfiguration());
}
@Test(timeout=1000)
public void testPeerRemoval4Hop() {
this.testPeerRemoval(PeerConfiguration.fourHopRoutedConfiguration());
}
@Test(timeout=1000)
public void testPeerRemovalNontrivial() {
this.testPeerRemoval(PeerConfiguration.nontrivial2HopNetworkConfiguration());
}
@Test(timeout=1000)
public void testPeerRemovalDisconnectedPeers() {
this.testPeerRemoval(PeerConfiguration.configurationWithDisconnectedPeers());
}
public void testPeerRemoval(final PeerConfiguration configuration) {
final Set<UUID> reachablePeerIdentifiers = new HashSet<>();
for (LocalPeer reachablePeer : configuration.reachablePeers) {
reachablePeerIdentifiers.add(reachablePeer.getUniqueIdentifier());
}
final Set<UUID> removedPeerIdentifiers = new HashSet<>();
final CountDown peerAddedCountDown = new CountDown((configuration.reachablePeers.size()-1) * 2, () -> {
configuration.peer2.stop();
});
final CountDown peerRemovedCountDown = new CountDown(configuration.reachablePeers.size()-1, () -> {
reachablePeerIdentifiers.removeAll(removedPeerIdentifiers);
assertTrue("All peers were removed", reachablePeerIdentifiers.size() == 1);
assertTrue("Peer itself may not be removed", reachablePeerIdentifiers.contains(configuration.peer2.getUniqueIdentifier()));
configuration.runloop.stop();
});
for (LocalPeer peer : configuration.participatingPeers) {
if (peer == configuration.peer1) {
peer.start(discoveredPeer -> peerAddedCountDown.countDown(), removedPeer -> {});
} else if (peer == configuration.peer2) {
peer.start(discoveredPeer -> peerAddedCountDown.countDown(), removedPeer -> {
removedPeerIdentifiers.add(removedPeer.getUniqueIdentifier());
peerRemovedCountDown.countDown();
});
} else {
peer.start(p -> {}, p -> {});
}
}
configuration.runloop.start();
}
/**
* Tests whether adding/removing modules affects peer discovery correctly
* */
@Test(timeout=1000)
public void testPeerDiscoveryWithModuleModifications() {
new PeerDiscoveryWithModuleModificationsTest().start();
}
static class PeerDiscoveryWithModuleModificationsTest {
LocalPeer localPeer1;
LocalPeer localPeer2;
public void start() {
final RunLoop runloop = new RunLoop(false);
final DummyNetworkInterface networkInterface1 = new DummyNetworkInterface("test1", runloop, 1024, 1);
final DummyNetworkInterface networkInterface2 = new DummyNetworkInterface("test2", runloop, 1024, 1);
final DummyModule peer1Module1 = new DummyModule(networkInterface1, runloop);
final DummyModule peer1Module2 = new DummyModule(networkInterface2, runloop);
final DummyModule peer2Module1 = new DummyModule(networkInterface1, runloop);
final DummyModule peer2Module2 = new DummyModule(networkInterface2, runloop);
final CountDown peerAddedCountDown = new CountDown(2, new Runnable() {
@Override
public void run() {
// This should not trigger any additional onPeerDiscovereds. If it did, the count down called would throw an exception.
localPeer2.addModule(peer2Module2);
// Allow possible discovery methods to be called, then continue.
runloop.execute(new Runnable() {
@Override
public void run() {
// By removing these two modules, the peers should not be able to discover each other and should be removed, triggering the peerRemovedCountDown.
localPeer1.removeModule(peer1Module2);
localPeer2.removeModule(peer2Module1);
}
});
}
});
final CountDown peerRemovedCountDown = new CountDown(2, new Runnable() {
@Override
public void run() {
runloop.stop();
}
});
this.localPeer1 = new LocalPeer(Arrays.asList(peer1Module1, peer1Module2), runloop);
this.localPeer2 = new LocalPeer(Arrays.asList(peer2Module1), runloop);
localPeer1.start(discoveredPeer -> peerAddedCountDown.countDown(), removedPeer -> peerRemovedCountDown.countDown());
localPeer2.start(discoveredPeer -> peerAddedCountDown.countDown(), removedPeer -> peerRemovedCountDown.countDown());
runloop.start();
}
}
}