From 0e47e53b609a46a0f360b87a6d667db3bc7d6156 Mon Sep 17 00:00:00 2001 From: Viktor Kolomeyko Date: Tue, 10 Oct 2017 12:28:19 +0100 Subject: [PATCH] Make AttachmentLoadingTests more stable (#1810) --- .../node/services/AttachmentLoadingTests.kt | 64 +++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt index e5a79d7d5c..3c15d0aec5 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt @@ -16,6 +16,7 @@ import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.loggerFor +import net.corda.core.utilities.seconds import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.internal.cordapp.CordappProviderImpl import net.corda.nodeapi.User @@ -25,6 +26,7 @@ import net.corda.testing.TestDependencyInjectionBase import net.corda.testing.driver.DriverDSLExposedInterface import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver +import net.corda.testing.eventually import net.corda.testing.node.MockServices import org.junit.Assert.assertEquals import org.junit.Before @@ -53,6 +55,37 @@ class AttachmentLoadingTests : TestDependencyInjectionBase() { val flowInitiatorClass = Class.forName("net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator", true, URLClassLoader(arrayOf(isolatedJAR))) .asSubclass(FlowLogic::class.java) + + private fun DriverDSLExposedInterface.createTwoNodesAndNotary(): List { + val adminUser = User("admin", "admin", permissions = setOf("ALL")) + val nodes = listOf( + startNode(providedName = bankAName, rpcUsers = listOf(adminUser)), + startNode(providedName = bankBName, rpcUsers = listOf(adminUser)), + startNotaryNode(providedName = notaryName, rpcUsers = listOf(adminUser), validating = false) + ).transpose().getOrThrow() // Wait for all nodes to start up. + nodes.forEach { it.rpc.waitUntilNetworkReady().getOrThrow() } + return nodes + } + + private fun DriverDSLExposedInterface.installIsolatedCordappTo(nodeName: CordaX500Name) { + // Copy the app jar to the first node. The second won't have it. + val path = (baseDirectory(nodeName.toString()) / "plugins").createDirectories() / "isolated.jar" + logger.info("Installing isolated jar to $path") + isolatedJAR.openStream().buffered().use { input -> + Files.newOutputStream(path).buffered().use { output -> + input.copyTo(output) + } + } + } + + // Due to cluster instability after nodes been started it may take some time to all the nodes to become available + // *and* discover each other to reliably communicate. Hence, eventual nature of the test. + // TODO: Remove this method and usages of it once NetworkMap service been re-worked + private fun eventuallyPassingTest(block: () -> Unit) { + eventually(30.seconds) { + block() + } + } } private lateinit var services: Services @@ -85,9 +118,10 @@ class AttachmentLoadingTests : TestDependencyInjectionBase() { driver(initialiseSerialization = false) { installIsolatedCordappTo(bankAName) val (bankA, bankB, _) = createTwoNodesAndNotary() - - assertFailsWith("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() + eventuallyPassingTest { + assertFailsWith("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() + } } } } @@ -98,29 +132,9 @@ class AttachmentLoadingTests : TestDependencyInjectionBase() { installIsolatedCordappTo(bankAName) installIsolatedCordappTo(bankBName) val (bankA, bankB, _) = createTwoNodesAndNotary() - bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow() - } - } - - private fun DriverDSLExposedInterface.installIsolatedCordappTo(nodeName: CordaX500Name) { - // Copy the app jar to the first node. The second won't have it. - val path = (baseDirectory(nodeName.toString()) / "plugins").createDirectories() / "isolated.jar" - logger.info("Installing isolated jar to $path") - isolatedJAR.openStream().buffered().use { input -> - Files.newOutputStream(path).buffered().use { output -> - input.copyTo(output) + eventuallyPassingTest { + bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow() } } } - - private fun DriverDSLExposedInterface.createTwoNodesAndNotary(): List { - val adminUser = User("admin", "admin", permissions = setOf("ALL")) - val nodes = listOf( - startNode(providedName = bankAName, rpcUsers = listOf(adminUser)), - startNode(providedName = bankBName, rpcUsers = listOf(adminUser)), - startNotaryNode(providedName = notaryName, rpcUsers = listOf(adminUser), validating = false) - ).transpose().getOrThrow() // Wait for all nodes to start up. - nodes.forEach { it.rpc.waitUntilNetworkReady().getOrThrow() } - return nodes - } }