mirror of
https://github.com/corda/corda.git
synced 2025-05-29 21:54:26 +00:00
* Don't expose StartedNode via Node Driver * Dont expose StartedNode/Abstract Node via MockNetwork * Remove internal var from constructor as it doesn't hide from public api and change to internal initialisation method * Update api * Rename MockNode to StartedMockNode to avoid confusion Update documentation Update api-current.txt * Fix typo * Fix test failure * Modify flow tests to use internal mock network and remove additional internal exposures from StartedMockNode * Fix api-current * Change InProcess and OutOfProcess to interfaces * Explicitly declare MockNetwork parameters Dont expose StateMachineManager Move affected tests to use internal mock network * Fix api-current * Changes requested via review * Fix IRS Demo address * Fix api * Remove internal attribute from classes in internal package * Remove accidentally added code * Move useHttps into NodeHandleInternal * Remove duplicated code * Update api-current * Make webAddress internal on NodeHandle * Make sure parameters in public api are explicitly specified * Use correct address in IRS Demo * Get webaddress from webserver handle * Update api-current # Conflicts: # .ci/api-current.txt
This commit is contained in:
parent
805178debc
commit
e363090f30
@ -75,7 +75,7 @@ class NodeMonitorModelTest {
|
|||||||
vaultUpdates = monitor.vaultUpdates.bufferUntilSubscribed()
|
vaultUpdates = monitor.vaultUpdates.bufferUntilSubscribed()
|
||||||
networkMapUpdates = monitor.networkMap.bufferUntilSubscribed()
|
networkMapUpdates = monitor.networkMap.bufferUntilSubscribed()
|
||||||
|
|
||||||
monitor.register(aliceNodeHandle.configuration.rpcOptions.address!!, cashUser.username, cashUser.password)
|
monitor.register(aliceNodeHandle.rpcAddress, cashUser.username, cashUser.password)
|
||||||
rpc = monitor.proxyObservable.value!!
|
rpc = monitor.proxyObservable.value!!
|
||||||
notaryParty = defaultNotaryIdentity
|
notaryParty = defaultNotaryIdentity
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ class NodeMonitorModelTest {
|
|||||||
bobNode = bobNodeHandle.nodeInfo
|
bobNode = bobNodeHandle.nodeInfo
|
||||||
val monitorBob = NodeMonitorModel()
|
val monitorBob = NodeMonitorModel()
|
||||||
stateMachineUpdatesBob = monitorBob.stateMachineUpdates.bufferUntilSubscribed()
|
stateMachineUpdatesBob = monitorBob.stateMachineUpdates.bufferUntilSubscribed()
|
||||||
monitorBob.register(bobNodeHandle.configuration.rpcOptions.address!!, cashUser.username, cashUser.password)
|
monitorBob.register(bobNodeHandle.rpcAddress, cashUser.username, cashUser.password)
|
||||||
rpcBob = monitorBob.proxyObservable.value!!
|
rpcBob = monitorBob.proxyObservable.value!!
|
||||||
runTest()
|
runTest()
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ package net.corda.core.flows;
|
|||||||
import co.paralleluniverse.fibers.Suspendable;
|
import co.paralleluniverse.fibers.Suspendable;
|
||||||
import com.google.common.primitives.Primitives;
|
import com.google.common.primitives.Primitives;
|
||||||
import net.corda.core.identity.Party;
|
import net.corda.core.identity.Party;
|
||||||
import net.corda.node.internal.StartedNode;
|
|
||||||
import net.corda.testing.core.TestConstants;
|
import net.corda.testing.core.TestConstants;
|
||||||
import net.corda.testing.node.MockNetwork;
|
import net.corda.testing.node.MockNetwork;
|
||||||
|
import net.corda.testing.node.StartedMockNode;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -21,8 +21,8 @@ import static net.corda.testing.node.NodeTestUtils.startFlow;
|
|||||||
|
|
||||||
public class FlowsInJavaTest {
|
public class FlowsInJavaTest {
|
||||||
private final MockNetwork mockNet = new MockNetwork(emptyList());
|
private final MockNetwork mockNet = new MockNetwork(emptyList());
|
||||||
private StartedNode<MockNetwork.MockNode> aliceNode;
|
private StartedMockNode aliceNode;
|
||||||
private StartedNode<MockNetwork.MockNode> bobNode;
|
private StartedMockNode bobNode;
|
||||||
private Party bob;
|
private Party bob;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -15,6 +15,7 @@ import net.corda.testing.core.BOB_NAME
|
|||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.node.MockNodeParameters
|
import net.corda.testing.node.MockNodeParameters
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -27,11 +28,11 @@ import kotlin.test.assertEquals
|
|||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class AttachmentTests {
|
class AttachmentTests {
|
||||||
lateinit var mockNet: MockNetwork
|
lateinit var mockNet: InternalMockNetwork
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
mockNet = MockNetwork(emptyList())
|
mockNet = InternalMockNetwork(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -100,7 +101,7 @@ class AttachmentTests {
|
|||||||
fun maliciousResponse() {
|
fun maliciousResponse() {
|
||||||
// Make a node that doesn't do sanity checking at load time.
|
// Make a node that doesn't do sanity checking at load time.
|
||||||
val aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME), nodeFactory = { args ->
|
val aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME), nodeFactory = { args ->
|
||||||
object : MockNetwork.MockNode(args) {
|
object : InternalMockNetwork.MockNode(args) {
|
||||||
override fun start() = super.start().apply { attachments.checkAttachmentsOnLoad = false }
|
override fun start() = super.start().apply { attachments.checkAttachmentsOnLoad = false }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -11,11 +11,11 @@ import net.corda.core.identity.groupAbstractPartyByWellKnownParty
|
|||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.core.*
|
import net.corda.testing.core.*
|
||||||
import net.corda.testing.internal.rigorousMock
|
import net.corda.testing.internal.rigorousMock
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
|
import net.corda.testing.node.StartedMockNode
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
@ -30,9 +30,9 @@ class CollectSignaturesFlowTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var aliceNode: StartedMockNode
|
||||||
private lateinit var bobNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var bobNode: StartedMockNode
|
||||||
private lateinit var charlieNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var charlieNode: StartedMockNode
|
||||||
private lateinit var alice: Party
|
private lateinit var alice: Party
|
||||||
private lateinit var bob: Party
|
private lateinit var bob: Party
|
||||||
private lateinit var charlie: Party
|
private lateinit var charlie: Party
|
||||||
|
@ -19,17 +19,14 @@ import net.corda.finance.flows.CashIssueFlow
|
|||||||
import net.corda.node.internal.SecureCordaRPCOps
|
import net.corda.node.internal.SecureCordaRPCOps
|
||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
import net.corda.node.services.Permissions.Companion.startFlow
|
import net.corda.node.services.Permissions.Companion.startFlow
|
||||||
import net.corda.testing.core.ALICE_NAME
|
|
||||||
import net.corda.testing.core.BOB_NAME
|
|
||||||
import net.corda.testing.node.User
|
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.contracts.DummyContractV2
|
import net.corda.testing.contracts.DummyContractV2
|
||||||
import net.corda.testing.node.internal.RPCDriverDSL
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.node.internal.rpcDriver
|
import net.corda.testing.core.BOB_NAME
|
||||||
import net.corda.testing.node.internal.rpcTestUser
|
|
||||||
import net.corda.testing.node.internal.startRpcClient
|
|
||||||
import net.corda.testing.node.MockNetwork
|
|
||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
|
import net.corda.testing.node.User
|
||||||
|
import net.corda.testing.node.internal.*
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork.MockNode
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -40,16 +37,16 @@ import kotlin.test.assertFailsWith
|
|||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class ContractUpgradeFlowTest {
|
class ContractUpgradeFlowTest {
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: InternalMockNetwork
|
||||||
private lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var aliceNode: StartedNode<MockNode>
|
||||||
private lateinit var bobNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var bobNode: StartedNode<MockNode>
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
private lateinit var alice: Party
|
private lateinit var alice: Party
|
||||||
private lateinit var bob: Party
|
private lateinit var bob: Party
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.finance.contracts.asset", "net.corda.core.flows"))
|
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.finance.contracts.asset", "net.corda.core.flows"))
|
||||||
aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||||
bobNode = mockNet.createPartyNode(BOB_NAME)
|
bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||||
notary = mockNet.defaultNotaryIdentity
|
notary = mockNet.defaultNotaryIdentity
|
||||||
@ -103,7 +100,7 @@ class ContractUpgradeFlowTest {
|
|||||||
|
|
||||||
val result = resultFuture.getOrThrow()
|
val result = resultFuture.getOrThrow()
|
||||||
|
|
||||||
fun check(node: StartedNode<*>) {
|
fun check(node: StartedNode<MockNode>) {
|
||||||
val nodeStx = node.database.transaction {
|
val nodeStx = node.database.transaction {
|
||||||
node.services.validatedTransactions.getTransaction(result.ref.txhash)
|
node.services.validatedTransactions.getTransaction(result.ref.txhash)
|
||||||
}
|
}
|
||||||
@ -123,7 +120,7 @@ class ContractUpgradeFlowTest {
|
|||||||
check(bobNode)
|
check(bobNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RPCDriverDSL.startProxy(node: StartedNode<*>, user: User): CordaRPCOps {
|
private fun RPCDriverDSL.startProxy(node: StartedNode<MockNode>, user: User): CordaRPCOps {
|
||||||
return startRpcClient<CordaRPCOps>(
|
return startRpcClient<CordaRPCOps>(
|
||||||
rpcAddress = startRpcServer(
|
rpcAddress = startRpcServer(
|
||||||
rpcUser = user,
|
rpcUser = user,
|
||||||
|
@ -5,6 +5,8 @@ import net.corda.core.utilities.UntrustworthyData
|
|||||||
import net.corda.core.utilities.unwrap
|
import net.corda.core.utilities.unwrap
|
||||||
import net.corda.node.internal.InitiatedFlowFactory
|
import net.corda.node.internal.InitiatedFlowFactory
|
||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
|
import net.corda.testing.node.StartedMockNode
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,14 +39,14 @@ class NoAnswer(private val closure: () -> Unit = {}) : FlowLogic<Unit>() {
|
|||||||
/**
|
/**
|
||||||
* Allows to register a flow of type [R] against an initiating flow of type [I].
|
* Allows to register a flow of type [R] against an initiating flow of type [I].
|
||||||
*/
|
*/
|
||||||
inline fun <I : FlowLogic<*>, reified R : FlowLogic<*>> StartedNode<*>.registerInitiatedFlow(initiatingFlowType: KClass<I>, crossinline construct: (session: FlowSession) -> R) {
|
inline fun <I : FlowLogic<*>, reified R : FlowLogic<*>> StartedNode<InternalMockNetwork.MockNode>.registerInitiatedFlow(initiatingFlowType: KClass<I>, crossinline construct: (session: FlowSession) -> R) {
|
||||||
internalRegisterFlowFactory(initiatingFlowType.java, InitiatedFlowFactory.Core { session -> construct(session) }, R::class.javaObjectType, true)
|
internalRegisterFlowFactory(initiatingFlowType.java, InitiatedFlowFactory.Core { session -> construct(session) }, R::class.javaObjectType, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to register a flow of type [Answer] against an initiating flow of type [I], returning a valure of type [R].
|
* Allows to register a flow of type [Answer] against an initiating flow of type [I], returning a valure of type [R].
|
||||||
*/
|
*/
|
||||||
inline fun <I : FlowLogic<*>, reified R : Any> StartedNode<*>.registerAnswer(initiatingFlowType: KClass<I>, value: R) {
|
inline fun <I : FlowLogic<*>, reified R : Any> StartedNode<InternalMockNetwork.MockNode>.registerAnswer(initiatingFlowType: KClass<I>, value: R) {
|
||||||
internalRegisterFlowFactory(initiatingFlowType.java, InitiatedFlowFactory.Core { session -> Answer(session, value) }, Answer::class.javaObjectType, true)
|
internalRegisterFlowFactory(initiatingFlowType.java, InitiatedFlowFactory.Core { session -> Answer(session, value) }, Answer::class.javaObjectType, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,15 +5,15 @@ import net.corda.core.identity.Party
|
|||||||
import net.corda.core.utilities.UntrustworthyData
|
import net.corda.core.utilities.UntrustworthyData
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.unwrap
|
import net.corda.core.utilities.unwrap
|
||||||
import net.corda.testing.node.MockNetwork
|
|
||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class ReceiveMultipleFlowTests {
|
class ReceiveMultipleFlowTests {
|
||||||
private val mockNet = MockNetwork(emptyList())
|
private val mockNet = InternalMockNetwork(emptyList())
|
||||||
private val nodes = (0..2).map { mockNet.createPartyNode() }
|
private val nodes = (0..2).map { mockNet.createPartyNode() }
|
||||||
@After
|
@After
|
||||||
fun stopNodes() {
|
fun stopNodes() {
|
||||||
|
@ -8,10 +8,10 @@ import net.corda.core.identity.Party
|
|||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.sequence
|
import net.corda.core.utilities.sequence
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
|
import net.corda.testing.node.StartedMockNode
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -28,9 +28,9 @@ import kotlin.test.assertNull
|
|||||||
// DOCSTART 3
|
// DOCSTART 3
|
||||||
class ResolveTransactionsFlowTest {
|
class ResolveTransactionsFlowTest {
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var notaryNode: StartedMockNode
|
||||||
private lateinit var megaCorpNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var megaCorpNode: StartedMockNode
|
||||||
private lateinit var miniCorpNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var miniCorpNode: StartedMockNode
|
||||||
private lateinit var megaCorp: Party
|
private lateinit var megaCorp: Party
|
||||||
private lateinit var miniCorp: Party
|
private lateinit var miniCorp: Party
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
|
@ -21,6 +21,7 @@ import net.corda.testing.core.BOB_NAME
|
|||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.node.MockNodeParameters
|
import net.corda.testing.node.MockNodeParameters
|
||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -63,14 +64,14 @@ private fun updateAttachment(attachmentId: SecureHash, data: ByteArray) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AttachmentSerializationTest {
|
class AttachmentSerializationTest {
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: InternalMockNetwork
|
||||||
private lateinit var server: StartedNode<MockNetwork.MockNode>
|
private lateinit var server: StartedNode<InternalMockNetwork.MockNode>
|
||||||
private lateinit var client: StartedNode<MockNetwork.MockNode>
|
private lateinit var client: StartedNode<InternalMockNetwork.MockNode>
|
||||||
private lateinit var serverIdentity: Party
|
private lateinit var serverIdentity: Party
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
mockNet = MockNetwork(emptyList())
|
mockNet = InternalMockNetwork(emptyList())
|
||||||
server = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
server = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
||||||
client = mockNet.createNode(MockNodeParameters(legalName = BOB_NAME))
|
client = mockNet.createNode(MockNodeParameters(legalName = BOB_NAME))
|
||||||
client.internals.disableDBCloseOnStop() // Otherwise the in-memory database may disappear (taking the checkpoint with it) while we reboot the client.
|
client.internals.disableDBCloseOnStop() // Otherwise the in-memory database may disappear (taking the checkpoint with it) while we reboot the client.
|
||||||
@ -161,7 +162,7 @@ class AttachmentSerializationTest {
|
|||||||
private fun rebootClientAndGetAttachmentContent(checkAttachmentsOnLoad: Boolean = true): String {
|
private fun rebootClientAndGetAttachmentContent(checkAttachmentsOnLoad: Boolean = true): String {
|
||||||
client.dispose()
|
client.dispose()
|
||||||
client = mockNet.createNode(MockNodeParameters(client.internals.id, client.internals.configuration.myLegalName), { args ->
|
client = mockNet.createNode(MockNodeParameters(client.internals.id, client.internals.configuration.myLegalName), { args ->
|
||||||
object : MockNetwork.MockNode(args) {
|
object : InternalMockNetwork.MockNode(args) {
|
||||||
override fun start() = super.start().apply { attachments.checkAttachmentsOnLoad = checkAttachmentsOnLoad }
|
override fun start() = super.start().apply { attachments.checkAttachmentsOnLoad = checkAttachmentsOnLoad }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -181,6 +181,9 @@ UNRELEASED
|
|||||||
* Marked ``stateMachine`` on ``FlowLogic`` as ``CordaInternal`` to make clear that is it not part of the public api and is
|
* Marked ``stateMachine`` on ``FlowLogic`` as ``CordaInternal`` to make clear that is it not part of the public api and is
|
||||||
only for internal use
|
only for internal use
|
||||||
|
|
||||||
|
* Created new ``StartedMockNode`` and ``UnstartedMockNode`` classes which are wrappers around our MockNode implementation
|
||||||
|
that expose relevant methods for testing without exposing internals, create these using a ``MockNetwork``.
|
||||||
|
|
||||||
.. _changelog_v1:
|
.. _changelog_v1:
|
||||||
|
|
||||||
Release 1.0
|
Release 1.0
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.docs
|
package net.corda.docs
|
||||||
|
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.internal.concurrent.transpose
|
import net.corda.core.internal.concurrent.transpose
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
@ -45,10 +46,10 @@ class IntegrationTestingTutorial {
|
|||||||
// END 1
|
// END 1
|
||||||
|
|
||||||
// START 2
|
// START 2
|
||||||
val aliceClient = alice.rpcClientToNode()
|
val aliceClient = CordaRPCClient(alice.rpcAddress)
|
||||||
val aliceProxy = aliceClient.start("aliceUser", "testPassword1").proxy
|
val aliceProxy = aliceClient.start("aliceUser", "testPassword1").proxy
|
||||||
|
|
||||||
val bobClient = bob.rpcClientToNode()
|
val bobClient = CordaRPCClient(bob.rpcAddress)
|
||||||
val bobProxy = bobClient.start("bobUser", "testPassword2").proxy
|
val bobProxy = bobClient.start("bobUser", "testPassword2").proxy
|
||||||
// END 2
|
// END 2
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
package net.corda.docs
|
package net.corda.docs
|
||||||
|
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
@ -53,7 +54,7 @@ fun main(args: Array<String>) {
|
|||||||
// END 1
|
// END 1
|
||||||
|
|
||||||
// START 2
|
// START 2
|
||||||
val client = node.rpcClientToNode()
|
val client = CordaRPCClient(node.rpcAddress)
|
||||||
val proxy = client.start("user", "password").proxy
|
val proxy = client.start("user", "password").proxy
|
||||||
|
|
||||||
thread {
|
thread {
|
||||||
|
@ -13,15 +13,10 @@ import net.corda.core.serialization.serialize
|
|||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.unwrap
|
import net.corda.core.utilities.unwrap
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.node.services.messaging.Message
|
import net.corda.node.services.messaging.Message
|
||||||
import net.corda.node.services.statemachine.DataSessionMessage
|
import net.corda.node.services.statemachine.DataSessionMessage
|
||||||
import net.corda.node.services.statemachine.ExistingSessionMessage
|
import net.corda.node.services.statemachine.ExistingSessionMessage
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork
|
import net.corda.testing.node.*
|
||||||
import net.corda.testing.node.MessagingServiceSpy
|
|
||||||
import net.corda.testing.node.MockNetwork
|
|
||||||
import net.corda.testing.node.setMessagingServiceSpy
|
|
||||||
import net.corda.testing.node.startFlow
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
@ -58,8 +53,8 @@ class TutorialMockNetwork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lateinit private var mockNet: MockNetwork
|
lateinit private var mockNet: MockNetwork
|
||||||
lateinit private var nodeA: StartedNode<MockNetwork.MockNode>
|
lateinit private var nodeA: StartedMockNode
|
||||||
lateinit private var nodeB: StartedNode<MockNetwork.MockNode>
|
lateinit private var nodeB: StartedMockNode
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
@JvmField
|
@JvmField
|
||||||
|
@ -7,9 +7,9 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.finance.*
|
import net.corda.finance.*
|
||||||
import net.corda.finance.contracts.getCashBalances
|
import net.corda.finance.contracts.getCashBalances
|
||||||
import net.corda.finance.flows.CashIssueFlow
|
import net.corda.finance.flows.CashIssueFlow
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.testing.core.chooseIdentity
|
import net.corda.testing.core.chooseIdentity
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
|
import net.corda.testing.node.StartedMockNode
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
@ -19,8 +19,8 @@ import java.util.*
|
|||||||
|
|
||||||
class CustomVaultQueryTest {
|
class CustomVaultQueryTest {
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
private lateinit var nodeA: StartedMockNode
|
||||||
private lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
private lateinit var nodeB: StartedMockNode
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -7,9 +7,9 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.finance.*
|
import net.corda.finance.*
|
||||||
import net.corda.finance.contracts.getCashBalances
|
import net.corda.finance.contracts.getCashBalances
|
||||||
import net.corda.finance.flows.CashIssueFlow
|
import net.corda.finance.flows.CashIssueFlow
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.testing.core.chooseIdentity
|
import net.corda.testing.core.chooseIdentity
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
|
import net.corda.testing.node.StartedMockNode
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -18,8 +18,8 @@ import kotlin.test.assertEquals
|
|||||||
|
|
||||||
class FxTransactionBuildTutorialTest {
|
class FxTransactionBuildTutorialTest {
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
private lateinit var nodeA: StartedMockNode
|
||||||
private lateinit var nodeB: StartedNode<MockNetwork.MockNode>
|
private lateinit var nodeB: StartedMockNode
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -6,11 +6,10 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.finance.DOLLARS
|
import net.corda.finance.DOLLARS
|
||||||
import net.corda.finance.`issued by`
|
import net.corda.finance.`issued by`
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.testing.core.BOC_NAME
|
import net.corda.testing.core.BOC_NAME
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.node.MockNetwork.MockNode
|
import net.corda.testing.node.StartedMockNode
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -22,7 +21,7 @@ class CashExitFlowTests {
|
|||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private val initialBalance = 2000.DOLLARS
|
private val initialBalance = 2000.DOLLARS
|
||||||
private val ref = OpaqueBytes.of(0x01)
|
private val ref = OpaqueBytes.of(0x01)
|
||||||
private lateinit var bankOfCordaNode: StartedNode<MockNode>
|
private lateinit var bankOfCordaNode: StartedMockNode
|
||||||
private lateinit var bankOfCorda: Party
|
private lateinit var bankOfCorda: Party
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
|
|
||||||
|
@ -6,11 +6,10 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.finance.DOLLARS
|
import net.corda.finance.DOLLARS
|
||||||
import net.corda.finance.`issued by`
|
import net.corda.finance.`issued by`
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.testing.core.BOC_NAME
|
import net.corda.testing.core.BOC_NAME
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.node.MockNetwork.MockNode
|
import net.corda.testing.node.StartedMockNode
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -20,7 +19,7 @@ import kotlin.test.assertFailsWith
|
|||||||
|
|
||||||
class CashIssueFlowTests {
|
class CashIssueFlowTests {
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var bankOfCordaNode: StartedNode<MockNode>
|
private lateinit var bankOfCordaNode: StartedMockNode
|
||||||
private lateinit var bankOfCorda: Party
|
private lateinit var bankOfCorda: Party
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
|
|
||||||
|
@ -9,11 +9,10 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.finance.DOLLARS
|
import net.corda.finance.DOLLARS
|
||||||
import net.corda.finance.`issued by`
|
import net.corda.finance.`issued by`
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.testing.core.*
|
import net.corda.testing.core.*
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.node.MockNetwork.MockNode
|
import net.corda.testing.node.StartedMockNode
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -25,9 +24,9 @@ class CashPaymentFlowTests {
|
|||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private val initialBalance = 2000.DOLLARS
|
private val initialBalance = 2000.DOLLARS
|
||||||
private val ref = OpaqueBytes.of(0x01)
|
private val ref = OpaqueBytes.of(0x01)
|
||||||
private lateinit var bankOfCordaNode: StartedNode<MockNode>
|
private lateinit var bankOfCordaNode: StartedMockNode
|
||||||
private lateinit var bankOfCorda: Party
|
private lateinit var bankOfCorda: Party
|
||||||
private lateinit var aliceNode: StartedNode<MockNode>
|
private lateinit var aliceNode: StartedMockNode
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun start() {
|
fun start() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.corda.node
|
package net.corda.node
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
@ -25,7 +26,7 @@ class BootTests {
|
|||||||
fun `java deserialization is disabled`() {
|
fun `java deserialization is disabled`() {
|
||||||
driver {
|
driver {
|
||||||
val user = User("u", "p", setOf(startFlow<ObjectInputStreamFlow>()))
|
val user = User("u", "p", setOf(startFlow<ObjectInputStreamFlow>()))
|
||||||
val future = startNode(rpcUsers = listOf(user)).getOrThrow().rpcClientToNode().
|
val future = CordaRPCClient(startNode(rpcUsers = listOf(user)).getOrThrow().rpcAddress).
|
||||||
start(user.username, user.password).proxy.startFlow(::ObjectInputStreamFlow).returnValue
|
start(user.username, user.password).proxy.startFlow(::ObjectInputStreamFlow).returnValue
|
||||||
assertThatThrownBy { future.getOrThrow() }.isInstanceOf(InvalidClassException::class.java).hasMessage("filter status: REJECTED")
|
assertThatThrownBy { future.getOrThrow() }.isInstanceOf(InvalidClassException::class.java).hasMessage("filter status: REJECTED")
|
||||||
}
|
}
|
||||||
@ -37,7 +38,7 @@ class BootTests {
|
|||||||
assertThat(logConfigFile).isRegularFile()
|
assertThat(logConfigFile).isRegularFile()
|
||||||
driver(isDebug = true, systemProperties = mapOf("log4j.configurationFile" to logConfigFile.toString())) {
|
driver(isDebug = true, systemProperties = mapOf("log4j.configurationFile" to logConfigFile.toString())) {
|
||||||
val alice = startNode(providedName = ALICE_NAME).get()
|
val alice = startNode(providedName = ALICE_NAME).get()
|
||||||
val logFolder = alice.configuration.baseDirectory / NodeStartup.LOGS_DIRECTORY_NAME
|
val logFolder = alice.baseDirectory / NodeStartup.LOGS_DIRECTORY_NAME
|
||||||
val logFile = logFolder.toFile().listFiles { _, name -> name.endsWith(".log") }.single()
|
val logFile = logFolder.toFile().listFiles { _, name -> name.endsWith(".log") }.single()
|
||||||
// Start second Alice, should fail
|
// Start second Alice, should fail
|
||||||
assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.corda.node
|
package net.corda.node
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.concurrent.transpose
|
import net.corda.core.internal.concurrent.transpose
|
||||||
@ -25,7 +26,7 @@ class CordappScanningDriverTest {
|
|||||||
val (alice, bob) = listOf(
|
val (alice, bob) = listOf(
|
||||||
startNode(providedName = ALICE_NAME, rpcUsers = listOf(user)),
|
startNode(providedName = ALICE_NAME, rpcUsers = listOf(user)),
|
||||||
startNode(providedName = BOB_NAME)).transpose().getOrThrow()
|
startNode(providedName = BOB_NAME)).transpose().getOrThrow()
|
||||||
val initiatedFlowClass = alice.rpcClientToNode()
|
val initiatedFlowClass = CordaRPCClient(alice.rpcAddress)
|
||||||
.start(user.username, user.password)
|
.start(user.username, user.password)
|
||||||
.proxy
|
.proxy
|
||||||
.startFlow(::ReceiveFlow, bob.nodeInfo.chooseIdentity())
|
.startFlow(::ReceiveFlow, bob.nodeInfo.chooseIdentity())
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.node
|
|||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import com.google.common.base.Stopwatch
|
import com.google.common.base.Stopwatch
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.internal.concurrent.transpose
|
import net.corda.core.internal.concurrent.transpose
|
||||||
@ -14,19 +15,18 @@ import net.corda.finance.flows.CashIssueFlow
|
|||||||
import net.corda.finance.flows.CashPaymentFlow
|
import net.corda.finance.flows.CashPaymentFlow
|
||||||
import net.corda.node.services.Permissions.Companion.startFlow
|
import net.corda.node.services.Permissions.Companion.startFlow
|
||||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||||
|
import net.corda.testing.driver.InProcess
|
||||||
import net.corda.testing.node.User
|
import net.corda.testing.node.User
|
||||||
import net.corda.testing.driver.NodeHandle
|
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.internal.performance.div
|
import net.corda.testing.internal.performance.div
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
import net.corda.testing.node.internal.InternalDriverDSL
|
import net.corda.testing.node.internal.InternalDriverDSL
|
||||||
|
import net.corda.testing.node.internal.internalDriver
|
||||||
import net.corda.testing.node.internal.performance.startPublishingFixedRateInjector
|
import net.corda.testing.node.internal.performance.startPublishingFixedRateInjector
|
||||||
import net.corda.testing.node.internal.performance.startReporter
|
import net.corda.testing.node.internal.performance.startReporter
|
||||||
import net.corda.testing.node.internal.performance.startTightLoopInjector
|
import net.corda.testing.node.internal.performance.startTightLoopInjector
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Ignore
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.lang.management.ManagementFactory
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.streams.toList
|
import kotlin.streams.toList
|
||||||
@ -50,7 +50,7 @@ class NodePerformanceTests {
|
|||||||
driver(startNodesInProcess = true) {
|
driver(startNodesInProcess = true) {
|
||||||
val a = startNode(rpcUsers = listOf(User("A", "A", setOf(startFlow<EmptyFlow>())))).get()
|
val a = startNode(rpcUsers = listOf(User("A", "A", setOf(startFlow<EmptyFlow>())))).get()
|
||||||
|
|
||||||
a.rpcClientToNode().use("A", "A") { connection ->
|
CordaRPCClient(a.rpcAddress).use("A", "A") { connection ->
|
||||||
val timings = Collections.synchronizedList(ArrayList<Long>())
|
val timings = Collections.synchronizedList(ArrayList<Long>())
|
||||||
val N = 10000
|
val N = 10000
|
||||||
val overallTiming = Stopwatch.createStarted().apply {
|
val overallTiming = Stopwatch.createStarted().apply {
|
||||||
@ -77,11 +77,11 @@ class NodePerformanceTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `empty flow rate`() {
|
fun `empty flow rate`() {
|
||||||
driver(startNodesInProcess = true) {
|
internalDriver(startNodesInProcess = true) {
|
||||||
val a = startNode(rpcUsers = listOf(User("A", "A", setOf(startFlow<EmptyFlow>())))).get()
|
val a = startNode(rpcUsers = listOf(User("A", "A", setOf(startFlow<EmptyFlow>())))).get()
|
||||||
a as NodeHandle.InProcess
|
a as InProcess
|
||||||
val metricRegistry = startReporter((this as InternalDriverDSL).shutdownManager, a.node.services.monitoringService.metrics)
|
val metricRegistry = startReporter(this.shutdownManager, a.services.monitoringService.metrics)
|
||||||
a.rpcClientToNode().use("A", "A") { connection ->
|
CordaRPCClient(a.rpcAddress).use("A", "A") { connection ->
|
||||||
startPublishingFixedRateInjector(metricRegistry, 8, 5.minutes, 2000L / TimeUnit.SECONDS) {
|
startPublishingFixedRateInjector(metricRegistry, 8, 5.minutes, 2000L / TimeUnit.SECONDS) {
|
||||||
connection.proxy.startFlow(::EmptyFlow).returnValue.get()
|
connection.proxy.startFlow(::EmptyFlow).returnValue.get()
|
||||||
}
|
}
|
||||||
@ -92,14 +92,14 @@ class NodePerformanceTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `self pay rate`() {
|
fun `self pay rate`() {
|
||||||
val user = User("A", "A", setOf(startFlow<CashIssueFlow>(), startFlow<CashPaymentFlow>()))
|
val user = User("A", "A", setOf(startFlow<CashIssueFlow>(), startFlow<CashPaymentFlow>()))
|
||||||
driver(
|
internalDriver(
|
||||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY_NAME, rpcUsers = listOf(user))),
|
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY_NAME, rpcUsers = listOf(user))),
|
||||||
startNodesInProcess = true,
|
startNodesInProcess = true,
|
||||||
extraCordappPackagesToScan = listOf("net.corda.finance")
|
extraCordappPackagesToScan = listOf("net.corda.finance")
|
||||||
) {
|
) {
|
||||||
val notary = defaultNotaryNode.getOrThrow() as NodeHandle.InProcess
|
val notary = defaultNotaryNode.getOrThrow() as InProcess
|
||||||
val metricRegistry = startReporter((this as InternalDriverDSL).shutdownManager, notary.node.services.monitoringService.metrics)
|
val metricRegistry = startReporter(this.shutdownManager, notary.services.monitoringService.metrics)
|
||||||
notary.rpcClientToNode().use("A", "A") { connection ->
|
CordaRPCClient(notary.rpcAddress).use("A", "A") { connection ->
|
||||||
println("ISSUING")
|
println("ISSUING")
|
||||||
val doneFutures = (1..100).toList().parallelStream().map {
|
val doneFutures = (1..100).toList().parallelStream().map {
|
||||||
connection.proxy.startFlow(::CashIssueFlow, 1.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue
|
connection.proxy.startFlow(::CashIssueFlow, 1.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue
|
||||||
|
@ -18,7 +18,6 @@ import net.corda.core.transactions.TransactionBuilder
|
|||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.Try
|
import net.corda.core.utilities.Try
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.node.services.config.BFTSMaRtConfiguration
|
import net.corda.node.services.config.BFTSMaRtConfiguration
|
||||||
import net.corda.node.services.config.NotaryConfig
|
import net.corda.node.services.config.NotaryConfig
|
||||||
import net.corda.node.services.transactions.minClusterSize
|
import net.corda.node.services.transactions.minClusterSize
|
||||||
@ -31,7 +30,7 @@ import net.corda.testing.common.internal.testNetworkParameters
|
|||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.core.dummyCommand
|
import net.corda.testing.core.dummyCommand
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.node.MockNetwork.MockNode
|
import net.corda.testing.node.StartedMockNode
|
||||||
import net.corda.testing.node.MockNodeParameters
|
import net.corda.testing.node.MockNodeParameters
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
@ -44,7 +43,7 @@ import kotlin.test.assertTrue
|
|||||||
class BFTNotaryServiceTests {
|
class BFTNotaryServiceTests {
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
private lateinit var node: StartedNode<MockNode>
|
private lateinit var node: StartedMockNode
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun before() {
|
fun before() {
|
||||||
@ -154,7 +153,7 @@ class BFTNotaryServiceTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun StartedNode<*>.signInitialTransaction(notary: Party, block: TransactionBuilder.() -> Any?): SignedTransaction {
|
private fun StartedMockNode.signInitialTransaction(notary: Party, block: TransactionBuilder.() -> Any?): SignedTransaction {
|
||||||
return services.signInitialTransaction(
|
return services.signInitialTransaction(
|
||||||
TransactionBuilder(notary).apply {
|
TransactionBuilder(notary).apply {
|
||||||
addCommand(dummyCommand(services.myInfo.chooseIdentity().owningKey))
|
addCommand(dummyCommand(services.myInfo.chooseIdentity().owningKey))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.node.services
|
package net.corda.node.services
|
||||||
|
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.bufferUntilSubscribed
|
import net.corda.core.internal.bufferUntilSubscribed
|
||||||
@ -15,6 +16,7 @@ import net.corda.node.services.Permissions.Companion.invokeRpc
|
|||||||
import net.corda.node.services.Permissions.Companion.startFlow
|
import net.corda.node.services.Permissions.Companion.startFlow
|
||||||
import net.corda.testing.core.*
|
import net.corda.testing.core.*
|
||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.NodeHandle
|
||||||
|
import net.corda.testing.driver.OutOfProcess
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
import net.corda.testing.node.User
|
import net.corda.testing.node.User
|
||||||
@ -26,7 +28,7 @@ import java.util.*
|
|||||||
|
|
||||||
class DistributedServiceTests {
|
class DistributedServiceTests {
|
||||||
private lateinit var alice: NodeHandle
|
private lateinit var alice: NodeHandle
|
||||||
private lateinit var notaryNodes: List<NodeHandle.OutOfProcess>
|
private lateinit var notaryNodes: List<OutOfProcess>
|
||||||
private lateinit var aliceProxy: CordaRPCOps
|
private lateinit var aliceProxy: CordaRPCOps
|
||||||
private lateinit var raftNotaryIdentity: Party
|
private lateinit var raftNotaryIdentity: Party
|
||||||
private lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>>
|
private lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>>
|
||||||
@ -49,7 +51,7 @@ class DistributedServiceTests {
|
|||||||
) {
|
) {
|
||||||
alice = startNode(providedName = ALICE_NAME, rpcUsers = listOf(testUser)).getOrThrow()
|
alice = startNode(providedName = ALICE_NAME, rpcUsers = listOf(testUser)).getOrThrow()
|
||||||
raftNotaryIdentity = defaultNotaryIdentity
|
raftNotaryIdentity = defaultNotaryIdentity
|
||||||
notaryNodes = defaultNotaryHandle.nodeHandles.getOrThrow().map { it as NodeHandle.OutOfProcess }
|
notaryNodes = defaultNotaryHandle.nodeHandles.getOrThrow().map { it as OutOfProcess }
|
||||||
|
|
||||||
assertThat(notaryNodes).hasSize(3)
|
assertThat(notaryNodes).hasSize(3)
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ class DistributedServiceTests {
|
|||||||
|
|
||||||
// Connect to Alice and the notaries
|
// Connect to Alice and the notaries
|
||||||
fun connectRpc(node: NodeHandle): CordaRPCOps {
|
fun connectRpc(node: NodeHandle): CordaRPCOps {
|
||||||
val client = node.rpcClientToNode()
|
val client = CordaRPCClient(node.rpcAddress)
|
||||||
return client.start("test", "test").proxy
|
return client.start("test", "test").proxy
|
||||||
}
|
}
|
||||||
aliceProxy = connectRpc(alice)
|
aliceProxy = connectRpc(alice)
|
||||||
|
@ -10,13 +10,12 @@ import net.corda.core.identity.Party
|
|||||||
import net.corda.core.internal.concurrent.map
|
import net.corda.core.internal.concurrent.map
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||||
import net.corda.testing.core.chooseIdentity
|
import net.corda.testing.core.chooseIdentity
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.driver.NodeHandle
|
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.core.dummyCommand
|
import net.corda.testing.core.dummyCommand
|
||||||
|
import net.corda.testing.driver.InProcess
|
||||||
import net.corda.testing.node.ClusterSpec
|
import net.corda.testing.node.ClusterSpec
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
@ -35,7 +34,7 @@ class RaftNotaryServiceTests {
|
|||||||
extraCordappPackagesToScan = listOf("net.corda.testing.contracts"),
|
extraCordappPackagesToScan = listOf("net.corda.testing.contracts"),
|
||||||
notarySpecs = listOf(NotarySpec(notaryName, cluster = ClusterSpec.Raft(clusterSize = 3)))
|
notarySpecs = listOf(NotarySpec(notaryName, cluster = ClusterSpec.Raft(clusterSize = 3)))
|
||||||
) {
|
) {
|
||||||
val bankA = startNode(providedName = DUMMY_BANK_A_NAME).map { (it as NodeHandle.InProcess).node }.getOrThrow()
|
val bankA = startNode(providedName = DUMMY_BANK_A_NAME).map { (it as InProcess) }.getOrThrow()
|
||||||
val inputState = issueState(bankA, defaultNotaryIdentity)
|
val inputState = issueState(bankA, defaultNotaryIdentity)
|
||||||
|
|
||||||
val firstTxBuilder = TransactionBuilder(defaultNotaryIdentity)
|
val firstTxBuilder = TransactionBuilder(defaultNotaryIdentity)
|
||||||
@ -47,7 +46,7 @@ class RaftNotaryServiceTests {
|
|||||||
firstSpend.getOrThrow()
|
firstSpend.getOrThrow()
|
||||||
|
|
||||||
val secondSpendBuilder = TransactionBuilder(defaultNotaryIdentity).withItems(inputState).run {
|
val secondSpendBuilder = TransactionBuilder(defaultNotaryIdentity).withItems(inputState).run {
|
||||||
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.chooseIdentity())
|
val dummyState = DummyContract.SingleOwnerState(0, bankA.services.myInfo.chooseIdentity())
|
||||||
addOutputState(dummyState, DummyContract.PROGRAM_ID)
|
addOutputState(dummyState, DummyContract.PROGRAM_ID)
|
||||||
addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
|
addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
|
||||||
this
|
this
|
||||||
@ -61,11 +60,12 @@ class RaftNotaryServiceTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun issueState(node: StartedNode<*>, notary: Party): StateAndRef<*> {
|
private fun issueState(nodeHandle: InProcess, notary: Party): StateAndRef<*> {
|
||||||
return node.database.transaction {
|
return nodeHandle.database.transaction {
|
||||||
val builder = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
|
|
||||||
val stx = node.services.signInitialTransaction(builder)
|
val builder = DummyContract.generateInitial(Random().nextInt(), notary, nodeHandle.services.myInfo.chooseIdentity().ref(0))
|
||||||
node.services.recordTransactions(stx)
|
val stx = nodeHandle.services.signInitialTransaction(builder)
|
||||||
|
nodeHandle.services.recordTransactions(stx)
|
||||||
StateAndRef(builder.outputStates().first(), StateRef(stx.id, 0))
|
StateAndRef(builder.outputStates().first(), StateRef(stx.id, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ class NetworkMapTest {
|
|||||||
notarySpecs = emptyList()
|
notarySpecs = emptyList()
|
||||||
) {
|
) {
|
||||||
val alice = startNode(providedName = ALICE_NAME).getOrThrow()
|
val alice = startNode(providedName = ALICE_NAME).getOrThrow()
|
||||||
val networkParameters = (alice.configuration.baseDirectory / NETWORK_PARAMS_FILE_NAME)
|
val networkParameters = (alice.baseDirectory / NETWORK_PARAMS_FILE_NAME)
|
||||||
.readAll()
|
.readAll()
|
||||||
.deserialize<SignedDataWithCert<NetworkParameters>>()
|
.deserialize<SignedDataWithCert<NetworkParameters>>()
|
||||||
.verified()
|
.verified()
|
||||||
@ -147,7 +147,7 @@ class NetworkMapTest {
|
|||||||
|
|
||||||
private fun NodeHandle.onlySees(vararg nodes: NodeInfo) {
|
private fun NodeHandle.onlySees(vararg nodes: NodeInfo) {
|
||||||
// Make sure the nodes aren't getting the node infos from their additional directories
|
// Make sure the nodes aren't getting the node infos from their additional directories
|
||||||
val nodeInfosDir = configuration.baseDirectory / CordformNode.NODE_INFO_DIRECTORY
|
val nodeInfosDir = baseDirectory / CordformNode.NODE_INFO_DIRECTORY
|
||||||
if (nodeInfosDir.exists()) {
|
if (nodeInfosDir.exists()) {
|
||||||
assertThat(nodeInfosDir.list { it.toList() }).isEmpty()
|
assertThat(nodeInfosDir.list { it.toList() }).isEmpty()
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.node.services.rpc
|
package net.corda.node.services.rpc
|
||||||
|
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.services.Permissions.Companion.all
|
import net.corda.node.services.Permissions.Companion.all
|
||||||
@ -32,7 +33,7 @@ class RpcSslTest {
|
|||||||
var successful = false
|
var successful = false
|
||||||
driver(isDebug = true, startNodesInProcess = true, portAllocation = PortAllocation.RandomFree) {
|
driver(isDebug = true, startNodesInProcess = true, portAllocation = PortAllocation.RandomFree) {
|
||||||
startNode(rpcUsers = listOf(user), customOverrides = nodeSslOptions.useSslRpcOverrides()).getOrThrow().use { node ->
|
startNode(rpcUsers = listOf(user), customOverrides = nodeSslOptions.useSslRpcOverrides()).getOrThrow().use { node ->
|
||||||
node.rpcClientToNode(clientSslOptions).start(user.username, user.password).use { connection ->
|
CordaRPCClient(node.rpcAddress, sslConfiguration = clientSslOptions).start(user.username, user.password).use { connection ->
|
||||||
connection.proxy.apply {
|
connection.proxy.apply {
|
||||||
nodeInfo()
|
nodeInfo()
|
||||||
successful = true
|
successful = true
|
||||||
@ -51,7 +52,7 @@ class RpcSslTest {
|
|||||||
var successful = false
|
var successful = false
|
||||||
driver(isDebug = true, startNodesInProcess = true, portAllocation = PortAllocation.RandomFree) {
|
driver(isDebug = true, startNodesInProcess = true, portAllocation = PortAllocation.RandomFree) {
|
||||||
startNode(rpcUsers = listOf(user)).getOrThrow().use { node ->
|
startNode(rpcUsers = listOf(user)).getOrThrow().use { node ->
|
||||||
node.rpcClientToNode().start(user.username, user.password).use { connection ->
|
CordaRPCClient(node.rpcAddress).start(user.username, user.password).use { connection ->
|
||||||
connection.proxy.apply {
|
connection.proxy.apply {
|
||||||
nodeInfo()
|
nodeInfo()
|
||||||
successful = true
|
successful = true
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.corda.node.services.statemachine
|
package net.corda.node.services.statemachine
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.internal.InputStreamAndHash
|
import net.corda.core.internal.InputStreamAndHash
|
||||||
@ -73,7 +74,7 @@ class LargeTransactionsTest {
|
|||||||
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts"), portAllocation = PortAllocation.RandomFree) {
|
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts"), portAllocation = PortAllocation.RandomFree) {
|
||||||
val rpcUser = User("admin", "admin", setOf("ALL"))
|
val rpcUser = User("admin", "admin", setOf("ALL"))
|
||||||
val (alice, _) = listOf(ALICE_NAME, BOB_NAME).map { startNode(providedName = it, rpcUsers = listOf(rpcUser)) }.transpose().getOrThrow()
|
val (alice, _) = listOf(ALICE_NAME, BOB_NAME).map { startNode(providedName = it, rpcUsers = listOf(rpcUser)) }.transpose().getOrThrow()
|
||||||
alice.rpcClientToNode().use(rpcUser.username, rpcUser.password) {
|
CordaRPCClient(alice.rpcAddress).use(rpcUser.username, rpcUser.password) {
|
||||||
val hash1 = it.proxy.uploadAttachment(bigFile1.inputStream)
|
val hash1 = it.proxy.uploadAttachment(bigFile1.inputStream)
|
||||||
val hash2 = it.proxy.uploadAttachment(bigFile2.inputStream)
|
val hash2 = it.proxy.uploadAttachment(bigFile2.inputStream)
|
||||||
val hash3 = it.proxy.uploadAttachment(bigFile3.inputStream)
|
val hash3 = it.proxy.uploadAttachment(bigFile3.inputStream)
|
||||||
|
@ -12,15 +12,13 @@ import net.corda.core.serialization.deserialize
|
|||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.node.internal.Node
|
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.node.services.messaging.MessagingService
|
import net.corda.node.services.messaging.MessagingService
|
||||||
import net.corda.node.services.messaging.ReceivedMessage
|
import net.corda.node.services.messaging.ReceivedMessage
|
||||||
import net.corda.node.services.messaging.send
|
import net.corda.node.services.messaging.send
|
||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.core.chooseIdentity
|
import net.corda.testing.core.chooseIdentity
|
||||||
import net.corda.testing.driver.DriverDSL
|
import net.corda.testing.driver.DriverDSL
|
||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.InProcess
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.node.ClusterSpec
|
import net.corda.testing.node.ClusterSpec
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
@ -44,13 +42,14 @@ class P2PMessagingTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `distributed service requests are retried if one of the nodes in the cluster goes down without sending a response`() {
|
fun `distributed service requests are retried if one of the nodes in the cluster goes down without sending a response`() {
|
||||||
startDriverWithDistributedService { distributedServiceNodes ->
|
startDriverWithDistributedService { distributedServiceNodes ->
|
||||||
val alice = startAlice()
|
val alice = startAlice()
|
||||||
val serviceAddress = alice.services.networkMapCache.run {
|
val serviceAddress = alice.services.networkMapCache.run {
|
||||||
val notaryParty = notaryIdentities.randomOrNull()!!
|
val notaryParty = notaryIdentities.randomOrNull()!!
|
||||||
alice.network.getAddressOfParty(getPartyInfo(notaryParty)!!)
|
alice.services.networkService.getAddressOfParty(getPartyInfo(notaryParty)!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseMessage = "response"
|
val responseMessage = "response"
|
||||||
@ -76,7 +75,7 @@ class P2PMessagingTest {
|
|||||||
val alice = startAlice()
|
val alice = startAlice()
|
||||||
val serviceAddress = alice.services.networkMapCache.run {
|
val serviceAddress = alice.services.networkMapCache.run {
|
||||||
val notaryParty = notaryIdentities.randomOrNull()!!
|
val notaryParty = notaryIdentities.randomOrNull()!!
|
||||||
alice.network.getAddressOfParty(getPartyInfo(notaryParty)!!)
|
alice.services.networkService.getAddressOfParty(getPartyInfo(notaryParty)!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseMessage = "response"
|
val responseMessage = "response"
|
||||||
@ -89,7 +88,7 @@ class P2PMessagingTest {
|
|||||||
// Wait until the first request is received
|
// Wait until the first request is received
|
||||||
crashingNodes.firstRequestReceived.await()
|
crashingNodes.firstRequestReceived.await()
|
||||||
// Stop alice's node after we ensured that the first request was delivered and ignored.
|
// Stop alice's node after we ensured that the first request was delivered and ignored.
|
||||||
alice.dispose()
|
alice.stop()
|
||||||
val numberOfRequestsReceived = crashingNodes.requestsReceived.get()
|
val numberOfRequestsReceived = crashingNodes.requestsReceived.get()
|
||||||
assertThat(numberOfRequestsReceived).isGreaterThanOrEqualTo(1)
|
assertThat(numberOfRequestsReceived).isGreaterThanOrEqualTo(1)
|
||||||
|
|
||||||
@ -99,7 +98,7 @@ class P2PMessagingTest {
|
|||||||
val aliceRestarted = startAlice()
|
val aliceRestarted = startAlice()
|
||||||
|
|
||||||
val responseFuture = openFuture<Any>()
|
val responseFuture = openFuture<Any>()
|
||||||
aliceRestarted.network.runOnNextMessage("test.response") {
|
aliceRestarted.services.networkService.runOnNextMessage("test.response") {
|
||||||
responseFuture.set(it.data.deserialize())
|
responseFuture.set(it.data.deserialize())
|
||||||
}
|
}
|
||||||
val response = responseFuture.getOrThrow()
|
val response = responseFuture.getOrThrow()
|
||||||
@ -109,15 +108,16 @@ class P2PMessagingTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startDriverWithDistributedService(dsl: DriverDSL.(List<StartedNode<Node>>) -> Unit) {
|
|
||||||
|
private fun startDriverWithDistributedService(dsl: DriverDSL.(List<InProcess>) -> Unit) {
|
||||||
driver(startNodesInProcess = true, notarySpecs = listOf(NotarySpec(DISTRIBUTED_SERVICE_NAME, cluster = ClusterSpec.Raft(clusterSize = 2)))) {
|
driver(startNodesInProcess = true, notarySpecs = listOf(NotarySpec(DISTRIBUTED_SERVICE_NAME, cluster = ClusterSpec.Raft(clusterSize = 2)))) {
|
||||||
dsl(defaultNotaryHandle.nodeHandles.getOrThrow().map { (it as NodeHandle.InProcess).node })
|
dsl(defaultNotaryHandle.nodeHandles.getOrThrow().map { (it as InProcess) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DriverDSL.startAlice(): StartedNode<Node> {
|
private fun DriverDSL.startAlice(): InProcess {
|
||||||
return startNode(providedName = ALICE_NAME, customOverrides = mapOf("messageRedeliveryDelaySeconds" to 1))
|
return startNode(providedName = ALICE_NAME, customOverrides = mapOf("messageRedeliveryDelaySeconds" to 1))
|
||||||
.map { (it as NodeHandle.InProcess).node }
|
.map { (it as InProcess) }
|
||||||
.getOrThrow()
|
.getOrThrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ class P2PMessagingTest {
|
|||||||
* initially set to true. This may be used to simulate scenarios where nodes receive request messages but crash
|
* initially set to true. This may be used to simulate scenarios where nodes receive request messages but crash
|
||||||
* before sending back a response.
|
* before sending back a response.
|
||||||
*/
|
*/
|
||||||
private fun simulateCrashingNodes(distributedServiceNodes: List<StartedNode<*>>, responseMessage: String): CrashingNodes {
|
private fun simulateCrashingNodes(distributedServiceNodes: List<InProcess>, responseMessage: String): CrashingNodes {
|
||||||
val crashingNodes = CrashingNodes(
|
val crashingNodes = CrashingNodes(
|
||||||
requestsReceived = AtomicInteger(0),
|
requestsReceived = AtomicInteger(0),
|
||||||
firstRequestReceived = CountDownLatch(1),
|
firstRequestReceived = CountDownLatch(1),
|
||||||
@ -141,8 +141,8 @@ class P2PMessagingTest {
|
|||||||
)
|
)
|
||||||
|
|
||||||
distributedServiceNodes.forEach {
|
distributedServiceNodes.forEach {
|
||||||
val nodeName = it.info.chooseIdentity().name
|
val nodeName = it.services.myInfo.chooseIdentity().name
|
||||||
it.network.addMessageHandler("test.request") { netMessage, _ ->
|
it.services.networkService.addMessageHandler("test.request") { netMessage, _ ->
|
||||||
crashingNodes.requestsReceived.incrementAndGet()
|
crashingNodes.requestsReceived.incrementAndGet()
|
||||||
crashingNodes.firstRequestReceived.countDown()
|
crashingNodes.firstRequestReceived.countDown()
|
||||||
// The node which receives the first request will ignore all requests
|
// The node which receives the first request will ignore all requests
|
||||||
@ -154,21 +154,21 @@ class P2PMessagingTest {
|
|||||||
} else {
|
} else {
|
||||||
println("sending response")
|
println("sending response")
|
||||||
val request = netMessage.data.deserialize<TestRequest>()
|
val request = netMessage.data.deserialize<TestRequest>()
|
||||||
val response = it.network.createMessage("test.response", responseMessage.serialize().bytes)
|
val response = it.services.networkService.createMessage("test.response", responseMessage.serialize().bytes)
|
||||||
it.network.send(response, request.replyTo)
|
it.services.networkService.send(response, request.replyTo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return crashingNodes
|
return crashingNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertAllNodesAreUsed(participatingServiceNodes: List<StartedNode<*>>, serviceName: CordaX500Name, originatingNode: StartedNode<*>) {
|
private fun assertAllNodesAreUsed(participatingServiceNodes: List<InProcess>, serviceName: CordaX500Name, originatingNode: InProcess) {
|
||||||
// Setup each node in the distributed service to return back it's NodeInfo so that we can know which node is being used
|
// Setup each node in the distributed service to return back it's NodeInfo so that we can know which node is being used
|
||||||
participatingServiceNodes.forEach { node ->
|
participatingServiceNodes.forEach { node ->
|
||||||
node.respondWith(node.info)
|
node.respondWith(node.services.myInfo)
|
||||||
}
|
}
|
||||||
val serviceAddress = originatingNode.services.networkMapCache.run {
|
val serviceAddress = originatingNode.services.networkMapCache.run {
|
||||||
originatingNode.network.getAddressOfParty(getPartyInfo(getNotary(serviceName)!!)!!)
|
originatingNode.services.networkService.getAddressOfParty(getPartyInfo(getNotary(serviceName)!!)!!)
|
||||||
}
|
}
|
||||||
val participatingNodes = HashSet<Any>()
|
val participatingNodes = HashSet<Any>()
|
||||||
// Try several times so that we can be fairly sure that any node not participating is not due to Artemis' selection
|
// Try several times so that we can be fairly sure that any node not participating is not due to Artemis' selection
|
||||||
@ -180,23 +180,23 @@ class P2PMessagingTest {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertThat(participatingNodes).containsOnlyElementsOf(participatingServiceNodes.map(StartedNode<*>::info))
|
assertThat(participatingNodes).containsOnlyElementsOf(participatingServiceNodes.map { it.services.myInfo })
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun StartedNode<*>.respondWith(message: Any) {
|
private fun InProcess.respondWith(message: Any) {
|
||||||
network.addMessageHandler("test.request") { netMessage, _ ->
|
services.networkService.addMessageHandler("test.request") { netMessage, _ ->
|
||||||
val request = netMessage.data.deserialize<TestRequest>()
|
val request = netMessage.data.deserialize<TestRequest>()
|
||||||
val response = network.createMessage("test.response", message.serialize().bytes)
|
val response = services.networkService.createMessage("test.response", message.serialize().bytes)
|
||||||
network.send(response, request.replyTo)
|
services.networkService.send(response, request.replyTo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun StartedNode<*>.receiveFrom(target: MessageRecipients, retryId: Long? = null): CordaFuture<Any> {
|
private fun InProcess.receiveFrom(target: MessageRecipients, retryId: Long? = null): CordaFuture<Any> {
|
||||||
val response = openFuture<Any>()
|
val response = openFuture<Any>()
|
||||||
network.runOnNextMessage("test.response") { netMessage ->
|
services.networkService.runOnNextMessage("test.response") { netMessage ->
|
||||||
response.set(netMessage.data.deserialize())
|
response.set(netMessage.data.deserialize())
|
||||||
}
|
}
|
||||||
network.send("test.request", TestRequest(replyTo = network.myAddress), target, retryId = retryId)
|
services.networkService.send("test.request", TestRequest(replyTo = services.networkService.myAddress), target, retryId = retryId)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.corda.test.node
|
package net.corda.test.node
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.flows.FinalityFlow
|
import net.corda.core.flows.FinalityFlow
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
@ -47,7 +48,7 @@ class NodeStatePersistenceTests {
|
|||||||
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
|
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
|
||||||
// Ensure the notary node has finished starting up, before starting a flow that needs a notary
|
// Ensure the notary node has finished starting up, before starting a flow that needs a notary
|
||||||
defaultNotaryNode.getOrThrow()
|
defaultNotaryNode.getOrThrow()
|
||||||
nodeHandle.rpcClientToNode().start(user.username, user.password).use {
|
CordaRPCClient(nodeHandle.rpcAddress).start(user.username, user.password).use {
|
||||||
it.proxy.startFlow(::SendMessageFlow, message, defaultNotaryIdentity).returnValue.getOrThrow()
|
it.proxy.startFlow(::SendMessageFlow, message, defaultNotaryIdentity).returnValue.getOrThrow()
|
||||||
}
|
}
|
||||||
nodeHandle.stop()
|
nodeHandle.stop()
|
||||||
@ -55,7 +56,7 @@ class NodeStatePersistenceTests {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
val nodeHandle = startNode(providedName = nodeName, rpcUsers = listOf(user)).getOrThrow()
|
val nodeHandle = startNode(providedName = nodeName, rpcUsers = listOf(user)).getOrThrow()
|
||||||
val result = nodeHandle.rpcClientToNode().start(user.username, user.password).use {
|
val result = CordaRPCClient(nodeHandle.rpcAddress).start(user.username, user.password).use {
|
||||||
val page = it.proxy.vaultQuery(MessageState::class.java)
|
val page = it.proxy.vaultQuery(MessageState::class.java)
|
||||||
page.states.singleOrNull()
|
page.states.singleOrNull()
|
||||||
}
|
}
|
||||||
@ -81,7 +82,7 @@ class NodeStatePersistenceTests {
|
|||||||
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
|
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
|
||||||
// Ensure the notary node has finished starting up, before starting a flow that needs a notary
|
// Ensure the notary node has finished starting up, before starting a flow that needs a notary
|
||||||
defaultNotaryNode.getOrThrow()
|
defaultNotaryNode.getOrThrow()
|
||||||
nodeHandle.rpcClientToNode().start(user.username, user.password).use {
|
CordaRPCClient(nodeHandle.rpcAddress).start(user.username, user.password).use {
|
||||||
it.proxy.startFlow(::SendMessageFlow, message, defaultNotaryIdentity).returnValue.getOrThrow()
|
it.proxy.startFlow(::SendMessageFlow, message, defaultNotaryIdentity).returnValue.getOrThrow()
|
||||||
}
|
}
|
||||||
nodeHandle.stop()
|
nodeHandle.stop()
|
||||||
@ -89,7 +90,7 @@ class NodeStatePersistenceTests {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
val nodeHandle = startNode(providedName = nodeName, rpcUsers = listOf(user), customOverrides = mapOf("devMode" to "false")).getOrThrow()
|
val nodeHandle = startNode(providedName = nodeName, rpcUsers = listOf(user), customOverrides = mapOf("devMode" to "false")).getOrThrow()
|
||||||
val result = nodeHandle.rpcClientToNode().start(user.username, user.password).use {
|
val result = CordaRPCClient(nodeHandle.rpcAddress).start(user.username, user.password).use {
|
||||||
val page = it.proxy.vaultQuery(MessageState::class.java)
|
val page = it.proxy.vaultQuery(MessageState::class.java)
|
||||||
page.states.singleOrNull()
|
page.states.singleOrNull()
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,9 @@ import net.corda.testing.core.ALICE_NAME
|
|||||||
import net.corda.testing.core.expect
|
import net.corda.testing.core.expect
|
||||||
import net.corda.testing.core.expectEvents
|
import net.corda.testing.core.expectEvents
|
||||||
import net.corda.testing.core.sequence
|
import net.corda.testing.core.sequence
|
||||||
import net.corda.testing.node.MockNetwork
|
|
||||||
import net.corda.testing.node.MockNetwork.MockNode
|
|
||||||
import net.corda.testing.node.MockNodeParameters
|
import net.corda.testing.node.MockNodeParameters
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork.MockNode
|
||||||
import net.corda.testing.node.testActor
|
import net.corda.testing.node.testActor
|
||||||
import org.apache.commons.io.IOUtils
|
import org.apache.commons.io.IOUtils
|
||||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||||
@ -68,7 +68,7 @@ class CordaRPCOpsImplTest {
|
|||||||
val testJar = "net/corda/node/testing/test.jar"
|
val testJar = "net/corda/node/testing/test.jar"
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: InternalMockNetwork
|
||||||
private lateinit var aliceNode: StartedNode<MockNode>
|
private lateinit var aliceNode: StartedNode<MockNode>
|
||||||
private lateinit var alice: Party
|
private lateinit var alice: Party
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
@ -79,7 +79,7 @@ class CordaRPCOpsImplTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
mockNet = MockNetwork(cordappPackages = listOf("net.corda.finance.contracts.asset"))
|
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.finance.contracts.asset"))
|
||||||
aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
||||||
rpc = SecureCordaRPCOps(aliceNode.services, aliceNode.smm, aliceNode.database, aliceNode.services)
|
rpc = SecureCordaRPCOps(aliceNode.services, aliceNode.smm, aliceNode.database, aliceNode.services)
|
||||||
CURRENT_RPC_CONTEXT.set(RpcAuthContext(InvocationContext.rpc(testActor()), buildSubject("TEST_USER", emptySet())))
|
CURRENT_RPC_CONTEXT.set(RpcAuthContext(InvocationContext.rpc(testActor()), buildSubject("TEST_USER", emptySet())))
|
||||||
|
@ -15,6 +15,7 @@ import net.corda.finance.DOLLARS
|
|||||||
import net.corda.finance.flows.CashIssueFlow
|
import net.corda.finance.flows.CashIssueFlow
|
||||||
import net.corda.node.internal.cordapp.DummyRPCFlow
|
import net.corda.node.internal.cordapp.DummyRPCFlow
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
|
import net.corda.testing.node.StartedMockNode
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -75,7 +76,7 @@ class LegacyCordaService(@Suppress("UNUSED_PARAMETER") simpleServiceHub: Service
|
|||||||
|
|
||||||
class CordaServiceTest {
|
class CordaServiceTest {
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
|
private lateinit var nodeA: StartedMockNode
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun start() {
|
fun start() {
|
||||||
|
@ -27,7 +27,7 @@ class NetworkParametersTest {
|
|||||||
private val mockNet = MockNetwork(
|
private val mockNet = MockNetwork(
|
||||||
emptyList(),
|
emptyList(),
|
||||||
MockNetworkParameters(networkSendManuallyPumped = true),
|
MockNetworkParameters(networkSendManuallyPumped = true),
|
||||||
notarySpecs = listOf(MockNetwork.NotarySpec(DUMMY_NOTARY_NAME)))
|
notarySpecs = listOf(MockNetworkNotarySpec(DUMMY_NOTARY_NAME)))
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun tearDown() {
|
fun tearDown() {
|
||||||
|
@ -48,6 +48,8 @@ import net.corda.testing.dsl.TestTransactionDSLInterpreter
|
|||||||
import net.corda.testing.internal.rigorousMock
|
import net.corda.testing.internal.rigorousMock
|
||||||
import net.corda.testing.internal.vault.VaultFiller
|
import net.corda.testing.internal.vault.VaultFiller
|
||||||
import net.corda.testing.node.*
|
import net.corda.testing.node.*
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
|
import net.corda.testing.node.internal.pumpReceive
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -83,7 +85,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
private val DUMMY_NOTARY get() = dummyNotary.party
|
private val DUMMY_NOTARY get() = dummyNotary.party
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: InternalMockNetwork
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun before() {
|
fun before() {
|
||||||
@ -101,7 +103,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
// We run this in parallel threads to help catch any race conditions that may exist. The other tests
|
// 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
|
// we run in the unit test thread exclusively to speed things up, ensure deterministic results and
|
||||||
// allow interruption half way through.
|
// allow interruption half way through.
|
||||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
|
mockNet = InternalMockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
|
||||||
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
||||||
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
||||||
val notaryNode = mockNet.defaultNotaryNode
|
val notaryNode = mockNet.defaultNotaryNode
|
||||||
@ -153,7 +155,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
|
|
||||||
@Test(expected = InsufficientBalanceException::class)
|
@Test(expected = InsufficientBalanceException::class)
|
||||||
fun `trade cash for commercial paper fails using soft locking`() {
|
fun `trade cash for commercial paper fails using soft locking`() {
|
||||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
|
mockNet = InternalMockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
|
||||||
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
||||||
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
||||||
val notaryNode = mockNet.defaultNotaryNode
|
val notaryNode = mockNet.defaultNotaryNode
|
||||||
@ -211,7 +213,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `shutdown and restore`() {
|
fun `shutdown and restore`() {
|
||||||
mockNet = MockNetwork(cordappPackages = cordappPackages)
|
mockNet = InternalMockNetwork(cordappPackages = cordappPackages)
|
||||||
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
||||||
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
||||||
val notaryNode = mockNet.defaultNotaryNode
|
val notaryNode = mockNet.defaultNotaryNode
|
||||||
@ -308,11 +310,10 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
|
|
||||||
// Creates a mock node with an overridden storage service that uses a RecordingMap, that lets us test the order
|
// Creates a mock node with an overridden storage service that uses a RecordingMap, that lets us test the order
|
||||||
// of gets and puts.
|
// of gets and puts.
|
||||||
private fun makeNodeWithTracking(
|
private fun makeNodeWithTracking(name: CordaX500Name): StartedNode<InternalMockNetwork.MockNode> {
|
||||||
name: CordaX500Name): StartedNode<MockNetwork.MockNode> {
|
|
||||||
// Create a node in the mock network ...
|
// Create a node in the mock network ...
|
||||||
return mockNet.createNode(MockNodeParameters(legalName = name), nodeFactory = { args ->
|
return mockNet.createNode(MockNodeParameters(legalName = name), nodeFactory = { args ->
|
||||||
object : MockNetwork.MockNode(args) {
|
object : InternalMockNetwork.MockNode(args) {
|
||||||
// That constructs a recording tx storage
|
// That constructs a recording tx storage
|
||||||
override fun makeTransactionStorage(database: CordaPersistence, transactionCacheSizeBytes: Long): WritableTransactionStorage {
|
override fun makeTransactionStorage(database: CordaPersistence, transactionCacheSizeBytes: Long): WritableTransactionStorage {
|
||||||
return RecordingTransactionStorage(database, super.makeTransactionStorage(database, transactionCacheSizeBytes))
|
return RecordingTransactionStorage(database, super.makeTransactionStorage(database, transactionCacheSizeBytes))
|
||||||
@ -323,7 +324,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `check dependencies of sale asset are resolved`() {
|
fun `check dependencies of sale asset are resolved`() {
|
||||||
mockNet = MockNetwork(cordappPackages = cordappPackages)
|
mockNet = InternalMockNetwork(cordappPackages = cordappPackages)
|
||||||
val notaryNode = mockNet.defaultNotaryNode
|
val notaryNode = mockNet.defaultNotaryNode
|
||||||
val aliceNode = makeNodeWithTracking(ALICE_NAME)
|
val aliceNode = makeNodeWithTracking(ALICE_NAME)
|
||||||
val bobNode = makeNodeWithTracking(BOB_NAME)
|
val bobNode = makeNodeWithTracking(BOB_NAME)
|
||||||
@ -427,7 +428,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `track works`() {
|
fun `track works`() {
|
||||||
mockNet = MockNetwork(cordappPackages = cordappPackages)
|
mockNet = InternalMockNetwork(cordappPackages = cordappPackages)
|
||||||
val notaryNode = mockNet.defaultNotaryNode
|
val notaryNode = mockNet.defaultNotaryNode
|
||||||
val aliceNode = makeNodeWithTracking(ALICE_NAME)
|
val aliceNode = makeNodeWithTracking(ALICE_NAME)
|
||||||
val bobNode = makeNodeWithTracking(BOB_NAME)
|
val bobNode = makeNodeWithTracking(BOB_NAME)
|
||||||
@ -505,7 +506,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `dependency with error on buyer side`() {
|
fun `dependency with error on buyer side`() {
|
||||||
mockNet = MockNetwork(cordappPackages = cordappPackages)
|
mockNet = InternalMockNetwork(cordappPackages = cordappPackages)
|
||||||
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
||||||
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
||||||
runWithError(ledgerIdentityService, true, false, "at least one cash input")
|
runWithError(ledgerIdentityService, true, false, "at least one cash input")
|
||||||
@ -514,7 +515,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `dependency with error on seller side`() {
|
fun `dependency with error on seller side`() {
|
||||||
mockNet = MockNetwork(cordappPackages = cordappPackages)
|
mockNet = InternalMockNetwork(cordappPackages = cordappPackages)
|
||||||
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
val ledgerIdentityService = rigorousMock<IdentityServiceInternal>()
|
||||||
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
MockServices(cordappPackages, ledgerIdentityService, MEGA_CORP.name).ledger(DUMMY_NOTARY) {
|
||||||
runWithError(ledgerIdentityService, false, true, "Issuances have a time-window")
|
runWithError(ledgerIdentityService, false, true, "Issuances have a time-window")
|
||||||
@ -530,8 +531,8 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
|
|||||||
|
|
||||||
private fun runBuyerAndSeller(notary: Party,
|
private fun runBuyerAndSeller(notary: Party,
|
||||||
buyer: Party,
|
buyer: Party,
|
||||||
sellerNode: StartedNode<MockNetwork.MockNode>,
|
sellerNode: StartedNode<InternalMockNetwork.MockNode>,
|
||||||
buyerNode: StartedNode<MockNetwork.MockNode>,
|
buyerNode: StartedNode<InternalMockNetwork.MockNode>,
|
||||||
assetToSell: StateAndRef<OwnableState>): RunResult {
|
assetToSell: StateAndRef<OwnableState>): RunResult {
|
||||||
val buyerFlows: Observable<out FlowLogic<*>> = buyerNode.registerInitiatedFlow(BuyerAcceptor::class.java)
|
val buyerFlows: Observable<out FlowLogic<*>> = buyerNode.registerInitiatedFlow(BuyerAcceptor::class.java)
|
||||||
val firstBuyerFiber = buyerFlows.toFuture().map { it.stateMachine }
|
val firstBuyerFiber = buyerFlows.toFuture().map { it.stateMachine }
|
||||||
|
@ -12,13 +12,9 @@ import net.corda.core.transactions.TransactionBuilder
|
|||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.node.internal.StartedNode
|
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.core.*
|
import net.corda.testing.core.*
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.*
|
||||||
import net.corda.testing.node.MockNetwork.NotarySpec
|
|
||||||
import net.corda.testing.node.MockNodeParameters
|
|
||||||
import net.corda.testing.node.startFlow
|
|
||||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -30,9 +26,9 @@ import kotlin.test.assertTrue
|
|||||||
|
|
||||||
class NotaryChangeTests {
|
class NotaryChangeTests {
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var oldNotaryNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var oldNotaryNode: StartedMockNode
|
||||||
private lateinit var clientNodeA: StartedNode<MockNetwork.MockNode>
|
private lateinit var clientNodeA: StartedMockNode
|
||||||
private lateinit var clientNodeB: StartedNode<MockNetwork.MockNode>
|
private lateinit var clientNodeB: StartedMockNode
|
||||||
private lateinit var newNotaryParty: Party
|
private lateinit var newNotaryParty: Party
|
||||||
private lateinit var oldNotaryParty: Party
|
private lateinit var oldNotaryParty: Party
|
||||||
private lateinit var clientA: Party
|
private lateinit var clientA: Party
|
||||||
@ -41,7 +37,7 @@ class NotaryChangeTests {
|
|||||||
fun setUp() {
|
fun setUp() {
|
||||||
val oldNotaryName = CordaX500Name("Regulator A", "Paris", "FR")
|
val oldNotaryName = CordaX500Name("Regulator A", "Paris", "FR")
|
||||||
mockNet = MockNetwork(
|
mockNet = MockNetwork(
|
||||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY_NAME), NotarySpec(oldNotaryName)),
|
notarySpecs = listOf(MockNetworkNotarySpec(DUMMY_NOTARY_NAME), MockNetworkNotarySpec(oldNotaryName)),
|
||||||
cordappPackages = listOf("net.corda.testing.contracts")
|
cordappPackages = listOf("net.corda.testing.contracts")
|
||||||
)
|
)
|
||||||
clientNodeA = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
clientNodeA = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
||||||
@ -145,7 +141,7 @@ class NotaryChangeTests {
|
|||||||
assertEquals(issued.state, changedNotaryBack.state)
|
assertEquals(issued.state, changedNotaryBack.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changeNotary(movedState: StateAndRef<DummyContract.SingleOwnerState>, node: StartedNode<*>, newNotary: Party): StateAndRef<DummyContract.SingleOwnerState> {
|
private fun changeNotary(movedState: StateAndRef<DummyContract.SingleOwnerState>, node: StartedMockNode, newNotary: Party): StateAndRef<DummyContract.SingleOwnerState> {
|
||||||
val flow = NotaryChangeFlow(movedState, newNotary)
|
val flow = NotaryChangeFlow(movedState, newNotary)
|
||||||
val future = node.services.startFlow(flow)
|
val future = node.services.startFlow(flow)
|
||||||
mockNet.runNetwork()
|
mockNet.runNetwork()
|
||||||
@ -153,7 +149,7 @@ class NotaryChangeTests {
|
|||||||
return future.getOrThrow()
|
return future.getOrThrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun moveState(state: StateAndRef<DummyContract.SingleOwnerState>, fromNode: StartedNode<*>, toNode: StartedNode<*>): StateAndRef<DummyContract.SingleOwnerState> {
|
private fun moveState(state: StateAndRef<DummyContract.SingleOwnerState>, fromNode: StartedMockNode, toNode: StartedMockNode): StateAndRef<DummyContract.SingleOwnerState> {
|
||||||
val tx = DummyContract.move(state, toNode.info.chooseIdentity())
|
val tx = DummyContract.move(state, toNode.info.chooseIdentity())
|
||||||
val stx = fromNode.services.signInitialTransaction(tx)
|
val stx = fromNode.services.signInitialTransaction(tx)
|
||||||
|
|
||||||
@ -203,7 +199,7 @@ fun issueState(services: ServiceHub, nodeIdentity: Party, notaryIdentity: Party)
|
|||||||
return stx.tx.outRef(0)
|
return stx.tx.outRef(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun issueMultiPartyState(nodeA: StartedNode<*>, nodeB: StartedNode<*>, notaryNode: StartedNode<*>, notaryIdentity: Party): StateAndRef<DummyContract.MultiOwnerState> {
|
fun issueMultiPartyState(nodeA: StartedMockNode, nodeB: StartedMockNode, notaryNode: StartedMockNode, notaryIdentity: Party): StateAndRef<DummyContract.MultiOwnerState> {
|
||||||
val participants = listOf(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())
|
val participants = listOf(nodeA.info.chooseIdentity(), nodeB.info.chooseIdentity())
|
||||||
val state = TransactionState(
|
val state = TransactionState(
|
||||||
DummyContract.MultiOwnerState(0, participants),
|
DummyContract.MultiOwnerState(0, participants),
|
||||||
|
@ -25,8 +25,9 @@ import net.corda.testing.core.ALICE_NAME
|
|||||||
import net.corda.testing.core.BOB_NAME
|
import net.corda.testing.core.BOB_NAME
|
||||||
import net.corda.testing.core.dummyCommand
|
import net.corda.testing.core.dummyCommand
|
||||||
import net.corda.testing.core.singleIdentity
|
import net.corda.testing.core.singleIdentity
|
||||||
import net.corda.testing.node.MockNetwork
|
|
||||||
import net.corda.testing.node.MockNodeParameters
|
import net.corda.testing.node.MockNodeParameters
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork.MockNode
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.*
|
import org.junit.Assert.*
|
||||||
@ -42,9 +43,9 @@ class ScheduledFlowTests {
|
|||||||
val SORTING = Sort(listOf(Sort.SortColumn(SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_TXN_ID), Sort.Direction.DESC)))
|
val SORTING = Sort(listOf(Sort.SortColumn(SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_TXN_ID), Sort.Direction.DESC)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: InternalMockNetwork
|
||||||
private lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var aliceNode: StartedNode<MockNode>
|
||||||
private lateinit var bobNode: StartedNode<MockNetwork.MockNode>
|
private lateinit var bobNode: StartedNode<MockNode>
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
private lateinit var alice: Party
|
private lateinit var alice: Party
|
||||||
private lateinit var bob: Party
|
private lateinit var bob: Party
|
||||||
@ -102,7 +103,7 @@ class ScheduledFlowTests {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.testing.contracts"))
|
mockNet = InternalMockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.testing.contracts"))
|
||||||
aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
|
||||||
bobNode = mockNet.createNode(MockNodeParameters(legalName = BOB_NAME))
|
bobNode = mockNet.createNode(MockNodeParameters(legalName = BOB_NAME))
|
||||||
notary = mockNet.defaultNotaryIdentity
|
notary = mockNet.defaultNotaryIdentity
|
||||||
|
@ -11,7 +11,7 @@ import net.corda.core.utilities.getOrThrow
|
|||||||
import net.corda.node.services.api.ServiceHubInternal
|
import net.corda.node.services.api.ServiceHubInternal
|
||||||
import net.corda.node.services.schema.NodeSchemaService.NodeCoreV1
|
import net.corda.node.services.schema.NodeSchemaService.NodeCoreV1
|
||||||
import net.corda.node.services.schema.NodeSchemaService.NodeNotaryV1
|
import net.corda.node.services.schema.NodeSchemaService.NodeNotaryV1
|
||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.InProcess
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
|
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
@ -26,7 +26,7 @@ import kotlin.test.assertTrue
|
|||||||
|
|
||||||
class NodeSchemaServiceTest {
|
class NodeSchemaServiceTest {
|
||||||
/**
|
/**
|
||||||
* Note: this test requires explicitly registering custom contract schemas with a MockNode
|
* Note: this test requires explicitly registering custom contract schemas with a StartedMockNode
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun `registering custom schemas for testing with MockNode`() {
|
fun `registering custom schemas for testing with MockNode`() {
|
||||||
@ -79,7 +79,7 @@ class NodeSchemaServiceTest {
|
|||||||
fun `custom schemas are loaded eagerly`() {
|
fun `custom schemas are loaded eagerly`() {
|
||||||
val expected = setOf("PARENTS", "CHILDREN")
|
val expected = setOf("PARENTS", "CHILDREN")
|
||||||
val tables = driver(startNodesInProcess = true) {
|
val tables = driver(startNodesInProcess = true) {
|
||||||
(defaultNotaryNode.getOrThrow() as NodeHandle.InProcess).node.database.transaction {
|
(defaultNotaryNode.getOrThrow() as InProcess).database.transaction {
|
||||||
session.createNativeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES").list()
|
session.createNativeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES").list()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,11 +34,11 @@ import net.corda.testing.core.*
|
|||||||
import net.corda.testing.internal.LogHelper
|
import net.corda.testing.internal.LogHelper
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork.MessageTransfer
|
import net.corda.testing.node.InMemoryMessagingNetwork.MessageTransfer
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||||
import net.corda.testing.node.MockNetwork
|
|
||||||
import net.corda.testing.node.MockNetwork.MockNode
|
|
||||||
import net.corda.testing.node.MockNodeParameters
|
import net.corda.testing.node.MockNodeParameters
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork.MockNode
|
||||||
|
import net.corda.testing.node.internal.pumpReceive
|
||||||
import net.corda.testing.node.internal.startFlow
|
import net.corda.testing.node.internal.startFlow
|
||||||
import net.corda.testing.node.pumpReceive
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType
|
import org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType
|
||||||
@ -62,7 +62,7 @@ class FlowFrameworkTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: InternalMockNetwork
|
||||||
private val receivedSessionMessages = ArrayList<SessionTransfer>()
|
private val receivedSessionMessages = ArrayList<SessionTransfer>()
|
||||||
private lateinit var aliceNode: StartedNode<MockNode>
|
private lateinit var aliceNode: StartedNode<MockNode>
|
||||||
private lateinit var bobNode: StartedNode<MockNode>
|
private lateinit var bobNode: StartedNode<MockNode>
|
||||||
@ -76,7 +76,7 @@ class FlowFrameworkTests {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun start() {
|
fun start() {
|
||||||
mockNet = MockNetwork(
|
mockNet = InternalMockNetwork(
|
||||||
servicePeerAllocationStrategy = RoundRobin(),
|
servicePeerAllocationStrategy = RoundRobin(),
|
||||||
cordappPackages = listOf("net.corda.finance.contracts", "net.corda.testing.contracts")
|
cordappPackages = listOf("net.corda.finance.contracts", "net.corda.testing.contracts")
|
||||||
)
|
)
|
||||||
@ -145,7 +145,7 @@ class FlowFrameworkTests {
|
|||||||
val restoredFlow = bobNode.restartAndGetRestoredFlow<InitiatedReceiveFlow>()
|
val restoredFlow = bobNode.restartAndGetRestoredFlow<InitiatedReceiveFlow>()
|
||||||
assertThat(restoredFlow.receivedPayloads[0]).isEqualTo("Hello")
|
assertThat(restoredFlow.receivedPayloads[0]).isEqualTo("Hello")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `flow loaded from checkpoint will respond to messages from before start`() {
|
fun `flow loaded from checkpoint will respond to messages from before start`() {
|
||||||
aliceNode.registerFlowFactory(ReceiveFlow::class) { InitiatedSendFlow("Hello", it) }
|
aliceNode.registerFlowFactory(ReceiveFlow::class) { InitiatedSendFlow("Hello", it) }
|
||||||
|
@ -30,6 +30,7 @@ import net.corda.testing.core.chooseIdentity
|
|||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.internal.rigorousMock
|
import net.corda.testing.internal.rigorousMock
|
||||||
import net.corda.testing.node.MockNodeParameters
|
import net.corda.testing.node.MockNodeParameters
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
import net.corda.testing.node.startFlow
|
import net.corda.testing.node.startFlow
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -38,7 +39,7 @@ import java.util.concurrent.atomic.AtomicBoolean
|
|||||||
import kotlin.reflect.jvm.jvmName
|
import kotlin.reflect.jvm.jvmName
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class NodePair(private val mockNet: MockNetwork) {
|
class NodePair(private val mockNet: InternalMockNetwork) {
|
||||||
private class ServerLogic(private val session: FlowSession, private val running: AtomicBoolean) : FlowLogic<Unit>() {
|
private class ServerLogic(private val session: FlowSession, private val running: AtomicBoolean) : FlowLogic<Unit>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() {
|
override fun call() {
|
||||||
@ -81,8 +82,8 @@ class VaultSoftLockManagerTest {
|
|||||||
private val mockVault = rigorousMock<VaultServiceInternal>().also {
|
private val mockVault = rigorousMock<VaultServiceInternal>().also {
|
||||||
doNothing().whenever(it).softLockRelease(any(), anyOrNull())
|
doNothing().whenever(it).softLockRelease(any(), anyOrNull())
|
||||||
}
|
}
|
||||||
private val mockNet = MockNetwork(cordappPackages = listOf(ContractImpl::class.packageName), defaultFactory = { args ->
|
private val mockNet = InternalMockNetwork(cordappPackages = listOf(ContractImpl::class.packageName), defaultFactory = { args ->
|
||||||
object : MockNetwork.MockNode(args) {
|
object : InternalMockNetwork.MockNode(args) {
|
||||||
override fun makeVaultService(keyManagementService: KeyManagementService, stateLoader: StateLoader, hibernateConfig: HibernateConfiguration): VaultServiceInternal {
|
override fun makeVaultService(keyManagementService: KeyManagementService, stateLoader: StateLoader, hibernateConfig: HibernateConfiguration): VaultServiceInternal {
|
||||||
val realVault = super.makeVaultService(keyManagementService, stateLoader, hibernateConfig)
|
val realVault = super.makeVaultService(keyManagementService, stateLoader, hibernateConfig)
|
||||||
return object : VaultServiceInternal by realVault {
|
return object : VaultServiceInternal by realVault {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.attachmentdemo
|
package net.corda.attachmentdemo
|
||||||
|
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.services.Permissions.Companion.invokeRpc
|
import net.corda.node.services.Permissions.Companion.invokeRpc
|
||||||
@ -9,6 +10,7 @@ import net.corda.testing.core.DUMMY_BANK_B_NAME
|
|||||||
import net.corda.testing.node.User
|
import net.corda.testing.node.User
|
||||||
import net.corda.testing.driver.PortAllocation
|
import net.corda.testing.driver.PortAllocation
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
|
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.concurrent.CompletableFuture.supplyAsync
|
import java.util.concurrent.CompletableFuture.supplyAsync
|
||||||
|
|
||||||
@ -30,17 +32,17 @@ class AttachmentDemoTest {
|
|||||||
startNode(providedName = DUMMY_BANK_A_NAME, rpcUsers = demoUser, maximumHeapSize = "1g"),
|
startNode(providedName = DUMMY_BANK_A_NAME, rpcUsers = demoUser, maximumHeapSize = "1g"),
|
||||||
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = demoUser, maximumHeapSize = "1g")
|
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = demoUser, maximumHeapSize = "1g")
|
||||||
).map { it.getOrThrow() }
|
).map { it.getOrThrow() }
|
||||||
startWebserver(nodeB).getOrThrow()
|
val webserverHandle = startWebserver(nodeB).getOrThrow()
|
||||||
|
|
||||||
val senderThread = supplyAsync {
|
val senderThread = supplyAsync {
|
||||||
nodeA.rpcClientToNode().start(demoUser[0].username, demoUser[0].password).use {
|
CordaRPCClient(nodeA.rpcAddress).start(demoUser[0].username, demoUser[0].password).use {
|
||||||
sender(it.proxy, numOfExpectedBytes)
|
sender(it.proxy, numOfExpectedBytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val recipientThread = supplyAsync {
|
val recipientThread = supplyAsync {
|
||||||
nodeB.rpcClientToNode().start(demoUser[0].username, demoUser[0].password).use {
|
CordaRPCClient(nodeB.rpcAddress).start(demoUser[0].username, demoUser[0].password).use {
|
||||||
recipient(it.proxy, nodeB.webAddress.port)
|
recipient(it.proxy, webserverHandle.listenAddress.port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.bank
|
package net.corda.bank
|
||||||
|
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.node.services.Vault
|
import net.corda.core.node.services.Vault
|
||||||
@ -37,11 +38,11 @@ class BankOfCordaRPCClientTest {
|
|||||||
).map { it.getOrThrow() }
|
).map { it.getOrThrow() }
|
||||||
|
|
||||||
// Bank of Corda RPC Client
|
// Bank of Corda RPC Client
|
||||||
val bocClient = nodeBankOfCorda.rpcClientToNode()
|
val bocClient = CordaRPCClient(nodeBankOfCorda.rpcAddress)
|
||||||
val bocProxy = bocClient.start("bocManager", "password1").proxy
|
val bocProxy = bocClient.start("bocManager", "password1").proxy
|
||||||
|
|
||||||
// Big Corporation RPC Client
|
// Big Corporation RPC Client
|
||||||
val bigCorpClient = nodeBigCorporation.rpcClientToNode()
|
val bigCorpClient = CordaRPCClient(nodeBigCorporation.rpcAddress)
|
||||||
val bigCorpProxy = bigCorpClient.start("bigCorpCFO", "password2").proxy
|
val bigCorpProxy = bigCorpClient.start("bigCorpCFO", "password2").proxy
|
||||||
|
|
||||||
// Register for Bank of Corda Vault updates
|
// Register for Bank of Corda Vault updates
|
||||||
|
@ -15,6 +15,7 @@ import net.corda.core.identity.CordaX500Name
|
|||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.messaging.vaultTrackBy
|
import net.corda.core.messaging.vaultTrackBy
|
||||||
import net.corda.core.toFuture
|
import net.corda.core.toFuture
|
||||||
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
@ -78,7 +79,7 @@ class IRSDemoTest {
|
|||||||
registerIRSModule(mapper)
|
registerIRSModule(mapper)
|
||||||
HttpApi.fromHostAndPort(it.second, "api/irs", mapper = mapper)
|
HttpApi.fromHostAndPort(it.second, "api/irs", mapper = mapper)
|
||||||
}
|
}
|
||||||
val nextFixingDates = getFixingDateObservable(nodeA.configuration)
|
val nextFixingDates = getFixingDateObservable(nodeA.rpcAddress)
|
||||||
val numADeals = getTradeCount(nodeAApi)
|
val numADeals = getTradeCount(nodeAApi)
|
||||||
val numBDeals = getTradeCount(nodeBApi)
|
val numBDeals = getTradeCount(nodeBApi)
|
||||||
|
|
||||||
@ -102,8 +103,8 @@ class IRSDemoTest {
|
|||||||
return getTrades(nodeApi)[0].calculation.floatingLegPaymentSchedule.count { it.value.rate.ratioUnit != null }
|
return getTrades(nodeApi)[0].calculation.floatingLegPaymentSchedule.count { it.value.rate.ratioUnit != null }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFixingDateObservable(config: NodeConfiguration): Observable<LocalDate?> {
|
private fun getFixingDateObservable(address: NetworkHostAndPort): Observable<LocalDate?> {
|
||||||
val client = CordaRPCClient(config.rpcOptions.address!!)
|
val client = CordaRPCClient(address)
|
||||||
val proxy = client.start("user", "password").proxy
|
val proxy = client.start("user", "password").proxy
|
||||||
val vaultUpdates = proxy.vaultTrackBy<InterestRateSwap.State>().updates
|
val vaultUpdates = proxy.vaultTrackBy<InterestRateSwap.State>().updates
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import net.corda.testing.driver.DriverParameters
|
|||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.NodeHandle
|
||||||
import net.corda.testing.driver.PortAllocation
|
import net.corda.testing.driver.PortAllocation
|
||||||
import net.corda.testing.driver.WebserverHandle
|
import net.corda.testing.driver.WebserverHandle
|
||||||
|
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
import net.corda.testing.node.internal.*
|
import net.corda.testing.node.internal.*
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@ -68,12 +69,12 @@ data class SpringBootDriverDSL(private val driverDSL: DriverDSLImpl) : InternalD
|
|||||||
val debugPort = if (driverDSL.isDebug) driverDSL.debugPortAllocation.nextPort() else null
|
val debugPort = if (driverDSL.isDebug) driverDSL.debugPortAllocation.nextPort() else null
|
||||||
val process = startApplication(handle, debugPort, clazz)
|
val process = startApplication(handle, debugPort, clazz)
|
||||||
driverDSL.shutdownManager.registerProcessShutdown(process)
|
driverDSL.shutdownManager.registerProcessShutdown(process)
|
||||||
val webReadyFuture = addressMustBeBoundFuture(driverDSL.executorService, handle.webAddress, process)
|
val webReadyFuture = addressMustBeBoundFuture(driverDSL.executorService, (handle as NodeHandleInternal).webAddress, process)
|
||||||
return webReadyFuture.map { queryWebserver(handle, process, checkUrl) }
|
return webReadyFuture.map { queryWebserver(handle, process, checkUrl) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun queryWebserver(handle: NodeHandle, process: Process, checkUrl: String): WebserverHandle {
|
private fun queryWebserver(handle: NodeHandle, process: Process, checkUrl: String): WebserverHandle {
|
||||||
val protocol = if (handle.useHTTPS) "https://" else "http://"
|
val protocol = if ((handle as NodeHandleInternal).useHTTPS) "https://" else "http://"
|
||||||
val url = URL(URL("$protocol${handle.webAddress}"), checkUrl)
|
val url = URL(URL("$protocol${handle.webAddress}"), checkUrl)
|
||||||
val client = OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).build()
|
val client = OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).build()
|
||||||
|
|
||||||
@ -102,19 +103,19 @@ data class SpringBootDriverDSL(private val driverDSL: DriverDSLImpl) : InternalD
|
|||||||
className = className, // cannot directly get class for this, so just use string
|
className = className, // cannot directly get class for this, so just use string
|
||||||
jdwpPort = debugPort,
|
jdwpPort = debugPort,
|
||||||
extraJvmArguments = listOf(
|
extraJvmArguments = listOf(
|
||||||
"-Dname=node-${handle.configuration.p2pAddress}-webserver",
|
"-Dname=node-${handle.p2pAddress}-webserver",
|
||||||
"-Djava.io.tmpdir=${System.getProperty("java.io.tmpdir")}"
|
"-Djava.io.tmpdir=${System.getProperty("java.io.tmpdir")}"
|
||||||
// Inherit from parent process
|
// Inherit from parent process
|
||||||
),
|
),
|
||||||
classpath = ProcessUtilities.defaultClassPath,
|
classpath = ProcessUtilities.defaultClassPath,
|
||||||
workingDirectory = handle.configuration.baseDirectory,
|
workingDirectory = handle.baseDirectory,
|
||||||
errorLogPath = Paths.get("error.$className.log"),
|
errorLogPath = Paths.get("error.$className.log"),
|
||||||
arguments = listOf(
|
arguments = listOf(
|
||||||
"--base-directory", handle.configuration.baseDirectory.toString(),
|
"--base-directory", handle.baseDirectory.toString(),
|
||||||
"--server.port=${handle.webAddress.port}",
|
"--server.port=${(handle as NodeHandleInternal).webAddress.port}",
|
||||||
"--corda.host=${handle.configuration.rpcOptions.address}",
|
"--corda.host=${handle.rpcAddress}",
|
||||||
"--corda.user=${handle.configuration.rpcUsers.first().username}",
|
"--corda.user=${handle.rpcUsers.first().username}",
|
||||||
"--corda.password=${handle.configuration.rpcUsers.first().password}"
|
"--corda.password=${handle.rpcUsers.first().password}"
|
||||||
),
|
),
|
||||||
maximumHeapSize = null
|
maximumHeapSize = null
|
||||||
)
|
)
|
||||||
|
@ -19,6 +19,7 @@ import net.corda.node.services.statemachine.*
|
|||||||
import net.corda.testing.core.chooseIdentity
|
import net.corda.testing.core.chooseIdentity
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork
|
import net.corda.testing.node.InMemoryMessagingNetwork
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
import rx.Scheduler
|
import rx.Scheduler
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
@ -105,8 +106,8 @@ class NetworkMapVisualiser : Application() {
|
|||||||
}
|
}
|
||||||
// Fire the message bullets between nodes.
|
// Fire the message bullets between nodes.
|
||||||
simulation.mockNet.messagingNetwork.sentMessages.observeOn(uiThread).subscribe { msg: InMemoryMessagingNetwork.MessageTransfer ->
|
simulation.mockNet.messagingNetwork.sentMessages.observeOn(uiThread).subscribe { msg: InMemoryMessagingNetwork.MessageTransfer ->
|
||||||
val senderNode: MockNetwork.MockNode = simulation.mockNet.addressToNode(msg.sender)
|
val senderNode: InternalMockNetwork.MockNode = simulation.mockNet.addressToNode(msg.sender)
|
||||||
val destNode: MockNetwork.MockNode = simulation.mockNet.addressToNode(msg.recipients)
|
val destNode: InternalMockNetwork.MockNode = simulation.mockNet.addressToNode(msg.recipients)
|
||||||
|
|
||||||
if (transferIsInteresting(msg)) {
|
if (transferIsInteresting(msg)) {
|
||||||
viewModel.nodesToWidgets[senderNode]!!.pulseAnim.play()
|
viewModel.nodesToWidgets[senderNode]!!.pulseAnim.play()
|
||||||
@ -114,7 +115,7 @@ class NetworkMapVisualiser : Application() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Pulse all parties in a trade when the trade completes
|
// Pulse all parties in a trade when the trade completes
|
||||||
simulation.doneSteps.observeOn(uiThread).subscribe { nodes: Collection<MockNetwork.MockNode> ->
|
simulation.doneSteps.observeOn(uiThread).subscribe { nodes: Collection<InternalMockNetwork.MockNode> ->
|
||||||
nodes.forEach { viewModel.nodesToWidgets[it]!!.longPulseAnim.play() }
|
nodes.forEach { viewModel.nodesToWidgets[it]!!.longPulseAnim.play() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import net.corda.finance.utils.ScreenCoordinate
|
|||||||
import net.corda.netmap.simulation.IRSSimulation
|
import net.corda.netmap.simulation.IRSSimulation
|
||||||
import net.corda.netmap.simulation.place
|
import net.corda.netmap.simulation.place
|
||||||
import net.corda.testing.core.chooseIdentity
|
import net.corda.testing.core.chooseIdentity
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class VisualiserViewModel {
|
class VisualiserViewModel {
|
||||||
@ -25,10 +25,10 @@ class VisualiserViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class NodeWidget(val node: MockNetwork.MockNode, val innerDot: Circle, val outerDot: Circle, val longPulseDot: Circle,
|
inner class NodeWidget(val node: InternalMockNetwork.MockNode, val innerDot: Circle, val outerDot: Circle, val longPulseDot: Circle,
|
||||||
val pulseAnim: Animation, val longPulseAnim: Animation,
|
val pulseAnim: Animation, val longPulseAnim: Animation,
|
||||||
val nameLabel: Label, val statusLabel: Label) {
|
val nameLabel: Label, val statusLabel: Label) {
|
||||||
fun position(nodeCoords: (node: MockNetwork.MockNode) -> ScreenCoordinate) {
|
fun position(nodeCoords: (node: InternalMockNetwork.MockNode) -> ScreenCoordinate) {
|
||||||
val (x, y) = nodeCoords(node)
|
val (x, y) = nodeCoords(node)
|
||||||
innerDot.centerX = x
|
innerDot.centerX = x
|
||||||
innerDot.centerY = y
|
innerDot.centerY = y
|
||||||
@ -47,7 +47,7 @@ class VisualiserViewModel {
|
|||||||
|
|
||||||
val trackerBoxes = HashMap<ProgressTracker, TrackerWidget>()
|
val trackerBoxes = HashMap<ProgressTracker, TrackerWidget>()
|
||||||
val doneTrackers = ArrayList<ProgressTracker>()
|
val doneTrackers = ArrayList<ProgressTracker>()
|
||||||
val nodesToWidgets = HashMap<MockNetwork.MockNode, NodeWidget>()
|
val nodesToWidgets = HashMap<InternalMockNetwork.MockNode, NodeWidget>()
|
||||||
|
|
||||||
var bankCount: Int = 0
|
var bankCount: Int = 0
|
||||||
var serviceCount: Int = 0
|
var serviceCount: Int = 0
|
||||||
@ -78,7 +78,7 @@ class VisualiserViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun nodeMapCoords(node: MockNetwork.MockNode): ScreenCoordinate {
|
fun nodeMapCoords(node: InternalMockNetwork.MockNode): ScreenCoordinate {
|
||||||
// For an image of the whole world, we use:
|
// For an image of the whole world, we use:
|
||||||
// return node.place.coordinate.project(mapImage.fitWidth, mapImage.fitHeight, 85.0511, -85.0511, -180.0, 180.0)
|
// return node.place.coordinate.project(mapImage.fitWidth, mapImage.fitHeight, 85.0511, -85.0511, -180.0, 180.0)
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ class VisualiserViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun makeNodeWidget(forNode: MockNetwork.MockNode, type: String, label: CordaX500Name = CordaX500Name(organisation = "Bank of Bologna", locality = "Bologna", country = "IT"),
|
fun makeNodeWidget(forNode: InternalMockNetwork.MockNode, type: String, label: CordaX500Name = CordaX500Name(organisation = "Bank of Bologna", locality = "Bologna", country = "IT"),
|
||||||
nodeType: NetworkMapVisualiser.NodeType, index: Int): NodeWidget {
|
nodeType: NetworkMapVisualiser.NodeType, index: Int): NodeWidget {
|
||||||
fun emitRadarPulse(initialRadius: Double, targetRadius: Double, duration: Double): Pair<Circle, Animation> {
|
fun emitRadarPulse(initialRadius: Double, targetRadius: Double, duration: Double): Pair<Circle, Animation> {
|
||||||
val pulse = Circle(initialRadius).apply {
|
val pulse = Circle(initialRadius).apply {
|
||||||
@ -180,7 +180,7 @@ class VisualiserViewModel {
|
|||||||
return widget
|
return widget
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fireBulletBetweenNodes(senderNode: MockNetwork.MockNode, destNode: MockNetwork.MockNode, startType: String, endType: String) {
|
fun fireBulletBetweenNodes(senderNode: InternalMockNetwork.MockNode, destNode: InternalMockNetwork.MockNode, startType: String, endType: String) {
|
||||||
val sx = nodesToWidgets[senderNode]!!.innerDot.centerX
|
val sx = nodesToWidgets[senderNode]!!.innerDot.centerX
|
||||||
val sy = nodesToWidgets[senderNode]!!.innerDot.centerY
|
val sy = nodesToWidgets[senderNode]!!.innerDot.centerY
|
||||||
val dx = nodesToWidgets[destNode]!!.innerDot.centerX
|
val dx = nodesToWidgets[destNode]!!.innerDot.centerX
|
||||||
|
@ -10,9 +10,12 @@ import net.corda.irs.api.NodeInterestRates
|
|||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
import net.corda.node.services.statemachine.StateMachineManager
|
import net.corda.node.services.statemachine.StateMachineManager
|
||||||
import net.corda.testing.core.TestIdentity
|
import net.corda.testing.core.TestIdentity
|
||||||
import net.corda.testing.node.*
|
import net.corda.testing.node.InMemoryMessagingNetwork
|
||||||
import net.corda.testing.node.MockNetwork.MockNode
|
import net.corda.testing.node.MockNodeParameters
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
|
import net.corda.testing.node.TestClock
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
|
import net.corda.testing.node.internal.MockNodeArgs
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
@ -24,7 +27,7 @@ import java.util.concurrent.CompletableFuture
|
|||||||
import java.util.concurrent.CompletableFuture.allOf
|
import java.util.concurrent.CompletableFuture.allOf
|
||||||
import java.util.concurrent.Future
|
import java.util.concurrent.Future
|
||||||
|
|
||||||
internal val MockNode.place get() = configuration.myLegalName.locality.let { CityDatabase[it] }!!
|
internal val InternalMockNetwork.MockNode.place get() = configuration.myLegalName.locality.let { CityDatabase[it] }!!
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for network simulations that are based on the unit test / mock environment.
|
* Base class for network simulations that are based on the unit test / mock environment.
|
||||||
@ -50,7 +53,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
|
|
||||||
val bankLocations = listOf(Pair("London", "GB"), Pair("Frankfurt", "DE"), Pair("Rome", "IT"))
|
val bankLocations = listOf(Pair("London", "GB"), Pair("Frankfurt", "DE"), Pair("Rome", "IT"))
|
||||||
|
|
||||||
class RatesOracleNode(args: MockNodeArgs) : MockNode(args) {
|
class RatesOracleNode(args: MockNodeArgs) : InternalMockNetwork.MockNode(args) {
|
||||||
companion object {
|
companion object {
|
||||||
// TODO: Make a more realistic legal name
|
// TODO: Make a more realistic legal name
|
||||||
val RATES_SERVICE_NAME = CordaX500Name(organisation = "Rates Service Provider", locality = "Madrid", country = "ES")
|
val RATES_SERVICE_NAME = CordaX500Name(organisation = "Rates Service Provider", locality = "Madrid", country = "ES")
|
||||||
@ -67,7 +70,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val mockNet = MockNetwork(
|
val mockNet = InternalMockNetwork(
|
||||||
networkSendManuallyPumped = networkSendManuallyPumped,
|
networkSendManuallyPumped = networkSendManuallyPumped,
|
||||||
threadPerNode = runAsync,
|
threadPerNode = runAsync,
|
||||||
cordappPackages = listOf("net.corda.finance.contract", "net.corda.irs"))
|
cordappPackages = listOf("net.corda.finance.contract", "net.corda.irs"))
|
||||||
@ -77,8 +80,8 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
val regulators = listOf(mockNet.createUnstartedNode(defaultParams.copy(legalName = DUMMY_REGULATOR.name)))
|
val regulators = listOf(mockNet.createUnstartedNode(defaultParams.copy(legalName = DUMMY_REGULATOR.name)))
|
||||||
val ratesOracle = mockNet.createUnstartedNode(defaultParams.copy(legalName = RatesOracleNode.RATES_SERVICE_NAME), ::RatesOracleNode)
|
val ratesOracle = mockNet.createUnstartedNode(defaultParams.copy(legalName = RatesOracleNode.RATES_SERVICE_NAME), ::RatesOracleNode)
|
||||||
// All nodes must be in one of these two lists for the purposes of the visualiser tool.
|
// All nodes must be in one of these two lists for the purposes of the visualiser tool.
|
||||||
val serviceProviders: List<MockNode> = listOf(mockNet.defaultNotaryNode.internals, ratesOracle)
|
val serviceProviders: List<InternalMockNetwork.MockNode> = listOf(mockNet.defaultNotaryNode.internals, ratesOracle)
|
||||||
val banks: List<MockNode> = bankLocations.mapIndexed { i, (city, country) ->
|
val banks: List<InternalMockNetwork.MockNode> = bankLocations.mapIndexed { i, (city, country) ->
|
||||||
val legalName = CordaX500Name(organisation = "Bank ${'A' + i}", locality = city, country = 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.
|
// 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())))
|
mockNet.createUnstartedNode(defaultParams.copy(legalName = legalName, entropyRoot = BigInteger.valueOf(i.toLong())))
|
||||||
@ -86,12 +89,12 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
val clocks = (serviceProviders + regulators + banks).map { it.platformClock as TestClock }
|
val clocks = (serviceProviders + regulators + banks).map { it.platformClock as TestClock }
|
||||||
|
|
||||||
// These are used from the network visualiser tool.
|
// These are used from the network visualiser tool.
|
||||||
private val _allFlowSteps = PublishSubject.create<Pair<MockNode, ProgressTracker.Change>>()
|
private val _allFlowSteps = PublishSubject.create<Pair<InternalMockNetwork.MockNode, ProgressTracker.Change>>()
|
||||||
private val _doneSteps = PublishSubject.create<Collection<MockNode>>()
|
private val _doneSteps = PublishSubject.create<Collection<InternalMockNetwork.MockNode>>()
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val allFlowSteps: Observable<Pair<MockNode, ProgressTracker.Change>> = _allFlowSteps
|
val allFlowSteps: Observable<Pair<InternalMockNetwork.MockNode, ProgressTracker.Change>> = _allFlowSteps
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val doneSteps: Observable<Collection<MockNode>> = _doneSteps
|
val doneSteps: Observable<Collection<InternalMockNetwork.MockNode>> = _doneSteps
|
||||||
|
|
||||||
private var pumpCursor = 0
|
private var pumpCursor = 0
|
||||||
|
|
||||||
@ -120,7 +123,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
|
* A place for simulations to stash human meaningful text about what the node is "thinking", which might appear
|
||||||
* in the UI somewhere.
|
* in the UI somewhere.
|
||||||
*/
|
*/
|
||||||
val extraNodeLabels: MutableMap<MockNode, String> = Collections.synchronizedMap(HashMap())
|
val extraNodeLabels: MutableMap<InternalMockNetwork.MockNode, String> = Collections.synchronizedMap(HashMap())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterates the simulation by one step.
|
* Iterates the simulation by one step.
|
||||||
@ -151,7 +154,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun showProgressFor(nodes: List<StartedNode<MockNode>>) {
|
protected fun showProgressFor(nodes: List<StartedNode<InternalMockNetwork.MockNode>>) {
|
||||||
nodes.forEach { node ->
|
nodes.forEach { node ->
|
||||||
node.smm.changes.filter { it is StateMachineManager.Change.Add }.subscribe {
|
node.smm.changes.filter { it is StateMachineManager.Change.Add }.subscribe {
|
||||||
linkFlowProgress(node.internals, it.logic)
|
linkFlowProgress(node.internals, it.logic)
|
||||||
@ -159,7 +162,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun linkFlowProgress(node: MockNode, flow: FlowLogic<*>) {
|
private fun linkFlowProgress(node: InternalMockNetwork.MockNode, flow: FlowLogic<*>) {
|
||||||
val pt = flow.progressTracker ?: return
|
val pt = flow.progressTracker ?: return
|
||||||
pt.changes.subscribe { change: ProgressTracker.Change ->
|
pt.changes.subscribe { change: ProgressTracker.Change ->
|
||||||
// Runs on node thread.
|
// Runs on node thread.
|
||||||
@ -168,14 +171,14 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected fun showConsensusFor(nodes: List<MockNode>) {
|
protected fun showConsensusFor(nodes: List<InternalMockNetwork.MockNode>) {
|
||||||
val node = nodes.first()
|
val node = nodes.first()
|
||||||
node.started!!.smm.changes.filter { it is StateMachineManager.Change.Add }.first().subscribe {
|
node.started!!.smm.changes.filter { it is StateMachineManager.Change.Add }.first().subscribe {
|
||||||
linkConsensus(nodes, it.logic)
|
linkConsensus(nodes, it.logic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun linkConsensus(nodes: Collection<MockNode>, flow: FlowLogic<*>) {
|
private fun linkConsensus(nodes: Collection<InternalMockNetwork.MockNode>, flow: FlowLogic<*>) {
|
||||||
flow.progressTracker?.changes?.subscribe { _: ProgressTracker.Change ->
|
flow.progressTracker?.changes?.subscribe { _: ProgressTracker.Change ->
|
||||||
// Runs on node thread.
|
// Runs on node thread.
|
||||||
if (flow.progressTracker!!.currentStep == ProgressTracker.DONE) {
|
if (flow.progressTracker!!.currentStep == ProgressTracker.DONE) {
|
||||||
|
@ -12,7 +12,7 @@ import net.corda.testing.core.BOC_NAME
|
|||||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||||
import net.corda.testing.core.DUMMY_BANK_B_NAME
|
import net.corda.testing.core.DUMMY_BANK_B_NAME
|
||||||
import net.corda.testing.core.chooseIdentity
|
import net.corda.testing.core.chooseIdentity
|
||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.InProcess
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.node.User
|
import net.corda.testing.node.User
|
||||||
import net.corda.testing.node.internal.poll
|
import net.corda.testing.node.internal.poll
|
||||||
@ -37,14 +37,14 @@ class TraderDemoTest {
|
|||||||
startNode(providedName = DUMMY_BANK_A_NAME, rpcUsers = listOf(demoUser)),
|
startNode(providedName = DUMMY_BANK_A_NAME, rpcUsers = listOf(demoUser)),
|
||||||
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser)),
|
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser)),
|
||||||
startNode(providedName = BOC_NAME, rpcUsers = listOf(bankUser))
|
startNode(providedName = BOC_NAME, rpcUsers = listOf(bankUser))
|
||||||
).map { (it.getOrThrow() as NodeHandle.InProcess).node }
|
).map { (it.getOrThrow() as InProcess) }
|
||||||
nodeA.registerInitiatedFlow(BuyerFlow::class.java)
|
nodeA.registerInitiatedFlow(BuyerFlow::class.java)
|
||||||
val (nodeARpc, nodeBRpc) = listOf(nodeA, nodeB).map {
|
val (nodeARpc, nodeBRpc) = listOf(nodeA, nodeB).map {
|
||||||
val client = CordaRPCClient(it.internals.configuration.rpcOptions.address!!)
|
val client = CordaRPCClient(it.rpcAddress)
|
||||||
client.start(demoUser.username, demoUser.password).proxy
|
client.start(demoUser.username, demoUser.password).proxy
|
||||||
}
|
}
|
||||||
val nodeBankRpc = let {
|
val nodeBankRpc = let {
|
||||||
val client = CordaRPCClient(bankNode.internals.configuration.rpcOptions.address!!)
|
val client = CordaRPCClient(bankNode.rpcAddress)
|
||||||
client.start(bankUser.username, bankUser.password).proxy
|
client.start(bankUser.username, bankUser.password).proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,8 +56,8 @@ class TraderDemoTest {
|
|||||||
val expectedBCash = clientB.cashCount + 1
|
val expectedBCash = clientB.cashCount + 1
|
||||||
val expectedPaper = listOf(clientA.commercialPaperCount + 1, clientB.commercialPaperCount)
|
val expectedPaper = listOf(clientA.commercialPaperCount + 1, clientB.commercialPaperCount)
|
||||||
|
|
||||||
clientBank.runIssuer(amount = 100.DOLLARS, buyerName = nodeA.info.chooseIdentity().name, sellerName = nodeB.info.chooseIdentity().name)
|
clientBank.runIssuer(amount = 100.DOLLARS, buyerName = nodeA.services.myInfo.chooseIdentity().name, sellerName = nodeB.services.myInfo.chooseIdentity().name)
|
||||||
clientB.runSeller(buyerName = nodeA.info.chooseIdentity().name, amount = 5.DOLLARS)
|
clientB.runSeller(buyerName = nodeA.services.myInfo.chooseIdentity().name, amount = 5.DOLLARS)
|
||||||
|
|
||||||
assertThat(clientA.cashCount).isGreaterThan(originalACash)
|
assertThat(clientA.cashCount).isGreaterThan(originalACash)
|
||||||
assertThat(clientB.cashCount).isEqualTo(expectedBCash)
|
assertThat(clientB.cashCount).isEqualTo(expectedBCash)
|
||||||
|
@ -15,6 +15,7 @@ import net.corda.testing.node.internal.addressMustNotBeBound
|
|||||||
import net.corda.testing.node.internal.internalDriver
|
import net.corda.testing.node.internal.internalDriver
|
||||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||||
|
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||||
import net.corda.testing.http.HttpApi
|
import net.corda.testing.http.HttpApi
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@ -27,10 +28,11 @@ class DriverTests {
|
|||||||
private companion object {
|
private companion object {
|
||||||
val DUMMY_REGULATOR_NAME = CordaX500Name("Regulator A", "Paris", "FR")
|
val DUMMY_REGULATOR_NAME = CordaX500Name("Regulator A", "Paris", "FR")
|
||||||
val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
|
val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
|
||||||
|
|
||||||
fun nodeMustBeUp(handleFuture: CordaFuture<out NodeHandle>) = handleFuture.getOrThrow().apply {
|
fun nodeMustBeUp(handleFuture: CordaFuture<out NodeHandle>) = handleFuture.getOrThrow().apply {
|
||||||
val hostAndPort = nodeInfo.addresses.single()
|
val hostAndPort = nodeInfo.addresses.single()
|
||||||
// Check that the port is bound
|
// Check that the port is bound
|
||||||
addressMustBeBound(executorService, hostAndPort, (this as? NodeHandle.OutOfProcess)?.process)
|
addressMustBeBound(executorService, hostAndPort, (this as? OutOfProcess)?.process)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun nodeMustBeDown(handle: NodeHandle) {
|
fun nodeMustBeDown(handle: NodeHandle) {
|
||||||
@ -80,7 +82,7 @@ class DriverTests {
|
|||||||
val logConfigFile = projectRootDir / "config" / "dev" / "log4j2.xml"
|
val logConfigFile = projectRootDir / "config" / "dev" / "log4j2.xml"
|
||||||
assertThat(logConfigFile).isRegularFile()
|
assertThat(logConfigFile).isRegularFile()
|
||||||
driver(isDebug = true, systemProperties = mapOf("log4j.configurationFile" to logConfigFile.toString())) {
|
driver(isDebug = true, systemProperties = mapOf("log4j.configurationFile" to logConfigFile.toString())) {
|
||||||
val baseDirectory = startNode(providedName = DUMMY_BANK_A_NAME).getOrThrow().configuration.baseDirectory
|
val baseDirectory = startNode(providedName = DUMMY_BANK_A_NAME).getOrThrow().baseDirectory
|
||||||
val logFile = (baseDirectory / NodeStartup.LOGS_DIRECTORY_NAME).list { it.sorted().findFirst().get() }
|
val logFile = (baseDirectory / NodeStartup.LOGS_DIRECTORY_NAME).list { it.sorted().findFirst().get() }
|
||||||
val debugLinesPresent = logFile.readLines { lines -> lines.anyMatch { line -> line.startsWith("[DEBUG]") } }
|
val debugLinesPresent = logFile.readLines { lines -> lines.anyMatch { line -> line.startsWith("[DEBUG]") } }
|
||||||
assertThat(debugLinesPresent).isTrue()
|
assertThat(debugLinesPresent).isTrue()
|
||||||
@ -105,7 +107,7 @@ class DriverTests {
|
|||||||
// First check that the process-id file is created by the node on startup, so that we can be sure our check that
|
// First check that the process-id file is created by the node on startup, so that we can be sure our check that
|
||||||
// it's deleted on shutdown isn't a false-positive.
|
// it's deleted on shutdown isn't a false-positive.
|
||||||
driver {
|
driver {
|
||||||
val baseDirectory = defaultNotaryNode.getOrThrow().configuration.baseDirectory
|
val baseDirectory = defaultNotaryNode.getOrThrow().baseDirectory
|
||||||
assertThat(baseDirectory / "process-id").exists()
|
assertThat(baseDirectory / "process-id").exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.testing.node
|
|||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.client.jackson.JacksonSupport
|
import net.corda.client.jackson.JacksonSupport
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.list
|
import net.corda.core.internal.list
|
||||||
@ -228,7 +229,7 @@ class FlowStackSnapshotTest {
|
|||||||
fun `flowStackSnapshot contains full frames when methods with side effects are called`() {
|
fun `flowStackSnapshot contains full frames when methods with side effects are called`() {
|
||||||
driver(startNodesInProcess = true) {
|
driver(startNodesInProcess = true) {
|
||||||
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<SideEffectFlow>())))).get()
|
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<SideEffectFlow>())))).get()
|
||||||
a.rpcClientToNode().use(Constants.USER, Constants.PASSWORD) { connection ->
|
CordaRPCClient(a.rpcAddress).use(Constants.USER, Constants.PASSWORD) { connection ->
|
||||||
val stackSnapshotFrames = connection.proxy.startFlow(::SideEffectFlow).returnValue.get()
|
val stackSnapshotFrames = connection.proxy.startFlow(::SideEffectFlow).returnValue.get()
|
||||||
val iterator = stackSnapshotFrames.listIterator()
|
val iterator = stackSnapshotFrames.listIterator()
|
||||||
assertFrame("run", false, iterator.next())
|
assertFrame("run", false, iterator.next())
|
||||||
@ -243,7 +244,7 @@ class FlowStackSnapshotTest {
|
|||||||
fun `flowStackSnapshot contains empty frames when methods with no side effects are called`() {
|
fun `flowStackSnapshot contains empty frames when methods with no side effects are called`() {
|
||||||
driver(startNodesInProcess = true) {
|
driver(startNodesInProcess = true) {
|
||||||
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<NoSideEffectFlow>())))).get()
|
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<NoSideEffectFlow>())))).get()
|
||||||
a.rpcClientToNode().use(Constants.USER, Constants.PASSWORD) { connection ->
|
CordaRPCClient(a.rpcAddress).use(Constants.USER, Constants.PASSWORD) { connection ->
|
||||||
val stackSnapshotFrames = connection.proxy.startFlow(::NoSideEffectFlow).returnValue.get()
|
val stackSnapshotFrames = connection.proxy.startFlow(::NoSideEffectFlow).returnValue.get()
|
||||||
val iterator = stackSnapshotFrames.listIterator()
|
val iterator = stackSnapshotFrames.listIterator()
|
||||||
assertFrame("run", false, iterator.next())
|
assertFrame("run", false, iterator.next())
|
||||||
@ -258,10 +259,9 @@ class FlowStackSnapshotTest {
|
|||||||
fun `persistFlowStackSnapshot persists empty frames to a file when methods with no side effects are called`() {
|
fun `persistFlowStackSnapshot persists empty frames to a file when methods with no side effects are called`() {
|
||||||
driver(startNodesInProcess = true) {
|
driver(startNodesInProcess = true) {
|
||||||
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<PersistingNoSideEffectFlow>())))).get()
|
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<PersistingNoSideEffectFlow>())))).get()
|
||||||
|
CordaRPCClient(a.rpcAddress).use(Constants.USER, Constants.PASSWORD) { connection ->
|
||||||
a.rpcClientToNode().use(Constants.USER, Constants.PASSWORD) { connection ->
|
|
||||||
val flowId = connection.proxy.startFlow(::PersistingNoSideEffectFlow).returnValue.get()
|
val flowId = connection.proxy.startFlow(::PersistingNoSideEffectFlow).returnValue.get()
|
||||||
val snapshotFromFile = readFlowStackSnapshotFromDir(a.configuration.baseDirectory, flowId)
|
val snapshotFromFile = readFlowStackSnapshotFromDir(a.baseDirectory, flowId)
|
||||||
val stackSnapshotFrames = convertToStackSnapshotFrames(snapshotFromFile)
|
val stackSnapshotFrames = convertToStackSnapshotFrames(snapshotFromFile)
|
||||||
val iterator = stackSnapshotFrames.listIterator()
|
val iterator = stackSnapshotFrames.listIterator()
|
||||||
assertFrame("call", true, iterator.next())
|
assertFrame("call", true, iterator.next())
|
||||||
@ -276,10 +276,10 @@ class FlowStackSnapshotTest {
|
|||||||
driver(startNodesInProcess = true) {
|
driver(startNodesInProcess = true) {
|
||||||
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<MultiplePersistingSideEffectFlow>())))).get()
|
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<MultiplePersistingSideEffectFlow>())))).get()
|
||||||
|
|
||||||
a.rpcClientToNode().use(Constants.USER, Constants.PASSWORD) { connection ->
|
CordaRPCClient(a.rpcAddress).use(Constants.USER, Constants.PASSWORD) { connection ->
|
||||||
val numberOfFlowSnapshots = 5
|
val numberOfFlowSnapshots = 5
|
||||||
val flowId = connection.proxy.startFlow(::MultiplePersistingSideEffectFlow, 5).returnValue.get()
|
val flowId = connection.proxy.startFlow(::MultiplePersistingSideEffectFlow, 5).returnValue.get()
|
||||||
val fileCount = countFilesInDir(a.configuration.baseDirectory, flowId)
|
val fileCount = countFilesInDir(a.baseDirectory, flowId)
|
||||||
assertEquals(numberOfFlowSnapshots, fileCount)
|
assertEquals(numberOfFlowSnapshots, fileCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,9 +307,9 @@ class FlowStackSnapshotTest {
|
|||||||
driver(startNodesInProcess = true) {
|
driver(startNodesInProcess = true) {
|
||||||
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<PersistingSideEffectFlow>())))).get()
|
val a = startNode(rpcUsers = listOf(User(Constants.USER, Constants.PASSWORD, setOf(startFlow<PersistingSideEffectFlow>())))).get()
|
||||||
|
|
||||||
a.rpcClientToNode().use(Constants.USER, Constants.PASSWORD) { connection ->
|
CordaRPCClient(a.rpcAddress).use(Constants.USER, Constants.PASSWORD) { connection ->
|
||||||
val flowId = connection.proxy.startFlow(::PersistingSideEffectFlow).returnValue.get()
|
val flowId = connection.proxy.startFlow(::PersistingSideEffectFlow).returnValue.get()
|
||||||
val snapshotFromFile = readFlowStackSnapshotFromDir(a.configuration.baseDirectory, flowId)
|
val snapshotFromFile = readFlowStackSnapshotFromDir(a.baseDirectory, flowId)
|
||||||
var inCallCount = 0
|
var inCallCount = 0
|
||||||
var inPersistCount = 0
|
var inPersistCount = 0
|
||||||
snapshotFromFile.stackFrames.forEach {
|
snapshotFromFile.stackFrames.forEach {
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.testing.node
|
|||||||
|
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.testing.common.internal.ProjectStructure.projectRootDir
|
import net.corda.testing.common.internal.ProjectStructure.projectRootDir
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
import net.corda.testing.node.internal.ProcessUtilities.startJavaProcess
|
import net.corda.testing.node.internal.ProcessUtilities.startJavaProcess
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package net.corda.testing.node.internal
|
||||||
|
|
||||||
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.testing.common.internal.ProjectStructure.projectRootDir
|
||||||
|
import net.corda.testing.node.internal.ProcessUtilities.startJavaProcess
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class InternalMockNetworkIntegrationTests {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
InternalMockNetwork(emptyList()).run {
|
||||||
|
repeat(2) { createNode() }
|
||||||
|
runNetwork()
|
||||||
|
stopNodes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `does not leak non-daemon threads`() {
|
||||||
|
val quasar = projectRootDir / "lib" / "quasar.jar"
|
||||||
|
assertEquals(0, startJavaProcess<InternalMockNetworkIntegrationTests>(emptyList(), extraJvmArguments = listOf("-javaagent:$quasar")).waitFor())
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
package net.corda.testing.driver
|
package net.corda.testing.driver
|
||||||
|
|
||||||
import net.corda.client.rpc.CordaRPCClient
|
|
||||||
import net.corda.core.DoNotImplement
|
import net.corda.core.DoNotImplement
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
@ -12,15 +12,17 @@ import net.corda.core.node.NodeInfo
|
|||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.node.internal.Node
|
import net.corda.node.internal.Node
|
||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
|
import net.corda.node.services.api.StartedNodeServices
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.services.config.VerifierType
|
import net.corda.node.services.config.VerifierType
|
||||||
import net.corda.nodeapi.internal.config.SSLConfiguration
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
import net.corda.testing.node.User
|
import net.corda.testing.node.User
|
||||||
import net.corda.testing.node.internal.DriverDSLImpl
|
import net.corda.testing.node.internal.DriverDSLImpl
|
||||||
import net.corda.testing.node.internal.genericDriver
|
import net.corda.testing.node.internal.genericDriver
|
||||||
import net.corda.testing.node.internal.getTimestampAsDirectoryName
|
import net.corda.testing.node.internal.getTimestampAsDirectoryName
|
||||||
|
import rx.Observable
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import java.net.ServerSocket
|
import java.net.ServerSocket
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -33,73 +35,37 @@ import java.util.concurrent.atomic.AtomicInteger
|
|||||||
data class NotaryHandle(val identity: Party, val validating: Boolean, val nodeHandles: CordaFuture<List<NodeHandle>>)
|
data class NotaryHandle(val identity: Party, val validating: Boolean, val nodeHandles: CordaFuture<List<NodeHandle>>)
|
||||||
|
|
||||||
@DoNotImplement
|
@DoNotImplement
|
||||||
sealed class NodeHandle : AutoCloseable {
|
interface NodeHandle : AutoCloseable {
|
||||||
abstract val nodeInfo: NodeInfo
|
val nodeInfo: NodeInfo
|
||||||
/**
|
/**
|
||||||
* Interface to the node's RPC system. The first RPC user will be used to login if are any, otherwise a default one
|
* Interface to the node's RPC system. The first RPC user will be used to login if are any, otherwise a default one
|
||||||
* will be added and that will be used.
|
* will be added and that will be used.
|
||||||
*/
|
*/
|
||||||
abstract val rpc: CordaRPCOps
|
val rpc: CordaRPCOps
|
||||||
abstract val configuration: NodeConfiguration
|
val p2pAddress: NetworkHostAndPort
|
||||||
abstract val webAddress: NetworkHostAndPort
|
val rpcAddress: NetworkHostAndPort
|
||||||
abstract val useHTTPS: Boolean
|
val rpcUsers: List<User>
|
||||||
|
val baseDirectory: Path
|
||||||
/**
|
/**
|
||||||
* Stops the referenced node.
|
* Stops the referenced node.
|
||||||
*/
|
*/
|
||||||
abstract fun stop()
|
fun stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@DoNotImplement
|
||||||
|
interface OutOfProcess : NodeHandle {
|
||||||
|
val process: Process
|
||||||
|
}
|
||||||
|
|
||||||
|
@DoNotImplement
|
||||||
|
interface InProcess : NodeHandle {
|
||||||
|
val database: CordaPersistence
|
||||||
|
val services: StartedNodeServices
|
||||||
/**
|
/**
|
||||||
* Closes and stops the node.
|
* Register a flow that is initiated by another flow
|
||||||
*/
|
*/
|
||||||
override fun close() = stop()
|
fun <T : FlowLogic<*>> registerInitiatedFlow(initiatedFlowClass: Class<T>): Observable<T>
|
||||||
|
|
||||||
data class OutOfProcess(
|
|
||||||
override val nodeInfo: NodeInfo,
|
|
||||||
override val rpc: CordaRPCOps,
|
|
||||||
override val configuration: NodeConfiguration,
|
|
||||||
override val webAddress: NetworkHostAndPort,
|
|
||||||
override val useHTTPS: Boolean,
|
|
||||||
val debugPort: Int?,
|
|
||||||
val process: Process,
|
|
||||||
private val onStopCallback: () -> Unit
|
|
||||||
) : NodeHandle() {
|
|
||||||
override fun stop() {
|
|
||||||
with(process) {
|
|
||||||
destroy()
|
|
||||||
waitFor()
|
|
||||||
}
|
|
||||||
onStopCallback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class InProcess(
|
|
||||||
override val nodeInfo: NodeInfo,
|
|
||||||
override val rpc: CordaRPCOps,
|
|
||||||
override val configuration: NodeConfiguration,
|
|
||||||
override val webAddress: NetworkHostAndPort,
|
|
||||||
override val useHTTPS: Boolean,
|
|
||||||
val node: StartedNode<Node>,
|
|
||||||
val nodeThread: Thread,
|
|
||||||
private val onStopCallback: () -> Unit
|
|
||||||
) : NodeHandle() {
|
|
||||||
override fun stop() {
|
|
||||||
node.dispose()
|
|
||||||
with(nodeThread) {
|
|
||||||
interrupt()
|
|
||||||
join()
|
|
||||||
}
|
|
||||||
onStopCallback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connects to node through RPC.
|
|
||||||
*
|
|
||||||
* @param sslConfiguration specifies SSL options.
|
|
||||||
*/
|
|
||||||
@JvmOverloads
|
|
||||||
fun rpcClientToNode(sslConfiguration: SSLConfiguration? = null): CordaRPCClient = CordaRPCClient(configuration.rpcOptions.address!!, sslConfiguration = sslConfiguration)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class WebserverHandle(
|
data class WebserverHandle(
|
||||||
@ -137,12 +103,12 @@ data class NodeParameters(
|
|||||||
val startInSameProcess: Boolean? = null,
|
val startInSameProcess: Boolean? = null,
|
||||||
val maximumHeapSize: String = "200m"
|
val maximumHeapSize: String = "200m"
|
||||||
) {
|
) {
|
||||||
fun setProvidedName(providedName: CordaX500Name?) = copy(providedName = providedName)
|
fun setProvidedName(providedName: CordaX500Name?): NodeParameters = copy(providedName = providedName)
|
||||||
fun setRpcUsers(rpcUsers: List<User>) = copy(rpcUsers = rpcUsers)
|
fun setRpcUsers(rpcUsers: List<User>): NodeParameters = copy(rpcUsers = rpcUsers)
|
||||||
fun setVerifierType(verifierType: VerifierType) = copy(verifierType = verifierType)
|
fun setVerifierType(verifierType: VerifierType): NodeParameters = copy(verifierType = verifierType)
|
||||||
fun setCustomerOverrides(customOverrides: Map<String, Any?>) = copy(customOverrides = customOverrides)
|
fun setCustomerOverrides(customOverrides: Map<String, Any?>): NodeParameters = copy(customOverrides = customOverrides)
|
||||||
fun setStartInSameProcess(startInSameProcess: Boolean?) = copy(startInSameProcess = startInSameProcess)
|
fun setStartInSameProcess(startInSameProcess: Boolean?): NodeParameters = copy(startInSameProcess = startInSameProcess)
|
||||||
fun setMaximumHeapSize(maximumHeapSize: String) = copy(maximumHeapSize = maximumHeapSize)
|
fun setMaximumHeapSize(maximumHeapSize: String): NodeParameters = copy(maximumHeapSize = maximumHeapSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class JmxPolicy(val startJmxHttpServer: Boolean = false,
|
data class JmxPolicy(val startJmxHttpServer: Boolean = false,
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
package net.corda.testing.driver.internal
|
||||||
|
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
|
import net.corda.core.node.NodeInfo
|
||||||
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
|
import net.corda.node.internal.Node
|
||||||
|
import net.corda.node.internal.StartedNode
|
||||||
|
import net.corda.node.services.api.StartedNodeServices
|
||||||
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
|
import net.corda.testing.driver.InProcess
|
||||||
|
import net.corda.testing.driver.NodeHandle
|
||||||
|
import net.corda.testing.driver.OutOfProcess
|
||||||
|
import net.corda.testing.node.User
|
||||||
|
import rx.Observable
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
interface NodeHandleInternal : NodeHandle {
|
||||||
|
val configuration: NodeConfiguration
|
||||||
|
val useHTTPS: Boolean
|
||||||
|
val webAddress: NetworkHostAndPort
|
||||||
|
override val p2pAddress: NetworkHostAndPort get() = configuration.p2pAddress
|
||||||
|
override val rpcAddress: NetworkHostAndPort get() = configuration.rpcOptions.address!!
|
||||||
|
override val baseDirectory: Path get() = configuration.baseDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
data class OutOfProcessImpl(
|
||||||
|
override val nodeInfo: NodeInfo,
|
||||||
|
override val rpc: CordaRPCOps,
|
||||||
|
override val configuration: NodeConfiguration,
|
||||||
|
override val webAddress: NetworkHostAndPort,
|
||||||
|
override val useHTTPS: Boolean,
|
||||||
|
val debugPort: Int?,
|
||||||
|
override val process: Process,
|
||||||
|
private val onStopCallback: () -> Unit
|
||||||
|
) : OutOfProcess, NodeHandleInternal {
|
||||||
|
override val rpcUsers: List<User> = configuration.rpcUsers.map { User(it.username, it.password, it.permissions) }
|
||||||
|
override fun stop() {
|
||||||
|
with(process) {
|
||||||
|
destroy()
|
||||||
|
waitFor()
|
||||||
|
}
|
||||||
|
onStopCallback()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() = stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class InProcessImpl(
|
||||||
|
override val nodeInfo: NodeInfo,
|
||||||
|
override val rpc: CordaRPCOps,
|
||||||
|
override val configuration: NodeConfiguration,
|
||||||
|
override val webAddress: NetworkHostAndPort,
|
||||||
|
override val useHTTPS: Boolean,
|
||||||
|
private val nodeThread: Thread,
|
||||||
|
private val onStopCallback: () -> Unit,
|
||||||
|
private val node: StartedNode<Node>
|
||||||
|
) : InProcess, NodeHandleInternal {
|
||||||
|
override val database: CordaPersistence get() = node.database
|
||||||
|
override val services: StartedNodeServices get() = node.services
|
||||||
|
override val rpcUsers: List<User> = configuration.rpcUsers.map { User(it.username, it.password, it.permissions) }
|
||||||
|
override fun stop() {
|
||||||
|
node.dispose()
|
||||||
|
with(nodeThread) {
|
||||||
|
interrupt()
|
||||||
|
join()
|
||||||
|
}
|
||||||
|
onStopCallback()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() = stop()
|
||||||
|
override fun <T : FlowLogic<*>> registerInitiatedFlow(initiatedFlowClass: Class<T>): Observable<T> = node.registerInitiatedFlow(initiatedFlowClass)
|
||||||
|
}
|
@ -304,7 +304,7 @@ class InMemoryMessagingNetwork internal constructor(
|
|||||||
|
|
||||||
override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
|
override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
|
||||||
return when (partyInfo) {
|
return when (partyInfo) {
|
||||||
is PartyInfo.SingleNode -> peersMapping[partyInfo.party.name] ?: throw IllegalArgumentException("No MockNode for party ${partyInfo.party.name}")
|
is PartyInfo.SingleNode -> peersMapping[partyInfo.party.name] ?: throw IllegalArgumentException("No StartedMockNode for party ${partyInfo.party.name}")
|
||||||
is PartyInfo.DistributedNode -> ServiceHandle(partyInfo.party)
|
is PartyInfo.DistributedNode -> ServiceHandle(partyInfo.party)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,178 @@
|
|||||||
|
package net.corda.testing.node
|
||||||
|
|
||||||
|
import com.google.common.jimfs.Jimfs
|
||||||
|
import net.corda.core.concurrent.CordaFuture
|
||||||
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.node.NodeInfo
|
||||||
|
import net.corda.node.VersionInfo
|
||||||
|
import net.corda.node.internal.StartedNode
|
||||||
|
import net.corda.node.services.api.StartedNodeServices
|
||||||
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
|
import net.corda.node.services.messaging.MessagingService
|
||||||
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
|
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
|
import net.corda.testing.node.internal.setMessagingServiceSpy
|
||||||
|
import rx.Observable
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend this class in order to intercept and modify messages passing through the [MessagingService] when using the [InMemoryMessagingNetwork].
|
||||||
|
*/
|
||||||
|
open class MessagingServiceSpy(val messagingService: MessagingService) : MessagingService by messagingService
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param entropyRoot the initial entropy value to use when generating keys. Defaults to an (insecure) random value,
|
||||||
|
* but can be overridden to cause nodes to have stable or colliding identity/service keys.
|
||||||
|
* @param configOverrides add/override behaviour of the [NodeConfiguration] mock object.
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
data class MockNodeParameters(
|
||||||
|
val forcedID: Int? = null,
|
||||||
|
val legalName: CordaX500Name? = null,
|
||||||
|
val entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
|
||||||
|
val configOverrides: (NodeConfiguration) -> Any? = {},
|
||||||
|
val version: VersionInfo = MockServices.MOCK_VERSION_INFO) {
|
||||||
|
fun setForcedID(forcedID: Int?): MockNodeParameters = copy(forcedID = forcedID)
|
||||||
|
fun setLegalName(legalName: CordaX500Name?): MockNodeParameters = copy(legalName = legalName)
|
||||||
|
fun setEntropyRoot(entropyRoot: BigInteger): MockNodeParameters = copy(entropyRoot = entropyRoot)
|
||||||
|
fun setConfigOverrides(configOverrides: (NodeConfiguration) -> Any?): MockNodeParameters = copy(configOverrides = configOverrides)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Helper builder for configuring a [InternalMockNetwork] from Java. */
|
||||||
|
@Suppress("unused")
|
||||||
|
data class MockNetworkParameters(
|
||||||
|
val networkSendManuallyPumped: Boolean = false,
|
||||||
|
val threadPerNode: Boolean = false,
|
||||||
|
val servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random(),
|
||||||
|
val initialiseSerialization: Boolean = true,
|
||||||
|
val notarySpecs: List<MockNetworkNotarySpec> = listOf(MockNetworkNotarySpec(DUMMY_NOTARY_NAME)),
|
||||||
|
val maxTransactionSize: Int = Int.MAX_VALUE) {
|
||||||
|
fun setNetworkSendManuallyPumped(networkSendManuallyPumped: Boolean): MockNetworkParameters = copy(networkSendManuallyPumped = networkSendManuallyPumped)
|
||||||
|
fun setThreadPerNode(threadPerNode: Boolean): MockNetworkParameters = copy(threadPerNode = threadPerNode)
|
||||||
|
fun setServicePeerAllocationStrategy(servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy): MockNetworkParameters = copy(servicePeerAllocationStrategy = servicePeerAllocationStrategy)
|
||||||
|
fun setInitialiseSerialization(initialiseSerialization: Boolean): MockNetworkParameters = copy(initialiseSerialization = initialiseSerialization)
|
||||||
|
fun setNotarySpecs(notarySpecs: List<MockNetworkNotarySpec>): MockNetworkParameters = copy(notarySpecs = notarySpecs)
|
||||||
|
fun setMaxTransactionSize(maxTransactionSize: Int): MockNetworkParameters = copy(maxTransactionSize = maxTransactionSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents a node configuration for injection via [MockNetworkParameters] **/
|
||||||
|
data class MockNetworkNotarySpec(val name: CordaX500Name, val validating: Boolean = true) {
|
||||||
|
constructor(name: CordaX500Name) : this(name, validating = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A class that represents an unstarted mock node for testing. **/
|
||||||
|
class UnstartedMockNode private constructor(private val node: InternalMockNetwork.MockNode) {
|
||||||
|
companion object {
|
||||||
|
internal fun create(node: InternalMockNetwork.MockNode): UnstartedMockNode {
|
||||||
|
return UnstartedMockNode(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val id get() : Int = node.id
|
||||||
|
/** Start the node **/
|
||||||
|
fun start() = StartedMockNode.create(node.start())
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A class that represents a started mock node for testing. **/
|
||||||
|
class StartedMockNode private constructor(private val node: StartedNode<InternalMockNetwork.MockNode>) {
|
||||||
|
companion object {
|
||||||
|
internal fun create(node: StartedNode<InternalMockNetwork.MockNode>): StartedMockNode {
|
||||||
|
return StartedMockNode(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val services get() : StartedNodeServices = node.services
|
||||||
|
val database get() : CordaPersistence = node.database
|
||||||
|
val id get() : Int = node.internals.id
|
||||||
|
val info get() : NodeInfo = node.services.myInfo
|
||||||
|
val network get() : MessagingService = node.network
|
||||||
|
/** Register a flow that is initiated by another flow **/
|
||||||
|
fun <F : FlowLogic<*>> registerInitiatedFlow(initiatedFlowClass: Class<F>): Observable<F> = node.registerInitiatedFlow(initiatedFlowClass)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a [MessagingServiceSpy] to the [InternalMockNetwork.MockNode] allowing
|
||||||
|
* interception and modification of messages.
|
||||||
|
*/
|
||||||
|
fun setMessagingServiceSpy(messagingServiceSpy: MessagingServiceSpy) = node.setMessagingServiceSpy(messagingServiceSpy)
|
||||||
|
|
||||||
|
/** Stop the node **/
|
||||||
|
fun stop() = node.internals.stop()
|
||||||
|
|
||||||
|
/** Receive a message from the queue. */
|
||||||
|
fun pumpReceive(block: Boolean = false): InMemoryMessagingNetwork.MessageTransfer? {
|
||||||
|
return (services.networkService as InMemoryMessagingNetwork.TestMessagingService).pumpReceive(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the currently live flows of type [flowClass], and their corresponding result future. */
|
||||||
|
fun <F : FlowLogic<*>> findStateMachines(flowClass: Class<F>): List<Pair<F, CordaFuture<*>>> = node.smm.findStateMachines(flowClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* memory H2 database instance.
|
||||||
|
*
|
||||||
|
* Mock network nodes require manual pumping by default: they will not run asynchronous. This means that
|
||||||
|
* for message exchanges to take place (and associated handlers to run), you must call the [runNetwork]
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* You can get a printout of every message sent by using code like:
|
||||||
|
*
|
||||||
|
* LogHelper.setLevel("+messages")
|
||||||
|
*
|
||||||
|
* By default a single notary node is automatically started, which forms part of the network parameters for all the nodes.
|
||||||
|
* This node is available by calling [defaultNotaryNode].
|
||||||
|
*/
|
||||||
|
open class MockNetwork(
|
||||||
|
val cordappPackages: List<String>,
|
||||||
|
val defaultParameters: MockNetworkParameters = MockNetworkParameters(),
|
||||||
|
val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped,
|
||||||
|
val threadPerNode: Boolean = defaultParameters.threadPerNode,
|
||||||
|
val servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy,
|
||||||
|
val initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
||||||
|
val notarySpecs: List<MockNetworkNotarySpec> = defaultParameters.notarySpecs,
|
||||||
|
val maxTransactionSize: Int = defaultParameters.maxTransactionSize) {
|
||||||
|
@JvmOverloads
|
||||||
|
constructor(cordappPackages: List<String>, parameters: MockNetworkParameters = MockNetworkParameters()) : this(cordappPackages, defaultParameters = parameters)
|
||||||
|
|
||||||
|
private val internalMockNetwork: InternalMockNetwork = InternalMockNetwork(cordappPackages, defaultParameters, networkSendManuallyPumped, threadPerNode, servicePeerAllocationStrategy, initialiseSerialization, notarySpecs, maxTransactionSize)
|
||||||
|
val defaultNotaryNode get() : StartedMockNode = StartedMockNode.create(internalMockNetwork.defaultNotaryNode)
|
||||||
|
val defaultNotaryIdentity get() : Party = internalMockNetwork.defaultNotaryIdentity
|
||||||
|
val notaryNodes get() : List<StartedMockNode> = internalMockNetwork.notaryNodes.map { StartedMockNode.create(it) }
|
||||||
|
val nextNodeId get() : Int = internalMockNetwork.nextNodeId
|
||||||
|
|
||||||
|
/** Create a started node with the given identity. **/
|
||||||
|
fun createPartyNode(legalName: CordaX500Name? = null): StartedMockNode = StartedMockNode.create(internalMockNetwork.createPartyNode(legalName))
|
||||||
|
|
||||||
|
/** Create a started node with the given parameters. **/
|
||||||
|
fun createNode(parameters: MockNodeParameters = MockNodeParameters()): StartedMockNode = StartedMockNode.create(internalMockNetwork.createNode(parameters))
|
||||||
|
|
||||||
|
/** Create an unstarted node with the given parameters. **/
|
||||||
|
fun createUnstartedNode(parameters: MockNodeParameters = MockNodeParameters()): UnstartedMockNode = UnstartedMockNode.create(internalMockNetwork.createUnstartedNode(parameters))
|
||||||
|
|
||||||
|
/** Start all nodes that aren't already started. **/
|
||||||
|
fun startNodes() = internalMockNetwork.startNodes()
|
||||||
|
|
||||||
|
/** Stop all nodes. **/
|
||||||
|
fun stopNodes() = internalMockNetwork.stopNodes()
|
||||||
|
|
||||||
|
/** Block until all scheduled activity, active flows and network activity has ceased. **/
|
||||||
|
fun waitQuiescent() = internalMockNetwork.waitQuiescent()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks every node in order to process any queued up inbound messages. This may in turn result in nodes
|
||||||
|
* sending more messages to each other, thus, a typical usage is to call runNetwork with the [rounds]
|
||||||
|
* parameter set to -1 (the default) which simply runs as many rounds as necessary to result in network
|
||||||
|
* stability (no nodes sent any messages in the last round).
|
||||||
|
*/
|
||||||
|
@JvmOverloads
|
||||||
|
fun runNetwork(rounds: Int = -1) = internalMockNetwork.runNetwork(rounds)
|
||||||
|
|
||||||
|
/** Get the base directory for the given node id. **/
|
||||||
|
fun baseDirectory(nodeId: Int): Path = internalMockNetwork.baseDirectory(nodeId)
|
||||||
|
}
|
@ -44,6 +44,9 @@ import net.corda.testing.core.BOB_NAME
|
|||||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||||
import net.corda.testing.core.setGlobalSerialization
|
import net.corda.testing.core.setGlobalSerialization
|
||||||
import net.corda.testing.driver.*
|
import net.corda.testing.driver.*
|
||||||
|
import net.corda.testing.driver.internal.InProcessImpl
|
||||||
|
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||||
|
import net.corda.testing.driver.internal.OutOfProcessImpl
|
||||||
import net.corda.testing.node.ClusterSpec
|
import net.corda.testing.node.ClusterSpec
|
||||||
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
@ -355,7 +358,7 @@ class DriverDSLImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun queryWebserver(handle: NodeHandle, process: Process): WebserverHandle {
|
private fun queryWebserver(handle: NodeHandle, process: Process): WebserverHandle {
|
||||||
val protocol = if (handle.useHTTPS) "https://" else "http://"
|
val protocol = if ((handle as NodeHandleInternal).useHTTPS) "https://" else "http://"
|
||||||
val url = URL("$protocol${handle.webAddress}/api/status")
|
val url = URL("$protocol${handle.webAddress}/api/status")
|
||||||
val client = OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build()
|
val client = OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build()
|
||||||
|
|
||||||
@ -375,7 +378,7 @@ class DriverDSLImpl(
|
|||||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||||
val process = startWebserver(handle, debugPort, maximumHeapSize)
|
val process = startWebserver(handle, debugPort, maximumHeapSize)
|
||||||
shutdownManager.registerProcessShutdown(process)
|
shutdownManager.registerProcessShutdown(process)
|
||||||
val webReadyFuture = addressMustBeBoundFuture(executorService, handle.webAddress, process)
|
val webReadyFuture = addressMustBeBoundFuture(executorService, (handle as NodeHandleInternal).webAddress, process)
|
||||||
return webReadyFuture.map { queryWebserver(handle, process) }
|
return webReadyFuture.map { queryWebserver(handle, process) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -654,7 +657,7 @@ class DriverDSLImpl(
|
|||||||
return nodeAndThreadFuture.flatMap { (node, thread) ->
|
return nodeAndThreadFuture.flatMap { (node, thread) ->
|
||||||
establishRpc(config, openFuture()).flatMap { rpc ->
|
establishRpc(config, openFuture()).flatMap { rpc ->
|
||||||
allNodesConnected(rpc).map {
|
allNodesConnected(rpc).map {
|
||||||
NodeHandle.InProcess(rpc.nodeInfo(), rpc, config.corda, webAddress, useHTTPS, node, thread, onNodeExit)
|
InProcessImpl(rpc.nodeInfo(), rpc, config.corda, webAddress, useHTTPS, thread, onNodeExit, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -683,7 +686,7 @@ class DriverDSLImpl(
|
|||||||
}
|
}
|
||||||
processDeathFuture.cancel(false)
|
processDeathFuture.cancel(false)
|
||||||
log.info("Node handle is ready. NodeInfo: ${rpc.nodeInfo()}, WebAddress: $webAddress")
|
log.info("Node handle is ready. NodeInfo: ${rpc.nodeInfo()}, WebAddress: $webAddress")
|
||||||
NodeHandle.OutOfProcess(rpc.nodeInfo(), rpc, config.corda, webAddress, useHTTPS, debugPort, process, onNodeExit)
|
OutOfProcessImpl(rpc.nodeInfo(), rpc, config.corda, webAddress, useHTTPS, debugPort, process, onNodeExit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -833,10 +836,10 @@ class DriverDSLImpl(
|
|||||||
val className = "net.corda.webserver.WebServer"
|
val className = "net.corda.webserver.WebServer"
|
||||||
return ProcessUtilities.startCordaProcess(
|
return ProcessUtilities.startCordaProcess(
|
||||||
className = className, // cannot directly get class for this, so just use string
|
className = className, // cannot directly get class for this, so just use string
|
||||||
arguments = listOf("--base-directory", handle.configuration.baseDirectory.toString()),
|
arguments = listOf("--base-directory", handle.baseDirectory.toString()),
|
||||||
jdwpPort = debugPort,
|
jdwpPort = debugPort,
|
||||||
extraJvmArguments = listOf(
|
extraJvmArguments = listOf(
|
||||||
"-Dname=node-${handle.configuration.p2pAddress}-webserver",
|
"-Dname=node-${handle.p2pAddress}-webserver",
|
||||||
"-Djava.io.tmpdir=${System.getProperty("java.io.tmpdir")}" // Inherit from parent process
|
"-Djava.io.tmpdir=${System.getProperty("java.io.tmpdir")}" // Inherit from parent process
|
||||||
),
|
),
|
||||||
errorLogPath = Paths.get("error.$className.log"),
|
errorLogPath = Paths.get("error.$className.log"),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package net.corda.testing.node
|
package net.corda.testing.node.internal
|
||||||
|
|
||||||
import com.google.common.jimfs.Configuration.unix
|
import com.google.common.jimfs.Configuration.unix
|
||||||
import com.google.common.jimfs.Jimfs
|
import com.google.common.jimfs.Jimfs
|
||||||
@ -7,6 +7,7 @@ import com.nhaarman.mockito_kotlin.whenever
|
|||||||
import net.corda.core.DoNotImplement
|
import net.corda.core.DoNotImplement
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
@ -28,6 +29,7 @@ import net.corda.core.utilities.contextLogger
|
|||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.node.VersionInfo
|
import net.corda.node.VersionInfo
|
||||||
import net.corda.node.internal.AbstractNode
|
import net.corda.node.internal.AbstractNode
|
||||||
|
import net.corda.node.internal.InitiatedFlowFactory
|
||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
import net.corda.node.internal.cordapp.CordappLoader
|
import net.corda.node.internal.cordapp.CordappLoader
|
||||||
import net.corda.node.services.api.IdentityServiceInternal
|
import net.corda.node.services.api.IdentityServiceInternal
|
||||||
@ -52,8 +54,11 @@ import net.corda.testing.internal.rigorousMock
|
|||||||
import net.corda.testing.internal.testThreadFactory
|
import net.corda.testing.internal.testThreadFactory
|
||||||
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
|
import net.corda.testing.core.setGlobalSerialization
|
||||||
|
import net.corda.testing.node.*
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||||
import org.apache.sshd.common.util.security.SecurityUtils
|
import org.apache.sshd.common.util.security.SecurityUtils
|
||||||
|
import rx.Observable
|
||||||
import rx.internal.schedulers.CachedThreadScheduler
|
import rx.internal.schedulers.CachedThreadScheduler
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -63,48 +68,13 @@ import java.time.Clock
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
fun StartedNode<MockNetwork.MockNode>.pumpReceive(block: Boolean = false): InMemoryMessagingNetwork.MessageTransfer? {
|
fun StartedNode<InternalMockNetwork.MockNode>.pumpReceive(block: Boolean = false): InMemoryMessagingNetwork.MessageTransfer? {
|
||||||
return (network as InMemoryMessagingNetwork.TestMessagingService).pumpReceive(block)
|
return (network as InMemoryMessagingNetwork.TestMessagingService).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: (MockNodeArgs) -> MockNetwork.MockNode = MockNetwork::MockNode,
|
|
||||||
val initialiseSerialization: Boolean = true,
|
|
||||||
val notarySpecs: List<MockNetwork.NotarySpec> = listOf(MockNetwork.NotarySpec(DUMMY_NOTARY_NAME))) {
|
|
||||||
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: (MockNodeArgs) -> MockNetwork.MockNode) = copy(defaultFactory = defaultFactory)
|
|
||||||
fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization)
|
|
||||||
fun setNotarySpecs(notarySpecs: List<MockNetwork.NotarySpec>) = copy(notarySpecs = notarySpecs)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param entropyRoot the initial entropy value to use when generating keys. Defaults to an (insecure) random value,
|
|
||||||
* but can be overridden to cause nodes to have stable or colliding identity/service keys.
|
|
||||||
* @param configOverrides add/override behaviour of the [NodeConfiguration] mock object.
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
data class MockNodeParameters(
|
|
||||||
val forcedID: Int? = null,
|
|
||||||
val legalName: CordaX500Name? = null,
|
|
||||||
val entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
|
|
||||||
val configOverrides: (NodeConfiguration) -> Any? = {},
|
|
||||||
val version: VersionInfo = MOCK_VERSION_INFO) {
|
|
||||||
fun setForcedID(forcedID: Int?) = copy(forcedID = forcedID)
|
|
||||||
fun setLegalName(legalName: CordaX500Name?) = copy(legalName = legalName)
|
|
||||||
fun setEntropyRoot(entropyRoot: BigInteger) = copy(entropyRoot = entropyRoot)
|
|
||||||
fun setConfigOverrides(configOverrides: (NodeConfiguration) -> Any?) = copy(configOverrides = configOverrides)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class MockNodeArgs(
|
data class MockNodeArgs(
|
||||||
val config: NodeConfiguration,
|
val config: NodeConfiguration,
|
||||||
val network: MockNetwork,
|
val network: InternalMockNetwork,
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val entropyRoot: BigInteger,
|
val entropyRoot: BigInteger,
|
||||||
val version: VersionInfo = MOCK_VERSION_INFO
|
val version: VersionInfo = MOCK_VERSION_INFO
|
||||||
@ -126,19 +96,15 @@ data class MockNodeArgs(
|
|||||||
* By default a single notary node is automatically started, which forms part of the network parameters for all the nodes.
|
* By default a single notary node is automatically started, which forms part of the network parameters for all the nodes.
|
||||||
* This node is available by calling [defaultNotaryNode].
|
* This node is available by calling [defaultNotaryNode].
|
||||||
*/
|
*/
|
||||||
open class MockNetwork(private val cordappPackages: List<String>,
|
open class InternalMockNetwork(private val cordappPackages: List<String>,
|
||||||
defaultParameters: MockNetworkParameters = MockNetworkParameters(),
|
defaultParameters: MockNetworkParameters = MockNetworkParameters(),
|
||||||
private val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped,
|
val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped,
|
||||||
private val threadPerNode: Boolean = defaultParameters.threadPerNode,
|
val threadPerNode: Boolean = defaultParameters.threadPerNode,
|
||||||
servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy,
|
servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy,
|
||||||
private val defaultFactory: (MockNodeArgs) -> MockNode = defaultParameters.defaultFactory,
|
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
||||||
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
|
val notarySpecs: List<MockNetworkNotarySpec> = defaultParameters.notarySpecs,
|
||||||
private val notarySpecs: List<NotarySpec> = defaultParameters.notarySpecs,
|
maxTransactionSize: Int = Int.MAX_VALUE,
|
||||||
maxTransactionSize: Int = Int.MAX_VALUE) {
|
val defaultFactory: (MockNodeArgs) -> MockNode = InternalMockNetwork::MockNode) {
|
||||||
/** Helper constructor for creating a [MockNetwork] with custom parameters from Java. */
|
|
||||||
@JvmOverloads
|
|
||||||
constructor(cordappPackages: List<String>, parameters: MockNetworkParameters = MockNetworkParameters()) : this(cordappPackages, defaultParameters = parameters)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Apache SSHD for whatever reason registers a SFTP FileSystemProvider - which gets loaded by JimFS.
|
// Apache SSHD for whatever reason registers a SFTP FileSystemProvider - which gets loaded by JimFS.
|
||||||
// This SFTP support loads BouncyCastle, which we want to avoid.
|
// This SFTP support loads BouncyCastle, which we want to avoid.
|
||||||
@ -158,7 +124,7 @@ open class MockNetwork(private val cordappPackages: List<String>,
|
|||||||
private val serializationEnv = try {
|
private val serializationEnv = try {
|
||||||
setGlobalSerialization(initialiseSerialization)
|
setGlobalSerialization(initialiseSerialization)
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
throw IllegalStateException("Using more than one MockNetwork simultaneously is not supported.", e)
|
throw IllegalStateException("Using more than one InternalMockNetwork simultaneously is not supported.", e)
|
||||||
}
|
}
|
||||||
private val sharedUserCount = AtomicInteger(0)
|
private val sharedUserCount = AtomicInteger(0)
|
||||||
|
|
||||||
@ -329,12 +295,12 @@ open class MockNetwork(private val cordappPackages: List<String>,
|
|||||||
// This is not thread safe, but node construction is done on a single thread, so that should always be fine
|
// This is not thread safe, but node construction is done on a single thread, so that should always be fine
|
||||||
override fun generateKeyPair(): KeyPair {
|
override fun generateKeyPair(): KeyPair {
|
||||||
counter = counter.add(BigInteger.ONE)
|
counter = counter.add(BigInteger.ONE)
|
||||||
// The MockNode specifically uses EdDSA keys as they are fixed and stored in json files for some tests (e.g IRSSimulation).
|
// The StartedMockNode specifically uses EdDSA keys as they are fixed and stored in json files for some tests (e.g IRSSimulation).
|
||||||
return Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, counter)
|
return Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, counter)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MockNetwork will ensure nodes are connected to each other. The nodes themselves
|
* InternalMockNetwork will ensure nodes are connected to each other. The nodes themselves
|
||||||
* won't be able to tell if that happened already or not.
|
* won't be able to tell if that happened already or not.
|
||||||
*/
|
*/
|
||||||
override fun checkNetworkMapIsInitialized() = Unit
|
override fun checkNetworkMapIsInitialized() = Unit
|
||||||
@ -478,20 +444,12 @@ open class MockNetwork(private val cordappPackages: List<String>,
|
|||||||
busyLatch.await()
|
busyLatch.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class NotarySpec(val name: CordaX500Name, val validating: Boolean = true) {
|
|
||||||
constructor(name: CordaX500Name) : this(name, validating = true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend this class in order to intercept and modify messages passing through the [MessagingService] when using the [InMemoryMessagingNetwork].
|
* Attach a [MessagingServiceSpy] to the [InternalMockNetwork.MockNode] allowing interception and modification of messages.
|
||||||
*/
|
*/
|
||||||
open class MessagingServiceSpy(val messagingService: MessagingService) : MessagingService by messagingService
|
fun StartedNode<InternalMockNetwork.MockNode>.setMessagingServiceSpy(messagingServiceSpy: MessagingServiceSpy) {
|
||||||
|
|
||||||
/**
|
|
||||||
* Attach a [MessagingServiceSpy] to the [MockNetwork.MockNode] allowing interception and modification of messages.
|
|
||||||
*/
|
|
||||||
fun StartedNode<MockNetwork.MockNode>.setMessagingServiceSpy(messagingServiceSpy: MessagingServiceSpy) {
|
|
||||||
internals.setMessagingServiceSpy(messagingServiceSpy)
|
internals.setMessagingServiceSpy(messagingServiceSpy)
|
||||||
}
|
}
|
||||||
|
|
@ -60,4 +60,4 @@ object ProcessUtilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val defaultClassPath: String get() = System.getProperty("java.class.path")
|
val defaultClassPath: String get() = System.getProperty("java.class.path")
|
||||||
}
|
}
|
@ -6,22 +6,15 @@ import static java.util.Collections.emptyList;
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class MockNodeFactoryInJavaTest {
|
public class MockNodeFactoryInJavaTest {
|
||||||
private static class CustomNode extends MockNetwork.MockNode {
|
|
||||||
private CustomNode(@NotNull MockNodeArgs args) {
|
|
||||||
super(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does not need to run, only compile.
|
* Does not need to run, only compile.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static void factoryIsEasyToPassInUsingJava() {
|
private static void factoryIsEasyToPassInUsingJava() {
|
||||||
//noinspection Convert2MethodRef
|
//noinspection Convert2MethodRef
|
||||||
new MockNetwork(emptyList(), new MockNetworkParameters().setDefaultFactory(args -> new CustomNode(args)));
|
new MockNetwork(emptyList());
|
||||||
new MockNetwork(emptyList(), new MockNetworkParameters().setDefaultFactory(CustomNode::new));
|
new MockNetwork(emptyList(), new MockNetworkParameters().setInitialiseSerialization(false));
|
||||||
//noinspection Convert2MethodRef
|
//noinspection Convert2MethodRef
|
||||||
new MockNetwork(emptyList()).createNode(new MockNodeParameters(), args -> new CustomNode(args));
|
new MockNetwork(emptyList()).createNode(new MockNodeParameters());
|
||||||
new MockNetwork(emptyList()).createNode(new MockNodeParameters(), CustomNode::new);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
package net.corda.testing.node
|
package net.corda.testing.node.internal
|
||||||
|
|
||||||
import net.corda.core.serialization.internal.effectiveSerializationEnv
|
import net.corda.core.serialization.internal.effectiveSerializationEnv
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class MockNetworkTests {
|
class InternalMockNetworkTests {
|
||||||
@Test
|
@Test
|
||||||
fun `does not leak serialization env if init fails`() {
|
fun `does not leak serialization env if init fails`() {
|
||||||
val e = Exception("didn't work")
|
val e = Exception("didn't work")
|
||||||
assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
object : MockNetwork(emptyList(), initialiseSerialization = true) {
|
object : InternalMockNetwork(emptyList(), initialiseSerialization = true) {
|
||||||
override fun createNotaries() = throw e
|
override fun createNotaries() = throw e
|
||||||
}
|
}
|
||||||
}.isSameAs(e)
|
}.isSameAs(e)
|
||||||
assertThatThrownBy { effectiveSerializationEnv }.isInstanceOf(IllegalStateException::class.java)
|
assertThatThrownBy { effectiveSerializationEnv }.isInstanceOf(IllegalStateException::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ import joptsimple.OptionSet
|
|||||||
import net.corda.client.mock.ErrorFlowsEventGenerator
|
import net.corda.client.mock.ErrorFlowsEventGenerator
|
||||||
import net.corda.client.mock.EventGenerator
|
import net.corda.client.mock.EventGenerator
|
||||||
import net.corda.client.mock.Generator
|
import net.corda.client.mock.Generator
|
||||||
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.client.rpc.CordaRPCConnection
|
import net.corda.client.rpc.CordaRPCConnection
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
@ -83,7 +84,7 @@ class ExplorerSimulation(private val options: OptionSet) {
|
|||||||
issuerNodeUSD = issuerUSD.get()
|
issuerNodeUSD = issuerUSD.get()
|
||||||
|
|
||||||
arrayOf(notaryNode, aliceNode, bobNode, issuerNodeGBP, issuerNodeUSD).forEach {
|
arrayOf(notaryNode, aliceNode, bobNode, issuerNodeGBP, issuerNodeUSD).forEach {
|
||||||
println("${it.nodeInfo.legalIdentities.first()} started on ${it.configuration.rpcOptions.address}")
|
println("${it.nodeInfo.legalIdentities.first()} started on ${it.rpcAddress}")
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
@ -95,19 +96,19 @@ class ExplorerSimulation(private val options: OptionSet) {
|
|||||||
|
|
||||||
private fun setUpRPC() {
|
private fun setUpRPC() {
|
||||||
// Register with alice to use alice's RPC proxy to create random events.
|
// Register with alice to use alice's RPC proxy to create random events.
|
||||||
val aliceClient = aliceNode.rpcClientToNode()
|
val aliceClient = CordaRPCClient(aliceNode.rpcAddress)
|
||||||
val aliceConnection = aliceClient.start(user.username, user.password)
|
val aliceConnection = aliceClient.start(user.username, user.password)
|
||||||
val aliceRPC = aliceConnection.proxy
|
val aliceRPC = aliceConnection.proxy
|
||||||
|
|
||||||
val bobClient = bobNode.rpcClientToNode()
|
val bobClient = CordaRPCClient(bobNode.rpcAddress)
|
||||||
val bobConnection = bobClient.start(user.username, user.password)
|
val bobConnection = bobClient.start(user.username, user.password)
|
||||||
val bobRPC = bobConnection.proxy
|
val bobRPC = bobConnection.proxy
|
||||||
|
|
||||||
val issuerClientGBP = issuerNodeGBP.rpcClientToNode()
|
val issuerClientGBP = CordaRPCClient(issuerNodeGBP.rpcAddress)
|
||||||
val issuerGBPConnection = issuerClientGBP.start(manager.username, manager.password)
|
val issuerGBPConnection = issuerClientGBP.start(manager.username, manager.password)
|
||||||
val issuerRPCGBP = issuerGBPConnection.proxy
|
val issuerRPCGBP = issuerGBPConnection.proxy
|
||||||
|
|
||||||
val issuerClientUSD = issuerNodeUSD.rpcClientToNode()
|
val issuerClientUSD = CordaRPCClient(issuerNodeUSD.rpcAddress)
|
||||||
val issuerUSDConnection = issuerClientUSD.start(manager.username, manager.password)
|
val issuerUSDConnection = issuerClientUSD.start(manager.username, manager.password)
|
||||||
val issuerRPCUSD = issuerUSDConnection.proxy
|
val issuerRPCUSD = issuerUSDConnection.proxy
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import net.corda.testing.driver.JmxPolicy
|
|||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.NodeHandle
|
||||||
import net.corda.testing.driver.PortAllocation
|
import net.corda.testing.driver.PortAllocation
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
|
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
import net.corda.testing.node.internal.*
|
import net.corda.testing.node.internal.*
|
||||||
import org.apache.activemq.artemis.api.core.SimpleString
|
import org.apache.activemq.artemis.api.core.SimpleString
|
||||||
@ -255,7 +256,7 @@ data class VerifierDriverDSL(private val driverDSL: DriverDSLImpl) : InternalDri
|
|||||||
|
|
||||||
/** Starts a verifier connecting to the specified node */
|
/** Starts a verifier connecting to the specified node */
|
||||||
fun startVerifier(nodeHandle: NodeHandle): CordaFuture<VerifierHandle> {
|
fun startVerifier(nodeHandle: NodeHandle): CordaFuture<VerifierHandle> {
|
||||||
return startVerifier(nodeHandle.configuration.p2pAddress)
|
return startVerifier(nodeHandle.p2pAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Starts a verifier connecting to the specified requestor */
|
/** Starts a verifier connecting to the specified requestor */
|
||||||
@ -263,8 +264,8 @@ data class VerifierDriverDSL(private val driverDSL: DriverDSLImpl) : InternalDri
|
|||||||
return startVerifier(verificationRequestorHandle.p2pAddress)
|
return startVerifier(verificationRequestorHandle.p2pAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <A> NodeHandle.connectToNode(closure: (ClientSession) -> A): A {
|
private fun <A> NodeHandleInternal.connectToNode(closure: (ClientSession) -> A): A {
|
||||||
val transport = ArtemisTcpTransport.tcpTransport(ConnectionDirection.Outbound(), configuration.p2pAddress, configuration)
|
val transport = ArtemisTcpTransport.tcpTransport(ConnectionDirection.Outbound(), p2pAddress, configuration)
|
||||||
val locator = ActiveMQClient.createServerLocatorWithoutHA(transport)
|
val locator = ActiveMQClient.createServerLocatorWithoutHA(transport)
|
||||||
val sessionFactory = locator.createSessionFactory()
|
val sessionFactory = locator.createSessionFactory()
|
||||||
val session = sessionFactory.createSession(NODE_USER, NODE_USER, false, true, true, locator.isPreAcknowledge, locator.ackBatchSize)
|
val session = sessionFactory.createSession(NODE_USER, NODE_USER, false, true, true, locator.isPreAcknowledge, locator.ackBatchSize)
|
||||||
@ -277,7 +278,7 @@ data class VerifierDriverDSL(private val driverDSL: DriverDSLImpl) : InternalDri
|
|||||||
* Waits until [number] verifiers are listening for verification requests coming from the Node. Check
|
* Waits until [number] verifiers are listening for verification requests coming from the Node. Check
|
||||||
* [VerificationRequestorHandle.waitUntilNumberOfVerifiers] for an equivalent for requestors.
|
* [VerificationRequestorHandle.waitUntilNumberOfVerifiers] for an equivalent for requestors.
|
||||||
*/
|
*/
|
||||||
fun NodeHandle.waitUntilNumberOfVerifiers(number: Int) {
|
fun NodeHandleInternal.waitUntilNumberOfVerifiers(number: Int) {
|
||||||
connectToNode { session ->
|
connectToNode { session ->
|
||||||
poll(driverDSL.executorService, "$number verifiers to come online") {
|
poll(driverDSL.executorService, "$number verifiers to come online") {
|
||||||
if (session.queueQuery(SimpleString(VerifierApi.VERIFICATION_REQUESTS_QUEUE_NAME)).consumerCount >= number) {
|
if (session.queueQuery(SimpleString(VerifierApi.VERIFICATION_REQUESTS_QUEUE_NAME)).consumerCount >= number) {
|
||||||
|
@ -15,6 +15,7 @@ import net.corda.node.services.config.VerifierType
|
|||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||||
import net.corda.testing.core.SerializationEnvironmentRule
|
import net.corda.testing.core.SerializationEnvironmentRule
|
||||||
|
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||||
import net.corda.testing.node.NotarySpec
|
import net.corda.testing.node.NotarySpec
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -139,7 +140,7 @@ class VerifierTests {
|
|||||||
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY_NAME, verifierType = VerifierType.OutOfProcess))
|
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY_NAME, verifierType = VerifierType.OutOfProcess))
|
||||||
) {
|
) {
|
||||||
val aliceNode = startNode(providedName = ALICE_NAME).getOrThrow()
|
val aliceNode = startNode(providedName = ALICE_NAME).getOrThrow()
|
||||||
val notaryNode = defaultNotaryNode.getOrThrow()
|
val notaryNode = defaultNotaryNode.getOrThrow() as NodeHandleInternal
|
||||||
val alice = aliceNode.rpc.wellKnownPartyFromX500Name(ALICE_NAME)!!
|
val alice = aliceNode.rpc.wellKnownPartyFromX500Name(ALICE_NAME)!!
|
||||||
startVerifier(notaryNode)
|
startVerifier(notaryNode)
|
||||||
aliceNode.rpc.startFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue.get()
|
aliceNode.rpc.startFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue.get()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user