mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-26 00:15:18 -04:00
updated to master branch of tomp2p. refactored messaging. bootstrapping to seed node (server supported). right management.
This commit is contained in:
parent
222045ca5a
commit
57d5ddcc4f
54 changed files with 3284 additions and 717 deletions
18
src/test/java/io/bitsquare/BitSquareTestSuite.java
Normal file
18
src/test/java/io/bitsquare/BitSquareTestSuite.java
Normal file
|
@ -0,0 +1,18 @@
|
|||
package io.bitsquare;
|
||||
|
||||
import io.bitsquare.btc.BtcValidatorTest;
|
||||
import io.bitsquare.gui.util.BitSquareConverterTest;
|
||||
import io.bitsquare.gui.util.BitSquareValidatorTest;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
BtcValidatorTest.class,
|
||||
BitSquareConverterTest.class,
|
||||
BitSquareValidatorTest.class,
|
||||
})
|
||||
|
||||
public class BitSquareTestSuite
|
||||
{
|
||||
}
|
34
src/test/java/io/bitsquare/btc/BtcValidatorTest.java
Normal file
34
src/test/java/io/bitsquare/btc/BtcValidatorTest.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
package io.bitsquare.btc;
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import java.math.BigInteger;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class BtcValidatorTest
|
||||
{
|
||||
@Test
|
||||
public void testIsMinSpendableAmount()
|
||||
{
|
||||
BigInteger amount = null;
|
||||
//noinspection ConstantConditions
|
||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||
|
||||
amount = BigInteger.ZERO;
|
||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||
|
||||
amount = FeePolicy.TX_FEE;
|
||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||
|
||||
amount = Transaction.MIN_NONDUST_OUTPUT;
|
||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||
|
||||
amount = FeePolicy.TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT);
|
||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||
|
||||
amount = FeePolicy.TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.ONE);
|
||||
assertTrue("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.bitsquare.gui.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class BitSquareConverterTest
|
||||
{
|
||||
|
||||
@Test
|
||||
public void testStringToDouble()
|
||||
{
|
||||
|
||||
assertEquals(1, BitSquareConverter.stringToDouble("1"), 0);
|
||||
assertEquals(0.1, BitSquareConverter.stringToDouble("0.1"), 0);
|
||||
assertEquals(0.1, BitSquareConverter.stringToDouble("0,1"), 0);
|
||||
assertEquals(1, BitSquareConverter.stringToDouble("1.0"), 0);
|
||||
assertEquals(1, BitSquareConverter.stringToDouble("1,0"), 0);
|
||||
|
||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("1,000.2"), 0);
|
||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("1,000.2"), 0);
|
||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(null), 0);
|
||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(""), 0);
|
||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(""), 0);
|
||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("."), 0);
|
||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(","), 0);
|
||||
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("a"), 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package io.bitsquare.gui.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class BitSquareValidatorTest
|
||||
{
|
||||
@Test
|
||||
public void testValidateStringAsDouble()
|
||||
{
|
||||
assertTrue(BitSquareValidator.validateStringAsDouble("0"));
|
||||
assertTrue(BitSquareValidator.validateStringAsDouble("1"));
|
||||
assertTrue(BitSquareValidator.validateStringAsDouble("0,1"));
|
||||
assertTrue(BitSquareValidator.validateStringAsDouble("0.01"));
|
||||
|
||||
assertFalse(BitSquareValidator.validateStringAsDouble(""));
|
||||
assertFalse(BitSquareValidator.validateStringAsDouble("a"));
|
||||
assertFalse(BitSquareValidator.validateStringAsDouble("0.0.1"));
|
||||
assertFalse(BitSquareValidator.validateStringAsDouble("1,000.1"));
|
||||
assertFalse(BitSquareValidator.validateStringAsDouble("1.000,1"));
|
||||
assertFalse(BitSquareValidator.validateStringAsDouble(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateStringNotEmpty()
|
||||
{
|
||||
assertTrue(BitSquareValidator.validateStringNotEmpty("a"));
|
||||
assertTrue(BitSquareValidator.validateStringNotEmpty("123"));
|
||||
|
||||
assertFalse(BitSquareValidator.validateStringNotEmpty(""));
|
||||
assertFalse(BitSquareValidator.validateStringNotEmpty(" "));
|
||||
assertFalse(BitSquareValidator.validateStringNotEmpty(null));
|
||||
}
|
||||
|
||||
|
||||
}
|
375
src/test/java/io/bitsquare/msg/P2PNodeTest.java
Normal file
375
src/test/java/io/bitsquare/msg/P2PNodeTest.java
Normal file
|
@ -0,0 +1,375 @@
|
|||
package io.bitsquare.msg;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.util.Random;
|
||||
import net.tomp2p.dht.FutureGet;
|
||||
import net.tomp2p.dht.FuturePut;
|
||||
import net.tomp2p.dht.FutureRemove;
|
||||
import net.tomp2p.dht.PeerDHT;
|
||||
import net.tomp2p.futures.FutureDirect;
|
||||
import net.tomp2p.peers.Number160;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import net.tomp2p.rpc.ObjectDataReply;
|
||||
import net.tomp2p.storage.Data;
|
||||
import net.tomp2p.utils.Utils;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class P2PNodeTest
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(P2PNodeTest.class);
|
||||
|
||||
final private static Random rnd = new Random(42L);
|
||||
|
||||
@Test
|
||||
public void testSendData() throws Exception
|
||||
{
|
||||
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, 41001);
|
||||
PeerDHT master = peers[0];
|
||||
PeerDHT client = peers[1];
|
||||
PeerDHT otherPeer = peers[2];
|
||||
UtilsDHT2.perfectRouting(peers);
|
||||
|
||||
|
||||
for (final PeerDHT peer : peers)
|
||||
{
|
||||
peer.peer().objectDataReply(new ObjectDataReply()
|
||||
{
|
||||
@Override
|
||||
public Object reply(PeerAddress sender, Object request) throws Exception
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
|
||||
keyGen.initialize(1024);
|
||||
KeyPair keyPairClient = keyGen.genKeyPair();
|
||||
KeyPair keyPairOtherPeer = keyGen.genKeyPair();
|
||||
|
||||
P2PNode node;
|
||||
Number160 locationKey;
|
||||
Object object;
|
||||
FutureDirect futureDirect;
|
||||
|
||||
node = new P2PNode(keyPairClient, client);
|
||||
object = "clients data";
|
||||
futureDirect = node.sendData(otherPeer.peerAddress(), object);
|
||||
futureDirect.awaitUninterruptibly();
|
||||
|
||||
assertTrue(futureDirect.isSuccess());
|
||||
// we return true from objectDataReply
|
||||
assertTrue((Boolean) futureDirect.object());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProtectedPutGet() throws Exception
|
||||
{
|
||||
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, 41001);
|
||||
PeerDHT master = peers[0];
|
||||
PeerDHT client = peers[1];
|
||||
PeerDHT otherPeer = peers[2];
|
||||
UtilsDHT2.perfectRouting(peers);
|
||||
|
||||
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
|
||||
keyGen.initialize(1024);
|
||||
KeyPair keyPairClient = keyGen.genKeyPair();
|
||||
KeyPair keyPairOtherPeer = keyGen.genKeyPair();
|
||||
|
||||
P2PNode node;
|
||||
Number160 locationKey;
|
||||
Data data;
|
||||
FuturePut futurePut;
|
||||
FutureGet futureGet;
|
||||
|
||||
// otherPeer tries to squat clients location store
|
||||
// he can do it but as he has not the domain key of the client he cannot do any harm
|
||||
// he only can store und that path: locationKey.otherPeerDomainKey.data
|
||||
node = new P2PNode(keyPairOtherPeer, otherPeer);
|
||||
locationKey = Number160.createHash("clients location");
|
||||
data = new Data("otherPeer data");
|
||||
futurePut = node.putDomainProtectedData(locationKey, data);
|
||||
futurePut.awaitUninterruptibly();
|
||||
assertTrue(futurePut.isSuccess());
|
||||
|
||||
futureGet = node.getDomainProtectedData(locationKey, keyPairOtherPeer.getPublic());
|
||||
futureGet.awaitUninterruptibly();
|
||||
assertTrue(futureGet.isSuccess());
|
||||
assertEquals("otherPeer data", futureGet.data().object());
|
||||
|
||||
// client store his data und his domainkey, no problem with previous occupied
|
||||
// he only can store und that path: locationKey.clientDomainKey.data
|
||||
node = new P2PNode(keyPairClient, client);
|
||||
locationKey = Number160.createHash("clients location");
|
||||
data = new Data("client data");
|
||||
futurePut = node.putDomainProtectedData(locationKey, data);
|
||||
futurePut.awaitUninterruptibly();
|
||||
assertTrue(futurePut.isSuccess());
|
||||
|
||||
futureGet = node.getDomainProtectedData(locationKey, keyPairClient.getPublic());
|
||||
futureGet.awaitUninterruptibly();
|
||||
assertTrue(futureGet.isSuccess());
|
||||
assertEquals("client data", futureGet.data().object());
|
||||
|
||||
// also other peers can read that data if they know the public key of the client
|
||||
node = new P2PNode(keyPairOtherPeer, otherPeer);
|
||||
futureGet = node.getDomainProtectedData(locationKey, keyPairClient.getPublic());
|
||||
futureGet.awaitUninterruptibly();
|
||||
assertTrue(futureGet.isSuccess());
|
||||
assertEquals("client data", futureGet.data().object());
|
||||
|
||||
|
||||
// other peer try to use pub key of other peer as domain key hash.
|
||||
// must fail as he don't have the full key pair (private key of client missing)
|
||||
locationKey = Number160.createHash("clients location");
|
||||
data = new Data("otherPeer data hack");
|
||||
|
||||
data.protectEntry(keyPairOtherPeer);
|
||||
// he use the pub key from the client
|
||||
final Number160 keyHash = Utils.makeSHAHash(keyPairClient.getPublic().getEncoded());
|
||||
futurePut = otherPeer.put(locationKey).data(data).keyPair(keyPairOtherPeer).domainKey(keyHash).protectDomain().start();
|
||||
|
||||
futurePut.awaitUninterruptibly();
|
||||
assertFalse(futurePut.isSuccess());
|
||||
|
||||
// he can read his prev. stored data
|
||||
node = new P2PNode(keyPairOtherPeer, otherPeer);
|
||||
futureGet = node.getDomainProtectedData(locationKey, keyPairOtherPeer.getPublic());
|
||||
futureGet.awaitUninterruptibly();
|
||||
assertTrue(futureGet.isSuccess());
|
||||
assertEquals("otherPeer data", futureGet.data().object());
|
||||
|
||||
// he can read clients data
|
||||
futureGet = node.getDomainProtectedData(locationKey, keyPairClient.getPublic());
|
||||
futureGet.awaitUninterruptibly();
|
||||
assertTrue(futureGet.isSuccess());
|
||||
assertEquals("client data", futureGet.data().object());
|
||||
|
||||
master.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddToListGetList() throws Exception
|
||||
{
|
||||
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, 41001);
|
||||
PeerDHT master = peers[0];
|
||||
PeerDHT client = peers[1];
|
||||
PeerDHT otherPeer = peers[2];
|
||||
UtilsDHT2.perfectRouting(peers);
|
||||
|
||||
P2PNode node;
|
||||
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
|
||||
keyGen.initialize(1024);
|
||||
KeyPair keyPairClient = keyGen.genKeyPair();
|
||||
KeyPair keyPairOtherPeer = keyGen.genKeyPair();
|
||||
|
||||
Number160 locationKey;
|
||||
Data data;
|
||||
FuturePut futurePut;
|
||||
FutureGet futureGet;
|
||||
|
||||
// client add a value
|
||||
node = new P2PNode(keyPairClient, client);
|
||||
locationKey = Number160.createHash("add to list clients location");
|
||||
data = new Data("add to list client data1");
|
||||
Data data_1 = data;
|
||||
futurePut = node.addProtectedData(locationKey, data);
|
||||
futurePut.awaitUninterruptibly();
|
||||
assertTrue(futurePut.isSuccess());
|
||||
|
||||
data = new Data("add to list client data2");
|
||||
Data data_2 = data;
|
||||
futurePut = node.addProtectedData(locationKey, data);
|
||||
futurePut.awaitUninterruptibly();
|
||||
assertTrue(futurePut.isSuccess());
|
||||
|
||||
futureGet = node.getDataMap(locationKey);
|
||||
futureGet.awaitUninterruptibly();
|
||||
assertTrue(futureGet.isSuccess());
|
||||
boolean foundData1 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list client data1");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
boolean foundData2 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list client data2");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
assertTrue(foundData1);
|
||||
assertTrue(foundData2);
|
||||
assertEquals(2, futureGet.dataMap().values().size());
|
||||
|
||||
|
||||
// other peer tried to overwrite that entry
|
||||
// but will not succeed, instead he will add a new entry.
|
||||
// TODO investigate why it is not possible to overwrite the entry with that method
|
||||
// The protection entry with the key does not make any difference as also the client himself cannot overwrite any entry
|
||||
// http://tomp2p.net/doc/P2P-with-TomP2P-1.pdf
|
||||
// "add(location_key, value) is translated to put(location_key, hash(value), value)"
|
||||
|
||||
// fake content key with content key from previous clients entry
|
||||
Number160 contentKey = Number160.createHash("add to list client data1");
|
||||
|
||||
data = new Data("add to list other peer data HACK!");
|
||||
data.protectEntry(keyPairOtherPeer); // also with client key it does not work...
|
||||
futurePut = otherPeer.put(locationKey).data(contentKey, data).keyPair(keyPairOtherPeer).start();
|
||||
futurePut.awaitUninterruptibly();
|
||||
assertTrue(futurePut.isSuccess());
|
||||
|
||||
node = new P2PNode(keyPairOtherPeer, otherPeer);
|
||||
futureGet = node.getDataMap(locationKey);
|
||||
futureGet.awaitUninterruptibly();
|
||||
assertTrue(futureGet.isSuccess());
|
||||
|
||||
foundData1 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list client data1");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
foundData2 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list client data2");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
boolean foundData3 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list other peer data HACK!");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
assertTrue(foundData1);
|
||||
assertTrue(foundData2);
|
||||
assertTrue(foundData3);
|
||||
assertEquals(3, futureGet.dataMap().values().size());
|
||||
|
||||
|
||||
// client removes his entry -> OK
|
||||
node = new P2PNode(keyPairClient, client);
|
||||
FutureRemove futureRemove = node.removeFromDataMap(locationKey, data_1);
|
||||
futureRemove.awaitUninterruptibly();
|
||||
assertTrue(futureRemove.isSuccess());
|
||||
|
||||
futureGet = node.getDataMap(locationKey);
|
||||
futureGet.awaitUninterruptibly();
|
||||
assertTrue(futureGet.isSuccess());
|
||||
|
||||
foundData1 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list client data1");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
foundData2 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list client data2");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
foundData3 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list other peer data HACK!");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
assertFalse(foundData1);
|
||||
assertTrue(foundData2);
|
||||
assertTrue(foundData3);
|
||||
assertEquals(2, futureGet.dataMap().values().size());
|
||||
|
||||
|
||||
// otherPeer tries to removes client entry -> FAIL
|
||||
node = new P2PNode(keyPairOtherPeer, otherPeer);
|
||||
futureRemove = node.removeFromDataMap(locationKey, data_2);
|
||||
futureRemove.awaitUninterruptibly();
|
||||
assertFalse(futureRemove.isSuccess());
|
||||
|
||||
futureGet = node.getDataMap(locationKey);
|
||||
futureGet.awaitUninterruptibly();
|
||||
assertTrue(futureGet.isSuccess());
|
||||
|
||||
foundData1 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list client data1");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
foundData2 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list client data2");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
foundData3 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
|
||||
try
|
||||
{
|
||||
return data1.object().equals("add to list other peer data HACK!");
|
||||
} catch (ClassNotFoundException | IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
assertFalse(foundData1);
|
||||
assertTrue(foundData2);
|
||||
assertTrue(foundData3);
|
||||
assertEquals(2, futureGet.dataMap().values().size());
|
||||
|
||||
|
||||
master.shutdown();
|
||||
}
|
||||
|
||||
|
||||
}
|
412
src/test/java/io/bitsquare/msg/UtilsDHT2.java
Normal file
412
src/test/java/io/bitsquare/msg/UtilsDHT2.java
Normal file
|
@ -0,0 +1,412 @@
|
|||
/*
|
||||
* Copyright 2012 Thomas Bocek
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package io.bitsquare.msg;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.*;
|
||||
import net.tomp2p.connection.Bindings;
|
||||
import net.tomp2p.dht.PeerBuilderDHT;
|
||||
import net.tomp2p.dht.PeerDHT;
|
||||
import net.tomp2p.futures.FutureBootstrap;
|
||||
import net.tomp2p.futures.FutureDiscover;
|
||||
import net.tomp2p.message.Message;
|
||||
import net.tomp2p.message.Message.Type;
|
||||
import net.tomp2p.p2p.AutomaticFuture;
|
||||
import net.tomp2p.p2p.Peer;
|
||||
import net.tomp2p.p2p.PeerBuilder;
|
||||
import net.tomp2p.peers.*;
|
||||
|
||||
public class UtilsDHT2
|
||||
{
|
||||
/**
|
||||
* Used to make the testcases predictable. Used as an input for {@link java.util.Random}.
|
||||
*/
|
||||
public static final long THE_ANSWER = 42L;
|
||||
|
||||
/**
|
||||
* Having two peers in a network, the seed needs to be different, otherwise we create a peer with the same id twice.
|
||||
*/
|
||||
public static final long THE_ANSWER2 = 43L;
|
||||
|
||||
public static Message createDummyMessage() throws UnknownHostException
|
||||
{
|
||||
return createDummyMessage(false, false);
|
||||
}
|
||||
|
||||
public static Message createDummyMessage(boolean firewallUDP, boolean firewallTCP)
|
||||
throws UnknownHostException
|
||||
{
|
||||
return createDummyMessage(new Number160("0x4321"), "127.0.0.1", 8001, 8002, new Number160("0x1234"),
|
||||
"127.0.0.1", 8003, 8004, (byte) 0, Type.REQUEST_1, firewallUDP, firewallTCP);
|
||||
}
|
||||
|
||||
public static PeerAddress createAddress(Number160 id) throws UnknownHostException
|
||||
{
|
||||
return createAddress(id, "127.0.0.1", 8005, 8006, false, false);
|
||||
}
|
||||
|
||||
public static PeerAddress createAddress() throws UnknownHostException
|
||||
{
|
||||
return createAddress(new Number160("0x5678"), "127.0.0.1", 8005, 8006, false, false);
|
||||
}
|
||||
|
||||
public static PeerAddress createAddress(int id) throws UnknownHostException
|
||||
{
|
||||
return createAddress(new Number160(id), "127.0.0.1", 8005, 8006, false, false);
|
||||
}
|
||||
|
||||
public static PeerAddress createAddress(String id) throws UnknownHostException
|
||||
{
|
||||
return createAddress(new Number160(id), "127.0.0.1", 8005, 8006, false, false);
|
||||
}
|
||||
|
||||
public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender,
|
||||
int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException
|
||||
{
|
||||
InetAddress inetSend = InetAddress.getByName(inetSender);
|
||||
PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender);
|
||||
PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, firewallTCP, firewallUDP, false,
|
||||
PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES);
|
||||
return n1;
|
||||
}
|
||||
|
||||
public static Message createDummyMessage(Number160 idSender, String inetSender, int tcpPortSendor,
|
||||
int udpPortSender, Number160 idRecipien, String inetRecipient, int tcpPortRecipient,
|
||||
int udpPortRecipient, byte command, Type type, boolean firewallUDP, boolean firewallTCP)
|
||||
throws UnknownHostException
|
||||
{
|
||||
Message message = new Message();
|
||||
PeerAddress n1 = createAddress(idSender, inetSender, tcpPortSendor, udpPortSender, firewallUDP,
|
||||
firewallTCP);
|
||||
message.sender(n1);
|
||||
//
|
||||
PeerAddress n2 = createAddress(idRecipien, inetRecipient, tcpPortRecipient, udpPortRecipient,
|
||||
firewallUDP, firewallTCP);
|
||||
message.recipient(n2);
|
||||
message.type(type);
|
||||
message.command(command);
|
||||
return message;
|
||||
}
|
||||
|
||||
public static PeerDHT[] createNodes(int nrOfPeers, Random rnd, int port) throws Exception
|
||||
{
|
||||
return createNodes(nrOfPeers, rnd, port, null);
|
||||
}
|
||||
|
||||
public static PeerDHT[] createNodes(int nrOfPeers, Random rnd, int port, AutomaticFuture automaticFuture)
|
||||
throws Exception
|
||||
{
|
||||
return createNodes(nrOfPeers, rnd, port, automaticFuture, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates peers for testing. The first peer (peer[0]) will be used as the master. This means that shutting down
|
||||
* peer[0] will shut down all other peers
|
||||
*
|
||||
* @param nrOfPeers The number of peers to create including the master
|
||||
* @param rnd The random object to create random peer IDs
|
||||
* @param port The port where the master peer will listen to
|
||||
* @return All the peers, with the master peer at position 0 -> peer[0]
|
||||
* @throws Exception If the creation of nodes fail.
|
||||
*/
|
||||
public static PeerDHT[] createNodes(int nrOfPeers, Random rnd, int port, AutomaticFuture automaticFuture,
|
||||
boolean maintenance) throws Exception
|
||||
{
|
||||
if (nrOfPeers < 1)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot create less than 1 peer");
|
||||
}
|
||||
Bindings bindings = new Bindings();
|
||||
PeerDHT[] peers = new PeerDHT[nrOfPeers];
|
||||
final Peer master;
|
||||
if (automaticFuture != null)
|
||||
{
|
||||
Number160 peerId = new Number160(rnd);
|
||||
PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId));
|
||||
master = new PeerBuilder(peerId)
|
||||
.ports(port).enableMaintenance(maintenance)
|
||||
.externalBindings(bindings).peerMap(peerMap).start().addAutomaticFuture(automaticFuture);
|
||||
peers[0] = new PeerBuilderDHT(master).start();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Number160 peerId = new Number160(rnd);
|
||||
PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId));
|
||||
master = new PeerBuilder(peerId).enableMaintenance(maintenance).externalBindings(bindings)
|
||||
.peerMap(peerMap).ports(port).start();
|
||||
peers[0] = new PeerBuilderDHT(master).start();
|
||||
}
|
||||
|
||||
for (int i = 1; i < nrOfPeers; i++)
|
||||
{
|
||||
if (automaticFuture != null)
|
||||
{
|
||||
Number160 peerId = new Number160(rnd);
|
||||
PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId));
|
||||
Peer peer = new PeerBuilder(peerId)
|
||||
.masterPeer(master)
|
||||
.enableMaintenance(maintenance).enableMaintenance(maintenance).peerMap(peerMap).externalBindings(bindings).start().addAutomaticFuture(automaticFuture);
|
||||
peers[i] = new PeerBuilderDHT(peer).start();
|
||||
}
|
||||
else
|
||||
{
|
||||
Number160 peerId = new Number160(rnd);
|
||||
PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId).peerNoVerification());
|
||||
Peer peer = new PeerBuilder(peerId).enableMaintenance(maintenance)
|
||||
.externalBindings(bindings).peerMap(peerMap).masterPeer(master)
|
||||
.start();
|
||||
peers[i] = new PeerBuilderDHT(peer).start();
|
||||
}
|
||||
}
|
||||
System.err.println("peers created.");
|
||||
return peers;
|
||||
}
|
||||
|
||||
public static Peer[] createRealNodes(int nrOfPeers, Random rnd, int startPort,
|
||||
AutomaticFuture automaticFuture) throws Exception
|
||||
{
|
||||
if (nrOfPeers < 1)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot create less than 1 peer");
|
||||
}
|
||||
Peer[] peers = new Peer[nrOfPeers];
|
||||
for (int i = 0; i < nrOfPeers; i++)
|
||||
{
|
||||
peers[i] = new PeerBuilder(new Number160(rnd))
|
||||
.ports(startPort + i).start().addAutomaticFuture(automaticFuture);
|
||||
}
|
||||
System.err.println("real peers created.");
|
||||
return peers;
|
||||
}
|
||||
|
||||
public static Peer[] createNonMaintenanceNodes(int nrOfPeers, Random rnd, int port) throws IOException
|
||||
{
|
||||
if (nrOfPeers < 1)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot create less than 1 peer");
|
||||
}
|
||||
Peer[] peers = new Peer[nrOfPeers];
|
||||
peers[0] = new PeerBuilder(new Number160(rnd)).enableMaintenance(false).ports(port).start();
|
||||
for (int i = 1; i < nrOfPeers; i++)
|
||||
{
|
||||
peers[i] = new PeerBuilder(new Number160(rnd)).enableMaintenance(false).masterPeer(peers[0])
|
||||
.start();
|
||||
}
|
||||
System.err.println("non-maintenance peers created.");
|
||||
return peers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perfect routing, where each neighbor has contacted each other. This means that for small number of peers, every
|
||||
* peer knows every other peer.
|
||||
*
|
||||
* @param peers The peers taking part in the p2p network.
|
||||
*/
|
||||
public static void perfectRouting(PeerDHT... peers)
|
||||
{
|
||||
for (int i = 0; i < peers.length; i++)
|
||||
{
|
||||
for (int j = 0; j < peers.length; j++)
|
||||
peers[i].peer().peerBean().peerMap().peerFound(peers[j].peer().peerAddress(), null);
|
||||
}
|
||||
System.err.println("perfect routing done.");
|
||||
}
|
||||
|
||||
public static void perfectRoutingIndirect(PeerDHT... peers)
|
||||
{
|
||||
for (int i = 0; i < peers.length; i++)
|
||||
{
|
||||
for (int j = 0; j < peers.length; j++)
|
||||
peers[i].peerBean().peerMap().peerFound(peers[j].peerAddress(), peers[j].peerAddress());
|
||||
}
|
||||
System.err.println("perfect routing done.");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException
|
||||
{
|
||||
createTempDirectory();
|
||||
}
|
||||
|
||||
private static final int TEMP_DIR_ATTEMPTS = 10000;
|
||||
|
||||
public static File createTempDirectory() throws IOException
|
||||
{
|
||||
File baseDir = new File(System.getProperty("java.io.tmpdir"));
|
||||
String baseName = System.currentTimeMillis() + "-";
|
||||
|
||||
for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++)
|
||||
{
|
||||
File tempDir = new File(baseDir, baseName + counter);
|
||||
if (tempDir.mkdir())
|
||||
{
|
||||
return tempDir;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Failed to create directory within " + TEMP_DIR_ATTEMPTS
|
||||
+ " attempts (tried " + baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + ')');
|
||||
}
|
||||
|
||||
public static Peer[] createAndAttachNodes(int nr, int port, Random rnd) throws Exception
|
||||
{
|
||||
Peer[] peers = new Peer[nr];
|
||||
for (int i = 0; i < nr; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
peers[0] = new PeerBuilder(new Number160(rnd)).ports(port).start();
|
||||
}
|
||||
else
|
||||
{
|
||||
peers[i] = new PeerBuilder(new Number160(rnd)).masterPeer(peers[0]).start();
|
||||
}
|
||||
}
|
||||
return peers;
|
||||
}
|
||||
|
||||
public static void bootstrap(Peer[] peers)
|
||||
{
|
||||
List<FutureBootstrap> futures1 = new ArrayList<FutureBootstrap>();
|
||||
List<FutureDiscover> futures2 = new ArrayList<FutureDiscover>();
|
||||
for (int i = 1; i < peers.length; i++)
|
||||
{
|
||||
FutureDiscover tmp = peers[i].discover().peerAddress(peers[0].peerAddress()).start();
|
||||
futures2.add(tmp);
|
||||
}
|
||||
for (FutureDiscover future : futures2)
|
||||
{
|
||||
future.awaitUninterruptibly();
|
||||
}
|
||||
for (int i = 1; i < peers.length; i++)
|
||||
{
|
||||
FutureBootstrap tmp = peers[i].bootstrap().peerAddress(peers[0].peerAddress()).start();
|
||||
futures1.add(tmp);
|
||||
}
|
||||
for (int i = 1; i < peers.length; i++)
|
||||
{
|
||||
FutureBootstrap tmp = peers[0].bootstrap().peerAddress(peers[i].peerAddress()).start();
|
||||
futures1.add(tmp);
|
||||
}
|
||||
for (FutureBootstrap future : futures1)
|
||||
future.awaitUninterruptibly();
|
||||
}
|
||||
|
||||
public static void routing(Number160 key, Peer[] peers, int start)
|
||||
{
|
||||
System.out.println("routing: searching for key " + key);
|
||||
NavigableSet<PeerAddress> pa1 = new TreeSet<PeerAddress>(PeerMap.createComparator(key));
|
||||
NavigableSet<PeerAddress> queried = new TreeSet<PeerAddress>(PeerMap.createComparator(key));
|
||||
Number160 result = Number160.ZERO;
|
||||
Number160 resultPeer = new Number160("0xd75d1a3d57841fbc9e2a3d175d6a35dc2e15b9f");
|
||||
int round = 0;
|
||||
while (!resultPeer.equals(result))
|
||||
{
|
||||
System.out.println("round " + round);
|
||||
round++;
|
||||
pa1.addAll(peers[start].peerBean().peerMap().all());
|
||||
queried.add(peers[start].peerAddress());
|
||||
System.out.println("closest so far: " + queried.first());
|
||||
PeerAddress next = pa1.pollFirst();
|
||||
while (queried.contains(next))
|
||||
{
|
||||
next = pa1.pollFirst();
|
||||
}
|
||||
result = next.peerId();
|
||||
start = findNr(next.peerId().toString(), peers);
|
||||
}
|
||||
}
|
||||
|
||||
public static void findInMap(PeerAddress key, Peer[] peers)
|
||||
{
|
||||
for (int i = 0; i < peers.length; i++)
|
||||
{
|
||||
if (peers[i].peerBean().peerMap().contains(key))
|
||||
{
|
||||
System.out.println("Peer " + i + " with the id " + peers[i].peerID() + " knows the peer "
|
||||
+ key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int findNr(String string, Peer[] peers)
|
||||
{
|
||||
for (int i = 0; i < peers.length; i++)
|
||||
{
|
||||
if (peers[i].peerID().equals(new Number160(string)))
|
||||
{
|
||||
System.out.println("we found the number " + i + " for peer with id " + string);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static Peer find(String string, Peer[] peers)
|
||||
{
|
||||
for (int i = 0; i < peers.length; i++)
|
||||
{
|
||||
if (peers[i].peerID().equals(new Number160(string)))
|
||||
{
|
||||
System.out.println("!!we found the number " + i + " for peer with id " + string);
|
||||
return peers[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void exec(String cmd) throws Exception
|
||||
{
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
p.waitFor();
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line = null;
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
System.out.println(line);
|
||||
}
|
||||
br.close();
|
||||
}
|
||||
|
||||
public static PeerAddress createAddressIP(String inet) throws UnknownHostException
|
||||
{
|
||||
return createAddress(Number160.createHash(inet), inet, 8005, 8006, false, false);
|
||||
}
|
||||
|
||||
public static PeerAddress[] createDummyAddress(int size, int portTCP, int portUDP) throws UnknownHostException
|
||||
{
|
||||
PeerAddress[] pa = new PeerAddress[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
pa[i] = createAddress(i + 1, portTCP, portUDP);
|
||||
}
|
||||
return pa;
|
||||
}
|
||||
|
||||
public static PeerAddress createAddress(int iid, int portTCP, int portUDP) throws UnknownHostException
|
||||
{
|
||||
Number160 id = new Number160(iid);
|
||||
InetAddress address = InetAddress.getByName("127.0.0.1");
|
||||
return new PeerAddress(id, address, portTCP, portUDP);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package lighthouse.threading;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
||||
public class ConcatenatingListTest
|
||||
{
|
||||
@Test
|
||||
public void basic() throws Exception
|
||||
{
|
||||
ObservableList<String> a = FXCollections.observableArrayList();
|
||||
ObservableList<String> b = FXCollections.observableArrayList();
|
||||
ConcatenatingList<String> concat = new ConcatenatingList<>(a, b);
|
||||
assertEquals(0, concat.size());
|
||||
a.add("1");
|
||||
assertEquals(1, concat.size());
|
||||
assertEquals("1", concat.get(0));
|
||||
b.add("2");
|
||||
assertEquals(2, concat.size());
|
||||
assertEquals("2", concat.get(1));
|
||||
}
|
||||
}
|
91
src/test/java/lighthouse/threading/MappedListTest.java
Normal file
91
src/test/java/lighthouse/threading/MappedListTest.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
package lighthouse.threading;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class MappedListTest
|
||||
{
|
||||
private ObservableList<String> inputs;
|
||||
private ObservableList<String> outputs;
|
||||
private Queue<ListChangeListener.Change<? extends String>> changes;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
inputs = FXCollections.observableArrayList();
|
||||
outputs = new MappedList<>(inputs, str -> "Hello " + str);
|
||||
changes = new LinkedList<>();
|
||||
outputs.addListener(changes::add);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void add() throws Exception
|
||||
{
|
||||
assertEquals(0, outputs.size());
|
||||
inputs.add("Mike");
|
||||
ListChangeListener.Change<? extends String> change = getChange();
|
||||
assertTrue(change.wasAdded());
|
||||
assertEquals("Hello Mike", change.getAddedSubList().get(0));
|
||||
assertEquals(1, outputs.size());
|
||||
assertEquals("Hello Mike", outputs.get(0));
|
||||
inputs.remove(0);
|
||||
assertEquals(0, outputs.size());
|
||||
}
|
||||
|
||||
private ListChangeListener.Change<? extends String> getChange()
|
||||
{
|
||||
ListChangeListener.Change<? extends String> change = changes.poll();
|
||||
change.next();
|
||||
return change;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void remove()
|
||||
{
|
||||
inputs.add("Mike");
|
||||
inputs.add("Dave");
|
||||
inputs.add("Katniss");
|
||||
getChange();
|
||||
getChange();
|
||||
getChange();
|
||||
assertEquals("Hello Mike", outputs.get(0));
|
||||
assertEquals("Hello Dave", outputs.get(1));
|
||||
assertEquals("Hello Katniss", outputs.get(2));
|
||||
inputs.remove(0);
|
||||
ListChangeListener.Change<? extends String> change = getChange();
|
||||
assertTrue(change.wasRemoved());
|
||||
assertEquals(2, outputs.size());
|
||||
assertEquals(1, change.getRemovedSize());
|
||||
assertEquals("Hello Mike", change.getRemoved().get(0));
|
||||
assertEquals("Hello Dave", outputs.get(0));
|
||||
|
||||
inputs.remove(1);
|
||||
assertEquals(1, outputs.size());
|
||||
assertEquals("Hello Dave", outputs.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replace() throws Exception
|
||||
{
|
||||
inputs.add("Mike");
|
||||
inputs.add("Dave");
|
||||
getChange();
|
||||
getChange();
|
||||
inputs.set(0, "Bob");
|
||||
assertEquals("Hello Bob", outputs.get(0));
|
||||
ListChangeListener.Change<? extends String> change = getChange();
|
||||
assertTrue(change.wasReplaced());
|
||||
assertEquals("Hello Mike", change.getRemoved().get(0));
|
||||
assertEquals("Hello Bob", change.getAddedSubList().get(0));
|
||||
}
|
||||
|
||||
// Could also test permutation here if I could figure out how to actually apply one!
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue