diff --git a/confidential-identities/src/test/kotlin/net/corda/confidential/SwapIdentitiesFlowTests.kt b/confidential-identities/src/test/kotlin/net/corda/confidential/SwapIdentitiesFlowTests.kt index 8030469fe5..8e73042899 100644 --- a/confidential-identities/src/test/kotlin/net/corda/confidential/SwapIdentitiesFlowTests.kt +++ b/confidential-identities/src/test/kotlin/net/corda/confidential/SwapIdentitiesFlowTests.kt @@ -13,7 +13,7 @@ class SwapIdentitiesFlowTests { @Test fun `issue key`() { // We run this in parallel threads to help catch any race conditions that may exist. - val mockNet = MockNetwork(false, true) + val mockNet = MockNetwork(threadPerNode = true) // Set up values we'll need val notaryNode = mockNet.createNotaryNode() @@ -53,7 +53,7 @@ class SwapIdentitiesFlowTests { @Test fun `verifies identity name`() { // We run this in parallel threads to help catch any race conditions that may exist. - val mockNet = MockNetwork(false, true) + val mockNet = MockNetwork(threadPerNode = true) // Set up values we'll need val notaryNode = mockNet.createNotaryNode(DUMMY_NOTARY.name) @@ -78,7 +78,7 @@ class SwapIdentitiesFlowTests { @Test fun `verifies signature`() { // We run this in parallel threads to help catch any race conditions that may exist. - val mockNet = MockNetwork(false, true) + val mockNet = MockNetwork(threadPerNode = true) // Set up values we'll need val notaryNode = mockNet.createNotaryNode(DUMMY_NOTARY.name) diff --git a/docs/source/key-concepts-contract-constraints.rst b/docs/source/key-concepts-contract-constraints.rst index edd4c6694d..35db806193 100644 --- a/docs/source/key-concepts-contract-constraints.rst +++ b/docs/source/key-concepts-contract-constraints.rst @@ -95,9 +95,9 @@ to specify JAR URLs in the case that the CorDapp(s) involved in testing already MockNetwork/MockNode ******************** -The most simple way to ensure that a vanilla instance of a MockNode generates the correct CorDapps is to make a call -to ``setCordappPackages`` before the MockNetwork/Node are created and then ``unsetCordappPackages`` after the test -has finished. These calls will cause the ``AbstractNode`` to use the named packages as sources for CorDapps. All files +The most simple way to ensure that a vanilla instance of a MockNode generates the correct CorDapps is to use the +``cordappPackages`` constructor parameter (Kotlin) or the ``setCordappPackages`` method on ``MockNetworkParameters`` (Java) +when creating the MockNetwork. This will cause the ``AbstractNode`` to use the named packages as sources for CorDapps. All files within those packages will be zipped into a JAR and added to the attachment store and loaded as CorDapps by the ``CordappLoader``. An example of this usage would be: @@ -108,17 +108,7 @@ within those packages will be zipped into a JAR and added to the attachment stor @Before void setup() { - // The ordering of the two below lines is important - if the MockNetwork is created before the nodes and network - // are created the CorDapps will not be loaded into the MockNodes correctly. - setCordappPackages(Arrays.asList("com.domain.cordapp")) - network = new MockNetwork() - } - - @After - void teardown() { - // This must be called at the end otherwise the global state set by setCordappPackages may leak into future - // tests in the same test runner environment. - unsetCordappPackages() + network = new MockNetwork(new MockNetworkParameters().setCordappPackages(Arrays.asList("com.domain.cordapp"))) } ... // Your tests go here diff --git a/docs/source/upgrade-notes.rst b/docs/source/upgrade-notes.rst index 0040c48e05..1dcb0d72b4 100644 --- a/docs/source/upgrade-notes.rst +++ b/docs/source/upgrade-notes.rst @@ -25,6 +25,19 @@ versions you are currently using are still in force. We also strongly recommend cross referencing with the :doc:`changelog` to confirm changes. +UNRELEASED +---------- + +Testing +^^^^^^^ + +* The registration mechanism for CorDapps in ``MockNetwork`` unit tests has changed. + + It is now done via the ``cordappPackages`` constructor parameter of MockNetwork. + This takes a list of `String` values which should be the + package names of the CorDapps containing the contract verification code you wish to load. + The ``unsetCordappPackages`` method is now redundant and has been removed. + :ref:`Milestone 14 ` ------------ diff --git a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt index 93edb33b92..148ca7bbb4 100644 --- a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt @@ -99,7 +99,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) { // We run this in parallel threads to help catch any race conditions that may exist. The other tests // we run in the unit test thread exclusively to speed things up, ensure deterministic results and // allow interruption half way through. - mockNet = MockNetwork(false, true, cordappPackages = cordappPackages) + mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages) ledger(MockServices(cordappPackages), initialiseSerialization = false) { val notaryNode = mockNet.createNotaryNode() val aliceNode = mockNet.createPartyNode(ALICE_NAME) @@ -149,7 +149,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) { @Test(expected = InsufficientBalanceException::class) fun `trade cash for commercial paper fails using soft locking`() { - mockNet = MockNetwork(false, true, cordappPackages = cordappPackages) + mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages) ledger(MockServices(cordappPackages), initialiseSerialization = false) { val notaryNode = mockNet.createNotaryNode() val aliceNode = mockNet.createPartyNode(ALICE_NAME) @@ -205,7 +205,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) { @Test fun `shutdown and restore`() { - mockNet = MockNetwork(false, cordappPackages = cordappPackages) + mockNet = MockNetwork(cordappPackages = cordappPackages) ledger(MockServices(cordappPackages), initialiseSerialization = false) { val notaryNode = mockNet.createNotaryNode() val aliceNode = mockNet.createPartyNode(ALICE_NAME) @@ -326,7 +326,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) { @Test fun `check dependencies of sale asset are resolved`() { - mockNet = MockNetwork(false, cordappPackages = cordappPackages) + mockNet = MockNetwork(cordappPackages = cordappPackages) val notaryNode = mockNet.createNotaryNode() val aliceNode = makeNodeWithTracking(ALICE_NAME) val bobNode = makeNodeWithTracking(BOB_NAME) @@ -433,7 +433,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) { @Test fun `track works`() { - mockNet = MockNetwork(false, cordappPackages = cordappPackages) + mockNet = MockNetwork(cordappPackages = cordappPackages) val notaryNode = mockNet.createNotaryNode() val aliceNode = makeNodeWithTracking(ALICE_NAME) val bobNode = makeNodeWithTracking(BOB_NAME) @@ -515,7 +515,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) { @Test fun `dependency with error on buyer side`() { - mockNet = MockNetwork(false, cordappPackages = cordappPackages) + mockNet = MockNetwork(cordappPackages = cordappPackages) ledger(MockServices(cordappPackages), initialiseSerialization = false) { runWithError(true, false, "at least one cash input") } @@ -523,7 +523,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) { @Test fun `dependency with error on seller side`() { - mockNet = MockNetwork(false, cordappPackages = cordappPackages) + mockNet = MockNetwork(cordappPackages = cordappPackages) ledger(MockServices(cordappPackages), initialiseSerialization = false) { runWithError(false, true, "Issuances have a time-window") } diff --git a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/simulation/Simulation.kt b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/simulation/Simulation.kt index b9abcd6538..19c5750d65 100644 --- a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/simulation/Simulation.kt +++ b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/simulation/Simulation.kt @@ -140,7 +140,10 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, } } - val mockNet = MockNetwork(networkSendManuallyPumped, runAsync, cordappPackages = listOf("net.corda.irs.contract", "net.corda.finance.contract")) + val mockNet = MockNetwork( + networkSendManuallyPumped = networkSendManuallyPumped, + threadPerNode = runAsync, + cordappPackages = listOf("net.corda.irs.contract", "net.corda.finance.contract")) // This one must come first. val networkMap = mockNet.startNetworkMapNode(nodeFactory = NetworkMapNodeFactory) val notary = mockNet.createNotaryNode(validating = false, nodeFactory = NotaryNodeFactory) diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt index b7eec16259..d6733b1576 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt @@ -272,9 +272,8 @@ sealed class PortAllocation { } } -/** - * Helper builder for configuring a [Node] from Java. - */ +/** Helper builder for configuring a [Node] from Java. */ +@Suppress("unused") data class NodeParameters( val providedName: CordaX500Name? = null, val rpcUsers: List = emptyList(), @@ -366,9 +365,8 @@ fun driver( return driver(defaultParameters = parameters, dsl = dsl) } -/** - * Helper builder for configuring a [driver] from Java. - */ +/** Helper builder for configuring a [driver] from Java. */ +@Suppress("unused") data class DriverParameters( val isDebug: Boolean = false, val driverDirectory: Path = Paths.get("build", getTimestampAsDirectoryName()), diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt index 1c8b4635cc..f574d4d9bb 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt @@ -61,6 +61,23 @@ fun StartedNode.pumpReceive(block: Boolean = false): InMem return (network as InMemoryMessagingNetwork.InMemoryMessaging).pumpReceive(block) } +/** Helper builder for configuring a [MockNetwork] from Java. */ +@Suppress("unused") +data class MockNetworkParameters( + val networkSendManuallyPumped: Boolean = false, + val threadPerNode: Boolean = false, + val servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random(), + val defaultFactory: MockNetwork.Factory<*> = MockNetwork.DefaultFactory, + val initialiseSerialization: Boolean = true, + val cordappPackages: List = emptyList()) { + fun setNetworkSendManuallyPumped(networkSendManuallyPumped: Boolean) = copy(networkSendManuallyPumped = networkSendManuallyPumped) + fun setThreadPerNode(threadPerNode: Boolean) = copy(threadPerNode = threadPerNode) + fun setServicePeerAllocationStrategy(servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy) = copy(servicePeerAllocationStrategy = servicePeerAllocationStrategy) + fun setDefaultFactory(defaultFactory: MockNetwork.Factory<*>) = copy(defaultFactory = defaultFactory) + fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization) + fun setCordappPackages(cordappPackages: List) = copy(cordappPackages = cordappPackages) +} + /** * A mock node brings up a suite of in-memory services in a fast manner suitable for unit testing. * Components that do IO are either swapped out for mocks, or pointed to a [Jimfs] in memory filesystem or an in @@ -74,13 +91,16 @@ fun StartedNode.pumpReceive(block: Boolean = false): InMem * * LogHelper.setLevel("+messages") */ -class MockNetwork(private val networkSendManuallyPumped: Boolean = false, - private val threadPerNode: Boolean = false, - servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = - InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random(), - private val defaultFactory: Factory<*> = MockNetwork.DefaultFactory, - private val initialiseSerialization: Boolean = true, - private val cordappPackages: List = emptyList()) : Closeable { +class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParameters(), + private val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped, + private val threadPerNode: Boolean = defaultParameters.threadPerNode, + servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy, + private val defaultFactory: Factory<*> = defaultParameters.defaultFactory, + private val initialiseSerialization: Boolean = defaultParameters.initialiseSerialization, + private val cordappPackages: List = defaultParameters.cordappPackages) : Closeable { + /** Helper constructor for creating a [MockNetwork] with custom parameters from Java. */ + constructor(parameters: MockNetworkParameters) : this(defaultParameters = parameters) + companion object { // TODO In future PR we're removing the concept of network map node so the details of this mock are not important. val MOCK_NET_MAP = Party(CordaX500Name(organisation = "Mock Network Map", locality = "Madrid", country = "ES"), DUMMY_KEY_1.public)