Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

[NC-1970] admin_addPeer acceptance test #651

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Accounts;
import tech.pegasys.pantheon.tests.acceptance.dsl.blockchain.Blockchain;
import tech.pegasys.pantheon.tests.acceptance.dsl.contract.ContractVerifier;
import tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc.Admin;
import tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc.Clique;
import tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc.Eth;
import tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc.Ibft;
Expand Down Expand Up @@ -45,6 +46,7 @@ public class AcceptanceTestBase {
protected final Eth eth;
protected final Net net;
protected final Perm perm;
protected final Admin admin;
protected final PantheonNodeFactory pantheon;
protected final ContractVerifier contractVerifier;
protected final WaitConditions wait;
Expand All @@ -61,6 +63,7 @@ protected AcceptanceTestBase() {
cluster = new Cluster(net);
transactions = new Transactions(accounts);
perm = new Perm(transactions);
admin = new Admin();
web3 = new Web3(new Web3Transactions());
pantheon = new PantheonNodeFactory();
contractVerifier = new ContractVerifier(accounts.getPrimaryBenefactor());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node;

@FunctionalInterface
public interface Condition {

void verify(Node node);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2019 ConsenSys AG.
*
* 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 tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc;

import static org.assertj.core.api.Assertions.assertThat;

import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;

import java.io.IOException;

import org.web3j.protocol.core.Response;

public class Admin {
private Transaction<Boolean> addPeerTransaction(final String enode) {
return (n) -> {
try {
final Response<Boolean> resp = n.adminAddPeer(enode).send();
assertThat(resp).isNotNull();
assertThat(resp.hasError()).isFalse();
return resp.getResult();
} catch (final IOException e) {
throw new RuntimeException(e);
}
};
}

public Condition addPeer(final String enode) {
return (n) -> {
final Boolean result = n.execute(addPeerTransaction(enode));
assertThat(result).isTrue();
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public PantheonNode(
final GenesisConfigProvider genesisConfigProvider,
final int p2pPort,
final Boolean p2pEnabled,
final boolean discovery)
final boolean discoveryEnabled)
throws IOException {
this.homeDirectory = Files.createTempDirectory("acctest");
this.keyPair = KeyPairUtil.loadKeyPair(homeDirectory);
Expand All @@ -106,7 +106,7 @@ public PantheonNode(
this.genesisConfigProvider = genesisConfigProvider;
this.devMode = devMode;
this.p2pEnabled = p2pEnabled;
this.discoveryEnabled = discovery;
this.discoveryEnabled = discoveryEnabled;
LOG.info("Created PantheonNode {}", this.toString());
}

Expand Down Expand Up @@ -188,7 +188,7 @@ public void useWebSocketsForJsonRpc() {
final WebSocketService webSocketService = new WebSocketService(url, true);
try {
webSocketService.connect();
} catch (ConnectException e) {
} catch (final ConnectException e) {
throw new RuntimeException("Error connection to WebSocket endpoint", e);
}

Expand All @@ -200,7 +200,7 @@ public void useWebSocketsForJsonRpc() {
}

private void checkIfWebSocketEndpointIsAvailable(final String url) {
WebSocketClient webSocketClient = new WebSocketClient(URI.create(url));
final WebSocketClient webSocketClient = new WebSocketClient(URI.create(url));
// Web3j implementation always invoke the listener (even when one hasn't been set). We are using
// this stub implementation to avoid a NullPointerException.
webSocketClient.setListener(
Expand All @@ -226,7 +226,7 @@ public void onClose() {
webSocketClient.connect();
try {
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(webSocketClient::isOpen);
} catch (ConditionTimeoutException e) {
} catch (final ConditionTimeoutException e) {
throw new WebsocketNotConnectedException();
} finally {
webSocketClient.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ class PantheonFactoryConfiguration {
private final MetricsConfiguration metricsConfiguration;
private final PermissioningConfiguration permissioningConfiguration;
private final boolean devMode;
private final Boolean discoveryEnabled;
private final GenesisConfigProvider genesisConfigProvider;
private final Boolean p2pEnabled;
private final boolean discoveryEnabled;

PantheonFactoryConfiguration(
final String name,
Expand All @@ -42,7 +42,7 @@ class PantheonFactoryConfiguration {
final boolean devMode,
final GenesisConfigProvider genesisConfigProvider,
final Boolean p2pEnabled,
final Boolean discoveryEnabled) {
final boolean discoveryEnabled) {
this.name = name;
this.miningParameters = miningParameters;
this.jsonRpcConfiguration = jsonRpcConfiguration;
Expand Down Expand Up @@ -83,7 +83,7 @@ public boolean isDevMode() {
return devMode;
}

public Boolean isDiscoveryEnabled() {
public boolean isDiscoveryEnabled() {
return discoveryEnabled;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ public class PantheonFactoryConfigurationBuilder {
private PermissioningConfiguration permissioningConfiguration =
PermissioningConfiguration.createDefault();
private boolean devMode = true;
private Boolean discoveryEnabled = true;
private GenesisConfigProvider genesisConfigProvider = ignore -> Optional.empty();
private Boolean p2pEnabled = true;
private boolean discoveryEnabled = true;

public PantheonFactoryConfigurationBuilder setName(final String name) {
this.name = name;
Expand Down Expand Up @@ -109,13 +109,13 @@ public PantheonFactoryConfigurationBuilder setGenesisConfigProvider(
return this;
}

public PantheonFactoryConfigurationBuilder setDiscoveryEnabled(final Boolean discoveryEnabled) {
this.discoveryEnabled = discoveryEnabled;
public PantheonFactoryConfigurationBuilder setP2pEnabled(final Boolean p2pEnabled) {
this.p2pEnabled = p2pEnabled;
return this;
}

public PantheonFactoryConfigurationBuilder setP2pEnabled(final Boolean p2pEnabled) {
this.p2pEnabled = p2pEnabled;
public PantheonFactoryConfigurationBuilder setDiscoveryEnabled(final boolean discoveryEnabled) {
this.discoveryEnabled = discoveryEnabled;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,17 @@ public PantheonNode createArchiveNode(final String name) throws IOException {
.build());
}

public PantheonNode createArchiveNodeWithDiscoveryDisabledAndAdmin(final String name)
throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
.setName(name)
.setJsonRpcConfiguration(jsonRpcConfigWithAdmin())
.webSocketEnabled()
.setDiscoveryEnabled(false)
.build());
}

public PantheonNode createArchiveNodeWithP2pDisabled(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
Expand Down Expand Up @@ -324,6 +335,10 @@ private JsonRpcConfiguration jsonRpcConfigWithPermissioning() {
return createJsonRpcConfigWithRpcApiEnabled(RpcApis.PERM);
}

private JsonRpcConfiguration jsonRpcConfigWithAdmin() {
return createJsonRpcConfigWithRpcApiEnabled(RpcApis.ADMIN);
}

private JsonRpcConfiguration createJsonRpcConfigWithRpcApiEnabled(final RpcApi rpcApi) {
final JsonRpcConfiguration jsonRpcConfig = createJsonRpcEnabledConfig();
final List<RpcApi> rpcApis = new ArrayList<>(jsonRpcConfig.getRpcApis());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,14 @@ public static class AddNodeResponse extends Response<Boolean> {}
public static class RemoveNodeResponse extends Response<Boolean> {}

public static class GetNodesWhitelistResponse extends Response<List<String>> {}

public static class AdminAddPeerResponse extends Response<Boolean> {}

public Request<?, AdminAddPeerResponse> adminAddPeer(final String enodeAddress) {
return new Request<>(
"admin_addPeer",
Collections.singletonList(enodeAddress),
web3jService,
AdminAddPeerResponse.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction;

@FunctionalInterface
public interface Transaction<T> {

T execute(final PantheonWeb3j node);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2019 ConsenSys AG.
*
* 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 tech.pegasys.pantheon.tests.acceptance.jsonrpc.admin;

import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.cluster.Cluster;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.cluster.ClusterConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class AdminAddPeerAcceptanceTest extends AcceptanceTestBase {
private PantheonNode nodeA;
private PantheonNode nodeB;
private Cluster p2pDisabledCluster;

@Before
public void setUp() throws Exception {
final ClusterConfiguration clusterConfiguration =
new ClusterConfigurationBuilder().setAwaitPeerDiscovery(false).build();
p2pDisabledCluster = new Cluster(clusterConfiguration, net);
nodeA = pantheon.createArchiveNodeWithDiscoveryDisabledAndAdmin("nodeA");
nodeB = pantheon.createArchiveNodeWithDiscoveryDisabledAndAdmin("nodeB");
p2pDisabledCluster.start(nodeA, nodeB);
}

@After
public void tearDown() {
p2pDisabledCluster.stop();
}

@Test
public void adminAddPeerForcesConnection() {
final String nodeBEnode = nodeB.enodeUrl();
nodeA.verify(net.awaitPeerCount(0));
nodeA.verify(admin.addPeer(nodeBEnode));
nodeA.verify(net.awaitPeerCount(1));
nodeB.verify(net.awaitPeerCount(1));
}
}