mirror of
https://github.com/corda/corda.git
synced 2025-03-14 00:06:45 +00:00
Merge remote-tracking branch 'open/master' into os-merge-68145e1
# Conflicts: # node/src/integration-test/kotlin/net/corda/node/flows/FlowOverrideTests.kt # testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt # tools/explorer/src/main/kotlin/net/corda/explorer/ExplorerSimulation.kt
This commit is contained in:
commit
73ca1601fb
@ -149,7 +149,7 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
||||
"is not satisfied. Encumbered states should also be referenced as an encumbrance of another state to form " +
|
||||
"a full cycle. Offending indices $nonMatching", null)
|
||||
|
||||
/**HEAD
|
||||
/**
|
||||
* All encumbered states should be assigned to the same notary. This is due to the fact that multi-notary
|
||||
* transactions are not supported and thus two encumbered states with different notaries cannot be consumed
|
||||
* in the same transaction.
|
||||
|
@ -10,6 +10,7 @@ import net.corda.core.utilities.unwrap
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.driver.DriverParameters
|
||||
import net.corda.testing.driver.NodeParameters
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.internal.IntegrationTest
|
||||
import net.corda.testing.internal.IntegrationTestSchemas
|
||||
@ -55,8 +56,14 @@ class AsymmetricCorDappsTests : IntegrationTest() {
|
||||
@Test
|
||||
fun `no shared cordapps with asymmetric specific classes`() {
|
||||
driver(DriverParameters(startNodesInProcess = false, cordappsForAllNodes = emptySet())) {
|
||||
val nodeA = startNode(providedName = ALICE_NAME, additionalCordapps = setOf(cordappForClasses(Ping::class.java))).getOrThrow()
|
||||
val nodeB = startNode(providedName = BOB_NAME, additionalCordapps = setOf(cordappForClasses(Ping::class.java, Pong::class.java))).getOrThrow()
|
||||
val nodeA = startNode(NodeParameters(
|
||||
providedName = ALICE_NAME,
|
||||
additionalCordapps = setOf(cordappForClasses(Ping::class.java))
|
||||
)).getOrThrow()
|
||||
val nodeB = startNode(NodeParameters(
|
||||
providedName = BOB_NAME,
|
||||
additionalCordapps = setOf(cordappForClasses(Ping::class.java, Pong::class.java))
|
||||
)).getOrThrow()
|
||||
nodeA.rpc.startFlow(::Ping, nodeB.nodeInfo.singleIdentity(), 1).returnValue.getOrThrow()
|
||||
}
|
||||
}
|
||||
@ -66,8 +73,10 @@ class AsymmetricCorDappsTests : IntegrationTest() {
|
||||
val sharedCordapp = cordappForClasses(Ping::class.java)
|
||||
val cordappForNodeB = cordappForClasses(Pong::class.java)
|
||||
driver(DriverParameters(startNodesInProcess = false, cordappsForAllNodes = setOf(sharedCordapp))) {
|
||||
|
||||
val (nodeA, nodeB) = listOf(startNode(providedName = ALICE_NAME), startNode(providedName = BOB_NAME, additionalCordapps = setOf(cordappForNodeB))).transpose().getOrThrow()
|
||||
val (nodeA, nodeB) = listOf(
|
||||
startNode(NodeParameters(providedName = ALICE_NAME)),
|
||||
startNode(NodeParameters(providedName = BOB_NAME, additionalCordapps = setOf(cordappForNodeB)))
|
||||
).transpose().getOrThrow()
|
||||
nodeA.rpc.startFlow(::Ping, nodeB.nodeInfo.singleIdentity(), 1).returnValue.getOrThrow()
|
||||
}
|
||||
}
|
||||
@ -77,8 +86,10 @@ class AsymmetricCorDappsTests : IntegrationTest() {
|
||||
val sharedCordapp = cordappForClasses(Ping::class.java)
|
||||
val cordappForNodeB = cordappForClasses(Pong::class.java)
|
||||
driver(DriverParameters(startNodesInProcess = true, cordappsForAllNodes = setOf(sharedCordapp))) {
|
||||
|
||||
val (nodeA, nodeB) = listOf(startNode(providedName = ALICE_NAME), startNode(providedName = BOB_NAME, additionalCordapps = setOf(cordappForNodeB))).transpose().getOrThrow()
|
||||
val (nodeA, nodeB) = listOf(
|
||||
startNode(NodeParameters(providedName = ALICE_NAME)),
|
||||
startNode(NodeParameters(providedName = BOB_NAME, additionalCordapps = setOf(cordappForNodeB)))
|
||||
).transpose().getOrThrow()
|
||||
nodeA.rpc.startFlow(::Ping, nodeB.nodeInfo.singleIdentity(), 1).returnValue.getOrThrow()
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.driver.DriverDSL
|
||||
import net.corda.testing.driver.DriverParameters
|
||||
import net.corda.testing.driver.NodeParameters
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.internal.IntegrationTest
|
||||
import net.corda.testing.internal.IntegrationTestSchemas
|
||||
@ -119,7 +120,7 @@ class FlowCheckpointVersionNodeStartupCheckTest: IntegrationTest() {
|
||||
|
||||
private fun DriverDSL.createSuspendedFlowInBob(cordapps: Set<TestCordapp>) {
|
||||
val (alice, bob) = listOf(ALICE_NAME, BOB_NAME)
|
||||
.map { startNode(providedName = it, additionalCordapps = cordapps) }
|
||||
.map { startNode(NodeParameters(providedName = it, additionalCordapps = cordapps)) }
|
||||
.transpose()
|
||||
.getOrThrow()
|
||||
alice.stop()
|
||||
@ -131,12 +132,12 @@ class FlowCheckpointVersionNodeStartupCheckTest: IntegrationTest() {
|
||||
|
||||
private fun DriverDSL.assertBobFailsToStartWithLogMessage(cordapps: Collection<TestCordapp>, logMessage: String) {
|
||||
assertFailsWith(ListenProcessDeathException::class) {
|
||||
startNode(
|
||||
startNode(NodeParameters(
|
||||
providedName = BOB_NAME,
|
||||
customOverrides = mapOf("devMode" to false),
|
||||
additionalCordapps = cordapps,
|
||||
regenerateCordappsOnStart = true
|
||||
).getOrThrow()
|
||||
)).getOrThrow()
|
||||
}
|
||||
|
||||
val logDir = baseDirectory(BOB_NAME) / NodeStartup.LOGS_DIRECTORY_NAME
|
||||
|
@ -11,13 +11,14 @@ import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.driver.DriverParameters
|
||||
import net.corda.testing.driver.NodeParameters
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.internal.IntegrationTest
|
||||
import net.corda.testing.internal.IntegrationTestSchemas
|
||||
import net.corda.testing.internal.toDatabaseSchemaName
|
||||
import net.corda.testing.node.internal.cordappForClasses
|
||||
import org.hamcrest.CoreMatchers.`is`
|
||||
import org.junit.Assert
|
||||
import org.junit.Assert.assertThat
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Test
|
||||
|
||||
@ -41,7 +42,7 @@ class FlowOverrideTests : IntegrationTest() {
|
||||
@InitiatedBy(Ping::class)
|
||||
open class Pong(private val pingSession: FlowSession) : FlowLogic<Unit>() {
|
||||
companion object {
|
||||
val PONG = "PONG"
|
||||
const val PONG = "PONG"
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
@ -62,7 +63,7 @@ class FlowOverrideTests : IntegrationTest() {
|
||||
class Pongiest(private val pingSession: FlowSession) : Pong(pingSession) {
|
||||
|
||||
companion object {
|
||||
val GORGONZOLA = "Gorgonzola"
|
||||
const val GORGONZOLA = "Gorgonzola"
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
@ -71,16 +72,21 @@ class FlowOverrideTests : IntegrationTest() {
|
||||
}
|
||||
}
|
||||
|
||||
private val nodeAClasses = setOf(Ping::class.java,
|
||||
Pong::class.java, Pongiest::class.java)
|
||||
private val nodeAClasses = setOf(Ping::class.java, Pong::class.java, Pongiest::class.java)
|
||||
private val nodeBClasses = setOf(Ping::class.java, Pong::class.java)
|
||||
|
||||
@Test
|
||||
fun `should use the most specific implementation of a responding flow`() {
|
||||
driver(DriverParameters(startNodesInProcess = true, cordappsForAllNodes = emptySet())) {
|
||||
val nodeA = startNode(providedName = ALICE_NAME, additionalCordapps = setOf(cordappForClasses(*nodeAClasses.toTypedArray()))).getOrThrow()
|
||||
val nodeB = startNode(providedName = BOB_NAME, additionalCordapps = setOf(cordappForClasses(*nodeBClasses.toTypedArray()))).getOrThrow()
|
||||
Assert.assertThat(nodeB.rpc.startFlow(::Ping, nodeA.nodeInfo.singleIdentity()).returnValue.getOrThrow(), `is`(net.corda.node.flows.FlowOverrideTests.Pongiest.GORGONZOLA))
|
||||
val nodeA = startNode(NodeParameters(
|
||||
providedName = ALICE_NAME,
|
||||
additionalCordapps = setOf(cordappForClasses(*nodeAClasses.toTypedArray()))
|
||||
)).getOrThrow()
|
||||
val nodeB = startNode(NodeParameters(
|
||||
providedName = BOB_NAME,
|
||||
additionalCordapps = setOf(cordappForClasses(*nodeBClasses.toTypedArray()))
|
||||
)).getOrThrow()
|
||||
assertThat(nodeB.rpc.startFlow(::Ping, nodeA.nodeInfo.singleIdentity()).returnValue.getOrThrow(), `is`(Pongiest.GORGONZOLA))
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,9 +94,16 @@ class FlowOverrideTests : IntegrationTest() {
|
||||
fun `should use the overriden implementation of a responding flow`() {
|
||||
val flowOverrides = mapOf(Ping::class.java to Pong::class.java)
|
||||
driver(DriverParameters(startNodesInProcess = true, cordappsForAllNodes = emptySet())) {
|
||||
val nodeA = startNode(providedName = ALICE_NAME, additionalCordapps = setOf(cordappForClasses(*nodeAClasses.toTypedArray())), flowOverrides = flowOverrides).getOrThrow()
|
||||
val nodeB = startNode(providedName = BOB_NAME, additionalCordapps = setOf(cordappForClasses(*nodeBClasses.toTypedArray()))).getOrThrow()
|
||||
Assert.assertThat(nodeB.rpc.startFlow(::Ping, nodeA.nodeInfo.singleIdentity()).returnValue.getOrThrow(), `is`(net.corda.node.flows.FlowOverrideTests.Pong.PONG))
|
||||
val nodeA = startNode(NodeParameters(
|
||||
providedName = ALICE_NAME,
|
||||
additionalCordapps = setOf(cordappForClasses(*nodeAClasses.toTypedArray())),
|
||||
flowOverrides = flowOverrides
|
||||
)).getOrThrow()
|
||||
val nodeB = startNode(NodeParameters(
|
||||
providedName = BOB_NAME,
|
||||
additionalCordapps = setOf(cordappForClasses(*nodeBClasses.toTypedArray()))
|
||||
)).getOrThrow()
|
||||
assertThat(nodeB.rpc.startFlow(::Ping, nodeA.nodeInfo.singleIdentity()).returnValue.getOrThrow(), `is`(Pong.PONG))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import net.corda.testing.core.TestIdentity
|
||||
import net.corda.testing.driver.DriverParameters
|
||||
import net.corda.testing.driver.NodeParameters
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.internal.*
|
||||
import net.corda.testing.node.internal.cordappsForPackages
|
||||
@ -107,8 +108,9 @@ class AttachmentLoadingTests : IntegrationTest() {
|
||||
fun `test that attachments retrieved over the network are not used for code`() {
|
||||
withoutTestSerialization {
|
||||
driver(DriverParameters(startNodesInProcess = true, notarySpecs = emptyList(), cordappsForAllNodes = emptySet())) {
|
||||
val bankA = startNode(providedName = bankAName, additionalCordapps = cordappsForPackages("net.corda.finance.contracts.isolated")).getOrThrow()
|
||||
val bankB = startNode(providedName = bankBName, additionalCordapps = cordappsForPackages("net.corda.finance.contracts.isolated")).getOrThrow()
|
||||
val additionalCordapps = cordappsForPackages("net.corda.finance.contracts.isolated")
|
||||
val bankA = startNode(NodeParameters(providedName = bankAName, additionalCordapps = additionalCordapps)).getOrThrow()
|
||||
val bankB = startNode(NodeParameters(providedName = bankBName, additionalCordapps = additionalCordapps)).getOrThrow()
|
||||
assertFailsWith<CordaRuntimeException>("Party C=CH,L=Zurich,O=BankB rejected session request: Don't know net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator") {
|
||||
bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow()
|
||||
}
|
||||
|
@ -33,22 +33,43 @@ import kotlin.reflect.jvm.javaType
|
||||
* will find it useful to revert to earlier states of knowledge about which types have been visited on a given branch.
|
||||
*/
|
||||
internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
val resolutionContext: Type? = null,
|
||||
val visited: Set<TypeIdentifier> = emptySet(),
|
||||
val cycles: MutableList<LocalTypeInformation.Cycle> = mutableListOf()) {
|
||||
var resolutionContext: Type? = null,
|
||||
var visited: Set<TypeIdentifier> = emptySet(),
|
||||
val cycles: MutableList<LocalTypeInformation.Cycle> = mutableListOf(),
|
||||
var warnIfNonComposable: Boolean = true) {
|
||||
|
||||
companion object {
|
||||
private val logger = contextLogger()
|
||||
}
|
||||
|
||||
/**
|
||||
* If we are examining the type of a read-only property, or a type flagged as [Opaque], then we do not need to warn
|
||||
* if the [LocalTypeInformation] for that type (or any of its related types) is [LocalTypeInformation.NonComposable].
|
||||
*/
|
||||
private inline fun <T> suppressWarningsAnd(block: LocalTypeInformationBuilder.() -> T): T {
|
||||
val previous = warnIfNonComposable
|
||||
return try {
|
||||
warnIfNonComposable = false
|
||||
block()
|
||||
} finally {
|
||||
warnIfNonComposable = previous
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively build [LocalTypeInformation] for the given [Type] and [TypeIdentifier]
|
||||
*/
|
||||
fun build(type: Type, typeIdentifier: TypeIdentifier): LocalTypeInformation =
|
||||
if (typeIdentifier in visited) LocalTypeInformation.Cycle(type, typeIdentifier).apply { cycles.add(this) }
|
||||
else lookup.findOrBuild(type, typeIdentifier) { isOpaque ->
|
||||
copy(visited = visited + typeIdentifier).buildIfNotFound(type, typeIdentifier, isOpaque)
|
||||
}
|
||||
if (typeIdentifier in visited) LocalTypeInformation.Cycle(type, typeIdentifier).apply { cycles.add(this) }
|
||||
else lookup.findOrBuild(type, typeIdentifier) { isOpaque ->
|
||||
val previous = visited
|
||||
try {
|
||||
visited = visited + typeIdentifier
|
||||
buildIfNotFound(type, typeIdentifier, isOpaque)
|
||||
} finally {
|
||||
visited = previous
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveAndBuild(type: Type): LocalTypeInformation {
|
||||
val resolved = type.resolveAgainstContext()
|
||||
@ -57,7 +78,7 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
}
|
||||
|
||||
private fun Type.resolveAgainstContext(): Type =
|
||||
if (resolutionContext == null) this else resolveAgainst(resolutionContext)
|
||||
resolutionContext?.let(::resolveAgainst) ?: this
|
||||
|
||||
private fun buildIfNotFound(type: Type, typeIdentifier: TypeIdentifier, isOpaque: Boolean): LocalTypeInformation {
|
||||
val rawType = type.asClass()
|
||||
@ -79,7 +100,7 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
private fun buildForClass(type: Class<*>, typeIdentifier: TypeIdentifier, isOpaque: Boolean): LocalTypeInformation = withContext(type) {
|
||||
when {
|
||||
Collection::class.java.isAssignableFrom(type) &&
|
||||
!EnumSet::class.java.isAssignableFrom(type) -> LocalTypeInformation.ACollection(type, typeIdentifier, LocalTypeInformation.Unknown)
|
||||
!EnumSet::class.java.isAssignableFrom(type) -> LocalTypeInformation.ACollection(type, typeIdentifier, LocalTypeInformation.Unknown)
|
||||
Map::class.java.isAssignableFrom(type) -> LocalTypeInformation.AMap(type, typeIdentifier, LocalTypeInformation.Unknown, LocalTypeInformation.Unknown)
|
||||
type.kotlin.javaPrimitiveType != null -> LocalTypeInformation.Atomic(type.kotlin.javaPrimitiveType!!, typeIdentifier)
|
||||
type.isEnum -> LocalTypeInformation.AnEnum(
|
||||
@ -95,9 +116,12 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
type.isInterface -> buildInterface(type, typeIdentifier, emptyList())
|
||||
type.isAbstractClass -> buildAbstract(type, typeIdentifier, emptyList())
|
||||
isOpaque -> LocalTypeInformation.Opaque(
|
||||
type,
|
||||
typeIdentifier,
|
||||
buildNonAtomic(type, type, typeIdentifier, emptyList(), true))
|
||||
type,
|
||||
typeIdentifier,
|
||||
suppressWarningsAnd { buildNonAtomic(type, type, typeIdentifier, emptyList()) })
|
||||
Exception::class.java.isAssignableFrom(type.asClass()) -> suppressWarningsAnd {
|
||||
buildNonAtomic(type, type, typeIdentifier, emptyList())
|
||||
}
|
||||
else -> buildNonAtomic(type, type, typeIdentifier, emptyList())
|
||||
}
|
||||
}
|
||||
@ -109,7 +133,7 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
isOpaque: Boolean): LocalTypeInformation = withContext(type) {
|
||||
when {
|
||||
Collection::class.java.isAssignableFrom(rawType) &&
|
||||
!EnumSet::class.java.isAssignableFrom(rawType) ->
|
||||
!EnumSet::class.java.isAssignableFrom(rawType) ->
|
||||
LocalTypeInformation.ACollection(type, typeIdentifier, buildTypeParameterInformation(type)[0])
|
||||
Map::class.java.isAssignableFrom(rawType) -> {
|
||||
val (keyType, valueType) = buildTypeParameterInformation(type)
|
||||
@ -118,8 +142,8 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
rawType.isInterface -> buildInterface(type, typeIdentifier, buildTypeParameterInformation(type))
|
||||
rawType.isAbstractClass -> buildAbstract(type, typeIdentifier, buildTypeParameterInformation(type))
|
||||
isOpaque -> LocalTypeInformation.Opaque(rawType,
|
||||
typeIdentifier,
|
||||
buildNonAtomic(rawType, type, typeIdentifier, buildTypeParameterInformation(type), true))
|
||||
typeIdentifier,
|
||||
suppressWarningsAnd { buildNonAtomic(rawType, type, typeIdentifier, buildTypeParameterInformation(type)) })
|
||||
else -> buildNonAtomic(rawType, type, typeIdentifier, buildTypeParameterInformation(type))
|
||||
}
|
||||
}
|
||||
@ -143,8 +167,15 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
buildInterfaceInformation(type),
|
||||
typeParameters)
|
||||
|
||||
private inline fun <T> withContext(newContext: Type, block: LocalTypeInformationBuilder.() -> T): T =
|
||||
copy(resolutionContext = newContext).run(block)
|
||||
private inline fun <T> withContext(newContext: Type, block: LocalTypeInformationBuilder.() -> T): T {
|
||||
val previous = resolutionContext
|
||||
return try {
|
||||
resolutionContext = newContext
|
||||
block()
|
||||
} finally {
|
||||
resolutionContext = previous
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a non-atomic type, which is either [Composable] or [NonComposable].
|
||||
@ -156,13 +187,13 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
* Rather than throwing an exception if a type is [NonComposable], we capture its type information so that it can
|
||||
* still be used to _serialize_ values, or as the basis for deciding on an evolution strategy.
|
||||
*/
|
||||
private fun buildNonAtomic(rawType: Class<*>, type: Type, typeIdentifier: TypeIdentifier, typeParameterInformation: List<LocalTypeInformation>, suppressWarning: Boolean = false): LocalTypeInformation {
|
||||
private fun buildNonAtomic(rawType: Class<*>, type: Type, typeIdentifier: TypeIdentifier, typeParameterInformation: List<LocalTypeInformation>): LocalTypeInformation {
|
||||
val superclassInformation = buildSuperclassInformation(type)
|
||||
val interfaceInformation = buildInterfaceInformation(type)
|
||||
val observedConstructor = constructorForDeserialization(type)
|
||||
|
||||
if (observedConstructor == null) {
|
||||
if (!suppressWarning) {
|
||||
if (warnIfNonComposable) {
|
||||
logger.info("No unique deserialisation constructor found for class $rawType, type is marked as non-composable")
|
||||
}
|
||||
return LocalTypeInformation.NonComposable(type, typeIdentifier, null, buildReadOnlyProperties(rawType),
|
||||
@ -175,7 +206,7 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
val hasNonComposableProperties = properties.values.any { it.type is LocalTypeInformation.NonComposable }
|
||||
|
||||
if (!propertiesSatisfyConstructor(constructorInformation, properties) || hasNonComposableProperties) {
|
||||
if (!suppressWarning) {
|
||||
if (warnIfNonComposable) {
|
||||
if (hasNonComposableProperties) {
|
||||
logger.info("Type ${type.typeName} has non-composable properties and has been marked as non-composable")
|
||||
} else {
|
||||
@ -214,7 +245,7 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
}
|
||||
|
||||
private fun buildSuperclassInformation(type: Type): LocalTypeInformation =
|
||||
resolveAndBuild(type.asClass().genericSuperclass)
|
||||
resolveAndBuild(type.asClass().genericSuperclass)
|
||||
|
||||
private fun buildInterfaceInformation(type: Type) =
|
||||
type.allInterfaces.asSequence().mapNotNull {
|
||||
@ -244,8 +275,10 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
if (descriptor.field == null || descriptor.getter == null) null
|
||||
else {
|
||||
val paramType = (descriptor.getter.genericReturnType).resolveAgainstContext()
|
||||
val paramTypeInformation = build(paramType, TypeIdentifier.forGenericType(paramType, resolutionContext
|
||||
?: rawType))
|
||||
// Because this parameter is read-only, we don't need to warn if its type is non-composable.
|
||||
val paramTypeInformation = suppressWarningsAnd {
|
||||
build(paramType, TypeIdentifier.forGenericType(paramType, resolutionContext ?: rawType))
|
||||
}
|
||||
val isMandatory = paramType.asClass().isPrimitive || !descriptor.getter.returnsNullable()
|
||||
name to LocalPropertyInformation.ReadOnlyProperty(descriptor.getter, paramTypeInformation, isMandatory)
|
||||
}
|
||||
@ -275,10 +308,10 @@ internal data class LocalTypeInformationBuilder(val lookup: LocalTypeLookup,
|
||||
name: String,
|
||||
descriptor: PropertyDescriptor,
|
||||
constructorInformation: LocalConstructorInformation): LocalPropertyInformation? {
|
||||
val constructorIndex = constructorParameterIndices[name] ?:
|
||||
// In some very rare cases we have a constructor parameter matched by a getter with no backing field,
|
||||
// and cannot infer whether the property name should be capitalised or not.
|
||||
constructorParameterIndices[name.decapitalize()] ?: return null
|
||||
// In some very rare cases we have a constructor parameter matched by a getter with no backing field,
|
||||
// and cannot infer whether the property name should be capitalised or not.
|
||||
val constructorIndex = constructorParameterIndices[name] ?: constructorParameterIndices[name.decapitalize()]
|
||||
if (constructorIndex == null) return null
|
||||
|
||||
if (descriptor.getter == null) {
|
||||
if (descriptor.field == null) return null
|
||||
|
@ -5,7 +5,6 @@ package net.corda.testing.driver
|
||||
import net.corda.core.DoNotImplement
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.node.NetworkParameters
|
||||
@ -13,7 +12,6 @@ import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.internal.Node
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||
import net.corda.testing.driver.internal.incrementalPortAllocation
|
||||
@ -122,181 +120,6 @@ abstract class PortAllocation {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper builder for configuring a [Node] from Java.
|
||||
*
|
||||
* @property providedName Optional name of the node, which will be its legal name in [Party]. Defaults to something
|
||||
* random. Note that this must be unique as the driver uses it as a primary key!
|
||||
* @property rpcUsers List of users who are authorised to use the RPC system. Defaults to a single user with
|
||||
* all permissions.
|
||||
* @property verifierType The type of transaction verifier to use. See: [VerifierType]
|
||||
* @property customOverrides A map of custom node configuration overrides.
|
||||
* @property startInSameProcess Determines if the node should be started inside the same process the Driver is running
|
||||
* in. If null the Driver-level value will be used.
|
||||
* @property maximumHeapSize The maximum JVM heap size to use for the node.
|
||||
* @property logLevel Logging level threshold.
|
||||
* @property additionalCordapps Additional [TestCordapp]s that this node will have available, in addition to the ones common to all nodes managed by the [DriverDSL].
|
||||
* @property regenerateCordappsOnStart Whether existing [TestCordapp]s unique to this node will be re-generated on start. Useful when stopping and restarting the same node.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
data class NodeParameters(
|
||||
val providedName: CordaX500Name? = null,
|
||||
val rpcUsers: List<User> = emptyList(),
|
||||
val verifierType: VerifierType = VerifierType.InMemory,
|
||||
val customOverrides: Map<String, Any?> = emptyMap(),
|
||||
val startInSameProcess: Boolean? = null,
|
||||
val maximumHeapSize: String = "512m",
|
||||
val logLevel: String? = null,
|
||||
val additionalCordapps: Collection<TestCordapp> = emptySet(),
|
||||
val regenerateCordappsOnStart: Boolean = false,
|
||||
val flowOverrides: Map<Class<out FlowLogic<*>>, Class<out FlowLogic<*>>> = emptyMap()
|
||||
) {
|
||||
/**
|
||||
* Helper builder for configuring a [Node] from Java.
|
||||
*
|
||||
* @param providedName Optional name of the node, which will be its legal name in [Party]. Defaults to something
|
||||
* random. Note that this must be unique as the driver uses it as a primary key!
|
||||
* @param rpcUsers List of users who are authorised to use the RPC system. Defaults to a single user with
|
||||
* all permissions.
|
||||
* @param verifierType The type of transaction verifier to use. See: [VerifierType]
|
||||
* @param customOverrides A map of custom node configuration overrides.
|
||||
* @param startInSameProcess Determines if the node should be started inside the same process the Driver is running
|
||||
* in. If null the Driver-level value will be used.
|
||||
* @param maximumHeapSize The maximum JVM heap size to use for the node.
|
||||
* @param logLevel Logging level threshold.
|
||||
*/
|
||||
constructor(
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String,
|
||||
logLevel: String? = null
|
||||
) : this(
|
||||
providedName,
|
||||
rpcUsers,
|
||||
verifierType,
|
||||
customOverrides,
|
||||
startInSameProcess,
|
||||
maximumHeapSize,
|
||||
logLevel,
|
||||
additionalCordapps = emptySet(),
|
||||
regenerateCordappsOnStart = false
|
||||
)
|
||||
|
||||
/**
|
||||
* Helper builder for configuring a [Node] from Java.
|
||||
*
|
||||
* @param providedName Optional name of the node, which will be its legal name in [Party]. Defaults to something
|
||||
* random. Note that this must be unique as the driver uses it as a primary key!
|
||||
* @param rpcUsers List of users who are authorised to use the RPC system. Defaults to a single user with
|
||||
* all permissions.
|
||||
* @param verifierType The type of transaction verifier to use. See: [VerifierType]
|
||||
* @param customOverrides A map of custom node configuration overrides.
|
||||
* @param startInSameProcess Determines if the node should be started inside the same process the Driver is running
|
||||
* in. If null the Driver-level value will be used.
|
||||
* @param maximumHeapSize The maximum JVM heap size to use for the node.
|
||||
*/
|
||||
constructor(
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String
|
||||
) : this(
|
||||
providedName,
|
||||
rpcUsers,
|
||||
verifierType,
|
||||
customOverrides,
|
||||
startInSameProcess,
|
||||
maximumHeapSize,
|
||||
null,
|
||||
additionalCordapps = emptySet(),
|
||||
regenerateCordappsOnStart = false)
|
||||
|
||||
/**
|
||||
* Helper builder for configuring a [Node] from Java.
|
||||
*
|
||||
* @param providedName Optional name of the node, which will be its legal name in [Party]. Defaults to something
|
||||
* random. Note that this must be unique as the driver uses it as a primary key!
|
||||
* @param rpcUsers List of users who are authorised to use the RPC system. Defaults to a single user with
|
||||
* all permissions.
|
||||
* @param verifierType The type of transaction verifier to use. See: [VerifierType]
|
||||
* @param customOverrides A map of custom node configuration overrides.
|
||||
* @param startInSameProcess Determines if the node should be started inside the same process the Driver is running
|
||||
* in. If null the Driver-level value will be used.
|
||||
* @param maximumHeapSize The maximum JVM heap size to use for the node.
|
||||
* @param additionalCordapps Additional [TestCordapp]s that this node will have available, in addition to the ones common to all nodes managed by the [DriverDSL].
|
||||
* @param regenerateCordappsOnStart Whether existing [TestCordapp]s unique to this node will be re-generated on start. Useful when stopping and restarting the same node.
|
||||
*/
|
||||
constructor(
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String,
|
||||
additionalCordapps: Set<TestCordapp> = emptySet(),
|
||||
regenerateCordappsOnStart: Boolean = false
|
||||
) : this(
|
||||
providedName,
|
||||
rpcUsers,
|
||||
verifierType,
|
||||
customOverrides,
|
||||
startInSameProcess,
|
||||
maximumHeapSize,
|
||||
null,
|
||||
additionalCordapps,
|
||||
regenerateCordappsOnStart)
|
||||
|
||||
fun copy(
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String
|
||||
) = this.copy(
|
||||
providedName,
|
||||
rpcUsers,
|
||||
verifierType,
|
||||
customOverrides,
|
||||
startInSameProcess,
|
||||
maximumHeapSize,
|
||||
null)
|
||||
|
||||
fun copy(
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String,
|
||||
logLevel: String?
|
||||
) = this.copy(
|
||||
providedName,
|
||||
rpcUsers,
|
||||
verifierType,
|
||||
customOverrides,
|
||||
startInSameProcess,
|
||||
maximumHeapSize,
|
||||
logLevel,
|
||||
additionalCordapps = additionalCordapps,
|
||||
regenerateCordappsOnStart = regenerateCordappsOnStart)
|
||||
|
||||
fun withProvidedName(providedName: CordaX500Name?): NodeParameters = copy(providedName = providedName)
|
||||
fun withRpcUsers(rpcUsers: List<User>): NodeParameters = copy(rpcUsers = rpcUsers)
|
||||
fun withVerifierType(verifierType: VerifierType): NodeParameters = copy(verifierType = verifierType)
|
||||
fun withCustomOverrides(customOverrides: Map<String, Any?>): NodeParameters = copy(customOverrides = customOverrides)
|
||||
fun withStartInSameProcess(startInSameProcess: Boolean?): NodeParameters = copy(startInSameProcess = startInSameProcess)
|
||||
fun withMaximumHeapSize(maximumHeapSize: String): NodeParameters = copy(maximumHeapSize = maximumHeapSize)
|
||||
fun withLogLevel(logLevel: String?): NodeParameters = copy(logLevel = logLevel)
|
||||
fun withAdditionalCordapps(additionalCordapps: Set<TestCordapp>): NodeParameters = copy(additionalCordapps = additionalCordapps)
|
||||
fun withDeleteExistingCordappsDirectory(regenerateCordappsOnStart: Boolean): NodeParameters = copy(regenerateCordappsOnStart = regenerateCordappsOnStart)
|
||||
}
|
||||
|
||||
/**
|
||||
* [driver] allows one to start up nodes like this:
|
||||
* driver {
|
||||
|
@ -2,14 +2,11 @@ package net.corda.testing.driver
|
||||
|
||||
import net.corda.core.DoNotImplement
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.concurrent.map
|
||||
import net.corda.node.internal.Node
|
||||
import net.corda.testing.node.TestCordapp
|
||||
import net.corda.testing.node.User
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import net.corda.testing.node.User
|
||||
import java.nio.file.Path
|
||||
|
||||
enum class VerifierType {
|
||||
@ -56,11 +53,32 @@ interface DriverDSL {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a node using the default values of [NodeParameters].
|
||||
*
|
||||
* @return A [CordaFuture] on the [NodeHandle] to the node. The future will complete when the node is available and
|
||||
* it sees all previously started nodes, including the notaries.
|
||||
*/
|
||||
fun startNode(): CordaFuture<NodeHandle> = startNode(NodeParameters())
|
||||
|
||||
/**
|
||||
* Start a node using the parameter values of the given [NodeParameters].
|
||||
*
|
||||
* @param parameters The node parameters.
|
||||
*
|
||||
* @return A [CordaFuture] on the [NodeHandle] to the node. The future will complete when the node is available and
|
||||
* it sees all previously started nodes, including the notaries.
|
||||
*/
|
||||
fun startNode(parameters: NodeParameters): CordaFuture<NodeHandle>
|
||||
|
||||
/**
|
||||
* Start a node.
|
||||
*
|
||||
* @param defaultParameters The default parameters for the node. Allows the node to be configured in builder style
|
||||
* when called from Java code.
|
||||
* NOTE: This method does not provide all the node parameters that are available and only exists for backwards compatibility. It is
|
||||
* recommended you use [NodeParameters].
|
||||
*
|
||||
* @param defaultParameters The default parameters for the node. If any of the remaining parameters to this method are specified then
|
||||
* their values are taken instead of the corresponding value in [defaultParameters].
|
||||
* @param providedName Optional name of the node, which will be its legal name in [Party]. Defaults to something
|
||||
* random. Note that this must be unique as the driver uses it as a primary key!
|
||||
* @param rpcUsers List of users who are authorised to use the RPC system. Defaults to empty list.
|
||||
@ -82,48 +100,16 @@ interface DriverDSL {
|
||||
customOverrides: Map<String, Any?> = defaultParameters.customOverrides,
|
||||
startInSameProcess: Boolean? = defaultParameters.startInSameProcess,
|
||||
maximumHeapSize: String = defaultParameters.maximumHeapSize
|
||||
): CordaFuture<NodeHandle>
|
||||
|
||||
/**
|
||||
* Start a node.
|
||||
*
|
||||
* @param defaultParameters The default parameters for the node. Allows the node to be configured in builder style
|
||||
* when called from Java code.
|
||||
* @param providedName Optional name of the node, which will be its legal name in [Party]. Defaults to something
|
||||
* random. Note that this must be unique as the driver uses it as a primary key!
|
||||
* @param rpcUsers List of users who are authorised to use the RPC system. Defaults to empty list.
|
||||
* @param verifierType The type of transaction verifier to use. See: [VerifierType].
|
||||
* @param customOverrides A map of custom node configuration overrides.
|
||||
* @param startInSameProcess Determines if the node should be started inside the same process the Driver is running
|
||||
* in. If null the Driver-level value will be used.
|
||||
* @param maximumHeapSize The maximum JVM heap size to use for the node as a [String]. By default a number is interpreted
|
||||
* as being in bytes. Append the letter 'k' or 'K' to the value to indicate Kilobytes, 'm' or 'M' to indicate
|
||||
* megabytes, and 'g' or 'G' to indicate gigabytes. The default value is "512m" = 512 megabytes.
|
||||
* @param additionalCordapps Additional [TestCordapp]s that this node will have available, in addition to the ones common to all nodes managed by the [DriverDSL].
|
||||
* @param regenerateCordappsOnStart Whether existing [TestCordapp]s unique to this node will be re-generated on start. Useful when stopping and restarting the same node.
|
||||
* @return A [CordaFuture] on the [NodeHandle] to the node. The future will complete when the node is available and
|
||||
* it sees all previously started nodes, including the notaries.
|
||||
*/
|
||||
fun startNode(
|
||||
defaultParameters: NodeParameters = NodeParameters(),
|
||||
providedName: CordaX500Name? = defaultParameters.providedName,
|
||||
rpcUsers: List<User> = defaultParameters.rpcUsers,
|
||||
verifierType: VerifierType = defaultParameters.verifierType,
|
||||
customOverrides: Map<String, Any?> = defaultParameters.customOverrides,
|
||||
startInSameProcess: Boolean? = defaultParameters.startInSameProcess,
|
||||
maximumHeapSize: String = defaultParameters.maximumHeapSize,
|
||||
additionalCordapps: Collection<TestCordapp> = defaultParameters.additionalCordapps,
|
||||
regenerateCordappsOnStart: Boolean = defaultParameters.regenerateCordappsOnStart,
|
||||
flowOverrides: Map<out Class<out FlowLogic<*>>, Class<out FlowLogic<*>>> = defaultParameters.flowOverrides
|
||||
): CordaFuture<NodeHandle>
|
||||
|
||||
/**
|
||||
* Helper function for starting a [Node] with custom parameters from Java.
|
||||
*
|
||||
* @param parameters The default parameters for the driver.
|
||||
* @return [NodeHandle] that will be available sometime in the future.
|
||||
*/
|
||||
fun startNode(parameters: NodeParameters): CordaFuture<NodeHandle> = startNode(defaultParameters = parameters)
|
||||
): CordaFuture<NodeHandle> {
|
||||
return startNode(defaultParameters.copy(
|
||||
providedName = providedName,
|
||||
rpcUsers = rpcUsers,
|
||||
verifierType = verifierType,
|
||||
customOverrides = customOverrides,
|
||||
startInSameProcess = startInSameProcess,
|
||||
maximumHeapSize = maximumHeapSize
|
||||
))
|
||||
}
|
||||
|
||||
/** Call [startWebserver] with a default maximumHeapSize. */
|
||||
@Suppress("DEPRECATION")
|
||||
|
@ -0,0 +1,86 @@
|
||||
package net.corda.testing.driver
|
||||
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.testing.node.TestCordapp
|
||||
import net.corda.testing.node.User
|
||||
|
||||
/**
|
||||
* Parameters for creating a node for [DriverDSL.startNode].
|
||||
*
|
||||
* @property providedName Optional name of the node, which will be its legal name in [Party]. Defaults to something
|
||||
* random. Note that this must be unique as the driver uses it as a primary key!
|
||||
* @property rpcUsers List of users who are authorised to use the RPC system. Defaults to a single user with
|
||||
* all permissions.
|
||||
* @property verifierType The type of transaction verifier to use. See: [VerifierType]
|
||||
* @property customOverrides A map of custom node configuration overrides.
|
||||
* @property startInSameProcess Determines if the node should be started inside the same process the Driver is running
|
||||
* in. If null the Driver-level value will be used.
|
||||
* @property maximumHeapSize The maximum JVM heap size to use for the node. Defaults to 512 MB.
|
||||
* @property additionalCordapps Additional [TestCordapp]s that this node will have available, in addition to the ones common to all nodes
|
||||
* managed by the [DriverDSL].
|
||||
* @property regenerateCordappsOnStart Whether existing [TestCordapp]s unique to this node will be re-generated on start. Useful when stopping
|
||||
* and restarting the same node.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
data class NodeParameters(
|
||||
val providedName: CordaX500Name? = null,
|
||||
val rpcUsers: List<User> = emptyList(),
|
||||
val verifierType: VerifierType = VerifierType.InMemory,
|
||||
val customOverrides: Map<String, Any?> = emptyMap(),
|
||||
val startInSameProcess: Boolean? = null,
|
||||
val maximumHeapSize: String = "512m",
|
||||
val additionalCordapps: Collection<TestCordapp> = emptySet(),
|
||||
val regenerateCordappsOnStart: Boolean = false,
|
||||
val flowOverrides: Map<out Class<out FlowLogic<*>>, Class<out FlowLogic<*>>> = emptyMap()
|
||||
) {
|
||||
/**
|
||||
* Create a new node parameters object with default values. Each parameter can be specified with its wither method which returns a copy
|
||||
* with that value.
|
||||
*/
|
||||
constructor() : this(providedName = null)
|
||||
|
||||
fun withProvidedName(providedName: CordaX500Name?): NodeParameters = copy(providedName = providedName)
|
||||
fun withRpcUsers(rpcUsers: List<User>): NodeParameters = copy(rpcUsers = rpcUsers)
|
||||
fun withVerifierType(verifierType: VerifierType): NodeParameters = copy(verifierType = verifierType)
|
||||
fun withCustomOverrides(customOverrides: Map<String, Any?>): NodeParameters = copy(customOverrides = customOverrides)
|
||||
fun withStartInSameProcess(startInSameProcess: Boolean?): NodeParameters = copy(startInSameProcess = startInSameProcess)
|
||||
fun withMaximumHeapSize(maximumHeapSize: String): NodeParameters = copy(maximumHeapSize = maximumHeapSize)
|
||||
fun withAdditionalCordapps(additionalCordapps: Set<TestCordapp>): NodeParameters = copy(additionalCordapps = additionalCordapps)
|
||||
fun withRegenerateCordappsOnStart(regenerateCordappsOnStart: Boolean): NodeParameters = copy(regenerateCordappsOnStart = regenerateCordappsOnStart)
|
||||
fun withFlowOverrides(flowOverrides: Map<Class<out FlowLogic<*>>, Class<out FlowLogic<*>>>): NodeParameters = copy(flowOverrides = flowOverrides)
|
||||
|
||||
constructor(
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String
|
||||
) : this(
|
||||
providedName,
|
||||
rpcUsers,
|
||||
verifierType,
|
||||
customOverrides,
|
||||
startInSameProcess,
|
||||
maximumHeapSize,
|
||||
additionalCordapps = emptySet())
|
||||
|
||||
fun copy(
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String
|
||||
) = this.copy(
|
||||
providedName = providedName,
|
||||
rpcUsers = rpcUsers,
|
||||
verifierType = verifierType,
|
||||
customOverrides = customOverrides,
|
||||
startInSameProcess = startInSameProcess,
|
||||
maximumHeapSize = maximumHeapSize,
|
||||
additionalCordapps = additionalCordapps
|
||||
)
|
||||
}
|
@ -9,7 +9,6 @@ import net.corda.client.rpc.internal.createCordaRPCClientWithSslAndClassLoader
|
||||
import net.corda.cliutils.CommonCliConstants.BASE_DIR
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.concurrent.firstOf
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.concurrent.*
|
||||
@ -25,6 +24,7 @@ import net.corda.node.internal.NodeWithInfo
|
||||
import net.corda.node.internal.clientSslOptionsCompatibleWith
|
||||
import net.corda.node.services.Permissions
|
||||
import net.corda.node.services.config.*
|
||||
import net.corda.node.services.config.NodeConfiguration.Companion.cordappDirectoriesKey
|
||||
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
|
||||
import net.corda.node.utilities.registration.NodeRegistrationHelper
|
||||
import net.corda.nodeapi.internal.DevIdentityGenerator
|
||||
@ -40,7 +40,6 @@ import net.corda.testing.core.ALICE_NAME
|
||||
import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||
import net.corda.testing.driver.*
|
||||
import net.corda.testing.driver.VerifierType
|
||||
import net.corda.testing.driver.internal.InProcessImpl
|
||||
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||
import net.corda.testing.driver.internal.OutOfProcessImpl
|
||||
@ -49,7 +48,6 @@ import net.corda.testing.internal.stubs.CertificateStoreStubs
|
||||
import net.corda.testing.node.ClusterSpec
|
||||
import net.corda.testing.node.NotarySpec
|
||||
import net.corda.testing.node.TestCordapp
|
||||
import net.corda.testing.node.User
|
||||
import net.corda.testing.node.internal.DriverDSLImpl.Companion.cordappsInCurrentAndAdditionalPackages
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
@ -196,73 +194,14 @@ class DriverDSLImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun startNode(defaultParameters: NodeParameters,
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String): CordaFuture<NodeHandle> {
|
||||
return startNode(
|
||||
defaultParameters,
|
||||
providedName,
|
||||
rpcUsers,
|
||||
verifierType,
|
||||
customOverrides,
|
||||
startInSameProcess,
|
||||
maximumHeapSize,
|
||||
defaultParameters.additionalCordapps,
|
||||
defaultParameters.regenerateCordappsOnStart,
|
||||
emptyMap(),
|
||||
null
|
||||
)
|
||||
}
|
||||
override fun startNode(defaultParameters: NodeParameters,
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String,
|
||||
additionalCordapps: Collection<TestCordapp>,
|
||||
regenerateCordappsOnStart: Boolean,
|
||||
flowOverrides: Map<out Class<out FlowLogic<*>>, Class<out FlowLogic<*>>>): CordaFuture<NodeHandle> {
|
||||
return startNode(
|
||||
defaultParameters,
|
||||
providedName,
|
||||
rpcUsers,
|
||||
verifierType,
|
||||
customOverrides,
|
||||
startInSameProcess,
|
||||
maximumHeapSize,
|
||||
additionalCordapps,
|
||||
regenerateCordappsOnStart,
|
||||
flowOverrides,
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
override fun startNode(
|
||||
defaultParameters: NodeParameters,
|
||||
providedName: CordaX500Name?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean?,
|
||||
maximumHeapSize: String,
|
||||
additionalCordapps: Collection<TestCordapp>,
|
||||
regenerateCordappsOnStart: Boolean,
|
||||
flowOverrides: Map<out Class<out FlowLogic<*>>, Class<out FlowLogic<*>>>,
|
||||
bytemanPort: Int?
|
||||
): CordaFuture<NodeHandle> {
|
||||
override fun startNode(parameters: NodeParameters): CordaFuture<NodeHandle> {
|
||||
val p2pAddress = portAllocation.nextHostAndPort()
|
||||
// TODO: Derive name from the full picked name, don't just wrap the common name
|
||||
val name = providedName
|
||||
?: CordaX500Name("${oneOf(names).organisation}-${p2pAddress.port}", "London", "GB")
|
||||
val name = parameters.providedName ?: CordaX500Name("${oneOf(names).organisation}-${p2pAddress.port}", "London", "GB")
|
||||
|
||||
val registrationFuture = if (compatibilityZone?.rootCert != null) {
|
||||
// We don't need the network map to be available to be able to register the node
|
||||
startNodeRegistration(name, compatibilityZone.rootCert, compatibilityZone.config(), customOverrides)
|
||||
startNodeRegistration(name, compatibilityZone.rootCert, compatibilityZone.config(), parameters.customOverrides)
|
||||
} else {
|
||||
doneFuture(Unit)
|
||||
}
|
||||
@ -270,28 +209,21 @@ class DriverDSLImpl(
|
||||
return registrationFuture.flatMap {
|
||||
networkMapAvailability.flatMap {
|
||||
// But starting the node proper does require the network map
|
||||
startRegisteredNode(name, it, rpcUsers, verifierType, customOverrides, startInSameProcess, maximumHeapSize, p2pAddress, additionalCordapps, regenerateCordappsOnStart, flowOverrides, signCordapps, bytemanPort)
|
||||
startRegisteredNode(name, it, parameters, p2pAddress, signCordapps, bytemanPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startRegisteredNode(name: CordaX500Name,
|
||||
localNetworkMap: LocalNetworkMap?,
|
||||
rpcUsers: List<User>,
|
||||
verifierType: VerifierType,
|
||||
customOverrides: Map<String, Any?>,
|
||||
startInSameProcess: Boolean? = null,
|
||||
maximumHeapSize: String = "512m",
|
||||
parameters: NodeParameters,
|
||||
p2pAddress: NetworkHostAndPort = portAllocation.nextHostAndPort(),
|
||||
additionalCordapps: Collection<TestCordapp> = emptySet(),
|
||||
regenerateCordappsOnStart: Boolean = false,
|
||||
flowOverrides: Map<out Class<out FlowLogic<*>>, Class<out FlowLogic<*>>> = emptyMap(),
|
||||
signCordapps: Boolean = false,
|
||||
bytemanPort: Int? = null): CordaFuture<NodeHandle> {
|
||||
val rpcAddress = portAllocation.nextHostAndPort()
|
||||
val rpcAdminAddress = portAllocation.nextHostAndPort()
|
||||
val webAddress = portAllocation.nextHostAndPort()
|
||||
val users = rpcUsers.map { it.copy(permissions = it.permissions + DRIVER_REQUIRED_PERMISSIONS) }
|
||||
val users = parameters.rpcUsers.map { it.copy(permissions = it.permissions + DRIVER_REQUIRED_PERMISSIONS) }
|
||||
val czUrlConfig = when (compatibilityZone) {
|
||||
null -> emptyMap()
|
||||
is SharedCompatibilityZoneParams ->
|
||||
@ -308,7 +240,8 @@ class DriverDSLImpl(
|
||||
emptyMap()
|
||||
}
|
||||
|
||||
val flowOverrideConfig = FlowOverrideConfig(flowOverrides.entries.map { FlowOverride(it.key.canonicalName, it.value.canonicalName) })
|
||||
val flowOverrideConfig = FlowOverrideConfig(parameters.flowOverrides.map { FlowOverride(it.key.canonicalName, it.value.canonicalName) })
|
||||
|
||||
val overrides = configOf(
|
||||
NodeConfiguration::myLegalName.name to name.toString(),
|
||||
NodeConfiguration::p2pAddress.name to p2pAddress.toString(),
|
||||
@ -316,17 +249,17 @@ class DriverDSLImpl(
|
||||
"rpcSettings.adminAddress" to rpcAdminAddress.toString(),
|
||||
NodeConfiguration::useTestClock.name to useTestClock,
|
||||
NodeConfiguration::rpcUsers.name to if (users.isEmpty()) defaultRpcUserList else users.map { it.toConfig().root().unwrapped() },
|
||||
NodeConfiguration::verifierType.name to verifierType.name,
|
||||
NodeConfiguration::verifierType.name to parameters.verifierType.name,
|
||||
"enterpriseConfiguration.tuning.flowThreadPoolSize" to "1",
|
||||
NodeConfiguration::flowOverrides.name to flowOverrideConfig.toConfig().root().unwrapped(),
|
||||
NodeConfiguration::enableSNI.name to enableSNI
|
||||
) + czUrlConfig + jmxConfig + customOverrides
|
||||
) + czUrlConfig + jmxConfig + parameters.customOverrides
|
||||
val config = NodeConfig(ConfigHelper.loadConfig(
|
||||
baseDirectory = baseDirectory(name),
|
||||
allowMissingConfig = true,
|
||||
configOverrides = if (overrides.hasPath("devMode")) overrides else overrides + mapOf("devMode" to true)
|
||||
)).checkAndOverrideForInMemoryDB()
|
||||
return startNodeInternal(config, webAddress, startInSameProcess, maximumHeapSize, localNetworkMap, additionalCordapps, regenerateCordappsOnStart, signCordapps, bytemanPort)
|
||||
return startNodeInternal(config, webAddress, localNetworkMap, parameters, signCordapps, bytemanPort)
|
||||
}
|
||||
|
||||
private fun startNodeRegistration(
|
||||
@ -543,9 +476,7 @@ class DriverDSLImpl(
|
||||
return startRegisteredNode(
|
||||
spec.name,
|
||||
localNetworkMap,
|
||||
spec.rpcUsers,
|
||||
spec.verifierType,
|
||||
customOverrides = notaryConfig + customOverrides
|
||||
NodeParameters(rpcUsers = spec.rpcUsers, verifierType = spec.verifierType, customOverrides = notaryConfig + customOverrides)
|
||||
).map { listOf(it) }
|
||||
}
|
||||
|
||||
@ -571,9 +502,8 @@ class DriverDSLImpl(
|
||||
val firstNodeFuture = startRegisteredNode(
|
||||
nodeNames[0],
|
||||
localNetworkMap,
|
||||
spec.rpcUsers,
|
||||
spec.verifierType,
|
||||
customOverrides = notaryConfig(clusterAddress))
|
||||
NodeParameters(rpcUsers = spec.rpcUsers, verifierType = spec.verifierType, customOverrides = notaryConfig(clusterAddress))
|
||||
)
|
||||
|
||||
// All other nodes will join the cluster
|
||||
val restNodeFutures = nodeNames.drop(1).map {
|
||||
@ -581,9 +511,7 @@ class DriverDSLImpl(
|
||||
startRegisteredNode(
|
||||
it,
|
||||
localNetworkMap,
|
||||
spec.rpcUsers,
|
||||
spec.verifierType,
|
||||
customOverrides = notaryConfig(nodeAddress, clusterAddress)
|
||||
NodeParameters(rpcUsers = spec.rpcUsers, verifierType = spec.verifierType, customOverrides = notaryConfig(nodeAddress, clusterAddress))
|
||||
)
|
||||
}
|
||||
|
||||
@ -621,11 +549,8 @@ class DriverDSLImpl(
|
||||
|
||||
private fun startNodeInternal(specifiedConfig: NodeConfig,
|
||||
webAddress: NetworkHostAndPort,
|
||||
startInProcess: Boolean?,
|
||||
maximumHeapSize: String,
|
||||
localNetworkMap: LocalNetworkMap?,
|
||||
additionalCordapps: Collection<TestCordapp>,
|
||||
regenerateCordappsOnStart: Boolean = false,
|
||||
parameters: NodeParameters,
|
||||
signCordapps: Boolean = false,
|
||||
bytemanPort: Int? = null): CordaFuture<NodeHandle> {
|
||||
val visibilityHandle = networkVisibilityController.register(specifiedConfig.corda.myLegalName)
|
||||
@ -640,24 +565,24 @@ class DriverDSLImpl(
|
||||
|
||||
val useHTTPS = specifiedConfig.typesafe.run { hasPath("useHTTPS") && getBoolean("useHTTPS") }
|
||||
|
||||
val existingCorDappDirectoriesOption = if (regenerateCordappsOnStart) {
|
||||
val existingCorDappDirectories = if (parameters.regenerateCordappsOnStart) {
|
||||
emptyList()
|
||||
} else if (specifiedConfig.typesafe.hasPath(NodeConfiguration.cordappDirectoriesKey)) {
|
||||
specifiedConfig.typesafe.getStringList(NodeConfiguration.cordappDirectoriesKey)
|
||||
} else if (specifiedConfig.typesafe.hasPath(cordappDirectoriesKey)) {
|
||||
specifiedConfig.typesafe.getStringList(cordappDirectoriesKey)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
// Instead of using cordappsForAllNodes we get only these that are missing from additionalCordapps
|
||||
// This way we prevent errors when we want the same CordApp but with different config
|
||||
val appOverrides = additionalCordapps.map { it.name to it.version}.toSet()
|
||||
val appOverrides = parameters.additionalCordapps.map { it.name to it.version }.toSet()
|
||||
val baseCordapps = cordappsForAllNodes.filter { !appOverrides.contains(it.name to it.version) }
|
||||
|
||||
val cordappDirectories = existingCorDappDirectoriesOption + (baseCordapps + additionalCordapps).map { TestCordappDirectories.getJarDirectory(it, signJar = signCordapps).toString() }
|
||||
val cordappDirectories = existingCorDappDirectories + (baseCordapps + parameters.additionalCordapps).map { TestCordappDirectories.getJarDirectory(it, signJar = signCordapps).toString() }
|
||||
|
||||
val config = NodeConfig(specifiedConfig.typesafe.withValue(NodeConfiguration.cordappDirectoriesKey, ConfigValueFactory.fromIterable(cordappDirectories.toSet())))
|
||||
val config = NodeConfig(specifiedConfig.typesafe.withValue(cordappDirectoriesKey, ConfigValueFactory.fromIterable(cordappDirectories.toSet())))
|
||||
|
||||
if (startInProcess ?: startNodesInProcess) {
|
||||
if (parameters.startInSameProcess ?: startNodesInProcess) {
|
||||
val nodeAndThreadFuture = startInProcessNode(executorService, config)
|
||||
shutdownManager.registerShutdown(
|
||||
nodeAndThreadFuture.map { (node, thread) ->
|
||||
@ -684,7 +609,7 @@ class DriverDSLImpl(
|
||||
return nodeFuture
|
||||
} else {
|
||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||
val process = startOutOfProcessNode(config, quasarJarPath, debugPort, bytemanJarPath, bytemanPort, systemProperties, maximumHeapSize)
|
||||
val process = startOutOfProcessNode(config, quasarJarPath, debugPort, bytemanJarPath, bytemanPort, systemProperties, parameters.maximumHeapSize)
|
||||
|
||||
// Destroy the child process when the parent exits.This is needed even when `waitForAllNodesToFinish` is
|
||||
// true because we don't want orphaned processes in the case that the parent process is terminated by the
|
||||
@ -1269,14 +1194,15 @@ internal fun DriverParameters.cordappsForAllNodes(): Collection<TestCordapp> = c
|
||||
?: cordappsInCurrentAndAdditionalPackages(extraCordappPackagesToScan)
|
||||
|
||||
fun DriverDSL.startNode(providedName: CordaX500Name, devMode: Boolean, parameters: NodeParameters = NodeParameters()): CordaFuture<NodeHandle> {
|
||||
var customOverrides = emptyMap<String, String>()
|
||||
if (!devMode) {
|
||||
val customOverrides = if (!devMode) {
|
||||
val nodeDir = baseDirectory(providedName)
|
||||
val certificatesDirectory = nodeDir / "certificates"
|
||||
val signingCertStore = CertificateStoreStubs.Signing.withCertificatesDirectory(certificatesDirectory)
|
||||
val p2pSslConfig = CertificateStoreStubs.P2P.withCertificatesDirectory(certificatesDirectory)
|
||||
p2pSslConfig.configureDevKeyAndTrustStores(providedName, signingCertStore, certificatesDirectory)
|
||||
customOverrides = mapOf("devMode" to "false")
|
||||
parameters.customOverrides + mapOf("devMode" to "false")
|
||||
} else {
|
||||
parameters.customOverrides
|
||||
}
|
||||
return startNode(parameters, providedName = providedName, customOverrides = customOverrides)
|
||||
return startNode(parameters.copy(providedName = providedName, customOverrides = customOverrides))
|
||||
}
|
||||
|
@ -90,16 +90,16 @@ class ExplorerSimulation(private val options: OptionSet) {
|
||||
val bob = startNode(providedName = BOB_NAME, rpcUsers = listOf(user))
|
||||
val ukBankName = CordaX500Name(organisation = "UK Bank Plc", locality = "London", country = "GB")
|
||||
val usaBankName = CordaX500Name(organisation = "USA Bank Corp", locality = "New York", country = "US")
|
||||
val issuerGBP = startNode(
|
||||
val issuerGBP = startNode(NodeParameters(
|
||||
providedName = ukBankName,
|
||||
rpcUsers = listOf(manager),
|
||||
additionalCordapps = listOf(FINANCE_CORDAPP.withConfig(mapOf("issuableCurrencies" to listOf("GBP"))))
|
||||
)
|
||||
val issuerUSD = startNode(
|
||||
))
|
||||
val issuerUSD = startNode(NodeParameters(
|
||||
providedName = usaBankName,
|
||||
rpcUsers = listOf(manager),
|
||||
additionalCordapps = listOf(FINANCE_CORDAPP.withConfig(mapOf("issuableCurrencies" to listOf("USD"))))
|
||||
)
|
||||
))
|
||||
val bno = startNode(providedName = IOUFlow.allowedMembershipName, rpcUsers = listOf(user))
|
||||
|
||||
notaryNode = defaultNotaryNode.get()
|
||||
|
Loading…
x
Reference in New Issue
Block a user