Spinoff driver into own project with demorun (#1401)

This commit is contained in:
Andrzej Cichocki 2017-09-05 09:50:51 +01:00 committed by GitHub
parent ead4d09011
commit 15f741f315
45 changed files with 251 additions and 198 deletions

7
.idea/compiler.xml generated
View File

@ -28,6 +28,9 @@
<module name="docs_source_example-code_main" target="1.8" /> <module name="docs_source_example-code_main" target="1.8" />
<module name="docs_source_example-code_test" target="1.8" /> <module name="docs_source_example-code_test" target="1.8" />
<module name="docs_test" target="1.8" /> <module name="docs_test" target="1.8" />
<module name="driver_integrationTest" target="1.8" />
<module name="driver_main" target="1.8" />
<module name="driver_test" target="1.8" />
<module name="experimental_main" target="1.8" /> <module name="experimental_main" target="1.8" />
<module name="experimental_test" target="1.8" /> <module name="experimental_test" target="1.8" />
<module name="explorer-capsule_main" target="1.6" /> <module name="explorer-capsule_main" target="1.6" />
@ -83,9 +86,11 @@
<module name="smoke-test-utils_test" target="1.8" /> <module name="smoke-test-utils_test" target="1.8" />
<module name="test-common_main" target="1.8" /> <module name="test-common_main" target="1.8" />
<module name="test-common_test" target="1.8" /> <module name="test-common_test" target="1.8" />
<module name="test-utils_integrationTest" target="1.8" />
<module name="test-utils_main" target="1.8" /> <module name="test-utils_main" target="1.8" />
<module name="test-utils_test" target="1.8" /> <module name="test-utils_test" target="1.8" />
<module name="testing-node-driver_integrationTest" target="1.8" />
<module name="testing-node-driver_main" target="1.8" />
<module name="testing-node-driver_test" target="1.8" />
<module name="tools_main" target="1.8" /> <module name="tools_main" target="1.8" />
<module name="tools_test" target="1.8" /> <module name="tools_test" target="1.8" />
<module name="trader-demo_integrationTest" target="1.8" /> <module name="trader-demo_integrationTest" target="1.8" />

View File

@ -251,7 +251,7 @@ bintrayConfig {
projectUrl = 'https://github.com/corda/corda' projectUrl = 'https://github.com/corda/corda'
gpgSign = true gpgSign = true
gpgPassphrase = System.getenv('CORDA_BINTRAY_GPG_PASSPHRASE') gpgPassphrase = System.getenv('CORDA_BINTRAY_GPG_PASSPHRASE')
publications = ['corda-jfx', 'corda-mock', 'corda-rpc', 'corda-core', 'corda', 'corda-finance', 'corda-node', 'corda-node-api', 'corda-test-common', 'corda-test-utils', 'corda-jackson', 'corda-verifier', 'corda-webserver-impl', 'corda-webserver'] publications = ['corda-jfx', 'corda-mock', 'corda-rpc', 'corda-core', 'corda', 'corda-finance', 'corda-node', 'corda-node-api', 'corda-test-common', 'corda-test-utils', 'corda-jackson', 'corda-verifier', 'corda-webserver-impl', 'corda-webserver', 'corda-node-driver']
license { license {
name = 'Apache-2.0' name = 'Apache-2.0'
url = 'https://www.apache.org/licenses/LICENSE-2.0' url = 'https://www.apache.org/licenses/LICENSE-2.0'
@ -286,7 +286,7 @@ artifactory {
password = System.getenv('CORDA_ARTIFACTORY_PASSWORD') password = System.getenv('CORDA_ARTIFACTORY_PASSWORD')
} }
defaults { defaults {
publications('corda-jfx', 'corda-mock', 'corda-rpc', 'corda-core', 'corda', 'cordform-common', 'corda-finance', 'corda-node', 'corda-node-api', 'corda-test-common', 'corda-test-utils', 'corda-jackson', 'corda-verifier', 'corda-webserver-impl', 'corda-webserver') publications('corda-jfx', 'corda-mock', 'corda-rpc', 'corda-core', 'corda', 'cordform-common', 'corda-finance', 'corda-node', 'corda-node-api', 'corda-test-common', 'corda-test-utils', 'corda-jackson', 'corda-verifier', 'corda-webserver-impl', 'corda-webserver', 'corda-node-driver')
} }
} }
} }

View File

@ -50,6 +50,7 @@ dependencies {
// Integration test helpers // Integration test helpers
integrationTestCompile "junit:junit:$junit_version" integrationTestCompile "junit:junit:$junit_version"
integrationTestCompile project(':node-driver')
} }
task integrationTest(type: Test) { task integrationTest(type: Test) {

View File

@ -67,7 +67,7 @@ dependencies {
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile project(':test-utils') testCompile project(':node-driver')
testCompile project(':client:mock') testCompile project(':client:mock')
// Smoke tests do NOT have any Node code on the classpath! // Smoke tests do NOT have any Node code on the classpath!

View File

@ -22,7 +22,7 @@ dependencies {
// Bring in the MockNode infrastructure for writing protocol unit tests. // Bring in the MockNode infrastructure for writing protocol unit tests.
testCompile project(":node") testCompile project(":node")
testCompile project(":test-utils") testCompile project(":node-driver")
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

View File

@ -32,7 +32,7 @@ compileTestJava.dependsOn tasks.getByPath(':node:capsule:buildCordaJAR')
dependencies { dependencies {
cordaCompile project(':core') cordaCompile project(':core')
cordaCompile project(':client:jfx') cordaCompile project(':client:jfx')
cordaCompile project(':test-utils') cordaCompile project(':node-driver')
testCompile project(':verifier') testCompile project(':verifier')
compile "org.graphstream:gs-core:1.3" compile "org.graphstream:gs-core:1.3"

View File

@ -29,5 +29,5 @@ dependencies {
compile "com.google.guava:guava:$guava_version" compile "com.google.guava:guava:$guava_version"
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
testCompile project(':test-utils') testCompile project(':node-driver')
} }

View File

@ -9,6 +9,7 @@ import org.junit.Test;
import static net.corda.finance.CurrencyUtils.DOLLARS; import static net.corda.finance.CurrencyUtils.DOLLARS;
import static net.corda.finance.CurrencyUtils.issuedBy; import static net.corda.finance.CurrencyUtils.issuedBy;
import static net.corda.testing.CoreTestUtils.*; import static net.corda.testing.CoreTestUtils.*;
import static net.corda.testing.NodeTestUtils.*;
/** /**
* This is an incomplete Java replica of CashTests.kt to show how to use the Java test DSL * This is an incomplete Java replica of CashTests.kt to show how to use the Java test DSL

View File

@ -30,7 +30,7 @@ dependencies {
cordaCompile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts') cordaCompile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
cordaCompile project(':core') cordaCompile project(':core')
cordaCompile project(':webserver') cordaCompile project(':webserver')
cordaCompile project(':test-utils') cordaCompile project(':node-driver')
} }
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) { task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {

View File

@ -34,7 +34,7 @@ dependencies {
cordaCompile project(':client:jfx') cordaCompile project(':client:jfx')
cordaCompile project(':client:rpc') cordaCompile project(':client:rpc')
cordaCompile project(':webserver') cordaCompile project(':webserver')
cordaCompile project(':test-utils') cordaCompile project(':node-driver')
// Javax is required for webapis // Javax is required for webapis
compile "org.glassfish.jersey.core:jersey-server:${jersey_version}" compile "org.glassfish.jersey.core:jersey-server:${jersey_version}"

View File

@ -43,7 +43,7 @@ dependencies {
// Specify your cordapp's dependencies below, including dependent cordapps // Specify your cordapp's dependencies below, including dependent cordapps
compile "com.squareup.okhttp3:okhttp:$okhttp_version" compile "com.squareup.okhttp3:okhttp:$okhttp_version"
testCompile project(':test-utils') testCompile project(':node-driver')
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
} }

View File

@ -7,7 +7,7 @@ apply plugin: 'us.kirchmeier.capsule'
dependencies { dependencies {
compile project(':samples:irs-demo') compile project(':samples:irs-demo')
compile project(':test-utils') compile project(':node-driver')
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"

View File

@ -23,8 +23,7 @@ dependencies {
cordaCompile project(':core') cordaCompile project(':core')
cordaCompile project(':client:jfx') cordaCompile project(':client:jfx')
cordaCompile project(':client:rpc') cordaCompile project(':client:rpc')
cordaCompile project(':test-utils') cordaCompile project(':node-driver')
cordaCompile project(':cordform-common')
} }
idea { idea {

View File

@ -56,7 +56,7 @@ dependencies {
compile "com.opengamma.strata:strata-math:${strata_version}" compile "com.opengamma.strata:strata-math:${strata_version}"
// Test dependencies // Test dependencies
testCompile project(':test-utils') testCompile project(':node-driver')
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
} }

View File

@ -21,6 +21,8 @@ include 'verifier'
include 'test-common' include 'test-common'
include 'test-utils' include 'test-utils'
include 'smoke-test-utils' include 'smoke-test-utils'
include 'node-driver'
project(':node-driver').projectDir = new File("$settingsDir/testing/node-driver")
include 'tools:explorer' include 'tools:explorer'
include 'tools:explorer:capsule' include 'tools:explorer:capsule'
include 'tools:demobench' include 'tools:demobench'

View File

@ -10,22 +10,6 @@ description 'Testing utilities for Corda'
configurations { configurations {
// we don't want isolated.jar in classPath, since we want to test jar being dynamically loaded as an attachment // we don't want isolated.jar in classPath, since we want to test jar being dynamically loaded as an attachment
runtime.exclude module: 'isolated' runtime.exclude module: 'isolated'
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
sourceSets {
integrationTest {
kotlin {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/integration-test/kotlin')
}
resources {
srcDir file('src/integration-test/resources')
}
}
} }
dependencies { dependencies {
@ -49,15 +33,6 @@ dependencies {
// OkHTTP: Simple HTTP library. // OkHTTP: Simple HTTP library.
compile "com.squareup.okhttp3:okhttp:$okhttp_version" compile "com.squareup.okhttp3:okhttp:$okhttp_version"
// Integration test helpers
integrationTestCompile "org.assertj:assertj-core:${assertj_version}"
integrationTestCompile "junit:junit:$junit_version"
}
task integrationTest(type: Test) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
} }
jar { jar {

View File

@ -3,34 +3,26 @@
package net.corda.testing package net.corda.testing
import com.nhaarman.mockito_kotlin.spy
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.StateRef import net.corda.core.contracts.StateRef
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.IdentityService import net.corda.core.node.services.IdentityService
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.* import net.corda.core.utilities.*
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.loggerFor
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.config.VerifierType
import net.corda.node.services.config.configureDevKeyAndTrustStores import net.corda.node.services.config.configureDevKeyAndTrustStores
import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.utilities.CertificateType import net.corda.node.utilities.CertificateType
import net.corda.node.utilities.X509Utilities import net.corda.node.utilities.X509Utilities
import net.corda.nodeapi.config.SSLConfiguration import net.corda.nodeapi.config.SSLConfiguration
import net.corda.nodeapi.internal.serialization.AMQP_ENABLED import net.corda.nodeapi.internal.serialization.AMQP_ENABLED
import net.corda.testing.node.MockServices
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.X500NameBuilder import org.bouncycastle.asn1.x500.X500NameBuilder
import org.bouncycastle.asn1.x500.style.BCStyle import org.bouncycastle.asn1.x500.style.BCStyle
import java.net.URL
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path
import java.security.KeyPair import java.security.KeyPair
import java.security.PublicKey import java.security.PublicKey
import java.security.cert.CertificateFactory import java.security.cert.CertificateFactory
@ -126,62 +118,6 @@ fun getFreeLocalPorts(hostName: String, numberToAlloc: Int): List<NetworkHostAnd
return (freePort .. freePort + numberToAlloc - 1).map { NetworkHostAndPort(hostName, it) } return (freePort .. freePort + numberToAlloc - 1).map { NetworkHostAndPort(hostName, it) }
} }
/**
* Creates and tests a ledger built by the passed in dsl. The provided services can be customised, otherwise a default
* of a freshly built [MockServices] is used.
*/
@JvmOverloads fun ledger(
services: ServiceHub = MockServices(),
initialiseSerialization: Boolean = true,
dsl: LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.() -> Unit
): LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter> {
if (initialiseSerialization) initialiseTestSerialization()
try {
val ledgerDsl = LedgerDSL(TestLedgerDSLInterpreter(services))
dsl(ledgerDsl)
return ledgerDsl
} finally {
if (initialiseSerialization) resetTestSerialization()
}
}
/**
* Creates a ledger with a single transaction, built by the passed in dsl.
*
* @see LedgerDSLInterpreter._transaction
*/
@JvmOverloads fun transaction(
transactionLabel: String? = null,
transactionBuilder: TransactionBuilder = TransactionBuilder(notary = DUMMY_NOTARY),
initialiseSerialization: Boolean = true,
dsl: TransactionDSL<TransactionDSLInterpreter>.() -> EnforceVerifyOrFail
) = ledger(initialiseSerialization = initialiseSerialization) {
dsl(TransactionDSL(TestTransactionDSLInterpreter(this.interpreter, transactionBuilder)))
}
fun testNodeConfiguration(
baseDirectory: Path,
myLegalName: X500Name): NodeConfiguration {
abstract class MockableNodeConfiguration : NodeConfiguration // Otherwise Mockito is defeated by val getters.
val nc = spy<MockableNodeConfiguration>()
whenever(nc.baseDirectory).thenReturn(baseDirectory)
whenever(nc.myLegalName).thenReturn(myLegalName)
whenever(nc.minimumPlatformVersion).thenReturn(1)
whenever(nc.keyStorePassword).thenReturn("cordacadevpass")
whenever(nc.trustStorePassword).thenReturn("trustpass")
whenever(nc.rpcUsers).thenReturn(emptyList())
whenever(nc.dataSourceProperties).thenReturn(makeTestDataSourceProperties(myLegalName.commonName))
whenever(nc.database).thenReturn(makeTestDatabaseProperties())
whenever(nc.emailAddress).thenReturn("")
whenever(nc.exportJMXto).thenReturn("")
whenever(nc.devMode).thenReturn(true)
whenever(nc.certificateSigningService).thenReturn(URL("http://localhost"))
whenever(nc.certificateChainCheckPolicies).thenReturn(emptyList())
whenever(nc.verifierType).thenReturn(VerifierType.InMemory)
whenever(nc.messageRedeliveryDelaySeconds).thenReturn(5)
return nc
}
@JvmOverloads @JvmOverloads
fun configureTestSSL(legalName: X500Name = MEGA_CORP.name): SSLConfiguration = object : SSLConfiguration { fun configureTestSSL(legalName: X500Name = MEGA_CORP.name): SSLConfiguration = object : SSLConfiguration {
override val certificatesDirectory = Files.createTempDirectory("certs") override val certificatesDirectory = Files.createTempDirectory("certs")

View File

@ -9,13 +9,7 @@ import net.corda.core.crypto.entropyToKeyPair
import net.corda.core.crypto.generateKeyPair import net.corda.core.crypto.generateKeyPair
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.concurrent.transpose
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.services.ServiceInfo
import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.node.utilities.X509Utilities import net.corda.node.utilities.X509Utilities
import net.corda.nodeapi.User
import net.corda.testing.driver.DriverDSLExposedInterface
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import java.math.BigInteger import java.math.BigInteger
import java.security.KeyPair import java.security.KeyPair
@ -81,51 +75,3 @@ object DummyCommandData : TypeOnlyCommandData()
val DUMMY_IDENTITY_1: PartyAndCertificate get() = getTestPartyAndCertificate(DUMMY_PARTY) val DUMMY_IDENTITY_1: PartyAndCertificate get() = getTestPartyAndCertificate(DUMMY_PARTY)
val DUMMY_PARTY: Party get() = Party(X500Name("CN=Dummy,O=Dummy,L=Madrid,C=ES"), DUMMY_KEY_1.public) val DUMMY_PARTY: Party get() = Party(X500Name("CN=Dummy,O=Dummy,L=Madrid,C=ES"), DUMMY_KEY_1.public)
//
// Extensions to the Driver DSL to auto-manufacture nodes by name.
//
/**
* A simple wrapper for objects provided by the integration test driver DSL. The fields are lazy so
* node construction won't start until you access the members. You can get one of these from the
* [alice], [bob] and [aliceBobAndNotary] functions.
*/
class PredefinedTestNode internal constructor(party: Party, driver: DriverDSLExposedInterface, services: Set<ServiceInfo>) {
val rpcUsers = listOf(User("admin", "admin", setOf("ALL"))) // TODO: Randomize?
val nodeFuture by lazy { driver.startNode(providedName = party.name, rpcUsers = rpcUsers, advertisedServices = services) }
val node by lazy { nodeFuture.get()!! }
val rpc by lazy { node.rpcClientToNode() }
fun <R> useRPC(block: (CordaRPCOps) -> R) = rpc.use(rpcUsers[0].username, rpcUsers[0].password) { block(it.proxy) }
}
// TODO: Probably we should inject the above keys through the driver to make the nodes use it, rather than have the warnings below.
/**
* Returns a plain, entirely stock node pre-configured with the [ALICE] identity. Note that a random key will be generated
* for it: you won't have [ALICE_KEY].
*/
fun DriverDSLExposedInterface.alice(): PredefinedTestNode = PredefinedTestNode(ALICE, this, emptySet())
/**
* Returns a plain, entirely stock node pre-configured with the [BOB] identity. Note that a random key will be generated
* for it: you won't have [BOB_KEY].
*/
fun DriverDSLExposedInterface.bob(): PredefinedTestNode = PredefinedTestNode(BOB, this, emptySet())
/**
* Returns a plain single node notary pre-configured with the [DUMMY_NOTARY] identity. Note that a random key will be generated
* for it: you won't have [DUMMY_NOTARY_KEY].
*/
fun DriverDSLExposedInterface.notary(): PredefinedTestNode = PredefinedTestNode(DUMMY_NOTARY, this, setOf(ServiceInfo(ValidatingNotaryService.type)))
/**
* Returns plain, entirely stock nodes pre-configured with the [ALICE], [BOB] and [DUMMY_NOTARY] X.500 names in that
* order. They have been started up in parallel and are now ready to use.
*/
fun DriverDSLExposedInterface.aliceBobAndNotary(): List<PredefinedTestNode> {
val alice = alice()
val bob = bob()
val notary = notary()
listOf(alice.nodeFuture, bob.nodeFuture, notary.nodeFuture).transpose().get()
return listOf(alice, bob, notary)
}

View File

@ -0,0 +1,41 @@
package net.corda.testing.node
import net.corda.core.contracts.Attachment
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256
import net.corda.core.internal.AbstractAttachment
import net.corda.core.node.services.AttachmentStorage
import net.corda.core.serialization.SingletonSerializeAsToken
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.InputStream
import java.util.HashMap
import java.util.jar.JarInputStream
class MockAttachmentStorage : AttachmentStorage, SingletonSerializeAsToken() {
val files = HashMap<SecureHash, ByteArray>()
override fun openAttachment(id: SecureHash): Attachment? {
val f = files[id] ?: return null
return object : AbstractAttachment({ f }) {
override val id = id
}
}
override fun importAttachment(jar: InputStream): SecureHash {
// JIS makes read()/readBytes() return bytes of the current file, but we want to hash the entire container here.
require(jar !is JarInputStream)
val bytes = run {
val s = ByteArrayOutputStream()
jar.copyTo(s)
s.close()
s.toByteArray()
}
val sha256 = bytes.sha256()
if (files.containsKey(sha256))
throw FileAlreadyExistsException(File("!! MOCK FILE NAME"))
files[sha256] = bytes
return sha256
}
}

View File

@ -0,0 +1,49 @@
apply plugin: 'kotlin'
apply plugin: 'kotlin-jpa'
apply plugin: 'net.corda.plugins.quasar-utils'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'com.jfrog.artifactory'
//noinspection GroovyAssignabilityCheck
configurations {
// we don't want isolated.jar in classPath, since we want to test jar being dynamically loaded as an attachment
runtime.exclude module: 'isolated'
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
sourceSets {
integrationTest {
kotlin {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/integration-test/kotlin')
}
resources {
srcDir file('src/integration-test/resources')
}
}
}
dependencies {
compile project(':test-utils')
compile project(':cordform-common')
// Integration test helpers
integrationTestCompile "org.assertj:assertj-core:${assertj_version}"
integrationTestCompile "junit:junit:$junit_version"
}
task integrationTest(type: Test) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}
jar {
baseName 'corda-node-driver'
}
publish {
name jar.baseName
}

View File

@ -0,0 +1,59 @@
@file:JvmName("DriverConstants")
package net.corda.testing
import net.corda.core.identity.Party
import net.corda.core.internal.concurrent.transpose
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.services.ServiceInfo
import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.nodeapi.User
import net.corda.testing.driver.DriverDSLExposedInterface
//
// Extensions to the Driver DSL to auto-manufacture nodes by name.
//
/**
* A simple wrapper for objects provided by the integration test driver DSL. The fields are lazy so
* node construction won't start until you access the members. You can get one of these from the
* [alice], [bob] and [aliceBobAndNotary] functions.
*/
class PredefinedTestNode internal constructor(party: Party, driver: DriverDSLExposedInterface, services: Set<ServiceInfo>) {
val rpcUsers = listOf(User("admin", "admin", setOf("ALL"))) // TODO: Randomize?
val nodeFuture by lazy { driver.startNode(providedName = party.name, rpcUsers = rpcUsers, advertisedServices = services) }
val node by lazy { nodeFuture.get()!! }
val rpc by lazy { node.rpcClientToNode() }
fun <R> useRPC(block: (CordaRPCOps) -> R) = rpc.use(rpcUsers[0].username, rpcUsers[0].password) { block(it.proxy) }
}
// TODO: Probably we should inject the above keys through the driver to make the nodes use it, rather than have the warnings below.
/**
* Returns a plain, entirely stock node pre-configured with the [ALICE] identity. Note that a random key will be generated
* for it: you won't have [ALICE_KEY].
*/
fun DriverDSLExposedInterface.alice(): PredefinedTestNode = PredefinedTestNode(ALICE, this, emptySet())
/**
* Returns a plain, entirely stock node pre-configured with the [BOB] identity. Note that a random key will be generated
* for it: you won't have [BOB_KEY].
*/
fun DriverDSLExposedInterface.bob(): PredefinedTestNode = PredefinedTestNode(BOB, this, emptySet())
/**
* Returns a plain single node notary pre-configured with the [DUMMY_NOTARY] identity. Note that a random key will be generated
* for it: you won't have [DUMMY_NOTARY_KEY].
*/
fun DriverDSLExposedInterface.notary(): PredefinedTestNode = PredefinedTestNode(DUMMY_NOTARY, this, setOf(ServiceInfo(ValidatingNotaryService.type)))
/**
* Returns plain, entirely stock nodes pre-configured with the [ALICE], [BOB] and [DUMMY_NOTARY] X.500 names in that
* order. They have been started up in parallel and are now ready to use.
*/
fun DriverDSLExposedInterface.aliceBobAndNotary(): List<PredefinedTestNode> {
val alice = alice()
val bob = bob()
val notary = notary()
listOf(alice.nodeFuture, bob.nodeFuture, notary.nodeFuture).transpose().get()
return listOf(alice, bob, notary)
}

View File

@ -0,0 +1,73 @@
@file:JvmName("NodeTestUtils")
package net.corda.testing
import com.nhaarman.mockito_kotlin.spy
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.node.ServiceHub
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.commonName
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.config.VerifierType
import net.corda.testing.node.MockServices
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
import org.bouncycastle.asn1.x500.X500Name
import java.net.URL
import java.nio.file.Path
/**
* Creates and tests a ledger built by the passed in dsl. The provided services can be customised, otherwise a default
* of a freshly built [MockServices] is used.
*/
@JvmOverloads fun ledger(
services: ServiceHub = MockServices(),
initialiseSerialization: Boolean = true,
dsl: LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.() -> Unit
): LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter> {
if (initialiseSerialization) initialiseTestSerialization()
try {
val ledgerDsl = LedgerDSL(TestLedgerDSLInterpreter(services))
dsl(ledgerDsl)
return ledgerDsl
} finally {
if (initialiseSerialization) resetTestSerialization()
}
}
/**
* Creates a ledger with a single transaction, built by the passed in dsl.
*
* @see LedgerDSLInterpreter._transaction
*/
@JvmOverloads fun transaction(
transactionLabel: String? = null,
transactionBuilder: TransactionBuilder = TransactionBuilder(notary = DUMMY_NOTARY),
initialiseSerialization: Boolean = true,
dsl: TransactionDSL<TransactionDSLInterpreter>.() -> EnforceVerifyOrFail
) = ledger(initialiseSerialization = initialiseSerialization) {
dsl(TransactionDSL(TestTransactionDSLInterpreter(this.interpreter, transactionBuilder)))
}
fun testNodeConfiguration(
baseDirectory: Path,
myLegalName: X500Name): NodeConfiguration {
abstract class MockableNodeConfiguration : NodeConfiguration // Otherwise Mockito is defeated by val getters.
val nc = spy<MockableNodeConfiguration>()
whenever(nc.baseDirectory).thenReturn(baseDirectory)
whenever(nc.myLegalName).thenReturn(myLegalName)
whenever(nc.minimumPlatformVersion).thenReturn(1)
whenever(nc.keyStorePassword).thenReturn("cordacadevpass")
whenever(nc.trustStorePassword).thenReturn("trustpass")
whenever(nc.rpcUsers).thenReturn(emptyList())
whenever(nc.dataSourceProperties).thenReturn(makeTestDataSourceProperties(myLegalName.commonName))
whenever(nc.database).thenReturn(makeTestDatabaseProperties())
whenever(nc.emailAddress).thenReturn("")
whenever(nc.exportJMXto).thenReturn("")
whenever(nc.devMode).thenReturn(true)
whenever(nc.certificateSigningService).thenReturn(URL("http://localhost"))
whenever(nc.certificateChainCheckPolicies).thenReturn(emptyList())
whenever(nc.verifierType).thenReturn(VerifierType.InMemory)
whenever(nc.messageRedeliveryDelaySeconds).thenReturn(5)
return nc
}

View File

@ -1,7 +1,5 @@
package net.corda.testing.node package net.corda.testing.node
import net.corda.core.internal.AbstractAttachment
import net.corda.core.contracts.Attachment
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.flows.StateMachineRunId import net.corda.core.flows.StateMachineRunId
import net.corda.core.identity.PartyAndCertificate import net.corda.core.identity.PartyAndCertificate
@ -37,16 +35,12 @@ import net.corda.testing.schemas.DummyLinearStateSchemaV1
import org.bouncycastle.operator.ContentSigner import org.bouncycastle.operator.ContentSigner
import rx.Observable import rx.Observable
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.InputStream
import java.security.KeyPair import java.security.KeyPair
import java.security.PrivateKey import java.security.PrivateKey
import java.security.PublicKey import java.security.PublicKey
import java.sql.Connection import java.sql.Connection
import java.time.Clock import java.time.Clock
import java.util.* import java.util.*
import java.util.jar.JarInputStream
// TODO: We need a single, rationalised unit testing environment that is usable for everything. Fix this! // TODO: We need a single, rationalised unit testing environment that is usable for everything. Fix this!
// That means it probably shouldn't be in the 'core' module, which lacks enough code to create a realistic test env. // That means it probably shouldn't be in the 'core' module, which lacks enough code to create a realistic test env.
@ -217,34 +211,6 @@ class MockKeyManagementService(val identityService: IdentityService,
} }
} }
class MockAttachmentStorage : AttachmentStorage, SingletonSerializeAsToken() {
val files = HashMap<SecureHash, ByteArray>()
override fun openAttachment(id: SecureHash): Attachment? {
val f = files[id] ?: return null
return object : AbstractAttachment({ f }) {
override val id = id
}
}
override fun importAttachment(jar: InputStream): SecureHash {
// JIS makes read()/readBytes() return bytes of the current file, but we want to hash the entire container here.
require(jar !is JarInputStream)
val bytes = run {
val s = ByteArrayOutputStream()
jar.copyTo(s)
s.close()
s.toByteArray()
}
val sha256 = bytes.sha256()
if (files.containsKey(sha256))
throw FileAlreadyExistsException(File("!! MOCK FILE NAME"))
files[sha256] = bytes
return sha256
}
}
class MockStateMachineRecordedTransactionMappingStorage( class MockStateMachineRecordedTransactionMappingStorage(
val storage: StateMachineRecordedTransactionMappingStorage = InMemoryStateMachineRecordedTransactionMappingStorage() val storage: StateMachineRecordedTransactionMappingStorage = InMemoryStateMachineRecordedTransactionMappingStorage()
) : StateMachineRecordedTransactionMappingStorage by storage ) : StateMachineRecordedTransactionMappingStorage by storage

View File

@ -27,7 +27,7 @@ dependencies {
compile project(':core') compile project(':core')
compile project(':client:jfx') compile project(':client:jfx')
compile project(':client:mock') compile project(':client:mock')
compile project(':test-utils') compile project(':node-driver')
compile project(':finance') compile project(':finance')
// Capsule is a library for building independently executable fat JARs. // Capsule is a library for building independently executable fat JARs.

View File

@ -6,7 +6,7 @@ mainClassName = 'net.corda.loadtest.MainKt'
dependencies { dependencies {
compile project(':client:mock') compile project(':client:mock')
compile project(':client:rpc') compile project(':client:rpc')
compile project(':test-utils') compile project(':node-driver')
// https://mvnrepository.com/artifact/com.jcraft/jsch // https://mvnrepository.com/artifact/com.jcraft/jsch
compile group: 'com.jcraft', name: 'jsch', version: '0.1.54' compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'

View File

@ -39,7 +39,7 @@ dependencies {
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}" compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
compile "org.apache.logging.log4j:log4j-core:${log4j_version}" compile "org.apache.logging.log4j:log4j-core:${log4j_version}"
integrationTestCompile project(":test-utils") integrationTestCompile project(":node-driver")
integrationTestCompile project(":client:mock") integrationTestCompile project(":client:mock")
// Integration test helpers // Integration test helpers

View File

@ -57,7 +57,7 @@ dependencies {
// For rendering the index page. // For rendering the index page.
compile "org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.3" compile "org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.3"
testCompile project(':test-utils') integrationTestCompile project(':node-driver')
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
} }