From a7358ffa1a988c47cc7ca4d5c3cc9c18032aa9ee Mon Sep 17 00:00:00 2001 From: Chris Rankin Date: Wed, 1 Apr 2020 17:42:29 +0100 Subject: [PATCH] CORDA-3643: Initialise MockNetwork's serialisation environment with all custom cordapps. (#6115) --- .../node/MockNetworkCustomSerializerTest.kt | 63 ++++++++++++++++++ .../MockNetworkSerializationWhitelistTest.kt | 66 +++++++++++++++++++ .../node/internal/InternalMockNetwork.kt | 24 +++++-- 3 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 node/src/integration-test/kotlin/net/corda/node/MockNetworkCustomSerializerTest.kt create mode 100644 node/src/integration-test/kotlin/net/corda/node/MockNetworkSerializationWhitelistTest.kt diff --git a/node/src/integration-test/kotlin/net/corda/node/MockNetworkCustomSerializerTest.kt b/node/src/integration-test/kotlin/net/corda/node/MockNetworkCustomSerializerTest.kt new file mode 100644 index 0000000000..abb7ea49a4 --- /dev/null +++ b/node/src/integration-test/kotlin/net/corda/node/MockNetworkCustomSerializerTest.kt @@ -0,0 +1,63 @@ +package net.corda.node + +import net.corda.contracts.serialization.custom.Currantsy +import net.corda.core.contracts.TransactionVerificationException.ContractRejection +import net.corda.flows.serialization.custom.CustomSerializerFlow +import net.corda.testing.common.internal.testNetworkParameters +import net.corda.testing.node.MockNetwork +import net.corda.testing.node.MockNetworkParameters +import net.corda.testing.node.internal.cordappWithPackages +import org.assertj.core.api.Assertions.assertThat +import org.junit.After +import org.junit.Before +import org.junit.BeforeClass +import org.junit.Test +import java.util.concurrent.ExecutionException +import kotlin.test.assertFailsWith + +@Suppress("FunctionName") +class MockNetworkCustomSerializerTest { + companion object { + private const val CURRANTS = 5000L + + @JvmField + val currantsy = Currantsy(CURRANTS) + + @BeforeClass + @JvmStatic + fun checkData() { + assertNotCordaSerializable() + } + } + + private lateinit var mockNetwork: MockNetwork + + @Before + fun setup() { + mockNetwork = MockNetwork( + MockNetworkParameters( + networkParameters = testNetworkParameters(minimumPlatformVersion = 4), + cordappsForAllNodes = listOf( + cordappWithPackages("net.corda.flows.serialization.custom").signed(), + cordappWithPackages("net.corda.contracts.serialization.custom").signed() + ) + ) + ) + } + + @After + fun shutdown() { + mockNetwork.stopNodes() + } + + @Test(timeout = 300_000) + fun `flow with custom serializer mock network`() { + val a = mockNetwork.createPartyNode() + val ex = assertFailsWith { + a.startFlow(CustomSerializerFlow(currantsy)).get() + } + assertThat(ex) + .hasCauseExactlyInstanceOf(ContractRejection::class.java) + .hasMessageContaining("Too many currants! $currantsy is unraisinable!") + } +} \ No newline at end of file diff --git a/node/src/integration-test/kotlin/net/corda/node/MockNetworkSerializationWhitelistTest.kt b/node/src/integration-test/kotlin/net/corda/node/MockNetworkSerializationWhitelistTest.kt new file mode 100644 index 0000000000..31d8787505 --- /dev/null +++ b/node/src/integration-test/kotlin/net/corda/node/MockNetworkSerializationWhitelistTest.kt @@ -0,0 +1,66 @@ +package net.corda.node + +import net.corda.contracts.serialization.whitelist.WhitelistData +import net.corda.core.contracts.TransactionVerificationException.ContractRejection +import net.corda.flows.serialization.whitelist.WhitelistFlow +import net.corda.testing.common.internal.testNetworkParameters +import net.corda.testing.node.MockNetwork +import net.corda.testing.node.MockNetworkParameters +import net.corda.testing.node.internal.cordappWithPackages +import org.assertj.core.api.Assertions.assertThat +import org.junit.After +import org.junit.Before +import org.junit.BeforeClass +import org.junit.Test +import java.util.concurrent.ExecutionException +import kotlin.test.assertFailsWith + +@Suppress("FunctionName") +class MockNetworkSerializationWhitelistTest { + companion object { + private const val DATA = 654321L + + @JvmField + val contractCordapp = cordappWithPackages("net.corda.contracts.serialization.whitelist").signed() + + @JvmField + val workflowCordapp = cordappWithPackages("net.corda.flows.serialization.whitelist").signed() + + @JvmField + val badData = WhitelistData(DATA) + + @BeforeClass + @JvmStatic + fun checkData() { + assertNotCordaSerializable() + } + } + + private lateinit var mockNetwork: MockNetwork + + @Before + fun setup() { + mockNetwork = MockNetwork( + MockNetworkParameters( + networkParameters = testNetworkParameters(minimumPlatformVersion = 4), + cordappsForAllNodes = listOf(contractCordapp, workflowCordapp) + ) + ) + } + + @After + fun shutdown() { + mockNetwork.stopNodes() + } + + @Test(timeout = 300_000) + fun `test serialization whitelist with mock network`() { + val node = mockNetwork.createPartyNode() + val ex = assertFailsWith { + node.startFlow(WhitelistFlow(badData)).get() + } + assertThat(ex) + .hasCauseExactlyInstanceOf(ContractRejection::class.java) + .hasMessageContaining("WhitelistData $badData exceeds maximum value!") + } +} \ No newline at end of file diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt index 855db08b1f..5cac265b8b 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt @@ -62,6 +62,7 @@ import rx.Observable import rx.Scheduler import rx.internal.schedulers.CachedThreadScheduler import java.math.BigInteger +import java.net.URLClassLoader import java.nio.file.Path import java.nio.file.Paths import java.security.PublicKey @@ -148,6 +149,14 @@ open class InternalMockNetwork(cordappPackages: List = emptyList(), val defaultFactory: (MockNodeArgs) -> MockNode = { args -> MockNode(args) }, cordappsForAllNodes: Collection = emptySet(), val autoVisibleNodes: Boolean = true) : AutoCloseable { + companion object { + fun createCordappClassLoader(cordapps: Collection?): URLClassLoader? { + if (cordapps == null || cordapps.isEmpty()) { + return null + } + return URLClassLoader(cordapps.map { it.jarFile.toUri().toURL() }.toTypedArray()) + } + } var networkParameters: NetworkParameters = initialNetworkParameters private set @@ -168,9 +177,12 @@ open class InternalMockNetwork(cordappPackages: List = emptyList(), private val networkId = random63BitValue() private val networkParametersCopier: NetworkParametersCopier private val _nodes = mutableListOf() - private val serializationEnv = checkNotNull(setDriverSerialization()) { "Using more than one mock network simultaneously is not supported." } private val sharedUserCount = AtomicInteger(0) private val combinedCordappsForAllNodes = cordappsForPackages(cordappPackages) + cordappsForAllNodes + private val cordappClassLoader = createCordappClassLoader(combinedCordappsForAllNodes) + private val serializationEnv = checkNotNull(setDriverSerialization(cordappClassLoader)) { + "Using more than one mock network simultaneously is not supported." + } /** A read only view of the current set of nodes. */ val nodes: List get() = _nodes @@ -565,11 +577,13 @@ open class InternalMockNetwork(cordappPackages: List = emptyList(), } fun stopNodes() { - // Serialization env must be unset even if other parts of this method fail. - serializationEnv.use { - nodes.forEach { it.started?.dispose() } + cordappClassLoader.use { _ -> + // Serialization env must be unset even if other parts of this method fail. + serializationEnv.use { + nodes.forEach { it.started?.dispose() } + } + messagingNetwork.stop() } - messagingNetwork.stop() } /** Block until all scheduled activity, active flows and network activity has ceased. */