mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Check vault updates in IssuerFlowTest
Modify issuer flow test to verify the consumed/produced states, rather than just checking the transaction matches the value returned via the flow state machine. This is both a simpler and more relevant test.
This commit is contained in:
parent
7caee508ec
commit
d6d5edc33b
@ -5,7 +5,13 @@ import net.corda.core.contracts.DOLLARS
|
||||
import net.corda.core.contracts.`issued by`
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.node.services.trackBy
|
||||
import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.node.utilities.transaction
|
||||
import net.corda.testing.expect
|
||||
import net.corda.testing.expectEvents
|
||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
@ -51,15 +57,39 @@ class CashPaymentFlowTests {
|
||||
val payTo = notaryNode.info.legalIdentity
|
||||
val expectedPayment = 500.DOLLARS
|
||||
val expectedChange = 1500.DOLLARS
|
||||
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expectedPayment,
|
||||
payTo)).resultFuture
|
||||
mockNet.runNetwork()
|
||||
val (paymentTx, receipient) = future.getOrThrow()
|
||||
val states = paymentTx.tx.outputs.map { it.data }.filterIsInstance<Cash.State>()
|
||||
val paymentState: Cash.State = states.single { it.owner == receipient }
|
||||
val changeState: Cash.State = states.single { it != paymentState }
|
||||
assertEquals(expectedChange.`issued by`(bankOfCorda.ref(ref)), changeState.amount)
|
||||
assertEquals(expectedPayment.`issued by`(bankOfCorda.ref(ref)), paymentState.amount)
|
||||
|
||||
bankOfCordaNode.database.transaction {
|
||||
// Register for vault updates
|
||||
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
||||
val (_, vaultUpdatesBoc) = bankOfCordaNode.services.vaultQueryService.trackBy<Cash.State>(criteria)
|
||||
val (_, vaultUpdatesBankClient) = notaryNode.services.vaultQueryService.trackBy<Cash.State>(criteria)
|
||||
|
||||
val future = bankOfCordaNode.services.startFlow(CashPaymentFlow(expectedPayment,
|
||||
payTo)).resultFuture
|
||||
mockNet.runNetwork()
|
||||
future.getOrThrow()
|
||||
|
||||
// Check Bank of Corda vault updates - we take in some issued cash and split it into $500 to the notary
|
||||
// and $1,500 back to us, so we expect to consume one state, produce one state for our own vault
|
||||
vaultUpdatesBoc.expectEvents {
|
||||
expect { update ->
|
||||
require(update.consumed.size == 1) { "Expected 1 consumed states, actual: $update" }
|
||||
require(update.produced.size == 1) { "Expected 1 produced states, actual: $update" }
|
||||
val changeState = update.produced.single().state.data as Cash.State
|
||||
assertEquals(expectedChange.`issued by`(bankOfCorda.ref(ref)), changeState.amount)
|
||||
}
|
||||
}
|
||||
|
||||
// Check notary node vault updates
|
||||
vaultUpdatesBankClient.expectEvents {
|
||||
expect { update ->
|
||||
require(update.consumed.isEmpty()) { update.consumed.size }
|
||||
require(update.produced.size == 1) { update.produced.size }
|
||||
val paymentState = update.produced.single().state.data as Cash.State
|
||||
assertEquals(expectedPayment.`issued by`(bankOfCorda.ref(ref)), paymentState.amount)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,30 +1,28 @@
|
||||
package net.corda.flows
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import net.corda.testing.contracts.calculateRandomlySizedAmounts
|
||||
import net.corda.contracts.asset.Cash
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.DOLLARS
|
||||
import net.corda.core.contracts.currency
|
||||
import net.corda.core.flows.FlowException
|
||||
import net.corda.core.internal.FlowStateMachine
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.map
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.toFuture
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.node.services.trackBy
|
||||
import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.testing.DUMMY_NOTARY
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.flows.IssuerFlow.IssuanceRequester
|
||||
import net.corda.testing.BOC
|
||||
import net.corda.testing.MEGA_CORP
|
||||
import net.corda.node.utilities.transaction
|
||||
import net.corda.testing.*
|
||||
import net.corda.testing.contracts.calculateRandomlySizedAmounts
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetwork.MockNode
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import rx.Observable
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
class IssuerFlowTest {
|
||||
@ -39,11 +37,6 @@ class IssuerFlowTest {
|
||||
notaryNode = mockNet.createNotaryNode(null, DUMMY_NOTARY.name)
|
||||
bankOfCordaNode = mockNet.createPartyNode(notaryNode.network.myAddress, BOC.name)
|
||||
bankClientNode = mockNet.createPartyNode(notaryNode.network.myAddress, MEGA_CORP.name)
|
||||
val nodes = listOf(notaryNode, bankOfCordaNode, bankClientNode)
|
||||
|
||||
nodes.forEach { node ->
|
||||
nodes.map { it.info.legalIdentityAndCert }.forEach(node.services.identityService::registerIdentity)
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
@ -53,24 +46,82 @@ class IssuerFlowTest {
|
||||
|
||||
@Test
|
||||
fun `test issuer flow`() {
|
||||
// using default IssueTo Party Reference
|
||||
val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, 1000000.DOLLARS,
|
||||
bankClientNode.info.legalIdentity, OpaqueBytes.of(123))
|
||||
assertEquals(issuerResult.get().stx, issuer.get().resultFuture.get())
|
||||
val (vaultUpdatesBoc, vaultUpdatesBankClient) = bankOfCordaNode.database.transaction {
|
||||
// Register for vault updates
|
||||
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
||||
val (_, vaultUpdatesBoc) = bankOfCordaNode.services.vaultQueryService.trackBy<Cash.State>(criteria)
|
||||
val (_, vaultUpdatesBankClient) = bankClientNode.services.vaultQueryService.trackBy<Cash.State>(criteria)
|
||||
|
||||
// using default IssueTo Party Reference
|
||||
val issuerResult = runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, 1000000.DOLLARS,
|
||||
bankClientNode.info.legalIdentity, OpaqueBytes.of(123))
|
||||
issuerResult.get()
|
||||
|
||||
Pair(vaultUpdatesBoc, vaultUpdatesBankClient)
|
||||
}
|
||||
|
||||
// Check Bank of Corda Vault Updates
|
||||
vaultUpdatesBoc.expectEvents {
|
||||
sequence(
|
||||
// ISSUE
|
||||
expect { update ->
|
||||
require(update.consumed.isEmpty()) { "Expected 0 consumed states, actual: $update" }
|
||||
require(update.produced.size == 1) { "Expected 1 produced states, actual: $update" }
|
||||
val issued = update.produced.single().state.data as Cash.State
|
||||
require(issued.owner == bankOfCordaNode.info.legalIdentity)
|
||||
require(issued.owner != bankClientNode.info.legalIdentity)
|
||||
},
|
||||
// MOVE
|
||||
expect { update ->
|
||||
require(update.consumed.size == 1) { "Expected 1 consumed states, actual: $update" }
|
||||
require(update.produced.isEmpty()) { "Expected 0 produced states, actual: $update" }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Check Bank Client Vault Updates
|
||||
vaultUpdatesBankClient.expectEvents {
|
||||
// MOVE
|
||||
expect { update ->
|
||||
require(update.consumed.isEmpty()) { update.consumed.size }
|
||||
require(update.produced.size == 1) { update.produced.size }
|
||||
val paidState = update.produced.single().state.data as Cash.State
|
||||
require(paidState.owner == bankClientNode.info.legalIdentity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test issuer flow rejects restricted`() {
|
||||
// try to issue an amount of a restricted currency
|
||||
assertFailsWith<FlowException> {
|
||||
runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, Amount(100000L, currency("BRL")),
|
||||
bankClientNode.info.legalIdentity, OpaqueBytes.of(123)).issueRequestResult.getOrThrow()
|
||||
bankClientNode.info.legalIdentity, OpaqueBytes.of(123)).getOrThrow()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test issue flow to self`() {
|
||||
// using default IssueTo Party Reference
|
||||
val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankOfCordaNode, 1000000.DOLLARS,
|
||||
bankOfCordaNode.info.legalIdentity, OpaqueBytes.of(123))
|
||||
assertEquals(issuerResult.get().stx, issuer.get().resultFuture.get())
|
||||
val vaultUpdatesBoc = bankOfCordaNode.database.transaction {
|
||||
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
||||
val (_, vaultUpdatesBoc) = bankOfCordaNode.services.vaultQueryService.trackBy<Cash.State>(criteria)
|
||||
|
||||
// using default IssueTo Party Reference
|
||||
runIssuerAndIssueRequester(bankOfCordaNode, bankOfCordaNode, 1000000.DOLLARS,
|
||||
bankOfCordaNode.info.legalIdentity, OpaqueBytes.of(123)).getOrThrow()
|
||||
vaultUpdatesBoc
|
||||
}
|
||||
|
||||
// Check Bank of Corda Vault Updates
|
||||
vaultUpdatesBoc.expectEvents {
|
||||
sequence(
|
||||
// ISSUE
|
||||
expect { update ->
|
||||
require(update.consumed.isEmpty()) { "Expected 0 consumed states, actual: $update" }
|
||||
require(update.produced.size == 1) { "Expected 1 produced states, actual: $update" }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -83,7 +134,7 @@ class IssuerFlowTest {
|
||||
bankClientNode.info.legalIdentity, OpaqueBytes.of(123))
|
||||
}
|
||||
handles.forEach {
|
||||
require(it.issueRequestResult.get().stx is SignedTransaction)
|
||||
require(it.get().stx is SignedTransaction)
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,20 +142,10 @@ class IssuerFlowTest {
|
||||
issueToNode: MockNode,
|
||||
amount: Amount<Currency>,
|
||||
party: Party,
|
||||
ref: OpaqueBytes): RunResult {
|
||||
ref: OpaqueBytes): ListenableFuture<AbstractCashFlow.Result> {
|
||||
val issueToPartyAndRef = party.ref(ref)
|
||||
val issuerFlows: Observable<IssuerFlow.Issuer> = issuerNode.registerInitiatedFlow(IssuerFlow.Issuer::class.java)
|
||||
val firstIssuerFiber = issuerFlows.toFuture().map { it.stateMachine }
|
||||
|
||||
val issueRequest = IssuanceRequester(amount, party, issueToPartyAndRef.reference, issuerNode.info.legalIdentity,
|
||||
anonymous = false)
|
||||
val issueRequestResultFuture = issueToNode.services.startFlow(issueRequest).resultFuture
|
||||
|
||||
return IssuerFlowTest.RunResult(firstIssuerFiber, issueRequestResultFuture)
|
||||
return issueToNode.services.startFlow(issueRequest).resultFuture
|
||||
}
|
||||
|
||||
private data class RunResult(
|
||||
val issuer: ListenableFuture<FlowStateMachine<*>>,
|
||||
val issueRequestResult: ListenableFuture<AbstractCashFlow.Result>
|
||||
)
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
package net.corda.bank
|
||||
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import net.corda.contracts.asset.Cash
|
||||
import net.corda.core.contracts.DOLLARS
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.node.services.trackBy
|
||||
import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.flows.IssuerFlow.IssuanceRequester
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.node.services.startFlowPermission
|
||||
@ -33,10 +37,11 @@ class BankOfCordaRPCClientTest {
|
||||
val bigCorpProxy = bigCorpClient.start("bigCorpCFO", "password2").proxy
|
||||
|
||||
// Register for Bank of Corda Vault updates
|
||||
val vaultUpdatesBoc = bocProxy.vaultAndUpdates().second
|
||||
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
||||
val (_, vaultUpdatesBoc) = bocProxy.vaultTrackByCriteria<Cash.State>(Cash.State::class.java, criteria)
|
||||
|
||||
// Register for Big Corporation Vault updates
|
||||
val vaultUpdatesBigCorp = bigCorpProxy.vaultAndUpdates().second
|
||||
val (_, vaultUpdatesBigCorp) = bigCorpProxy.vaultTrackByCriteria<Cash.State>(Cash.State::class.java, criteria)
|
||||
|
||||
// Kick-off actual Issuer Flow
|
||||
// TODO: Update checks below to reflect states consumed/produced under anonymisation
|
||||
|
Loading…
Reference in New Issue
Block a user