From ba7514644608db983722330f557e44f9bf91f42e Mon Sep 17 00:00:00 2001 From: Andrzej Cichocki Date: Wed, 25 Oct 2017 14:33:36 +0100 Subject: [PATCH] CORDA-716 Unpollute MockNode with Simulation-specific code (#1945) --- .../net/corda/netmap/NetworkMapVisualiser.kt | 3 +- .../net/corda/netmap/VisualiserViewModel.kt | 1 + .../net/corda/netmap/simulation/Simulation.kt | 51 ++++++++----------- .../kotlin/net/corda/testing/node/MockNode.kt | 17 +------ 4 files changed, 24 insertions(+), 48 deletions(-) diff --git a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/NetworkMapVisualiser.kt b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/NetworkMapVisualiser.kt index ee1ca11da9..7034e4b4e8 100644 --- a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/NetworkMapVisualiser.kt +++ b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/NetworkMapVisualiser.kt @@ -15,7 +15,6 @@ import net.corda.core.serialization.deserialize import net.corda.core.utilities.ProgressTracker import net.corda.netmap.VisualiserViewModel.Style import net.corda.netmap.simulation.IRSSimulation -import net.corda.netmap.simulation.Simulation import net.corda.node.services.network.NetworkMapService import net.corda.node.services.statemachine.SessionConfirm import net.corda.node.services.statemachine.SessionEnd @@ -118,7 +117,7 @@ class NetworkMapVisualiser : Application() { } } // Pulse all parties in a trade when the trade completes - simulation.doneSteps.observeOn(uiThread).subscribe { nodes: Collection -> + simulation.doneSteps.observeOn(uiThread).subscribe { nodes: Collection -> nodes.forEach { viewModel.nodesToWidgets[it]!!.longPulseAnim.play() } } diff --git a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/VisualiserViewModel.kt b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/VisualiserViewModel.kt index f8f9c1f625..eda67a0277 100644 --- a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/VisualiserViewModel.kt +++ b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/VisualiserViewModel.kt @@ -11,6 +11,7 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.utilities.ProgressTracker import net.corda.finance.utils.ScreenCoordinate import net.corda.netmap.simulation.IRSSimulation +import net.corda.netmap.simulation.place import net.corda.testing.chooseIdentity import net.corda.testing.node.MockNetwork import java.util.* 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 157f93eb58..0533308ec2 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 @@ -4,16 +4,15 @@ import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.whenever import net.corda.core.flows.FlowLogic import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.uncheckedCast import net.corda.core.utilities.ProgressTracker import net.corda.finance.utils.CityDatabase -import net.corda.finance.utils.WorldMapLocation import net.corda.irs.api.NodeInterestRates import net.corda.node.internal.StartedNode import net.corda.node.services.statemachine.StateMachineManager import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_REGULATOR import net.corda.testing.node.* +import net.corda.testing.node.MockNetwork.MockNode import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import rx.Observable import rx.subjects.PublishSubject @@ -26,6 +25,8 @@ import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture.allOf import java.util.concurrent.Future +internal val MockNode.place get() = configuration.myLegalName.locality.let { CityDatabase[it] }!! + /** * Base class for network simulations that are based on the unit test / mock environment. * @@ -49,24 +50,12 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, val bankLocations = listOf(Pair("London", "GB"), Pair("Frankfurt", "DE"), Pair("Rome", "IT")) - // This puts together a mock network of SimulatedNodes. - open class SimulatedNode(args: MockNodeArgs) : MockNetwork.MockNode(args) { - override val started: StartedNode? get() = uncheckedCast(super.started) - override fun findMyLocation(): WorldMapLocation? { - return configuration.myLegalName.locality.let { CityDatabase[it] } - } - } - - private object SimulatedNodeFactory : MockNetwork.Factory { - override fun create(args: MockNodeArgs) = SimulatedNode(args) - } - - object RatesOracleFactory : MockNetwork.Factory { + object RatesOracleFactory : MockNetwork.Factory { // TODO: Make a more realistic legal name val RATES_SERVICE_NAME = CordaX500Name(organisation = "Rates Service Provider", locality = "Madrid", country = "ES") - override fun create(args: MockNodeArgs): SimulatedNode { - return object : SimulatedNode(args) { + override fun create(args: MockNodeArgs): MockNode { + return object : MockNode(args) { override fun start() = super.start().apply { registerInitiatedFlow(NodeInterestRates.FixQueryHandler::class.java) registerInitiatedFlow(NodeInterestRates.FixSignHandler::class.java) @@ -84,28 +73,28 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, networkSendManuallyPumped = networkSendManuallyPumped, threadPerNode = runAsync, cordappPackages = listOf("net.corda.irs.contract", "net.corda.finance.contract", "net.corda.irs")) - val notary = mockNet.createNotaryNode(defaultParams.copy(legalName = DUMMY_NOTARY.name), false, SimulatedNodeFactory) + val notary = mockNet.createNotaryNode(DUMMY_NOTARY.name, false) // TODO: Regulatory nodes don't actually exist properly, this is a last minute demo request. // So we just fire a message at a node that doesn't know how to handle it, and it'll ignore it. // But that's fine for visualisation purposes. - val regulators = listOf(mockNet.createUnstartedNode(defaultParams.copy(legalName = DUMMY_REGULATOR.name), SimulatedNodeFactory)) + val regulators = listOf(mockNet.createUnstartedNode(defaultParams.copy(legalName = DUMMY_REGULATOR.name))) val ratesOracle = mockNet.createUnstartedNode(defaultParams.copy(legalName = RatesOracleFactory.RATES_SERVICE_NAME), RatesOracleFactory) // All nodes must be in one of these two lists for the purposes of the visualiser tool. - val serviceProviders: List = listOf(notary.internals, ratesOracle) - val banks: List = bankLocations.mapIndexed { i, (city, country) -> + val serviceProviders: List = listOf(notary.internals, ratesOracle) + val banks: List = bankLocations.mapIndexed { i, (city, country) -> val legalName = CordaX500Name(organisation = "Bank ${'A' + i}", locality = city, country = country) // Use deterministic seeds so the simulation is stable. Needed so that party owning keys are stable. - mockNet.createUnstartedNode(defaultParams.copy(legalName = legalName, entropyRoot = BigInteger.valueOf(i.toLong())), SimulatedNodeFactory) + mockNet.createUnstartedNode(defaultParams.copy(legalName = legalName, entropyRoot = BigInteger.valueOf(i.toLong()))) } val clocks = (serviceProviders + regulators + banks).map { it.platformClock as TestClock } // These are used from the network visualiser tool. - private val _allFlowSteps = PublishSubject.create>() - private val _doneSteps = PublishSubject.create>() + private val _allFlowSteps = PublishSubject.create>() + private val _doneSteps = PublishSubject.create>() @Suppress("unused") - val allFlowSteps: Observable> = _allFlowSteps + val allFlowSteps: Observable> = _allFlowSteps @Suppress("unused") - val doneSteps: Observable> = _doneSteps + val doneSteps: Observable> = _doneSteps private var pumpCursor = 0 @@ -133,7 +122,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, * A place for simulations to stash human meaningful text about what the node is "thinking", which might appear * in the UI somewhere. */ - val extraNodeLabels: MutableMap = Collections.synchronizedMap(HashMap()) + val extraNodeLabels: MutableMap = Collections.synchronizedMap(HashMap()) /** * Iterates the simulation by one step. @@ -164,7 +153,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, return null } - protected fun showProgressFor(nodes: List>) { + protected fun showProgressFor(nodes: List>) { nodes.forEach { node -> node.smm.changes.filter { it is StateMachineManager.Change.Add }.subscribe { linkFlowProgress(node.internals, it.logic) @@ -172,7 +161,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, } } - private fun linkFlowProgress(node: SimulatedNode, flow: FlowLogic<*>) { + private fun linkFlowProgress(node: MockNode, flow: FlowLogic<*>) { val pt = flow.progressTracker ?: return pt.changes.subscribe { change: ProgressTracker.Change -> // Runs on node thread. @@ -181,14 +170,14 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, } - protected fun showConsensusFor(nodes: List) { + protected fun showConsensusFor(nodes: List) { val node = nodes.first() node.started!!.smm.changes.filter { it is StateMachineManager.Change.Add }.first().subscribe { linkConsensus(nodes, it.logic) } } - private fun linkConsensus(nodes: Collection, flow: FlowLogic<*>) { + private fun linkConsensus(nodes: Collection, flow: FlowLogic<*>) { flow.progressTracker?.changes?.subscribe { _: ProgressTracker.Change -> // Runs on node thread. if (flow.progressTracker!!.currentStep == ProgressTracker.DONE) { 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 71a9148900..e0bec83c67 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 @@ -17,12 +17,10 @@ import net.corda.core.messaging.RPCOps import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.node.services.IdentityService import net.corda.core.node.services.KeyManagementService -import net.corda.core.node.services.PartyInfo import net.corda.core.serialization.SerializationWhitelist import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.loggerFor -import net.corda.finance.utils.WorldMapLocation import net.corda.node.internal.AbstractNode import net.corda.node.internal.StartedNode import net.corda.node.internal.cordapp.CordappLoader @@ -54,7 +52,6 @@ import java.math.BigInteger import java.nio.file.Path import java.security.KeyPair import java.security.PublicKey -import java.util.* import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger @@ -241,9 +238,6 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete // It's OK to not have a network map service in the mock network. override fun noNetworkMapConfigured() = doneFuture(Unit) - // There is no need to slow down the unit tests by initialising CityDatabase - open fun findMyLocation(): WorldMapLocation? = null // It's left only for NetworkVisualiserSimulation - override fun makeTransactionVerifierService() = InMemoryTransactionVerifierService(1) override fun myAddresses() = emptyList() @@ -253,13 +247,6 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete val testSerializationWhitelists by lazy { super.serializationWhitelists.toMutableList() } override val serializationWhitelists: List get() = testSerializationWhitelists - - // This does not indirect through the NodeInfo object so it can be called before the node is started. - // It is used from the network visualiser tool. - @Suppress("unused") - val place: WorldMapLocation - get() = findMyLocation()!! - private var dbCloser: (() -> Any?)? = null override fun initialiseDatabasePersistence(schemaService: SchemaService, insideTransaction: () -> T) = super.initialiseDatabasePersistence(schemaService) { dbCloser = database::close @@ -430,12 +417,12 @@ fun network(nodesCount: Int, action: MockNetwork.(nodes: List.setMessagingServiceSpy(messagingServiceSpy: MessagingServiceSpy) { internals.setMessagingServiceSpy(messagingServiceSpy)