diff --git a/src/test/java/io/bitsquare/msg/TomP2PTests.java b/src/test/java/io/bitsquare/msg/TomP2PTests.java index d347af6e76..4044f12523 100644 --- a/src/test/java/io/bitsquare/msg/TomP2PTests.java +++ b/src/test/java/io/bitsquare/msg/TomP2PTests.java @@ -17,8 +17,13 @@ package io.bitsquare.msg; +import io.bitsquare.network.BootstrapNode; +import io.bitsquare.network.Node; + import java.io.IOException; +import java.net.UnknownHostException; + import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; @@ -63,104 +68,59 @@ import static org.junit.Assert.*; * To configure your test environment edit the static fields for id, IP and port. * In the configure method and the connectionType you can define your test scenario. */ - @Ignore public class TomP2PTests { private static final Logger log = LoggerFactory.getLogger(TomP2PTests.class); - /** - * Use UNKNOWN when you want to test the strategy to try first direct, then nat and lat relay - * Use on eof the others when you want to connect only with that mode. Be sure that you can really succeed in that - * mode (e.g. for NAT you need to have a UPnP or NAT PMP enabled router). - */ private enum ConnectionType { - UNKNOWN, - DIRECT, - NAT, - RELAY + UNKNOWN, DIRECT, NAT, RELAY } + // If you want to test in one specific connection mode define it directly, otherwise use UNKNOWN + private static final ConnectionType FORCED_CONNECTION_TYPE = ConnectionType.DIRECT; + + // Typically you run the seed node in localhost to test direct connection. + // If you have a setup where you are not behind a router you can also use a WAN side seed node. + private static final Node BOOTSTRAP_NODE = + (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) ? BootstrapNode.LOCALHOST : BootstrapNode.DIGITAL_OCEAN1; + + private static final PeerAddress BOOTSTRAP_NODE_ADDRESS; + + static { + try { + BOOTSTRAP_NODE_ADDRESS = new PeerAddress( + Number160.createHash(BOOTSTRAP_NODE.getId()), + BOOTSTRAP_NODE.getIp(), BOOTSTRAP_NODE.getPort(), BOOTSTRAP_NODE.getPort()); + } catch (UnknownHostException ex) { + throw new RuntimeException(BOOTSTRAP_NODE.toString(), ex); + } + } + + // If cache is used tests get faster as it doesn't create and bootstrap a new node at every test. + // Need to observe if it can have some side effects. + private static final boolean CACHE_CLIENTS = true; + + // Use that to stress test with repeated run of the test method body + private static final int STRESS_TEST_LOOP_COUNT = 1; + // need to be static to keep them during tests private final static Map cachedPeers = new HashMap<>(); - private String seedId; - private String seedIP; - private int seedPort; private PeerDHT peer1DHT; private PeerDHT peer2DHT; private int client1Port; private int client2Port; private ConnectionType resolvedConnectionType; - - /////////////////////////////////////////////////////////////////////////////////////////// - // Configure - /////////////////////////////////////////////////////////////////////////////////////////// - - // Setup your seed node - private final static String SEED_ID_WAN_1 = "digitalocean1.bitsquare.io"; - private final static String SEED_IP_WAN_1 = "188.226.179.109"; - private final static int SEED_PORT_WAN_1 = 5000; - - // Setup a second seed node used in some tests - private final static String SEED_ID_WAN_2 = "digitalocean2.bitsquare.io"; - private final static String SEED_IP_WAN_2 = "188.226.179.109"; - private final static int SEED_PORT_WAN_2 = 5001; - - // If you want to test in one specific connection mode define it directly, otherwise use UNKNOWN - private final ConnectionType forcedConnectionType = ConnectionType.DIRECT; - - // In port forwarding mode the isSuccess returns false, but the DHT operations succeeded. - // Needs investigation why. Will be removed as far its fixed. - private boolean ignoreSuccessTests = false; - - // If cache is used tests get faster as it doesn't create and bootstrap a new node at every test. - // Need to observe if it can have some side effects. - private boolean cacheClients = true; - - // Use that to stress test with repeated run of the test method body - private int stressTestLoopCount = 1; - @Before public void configure() { - // Typically you run the seed node in localhost to test direct connection. - // If you have a setup where you are not behind a router you can also use a WAN side seed node. - if (forcedConnectionType == ConnectionType.DIRECT) { - seedId = "localhost"; - seedIP = "127.0.0.1"; - seedPort = 5000; - } - else { - seedId = SEED_ID_WAN_1; - seedIP = SEED_IP_WAN_1; - seedPort = SEED_PORT_WAN_1; - } - - // Only in NAT mode we have to deal with that bug. - if (forcedConnectionType == ConnectionType.NAT || resolvedConnectionType == ConnectionType.NAT) - ignoreSuccessTests = true; - client1Port = getNewRandomPort(); client2Port = getNewRandomPort(); } - private int getNewRandomPort() { - // new Ports().tcpPort() returns a random port - int newPort = new Ports().tcpPort(); - while (newPort == client1Port || newPort == client2Port) - newPort = new Ports().tcpPort(); - - return newPort; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Tests - /////////////////////////////////////////////////////////////////////////////////////////// - @After public void shutdown() { - if (!cacheClients) { + if (!CACHE_CLIENTS) { if (peer1DHT != null) peer1DHT.shutdown().awaitUninterruptibly(); if (peer2DHT != null) @@ -170,9 +130,9 @@ public class TomP2PTests { @Test public void bootstrapInUnknownMode() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); - if (forcedConnectionType == ConnectionType.UNKNOWN) + if (FORCED_CONNECTION_TYPE == ConnectionType.UNKNOWN) assertNotNull(bootstrapInUnknownMode("node_1", client1Port)); shutdown(); @@ -181,9 +141,9 @@ public class TomP2PTests { @Test public void testBootstrapDirectConnection() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); - if (forcedConnectionType == ConnectionType.DIRECT) + if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) assertNotNull(bootstrapDirectConnection("node_1", client1Port)); shutdown(); @@ -192,9 +152,9 @@ public class TomP2PTests { @Test public void testBootstrapWithPortForwarding() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); - if (forcedConnectionType == ConnectionType.NAT) + if (FORCED_CONNECTION_TYPE == ConnectionType.NAT) assertNotNull(bootstrapWithPortForwarding("node_1", client1Port)); shutdown(); @@ -203,9 +163,9 @@ public class TomP2PTests { @Test public void testBootstrapInRelayMode() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); - if (forcedConnectionType == ConnectionType.RELAY) + if (FORCED_CONNECTION_TYPE == ConnectionType.RELAY) assertNotNull(bootstrapInRelayMode("node_1", client1Port)); shutdown(); @@ -214,13 +174,13 @@ public class TomP2PTests { @Test public void testPut() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); peer1DHT = getDHTPeer("node_1", client1Port); FuturePut futurePut = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo")).start(); futurePut.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futurePut.isSuccess()); shutdown(); @@ -229,19 +189,19 @@ public class TomP2PTests { @Test public void testPutGet() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); peer1DHT = getDHTPeer("node_1", client1Port); FuturePut futurePut = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo")).start(); futurePut.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futurePut.isSuccess()); peer2DHT = getDHTPeer("node_2", client2Port); FutureGet futureGet = peer2DHT.get(Number160.createHash("key")).start(); futureGet.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futureGet.isSuccess()); assertEquals("hallo", futureGet.data().object()); @@ -251,17 +211,17 @@ public class TomP2PTests { @Test public void testAdd() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); peer1DHT = getDHTPeer("node_1", client1Port); FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start(); futurePut1.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futurePut1.isSuccess()); FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start(); futurePut2.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futurePut2.isSuccess()); shutdown(); @@ -270,24 +230,24 @@ public class TomP2PTests { @Test public void testAddGet() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); peer1DHT = getDHTPeer("node_1", client1Port); FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start(); futurePut1.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futurePut1.isSuccess()); FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start(); futurePut2.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futurePut2.isSuccess()); peer2DHT = getDHTPeer("node_2", client2Port); FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start(); futureGet.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futureGet.isSuccess()); assertTrue(futureGet.dataMap().values().contains(new Data("hallo1"))); @@ -300,17 +260,17 @@ public class TomP2PTests { @Test public void testAddRemove() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); peer1DHT = getDHTPeer("node_1", client1Port); FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start(); futurePut1.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futurePut1.isSuccess()); FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start(); futurePut2.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futurePut2.isSuccess()); @@ -321,12 +281,12 @@ public class TomP2PTests { futureRemove.awaitUninterruptibly(); // That fails sometimes in direct mode and NAT - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futureRemove.isSuccess()); FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start(); futureGet.awaitUninterruptibly(); - if (!ignoreSuccessTests) + if (shouldEvaluateSuccess()) assertTrue(futureGet.isSuccess()); assertTrue(futureGet.dataMap().values().contains(new Data("hallo2"))); @@ -342,9 +302,9 @@ public class TomP2PTests { // That will probably be fixed in a future version of TomP2P @Test public void testSendDirectBetweenLocalPeers() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); - if (forcedConnectionType != ConnectionType.NAT && resolvedConnectionType != ConnectionType.NAT) { + if (FORCED_CONNECTION_TYPE != ConnectionType.NAT && resolvedConnectionType != ConnectionType.NAT) { peer1DHT = getDHTPeer("node_1", client1Port); peer2DHT = getDHTPeer("node_2", client2Port); @@ -380,14 +340,12 @@ public class TomP2PTests { // A node can send a message to another peer which is not in the same LAN. @Test public void testSendDirectToSeedNode() throws Exception { - for (int i = 0; i < stressTestLoopCount; i++) { + for (int i = 0; i < STRESS_TEST_LOOP_COUNT; i++) { configure(); peer1DHT = getDHTPeer("node_1", client1Port); - PeerAddress reachablePeerAddress = new PeerAddress(Number160.createHash(seedId), seedIP, seedPort, - seedPort); - FuturePeerConnection futurePeerConnection = peer1DHT.peer().createPeerConnection - (reachablePeerAddress, 500); + FuturePeerConnection futurePeerConnection = + peer1DHT.peer().createPeerConnection(BOOTSTRAP_NODE_ADDRESS, 500); FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start(); futureDirect.awaitUninterruptibly(); assertTrue(futureDirect.isSuccess()); @@ -398,26 +356,15 @@ public class TomP2PTests { } - /////////////////////////////////////////////////////////////////////////////////////////// - // Bootstrapping - /////////////////////////////////////////////////////////////////////////////////////////// - private Peer bootstrapDirectConnection(String clientId, int clientPort) { - return bootstrapDirectConnection(clientId, clientPort, seedId, seedIP, seedPort); - } - - private Peer bootstrapDirectConnection(String clientId, int clientPort, String seedNodeId, - String seedNodeIP, int seedNodePort) { final String id = clientId + clientPort; - if (cacheClients && cachedPeers.containsKey(id)) { + if (CACHE_CLIENTS && cachedPeers.containsKey(id)) { return cachedPeers.get(id); } Peer peer = null; try { peer = new PeerBuilder(Number160.createHash(clientId)).ports(clientPort).start(); - PeerAddress masterNodeAddress = new PeerAddress(Number160.createHash(seedNodeId), seedNodeIP, seedNodePort, - seedNodePort); - FutureDiscover futureDiscover = peer.discover().peerAddress(masterNodeAddress).start(); + FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); futureDiscover.awaitUninterruptibly(); if (futureDiscover.isSuccess()) { log.info("Discover with direct connection successful. Address = " + futureDiscover.peerAddress()); @@ -440,28 +387,21 @@ public class TomP2PTests { } private Peer bootstrapWithPortForwarding(String clientId, int clientPort) { - return bootstrapWithPortForwarding(clientId, clientPort, seedId, seedIP, seedPort); - } - - private Peer bootstrapWithPortForwarding(String clientId, int clientPort, String seedNodeId, - String seedNodeIP, int seedNodePort) { final String id = clientId + clientPort; - if (cacheClients && cachedPeers.containsKey(id)) { + if (CACHE_CLIENTS && cachedPeers.containsKey(id)) { return cachedPeers.get(id); } Peer peer = null; try { peer = new PeerBuilder(Number160.createHash(clientId)).ports(clientPort).behindFirewall().start(); PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); - PeerAddress masterNodeAddress = new PeerAddress(Number160.createHash(seedNodeId), seedNodeIP, seedNodePort, - seedNodePort); - FutureDiscover futureDiscover = peer.discover().peerAddress(masterNodeAddress).start(); + FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover); futureNAT.awaitUninterruptibly(); if (futureNAT.isSuccess()) { log.info("Automatic port forwarding is setup. Now we do a futureDiscover again. Address = " + futureNAT.peerAddress()); - futureDiscover = peer.discover().peerAddress(masterNodeAddress).start(); + futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); futureDiscover.awaitUninterruptibly(); if (futureDiscover.isSuccess()) { log.info("Discover with automatic port forwarding was successful. Address = " + futureDiscover @@ -493,13 +433,8 @@ public class TomP2PTests { } private Peer bootstrapInRelayMode(String clientId, int clientPort) { - return bootstrapInRelayMode(clientId, clientPort, seedId, seedIP, seedPort); - } - - private Peer bootstrapInRelayMode(String clientId, int clientPort, String seedNodeId, - String seedNodeIP, int seedNodePort) { final String id = clientId + clientPort; - if (cacheClients && cachedPeers.containsKey(id)) { + if (CACHE_CLIENTS && cachedPeers.containsKey(id)) { return cachedPeers.get(id); } @@ -507,9 +442,7 @@ public class TomP2PTests { try { peer = new PeerBuilder(Number160.createHash(clientId)).ports(clientPort).behindFirewall().start(); PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); - PeerAddress masterNodeAddress = new PeerAddress(Number160.createHash(seedNodeId), seedNodeIP, seedNodePort, - seedNodePort); - FutureDiscover futureDiscover = peer.discover().peerAddress(masterNodeAddress).start(); + FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover); FutureRelayNAT futureRelayNAT = peerNAT.startRelay(futureDiscover, futureNAT); futureRelayNAT.awaitUninterruptibly(); @@ -536,63 +469,61 @@ public class TomP2PTests { } private Peer bootstrapInUnknownMode(String clientId, int clientPort) { - return bootstrapInUnknownMode(clientId, clientPort, seedId, seedIP, seedPort); - } - - private Peer bootstrapInUnknownMode(String clientId, int clientPort, String seedNodeId, - String seedNodeIP, int seedNodePort) { resolvedConnectionType = ConnectionType.DIRECT; - Peer peer = bootstrapDirectConnection(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort); + Peer peer = bootstrapDirectConnection(clientId, clientPort); if (peer != null) return peer; resolvedConnectionType = ConnectionType.NAT; - peer = bootstrapWithPortForwarding(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort); + peer = bootstrapWithPortForwarding(clientId, clientPort); if (peer != null) return peer; resolvedConnectionType = ConnectionType.RELAY; - peer = bootstrapInRelayMode(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort); + peer = bootstrapInRelayMode(clientId, clientPort); if (peer != null) return peer; else - log.error("Bootstrapping in all modes failed. Check if the seed node is running. " + - "seedNodeId= " + seedNodeId + - "seedNodeIP= " + seedNodeIP + - "seedNodePort= " + seedNodePort); + log.error("Bootstrapping in all modes failed. Is bootstrap node " + BOOTSTRAP_NODE + "running?"); resolvedConnectionType = null; return peer; } private PeerDHT getDHTPeer(String clientId, int clientPort) { - return getDHTPeer(clientId, clientPort, seedId, seedIP, seedPort); - } - - private PeerDHT getDHTPeer(String clientId, int clientPort, String seedNodeId, - String seedNodeIP, int seedNodePort) { Peer peer; - if (forcedConnectionType == ConnectionType.DIRECT) { - peer = bootstrapDirectConnection(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort); + if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) { + peer = bootstrapDirectConnection(clientId, clientPort); } - else if (forcedConnectionType == ConnectionType.NAT) { - peer = bootstrapWithPortForwarding(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort); + else if (FORCED_CONNECTION_TYPE == ConnectionType.NAT) { + peer = bootstrapWithPortForwarding(clientId, clientPort); } - else if (forcedConnectionType == ConnectionType.RELAY) { - peer = bootstrapInRelayMode(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort); + else if (FORCED_CONNECTION_TYPE == ConnectionType.RELAY) { + peer = bootstrapInRelayMode(clientId, clientPort); } else { - peer = bootstrapInUnknownMode(clientId, clientPort, seedNodeId, seedNodeIP, seedNodePort); + peer = bootstrapInUnknownMode(clientId, clientPort); } if (peer == null) - Assert.fail("Bootstrapping failed. Check if the seed node is running. " + - "forcedConnectionType= " + forcedConnectionType + - " resolvedConnectionType= " + resolvedConnectionType + - " seedNodeId= " + seedNodeId + - " seedNodeIP= " + seedNodeIP + - " seedNodePort= " + seedNodePort); + Assert.fail("Bootstrapping failed." + + " forcedConnectionType= " + FORCED_CONNECTION_TYPE + + " resolvedConnectionType= " + resolvedConnectionType + "." + + " Is bootstrap node " + BOOTSTRAP_NODE + "running?"); return new PeerBuilderDHT(peer).start(); } + + private int getNewRandomPort() { + // new Ports().tcpPort() returns a random port + int newPort = new Ports().tcpPort(); + while (newPort == client1Port || newPort == client2Port) + newPort = new Ports().tcpPort(); + + return newPort; + } + + private boolean shouldEvaluateSuccess() { + return FORCED_CONNECTION_TYPE == ConnectionType.NAT || resolvedConnectionType == ConnectionType.NAT; + } }