mirror of
https://github.com/corda/corda.git
synced 2024-12-19 21:17:58 +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_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" />
|
||||||
|
@ -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')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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!
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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')
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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']) {
|
||||||
|
@ -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}"
|
||||||
|
@ -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}"
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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 {
|
||||||
|
@ -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}"
|
||||||
}
|
}
|
||||||
|
@ -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'
|
||||||
|
@ -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 {
|
||||||
|
@ -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")
|
||||||
|
@ -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)
|
|
||||||
}
|
|
@ -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
|
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
|
@ -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.
|
||||||
|
@ -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'
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user