mirror of
https://github.com/corda/corda.git
synced 2025-01-30 08:04:16 +00:00
Renaming matchers
This commit is contained in:
parent
0780d6051e
commit
fc5cc89fdb
@ -5,8 +5,8 @@ import com.natpryce.hamkrest.*
|
|||||||
import com.natpryce.hamkrest.assertion.assert
|
import com.natpryce.hamkrest.assertion.assert
|
||||||
import net.corda.core.contracts.Attachment
|
import net.corda.core.contracts.Attachment
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.matchers.fails
|
import net.corda.core.flows.matchers.flow.willThrow
|
||||||
import net.corda.core.flows.matchers.succeedsWith
|
import net.corda.core.flows.matchers.flow.willReturn
|
||||||
import net.corda.core.flows.mixins.WithMockNet
|
import net.corda.core.flows.mixins.WithMockNet
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
@ -51,7 +51,7 @@ class AttachmentTests : WithMockNet {
|
|||||||
// Get node one to run a flow to fetch it and insert it.
|
// Get node one to run a flow to fetch it and insert it.
|
||||||
assert.that(
|
assert.that(
|
||||||
bobNode.startAttachmentFlow(id, alice),
|
bobNode.startAttachmentFlow(id, alice),
|
||||||
succeedsWith(noAttachments()))
|
willReturn(noAttachments()))
|
||||||
|
|
||||||
// Verify it was inserted into node one's store.
|
// Verify it was inserted into node one's store.
|
||||||
val attachment = bobNode.getAttachmentWithId(id)
|
val attachment = bobNode.getAttachmentWithId(id)
|
||||||
@ -62,7 +62,7 @@ class AttachmentTests : WithMockNet {
|
|||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
bobNode.startAttachmentFlow(id, alice),
|
bobNode.startAttachmentFlow(id, alice),
|
||||||
succeedsWith(soleAttachment(attachment)))
|
willReturn(soleAttachment(attachment)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -72,10 +72,14 @@ class AttachmentTests : WithMockNet {
|
|||||||
// Get node one to fetch a non-existent attachment.
|
// Get node one to fetch a non-existent attachment.
|
||||||
assert.that(
|
assert.that(
|
||||||
bobNode.startAttachmentFlow(hash, alice),
|
bobNode.startAttachmentFlow(hash, alice),
|
||||||
fails<FetchDataFlow.HashNotFound>(
|
willThrow(withRequestedHash(hash)))
|
||||||
has("requested hash", { it.requested }, equalTo(hash))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun withRequestedHash(expected: SecureHash) = has(
|
||||||
|
"requested hash",
|
||||||
|
FetchDataFlow.HashNotFound::requested,
|
||||||
|
equalTo(expected))
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun maliciousResponse() {
|
fun maliciousResponse() {
|
||||||
// Make a node that doesn't do sanity checking at load time.
|
// Make a node that doesn't do sanity checking at load time.
|
||||||
@ -96,7 +100,7 @@ class AttachmentTests : WithMockNet {
|
|||||||
// Get n1 to fetch the attachment. Should receive corrupted bytes.
|
// Get n1 to fetch the attachment. Should receive corrupted bytes.
|
||||||
assert.that(
|
assert.that(
|
||||||
bobNode.startAttachmentFlow(id, badAlice),
|
bobNode.startAttachmentFlow(id, badAlice),
|
||||||
fails<FetchDataFlow.DownloadedVsRequestedDataMismatch>()
|
willThrow<FetchDataFlow.DownloadedVsRequestedDataMismatch>()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ import com.natpryce.hamkrest.assertion.assert
|
|||||||
import net.corda.core.contracts.Command
|
import net.corda.core.contracts.Command
|
||||||
import net.corda.core.contracts.StateAndContract
|
import net.corda.core.contracts.StateAndContract
|
||||||
import net.corda.core.contracts.requireThat
|
import net.corda.core.contracts.requireThat
|
||||||
import net.corda.core.flows.matchers.fails
|
import net.corda.core.flows.matchers.flow.willThrow
|
||||||
import net.corda.core.flows.matchers.succeedsWith
|
import net.corda.core.flows.matchers.flow.willReturn
|
||||||
import net.corda.core.flows.mixins.WithContracts
|
import net.corda.core.flows.mixins.WithContracts
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
@ -28,6 +28,7 @@ class CollectSignaturesFlowTests : WithContracts {
|
|||||||
private val miniCorp = TestIdentity(CordaX500Name("MiniCorp", "London", "GB"))
|
private val miniCorp = TestIdentity(CordaX500Name("MiniCorp", "London", "GB"))
|
||||||
private val miniCorpServices = MockServices(listOf("net.corda.testing.contracts"), miniCorp, rigorousMock())
|
private val miniCorpServices = MockServices(listOf("net.corda.testing.contracts"), miniCorp, rigorousMock())
|
||||||
private val classMockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.core.flows"))
|
private val classMockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.core.flows"))
|
||||||
|
|
||||||
private const val MAGIC_NUMBER = 1337
|
private const val MAGIC_NUMBER = 1337
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ -35,7 +36,6 @@ class CollectSignaturesFlowTests : WithContracts {
|
|||||||
fun tearDown() = classMockNet.stopNodes()
|
fun tearDown() = classMockNet.stopNodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val magicNumber = MAGIC_NUMBER
|
|
||||||
override val mockNet = classMockNet
|
override val mockNet = classMockNet
|
||||||
|
|
||||||
private val aliceNode = makeNode(ALICE_NAME)
|
private val aliceNode = makeNode(ALICE_NAME)
|
||||||
@ -53,7 +53,7 @@ class CollectSignaturesFlowTests : WithContracts {
|
|||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
aliceNode.startTestFlow(alice, bConfidentialIdentity.party, charlie),
|
aliceNode.startTestFlow(alice, bConfidentialIdentity.party, charlie),
|
||||||
succeedsWith(requiredSignatures(3))
|
willReturn(requiredSignatures(3))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ class CollectSignaturesFlowTests : WithContracts {
|
|||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
aliceNode.collectSignatures(ptx),
|
aliceNode.collectSignatures(ptx),
|
||||||
succeedsWith(requiredSignatures(1))
|
willReturn(requiredSignatures(1))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,20 +73,21 @@ class CollectSignaturesFlowTests : WithContracts {
|
|||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
aliceNode.collectSignatures(ptx),
|
aliceNode.collectSignatures(ptx),
|
||||||
fails(errorMessage("The Initiator of CollectSignaturesFlow must have signed the transaction.")))
|
willThrow(errorMessage("The Initiator of CollectSignaturesFlow must have signed the transaction.")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `passes with multiple initial signatures`() {
|
fun `passes with multiple initial signatures`() {
|
||||||
val signedByA = aliceNode.signDummyContract(
|
val signedByA = aliceNode.signDummyContract(
|
||||||
alice.ref(1),
|
alice.ref(1),
|
||||||
|
MAGIC_NUMBER,
|
||||||
bob.ref(2),
|
bob.ref(2),
|
||||||
bob.ref(3))
|
bob.ref(3))
|
||||||
val signedByBoth = bobNode.addSignatureTo(signedByA)
|
val signedByBoth = bobNode.addSignatureTo(signedByA)
|
||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
aliceNode.collectSignatures(signedByBoth),
|
aliceNode.collectSignatures(signedByBoth),
|
||||||
succeedsWith(requiredSignatures(2))
|
willReturn(requiredSignatures(2))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +95,7 @@ class CollectSignaturesFlowTests : WithContracts {
|
|||||||
private fun StartedNode<*>.startTestFlow(vararg party: Party) =
|
private fun StartedNode<*>.startTestFlow(vararg party: Party) =
|
||||||
startFlow(
|
startFlow(
|
||||||
TestFlow.Initiator(DummyContract.MultiOwnerState(
|
TestFlow.Initiator(DummyContract.MultiOwnerState(
|
||||||
magicNumber,
|
MAGIC_NUMBER,
|
||||||
listOf(*party)),
|
listOf(*party)),
|
||||||
mockNet.defaultNotaryIdentity))
|
mockNet.defaultNotaryIdentity))
|
||||||
.andRunNetwork()
|
.andRunNetwork()
|
||||||
|
@ -0,0 +1,144 @@
|
|||||||
|
package net.corda.core.flows
|
||||||
|
|
||||||
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
|
import com.natpryce.hamkrest.*
|
||||||
|
import com.natpryce.hamkrest.assertion.assert
|
||||||
|
import net.corda.core.CordaRuntimeException
|
||||||
|
import net.corda.core.contracts.*
|
||||||
|
import net.corda.core.flows.matchers.rpc.willThrow
|
||||||
|
import net.corda.core.flows.matchers.rpc.willReturn
|
||||||
|
import net.corda.core.flows.mixins.WithContracts
|
||||||
|
import net.corda.core.flows.mixins.WithFinality
|
||||||
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.internal.Emoji
|
||||||
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
|
import net.corda.core.transactions.ContractUpgradeLedgerTransaction
|
||||||
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.finance.contracts.asset.Cash
|
||||||
|
import net.corda.node.internal.StartedNode
|
||||||
|
import net.corda.node.services.Permissions.Companion.startFlow
|
||||||
|
import net.corda.testing.contracts.DummyContract
|
||||||
|
import net.corda.testing.contracts.DummyContractV2
|
||||||
|
import net.corda.testing.core.ALICE_NAME
|
||||||
|
import net.corda.testing.core.BOB_NAME
|
||||||
|
import net.corda.testing.core.singleIdentity
|
||||||
|
import net.corda.testing.node.User
|
||||||
|
import net.corda.testing.node.internal.*
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork.MockNode
|
||||||
|
import org.junit.AfterClass
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class ContractUpgradeFlowRPCTest : WithContracts, WithFinality {
|
||||||
|
companion object {
|
||||||
|
private val classMockNet = InternalMockNetwork(cordappPackages = listOf(
|
||||||
|
"net.corda.testing.contracts",
|
||||||
|
"net.corda.finance.contracts.asset",
|
||||||
|
"net.corda.core.flows"))
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@AfterClass
|
||||||
|
fun tearDown() = classMockNet.stopNodes()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val mockNet = classMockNet
|
||||||
|
|
||||||
|
private val aliceNode = makeNode(ALICE_NAME)
|
||||||
|
private val bobNode = makeNode(BOB_NAME)
|
||||||
|
|
||||||
|
private val alice = aliceNode.info.singleIdentity()
|
||||||
|
private val bob = bobNode.info.singleIdentity()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `2 parties contract upgrade using RPC`() = rpcDriver {
|
||||||
|
val testUser = createTestUser()
|
||||||
|
val rpcA = startProxy(aliceNode, testUser)
|
||||||
|
val rpcB = startProxy(bobNode, testUser)
|
||||||
|
|
||||||
|
// Create, sign and finalise dummy contract.
|
||||||
|
val signedByA = aliceNode.signDummyContract(alice.ref(1), 0, bob.ref(1))
|
||||||
|
val stx = bobNode.addSignatureTo(signedByA)
|
||||||
|
assert.that(rpcA.finalise(stx, bob), willReturn())
|
||||||
|
|
||||||
|
val atx = aliceNode.getValidatedTransaction(stx)
|
||||||
|
val btx = bobNode.getValidatedTransaction(stx)
|
||||||
|
|
||||||
|
// Cannot upgrade contract without prior authorisation from counterparty
|
||||||
|
assert.that(
|
||||||
|
rpcA.initiateDummyContractUpgrade(atx),
|
||||||
|
willThrow<CordaRuntimeException>())
|
||||||
|
|
||||||
|
// Party B authorises the contract state upgrade, and immediately deauthorises the same.
|
||||||
|
assert.that(rpcB.authoriseDummyContractUpgrade(btx), willReturn())
|
||||||
|
assert.that(rpcB.deauthoriseContractUpgrade(btx), willReturn())
|
||||||
|
|
||||||
|
// Cannot upgrade contract if counterparty has deauthorised a previously-given authority
|
||||||
|
assert.that(
|
||||||
|
rpcA.initiateDummyContractUpgrade(atx),
|
||||||
|
willThrow<CordaRuntimeException>())
|
||||||
|
|
||||||
|
// Party B authorise the contract state upgrade.
|
||||||
|
assert.that(rpcB.authoriseDummyContractUpgrade(btx), willReturn())
|
||||||
|
|
||||||
|
// Party A initiates contract upgrade flow, expected to succeed this time.
|
||||||
|
assert.that(
|
||||||
|
rpcA.initiateDummyContractUpgrade(atx),
|
||||||
|
willReturn(
|
||||||
|
aliceNode.hasDummyContractUpgradeTransaction()
|
||||||
|
and bobNode.hasDummyContractUpgradeTransaction()))
|
||||||
|
}
|
||||||
|
|
||||||
|
//region RPC DSL
|
||||||
|
private fun RPCDriverDSL.startProxy(node: StartedNode<MockNode>, user: User): CordaRPCOps {
|
||||||
|
return startRpcClient<CordaRPCOps>(
|
||||||
|
rpcAddress = startRpcServer(
|
||||||
|
rpcUser = user,
|
||||||
|
ops = node.rpcOps
|
||||||
|
).get().broker.hostAndPort!!,
|
||||||
|
username = user.username,
|
||||||
|
password = user.password
|
||||||
|
).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun RPCDriverDSL.createTestUser() = rpcTestUser.copy(permissions = setOf(
|
||||||
|
startFlow<WithFinality.FinalityInvoker>(),
|
||||||
|
startFlow<ContractUpgradeFlow.Initiate<*, *>>(),
|
||||||
|
startFlow<ContractUpgradeFlow.Authorise>(),
|
||||||
|
startFlow<ContractUpgradeFlow.Deauthorise>()
|
||||||
|
))
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Operations
|
||||||
|
private fun CordaRPCOps.initiateDummyContractUpgrade(tx: SignedTransaction) =
|
||||||
|
initiateContractUpgrade(tx, DummyContractV2::class)
|
||||||
|
|
||||||
|
private fun CordaRPCOps.authoriseDummyContractUpgrade(tx: SignedTransaction) =
|
||||||
|
authoriseContractUpgrade(tx, DummyContractV2::class)
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Matchers
|
||||||
|
private fun StartedNode<*>.hasDummyContractUpgradeTransaction() =
|
||||||
|
hasContractUpgradeTransaction<DummyContract.State, DummyContractV2.State>()
|
||||||
|
|
||||||
|
private inline fun <reified FROM : Any, reified TO: Any> StartedNode<*>.hasContractUpgradeTransaction() =
|
||||||
|
has<StateAndRef<ContractState>, ContractUpgradeLedgerTransaction>(
|
||||||
|
"a contract upgrade transaction",
|
||||||
|
{ getContractUpgradeTransaction(it) },
|
||||||
|
isUpgrade<FROM, TO>())
|
||||||
|
|
||||||
|
private fun StartedNode<*>.getContractUpgradeTransaction(state: StateAndRef<ContractState>) = database.transaction {
|
||||||
|
services.validatedTransactions.getTransaction(state.ref.txhash)!!
|
||||||
|
.resolveContractUpgradeTransaction(services)
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified FROM : Any, reified TO : Any> isUpgrade() =
|
||||||
|
isUpgradeFrom<FROM>() and isUpgradeTo<TO>()
|
||||||
|
|
||||||
|
private inline fun <reified T: Any> isUpgradeFrom() =
|
||||||
|
has<ContractUpgradeLedgerTransaction, Any>("input data", { it.inputs.single().state.data }, isA<T>(anything))
|
||||||
|
|
||||||
|
private inline fun <reified T: Any> isUpgradeTo() =
|
||||||
|
has<ContractUpgradeLedgerTransaction, Any>("output data", { it.outputs.single().data }, isA<T>(anything))
|
||||||
|
//endregion
|
||||||
|
}
|
@ -3,9 +3,9 @@ package net.corda.core.flows
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import com.natpryce.hamkrest.*
|
import com.natpryce.hamkrest.*
|
||||||
import com.natpryce.hamkrest.assertion.assert
|
import com.natpryce.hamkrest.assertion.assert
|
||||||
import net.corda.core.CordaRuntimeException
|
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.flows.matchers.*
|
import net.corda.core.flows.matchers.flow.willThrow
|
||||||
|
import net.corda.core.flows.matchers.flow.willReturn
|
||||||
import net.corda.core.flows.mixins.WithContracts
|
import net.corda.core.flows.mixins.WithContracts
|
||||||
import net.corda.core.flows.mixins.WithFinality
|
import net.corda.core.flows.mixins.WithFinality
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
@ -48,7 +48,6 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val mockNet = classMockNet
|
override val mockNet = classMockNet
|
||||||
override val magicNumber = 0
|
|
||||||
|
|
||||||
private val aliceNode = makeNode(ALICE_NAME)
|
private val aliceNode = makeNode(ALICE_NAME)
|
||||||
private val bobNode = makeNode(BOB_NAME)
|
private val bobNode = makeNode(BOB_NAME)
|
||||||
@ -60,7 +59,7 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
|
|||||||
@Test
|
@Test
|
||||||
fun `2 parties contract upgrade`() {
|
fun `2 parties contract upgrade`() {
|
||||||
// Create dummy contract.
|
// Create dummy contract.
|
||||||
val signedByA = aliceNode.signDummyContract(alice.ref(1), bob.ref(1))
|
val signedByA = aliceNode.signDummyContract(alice.ref(1),0, bob.ref(1))
|
||||||
val stx = bobNode.addSignatureTo(signedByA)
|
val stx = bobNode.addSignatureTo(signedByA)
|
||||||
|
|
||||||
aliceNode.finalise(stx, bob)
|
aliceNode.finalise(stx, bob)
|
||||||
@ -71,63 +70,24 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
|
|||||||
// The request is expected to be rejected because party B hasn't authorised the upgrade yet.
|
// The request is expected to be rejected because party B hasn't authorised the upgrade yet.
|
||||||
assert.that(
|
assert.that(
|
||||||
aliceNode.initiateDummyContractUpgrade(atx),
|
aliceNode.initiateDummyContractUpgrade(atx),
|
||||||
fails<UnexpectedFlowEndException>())
|
willThrow<UnexpectedFlowEndException>())
|
||||||
|
|
||||||
// Party B authorise the contract state upgrade, and immediately deauthorise the same.
|
// Party B authorise the contract state upgrade, and immediately deauthorise the same.
|
||||||
assert.that(bobNode.authoriseDummyContractUpgrade(btx), succeeds())
|
assert.that(bobNode.authoriseDummyContractUpgrade(btx), willReturn())
|
||||||
assert.that(bobNode.deauthoriseContractUpgrade(btx), succeeds())
|
assert.that(bobNode.deauthoriseContractUpgrade(btx), willReturn())
|
||||||
|
|
||||||
// The request is expected to be rejected because party B has subsequently deauthorised a previously authorised upgrade.
|
// The request is expected to be rejected because party B has subsequently deauthorised a previously authorised upgrade.
|
||||||
assert.that(
|
assert.that(
|
||||||
aliceNode.initiateDummyContractUpgrade(atx),
|
aliceNode.initiateDummyContractUpgrade(atx),
|
||||||
fails<UnexpectedFlowEndException>())
|
willThrow<UnexpectedFlowEndException>())
|
||||||
|
|
||||||
// Party B authorise the contract state upgrade
|
// Party B authorise the contract state upgrade
|
||||||
assert.that(bobNode.authoriseDummyContractUpgrade(btx), succeeds())
|
assert.that(bobNode.authoriseDummyContractUpgrade(btx), willReturn())
|
||||||
|
|
||||||
// Party A initiates contract upgrade flow, expected to succeed this time.
|
// Party A initiates contract upgrade flow, expected to succeed this time.
|
||||||
assert.that(
|
assert.that(
|
||||||
aliceNode.initiateDummyContractUpgrade(atx),
|
aliceNode.initiateDummyContractUpgrade(atx),
|
||||||
succeedsWith(
|
willReturn(
|
||||||
aliceNode.hasDummyContractUpgradeTransaction()
|
|
||||||
and bobNode.hasDummyContractUpgradeTransaction()))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `2 parties contract upgrade using RPC`() = rpcDriver {
|
|
||||||
val testUser = createTestUser()
|
|
||||||
val rpcA = startProxy(aliceNode, testUser)
|
|
||||||
val rpcB = startProxy(bobNode, testUser)
|
|
||||||
|
|
||||||
// Create, sign and finalise dummy contract.
|
|
||||||
val signedByA = aliceNode.signDummyContract(alice.ref(1), bob.ref(1))
|
|
||||||
val stx = bobNode.addSignatureTo(signedByA)
|
|
||||||
assert.that(rpcA.finalise(stx, bob), rpcSucceeds())
|
|
||||||
|
|
||||||
val atx = aliceNode.getValidatedTransaction(stx)
|
|
||||||
val btx = bobNode.getValidatedTransaction(stx)
|
|
||||||
|
|
||||||
// Cannot upgrade contract without prior authorisation from counterparty
|
|
||||||
assert.that(
|
|
||||||
rpcA.initiateDummyContractUpgrade(atx),
|
|
||||||
rpcFails<CordaRuntimeException>())
|
|
||||||
|
|
||||||
// Party B authorises the contract state upgrade, and immediately deauthorises the same.
|
|
||||||
assert.that(rpcB.authoriseDummyContractUpgrade(btx), rpcSucceeds())
|
|
||||||
assert.that(rpcB.deauthoriseContractUpgrade(btx), rpcSucceeds())
|
|
||||||
|
|
||||||
// Cannot upgrade contract if counterparty has deauthorised a previously-given authority
|
|
||||||
assert.that(
|
|
||||||
rpcA.initiateDummyContractUpgrade(atx),
|
|
||||||
rpcFails<CordaRuntimeException>())
|
|
||||||
|
|
||||||
// Party B authorise the contract state upgrade.
|
|
||||||
assert.that(rpcB.authoriseDummyContractUpgrade(btx), rpcSucceeds())
|
|
||||||
|
|
||||||
// Party A initiates contract upgrade flow, expected to succeed this time.
|
|
||||||
assert.that(
|
|
||||||
rpcA.initiateDummyContractUpgrade(atx),
|
|
||||||
rpcSucceedsWith(
|
|
||||||
aliceNode.hasDummyContractUpgradeTransaction()
|
aliceNode.hasDummyContractUpgradeTransaction()
|
||||||
and bobNode.hasDummyContractUpgradeTransaction()))
|
and bobNode.hasDummyContractUpgradeTransaction()))
|
||||||
}
|
}
|
||||||
@ -164,7 +124,7 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
|
|||||||
assert.that(aliceNode.getBaseStateFromVault(), hasContractState(isA<Cash.State>(anything)))
|
assert.that(aliceNode.getBaseStateFromVault(), hasContractState(isA<Cash.State>(anything)))
|
||||||
|
|
||||||
// Starts contract upgrade flow.
|
// Starts contract upgrade flow.
|
||||||
assert.that(aliceNode.initiateContractUpgrade(stateAndRef, CashV2::class), succeeds())
|
assert.that(aliceNode.initiateContractUpgrade(stateAndRef, CashV2::class), willReturn())
|
||||||
|
|
||||||
// Get contract state from the vault.
|
// Get contract state from the vault.
|
||||||
val upgradedState = aliceNode.getCashStateFromVault()
|
val upgradedState = aliceNode.getCashStateFromVault()
|
||||||
@ -182,7 +142,7 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
|
|||||||
addCommand(CashV2.Move(), alice.owningKey)
|
addCommand(CashV2.Move(), alice.owningKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.that(aliceNode.finalise(spendUpgradedTx), succeeds())
|
assert.that(aliceNode.finalise(spendUpgradedTx), willReturn())
|
||||||
assert.that(aliceNode.getCashStateFromVault(), hasContractState(equalTo(movedState)))
|
assert.that(aliceNode.getCashStateFromVault(), hasContractState(equalTo(movedState)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,45 +168,12 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
|
|||||||
override fun verify(tx: LedgerTransaction) {}
|
override fun verify(tx: LedgerTransaction) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@StartableByRPC
|
|
||||||
class FinalityInvoker(private val transaction: SignedTransaction,
|
|
||||||
private val extraRecipients: Set<Party>) : FlowLogic<SignedTransaction>() {
|
|
||||||
@Suspendable
|
|
||||||
override fun call(): SignedTransaction = subFlow(FinalityFlow(transaction, extraRecipients))
|
|
||||||
}
|
|
||||||
|
|
||||||
//region RPC DSL
|
|
||||||
private fun RPCDriverDSL.startProxy(node: StartedNode<MockNode>, user: User): CordaRPCOps {
|
|
||||||
return startRpcClient<CordaRPCOps>(
|
|
||||||
rpcAddress = startRpcServer(
|
|
||||||
rpcUser = user,
|
|
||||||
ops = node.rpcOps
|
|
||||||
).get().broker.hostAndPort!!,
|
|
||||||
username = user.username,
|
|
||||||
password = user.password
|
|
||||||
).get()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun RPCDriverDSL.createTestUser() = rpcTestUser.copy(permissions = setOf(
|
|
||||||
startFlow<FinalityInvoker>(),
|
|
||||||
startFlow<ContractUpgradeFlow.Initiate<*, *>>(),
|
|
||||||
startFlow<ContractUpgradeFlow.Authorise>(),
|
|
||||||
startFlow<ContractUpgradeFlow.Deauthorise>()
|
|
||||||
))
|
|
||||||
//endregion
|
|
||||||
|
|
||||||
//region Operations
|
//region Operations
|
||||||
private fun StartedNode<*>.initiateDummyContractUpgrade(tx: SignedTransaction) =
|
private fun StartedNode<*>.initiateDummyContractUpgrade(tx: SignedTransaction) =
|
||||||
initiateContractUpgrade(tx, DummyContractV2::class)
|
initiateContractUpgrade(tx, DummyContractV2::class)
|
||||||
|
|
||||||
private fun StartedNode<*>.authoriseDummyContractUpgrade(tx: SignedTransaction) =
|
private fun StartedNode<*>.authoriseDummyContractUpgrade(tx: SignedTransaction) =
|
||||||
authoriseContractUpgrade(tx, DummyContractV2::class)
|
authoriseContractUpgrade(tx, DummyContractV2::class)
|
||||||
|
|
||||||
private fun CordaRPCOps.initiateDummyContractUpgrade(tx: SignedTransaction) =
|
|
||||||
initiateContractUpgrade(tx, DummyContractV2::class)
|
|
||||||
|
|
||||||
private fun CordaRPCOps.authoriseDummyContractUpgrade(tx: SignedTransaction) =
|
|
||||||
authoriseContractUpgrade(tx, DummyContractV2::class)
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Matchers
|
//region Matchers
|
||||||
|
@ -2,8 +2,8 @@ package net.corda.core.flows
|
|||||||
|
|
||||||
import com.natpryce.hamkrest.and
|
import com.natpryce.hamkrest.and
|
||||||
import com.natpryce.hamkrest.assertion.assert
|
import com.natpryce.hamkrest.assertion.assert
|
||||||
import net.corda.core.flows.matchers.fails
|
import net.corda.core.flows.matchers.flow.willThrow
|
||||||
import net.corda.core.flows.matchers.succeedsWith
|
import net.corda.core.flows.matchers.flow.willReturn
|
||||||
import net.corda.core.flows.mixins.WithFinality
|
import net.corda.core.flows.mixins.WithFinality
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
@ -42,9 +42,9 @@ class FinalityFlowTests : WithFinality {
|
|||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
aliceNode.finalise(stx),
|
aliceNode.finalise(stx),
|
||||||
succeedsWith(
|
willReturn(
|
||||||
requiredSignatures(1)
|
requiredSignatures(1)
|
||||||
and transactionVisibleTo(bobNode)))
|
and transactionVisibleTo(bobNode)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -54,7 +54,7 @@ class FinalityFlowTests : WithFinality {
|
|||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
aliceNode.finalise(stx),
|
aliceNode.finalise(stx),
|
||||||
fails<IllegalArgumentException>())
|
willThrow<IllegalArgumentException>())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun StartedNode<*>.signCashTransactionWith(other: Party): SignedTransaction {
|
private fun StartedNode<*>.signCashTransactionWith(other: Party): SignedTransaction {
|
||||||
|
@ -4,7 +4,7 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import com.natpryce.hamkrest.assertion.assert
|
import com.natpryce.hamkrest.assertion.assert
|
||||||
import com.natpryce.hamkrest.equalTo
|
import com.natpryce.hamkrest.equalTo
|
||||||
import com.natpryce.hamkrest.isA
|
import com.natpryce.hamkrest.isA
|
||||||
import net.corda.core.flows.matchers.succeedsWith
|
import net.corda.core.flows.matchers.flow.willReturn
|
||||||
import net.corda.core.flows.mixins.WithMockNet
|
import net.corda.core.flows.mixins.WithMockNet
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.utilities.UntrustworthyData
|
import net.corda.core.utilities.UntrustworthyData
|
||||||
@ -60,7 +60,7 @@ class ReceiveMultipleFlowTests : WithMockNet {
|
|||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
nodes[0].startFlowAndRunNetwork(initiatingFlow),
|
nodes[0].startFlowAndRunNetwork(initiatingFlow),
|
||||||
succeedsWith(isA(equalTo(answer))))
|
willReturn(isA(equalTo(answer))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -72,7 +72,7 @@ class ReceiveMultipleFlowTests : WithMockNet {
|
|||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
nodes[0].startFlowAndRunNetwork(ParallelAlgorithmMap(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())),
|
nodes[0].startFlowAndRunNetwork(ParallelAlgorithmMap(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())),
|
||||||
succeedsWith(equalTo(doubleValue * stringValue.length)))
|
willReturn(equalTo(doubleValue * stringValue.length)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -84,7 +84,7 @@ class ReceiveMultipleFlowTests : WithMockNet {
|
|||||||
|
|
||||||
assert.that(
|
assert.that(
|
||||||
nodes[0].startFlowAndRunNetwork(ParallelAlgorithmList(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())),
|
nodes[0].startFlowAndRunNetwork(ParallelAlgorithmList(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())),
|
||||||
succeedsWith(equalTo(listOf(value1, value2))))
|
willReturn(equalTo(listOf(value1, value2))))
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParallelAlgorithmMap(doubleMember: Party, stringMember: Party) : AlgorithmDefinition(doubleMember, stringMember) {
|
class ParallelAlgorithmMap(doubleMember: Party, stringMember: Party) : AlgorithmDefinition(doubleMember, stringMember) {
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
package net.corda.core.flows.matchers
|
|
||||||
|
|
||||||
import com.natpryce.hamkrest.MatchResult
|
|
||||||
import com.natpryce.hamkrest.Matcher
|
|
||||||
import net.corda.core.internal.FlowStateMachine
|
|
||||||
import net.corda.core.utilities.getOrThrow
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches a Flow that succeeds with a result matched by the given matcher
|
|
||||||
*/
|
|
||||||
fun <T> succeeds() = object : Matcher<FlowStateMachine<T>> {
|
|
||||||
override val description: String = "is a flow that succeeds"
|
|
||||||
|
|
||||||
override fun invoke(actual: FlowStateMachine<T>): MatchResult = try {
|
|
||||||
actual.resultFuture.getOrThrow()
|
|
||||||
MatchResult.Match
|
|
||||||
} catch (e: Exception) {
|
|
||||||
MatchResult.Mismatch("Failed with $e")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches a Flow that succeeds with a result matched by the given matcher
|
|
||||||
*/
|
|
||||||
fun <T> succeedsWith(successMatcher: Matcher<T>) = object : Matcher<FlowStateMachine<out T>> {
|
|
||||||
override val description: String = "is a flow that succeeds with a value that ${successMatcher.description}"
|
|
||||||
|
|
||||||
override fun invoke(actual: FlowStateMachine<out T>): MatchResult = try {
|
|
||||||
successMatcher(actual.resultFuture.getOrThrow())
|
|
||||||
} catch (e: Exception) {
|
|
||||||
MatchResult.Mismatch("Failed with $e")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches a Flow that fails, with an exception matched by the given matcher.
|
|
||||||
*/
|
|
||||||
inline fun <reified E: Exception> fails(failureMatcher: Matcher<E>) = object : Matcher<FlowStateMachine<*>> {
|
|
||||||
override val description: String
|
|
||||||
get() = "is a flow that fails with a ${E::class.java.simpleName} that ${failureMatcher.description}"
|
|
||||||
|
|
||||||
override fun invoke(actual: FlowStateMachine<*>): MatchResult = try {
|
|
||||||
actual.resultFuture.getOrThrow()
|
|
||||||
MatchResult.Mismatch("Succeeded")
|
|
||||||
} catch (e: Exception) {
|
|
||||||
when(e) {
|
|
||||||
is E -> failureMatcher(e)
|
|
||||||
else -> MatchResult.Mismatch("Failure class was ${e.javaClass}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches a Flow that fails, with an exception of the specified type.
|
|
||||||
*/
|
|
||||||
inline fun <reified E: Exception> fails() = object : Matcher<FlowStateMachine<*>> {
|
|
||||||
override val description: String
|
|
||||||
get() = "is a flow that fails with a ${E::class.java}"
|
|
||||||
|
|
||||||
override fun invoke(actual: FlowStateMachine<*>): MatchResult = try {
|
|
||||||
actual.resultFuture.getOrThrow()
|
|
||||||
MatchResult.Mismatch("Succeeded")
|
|
||||||
} catch (e: Exception) {
|
|
||||||
when(e) {
|
|
||||||
is E -> MatchResult.Match
|
|
||||||
else -> MatchResult.Mismatch("Failure class was ${e.javaClass}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,69 @@
|
|||||||
|
package net.corda.core.flows.matchers
|
||||||
|
|
||||||
|
import com.natpryce.hamkrest.MatchResult
|
||||||
|
import com.natpryce.hamkrest.Matcher
|
||||||
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import java.util.concurrent.Future
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a Flow that succeeds with a result matched by the given matcher
|
||||||
|
*/
|
||||||
|
fun <T> willReturn() = object : Matcher<Future<T>> {
|
||||||
|
override val description: String = "is a future that will succeed"
|
||||||
|
|
||||||
|
override fun invoke(actual: Future<T>): MatchResult = try {
|
||||||
|
actual.getOrThrow()
|
||||||
|
MatchResult.Match
|
||||||
|
} catch (e: Exception) {
|
||||||
|
MatchResult.Mismatch("Failed with $e")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a Flow that succeeds with a result matched by the given matcher
|
||||||
|
*/
|
||||||
|
fun <T> willSucceedWithResult(successMatcher: Matcher<T>) = object : Matcher<Future<out T>> {
|
||||||
|
override val description: String = "is a future that will succeed with a value that ${successMatcher.description}"
|
||||||
|
|
||||||
|
override fun invoke(actual: Future<out T>): MatchResult = try {
|
||||||
|
successMatcher(actual.getOrThrow())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
MatchResult.Mismatch("Failed with $e")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a Flow that fails, with an exception matched by the given matcher.
|
||||||
|
*/
|
||||||
|
inline fun <reified E: Exception> willFailWithException(failureMatcher: Matcher<E>) = object : Matcher<Future<*>> {
|
||||||
|
override val description: String
|
||||||
|
get() = "is a future that will fail with a ${E::class.java.simpleName} that ${failureMatcher.description}"
|
||||||
|
|
||||||
|
override fun invoke(actual: Future<*>): MatchResult = try {
|
||||||
|
actual.getOrThrow()
|
||||||
|
MatchResult.Mismatch("Succeeded")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
when(e) {
|
||||||
|
is E -> failureMatcher(e)
|
||||||
|
else -> MatchResult.Mismatch("Failure class was ${e.javaClass}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a Flow that fails, with an exception of the specified type.
|
||||||
|
*/
|
||||||
|
inline fun <reified E: Exception> willThrow() = object : Matcher<Future<*>> {
|
||||||
|
override val description: String
|
||||||
|
get() = "is a future that will fail with a ${E::class.java}"
|
||||||
|
|
||||||
|
override fun invoke(actual: Future<*>): MatchResult = try {
|
||||||
|
actual.getOrThrow()
|
||||||
|
MatchResult.Mismatch("Succeeded")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
when(e) {
|
||||||
|
is E -> MatchResult.Match
|
||||||
|
else -> MatchResult.Mismatch("Failure class was ${e.javaClass}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,69 +0,0 @@
|
|||||||
package net.corda.core.flows.matchers
|
|
||||||
|
|
||||||
import com.natpryce.hamkrest.MatchResult
|
|
||||||
import com.natpryce.hamkrest.Matcher
|
|
||||||
import net.corda.core.messaging.FlowHandle
|
|
||||||
import net.corda.core.utilities.getOrThrow
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches an RPC flow handle that succeeds with a result matched by the given matcher
|
|
||||||
*/
|
|
||||||
fun <T> rpcSucceeds() = object : Matcher<FlowHandle<T>> {
|
|
||||||
override val description: String = "is an RPC flow handle that succeeds"
|
|
||||||
|
|
||||||
override fun invoke(actual: FlowHandle<T>): MatchResult = try {
|
|
||||||
actual.returnValue.getOrThrow()
|
|
||||||
MatchResult.Match
|
|
||||||
} catch (e: Exception) {
|
|
||||||
MatchResult.Mismatch("Failed with $e")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches an RPC flow handle that succeeds with a result matched by the given matcher
|
|
||||||
*/
|
|
||||||
fun <T> rpcSucceedsWith(successMatcher: Matcher<T>) = object : Matcher<FlowHandle<T>> {
|
|
||||||
override val description: String = "is an RPC flow handle that succeeds with a value that ${successMatcher.description}"
|
|
||||||
|
|
||||||
override fun invoke(actual: FlowHandle<T>): MatchResult = try {
|
|
||||||
successMatcher(actual.returnValue.getOrThrow())
|
|
||||||
} catch (e: Exception) {
|
|
||||||
MatchResult.Mismatch("Failed with $e")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches an RPC Flow handle that fails, with an exception matched by the given matcher.
|
|
||||||
*/
|
|
||||||
inline fun <reified E: Exception> rpcFails(failureMatcher: Matcher<E>) = object : Matcher<FlowHandle<*>> {
|
|
||||||
override val description: String
|
|
||||||
get() = "is an RPC flow handle that fails with a ${E::class.java.simpleName} that ${failureMatcher.description}"
|
|
||||||
|
|
||||||
override fun invoke(actual: FlowHandle<*>): MatchResult = try {
|
|
||||||
actual.returnValue.getOrThrow()
|
|
||||||
MatchResult.Mismatch("Succeeded")
|
|
||||||
} catch (e: Exception) {
|
|
||||||
when(e) {
|
|
||||||
is E -> failureMatcher(e)
|
|
||||||
else -> MatchResult.Mismatch("Failure class was ${e.javaClass}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches a Flow that fails, with an exception of the specified type.
|
|
||||||
*/
|
|
||||||
inline fun <reified E: Exception> rpcFails() = object : Matcher<FlowHandle<*>> {
|
|
||||||
override val description: String
|
|
||||||
get() = "is an RPC flow handle that fails with a ${E::class.java}"
|
|
||||||
|
|
||||||
override fun invoke(actual: FlowHandle<*>): MatchResult = try {
|
|
||||||
actual.returnValue.getOrThrow()
|
|
||||||
MatchResult.Mismatch("Succeeded")
|
|
||||||
} catch (e: Exception) {
|
|
||||||
when(e) {
|
|
||||||
is E -> MatchResult.Match
|
|
||||||
else -> MatchResult.Mismatch("Failure class was ${e.javaClass}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,35 @@
|
|||||||
|
package net.corda.core.flows.matchers.flow
|
||||||
|
|
||||||
|
import com.natpryce.hamkrest.Matcher
|
||||||
|
import com.natpryce.hamkrest.has
|
||||||
|
import net.corda.core.flows.matchers.willThrow
|
||||||
|
import net.corda.core.flows.matchers.willFailWithException
|
||||||
|
import net.corda.core.flows.matchers.willReturn
|
||||||
|
import net.corda.core.flows.matchers.willSucceedWithResult
|
||||||
|
import net.corda.core.internal.FlowStateMachine
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a Flow that succeeds with a result matched by the given matcher
|
||||||
|
*/
|
||||||
|
fun <T> willReturn() = has(FlowStateMachine<T>::resultFuture, willReturn())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a Flow that succeeds with a result matched by the given matcher
|
||||||
|
*/
|
||||||
|
fun <T> willReturn(successMatcher: Matcher<T>) = has(
|
||||||
|
FlowStateMachine<out T>::resultFuture,
|
||||||
|
willSucceedWithResult(successMatcher))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a Flow that fails, with an exception matched by the given matcher.
|
||||||
|
*/
|
||||||
|
inline fun <reified E: Exception> willThrow(failureMatcher: Matcher<E>) = has(
|
||||||
|
FlowStateMachine<*>::resultFuture,
|
||||||
|
willFailWithException(failureMatcher))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a Flow that fails, with an exception of the specified type.
|
||||||
|
*/
|
||||||
|
inline fun <reified E: Exception> willThrow() = has(
|
||||||
|
FlowStateMachine<*>::resultFuture,
|
||||||
|
willThrow<E>())
|
@ -0,0 +1,33 @@
|
|||||||
|
package net.corda.core.flows.matchers.rpc
|
||||||
|
|
||||||
|
import com.natpryce.hamkrest.Matcher
|
||||||
|
import com.natpryce.hamkrest.has
|
||||||
|
import net.corda.core.flows.matchers.willThrow
|
||||||
|
import net.corda.core.flows.matchers.willFailWithException
|
||||||
|
import net.corda.core.flows.matchers.willReturn
|
||||||
|
import net.corda.core.flows.matchers.willSucceedWithResult
|
||||||
|
import net.corda.core.messaging.FlowHandle
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a flow handle that succeeds with a result matched by the given matcher
|
||||||
|
*/
|
||||||
|
fun <T> willReturn() = has(FlowHandle<T>::returnValue, willReturn())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a flow handle that succeeds with a result matched by the given matcher
|
||||||
|
*/
|
||||||
|
fun <T> willReturn(successMatcher: Matcher<T>) = has(FlowHandle<out T>::returnValue, willSucceedWithResult(successMatcher))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a flow handle that fails, with an exception matched by the given matcher.
|
||||||
|
*/
|
||||||
|
inline fun <reified E: Exception> willThrow(failureMatcher: Matcher<E>) = has(
|
||||||
|
FlowHandle<*>::returnValue,
|
||||||
|
willFailWithException(failureMatcher))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches a flow handle that fails, with an exception of the specified type.
|
||||||
|
*/
|
||||||
|
inline fun <reified E: Exception> willThrow() = has(
|
||||||
|
FlowHandle<*>::returnValue,
|
||||||
|
willThrow<E>())
|
@ -21,10 +21,8 @@ import kotlin.reflect.KClass
|
|||||||
*/
|
*/
|
||||||
interface WithContracts : WithMockNet {
|
interface WithContracts : WithMockNet {
|
||||||
|
|
||||||
val magicNumber: Int
|
|
||||||
|
|
||||||
//region Generators
|
//region Generators
|
||||||
fun createDummyContract(owner: PartyAndReference, vararg others: PartyAndReference) =
|
fun createDummyContract(owner: PartyAndReference, magicNumber: Int = 0, vararg others: PartyAndReference) =
|
||||||
DummyContract.generateInitial(
|
DummyContract.generateInitial(
|
||||||
magicNumber,
|
magicNumber,
|
||||||
mockNet.defaultNotaryIdentity,
|
mockNet.defaultNotaryIdentity,
|
||||||
@ -33,21 +31,11 @@ interface WithContracts : WithMockNet {
|
|||||||
//region
|
//region
|
||||||
|
|
||||||
//region Operations
|
//region Operations
|
||||||
fun StartedNode<*>.createConfidentialIdentity(party: Party) = database.transaction {
|
fun StartedNode<*>.signDummyContract(owner: PartyAndReference, magicNumber: Int = 0, vararg others: PartyAndReference) =
|
||||||
services.keyManagementService.freshKeyAndCert(
|
services.signDummyContract(owner, magicNumber, *others).andRunNetwork()
|
||||||
services.myInfo.legalIdentitiesAndCerts.single { it.name == party.name },
|
|
||||||
false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun StartedNode<*>.verifyAndRegister(identity: PartyAndCertificate) = database.transaction {
|
fun ServiceHub.signDummyContract(owner: PartyAndReference, magicNumber: Int = 0, vararg others: PartyAndReference) =
|
||||||
services.identityService.verifyAndRegisterIdentity(identity)
|
signInitialTransaction(createDummyContract(owner, magicNumber, *others))
|
||||||
}
|
|
||||||
|
|
||||||
fun StartedNode<*>.signDummyContract(owner: PartyAndReference, vararg others: PartyAndReference) =
|
|
||||||
services.signDummyContract(owner, *others).andRunNetwork()
|
|
||||||
|
|
||||||
fun ServiceHub.signDummyContract(owner: PartyAndReference, vararg others: PartyAndReference) =
|
|
||||||
signInitialTransaction(createDummyContract(owner, *others))
|
|
||||||
|
|
||||||
fun StartedNode<*>.collectSignatures(ptx: SignedTransaction) =
|
fun StartedNode<*>.collectSignatures(ptx: SignedTransaction) =
|
||||||
startFlowAndRunNetwork(CollectSignaturesFlow(ptx, emptySet()))
|
startFlowAndRunNetwork(CollectSignaturesFlow(ptx, emptySet()))
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package net.corda.core.flows.mixins
|
package net.corda.core.flows.mixins
|
||||||
|
|
||||||
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import com.natpryce.hamkrest.Matcher
|
import com.natpryce.hamkrest.Matcher
|
||||||
import com.natpryce.hamkrest.equalTo
|
import com.natpryce.hamkrest.equalTo
|
||||||
import net.corda.core.flows.ContractUpgradeFlowTest
|
import net.corda.core.flows.ContractUpgradeFlowTest
|
||||||
import net.corda.core.flows.FinalityFlow
|
import net.corda.core.flows.FinalityFlow
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
@ -22,7 +25,7 @@ interface WithFinality : WithMockNet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun CordaRPCOps.finalise(stx: SignedTransaction, vararg parties: Party) =
|
fun CordaRPCOps.finalise(stx: SignedTransaction, vararg parties: Party) =
|
||||||
startFlow(ContractUpgradeFlowTest::FinalityInvoker, stx, parties.toSet())
|
startFlow(::FinalityInvoker, stx, parties.toSet())
|
||||||
.andRunNetwork()
|
.andRunNetwork()
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
@ -33,4 +36,11 @@ interface WithFinality : WithMockNet {
|
|||||||
equalTo(actual)(other.getValidatedTransaction(actual))
|
equalTo(actual)(other.getValidatedTransaction(actual))
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
@StartableByRPC
|
||||||
|
class FinalityInvoker(private val transaction: SignedTransaction,
|
||||||
|
private val extraRecipients: Set<Party>) : FlowLogic<SignedTransaction>() {
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): SignedTransaction = subFlow(FinalityFlow(transaction, extraRecipients))
|
||||||
|
}
|
||||||
}
|
}
|
@ -4,6 +4,8 @@ import com.natpryce.hamkrest.*
|
|||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.internal.FlowStateMachine
|
import net.corda.core.internal.FlowStateMachine
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
@ -33,10 +35,7 @@ interface WithMockNet {
|
|||||||
/**
|
/**
|
||||||
* Run the mock network before proceeding
|
* Run the mock network before proceeding
|
||||||
*/
|
*/
|
||||||
fun <T: Any> T.andRunNetwork(): T {
|
fun <T: Any> T.andRunNetwork(): T = apply { mockNet.runNetwork() }
|
||||||
mockNet.runNetwork()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
//region Operations
|
//region Operations
|
||||||
/**
|
/**
|
||||||
@ -62,6 +61,16 @@ interface WithMockNet {
|
|||||||
*/
|
*/
|
||||||
fun <T> StartedNode<*>.startFlowAndRunNetwork(logic: FlowLogic<T>): FlowStateMachine<T> =
|
fun <T> StartedNode<*>.startFlowAndRunNetwork(logic: FlowLogic<T>): FlowStateMachine<T> =
|
||||||
startFlow(logic).andRunNetwork()
|
startFlow(logic).andRunNetwork()
|
||||||
|
|
||||||
|
fun StartedNode<*>.createConfidentialIdentity(party: Party) = database.transaction {
|
||||||
|
services.keyManagementService.freshKeyAndCert(
|
||||||
|
services.myInfo.legalIdentitiesAndCerts.single { it.name == party.name },
|
||||||
|
false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun StartedNode<*>.verifyAndRegister(identity: PartyAndCertificate) = database.transaction {
|
||||||
|
services.identityService.verifyAndRegisterIdentity(identity)
|
||||||
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Matchers
|
//region Matchers
|
||||||
|
Loading…
x
Reference in New Issue
Block a user