mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-19 23:36:00 -04:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
e4743ca469
@ -17,46 +17,37 @@
|
||||
|
||||
package io.bitsquare.app;
|
||||
|
||||
import io.bitsquare.network.BootstrapNode;
|
||||
import io.bitsquare.network.BootstrapNodes;
|
||||
import io.bitsquare.network.Node;
|
||||
|
||||
import net.sourceforge.argparse4j.ArgumentParsers;
|
||||
import net.sourceforge.argparse4j.inf.ArgumentParserException;
|
||||
import net.sourceforge.argparse4j.inf.Namespace;
|
||||
|
||||
/*
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-d PEER_ID, --peerid PEER Seed peer ID (default: "digitalocean1.bitsquare.io")
|
||||
-p PORT, --port PORT IP port to listen on. (default: 5000)
|
||||
-i INTERFACE, --interface INTERFACE Network interface to listen on.
|
||||
-n NAME, --name NAME Append name to application name.
|
||||
*/
|
||||
public class ArgumentParser {
|
||||
|
||||
public static final String PEER_ID_FLAG = "peerid";
|
||||
public static final String PORT_FLAG = "port";
|
||||
public static final String INTERFACE_HINT_FLAG = "interface";
|
||||
public static final String NAME_FLAG = "name";
|
||||
|
||||
private static final Integer PORT_DEFAULT = 5000;
|
||||
private static final String PEER_ID_DEFAULT = BootstrapNode.DIGITAL_OCEAN1.getId();
|
||||
public static final String PEER_ID_DEFAULT = BootstrapNodes.DIGITAL_OCEAN_1.getId();
|
||||
|
||||
private final net.sourceforge.argparse4j.inf.ArgumentParser parser;
|
||||
|
||||
public ArgumentParser() {
|
||||
parser = ArgumentParsers.newArgumentParser("Bitsquare")
|
||||
.defaultHelp(true)
|
||||
.description("Bitsquare - The decentralized bitcoin exchange.");
|
||||
.description("Bitsquare - The decentralized bitcoin exchange");
|
||||
parser.addArgument("-d", "--" + PEER_ID_FLAG)
|
||||
.setDefault(PEER_ID_DEFAULT)
|
||||
.help("Seed peer ID.");
|
||||
.help("Seed peer ID");
|
||||
parser.addArgument("-p", "--" + PORT_FLAG)
|
||||
.setDefault(PORT_DEFAULT)
|
||||
.help("IP port to listen on.");
|
||||
.setDefault(Node.DEFAULT_PORT)
|
||||
.help("Port to listen on");
|
||||
parser.addArgument("-i", "--" + INTERFACE_HINT_FLAG)
|
||||
.help("Network interface to listen on.");
|
||||
.help("Network interface to listen on");
|
||||
parser.addArgument("-n", "--" + NAME_FLAG)
|
||||
.help("Append name to application name.");
|
||||
.help("Name to append name to default application name");
|
||||
}
|
||||
|
||||
public Namespace parseArgs(String... args) {
|
||||
|
@ -21,7 +21,7 @@ import io.bitsquare.app.ArgumentParser;
|
||||
import io.bitsquare.msg.actor.DHTManager;
|
||||
import io.bitsquare.msg.actor.command.InitializePeer;
|
||||
import io.bitsquare.msg.actor.event.PeerInitialized;
|
||||
import io.bitsquare.network.BootstrapNode;
|
||||
import io.bitsquare.network.BootstrapNodes;
|
||||
import io.bitsquare.network.Node;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
@ -56,10 +56,13 @@ public class SeedNode {
|
||||
interfaceHint = namespace.getString(ArgumentParser.INTERFACE_HINT_FLAG);
|
||||
|
||||
int serverPort = Integer.valueOf(namespace.getString(ArgumentParser.PORT_FLAG));
|
||||
String seedID = namespace.getString(ArgumentParser.PEER_ID_FLAG);
|
||||
String seedID = BootstrapNodes.LOCALHOST.getId();
|
||||
if (namespace.getString(ArgumentParser.PEER_ID_FLAG) != null) {
|
||||
seedID = namespace.getString(ArgumentParser.PEER_ID_FLAG);
|
||||
}
|
||||
|
||||
final Set<PeerAddress> peerAddresses = new HashSet<>();
|
||||
for (Node node : BootstrapNode.values()) {
|
||||
for (Node node : BootstrapNodes.all()) {
|
||||
if (!node.getId().equals(seedID)) {
|
||||
try {
|
||||
peerAddresses.add(new PeerAddress(Number160.createHash(node.getId()), node.getIp(),
|
||||
|
@ -30,15 +30,17 @@ import java.util.Properties;
|
||||
|
||||
public class BitcoinModule extends AbstractBitsquareModule {
|
||||
|
||||
private final BitcoinNetwork defaultNetwork;
|
||||
private static final BitcoinNetwork DEFAULT_NETWORK = BitcoinNetwork.REGTEST;
|
||||
|
||||
private final BitcoinNetwork network;
|
||||
|
||||
public BitcoinModule(Properties properties) {
|
||||
this(properties, BitcoinNetwork.REGTEST);
|
||||
this(properties, DEFAULT_NETWORK);
|
||||
}
|
||||
|
||||
public BitcoinModule(Properties properties, BitcoinNetwork defaultNetwork) {
|
||||
public BitcoinModule(Properties properties, BitcoinNetwork network) {
|
||||
super(properties);
|
||||
this.defaultNetwork = defaultNetwork;
|
||||
this.network = network;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,7 +57,7 @@ public class BitcoinModule extends AbstractBitsquareModule {
|
||||
}
|
||||
|
||||
private NetworkParameters network() {
|
||||
String networkName = properties.getProperty("networkType", defaultNetwork.name());
|
||||
String networkName = properties.getProperty("networkType", network.name());
|
||||
|
||||
switch (BitcoinNetwork.valueOf(networkName.toUpperCase())) {
|
||||
case MAINNET:
|
||||
|
@ -18,7 +18,7 @@
|
||||
package io.bitsquare.msg;
|
||||
|
||||
import io.bitsquare.AbstractBitsquareModule;
|
||||
import io.bitsquare.network.BootstrapNode;
|
||||
import io.bitsquare.network.BootstrapNodes;
|
||||
import io.bitsquare.network.Node;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
@ -44,7 +44,7 @@ public class DefaultMessageModule extends AbstractBitsquareModule implements Mes
|
||||
|
||||
bind(Node.class)
|
||||
.annotatedWith(Names.named("bootstrapNode"))
|
||||
.toInstance(BootstrapNode.LOCAL_HOST);
|
||||
.toInstance(BootstrapNodes.LOCALHOST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,32 +17,16 @@
|
||||
|
||||
package io.bitsquare.network;
|
||||
|
||||
public enum BootstrapNode implements Node {
|
||||
LOCAL_HOST("localhost", "127.0.0.1", 5000),
|
||||
DIGITAL_OCEAN1("digitalocean1.bitsquare.io", "188.226.179.109", 5000);
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
private final String id;
|
||||
private final String ip;
|
||||
private final int port;
|
||||
public interface BootstrapNodes {
|
||||
Node LOCALHOST = Node.at("localhost", "127.0.0.1");
|
||||
Node DIGITAL_OCEAN_1 = Node.at("digitalocean1.bitsquare.io", "188.226.179.109");
|
||||
|
||||
BootstrapNode(String id, String ip, int port) {
|
||||
this.id = id;
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
return port;
|
||||
static List<Node> all() {
|
||||
return Arrays.asList(
|
||||
LOCALHOST, DIGITAL_OCEAN_1
|
||||
);
|
||||
}
|
||||
}
|
@ -17,13 +17,66 @@
|
||||
|
||||
package io.bitsquare.network;
|
||||
|
||||
public interface Node {
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
String getId();
|
||||
public final class Node {
|
||||
public static final int DEFAULT_PORT = 5000;
|
||||
|
||||
String getIp();
|
||||
private final String id;
|
||||
private final String ip;
|
||||
private final int port;
|
||||
|
||||
int getPort();
|
||||
private Node(String id, String ip, int port) {
|
||||
this.id = id;
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public static Node at(String id, String ip) {
|
||||
return Node.at(id, ip, DEFAULT_PORT);
|
||||
}
|
||||
|
||||
public static Node at(String id, String ip, int port) {
|
||||
return new Node(id, ip, port);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object)
|
||||
return true;
|
||||
|
||||
if (object == null || getClass() != object.getClass())
|
||||
return false;
|
||||
|
||||
Node that = (Node) object;
|
||||
return Objects.equal(this.id, that.id) &&
|
||||
Objects.equal(this.ip, that.ip) &&
|
||||
Objects.equal(this.port, that.port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(id, ip, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toStringHelper(Node.class.getSimpleName())
|
||||
.add("id", id)
|
||||
.add("ip", ip)
|
||||
.add("port", port)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
package io.bitsquare.msg;
|
||||
|
||||
import io.bitsquare.network.Node;
|
||||
|
||||
import net.tomp2p.dht.PeerBuilderDHT;
|
||||
import net.tomp2p.dht.PeerDHT;
|
||||
import net.tomp2p.nat.PeerBuilderNAT;
|
||||
@ -37,7 +39,7 @@ public class SeedNodeForTesting {
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Define your seed node IP and port
|
||||
// "127.0.0.1" for localhost or SEED_ID_WAN_1
|
||||
new SeedNodeForTesting().startSeedNode("localhost", 5000);
|
||||
new SeedNodeForTesting().startSeedNode("localhost", Node.DEFAULT_PORT);
|
||||
}
|
||||
|
||||
public Thread startSeedNode(String seedNodeId, int seedNodePort) {
|
||||
|
@ -17,8 +17,14 @@
|
||||
|
||||
package io.bitsquare.msg;
|
||||
|
||||
import io.bitsquare.network.BootstrapNodes;
|
||||
import io.bitsquare.network.Node;
|
||||
import io.bitsquare.util.Repeat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -63,104 +69,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) ? BootstrapNodes.LOCALHOST : BootstrapNodes.DIGITAL_OCEAN_1;
|
||||
|
||||
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 to stress tests by repeating them
|
||||
private static final int STRESS_TEST_COUNT = 1;
|
||||
|
||||
// need to be static to keep them during tests
|
||||
private final static Map<String, Peer> 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;
|
||||
|
||||
public void setUp() {
|
||||
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) {
|
||||
public void tearDown() {
|
||||
if (!CACHE_CLIENTS) {
|
||||
if (peer1DHT != null)
|
||||
peer1DHT.shutdown().awaitUninterruptibly();
|
||||
if (peer2DHT != null)
|
||||
@ -169,171 +130,134 @@ public class TomP2PTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void bootstrapInUnknownMode() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
if (forcedConnectionType == ConnectionType.UNKNOWN)
|
||||
assertNotNull(bootstrapInUnknownMode("node_1", client1Port));
|
||||
|
||||
shutdown();
|
||||
}
|
||||
if (FORCED_CONNECTION_TYPE == ConnectionType.UNKNOWN)
|
||||
assertNotNull(bootstrapInUnknownMode("node_1", client1Port));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testBootstrapDirectConnection() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
if (forcedConnectionType == ConnectionType.DIRECT)
|
||||
assertNotNull(bootstrapDirectConnection("node_1", client1Port));
|
||||
|
||||
shutdown();
|
||||
}
|
||||
if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT)
|
||||
assertNotNull(bootstrapDirectConnection("node_1", client1Port));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testBootstrapWithPortForwarding() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
if (forcedConnectionType == ConnectionType.NAT)
|
||||
assertNotNull(bootstrapWithPortForwarding("node_1", client1Port));
|
||||
|
||||
shutdown();
|
||||
}
|
||||
if (FORCED_CONNECTION_TYPE == ConnectionType.NAT)
|
||||
assertNotNull(bootstrapWithPortForwarding("node_1", client1Port));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testBootstrapInRelayMode() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
if (forcedConnectionType == ConnectionType.RELAY)
|
||||
if (FORCED_CONNECTION_TYPE == ConnectionType.RELAY)
|
||||
assertNotNull(bootstrapInRelayMode("node_1", client1Port));
|
||||
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testPut() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; 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();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testPutGet() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo")).start();
|
||||
futurePut.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futurePut.isSuccess());
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo")).start();
|
||||
futurePut.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut.isSuccess());
|
||||
|
||||
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
FutureGet futureGet = peer2DHT.get(Number160.createHash("key")).start();
|
||||
futureGet.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futureGet.isSuccess());
|
||||
assertEquals("hallo", futureGet.data().object());
|
||||
|
||||
shutdown();
|
||||
}
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
FutureGet futureGet = peer2DHT.get(Number160.createHash("key")).start();
|
||||
futureGet.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futureGet.isSuccess());
|
||||
assertEquals("hallo", futureGet.data().object());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testAdd() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futurePut1.isSuccess());
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut1.isSuccess());
|
||||
|
||||
FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start();
|
||||
futurePut2.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futurePut2.isSuccess());
|
||||
|
||||
shutdown();
|
||||
}
|
||||
FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start();
|
||||
futurePut2.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut2.isSuccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testAddGet() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futurePut1.isSuccess());
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut1.isSuccess());
|
||||
|
||||
FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start();
|
||||
futurePut2.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futurePut2.isSuccess());
|
||||
FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start();
|
||||
futurePut2.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut2.isSuccess());
|
||||
|
||||
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start();
|
||||
futureGet.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futureGet.isSuccess());
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start();
|
||||
futureGet.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futureGet.isSuccess());
|
||||
|
||||
assertTrue(futureGet.dataMap().values().contains(new Data("hallo1")));
|
||||
assertTrue(futureGet.dataMap().values().contains(new Data("hallo2")));
|
||||
assertTrue(futureGet.dataMap().values().size() == 2);
|
||||
|
||||
shutdown();
|
||||
}
|
||||
assertTrue(futureGet.dataMap().values().contains(new Data("hallo1")));
|
||||
assertTrue(futureGet.dataMap().values().contains(new Data("hallo2")));
|
||||
assertTrue(futureGet.dataMap().values().size() == 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testAddRemove() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futurePut1.isSuccess());
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start();
|
||||
futurePut1.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut1.isSuccess());
|
||||
|
||||
FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start();
|
||||
futurePut2.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futurePut2.isSuccess());
|
||||
FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start();
|
||||
futurePut2.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futurePut2.isSuccess());
|
||||
|
||||
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
Number160 contentKey = new Data("hallo1").hash();
|
||||
FutureRemove futureRemove = peer2DHT.remove(Number160.createHash("locationKey")).contentKey(contentKey)
|
||||
.start();
|
||||
futureRemove.awaitUninterruptibly();
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
Number160 contentKey = new Data("hallo1").hash();
|
||||
FutureRemove futureRemove = peer2DHT.remove(Number160.createHash("locationKey")).contentKey(contentKey)
|
||||
.start();
|
||||
futureRemove.awaitUninterruptibly();
|
||||
|
||||
// That fails sometimes in direct mode and NAT
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futureRemove.isSuccess());
|
||||
// That fails sometimes in direct mode and NAT
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futureRemove.isSuccess());
|
||||
|
||||
FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start();
|
||||
futureGet.awaitUninterruptibly();
|
||||
if (!ignoreSuccessTests)
|
||||
assertTrue(futureGet.isSuccess());
|
||||
FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start();
|
||||
futureGet.awaitUninterruptibly();
|
||||
if (shouldEvaluateSuccess())
|
||||
assertTrue(futureGet.isSuccess());
|
||||
|
||||
assertTrue(futureGet.dataMap().values().contains(new Data("hallo2")));
|
||||
assertTrue(futureGet.dataMap().values().size() == 1);
|
||||
|
||||
shutdown();
|
||||
}
|
||||
assertTrue(futureGet.dataMap().values().contains(new Data("hallo2")));
|
||||
assertTrue(futureGet.dataMap().values().size() == 1);
|
||||
}
|
||||
|
||||
|
||||
@ -341,83 +265,62 @@ public class TomP2PTests {
|
||||
// So if both clients are behind NAT they cannot send direct message to each other.
|
||||
// That will probably be fixed in a future version of TomP2P
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testSendDirectBetweenLocalPeers() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
if (forcedConnectionType != ConnectionType.NAT && resolvedConnectionType != ConnectionType.NAT) {
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
if (FORCED_CONNECTION_TYPE != ConnectionType.NAT && resolvedConnectionType != ConnectionType.NAT) {
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
peer2DHT = getDHTPeer("node_2", client2Port);
|
||||
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
|
||||
final StringBuilder result = new StringBuilder();
|
||||
peer2DHT.peer().objectDataReply((sender, request) -> {
|
||||
countDownLatch.countDown();
|
||||
result.append(String.valueOf(request));
|
||||
return "pong";
|
||||
});
|
||||
FuturePeerConnection futurePeerConnection = peer1DHT.peer().createPeerConnection(peer2DHT.peer()
|
||||
.peerAddress(), 500);
|
||||
FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start();
|
||||
futureDirect.awaitUninterruptibly();
|
||||
final StringBuilder result = new StringBuilder();
|
||||
peer2DHT.peer().objectDataReply((sender, request) -> {
|
||||
countDownLatch.countDown();
|
||||
result.append(String.valueOf(request));
|
||||
return "pong";
|
||||
});
|
||||
FuturePeerConnection futurePeerConnection = peer1DHT.peer().createPeerConnection(peer2DHT.peer()
|
||||
.peerAddress(), 500);
|
||||
FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start();
|
||||
futureDirect.awaitUninterruptibly();
|
||||
|
||||
|
||||
countDownLatch.await(3, TimeUnit.SECONDS);
|
||||
if (countDownLatch.getCount() > 0)
|
||||
Assert.fail("The test method did not complete successfully!");
|
||||
countDownLatch.await(3, TimeUnit.SECONDS);
|
||||
if (countDownLatch.getCount() > 0)
|
||||
Assert.fail("The test method did not complete successfully!");
|
||||
|
||||
assertEquals("hallo", result.toString());
|
||||
assertTrue(futureDirect.isSuccess());
|
||||
log.debug(futureDirect.object().toString());
|
||||
assertEquals("pong", futureDirect.object());
|
||||
}
|
||||
|
||||
shutdown();
|
||||
assertEquals("hallo", result.toString());
|
||||
assertTrue(futureDirect.isSuccess());
|
||||
log.debug(futureDirect.object().toString());
|
||||
assertEquals("pong", futureDirect.object());
|
||||
}
|
||||
}
|
||||
|
||||
// That test should always succeed as we use the server seed node as receiver.
|
||||
// A node can send a message to another peer which is not in the same LAN.
|
||||
@Test
|
||||
@Repeat(STRESS_TEST_COUNT)
|
||||
public void testSendDirectToSeedNode() throws Exception {
|
||||
for (int i = 0; i < stressTestLoopCount; i++) {
|
||||
configure();
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
PeerAddress reachablePeerAddress = new PeerAddress(Number160.createHash(seedId), seedIP, seedPort,
|
||||
seedPort);
|
||||
peer1DHT = getDHTPeer("node_1", client1Port);
|
||||
|
||||
FuturePeerConnection futurePeerConnection = peer1DHT.peer().createPeerConnection
|
||||
(reachablePeerAddress, 500);
|
||||
FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start();
|
||||
futureDirect.awaitUninterruptibly();
|
||||
assertTrue(futureDirect.isSuccess());
|
||||
assertEquals("pong", futureDirect.object());
|
||||
|
||||
shutdown();
|
||||
}
|
||||
FuturePeerConnection futurePeerConnection =
|
||||
peer1DHT.peer().createPeerConnection(BOOTSTRAP_NODE_ADDRESS, 500);
|
||||
FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start();
|
||||
futureDirect.awaitUninterruptibly();
|
||||
assertTrue(futureDirect.isSuccess());
|
||||
assertEquals("pong", futureDirect.object());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 +343,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 +389,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 +398,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 +425,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;
|
||||
}
|
||||
}
|
||||
|
54
src/test/java/io/bitsquare/network/NodeTests.java
Normal file
54
src/test/java/io/bitsquare/network/NodeTests.java
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.network;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class NodeTests {
|
||||
|
||||
@Test
|
||||
public void testEqualsAndHashCode() {
|
||||
Node node1a = Node.at("bitsquare1.example.com", "203.0.113.1");
|
||||
Node node1b = Node.at("bitsquare1.example.com", "203.0.113.1");
|
||||
|
||||
assertThat(node1a, equalTo(node1a));
|
||||
|
||||
assertThat(node1a, equalTo(node1b));
|
||||
assertThat(node1b, equalTo(node1a));
|
||||
|
||||
assertThat(node1a, not((Object) equalTo(null)));
|
||||
assertThat(node1a, not((Object) equalTo("not a node")));
|
||||
|
||||
assertThat(node1a, not(equalTo(Node.at("bitsquare2.example.com", node1a.getIp()))));
|
||||
assertThat(node1a, not(equalTo(Node.at(node1a.getId(), "203.0.113.2"))));
|
||||
assertThat(node1a, not(equalTo(Node.at(node1a.getId(), node1a.getIp(), Node.DEFAULT_PORT + 1))));
|
||||
|
||||
Node node2 = Node.at("bitsquare2.example.com", "203.0.113.2");
|
||||
assertThat(node1a.hashCode(), equalTo(node1b.hashCode()));
|
||||
assertThat(node1a.hashCode(), not(equalTo(node2.hashCode())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
Node node = Node.at("bitsquare1.example.com", "203.0.113.1", 5001);
|
||||
assertThat(node.toString(), equalTo("Node{id=bitsquare1.example.com, ip=203.0.113.1, port=5001}"));
|
||||
}
|
||||
}
|
38
src/test/java/io/bitsquare/util/Repeat.java
Normal file
38
src/test/java/io/bitsquare/util/Repeat.java
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.util;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Method-level annotation to be used in connection with {@link RepeatRule} to cause a
|
||||
* given {@link org.junit.Test} method to be repeated a specified number of times.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Repeat {
|
||||
|
||||
/**
|
||||
* Specifies the number of times to repeat the annotated {@link org.junit.Test}.
|
||||
*/
|
||||
int value();
|
||||
}
|
57
src/test/java/io/bitsquare/util/RepeatRule.java
Normal file
57
src/test/java/io/bitsquare/util/RepeatRule.java
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.util;
|
||||
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
/**
|
||||
* @see {@link Repeat}
|
||||
*/
|
||||
public class RepeatRule implements TestRule {
|
||||
|
||||
private static class RepeatStatement extends Statement {
|
||||
|
||||
private final int times;
|
||||
private final Statement statement;
|
||||
|
||||
private RepeatStatement(int times, Statement statement) {
|
||||
this.times = times;
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
for (int i = 0; i < times; i++) {
|
||||
statement.evaluate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement statement, Description description) {
|
||||
Statement result = statement;
|
||||
Repeat repeat = description.getAnnotation(Repeat.class);
|
||||
if (repeat != null) {
|
||||
int times = repeat.value();
|
||||
result = new RepeatStatement(times, statement);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
68
src/test/java/io/bitsquare/util/RepeatRuleTests.java
Normal file
68
src/test/java/io/bitsquare/util/RepeatRuleTests.java
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.util;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class RepeatRuleTests {
|
||||
|
||||
private static final int EXPECTED_COUNT = 10;
|
||||
private static int ACTUAL_BEFORE_COUNT;
|
||||
private static int ACTUAL_TEST_COUNT;
|
||||
private static int ACTUAL_AFTER_COUNT;
|
||||
|
||||
public @Rule RepeatRule repeatRule = new RepeatRule();
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeTests() {
|
||||
ACTUAL_BEFORE_COUNT = 0;
|
||||
ACTUAL_TEST_COUNT = 0;
|
||||
ACTUAL_AFTER_COUNT = 0;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ACTUAL_BEFORE_COUNT++;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Repeat(EXPECTED_COUNT)
|
||||
public void shouldBeRepeated() {
|
||||
ACTUAL_TEST_COUNT++;
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ACTUAL_AFTER_COUNT++;
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterTests() {
|
||||
assertThat(ACTUAL_BEFORE_COUNT, equalTo(EXPECTED_COUNT));
|
||||
assertThat(ACTUAL_TEST_COUNT, equalTo(EXPECTED_COUNT));
|
||||
assertThat(ACTUAL_AFTER_COUNT, equalTo(EXPECTED_COUNT));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user