mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Spinoff driver into own project with demorun (#1401)
This commit is contained in:
parent
ead4d09011
commit
15f741f315
7
.idea/compiler.xml
generated
7
.idea/compiler.xml
generated
@ -28,6 +28,9 @@
|
||||
<module name="docs_source_example-code_main" target="1.8" />
|
||||
<module name="docs_source_example-code_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_test" target="1.8" />
|
||||
<module name="explorer-capsule_main" target="1.6" />
|
||||
@ -83,9 +86,11 @@
|
||||
<module name="smoke-test-utils_test" target="1.8" />
|
||||
<module name="test-common_main" 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_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_test" target="1.8" />
|
||||
<module name="trader-demo_integrationTest" target="1.8" />
|
||||
|
@ -251,7 +251,7 @@ bintrayConfig {
|
||||
projectUrl = 'https://github.com/corda/corda'
|
||||
gpgSign = true
|
||||
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 {
|
||||
name = 'Apache-2.0'
|
||||
url = 'https://www.apache.org/licenses/LICENSE-2.0'
|
||||
@ -286,7 +286,7 @@ artifactory {
|
||||
password = System.getenv('CORDA_ARTIFACTORY_PASSWORD')
|
||||
}
|
||||
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')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ dependencies {
|
||||
|
||||
// Integration test helpers
|
||||
integrationTestCompile "junit:junit:$junit_version"
|
||||
integrationTestCompile project(':node-driver')
|
||||
}
|
||||
|
||||
task integrationTest(type: Test) {
|
||||
|
@ -67,7 +67,7 @@ dependencies {
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||
|
||||
testCompile project(':test-utils')
|
||||
testCompile project(':node-driver')
|
||||
testCompile project(':client:mock')
|
||||
|
||||
// Smoke tests do NOT have any Node code on the classpath!
|
||||
|
@ -22,7 +22,7 @@ dependencies {
|
||||
|
||||
// Bring in the MockNode infrastructure for writing protocol unit tests.
|
||||
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-reflect:$kotlin_version"
|
||||
|
@ -32,7 +32,7 @@ compileTestJava.dependsOn tasks.getByPath(':node:capsule:buildCordaJAR')
|
||||
dependencies {
|
||||
cordaCompile project(':core')
|
||||
cordaCompile project(':client:jfx')
|
||||
cordaCompile project(':test-utils')
|
||||
cordaCompile project(':node-driver')
|
||||
testCompile project(':verifier')
|
||||
|
||||
compile "org.graphstream:gs-core:1.3"
|
||||
|
@ -29,5 +29,5 @@ dependencies {
|
||||
compile "com.google.guava:guava:$guava_version"
|
||||
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile project(':test-utils')
|
||||
testCompile project(':node-driver')
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import org.junit.Test;
|
||||
import static net.corda.finance.CurrencyUtils.DOLLARS;
|
||||
import static net.corda.finance.CurrencyUtils.issuedBy;
|
||||
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
|
||||
|
@ -30,7 +30,7 @@ dependencies {
|
||||
cordaCompile project(path: ":webserver:webcapsule", configuration: 'runtimeArtifacts')
|
||||
cordaCompile project(':core')
|
||||
cordaCompile project(':webserver')
|
||||
cordaCompile project(':test-utils')
|
||||
cordaCompile project(':node-driver')
|
||||
}
|
||||
|
||||
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
||||
|
@ -34,7 +34,7 @@ dependencies {
|
||||
cordaCompile project(':client:jfx')
|
||||
cordaCompile project(':client:rpc')
|
||||
cordaCompile project(':webserver')
|
||||
cordaCompile project(':test-utils')
|
||||
cordaCompile project(':node-driver')
|
||||
|
||||
// Javax is required for webapis
|
||||
compile "org.glassfish.jersey.core:jersey-server:${jersey_version}"
|
||||
|
@ -43,7 +43,7 @@ dependencies {
|
||||
// Specify your cordapp's dependencies below, including dependent cordapps
|
||||
compile "com.squareup.okhttp3:okhttp:$okhttp_version"
|
||||
|
||||
testCompile project(':test-utils')
|
||||
testCompile project(':node-driver')
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ apply plugin: 'us.kirchmeier.capsule'
|
||||
|
||||
dependencies {
|
||||
compile project(':samples:irs-demo')
|
||||
compile project(':test-utils')
|
||||
compile project(':node-driver')
|
||||
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
@ -23,8 +23,7 @@ dependencies {
|
||||
cordaCompile project(':core')
|
||||
cordaCompile project(':client:jfx')
|
||||
cordaCompile project(':client:rpc')
|
||||
cordaCompile project(':test-utils')
|
||||
cordaCompile project(':cordform-common')
|
||||
cordaCompile project(':node-driver')
|
||||
}
|
||||
|
||||
idea {
|
||||
|
@ -56,7 +56,7 @@ dependencies {
|
||||
compile "com.opengamma.strata:strata-math:${strata_version}"
|
||||
|
||||
// Test dependencies
|
||||
testCompile project(':test-utils')
|
||||
testCompile project(':node-driver')
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ include 'verifier'
|
||||
include 'test-common'
|
||||
include '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:capsule'
|
||||
include 'tools:demobench'
|
||||
|
@ -10,22 +10,6 @@ description 'Testing utilities for Corda'
|
||||
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 {
|
||||
@ -49,15 +33,6 @@ dependencies {
|
||||
|
||||
// OkHTTP: Simple HTTP library.
|
||||
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 {
|
||||
|
@ -3,34 +3,26 @@
|
||||
|
||||
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.crypto.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.node.services.IdentityService
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
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.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.config.VerifierType
|
||||
import net.corda.node.services.config.configureDevKeyAndTrustStores
|
||||
import net.corda.node.services.identity.InMemoryIdentityService
|
||||
import net.corda.node.utilities.CertificateType
|
||||
import net.corda.node.utilities.X509Utilities
|
||||
import net.corda.nodeapi.config.SSLConfiguration
|
||||
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.X500NameBuilder
|
||||
import org.bouncycastle.asn1.x500.style.BCStyle
|
||||
import java.net.URL
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.security.KeyPair
|
||||
import java.security.PublicKey
|
||||
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) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
fun configureTestSSL(legalName: X500Name = MEGA_CORP.name): SSLConfiguration = object : SSLConfiguration {
|
||||
override val certificatesDirectory = Files.createTempDirectory("certs")
|
||||
|
@ -9,13 +9,7 @@ import net.corda.core.crypto.entropyToKeyPair
|
||||
import net.corda.core.crypto.generateKeyPair
|
||||
import net.corda.core.identity.Party
|
||||
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.nodeapi.User
|
||||
import net.corda.testing.driver.DriverDSLExposedInterface
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import java.math.BigInteger
|
||||
import java.security.KeyPair
|
||||
@ -81,51 +75,3 @@ object DummyCommandData : TypeOnlyCommandData()
|
||||
|
||||
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)
|
||||
|
||||
//
|
||||
// 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)
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
49
testing/node-driver/build.gradle
Normal file
49
testing/node-driver/build.gradle
Normal 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
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
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.flows.StateMachineRunId
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
@ -37,16 +35,12 @@ import net.corda.testing.schemas.DummyLinearStateSchemaV1
|
||||
import org.bouncycastle.operator.ContentSigner
|
||||
import rx.Observable
|
||||
import rx.subjects.PublishSubject
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.security.KeyPair
|
||||
import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
import java.sql.Connection
|
||||
import java.time.Clock
|
||||
import java.util.*
|
||||
import java.util.jar.JarInputStream
|
||||
|
||||
// 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.
|
||||
@ -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(
|
||||
val storage: StateMachineRecordedTransactionMappingStorage = InMemoryStateMachineRecordedTransactionMappingStorage()
|
||||
) : StateMachineRecordedTransactionMappingStorage by storage
|
@ -27,7 +27,7 @@ dependencies {
|
||||
compile project(':core')
|
||||
compile project(':client:jfx')
|
||||
compile project(':client:mock')
|
||||
compile project(':test-utils')
|
||||
compile project(':node-driver')
|
||||
compile project(':finance')
|
||||
|
||||
// Capsule is a library for building independently executable fat JARs.
|
||||
|
@ -6,7 +6,7 @@ mainClassName = 'net.corda.loadtest.MainKt'
|
||||
dependencies {
|
||||
compile project(':client:mock')
|
||||
compile project(':client:rpc')
|
||||
compile project(':test-utils')
|
||||
compile project(':node-driver')
|
||||
|
||||
// https://mvnrepository.com/artifact/com.jcraft/jsch
|
||||
compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'
|
||||
|
@ -39,7 +39,7 @@ dependencies {
|
||||
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
|
||||
compile "org.apache.logging.log4j:log4j-core:${log4j_version}"
|
||||
|
||||
integrationTestCompile project(":test-utils")
|
||||
integrationTestCompile project(":node-driver")
|
||||
integrationTestCompile project(":client:mock")
|
||||
|
||||
// Integration test helpers
|
||||
|
@ -57,7 +57,7 @@ dependencies {
|
||||
// For rendering the index page.
|
||||
compile "org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.3"
|
||||
|
||||
testCompile project(':test-utils')
|
||||
integrationTestCompile project(':node-driver')
|
||||
testCompile "junit:junit:$junit_version"
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user