From b92306b82b4078d87ca04e3354dd5355eefa1d1c Mon Sep 17 00:00:00 2001 From: Andras Slemmer Date: Fri, 1 Sep 2017 12:21:35 +0100 Subject: [PATCH 1/3] Add a Java-style builder for Driver parameters --- .../kotlin/net/corda/testing/driver/Driver.kt | 81 +++++++++++++------ 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt b/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt index 58e333413d..f208e272df 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt @@ -244,32 +244,67 @@ sealed class PortAllocation { */ @JvmOverloads fun driver( - isDebug: Boolean = false, - driverDirectory: Path = Paths.get("build", getTimestampAsDirectoryName()), - portAllocation: PortAllocation = PortAllocation.Incremental(10000), - debugPortAllocation: PortAllocation = PortAllocation.Incremental(5005), - systemProperties: Map = emptyMap(), - useTestClock: Boolean = false, - initialiseSerialization: Boolean = true, - networkMapStartStrategy: NetworkMapStartStrategy = NetworkMapStartStrategy.Dedicated(startAutomatically = true), - startNodesInProcess: Boolean = false, + defaultParameters: DriverParameters = DriverParameters(), + isDebug: Boolean = defaultParameters.isDebug, + driverDirectory: Path = defaultParameters.driverDirectory, + portAllocation: PortAllocation = defaultParameters.portAllocation, + debugPortAllocation: PortAllocation = defaultParameters.debugPortAllocation, + systemProperties: Map = defaultParameters.systemProperties, + useTestClock: Boolean = defaultParameters.useTestClock, + initialiseSerialization: Boolean = defaultParameters.initialiseSerialization, + networkMapStartStrategy: NetworkMapStartStrategy = defaultParameters.networkMapStartStrategy, + startNodesInProcess: Boolean = defaultParameters.startNodesInProcess, dsl: DriverDSLExposedInterface.() -> A -) = genericDriver( - driverDsl = DriverDSL( - portAllocation = portAllocation, - debugPortAllocation = debugPortAllocation, - systemProperties = systemProperties, - driverDirectory = driverDirectory.toAbsolutePath(), - useTestClock = useTestClock, - networkMapStartStrategy = networkMapStartStrategy, - startNodesInProcess = startNodesInProcess, - isDebug = isDebug - ), - coerce = { it }, - dsl = dsl, - initialiseSerialization = initialiseSerialization +): A { + return genericDriver( + driverDsl = DriverDSL( + portAllocation = portAllocation, + debugPortAllocation = debugPortAllocation, + systemProperties = systemProperties, + driverDirectory = driverDirectory.toAbsolutePath(), + useTestClock = useTestClock, + networkMapStartStrategy = networkMapStartStrategy, + startNodesInProcess = startNodesInProcess, + isDebug = isDebug + ), + coerce = { it }, + dsl = dsl, + initialiseSerialization = initialiseSerialization + ) +} + +fun driver( + builder: DriverBuilder, + dsl: DriverDSLExposedInterface.() -> A +): A { + return driver(defaultParameters = builder.parameters, dsl = dsl) +} + +data class DriverParameters( + val isDebug: Boolean = false, + val driverDirectory: Path = Paths.get("build", getTimestampAsDirectoryName()), + val portAllocation: PortAllocation = PortAllocation.Incremental(10000), + val debugPortAllocation: PortAllocation = PortAllocation.Incremental(5005), + val systemProperties: Map = emptyMap(), + val useTestClock: Boolean = false, + val initialiseSerialization: Boolean = true, + val networkMapStartStrategy: NetworkMapStartStrategy = NetworkMapStartStrategy.Dedicated(startAutomatically = true), + val startNodesInProcess: Boolean = false ) +class DriverBuilder(val parameters: DriverParameters) { + constructor() : this(DriverParameters()) + fun setIsDebug(newValue: Boolean) = DriverBuilder(parameters.copy(isDebug = newValue)) + fun setDriverDirectory(newValue: Path) = DriverBuilder(parameters.copy(driverDirectory = newValue)) + fun setPortAllocation(newValue: PortAllocation) = DriverBuilder(parameters.copy(portAllocation = newValue)) + fun setDebugPortAllocation(newValue: PortAllocation) = DriverBuilder(parameters.copy(debugPortAllocation = newValue)) + fun setSystemProperties(newValue: Map) = DriverBuilder(parameters.copy(systemProperties = newValue)) + fun setUseTestClock(newValue: Boolean) = DriverBuilder(parameters.copy(useTestClock = newValue)) + fun setInitialiseSerialization(newValue: Boolean) = DriverBuilder(parameters.copy(initialiseSerialization = newValue)) + fun setNetworkMapStartStrategy(newValue: NetworkMapStartStrategy) = DriverBuilder(parameters.copy(networkMapStartStrategy = newValue)) + fun setStartNodesInProcess(newValue: Boolean) = DriverBuilder(parameters.copy(startNodesInProcess = newValue)) +} + /** * This is a helper method to allow extending of the DSL, along the lines of * interface SomeOtherExposedDSLInterface : DriverDSLExposedInterface From e3ddf84cf83974a50446a7bc8b1d2ceed59b009a Mon Sep 17 00:00:00 2001 From: joeldudleyr3 Date: Fri, 1 Sep 2017 13:51:12 +0100 Subject: [PATCH 2/3] Combines Parameters with Builder. --- .../kotlin/net/corda/testing/driver/Driver.kt | 89 +++++++++++-------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt b/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt index f208e272df..44933024c0 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt @@ -146,6 +146,7 @@ interface DriverDSLExposedInterface : CordformContext { * @return A future that completes with the non-null value [check] has returned. */ fun pollUntilNonNull(pollName: String, pollInterval: Duration = 500.millis, warnCount: Int = 120, check: () -> A?): CordaFuture + /** * Polls the given function until it returns true. * @see pollUntilNonNull @@ -242,11 +243,10 @@ sealed class PortAllocation { * @param dsl The dsl itself. * @return The value returned in the [dsl] closure. */ -@JvmOverloads fun driver( - defaultParameters: DriverParameters = DriverParameters(), isDebug: Boolean = defaultParameters.isDebug, - driverDirectory: Path = defaultParameters.driverDirectory, + // The directory must be different for each call to `driver`. + driverDirectory: Path = Paths.get("build", getTimestampAsDirectoryName()), portAllocation: PortAllocation = defaultParameters.portAllocation, debugPortAllocation: PortAllocation = defaultParameters.debugPortAllocation, systemProperties: Map = defaultParameters.systemProperties, @@ -274,10 +274,21 @@ fun driver( } fun driver( - builder: DriverBuilder, + parameters: DriverParameters, dsl: DriverDSLExposedInterface.() -> A ): A { - return driver(defaultParameters = builder.parameters, dsl = dsl) + return driver( + isDebug = parameters.isDebug, + driverDirectory = parameters.driverDirectory, + portAllocation = parameters.portAllocation, + debugPortAllocation = parameters.debugPortAllocation, + systemProperties = parameters.systemProperties, + useTestClock = parameters.useTestClock, + initialiseSerialization = parameters.initialiseSerialization, + networkMapStartStrategy = parameters.networkMapStartStrategy, + startNodesInProcess = parameters.startNodesInProcess, + dsl = dsl + ) } data class DriverParameters( @@ -290,21 +301,20 @@ data class DriverParameters( val initialiseSerialization: Boolean = true, val networkMapStartStrategy: NetworkMapStartStrategy = NetworkMapStartStrategy.Dedicated(startAutomatically = true), val startNodesInProcess: Boolean = false -) - -class DriverBuilder(val parameters: DriverParameters) { - constructor() : this(DriverParameters()) - fun setIsDebug(newValue: Boolean) = DriverBuilder(parameters.copy(isDebug = newValue)) - fun setDriverDirectory(newValue: Path) = DriverBuilder(parameters.copy(driverDirectory = newValue)) - fun setPortAllocation(newValue: PortAllocation) = DriverBuilder(parameters.copy(portAllocation = newValue)) - fun setDebugPortAllocation(newValue: PortAllocation) = DriverBuilder(parameters.copy(debugPortAllocation = newValue)) - fun setSystemProperties(newValue: Map) = DriverBuilder(parameters.copy(systemProperties = newValue)) - fun setUseTestClock(newValue: Boolean) = DriverBuilder(parameters.copy(useTestClock = newValue)) - fun setInitialiseSerialization(newValue: Boolean) = DriverBuilder(parameters.copy(initialiseSerialization = newValue)) - fun setNetworkMapStartStrategy(newValue: NetworkMapStartStrategy) = DriverBuilder(parameters.copy(networkMapStartStrategy = newValue)) - fun setStartNodesInProcess(newValue: Boolean) = DriverBuilder(parameters.copy(startNodesInProcess = newValue)) +) { + fun setIsDebug(isDebug: Boolean) = copy(isDebug = isDebug) + fun setDriverDirectory(driverDirectory: Path) = copy(driverDirectory = driverDirectory) + fun setPortAllocation(portAllocation: PortAllocation) = copy(portAllocation = portAllocation) + fun setDebugPortAllocation(debugPortAllocation: PortAllocation) = copy(debugPortAllocation = debugPortAllocation) + fun setSystemProperties(systemProperties: Map) = copy(systemProperties = systemProperties) + fun setUseTestClock(useTestClock: Boolean) = copy(useTestClock = useTestClock) + fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization) + fun setNetworkMapStartStrategy(networkMapStartStrategy: NetworkMapStartStrategy) = copy(networkMapStartStrategy = networkMapStartStrategy) + fun setStartNodesInProcess(startNodesInProcess: Boolean) = copy(startNodesInProcess = startNodesInProcess) } +private val defaultParameters = DriverParameters() + /** * This is a helper method to allow extending of the DSL, along the lines of * interface SomeOtherExposedDSLInterface : DriverDSLExposedInterface @@ -438,15 +448,17 @@ class ShutdownManager(private val executorService: ExecutorService) { } } val shutdowns = shutdownActionFutures.map { Try.on { it.getOrThrow(1.seconds) } } - shutdowns.reversed().forEach { when (it) { - is Try.Success -> - try { - it.value() - } catch (t: Throwable) { - log.warn("Exception while shutting down", t) - } - is Try.Failure -> log.warn("Exception while getting shutdown method, disregarding", it.exception) - } } + shutdowns.reversed().forEach { + when (it) { + is Try.Success -> + try { + it.value() + } catch (t: Throwable) { + log.warn("Exception while shutting down", t) + } + is Try.Failure -> log.warn("Exception while getting shutdown method, disregarding", it.exception) + } + } } fun registerShutdown(shutdown: CordaFuture<() -> Unit>) { @@ -455,6 +467,7 @@ class ShutdownManager(private val executorService: ExecutorService) { registeredShutdowns.add(shutdown) } } + fun registerShutdown(shutdown: () -> Unit) = registerShutdown(doneFuture(shutdown)) fun registerProcessShutdown(processFuture: CordaFuture) { @@ -667,7 +680,7 @@ class DriverDSL( rpcUsers = rpcUsers, verifierType = verifierType, customOverrides = mapOf("notaryNodeAddress" to notaryClusterAddress.toString(), - "database.serverNameTablePrefix" to if (nodeNames.isNotEmpty()) nodeNames.first().toString().replace(Regex("[^0-9A-Za-z]+"),"") else ""), + "database.serverNameTablePrefix" to if (nodeNames.isNotEmpty()) nodeNames.first().toString().replace(Regex("[^0-9A-Za-z]+"), "") else ""), startInSameProcess = startInSameProcess ) // All other nodes will join the cluster @@ -696,7 +709,7 @@ class DriverDSL( if (response.isSuccessful && (response.body().string() == "started")) { return WebserverHandle(handle.webAddress, process) } - } catch(e: ConnectException) { + } catch (e: ConnectException) { log.debug("Retrying webserver info at ${handle.webAddress}") } @@ -746,10 +759,12 @@ class DriverDSL( if (startInProcess ?: startNodesInProcess) { val nodeAndThreadFuture = startInProcessNode(executorService, nodeConfiguration, config) shutdownManager.registerShutdown( - nodeAndThreadFuture.map { (node, thread) -> { - node.stop() - thread.interrupt() - } } + nodeAndThreadFuture.map { (node, thread) -> + { + node.stop() + thread.interrupt() + } + } ) return nodeAndThreadFuture.flatMap { (node, thread) -> establishRpc(nodeConfiguration.p2pAddress, nodeConfiguration, openFuture()).flatMap { rpc -> @@ -857,8 +872,8 @@ class DriverDSL( workingDirectory = nodeConf.baseDirectory ) } - return processFuture.flatMap { - process -> addressMustBeBoundFuture(executorService, nodeConf.p2pAddress, process).map { process } + return processFuture.flatMap { process -> + addressMustBeBoundFuture(executorService, nodeConf.p2pAddress, process).map { process } } } @@ -874,8 +889,8 @@ class DriverDSL( arguments = listOf("--base-directory", handle.configuration.baseDirectory.toString()), jdwpPort = debugPort, extraJvmArguments = listOf( - "-Dname=node-${handle.configuration.p2pAddress}-webserver", - "-Djava.io.tmpdir=${System.getProperty("java.io.tmpdir")}" // Inherit from parent process + "-Dname=node-${handle.configuration.p2pAddress}-webserver", + "-Djava.io.tmpdir=${System.getProperty("java.io.tmpdir")}" // Inherit from parent process ), errorLogPath = Paths.get("error.$className.log") ) From c43dd079e4966f8ca1886e6de6ecbcaa20f0f1c9 Mon Sep 17 00:00:00 2001 From: joeldudleyr3 Date: Fri, 1 Sep 2017 15:34:57 +0100 Subject: [PATCH 3/3] Addresses review feedback. --- .../kotlin/net/corda/testing/driver/Driver.kt | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt b/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt index 44933024c0..e2c2539f10 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt @@ -229,6 +229,8 @@ sealed class PortAllocation { * * The driver implicitly bootstraps a [NetworkMapService]. * + * @param defaultParameters The default parameters for the driver. Allows the driver to be configured in builder style + * when called from Java code. * @param isDebug Indicates whether the spawned nodes should start in jdwt debug mode and have debug level logging. * @param driverDirectory The base directory node directories go into, defaults to "build//". The node * directories themselves are "//", where legalName defaults to "-" @@ -244,9 +246,9 @@ sealed class PortAllocation { * @return The value returned in the [dsl] closure. */ fun driver( + defaultParameters: DriverParameters = DriverParameters(), isDebug: Boolean = defaultParameters.isDebug, - // The directory must be different for each call to `driver`. - driverDirectory: Path = Paths.get("build", getTimestampAsDirectoryName()), + driverDirectory: Path = defaultParameters.driverDirectory, portAllocation: PortAllocation = defaultParameters.portAllocation, debugPortAllocation: PortAllocation = defaultParameters.debugPortAllocation, systemProperties: Map = defaultParameters.systemProperties, @@ -273,24 +275,23 @@ fun driver( ) } +/** + * Helper function for starting a [driver] with custom parameters from Java. + * + * @param defaultParameters The default parameters for the driver. + * @param dsl The dsl itself. + * @return The value returned in the [dsl] closure. + */ fun driver( parameters: DriverParameters, dsl: DriverDSLExposedInterface.() -> A ): A { - return driver( - isDebug = parameters.isDebug, - driverDirectory = parameters.driverDirectory, - portAllocation = parameters.portAllocation, - debugPortAllocation = parameters.debugPortAllocation, - systemProperties = parameters.systemProperties, - useTestClock = parameters.useTestClock, - initialiseSerialization = parameters.initialiseSerialization, - networkMapStartStrategy = parameters.networkMapStartStrategy, - startNodesInProcess = parameters.startNodesInProcess, - dsl = dsl - ) + return driver(defaultParameters = parameters, dsl = dsl) } +/** + * Helper builder for configuring a [driver] from Java. + */ data class DriverParameters( val isDebug: Boolean = false, val driverDirectory: Path = Paths.get("build", getTimestampAsDirectoryName()), @@ -313,8 +314,6 @@ data class DriverParameters( fun setStartNodesInProcess(startNodesInProcess: Boolean) = copy(startNodesInProcess = startNodesInProcess) } -private val defaultParameters = DriverParameters() - /** * This is a helper method to allow extending of the DSL, along the lines of * interface SomeOtherExposedDSLInterface : DriverDSLExposedInterface