Add PeerManagerTest

The old PeerManagerTest was located under network/p2p/routing, which is
no longer the correct location. Additionally, it was outdated so I
just removed it and added a new file under network/p2p/peers containing
tests for checkMaxConnections.
This commit is contained in:
Devin Bileck 2019-11-09 23:44:11 -08:00
parent 6f80b8a964
commit b45765feb5
No known key found for this signature in database
GPG key ID: C86D829C2399D073
2 changed files with 188 additions and 486 deletions

View file

@ -0,0 +1,188 @@
/*
* This file is part of Bisq.
*
* Bisq 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.
*
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.network.p2p.peers;
import bisq.network.p2p.MockNode;
import bisq.network.p2p.network.CloseConnectionReason;
import bisq.network.p2p.network.Connection;
import bisq.network.p2p.network.InboundConnection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.*;
public class PeerManagerTest {
private MockNode node;
private int maxConnectionsPeer;
private int maxConnectionsNonDirect;
@Before
public void Setup() {
node = new MockNode(2);
maxConnectionsPeer = Math.max(4, (int) Math.round(node.getMaxConnections() * 1.3));
maxConnectionsNonDirect = Math.max(8, (int) Math.round(node.getMaxConnections() * 1.7));
}
@Test
public void testCheckMaxConnectionsNotExceeded() {
for (int i = 0; i < 2; i++) {
node.addInboundConnection(Connection.PeerType.PEER);
}
assertEquals(2, node.getNetworkNode().getAllConnections().size());
assertFalse(node.getPeerManager().checkMaxConnections());
node.getNetworkNode().getAllConnections().forEach(connection -> {
verify(connection, never()).shutDown(eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN), isA(Runnable.class));
});
}
@Test
public void testCheckMaxConnectionsExceededWithInboundPeers() throws InterruptedException {
for (int i = 0; i < 3; i++) {
node.addInboundConnection(Connection.PeerType.PEER);
}
assertEquals(3, node.getNetworkNode().getAllConnections().size());
List<Connection> inboundSortedPeerConnections = node.getNetworkNode().getAllConnections().stream()
.filter(e -> e instanceof InboundConnection)
.filter(e -> e.getPeerType() == Connection.PeerType.PEER)
.sorted(Comparator.comparingLong(o -> o.getStatistic().getLastActivityTimestamp()))
.collect(Collectors.toList());
Connection oldestConnection = inboundSortedPeerConnections.remove(0);
assertTrue(node.getPeerManager().checkMaxConnections());
// Need to wait because the shutDownCompleteHandler calls
// checkMaxConnections on the user thread after a delay
Thread.sleep(500);
verify(oldestConnection, times(1)).shutDown(
eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN),
isA(Runnable.class));
inboundSortedPeerConnections.forEach(connection -> {
verify(connection, never()).shutDown(
eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN),
isA(Runnable.class));
});
}
@Test
public void testCheckMaxConnectionsPeerLimitNotExceeded() {
for (int i = 0; i < maxConnectionsPeer; i++) {
node.addOutboundConnection(Connection.PeerType.PEER);
}
assertEquals(maxConnectionsPeer, node.getNetworkNode().getAllConnections().size());
assertFalse(node.getPeerManager().checkMaxConnections());
node.getNetworkNode().getAllConnections().forEach(connection -> {
verify(connection, never()).shutDown(eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN), isA(Runnable.class));
});
}
@Test
public void testCheckMaxConnectionsPeerLimitExceeded() throws InterruptedException {
for (int i = 0; i < maxConnectionsPeer + 1; i++) {
node.addOutboundConnection(Connection.PeerType.PEER);
}
assertEquals(maxConnectionsPeer + 1, node.getNetworkNode().getAllConnections().size());
List<Connection> sortedPeerConnections = node.getNetworkNode().getAllConnections().stream()
.filter(e -> e.getPeerType() == Connection.PeerType.PEER)
.sorted(Comparator.comparingLong(o -> o.getStatistic().getLastActivityTimestamp()))
.collect(Collectors.toList());
Connection oldestConnection = sortedPeerConnections.remove(0);
assertTrue(node.getPeerManager().checkMaxConnections());
// Need to wait because the shutDownCompleteHandler calls
// checkMaxConnections on the user thread after a delay
Thread.sleep(500);
verify(oldestConnection, times(1)).shutDown(
eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN),
isA(Runnable.class));
sortedPeerConnections.forEach(connection -> {
verify(connection, never()).shutDown(
eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN),
isA(Runnable.class));
});
}
@Test
public void testCheckMaxConnectionsNonDirectLimitNotExceeded() {
for (int i = 0; i < maxConnectionsNonDirect; i++) {
node.addOutboundConnection(Connection.PeerType.SEED_NODE);
}
assertEquals(maxConnectionsNonDirect, node.getNetworkNode().getAllConnections().size());
assertFalse(node.getPeerManager().checkMaxConnections());
node.getNetworkNode().getAllConnections().forEach(connection -> {
verify(connection, never()).shutDown(eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN), isA(Runnable.class));
});
}
@Test
public void testCheckMaxConnectionsNonDirectLimitExceeded() throws InterruptedException {
for (int i = 0; i < maxConnectionsNonDirect + 1; i++) {
node.addOutboundConnection(Connection.PeerType.PEER);
}
assertEquals(maxConnectionsNonDirect + 1, node.getNetworkNode().getAllConnections().size());
List<Connection> sortedPeerConnections = node.getNetworkNode().getAllConnections().stream()
.filter(e -> e.getPeerType() != Connection.PeerType.DIRECT_MSG_PEER &&
e.getPeerType() != Connection.PeerType.INITIAL_DATA_REQUEST)
.sorted(Comparator.comparingLong(o -> o.getStatistic().getLastActivityTimestamp()))
.collect(Collectors.toList());
Connection oldestConnection = sortedPeerConnections.remove(0);
assertTrue(node.getPeerManager().checkMaxConnections());
// Need to wait because the shutDownCompleteHandler calls
// checkMaxConnections on the user thread after a delay
Thread.sleep(500);
verify(oldestConnection, times(1)).shutDown(
eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN),
isA(Runnable.class));
sortedPeerConnections.forEach(connection -> {
verify(connection, never()).shutDown(
eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN),
isA(Runnable.class));
});
}
@Test
public void testCheckMaxConnectionsExceededWithOutboundSeeds() {
for (int i = 0; i < 3; i++) {
node.addOutboundConnection(Connection.PeerType.SEED_NODE);
}
assertEquals(3, node.getNetworkNode().getAllConnections().size());
assertFalse(node.getPeerManager().checkMaxConnections());
node.getNetworkNode().getAllConnections().forEach(connection -> {
verify(connection, never()).shutDown(eq(CloseConnectionReason.TOO_MANY_CONNECTIONS_OPEN), isA(Runnable.class));
});
}
}

View file

@ -1,486 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq 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.
*
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.network.p2p.routing;
import bisq.network.p2p.DummySeedNode;
import bisq.network.p2p.NodeAddress;
import bisq.network.p2p.P2PService;
import bisq.network.p2p.P2PServiceListener;
import bisq.network.p2p.network.LocalhostNetworkNode;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
// TorNode created. Took 6 sec.
// Hidden service created. Took 40-50 sec.
// Connection establishment takes about 4 sec.
// need to define seed node addresses first before using tor version
//TODO P2P network tests are outdated
@SuppressWarnings({"UnusedAssignment", "EmptyMethod"})
@Ignore
public class PeerManagerTest {
private static final Logger log = LoggerFactory.getLogger(PeerManagerTest.class);
private static final int MAX_CONNECTIONS = 100;
final boolean useLocalhostForP2P = true;
private CountDownLatch latch;
private Set<NodeAddress> seedNodes;
private int sleepTime;
private DummySeedNode seedNode1, seedNode2, seedNode3;
@Before
public void setup() throws InterruptedException {
LocalhostNetworkNode.setSimulateTorDelayTorNode(50);
LocalhostNetworkNode.setSimulateTorDelayHiddenService(8);
seedNodes = new HashSet<>();
//noinspection ConstantConditions
if (useLocalhostForP2P) {
//seedNodes.add(new NodeAddress("localhost:8001"));
// seedNodes.add(new NodeAddress("localhost:8002"));
seedNodes.add(new NodeAddress("localhost:8003"));
sleepTime = 100;
} else {
seedNodes.add(new NodeAddress("3omjuxn7z73pxoee.onion:8001"));
seedNodes.add(new NodeAddress("j24fxqyghjetgpdx.onion:8002"));
seedNodes.add(new NodeAddress("45367tl6unwec6kw.onion:8003"));
sleepTime = 1000;
}
}
@After
public void tearDown() throws InterruptedException {
Thread.sleep(sleepTime);
if (seedNode1 != null) {
CountDownLatch shutDownLatch = new CountDownLatch(1);
seedNode1.shutDown(shutDownLatch::countDown);
shutDownLatch.await();
}
if (seedNode2 != null) {
CountDownLatch shutDownLatch = new CountDownLatch(1);
seedNode2.shutDown(shutDownLatch::countDown);
shutDownLatch.await();
}
if (seedNode3 != null) {
CountDownLatch shutDownLatch = new CountDownLatch(1);
seedNode3.shutDown(shutDownLatch::countDown);
shutDownLatch.await();
}
}
// @Test
public void testSingleSeedNode() throws InterruptedException {
LocalhostNetworkNode.setSimulateTorDelayTorNode(0);
LocalhostNetworkNode.setSimulateTorDelayHiddenService(0);
seedNodes = new HashSet<>();
NodeAddress nodeAddress = new NodeAddress("localhost:8001");
seedNodes.add(nodeAddress);
seedNode1 = new DummySeedNode("test_dummy_dir");
latch = new CountDownLatch(2);
seedNode1.createAndStartP2PService(nodeAddress, MAX_CONNECTIONS, useLocalhostForP2P, 2, true,
seedNodes, new P2PServiceListener() {
@Override
public void onDataReceived() {
latch.countDown();
}
@Override
public void onTorNodeReady() {
}
@Override
public void onNoSeedNodeAvailable() {
}
@Override
public void onNoPeersAvailable() {
}
@Override
public void onUpdatedDataReceived() {
}
@Override
public void onHiddenServicePublished() {
latch.countDown();
}
@Override
public void onSetupFailed(Throwable throwable) {
}
@Override
public void onRequestCustomBridges() {
}
});
P2PService p2PService1 = seedNode1.getSeedNodeP2PService();
latch.await();
Thread.sleep(500);
//Assert.assertEquals(0, p2PService1.getPeerManager().getAuthenticatedAndReportedPeers().size());
}
@Test
public void test2SeedNodes() throws InterruptedException {
LocalhostNetworkNode.setSimulateTorDelayTorNode(0);
LocalhostNetworkNode.setSimulateTorDelayHiddenService(0);
seedNodes = new HashSet<>();
NodeAddress nodeAddress1 = new NodeAddress("localhost:8001");
seedNodes.add(nodeAddress1);
NodeAddress nodeAddress2 = new NodeAddress("localhost:8002");
seedNodes.add(nodeAddress2);
latch = new CountDownLatch(6);
seedNode1 = new DummySeedNode("test_dummy_dir");
seedNode1.createAndStartP2PService(nodeAddress1, MAX_CONNECTIONS, useLocalhostForP2P, 2, true, seedNodes, new P2PServiceListener() {
@Override
public void onDataReceived() {
latch.countDown();
}
@Override
public void onNoSeedNodeAvailable() {
}
@Override
public void onTorNodeReady() {
}
@Override
public void onNoPeersAvailable() {
}
@Override
public void onUpdatedDataReceived() {
latch.countDown();
}
@Override
public void onHiddenServicePublished() {
latch.countDown();
}
@Override
public void onSetupFailed(Throwable throwable) {
}
@Override
public void onRequestCustomBridges() {
}
});
P2PService p2PService1 = seedNode1.getSeedNodeP2PService();
Thread.sleep(500);
seedNode2 = new DummySeedNode("test_dummy_dir");
seedNode2.createAndStartP2PService(nodeAddress2, MAX_CONNECTIONS, useLocalhostForP2P, 2, true, seedNodes, new P2PServiceListener() {
@Override
public void onDataReceived() {
latch.countDown();
}
@Override
public void onNoSeedNodeAvailable() {
}
@Override
public void onTorNodeReady() {
}
@Override
public void onNoPeersAvailable() {
}
@Override
public void onUpdatedDataReceived() {
latch.countDown();
}
@Override
public void onHiddenServicePublished() {
latch.countDown();
}
@Override
public void onSetupFailed(Throwable throwable) {
}
@Override
public void onRequestCustomBridges() {
}
});
P2PService p2PService2 = seedNode2.getSeedNodeP2PService();
latch.await();
// Assert.assertEquals(1, p2PService1.getPeerManager().getAuthenticatedAndReportedPeers().size());
// Assert.assertEquals(1, p2PService2.getPeerManager().getAuthenticatedAndReportedPeers().size());
}
// @Test
public void testAuthentication() throws InterruptedException {
log.debug("### start");
LocalhostNetworkNode.setSimulateTorDelayTorNode(0);
LocalhostNetworkNode.setSimulateTorDelayHiddenService(0);
DummySeedNode seedNode1 = getAndStartSeedNode(8001);
log.debug("### seedNode1");
Thread.sleep(100);
log.debug("### seedNode1 100");
Thread.sleep(1000);
DummySeedNode seedNode2 = getAndStartSeedNode(8002);
// authentication:
// node2 -> node1 RequestAuthenticationMessage
// node1: close connection
// node1 -> node2 ChallengeMessage on new connection
// node2: authentication to node1 done if nonce ok
// node2 -> node1 GetPeersMessage
// node1: authentication to node2 done if nonce ok
// node1 -> node2 PeersMessage
// first authentication from seedNode2 to seedNode1, then from seedNode1 to seedNode2
//TODO
/* CountDownLatch latch1 = new CountDownLatch(2);
AuthenticationListener routingListener1 = new AuthenticationListener() {
@Override
public void onConnectionAuthenticated(Connection connection) {
log.debug("onConnectionAuthenticated " + connection);
latch1.countDown();
}
};
seedNode1.getP2PService().getPeerGroup().addPeerListener(routingListener1);
AuthenticationListener routingListener2 = new AuthenticationListener() {
@Override
public void onConnectionAuthenticated(Connection connection) {
log.debug("onConnectionAuthenticated " + connection);
latch1.countDown();
}
};
seedNode2.getP2PService().getPeerGroup().addPeerListener(routingListener2);
latch1.await();
seedNode1.getP2PService().getPeerGroup().removePeerListener(routingListener1);
seedNode2.getP2PService().getPeerGroup().removePeerListener(routingListener2);
// wait until Peers msg finished
Thread.sleep(sleepTime);
// authentication:
// authentication from seedNode3 to seedNode1, then from seedNode1 to seedNode3
// authentication from seedNode3 to seedNode2, then from seedNode2 to seedNode3
SeedNode seedNode3 = getAndStartSeedNode(8003);
CountDownLatch latch2 = new CountDownLatch(3);
seedNode1.getP2PService().getPeerGroup().addPeerListener(new AuthenticationListener() {
@Override
public void onConnectionAuthenticated(Connection connection) {
log.debug("onConnectionAuthenticated " + connection);
latch2.countDown();
}
});
seedNode2.getP2PService().getPeerGroup().addPeerListener(new AuthenticationListener() {
@Override
public void onConnectionAuthenticated(Connection connection) {
log.debug("onConnectionAuthenticated " + connection);
latch2.countDown();
}
});
seedNode3.getP2PService().getPeerGroup().addPeerListener(new AuthenticationListener() {
@Override
public void onConnectionAuthenticated(Connection connection) {
log.debug("onConnectionAuthenticated " + connection);
latch2.countDown();
}
});
latch2.await();
// wait until Peers msg finished
Thread.sleep(sleepTime);
CountDownLatch shutDownLatch = new CountDownLatch(3);
seedNode1.shutDown(() -> shutDownLatch.countDown());
seedNode2.shutDown(() -> shutDownLatch.countDown());
seedNode3.shutDown(() -> shutDownLatch.countDown());
shutDownLatch.await();*/
}
//@Test
public void testAuthenticationWithDisconnect() throws InterruptedException {
//TODO
/* LocalhostNetworkNode.setSimulateTorDelayTorNode(0);
LocalhostNetworkNode.setSimulateTorDelayHiddenService(0);
SeedNode seedNode1 = getAndStartSeedNode(8001);
SeedNode seedNode2 = getAndStartSeedNode(8002);
// authentication:
// node2 -> node1 RequestAuthenticationMessage
// node1: close connection
// node1 -> node2 ChallengeMessage on new connection
// node2: authentication to node1 done if nonce ok
// node2 -> node1 GetPeersMessage
// node1: authentication to node2 done if nonce ok
// node1 -> node2 PeersMessage
// first authentication from seedNode2 to seedNode1, then from seedNode1 to seedNode2
CountDownLatch latch1 = new CountDownLatch(2);
AuthenticationListener routingListener1 = new AuthenticationListener() {
@Override
public void onConnectionAuthenticated(Connection connection) {
log.debug("onConnectionAuthenticated " + connection);
latch1.countDown();
}
};
seedNode1.getP2PService().getPeerGroup().addPeerListener(routingListener1);
AuthenticationListener routingListener2 = new AuthenticationListener() {
@Override
public void onConnectionAuthenticated(Connection connection) {
log.debug("onConnectionAuthenticated " + connection);
latch1.countDown();
}
};
seedNode2.getP2PService().getPeerGroup().addPeerListener(routingListener2);
latch1.await();
// shut down node 2
Thread.sleep(sleepTime);
seedNode1.getP2PService().getPeerGroup().removePeerListener(routingListener1);
seedNode2.getP2PService().getPeerGroup().removePeerListener(routingListener2);
CountDownLatch shutDownLatch1 = new CountDownLatch(1);
seedNode2.shutDown(() -> shutDownLatch1.countDown());
shutDownLatch1.await();
// restart node 2
seedNode2 = getAndStartSeedNode(8002);
CountDownLatch latch3 = new CountDownLatch(1);
routingListener2 = new AuthenticationListener() {
@Override
public void onConnectionAuthenticated(Connection connection) {
log.debug("onConnectionAuthenticated " + connection);
latch3.countDown();
}
};
seedNode2.getP2PService().getPeerGroup().addPeerListener(routingListener2);
latch3.await();
Thread.sleep(sleepTime);
CountDownLatch shutDownLatch = new CountDownLatch(2);
seedNode1.shutDown(() -> shutDownLatch.countDown());
seedNode2.shutDown(() -> shutDownLatch.countDown());
shutDownLatch.await();*/
}
//@Test
public void testAuthenticationWithManyNodes() throws InterruptedException {
//TODO
/* int authentications = 0;
int length = 3;
SeedNode[] nodes = new SeedNode[length];
for (int i = 0; i < length; i++) {
SeedNode node = getAndStartSeedNode(8001 + i);
nodes[i] = node;
latch = new CountDownLatch(i * 2);
authentications += (i * 2);
node.getP2PService().getPeerGroup().addPeerListener(new AuthenticationListener() {
@Override
public void onConnectionAuthenticated(Connection connection) {
log.debug("onConnectionAuthenticated " + connection);
latch.countDown();
}
});
latch.await();
Thread.sleep(sleepTime);
}
log.debug("total authentications " + authentications);
Profiler.printSystemLoad(log);
// total authentications at 8 nodes = 56
// total authentications at com nodes = 90, System load (no. threads/used memory (MB)): 170/20
// total authentications at 20 nodes = 380, System load (no. threads/used memory (MB)): 525/46
for (int i = 0; i < length; i++) {
nodes[i].getP2PService().getPeerGroup().printAuthenticatedPeers();
nodes[i].getP2PService().getPeerGroup().printReportedPeers();
}
CountDownLatch shutDownLatch = new CountDownLatch(length);
for (int i = 0; i < length; i++) {
nodes[i].shutDown(() -> shutDownLatch.countDown());
}
shutDownLatch.await();*/
}
private DummySeedNode getAndStartSeedNode(int port) throws InterruptedException {
DummySeedNode seedNode = new DummySeedNode("test_dummy_dir");
latch = new CountDownLatch(1);
seedNode.createAndStartP2PService(new NodeAddress("localhost", port), MAX_CONNECTIONS, useLocalhostForP2P, 2, true, seedNodes, new P2PServiceListener() {
@Override
public void onDataReceived() {
latch.countDown();
}
@Override
public void onNoSeedNodeAvailable() {
}
@Override
public void onTorNodeReady() {
}
@Override
public void onNoPeersAvailable() {
}
@Override
public void onUpdatedDataReceived() {
}
@Override
public void onHiddenServicePublished() {
}
@Override
public void onSetupFailed(Throwable throwable) {
}
@Override
public void onRequestCustomBridges() {
}
});
latch.await();
Thread.sleep(sleepTime);
return seedNode;
}
}