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.Party
import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.internal.concurrent.transpose
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.StateMachineTransactionMapping
import net.corda.core.messaging.StateMachineUpdate
@ -50,44 +49,44 @@ class NodeMonitorModelTest {
private lateinit var vaultUpdates: Observable<Vault.Update<ContractState>>
private lateinit var networkMapUpdates: Observable<NetworkMapCache.MapChange>
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)
rpc = monitor.proxyObservable.value!!
notaryParty = notaryHandle.nodeInfo.legalIdentities[0]
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 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()
bobNode = bobNodeHandle.nodeInfo
val monitorBob = NodeMonitorModel()
stateMachineUpdatesBob = monitorBob.stateMachineUpdates.bufferUntilSubscribed()
monitorBob.register(bobNodeHandle.configuration.rpcAddress!!, cashUser.username, cashUser.password)
rpcBob = monitorBob.proxyObservable.value!!
runTest()
monitor.register(aliceNodeHandle.configuration.rpcAddress!!, cashUser.username, cashUser.password)
rpc = monitor.proxyObservable.value!!
notaryParty = defaultNotaryIdentity
val bobNodeHandle = startNode(providedName = BOB.name, rpcUsers = listOf(cashUser)).getOrThrow()
bobNode = bobNodeHandle.nodeInfo
val monitorBob = NodeMonitorModel()
stateMachineUpdatesBob = monitorBob.stateMachineUpdates.bufferUntilSubscribed()
monitorBob.register(bobNodeHandle.configuration.rpcAddress!!, cashUser.username, cashUser.password)
rpcBob = monitorBob.proxyObservable.value!!
runTest()
}
}
@Test

View File

@ -14,8 +14,11 @@ import net.corda.finance.DOLLARS
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.flows.CashIssueAndPaymentFlow
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.singleIdentity
import org.junit.After
import org.junit.Before
import org.junit.Test
@ -24,12 +27,16 @@ import kotlin.test.assertNotNull
import kotlin.test.assertNull
class IdentitySyncFlowTests {
lateinit var mockNet: MockNetwork
private lateinit var mockNet: MockNetwork
@Before
fun before() {
// 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
@ -40,12 +47,11 @@ class IdentitySyncFlowTests {
@Test
fun `sync confidential identities`() {
// Set up values we'll need
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME)
val alice: Party = aliceNode.info.singleIdentity()
val bob: Party = bobNode.info.singleIdentity()
val notary = notaryNode.services.getDefaultNotary()
val notary = mockNet.defaultNotaryIdentity
bobNode.internals.registerInitiatedFlow(Receive::class.java)
// Alice issues then pays some cash to a new confidential identity that Bob doesn't know about
@ -70,14 +76,13 @@ class IdentitySyncFlowTests {
@Test
fun `don't offer other's identities confidential identities`() {
// Set up values we'll need
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME)
val charlieNode = mockNet.createPartyNode(CHARLIE_NAME)
val alice: Party = aliceNode.info.singleIdentity()
val bob: Party = bobNode.info.singleIdentity()
val charlie: Party = charlieNode.info.singleIdentity()
val notary = notaryNode.services.getDefaultNotary()
val notary = mockNet.defaultNotaryIdentity
bobNode.internals.registerInitiatedFlow(Receive::class.java)
// 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.
*/
@InitiatingFlow
class Initiator(val otherSide: Party, val tx: WireTransaction): FlowLogic<Boolean>() {
class Initiator(private val otherSide: Party, private val tx: WireTransaction): FlowLogic<Boolean>() {
@Suspendable
override fun call(): Boolean {
val session = initiateFlow(otherSide)
@ -116,7 +121,7 @@ class IdentitySyncFlowTests {
}
@InitiatedBy(IdentitySyncFlowTests.Initiator::class)
class Receive(val otherSideSession: FlowSession): FlowLogic<Unit>() {
class Receive(private val otherSideSession: FlowSession): FlowLogic<Unit>() {
@Suspendable
override fun call() {
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.testing.*
import net.corda.testing.node.MockNetwork
import org.junit.Before
import org.junit.Test
import kotlin.test.*
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
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
mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE.name)
val bobNode = mockNet.createPartyNode(BOB.name)
val alice = aliceNode.info.singleIdentity()
@ -52,19 +57,16 @@ class SwapIdentitiesFlowTests {
*/
@Test
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
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createPartyNode(ALICE.name)
val bobNode = mockNet.createPartyNode(BOB.name)
val charlieNode = mockNet.createPartyNode(CHARLIE.name)
val bob: Party = bobNode.services.myInfo.singleIdentity()
val notBob = notaryNode.database.transaction {
notaryNode.services.keyManagementService.freshKeyAndCert(notaryNode.services.myInfo.chooseIdentityAndCert(), false)
val notBob = charlieNode.database.transaction {
charlieNode.services.keyManagementService.freshKeyAndCert(charlieNode.services.myInfo.chooseIdentityAndCert(), false)
}
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.") {
SwapIdentitiesFlow.validateAndRegisterIdentity(aliceNode.services.identityService, bob, notBob, signature.withoutKey())
}
@ -77,11 +79,8 @@ class SwapIdentitiesFlowTests {
*/
@Test
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
val notaryNode = mockNet.createNotaryNode()
val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE.name)
val bobNode = mockNet.createPartyNode(BOB.name)
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,
* [isNotary] is only true.
* [isNotary] is also true.
* @see isNotary
*/
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;
public class FlowsInJavaTest {
private final MockNetwork mockNet = new MockNetwork();
private StartedNode<MockNetwork.MockNode> aliceNode;
private StartedNode<MockNetwork.MockNode> bobNode;
@Before
public void setUp() throws Exception {
mockNet.createNotaryNode();
aliceNode = mockNet.createPartyNode(TestConstants.getALICE().getName());
bobNode = mockNet.createPartyNode(TestConstants.getBOB().getName());
mockNet.runNetwork();

View File

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

View File

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

View File

@ -41,14 +41,13 @@ class ContractUpgradeFlowTest {
@Before
fun setup() {
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)
bobNode = mockNet.createPartyNode(BOB.name)
// Process registration
mockNet.runNetwork()
notary = notaryNode.services.getDefaultNotary()
notary = mockNet.defaultNotaryIdentity
}
@After

View File

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

View File

@ -13,7 +13,7 @@ import org.junit.Test
class ReceiveMultipleFlowTests {
@Test
fun `receive all messages in parallel using map style`() {
network(3) { nodes, _ ->
network(3) { nodes ->
val doubleValue = 5.0
nodes[1].registerAnswer(AlgorithmDefinition::class, doubleValue)
val stringValue = "Thriller"
@ -30,7 +30,7 @@ class ReceiveMultipleFlowTests {
@Test
fun `receive all messages in parallel using list style`() {
network(3) { nodes, _ ->
network(3) { nodes ->
val value1 = 5.0
nodes[1].registerAnswer(ParallelAlgorithmList::class, value1)
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.sequence
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.getDefaultNotary
import net.corda.testing.node.MockNetwork
@ -26,18 +28,18 @@ import kotlin.test.assertNull
// DOCSTART 3
class ResolveTransactionsFlowTest {
lateinit var mockNet: MockNetwork
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
lateinit var megaCorpNode: StartedNode<MockNetwork.MockNode>
lateinit var miniCorpNode: StartedNode<MockNetwork.MockNode>
lateinit var megaCorp: Party
lateinit var miniCorp: Party
lateinit var notary: Party
private lateinit var mockNet: MockNetwork
private lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
private lateinit var megaCorpNode: StartedNode<MockNetwork.MockNode>
private lateinit var miniCorpNode: StartedNode<MockNetwork.MockNode>
private lateinit var megaCorp: Party
private lateinit var miniCorp: Party
private lateinit var notary: Party
@Before
fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
notaryNode = mockNet.createNotaryNode()
notaryNode = mockNet.defaultNotaryNode
megaCorpNode = mockNet.createPartyNode(MEGA_CORP.name)
miniCorpNode = mockNet.createPartyNode(MINI_CORP.name)
megaCorpNode.internals.registerInitiatedFlow(TestResponseFlow::class.java)

View File

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

View File

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

View File

@ -55,7 +55,6 @@ class TutorialMockNetwork {
}
lateinit private var mockNet: MockNetwork
lateinit private var notary: StartedNode<MockNetwork.MockNode>
lateinit private var nodeA: StartedNode<MockNetwork.MockNode>
lateinit private var nodeB: StartedNode<MockNetwork.MockNode>
@ -66,7 +65,6 @@ class TutorialMockNetwork {
@Before
fun setUp() {
mockNet = MockNetwork()
notary = mockNet.createNotaryNode()
nodeA = 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.schemas.CashSchemaV1
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 org.junit.After
import org.junit.Assert
@ -19,23 +20,20 @@ import org.junit.Test
import java.util.*
class CustomVaultQueryTest {
lateinit var mockNet: MockNetwork
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
lateinit var nodeB: StartedNode<MockNetwork.MockNode>
lateinit var notary: Party
private lateinit var mockNet: MockNetwork
private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
private lateinit var nodeB: StartedNode<MockNetwork.MockNode>
private lateinit var notary: Party
@Before
fun setup() {
mockNet = MockNetwork(
threadPerNode = true,
mockNet = MockNetwork(threadPerNode = true,
cordappPackages = listOf(
"net.corda.finance.contracts.asset",
CashSchemaV1::class.packageName,
"net.corda.docs"
)
)
mockNet.createNotaryNode()
nodeA = mockNet.createPartyNode()
nodeB = mockNet.createPartyNode()
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.schemas.CashSchemaV1
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 org.junit.After
import org.junit.Before
@ -18,15 +19,14 @@ import org.junit.Test
import kotlin.test.assertEquals
class FxTransactionBuildTutorialTest {
lateinit var mockNet: MockNetwork
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
lateinit var nodeB: StartedNode<MockNetwork.MockNode>
lateinit var notary: Party
private lateinit var mockNet: MockNetwork
private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
private lateinit var nodeB: StartedNode<MockNetwork.MockNode>
private lateinit var notary: Party
@Before
fun setup() {
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.finance.contracts.asset", CashSchemaV1::class.packageName))
mockNet.createNotaryNode()
nodeA = mockNet.createPartyNode()
nodeB = mockNet.createPartyNode()
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.utilities.getOrThrow
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 org.junit.After
import org.junit.Before
@ -18,11 +19,11 @@ import org.junit.Test
import kotlin.test.assertEquals
class WorkflowTransactionBuildTutorialTest {
lateinit var mockNet: MockNetwork
lateinit var aliceServices: StartedNodeServices
lateinit var bobServices: StartedNodeServices
lateinit var alice: Party
lateinit var bob: Party
private lateinit var mockNet: MockNetwork
private lateinit var aliceServices: StartedNodeServices
private lateinit var bobServices: StartedNodeServices
private lateinit var alice: Party
private lateinit var bob: Party
// Helper method to locate the latest Vault version of a LinearState
private inline fun <reified T : LinearState> ServiceHub.latest(ref: UniqueIdentifier): StateAndRef<T> {
@ -33,8 +34,6 @@ class WorkflowTransactionBuildTutorialTest {
@Before
fun setup() {
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 bobNode = mockNet.createPartyNode(BOB_NAME)
aliceNode.internals.registerInitiatedFlow(RecordCompletionFlow::class.java)

View File

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

View File

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

View File

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

View File

@ -26,18 +26,16 @@ class CashPaymentFlowTests {
private val ref = OpaqueBytes.of(0x01)
private lateinit var bankOfCordaNode: StartedNode<MockNode>
private lateinit var bankOfCorda: Party
private lateinit var notaryNode: StartedNode<MockNode>
private lateinit var notary: Party
private lateinit var aliceNode: StartedNode<MockNode>
@Before
fun start() {
mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset"))
notaryNode = mockNet.createNotaryNode()
bankOfCordaNode = mockNet.createPartyNode(BOC.name)
aliceNode = mockNet.createPartyNode(ALICE.name)
bankOfCorda = bankOfCordaNode.info.chooseIdentity()
notary = notaryNode.services.getDefaultNotary()
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, notary)).resultFuture
mockNet.runNetwork()
val future = bankOfCordaNode.services.startFlow(CashIssueFlow(initialBalance, ref, mockNet.defaultNotaryIdentity)).resultFuture
future.getOrThrow()
}
@ -48,7 +46,7 @@ class CashPaymentFlowTests {
@Test
fun `pay some cash`() {
val payTo = notaryNode.info.chooseIdentity()
val payTo = aliceNode.info.chooseIdentity()
val expectedPayment = 500.DOLLARS
val expectedChange = 1500.DOLLARS
@ -56,7 +54,7 @@ class CashPaymentFlowTests {
// Register for vault updates
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
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,
payTo)).resultFuture
@ -88,7 +86,7 @@ class CashPaymentFlowTests {
@Test
fun `pay more than we have`() {
val payTo = notaryNode.info.chooseIdentity()
val payTo = aliceNode.info.chooseIdentity()
val expected = 4000.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
payTo)).resultFuture
@ -100,7 +98,7 @@ class CashPaymentFlowTests {
@Test
fun `pay zero cash`() {
val payTo = notaryNode.info.chooseIdentity()
val payTo = aliceNode.info.chooseIdentity()
val expected = 0.DOLLARS
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expected,
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.nodeapi.User
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver
import net.corda.testing.node.NotarySpec
import net.corda.testing.performance.div
import net.corda.testing.performance.startPublishingFixedRateInjector
import net.corda.testing.performance.startReporter
@ -102,26 +102,25 @@ class NodePerformanceTests {
@Test
fun `self pay rate`() {
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance")) {
val a = startNotaryNode(
DUMMY_NOTARY.name,
rpcUsers = listOf(User("A", "A", setOf(startFlow<CashIssueFlow>(), startFlow<CashPaymentFlow>())))
).getOrThrow()
a as NodeHandle.InProcess
val metricRegistry = startReporter(shutdownManager, a.node.services.monitoringService.metrics)
a.rpcClientToNode().use("A", "A") { connection ->
val notary = connection.proxy.notaryIdentities().first()
val user = User("A", "A", setOf(startFlow<CashIssueFlow>(), startFlow<CashPaymentFlow>()))
driver(
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, rpcUsers = listOf(user))),
startNodesInProcess = true,
extraCordappPackagesToScan = listOf("net.corda.finance")
) {
val notary = defaultNotaryNode.getOrThrow() as NodeHandle.InProcess
val metricRegistry = startReporter(shutdownManager, notary.node.services.monitoringService.metrics)
notary.rpcClientToNode().use("A", "A") { connection ->
println("ISSUING")
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()
doneFutures.transpose().get()
println("STARTING PAYMENT")
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.serialization.SerializationFactory
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.seconds
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.internal.cordapp.CordappProviderImpl
import net.corda.nodeapi.User
import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.driver.DriverDSLExposedInterface
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver
import net.corda.testing.eventually
import net.corda.testing.node.MockServices
import org.junit.Assert.assertEquals
import org.junit.Before
@ -56,19 +52,15 @@ class AttachmentLoadingTests {
val bankAName = CordaX500Name("BankA", "Zurich", "CH")
val bankBName = CordaX500Name("BankB", "Zurich", "CH")
val notaryName = CordaX500Name("Notary", "Zurich", "CH")
val flowInitiatorClass: Class<out FlowLogic<*>> =
Class.forName("net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator", true, URLClassLoader(arrayOf(isolatedJAR)))
.asSubclass(FlowLogic::class.java)
private fun DriverDSLExposedInterface.createNotaryAndTwoNodes(): List<NodeHandle> {
val adminUser = User("admin", "admin", permissions = setOf("ALL"))
val nodes = listOf(
startNotaryNode(providedName = notaryName, rpcUsers = listOf(adminUser), validating = false),
startNode(providedName = bankAName, rpcUsers = listOf(adminUser)),
startNode(providedName = bankBName, rpcUsers = listOf(adminUser))
).transpose().getOrThrow() // Wait for all nodes to start up.
return nodes
private fun DriverDSLExposedInterface.createTwoNodes(): List<NodeHandle> {
return listOf(
startNode(providedName = bankAName),
startNode(providedName = bankBName)
).transpose().getOrThrow()
}
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
@ -105,9 +88,8 @@ class AttachmentLoadingTests {
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 contract = contractClass.newInstance()
val txBuilder = generateInitialMethod.invoke(contract, PartyAndReference(DUMMY_BANK_A, OpaqueBytes(kotlin.ByteArray(1))), 1, DUMMY_NOTARY) as TransactionBuilder
val context = SerializationFactory.defaultFactory.defaultContext
.withClassLoader(appClassLoader)
val txBuilder = generateInitialMethod.invoke(contract, DUMMY_BANK_A.ref(1), 1, DUMMY_NOTARY) as TransactionBuilder
val context = SerializationFactory.defaultFactory.defaultContext.withClassLoader(appClassLoader)
val ledgerTx = txBuilder.toLedgerTransaction(services, context)
contract.verify(ledgerTx)
@ -121,11 +103,9 @@ class AttachmentLoadingTests {
fun `test that attachments retrieved over the network are not used for code`() {
driver(initialiseSerialization = false) {
installIsolatedCordappTo(bankAName)
val (_, bankA, bankB) = createNotaryAndTwoNodes()
eventuallyPassingTest {
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()
}
val (bankA, bankB) = createTwoNodes()
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()
}
}
}
@ -135,10 +115,8 @@ class AttachmentLoadingTests {
driver(initialiseSerialization = false) {
installIsolatedCordappTo(bankAName)
installIsolatedCordappTo(bankBName)
val (_, bankA, bankB) = createNotaryAndTwoNodes()
eventuallyPassingTest {
bankA.rpc.startFlowDynamic(flowInitiatorClass, bankB.nodeInfo.legalIdentities.first()).returnValue.getOrThrow()
}
val (bankA, bankB) = createTwoNodes()
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.flows.CashIssueFlow
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.transactions.RaftValidatingNotaryService
import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.nodeapi.User
import net.corda.testing.*
import net.corda.testing.driver.NodeHandle
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 rx.Observable
import java.util.*
import kotlin.test.assertEquals
class DistributedServiceTests {
lateinit var alice: NodeHandle
lateinit var notaries: List<NodeHandle.OutOfProcess>
lateinit var aliceProxy: CordaRPCOps
lateinit var raftNotaryIdentity: Party
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
val clusterSize = 3
private lateinit var alice: NodeHandle
private lateinit var notaryNodes: List<NodeHandle.OutOfProcess>
private lateinit var aliceProxy: CordaRPCOps
private lateinit var raftNotaryIdentity: Party
private lateinit var notaryStateMachines: Observable<Pair<Party, StateMachineUpdate>>
private fun setup(testBlock: () -> Unit) {
val testUser = User("test", "test", permissions = setOf(
startFlow<CashIssueFlow>(),
startFlow<CashPaymentFlow>(),
invokeRpc(CordaRPCOps::nodeInfo),
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()
val (notaryIdentity, notaryNodes) = notariesFuture.get()
raftNotaryIdentity = notaryIdentity
notaries = notaryNodes.map { it as NodeHandle.OutOfProcess }
driver(
extraCordappPackagesToScan = listOf("net.corda.finance.contracts"),
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, rpcUsers = listOf(testUser), cluster = ClusterSpec.Raft(clusterSize = 3))))
{
alice = startNode(providedName = ALICE.name, rpcUsers = listOf(testUser)).getOrThrow()
raftNotaryIdentity = defaultNotaryIdentity
notaryNodes = defaultNotaryHandle.nodeHandles.getOrThrow().map { it as NodeHandle.OutOfProcess }
assertEquals(notaries.size, clusterSize)
// Check that each notary has different identity as a node.
assertEquals(notaries.size, notaries.map { it.nodeInfo.chooseIdentity() }.toSet().size)
// Connect to Alice and the notaries
fun connectRpc(node: NodeHandle): CordaRPCOps {
val client = node.rpcClientToNode()
return client.start("test", "test").proxy
assertThat(notaryNodes).hasSize(3)
for (notaryNode in notaryNodes) {
assertThat(notaryNode.nodeInfo.legalIdentities).contains(raftNotaryIdentity)
}
// 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
@ -106,8 +110,8 @@ class DistributedServiceTests {
paySelf(5.POUNDS)
}
// Now kill a notary
with(notaries[0].process) {
// Now kill a notary node
with(notaryNodes[0].process) {
destroy()
waitFor()
}

View File

@ -18,6 +18,8 @@ import net.corda.testing.contracts.DummyContract
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver
import net.corda.testing.dummyCommand
import net.corda.testing.node.ClusterSpec
import net.corda.testing.node.NotarySpec
import org.junit.Test
import java.util.*
import kotlin.test.assertEquals
@ -28,13 +30,16 @@ class RaftNotaryServiceTests {
@Test
fun `detect double spend`() {
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts")) {
val (notaryParty) = startNotaryCluster(notaryName, 3).getOrThrow()
driver(
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 inputState = issueState(bankA, notaryParty)
val inputState = issueState(bankA, defaultNotaryIdentity)
val firstTxBuilder = TransactionBuilder(notaryParty)
val firstTxBuilder = TransactionBuilder(defaultNotaryIdentity)
.addInputState(inputState)
.addCommand(dummyCommand(bankA.services.myInfo.chooseIdentity().owningKey))
val firstSpendTx = bankA.services.signInitialTransaction(firstTxBuilder)
@ -42,7 +47,7 @@ class RaftNotaryServiceTests {
val firstSpend = bankA.services.startFlow(NotaryFlow.Client(firstSpendTx))
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())
addOutputState(dummyState, DummyContract.PROGRAM_ID)
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.testing.BOB
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.aliceAndBob
import net.corda.testing.contracts.DummyContract
import net.corda.testing.contracts.DummyState
import net.corda.testing.driver.driver
import net.corda.testing.dummyCommand
import net.corda.testing.notaryAliceAndBob
import org.junit.Test
import kotlin.test.assertEquals
@ -65,7 +65,7 @@ class LargeTransactionsTest {
val bigFile3 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 2)
val bigFile4 = InputStreamAndHash.createInMemoryTestZip(1024 * 1024 * 3, 3)
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts")) {
val (_, alice) = notaryAliceAndBob()
val (alice, _) = aliceAndBob()
alice.useRPC {
val hash1 = it.uploadAttachment(bigFile1.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.NodeHandle
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 java.util.*
@ -35,16 +37,14 @@ class P2PMessagingTest {
@Test
fun `communicating with a distributed service which we're part of`() {
driver(startNodesInProcess = true) {
val distributedService = startDistributedService()
startDriverWithDistributedService { distributedService ->
assertAllNodesAreUsed(distributedService, DISTRIBUTED_SERVICE_NAME, distributedService[0])
}
}
@Test
fun `distributed service requests are retried if one of the nodes in the cluster goes down without sending a response`() {
driver(startNodesInProcess = true) {
val distributedServiceNodes = startDistributedService()
startDriverWithDistributedService { distributedServiceNodes ->
val alice = startAlice()
val serviceAddress = alice.services.networkMapCache.run {
val notaryParty = notaryIdentities.randomOrNull()!!
@ -77,8 +77,7 @@ class P2PMessagingTest {
@Test
fun `distributed service request retries are persisted across client node restarts`() {
driver(startNodesInProcess = true) {
val distributedServiceNodes = startDistributedService()
startDriverWithDistributedService { distributedServiceNodes ->
val alice = startAlice()
val serviceAddress = alice.services.networkMapCache.run {
val notaryParty = notaryIdentities.randomOrNull()!!
@ -117,11 +116,10 @@ class P2PMessagingTest {
}
}
private fun DriverDSLExposedInterface.startDistributedService(): List<StartedNode<Node>> {
return startNotaryCluster(DISTRIBUTED_SERVICE_NAME, 2)
.getOrThrow()
.second
.map { (it as NodeHandle.InProcess).node }
private fun startDriverWithDistributedService(dsl: DriverDSLExposedInterface.(List<StartedNode<Node>>) -> Unit) {
driver(startNodesInProcess = true, notarySpecs = listOf(NotarySpec(DISTRIBUTED_SERVICE_NAME, cluster = ClusterSpec.Raft(clusterSize = 2)))) {
dsl(defaultNotaryHandle.nodeHandles.getOrThrow().map { (it as NodeHandle.InProcess).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.utilities.ProgressTracker
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.startFlow
import net.corda.nodeapi.User
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.chooseIdentity
import net.corda.testing.driver.driver
import org.junit.Assume.assumeFalse
@ -43,7 +42,6 @@ class NodeStatePersistenceTests {
val message = Message("Hello world!")
driver(isDebug = true, startNodesInProcess = isQuasarAgentSpecified()) {
val nodeName = {
startNotaryNode(DUMMY_NOTARY.name, validating = false).getOrThrow()
val nodeHandle = startNode(rpcUsers = listOf(user)).getOrThrow()
val nodeName = nodeHandle.nodeInfo.chooseIdentity().name
nodeHandle.rpcClientToNode().start(user.username, user.password).use {

View File

@ -31,6 +31,7 @@ import java.security.PublicKey
import java.util.*
import javax.annotation.concurrent.ThreadSafe
import kotlin.collections.HashMap
import kotlin.collections.HashSet
class NetworkMapCacheImpl(
networkMapCacheBase: NetworkMapCacheBaseInternal,
@ -85,7 +86,7 @@ open class PersistentNetworkMapCache(
override val loadDBSuccess get() = _loadDBSuccess
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,
configuration.additionalNodeInfoPollingFrequencyMsec)

View File

@ -50,14 +50,12 @@ import kotlin.test.assertNull
import kotlin.test.assertTrue
class CordaRPCOpsImplTest {
private companion object {
val testJar = "net/corda/node/testing/test.jar"
}
private lateinit var mockNet: MockNetwork
private lateinit var aliceNode: StartedNode<MockNode>
private lateinit var notaryNode: StartedNode<MockNode>
private lateinit var notary: Party
private lateinit var rpc: CordaRPCOps
private lateinit var stateMachineUpdates: Observable<StateMachineUpdate>
@ -69,7 +67,6 @@ class CordaRPCOpsImplTest {
@Before
fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.finance.contracts.asset"))
notaryNode = mockNet.createNotaryNode(validating = false)
aliceNode = mockNet.createNode()
rpc = SecureCordaRPCOps(aliceNode.services, aliceNode.smm, aliceNode.database, aliceNode.services)
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 CordaServiceTest {
lateinit var mockNet: MockNetwork
lateinit var notaryNode: StartedNode<MockNetwork.MockNode>
lateinit var nodeA: StartedNode<MockNetwork.MockNode>
private lateinit var mockNet: MockNetwork
private lateinit var nodeA: StartedNode<MockNetwork.MockNode>
@Before
fun start() {
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.node.internal","net.corda.finance"))
notaryNode = mockNet.createNotaryNode()
nodeA = mockNet.createNode()
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.
*/
@RunWith(Parameterized::class)
class TwoPartyTradeFlowTests(val anonymous: Boolean) {
class TwoPartyTradeFlowTests(private val anonymous: Boolean) {
companion object {
private val cordappPackages = listOf("net.corda.finance.contracts")
@JvmStatic
@ -93,7 +93,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
// allow interruption half way through.
mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
ledger(MockServices(cordappPackages), initialiseSerialization = false) {
val notaryNode = mockNet.createNotaryNode()
val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_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`() {
mockNet = MockNetwork(threadPerNode = true, cordappPackages = cordappPackages)
ledger(MockServices(cordappPackages), initialiseSerialization = false) {
val notaryNode = mockNet.createNotaryNode()
val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME)
val bankNode = mockNet.createPartyNode(BOC_NAME)
@ -199,7 +199,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
fun `shutdown and restore`() {
mockNet = MockNetwork(cordappPackages = cordappPackages)
ledger(MockServices(cordappPackages), initialiseSerialization = false) {
val notaryNode = mockNet.createNotaryNode()
val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
var bobNode = mockNet.createPartyNode(BOB_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
// 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 ...
return mockNet.createNode(MockNodeParameters(legalName = name), nodeFactory = { args ->
object : MockNetwork.MockNode(args) {
@ -307,7 +308,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
@Test
fun `check dependencies of sale asset are resolved`() {
mockNet = MockNetwork(cordappPackages = cordappPackages)
val notaryNode = mockNet.createNotaryNode()
val notaryNode = mockNet.defaultNotaryNode
val aliceNode = makeNodeWithTracking(ALICE_NAME)
val bobNode = makeNodeWithTracking(BOB_NAME)
val bankNode = makeNodeWithTracking(BOC_NAME)
@ -413,7 +414,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
@Test
fun `track works`() {
mockNet = MockNetwork(cordappPackages = cordappPackages)
val notaryNode = mockNet.createNotaryNode()
val notaryNode = mockNet.defaultNotaryNode
val aliceNode = makeNodeWithTracking(ALICE_NAME)
val bobNode = makeNodeWithTracking(BOB_NAME)
val bankNode = makeNodeWithTracking(BOC_NAME)
@ -568,7 +569,7 @@ class TwoPartyTradeFlowTests(val anonymous: Boolean) {
aliceError: Boolean,
expectedMessageSubstring: String
) {
val notaryNode = mockNet.createNotaryNode()
val notaryNode = mockNet.defaultNotaryNode
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
val bobNode = mockNet.createPartyNode(BOB_NAME)
val bankNode = mockNet.createPartyNode(BOC_NAME)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,10 +14,13 @@ import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.seconds
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.dummyCommand
import net.corda.testing.getDefaultNotary
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNodeParameters
import net.corda.testing.singleIdentity
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
@ -28,20 +31,19 @@ import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class NotaryServiceTests {
lateinit var mockNet: MockNetwork
lateinit var notaryServices: StartedNodeServices
lateinit var aliceServices: StartedNodeServices
lateinit var notary: Party
lateinit var alice: Party
private lateinit var mockNet: MockNetwork
private lateinit var notaryServices: StartedNodeServices
private lateinit var aliceServices: StartedNodeServices
private lateinit var notary: Party
private lateinit var alice: Party
@Before
fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
val notaryNode = mockNet.createNotaryNode(validating = false)
aliceServices = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME)).services
mockNet.runNetwork() // Clear network map registration messages
notaryServices = notaryNode.services
notary = notaryServices.getDefaultNotary()
notaryServices = mockNet.defaultNotaryNode.services //TODO get rid of that
notary = aliceServices.getDefaultNotary()
alice = aliceServices.myInfo.singleIdentity()
}
@ -155,7 +157,7 @@ class NotaryServiceTests {
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 signedByNode = services.signInitialTransaction(tx)
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.node.services.api.StartedNodeServices
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.dummyCommand
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNodeParameters
import net.corda.testing.singleIdentity
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
@ -28,21 +31,20 @@ import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class ValidatingNotaryServiceTests {
lateinit var mockNet: MockNetwork
lateinit var notaryServices: StartedNodeServices
lateinit var aliceServices: StartedNodeServices
lateinit var notary: Party
lateinit var alice: Party
private lateinit var mockNet: MockNetwork
private lateinit var notaryServices: StartedNodeServices
private lateinit var aliceServices: StartedNodeServices
private lateinit var notary: Party
private lateinit var alice: Party
@Before
fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
val notaryNode = mockNet.createNotaryNode()
val aliceNode = mockNet.createNode(MockNodeParameters(legalName = ALICE_NAME))
mockNet.runNetwork() // Clear network map registration messages
notaryServices = notaryNode.services
notaryServices = mockNet.defaultNotaryNode.services
aliceServices = aliceNode.services
notary = notaryServices.getDefaultNotary()
notary = mockNet.defaultNotaryIdentity
alice = aliceNode.info.singleIdentity()
}
@ -97,7 +99,7 @@ class ValidatingNotaryServiceTests {
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 signedByNode = serviceHub.signInitialTransaction(tx)
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.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.PortAllocation
import net.corda.testing.driver.driver
import org.junit.Test
@ -27,11 +26,10 @@ class AttachmentDemoTest {
invokeRpc(CordaRPCOps::wellKnownPartyFromX500Name),
invokeRpc(CordaRPCOps::internalVerifiedTransactionsFeed)
)))
val (_, nodeA, nodeB) = listOf(
startNotaryNode(DUMMY_NOTARY.name, validating = false),
val (nodeA, nodeB) = listOf(
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser, maximumHeapSize = "1g"),
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser, maximumHeapSize = "1g"))
.map { it.getOrThrow() }
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser, maximumHeapSize = "1g")
).map { it.getOrThrow() }
startWebserver(nodeB).getOrThrow()
val senderThread = supplyAsync {

View File

@ -4,7 +4,6 @@ import net.corda.core.internal.div
import net.corda.nodeapi.User
import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver
/**
@ -14,7 +13,6 @@ import net.corda.testing.driver.driver
fun main(args: Array<String>) {
val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.flows.FinalityFlow")))
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_B.name, rpcUsers = demoUser)
waitForAllNodesToFinish()

View File

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

View File

@ -23,12 +23,12 @@ class BankOfCordaRPCClientTest {
invokeRpc(CordaRPCOps::wellKnownPartyFromX500Name),
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(
startFlow<CashIssueAndPaymentFlow>()) + commonPermissions)
val bigCorpCFO = User("bigCorpCFO", "password2", permissions = emptySet<String>() + commonPermissions)
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))
).map { it.getOrThrow() }
@ -51,12 +51,11 @@ class BankOfCordaRPCClientTest {
// Kick-off actual Issuer Flow
val anonymous = true
val notary = bocProxy.notaryIdentities().first()
bocProxy.startFlow(::CashIssueAndPaymentFlow,
1000.DOLLARS, BIG_CORP_PARTY_REF,
bigCorporation,
anonymous,
notary).returnValue.getOrThrow()
defaultNotaryIdentity).returnValue.getOrThrow()
// Check Bank of Corda Vault Updates
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.CashPaymentFlow
import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.nodeapi.User
import net.corda.testing.BOC
import net.corda.testing.DUMMY_NOTARY
@ -58,7 +57,6 @@ private class BankOfCordaDriver {
when (role) {
Role.ISSUER -> {
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.finance.contracts.asset")) {
startNotaryNode(providedName = DUMMY_NOTARY.name, validating = true)
val bankUser = User(
BANK_USERNAME,
"test",
@ -83,7 +81,7 @@ private class BankOfCordaDriver {
}
else -> {
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) {
Role.ISSUE_CASH_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.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver
/**
@ -11,17 +10,17 @@ import net.corda.testing.driver.driver
* Do not use in a production environment.
*/
fun main(args: Array<String>) {
driver(dsl = {
val (controller, nodeA, nodeB) = listOf(
startNotaryNode(DUMMY_NOTARY.name, validating = false),
driver(useTestClock = true, isDebug = true) {
val (nodeA, nodeB) = listOf(
startNode(providedName = DUMMY_BANK_A.name),
startNode(providedName = DUMMY_BANK_B.name))
.map { it.getOrThrow() }
startNode(providedName = DUMMY_BANK_B.name)
).map { it.getOrThrow() }
val controller = defaultNotaryNode.getOrThrow()
startWebserver(controller)
startWebserver(nodeA)
startWebserver(nodeB)
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.module.SimpleModule
import com.fasterxml.jackson.module.kotlin.readValue
import net.corda.client.jackson.JacksonSupport
import net.corda.client.rpc.CordaRPCClient
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.identity.Party
@ -24,6 +25,7 @@ import net.corda.nodeapi.User
import net.corda.test.spring.springDriver
import net.corda.testing.*
import net.corda.testing.http.HttpApi
import net.corda.testing.node.NotarySpec
import org.apache.commons.io.IOUtils
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
@ -44,11 +46,17 @@ class IRSDemoTest : IntegrationTestCategory {
@Test
fun `runs IRS demo`() {
springDriver(useTestClock = true, isDebug = true, extraCordappPackagesToScan = listOf("net.corda.irs")) {
val (controller, nodeA, nodeB) = listOf(
startNotaryNode(DUMMY_NOTARY.name, validating = true, rpcUsers = rpcUsers),
springDriver(
useTestClock = true,
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_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")
@ -61,7 +69,7 @@ class IRSDemoTest : IntegrationTestCategory {
log.info("All webservers started")
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)
registerIRSModule(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?> {
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.utilities.loggerFor
import net.corda.testing.driver.*
import net.corda.testing.node.NotarySpec
import okhttp3.OkHttpClient
import okhttp3.Request
import java.net.ConnectException
@ -41,6 +42,7 @@ fun <A> springDriver(
useTestClock: Boolean = defaultParameters.useTestClock,
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
notarySpecs: List<NotarySpec>,
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
dsl: SpringDriverExposedDSLInterface.() -> A
) = genericDriver(
@ -54,9 +56,9 @@ fun <A> springDriver(
initialiseSerialization = initialiseSerialization,
startNodesInProcess = startNodesInProcess,
extraCordappPackagesToScan = extraCordappPackagesToScan,
notarySpecs = notarySpecs,
driverDslWrapper = { driverDSL:DriverDSL -> SpringBootDriverDSL(driverDSL) },
coerce = { it },
dsl = dsl
coerce = { it }, dsl = dsl
)
data class SpringBootDriverDSL(

View File

@ -31,7 +31,6 @@ import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletableFuture.allOf
/**
* 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)
node2.internals.registerInitiatedFlow(FixingFlow.Fixer::class.java)
val notaryId = notary.info.legalIdentities[0]
@InitiatingFlow
class StartDealFlow(val otherParty: Party,
val payload: AutoOffer) : FlowLogic<SignedTransaction>() {
@ -166,7 +163,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
val instigator = StartDealFlow(
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
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.node.internal.StartedNode
import net.corda.node.services.statemachine.StateMachineManager
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_REGULATOR
import net.corda.testing.node.*
import net.corda.testing.node.MockNetwork.MockNode
@ -71,14 +70,13 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
networkSendManuallyPumped = networkSendManuallyPumped,
threadPerNode = runAsync,
cordappPackages = listOf("net.corda.irs.contract", "net.corda.finance.contract", "net.corda.irs"))
val notary = mockNet.createNotaryNode(defaultParams.copy(legalName = DUMMY_NOTARY.name), false)
// TODO: Regulatory nodes don't actually exist properly, this is a last minute demo request.
// So we just fire a message at a node that doesn't know how to handle it, and it'll ignore it.
// But that's fine for visualisation purposes.
val regulators = listOf(mockNet.createUnstartedNode(defaultParams.copy(legalName = DUMMY_REGULATOR.name)))
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.
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 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.

View File

@ -3,7 +3,9 @@ package net.corda.vega
import com.opengamma.strata.product.common.BuySell
import net.corda.core.identity.CordaX500Name
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.http.HttpApi
import net.corda.vega.api.PortfolioApi
@ -27,7 +29,6 @@ class SimmValuationTest : IntegrationTestCategory {
@Test
fun `runs SIMM valuation demo`() {
driver(isDebug = true, extraCordappPackagesToScan = listOf("net.corda.vega.contracts")) {
startNotaryNode(DUMMY_NOTARY.name, validating = false).getOrThrow()
val nodeAFuture = startNode(providedName = nodeALegalName)
val nodeBFuture = startNode(providedName = nodeBLegalName)
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_B
import net.corda.testing.DUMMY_BANK_C
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver
/**
@ -13,17 +12,17 @@ import net.corda.testing.driver.driver
* via the web api.
*/
fun main(args: Array<String>) {
driver(dsl = {
val notaryFuture = startNotaryNode(DUMMY_NOTARY.name, validating = false)
val nodeAFuture = startNode(providedName = DUMMY_BANK_A.name)
val nodeBFuture = startNode(providedName = DUMMY_BANK_B.name)
val nodeCFuture = startNode(providedName = DUMMY_BANK_C.name)
val (nodeA, nodeB, nodeC) = listOf(nodeAFuture, nodeBFuture, nodeCFuture, notaryFuture).map { it.getOrThrow() }
driver(isDebug = true) {
val (nodeA, nodeB, nodeC) = listOf(
startNode(providedName = DUMMY_BANK_A.name),
startNode(providedName = DUMMY_BANK_B.name),
startNode(providedName = DUMMY_BANK_C.name)
).map { it.getOrThrow() }
startWebserver(nodeA)
startWebserver(nodeB)
startWebserver(nodeC)
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.startFlow
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.driver
import net.corda.testing.driver.poll
@ -30,8 +33,7 @@ class TraderDemoTest {
startFlow<CommercialPaperIssueFlow>(),
all()))
driver(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance")) {
val (_, nodeA, nodeB, bankNode) = listOf(
startNotaryNode(DUMMY_NOTARY.name, validating = false),
val (nodeA, nodeB, bankNode) = listOf(
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = listOf(demoUser)),
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = listOf(demoUser)),
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.DUMMY_BANK_A
import net.corda.testing.DUMMY_BANK_B
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.driver
import net.corda.traderdemo.flow.CommercialPaperIssueFlow
import net.corda.traderdemo.flow.SellerFlow
@ -27,7 +26,6 @@ fun main(args: Array<String>) {
val user = User("user1", "test", permissions = setOf(startFlow<CashIssueFlow>(),
startFlow<CommercialPaperIssueFlow>(),
startFlow<SellerFlow>()))
startNotaryNode(DUMMY_NOTARY.name, validating = false)
startNode(providedName = DUMMY_BANK_A.name, rpcUsers = demoUser)
startNode(providedName = DUMMY_BANK_B.name, rpcUsers = demoUser)
startNode(providedName = BOC.name, rpcUsers = listOf(user))

View File

@ -290,7 +290,6 @@ class FlowStackSnapshotTest {
@Test
fun `flowStackSnapshot object is serializable`() {
val mockNet = MockNetwork(threadPerNode = true)
mockNet.createNotaryNode()
val node = mockNet.createPartyNode()
node.internals.registerInitiatedFlow(DummyFlow::class.java)
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.node.internal.NodeStartup
import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.DUMMY_REGULATOR
import net.corda.testing.ProjectStructure.projectRootDir
import org.assertj.core.api.Assertions.assertThat
@ -18,7 +17,6 @@ import java.util.concurrent.ScheduledExecutorService
class DriverTests {
companion object {
private val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)
private fun nodeMustBeUp(handleFuture: CordaFuture<out NodeHandle>) = handleFuture.getOrThrow().apply {
@ -32,26 +30,15 @@ class DriverTests {
// Check that the port is bound
addressMustNotBeBound(executorService, hostAndPort)
}
}
@Test
fun `simple node startup and shutdown`() {
val handles = driver {
val notary = startNotaryNode(DUMMY_NOTARY.name, validating = false)
val handle = driver {
val regulator = startNode(providedName = DUMMY_REGULATOR.name)
listOf(nodeMustBeUp(notary), nodeMustBeUp(regulator))
nodeMustBeUp(regulator)
}
handles.map { nodeMustBeDown(it) }
}
@Test
fun `starting node with no services`() {
val noService = driver {
val noService = startNode(providedName = DUMMY_BANK_A.name)
nodeMustBeUp(noService)
}
nodeMustBeDown(noService)
nodeMustBeDown(handle)
}
@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
* 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 nodeFuture by lazy {
if (ifNotaryIsValidating != null) {
driver.startNotaryNode(providedName = party.name, rpcUsers = rpcUsers, validating = ifNotaryIsValidating)
} else {
driver.startNode(providedName = party.name, rpcUsers = rpcUsers)
}
}
val nodeFuture by lazy { driver.startNode(providedName = party.name, rpcUsers = rpcUsers) }
val node by lazy { nodeFuture.get()!! }
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
* 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
* 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
* for it: you won't have [DUMMY_NOTARY_KEY].
* Returns plain, entirely stock nodes pre-configured with the [ALICE] and [BOB] X.500 names in that order. They have been
* started up in parallel and are now ready to use.
*/
fun DriverDSLExposedInterface.notary(): PredefinedTestNode = PredefinedTestNode(DUMMY_NOTARY, this, true)
/**
* 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()
fun DriverDSLExposedInterface.aliceAndBob(): List<PredefinedTestNode> {
val alice = alice()
val bob = bob()
listOf(notary.nodeFuture, alice.nodeFuture, bob.nodeFuture).transpose().get()
return listOf(alice, bob, notary)
listOf(alice.nodeFuture, bob.nodeFuture).transpose().get()
return listOf(alice, bob)
}

View File

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

View File

@ -16,6 +16,7 @@ import net.corda.core.identity.Party
import net.corda.core.internal.*
import net.corda.core.internal.concurrent.*
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.NetworkParameters
import net.corda.core.node.NodeInfo
import net.corda.core.node.NotaryInfo
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.config.toConfig
import net.corda.nodeapi.internal.addShutdownHook
import net.corda.testing.ALICE
import net.corda.testing.BOB
import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.*
import net.corda.testing.common.internal.NetworkParametersCopier
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.NotarySpec
import okhttp3.OkHttpClient
import okhttp3.Request
import org.slf4j.Logger
@ -84,10 +84,48 @@ private val DRIVER_REQUIRED_PERMISSIONS = setOf(
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.
*/
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.
*
@ -110,13 +148,6 @@ interface DriverDSLExposedInterface : CordformContext {
startInSameProcess: Boolean? = defaultParameters.startInSameProcess,
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.
*
@ -131,24 +162,6 @@ interface DriverDSLExposedInterface : CordformContext {
maximumHeapSize: String = "200m"
): 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. */
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 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].
* @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.
* @return The value returned in the [dsl] closure.
*/
@ -323,6 +338,7 @@ fun <A> driver(
useTestClock: Boolean = defaultParameters.useTestClock,
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
notarySpecs: List<NotarySpec> = defaultParameters.notarySpecs,
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
dsl: DriverDSLExposedInterface.() -> A
): A {
@ -335,6 +351,7 @@ fun <A> driver(
useTestClock = useTestClock,
isDebug = isDebug,
startNodesInProcess = startNodesInProcess,
notarySpecs = notarySpecs,
extraCordappPackagesToScan = extraCordappPackagesToScan
),
coerce = { it },
@ -368,6 +385,7 @@ data class DriverParameters(
val useTestClock: Boolean = false,
val initialiseSerialization: Boolean = true,
val startNodesInProcess: Boolean = false,
val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY.name)),
val extraCordappPackagesToScan: List<String> = emptyList()
) {
fun setIsDebug(isDebug: Boolean) = copy(isDebug = isDebug)
@ -379,6 +397,7 @@ data class DriverParameters(
fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization)
fun setStartNodesInProcess(startNodesInProcess: Boolean) = copy(startNodesInProcess = startNodesInProcess)
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,
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
startNodesInProcess: Boolean = defaultParameters.startNodesInProcess,
notarySpecs: List<NotarySpec>,
extraCordappPackagesToScan: List<String> = defaultParameters.extraCordappPackagesToScan,
driverDslWrapper: (DriverDSL) -> D,
coerce: (D) -> DI,
dsl: DI.() -> A
coerce: (D) -> DI, dsl: DI.() -> A
): A {
val serializationEnv = initialiseTestSerialization(initialiseSerialization)
val driverDsl = driverDslWrapper(
@ -443,7 +462,8 @@ fun <DI : DriverDSLExposedInterface, D : DriverDSLInternalInterface, A> genericD
useTestClock = useTestClock,
isDebug = isDebug,
startNodesInProcess = startNodesInProcess,
extraCordappPackagesToScan = extraCordappPackagesToScan
extraCordappPackagesToScan = extraCordappPackagesToScan,
notarySpecs = notarySpecs
)
)
val shutdownHook = addShutdownHook(driverDsl::shutdown)
@ -643,7 +663,8 @@ class DriverDSL(
val useTestClock: Boolean,
val isDebug: Boolean,
val startNodesInProcess: Boolean,
extraCordappPackagesToScan: List<String>
extraCordappPackagesToScan: List<String>,
val notarySpecs: List<NotarySpec>
) : DriverDSLInternalInterface {
private var _executorService: ScheduledExecutorService? = null
val executorService get() = _executorService!!
@ -656,7 +677,9 @@ class DriverDSL(
private val nodeInfoFilesCopier = NodeInfoFilesCopier()
// 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 var networkParameters: NetworkParametersCopier? = null
private lateinit var _notaries: List<NotaryHandle>
override val notaryHandles: List<NotaryHandle> get() = _notaries
private lateinit var networkParameters: NetworkParametersCopier
class State {
val processes = ArrayList<CordaFuture<Process>>()
@ -744,16 +767,6 @@ class DriverDSL(
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>> {
return nodes.map { node ->
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 {
val protocol = if (handle.configuration.useHTTPS) "https://" else "http://"
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())
_shutdownManager = ShutdownManager(executorService)
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 {
@ -925,10 +963,7 @@ class DriverDSL(
maximumHeapSize: String): CordaFuture<NodeHandle> {
val configuration = config.parseAsNodeConfiguration()
val baseDirectory = configuration.baseDirectory.createDirectories()
if (networkParameters == null) {
networkParameters = NetworkParametersCopier(testNetworkParameters(emptyList()))
}
networkParameters!!.install(baseDirectory)
networkParameters.install(baseDirectory)
nodeInfoFilesCopier.addConfig(baseDirectory)
val onNodeExit: () -> Unit = {
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.random63BitValue
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.internal.createDirectories
import net.corda.core.internal.createDirectory
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:
*
* 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(),
private val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped,
@ -117,6 +121,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy,
private val defaultFactory: (MockNodeArgs) -> MockNode = defaultParameters.defaultFactory,
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
private val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY.name)),
private val cordappPackages: List<String> = defaultParameters.cordappPackages) : Closeable {
/** Helper constructor for creating a [MockNetwork] with custom parameters from Java. */
constructor(parameters: MockNetworkParameters) : this(defaultParameters = parameters)
@ -128,22 +133,43 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch)
// A unique identifier for this network to segregate databases with the same nodeID but different networks.
private val networkId = random63BitValue()
private lateinit var networkParameters: NetworkParametersCopier
private var notaryInfos: MutableList<NotaryInfo>? = ArrayList()
private val _nodes = ArrayList<MockNode>()
private val networkParameters: NetworkParametersCopier
private val _nodes = mutableListOf<MockNode>()
private val serializationEnv = initialiseTestSerialization(initialiseSerialization)
private val sharedUserCount = AtomicInteger(0)
/** A read only view of the current set of executing 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.
*/
private val sharedUserCount = AtomicInteger(0)
private val sharedServerThread = object : ServiceAffinityExecutor("Mock network", 1) {
override fun shutdown() {
// 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(
args.config,
TestClock(),
@ -188,20 +240,12 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
override val started: StartedNode<MockNode>? get() = uncheckedCast(super.started)
override fun start(): StartedNode<MockNode> {
installNetworkParameters()
mockNet.networkParameters.install(configuration.baseDirectory)
val started: StartedNode<MockNode> = uncheckedCast(super.start())
advertiseNodeToNetwork(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>) {
mockNet.nodes
.mapNotNull { it.started }
@ -273,9 +317,6 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
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
override fun acceptableLiveFiberCountOnStop(): Int = acceptableLiveFiberCountOnStop
@ -321,23 +362,11 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
doReturn(makeTestDataSourceProperties("node_${id}_net_$networkId")).whenever(it).dataSourceProperties
parameters.configOverrides(it)
}
val node = nodeFactory(MockNodeArgs(config, this, id, parameters.entropyRoot))
_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) {
node.start()
}
return node
}
@ -365,24 +394,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
}
@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> {
return createNode(MockNodeParameters(legalName = legalName))
}
@ -418,14 +430,16 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
override fun close() {
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) {
MockNetwork().use {
it.runNetwork()
val notary = it.createNotaryNode()
val nodes = (1..nodesCount).map { _ -> it.createPartyNode() }
action(it, nodes, notary)
fun network(nodesCount: Int, action: MockNetwork.(List<StartedNode<MockNetwork.MockNode>>) -> Unit) {
MockNetwork().use { mockNet ->
val nodes = (1..nodesCount).map { mockNet.createPartyNode() }
mockNet.action(nodes)
}
}

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.testing.ALICE
import net.corda.testing.BOB
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.PortAllocation
import net.corda.testing.driver.driver
import java.time.Instant
import java.util.*
class ExplorerSimulation(val options: OptionSet) {
class ExplorerSimulation(private val options: OptionSet) {
private val user = User("user1", "test", permissions = setOf(
startFlow<CashPaymentFlow>(),
startFlow<CashConfigDataFlow>()
@ -67,23 +66,16 @@ class ExplorerSimulation(val options: OptionSet) {
val portAllocation = PortAllocation.Incremental(20000)
driver(portAllocation = portAllocation, extraCordappPackagesToScan = listOf("net.corda.finance")) {
// 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 = arrayListOf(user),
customOverrides = mapOf("nearestCity" to "Milan"))
val bob = startNode(providedName = BOB.name, rpcUsers = arrayListOf(user),
customOverrides = mapOf("nearestCity" to "Madrid"))
val alice = startNode(providedName = ALICE.name, rpcUsers = listOf(user))
val bob = startNode(providedName = BOB.name, rpcUsers = listOf(user))
val ukBankName = CordaX500Name(organisation = "UK Bank Plc", locality = "London", country = "GB")
val usaBankName = CordaX500Name(organisation = "USA Bank Corp", locality = "New York", country = "US")
val issuerGBP = startNode(providedName = ukBankName, rpcUsers = arrayListOf(manager),
customOverrides = mapOf(
"issuableCurrencies" to listOf("GBP"),
"nearestCity" to "London"))
val issuerUSD = startNode(providedName = usaBankName, rpcUsers = arrayListOf(manager),
customOverrides = mapOf(
"issuableCurrencies" to listOf("USD"),
"nearestCity" to "New York"))
val issuerGBP = startNode(providedName = ukBankName, rpcUsers = listOf(manager),
customOverrides = mapOf("issuableCurrencies" to listOf("GBP")))
val issuerUSD = startNode(providedName = usaBankName, rpcUsers = listOf(manager),
customOverrides = mapOf("issuableCurrencies" to listOf("USD")))
notaryNode = notary.get()
notaryNode = defaultNotaryNode.get()
aliceNode = alice.get()
bobNode = bob.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.SSLConfiguration
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.client.ActiveMQClient
import org.apache.activemq.artemis.api.core.client.ClientProducer
@ -77,6 +78,7 @@ fun <A> verifierDriver(
useTestClock: Boolean = false,
startNodesInProcess: Boolean = false,
extraCordappPackagesToScan: List<String> = emptyList(),
notarySpecs: List<NotarySpec> = emptyList(),
dsl: VerifierExposedDSLInterface.() -> A
) = genericDriver(
driverDsl = VerifierDriverDSL(
@ -88,7 +90,8 @@ fun <A> verifierDriver(
useTestClock = useTestClock,
isDebug = isDebug,
startNodesInProcess = startNodesInProcess,
extraCordappPackagesToScan = extraCordappPackagesToScan
extraCordappPackagesToScan = extraCordappPackagesToScan,
notarySpecs = notarySpecs
)
),
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_NAME
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.node.NotarySpec
import org.junit.Test
import java.util.*
import java.util.concurrent.atomic.AtomicInteger
@ -128,15 +129,15 @@ class VerifierTests {
@Test
fun `single verifier works with a node`() {
verifierDriver(extraCordappPackagesToScan = listOf("net.corda.finance.contracts")) {
val (notaryNode, aliceNode) = listOf(
startNotaryNode(DUMMY_NOTARY.name, verifierType = VerifierType.OutOfProcess),
startNode(providedName = ALICE.name)
).transpose().getOrThrow()
verifierDriver(
extraCordappPackagesToScan = listOf("net.corda.finance.contracts"),
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, verifierType = VerifierType.OutOfProcess))
) {
val aliceNode = startNode(providedName = ALICE.name).getOrThrow()
val notaryNode = defaultNotaryNode.getOrThrow()
val alice = aliceNode.rpc.wellKnownPartyFromX500Name(ALICE_NAME)!!
val notary = notaryNode.rpc.notaryPartyFromX500Name(DUMMY_NOTARY.name)!!
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)
for (i in 1..10) {
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.ScheduledExecutorService
class DriverTests {
class WebserverDriverTests {
companion object {
val executorService: ScheduledExecutorService = Executors.newScheduledThreadPool(2)