Merge pull request #6689 from corda/rni/notick/46-47-merge-2020-09-04

NOTICK Merge OS 4.6 to 4.7 2020-09-04
This commit is contained in:
Ross Nicoll 2020-09-04 15:52:38 +01:00 committed by GitHub
commit e069277830
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 490 additions and 156 deletions

49
.ci/dev/open-j9/Jenkinsfile vendored Normal file
View File

@ -0,0 +1,49 @@
import static com.r3.build.BuildControl.killAllExistingBuildsForJob
@Library('existing-build-control')
import static com.r3.build.BuildControl.killAllExistingBuildsForJob
killAllExistingBuildsForJob(env.JOB_NAME, env.BUILD_NUMBER.toInteger())
pipeline {
agent { label 'open-j9' }
options {
timestamps()
timeout(time: 10, unit: 'HOURS')
}
environment {
EXECUTOR_NUMBER = "${env.EXECUTOR_NUMBER}"
}
stages {
stage('Unit Tests') {
steps {
sh "./gradlew clean --continue test --info"
}
}
stage('Integration Tests') {
steps {
sh "./gradlew clean --continue integrationTest --info"
}
}
stage('Smoke Tests') {
steps {
sh "./gradlew clean --continue smokeTest --info"
}
}
stage('Slow Integration Tests') {
steps {
sh "./gradlew clean --continue slowIntegrationTest --info"
}
}
}
post {
always {
junit '**/build/test-results/**/*.xml'
}
cleanup {
deleteDir() /* clean up our workspace */
}
}
}

View File

@ -16,11 +16,11 @@ guavaVersion=28.0-jre
# Quasar version to use with Java 8: # Quasar version to use with Java 8:
quasarVersion=0.7.13_r3 quasarVersion=0.7.13_r3
# Quasar version to use with Java 11: # Quasar version to use with Java 11:
quasarVersion11=0.8.0_r3 quasarVersion11=0.8.1_r3
jdkClassifier11=jdk11 jdkClassifier11=jdk11
proguardVersion=6.1.1 proguardVersion=6.1.1
bouncycastleVersion=1.66 bouncycastleVersion=1.66
classgraphVersion=4.8.78 classgraphVersion=4.8.89
disruptorVersion=3.4.2 disruptorVersion=3.4.2
typesafeConfigVersion=1.3.4 typesafeConfigVersion=1.3.4
jsr305Version=3.0.2 jsr305Version=3.0.2

View File

@ -18,6 +18,8 @@ import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.singleIdentity import net.corda.testing.core.singleIdentity
import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.internal.IS_OPENJ9
import org.junit.Assume
import org.junit.Test import org.junit.Test
import java.time.Duration import java.time.Duration
import java.time.Instant import java.time.Instant
@ -27,6 +29,7 @@ class FlowSleepTest {
@Test(timeout = 300_000) @Test(timeout = 300_000)
fun `flow can sleep`() { fun `flow can sleep`() {
Assume.assumeTrue(!IS_OPENJ9)
driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) { driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) {
val alice = startNode(providedName = ALICE_NAME).getOrThrow() val alice = startNode(providedName = ALICE_NAME).getOrThrow()
val (start, finish) = alice.rpc.startFlow(::SleepyFlow).returnValue.getOrThrow(1.minutes) val (start, finish) = alice.rpc.startFlow(::SleepyFlow).returnValue.getOrThrow(1.minutes)
@ -52,6 +55,7 @@ class FlowSleepTest {
@Test(timeout = 300_000) @Test(timeout = 300_000)
fun `flow can sleep and perform other suspending functions`() { fun `flow can sleep and perform other suspending functions`() {
Assume.assumeTrue(!IS_OPENJ9)
// ensures that events received while the flow is sleeping are not processed // ensures that events received while the flow is sleeping are not processed
driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) { driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) {
val (alice, bob) = listOf(ALICE_NAME, BOB_NAME) val (alice, bob) = listOf(ALICE_NAME, BOB_NAME)

View File

@ -35,6 +35,8 @@ import org.bouncycastle.asn1.x9.X9ObjectIdentifiers
import org.bouncycastle.crypto.CryptoServicesRegistrar import org.bouncycastle.crypto.CryptoServicesRegistrar
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey
import org.bouncycastle.jcajce.provider.asymmetric.edec.BCEdDSAPrivateKey
import org.bouncycastle.jcajce.provider.asymmetric.edec.BCEdDSAPublicKey
import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateKey import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateKey
import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey
import org.bouncycastle.jce.ECNamedCurveTable import org.bouncycastle.jce.ECNamedCurveTable
@ -308,11 +310,11 @@ object Crypto {
fun decodePrivateKey(encodedKey: ByteArray): PrivateKey { fun decodePrivateKey(encodedKey: ByteArray): PrivateKey {
val keyInfo = PrivateKeyInfo.getInstance(encodedKey) val keyInfo = PrivateKeyInfo.getInstance(encodedKey)
if (keyInfo.privateKeyAlgorithm.algorithm == ASN1ObjectIdentifier(CordaOID.ALIAS_PRIVATE_KEY)) { if (keyInfo.privateKeyAlgorithm.algorithm == ASN1ObjectIdentifier(CordaOID.ALIAS_PRIVATE_KEY)) {
return decodeAliasPrivateKey(keyInfo) return convertIfBCEdDSAPrivateKey(decodeAliasPrivateKey(keyInfo))
} }
val signatureScheme = findSignatureScheme(keyInfo.privateKeyAlgorithm) val signatureScheme = findSignatureScheme(keyInfo.privateKeyAlgorithm)
val keyFactory = keyFactory(signatureScheme) val keyFactory = keyFactory(signatureScheme)
return keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)) return convertIfBCEdDSAPrivateKey(keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)))
} }
@DeleteForDJVM @DeleteForDJVM
@ -354,7 +356,7 @@ object Crypto {
} }
try { try {
val keyFactory = keyFactory(signatureScheme) val keyFactory = keyFactory(signatureScheme)
return keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)) return convertIfBCEdDSAPrivateKey(keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)))
} catch (ikse: InvalidKeySpecException) { } catch (ikse: InvalidKeySpecException) {
throw InvalidKeySpecException("This private key cannot be decoded, please ensure it is PKCS8 encoded and that " + throw InvalidKeySpecException("This private key cannot be decoded, please ensure it is PKCS8 encoded and that " +
"it corresponds to the input scheme's code name.", ikse) "it corresponds to the input scheme's code name.", ikse)
@ -373,7 +375,7 @@ object Crypto {
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(encodedKey) val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(encodedKey)
val signatureScheme = findSignatureScheme(subjectPublicKeyInfo.algorithm) val signatureScheme = findSignatureScheme(subjectPublicKeyInfo.algorithm)
val keyFactory = keyFactory(signatureScheme) val keyFactory = keyFactory(signatureScheme)
return keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)) return convertIfBCEdDSAPublicKey(keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)))
} }
/** /**
@ -408,7 +410,7 @@ object Crypto {
} }
try { try {
val keyFactory = keyFactory(signatureScheme) val keyFactory = keyFactory(signatureScheme)
return keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)) return convertIfBCEdDSAPublicKey(keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)))
} catch (ikse: InvalidKeySpecException) { } catch (ikse: InvalidKeySpecException) {
throw InvalidKeySpecException("This public key cannot be decoded, please ensure it is X509 encoded and " + throw InvalidKeySpecException("This public key cannot be decoded, please ensure it is X509 encoded and " +
"that it corresponds to the input scheme's code name.", ikse) "that it corresponds to the input scheme's code name.", ikse)
@ -988,6 +990,20 @@ object Crypto {
} }
} }
private fun convertIfBCEdDSAPublicKey(key: PublicKey): PublicKey {
return when (key) {
is BCEdDSAPublicKey -> EdDSAPublicKey(X509EncodedKeySpec(key.encoded))
else -> key
}
}
private fun convertIfBCEdDSAPrivateKey(key: PrivateKey): PrivateKey {
return when (key) {
is BCEdDSAPrivateKey -> EdDSAPrivateKey(PKCS8EncodedKeySpec(key.encoded))
else -> key
}
}
/** /**
* Convert a public key to a supported implementation. * Convert a public key to a supported implementation.
* @param key a public key. * @param key a public key.
@ -1015,6 +1031,7 @@ object Crypto {
is BCSphincs256PublicKey -> key is BCSphincs256PublicKey -> key
is EdDSAPublicKey -> key is EdDSAPublicKey -> key
is CompositeKey -> key is CompositeKey -> key
is BCEdDSAPublicKey -> convertIfBCEdDSAPublicKey(key)
else -> decodePublicKey(key.encoded) else -> decodePublicKey(key.encoded)
} }
} }
@ -1035,6 +1052,7 @@ object Crypto {
is BCRSAPrivateKey -> key is BCRSAPrivateKey -> key
is BCSphincs256PrivateKey -> key is BCSphincs256PrivateKey -> key
is EdDSAPrivateKey -> key is EdDSAPrivateKey -> key
is BCEdDSAPrivateKey -> convertIfBCEdDSAPrivateKey(key)
else -> decodePrivateKey(key.encoded) else -> decodePrivateKey(key.encoded)
} }
} }

View File

@ -1,5 +1,5 @@
kotlin.incremental=true kotlin.incremental=true
org.gradle.jvmargs=-XX:+UseG1GC -Xmx1g -Dfile.encoding=UTF-8 org.gradle.jvmargs=-XX:+UseG1GC -Xmx4g -Dfile.encoding=UTF-8
org.gradle.caching=false org.gradle.caching=false
owasp.failOnError=false owasp.failOnError=false
owasp.failBuildOnCVSS=11.0 owasp.failBuildOnCVSS=11.0

View File

@ -50,10 +50,13 @@ import net.corda.nodeapi.internal.crypto.loadOrCreateKeyStore
import net.corda.nodeapi.internal.crypto.save import net.corda.nodeapi.internal.crypto.save
import net.corda.nodeapi.internal.crypto.toBc import net.corda.nodeapi.internal.crypto.toBc
import net.corda.nodeapi.internal.crypto.x509 import net.corda.nodeapi.internal.crypto.x509
import net.corda.testing.internal.IS_OPENJ9
import net.i2p.crypto.eddsa.EdDSAPrivateKey import net.i2p.crypto.eddsa.EdDSAPrivateKey
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.bouncycastle.asn1.x509.* import org.bouncycastle.asn1.x509.*
import org.bouncycastle.jcajce.provider.asymmetric.edec.BCEdDSAPrivateKey
import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PrivateKey import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PrivateKey
import org.junit.Assume
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.rules.TemporaryFolder import org.junit.rules.TemporaryFolder
@ -374,6 +377,7 @@ class X509UtilitiesTest {
@Test(timeout=300_000) @Test(timeout=300_000)
fun `create server cert and use in OpenSSL channel`() { fun `create server cert and use in OpenSSL channel`() {
Assume.assumeTrue(!IS_OPENJ9)
val sslConfig = CertificateStoreStubs.P2P.withCertificatesDirectory(tempFolder.root.toPath(), keyStorePassword = "serverstorepass") val sslConfig = CertificateStoreStubs.P2P.withCertificatesDirectory(tempFolder.root.toPath(), keyStorePassword = "serverstorepass")
val (rootCa, intermediateCa) = createDevIntermediateCaCertPath() val (rootCa, intermediateCa) = createDevIntermediateCaCertPath()
@ -446,7 +450,9 @@ class X509UtilitiesTest {
private fun <U, C> getCorrectKeyFromKeystore(signatureScheme: SignatureScheme, uncastedClass: Class<U>, castedClass: Class<C>) { private fun <U, C> getCorrectKeyFromKeystore(signatureScheme: SignatureScheme, uncastedClass: Class<U>, castedClass: Class<C>) {
val keyPair = generateKeyPair(signatureScheme) val keyPair = generateKeyPair(signatureScheme)
val (keyFromKeystore, keyFromKeystoreCasted) = storeAndGetKeysFromKeystore(keyPair) val (keyFromKeystore, keyFromKeystoreCasted) = storeAndGetKeysFromKeystore(keyPair)
assertThat(keyFromKeystore).isInstanceOf(uncastedClass) if (uncastedClass == EdDSAPrivateKey::class.java && keyFromKeystore !is BCEdDSAPrivateKey) {
assertThat(keyFromKeystore).isInstanceOf(uncastedClass)
}
assertThat(keyFromKeystoreCasted).isInstanceOf(castedClass) assertThat(keyFromKeystoreCasted).isInstanceOf(castedClass)
} }

View File

@ -77,6 +77,16 @@ fun createDevNetworkMapCa(rootCa: CertificateAndKeyPair = DEV_ROOT_CA): Certific
return CertificateAndKeyPair(cert, keyPair) return CertificateAndKeyPair(cert, keyPair)
} }
fun createDevNetworkParametersCa(rootCa: CertificateAndKeyPair = DEV_ROOT_CA): CertificateAndKeyPair {
val keyPair = generateKeyPair()
val cert = X509Utilities.createCertificate(
CertificateType.NETWORK_PARAMETERS,
rootCa.certificate,
rootCa.keyPair,
X500Principal("CN=Network Parameters,O=R3 Ltd,L=London,C=GB"),
keyPair.public)
return CertificateAndKeyPair(cert, keyPair)
}
/** /**
* Create a dev node CA cert, as a sub-cert of the given [intermediateCa], and matching key pair using the given * Create a dev node CA cert, as a sub-cert of the given [intermediateCa], and matching key pair using the given
* [CordaX500Name] as the cert subject. * [CordaX500Name] as the cert subject.

View File

@ -463,12 +463,18 @@ fun Kryo.serializationContext(): SerializeAsTokenContext? = context.get(serializ
class ThrowableSerializer<T>(kryo: Kryo, type: Class<T>) : Serializer<Throwable>(false, true) { class ThrowableSerializer<T>(kryo: Kryo, type: Class<T>) : Serializer<Throwable>(false, true) {
private companion object { private companion object {
private val IS_OPENJ9 = System.getProperty("java.vm.name").toLowerCase().contains("openj9")
private val suppressedField = Throwable::class.java.getDeclaredField("suppressedExceptions") private val suppressedField = Throwable::class.java.getDeclaredField("suppressedExceptions")
private val sentinelValue = let { private val sentinelValue = let {
val sentinelField = Throwable::class.java.getDeclaredField("SUPPRESSED_SENTINEL") if (!IS_OPENJ9) {
sentinelField.isAccessible = true val sentinelField = Throwable::class.java.getDeclaredField("SUPPRESSED_SENTINEL")
sentinelField.get(null) sentinelField.isAccessible = true
sentinelField.get(null)
}
else {
Collections.EMPTY_LIST
}
} }
init { init {

View File

@ -30,7 +30,9 @@ import net.corda.testing.core.DummyCommandData
import net.corda.testing.core.singleIdentity import net.corda.testing.core.singleIdentity
import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import org.apache.commons.lang3.SystemUtils
import org.hibernate.exception.ConstraintViolationException import org.hibernate.exception.ConstraintViolationException
import org.junit.Assume
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import java.lang.RuntimeException import java.lang.RuntimeException
@ -315,6 +317,8 @@ class FlowEntityManagerTest : AbstractFlowEntityManagerTest() {
@Test(timeout = 300_000) @Test(timeout = 300_000)
fun `constraint violation that is caught inside an entity manager should allow a flow to continue processing as normal`() { fun `constraint violation that is caught inside an entity manager should allow a flow to continue processing as normal`() {
// This test is generating JDK11 contract code on JDK11
Assume.assumeTrue(!SystemUtils.IS_JAVA_11)
var counter = 0 var counter = 0
StaffedFlowHospital.onFlowDischarged.add { _, _ -> ++counter } StaffedFlowHospital.onFlowDischarged.add { _, _ -> ++counter }
driver(DriverParameters(startNodesInProcess = true)) { driver(DriverParameters(startNodesInProcess = true)) {

View File

@ -50,7 +50,8 @@ class H2SecurityTests {
inMemoryDB = false, inMemoryDB = false,
startNodesInProcess = false, startNodesInProcess = false,
notarySpecs = emptyList(), notarySpecs = emptyList(),
cordappsForAllNodes = emptyList() cordappsForAllNodes = emptyList(),
premigrateH2Database = false
)) { )) {
val port = getFreePort() val port = getFreePort()
startNode(customOverrides = mapOf(h2AddressKey to "localhost:$port", dbPasswordKey to "x")).getOrThrow() startNode(customOverrides = mapOf(h2AddressKey to "localhost:$port", dbPasswordKey to "x")).getOrThrow()
@ -71,7 +72,8 @@ class H2SecurityTests {
inMemoryDB = false, inMemoryDB = false,
startNodesInProcess = false, startNodesInProcess = false,
notarySpecs = emptyList(), notarySpecs = emptyList(),
cordappsForAllNodes = listOf(enclosedCordapp()) cordappsForAllNodes = listOf(enclosedCordapp()),
premigrateH2Database = false
)) { )) {
val port = getFreePort() val port = getFreePort()
val nodeHandle = startNode(rpcUsers = listOf(user), customOverrides = mapOf(h2AddressKey to "localhost:$port", val nodeHandle = startNode(rpcUsers = listOf(user), customOverrides = mapOf(h2AddressKey to "localhost:$port",

View File

@ -62,7 +62,7 @@ class NonDeterministicContractVerifyTest {
.returnValue.getOrThrow() .returnValue.getOrThrow()
} }
assertThat(ex) assertThat(ex)
.hasMessageMatching("^NoSuchMethodError: .*\\Qsandbox.java.time.Instant.now()\\E.*\$") .hasMessageMatching("^NoSuchMethodError: .*[\\Qsandbox.java.time.Instant.now()\\E|\\Qsandbox.java/time/Instant/now()\\E].*\$")
} }
} }
@ -101,7 +101,7 @@ class NonDeterministicContractVerifyTest {
.returnValue.getOrThrow() .returnValue.getOrThrow()
} }
assertThat(ex) assertThat(ex)
.hasMessageMatching("^NoSuchMethodError: .*\\Qsandbox.java.util.UUID.randomUUID()\\E.*\$") .hasMessageMatching("^NoSuchMethodError: .*[\\Qsandbox.java.util.UUID.randomUUID()\\E|\\Qsandbox/java/util/UUID/randomUUID()\\E].*\$")
} }
} }

View File

@ -82,7 +82,8 @@ class LargeTransactionsTest {
driver(DriverParameters( driver(DriverParameters(
startNodesInProcess = true, startNodesInProcess = true,
cordappsForAllNodes = listOf(DUMMY_CONTRACTS_CORDAPP, enclosedCordapp()), cordappsForAllNodes = listOf(DUMMY_CONTRACTS_CORDAPP, enclosedCordapp()),
networkParameters = testNetworkParameters(maxMessageSize = 15.MB.toInt(), maxTransactionSize = 13.MB.toInt()) networkParameters = testNetworkParameters(maxMessageSize = 15.MB.toInt(), maxTransactionSize = 13.MB.toInt()),
premigrateH2Database = false
)) { )) {
val rpcUser = User("admin", "admin", setOf("ALL")) val rpcUser = User("admin", "admin", setOf("ALL"))
val (alice, _) = listOf(ALICE_NAME, BOB_NAME).map { startNode(providedName = it, rpcUsers = listOf(rpcUser)) }.transpose().getOrThrow() val (alice, _) = listOf(ALICE_NAME, BOB_NAME).map { startNode(providedName = it, rpcUsers = listOf(rpcUser)) }.transpose().getOrThrow()

View File

@ -19,7 +19,6 @@ import net.corda.node.utilities.AppendOnlyPersistentMap
import net.corda.nodeapi.internal.crypto.X509CertificateFactory import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.network.SignedNetworkParameters import net.corda.nodeapi.internal.network.SignedNetworkParameters
import net.corda.nodeapi.internal.network.verifiedNetworkMapCert
import net.corda.nodeapi.internal.network.verifiedNetworkParametersCert import net.corda.nodeapi.internal.network.verifiedNetworkParametersCert
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
@ -86,7 +85,7 @@ class DBNetworkParametersStorage(
override fun saveParameters(signedNetworkParameters: SignedNetworkParameters) { override fun saveParameters(signedNetworkParameters: SignedNetworkParameters) {
log.trace { "Saving new network parameters to network parameters storage." } log.trace { "Saving new network parameters to network parameters storage." }
val networkParameters = signedNetworkParameters.verifiedNetworkMapCert(trustRoot) val networkParameters = signedNetworkParameters.verifiedNetworkParametersCert(trustRoot)
val hash = signedNetworkParameters.raw.hash val hash = signedNetworkParameters.raw.hash
log.trace { "Parameters to save $networkParameters with hash $hash" } log.trace { "Parameters to save $networkParameters with hash $hash" }
database.transaction { database.transaction {

View File

@ -348,7 +348,7 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
val cordappElement = cordappJarPath.url.toString() val cordappElement = cordappJarPath.url.toString()
logger.info("Scanning CorDapp in $cordappElement") logger.info("Scanning CorDapp in $cordappElement")
val scanResult = ClassGraph() val scanResult = ClassGraph()
.filterClasspathElements { elt -> elt == cordappElement } .filterClasspathElementsByURL { elt -> elt == cordappJarPath.url }
.overrideClassLoaders(appClassLoader) .overrideClassLoaders(appClassLoader)
.ignoreParentClassLoaders() .ignoreParentClassLoaders()
.enableAllInfo() .enableAllInfo()

View File

@ -42,12 +42,14 @@ import net.corda.testing.core.*
import net.corda.testing.dsl.LedgerDSL import net.corda.testing.dsl.LedgerDSL
import net.corda.testing.dsl.TestLedgerDSLInterpreter import net.corda.testing.dsl.TestLedgerDSLInterpreter
import net.corda.testing.dsl.TestTransactionDSLInterpreter import net.corda.testing.dsl.TestTransactionDSLInterpreter
import net.corda.testing.internal.IS_OPENJ9
import net.corda.testing.internal.LogHelper import net.corda.testing.internal.LogHelper
import net.corda.testing.internal.vault.VaultFiller import net.corda.testing.internal.vault.VaultFiller
import net.corda.testing.node.internal.* import net.corda.testing.node.internal.*
import net.corda.testing.node.ledger import net.corda.testing.node.ledger
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
import org.junit.Assume
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@ -211,6 +213,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
@Test(timeout=300_000) @Test(timeout=300_000)
fun `shutdown and restore`() { fun `shutdown and restore`() {
Assume.assumeTrue(!IS_OPENJ9)
mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP)) mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP))
val notaryNode = mockNet.defaultNotaryNode val notaryNode = mockNet.defaultNotaryNode
val notary = mockNet.defaultNotaryIdentity val notary = mockNet.defaultNotaryIdentity

View File

@ -2,16 +2,23 @@ package net.corda.node.services.network
import com.google.common.jimfs.Configuration import com.google.common.jimfs.Configuration
import com.google.common.jimfs.Jimfs import com.google.common.jimfs.Jimfs
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.* import net.corda.core.internal.*
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.utilities.days import net.corda.core.utilities.days
import net.corda.core.utilities.seconds import net.corda.core.utilities.seconds
import net.corda.coretesting.internal.DEV_INTERMEDIATE_CA
import net.corda.node.VersionInfo import net.corda.node.VersionInfo
import net.corda.node.internal.NetworkParametersReader import net.corda.node.internal.NetworkParametersReader
import net.corda.nodeapi.internal.network.* import net.corda.nodeapi.internal.network.*
import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.coretesting.internal.DEV_ROOT_CA import net.corda.coretesting.internal.DEV_ROOT_CA
import net.corda.nodeapi.internal.createDevNetworkMapCa
import net.corda.nodeapi.internal.createDevNetworkParametersCa
import net.corda.nodeapi.internal.createDevNodeCa
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
import net.corda.testing.core.TestIdentity
import net.corda.testing.node.internal.network.NetworkMapServer import net.corda.testing.node.internal.network.NetworkMapServer
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
@ -21,6 +28,7 @@ import org.junit.Test
import java.net.URL import java.net.URL
import java.nio.file.FileSystem import java.nio.file.FileSystem
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse import kotlin.test.assertFalse
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
@ -84,4 +92,23 @@ class NetworkParametersReaderTest {
val parameters = inByteArray.deserialize<SignedNetworkParameters>() val parameters = inByteArray.deserialize<SignedNetworkParameters>()
assertThat(parameters.verified().eventHorizon).isEqualTo(Int.MAX_VALUE.days) assertThat(parameters.verified().eventHorizon).isEqualTo(Int.MAX_VALUE.days)
} }
@Test(timeout = 300_000)
fun `verifying works with NETWORK_PARAMETERS role and NETWORK_MAP role, but fails for NODE_CA role`() {
val netParameters = testNetworkParameters(epoch = 1)
val certKeyPairNetworkParameters: CertificateAndKeyPair = createDevNetworkParametersCa()
val netParamsForNetworkParameters= certKeyPairNetworkParameters.sign(netParameters)
netParamsForNetworkParameters.verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
val certKeyPairNetworkMap: CertificateAndKeyPair = createDevNetworkMapCa()
val netParamsForNetworkMap = certKeyPairNetworkMap.sign(netParameters)
netParamsForNetworkMap.verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
val megaCorp = TestIdentity(CordaX500Name("MegaCorp", "London", "GB"))
val x = createDevNodeCa(DEV_INTERMEDIATE_CA, megaCorp.name)
val netParamsForNode = x.sign(netParameters)
assertFailsWith(IllegalArgumentException::class, "Incorrect cert role: NODE_CA") {
netParamsForNode.verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
}
}
} }

View File

@ -54,6 +54,7 @@ import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.dummyCommand import net.corda.testing.core.dummyCommand
import net.corda.testing.core.singleIdentity import net.corda.testing.core.singleIdentity
import net.corda.testing.flows.registerCordappFlowFactory import net.corda.testing.flows.registerCordappFlowFactory
import net.corda.testing.internal.IS_OPENJ9
import net.corda.testing.internal.LogHelper import net.corda.testing.internal.LogHelper
import net.corda.testing.node.InMemoryMessagingNetwork.MessageTransfer import net.corda.testing.node.InMemoryMessagingNetwork.MessageTransfer
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
@ -74,6 +75,7 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNotNull import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull import org.junit.Assert.assertNull
import org.junit.Assume
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import rx.Notification import rx.Notification
@ -82,6 +84,7 @@ import java.sql.SQLTransientConnectionException
import java.time.Clock import java.time.Clock
import java.time.Duration import java.time.Duration
import java.time.Instant import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.UUID import java.util.UUID
import java.util.concurrent.TimeoutException import java.util.concurrent.TimeoutException
import java.util.function.Predicate import java.util.function.Predicate
@ -384,6 +387,7 @@ class FlowFrameworkTests {
@Test(timeout = 300_000) @Test(timeout = 300_000)
fun `Flow metadata finish time is set in database when the flow finishes`() { fun `Flow metadata finish time is set in database when the flow finishes`() {
Assume.assumeTrue(!IS_OPENJ9)
val terminationSignal = Semaphore(0) val terminationSignal = Semaphore(0)
val clientId = UUID.randomUUID().toString() val clientId = UUID.randomUUID().toString()
val flow = aliceNode.services.startFlowWithClientId(clientId, NoOpFlow(terminateUponSignal = terminationSignal)) val flow = aliceNode.services.startFlowWithClientId(clientId, NoOpFlow(terminateUponSignal = terminationSignal))
@ -397,7 +401,7 @@ class FlowFrameworkTests {
aliceNode.database.transaction { aliceNode.database.transaction {
val metadata = session.find(DBCheckpointStorage.DBFlowMetadata::class.java, flow.id.uuid.toString()) val metadata = session.find(DBCheckpointStorage.DBFlowMetadata::class.java, flow.id.uuid.toString())
assertNotNull(metadata.finishInstant) assertNotNull(metadata.finishInstant)
assertTrue(metadata.finishInstant!! >= metadata.startInstant) assertTrue(metadata.finishInstant!!.truncatedTo(ChronoUnit.MILLIS) >= metadata.startInstant.truncatedTo(ChronoUnit.MILLIS))
} }
} }

View File

@ -48,6 +48,7 @@ import org.junit.Before
import org.junit.Ignore import org.junit.Ignore
import org.junit.Test import org.junit.Test
import java.time.Instant import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.UUID import java.util.UUID
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executors import java.util.concurrent.Executors
@ -118,7 +119,8 @@ class FlowMetadataRecordingTest {
assertThat(it.launchingCordapp).contains("custom-cordapp") assertThat(it.launchingCordapp).contains("custom-cordapp")
assertEquals(PLATFORM_VERSION, it.platformVersion) assertEquals(PLATFORM_VERSION, it.platformVersion)
assertEquals(user.username, it.startedBy) assertEquals(user.username, it.startedBy)
assertEquals(context!!.trace.invocationId.timestamp, it.invocationInstant) assertEquals(context!!.trace.invocationId.timestamp.truncatedTo((ChronoUnit.MILLIS)),
it.invocationInstant.truncatedTo(ChronoUnit.MILLIS))
assertTrue(it.startInstant >= it.invocationInstant) assertTrue(it.startInstant >= it.invocationInstant)
assertNull(it.finishInstant) assertNull(it.finishInstant)
} }
@ -159,7 +161,8 @@ class FlowMetadataRecordingTest {
assertThat(it.launchingCordapp).contains("custom-cordapp") assertThat(it.launchingCordapp).contains("custom-cordapp")
assertEquals(PLATFORM_VERSION, it.platformVersion) assertEquals(PLATFORM_VERSION, it.platformVersion)
assertEquals(user.username, it.startedBy) assertEquals(user.username, it.startedBy)
assertEquals(context!!.trace.invocationId.timestamp, it.invocationInstant) assertEquals(context!!.trace.invocationId.timestamp.truncatedTo(ChronoUnit.MILLIS),
it.invocationInstant.truncatedTo(ChronoUnit.MILLIS))
assertTrue(it.startInstant >= it.invocationInstant) assertTrue(it.startInstant >= it.invocationInstant)
assertNull(it.finishInstant) assertNull(it.finishInstant)
} }
@ -261,7 +264,8 @@ class FlowMetadataRecordingTest {
assertThat(it.launchingCordapp).contains("custom-cordapp") assertThat(it.launchingCordapp).contains("custom-cordapp")
assertEquals(8, it.platformVersion) assertEquals(8, it.platformVersion)
assertEquals(nodeAHandle.nodeInfo.singleIdentity().name.toString(), it.startedBy) assertEquals(nodeAHandle.nodeInfo.singleIdentity().name.toString(), it.startedBy)
assertEquals(context!!.trace.invocationId.timestamp, it.invocationInstant) assertEquals(context!!.trace.invocationId.timestamp.truncatedTo(ChronoUnit.MILLIS),
it.invocationInstant.truncatedTo(ChronoUnit.MILLIS))
assertTrue(it.startInstant >= it.invocationInstant) assertTrue(it.startInstant >= it.invocationInstant)
assertNull(it.finishInstant) assertNull(it.finishInstant)
} }
@ -309,7 +313,8 @@ class FlowMetadataRecordingTest {
assertThat(it.launchingCordapp).contains("custom-cordapp") assertThat(it.launchingCordapp).contains("custom-cordapp")
assertEquals(PLATFORM_VERSION, it.platformVersion) assertEquals(PLATFORM_VERSION, it.platformVersion)
assertEquals(MyService::class.java.name, it.startedBy) assertEquals(MyService::class.java.name, it.startedBy)
assertEquals(context!!.trace.invocationId.timestamp, it.invocationInstant) assertEquals(context!!.trace.invocationId.timestamp.truncatedTo(ChronoUnit.MILLIS),
it.invocationInstant.truncatedTo(ChronoUnit.MILLIS))
assertTrue(it.startInstant >= it.invocationInstant) assertTrue(it.startInstant >= it.invocationInstant)
assertNull(it.finishInstant) assertNull(it.finishInstant)
} }
@ -364,7 +369,8 @@ class FlowMetadataRecordingTest {
assertThat(it.launchingCordapp).contains("custom-cordapp") assertThat(it.launchingCordapp).contains("custom-cordapp")
assertEquals(PLATFORM_VERSION, it.platformVersion) assertEquals(PLATFORM_VERSION, it.platformVersion)
assertEquals("Scheduler", it.startedBy) assertEquals("Scheduler", it.startedBy)
assertEquals(context!!.trace.invocationId.timestamp, it.invocationInstant) assertEquals(context!!.trace.invocationId.timestamp.truncatedTo(ChronoUnit.MILLIS),
it.invocationInstant.truncatedTo(ChronoUnit.MILLIS))
assertTrue(it.startInstant >= it.invocationInstant) assertTrue(it.startInstant >= it.invocationInstant)
assertNull(it.finishInstant) assertNull(it.finishInstant)
} }

View File

@ -23,6 +23,7 @@ import net.corda.node.services.messaging.Message
import net.corda.node.services.persistence.DBTransactionStorage import net.corda.node.services.persistence.DBTransactionStorage
import net.corda.nodeapi.internal.persistence.contextTransaction import net.corda.nodeapi.internal.persistence.contextTransaction
import net.corda.testing.core.TestIdentity import net.corda.testing.core.TestIdentity
import net.corda.testing.internal.IS_OPENJ9
import net.corda.testing.node.internal.InternalMockNetwork import net.corda.testing.node.internal.InternalMockNetwork
import net.corda.testing.node.internal.MessagingServiceSpy import net.corda.testing.node.internal.MessagingServiceSpy
import net.corda.testing.node.internal.TestStartedNode import net.corda.testing.node.internal.TestStartedNode
@ -33,6 +34,7 @@ import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.h2.util.Utils import org.h2.util.Utils
import org.junit.After import org.junit.After
import org.junit.Assert.assertTrue import org.junit.Assert.assertTrue
import org.junit.Assume
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import java.sql.SQLException import java.sql.SQLException
@ -129,6 +131,7 @@ class RetryFlowMockTest {
@Test(timeout=300_000) @Test(timeout=300_000)
fun `Early end session message does not hang receiving flow`() { fun `Early end session message does not hang receiving flow`() {
Assume.assumeTrue(!IS_OPENJ9)
val partyB = nodeB.info.legalIdentities.first() val partyB = nodeB.info.legalIdentities.first()
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy { assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
nodeA.startFlow(UnbalancedSendAndReceiveFlow(partyB)).getOrThrow(20.seconds) nodeA.startFlow(UnbalancedSendAndReceiveFlow(partyB)).getOrThrow(20.seconds)

View File

@ -35,6 +35,7 @@ import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.contracts.DummyState import net.corda.testing.contracts.DummyState
import net.corda.testing.core.* import net.corda.testing.core.*
import net.corda.testing.internal.IS_OPENJ9
import net.corda.testing.internal.LogHelper import net.corda.testing.internal.LogHelper
import net.corda.testing.internal.vault.* import net.corda.testing.internal.vault.*
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
@ -468,6 +469,7 @@ class NodeVaultServiceTest {
@Test(timeout=300_000) @Test(timeout=300_000)
fun `unconsumedStatesForSpending from two issuer parties`() { fun `unconsumedStatesForSpending from two issuer parties`() {
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
database.transaction { database.transaction {
vaultFiller.fillWithSomeTestCash(100.DOLLARS, issuerServices, 1, DUMMY_CASH_ISSUER) vaultFiller.fillWithSomeTestCash(100.DOLLARS, issuerServices, 1, DUMMY_CASH_ISSUER)
vaultFiller.fillWithSomeTestCash(100.DOLLARS, bocServices, 1, BOC.ref(1)) vaultFiller.fillWithSomeTestCash(100.DOLLARS, bocServices, 1, BOC.ref(1))

View File

@ -25,15 +25,20 @@ import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetworkParameters import net.corda.testing.node.MockNetworkParameters
import net.corda.testing.node.StartedMockNode import net.corda.testing.node.StartedMockNode
import net.corda.testing.node.internal.cordappsForPackages import net.corda.testing.node.internal.cordappsForPackages
import org.apache.commons.lang3.SystemUtils
import org.junit.AfterClass import org.junit.AfterClass
import org.junit.Assume
import org.junit.BeforeClass import org.junit.BeforeClass
import org.junit.Test import org.junit.Test
import org.junit.jupiter.api.condition.DisabledOnJre
import org.junit.jupiter.api.condition.JRE
import javax.persistence.Column import javax.persistence.Column
import javax.persistence.Entity import javax.persistence.Entity
import javax.persistence.Index import javax.persistence.Index
import javax.persistence.Table import javax.persistence.Table
import kotlin.test.assertEquals import kotlin.test.assertEquals
@DisabledOnJre(JRE.JAVA_11)
class VaultQueryJoinTest { class VaultQueryJoinTest {
companion object { companion object {
private var mockNetwork: MockNetwork? = null private var mockNetwork: MockNetwork? = null
@ -46,6 +51,7 @@ class VaultQueryJoinTest {
@BeforeClass @BeforeClass
@JvmStatic @JvmStatic
fun setup() { fun setup() {
Assume.assumeTrue(!SystemUtils.IS_JAVA_11)
mockNetwork = MockNetwork( mockNetwork = MockNetwork(
MockNetworkParameters( MockNetworkParameters(
cordappsForAllNodes = cordappsForPackages( cordappsForAllNodes = cordappsForPackages(

View File

@ -32,6 +32,7 @@ import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.nodeapi.internal.persistence.DatabaseTransaction import net.corda.nodeapi.internal.persistence.DatabaseTransaction
import net.corda.testing.core.* import net.corda.testing.core.*
import net.corda.testing.internal.IS_OPENJ9
import net.corda.testing.internal.chooseIdentity import net.corda.testing.internal.chooseIdentity
import net.corda.testing.internal.configureDatabase import net.corda.testing.internal.configureDatabase
import net.corda.testing.internal.vault.* import net.corda.testing.internal.vault.*
@ -40,6 +41,7 @@ import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServ
import net.corda.testing.node.makeTestIdentityService import net.corda.testing.node.makeTestIdentityService
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatCode import org.assertj.core.api.Assertions.assertThatCode
import org.junit.Assume
import org.junit.ClassRule import org.junit.ClassRule
import org.junit.Ignore import org.junit.Ignore
import org.junit.Rule import org.junit.Rule
@ -1689,6 +1691,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
// pagination: invalid page number // pagination: invalid page number
@Test(timeout=300_000) @Test(timeout=300_000)
fun `invalid page number`() { fun `invalid page number`() {
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
expectedEx.expect(VaultQueryException::class.java) expectedEx.expect(VaultQueryException::class.java)
expectedEx.expectMessage("Page specification: invalid page number") expectedEx.expectMessage("Page specification: invalid page number")
@ -2235,6 +2238,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
@Test(timeout=300_000) @Test(timeout=300_000)
fun `unconsumed fungible states for owners`() { fun `unconsumed fungible states for owners`() {
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
database.transaction { database.transaction {
vaultFillerCashNotary.fillWithSomeTestCash(100.DOLLARS, notaryServices, 1, DUMMY_CASH_ISSUER) vaultFillerCashNotary.fillWithSomeTestCash(100.DOLLARS, notaryServices, 1, DUMMY_CASH_ISSUER)
vaultFiller.fillWithSomeTestCash(100.DOLLARS, notaryServices, 1, MEGA_CORP.ref(0), MEGA_CORP) vaultFiller.fillWithSomeTestCash(100.DOLLARS, notaryServices, 1, MEGA_CORP.ref(0), MEGA_CORP)
@ -2289,6 +2293,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
@Test(timeout=300_000) @Test(timeout=300_000)
fun `unconsumed cash balances for all currencies`() { fun `unconsumed cash balances for all currencies`() {
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
database.transaction { database.transaction {
listOf(100.DOLLARS, 200.DOLLARS, 300.POUNDS, 400.POUNDS, 500.SWISS_FRANCS, 600.SWISS_FRANCS).zip(1..6).forEach { (howMuch, states) -> listOf(100.DOLLARS, 200.DOLLARS, 300.POUNDS, 400.POUNDS, 500.SWISS_FRANCS, 600.SWISS_FRANCS).zip(1..6).forEach { (howMuch, states) ->
vaultFiller.fillWithSomeTestCash(howMuch, notaryServices, states, DUMMY_CASH_ISSUER) vaultFiller.fillWithSomeTestCash(howMuch, notaryServices, states, DUMMY_CASH_ISSUER)
@ -2471,6 +2476,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
// specifying Query on Linear state attributes // specifying Query on Linear state attributes
@Test(timeout=300_000) @Test(timeout=300_000)
fun `unconsumed linear heads for linearId between two timestamps`() { fun `unconsumed linear heads for linearId between two timestamps`() {
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
database.transaction { database.transaction {
val start = services.clock.instant() val start = services.clock.instant()
vaultFiller.fillWithSomeTestLinearStates(1, "TEST") vaultFiller.fillWithSomeTestLinearStates(1, "TEST")
@ -2776,6 +2782,8 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
} }
} }
//linus one OOM issue
@Ignore
@Test(timeout=300_000) @Test(timeout=300_000)
fun `record a transaction with number of inputs greater than vault page size`() { fun `record a transaction with number of inputs greater than vault page size`() {
val notary = dummyNotary val notary = dummyNotary

View File

@ -1,7 +1,9 @@
package net.corda.testing.node.internal package net.corda.testing.node.internal
import net.corda.testing.internal.IS_OPENJ9
import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.matchesPattern import org.hamcrest.Matchers.matchesPattern
import org.junit.Assume
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.junit.runners.Parameterized import org.junit.runners.Parameterized
@ -17,7 +19,7 @@ class CordaCliWrapperErrorHandlingTests(val arguments: List<String>, val outputR
val className = "net.corda.testing.node.internal.SampleCordaCliWrapper" val className = "net.corda.testing.node.internal.SampleCordaCliWrapper"
private val stackTraceRegex = "^.+Exception[^\\n]++(\\s+at .++)+[\\s\\S]*" private val stackTraceRegex = "^.+Exception[^\\n]++(\\s+at .++)+[\\s\\S]*"
private val exceptionWithoutStackTraceRegex ="${className}(\\s+.+)" private val exceptionWithoutStackTraceRegex ="(\\?\\[31m)*\\Q${className}\\E(\\?\\[0m)*(\\s+.+)"
private val emptyStringRegex = "^$" private val emptyStringRegex = "^$"
@JvmStatic @JvmStatic
@ -31,7 +33,8 @@ class CordaCliWrapperErrorHandlingTests(val arguments: List<String>, val outputR
@Test(timeout=300_000) @Test(timeout=300_000)
fun `Run CordaCliWrapper sample app with arguments and check error output matches regExp`() { fun `Run CordaCliWrapper sample app with arguments and check error output matches regExp`() {
// For openj9 the process error output appears sometimes to be garbled.
Assume.assumeTrue(!IS_OPENJ9)
val process = ProcessUtilities.startJavaProcess( val process = ProcessUtilities.startJavaProcess(
className = className, className = className,
arguments = arguments, arguments = arguments,

View File

@ -43,21 +43,28 @@ data class NotaryHandle(val identity: Party, val validating: Boolean, val nodeHa
interface NodeHandle : AutoCloseable { interface NodeHandle : AutoCloseable {
/** Get the [NodeInfo] for this node */ /** Get the [NodeInfo] for this node */
val nodeInfo: NodeInfo val nodeInfo: NodeInfo
/** /**
* Interface to the node's RPC system. The first RPC user will be used to login if are any, otherwise a default one * Interface to the node's RPC system. The first RPC user will be used to login if are any, otherwise a default one
* will be added and that will be used. * will be added and that will be used.
*/ */
val rpc: CordaRPCOps val rpc: CordaRPCOps
/** Get the p2p address for this node **/ /** Get the p2p address for this node **/
val p2pAddress: NetworkHostAndPort val p2pAddress: NetworkHostAndPort
/** Get the rpc address for this node **/ /** Get the rpc address for this node **/
val rpcAddress: NetworkHostAndPort val rpcAddress: NetworkHostAndPort
/** Get the rpc admin address for this node **/ /** Get the rpc admin address for this node **/
val rpcAdminAddress: NetworkHostAndPort val rpcAdminAddress: NetworkHostAndPort
/** Get the JMX server address for this node, if JMX is enabled **/ /** Get the JMX server address for this node, if JMX is enabled **/
val jmxAddress: NetworkHostAndPort? val jmxAddress: NetworkHostAndPort?
/** Get a [List] of [User]'s for this node **/ /** Get a [List] of [User]'s for this node **/
val rpcUsers: List<User> val rpcUsers: List<User>
/** The location of the node's base directory **/ /** The location of the node's base directory **/
val baseDirectory: Path val baseDirectory: Path
@ -67,7 +74,8 @@ interface NodeHandle : AutoCloseable {
fun stop() fun stop()
} }
fun NodeHandle.logFile(): File = (baseDirectory / "logs").toFile().walk().filter { it.name.startsWith("node-") && it.extension == "log" }.single() fun NodeHandle.logFile(): File = (baseDirectory / "logs").toFile().walk().filter { it.name.startsWith("node-") && it.extension == "log" }
.single()
/** Interface which represents an out of process node and exposes its process handle. **/ /** Interface which represents an out of process node and exposes its process handle. **/
@DoNotImplement @DoNotImplement
@ -91,7 +99,8 @@ interface InProcess : NodeHandle {
* Starts an already constructed flow. Note that you must be on the server thread to call this method. * Starts an already constructed flow. Note that you must be on the server thread to call this method.
* @param context indicates who started the flow, see: [InvocationContext]. * @param context indicates who started the flow, see: [InvocationContext].
*/ */
fun <T> startFlow(logic: FlowLogic<T>): CordaFuture<T> = internalServices.startFlow(logic, internalServices.newContext()).getOrThrow().resultFuture fun <T> startFlow(logic: FlowLogic<T>): CordaFuture<T> = internalServices.startFlow(logic, internalServices.newContext())
.getOrThrow().resultFuture
} }
/** /**
@ -206,7 +215,8 @@ fun <A> driver(defaultParameters: DriverParameters = DriverParameters(), dsl: Dr
djvmBootstrapSource = defaultParameters.djvmBootstrapSource, djvmBootstrapSource = defaultParameters.djvmBootstrapSource,
djvmCordaSource = defaultParameters.djvmCordaSource, djvmCordaSource = defaultParameters.djvmCordaSource,
environmentVariables = defaultParameters.environmentVariables, environmentVariables = defaultParameters.environmentVariables,
allowHibernateToManageAppSchema = defaultParameters.allowHibernateToManageAppSchema allowHibernateToManageAppSchema = defaultParameters.allowHibernateToManageAppSchema,
premigrateH2Database = defaultParameters.premigrateH2Database
), ),
coerce = { it }, coerce = { it },
dsl = dsl dsl = dsl
@ -245,6 +255,8 @@ fun <A> driver(defaultParameters: DriverParameters = DriverParameters(), dsl: Dr
* @property cordappsForAllNodes [TestCordapp]s that will be added to each node started by the [DriverDSL]. * @property cordappsForAllNodes [TestCordapp]s that will be added to each node started by the [DriverDSL].
* @property djvmBootstrapSource Location of a JAR containing the Java APIs for the DJVM to use. * @property djvmBootstrapSource Location of a JAR containing the Java APIs for the DJVM to use.
* @property djvmCordaSource Locations of JARs of user-supplied classes to execute within the DJVM sandbox. * @property djvmCordaSource Locations of JARs of user-supplied classes to execute within the DJVM sandbox.
* @property premigrateH2Database Whether to use a prebuilt H2 database schema or start from an empty schema.
* This can save time for tests which do not need to migrate from a blank schema.
*/ */
@Suppress("unused") @Suppress("unused")
data class DriverParameters( data class DriverParameters(
@ -263,12 +275,13 @@ data class DriverParameters(
@Suppress("DEPRECATION") val jmxPolicy: JmxPolicy = JmxPolicy(), @Suppress("DEPRECATION") val jmxPolicy: JmxPolicy = JmxPolicy(),
val networkParameters: NetworkParameters = testNetworkParameters(notaries = emptyList()), val networkParameters: NetworkParameters = testNetworkParameters(notaries = emptyList()),
val notaryCustomOverrides: Map<String, Any?> = emptyMap(), val notaryCustomOverrides: Map<String, Any?> = emptyMap(),
val inMemoryDB: Boolean = true, val inMemoryDB: Boolean = false,
val cordappsForAllNodes: Collection<TestCordapp>? = null, val cordappsForAllNodes: Collection<TestCordapp>? = null,
val djvmBootstrapSource: Path? = null, val djvmBootstrapSource: Path? = null,
val djvmCordaSource: List<Path> = emptyList(), val djvmCordaSource: List<Path> = emptyList(),
val environmentVariables : Map<String, String> = emptyMap(), val environmentVariables: Map<String, String> = emptyMap(),
val allowHibernateToManageAppSchema: Boolean = true val allowHibernateToManageAppSchema: Boolean = true,
val premigrateH2Database: Boolean = true
) { ) {
constructor(cordappsForAllNodes: Collection<TestCordapp>) : this(isDebug = false, cordappsForAllNodes = cordappsForAllNodes) constructor(cordappsForAllNodes: Collection<TestCordapp>) : this(isDebug = false, cordappsForAllNodes = cordappsForAllNodes)
@ -376,6 +389,49 @@ data class DriverParameters(
cordappsForAllNodes = null cordappsForAllNodes = null
) )
constructor(
isDebug: Boolean = false,
driverDirectory: Path = Paths.get("build") / "node-driver" / getTimestampAsDirectoryName(),
portAllocation: PortAllocation = incrementalPortAllocation(),
debugPortAllocation: PortAllocation = incrementalPortAllocation(),
systemProperties: Map<String, String> = emptyMap(),
useTestClock: Boolean = false,
startNodesInProcess: Boolean = false,
waitForAllNodesToFinish: Boolean = false,
notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY_NAME)),
extraCordappPackagesToScan: List<String> = emptyList(),
@Suppress("DEPRECATION") jmxPolicy: JmxPolicy = JmxPolicy(),
networkParameters: NetworkParameters = testNetworkParameters(notaries = emptyList()),
notaryCustomOverrides: Map<String, Any?> = emptyMap(),
inMemoryDB: Boolean = false,
cordappsForAllNodes: Collection<TestCordapp>? = null,
djvmBootstrapSource: Path? = null,
djvmCordaSource: List<Path> = emptyList(),
environmentVariables: Map<String, String> = emptyMap(),
allowHibernateToManageAppSchema: Boolean = true
) : this(
isDebug,
driverDirectory,
portAllocation,
debugPortAllocation,
systemProperties,
useTestClock,
startNodesInProcess,
waitForAllNodesToFinish,
notarySpecs,
extraCordappPackagesToScan,
jmxPolicy,
networkParameters,
notaryCustomOverrides,
inMemoryDB,
cordappsForAllNodes,
djvmBootstrapSource,
djvmCordaSource,
environmentVariables,
allowHibernateToManageAppSchema,
premigrateH2Database = true
)
constructor( constructor(
isDebug: Boolean, isDebug: Boolean,
driverDirectory: Path, driverDirectory: Path,
@ -417,6 +473,7 @@ data class DriverParameters(
fun withStartNodesInProcess(startNodesInProcess: Boolean): DriverParameters = copy(startNodesInProcess = startNodesInProcess) fun withStartNodesInProcess(startNodesInProcess: Boolean): DriverParameters = copy(startNodesInProcess = startNodesInProcess)
fun withWaitForAllNodesToFinish(waitForAllNodesToFinish: Boolean): DriverParameters = copy(waitForAllNodesToFinish = waitForAllNodesToFinish) fun withWaitForAllNodesToFinish(waitForAllNodesToFinish: Boolean): DriverParameters = copy(waitForAllNodesToFinish = waitForAllNodesToFinish)
fun withNotarySpecs(notarySpecs: List<NotarySpec>): DriverParameters = copy(notarySpecs = notarySpecs) fun withNotarySpecs(notarySpecs: List<NotarySpec>): DriverParameters = copy(notarySpecs = notarySpecs)
@Deprecated("extraCordappPackagesToScan does not preserve the original CorDapp's versioning and metadata, which may lead to " + @Deprecated("extraCordappPackagesToScan does not preserve the original CorDapp's versioning and metadata, which may lead to " +
"misleading results in tests. Use withCordappsForAllNodes instead.") "misleading results in tests. Use withCordappsForAllNodes instead.")
fun withExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>): DriverParameters = copy(extraCordappPackagesToScan = extraCordappPackagesToScan) fun withExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>): DriverParameters = copy(extraCordappPackagesToScan = extraCordappPackagesToScan)
@ -428,7 +485,7 @@ data class DriverParameters(
fun withCordappsForAllNodes(cordappsForAllNodes: Collection<TestCordapp>?): DriverParameters = copy(cordappsForAllNodes = cordappsForAllNodes) fun withCordappsForAllNodes(cordappsForAllNodes: Collection<TestCordapp>?): DriverParameters = copy(cordappsForAllNodes = cordappsForAllNodes)
fun withDjvmBootstrapSource(djvmBootstrapSource: Path?): DriverParameters = copy(djvmBootstrapSource = djvmBootstrapSource) fun withDjvmBootstrapSource(djvmBootstrapSource: Path?): DriverParameters = copy(djvmBootstrapSource = djvmBootstrapSource)
fun withDjvmCordaSource(djvmCordaSource: List<Path>): DriverParameters = copy(djvmCordaSource = djvmCordaSource) fun withDjvmCordaSource(djvmCordaSource: List<Path>): DriverParameters = copy(djvmCordaSource = djvmCordaSource)
fun withEnvironmentVariables(variables : Map<String, String>): DriverParameters = copy(environmentVariables = variables) fun withEnvironmentVariables(variables: Map<String, String>): DriverParameters = copy(environmentVariables = variables)
fun withAllowHibernateToManageAppSchema(value: Boolean): DriverParameters = copy(allowHibernateToManageAppSchema = value) fun withAllowHibernateToManageAppSchema(value: Boolean): DriverParameters = copy(allowHibernateToManageAppSchema = value)
fun copy( fun copy(
@ -530,4 +587,48 @@ data class DriverParameters(
djvmCordaSource = djvmCordaSource, djvmCordaSource = djvmCordaSource,
environmentVariables = environmentVariables environmentVariables = environmentVariables
) )
// Legacy copy() from v4.5
@Suppress("LongParameterList")
fun copy(isDebug: Boolean,
driverDirectory: Path,
portAllocation: PortAllocation,
debugPortAllocation: PortAllocation,
systemProperties: Map<String, String>,
useTestClock: Boolean,
startNodesInProcess: Boolean,
waitForAllNodesToFinish: Boolean,
notarySpecs: List<NotarySpec>,
extraCordappPackagesToScan: List<String>,
@Suppress("DEPRECATION") jmxPolicy: JmxPolicy,
networkParameters: NetworkParameters,
notaryCustomOverrides: Map<String, Any?>,
inMemoryDB: Boolean,
cordappsForAllNodes: Collection<TestCordapp>?,
djvmBootstrapSource: Path?,
djvmCordaSource: List<Path>,
environmentVariables: Map<String, String>,
allowHibernateToManageAppSchema: Boolean
) = this.copy(
isDebug = isDebug,
driverDirectory = driverDirectory,
portAllocation = portAllocation,
debugPortAllocation = debugPortAllocation,
systemProperties = systemProperties,
useTestClock = useTestClock,
startNodesInProcess = startNodesInProcess,
waitForAllNodesToFinish = waitForAllNodesToFinish,
notarySpecs = notarySpecs,
extraCordappPackagesToScan = extraCordappPackagesToScan,
jmxPolicy = jmxPolicy,
networkParameters = networkParameters,
notaryCustomOverrides = notaryCustomOverrides,
inMemoryDB = inMemoryDB,
cordappsForAllNodes = cordappsForAllNodes,
djvmBootstrapSource = djvmBootstrapSource,
djvmCordaSource = djvmCordaSource,
environmentVariables = environmentVariables,
allowHibernateToManageAppSchema = allowHibernateToManageAppSchema,
premigrateH2Database = true
)
} }

View File

@ -0,0 +1,23 @@
package net.corda.testing.node
import java.io.InputStream
import java.nio.file.Files
import java.nio.file.Path
object DatabaseSnapshot {
private const val previousCordaVersion: String = "4.5.1"
private const val databaseName: String = "persistence.mv.db"
private fun getDatabaseSnapshotStream(): InputStream {
val resourceUri = this::class.java.getResource("/databasesnapshots/${previousCordaVersion}/$databaseName")
return resourceUri.openStream()
}
fun copyDatabaseSnapshot(baseDirectory: Path) {
getDatabaseSnapshotStream().use { stream ->
Files.createDirectories(baseDirectory)
val path = baseDirectory.resolve(databaseName)
Files.copy(stream, path)
}
}
}

View File

@ -48,6 +48,7 @@ import net.corda.testing.internal.configureDatabase
import net.corda.testing.node.internal.* import net.corda.testing.node.internal.*
import net.corda.testing.services.MockAttachmentStorage import net.corda.testing.services.MockAttachmentStorage
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.nio.file.Paths
import java.security.KeyPair import java.security.KeyPair
import java.sql.Connection import java.sql.Connection
import java.time.Clock import java.time.Clock
@ -99,9 +100,17 @@ open class MockServices private constructor(
// TODO: Can we use an X509 principal generator here? // TODO: Can we use an X509 principal generator here?
@JvmStatic @JvmStatic
fun makeTestDataSourceProperties(nodeName: String = SecureHash.randomSHA256().toString()): Properties { fun makeTestDataSourceProperties(nodeName: String = SecureHash.randomSHA256().toString()): Properties {
val dbDir = Paths.get("","build", "mocknetworktestdb", nodeName)
.toAbsolutePath()
val dbPath = dbDir.resolve("persistence")
try {
DatabaseSnapshot.copyDatabaseSnapshot(dbDir)
} catch (ex: java.nio.file.FileAlreadyExistsException) {
DriverDSLImpl.log.warn("Database already exists on disk, not attempting to pre-migrate database.")
}
val props = Properties() val props = Properties()
props.setProperty("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource") props.setProperty("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource")
props.setProperty("dataSource.url", "jdbc:h2:mem:${nodeName}_persistence;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE") props.setProperty("dataSource.url", "jdbc:h2:file:$dbPath;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE")
props.setProperty("dataSource.user", "sa") props.setProperty("dataSource.user", "sa")
props.setProperty("dataSource.password", "") props.setProperty("dataSource.password", "")
return props return props
@ -357,7 +366,6 @@ open class MockServices private constructor(
constructor(cordappPackages: List<String>, initialIdentityName: CordaX500Name, identityService: IdentityService, networkParameters: NetworkParameters) constructor(cordappPackages: List<String>, initialIdentityName: CordaX500Name, identityService: IdentityService, networkParameters: NetworkParameters)
: this(cordappPackages, TestIdentity(initialIdentityName), identityService, networkParameters) : this(cordappPackages, TestIdentity(initialIdentityName), identityService, networkParameters)
constructor(cordappPackages: List<String>, initialIdentityName: CordaX500Name, identityService: IdentityService, networkParameters: NetworkParameters, key: KeyPair) constructor(cordappPackages: List<String>, initialIdentityName: CordaX500Name, identityService: IdentityService, networkParameters: NetworkParameters, key: KeyPair)
: this(cordappPackages, TestIdentity(initialIdentityName, key), identityService, networkParameters) : this(cordappPackages, TestIdentity(initialIdentityName, key), identityService, networkParameters)
@ -428,11 +436,12 @@ open class MockServices private constructor(
private val mockCordappProvider: MockCordappProvider = MockCordappProvider(cordappLoader, attachments).also { private val mockCordappProvider: MockCordappProvider = MockCordappProvider(cordappLoader, attachments).also {
it.start() it.start()
} }
override val transactionVerifierService: TransactionVerifierService get() = InMemoryTransactionVerifierService( override val transactionVerifierService: TransactionVerifierService
numberOfWorkers = 2, get() = InMemoryTransactionVerifierService(
cordappProvider = mockCordappProvider, numberOfWorkers = 2,
attachments = attachments cordappProvider = mockCordappProvider,
) attachments = attachments
)
override val cordappProvider: CordappProvider get() = mockCordappProvider override val cordappProvider: CordappProvider get() = mockCordappProvider
override var networkParametersService: NetworkParametersService = MockNetworkParametersStorage(initialNetworkParameters) override var networkParametersService: NetworkParametersService = MockNetworkParametersStorage(initialNetworkParameters)
override val diagnosticsService: DiagnosticsService = NodeDiagnosticsService() override val diagnosticsService: DiagnosticsService = NodeDiagnosticsService()

View File

@ -50,12 +50,12 @@ data class CustomCordapp(
@VisibleForTesting @VisibleForTesting
internal fun packageAsJar(file: Path) { internal fun packageAsJar(file: Path) {
val classGraph = ClassGraph() val classGraph = ClassGraph()
if(packages.isNotEmpty()){ if (packages.isNotEmpty()) {
classGraph.whitelistPaths(*packages.map { it.replace('.', '/') }.toTypedArray()) classGraph.acceptPaths(*packages.map { it.replace('.', '/') }.toTypedArray())
} }
if (classes.isNotEmpty()) { if (classes.isNotEmpty()) {
classes.forEach { classGraph.addClassLoader(it.classLoader) } classes.forEach { classGraph.addClassLoader(it.classLoader) }
classGraph.whitelistClasses(*classes.map { it.name }.toTypedArray()) classGraph.acceptClasses(*classes.map { it.name }.toTypedArray())
} }
classGraph.enableClassInfo().pooledScan().use { scanResult -> classGraph.enableClassInfo().pooledScan().use { scanResult ->

View File

@ -1,4 +1,5 @@
@file:Suppress("TooManyFunctions", "Deprecation") @file:Suppress("TooManyFunctions", "Deprecation")
package net.corda.testing.node.internal package net.corda.testing.node.internal
import co.paralleluniverse.fibers.instrument.JavaAgent import co.paralleluniverse.fibers.instrument.JavaAgent
@ -52,6 +53,7 @@ import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.millis import net.corda.core.utilities.millis
import net.corda.core.utilities.toHexString
import net.corda.coretesting.internal.stubs.CertificateStoreStubs import net.corda.coretesting.internal.stubs.CertificateStoreStubs
import net.corda.node.NodeRegistrationOption import net.corda.node.NodeRegistrationOption
import net.corda.node.VersionInfo import net.corda.node.VersionInfo
@ -96,6 +98,7 @@ import net.corda.testing.driver.internal.InProcessImpl
import net.corda.testing.driver.internal.NodeHandleInternal import net.corda.testing.driver.internal.NodeHandleInternal
import net.corda.testing.driver.internal.OutOfProcessImpl import net.corda.testing.driver.internal.OutOfProcessImpl
import net.corda.testing.node.ClusterSpec import net.corda.testing.node.ClusterSpec
import net.corda.testing.node.DatabaseSnapshot
import net.corda.testing.node.NotarySpec import net.corda.testing.node.NotarySpec
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -147,8 +150,9 @@ class DriverDSLImpl(
val cordappsForAllNodes: Collection<TestCordappInternal>?, val cordappsForAllNodes: Collection<TestCordappInternal>?,
val djvmBootstrapSource: Path?, val djvmBootstrapSource: Path?,
val djvmCordaSource: List<Path>, val djvmCordaSource: List<Path>,
val environmentVariables : Map<String, String>, val environmentVariables: Map<String, String>,
val allowHibernateToManageAppSchema: Boolean = true val allowHibernateToManageAppSchema: Boolean = true,
val premigrateH2Database: Boolean = true
) : InternalDriverDSL { ) : InternalDriverDSL {
private var _executorService: ScheduledExecutorService? = null private var _executorService: ScheduledExecutorService? = null
@ -156,8 +160,10 @@ class DriverDSLImpl(
private var _shutdownManager: ShutdownManager? = null private var _shutdownManager: ShutdownManager? = null
override val shutdownManager get() = _shutdownManager!! override val shutdownManager get() = _shutdownManager!!
private lateinit var extraCustomCordapps: Set<CustomCordapp> private lateinit var extraCustomCordapps: Set<CustomCordapp>
// Map from a nodes legal name to an observable emitting the number of nodes in its network map. // Map from a nodes legal name to an observable emitting the number of nodes in its network map.
private val networkVisibilityController = NetworkVisibilityController() private val networkVisibilityController = NetworkVisibilityController()
/** /**
* Future which completes when the network map infrastructure is available, whether a local one or one from the CZ. * Future which completes when the network map infrastructure is available, whether a local one or one from the CZ.
* This future acts as a gate to prevent nodes from starting too early. The value of the future is a [LocalNetworkMap] * This future acts as a gate to prevent nodes from starting too early. The value of the future is a [LocalNetworkMap]
@ -192,7 +198,7 @@ class DriverDSLImpl(
} }
private fun NodeConfig.checkAndOverrideForInMemoryDB(): NodeConfig = this.run { private fun NodeConfig.checkAndOverrideForInMemoryDB(): NodeConfig = this.run {
if (inMemoryDB && corda.dataSourceProperties.getProperty("dataSource.url").startsWith("jdbc:h2:")) { if (inMemoryDB && isH2Database(corda)) {
val jdbcUrl = "jdbc:h2:mem:persistence${inMemoryCounter.getAndIncrement()};DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=100" val jdbcUrl = "jdbc:h2:mem:persistence${inMemoryCounter.getAndIncrement()};DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=100"
corda.dataSourceProperties.setProperty("dataSource.url", jdbcUrl) corda.dataSourceProperties.setProperty("dataSource.url", jdbcUrl)
NodeConfig(typesafe + mapOf("dataSourceProperties" to mapOf("dataSource.url" to jdbcUrl))) NodeConfig(typesafe + mapOf("dataSourceProperties" to mapOf("dataSource.url" to jdbcUrl)))
@ -262,6 +268,15 @@ class DriverDSLImpl(
val name = parameters.providedName ?: CordaX500Name("${oneOf(names).organisation}-${p2pAddress.port}", "London", "GB") val name = parameters.providedName ?: CordaX500Name("${oneOf(names).organisation}-${p2pAddress.port}", "London", "GB")
val config = createConfig(name, parameters, p2pAddress) val config = createConfig(name, parameters, p2pAddress)
if (premigrateH2Database && isH2Database(config)) {
if (!inMemoryDB) {
try {
DatabaseSnapshot.copyDatabaseSnapshot(config.corda.baseDirectory)
} catch (ex: java.nio.file.FileAlreadyExistsException) {
log.warn("Database already exists on disk, not attempting to pre-migrate database.")
}
}
}
val registrationFuture = if (compatibilityZone?.rootCert != null) { val registrationFuture = if (compatibilityZone?.rootCert != null) {
// We don't need the network map to be available to be able to register the node // We don't need the network map to be available to be able to register the node
createSchema(config, false).flatMap { startNodeRegistration(it, compatibilityZone.rootCert, compatibilityZone.config()) } createSchema(config, false).flatMap { startNodeRegistration(it, compatibilityZone.rootCert, compatibilityZone.config()) }
@ -270,7 +285,7 @@ class DriverDSLImpl(
} }
return registrationFuture.flatMap { conf -> return registrationFuture.flatMap { conf ->
networkMapAvailability.flatMap {networkMap -> networkMapAvailability.flatMap { networkMap ->
// But starting the node proper does require the network map // But starting the node proper does require the network map
startRegisteredNode(conf, networkMap, parameters, bytemanPort) startRegisteredNode(conf, networkMap, parameters, bytemanPort)
} }
@ -376,9 +391,9 @@ class DriverDSLImpl(
startOutOfProcessMiniNode( startOutOfProcessMiniNode(
config, config,
arrayOf( arrayOf(
"initial-registration", "initial-registration",
"--network-root-truststore=${rootTruststorePath.toAbsolutePath()}", "--network-root-truststore=${rootTruststorePath.toAbsolutePath()}",
"--network-root-truststore-password=$rootTruststorePassword" "--network-root-truststore-password=$rootTruststorePassword"
) )
).map { config } ).map { config }
} }
@ -420,13 +435,13 @@ class DriverDSLImpl(
_shutdownManager = ShutdownManager(executorService) _shutdownManager = ShutdownManager(executorService)
val callerPackage = getCallerPackage().toMutableList() val callerPackage = getCallerPackage().toMutableList()
if(callerPackage.firstOrNull()?.startsWith("net.corda.node") == true) callerPackage.add("net.corda.testing") if (callerPackage.firstOrNull()?.startsWith("net.corda.node") == true) callerPackage.add("net.corda.testing")
extraCustomCordapps = cordappsForPackages(extraCordappPackagesToScan + callerPackage) extraCustomCordapps = cordappsForPackages(extraCordappPackagesToScan + callerPackage)
val notaryInfosFuture = if (compatibilityZone == null) { val notaryInfosFuture = if (compatibilityZone == null) {
// If no CZ is specified then the driver does the generation of the network parameters and the copying of the // If no CZ is specified then the driver does the generation of the network parameters and the copying of the
// node info files. // node info files.
startNotaryIdentityGeneration().map { notaryInfos -> Pair(notaryInfos, LocalNetworkMap(notaryInfos.map{it.second})) } startNotaryIdentityGeneration().map { notaryInfos -> Pair(notaryInfos, LocalNetworkMap(notaryInfos.map { it.second })) }
} else { } else {
// Otherwise it's the CZ's job to distribute thse via the HTTP network map, as that is what the nodes will be expecting. // Otherwise it's the CZ's job to distribute thse via the HTTP network map, as that is what the nodes will be expecting.
val notaryInfosFuture = if (compatibilityZone.rootCert == null) { val notaryInfosFuture = if (compatibilityZone.rootCert == null) {
@ -437,7 +452,7 @@ class DriverDSLImpl(
startAllNotaryRegistrations(compatibilityZone.rootCert, compatibilityZone) startAllNotaryRegistrations(compatibilityZone.rootCert, compatibilityZone)
} }
notaryInfosFuture.map { notaryInfos -> notaryInfosFuture.map { notaryInfos ->
compatibilityZone.publishNotaries(notaryInfos.map{it.second}) compatibilityZone.publishNotaries(notaryInfos.map { it.second })
Pair(notaryInfos, null) Pair(notaryInfos, null)
} }
} }
@ -445,14 +460,15 @@ class DriverDSLImpl(
networkMapAvailability = notaryInfosFuture.map { it.second } networkMapAvailability = notaryInfosFuture.map { it.second }
_notaries = notaryInfosFuture.map { (notaryInfos, localNetworkMap) -> _notaries = notaryInfosFuture.map { (notaryInfos, localNetworkMap) ->
val listOfFutureNodeHandles = startNotaries(notaryInfos.map{it.first}, localNetworkMap, notaryCustomOverrides) val listOfFutureNodeHandles = startNotaries(notaryInfos.map { it.first }, localNetworkMap, notaryCustomOverrides)
notaryInfos.zip(listOfFutureNodeHandles) { (_, notaryInfo), nodeHandlesFuture -> notaryInfos.zip(listOfFutureNodeHandles) { (_, notaryInfo), nodeHandlesFuture ->
NotaryHandle(notaryInfo.identity, notaryInfo.validating, nodeHandlesFuture) NotaryHandle(notaryInfo.identity, notaryInfo.validating, nodeHandlesFuture)
} }
} }
try { try {
_notaries.map { notary -> notary.map { handle -> handle.nodeHandles } }.getOrThrow(notaryHandleTimeout).forEach { future -> future.getOrThrow(notaryHandleTimeout) } _notaries.map { notary -> notary.map { handle -> handle.nodeHandles } }.getOrThrow(notaryHandleTimeout)
} catch(e: NodeListenProcessDeathException) { .forEach { future -> future.getOrThrow(notaryHandleTimeout) }
} catch (e: NodeListenProcessDeathException) {
val message = if (e.causeFromStdError.isNotBlank()) { val message = if (e.causeFromStdError.isNotBlank()) {
"Unable to start notaries. Failed with the following error: ${e.causeFromStdError}" "Unable to start notaries. Failed with the following error: ${e.causeFromStdError}"
} else { } else {
@ -487,7 +503,7 @@ class DriverDSLImpl(
} }
} }
private fun startNotaryIdentityGeneration(): CordaFuture<List<Pair<NodeConfig,NotaryInfo>>> { private fun startNotaryIdentityGeneration(): CordaFuture<List<Pair<NodeConfig, NotaryInfo>>> {
return executorService.fork { return executorService.fork {
notarySpecs.map { spec -> notarySpecs.map { spec ->
val notaryConfig = mapOf("notary" to mapOf("validating" to spec.validating)) val notaryConfig = mapOf("notary" to mapOf("validating" to spec.validating))
@ -537,32 +553,32 @@ class DriverDSLImpl(
spec: NotarySpec, spec: NotarySpec,
rootCert: X509Certificate, rootCert: X509Certificate,
compatibilityZone: CompatibilityZoneParams compatibilityZone: CompatibilityZoneParams
): CordaFuture<Pair<NodeConfig,NotaryInfo>> { ): CordaFuture<Pair<NodeConfig, NotaryInfo>> {
val parameters = NodeParameters(rpcUsers = spec.rpcUsers, verifierType = spec.verifierType, customOverrides = notaryCustomOverrides, maximumHeapSize = spec.maximumHeapSize) val parameters = NodeParameters(rpcUsers = spec.rpcUsers, verifierType = spec.verifierType, customOverrides = notaryCustomOverrides, maximumHeapSize = spec.maximumHeapSize)
return createSchema(createConfig(spec.name, parameters), false).flatMap { config -> return createSchema(createConfig(spec.name, parameters), false).flatMap { config ->
startNodeRegistration(config, rootCert, compatibilityZone.config())}.flatMap { config -> startNodeRegistration(config, rootCert, compatibilityZone.config())
// Node registration only gives us the node CA cert, not the identity cert. That is only created on first }.flatMap { config ->
// startup or when the node is told to just generate its node info file. We do that here. // Node registration only gives us the node CA cert, not the identity cert. That is only created on first
if (startNodesInProcess) { // startup or when the node is told to just generate its node info file. We do that here.
executorService.fork { if (startNodesInProcess) {
val nodeInfo = Node(config.corda, MOCK_VERSION_INFO, initialiseSerialization = false).generateAndSaveNodeInfo() executorService.fork {
Pair(config.withNotaryDefinition(spec.validating), NotaryInfo(nodeInfo.legalIdentities[0], spec.validating)) val nodeInfo = Node(config.corda, MOCK_VERSION_INFO, initialiseSerialization = false).generateAndSaveNodeInfo()
} Pair(config.withNotaryDefinition(spec.validating), NotaryInfo(nodeInfo.legalIdentities[0], spec.validating))
} else { }
// TODO The config we use here is uses a hardocded p2p port which changes when the node is run proper } else {
// This causes two node info files to be generated. // TODO The config we use here is uses a hardocded p2p port which changes when the node is run proper
startOutOfProcessMiniNode(config, arrayOf("generate-node-info")).map { // This causes two node info files to be generated.
// Once done we have to read the signed node info file that's been generated startOutOfProcessMiniNode(config, arrayOf("generate-node-info")).map {
val nodeInfoFile = config.corda.baseDirectory.list { paths -> // Once done we have to read the signed node info file that's been generated
paths.filter { it.fileName.toString().startsWith(NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX) }.findFirst() val nodeInfoFile = config.corda.baseDirectory.list { paths ->
.get() paths.filter { it.fileName.toString().startsWith(NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX) }.findFirst()
} .get()
val nodeInfo = nodeInfoFile.readObject<SignedNodeInfo>().verified()
Pair(config.withNotaryDefinition(spec.validating), NotaryInfo(nodeInfo.legalIdentities[0], spec.validating))
} }
val nodeInfo = nodeInfoFile.readObject<SignedNodeInfo>().verified()
Pair(config.withNotaryDefinition(spec.validating), NotaryInfo(nodeInfo.legalIdentities[0], spec.validating))
} }
} }
}
} }
private fun generateNodeNames(spec: NotarySpec): List<CordaX500Name> { private fun generateNodeNames(spec: NotarySpec): List<CordaX500Name> {
@ -571,7 +587,7 @@ class DriverDSLImpl(
private fun startNotaries(configs: List<NodeConfig>, localNetworkMap: LocalNetworkMap?, customOverrides: Map<String, Any?>): List<CordaFuture<List<NodeHandle>>> { private fun startNotaries(configs: List<NodeConfig>, localNetworkMap: LocalNetworkMap?, customOverrides: Map<String, Any?>): List<CordaFuture<List<NodeHandle>>> {
return notarySpecs.zip(configs).map { (spec, config) -> return notarySpecs.zip(configs).map { (spec, config) ->
when (spec.cluster) { when (spec.cluster) {
null -> startSingleNotary(config, spec, localNetworkMap, customOverrides) null -> startSingleNotary(config, spec, localNetworkMap, customOverrides)
is ClusterSpec.Raft, is ClusterSpec.Raft,
// DummyCluster is used for testing the notary communication path, and it does not matter // DummyCluster is used for testing the notary communication path, and it does not matter
@ -585,13 +601,13 @@ class DriverDSLImpl(
private fun startSingleNotary(config: NodeConfig, spec: NotarySpec, localNetworkMap: LocalNetworkMap?, customOverrides: Map<String, Any?>): CordaFuture<List<NodeHandle>> { private fun startSingleNotary(config: NodeConfig, spec: NotarySpec, localNetworkMap: LocalNetworkMap?, customOverrides: Map<String, Any?>): CordaFuture<List<NodeHandle>> {
val notaryConfig = mapOf("notary" to mapOf("validating" to spec.validating)) val notaryConfig = mapOf("notary" to mapOf("validating" to spec.validating))
return startRegisteredNode( return startRegisteredNode(
config, config,
localNetworkMap, localNetworkMap,
NodeParameters(rpcUsers = spec.rpcUsers, NodeParameters(rpcUsers = spec.rpcUsers,
verifierType = spec.verifierType, verifierType = spec.verifierType,
startInSameProcess = spec.startInProcess, startInSameProcess = spec.startInProcess,
customOverrides = notaryConfig + customOverrides, customOverrides = notaryConfig + customOverrides,
maximumHeapSize = spec.maximumHeapSize) maximumHeapSize = spec.maximumHeapSize)
).map { listOf(it) } ).map { listOf(it) }
} }
@ -758,14 +774,14 @@ class DriverDSLImpl(
} }
val effectiveP2PAddress = config.corda.messagingServerAddress ?: config.corda.p2pAddress val effectiveP2PAddress = config.corda.messagingServerAddress ?: config.corda.p2pAddress
val p2pReadyFuture = nodeMustBeStartedFuture( val p2pReadyFuture = nodeMustBeStartedFuture(
executorService, executorService,
config.corda.baseDirectory / "net.corda.node.Corda.${identifier}.stdout.log", config.corda.baseDirectory / "net.corda.node.Corda.${identifier}.stdout.log",
process process
) { ) {
NodeListenProcessDeathException( NodeListenProcessDeathException(
effectiveP2PAddress, effectiveP2PAddress,
process, process,
(config.corda.baseDirectory / "net.corda.node.Corda.$identifier.stderr.log").readText() (config.corda.baseDirectory / "net.corda.node.Corda.$identifier.stderr.log").readText()
) )
} }
@ -804,6 +820,7 @@ class DriverDSLImpl(
*/ */
inner class LocalNetworkMap(notaryInfos: List<NotaryInfo>) { inner class LocalNetworkMap(notaryInfos: List<NotaryInfo>) {
val networkParametersCopier = NetworkParametersCopier(networkParameters.copy(notaries = notaryInfos)) val networkParametersCopier = NetworkParametersCopier(networkParameters.copy(notaries = notaryInfos))
// TODO: this object will copy NodeInfo files from started nodes to other nodes additional-node-infos/ // TODO: this object will copy NodeInfo files from started nodes to other nodes additional-node-infos/
// This uses the FileSystem and adds a delay (~5 seconds) given by the time we wait before polling the file system. // This uses the FileSystem and adds a delay (~5 seconds) given by the time we wait before polling the file system.
// Investigate whether we can avoid that. // Investigate whether we can avoid that.
@ -832,6 +849,7 @@ class DriverDSLImpl(
private val notaryHandleTimeout = Duration.ofMinutes(1) private val notaryHandleTimeout = Duration.ofMinutes(1)
private val defaultRpcUserList = listOf(InternalUser("default", "default", setOf("ALL")).toConfig().root().unwrapped()) private val defaultRpcUserList = listOf(InternalUser("default", "default", setOf("ALL")).toConfig().root().unwrapped())
private val names = arrayOf(ALICE_NAME, BOB_NAME, DUMMY_BANK_A_NAME) private val names = arrayOf(ALICE_NAME, BOB_NAME, DUMMY_BANK_A_NAME)
/** /**
* A sub-set of permissions that grant most of the essential operations used in the unit/integration tests as well as * A sub-set of permissions that grant most of the essential operations used in the unit/integration tests as well as
* in demo application like NodeExplorer. * in demo application like NodeExplorer.
@ -856,14 +874,14 @@ class DriverDSLImpl(
private const val CORDA_TESTING_ATTRIBUTE = "Corda-Testing" private const val CORDA_TESTING_ATTRIBUTE = "Corda-Testing"
private val CORDAPP_MANIFEST_ATTRIBUTES: List<String> = unmodifiableList(listOf( private val CORDAPP_MANIFEST_ATTRIBUTES: List<String> = unmodifiableList(listOf(
CORDAPP_CONTRACT_NAME, CORDAPP_CONTRACT_NAME,
CORDAPP_CONTRACT_LICENCE, CORDAPP_CONTRACT_LICENCE,
CORDAPP_CONTRACT_VENDOR, CORDAPP_CONTRACT_VENDOR,
CORDAPP_CONTRACT_VERSION, CORDAPP_CONTRACT_VERSION,
CORDAPP_WORKFLOW_NAME, CORDAPP_WORKFLOW_NAME,
CORDAPP_WORKFLOW_LICENCE, CORDAPP_WORKFLOW_LICENCE,
CORDAPP_WORKFLOW_VENDOR, CORDAPP_WORKFLOW_VENDOR,
CORDAPP_WORKFLOW_VERSION CORDAPP_WORKFLOW_VERSION
)) ))
/** /**
@ -938,7 +956,7 @@ class DriverDSLImpl(
maximumHeapSize: String, maximumHeapSize: String,
logLevelOverride: String?, logLevelOverride: String?,
identifier: String, identifier: String,
environmentVariables : Map<String,String>, environmentVariables: Map<String, String>,
extraCmdLineFlag: Array<String> = emptyArray() extraCmdLineFlag: Array<String> = emptyArray()
): Process { ): Process {
log.info("Starting out-of-process Node ${config.corda.myLegalName.organisation}, " + log.info("Starting out-of-process Node ${config.corda.myLegalName.organisation}, " +
@ -979,7 +997,6 @@ class DriverDSLImpl(
else -> "DEBUG" else -> "DEBUG"
} }
val arguments = mutableListOf( val arguments = mutableListOf(
"--base-directory=${config.corda.baseDirectory}", "--base-directory=${config.corda.baseDirectory}",
"--logging-level=$loggingLevel", "--logging-level=$loggingLevel",
@ -1003,11 +1020,11 @@ class DriverDSLImpl(
// The following dependencies are excluded from the classpath of the created JVM, // The following dependencies are excluded from the classpath of the created JVM,
// so that the environment resembles a real one as close as possible. // so that the environment resembles a real one as close as possible.
val cp = ProcessUtilities.defaultClassPath.filter { cpEntry -> val cp = ProcessUtilities.defaultClassPath.filter { cpEntry ->
val cpPathEntry = Paths.get(cpEntry) val cpPathEntry = Paths.get(cpEntry)
cpPathEntry.isRegularFile() cpPathEntry.isRegularFile()
&& !isTestArtifact(cpPathEntry.fileName.toString()) && !isTestArtifact(cpPathEntry.fileName.toString())
&& !cpPathEntry.isExcludedJar && !cpPathEntry.isExcludedJar
} }
return ProcessUtilities.startJavaProcess( return ProcessUtilities.startJavaProcess(
@ -1023,6 +1040,12 @@ class DriverDSLImpl(
) )
} }
private fun isH2Database(config: NodeConfiguration)
= config.dataSourceProperties.getProperty("dataSource.url").startsWith("jdbc:h2:")
private fun isH2Database(config: NodeConfig)
= isH2Database(config.corda)
// Obvious test artifacts. This is NOT intended to be an exhaustive list! // Obvious test artifacts. This is NOT intended to be an exhaustive list!
// It is only intended to remove those FEW jars which BLATANTLY do not // It is only intended to remove those FEW jars which BLATANTLY do not
// belong inside a Corda Node. // belong inside a Corda Node.
@ -1046,12 +1069,13 @@ class DriverDSLImpl(
|| (manifest[TARGET_PLATFORM_VERSION] != null && manifest[MIN_PLATFORM_VERSION] != null) || (manifest[TARGET_PLATFORM_VERSION] != null && manifest[MIN_PLATFORM_VERSION] != null)
} }
private val Path.isExcludedJar: Boolean get() { private val Path.isExcludedJar: Boolean
return JarInputStream(Files.newInputStream(this).buffered()).use { jar -> get() {
val manifest = jar.manifest ?: return false return JarInputStream(Files.newInputStream(this).buffered()).use { jar ->
isCordapp(manifest) || isTestArtifact(manifest) val manifest = jar.manifest ?: return false
isCordapp(manifest) || isTestArtifact(manifest)
}
} }
}
private fun startWebserver(handle: NodeHandleInternal, debugPort: Int?, maximumHeapSize: String): Process { private fun startWebserver(handle: NodeHandleInternal, debugPort: Int?, maximumHeapSize: String): Process {
val className = "net.corda.webserver.WebServer" val className = "net.corda.webserver.WebServer"
@ -1220,8 +1244,8 @@ interface InternalDriverDSL : DriverDSL {
fun shutdown() fun shutdown()
fun startNode( fun startNode(
parameters: NodeParameters = NodeParameters(), parameters: NodeParameters = NodeParameters(),
bytemanPort: Int? = null bytemanPort: Int? = null
): CordaFuture<NodeHandle> ): CordaFuture<NodeHandle>
} }
@ -1268,28 +1292,29 @@ fun <DI : DriverDSL, D : InternalDriverDSL, A> genericDriver(
): A { ): A {
setDriverSerialization().use { _ -> setDriverSerialization().use { _ ->
val driverDsl = driverDslWrapper( val driverDsl = driverDslWrapper(
DriverDSLImpl( DriverDSLImpl(
portAllocation = defaultParameters.portAllocation, portAllocation = defaultParameters.portAllocation,
debugPortAllocation = defaultParameters.debugPortAllocation, debugPortAllocation = defaultParameters.debugPortAllocation,
systemProperties = defaultParameters.systemProperties, systemProperties = defaultParameters.systemProperties,
driverDirectory = defaultParameters.driverDirectory.toAbsolutePath(), driverDirectory = defaultParameters.driverDirectory.toAbsolutePath(),
useTestClock = defaultParameters.useTestClock, useTestClock = defaultParameters.useTestClock,
isDebug = defaultParameters.isDebug, isDebug = defaultParameters.isDebug,
startNodesInProcess = defaultParameters.startNodesInProcess, startNodesInProcess = defaultParameters.startNodesInProcess,
waitForAllNodesToFinish = defaultParameters.waitForAllNodesToFinish, waitForAllNodesToFinish = defaultParameters.waitForAllNodesToFinish,
extraCordappPackagesToScan = @Suppress("DEPRECATION") defaultParameters.extraCordappPackagesToScan, extraCordappPackagesToScan = @Suppress("DEPRECATION") defaultParameters.extraCordappPackagesToScan,
jmxPolicy = defaultParameters.jmxPolicy, jmxPolicy = defaultParameters.jmxPolicy,
notarySpecs = defaultParameters.notarySpecs, notarySpecs = defaultParameters.notarySpecs,
compatibilityZone = null, compatibilityZone = null,
networkParameters = defaultParameters.networkParameters, networkParameters = defaultParameters.networkParameters,
notaryCustomOverrides = defaultParameters.notaryCustomOverrides, notaryCustomOverrides = defaultParameters.notaryCustomOverrides,
inMemoryDB = defaultParameters.inMemoryDB, inMemoryDB = defaultParameters.inMemoryDB,
cordappsForAllNodes = uncheckedCast(defaultParameters.cordappsForAllNodes), cordappsForAllNodes = uncheckedCast(defaultParameters.cordappsForAllNodes),
djvmBootstrapSource = defaultParameters.djvmBootstrapSource, djvmBootstrapSource = defaultParameters.djvmBootstrapSource,
djvmCordaSource = defaultParameters.djvmCordaSource, djvmCordaSource = defaultParameters.djvmCordaSource,
environmentVariables = defaultParameters.environmentVariables, environmentVariables = defaultParameters.environmentVariables,
allowHibernateToManageAppSchema = defaultParameters.allowHibernateToManageAppSchema allowHibernateToManageAppSchema = defaultParameters.allowHibernateToManageAppSchema,
) premigrateH2Database = defaultParameters.premigrateH2Database
)
) )
val shutdownHook = addShutdownHook(driverDsl::shutdown) val shutdownHook = addShutdownHook(driverDsl::shutdown)
try { try {
@ -1324,7 +1349,7 @@ sealed class CompatibilityZoneParams(
) { ) {
abstract fun networkMapURL(): URL abstract fun networkMapURL(): URL
abstract fun doormanURL(): URL abstract fun doormanURL(): URL
abstract fun config() : NetworkServicesConfig abstract fun config(): NetworkServicesConfig
} }
/** /**
@ -1332,18 +1357,18 @@ sealed class CompatibilityZoneParams(
*/ */
class SharedCompatibilityZoneParams( class SharedCompatibilityZoneParams(
private val url: URL, private val url: URL,
private val pnm : UUID?, private val pnm: UUID?,
publishNotaries: (List<NotaryInfo>) -> Unit, publishNotaries: (List<NotaryInfo>) -> Unit,
rootCert: X509Certificate? = null rootCert: X509Certificate? = null
) : CompatibilityZoneParams(publishNotaries, rootCert) { ) : CompatibilityZoneParams(publishNotaries, rootCert) {
val config : NetworkServicesConfig by lazy { val config: NetworkServicesConfig by lazy {
NetworkServicesConfig(url, url, pnm, false) NetworkServicesConfig(url, url, pnm, false)
} }
override fun doormanURL() = url override fun doormanURL() = url
override fun networkMapURL() = url override fun networkMapURL() = url
override fun config() : NetworkServicesConfig = config override fun config(): NetworkServicesConfig = config
} }
/** /**
@ -1352,17 +1377,17 @@ class SharedCompatibilityZoneParams(
class SplitCompatibilityZoneParams( class SplitCompatibilityZoneParams(
private val doormanURL: URL, private val doormanURL: URL,
private val networkMapURL: URL, private val networkMapURL: URL,
private val pnm : UUID?, private val pnm: UUID?,
publishNotaries: (List<NotaryInfo>) -> Unit, publishNotaries: (List<NotaryInfo>) -> Unit,
rootCert: X509Certificate? = null rootCert: X509Certificate? = null
) : CompatibilityZoneParams(publishNotaries, rootCert) { ) : CompatibilityZoneParams(publishNotaries, rootCert) {
val config : NetworkServicesConfig by lazy { val config: NetworkServicesConfig by lazy {
NetworkServicesConfig(doormanURL, networkMapURL, pnm, false) NetworkServicesConfig(doormanURL, networkMapURL, pnm, false)
} }
override fun doormanURL() = doormanURL override fun doormanURL() = doormanURL
override fun networkMapURL() = networkMapURL override fun networkMapURL() = networkMapURL
override fun config() : NetworkServicesConfig = config override fun config(): NetworkServicesConfig = config
} }
@Suppress("LongParameterList") @Suppress("LongParameterList")
@ -1387,6 +1412,7 @@ fun <A> internalDriver(
djvmCordaSource: List<Path> = emptyList(), djvmCordaSource: List<Path> = emptyList(),
environmentVariables: Map<String, String> = emptyMap(), environmentVariables: Map<String, String> = emptyMap(),
allowHibernateToManageAppSchema: Boolean = true, allowHibernateToManageAppSchema: Boolean = true,
premigrateH2Database: Boolean = true,
dsl: DriverDSLImpl.() -> A dsl: DriverDSLImpl.() -> A
): A { ): A {
return genericDriver( return genericDriver(
@ -1410,15 +1436,21 @@ fun <A> internalDriver(
djvmBootstrapSource = djvmBootstrapSource, djvmBootstrapSource = djvmBootstrapSource,
djvmCordaSource = djvmCordaSource, djvmCordaSource = djvmCordaSource,
environmentVariables = environmentVariables, environmentVariables = environmentVariables,
allowHibernateToManageAppSchema = allowHibernateToManageAppSchema allowHibernateToManageAppSchema = allowHibernateToManageAppSchema,
premigrateH2Database = premigrateH2Database
), ),
coerce = { it }, coerce = { it },
dsl = dsl dsl = dsl
) )
} }
val DIRECTORY_TIMESTAMP_FORMAT: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss.SSS").withZone(UTC)
private val directoryRandom = Random()
fun getTimestampAsDirectoryName(): String { fun getTimestampAsDirectoryName(): String {
return DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss.SSS").withZone(UTC).format(Instant.now()) val base = DIRECTORY_TIMESTAMP_FORMAT.format(Instant.now())
// Introduce some randomness so starting two nodes in the same ms doesn't use the same path
val random = directoryRandom.nextLong().toBigInteger().toByteArray().toHexString()
return "$base-$random"
} }
fun writeConfig(path: Path, filename: String, config: Config) { fun writeConfig(path: Path, filename: String, config: Config) {

View File

@ -9,7 +9,7 @@ import net.corda.core.node.NetworkParameters
import net.corda.core.node.NotaryInfo import net.corda.core.node.NotaryInfo
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.nodeapi.internal.network.SignedNetworkParameters import net.corda.nodeapi.internal.network.SignedNetworkParameters
import net.corda.nodeapi.internal.network.verifiedNetworkMapCert import net.corda.nodeapi.internal.network.verifiedNetworkParametersCert
import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.ALICE_NAME import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.TestIdentity import net.corda.testing.core.TestIdentity
@ -30,7 +30,7 @@ class MockNetworkParametersStorage(private var currentParameters: NetworkParamet
} }
override fun setCurrentParameters(currentSignedParameters: SignedDataWithCert<NetworkParameters>, trustRoot: X509Certificate) { override fun setCurrentParameters(currentSignedParameters: SignedDataWithCert<NetworkParameters>, trustRoot: X509Certificate) {
setCurrentParametersUnverified(currentSignedParameters.verifiedNetworkMapCert(trustRoot)) setCurrentParametersUnverified(currentSignedParameters.verifiedNetworkParametersCert(trustRoot))
} }
override fun lookupSigned(hash: SecureHash): SignedDataWithCert<NetworkParameters>? { override fun lookupSigned(hash: SecureHash): SignedDataWithCert<NetworkParameters>? {

View File

@ -56,7 +56,7 @@ data class TestCordappImpl(val scanPackage: String, override val config: Map<Str
private fun findRootPaths(scanPackage: String): Set<Path> { private fun findRootPaths(scanPackage: String): Set<Path> {
return packageToRootPaths.computeIfAbsent(scanPackage) { return packageToRootPaths.computeIfAbsent(scanPackage) {
val classGraph = ClassGraph().whitelistPaths(scanPackage.replace('.', '/')) val classGraph = ClassGraph().acceptPaths(scanPackage.replace('.', '/'))
classGraph.pooledScan().use { scanResult -> classGraph.pooledScan().use { scanResult ->
scanResult.allResources scanResult.allResources
.asSequence() .asSequence()

View File

@ -252,4 +252,6 @@ fun isLocalPortBound(port: Int): Boolean {
// Failed to open server socket means that it is already bound by someone // Failed to open server socket means that it is already bound by someone
true true
} }
} }
val IS_OPENJ9 = System.getProperty("java.vm.name").toLowerCase().contains("openj9")

View File

@ -38,6 +38,8 @@ public class InteractiveShellJavaTest {
// should guarantee that FlowA will have synthetic method to access this field // should guarantee that FlowA will have synthetic method to access this field
private static final String synthetic = "synth"; private static final String synthetic = "synth";
private static final boolean IS_OPENJ9 = System.getProperty("java.vm.name").toLowerCase().contains("openj9");
abstract static class StringFlow extends FlowLogic<String> { abstract static class StringFlow extends FlowLogic<String> {
abstract String getA(); abstract String getA();
} }
@ -183,8 +185,10 @@ public class InteractiveShellJavaTest {
@Test @Test
public void flowStartSimple() throws InteractiveShell.NoApplicableConstructor { public void flowStartSimple() throws InteractiveShell.NoApplicableConstructor {
check("a: Hi there", "Hi there", FlowA.class); check("a: Hi there", "Hi there", FlowA.class);
check("b: 12", "12", FlowA.class); if (!IS_OPENJ9) {
check("b: 12, c: Yo", "12Yo", FlowA.class); check("b: 12", "12", FlowA.class);
check("b: 12, c: Yo", "12Yo", FlowA.class);
}
} }
@Test @Test
@ -210,11 +214,13 @@ public class InteractiveShellJavaTest {
@Test @Test
public void flowStartWithArrayType() throws InteractiveShell.NoApplicableConstructor { public void flowStartWithArrayType() throws InteractiveShell.NoApplicableConstructor {
check( if (!IS_OPENJ9) {
"b: [ One, Two, Three, Four ]", check(
"One+Two+Three+Four", "b: [ One, Two, Three, Four ]",
FlowA.class "One+Two+Three+Four",
); FlowA.class
);
}
} }
@Test @Test