From 665ae97b846c2abf6ba58f8ca33d4c4a6bad33c1 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Sat, 1 Dec 2018 20:52:05 -0700 Subject: [PATCH] Idiomatic Builder Pattern (#345) Use the Idiomatic builder pattern for PantheonControllerBuilder and RunnerBuilder. This reduces the number of test touch points when a new object is added to the builder. --- .../dsl/node/ThreadPantheonNodeRunner.java | 46 +- .../tech/pegasys/pantheon/RunnerBuilder.java | 96 +++- .../pegasys/pantheon/cli/PantheonCommand.java | 53 ++- .../cli/PantheonControllerBuilder.java | 56 ++- .../tech/pegasys/pantheon/RunnerTest.java | 59 ++- .../pantheon/cli/CommandTestAbstract.java | 11 +- .../pantheon/cli/PantheonCommandTest.java | 440 +++++------------- 7 files changed, 322 insertions(+), 439 deletions(-) diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java index 5531431674..fe892293d2 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java @@ -20,7 +20,7 @@ import tech.pegasys.pantheon.cli.EthNetworkConfig; import tech.pegasys.pantheon.cli.PantheonControllerBuilder; import tech.pegasys.pantheon.controller.KeyPairUtil; import tech.pegasys.pantheon.controller.PantheonController; -import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration.Builder; +import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; import java.io.IOException; import java.util.Collections; @@ -42,7 +42,6 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner { private final Map pantheonRunners = new HashMap<>(); private ExecutorService nodeExecutor = Executors.newCachedThreadPool(); - @SuppressWarnings("rawtypes") @Override public void startNode(final PantheonNode node) { if (nodeExecutor == null || nodeExecutor.isShutdown()) { @@ -53,35 +52,36 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner { final EthNetworkConfig ethNetworkConfig = node.ethNetworkConfig() .orElse(new EthNetworkConfig.Builder(mainnet()).setNetworkId(NETWORK_ID).build()); - PantheonController pantheonController; + final PantheonController pantheonController; try { pantheonController = - builder.build( - new Builder().build(), - node.homeDirectory(), - ethNetworkConfig, - false, - node.getMiningParameters(), - node.isDevMode(), - KeyPairUtil.getDefaultKeyFile(node.homeDirectory())); + builder + .synchronizerConfiguration(new SynchronizerConfiguration.Builder().build()) + .homePath(node.homeDirectory()) + .ethNetworkConfig(ethNetworkConfig) + .syncWithOttoman(false) + .miningParameters(node.getMiningParameters()) + .devMode(node.isDevMode()) + .nodePrivateKeyFile(KeyPairUtil.getDefaultKeyFile(node.homeDirectory())) + .build(); } catch (final IOException e) { throw new RuntimeException("Error building PantheonController", e); } final Runner runner = new RunnerBuilder() - .build( - Vertx.vertx(), - pantheonController, - true, - node.bootnodes(), - node.hostName(), - node.p2pPort(), - 25, - node.jsonRpcConfiguration(), - node.webSocketConfiguration(), - node.homeDirectory(), - Collections.emptySet()); + .vertx(Vertx.vertx()) + .pantheonController(pantheonController) + .discovery(true) + .bootstrapPeers(node.bootnodes()) + .discoveryHost(node.hostName()) + .discoveryPort(node.p2pPort()) + .maxPeers(25) + .jsonRpcConfiguration(node.jsonRpcConfiguration()) + .webSocketConfiguration(node.webSocketConfiguration()) + .dataDir(node.homeDirectory()) + .bannedNodeIds(Collections.emptySet()) + .build(); nodeExecutor.submit(runner::execute); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java index a29bbd4588..6707aa65f0 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java @@ -67,18 +67,74 @@ import io.vertx.core.Vertx; public class RunnerBuilder { - public Runner build( - final Vertx vertx, - final PantheonController pantheonController, - final boolean discovery, - final Collection bootstrapPeers, - final String discoveryHost, - final int listenPort, - final int maxPeers, - final JsonRpcConfiguration jsonRpcConfiguration, - final WebSocketConfiguration webSocketConfiguration, - final Path dataDir, - final Collection bannedNodeIds) { + private Vertx vertx; + private PantheonController pantheonController; + private boolean discovery; + private Collection bootstrapPeers; + private String discoveryHost; + private int listenPort; + private int maxPeers; + private JsonRpcConfiguration jsonRpcConfiguration; + private WebSocketConfiguration webSocketConfiguration; + private Path dataDir; + private Collection bannedNodeIds; + + public RunnerBuilder vertx(final Vertx vertx) { + this.vertx = vertx; + return this; + } + + public RunnerBuilder pantheonController(final PantheonController pantheonController) { + this.pantheonController = pantheonController; + return this; + } + + public RunnerBuilder discovery(final boolean discovery) { + this.discovery = discovery; + return this; + } + + public RunnerBuilder bootstrapPeers(final Collection bootstrapPeers) { + this.bootstrapPeers = bootstrapPeers; + return this; + } + + public RunnerBuilder discoveryHost(final String discoveryHost) { + this.discoveryHost = discoveryHost; + return this; + } + + public RunnerBuilder discoveryPort(final int listenPort) { + this.listenPort = listenPort; + return this; + } + + public RunnerBuilder maxPeers(final int maxPeers) { + this.maxPeers = maxPeers; + return this; + } + + public RunnerBuilder jsonRpcConfiguration(final JsonRpcConfiguration jsonRpcConfiguration) { + this.jsonRpcConfiguration = jsonRpcConfiguration; + return this; + } + + public RunnerBuilder webSocketConfiguration(final WebSocketConfiguration webSocketConfiguration) { + this.webSocketConfiguration = webSocketConfiguration; + return this; + } + + public RunnerBuilder dataDir(final Path dataDir) { + this.dataDir = dataDir; + return this; + } + + public RunnerBuilder bannedNodeIds(final Collection bannedNodeIds) { + this.bannedNodeIds = bannedNodeIds; + return this; + } + + public Runner build() { Preconditions.checkNotNull(pantheonController); @@ -187,7 +243,7 @@ public class RunnerBuilder { filterManager); final SubscriptionManager subscriptionManager = - createSubscriptionManager(vertx, context.getBlockchain(), transactionPool); + createSubscriptionManager(vertx, transactionPool); createLogsSubscriptionService( context.getBlockchain(), context.getWorldStateArchive(), subscriptionManager); @@ -251,7 +307,7 @@ public class RunnerBuilder { } private SubscriptionManager createSubscriptionManager( - final Vertx vertx, final Blockchain blockchain, final TransactionPool transactionPool) { + final Vertx vertx, final TransactionPool transactionPool) { final SubscriptionManager subscriptionManager = new SubscriptionManager(); final PendingTransactionSubscriptionService pendingTransactions = new PendingTransactionSubscriptionService(subscriptionManager); @@ -261,7 +317,7 @@ public class RunnerBuilder { return subscriptionManager; } - private LogsSubscriptionService createLogsSubscriptionService( + private void createLogsSubscriptionService( final Blockchain blockchain, final WorldStateArchive worldStateArchive, final SubscriptionManager subscriptionManager) { @@ -270,16 +326,14 @@ public class RunnerBuilder { subscriptionManager, new BlockchainQueries(blockchain, worldStateArchive)); blockchain.observeBlockAdded(logsSubscriptionService); - - return logsSubscriptionService; } - private SyncingSubscriptionService createSyncingSubscriptionService( + private void createSyncingSubscriptionService( final Synchronizer synchronizer, final SubscriptionManager subscriptionManager) { - return new SyncingSubscriptionService(subscriptionManager, synchronizer); + new SyncingSubscriptionService(subscriptionManager, synchronizer); } - private NewBlockHeadersSubscriptionService createNewBlockHeadersSubscriptionService( + private void createNewBlockHeadersSubscriptionService( final Blockchain blockchain, final WorldStateArchive worldStateArchive, final SubscriptionManager subscriptionManager) { @@ -288,8 +342,6 @@ public class RunnerBuilder { subscriptionManager, new BlockchainQueries(blockchain, worldStateArchive)); blockchain.observeBlockAdded(newBlockHeadersSubscriptionService); - - return newBlockHeadersSubscriptionService; } private WebSocketService createWebsocketService( diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java index 445bed5876..2659c3cdf4 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java @@ -45,8 +45,8 @@ import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.Function; @@ -217,7 +217,7 @@ public class PantheonCommand implements Runnable { split = ",", arity = "1..*" ) - private final Collection bannedNodeIds = null; + private final Collection bannedNodeIds = new ArrayList<>(); // TODO: Re-enable as per NC-1057/NC-1681 // @Option( @@ -447,14 +447,16 @@ public class PantheonCommand implements Runnable { PantheonController buildController() { try { - return controllerBuilder.build( - buildSyncConfig(syncMode), - dataDir, - ethNetworkConfig(), - syncWithOttoman, - new MiningParameters(coinbase, minTransactionGasPrice, extraData, isMiningEnabled), - isDevMode, - getNodePrivateKeyFile()); + return controllerBuilder + .synchronizerConfiguration(buildSyncConfig(syncMode)) + .homePath(dataDir) + .ethNetworkConfig(ethNetworkConfig()) + .syncWithOttoman(syncWithOttoman) + .miningParameters( + new MiningParameters(coinbase, minTransactionGasPrice, extraData, isMiningEnabled)) + .devMode(isDevMode) + .nodePrivateKeyFile(getNodePrivateKeyFile()) + .build(); } catch (final InvalidConfigurationException e) { throw new ExecutionException(new CommandLine(this), e.getMessage()); } catch (final IOException e) { @@ -504,20 +506,21 @@ public class PantheonCommand implements Runnable { checkNotNull(runnerBuilder); - // BEWARE: Peer discovery boolean must be inverted as it's negated in the options ! final Runner runner = - runnerBuilder.build( - Vertx.vertx(), - controller, - !noPeerDiscovery, - bootstrapNodes, - discoveryHostAndPort.getHost(), - discoveryHostAndPort.getPort(), - maxPeers, - jsonRpcConfiguration, - webSocketConfiguration, - dataDir, - bannedNodeIds == null ? Collections.emptySet() : bannedNodeIds); + runnerBuilder + .vertx(Vertx.vertx()) + .pantheonController(controller) + // BEWARE: Peer discovery boolean must be inverted as it's negated in the options ! + .discovery(!noPeerDiscovery) + .bootstrapPeers(bootstrapNodes) + .discoveryHost(discoveryHostAndPort.getHost()) + .discoveryPort(discoveryHostAndPort.getPort()) + .maxPeers(maxPeers) + .jsonRpcConfiguration(jsonRpcConfiguration) + .webSocketConfiguration(webSocketConfiguration) + .dataDir(dataDir) + .bannedNodeIds(bannedNodeIds) + .build(); addShutdownHook(runner); runner.execute(); @@ -530,7 +533,7 @@ public class PantheonCommand implements Runnable { () -> { try { runner.close(); - } catch (Exception e) { + } catch (final Exception e) { throw new RuntimeException(e); } })); @@ -634,7 +637,7 @@ public class PantheonCommand implements Runnable { private String genesisConfig() { try { return Resources.toString(genesisFile.toURI().toURL(), UTF_8); - } catch (IOException e) { + } catch (final IOException e) { throw new ParameterException( new CommandLine(this), String.format("Unable to load genesis file %s.", genesisFile), e); } diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java index 16521bb80c..b429842445 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java @@ -31,22 +31,58 @@ import java.nio.file.Path; public class PantheonControllerBuilder { - public PantheonController build( - final SynchronizerConfiguration synchronizerConfiguration, - final Path homePath, - final EthNetworkConfig ethNetworkConfig, - final boolean syncWithOttoman, - final MiningParameters miningParameters, - final boolean isDevMode, - final File nodePrivateKeyFile) - throws IOException { + private SynchronizerConfiguration synchronizerConfiguration; + private Path homePath; + private EthNetworkConfig ethNetworkConfig; + private boolean syncWithOttoman; + private MiningParameters miningParameters; + private boolean devMode; + private File nodePrivateKeyFile; + + public PantheonControllerBuilder synchronizerConfiguration( + final SynchronizerConfiguration synchronizerConfiguration) { + this.synchronizerConfiguration = synchronizerConfiguration; + return this; + } + + public PantheonControllerBuilder homePath(final Path homePath) { + this.homePath = homePath; + return this; + } + + public PantheonControllerBuilder ethNetworkConfig(final EthNetworkConfig ethNetworkConfig) { + this.ethNetworkConfig = ethNetworkConfig; + return this; + } + + public PantheonControllerBuilder syncWithOttoman(final boolean syncWithOttoman) { + this.syncWithOttoman = syncWithOttoman; + return this; + } + + public PantheonControllerBuilder miningParameters(final MiningParameters miningParameters) { + this.miningParameters = miningParameters; + return this; + } + + public PantheonControllerBuilder devMode(final boolean devMode) { + this.devMode = devMode; + return this; + } + + public PantheonControllerBuilder nodePrivateKeyFile(final File nodePrivateKeyFile) { + this.nodePrivateKeyFile = nodePrivateKeyFile; + return this; + } + + public PantheonController build() throws IOException { // instantiate a controller with mainnet config if no genesis file is defined // otherwise use the indicated genesis file final KeyPair nodeKeys = loadKeyPair(nodePrivateKeyFile); final StorageProvider storageProvider = RocksDbStorageProvider.create(homePath.resolve(DATABASE_PATH)); - if (isDevMode) { + if (devMode) { final GenesisConfigFile genesisConfig = GenesisConfigFile.development(); return MainnetPantheonController.init( storageProvider, diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java index 8389cf47c7..dd7785df58 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java @@ -118,20 +118,23 @@ public final class RunnerTest { final ExecutorService executorService = Executors.newFixedThreadPool(2); final JsonRpcConfiguration aheadJsonRpcConfiguration = jsonRpcConfiguration(); final WebSocketConfiguration aheadWebSocketConfiguration = wsRpcConfiguration(); - final RunnerBuilder runnerBuilder = new RunnerBuilder(); + final RunnerBuilder runnerBuilder = + new RunnerBuilder() + .vertx(Vertx.vertx()) + .discovery(true) + .discoveryHost(listenHost) + .discoveryPort(0) + .maxPeers(3) + .bannedNodeIds(Collections.emptySet()); + final Runner runnerAhead = - runnerBuilder.build( - Vertx.vertx(), - controllerAhead, - true, - Collections.emptyList(), - listenHost, - 0, - 3, - aheadJsonRpcConfiguration, - aheadWebSocketConfiguration, - dbAhead, - Collections.emptySet()); + runnerBuilder + .pantheonController(controllerAhead) + .bootstrapPeers(Collections.emptyList()) + .jsonRpcConfiguration(aheadJsonRpcConfiguration) + .webSocketConfiguration(aheadWebSocketConfiguration) + .dataDir(dbAhead) + .build(); try { executorService.submit(runnerAhead::execute); @@ -148,23 +151,19 @@ public final class RunnerTest { new MiningParametersTestBuilder().enabled(false).build(), KeyPair.generate()); final Runner runnerBehind = - runnerBuilder.build( - Vertx.vertx(), - controllerBehind, - true, - Collections.singletonList( - new DefaultPeer( - aheadDbNodeKeys.getPublicKey().getEncodedBytes(), - listenHost, - runnerAhead.getP2pUdpPort(), - runnerAhead.getP2pTcpPort())), - listenHost, - 0, - 3, - behindJsonRpcConfiguration, - behindWebSocketConfiguration, - temp.newFolder().toPath(), - Collections.emptySet()); + runnerBuilder + .pantheonController(controllerBehind) + .bootstrapPeers( + Collections.singletonList( + new DefaultPeer( + aheadDbNodeKeys.getPublicKey().getEncodedBytes(), + listenHost, + runnerAhead.getP2pUdpPort(), + runnerAhead.getP2pTcpPort()))) + .jsonRpcConfiguration(behindJsonRpcConfiguration) + .webSocketConfiguration(behindWebSocketConfiguration) + .dataDir(temp.newFolder().toPath()) + .build(); executorService.submit(runnerBehind::execute); final Call.Factory client = new OkHttpClient(); diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java b/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java index b3b762fb6a..46289b7947 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java @@ -75,9 +75,14 @@ public abstract class CommandTestAbstract { @Before public void initMocks() throws Exception { // doReturn used because of generic PantheonController - Mockito.doReturn(mockController) - .when(mockControllerBuilder) - .build(any(), any(), any(), anyBoolean(), any(), anyBoolean(), any()); + Mockito.doReturn(mockController).when(mockControllerBuilder).build(); + when(mockControllerBuilder.synchronizerConfiguration(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.homePath(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.ethNetworkConfig(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.syncWithOttoman(anyBoolean())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.miningParameters(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.devMode(anyBoolean())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.nodePrivateKeyFile(any())).thenReturn(mockControllerBuilder); when(mockSyncConfBuilder.build()).thenReturn(mockSyncConf); } diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java index fd7166b22d..0fda207ae5 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java @@ -84,19 +84,18 @@ public class PantheonCommandTest extends CommandTestAbstract { public void initMocks() throws Exception { super.initMocks(); - when(mockRunnerBuilder.build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - any(), - any(), - any(), - any())) - .thenReturn(mockRunner); + when(mockRunnerBuilder.vertx(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.pantheonController(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.discovery(anyBoolean())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.bootstrapPeers(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.discoveryHost(anyString())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.discoveryPort(anyInt())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.maxPeers(anyInt())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.jsonRpcConfiguration(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.webSocketConfiguration(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.dataDir(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.bannedNodeIds(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.build()).thenReturn(mockRunner); } @Test @@ -126,33 +125,27 @@ public class PantheonCommandTest extends CommandTestAbstract { public void callingPantheonCommandWithoutOptionsMustSyncWithDefaultValues() throws Exception { parseCommand(); - verify(mockRunnerBuilder) - .build( - any(), - any(), - eq(true), - eq(MAINNET_BOOTSTRAP_NODES), - eq("127.0.0.1"), - eq(30303), - eq(25), - eq(defaultJsonRpcConfiguration), - eq(defaultWebSocketConfiguration), - any(), - any()); + verify(mockRunnerBuilder).discovery(eq(true)); + verify(mockRunnerBuilder).bootstrapPeers(MAINNET_BOOTSTRAP_NODES); + verify(mockRunnerBuilder).discoveryHost(eq("127.0.0.1")); + verify(mockRunnerBuilder).discoveryPort(eq(30303)); + verify(mockRunnerBuilder).maxPeers(eq(25)); + verify(mockRunnerBuilder).jsonRpcConfiguration(eq(defaultJsonRpcConfiguration)); + verify(mockRunnerBuilder).webSocketConfiguration(eq(defaultWebSocketConfiguration)); + verify(mockRunnerBuilder).build(); final ArgumentCaptor miningArg = ArgumentCaptor.forClass(MiningParameters.class); final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder) - .build( - any(), - isNotNull(), - networkArg.capture(), - eq(false), - miningArg.capture(), - eq(false), - isNotNull()); + verify(mockControllerBuilder).synchronizerConfiguration(isNotNull()); + verify(mockControllerBuilder).homePath(isNotNull()); + verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilder).syncWithOttoman(eq(false)); + verify(mockControllerBuilder).miningParameters(miningArg.capture()); + verify(mockControllerBuilder).devMode(eq(false)); + verify(mockControllerBuilder).nodePrivateKeyFile(isNotNull()); + verify(mockControllerBuilder).build(); verify(mockSyncConfBuilder).syncMode(ArgumentMatchers.eq(SyncMode.FULL)); @@ -265,19 +258,14 @@ public class PantheonCommandTest extends CommandTestAbstract { parseCommand("--config", toml.toString()); - verify(mockRunnerBuilder) - .build( - any(), - any(), - eq(false), - stringListArgumentCaptor.capture(), - eq("1.2.3.4"), - eq(1234), - eq(42), - eq(jsonRpcConfiguration), - eq(webSocketConfiguration), - any(), - any()); + verify(mockRunnerBuilder).discovery(eq(false)); + verify(mockRunnerBuilder).bootstrapPeers(stringListArgumentCaptor.capture()); + verify(mockRunnerBuilder).discoveryHost(eq("1.2.3.4")); + verify(mockRunnerBuilder).discoveryPort(eq(1234)); + verify(mockRunnerBuilder).maxPeers(eq(42)); + verify(mockRunnerBuilder).jsonRpcConfiguration(eq(jsonRpcConfiguration)); + verify(mockRunnerBuilder).webSocketConfiguration(eq(webSocketConfiguration)); + verify(mockRunnerBuilder).build(); final Collection nodes = asList("enode://001@123:4567", "enode://002@123:4567", "enode://003@123:4567"); @@ -288,15 +276,9 @@ public class PantheonCommandTest extends CommandTestAbstract { .setGenesisConfig(GENESIS_CONFIG_TESTDATA) .setBootNodes(nodes) .build(); - verify(mockControllerBuilder) - .build( - any(), - eq(Paths.get("~/pantheondata")), - eq(networkConfig), - eq(false), - any(), - anyBoolean(), - any()); + verify(mockControllerBuilder).homePath(eq(Paths.get("~/pantheondata"))); + verify(mockControllerBuilder).ethNetworkConfig(eq(networkConfig)); + verify(mockControllerBuilder).syncWithOttoman(eq(false)); // TODO: Re-enable as per NC-1057/NC-1681 // verify(mockSyncConfBuilder).syncMode(ArgumentMatchers.eq(SyncMode.FAST)); @@ -320,21 +302,18 @@ public class PantheonCommandTest extends CommandTestAbstract { webSocketConfiguration.addRpcApi(CliqueRpcApis.CLIQUE); webSocketConfiguration.addRpcApi(IbftRpcApis.IBFT); - verify(mockRunnerBuilder) - .build( - any(), - any(), - eq(true), - eq(MAINNET_BOOTSTRAP_NODES), - eq("127.0.0.1"), - eq(30303), - eq(25), - eq(jsonRpcConfiguration), - eq(webSocketConfiguration), - any(), - any()); - - verify(mockControllerBuilder).build(any(), any(), any(), eq(false), any(), eq(false), any()); + verify(mockRunnerBuilder).discovery(eq(true)); + verify(mockRunnerBuilder).bootstrapPeers(MAINNET_BOOTSTRAP_NODES); + verify(mockRunnerBuilder).discoveryHost(eq("127.0.0.1")); + verify(mockRunnerBuilder).discoveryPort(eq(30303)); + verify(mockRunnerBuilder).maxPeers(eq(25)); + verify(mockRunnerBuilder).jsonRpcConfiguration(eq(jsonRpcConfiguration)); + verify(mockRunnerBuilder).webSocketConfiguration(eq(webSocketConfiguration)); + verify(mockRunnerBuilder).build(); + + verify(mockControllerBuilder).syncWithOttoman(eq(false)); + verify(mockControllerBuilder).devMode(eq(false)); + verify(mockControllerBuilder).build(); // TODO: Re-enable as per NC-1057/NC-1681 // verify(mockSyncConfBuilder).syncMode(ArgumentMatchers.eq(SyncMode.FULL)); @@ -351,15 +330,10 @@ public class PantheonCommandTest extends CommandTestAbstract { parseCommand("--node-private-key", file.getPath()); - verify(mockControllerBuilder) - .build( - any(), - isNotNull(), - any(), - eq(false), - any(), - anyBoolean(), - fileArgumentCaptor.capture()); + verify(mockControllerBuilder).homePath(isNotNull()); + verify(mockControllerBuilder).syncWithOttoman(eq(false)); + verify(mockControllerBuilder).nodePrivateKeyFile(fileArgumentCaptor.capture()); + verify(mockControllerBuilder).build(); assertThat(fileArgumentCaptor.getValue()).isEqualTo(file); @@ -373,15 +347,10 @@ public class PantheonCommandTest extends CommandTestAbstract { parseCommand("--datadir", path.toString()); - verify(mockControllerBuilder) - .build( - any(), - pathArgumentCaptor.capture(), - any(), - eq(false), - any(), - anyBoolean(), - eq(path.resolve("key").toFile())); + verify(mockControllerBuilder).homePath(pathArgumentCaptor.capture()); + verify(mockControllerBuilder).syncWithOttoman(eq(false)); + verify(mockControllerBuilder).nodePrivateKeyFile(eq(path.resolve("key").toFile())); + verify(mockControllerBuilder).build(); assertThat(pathArgumentCaptor.getValue()).isEqualByComparingTo(path); @@ -397,8 +366,8 @@ public class PantheonCommandTest extends CommandTestAbstract { parseCommand("--genesis", genesisFile.toString()); - verify(mockControllerBuilder) - .build(any(), any(), networkArg.capture(), anyBoolean(), any(), anyBoolean(), any()); + verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilder).build(); assertThat(networkArg.getValue().getGenesisConfig()).isEqualTo("genesis_config"); @@ -412,19 +381,7 @@ public class PantheonCommandTest extends CommandTestAbstract { // Discovery stored in runner is the negative of the option passed to CLI // So as passing the option means noDiscovery will be true, then discovery is false in runner - verify(mockRunnerBuilder) - .build( - any(), - any(), - eq(false), - any(), - anyString(), - anyInt(), - anyInt(), - any(), - any(), - any(), - any()); + verify(mockRunnerBuilder.discovery(eq(false))).build(); assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty(); @@ -453,19 +410,8 @@ public class PantheonCommandTest extends CommandTestAbstract { final String[] nodes = {"enode://001@123:4567", "enode://002@123:4567", "enode://003@123:4567"}; parseCommand("--bootnodes", String.join(",", nodes)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - stringListArgumentCaptor.capture(), - anyString(), - anyInt(), - anyInt(), - any(), - any(), - any(), - any()); + verify(mockRunnerBuilder).bootstrapPeers(stringListArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(stringListArgumentCaptor.getValue().toArray()).isEqualTo(nodes); @@ -478,19 +424,8 @@ public class PantheonCommandTest extends CommandTestAbstract { final String[] nodes = {"0001", "0002", "0003"}; parseCommand("--banned-nodeids", String.join(",", nodes)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - any(), - any(), - any(), - stringListArgumentCaptor.capture()); + verify(mockRunnerBuilder).bannedNodeIds(stringListArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(stringListArgumentCaptor.getValue().toArray()).isEqualTo(nodes); @@ -505,19 +440,9 @@ public class PantheonCommandTest extends CommandTestAbstract { final int port = 1234; parseCommand("--p2p-listen", String.format("%1$s:%2$s", host, port)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - stringArgumentCaptor.capture(), - intArgumentCaptor.capture(), - anyInt(), - any(), - any(), - any(), - any()); + verify(mockRunnerBuilder).discoveryHost(stringArgumentCaptor.capture()); + verify(mockRunnerBuilder).discoveryPort(intArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(stringArgumentCaptor.getValue()).isEqualTo(host); assertThat(intArgumentCaptor.getValue()).isEqualTo(port); @@ -532,19 +457,8 @@ public class PantheonCommandTest extends CommandTestAbstract { final int maxPeers = 123; parseCommand("--max-peers", String.valueOf(maxPeers)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - intArgumentCaptor.capture(), - any(), - any(), - any(), - any()); + verify(mockRunnerBuilder).maxPeers(intArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(intArgumentCaptor.getValue()).isEqualTo(maxPeers); @@ -579,19 +493,8 @@ public class PantheonCommandTest extends CommandTestAbstract { public void jsonRpcEnabledPropertyDefaultIsFalse() { parseCommand(); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - jsonRpcConfigArgumentCaptor.capture(), - any(), - any(), - any()); + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(jsonRpcConfigArgumentCaptor.getValue().isEnabled()).isFalse(); @@ -603,19 +506,8 @@ public class PantheonCommandTest extends CommandTestAbstract { public void jsonRpcEnabledPropertyMustBeUsed() { parseCommand("--rpc-enabled"); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - jsonRpcConfigArgumentCaptor.capture(), - any(), - any(), - any()); + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(jsonRpcConfigArgumentCaptor.getValue().isEnabled()).isTrue(); @@ -627,19 +519,8 @@ public class PantheonCommandTest extends CommandTestAbstract { public void rpcApisPropertyMustBeUsed() { parseCommand("--rpc-api", "ETH,NET"); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - jsonRpcConfigArgumentCaptor.capture(), - any(), - any(), - any()); + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(jsonRpcConfigArgumentCaptor.getValue().getRpcApis()) .containsExactlyInAnyOrder(RpcApis.ETH, RpcApis.NET); @@ -655,19 +536,8 @@ public class PantheonCommandTest extends CommandTestAbstract { final int port = 1234; parseCommand("--rpc-listen", String.format("%1$s:%2$s", host, port)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - jsonRpcConfigArgumentCaptor.capture(), - any(), - any(), - any()); + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(jsonRpcConfigArgumentCaptor.getValue().getHost()).isEqualTo(host); assertThat(jsonRpcConfigArgumentCaptor.getValue().getPort()).isEqualTo(port); @@ -681,19 +551,8 @@ public class PantheonCommandTest extends CommandTestAbstract { final String[] origins = {"http://domain1.com", "https://domain2.com"}; parseCommand("--rpc-cors-origins", String.join(",", origins)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - jsonRpcConfigArgumentCaptor.capture(), - any(), - any(), - any()); + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(jsonRpcConfigArgumentCaptor.getValue().getCorsAllowedDomains().toArray()) .isEqualTo(origins); @@ -707,19 +566,8 @@ public class PantheonCommandTest extends CommandTestAbstract { final String[] origins = {"*"}; parseCommand("--rpc-cors-origins", String.join(",", origins)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - jsonRpcConfigArgumentCaptor.capture(), - any(), - any(), - any()); + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(jsonRpcConfigArgumentCaptor.getValue().getCorsAllowedDomains().toArray()) .isEqualTo(origins); @@ -733,19 +581,8 @@ public class PantheonCommandTest extends CommandTestAbstract { final String[] origins = {"all"}; parseCommand("--rpc-cors-origins", String.join(",", origins)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - jsonRpcConfigArgumentCaptor.capture(), - any(), - any(), - any()); + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(jsonRpcConfigArgumentCaptor.getValue().getCorsAllowedDomains()) .isEqualTo(Lists.newArrayList("*")); @@ -759,19 +596,8 @@ public class PantheonCommandTest extends CommandTestAbstract { final String[] origins = {"none"}; parseCommand("--rpc-cors-origins", String.join(",", origins)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - jsonRpcConfigArgumentCaptor.capture(), - any(), - any(), - any()); + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(jsonRpcConfigArgumentCaptor.getValue().getCorsAllowedDomains()).isEmpty(); @@ -831,19 +657,8 @@ public class PantheonCommandTest extends CommandTestAbstract { public void wsRpcEnabledPropertyDefaultIsFalse() { parseCommand(); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - any(), - wsRpcConfigArgumentCaptor.capture(), - any(), - any()); + verify(mockRunnerBuilder).webSocketConfiguration(wsRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(wsRpcConfigArgumentCaptor.getValue().isEnabled()).isFalse(); @@ -855,19 +670,8 @@ public class PantheonCommandTest extends CommandTestAbstract { public void wsRpcEnabledPropertyMustBeUsed() { parseCommand("--ws-enabled"); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - any(), - wsRpcConfigArgumentCaptor.capture(), - any(), - any()); + verify(mockRunnerBuilder).webSocketConfiguration(wsRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(wsRpcConfigArgumentCaptor.getValue().isEnabled()).isTrue(); @@ -879,19 +683,8 @@ public class PantheonCommandTest extends CommandTestAbstract { public void wsApiPropertyMustBeUsed() { parseCommand("--ws-api", "ETH, NET"); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - any(), - wsRpcConfigArgumentCaptor.capture(), - any(), - any()); + verify(mockRunnerBuilder).webSocketConfiguration(wsRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(wsRpcConfigArgumentCaptor.getValue().getRpcApis()) .containsExactlyInAnyOrder(RpcApis.ETH, RpcApis.NET); @@ -906,19 +699,8 @@ public class PantheonCommandTest extends CommandTestAbstract { final int port = 1234; parseCommand("--ws-listen", String.format("%1$s:%2$s", host, port)); - verify(mockRunnerBuilder) - .build( - any(), - any(), - anyBoolean(), - any(), - anyString(), - anyInt(), - anyInt(), - any(), - wsRpcConfigArgumentCaptor.capture(), - any(), - any()); + verify(mockRunnerBuilder).webSocketConfiguration(wsRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); assertThat(wsRpcConfigArgumentCaptor.getValue().getHost()).isEqualTo(host); assertThat(wsRpcConfigArgumentCaptor.getValue().getPort()).isEqualTo(port); @@ -928,12 +710,9 @@ public class PantheonCommandTest extends CommandTestAbstract { } @Test - public void pantheonDoesNotStartInMiningModeIfCoinbaseNotSet() throws Exception { + public void pantheonDoesNotStartInMiningModeIfCoinbaseNotSet() { parseCommand("--miner-enabled"); - final ArgumentCaptor miningArg = - ArgumentCaptor.forClass(MiningParameters.class); - verifyZeroInteractions(mockControllerBuilder); } @@ -945,8 +724,9 @@ public class PantheonCommandTest extends CommandTestAbstract { final ArgumentCaptor miningArg = ArgumentCaptor.forClass(MiningParameters.class); - verify(mockControllerBuilder) - .build(any(), any(), any(), anyBoolean(), miningArg.capture(), anyBoolean(), any()); + verify(mockControllerBuilder).miningParameters(miningArg.capture()); + verify(mockControllerBuilder).build(); + assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty(); assertThat(miningArg.getValue().isMiningEnabled()).isTrue(); @@ -967,8 +747,9 @@ public class PantheonCommandTest extends CommandTestAbstract { final ArgumentCaptor miningArg = ArgumentCaptor.forClass(MiningParameters.class); - verify(mockControllerBuilder) - .build(any(), any(), any(), anyBoolean(), miningArg.capture(), anyBoolean(), any()); + verify(mockControllerBuilder).miningParameters(miningArg.capture()); + verify(mockControllerBuilder).build(); + assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty(); assertThat(miningArg.getValue().getCoinbase()).isEqualTo(Optional.of(requestedCoinbase)); @@ -980,7 +761,10 @@ public class PantheonCommandTest extends CommandTestAbstract { @Test public void devModeOptionMustBeUsed() throws Exception { parseCommand("--dev-mode"); - verify(mockControllerBuilder).build(any(), any(), any(), anyBoolean(), any(), eq(true), any()); + + verify(mockControllerBuilder).devMode(eq(true)); + verify(mockControllerBuilder).build(); + assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty(); } @@ -991,8 +775,10 @@ public class PantheonCommandTest extends CommandTestAbstract { final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder) - .build(any(), any(), networkArg.capture(), anyBoolean(), any(), anyBoolean(), any()); + + verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilder).build(); + assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty(); assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.rinkeby()); @@ -1013,8 +799,10 @@ public class PantheonCommandTest extends CommandTestAbstract { final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder) - .build(any(), any(), networkArg.capture(), anyBoolean(), any(), anyBoolean(), any()); + + verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilder).build(); + assertThat(commandOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty(); assertThat(networkArg.getValue().getGenesisConfig()).isEqualTo("genesis_config");