mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Merge remote-tracking branch 'origin/release/os/4.6' into rni/notick/46-47-merge-2020-09-04
This commit is contained in:
commit
0c16957622
49
.ci/dev/open-j9/Jenkinsfile
vendored
Normal file
49
.ci/dev/open-j9/Jenkinsfile
vendored
Normal 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 */
|
||||
}
|
||||
}
|
||||
}
|
@ -16,11 +16,11 @@ guavaVersion=28.0-jre
|
||||
# Quasar version to use with Java 8:
|
||||
quasarVersion=0.7.13_r3
|
||||
# Quasar version to use with Java 11:
|
||||
quasarVersion11=0.8.0_r3
|
||||
quasarVersion11=0.8.1_r3
|
||||
jdkClassifier11=jdk11
|
||||
proguardVersion=6.1.1
|
||||
bouncycastleVersion=1.66
|
||||
classgraphVersion=4.8.78
|
||||
classgraphVersion=4.8.89
|
||||
disruptorVersion=3.4.2
|
||||
typesafeConfigVersion=1.3.4
|
||||
jsr305Version=3.0.2
|
||||
|
@ -18,6 +18,8 @@ import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.driver.DriverParameters
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.internal.IS_OPENJ9
|
||||
import org.junit.Assume
|
||||
import org.junit.Test
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
@ -27,6 +29,7 @@ class FlowSleepTest {
|
||||
|
||||
@Test(timeout = 300_000)
|
||||
fun `flow can sleep`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9)
|
||||
driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) {
|
||||
val alice = startNode(providedName = ALICE_NAME).getOrThrow()
|
||||
val (start, finish) = alice.rpc.startFlow(::SleepyFlow).returnValue.getOrThrow(1.minutes)
|
||||
@ -52,6 +55,7 @@ class FlowSleepTest {
|
||||
|
||||
@Test(timeout = 300_000)
|
||||
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
|
||||
driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) {
|
||||
val (alice, bob) = listOf(ALICE_NAME, BOB_NAME)
|
||||
|
@ -35,6 +35,8 @@ import org.bouncycastle.asn1.x9.X9ObjectIdentifiers
|
||||
import org.bouncycastle.crypto.CryptoServicesRegistrar
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
|
||||
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.BCRSAPublicKey
|
||||
import org.bouncycastle.jce.ECNamedCurveTable
|
||||
@ -308,11 +310,11 @@ object Crypto {
|
||||
fun decodePrivateKey(encodedKey: ByteArray): PrivateKey {
|
||||
val keyInfo = PrivateKeyInfo.getInstance(encodedKey)
|
||||
if (keyInfo.privateKeyAlgorithm.algorithm == ASN1ObjectIdentifier(CordaOID.ALIAS_PRIVATE_KEY)) {
|
||||
return decodeAliasPrivateKey(keyInfo)
|
||||
return convertIfBCEdDSAPrivateKey(decodeAliasPrivateKey(keyInfo))
|
||||
}
|
||||
val signatureScheme = findSignatureScheme(keyInfo.privateKeyAlgorithm)
|
||||
val keyFactory = keyFactory(signatureScheme)
|
||||
return keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey))
|
||||
return convertIfBCEdDSAPrivateKey(keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)))
|
||||
}
|
||||
|
||||
@DeleteForDJVM
|
||||
@ -354,7 +356,7 @@ object Crypto {
|
||||
}
|
||||
try {
|
||||
val keyFactory = keyFactory(signatureScheme)
|
||||
return keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey))
|
||||
return convertIfBCEdDSAPrivateKey(keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)))
|
||||
} catch (ikse: InvalidKeySpecException) {
|
||||
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)
|
||||
@ -373,7 +375,7 @@ object Crypto {
|
||||
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(encodedKey)
|
||||
val signatureScheme = findSignatureScheme(subjectPublicKeyInfo.algorithm)
|
||||
val keyFactory = keyFactory(signatureScheme)
|
||||
return keyFactory.generatePublic(X509EncodedKeySpec(encodedKey))
|
||||
return convertIfBCEdDSAPublicKey(keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -408,7 +410,7 @@ object Crypto {
|
||||
}
|
||||
try {
|
||||
val keyFactory = keyFactory(signatureScheme)
|
||||
return keyFactory.generatePublic(X509EncodedKeySpec(encodedKey))
|
||||
return convertIfBCEdDSAPublicKey(keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)))
|
||||
} catch (ikse: InvalidKeySpecException) {
|
||||
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)
|
||||
@ -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.
|
||||
* @param key a public key.
|
||||
@ -1015,6 +1031,7 @@ object Crypto {
|
||||
is BCSphincs256PublicKey -> key
|
||||
is EdDSAPublicKey -> key
|
||||
is CompositeKey -> key
|
||||
is BCEdDSAPublicKey -> convertIfBCEdDSAPublicKey(key)
|
||||
else -> decodePublicKey(key.encoded)
|
||||
}
|
||||
}
|
||||
@ -1035,6 +1052,7 @@ object Crypto {
|
||||
is BCRSAPrivateKey -> key
|
||||
is BCSphincs256PrivateKey -> key
|
||||
is EdDSAPrivateKey -> key
|
||||
is BCEdDSAPrivateKey -> convertIfBCEdDSAPrivateKey(key)
|
||||
else -> decodePrivateKey(key.encoded)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
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
|
||||
owasp.failOnError=false
|
||||
owasp.failBuildOnCVSS=11.0
|
||||
|
@ -50,10 +50,13 @@ import net.corda.nodeapi.internal.crypto.loadOrCreateKeyStore
|
||||
import net.corda.nodeapi.internal.crypto.save
|
||||
import net.corda.nodeapi.internal.crypto.toBc
|
||||
import net.corda.nodeapi.internal.crypto.x509
|
||||
import net.corda.testing.internal.IS_OPENJ9
|
||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.bouncycastle.asn1.x509.*
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.edec.BCEdDSAPrivateKey
|
||||
import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PrivateKey
|
||||
import org.junit.Assume
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
@ -374,6 +377,7 @@ class X509UtilitiesTest {
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `create server cert and use in OpenSSL channel`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9)
|
||||
val sslConfig = CertificateStoreStubs.P2P.withCertificatesDirectory(tempFolder.root.toPath(), keyStorePassword = "serverstorepass")
|
||||
|
||||
val (rootCa, intermediateCa) = createDevIntermediateCaCertPath()
|
||||
@ -446,7 +450,9 @@ class X509UtilitiesTest {
|
||||
private fun <U, C> getCorrectKeyFromKeystore(signatureScheme: SignatureScheme, uncastedClass: Class<U>, castedClass: Class<C>) {
|
||||
val keyPair = generateKeyPair(signatureScheme)
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,16 @@ fun createDevNetworkMapCa(rootCa: CertificateAndKeyPair = DEV_ROOT_CA): Certific
|
||||
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
|
||||
* [CordaX500Name] as the cert subject.
|
||||
|
@ -463,12 +463,18 @@ fun Kryo.serializationContext(): SerializeAsTokenContext? = context.get(serializ
|
||||
class ThrowableSerializer<T>(kryo: Kryo, type: Class<T>) : Serializer<Throwable>(false, true) {
|
||||
|
||||
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 sentinelValue = let {
|
||||
val sentinelField = Throwable::class.java.getDeclaredField("SUPPRESSED_SENTINEL")
|
||||
sentinelField.isAccessible = true
|
||||
sentinelField.get(null)
|
||||
if (!IS_OPENJ9) {
|
||||
val sentinelField = Throwable::class.java.getDeclaredField("SUPPRESSED_SENTINEL")
|
||||
sentinelField.isAccessible = true
|
||||
sentinelField.get(null)
|
||||
}
|
||||
else {
|
||||
Collections.EMPTY_LIST
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -30,7 +30,9 @@ import net.corda.testing.core.DummyCommandData
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.driver.DriverParameters
|
||||
import net.corda.testing.driver.driver
|
||||
import org.apache.commons.lang3.SystemUtils
|
||||
import org.hibernate.exception.ConstraintViolationException
|
||||
import org.junit.Assume
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.lang.RuntimeException
|
||||
@ -315,6 +317,8 @@ class FlowEntityManagerTest : AbstractFlowEntityManagerTest() {
|
||||
|
||||
@Test(timeout = 300_000)
|
||||
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
|
||||
StaffedFlowHospital.onFlowDischarged.add { _, _ -> ++counter }
|
||||
driver(DriverParameters(startNodesInProcess = true)) {
|
||||
|
@ -50,7 +50,8 @@ class H2SecurityTests {
|
||||
inMemoryDB = false,
|
||||
startNodesInProcess = false,
|
||||
notarySpecs = emptyList(),
|
||||
cordappsForAllNodes = emptyList()
|
||||
cordappsForAllNodes = emptyList(),
|
||||
premigrateH2Database = false
|
||||
)) {
|
||||
val port = getFreePort()
|
||||
startNode(customOverrides = mapOf(h2AddressKey to "localhost:$port", dbPasswordKey to "x")).getOrThrow()
|
||||
@ -71,7 +72,8 @@ class H2SecurityTests {
|
||||
inMemoryDB = false,
|
||||
startNodesInProcess = false,
|
||||
notarySpecs = emptyList(),
|
||||
cordappsForAllNodes = listOf(enclosedCordapp())
|
||||
cordappsForAllNodes = listOf(enclosedCordapp()),
|
||||
premigrateH2Database = false
|
||||
)) {
|
||||
val port = getFreePort()
|
||||
val nodeHandle = startNode(rpcUsers = listOf(user), customOverrides = mapOf(h2AddressKey to "localhost:$port",
|
||||
|
@ -62,7 +62,7 @@ class NonDeterministicContractVerifyTest {
|
||||
.returnValue.getOrThrow()
|
||||
}
|
||||
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()
|
||||
}
|
||||
assertThat(ex)
|
||||
.hasMessageMatching("^NoSuchMethodError: .*\\Qsandbox.java.util.UUID.randomUUID()\\E.*\$")
|
||||
.hasMessageMatching("^NoSuchMethodError: .*[\\Qsandbox.java.util.UUID.randomUUID()\\E|\\Qsandbox/java/util/UUID/randomUUID()\\E].*\$")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,8 @@ class LargeTransactionsTest {
|
||||
driver(DriverParameters(
|
||||
startNodesInProcess = true,
|
||||
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 (alice, _) = listOf(ALICE_NAME, BOB_NAME).map { startNode(providedName = it, rpcUsers = listOf(rpcUser)) }.transpose().getOrThrow()
|
||||
|
@ -19,7 +19,6 @@ import net.corda.node.utilities.AppendOnlyPersistentMap
|
||||
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
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.persistence.CordaPersistence
|
||||
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
|
||||
@ -86,7 +85,7 @@ class DBNetworkParametersStorage(
|
||||
|
||||
override fun saveParameters(signedNetworkParameters: SignedNetworkParameters) {
|
||||
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
|
||||
log.trace { "Parameters to save $networkParameters with hash $hash" }
|
||||
database.transaction {
|
||||
|
@ -348,7 +348,7 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths:
|
||||
val cordappElement = cordappJarPath.url.toString()
|
||||
logger.info("Scanning CorDapp in $cordappElement")
|
||||
val scanResult = ClassGraph()
|
||||
.filterClasspathElements { elt -> elt == cordappElement }
|
||||
.filterClasspathElementsByURL { elt -> elt == cordappJarPath.url }
|
||||
.overrideClassLoaders(appClassLoader)
|
||||
.ignoreParentClassLoaders()
|
||||
.enableAllInfo()
|
||||
|
@ -42,12 +42,14 @@ import net.corda.testing.core.*
|
||||
import net.corda.testing.dsl.LedgerDSL
|
||||
import net.corda.testing.dsl.TestLedgerDSLInterpreter
|
||||
import net.corda.testing.dsl.TestTransactionDSLInterpreter
|
||||
import net.corda.testing.internal.IS_OPENJ9
|
||||
import net.corda.testing.internal.LogHelper
|
||||
import net.corda.testing.internal.vault.VaultFiller
|
||||
import net.corda.testing.node.internal.*
|
||||
import net.corda.testing.node.ledger
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
import org.junit.Assume
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@ -211,6 +213,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `shutdown and restore`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9)
|
||||
mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP))
|
||||
val notaryNode = mockNet.defaultNotaryNode
|
||||
val notary = mockNet.defaultNotaryIdentity
|
||||
|
@ -2,16 +2,23 @@ package net.corda.node.services.network
|
||||
|
||||
import com.google.common.jimfs.Configuration
|
||||
import com.google.common.jimfs.Jimfs
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.utilities.days
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.coretesting.internal.DEV_INTERMEDIATE_CA
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.node.internal.NetworkParametersReader
|
||||
import net.corda.nodeapi.internal.network.*
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
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 org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
@ -21,6 +28,7 @@ import org.junit.Test
|
||||
import java.net.URL
|
||||
import java.nio.file.FileSystem
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
@ -84,4 +92,23 @@ class NetworkParametersReaderTest {
|
||||
val parameters = inByteArray.deserialize<SignedNetworkParameters>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
@ -54,6 +54,7 @@ import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.dummyCommand
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.flows.registerCordappFlowFactory
|
||||
import net.corda.testing.internal.IS_OPENJ9
|
||||
import net.corda.testing.internal.LogHelper
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.MessageTransfer
|
||||
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.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assume
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import rx.Notification
|
||||
@ -82,6 +84,7 @@ import java.sql.SQLTransientConnectionException
|
||||
import java.time.Clock
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.TimeoutException
|
||||
import java.util.function.Predicate
|
||||
@ -384,6 +387,7 @@ class FlowFrameworkTests {
|
||||
|
||||
@Test(timeout = 300_000)
|
||||
fun `Flow metadata finish time is set in database when the flow finishes`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9)
|
||||
val terminationSignal = Semaphore(0)
|
||||
val clientId = UUID.randomUUID().toString()
|
||||
val flow = aliceNode.services.startFlowWithClientId(clientId, NoOpFlow(terminateUponSignal = terminationSignal))
|
||||
@ -397,7 +401,7 @@ class FlowFrameworkTests {
|
||||
aliceNode.database.transaction {
|
||||
val metadata = session.find(DBCheckpointStorage.DBFlowMetadata::class.java, flow.id.uuid.toString())
|
||||
assertNotNull(metadata.finishInstant)
|
||||
assertTrue(metadata.finishInstant!! >= metadata.startInstant)
|
||||
assertTrue(metadata.finishInstant!!.truncatedTo(ChronoUnit.MILLIS) >= metadata.startInstant.truncatedTo(ChronoUnit.MILLIS))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.time.Instant
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.Executors
|
||||
@ -118,7 +119,8 @@ class FlowMetadataRecordingTest {
|
||||
assertThat(it.launchingCordapp).contains("custom-cordapp")
|
||||
assertEquals(PLATFORM_VERSION, it.platformVersion)
|
||||
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)
|
||||
assertNull(it.finishInstant)
|
||||
}
|
||||
@ -159,7 +161,8 @@ class FlowMetadataRecordingTest {
|
||||
assertThat(it.launchingCordapp).contains("custom-cordapp")
|
||||
assertEquals(PLATFORM_VERSION, it.platformVersion)
|
||||
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)
|
||||
assertNull(it.finishInstant)
|
||||
}
|
||||
@ -261,7 +264,8 @@ class FlowMetadataRecordingTest {
|
||||
assertThat(it.launchingCordapp).contains("custom-cordapp")
|
||||
assertEquals(8, it.platformVersion)
|
||||
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)
|
||||
assertNull(it.finishInstant)
|
||||
}
|
||||
@ -309,7 +313,8 @@ class FlowMetadataRecordingTest {
|
||||
assertThat(it.launchingCordapp).contains("custom-cordapp")
|
||||
assertEquals(PLATFORM_VERSION, it.platformVersion)
|
||||
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)
|
||||
assertNull(it.finishInstant)
|
||||
}
|
||||
@ -364,7 +369,8 @@ class FlowMetadataRecordingTest {
|
||||
assertThat(it.launchingCordapp).contains("custom-cordapp")
|
||||
assertEquals(PLATFORM_VERSION, it.platformVersion)
|
||||
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)
|
||||
assertNull(it.finishInstant)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import net.corda.node.services.messaging.Message
|
||||
import net.corda.node.services.persistence.DBTransactionStorage
|
||||
import net.corda.nodeapi.internal.persistence.contextTransaction
|
||||
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.MessagingServiceSpy
|
||||
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.junit.After
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Assume
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.sql.SQLException
|
||||
@ -129,6 +131,7 @@ class RetryFlowMockTest {
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `Early end session message does not hang receiving flow`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9)
|
||||
val partyB = nodeB.info.legalIdentities.first()
|
||||
assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy {
|
||||
nodeA.startFlow(UnbalancedSendAndReceiveFlow(partyB)).getOrThrow(20.seconds)
|
||||
|
@ -35,6 +35,7 @@ import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.IS_OPENJ9
|
||||
import net.corda.testing.internal.LogHelper
|
||||
import net.corda.testing.internal.vault.*
|
||||
import net.corda.testing.node.MockServices
|
||||
@ -468,6 +469,7 @@ class NodeVaultServiceTest {
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `unconsumedStatesForSpending from two issuer parties`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
|
||||
database.transaction {
|
||||
vaultFiller.fillWithSomeTestCash(100.DOLLARS, issuerServices, 1, DUMMY_CASH_ISSUER)
|
||||
vaultFiller.fillWithSomeTestCash(100.DOLLARS, bocServices, 1, BOC.ref(1))
|
||||
|
@ -25,15 +25,20 @@ import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetworkParameters
|
||||
import net.corda.testing.node.StartedMockNode
|
||||
import net.corda.testing.node.internal.cordappsForPackages
|
||||
import org.apache.commons.lang3.SystemUtils
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Assume
|
||||
import org.junit.BeforeClass
|
||||
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.Entity
|
||||
import javax.persistence.Index
|
||||
import javax.persistence.Table
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@DisabledOnJre(JRE.JAVA_11)
|
||||
class VaultQueryJoinTest {
|
||||
companion object {
|
||||
private var mockNetwork: MockNetwork? = null
|
||||
@ -46,6 +51,7 @@ class VaultQueryJoinTest {
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setup() {
|
||||
Assume.assumeTrue(!SystemUtils.IS_JAVA_11)
|
||||
mockNetwork = MockNetwork(
|
||||
MockNetworkParameters(
|
||||
cordappsForAllNodes = cordappsForPackages(
|
||||
|
@ -32,6 +32,7 @@ import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
||||
import net.corda.nodeapi.internal.persistence.DatabaseTransaction
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.IS_OPENJ9
|
||||
import net.corda.testing.internal.chooseIdentity
|
||||
import net.corda.testing.internal.configureDatabase
|
||||
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 org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatCode
|
||||
import org.junit.Assume
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
@ -1689,6 +1691,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
// pagination: invalid page number
|
||||
@Test(timeout=300_000)
|
||||
fun `invalid page number`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
|
||||
expectedEx.expect(VaultQueryException::class.java)
|
||||
expectedEx.expectMessage("Page specification: invalid page number")
|
||||
|
||||
@ -2235,6 +2238,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `unconsumed fungible states for owners`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
|
||||
database.transaction {
|
||||
vaultFillerCashNotary.fillWithSomeTestCash(100.DOLLARS, notaryServices, 1, DUMMY_CASH_ISSUER)
|
||||
vaultFiller.fillWithSomeTestCash(100.DOLLARS, notaryServices, 1, MEGA_CORP.ref(0), MEGA_CORP)
|
||||
@ -2289,6 +2293,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `unconsumed cash balances for all currencies`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
|
||||
database.transaction {
|
||||
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)
|
||||
@ -2471,6 +2476,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
// specifying Query on Linear state attributes
|
||||
@Test(timeout=300_000)
|
||||
fun `unconsumed linear heads for linearId between two timestamps`() {
|
||||
Assume.assumeTrue(!IS_OPENJ9) // openj9 OOM issue
|
||||
database.transaction {
|
||||
val start = services.clock.instant()
|
||||
vaultFiller.fillWithSomeTestLinearStates(1, "TEST")
|
||||
@ -2776,6 +2782,8 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
}
|
||||
}
|
||||
|
||||
//linus one OOM issue
|
||||
@Ignore
|
||||
@Test(timeout=300_000)
|
||||
fun `record a transaction with number of inputs greater than vault page size`() {
|
||||
val notary = dummyNotary
|
||||
|
@ -1,7 +1,9 @@
|
||||
package net.corda.testing.node.internal
|
||||
|
||||
import net.corda.testing.internal.IS_OPENJ9
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.hamcrest.Matchers.matchesPattern
|
||||
import org.junit.Assume
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
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"
|
||||
|
||||
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 = "^$"
|
||||
|
||||
@JvmStatic
|
||||
@ -31,7 +33,8 @@ class CordaCliWrapperErrorHandlingTests(val arguments: List<String>, val outputR
|
||||
|
||||
@Test(timeout=300_000)
|
||||
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(
|
||||
className = className,
|
||||
arguments = arguments,
|
||||
|
@ -43,21 +43,28 @@ data class NotaryHandle(val identity: Party, val validating: Boolean, val nodeHa
|
||||
interface NodeHandle : AutoCloseable {
|
||||
/** Get the [NodeInfo] for this node */
|
||||
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
|
||||
* will be added and that will be used.
|
||||
*/
|
||||
val rpc: CordaRPCOps
|
||||
|
||||
/** Get the p2p address for this node **/
|
||||
val p2pAddress: NetworkHostAndPort
|
||||
|
||||
/** Get the rpc address for this node **/
|
||||
val rpcAddress: NetworkHostAndPort
|
||||
|
||||
/** Get the rpc admin address for this node **/
|
||||
val rpcAdminAddress: NetworkHostAndPort
|
||||
|
||||
/** Get the JMX server address for this node, if JMX is enabled **/
|
||||
val jmxAddress: NetworkHostAndPort?
|
||||
|
||||
/** Get a [List] of [User]'s for this node **/
|
||||
val rpcUsers: List<User>
|
||||
|
||||
/** The location of the node's base directory **/
|
||||
val baseDirectory: Path
|
||||
|
||||
@ -67,7 +74,8 @@ interface NodeHandle : AutoCloseable {
|
||||
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. **/
|
||||
@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.
|
||||
* @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,
|
||||
djvmCordaSource = defaultParameters.djvmCordaSource,
|
||||
environmentVariables = defaultParameters.environmentVariables,
|
||||
allowHibernateToManageAppSchema = defaultParameters.allowHibernateToManageAppSchema
|
||||
allowHibernateToManageAppSchema = defaultParameters.allowHibernateToManageAppSchema,
|
||||
premigrateH2Database = defaultParameters.premigrateH2Database
|
||||
),
|
||||
coerce = { it },
|
||||
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 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 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")
|
||||
data class DriverParameters(
|
||||
@ -263,12 +275,13 @@ data class DriverParameters(
|
||||
@Suppress("DEPRECATION") val jmxPolicy: JmxPolicy = JmxPolicy(),
|
||||
val networkParameters: NetworkParameters = testNetworkParameters(notaries = emptyList()),
|
||||
val notaryCustomOverrides: Map<String, Any?> = emptyMap(),
|
||||
val inMemoryDB: Boolean = true,
|
||||
val inMemoryDB: Boolean = false,
|
||||
val cordappsForAllNodes: Collection<TestCordapp>? = null,
|
||||
val djvmBootstrapSource: Path? = null,
|
||||
val djvmCordaSource: List<Path> = emptyList(),
|
||||
val environmentVariables : Map<String, String> = emptyMap(),
|
||||
val allowHibernateToManageAppSchema: Boolean = true
|
||||
val environmentVariables: Map<String, String> = emptyMap(),
|
||||
val allowHibernateToManageAppSchema: Boolean = true,
|
||||
val premigrateH2Database: Boolean = true
|
||||
) {
|
||||
constructor(cordappsForAllNodes: Collection<TestCordapp>) : this(isDebug = false, cordappsForAllNodes = cordappsForAllNodes)
|
||||
|
||||
@ -376,6 +389,49 @@ data class DriverParameters(
|
||||
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(
|
||||
isDebug: Boolean,
|
||||
driverDirectory: Path,
|
||||
@ -417,6 +473,7 @@ data class DriverParameters(
|
||||
fun withStartNodesInProcess(startNodesInProcess: Boolean): DriverParameters = copy(startNodesInProcess = startNodesInProcess)
|
||||
fun withWaitForAllNodesToFinish(waitForAllNodesToFinish: Boolean): DriverParameters = copy(waitForAllNodesToFinish = waitForAllNodesToFinish)
|
||||
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 " +
|
||||
"misleading results in tests. Use withCordappsForAllNodes instead.")
|
||||
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 withDjvmBootstrapSource(djvmBootstrapSource: Path?): DriverParameters = copy(djvmBootstrapSource = djvmBootstrapSource)
|
||||
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 copy(
|
||||
@ -530,4 +587,48 @@ data class DriverParameters(
|
||||
djvmCordaSource = djvmCordaSource,
|
||||
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
|
||||
)
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -48,6 +48,7 @@ import net.corda.testing.internal.configureDatabase
|
||||
import net.corda.testing.node.internal.*
|
||||
import net.corda.testing.services.MockAttachmentStorage
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.nio.file.Paths
|
||||
import java.security.KeyPair
|
||||
import java.sql.Connection
|
||||
import java.time.Clock
|
||||
@ -99,9 +100,17 @@ open class MockServices private constructor(
|
||||
// TODO: Can we use an X509 principal generator here?
|
||||
@JvmStatic
|
||||
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()
|
||||
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.password", "")
|
||||
return props
|
||||
@ -357,7 +366,6 @@ open class MockServices private constructor(
|
||||
constructor(cordappPackages: List<String>, initialIdentityName: CordaX500Name, identityService: IdentityService, networkParameters: NetworkParameters)
|
||||
: this(cordappPackages, TestIdentity(initialIdentityName), identityService, networkParameters)
|
||||
|
||||
|
||||
constructor(cordappPackages: List<String>, initialIdentityName: CordaX500Name, identityService: IdentityService, networkParameters: NetworkParameters, key: KeyPair)
|
||||
: this(cordappPackages, TestIdentity(initialIdentityName, key), identityService, networkParameters)
|
||||
|
||||
@ -428,11 +436,12 @@ open class MockServices private constructor(
|
||||
private val mockCordappProvider: MockCordappProvider = MockCordappProvider(cordappLoader, attachments).also {
|
||||
it.start()
|
||||
}
|
||||
override val transactionVerifierService: TransactionVerifierService get() = InMemoryTransactionVerifierService(
|
||||
numberOfWorkers = 2,
|
||||
cordappProvider = mockCordappProvider,
|
||||
attachments = attachments
|
||||
)
|
||||
override val transactionVerifierService: TransactionVerifierService
|
||||
get() = InMemoryTransactionVerifierService(
|
||||
numberOfWorkers = 2,
|
||||
cordappProvider = mockCordappProvider,
|
||||
attachments = attachments
|
||||
)
|
||||
override val cordappProvider: CordappProvider get() = mockCordappProvider
|
||||
override var networkParametersService: NetworkParametersService = MockNetworkParametersStorage(initialNetworkParameters)
|
||||
override val diagnosticsService: DiagnosticsService = NodeDiagnosticsService()
|
||||
|
@ -50,12 +50,12 @@ data class CustomCordapp(
|
||||
@VisibleForTesting
|
||||
internal fun packageAsJar(file: Path) {
|
||||
val classGraph = ClassGraph()
|
||||
if(packages.isNotEmpty()){
|
||||
classGraph.whitelistPaths(*packages.map { it.replace('.', '/') }.toTypedArray())
|
||||
if (packages.isNotEmpty()) {
|
||||
classGraph.acceptPaths(*packages.map { it.replace('.', '/') }.toTypedArray())
|
||||
}
|
||||
if (classes.isNotEmpty()) {
|
||||
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 ->
|
||||
|
@ -1,4 +1,5 @@
|
||||
@file:Suppress("TooManyFunctions", "Deprecation")
|
||||
|
||||
package net.corda.testing.node.internal
|
||||
|
||||
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.getOrThrow
|
||||
import net.corda.core.utilities.millis
|
||||
import net.corda.core.utilities.toHexString
|
||||
import net.corda.coretesting.internal.stubs.CertificateStoreStubs
|
||||
import net.corda.node.NodeRegistrationOption
|
||||
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.OutOfProcessImpl
|
||||
import net.corda.testing.node.ClusterSpec
|
||||
import net.corda.testing.node.DatabaseSnapshot
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
@ -147,8 +150,9 @@ class DriverDSLImpl(
|
||||
val cordappsForAllNodes: Collection<TestCordappInternal>?,
|
||||
val djvmBootstrapSource: Path?,
|
||||
val djvmCordaSource: List<Path>,
|
||||
val environmentVariables : Map<String, String>,
|
||||
val allowHibernateToManageAppSchema: Boolean = true
|
||||
val environmentVariables: Map<String, String>,
|
||||
val allowHibernateToManageAppSchema: Boolean = true,
|
||||
val premigrateH2Database: Boolean = true
|
||||
) : InternalDriverDSL {
|
||||
|
||||
private var _executorService: ScheduledExecutorService? = null
|
||||
@ -156,8 +160,10 @@ class DriverDSLImpl(
|
||||
private var _shutdownManager: ShutdownManager? = null
|
||||
override val shutdownManager get() = _shutdownManager!!
|
||||
private lateinit var extraCustomCordapps: Set<CustomCordapp>
|
||||
|
||||
// Map from a nodes legal name to an observable emitting the number of nodes in its network map.
|
||||
private val networkVisibilityController = NetworkVisibilityController()
|
||||
|
||||
/**
|
||||
* 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]
|
||||
@ -192,7 +198,7 @@ class DriverDSLImpl(
|
||||
}
|
||||
|
||||
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"
|
||||
corda.dataSourceProperties.setProperty("dataSource.url", 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 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) {
|
||||
// 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()) }
|
||||
@ -270,7 +285,7 @@ class DriverDSLImpl(
|
||||
}
|
||||
|
||||
return registrationFuture.flatMap { conf ->
|
||||
networkMapAvailability.flatMap {networkMap ->
|
||||
networkMapAvailability.flatMap { networkMap ->
|
||||
// But starting the node proper does require the network map
|
||||
startRegisteredNode(conf, networkMap, parameters, bytemanPort)
|
||||
}
|
||||
@ -376,9 +391,9 @@ class DriverDSLImpl(
|
||||
startOutOfProcessMiniNode(
|
||||
config,
|
||||
arrayOf(
|
||||
"initial-registration",
|
||||
"--network-root-truststore=${rootTruststorePath.toAbsolutePath()}",
|
||||
"--network-root-truststore-password=$rootTruststorePassword"
|
||||
"initial-registration",
|
||||
"--network-root-truststore=${rootTruststorePath.toAbsolutePath()}",
|
||||
"--network-root-truststore-password=$rootTruststorePassword"
|
||||
)
|
||||
).map { config }
|
||||
}
|
||||
@ -420,13 +435,13 @@ class DriverDSLImpl(
|
||||
_shutdownManager = ShutdownManager(executorService)
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
// node info files.
|
||||
startNotaryIdentityGeneration().map { notaryInfos -> Pair(notaryInfos, LocalNetworkMap(notaryInfos.map{it.second})) }
|
||||
startNotaryIdentityGeneration().map { notaryInfos -> Pair(notaryInfos, LocalNetworkMap(notaryInfos.map { it.second })) }
|
||||
} 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.
|
||||
val notaryInfosFuture = if (compatibilityZone.rootCert == null) {
|
||||
@ -437,7 +452,7 @@ class DriverDSLImpl(
|
||||
startAllNotaryRegistrations(compatibilityZone.rootCert, compatibilityZone)
|
||||
}
|
||||
notaryInfosFuture.map { notaryInfos ->
|
||||
compatibilityZone.publishNotaries(notaryInfos.map{it.second})
|
||||
compatibilityZone.publishNotaries(notaryInfos.map { it.second })
|
||||
Pair(notaryInfos, null)
|
||||
}
|
||||
}
|
||||
@ -445,14 +460,15 @@ class DriverDSLImpl(
|
||||
networkMapAvailability = notaryInfosFuture.map { it.second }
|
||||
|
||||
_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 ->
|
||||
NotaryHandle(notaryInfo.identity, notaryInfo.validating, nodeHandlesFuture)
|
||||
}
|
||||
}
|
||||
try {
|
||||
_notaries.map { notary -> notary.map { handle -> handle.nodeHandles } }.getOrThrow(notaryHandleTimeout).forEach { future -> future.getOrThrow(notaryHandleTimeout) }
|
||||
} catch(e: NodeListenProcessDeathException) {
|
||||
_notaries.map { notary -> notary.map { handle -> handle.nodeHandles } }.getOrThrow(notaryHandleTimeout)
|
||||
.forEach { future -> future.getOrThrow(notaryHandleTimeout) }
|
||||
} catch (e: NodeListenProcessDeathException) {
|
||||
val message = if (e.causeFromStdError.isNotBlank()) {
|
||||
"Unable to start notaries. Failed with the following error: ${e.causeFromStdError}"
|
||||
} 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 {
|
||||
notarySpecs.map { spec ->
|
||||
val notaryConfig = mapOf("notary" to mapOf("validating" to spec.validating))
|
||||
@ -537,32 +553,32 @@ class DriverDSLImpl(
|
||||
spec: NotarySpec,
|
||||
rootCert: X509Certificate,
|
||||
compatibilityZone: CompatibilityZoneParams
|
||||
): CordaFuture<Pair<NodeConfig,NotaryInfo>> {
|
||||
): CordaFuture<Pair<NodeConfig, NotaryInfo>> {
|
||||
val parameters = NodeParameters(rpcUsers = spec.rpcUsers, verifierType = spec.verifierType, customOverrides = notaryCustomOverrides, maximumHeapSize = spec.maximumHeapSize)
|
||||
return createSchema(createConfig(spec.name, parameters), false).flatMap { config ->
|
||||
startNodeRegistration(config, rootCert, compatibilityZone.config())}.flatMap { config ->
|
||||
// Node registration only gives us the node CA cert, not the identity cert. That is only created on first
|
||||
// startup or when the node is told to just generate its node info file. We do that here.
|
||||
if (startNodesInProcess) {
|
||||
executorService.fork {
|
||||
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
|
||||
// This causes two node info files to be generated.
|
||||
startOutOfProcessMiniNode(config, arrayOf("generate-node-info")).map {
|
||||
// Once done we have to read the signed node info file that's been generated
|
||||
val nodeInfoFile = config.corda.baseDirectory.list { paths ->
|
||||
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))
|
||||
startNodeRegistration(config, rootCert, compatibilityZone.config())
|
||||
}.flatMap { config ->
|
||||
// Node registration only gives us the node CA cert, not the identity cert. That is only created on first
|
||||
// startup or when the node is told to just generate its node info file. We do that here.
|
||||
if (startNodesInProcess) {
|
||||
executorService.fork {
|
||||
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
|
||||
// This causes two node info files to be generated.
|
||||
startOutOfProcessMiniNode(config, arrayOf("generate-node-info")).map {
|
||||
// Once done we have to read the signed node info file that's been generated
|
||||
val nodeInfoFile = config.corda.baseDirectory.list { paths ->
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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>>> {
|
||||
return notarySpecs.zip(configs).map { (spec, config) ->
|
||||
when (spec.cluster) {
|
||||
when (spec.cluster) {
|
||||
null -> startSingleNotary(config, spec, localNetworkMap, customOverrides)
|
||||
is ClusterSpec.Raft,
|
||||
// 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>> {
|
||||
val notaryConfig = mapOf("notary" to mapOf("validating" to spec.validating))
|
||||
return startRegisteredNode(
|
||||
config,
|
||||
localNetworkMap,
|
||||
NodeParameters(rpcUsers = spec.rpcUsers,
|
||||
verifierType = spec.verifierType,
|
||||
startInSameProcess = spec.startInProcess,
|
||||
customOverrides = notaryConfig + customOverrides,
|
||||
maximumHeapSize = spec.maximumHeapSize)
|
||||
config,
|
||||
localNetworkMap,
|
||||
NodeParameters(rpcUsers = spec.rpcUsers,
|
||||
verifierType = spec.verifierType,
|
||||
startInSameProcess = spec.startInProcess,
|
||||
customOverrides = notaryConfig + customOverrides,
|
||||
maximumHeapSize = spec.maximumHeapSize)
|
||||
).map { listOf(it) }
|
||||
}
|
||||
|
||||
@ -758,14 +774,14 @@ class DriverDSLImpl(
|
||||
}
|
||||
val effectiveP2PAddress = config.corda.messagingServerAddress ?: config.corda.p2pAddress
|
||||
val p2pReadyFuture = nodeMustBeStartedFuture(
|
||||
executorService,
|
||||
config.corda.baseDirectory / "net.corda.node.Corda.${identifier}.stdout.log",
|
||||
process
|
||||
executorService,
|
||||
config.corda.baseDirectory / "net.corda.node.Corda.${identifier}.stdout.log",
|
||||
process
|
||||
) {
|
||||
NodeListenProcessDeathException(
|
||||
effectiveP2PAddress,
|
||||
process,
|
||||
(config.corda.baseDirectory / "net.corda.node.Corda.$identifier.stderr.log").readText()
|
||||
effectiveP2PAddress,
|
||||
process,
|
||||
(config.corda.baseDirectory / "net.corda.node.Corda.$identifier.stderr.log").readText()
|
||||
)
|
||||
}
|
||||
|
||||
@ -804,6 +820,7 @@ class DriverDSLImpl(
|
||||
*/
|
||||
inner class LocalNetworkMap(notaryInfos: List<NotaryInfo>) {
|
||||
val networkParametersCopier = NetworkParametersCopier(networkParameters.copy(notaries = notaryInfos))
|
||||
|
||||
// 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.
|
||||
// Investigate whether we can avoid that.
|
||||
@ -832,6 +849,7 @@ class DriverDSLImpl(
|
||||
private val notaryHandleTimeout = Duration.ofMinutes(1)
|
||||
private val defaultRpcUserList = listOf(InternalUser("default", "default", setOf("ALL")).toConfig().root().unwrapped())
|
||||
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
|
||||
* in demo application like NodeExplorer.
|
||||
@ -856,14 +874,14 @@ class DriverDSLImpl(
|
||||
private const val CORDA_TESTING_ATTRIBUTE = "Corda-Testing"
|
||||
|
||||
private val CORDAPP_MANIFEST_ATTRIBUTES: List<String> = unmodifiableList(listOf(
|
||||
CORDAPP_CONTRACT_NAME,
|
||||
CORDAPP_CONTRACT_LICENCE,
|
||||
CORDAPP_CONTRACT_VENDOR,
|
||||
CORDAPP_CONTRACT_VERSION,
|
||||
CORDAPP_WORKFLOW_NAME,
|
||||
CORDAPP_WORKFLOW_LICENCE,
|
||||
CORDAPP_WORKFLOW_VENDOR,
|
||||
CORDAPP_WORKFLOW_VERSION
|
||||
CORDAPP_CONTRACT_NAME,
|
||||
CORDAPP_CONTRACT_LICENCE,
|
||||
CORDAPP_CONTRACT_VENDOR,
|
||||
CORDAPP_CONTRACT_VERSION,
|
||||
CORDAPP_WORKFLOW_NAME,
|
||||
CORDAPP_WORKFLOW_LICENCE,
|
||||
CORDAPP_WORKFLOW_VENDOR,
|
||||
CORDAPP_WORKFLOW_VERSION
|
||||
))
|
||||
|
||||
/**
|
||||
@ -938,7 +956,7 @@ class DriverDSLImpl(
|
||||
maximumHeapSize: String,
|
||||
logLevelOverride: String?,
|
||||
identifier: String,
|
||||
environmentVariables : Map<String,String>,
|
||||
environmentVariables: Map<String, String>,
|
||||
extraCmdLineFlag: Array<String> = emptyArray()
|
||||
): Process {
|
||||
log.info("Starting out-of-process Node ${config.corda.myLegalName.organisation}, " +
|
||||
@ -979,7 +997,6 @@ class DriverDSLImpl(
|
||||
else -> "DEBUG"
|
||||
}
|
||||
|
||||
|
||||
val arguments = mutableListOf(
|
||||
"--base-directory=${config.corda.baseDirectory}",
|
||||
"--logging-level=$loggingLevel",
|
||||
@ -1003,11 +1020,11 @@ class DriverDSLImpl(
|
||||
|
||||
// The following dependencies are excluded from the classpath of the created JVM,
|
||||
// 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)
|
||||
cpPathEntry.isRegularFile()
|
||||
&& !isTestArtifact(cpPathEntry.fileName.toString())
|
||||
&& !cpPathEntry.isExcludedJar
|
||||
&& !isTestArtifact(cpPathEntry.fileName.toString())
|
||||
&& !cpPathEntry.isExcludedJar
|
||||
}
|
||||
|
||||
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!
|
||||
// It is only intended to remove those FEW jars which BLATANTLY do not
|
||||
// belong inside a Corda Node.
|
||||
@ -1046,12 +1069,13 @@ class DriverDSLImpl(
|
||||
|| (manifest[TARGET_PLATFORM_VERSION] != null && manifest[MIN_PLATFORM_VERSION] != null)
|
||||
}
|
||||
|
||||
private val Path.isExcludedJar: Boolean get() {
|
||||
return JarInputStream(Files.newInputStream(this).buffered()).use { jar ->
|
||||
val manifest = jar.manifest ?: return false
|
||||
isCordapp(manifest) || isTestArtifact(manifest)
|
||||
private val Path.isExcludedJar: Boolean
|
||||
get() {
|
||||
return JarInputStream(Files.newInputStream(this).buffered()).use { jar ->
|
||||
val manifest = jar.manifest ?: return false
|
||||
isCordapp(manifest) || isTestArtifact(manifest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startWebserver(handle: NodeHandleInternal, debugPort: Int?, maximumHeapSize: String): Process {
|
||||
val className = "net.corda.webserver.WebServer"
|
||||
@ -1220,8 +1244,8 @@ interface InternalDriverDSL : DriverDSL {
|
||||
fun shutdown()
|
||||
|
||||
fun startNode(
|
||||
parameters: NodeParameters = NodeParameters(),
|
||||
bytemanPort: Int? = null
|
||||
parameters: NodeParameters = NodeParameters(),
|
||||
bytemanPort: Int? = null
|
||||
): CordaFuture<NodeHandle>
|
||||
}
|
||||
|
||||
@ -1268,28 +1292,29 @@ fun <DI : DriverDSL, D : InternalDriverDSL, A> genericDriver(
|
||||
): A {
|
||||
setDriverSerialization().use { _ ->
|
||||
val driverDsl = driverDslWrapper(
|
||||
DriverDSLImpl(
|
||||
portAllocation = defaultParameters.portAllocation,
|
||||
debugPortAllocation = defaultParameters.debugPortAllocation,
|
||||
systemProperties = defaultParameters.systemProperties,
|
||||
driverDirectory = defaultParameters.driverDirectory.toAbsolutePath(),
|
||||
useTestClock = defaultParameters.useTestClock,
|
||||
isDebug = defaultParameters.isDebug,
|
||||
startNodesInProcess = defaultParameters.startNodesInProcess,
|
||||
waitForAllNodesToFinish = defaultParameters.waitForAllNodesToFinish,
|
||||
extraCordappPackagesToScan = @Suppress("DEPRECATION") defaultParameters.extraCordappPackagesToScan,
|
||||
jmxPolicy = defaultParameters.jmxPolicy,
|
||||
notarySpecs = defaultParameters.notarySpecs,
|
||||
compatibilityZone = null,
|
||||
networkParameters = defaultParameters.networkParameters,
|
||||
notaryCustomOverrides = defaultParameters.notaryCustomOverrides,
|
||||
inMemoryDB = defaultParameters.inMemoryDB,
|
||||
cordappsForAllNodes = uncheckedCast(defaultParameters.cordappsForAllNodes),
|
||||
djvmBootstrapSource = defaultParameters.djvmBootstrapSource,
|
||||
djvmCordaSource = defaultParameters.djvmCordaSource,
|
||||
environmentVariables = defaultParameters.environmentVariables,
|
||||
allowHibernateToManageAppSchema = defaultParameters.allowHibernateToManageAppSchema
|
||||
)
|
||||
DriverDSLImpl(
|
||||
portAllocation = defaultParameters.portAllocation,
|
||||
debugPortAllocation = defaultParameters.debugPortAllocation,
|
||||
systemProperties = defaultParameters.systemProperties,
|
||||
driverDirectory = defaultParameters.driverDirectory.toAbsolutePath(),
|
||||
useTestClock = defaultParameters.useTestClock,
|
||||
isDebug = defaultParameters.isDebug,
|
||||
startNodesInProcess = defaultParameters.startNodesInProcess,
|
||||
waitForAllNodesToFinish = defaultParameters.waitForAllNodesToFinish,
|
||||
extraCordappPackagesToScan = @Suppress("DEPRECATION") defaultParameters.extraCordappPackagesToScan,
|
||||
jmxPolicy = defaultParameters.jmxPolicy,
|
||||
notarySpecs = defaultParameters.notarySpecs,
|
||||
compatibilityZone = null,
|
||||
networkParameters = defaultParameters.networkParameters,
|
||||
notaryCustomOverrides = defaultParameters.notaryCustomOverrides,
|
||||
inMemoryDB = defaultParameters.inMemoryDB,
|
||||
cordappsForAllNodes = uncheckedCast(defaultParameters.cordappsForAllNodes),
|
||||
djvmBootstrapSource = defaultParameters.djvmBootstrapSource,
|
||||
djvmCordaSource = defaultParameters.djvmCordaSource,
|
||||
environmentVariables = defaultParameters.environmentVariables,
|
||||
allowHibernateToManageAppSchema = defaultParameters.allowHibernateToManageAppSchema,
|
||||
premigrateH2Database = defaultParameters.premigrateH2Database
|
||||
)
|
||||
)
|
||||
val shutdownHook = addShutdownHook(driverDsl::shutdown)
|
||||
try {
|
||||
@ -1324,7 +1349,7 @@ sealed class CompatibilityZoneParams(
|
||||
) {
|
||||
abstract fun networkMapURL(): URL
|
||||
abstract fun doormanURL(): URL
|
||||
abstract fun config() : NetworkServicesConfig
|
||||
abstract fun config(): NetworkServicesConfig
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1332,18 +1357,18 @@ sealed class CompatibilityZoneParams(
|
||||
*/
|
||||
class SharedCompatibilityZoneParams(
|
||||
private val url: URL,
|
||||
private val pnm : UUID?,
|
||||
private val pnm: UUID?,
|
||||
publishNotaries: (List<NotaryInfo>) -> Unit,
|
||||
rootCert: X509Certificate? = null
|
||||
) : CompatibilityZoneParams(publishNotaries, rootCert) {
|
||||
|
||||
val config : NetworkServicesConfig by lazy {
|
||||
val config: NetworkServicesConfig by lazy {
|
||||
NetworkServicesConfig(url, url, pnm, false)
|
||||
}
|
||||
|
||||
override fun doormanURL() = url
|
||||
override fun networkMapURL() = url
|
||||
override fun config() : NetworkServicesConfig = config
|
||||
override fun config(): NetworkServicesConfig = config
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1352,17 +1377,17 @@ class SharedCompatibilityZoneParams(
|
||||
class SplitCompatibilityZoneParams(
|
||||
private val doormanURL: URL,
|
||||
private val networkMapURL: URL,
|
||||
private val pnm : UUID?,
|
||||
private val pnm: UUID?,
|
||||
publishNotaries: (List<NotaryInfo>) -> Unit,
|
||||
rootCert: X509Certificate? = null
|
||||
) : CompatibilityZoneParams(publishNotaries, rootCert) {
|
||||
val config : NetworkServicesConfig by lazy {
|
||||
val config: NetworkServicesConfig by lazy {
|
||||
NetworkServicesConfig(doormanURL, networkMapURL, pnm, false)
|
||||
}
|
||||
|
||||
override fun doormanURL() = doormanURL
|
||||
override fun networkMapURL() = networkMapURL
|
||||
override fun config() : NetworkServicesConfig = config
|
||||
override fun config(): NetworkServicesConfig = config
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ -1387,6 +1412,7 @@ fun <A> internalDriver(
|
||||
djvmCordaSource: List<Path> = emptyList(),
|
||||
environmentVariables: Map<String, String> = emptyMap(),
|
||||
allowHibernateToManageAppSchema: Boolean = true,
|
||||
premigrateH2Database: Boolean = true,
|
||||
dsl: DriverDSLImpl.() -> A
|
||||
): A {
|
||||
return genericDriver(
|
||||
@ -1410,15 +1436,21 @@ fun <A> internalDriver(
|
||||
djvmBootstrapSource = djvmBootstrapSource,
|
||||
djvmCordaSource = djvmCordaSource,
|
||||
environmentVariables = environmentVariables,
|
||||
allowHibernateToManageAppSchema = allowHibernateToManageAppSchema
|
||||
allowHibernateToManageAppSchema = allowHibernateToManageAppSchema,
|
||||
premigrateH2Database = premigrateH2Database
|
||||
),
|
||||
coerce = { it },
|
||||
dsl = dsl
|
||||
)
|
||||
}
|
||||
|
||||
val DIRECTORY_TIMESTAMP_FORMAT: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss.SSS").withZone(UTC)
|
||||
private val directoryRandom = Random()
|
||||
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) {
|
||||
|
@ -9,7 +9,7 @@ import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.NotaryInfo
|
||||
import net.corda.core.serialization.serialize
|
||||
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.core.ALICE_NAME
|
||||
import net.corda.testing.core.TestIdentity
|
||||
@ -30,7 +30,7 @@ class MockNetworkParametersStorage(private var currentParameters: NetworkParamet
|
||||
}
|
||||
|
||||
override fun setCurrentParameters(currentSignedParameters: SignedDataWithCert<NetworkParameters>, trustRoot: X509Certificate) {
|
||||
setCurrentParametersUnverified(currentSignedParameters.verifiedNetworkMapCert(trustRoot))
|
||||
setCurrentParametersUnverified(currentSignedParameters.verifiedNetworkParametersCert(trustRoot))
|
||||
}
|
||||
|
||||
override fun lookupSigned(hash: SecureHash): SignedDataWithCert<NetworkParameters>? {
|
||||
|
@ -56,7 +56,7 @@ data class TestCordappImpl(val scanPackage: String, override val config: Map<Str
|
||||
|
||||
private fun findRootPaths(scanPackage: String): Set<Path> {
|
||||
return packageToRootPaths.computeIfAbsent(scanPackage) {
|
||||
val classGraph = ClassGraph().whitelistPaths(scanPackage.replace('.', '/'))
|
||||
val classGraph = ClassGraph().acceptPaths(scanPackage.replace('.', '/'))
|
||||
classGraph.pooledScan().use { scanResult ->
|
||||
scanResult.allResources
|
||||
.asSequence()
|
||||
|
Binary file not shown.
@ -252,4 +252,6 @@ fun isLocalPortBound(port: Int): Boolean {
|
||||
// Failed to open server socket means that it is already bound by someone
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val IS_OPENJ9 = System.getProperty("java.vm.name").toLowerCase().contains("openj9")
|
@ -38,6 +38,8 @@ public class InteractiveShellJavaTest {
|
||||
// should guarantee that FlowA will have synthetic method to access this field
|
||||
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 String getA();
|
||||
}
|
||||
@ -183,8 +185,10 @@ public class InteractiveShellJavaTest {
|
||||
@Test
|
||||
public void flowStartSimple() throws InteractiveShell.NoApplicableConstructor {
|
||||
check("a: Hi there", "Hi there", FlowA.class);
|
||||
check("b: 12", "12", FlowA.class);
|
||||
check("b: 12, c: Yo", "12Yo", FlowA.class);
|
||||
if (!IS_OPENJ9) {
|
||||
check("b: 12", "12", FlowA.class);
|
||||
check("b: 12, c: Yo", "12Yo", FlowA.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -210,11 +214,13 @@ public class InteractiveShellJavaTest {
|
||||
|
||||
@Test
|
||||
public void flowStartWithArrayType() throws InteractiveShell.NoApplicableConstructor {
|
||||
check(
|
||||
"b: [ One, Two, Three, Four ]",
|
||||
"One+Two+Three+Four",
|
||||
FlowA.class
|
||||
);
|
||||
if (!IS_OPENJ9) {
|
||||
check(
|
||||
"b: [ One, Two, Three, Four ]",
|
||||
"One+Two+Three+Four",
|
||||
FlowA.class
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user