Removed the ability to manually start notary nodes from the driver and MockNetwork. Instead by default a single notary is automatically started. This can be customised at creation time of the driver and MockNetwork. This more accurately models the concept of network parameters in a CZ.

Also added helper methods to retrieve this default notary.
This commit is contained in:
Shams Asari 2017-11-05 12:34:42 +00:00
parent 9be37c2b88
commit 3bb018a5ce
64 changed files with 637 additions and 643 deletions

View File

@ -11,7 +11,6 @@ import net.corda.core.flows.StateMachineRunId
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.internal.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.internal.concurrent.transpose
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.StateMachineTransactionMapping import net.corda.core.messaging.StateMachineTransactionMapping
import net.corda.core.messaging.StateMachineUpdate import net.corda.core.messaging.StateMachineUpdate
@ -50,44 +49,44 @@ class NodeMonitorModelTest {
private lateinit var vaultUpdates: Observable<Vault.Update<ContractState>> private lateinit var vaultUpdates: Observable<Vault.Update<ContractState>>
private lateinit var networkMapUpdates: Observable<NetworkMapCache.MapChange> private lateinit var networkMapUpdates: Observable<NetworkMapCache.MapChange>
private lateinit var newNode: (CordaX500Name) -> NodeInfo private lateinit var newNode: (CordaX500Name) -> NodeInfo
private fun setup(runTest: () -> Unit) = driver(extraCordappPackagesToScan = listOf("net.corda.finance")) {
val cashUser = User("user1", "test", permissions = setOf(
startFlow<CashIssueFlow>(),
startFlow<CashPaymentFlow>(),
startFlow<CashExitFlow>(),
invokeRpc(CordaRPCOps::notaryIdentities),
invokeRpc("vaultTrackBy"),
invokeRpc("vaultQueryBy"),
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed),
invokeRpc(CordaRPCOps::stateMachineRecordedTransactionMappingFeed),
invokeRpc(CordaRPCOps::stateMachinesFeed),
invokeRpc(CordaRPCOps::networkMapFeed))
)
val (notaryHandle, aliceNodeHandle) = listOf(
startNotaryNode(DUMMY_NOTARY.name, validating = false),
startNode(providedName = ALICE.name, rpcUsers = listOf(cashUser))
).transpose().getOrThrow()
aliceNode = aliceNodeHandle.nodeInfo
newNode = { nodeName -> startNode(providedName = nodeName).getOrThrow().nodeInfo }
val monitor = NodeMonitorModel()
stateMachineTransactionMapping = monitor.stateMachineTransactionMapping.bufferUntilSubscribed()
stateMachineUpdates = monitor.stateMachineUpdates.bufferUntilSubscribed()
progressTracking = monitor.progressTracking.bufferUntilSubscribed()
transactions = monitor.transactions.bufferUntilSubscribed()
vaultUpdates = monitor.vaultUpdates.bufferUntilSubscribed()
networkMapUpdates = monitor.networkMap.bufferUntilSubscribed()
monitor.register(aliceNodeHandle.configuration.rpcAddress!!, cashUser.username, cashUser.password) private fun setup(runTest: () -> Unit) {
rpc = monitor.proxyObservable.value!! driver(extraCordappPackagesToScan = listOf("net.corda.finance")) {
notaryParty = notaryHandle.nodeInfo.legalIdentities[0] val cashUser = User("user1", "test", permissions = setOf(
startFlow<CashIssueFlow>(),
startFlow<CashPaymentFlow>(),
startFlow<CashExitFlow>(),
invokeRpc(CordaRPCOps::notaryIdentities),
invokeRpc("vaultTrackBy"),
invokeRpc("vaultQueryBy"),
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed),
invokeRpc(CordaRPCOps::stateMachineRecordedTransactionMappingFeed),
invokeRpc(CordaRPCOps::stateMachinesFeed),
invokeRpc(CordaRPCOps::networkMapFeed))
)
val aliceNodeHandle = startNode(providedName = ALICE.name, rpcUsers = listOf(cashUser)).getOrThrow()
aliceNode = aliceNodeHandle.nodeInfo
newNode = { nodeName -> startNode(providedName = nodeName).getOrThrow().nodeInfo }
val monitor = NodeMonitorModel()
stateMachineTransactionMapping = monitor.stateMachineTransactionMapping.bufferUntilSubscribed()
stateMachineUpdates = monitor.stateMachineUpdates.bufferUntilSubscribed()
progressTracking = monitor.progressTracking.bufferUntilSubscribed()
transactions = monitor.transactions.bufferUntilSubscribed()
vaultUpdates = monitor.vaultUpdates.bufferUntilSubscribed()
networkMapUpdates = monitor.networkMap.bufferUntilSubscribed()
val bobNodeHandle = startNode(providedName = BOB.name, rpcUsers = listOf(cashUser)).getOrThrow() monitor.register(aliceNodeHandle.configuration.rpcAddress!!, cashUser.username, cashUser.password)
bobNode = bobNodeHandle.nodeInfo rpc = monitor.proxyObservable.value!!
val monitorBob = NodeMonitorModel() notaryParty = defaultNotaryIdentity
stateMachineUpdatesBob = monitorBob.stateMachineUpdates.bufferUntilSubscribed()
monitorBob.register(bobNodeHandle.configuration.rpcAddress!!, cashUser.username, cashUser.password) val bobNodeHandle = startNode(providedName = BOB.name, rpcUsers = listOf(cashUser)).getOrThrow()
rpcBob = monitorBob.proxyObservable.value!! bobNode = bobNodeHandle.nodeInfo
runTest() val monitorBob = NodeMonitorModel()
stateMachineUpdatesBob = monitorBob.stateMachineUpdates.bufferUntilSubscribed()
monitorBob.register(bobNodeHandle.configuration.rpcAddress!!, cashUser.username, cashUser.password)
rpcBob = monitorBob.proxyObservable.value!!
runTest()
}
} }
@Test @Test

View File

@ -14,8 +14,11 @@ import net.corda.finance.DOLLARS
import net.corda.finance.contracts.asset.Cash import net.corda.finance.contracts.asset.Cash
import net.corda.finance.flows.CashIssueAndPaymentFlow import net.corda.finance.flows.CashIssueAndPaymentFlow
import net.corda.finance.flows.CashPaymentFlow import net.corda.finance.flows.CashPaymentFlow
import net.corda.testing.* import net.corda.testing.ALICE_NAME
import net.corda.testing.BOB_NAME
import net.corda.testing.CHARLIE_NAME
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.singleIdentity
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@ -24,12 +27,16 @@ import kotlin.test.assertNotNull
import kotlin.test.assertNull import kotlin.test.assertNull
class IdentitySyncFlowTests { class IdentitySyncFlowTests {
lateinit var mockNet: MockNetwork private lateinit var mockNet: MockNetwork
@Before @Before
fun before() { fun before() {
// We run this in parallel threads to help catch any race conditions that may exist. // We run this in parallel threads to help catch any race conditions that may exist.
mockNet = MockNetwork(networkSendManuallyPumped = false, threadPerNode = true, cordappPackages = listOf("net.corda.finance.contracts.asset")) mockNet = MockNetwork(
networkSendManuallyPumped = false,
threadPerNode = true,
cordappPackages = listOf("net.corda.finance.contracts.asset")
)
} }
@After @After
@ -40,12 +47,11 @@ class IdentitySyncFlowTests {
@Test @Test
fun `sync confidential identities`() { fun `sync confidential identities`() {
// Set up values we'll need // Set up values we'll need
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE_NAME) val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME) val bobNode = mockNet.createPartyNode(BOB_NAME)
val alice: Party = aliceNode.info.singleIdentity() val alice: Party = aliceNode.info.singleIdentity()
val bob: Party = bobNode.info.singleIdentity() val bob: Party = bobNode.info.singleIdentity()
val notary = notaryNode.services.getDefaultNotary() val notary = mockNet.defaultNotaryIdentity
bobNode.internals.registerInitiatedFlow(Receive::class.java) bobNode.internals.registerInitiatedFlow(Receive::class.java)
// Alice issues then pays some cash to a new confidential identity that Bob doesn't know about // Alice issues then pays some cash to a new confidential identity that Bob doesn't know about
@ -70,14 +76,13 @@ class IdentitySyncFlowTests {
@Test @Test
fun `don't offer other's identities confidential identities`() { fun `don't offer other's identities confidential identities`() {
// Set up values we'll need // Set up values we'll need
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE_NAME) val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME) val bobNode = mockNet.createPartyNode(BOB_NAME)
val charlieNode = mockNet.createPartyNode(CHARLIE_NAME) val charlieNode = mockNet.createPartyNode(CHARLIE_NAME)
val alice: Party = aliceNode.info.singleIdentity() val alice: Party = aliceNode.info.singleIdentity()
val bob: Party = bobNode.info.singleIdentity() val bob: Party = bobNode.info.singleIdentity()
val charlie: Party = charlieNode.info.singleIdentity() val charlie: Party = charlieNode.info.singleIdentity()
val notary = notaryNode.services.getDefaultNotary() val notary = mockNet.defaultNotaryIdentity
bobNode.internals.registerInitiatedFlow(Receive::class.java) bobNode.internals.registerInitiatedFlow(Receive::class.java)
// Charlie issues then pays some cash to a new confidential identity // Charlie issues then pays some cash to a new confidential identity
@ -105,7 +110,7 @@ class IdentitySyncFlowTests {
* Very lightweight wrapping flow to trigger the counterparty flow that receives the identities. * Very lightweight wrapping flow to trigger the counterparty flow that receives the identities.
*/ */
@InitiatingFlow @InitiatingFlow
class Initiator(val otherSide: Party, val tx: WireTransaction): FlowLogic<Boolean>() { class Initiator(private val otherSide: Party, private val tx: WireTransaction): FlowLogic<Boolean>() {
@Suspendable @Suspendable
override fun call(): Boolean { override fun call(): Boolean {
val session = initiateFlow(otherSide) val session = initiateFlow(otherSide)
@ -116,7 +121,7 @@ class IdentitySyncFlowTests {
} }
@InitiatedBy(IdentitySyncFlowTests.Initiator::class) @InitiatedBy(IdentitySyncFlowTests.Initiator::class)
class Receive(val otherSideSession: FlowSession): FlowLogic<Unit>() { class Receive(private val otherSideSession: FlowSession): FlowLogic<Unit>() {
@Suspendable @Suspendable
override fun call() { override fun call() {
subFlow(IdentitySyncFlow.Receive(otherSideSession)) subFlow(IdentitySyncFlow.Receive(otherSideSession))

View File

@ -6,17 +6,22 @@ import net.corda.core.identity.Party
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.Before
import org.junit.Test import org.junit.Test
import kotlin.test.* import kotlin.test.*
class SwapIdentitiesFlowTests { class SwapIdentitiesFlowTests {
private lateinit var mockNet: MockNetwork
@Before
fun setup() {
// We run this in parallel threads to help catch any race conditions that may exist.
mockNet = MockNetwork(networkSendManuallyPumped = false, threadPerNode = true)
}
@Test @Test
fun `issue key`() { fun `issue key`() {
// We run this in parallel threads to help catch any race conditions that may exist.
val mockNet = MockNetwork(threadPerNode = true)
// Set up values we'll need // Set up values we'll need
mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE.name) val aliceNode = mockNet.createPartyNode(ALICE.name)
val bobNode = mockNet.createPartyNode(BOB.name) val bobNode = mockNet.createPartyNode(BOB.name)
val alice = aliceNode.info.singleIdentity() val alice = aliceNode.info.singleIdentity()
@ -52,19 +57,16 @@ class SwapIdentitiesFlowTests {
*/ */
@Test @Test
fun `verifies identity name`() { fun `verifies identity name`() {
// We run this in parallel threads to help catch any race conditions that may exist.
val mockNet = MockNetwork(threadPerNode = true)
// Set up values we'll need // Set up values we'll need
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE.name) val aliceNode = mockNet.createPartyNode(ALICE.name)
val bobNode = mockNet.createPartyNode(BOB.name) val bobNode = mockNet.createPartyNode(BOB.name)
val charlieNode = mockNet.createPartyNode(CHARLIE.name)
val bob: Party = bobNode.services.myInfo.singleIdentity() val bob: Party = bobNode.services.myInfo.singleIdentity()
val notBob = notaryNode.database.transaction { val notBob = charlieNode.database.transaction {
notaryNode.services.keyManagementService.freshKeyAndCert(notaryNode.services.myInfo.chooseIdentityAndCert(), false) charlieNode.services.keyManagementService.freshKeyAndCert(charlieNode.services.myInfo.chooseIdentityAndCert(), false)
} }
val sigData = SwapIdentitiesFlow.buildDataToSign(notBob) val sigData = SwapIdentitiesFlow.buildDataToSign(notBob)
val signature = notaryNode.services.keyManagementService.sign(sigData, notBob.owningKey) val signature = charlieNode.services.keyManagementService.sign(sigData, notBob.owningKey)
assertFailsWith<SwapIdentitiesException>("Certificate subject must match counterparty's well known identity.") { assertFailsWith<SwapIdentitiesException>("Certificate subject must match counterparty's well known identity.") {
SwapIdentitiesFlow.validateAndRegisterIdentity(aliceNode.services.identityService, bob, notBob, signature.withoutKey()) SwapIdentitiesFlow.validateAndRegisterIdentity(aliceNode.services.identityService, bob, notBob, signature.withoutKey())
} }
@ -77,11 +79,8 @@ class SwapIdentitiesFlowTests {
*/ */
@Test @Test
fun `verifies signature`() { fun `verifies signature`() {
// We run this in parallel threads to help catch any race conditions that may exist.
val mockNet = MockNetwork(threadPerNode = true)
// Set up values we'll need // Set up values we'll need
val notaryNode = mockNet.createNotaryNode() val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE.name) val aliceNode = mockNet.createPartyNode(ALICE.name)
val bobNode = mockNet.createPartyNode(BOB.name) val bobNode = mockNet.createPartyNode(BOB.name)
val bob: Party = bobNode.services.myInfo.singleIdentity() val bob: Party = bobNode.services.myInfo.singleIdentity()

View File

@ -120,7 +120,7 @@ interface NetworkMapCacheBase {
/** /**
* Returns true if and only if the given [Party] is validating notary. For every party that is a validating notary, * Returns true if and only if the given [Party] is validating notary. For every party that is a validating notary,
* [isNotary] is only true. * [isNotary] is also true.
* @see isNotary * @see isNotary
*/ */
fun isValidatingNotary(party: Party): Boolean fun isValidatingNotary(party: Party): Boolean

View File

@ -18,14 +18,12 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
public class FlowsInJavaTest { public class FlowsInJavaTest {
private final MockNetwork mockNet = new MockNetwork(); private final MockNetwork mockNet = new MockNetwork();
private StartedNode<MockNetwork.MockNode> aliceNode; private StartedNode<MockNetwork.MockNode> aliceNode;
private StartedNode<MockNetwork.MockNode> bobNode; private StartedNode<MockNetwork.MockNode> bobNode;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
mockNet.createNotaryNode();
aliceNode = mockNet.createPartyNode(TestConstants.getALICE().getName()); aliceNode = mockNet.createPartyNode(TestConstants.getALICE().getName());
bobNode = mockNet.createPartyNode(TestConstants.getBOB().getName()); bobNode = mockNet.createPartyNode(TestConstants.getBOB().getName());
mockNet.runNetwork(); mockNet.runNetwork();

View File

@ -110,11 +110,11 @@ class AttachmentTests {
@Test @Test
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.createNotaryNode(MockNodeParameters(legalName = ALICE.name), nodeFactory = { args -> val aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE.name), nodeFactory = { args ->
object : MockNetwork.MockNode(args) { object : MockNetwork.MockNode(args) {
override fun start() = super.start().apply { attachments.checkAttachmentsOnLoad = false } override fun start() = super.start().apply { attachments.checkAttachmentsOnLoad = false }
} }
}, validating = false) })
val bobNode = mockNet.createNode(MockNodeParameters(legalName = BOB.name)) val bobNode = mockNet.createNode(MockNodeParameters(legalName = BOB.name))
mockNet.runNetwork() mockNet.runNetwork()
val alice = aliceNode.services.myInfo.identityFromX500Name(ALICE_NAME) val alice = aliceNode.services.myInfo.identityFromX500Name(ALICE_NAME)

View File

@ -27,19 +27,18 @@ class CollectSignaturesFlowTests {
private val cordappPackages = listOf("net.corda.testing.contracts") private val cordappPackages = listOf("net.corda.testing.contracts")
} }
lateinit var mockNet: MockNetwork private lateinit var mockNet: MockNetwork
lateinit var aliceNode: StartedNode<MockNetwork.MockNode> private lateinit var aliceNode: StartedNode<MockNetwork.MockNode>
lateinit var bobNode: StartedNode<MockNetwork.MockNode> private lateinit var bobNode: StartedNode<MockNetwork.MockNode>
lateinit var charlieNode: StartedNode<MockNetwork.MockNode> private lateinit var charlieNode: StartedNode<MockNetwork.MockNode>
lateinit var alice: Party private lateinit var alice: Party
lateinit var bob: Party private lateinit var bob: Party
lateinit var charlie: Party private lateinit var charlie: Party
lateinit var notary: Party private lateinit var notary: Party
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(cordappPackages = cordappPackages) mockNet = MockNetwork(cordappPackages = cordappPackages)
val notaryNode = mockNet.createNotaryNode()
aliceNode = mockNet.createPartyNode(ALICE.name) aliceNode = mockNet.createPartyNode(ALICE.name)
bobNode = mockNet.createPartyNode(BOB.name) bobNode = mockNet.createPartyNode(BOB.name)
charlieNode = mockNet.createPartyNode(CHARLIE.name) charlieNode = mockNet.createPartyNode(CHARLIE.name)
@ -47,7 +46,7 @@ class CollectSignaturesFlowTests {
alice = aliceNode.info.singleIdentity() alice = aliceNode.info.singleIdentity()
bob = bobNode.info.singleIdentity() bob = bobNode.info.singleIdentity()
charlie = charlieNode.info.singleIdentity() charlie = charlieNode.info.singleIdentity()
notary = notaryNode.services.getDefaultNotary() notary = mockNet.defaultNotaryIdentity
} }
@After @After

View File

@ -41,14 +41,13 @@ class ContractUpgradeFlowTest {
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.finance.contracts.asset", "net.corda.core.flows")) mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.finance.contracts.asset", "net.corda.core.flows"))
val notaryNode = mockNet.createNotaryNode()
aliceNode = mockNet.createPartyNode(ALICE.name) aliceNode = mockNet.createPartyNode(ALICE.name)
bobNode = mockNet.createPartyNode(BOB.name) bobNode = mockNet.createPartyNode(BOB.name)
// Process registration // Process registration
mockNet.runNetwork() mockNet.runNetwork()
notary = notaryNode.services.getDefaultNotary() notary = mockNet.defaultNotaryIdentity
} }
@After @After

View File

@ -26,7 +26,6 @@ class FinalityFlowTests {
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.finance.contracts.asset")) mockNet = MockNetwork(cordappPackages = listOf("net.corda.finance.contracts.asset"))
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE_NAME) val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME) val bobNode = mockNet.createPartyNode(BOB_NAME)
mockNet.runNetwork() mockNet.runNetwork()
@ -34,7 +33,7 @@ class FinalityFlowTests {
bobServices = bobNode.services bobServices = bobNode.services
alice = aliceNode.info.singleIdentity() alice = aliceNode.info.singleIdentity()
bob = bobNode.info.singleIdentity() bob = bobNode.info.singleIdentity()
notary = notaryNode.services.getDefaultNotary() notary = aliceServices.getDefaultNotary()
} }
@After @After

View File

@ -13,7 +13,7 @@ import org.junit.Test
class ReceiveMultipleFlowTests { class ReceiveMultipleFlowTests {
@Test @Test
fun `receive all messages in parallel using map style`() { fun `receive all messages in parallel using map style`() {
network(3) { nodes, _ -> network(3) { nodes ->
val doubleValue = 5.0 val doubleValue = 5.0
nodes[1].registerAnswer(AlgorithmDefinition::class, doubleValue) nodes[1].registerAnswer(AlgorithmDefinition::class, doubleValue)
val stringValue = "Thriller" val stringValue = "Thriller"
@ -30,7 +30,7 @@ class ReceiveMultipleFlowTests {
@Test @Test
fun `receive all messages in parallel using list style`() { fun `receive all messages in parallel using list style`() {
network(3) { nodes, _ -> network(3) { nodes ->
val value1 = 5.0 val value1 = 5.0
nodes[1].registerAnswer(ParallelAlgorithmList::class, value1) nodes[1].registerAnswer(ParallelAlgorithmList::class, value1)
val value2 = 6.0 val value2 = 6.0

View File

@ -8,7 +8,9 @@ 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.node.internal.StartedNode
import net.corda.testing.* import net.corda.testing.MEGA_CORP
import net.corda.testing.MINI_CORP
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.getDefaultNotary import net.corda.testing.getDefaultNotary
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
@ -26,18 +28,18 @@ import kotlin.test.assertNull
// DOCSTART 3 // DOCSTART 3
class ResolveTransactionsFlowTest { class ResolveTransactionsFlowTest {
lateinit var mockNet: MockNetwork private lateinit var mockNet: MockNetwork
lateinit var notaryNode: StartedNode<MockNetwork.MockNode> private lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
lateinit var megaCorpNode: StartedNode<MockNetwork.MockNode> private lateinit var megaCorpNode: StartedNode<MockNetwork.MockNode>
lateinit var miniCorpNode: StartedNode<MockNetwork.MockNode> private lateinit var miniCorpNode: StartedNode<MockNetwork.MockNode>
lateinit var megaCorp: Party private lateinit var megaCorp: Party
lateinit var miniCorp: Party private lateinit var miniCorp: Party
lateinit var notary: Party private lateinit var notary: Party
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts")) mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
notaryNode = mockNet.createNotaryNode() notaryNode = mockNet.defaultNotaryNode
megaCorpNode = mockNet.createPartyNode(MEGA_CORP.name) megaCorpNode = mockNet.createPartyNode(MEGA_CORP.name)
miniCorpNode = mockNet.createPartyNode(MINI_CORP.name) miniCorpNode = mockNet.createPartyNode(MINI_CORP.name)
megaCorpNode.internals.registerInitiatedFlow(TestResponseFlow::class.java) megaCorpNode.internals.registerInitiatedFlow(TestResponseFlow::class.java)

View File

@ -37,8 +37,7 @@ class IntegrationTestingTutorial {
invokeRpc("vaultTrackBy"), invokeRpc("vaultTrackBy"),
invokeRpc(CordaRPCOps::networkMapFeed) invokeRpc(CordaRPCOps::networkMapFeed)
)) ))
val (_, alice, bob) = listOf( val (alice, bob) = listOf(
startNotaryNode(DUMMY_NOTARY.name),
startNode(providedName = ALICE.name, rpcUsers = listOf(aliceUser)), startNode(providedName = ALICE.name, rpcUsers = listOf(aliceUser)),
startNode(providedName = BOB.name, rpcUsers = listOf(bobUser)) startNode(providedName = BOB.name, rpcUsers = listOf(bobUser))
).transpose().getOrThrow() ).transpose().getOrThrow()

View File

@ -1,3 +1,5 @@
@file:Suppress("unused")
package net.corda.docs package net.corda.docs
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
@ -17,7 +19,6 @@ 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.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import org.graphstream.graph.Edge import org.graphstream.graph.Edge
import org.graphstream.graph.Node import org.graphstream.graph.Node
@ -48,7 +49,6 @@ fun main(args: Array<String>) {
invokeRpc(CordaRPCOps::nodeInfo) invokeRpc(CordaRPCOps::nodeInfo)
)) ))
driver(driverDirectory = baseDirectory, extraCordappPackagesToScan = listOf("net.corda.finance")) { driver(driverDirectory = baseDirectory, extraCordappPackagesToScan = listOf("net.corda.finance")) {
startNotaryNode(DUMMY_NOTARY.name)
val node = startNode(providedName = ALICE.name, rpcUsers = listOf(user)).get() val node = startNode(providedName = ALICE.name, rpcUsers = listOf(user)).get()
// END 1 // END 1

View File

@ -55,7 +55,6 @@ class TutorialMockNetwork {
} }
lateinit private var mockNet: MockNetwork lateinit private var mockNet: MockNetwork
lateinit private var notary: StartedNode<MockNetwork.MockNode>
lateinit private var nodeA: StartedNode<MockNetwork.MockNode> lateinit private var nodeA: StartedNode<MockNetwork.MockNode>
lateinit private var nodeB: StartedNode<MockNetwork.MockNode> lateinit private var nodeB: StartedNode<MockNetwork.MockNode>
@ -66,7 +65,6 @@ class TutorialMockNetwork {
@Before @Before
fun setUp() { fun setUp() {
mockNet = MockNetwork() mockNet = MockNetwork()
notary = mockNet.createNotaryNode()
nodeA = mockNet.createPartyNode() nodeA = mockNet.createPartyNode()
nodeB = mockNet.createPartyNode() nodeB = mockNet.createPartyNode()

View File

@ -10,7 +10,8 @@ import net.corda.finance.contracts.getCashBalances
import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.schemas.CashSchemaV1 import net.corda.finance.schemas.CashSchemaV1
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.* import net.corda.testing.chooseIdentity
import net.corda.testing.getDefaultNotary
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Assert import org.junit.Assert
@ -19,23 +20,20 @@ import org.junit.Test
import java.util.* import java.util.*
class CustomVaultQueryTest { class CustomVaultQueryTest {
private lateinit var mockNet: MockNetwork
lateinit var mockNet: MockNetwork private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
lateinit var nodeA: StartedNode<MockNetwork.MockNode> private lateinit var nodeB: StartedNode<MockNetwork.MockNode>
lateinit var nodeB: StartedNode<MockNetwork.MockNode> private lateinit var notary: Party
lateinit var notary: Party
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork( mockNet = MockNetwork(threadPerNode = true,
threadPerNode = true,
cordappPackages = listOf( cordappPackages = listOf(
"net.corda.finance.contracts.asset", "net.corda.finance.contracts.asset",
CashSchemaV1::class.packageName, CashSchemaV1::class.packageName,
"net.corda.docs" "net.corda.docs"
) )
) )
mockNet.createNotaryNode()
nodeA = mockNet.createPartyNode() nodeA = mockNet.createPartyNode()
nodeB = mockNet.createPartyNode() nodeB = mockNet.createPartyNode()
nodeA.internals.registerInitiatedFlow(TopupIssuerFlow.TopupIssuer::class.java) nodeA.internals.registerInitiatedFlow(TopupIssuerFlow.TopupIssuer::class.java)

View File

@ -10,7 +10,8 @@ import net.corda.finance.contracts.getCashBalances
import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.schemas.CashSchemaV1 import net.corda.finance.schemas.CashSchemaV1
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.* import net.corda.testing.chooseIdentity
import net.corda.testing.getDefaultNotary
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -18,15 +19,14 @@ import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class FxTransactionBuildTutorialTest { class FxTransactionBuildTutorialTest {
lateinit var mockNet: MockNetwork private lateinit var mockNet: MockNetwork
lateinit var nodeA: StartedNode<MockNetwork.MockNode> private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
lateinit var nodeB: StartedNode<MockNetwork.MockNode> private lateinit var nodeB: StartedNode<MockNetwork.MockNode>
lateinit var notary: Party private lateinit var notary: Party
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.finance.contracts.asset", CashSchemaV1::class.packageName)) mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.finance.contracts.asset", CashSchemaV1::class.packageName))
mockNet.createNotaryNode()
nodeA = mockNet.createPartyNode() nodeA = mockNet.createPartyNode()
nodeB = mockNet.createPartyNode() nodeB = mockNet.createPartyNode()
nodeB.internals.registerInitiatedFlow(ForeignExchangeRemoteFlow::class.java) nodeB.internals.registerInitiatedFlow(ForeignExchangeRemoteFlow::class.java)

View File

@ -10,7 +10,8 @@ import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.toFuture import net.corda.core.toFuture
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.node.services.api.StartedNodeServices import net.corda.node.services.api.StartedNodeServices
import net.corda.testing.* import net.corda.testing.ALICE_NAME
import net.corda.testing.BOB_NAME
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -18,11 +19,11 @@ import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class WorkflowTransactionBuildTutorialTest { class WorkflowTransactionBuildTutorialTest {
lateinit var mockNet: MockNetwork private lateinit var mockNet: MockNetwork
lateinit var aliceServices: StartedNodeServices private lateinit var aliceServices: StartedNodeServices
lateinit var bobServices: StartedNodeServices private lateinit var bobServices: StartedNodeServices
lateinit var alice: Party private lateinit var alice: Party
lateinit var bob: Party private lateinit var bob: Party
// Helper method to locate the latest Vault version of a LinearState // Helper method to locate the latest Vault version of a LinearState
private inline fun <reified T : LinearState> ServiceHub.latest(ref: UniqueIdentifier): StateAndRef<T> { private inline fun <reified T : LinearState> ServiceHub.latest(ref: UniqueIdentifier): StateAndRef<T> {
@ -33,8 +34,6 @@ class WorkflowTransactionBuildTutorialTest {
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.docs")) mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.docs"))
// While we don't use the notary, we need there to be one on the network
mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE_NAME) val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME) val bobNode = mockNet.createPartyNode(BOB_NAME)
aliceNode.internals.registerInitiatedFlow(RecordCompletionFlow::class.java) aliceNode.internals.registerInitiatedFlow(RecordCompletionFlow::class.java)

View File

@ -1,41 +1,38 @@
package net.corda.finance.contracts.asset package net.corda.finance.contracts.asset
import net.corda.core.internal.packageName
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.finance.DOLLARS import net.corda.finance.DOLLARS
import net.corda.finance.flows.CashException import net.corda.finance.flows.CashException
import net.corda.finance.flows.CashPaymentFlow import net.corda.finance.flows.CashPaymentFlow
import net.corda.finance.schemas.CashSchemaV1
import net.corda.testing.chooseIdentity
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 org.assertj.core.api.Assertions.assertThatThrownBy import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.After
import org.junit.Test import org.junit.Test
class CashSelectionH2Test { class CashSelectionH2Test {
private val mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.finance"))
@After
fun cleanUp() {
mockNet.stopNodes()
}
@Test @Test
fun `check does not hold connection over retries`() { fun `check does not hold connection over retries`() {
val mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.finance.contracts.asset", CashSchemaV1::class.packageName)) val bankA = mockNet.createNode(MockNodeParameters(configOverrides = {
try { // Tweak connections to be minimal to make this easier (1 results in a hung node during start up, so use 2 connections).
val notaryNode = mockNet.createNotaryNode() it.dataSourceProperties.setProperty("maximumPoolSize", "2")
val bankA = mockNet.createNode(MockNodeParameters(configOverrides = { existingConfig -> }))
// Tweak connections to be minimal to make this easier (1 results in a hung node during start up, so use 2 connections). val notary = mockNet.defaultNotaryIdentity
existingConfig.dataSourceProperties.setProperty("maximumPoolSize", "2")
}))
mockNet.startNodes()
// Start more cash spends than we have connections. If spend leaks a connection on retry, we will run out of connections. // Start more cash spends than we have connections. If spend leaks a connection on retry, we will run out of connections.
val flow1 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notaryNode.info.chooseIdentity())) val flow1 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary))
val flow2 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notaryNode.info.chooseIdentity())) val flow2 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary))
val flow3 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notaryNode.info.chooseIdentity())) val flow3 = bankA.services.startFlow(CashPaymentFlow(amount = 100.DOLLARS, anonymous = false, recipient = notary))
assertThatThrownBy { flow1.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java) assertThatThrownBy { flow1.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java)
assertThatThrownBy { flow2.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java) assertThatThrownBy { flow2.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java)
assertThatThrownBy { flow3.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java) assertThatThrownBy { flow3.resultFuture.getOrThrow() }.isInstanceOf(CashException::class.java)
} finally {
mockNet.stopNodes()
}
} }
} }

View File

@ -7,7 +7,9 @@ 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.node.internal.StartedNode
import net.corda.testing.* import net.corda.testing.BOC
import net.corda.testing.chooseIdentity
import net.corda.testing.getDefaultNotary
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.MockNetwork.MockNode
@ -23,15 +25,13 @@ class CashExitFlowTests {
private val ref = OpaqueBytes.of(0x01) private val ref = OpaqueBytes.of(0x01)
private lateinit var bankOfCordaNode: StartedNode<MockNode> private lateinit var bankOfCordaNode: StartedNode<MockNode>
private lateinit var bankOfCorda: Party private lateinit var bankOfCorda: Party
private lateinit var notaryNode: StartedNode<MockNode>
private lateinit var notary: Party private lateinit var notary: Party
@Before @Before
fun start() { fun start() {
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset")) mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(),
notaryNode = mockNet.createNotaryNode() cordappPackages = listOf("net.corda.finance.contracts.asset"))
bankOfCordaNode = mockNet.createPartyNode(BOC.name) bankOfCordaNode = mockNet.createPartyNode(BOC.name)
notary = notaryNode.services.getDefaultNotary()
bankOfCorda = bankOfCordaNode.info.chooseIdentity() bankOfCorda = bankOfCordaNode.info.chooseIdentity()
mockNet.runNetwork() mockNet.runNetwork()

View File

@ -7,9 +7,8 @@ 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.node.internal.StartedNode
import net.corda.testing.chooseIdentity
import net.corda.testing.getDefaultNotary
import net.corda.testing.BOC import net.corda.testing.BOC
import net.corda.testing.chooseIdentity
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.MockNetwork.MockNode
@ -23,16 +22,14 @@ class CashIssueFlowTests {
private lateinit var mockNet: MockNetwork private lateinit var mockNet: MockNetwork
private lateinit var bankOfCordaNode: StartedNode<MockNode> private lateinit var bankOfCordaNode: StartedNode<MockNode>
private lateinit var bankOfCorda: Party private lateinit var bankOfCorda: Party
private lateinit var notaryNode: StartedNode<MockNode>
private lateinit var notary: Party private lateinit var notary: Party
@Before @Before
fun start() { fun start() {
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset")) mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset"))
notaryNode = mockNet.createNotaryNode()
bankOfCordaNode = mockNet.createPartyNode(BOC.name) bankOfCordaNode = mockNet.createPartyNode(BOC.name)
bankOfCorda = bankOfCordaNode.info.chooseIdentity() bankOfCorda = bankOfCordaNode.info.chooseIdentity()
notary = notaryNode.services.getDefaultNotary() notary = mockNet.defaultNotaryIdentity
mockNet.runNetwork() mockNet.runNetwork()
} }

View File

@ -26,18 +26,16 @@ class CashPaymentFlowTests {
private val ref = OpaqueBytes.of(0x01) private val ref = OpaqueBytes.of(0x01)
private lateinit var bankOfCordaNode: StartedNode<MockNode> private lateinit var bankOfCordaNode: StartedNode<MockNode>
private lateinit var bankOfCorda: Party private lateinit var bankOfCorda: Party
private lateinit var notaryNode: StartedNode<MockNode> private lateinit var aliceNode: StartedNode<MockNode>
private lateinit var notary: Party
@Before @Before
fun start() { fun start() {
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset")) mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset"))
notaryNode = mockNet.createNotaryNode()
bankOfCordaNode = mockNet.createPartyNode(BOC.name) bankOfCordaNode = mockNet.createPartyNode(BOC.name)
aliceNode = mockNet.createPartyNode(ALICE.name)
bankOfCorda = bankOfCordaNode.info.chooseIdentity() bankOfCorda = bankOfCordaNode.info.chooseIdentity()
notary = notaryNode.services.getDefaultNotary()
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
mockNet.runNetwork() mockNet.runNetwork()
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, mockNet.defaultNotaryIdentity)).resultFuture
future.getOrThrow() future.getOrThrow()
} }
@ -48,7 +46,7 @@ class CashPaymentFlowTests {
@Test @Test
fun `pay some cash`() { fun `pay some cash`() {
val payTo = notaryNode.info.chooseIdentity() val payTo = aliceNode.info.chooseIdentity()
val expectedPayment = 500.DOLLARS val expectedPayment = 500.DOLLARS
val expectedChange = 1500.DOLLARS val expectedChange = 1500.DOLLARS
@ -56,7 +54,7 @@ class CashPaymentFlowTests {
// Register for vault updates // Register for vault updates
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL) val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
val (_, vaultUpdatesBoc) = bankOfCordaNode.services.vaultService.trackBy<Cash.State>(criteria) val (_, vaultUpdatesBoc) = bankOfCordaNode.services.vaultService.trackBy<Cash.State>(criteria)
val (_, vaultUpdatesBankClient) = notaryNode.services.vaultService.trackBy<Cash.State>(criteria) val (_, vaultUpdatesBankClient) = aliceNode.services.vaultService.trackBy<Cash.State>(criteria)
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expectedPayment, val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expectedPayment,
payTo)).resultFuture payTo)).resultFuture
@ -88,7 +86,7 @@ class CashPaymentFlowTests {
@Test @Test
fun `pay more than we have`() { fun `pay more than we have`() {
val payTo = notaryNode.info.chooseIdentity() val payTo = aliceNode.info.chooseIdentity()
val expected = 4000.DOLLARS val expected = 4000.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected, val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
payTo)).resultFuture payTo)).resultFuture
@ -100,7 +98,7 @@ class CashPaymentFlowTests {
@Test @Test
fun `pay zero cash`() { fun `pay zero cash`() {
val payTo = notaryNode.info.chooseIdentity() val payTo = aliceNode.info.chooseIdentity()
val expected = 0.DOLLARS val expected = 0.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected, val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
payTo)).resultFuture payTo)).resultFuture

View File

@ -15,9 +15,9 @@ 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.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.node.NotarySpec
import net.corda.testing.performance.div import net.corda.testing.performance.div
import net.corda.testing.performance.startPublishingFixedRateInjector import net.corda.testing.performance.startPublishingFixedRateInjector
import net.corda.testing.performance.startReporter import net.corda.testing.performance.startReporter
@ -102,26 +102,25 @@ class NodePerformanceTests {
@Test @Test
fun `self pay rate`() { fun `self pay rate`() {
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance")) { val user = User("A", "A", setOf(startFlow<CashIssueFlow>(), startFlow<CashPaymentFlow>()))
val a = startNotaryNode( driver(
DUMMY_NOTARY.name, notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, rpcUsers = listOf(user))),
rpcUsers = listOf(User("A", "A", setOf(startFlow<CashIssueFlow>(), startFlow<CashPaymentFlow>()))) startNodesInProcess = true,
).getOrThrow() extraCordappPackagesToScan = listOf("net.corda.finance")
a as NodeHandle.InProcess ) {
val metricRegistry = startReporter(shutdownManager, a.node.services.monitoringService.metrics) val notary = defaultNotaryNode.getOrThrow() as NodeHandle.InProcess
a.rpcClientToNode().use("A", "A") { connection -> val metricRegistry = startReporter(shutdownManager, notary.node.services.monitoringService.metrics)
val notary = connection.proxy.notaryIdentities().first() notary.rpcClientToNode().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), notary).returnValue connection.proxy.startFlow(::CashIssueFlow, 1.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue
}.toList() }.toList()
doneFutures.transpose().get() doneFutures.transpose().get()
println("STARTING PAYMENT") println("STARTING PAYMENT")
startPublishingFixedRateInjector(metricRegistry, 8, 5.minutes, 100L / TimeUnit.SECONDS) { startPublishingFixedRateInjector(metricRegistry, 8, 5.minutes, 100L / TimeUnit.SECONDS) {
connection.proxy.startFlow(::CashPaymentFlow, 1.DOLLARS, a.nodeInfo.chooseIdentity()).returnValue.get() connection.proxy.startFlow(::CashPaymentFlow, 1.DOLLARS, defaultNotaryIdentity).returnValue.get()
} }
} }
} }
} }
} }

View File

@ -13,20 +13,16 @@ import net.corda.core.internal.div
import net.corda.core.internal.toLedgerTransaction import net.corda.core.internal.toLedgerTransaction
import net.corda.core.serialization.SerializationFactory import net.corda.core.serialization.SerializationFactory
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.seconds
import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.internal.cordapp.CordappProviderImpl import net.corda.node.internal.cordapp.CordappProviderImpl
import net.corda.nodeapi.User
import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.SerializationEnvironmentRule import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.driver.DriverDSLExposedInterface import net.corda.testing.driver.DriverDSLExposedInterface
import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.eventually
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Before import org.junit.Before
@ -56,19 +52,15 @@ class AttachmentLoadingTests {
val bankAName = CordaX500Name("BankA", "Zurich", "CH") val bankAName = CordaX500Name("BankA", "Zurich", "CH")
val bankBName = CordaX500Name("BankB", "Zurich", "CH") val bankBName = CordaX500Name("BankB", "Zurich", "CH")
val notaryName = CordaX500Name("Notary", "Zurich", "CH")
val flowInitiatorClass: Class<out FlowLogic<*>> = val flowInitiatorClass: Class<out FlowLogic<*>> =
Class.forName("net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator", true, URLClassLoader(arrayOf(isolatedJAR))) Class.forName("net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator", true, URLClassLoader(arrayOf(isolatedJAR)))
.asSubclass(FlowLogic::class.java) .asSubclass(FlowLogic::class.java)
private fun DriverDSLExposedInterface.createNotaryAndTwoNodes(): List<NodeHandle> { private fun DriverDSLExposedInterface.createTwoNodes(): List<NodeHandle> {
val adminUser = User("admin", "admin", permissions = setOf("ALL")) return listOf(
val nodes = listOf( startNode(providedName = bankAName),
startNotaryNode(providedName = notaryName, rpcUsers = listOf(adminUser), validating = false), startNode(providedName = bankBName)
startNode(providedName = bankAName, rpcUsers = listOf(adminUser)), ).transpose().getOrThrow()
startNode(providedName = bankBName, rpcUsers = listOf(adminUser))
).transpose().getOrThrow() // Wait for all nodes to start up.
return nodes
} }
private fun DriverDSLExposedInterface.installIsolatedCordappTo(nodeName: CordaX500Name) { private fun DriverDSLExposedInterface.installIsolatedCordappTo(nodeName: CordaX500Name) {
@ -81,15 +73,6 @@ class AttachmentLoadingTests {
} }
} }
} }
// Due to cluster instability after nodes been started it may take some time to all the nodes to become available
// *and* discover each other to reliably communicate. Hence, eventual nature of the test.
// TODO: Remove this method and usages of it once NetworkMap service been re-worked
private fun eventuallyPassingTest(block: () -> Unit) {
eventually<Throwable, Unit>(30.seconds) {
block()
}
}
} }
private lateinit var services: Services private lateinit var services: Services
@ -105,9 +88,8 @@ class AttachmentLoadingTests {
val contractClass = appClassLoader.loadClass(ISOLATED_CONTRACT_ID).asSubclass(Contract::class.java) val contractClass = appClassLoader.loadClass(ISOLATED_CONTRACT_ID).asSubclass(Contract::class.java)
val generateInitialMethod = contractClass.getDeclaredMethod("generateInitial", PartyAndReference::class.java, Integer.TYPE, Party::class.java) val generateInitialMethod = contractClass.getDeclaredMethod("generateInitial", PartyAndReference::class.java, Integer.TYPE, Party::class.java)
val contract = contractClass.newInstance() val contract = contractClass.newInstance()
val txBuilder = generateInitialMethod.invoke(contract, PartyAndReference(DUMMY_BANK_A, OpaqueBytes(kotlin.ByteArray(1))), 1, DUMMY_NOTARY) as TransactionBuilder val txBuilder = generateInitialMethod.invoke(contract, DUMMY_BANK_A.ref(1), 1, DUMMY_NOTARY) as TransactionBuilder
val context = SerializationFactory.defaultFactory.defaultContext val context = SerializationFactory.defaultFactory.defaultContext.withClassLoader(appClassLoader)
.withClassLoader(appClassLoader)
val ledgerTx = txBuilder.toLedgerTransaction(services, context) val ledgerTx = txBuilder.toLedgerTransaction(services, context)
contract.verify(ledgerTx) contract.verify(ledgerTx)
@ -121,11 +103,9 @@ class AttachmentLoadingTests {
fun `test that attachments retrieved over the network are not used for code`() { fun `test that attachments retrieved over the network are not used for code`() {
driver(initialiseSerialization = false) { driver(initialiseSerialization = false) {
installIsolatedCordappTo(bankAName) installIsolatedCordappTo(bankAName)
val (_, bankA, bankB) = createNotaryAndTwoNodes() val (bankA, bankB) = createTwoNodes()
eventuallyPassingTest { assertFailsWith<UnexpectedFlowEndException>("Party C=CH,L=Zurich,O=BankB rejected session request: Don't know net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator") {
assertFailsWith<UnexpectedFlowEndException>("Party C=CH,L=Zurich,O=BankB rejected session request: Don't know net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator") { bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow()
bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow()
}
} }
} }
} }
@ -135,10 +115,8 @@ class AttachmentLoadingTests {
driver(initialiseSerialization = false) { driver(initialiseSerialization = false) {
installIsolatedCordappTo(bankAName) installIsolatedCordappTo(bankAName)
installIsolatedCordappTo(bankBName) installIsolatedCordappTo(bankBName)
val (_, bankA, bankB) = createNotaryAndTwoNodes() val (bankA, bankB) = createTwoNodes()
eventuallyPassingTest { bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow()
bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow()
}
} }
} }
} }

View File

@ -11,60 +11,64 @@ import net.corda.core.utilities.getOrThrow
import net.corda.finance.POUNDS import net.corda.finance.POUNDS
import net.corda.finance.flows.CashIssueFlow 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.invokeRpc import net.corda.node.services.Permissions.Companion.invokeRpc
import net.corda.node.services.transactions.RaftValidatingNotaryService import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.node.ClusterSpec
import net.corda.testing.node.NotarySpec
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test import org.junit.Test
import rx.Observable import rx.Observable
import java.util.* import java.util.*
import kotlin.test.assertEquals
class DistributedServiceTests { class DistributedServiceTests {
lateinit var alice: NodeHandle private lateinit var alice: NodeHandle
lateinit var notaries: List<NodeHandle.OutOfProcess> private lateinit var notaryNodes: List<NodeHandle.OutOfProcess>
lateinit var aliceProxy: CordaRPCOps private lateinit var aliceProxy: CordaRPCOps
lateinit var raftNotaryIdentity: Party private lateinit var raftNotaryIdentity: Party
lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>> private lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>>
private fun setup(runTest: () -> Unit) = driver(extraCordappPackagesToScan = listOf("net.corda.finance.contracts")) {
// Start Alice and 3 notaries in a RAFT cluster private fun setup(testBlock: () -> Unit) {
val clusterSize = 3
val testUser = User("test", "test", permissions = setOf( val testUser = User("test", "test", permissions = setOf(
startFlow<CashIssueFlow>(), startFlow<CashIssueFlow>(),
startFlow<CashPaymentFlow>(), startFlow<CashPaymentFlow>(),
invokeRpc(CordaRPCOps::nodeInfo), invokeRpc(CordaRPCOps::nodeInfo),
invokeRpc(CordaRPCOps::stateMachinesFeed)) invokeRpc(CordaRPCOps::stateMachinesFeed))
) )
val notariesFuture = startNotaryCluster(
DUMMY_NOTARY.name.copy(commonName = RaftValidatingNotaryService.id),
rpcUsers = listOf(testUser),
clusterSize = clusterSize
)
val aliceFuture = startNode(providedName = ALICE.name, rpcUsers = listOf(testUser))
alice = aliceFuture.get() driver(
val (notaryIdentity, notaryNodes) = notariesFuture.get() extraCordappPackagesToScan = listOf("net.corda.finance.contracts"),
raftNotaryIdentity = notaryIdentity notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, rpcUsers = listOf(testUser), cluster = ClusterSpec.Raft(clusterSize = 3))))
notaries = notaryNodes.map { it as NodeHandle.OutOfProcess } {
alice = startNode(providedName = ALICE.name, rpcUsers = listOf(testUser)).getOrThrow()
raftNotaryIdentity = defaultNotaryIdentity
notaryNodes = defaultNotaryHandle.nodeHandles.getOrThrow().map { it as NodeHandle.OutOfProcess }
assertEquals(notaries.size, clusterSize) assertThat(notaryNodes).hasSize(3)
// Check that each notary has different identity as a node.
assertEquals(notaries.size, notaries.map { it.nodeInfo.chooseIdentity() }.toSet().size) for (notaryNode in notaryNodes) {
// Connect to Alice and the notaries assertThat(notaryNode.nodeInfo.legalIdentities).contains(raftNotaryIdentity)
fun connectRpc(node: NodeHandle): CordaRPCOps { }
val client = node.rpcClientToNode()
return client.start("test", "test").proxy // Check that each notary has different identity as a node.
assertThat(notaryNodes.flatMap { it.nodeInfo.legalIdentities - raftNotaryIdentity }.toSet()).hasSameSizeAs(notaryNodes)
// Connect to Alice and the notaries
fun connectRpc(node: NodeHandle): CordaRPCOps {
val client = node.rpcClientToNode()
return client.start("test", "test").proxy
}
aliceProxy = connectRpc(alice)
val rpcClientsToNotaries = notaryNodes.map(::connectRpc)
notaryStateMachines = Observable.from(rpcClientsToNotaries.map { proxy ->
proxy.stateMachinesFeed().updates.map { Pair(proxy.nodeInfo().chooseIdentity(), it) }
}).flatMap { it.onErrorResumeNext(Observable.empty()) }.bufferUntilSubscribed()
testBlock()
} }
aliceProxy = connectRpc(alice)
val rpcClientsToNotaries = notaries.map(::connectRpc)
notaryStateMachines = Observable.from(rpcClientsToNotaries.map { proxy ->
proxy.stateMachinesFeed().updates.map { Pair(proxy.nodeInfo().chooseIdentity(), it) }
}).flatMap { it.onErrorResumeNext(Observable.empty()) }.bufferUntilSubscribed()
runTest()
} }
// TODO Use a dummy distributed service rather than a Raft Notary Service as this test is only about Artemis' ability // TODO Use a dummy distributed service rather than a Raft Notary Service as this test is only about Artemis' ability
@ -106,8 +110,8 @@ class DistributedServiceTests {
paySelf(5.POUNDS) paySelf(5.POUNDS)
} }
// Now kill a notary // Now kill a notary node
with(notaries[0].process) { with(notaryNodes[0].process) {
destroy() destroy()
waitFor() waitFor()
} }

View File

@ -18,6 +18,8 @@ import net.corda.testing.contracts.DummyContract
import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.dummyCommand import net.corda.testing.dummyCommand
import net.corda.testing.node.ClusterSpec
import net.corda.testing.node.NotarySpec
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -28,13 +30,16 @@ class RaftNotaryServiceTests {
@Test @Test
fun `detect double spend`() { fun `detect double spend`() {
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts")) { driver(
val (notaryParty) = startNotaryCluster(notaryName, 3).getOrThrow() startNodesInProcess = true,
extraCordappPackagesToScan = listOf("net.corda.testing.contracts"),
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 NodeHandle.InProcess).node }.getOrThrow()
val inputState = issueState(bankA, notaryParty) val inputState = issueState(bankA, defaultNotaryIdentity)
val firstTxBuilder = TransactionBuilder(notaryParty) val firstTxBuilder = TransactionBuilder(defaultNotaryIdentity)
.addInputState(inputState) .addInputState(inputState)
.addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey)) .addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder) val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder)
@ -42,7 +47,7 @@ class RaftNotaryServiceTests {
val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx)) val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
firstSpend.resultFuture.getOrThrow() firstSpend.resultFuture.getOrThrow()
val secondSpendBuilder = TransactionBuilder(notaryParty).withItems(inputState).run { val secondSpendBuilder = TransactionBuilder(defaultNotaryIdentity).withItems(inputState).run {
val dummyState = DummyContract.SingleOwnerState(0, bankA.info.chooseIdentity()) val dummyState = DummyContract.SingleOwnerState(0, bankA.info.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))

View File

@ -8,11 +8,11 @@ import net.corda.core.messaging.startFlow
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.testing.BOB import net.corda.testing.BOB
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.aliceAndBob
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.contracts.DummyState import net.corda.testing.contracts.DummyState
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.dummyCommand import net.corda.testing.dummyCommand
import net.corda.testing.notaryAliceAndBob
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -65,7 +65,7 @@ class LargeTransactionsTest {
val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 2) val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 2)
val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 3) val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 3)
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts")) { driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts")) {
val (_, alice) = notaryAliceAndBob() val (alice, _) = aliceAndBob()
alice.useRPC { alice.useRPC {
val hash1 = it.uploadAttachment(bigFile1.inputStream) val hash1 = it.uploadAttachment(bigFile1.inputStream)
val hash2 = it.uploadAttachment(bigFile2.inputStream) val hash2 = it.uploadAttachment(bigFile2.inputStream)

View File

@ -21,6 +21,8 @@ import net.corda.testing.chooseIdentity
import net.corda.testing.driver.DriverDSLExposedInterface import net.corda.testing.driver.DriverDSLExposedInterface
import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.node.ClusterSpec
import net.corda.testing.node.NotarySpec
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*
@ -35,16 +37,14 @@ class P2PMessagingTest {
@Test @Test
fun `communicating with a distributed service which we're part of`() { fun `communicating with a distributed service which we're part of`() {
driver(startNodesInProcess = true) { startDriverWithDistributedService { distributedService ->
val distributedService = startDistributedService()
assertAllNodesAreUsed(distributedService, DISTRIBUTED_SERVICE_NAME, distributedService[0]) assertAllNodesAreUsed(distributedService, DISTRIBUTED_SERVICE_NAME, distributedService[0])
} }
} }
@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`() {
driver(startNodesInProcess = true) { startDriverWithDistributedService { distributedServiceNodes ->
val distributedServiceNodes = startDistributedService()
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()!!
@ -77,8 +77,7 @@ class P2PMessagingTest {
@Test @Test
fun `distributed service request retries are persisted across client node restarts`() { fun `distributed service request retries are persisted across client node restarts`() {
driver(startNodesInProcess = true) { startDriverWithDistributedService { distributedServiceNodes ->
val distributedServiceNodes = startDistributedService()
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()!!
@ -117,11 +116,10 @@ class P2PMessagingTest {
} }
} }
private fun DriverDSLExposedInterface.startDistributedService(): List<StartedNode<Node>> { private fun startDriverWithDistributedService(dsl: DriverDSLExposedInterface.(List<StartedNode<Node>>) -> Unit) {
return startNotaryCluster(DISTRIBUTED_SERVICE_NAME, 2) driver(startNodesInProcess = true, notarySpecs = listOf(NotarySpec(DISTRIBUTED_SERVICE_NAME, cluster = ClusterSpec.Raft(clusterSize = 2)))) {
.getOrThrow() dsl(defaultNotaryHandle.nodeHandles.getOrThrow().map { (it as NodeHandle.InProcess).node })
.second }
.map { (it as NodeHandle.InProcess).node }
} }
private fun DriverDSLExposedInterface.startAlice(): StartedNode<Node> { private fun DriverDSLExposedInterface.startAlice(): StartedNode<Node> {

View File

@ -17,10 +17,9 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.invokeRpc
import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity import net.corda.testing.chooseIdentity
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import org.junit.Assume.assumeFalse import org.junit.Assume.assumeFalse
@ -43,7 +42,6 @@ class NodeStatePersistenceTests {
val message = Message("Hello world!") val message = Message("Hello world!")
driver(isDebug = true, startNodesInProcess = isQuasarAgentSpecified()) { driver(isDebug = true, startNodesInProcess = isQuasarAgentSpecified()) {
val nodeName = { val nodeName = {
startNotaryNode(DUMMY_NOTARY.name, validating = false).getOrThrow()
val nodeHandle = startNode(rpcUsers = listOf(user)).getOrThrow() val nodeHandle = startNode(rpcUsers = listOf(user)).getOrThrow()
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
nodeHandle.rpcClientToNode().start(user.username, user.password).use { nodeHandle.rpcClientToNode().start(user.username, user.password).use {

View File

@ -31,6 +31,7 @@ import java.security.PublicKey
import java.util.* import java.util.*
import javax.annotation.concurrent.ThreadSafe import javax.annotation.concurrent.ThreadSafe
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.collections.HashSet
class NetworkMapCacheImpl( class NetworkMapCacheImpl(
networkMapCacheBase: NetworkMapCacheBaseInternal, networkMapCacheBase: NetworkMapCacheBaseInternal,
@ -85,7 +86,7 @@ open class PersistentNetworkMapCache(
override val loadDBSuccess get() = _loadDBSuccess override val loadDBSuccess get() = _loadDBSuccess
override val notaryIdentities: List<Party> = notaries.map { it.identity } override val notaryIdentities: List<Party> = notaries.map { it.identity }
private val validatingNotaries = notaries.mapNotNull { if (it.validating) it.identity else null } private val validatingNotaries = notaries.mapNotNullTo(HashSet()) { if (it.validating) it.identity else null }
private val nodeInfoSerializer = NodeInfoWatcher(configuration.baseDirectory, private val nodeInfoSerializer = NodeInfoWatcher(configuration.baseDirectory,
configuration.additionalNodeInfoPollingFrequencyMsec) configuration.additionalNodeInfoPollingFrequencyMsec)

View File

@ -50,14 +50,12 @@ import kotlin.test.assertNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
class CordaRPCOpsImplTest { class CordaRPCOpsImplTest {
private companion object { private companion object {
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: MockNetwork
private lateinit var aliceNode: StartedNode<MockNode> private lateinit var aliceNode: StartedNode<MockNode>
private lateinit var notaryNode: StartedNode<MockNode>
private lateinit var notary: Party private lateinit var notary: Party
private lateinit var rpc: CordaRPCOps private lateinit var rpc: CordaRPCOps
private lateinit var stateMachineUpdates: Observable<StateMachineUpdate> private lateinit var stateMachineUpdates: Observable<StateMachineUpdate>
@ -69,7 +67,6 @@ class CordaRPCOpsImplTest {
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.finance.contracts.asset")) mockNet = MockNetwork(cordappPackages = listOf("net.corda.finance.contracts.asset"))
notaryNode = mockNet.createNotaryNode(validating = false)
aliceNode = mockNet.createNode() aliceNode = mockNet.createNode()
rpc = SecureCordaRPCOps(aliceNode.services, aliceNode.smm, aliceNode.database, aliceNode.services) rpc = SecureCordaRPCOps(aliceNode.services, aliceNode.smm, aliceNode.database, aliceNode.services)
CURRENT_RPC_CONTEXT.set(RpcContext(user)) CURRENT_RPC_CONTEXT.set(RpcContext(user))

View File

@ -74,14 +74,12 @@ class TestCordaService2(val appServiceHub: AppServiceHub): SingletonSerializeAsT
class LegacyCordaService(@Suppress("UNUSED_PARAMETER") simpleServiceHub: ServiceHub) : SingletonSerializeAsToken() class LegacyCordaService(@Suppress("UNUSED_PARAMETER") simpleServiceHub: ServiceHub) : SingletonSerializeAsToken()
class CordaServiceTest { class CordaServiceTest {
lateinit var mockNet: MockNetwork private lateinit var mockNet: MockNetwork
lateinit var notaryNode: StartedNode<MockNetwork.MockNode> private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
@Before @Before
fun start() { fun start() {
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.node.internal","net.corda.finance")) mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.node.internal","net.corda.finance"))
notaryNode = mockNet.createNotaryNode()
nodeA = mockNet.createNode() nodeA = mockNet.createNode()
mockNet.startNodes() mockNet.startNodes()
} }

View File

@ -63,7 +63,7 @@ import kotlin.test.assertTrue
* We assume that Alice and Bob already found each other via some market, and have agreed the details already. * We assume that Alice and Bob already found each other via some market, and have agreed the details already.
*/ */
@RunWith(Parameterized::class) @RunWith(Parameterized::class)
class TwoPartyTradeFlowTests(val anonymous: Boolean) { class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
companion object { companion object {
private val cordappPackages = listOf("net.corda.finance.contracts") private val cordappPackages = listOf("net.corda.finance.contracts")
@JvmStatic @JvmStatic
@ -93,7 +93,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
// allow interruption half way through. // allow interruption half way through.
mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages) mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
ledger(MockServices(cordappPackages), initialiseSerialization = false) { ledger(MockServices(cordappPackages), initialiseSerialization = false) {
val notaryNode = mockNet.createNotaryNode() val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE_NAME) val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME) val bobNode = mockNet.createPartyNode(BOB_NAME)
val bankNode = mockNet.createPartyNode(BOC_NAME) val bankNode = mockNet.createPartyNode(BOC_NAME)
@ -143,7 +143,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
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 = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
ledger(MockServices(cordappPackages), initialiseSerialization = false) { ledger(MockServices(cordappPackages), initialiseSerialization = false) {
val notaryNode = mockNet.createNotaryNode() val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE_NAME) val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME) val bobNode = mockNet.createPartyNode(BOB_NAME)
val bankNode = mockNet.createPartyNode(BOC_NAME) val bankNode = mockNet.createPartyNode(BOC_NAME)
@ -199,7 +199,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
fun `shutdown and restore`() { fun `shutdown and restore`() {
mockNet = MockNetwork(cordappPackages = cordappPackages) mockNet = MockNetwork(cordappPackages = cordappPackages)
ledger(MockServices(cordappPackages), initialiseSerialization = false) { ledger(MockServices(cordappPackages), initialiseSerialization = false) {
val notaryNode = mockNet.createNotaryNode() val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE_NAME) val aliceNode = mockNet.createPartyNode(ALICE_NAME)
var bobNode = mockNet.createPartyNode(BOB_NAME) var bobNode = mockNet.createPartyNode(BOB_NAME)
val bankNode = mockNet.createPartyNode(BOC_NAME) val bankNode = mockNet.createPartyNode(BOC_NAME)
@ -292,7 +292,8 @@ class TwoPartyTradeFlowTests(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(name: CordaX500Name): StartedNode<MockNetwork.MockNode> { private fun makeNodeWithTracking(
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 : MockNetwork.MockNode(args) {
@ -307,7 +308,7 @@ class TwoPartyTradeFlowTests(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 = MockNetwork(cordappPackages = cordappPackages)
val notaryNode = mockNet.createNotaryNode() val notaryNode = mockNet.defaultNotaryNode
val aliceNode = makeNodeWithTracking(ALICE_NAME) val aliceNode = makeNodeWithTracking(ALICE_NAME)
val bobNode = makeNodeWithTracking(BOB_NAME) val bobNode = makeNodeWithTracking(BOB_NAME)
val bankNode = makeNodeWithTracking(BOC_NAME) val bankNode = makeNodeWithTracking(BOC_NAME)
@ -413,7 +414,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
@Test @Test
fun `track works`() { fun `track works`() {
mockNet = MockNetwork(cordappPackages = cordappPackages) mockNet = MockNetwork(cordappPackages = cordappPackages)
val notaryNode = mockNet.createNotaryNode() val notaryNode = mockNet.defaultNotaryNode
val aliceNode = makeNodeWithTracking(ALICE_NAME) val aliceNode = makeNodeWithTracking(ALICE_NAME)
val bobNode = makeNodeWithTracking(BOB_NAME) val bobNode = makeNodeWithTracking(BOB_NAME)
val bankNode = makeNodeWithTracking(BOC_NAME) val bankNode = makeNodeWithTracking(BOC_NAME)
@ -568,7 +569,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
aliceError: Boolean, aliceError: Boolean,
expectedMessageSubstring: String expectedMessageSubstring: String
) { ) {
val notaryNode = mockNet.createNotaryNode() val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE_NAME) val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME) val bobNode = mockNet.createPartyNode(BOB_NAME)
val bankNode = mockNet.createPartyNode(BOC_NAME) val bankNode = mockNet.createPartyNode(BOC_NAME)

View File

@ -1,7 +1,5 @@
package net.corda.node.services package net.corda.node.services
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.generateKeyPair import net.corda.core.crypto.generateKeyPair
import net.corda.core.flows.NotaryChangeFlow import net.corda.core.flows.NotaryChangeFlow
@ -15,14 +13,10 @@ 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.node.internal.StartedNode
import net.corda.node.services.config.NotaryConfig import net.corda.testing.*
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.getTestPartyAndCertificate
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNodeParameters import net.corda.testing.node.MockNetwork.NotarySpec
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
@ -42,23 +36,17 @@ class NotaryChangeTests {
@Before @Before
fun setUp() { fun setUp() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts")) val oldNotaryName = DUMMY_REGULATOR.name
val (oldNotaryNode, newNotaryNode) = listOf( mockNet = MockNetwork(
createUnstartedNotary(DUMMY_NOTARY.name), notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name), NotarySpec(oldNotaryName)),
createUnstartedNotary(DUMMY_NOTARY.name.copy(organisation = "Dummy Notary 2")) cordappPackages = listOf("net.corda.testing.contracts")
).map { it.start() } )
this.oldNotaryNode = oldNotaryNode
clientNodeA = mockNet.createNode() clientNodeA = mockNet.createNode()
clientNodeB = mockNet.createNode() clientNodeB = mockNet.createNode()
oldNotaryParty = newNotaryNode.services.networkMapCache.getNotary(DUMMY_NOTARY.name)!! oldNotaryNode = mockNet.notaryNodes[1]
newNotaryParty = newNotaryNode.services.networkMapCache.getNotary(DUMMY_NOTARY.name.copy(organisation = "Dummy Notary 2"))!! mockNet.runNetwork() // Clear network map registration messages
} newNotaryParty = clientNodeA.services.networkMapCache.getNotary(DUMMY_NOTARY.name)!!
oldNotaryParty = clientNodeA.services.networkMapCache.getNotary(oldNotaryName)!!
private fun createUnstartedNotary(name: CordaX500Name): MockNetwork.MockNode {
return mockNet.createUnstartedNode(MockNodeParameters(
legalName = name,
configOverrides = { doReturn(NotaryConfig(validating = true)).whenever(it).notary }
))
} }
@After @After

View File

@ -35,7 +35,6 @@ class ScheduledFlowTests {
} }
lateinit var mockNet: MockNetwork lateinit var mockNet: MockNetwork
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
lateinit var nodeA: StartedNode<MockNetwork.MockNode> lateinit var nodeA: StartedNode<MockNetwork.MockNode>
lateinit var nodeB: StartedNode<MockNetwork.MockNode> lateinit var nodeB: StartedNode<MockNetwork.MockNode>
@ -94,7 +93,6 @@ class ScheduledFlowTests {
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.testing.contracts")) mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.testing.contracts"))
notaryNode = mockNet.createNotaryNode()
val a = mockNet.createUnstartedNode() val a = mockNet.createUnstartedNode()
val b = mockNet.createUnstartedNode() val b = mockNet.createUnstartedNode()

View File

@ -38,13 +38,13 @@ class NetworkMapCacheTest {
@Test @Test
fun `getNodeByLegalIdentity`() { fun `getNodeByLegalIdentity`() {
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE.name) val aliceNode = mockNet.createPartyNode(ALICE.name)
val notaryCache: NetworkMapCache = notaryNode.services.networkMapCache val bobNode = mockNet.createPartyNode(BOB.name)
val bobCache: NetworkMapCache = bobNode.services.networkMapCache
val expected = aliceNode.info val expected = aliceNode.info
mockNet.runNetwork() mockNet.runNetwork()
val actual = notaryNode.database.transaction { notaryCache.getNodeByLegalIdentity(aliceNode.info.chooseIdentity()) } val actual = bobNode.database.transaction { bobCache.getNodeByLegalIdentity(aliceNode.info.chooseIdentity()) }
assertEquals(expected, actual) assertEquals(expected, actual)
// TODO: Should have a test case with anonymous lookup // TODO: Should have a test case with anonymous lookup
@ -52,30 +52,30 @@ class NetworkMapCacheTest {
@Test @Test
fun `getPeerByLegalName`() { fun `getPeerByLegalName`() {
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE.name) val aliceNode = mockNet.createPartyNode(ALICE.name)
val notaryCache: NetworkMapCache = notaryNode.services.networkMapCache val bobNode = mockNet.createPartyNode(BOB.name)
val bobCache: NetworkMapCache = bobNode.services.networkMapCache
val expected = aliceNode.info.legalIdentities.single() val expected = aliceNode.info.legalIdentities.single()
mockNet.runNetwork() mockNet.runNetwork()
val actual = notaryNode.database.transaction { notaryCache.getPeerByLegalName(ALICE.name) } val actual = bobNode.database.transaction { bobCache.getPeerByLegalName(ALICE.name) }
assertEquals(expected, actual) assertEquals(expected, actual)
} }
@Test @Test
fun `remove node from cache`() { fun `remove node from cache`() {
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE.name) val aliceNode = mockNet.createPartyNode(ALICE.name)
val notaryLegalIdentity = notaryNode.info.chooseIdentity() val bobNode = mockNet.createPartyNode(BOB.name)
val bobLegalIdentity = bobNode.info.chooseIdentity()
val alice = aliceNode.info.chooseIdentity() val alice = aliceNode.info.chooseIdentity()
val notaryCache = notaryNode.services.networkMapCache val bobCache = bobNode.services.networkMapCache
mockNet.runNetwork() mockNet.runNetwork()
notaryNode.database.transaction { bobNode.database.transaction {
assertThat(notaryCache.getNodeByLegalIdentity(alice) != null) assertThat(bobCache.getNodeByLegalIdentity(alice) != null)
notaryCache.removeNode(aliceNode.info) bobCache.removeNode(aliceNode.info)
assertThat(notaryCache.getNodeByLegalIdentity(alice) == null) assertThat(bobCache.getNodeByLegalIdentity(alice) == null)
assertThat(notaryCache.getNodeByLegalIdentity(notaryLegalIdentity) != null) assertThat(bobCache.getNodeByLegalIdentity(bobLegalIdentity) != null)
assertThat(notaryCache.getNodeByLegalName(alice.name) == null) assertThat(bobCache.getNodeByLegalName(alice.name) == null)
} }
} }
} }

View File

@ -43,9 +43,7 @@ class NodeSchemaServiceTest {
@Test @Test
fun `auto scanning of custom schemas for testing with Driver`() { fun `auto scanning of custom schemas for testing with Driver`() {
driver(startNodesInProcess = true) { driver(startNodesInProcess = true) {
val node = startNode() val result = defaultNotaryNode.getOrThrow().rpc.startFlow(::MappedSchemasFlow)
val nodeHandle = node.getOrThrow()
val result = nodeHandle.rpc.startFlow(::MappedSchemasFlow)
val mappedSchemas = result.returnValue.getOrThrow() val mappedSchemas = result.returnValue.getOrThrow()
assertTrue(mappedSchemas.contains(TestSchema.name)) assertTrue(mappedSchemas.contains(TestSchema.name))
} }
@ -54,11 +52,12 @@ class NodeSchemaServiceTest {
@Test @Test
fun `custom schemas are loaded eagerly`() { fun `custom schemas are loaded eagerly`() {
val expected = setOf("PARENTS", "CHILDREN") val expected = setOf("PARENTS", "CHILDREN")
assertEquals<Set<*>>(expected, driver { val tables = driver(startNodesInProcess = true) {
(startNode(startInSameProcess = true).getOrThrow() as NodeHandle.InProcess).node.database.transaction { (defaultNotaryNode.getOrThrow() as NodeHandle.InProcess).node.database.transaction {
session.createNativeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES").list() session.createNativeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES").list()
} }
}.toMutableSet().apply { retainAll(expected) }) }
assertEquals<Set<*>>(expected, tables.toMutableSet().apply { retainAll(expected) })
} }
@StartableByRPC @StartableByRPC

View File

@ -74,8 +74,8 @@ class FlowFrameworkTests {
fun start() { fun start() {
mockNet = MockNetwork( mockNet = MockNetwork(
servicePeerAllocationStrategy = RoundRobin(), servicePeerAllocationStrategy = RoundRobin(),
cordappPackages = listOf("net.corda.finance.contracts", "net.corda.testing.contracts")) cordappPackages = listOf("net.corda.finance.contracts", "net.corda.testing.contracts")
val notary = mockNet.createNotaryNode() )
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))
@ -84,7 +84,7 @@ class FlowFrameworkTests {
// Extract identities // Extract identities
alice = aliceNode.info.singleIdentity() alice = aliceNode.info.singleIdentity()
bob = bobNode.info.singleIdentity() bob = bobNode.info.singleIdentity()
notaryIdentity = notary.services.getDefaultNotary() notaryIdentity = aliceNode.services.getDefaultNotary()
} }
@After @After

View File

@ -14,10 +14,13 @@ import net.corda.core.transactions.TransactionBuilder
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.services.api.StartedNodeServices import net.corda.node.services.api.StartedNodeServices
import net.corda.testing.* import net.corda.testing.ALICE_NAME
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
import net.corda.testing.getDefaultNotary
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.singleIdentity
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
@ -28,20 +31,19 @@ import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
class NotaryServiceTests { class NotaryServiceTests {
lateinit var mockNet: MockNetwork private lateinit var mockNet: MockNetwork
lateinit var notaryServices: StartedNodeServices private lateinit var notaryServices: StartedNodeServices
lateinit var aliceServices: StartedNodeServices private lateinit var aliceServices: StartedNodeServices
lateinit var notary: Party private lateinit var notary: Party
lateinit var alice: Party private lateinit var alice: Party
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts")) mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
val notaryNode = mockNet.createNotaryNode(validating = false)
aliceServices = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME)).services aliceServices = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME)).services
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
notaryServices = notaryNode.services notaryServices = mockNet.defaultNotaryNode.services //TODO get rid of that
notary = notaryServices.getDefaultNotary() notary = aliceServices.getDefaultNotary()
alice = aliceServices.myInfo.singleIdentity() alice = aliceServices.myInfo.singleIdentity()
} }
@ -155,7 +157,7 @@ class NotaryServiceTests {
return future return future
} }
fun issueState(services: ServiceHub, identity: Party): StateAndRef<*> { private fun issueState(services: ServiceHub, identity: Party): StateAndRef<*> {
val tx = DummyContract.generateInitial(Random().nextInt(), notary, identity.ref(0)) val tx = DummyContract.generateInitial(Random().nextInt(), notary, identity.ref(0))
val signedByNode = services.signInitialTransaction(tx) val signedByNode = services.signInitialTransaction(tx)
val stx = notaryServices.addSignature(signedByNode, notary.owningKey) val stx = notaryServices.addSignature(signedByNode, notary.owningKey)

View File

@ -15,10 +15,13 @@ import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.node.services.api.StartedNodeServices import net.corda.node.services.api.StartedNodeServices
import net.corda.node.services.issueInvalidState import net.corda.node.services.issueInvalidState
import net.corda.testing.* import net.corda.testing.ALICE_NAME
import net.corda.testing.MEGA_CORP_KEY
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.dummyCommand
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.singleIdentity
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
@ -28,21 +31,20 @@ import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
class ValidatingNotaryServiceTests { class ValidatingNotaryServiceTests {
lateinit var mockNet: MockNetwork private lateinit var mockNet: MockNetwork
lateinit var notaryServices: StartedNodeServices private lateinit var notaryServices: StartedNodeServices
lateinit var aliceServices: StartedNodeServices private lateinit var aliceServices: StartedNodeServices
lateinit var notary: Party private lateinit var notary: Party
lateinit var alice: Party private lateinit var alice: Party
@Before @Before
fun setup() { fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts")) mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME)) val aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
mockNet.runNetwork() // Clear network map registration messages mockNet.runNetwork() // Clear network map registration messages
notaryServices = notaryNode.services notaryServices = mockNet.defaultNotaryNode.services
aliceServices = aliceNode.services aliceServices = aliceNode.services
notary = notaryServices.getDefaultNotary() notary = mockNet.defaultNotaryIdentity
alice = aliceNode.info.singleIdentity() alice = aliceNode.info.singleIdentity()
} }
@ -97,7 +99,7 @@ class ValidatingNotaryServiceTests {
return future return future
} }
fun issueState(serviceHub: ServiceHub, identity: Party): StateAndRef<*> { private fun issueState(serviceHub: ServiceHub, identity: Party): StateAndRef<*> {
val tx = DummyContract.generateInitial(Random().nextInt(), notary, identity.ref(0)) val tx = DummyContract.generateInitial(Random().nextInt(), notary, identity.ref(0))
val signedByNode = serviceHub.signInitialTransaction(tx) val signedByNode = serviceHub.signInitialTransaction(tx)
val stx = notaryServices.addSignature(signedByNode, notary.owningKey) val stx = notaryServices.addSignature(signedByNode, notary.owningKey)

View File

@ -7,7 +7,6 @@ import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
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 org.junit.Test import org.junit.Test
@ -27,11 +26,10 @@ class AttachmentDemoTest {
invokeRpc(CordaRPCOps::wellKnownPartyFromX500Name), invokeRpc(CordaRPCOps::wellKnownPartyFromX500Name),
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed) invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed)
))) )))
val (_, nodeA, nodeB) = listOf( val (nodeA, nodeB) = listOf(
startNotaryNode(DUMMY_NOTARY.name, validating = false),
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() startWebserver(nodeB).getOrThrow()
val senderThread = supplyAsync { val senderThread = supplyAsync {

View File

@ -4,7 +4,6 @@ import net.corda.core.internal.div
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
/** /**
@ -14,7 +13,6 @@ import net.corda.testing.driver.driver
fun main(args: Array<String>) { fun main(args: Array<String>) {
val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.flows.FinalityFlow"))) val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.flows.FinalityFlow")))
driver(isDebug = true, driverDirectory = "build" / "attachment-demo-nodes") { driver(isDebug = true, driverDirectory = "build" / "attachment-demo-nodes") {
startNotaryNode(DUMMY_NOTARY.name, validating = false)
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser) startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser)
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser) startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser)
waitForAllNodesToFinish() waitForAllNodesToFinish()

View File

@ -2,10 +2,8 @@ package net.corda.bank
import net.corda.bank.api.BankOfCordaClientApi import net.corda.bank.api.BankOfCordaClientApi
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
import net.corda.core.internal.concurrent.transpose
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.testing.BOC import net.corda.testing.BOC
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import org.junit.Test import org.junit.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -13,14 +11,13 @@ import kotlin.test.assertTrue
class BankOfCordaHttpAPITest { class BankOfCordaHttpAPITest {
@Test @Test
fun `issuer flow via Http`() { fun `issuer flow via Http`() {
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.finance")) { driver(extraCordappPackagesToScan = listOf("net.corda.finance"), isDebug = true) {
val (_, bocNode) = listOf( val (bocNode) = listOf(
startNotaryNode(providedName = DUMMY_NOTARY.name),
startNode(providedName = BOC.name), startNode(providedName = BOC.name),
startNode(providedName = BIGCORP_LEGAL_NAME) startNode(providedName = BIGCORP_LEGAL_NAME)
).transpose().getOrThrow() ).map { it.getOrThrow() }
val bocApiAddress = startWebserver(bocNode).getOrThrow().listenAddress val bocApiAddress = startWebserver(bocNode).getOrThrow().listenAddress
val issueRequestParams = IssueRequestParams(1000, "USD", BIGCORP_LEGAL_NAME, "1", BOC.name, DUMMY_NOTARY.name) val issueRequestParams = IssueRequestParams(1000, "USD", BIGCORP_LEGAL_NAME, "1", BOC.name, defaultNotaryIdentity.name)
assertTrue(BankOfCordaClientApi(bocApiAddress).requestWebIssue(issueRequestParams)) assertTrue(BankOfCordaClientApi(bocApiAddress).requestWebIssue(issueRequestParams))
} }
} }

View File

@ -23,12 +23,12 @@ class BankOfCordaRPCClientTest {
invokeRpc(CordaRPCOps::wellKnownPartyFromX500Name), invokeRpc(CordaRPCOps::wellKnownPartyFromX500Name),
invokeRpc(CordaRPCOps::notaryIdentities) invokeRpc(CordaRPCOps::notaryIdentities)
) )
driver(extraCordappPackagesToScan = listOf("net.corda.finance"), dsl = { driver(extraCordappPackagesToScan = listOf("net.corda.finance"), isDebug = true) {
val bocManager = User("bocManager", "password1", permissions = setOf( val bocManager = User("bocManager", "password1", permissions = setOf(
startFlow<CashIssueAndPaymentFlow>()) + commonPermissions) startFlow<CashIssueAndPaymentFlow>()) + commonPermissions)
val bigCorpCFO = User("bigCorpCFO", "password2", permissions = emptySet<String>() + commonPermissions) val bigCorpCFO = User("bigCorpCFO", "password2", permissions = emptySet<String>() + commonPermissions)
val (nodeBankOfCorda, nodeBigCorporation) = listOf( val (nodeBankOfCorda, nodeBigCorporation) = listOf(
startNotaryNode(BOC.name, rpcUsers = listOf(bocManager), validating = false), startNode(providedName = BOC.name, rpcUsers = listOf(bocManager)),
startNode(providedName = BIGCORP_LEGAL_NAME, rpcUsers = listOf(bigCorpCFO)) startNode(providedName = BIGCORP_LEGAL_NAME, rpcUsers = listOf(bigCorpCFO))
).map { it.getOrThrow() } ).map { it.getOrThrow() }
@ -51,12 +51,11 @@ class BankOfCordaRPCClientTest {
// Kick-off actual Issuer Flow // Kick-off actual Issuer Flow
val anonymous = true val anonymous = true
val notary = bocProxy.notaryIdentities().first()
bocProxy.startFlow(::CashIssueAndPaymentFlow, bocProxy.startFlow(::CashIssueAndPaymentFlow,
1000.DOLLARS, BIG_CORP_PARTY_REF, 1000.DOLLARS, BIG_CORP_PARTY_REF,
bigCorporation, bigCorporation,
anonymous, anonymous,
notary).returnValue.getOrThrow() defaultNotaryIdentity).returnValue.getOrThrow()
// Check Bank of Corda Vault Updates // Check Bank of Corda Vault Updates
vaultUpdatesBoc.expectEvents { vaultUpdatesBoc.expectEvents {
@ -84,6 +83,6 @@ class BankOfCordaRPCClientTest {
} }
) )
} }
}, isDebug = true) }
} }
} }

View File

@ -10,7 +10,6 @@ import net.corda.finance.flows.CashExitFlow
import net.corda.finance.flows.CashIssueAndPaymentFlow import net.corda.finance.flows.CashIssueAndPaymentFlow
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.node.services.transactions.ValidatingNotaryService
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.BOC import net.corda.testing.BOC
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
@ -58,7 +57,6 @@ private class BankOfCordaDriver {
when (role) { when (role) {
Role.ISSUER -> { Role.ISSUER -> {
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.finance.contracts.asset")) { driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.finance.contracts.asset")) {
startNotaryNode(providedName = DUMMY_NOTARY.name, validating = true)
val bankUser = User( val bankUser = User(
BANK_USERNAME, BANK_USERNAME,
"test", "test",
@ -83,7 +81,7 @@ private class BankOfCordaDriver {
} }
else -> { else -> {
val requestParams = IssueRequestParams(options.valueOf(quantity), options.valueOf(currency), BIGCORP_LEGAL_NAME, val requestParams = IssueRequestParams(options.valueOf(quantity), options.valueOf(currency), BIGCORP_LEGAL_NAME,
"1", BOC.name, DUMMY_NOTARY.name.copy(commonName = ValidatingNotaryService.id)) "1", BOC.name, DUMMY_NOTARY.name)
when(role) { when(role) {
Role.ISSUE_CASH_RPC -> { Role.ISSUE_CASH_RPC -> {
println("Requesting Cash via RPC ...") println("Requesting Cash via RPC ...")

View File

@ -3,7 +3,6 @@ package net.corda.irs
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
/** /**
@ -11,17 +10,17 @@ import net.corda.testing.driver.driver
* Do not use in a production environment. * Do not use in a production environment.
*/ */
fun main(args: Array<String>) { fun main(args: Array<String>) {
driver(dsl = { driver(useTestClock = true, isDebug = true) {
val (controller, nodeA, nodeB) = listOf( val (nodeA, nodeB) = listOf(
startNotaryNode(DUMMY_NOTARY.name, validating = false),
startNode(providedName = DUMMY_BANK_A.name), startNode(providedName = DUMMY_BANK_A.name),
startNode(providedName = DUMMY_BANK_B.name)) startNode(providedName = DUMMY_BANK_B.name)
.map { it.getOrThrow() } ).map { it.getOrThrow() }
val controller = defaultNotaryNode.getOrThrow()
startWebserver(controller) startWebserver(controller)
startWebserver(nodeA) startWebserver(nodeA)
startWebserver(nodeB) startWebserver(nodeB)
waitForAllNodesToFinish() waitForAllNodesToFinish()
}, useTestClock = true, isDebug = true) }
} }

View File

@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import net.corda.client.jackson.JacksonSupport
import net.corda.client.rpc.CordaRPCClient import net.corda.client.rpc.CordaRPCClient
import net.corda.core.contracts.UniqueIdentifier import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.identity.Party import net.corda.core.identity.Party
@ -24,6 +25,7 @@ import net.corda.nodeapi.User
import net.corda.test.spring.springDriver import net.corda.test.spring.springDriver
import net.corda.testing.* import net.corda.testing.*
import net.corda.testing.http.HttpApi import net.corda.testing.http.HttpApi
import net.corda.testing.node.NotarySpec
import org.apache.commons.io.IOUtils import org.apache.commons.io.IOUtils
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.Test import org.junit.Test
@ -44,11 +46,17 @@ class IRSDemoTest : IntegrationTestCategory {
@Test @Test
fun `runs IRS demo`() { fun `runs IRS demo`() {
springDriver(useTestClock = true, isDebug = true, extraCordappPackagesToScan = listOf("net.corda.irs")) { springDriver(
val (controller, nodeA, nodeB) = listOf( useTestClock = true,
startNotaryNode(DUMMY_NOTARY.name, validating = true, rpcUsers = rpcUsers), notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, rpcUsers = rpcUsers)),
isDebug = true,
extraCordappPackagesToScan = listOf("net.corda.irs")
) {
val (nodeA, nodeB) = listOf(
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = rpcUsers), startNode(providedName = DUMMY_BANK_A.name, rpcUsers = rpcUsers),
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = rpcUsers)).map { it.getOrThrow() } startNode(providedName = DUMMY_BANK_B.name, rpcUsers = rpcUsers)
).map { it.getOrThrow() }
val controller = defaultNotaryNode.getOrThrow()
log.info("All nodes started") log.info("All nodes started")
@ -61,7 +69,7 @@ class IRSDemoTest : IntegrationTestCategory {
log.info("All webservers started") log.info("All webservers started")
val (controllerApi, nodeAApi, nodeBApi) = listOf(controller, nodeA, nodeB).zip(listOf(controllerAddr, nodeAAddr, nodeBAddr)).map { val (controllerApi, nodeAApi, nodeBApi) = listOf(controller, nodeA, nodeB).zip(listOf(controllerAddr, nodeAAddr, nodeBAddr)).map {
val mapper = net.corda.client.jackson.JacksonSupport.createDefaultMapper(it.first.rpc) val mapper = JacksonSupport.createDefaultMapper(it.first.rpc)
registerFinanceJSONMappers(mapper) registerFinanceJSONMappers(mapper)
registerIRSModule(mapper) registerIRSModule(mapper)
HttpApi.fromHostAndPort(it.second, "api/irs", mapper = mapper) HttpApi.fromHostAndPort(it.second, "api/irs", mapper = mapper)
@ -86,7 +94,9 @@ class IRSDemoTest : IntegrationTestCategory {
} }
} }
fun getFloatingLegFixCount(nodeApi: HttpApi) = getTrades(nodeApi)[0].calculation.floatingLegPaymentSchedule.count { it.value.rate.ratioUnit != null } private fun getFloatingLegFixCount(nodeApi: HttpApi): Int {
return getTrades(nodeApi)[0].calculation.floatingLegPaymentSchedule.count { it.value.rate.ratioUnit != null }
}
private fun getFixingDateObservable(config: NodeConfiguration): Observable<LocalDate?> { private fun getFixingDateObservable(config: NodeConfiguration): Observable<LocalDate?> {
val client = CordaRPCClient(config.rpcAddress!!) val client = CordaRPCClient(config.rpcAddress!!)

View File

@ -6,6 +6,7 @@ import net.corda.core.internal.concurrent.fork
import net.corda.core.internal.concurrent.map import net.corda.core.internal.concurrent.map
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.testing.driver.* import net.corda.testing.driver.*
import net.corda.testing.node.NotarySpec
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import java.net.ConnectException import java.net.ConnectException
@ -41,6 +42,7 @@ fun <A> springDriver(
useTestClock: Boolean = defaultParameters.useTestClock, useTestClock: Boolean = defaultParameters.useTestClock,
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization, initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess, startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
notarySpecs: List<NotarySpec>,
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan, extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
dsl: SpringDriverExposedDSLInterface.() -> A dsl: SpringDriverExposedDSLInterface.() -> A
) = genericDriver( ) = genericDriver(
@ -54,9 +56,9 @@ fun <A> springDriver(
initialiseSerialization = initialiseSerialization, initialiseSerialization = initialiseSerialization,
startNodesInProcess = startNodesInProcess, startNodesInProcess = startNodesInProcess,
extraCordappPackagesToScan = extraCordappPackagesToScan, extraCordappPackagesToScan = extraCordappPackagesToScan,
notarySpecs = notarySpecs,
driverDslWrapper = { driverDSL:DriverDSL -> SpringBootDriverDSL(driverDSL) }, driverDslWrapper = { driverDSL:DriverDSL -> SpringBootDriverDSL(driverDSL) },
coerce = { it }, coerce = { it }, dsl = dsl
dsl = dsl
) )
data class SpringBootDriverDSL( data class SpringBootDriverDSL(

View File

@ -31,7 +31,6 @@ import java.util.*
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletableFuture.allOf import java.util.concurrent.CompletableFuture.allOf
/** /**
* A simulation in which banks execute interest rate swaps with each other, including the fixing events. * A simulation in which banks execute interest rate swaps with each other, including the fixing events.
*/ */
@ -140,8 +139,6 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
node1.internals.registerInitiatedFlow(FixingFlow.Fixer::class.java) node1.internals.registerInitiatedFlow(FixingFlow.Fixer::class.java)
node2.internals.registerInitiatedFlow(FixingFlow.Fixer::class.java) node2.internals.registerInitiatedFlow(FixingFlow.Fixer::class.java)
val notaryId = notary.info.legalIdentities[0]
@InitiatingFlow @InitiatingFlow
class StartDealFlow(val otherParty: Party, class StartDealFlow(val otherParty: Party,
val payload: AutoOffer) : FlowLogic<SignedTransaction>() { val payload: AutoOffer) : FlowLogic<SignedTransaction>() {
@ -166,7 +163,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
val instigator = StartDealFlow( val instigator = StartDealFlow(
node2.info.chooseIdentity(), node2.info.chooseIdentity(),
AutoOffer(notaryId, irs)) // TODO Pass notary as parameter to Simulation. AutoOffer(mockNet.defaultNotaryIdentity, irs)) // TODO Pass notary as parameter to Simulation.
val instigatorTxFuture = node1.services.startFlow(instigator).resultFuture val instigatorTxFuture = node1.services.startFlow(instigator).resultFuture
return allOf(instigatorTxFuture.toCompletableFuture(), acceptorTxFuture).thenCompose { instigatorTxFuture.toCompletableFuture() } return allOf(instigatorTxFuture.toCompletableFuture(), acceptorTxFuture).thenCompose { instigatorTxFuture.toCompletableFuture() }

View File

@ -9,7 +9,6 @@ import net.corda.finance.utils.CityDatabase
import net.corda.irs.api.NodeInterestRates 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.DUMMY_NOTARY
import net.corda.testing.DUMMY_REGULATOR import net.corda.testing.DUMMY_REGULATOR
import net.corda.testing.node.* import net.corda.testing.node.*
import net.corda.testing.node.MockNetwork.MockNode import net.corda.testing.node.MockNetwork.MockNode
@ -71,14 +70,13 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
networkSendManuallyPumped = networkSendManuallyPumped, networkSendManuallyPumped = networkSendManuallyPumped,
threadPerNode = runAsync, threadPerNode = runAsync,
cordappPackages = listOf("net.corda.irs.contract", "net.corda.finance.contract", "net.corda.irs")) cordappPackages = listOf("net.corda.irs.contract", "net.corda.finance.contract", "net.corda.irs"))
val notary = mockNet.createNotaryNode(defaultParams.copy(legalName = DUMMY_NOTARY.name), false)
// TODO: Regulatory nodes don't actually exist properly, this is a last minute demo request. // TODO: Regulatory nodes don't actually exist properly, this is a last minute demo request.
// So we just fire a message at a node that doesn't know how to handle it, and it'll ignore it. // So we just fire a message at a node that doesn't know how to handle it, and it'll ignore it.
// But that's fine for visualisation purposes. // But that's fine for visualisation purposes.
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(notary.internals, ratesOracle) val serviceProviders: List<MockNode> = listOf(mockNet.defaultNotaryNode.internals, ratesOracle)
val banks: List<MockNode> = bankLocations.mapIndexed { i, (city, country) -> val banks: List<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.

View File

@ -3,7 +3,9 @@ package net.corda.vega
import com.opengamma.strata.product.common.BuySell import com.opengamma.strata.product.common.BuySell
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.testing.* import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.IntegrationTestCategory
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.http.HttpApi import net.corda.testing.http.HttpApi
import net.corda.vega.api.PortfolioApi import net.corda.vega.api.PortfolioApi
@ -27,7 +29,6 @@ class SimmValuationTest : IntegrationTestCategory {
@Test @Test
fun `runs SIMM valuation demo`() { fun `runs SIMM valuation demo`() {
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.vega.contracts")) { driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.vega.contracts")) {
startNotaryNode(DUMMY_NOTARY.name, validating = false).getOrThrow()
val nodeAFuture = startNode(providedName = nodeALegalName) val nodeAFuture = startNode(providedName = nodeALegalName)
val nodeBFuture = startNode(providedName = nodeBLegalName) val nodeBFuture = startNode(providedName = nodeBLegalName)
val (nodeA, nodeB) = listOf(nodeAFuture, nodeBFuture).map { it.getOrThrow() } val (nodeA, nodeB) = listOf(nodeAFuture, nodeBFuture).map { it.getOrThrow() }

View File

@ -4,7 +4,6 @@ import net.corda.core.utilities.getOrThrow
import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_BANK_C import net.corda.testing.DUMMY_BANK_C
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
/** /**
@ -13,17 +12,17 @@ import net.corda.testing.driver.driver
* via the web api. * via the web api.
*/ */
fun main(args: Array<String>) { fun main(args: Array<String>) {
driver(dsl = { driver(isDebug = true) {
val notaryFuture = startNotaryNode(DUMMY_NOTARY.name, validating = false) val (nodeA, nodeB, nodeC) = listOf(
val nodeAFuture = startNode(providedName = DUMMY_BANK_A.name) startNode(providedName = DUMMY_BANK_A.name),
val nodeBFuture = startNode(providedName = DUMMY_BANK_B.name) startNode(providedName = DUMMY_BANK_B.name),
val nodeCFuture = startNode(providedName = DUMMY_BANK_C.name) startNode(providedName = DUMMY_BANK_C.name)
val (nodeA, nodeB, nodeC) = listOf(nodeAFuture, nodeBFuture, nodeCFuture, notaryFuture).map { it.getOrThrow() } ).map { it.getOrThrow() }
startWebserver(nodeA) startWebserver(nodeA)
startWebserver(nodeB) startWebserver(nodeB)
startWebserver(nodeC) startWebserver(nodeC)
waitForAllNodesToFinish() waitForAllNodesToFinish()
}, isDebug = true) }
} }

View File

@ -9,7 +9,10 @@ import net.corda.finance.flows.CashPaymentFlow
import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.Permissions.Companion.all
import net.corda.node.services.Permissions.Companion.startFlow import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.* import net.corda.testing.BOC
import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.driver.poll import net.corda.testing.driver.poll
@ -30,8 +33,7 @@ class TraderDemoTest {
startFlow<CommercialPaperIssueFlow>(), startFlow<CommercialPaperIssueFlow>(),
all())) all()))
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance")) { driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance")) {
val (_, nodeA, nodeB, bankNode) = listOf( val (nodeA, nodeB, bankNode) = listOf(
startNotaryNode(DUMMY_NOTARY.name, validating = false),
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))

View File

@ -8,7 +8,6 @@ import net.corda.nodeapi.User
import net.corda.testing.BOC import net.corda.testing.BOC
import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.traderdemo.flow.CommercialPaperIssueFlow import net.corda.traderdemo.flow.CommercialPaperIssueFlow
import net.corda.traderdemo.flow.SellerFlow import net.corda.traderdemo.flow.SellerFlow
@ -27,7 +26,6 @@ fun main(args: Array<String>) {
val user = User("user1", "test", permissions = setOf(startFlow<CashIssueFlow>(), val user = User("user1", "test", permissions = setOf(startFlow<CashIssueFlow>(),
startFlow<CommercialPaperIssueFlow>(), startFlow<CommercialPaperIssueFlow>(),
startFlow<SellerFlow>())) startFlow<SellerFlow>()))
startNotaryNode(DUMMY_NOTARY.name, validating = false)
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser) startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser)
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser) startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser)
startNode(providedName = BOC.name, rpcUsers = listOf(user)) startNode(providedName = BOC.name, rpcUsers = listOf(user))

View File

@ -290,7 +290,6 @@ class FlowStackSnapshotTest {
@Test @Test
fun `flowStackSnapshot object is serializable`() { fun `flowStackSnapshot object is serializable`() {
val mockNet = MockNetwork(threadPerNode = true) val mockNet = MockNetwork(threadPerNode = true)
mockNet.createNotaryNode()
val node = mockNet.createPartyNode() val node = mockNet.createPartyNode()
node.internals.registerInitiatedFlow(DummyFlow::class.java) node.internals.registerInitiatedFlow(DummyFlow::class.java)
node.services.startFlow(FlowStackSnapshotSerializationTestingFlow()).resultFuture.get() node.services.startFlow(FlowStackSnapshotSerializationTestingFlow()).resultFuture.get()

View File

@ -7,7 +7,6 @@ import net.corda.core.internal.readLines
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.NodeStartup import net.corda.node.internal.NodeStartup
import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_REGULATOR import net.corda.testing.DUMMY_REGULATOR
import net.corda.testing.ProjectStructure.projectRootDir import net.corda.testing.ProjectStructure.projectRootDir
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
@ -18,7 +17,6 @@ import java.util.concurrent.ScheduledExecutorService
class DriverTests { class DriverTests {
companion object { companion object {
private val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2) private val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
private fun nodeMustBeUp(handleFuture: CordaFuture<out NodeHandle>) = handleFuture.getOrThrow().apply { private fun nodeMustBeUp(handleFuture: CordaFuture<out NodeHandle>) = handleFuture.getOrThrow().apply {
@ -32,26 +30,15 @@ class DriverTests {
// Check that the port is bound // Check that the port is bound
addressMustNotBeBound(executorService, hostAndPort) addressMustNotBeBound(executorService, hostAndPort)
} }
} }
@Test @Test
fun `simple node startup and shutdown`() { fun `simple node startup and shutdown`() {
val handles = driver { val handle = driver {
val notary = startNotaryNode(DUMMY_NOTARY.name, validating = false)
val regulator = startNode(providedName = DUMMY_REGULATOR.name) val regulator = startNode(providedName = DUMMY_REGULATOR.name)
listOf(nodeMustBeUp(notary), nodeMustBeUp(regulator)) nodeMustBeUp(regulator)
} }
handles.map { nodeMustBeDown(it) } nodeMustBeDown(handle)
}
@Test
fun `starting node with no services`() {
val noService = driver {
val noService = startNode(providedName = DUMMY_BANK_A.name)
nodeMustBeUp(noService)
}
nodeMustBeDown(noService)
} }
@Test @Test

View File

@ -15,17 +15,11 @@ import net.corda.testing.driver.DriverDSLExposedInterface
/** /**
* A simple wrapper for objects provided by the integration test driver DSL. The fields are lazy so * A simple wrapper for objects provided by the integration test driver DSL. The fields are lazy so
* node construction won't start until you access the members. You can get one of these from the * node construction won't start until you access the members. You can get one of these from the
* [alice], [bob] and [notaryAliceAndBob] functions. * [alice], [bob] and [aliceAndBob] functions.
*/ */
class PredefinedTestNode internal constructor(party: Party, driver: DriverDSLExposedInterface, ifNotaryIsValidating: Boolean?) { class PredefinedTestNode internal constructor(party: Party, driver: DriverDSLExposedInterface) {
val rpcUsers = listOf(User("admin", "admin", setOf("ALL"))) // TODO: Randomize? val rpcUsers = listOf(User("admin", "admin", setOf("ALL"))) // TODO: Randomize?
val nodeFuture by lazy { val nodeFuture by lazy { driver.startNode(providedName = party.name, rpcUsers = rpcUsers) }
if (ifNotaryIsValidating != null) {
driver.startNotaryNode(providedName = party.name, rpcUsers = rpcUsers, validating = ifNotaryIsValidating)
} else {
driver.startNode(providedName = party.name, rpcUsers = rpcUsers)
}
}
val node by lazy { nodeFuture.get()!! } val node by lazy { nodeFuture.get()!! }
val rpc by lazy { node.rpcClientToNode() } val rpc by lazy { node.rpcClientToNode() }
@ -38,28 +32,21 @@ class PredefinedTestNode internal constructor(party: Party, driver: DriverDSLExp
* Returns a plain, entirely stock node pre-configured with the [ALICE] identity. Note that a random key will be generated * Returns a plain, entirely stock node pre-configured with the [ALICE] identity. Note that a random key will be generated
* for it: you won't have [ALICE_KEY]. * for it: you won't have [ALICE_KEY].
*/ */
fun DriverDSLExposedInterface.alice(): PredefinedTestNode = PredefinedTestNode(ALICE, this, null) fun DriverDSLExposedInterface.alice(): PredefinedTestNode = PredefinedTestNode(ALICE, this)
/** /**
* Returns a plain, entirely stock node pre-configured with the [BOB] identity. Note that a random key will be generated * Returns a plain, entirely stock node pre-configured with the [BOB] identity. Note that a random key will be generated
* for it: you won't have [BOB_KEY]. * for it: you won't have [BOB_KEY].
*/ */
fun DriverDSLExposedInterface.bob(): PredefinedTestNode = PredefinedTestNode(BOB, this, null) fun DriverDSLExposedInterface.bob(): PredefinedTestNode = PredefinedTestNode(BOB, this)
/** /**
* Returns a plain single node notary pre-configured with the [DUMMY_NOTARY] identity. Note that a random key will be generated * Returns plain, entirely stock nodes pre-configured with the [ALICE] and [BOB] X.500 names in that order. They have been
* for it: you won't have [DUMMY_NOTARY_KEY]. * started up in parallel and are now ready to use.
*/ */
fun DriverDSLExposedInterface.notary(): PredefinedTestNode = PredefinedTestNode(DUMMY_NOTARY, this, true) fun DriverDSLExposedInterface.aliceAndBob(): List<PredefinedTestNode> {
/**
* Returns plain, entirely stock nodes pre-configured with the [ALICE], [BOB] and [DUMMY_NOTARY] X.500 names in that
* order. They have been started up in parallel and are now ready to use.
*/
fun DriverDSLExposedInterface.notaryAliceAndBob(): List<PredefinedTestNode> {
val notary = notary()
val alice = alice() val alice = alice()
val bob = bob() val bob = bob()
listOf(notary.nodeFuture, alice.nodeFuture, bob.nodeFuture).transpose().get() listOf(alice.nodeFuture, bob.nodeFuture).transpose().get()
return listOf(alice, bob, notary) return listOf(alice, bob)
} }

View File

@ -23,6 +23,7 @@ import net.corda.nodeapi.RPCApi
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT
import net.corda.testing.driver.* import net.corda.testing.driver.*
import net.corda.testing.node.NotarySpec
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
import org.apache.activemq.artemis.api.core.TransportConfiguration import org.apache.activemq.artemis.api.core.TransportConfiguration
import org.apache.activemq.artemis.api.core.client.ActiveMQClient import org.apache.activemq.artemis.api.core.client.ActiveMQClient
@ -230,6 +231,7 @@ fun <A> rpcDriver(
initialiseSerialization: Boolean = true, initialiseSerialization: Boolean = true,
startNodesInProcess: Boolean = false, startNodesInProcess: Boolean = false,
extraCordappPackagesToScan: List<String> = emptyList(), extraCordappPackagesToScan: List<String> = emptyList(),
notarySpecs: List<NotarySpec> = emptyList(),
dsl: RPCDriverExposedDSLInterface.() -> A dsl: RPCDriverExposedDSLInterface.() -> A
) = genericDriver( ) = genericDriver(
driverDsl = RPCDriverDSL( driverDsl = RPCDriverDSL(
@ -241,7 +243,8 @@ fun <A> rpcDriver(
useTestClock = useTestClock, useTestClock = useTestClock,
isDebug = isDebug, isDebug = isDebug,
startNodesInProcess = startNodesInProcess, startNodesInProcess = startNodesInProcess,
extraCordappPackagesToScan = extraCordappPackagesToScan extraCordappPackagesToScan = extraCordappPackagesToScan,
notarySpecs = notarySpecs
) )
), ),
coerce = { it }, coerce = { it },

View File

@ -16,6 +16,7 @@ import net.corda.core.identity.Party
import net.corda.core.internal.* import net.corda.core.internal.*
import net.corda.core.internal.concurrent.* import net.corda.core.internal.concurrent.*
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.NetworkParameters
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.NotaryInfo import net.corda.core.node.NotaryInfo
import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.NetworkMapCache
@ -33,13 +34,12 @@ import net.corda.nodeapi.NodeInfoFilesCopier
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.nodeapi.config.toConfig import net.corda.nodeapi.config.toConfig
import net.corda.nodeapi.internal.addShutdownHook import net.corda.nodeapi.internal.addShutdownHook
import net.corda.testing.ALICE import net.corda.testing.*
import net.corda.testing.BOB
import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.common.internal.NetworkParametersCopier import net.corda.testing.common.internal.NetworkParametersCopier
import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.initialiseTestSerialization 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 okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.slf4j.Logger import org.slf4j.Logger
@ -84,10 +84,48 @@ private val DRIVER_REQUIRED_PERMISSIONS = setOf(
invokeRpc(CordaRPCOps::networkMapSnapshot) invokeRpc(CordaRPCOps::networkMapSnapshot)
) )
/**
* Object ecapsulating a notary started automatically by the driver.
*/
data class NotaryHandle(val identity: Party, val validating: Boolean, val nodeHandles: CordaFuture<List<NodeHandle>>)
/** /**
* This is the interface that's exposed to DSL users. * This is the interface that's exposed to DSL users.
*/ */
interface DriverDSLExposedInterface : CordformContext { interface DriverDSLExposedInterface : CordformContext {
/** Returns a list of [NotaryHandle]s matching the list of [NotarySpec]s passed into [driver]. */
val notaryHandles: List<NotaryHandle>
/**
* Returns the [NotaryHandle] for the single notary on the network. Throws if there are none or more than one.
* @see notaryHandles
*/
val defaultNotaryHandle: NotaryHandle get() {
return when (notaryHandles.size) {
0 -> throw IllegalStateException("There are no notaries defined on the network")
1 -> notaryHandles[0]
else -> throw IllegalStateException("There is more than one notary defined on the network")
}
}
/**
* Returns the identity of the single notary on the network. Throws if there are none or more than one.
* @see defaultNotaryHandle
*/
val defaultNotaryIdentity: Party get() = defaultNotaryHandle.identity
/**
* Returns a [CordaFuture] on the [NodeHandle] for the single-node notary on the network. Throws if there
* are no notaries or more than one, or if the notary is a distributed cluster.
* @see defaultNotaryHandle
* @see notaryHandles
*/
val defaultNotaryNode: CordaFuture<NodeHandle> get() {
return defaultNotaryHandle.nodeHandles.map {
it.singleOrNull() ?: throw IllegalStateException("Default notary is not a single node")
}
}
/** /**
* Start a node. * Start a node.
* *
@ -110,13 +148,6 @@ interface DriverDSLExposedInterface : CordformContext {
startInSameProcess: Boolean? = defaultParameters.startInSameProcess, startInSameProcess: Boolean? = defaultParameters.startInSameProcess,
maximumHeapSize: String = defaultParameters.maximumHeapSize): CordaFuture<NodeHandle> maximumHeapSize: String = defaultParameters.maximumHeapSize): CordaFuture<NodeHandle>
// TODO This method has been added temporarily, to be deleted once the set of notaries is defined at the network level.
fun startNotaryNode(providedName: CordaX500Name,
rpcUsers: List<User> = emptyList(),
verifierType: VerifierType = VerifierType.InMemory,
customOverrides: Map<String, Any?> = emptyMap(),
validating: Boolean = true): CordaFuture<NodeHandle>
/** /**
* Helper function for starting a [Node] with custom parameters from Java. * Helper function for starting a [Node] with custom parameters from Java.
* *
@ -131,24 +162,6 @@ interface DriverDSLExposedInterface : CordformContext {
maximumHeapSize: String = "200m" maximumHeapSize: String = "200m"
): List<CordaFuture<NodeHandle>> ): List<CordaFuture<NodeHandle>>
/**
* Starts a distributed notary cluster.
*
* @param notaryName The legal name of the advertised distributed notary service.
* @param clusterSize Number of nodes to create for the cluster.
* @param verifierType The type of transaction verifier to use. See: [VerifierType]
* @param rpcUsers List of users who are authorised to use the RPC system. Defaults to empty list.
* @param startInSameProcess Determines if the node should be started inside the same process the Driver is running
* in. If null the Driver-level value will be used.
* @return The [Party] identity of the distributed notary service, and the [NodeInfo]s of the notaries in the cluster.
*/
fun startNotaryCluster(
notaryName: CordaX500Name,
clusterSize: Int = 3,
verifierType: VerifierType = VerifierType.InMemory,
rpcUsers: List<User> = emptyList(),
startInSameProcess: Boolean? = null): CordaFuture<Pair<Party, List<NodeHandle>>>
/** Call [startWebserver] with a default maximumHeapSize. */ /** Call [startWebserver] with a default maximumHeapSize. */
fun startWebserver(handle: NodeHandle): CordaFuture<WebserverHandle> = startWebserver(handle, "200m") fun startWebserver(handle: NodeHandle): CordaFuture<WebserverHandle> = startWebserver(handle, "200m")
@ -310,6 +323,8 @@ data class NodeParameters(
* @param useTestClock If true the test clock will be used in Node. * @param useTestClock If true the test clock will be used in Node.
* @param startNodesInProcess Provides the default behaviour of whether new nodes should start inside this process or * @param startNodesInProcess Provides the default behaviour of whether new nodes should start inside this process or
* not. Note that this may be overridden in [DriverDSLExposedInterface.startNode]. * not. Note that this may be overridden in [DriverDSLExposedInterface.startNode].
* @param notarySpecs The notaries advertised in the [NetworkParameters] for this network. These nodes will be started
* automatically and will be available from [DriverDSLExposedInterface.notaryHandles]. Defaults to a simple validating notary.
* @param dsl The dsl itself. * @param dsl The dsl itself.
* @return The value returned in the [dsl] closure. * @return The value returned in the [dsl] closure.
*/ */
@ -323,6 +338,7 @@ fun <A> driver(
useTestClock: Boolean = defaultParameters.useTestClock, useTestClock: Boolean = defaultParameters.useTestClock,
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization, initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess, startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
notarySpecs: List<NotarySpec> = defaultParameters.notarySpecs,
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan, extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
dsl: DriverDSLExposedInterface.() -> A dsl: DriverDSLExposedInterface.() -> A
): A { ): A {
@ -335,6 +351,7 @@ fun <A> driver(
useTestClock = useTestClock, useTestClock = useTestClock,
isDebug = isDebug, isDebug = isDebug,
startNodesInProcess = startNodesInProcess, startNodesInProcess = startNodesInProcess,
notarySpecs = notarySpecs,
extraCordappPackagesToScan = extraCordappPackagesToScan extraCordappPackagesToScan = extraCordappPackagesToScan
), ),
coerce = { it }, coerce = { it },
@ -368,6 +385,7 @@ data class DriverParameters(
val useTestClock: Boolean = false, val useTestClock: Boolean = false,
val initialiseSerialization: Boolean = true, val initialiseSerialization: Boolean = true,
val startNodesInProcess: Boolean = false, val startNodesInProcess: Boolean = false,
val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY.name)),
val extraCordappPackagesToScan: List<String> = emptyList() val extraCordappPackagesToScan: List<String> = emptyList()
) { ) {
fun setIsDebug(isDebug: Boolean) = copy(isDebug = isDebug) fun setIsDebug(isDebug: Boolean) = copy(isDebug = isDebug)
@ -379,6 +397,7 @@ data class DriverParameters(
fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization) fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization)
fun setStartNodesInProcess(startNodesInProcess: Boolean) = copy(startNodesInProcess = startNodesInProcess) fun setStartNodesInProcess(startNodesInProcess: Boolean) = copy(startNodesInProcess = startNodesInProcess)
fun setExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>) = copy(extraCordappPackagesToScan = extraCordappPackagesToScan) fun setExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>) = copy(extraCordappPackagesToScan = extraCordappPackagesToScan)
fun setNotarySpecs(notarySpecs: List<NotarySpec>) = copy(notarySpecs = notarySpecs)
} }
/** /**
@ -428,10 +447,10 @@ fun <DI : DriverDSLExposedInterface, D : DriverDSLInternalInterface, A> genericD
useTestClock: Boolean = defaultParameters.useTestClock, useTestClock: Boolean = defaultParameters.useTestClock,
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization, initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess, startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
notarySpecs: List<NotarySpec>,
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan, extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
driverDslWrapper: (DriverDSL) -> D, driverDslWrapper: (DriverDSL) -> D,
coerce: (D) -> DI, coerce: (D) -> DI, dsl: DI.() -> A
dsl: DI.() -> A
): A { ): A {
val serializationEnv = initialiseTestSerialization(initialiseSerialization) val serializationEnv = initialiseTestSerialization(initialiseSerialization)
val driverDsl = driverDslWrapper( val driverDsl = driverDslWrapper(
@ -443,7 +462,8 @@ fun <DI : DriverDSLExposedInterface, D : DriverDSLInternalInterface, A> genericD
useTestClock = useTestClock, useTestClock = useTestClock,
isDebug = isDebug, isDebug = isDebug,
startNodesInProcess = startNodesInProcess, startNodesInProcess = startNodesInProcess,
extraCordappPackagesToScan = extraCordappPackagesToScan extraCordappPackagesToScan = extraCordappPackagesToScan,
notarySpecs = notarySpecs
) )
) )
val shutdownHook = addShutdownHook(driverDsl::shutdown) val shutdownHook = addShutdownHook(driverDsl::shutdown)
@ -643,7 +663,8 @@ class DriverDSL(
val useTestClock: Boolean, val useTestClock: Boolean,
val isDebug: Boolean, val isDebug: Boolean,
val startNodesInProcess: Boolean, val startNodesInProcess: Boolean,
extraCordappPackagesToScan: List<String> extraCordappPackagesToScan: List<String>,
val notarySpecs: List<NotarySpec>
) : DriverDSLInternalInterface { ) : DriverDSLInternalInterface {
private var _executorService: ScheduledExecutorService? = null private var _executorService: ScheduledExecutorService? = null
val executorService get() = _executorService!! val executorService get() = _executorService!!
@ -656,7 +677,9 @@ class DriverDSL(
private val nodeInfoFilesCopier = NodeInfoFilesCopier() private val nodeInfoFilesCopier = NodeInfoFilesCopier()
// Map from a nodes legal name to an observable emitting the number of nodes in its network map. // Map from a nodes legal name to an observable emitting the number of nodes in its network map.
private val countObservables = mutableMapOf<CordaX500Name, Observable<Int>>() private val countObservables = mutableMapOf<CordaX500Name, Observable<Int>>()
private var networkParameters: NetworkParametersCopier? = null private lateinit var _notaries: List<NotaryHandle>
override val notaryHandles: List<NotaryHandle> get() = _notaries
private lateinit var networkParameters: NetworkParametersCopier
class State { class State {
val processes = ArrayList<CordaFuture<Process>>() val processes = ArrayList<CordaFuture<Process>>()
@ -744,16 +767,6 @@ class DriverDSL(
return startNodeInternal(config, webAddress, startInSameProcess, maximumHeapSize) return startNodeInternal(config, webAddress, startInSameProcess, maximumHeapSize)
} }
override fun startNotaryNode(providedName: CordaX500Name,
rpcUsers: List<User>,
verifierType: VerifierType,
customOverrides: Map<String, Any?>,
validating: Boolean): CordaFuture<NodeHandle> {
createNetworkParameters(listOf(providedName), providedName, validating, "identity")
val config = customOverrides + NotaryConfig(validating).toConfigMap()
return startNode(providedName = providedName, rpcUsers = rpcUsers, verifierType = verifierType, customOverrides = config)
}
override fun startNodes(nodes: List<CordformNode>, startInSameProcess: Boolean?, maximumHeapSize: String): List<CordaFuture<NodeHandle>> { override fun startNodes(nodes: List<CordformNode>, startInSameProcess: Boolean?, maximumHeapSize: String): List<CordaFuture<NodeHandle>> {
return nodes.map { node -> return nodes.map { node ->
portAllocation.nextHostAndPort() // rpcAddress portAllocation.nextHostAndPort() // rpcAddress
@ -772,72 +785,6 @@ class DriverDSL(
} }
} }
// TODO This mapping is done is several plaecs including the gradle plugin. In general we need a better way of
// generating the configs for the nodes, probably making use of Any.toConfig()
private fun NotaryConfig.toConfigMap(): Map<String, Any> = mapOf("notary" to toConfig().root().unwrapped())
override fun startNotaryCluster(
notaryName: CordaX500Name,
clusterSize: Int,
verifierType: VerifierType,
rpcUsers: List<User>,
startInSameProcess: Boolean?
): CordaFuture<Pair<Party, List<NodeHandle>>> {
fun notaryConfig(nodeAddress: NetworkHostAndPort, clusterAddress: NetworkHostAndPort? = null): Map<String, Any> {
val clusterAddresses = if (clusterAddress != null) listOf(clusterAddress) else emptyList()
val config = NotaryConfig(validating = true, raft = RaftConfig(nodeAddress = nodeAddress, clusterAddresses = clusterAddresses))
return config.toConfigMap()
}
require(clusterSize > 0)
val nodeNames = (0 until clusterSize).map { notaryName.copy(organisation = "${notaryName.organisation}-$it") }
val notaryIdentity = createNetworkParameters(
nodeNames,
notaryName,
validating = true,
serviceId = NotaryService.constructId(validating = true, raft = true))
val clusterAddress = portAllocation.nextHostAndPort()
// Start the first node that will bootstrap the cluster
val firstNotaryFuture = startNode(
providedName = nodeNames[0],
rpcUsers = rpcUsers,
verifierType = verifierType,
customOverrides = notaryConfig(clusterAddress) + mapOf(
"database.serverNameTablePrefix" to nodeNames[0].toString().replace(Regex("[^0-9A-Za-z]+"), "")
),
startInSameProcess = startInSameProcess
)
// All other nodes will join the cluster
val restNotaryFutures = nodeNames.drop(1).map {
val nodeAddress = portAllocation.nextHostAndPort()
startNode(
providedName = it,
rpcUsers = rpcUsers,
verifierType = verifierType,
customOverrides = notaryConfig(nodeAddress, clusterAddress) + mapOf(
"database.serverNameTablePrefix" to it.toString().replace(Regex("[^0-9A-Za-z]+"), "")
))
}
return firstNotaryFuture.flatMap { firstNotary ->
restNotaryFutures.transpose().map { restNotaries -> Pair(notaryIdentity, listOf(firstNotary) + restNotaries) }
}
}
private fun createNetworkParameters(notaryNodeNames: List<CordaX500Name>, notaryName: CordaX500Name, validating: Boolean, serviceId: String): Party {
check(networkParameters == null) { "Notaries must be started first" }
val identity = ServiceIdentityGenerator.generateToDisk(
notaryNodeNames.map { baseDirectory(it) },
notaryName,
serviceId)
networkParameters = NetworkParametersCopier(testNetworkParameters(listOf(NotaryInfo(identity, validating))))
return identity
}
private fun queryWebserver(handle: NodeHandle, process: Process): WebserverHandle { private fun queryWebserver(handle: NodeHandle, process: Process): WebserverHandle {
val protocol = if (handle.configuration.useHTTPS) "https://" else "http://" val protocol = if (handle.configuration.useHTTPS) "https://" else "http://"
val url = URL("$protocol${handle.webAddress}/api/status") val url = URL("$protocol${handle.webAddress}/api/status")
@ -866,6 +813,97 @@ class DriverDSL(
_executorService = Executors.newScheduledThreadPool(2, ThreadFactoryBuilder().setNameFormat("driver-pool-thread-%d").build()) _executorService = Executors.newScheduledThreadPool(2, ThreadFactoryBuilder().setNameFormat("driver-pool-thread-%d").build())
_shutdownManager = ShutdownManager(executorService) _shutdownManager = ShutdownManager(executorService)
shutdownManager.registerShutdown { nodeInfoFilesCopier.close() } shutdownManager.registerShutdown { nodeInfoFilesCopier.close() }
val notaryInfos = generateNotaryIdentities()
// The network parameters must be serialised before starting any of the nodes
networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
val nodeHandles = startNotaries()
_notaries = notaryInfos.zip(nodeHandles) { (identity, validating), nodes -> NotaryHandle(identity, validating, nodes) }
}
private fun generateNotaryIdentities(): List<NotaryInfo> {
return notarySpecs.map { spec ->
val identity = if (spec.cluster == null) {
ServiceIdentityGenerator.generateToDisk(
dirs = listOf(baseDirectory(spec.name)),
serviceName = spec.name,
serviceId = "identity")
} else {
ServiceIdentityGenerator.generateToDisk(
dirs = generateNodeNames(spec).map { baseDirectory(it) },
serviceName = spec.name,
serviceId = NotaryService.constructId(
validating = spec.validating,
raft = spec.cluster is ClusterSpec.Raft))
}
NotaryInfo(identity, spec.validating)
}
}
private fun generateNodeNames(spec: NotarySpec): List<CordaX500Name> {
return (0 until spec.cluster!!.clusterSize).map { spec.name.copy(organisation = "${spec.name.organisation}-$it") }
}
private fun startNotaries(): List<CordaFuture<List<NodeHandle>>> {
return notarySpecs.map {
when {
it.cluster == null -> startSingleNotary(it)
it.cluster is ClusterSpec.Raft -> startRaftNotaryCluster(it)
else -> throw IllegalArgumentException("BFT-SMaRt not supported")
}
}
}
// TODO This mapping is done is several places including the gradle plugin. In general we need a better way of
// generating the configs for the nodes, probably making use of Any.toConfig()
private fun NotaryConfig.toConfigMap(): Map<String, Any> = mapOf("notary" to toConfig().root().unwrapped())
private fun startSingleNotary(spec: NotarySpec): CordaFuture<List<NodeHandle>> {
return startNode(
providedName = spec.name,
rpcUsers = spec.rpcUsers,
verifierType = spec.verifierType,
customOverrides = NotaryConfig(spec.validating).toConfigMap()
).map { listOf(it) }
}
private fun startRaftNotaryCluster(spec: NotarySpec): CordaFuture<List<NodeHandle>> {
fun notaryConfig(nodeAddress: NetworkHostAndPort, clusterAddress: NetworkHostAndPort? = null): Map<String, Any> {
val clusterAddresses = if (clusterAddress != null) listOf(clusterAddress) else emptyList()
val config = NotaryConfig(
validating = spec.validating,
raft = RaftConfig(nodeAddress = nodeAddress, clusterAddresses = clusterAddresses))
return config.toConfigMap()
}
val nodeNames = generateNodeNames(spec)
val clusterAddress = portAllocation.nextHostAndPort()
// Start the first node that will bootstrap the cluster
val firstNodeFuture = startNode(
providedName = nodeNames[0],
rpcUsers = spec.rpcUsers,
verifierType = spec.verifierType,
customOverrides = notaryConfig(clusterAddress) + mapOf(
"database.serverNameTablePrefix" to nodeNames[0].toString().replace(Regex("[^0-9A-Za-z]+"), "")
)
)
// All other nodes will join the cluster
val restNodeFutures = nodeNames.drop(1).map {
val nodeAddress = portAllocation.nextHostAndPort()
startNode(
providedName = it,
rpcUsers = spec.rpcUsers,
verifierType = spec.verifierType,
customOverrides = notaryConfig(nodeAddress, clusterAddress) + mapOf(
"database.serverNameTablePrefix" to it.toString().replace(Regex("[^0-9A-Za-z]+"), "")
)
)
}
return firstNodeFuture.flatMap { first ->
restNodeFutures.transpose().map { rest -> listOf(first) + rest }
}
} }
fun baseDirectory(nodeName: CordaX500Name): Path { fun baseDirectory(nodeName: CordaX500Name): Path {
@ -925,10 +963,7 @@ class DriverDSL(
maximumHeapSize: String): CordaFuture<NodeHandle> { maximumHeapSize: String): CordaFuture<NodeHandle> {
val configuration = config.parseAsNodeConfiguration() val configuration = config.parseAsNodeConfiguration()
val baseDirectory = configuration.baseDirectory.createDirectories() val baseDirectory = configuration.baseDirectory.createDirectories()
if (networkParameters == null) { networkParameters.install(baseDirectory)
networkParameters = NetworkParametersCopier(testNetworkParameters(emptyList()))
}
networkParameters!!.install(baseDirectory)
nodeInfoFilesCopier.addConfig(baseDirectory) nodeInfoFilesCopier.addConfig(baseDirectory)
val onNodeExit: () -> Unit = { val onNodeExit: () -> Unit = {
nodeInfoFilesCopier.removeConfig(baseDirectory) nodeInfoFilesCopier.removeConfig(baseDirectory)

View File

@ -7,6 +7,7 @@ import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.crypto.entropyToKeyPair import net.corda.core.crypto.entropyToKeyPair
import net.corda.core.crypto.random63BitValue import net.corda.core.crypto.random63BitValue
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.internal.createDirectories import net.corda.core.internal.createDirectories
import net.corda.core.internal.createDirectory import net.corda.core.internal.createDirectory
import net.corda.core.internal.uncheckedCast import net.corda.core.internal.uncheckedCast
@ -110,6 +111,9 @@ data class MockNodeArgs(
* You can get a printout of every message sent by using code like: * You can get a printout of every message sent by using code like:
* *
* LogHelper.setLevel("+messages") * 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].
*/ */
class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParameters(), class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParameters(),
private val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped, private val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped,
@ -117,6 +121,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy, servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy,
private val defaultFactory: (MockNodeArgs) -> MockNode = defaultParameters.defaultFactory, private val defaultFactory: (MockNodeArgs) -> MockNode = defaultParameters.defaultFactory,
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization, initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
private val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY.name)),
private val cordappPackages: List<String> = defaultParameters.cordappPackages) : Closeable { private val cordappPackages: List<String> = defaultParameters.cordappPackages) : Closeable {
/** Helper constructor for creating a [MockNetwork] with custom parameters from Java. */ /** Helper constructor for creating a [MockNetwork] with custom parameters from Java. */
constructor(parameters: MockNetworkParameters) : this(defaultParameters = parameters) constructor(parameters: MockNetworkParameters) : this(defaultParameters = parameters)
@ -128,22 +133,43 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch) val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch)
// A unique identifier for this network to segregate databases with the same nodeID but different networks. // A unique identifier for this network to segregate databases with the same nodeID but different networks.
private val networkId = random63BitValue() private val networkId = random63BitValue()
private lateinit var networkParameters: NetworkParametersCopier private val networkParameters: NetworkParametersCopier
private var notaryInfos: MutableList<NotaryInfo>? = ArrayList() private val _nodes = mutableListOf<MockNode>()
private val _nodes = ArrayList<MockNode>()
private val serializationEnv = initialiseTestSerialization(initialiseSerialization) private val serializationEnv = initialiseTestSerialization(initialiseSerialization)
private val sharedUserCount = AtomicInteger(0)
/** A read only view of the current set of executing nodes. */ /** A read only view of the current set of executing nodes. */
val nodes: List<MockNode> get() = _nodes val nodes: List<MockNode> get() = _nodes
init { /**
filesystem.getPath("/nodes").createDirectory() * Returns the list of nodes started by the network. Each notary specified when the network is constructed ([notarySpecs]
* parameter) maps 1:1 to the notaries returned by this list.
*/
val notaryNodes: List<StartedNode<MockNode>>
/**
* Returns the single notary node on the network. Throws if there are none or more than one.
* @see notaryNodes
*/
val defaultNotaryNode: StartedNode<MockNode> get() {
return when (notaryNodes.size) {
0 -> throw IllegalStateException("There are no notaries defined on the network")
1 -> notaryNodes[0]
else -> throw IllegalStateException("There is more than one notary defined on the network")
}
}
/**
* Return the identity of the default notary node.
* @see defaultNotaryNode
*/
val defaultNotaryIdentity: Party get() {
return defaultNotaryNode.info.legalIdentities.singleOrNull() ?: throw IllegalStateException("Default notary has multiple identities")
} }
/** /**
* Because this executor is shared, we need to be careful about nodes shutting it down. * Because this executor is shared, we need to be careful about nodes shutting it down.
*/ */
private val sharedUserCount = AtomicInteger(0)
private val sharedServerThread = object : ServiceAffinityExecutor("Mock network", 1) { private val sharedServerThread = object : ServiceAffinityExecutor("Mock network", 1) {
override fun shutdown() { override fun shutdown() {
// We don't actually allow the shutdown of the network-wide shared thread pool until all references to // We don't actually allow the shutdown of the network-wide shared thread pool until all references to
@ -163,6 +189,32 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
} }
} }
init {
filesystem.getPath("/nodes").createDirectory()
val notaryInfos = generateNotaryIdentities()
// The network parameters must be serialised before starting any of the nodes
networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
notaryNodes = createNotaries()
}
private fun generateNotaryIdentities(): List<NotaryInfo> {
return notarySpecs.mapIndexed { index, spec ->
val identity = ServiceIdentityGenerator.generateToDisk(
dirs = listOf(baseDirectory(nextNodeId + index)),
serviceName = spec.name,
serviceId = "identity")
NotaryInfo(identity, spec.validating)
}
}
private fun createNotaries(): List<StartedNode<MockNode>> {
return notarySpecs.map { spec ->
createNode(MockNodeParameters(legalName = spec.name, configOverrides = {
doReturn(NotaryConfig(spec.validating)).whenever(it).notary
}))
}
}
open class MockNode(args: MockNodeArgs) : AbstractNode( open class MockNode(args: MockNodeArgs) : AbstractNode(
args.config, args.config,
TestClock(), TestClock(),
@ -188,20 +240,12 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
override val started: StartedNode<MockNode>? get() = uncheckedCast(super.started) override val started: StartedNode<MockNode>? get() = uncheckedCast(super.started)
override fun start(): StartedNode<MockNode> { override fun start(): StartedNode<MockNode> {
installNetworkParameters() mockNet.networkParameters.install(configuration.baseDirectory)
val started: StartedNode<MockNode> = uncheckedCast(super.start()) val started: StartedNode<MockNode> = uncheckedCast(super.start())
advertiseNodeToNetwork(started) advertiseNodeToNetwork(started)
return started return started
} }
private fun installNetworkParameters() {
mockNet.notaryInfos?.let {
mockNet.networkParameters = NetworkParametersCopier(testNetworkParameters(it))
}
mockNet.notaryInfos = null
mockNet.networkParameters.install(configuration.baseDirectory)
}
private fun advertiseNodeToNetwork(newNode: StartedNode<MockNode>) { private fun advertiseNodeToNetwork(newNode: StartedNode<MockNode>) {
mockNet.nodes mockNet.nodes
.mapNotNull { it.started } .mapNotNull { it.started }
@ -273,9 +317,6 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
dbCloser = null dbCloser = null
} }
fun hasDBConnection() = dbCloser != null
// You can change this from zero if you have custom [FlowLogic] that park themselves. e.g. [StateMachineManagerTests]
var acceptableLiveFiberCountOnStop: Int = 0 var acceptableLiveFiberCountOnStop: Int = 0
override fun acceptableLiveFiberCountOnStop(): Int = acceptableLiveFiberCountOnStop override fun acceptableLiveFiberCountOnStop(): Int = acceptableLiveFiberCountOnStop
@ -321,23 +362,11 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
doReturn(makeTestDataSourceProperties("node_${id}_net_$networkId")).whenever(it).dataSourceProperties doReturn(makeTestDataSourceProperties("node_${id}_net_$networkId")).whenever(it).dataSourceProperties
parameters.configOverrides(it) parameters.configOverrides(it)
} }
val node = nodeFactory(MockNodeArgs(config, this, id, parameters.entropyRoot)) val node = nodeFactory(MockNodeArgs(config, this, id, parameters.entropyRoot))
_nodes += node _nodes += node
config.notary?.let { notaryConfig ->
val notaryInfos = notaryInfos ?: throw IllegalStateException("Cannot add notaries once nodes have started")
if (!notaryConfig.isClusterConfig) {
// Create the node's main identity, which will also double as its notary identity
val identity = ServiceIdentityGenerator.generateToDisk(listOf(config.baseDirectory), config.myLegalName, "identity")
notaryInfos += NotaryInfo(identity, notaryConfig.validating)
}
}
if (start) { if (start) {
node.start() node.start()
} }
return node return node
} }
@ -365,24 +394,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
} }
@JvmOverloads @JvmOverloads
fun createNotaryNode(parameters: MockNodeParameters = MockNodeParameters(legalName = DUMMY_NOTARY.name),
validating: Boolean = true): StartedNode<MockNode> {
return createNotaryNode(parameters, validating, defaultFactory)
}
fun <N : MockNode> createNotaryNode(parameters: MockNodeParameters = MockNodeParameters(legalName = DUMMY_NOTARY.name),
validating: Boolean = true,
nodeFactory: (MockNodeArgs) -> N): StartedNode<N> {
return createNode(
parameters.copy(configOverrides = {
doReturn(NotaryConfig(validating)).whenever(it).notary
parameters.configOverrides(it)
}),
nodeFactory
)
}
@JvmOverloads
fun createPartyNode(legalName: CordaX500Name? = null): StartedNode<MockNode> { fun createPartyNode(legalName: CordaX500Name? = null): StartedNode<MockNode> {
return createNode(MockNodeParameters(legalName = legalName)) return createNode(MockNodeParameters(legalName = legalName))
} }
@ -418,14 +430,16 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
override fun close() { override fun close() {
stopNodes() stopNodes()
} }
data class NotarySpec(val name: CordaX500Name, val validating: Boolean = true) {
constructor(name: CordaX500Name) : this(name, validating = true)
}
} }
fun network(nodesCount: Int, action: MockNetwork.(nodes: List<StartedNode<MockNetwork.MockNode>>, notary: StartedNode<MockNetwork.MockNode>) -> Unit) { fun network(nodesCount: Int, action: MockNetwork.(List<StartedNode<MockNetwork.MockNode>>) -> Unit) {
MockNetwork().use { MockNetwork().use { mockNet ->
it.runNetwork() val nodes = (1..nodesCount).map { mockNet.createPartyNode() }
val notary = it.createNotaryNode() mockNet.action(nodes)
val nodes = (1..nodesCount).map { _ -> it.createPartyNode() }
action(it, nodes, notary)
} }
} }

View File

@ -0,0 +1,23 @@
package net.corda.testing.node
import net.corda.core.identity.CordaX500Name
import net.corda.node.services.config.VerifierType
import net.corda.nodeapi.User
data class NotarySpec(
val name: CordaX500Name,
val validating: Boolean = true,
val rpcUsers: List<User> = emptyList(),
val verifierType: VerifierType = VerifierType.InMemory,
val cluster: ClusterSpec? = null
)
sealed class ClusterSpec {
abstract val clusterSize: Int
data class Raft(override val clusterSize: Int) : ClusterSpec() {
init {
require(clusterSize > 0)
}
}
}

View File

@ -24,14 +24,13 @@ import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.testing.BOB import net.corda.testing.BOB
import net.corda.testing.DUMMY_NOTARY
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 java.time.Instant import java.time.Instant
import java.util.* import java.util.*
class ExplorerSimulation(val options: OptionSet) { class ExplorerSimulation(private val options: OptionSet) {
private val user = User("user1", "test", permissions = setOf( private val user = User("user1", "test", permissions = setOf(
startFlow<CashPaymentFlow>(), startFlow<CashPaymentFlow>(),
startFlow<CashConfigDataFlow>() startFlow<CashConfigDataFlow>()
@ -67,23 +66,16 @@ class ExplorerSimulation(val options: OptionSet) {
val portAllocation = PortAllocation.Incremental(20000) val portAllocation = PortAllocation.Incremental(20000)
driver(portAllocation = portAllocation, extraCordappPackagesToScan = listOf("net.corda.finance")) { driver(portAllocation = portAllocation, extraCordappPackagesToScan = listOf("net.corda.finance")) {
// TODO : Supported flow should be exposed somehow from the node instead of set of ServiceInfo. // TODO : Supported flow should be exposed somehow from the node instead of set of ServiceInfo.
val notary = startNotaryNode(DUMMY_NOTARY.name, customOverrides = mapOf("nearestCity" to "Zurich"), validating = false) val alice = startNode(providedName = ALICE.name, rpcUsers = listOf(user))
val alice = startNode(providedName = ALICE.name, rpcUsers = arrayListOf(user), val bob = startNode(providedName = BOB.name, rpcUsers = listOf(user))
customOverrides = mapOf("nearestCity" to "Milan"))
val bob = startNode(providedName = BOB.name, rpcUsers = arrayListOf(user),
customOverrides = mapOf("nearestCity" to "Madrid"))
val ukBankName = CordaX500Name(organisation = "UK Bank Plc", locality = "London", country = "GB") val ukBankName = CordaX500Name(organisation = "UK Bank Plc", locality = "London", country = "GB")
val usaBankName = CordaX500Name(organisation = "USA Bank Corp", locality = "New York", country = "US") val usaBankName = CordaX500Name(organisation = "USA Bank Corp", locality = "New York", country = "US")
val issuerGBP = startNode(providedName = ukBankName, rpcUsers = arrayListOf(manager), val issuerGBP = startNode(providedName = ukBankName, rpcUsers = listOf(manager),
customOverrides = mapOf( customOverrides = mapOf("issuableCurrencies" to listOf("GBP")))
"issuableCurrencies" to listOf("GBP"), val issuerUSD = startNode(providedName = usaBankName, rpcUsers = listOf(manager),
"nearestCity" to "London")) customOverrides = mapOf("issuableCurrencies" to listOf("USD")))
val issuerUSD = startNode(providedName = usaBankName, rpcUsers = arrayListOf(manager),
customOverrides = mapOf(
"issuableCurrencies" to listOf("USD"),
"nearestCity" to "New York"))
notaryNode = notary.get() notaryNode = defaultNotaryNode.get()
aliceNode = alice.get() aliceNode = alice.get()
bobNode = bob.get() bobNode = bob.get()
issuerNodeGBP = issuerGBP.get() issuerNodeGBP = issuerGBP.get()

View File

@ -19,6 +19,7 @@ import net.corda.nodeapi.VerifierApi
import net.corda.nodeapi.config.NodeSSLConfiguration import net.corda.nodeapi.config.NodeSSLConfiguration
import net.corda.nodeapi.config.SSLConfiguration import net.corda.nodeapi.config.SSLConfiguration
import net.corda.testing.driver.* import net.corda.testing.driver.*
import net.corda.testing.node.NotarySpec
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
import org.apache.activemq.artemis.api.core.client.ActiveMQClient import org.apache.activemq.artemis.api.core.client.ActiveMQClient
import org.apache.activemq.artemis.api.core.client.ClientProducer import org.apache.activemq.artemis.api.core.client.ClientProducer
@ -77,6 +78,7 @@ fun <A> verifierDriver(
useTestClock: Boolean = false, useTestClock: Boolean = false,
startNodesInProcess: Boolean = false, startNodesInProcess: Boolean = false,
extraCordappPackagesToScan: List<String> = emptyList(), extraCordappPackagesToScan: List<String> = emptyList(),
notarySpecs: List<NotarySpec> = emptyList(),
dsl: VerifierExposedDSLInterface.() -> A dsl: VerifierExposedDSLInterface.() -> A
) = genericDriver( ) = genericDriver(
driverDsl = VerifierDriverDSL( driverDsl = VerifierDriverDSL(
@ -88,7 +90,8 @@ fun <A> verifierDriver(
useTestClock = useTestClock, useTestClock = useTestClock,
isDebug = isDebug, isDebug = isDebug,
startNodesInProcess = startNodesInProcess, startNodesInProcess = startNodesInProcess,
extraCordappPackagesToScan = extraCordappPackagesToScan extraCordappPackagesToScan = extraCordappPackagesToScan,
notarySpecs = notarySpecs
) )
), ),
coerce = { it }, coerce = { it },

View File

@ -15,6 +15,7 @@ import net.corda.node.services.config.VerifierType
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.testing.ALICE_NAME import net.corda.testing.ALICE_NAME
import net.corda.testing.DUMMY_NOTARY import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.node.NotarySpec
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
@ -128,15 +129,15 @@ class VerifierTests {
@Test @Test
fun `single verifier works with a node`() { fun `single verifier works with a node`() {
verifierDriver(extraCordappPackagesToScan = listOf("net.corda.finance.contracts")) { verifierDriver(
val (notaryNode, aliceNode) = listOf( extraCordappPackagesToScan = listOf("net.corda.finance.contracts"),
startNotaryNode(DUMMY_NOTARY.name, verifierType = VerifierType.OutOfProcess), notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, verifierType = VerifierType.OutOfProcess))
startNode(providedName = ALICE.name) ) {
).transpose().getOrThrow() val aliceNode = startNode(providedName = ALICE.name).getOrThrow()
val notaryNode = defaultNotaryNode.getOrThrow()
val alice = aliceNode.rpc.wellKnownPartyFromX500Name(ALICE_NAME)!! val alice = aliceNode.rpc.wellKnownPartyFromX500Name(ALICE_NAME)!!
val notary = notaryNode.rpc.notaryPartyFromX500Name(DUMMY_NOTARY.name)!!
startVerifier(notaryNode) startVerifier(notaryNode)
aliceNode.rpc.startFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), notary).returnValue.get() aliceNode.rpc.startFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue.get()
notaryNode.waitUntilNumberOfVerifiers(1) notaryNode.waitUntilNumberOfVerifiers(1)
for (i in 1..10) { for (i in 1..10) {
val cashFlowResult = aliceNode.rpc.startFlow(::CashPaymentFlow, 10.DOLLARS, alice).returnValue.get() val cashFlowResult = aliceNode.rpc.startFlow(::CashPaymentFlow, 10.DOLLARS, alice).returnValue.get()

View File

@ -11,7 +11,7 @@ import org.junit.Test
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.ScheduledExecutorService
class DriverTests { class WebserverDriverTests {
companion object { companion object {
val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2) val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)