mirror of
https://github.com/corda/corda.git
synced 2025-01-31 16:35:43 +00:00
commit
10b17d6862
@ -48,25 +48,42 @@ fun generateState() = DummyContract.State(Random().nextInt())
|
||||
// contract `fails requirement` "some substring of the error message"
|
||||
// }
|
||||
|
||||
infix fun Cash.State.`owned by`(owner: PublicKey) = copy(owner = owner)
|
||||
infix fun Cash.State.`issued by`(party: Party) = copy(amount = Amount<Issued<Currency>>(amount.quantity, issuanceDef.copy(issuer = deposit.copy(party = party))))
|
||||
infix fun Cash.State.`issued by`(deposit: PartyAndReference) = copy(amount = Amount<Issued<Currency>>(amount.quantity, issuanceDef.copy(issuer = deposit)))
|
||||
infix fun Cash.State.`with notary`(notary: Party) = TransactionState(this, notary)
|
||||
// For Java compatibility please define helper methods here and then define the infix notation
|
||||
object JavaTestHelpers {
|
||||
@JvmStatic fun ownedBy(state: Cash.State, owner: PublicKey) = state.copy(owner = owner)
|
||||
@JvmStatic fun issuedBy(state: Cash.State, party: Party) = state.copy(amount = Amount<Issued<Currency>>(state.amount.quantity, state.issuanceDef.copy(issuer = state.deposit.copy(party = party))))
|
||||
@JvmStatic fun issuedBy(state: Cash.State, deposit: PartyAndReference) = state.copy(amount = Amount<Issued<Currency>>(state.amount.quantity, state.issuanceDef.copy(issuer = deposit)))
|
||||
@JvmStatic fun withNotary(state: Cash.State, notary: Party) = TransactionState(state, notary)
|
||||
@JvmStatic fun withDeposit(state: Cash.State, deposit: PartyAndReference) = state.copy(amount = state.amount.copy(token = state.amount.token.copy(issuer = deposit)))
|
||||
|
||||
infix fun CommercialPaper.State.`owned by`(owner: PublicKey) = this.copy(owner = owner)
|
||||
infix fun CommercialPaper.State.`with notary`(notary: Party) = TransactionState(this, notary)
|
||||
infix fun ICommercialPaperState.`owned by`(new_owner: PublicKey) = this.withOwner(new_owner)
|
||||
@JvmStatic fun ownedBy(state: CommercialPaper.State, owner: PublicKey) = state.copy(owner = owner)
|
||||
@JvmStatic fun withNotary(state: CommercialPaper.State, notary: Party) = TransactionState(state, notary)
|
||||
@JvmStatic fun ownedBy(state: ICommercialPaperState, new_owner: PublicKey) = state.withOwner(new_owner)
|
||||
|
||||
infix fun Cash.State.`with deposit`(deposit: PartyAndReference): Cash.State =
|
||||
copy(amount = amount.copy(token = amount.token.copy(issuer = deposit)))
|
||||
@JvmStatic fun withNotary(state: ContractState, notary: Party) = TransactionState(state, notary)
|
||||
|
||||
@JvmStatic fun CASH(amount: Amount<Currency>) = Cash.State(
|
||||
Amount<Issued<Currency>>(amount.quantity, Issued<Currency>(DUMMY_CASH_ISSUER, amount.token)),
|
||||
NullPublicKey)
|
||||
@JvmStatic fun STATE(amount: Amount<Issued<Currency>>) = Cash.State(amount, NullPublicKey)
|
||||
}
|
||||
|
||||
|
||||
infix fun Cash.State.`owned by`(owner: PublicKey) = JavaTestHelpers.ownedBy(this, owner)
|
||||
infix fun Cash.State.`issued by`(party: Party) = JavaTestHelpers.issuedBy(this, party)
|
||||
infix fun Cash.State.`issued by`(deposit: PartyAndReference) = JavaTestHelpers.issuedBy(this, deposit)
|
||||
infix fun Cash.State.`with notary`(notary: Party) = JavaTestHelpers.withNotary(this, notary)
|
||||
infix fun Cash.State.`with deposit`(deposit: PartyAndReference): Cash.State = JavaTestHelpers.withDeposit(this, deposit)
|
||||
|
||||
infix fun CommercialPaper.State.`owned by`(owner: PublicKey) = JavaTestHelpers.ownedBy(this, owner)
|
||||
infix fun CommercialPaper.State.`with notary`(notary: Party) = JavaTestHelpers.withNotary(this, notary)
|
||||
infix fun ICommercialPaperState.`owned by`(new_owner: PublicKey) = JavaTestHelpers.ownedBy(this, new_owner)
|
||||
|
||||
infix fun ContractState.`with notary`(notary: Party) = JavaTestHelpers.withNotary(this, notary)
|
||||
|
||||
val DUMMY_CASH_ISSUER_KEY = generateKeyPair()
|
||||
val DUMMY_CASH_ISSUER = Party("Snake Oil Issuer", DUMMY_CASH_ISSUER_KEY.public).ref(1)
|
||||
/** Allows you to write 100.DOLLARS.CASH */
|
||||
val Amount<Currency>.CASH: Cash.State get() = Cash.State(
|
||||
Amount<Issued<Currency>>(this.quantity, Issued<Currency>(DUMMY_CASH_ISSUER, this.token)),
|
||||
NullPublicKey)
|
||||
val Amount<Currency>.CASH: Cash.State get() = JavaTestHelpers.CASH(this)
|
||||
val Amount<Issued<Currency>>.STATE: Cash.State get() = JavaTestHelpers.STATE(this)
|
||||
|
||||
val Amount<Issued<Currency>>.STATE: Cash.State get() = Cash.State(this, NullPublicKey)
|
||||
|
||||
infix fun ContractState.`with notary`(notary: Party) = TransactionState(this, notary)
|
||||
|
@ -0,0 +1,58 @@
|
||||
package com.r3corda.contracts.cash;
|
||||
|
||||
import com.r3corda.core.contracts.PartyAndReference;
|
||||
import com.r3corda.core.serialization.OpaqueBytes;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.r3corda.core.testing.JavaTestHelpers.*;
|
||||
import static com.r3corda.core.contracts.JavaTestHelpers.*;
|
||||
import static com.r3corda.contracts.testing.JavaTestHelpers.*;
|
||||
|
||||
/**
|
||||
* This is an incomplete Java replica of CashTests.kt to show how to use the Java test DSL
|
||||
*/
|
||||
public class CashTestsJava {
|
||||
|
||||
private OpaqueBytes defaultRef = new OpaqueBytes(new byte[]{1});;
|
||||
private PartyAndReference defaultIssuer = getMEGA_CORP().ref(defaultRef);
|
||||
private Cash.State inState = new Cash.State(issuedBy(DOLLARS(1000), defaultIssuer), getDUMMY_PUBKEY_1());
|
||||
private Cash.State outState = new Cash.State(inState.getAmount(), getDUMMY_PUBKEY_2());
|
||||
|
||||
@Test
|
||||
public void trivial() {
|
||||
|
||||
transaction(tx -> {
|
||||
tx.input(inState);
|
||||
tx.failsRequirement("the amounts balance");
|
||||
|
||||
tx.tweak(tw -> {
|
||||
tw.output(new Cash.State(issuedBy(DOLLARS(2000), defaultIssuer), getDUMMY_PUBKEY_2()));
|
||||
return tw.failsRequirement("the amounts balance");
|
||||
});
|
||||
|
||||
tx.tweak(tw -> {
|
||||
tw.output(outState);
|
||||
// No command arguments
|
||||
return tw.failsRequirement("required com.r3corda.contracts.cash.FungibleAsset.Commands.Move command");
|
||||
});
|
||||
tx.tweak(tw -> {
|
||||
tw.output(outState);
|
||||
tw.arg(getDUMMY_PUBKEY_2(), new Cash.Commands.Move());
|
||||
return tw.failsRequirement("the owning keys are the same as the signing keys");
|
||||
});
|
||||
tx.tweak(tw -> {
|
||||
tw.output(outState);
|
||||
tw.output(issuedBy(outState, getMINI_CORP()));
|
||||
tw.arg(getDUMMY_PUBKEY_1(), new Cash.Commands.Move());
|
||||
return tw.failsRequirement("at least one asset input");
|
||||
});
|
||||
|
||||
// Simple reallocation works.
|
||||
return tx.tweak(tw -> {
|
||||
tw.output(outState);
|
||||
tw.arg(getDUMMY_PUBKEY_1(), new Cash.Commands.Move());
|
||||
return tw.accepts();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import java.security.PublicKey
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Defines a simple domain specific language for the specificiation of financial contracts. Currently covers:
|
||||
* Defines a simple domain specific language for the specification of financial contracts. Currently covers:
|
||||
*
|
||||
* - Some utilities for working with commands.
|
||||
* - Code for working with currencies.
|
||||
@ -19,18 +19,32 @@ import java.util.*
|
||||
|
||||
fun currency(code: String) = Currency.getInstance(code)
|
||||
|
||||
val USD = currency("USD")
|
||||
val GBP = currency("GBP")
|
||||
val CHF = currency("CHF")
|
||||
// Java interop
|
||||
object JavaTestHelpers {
|
||||
@JvmStatic val USD: Currency get() = currency("USD")
|
||||
@JvmStatic val GBP: Currency get() = currency("GBP")
|
||||
@JvmStatic val CHF: Currency get() = currency("CHF")
|
||||
|
||||
val Int.DOLLARS: Amount<Currency> get() = Amount(this.toLong() * 100, USD)
|
||||
val Int.POUNDS: Amount<Currency> get() = Amount(this.toLong() * 100, GBP)
|
||||
val Int.SWISS_FRANCS: Amount<Currency> get() = Amount(this.toLong() * 100, CHF)
|
||||
@JvmStatic fun DOLLARS(amount: Int) = Amount(amount.toLong() * 100, USD)
|
||||
@JvmStatic fun DOLLARS(amount: Double) = Amount((amount * 100).toLong(), USD)
|
||||
@JvmStatic fun POUNDS(amount: Int) = Amount(amount.toLong() * 100, GBP)
|
||||
@JvmStatic fun SWISS_FRANCS(amount: Int) = Amount(amount.toLong() * 100, CHF)
|
||||
|
||||
val Double.DOLLARS: Amount<Currency> get() = Amount((this * 100).toLong(), USD)
|
||||
@JvmStatic fun issuedBy(currency: Currency, deposit: PartyAndReference) = Issued<Currency>(deposit, currency)
|
||||
@JvmStatic fun issuedBy(amount: Amount<Currency>, deposit: PartyAndReference) = Amount(amount.quantity, issuedBy(amount.token, deposit))
|
||||
}
|
||||
|
||||
infix fun Currency.`issued by`(deposit: PartyAndReference) : Issued<Currency> = Issued<Currency>(deposit, this)
|
||||
infix fun <T> Amount<T>.`issued by`(deposit: PartyAndReference) : Amount<Issued<T>> = Amount(quantity, Issued<T>(deposit, this.token))
|
||||
val USD = JavaTestHelpers.USD
|
||||
val GBP = JavaTestHelpers.GBP
|
||||
val CHF = JavaTestHelpers.CHF
|
||||
|
||||
val Int.DOLLARS: Amount<Currency> get() = JavaTestHelpers.DOLLARS(this)
|
||||
val Double.DOLLARS: Amount<Currency> get() = JavaTestHelpers.DOLLARS(this)
|
||||
val Int.POUNDS: Amount<Currency> get() = JavaTestHelpers.POUNDS(this)
|
||||
val Int.SWISS_FRANCS: Amount<Currency> get() = JavaTestHelpers.SWISS_FRANCS(this)
|
||||
|
||||
infix fun Currency.`issued by`(deposit: PartyAndReference) = JavaTestHelpers.issuedBy(this, deposit)
|
||||
infix fun Amount<Currency>.`issued by`(deposit: PartyAndReference) = JavaTestHelpers.issuedBy(this, deposit)
|
||||
|
||||
//// Requirements /////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -111,4 +125,4 @@ inline fun <reified T : CommandData> verifyMoveCommand(inputs: List<OwnableState
|
||||
requireThat {
|
||||
"the owning keys are the same as the signing keys" by keysThatSigned.containsAll(owningPubKeys)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.google.common.base.Throwables
|
||||
import com.google.common.net.HostAndPort
|
||||
import com.r3corda.core.contracts.*
|
||||
import com.r3corda.core.crypto.*
|
||||
import com.r3corda.core.node.services.IdentityService
|
||||
import com.r3corda.core.node.services.testing.MockIdentityService
|
||||
import com.r3corda.core.node.services.testing.MockStorageService
|
||||
import com.r3corda.core.seconds
|
||||
@ -39,41 +40,91 @@ object TestUtils {
|
||||
val keypair3 = generateKeyPair()
|
||||
}
|
||||
|
||||
// A dummy time at which we will be pretending test transactions are created.
|
||||
val TEST_TX_TIME = Instant.parse("2015-04-17T12:00:00.00Z")
|
||||
/**
|
||||
* JAVA INTEROP. Please keep the following points in mind when extending the Kotlin DSL
|
||||
*
|
||||
* - Annotate functions with Kotlin defaults with @JvmOverloads. This produces the relevant overloads for Java.
|
||||
* - Void closures in arguments are inconvenient in Java, use overloading to define non-closure variants as well.
|
||||
* - Top-level funs should be defined in a [JavaTestHelpers] object and annotated with @JvmStatic first and should be
|
||||
* referred to from the global fun. This allows static importing of [JavaTestHelpers] in Java tests, which mimicks
|
||||
* top-level funs.
|
||||
* - Top-level vals are trickier. *DO NOT USE @JvmField INSIDE [JavaTestHelpers]*. It's surprisingly easy to
|
||||
* introduce a static init cycle because of the way Kotlin compiles top-level things, which can cause
|
||||
* non-deterministic behaviour, including your field not being initialized at all! Instead opt for a proper Kotlin
|
||||
* val either with a custom @JvmStatic get() or a lazy delegate if the initialiser has side-effects See examples below.
|
||||
* - Infix functions work as regular ones from Java, but symbols with spaces in them don't! Define a camelCase variant
|
||||
* as well.
|
||||
* - varargs are exposed as array types in Java. Define overloads for common cases.
|
||||
* - The Int.DOLLARS syntax doesn't work from Java. To remedy add a @JvmStatic DOLLARS(Int) function to
|
||||
* [JavaTestHelpers]
|
||||
*/
|
||||
object JavaTestHelpers {
|
||||
// A dummy time at which we will be pretending test transactions are created.
|
||||
@JvmStatic val TEST_TX_TIME: Instant get() = Instant.parse("2015-04-17T12:00:00.00Z")
|
||||
|
||||
// A few dummy values for testing.
|
||||
val MEGA_CORP_KEY = TestUtils.keypair
|
||||
val MEGA_CORP_PUBKEY = MEGA_CORP_KEY.public
|
||||
// A few dummy values for testing.
|
||||
@JvmStatic val MEGA_CORP_KEY: KeyPair get() = TestUtils.keypair
|
||||
@JvmStatic val MEGA_CORP_PUBKEY: PublicKey get() = MEGA_CORP_KEY.public
|
||||
|
||||
val MINI_CORP_KEY = TestUtils.keypair2
|
||||
val MINI_CORP_PUBKEY = MINI_CORP_KEY.public
|
||||
@JvmStatic val MINI_CORP_KEY: KeyPair get() = TestUtils.keypair2
|
||||
@JvmStatic val MINI_CORP_PUBKEY: PublicKey get() = MINI_CORP_KEY.public
|
||||
|
||||
val ORACLE_KEY = TestUtils.keypair3
|
||||
val ORACLE_PUBKEY = ORACLE_KEY.public
|
||||
@JvmStatic val ORACLE_KEY: KeyPair get() = TestUtils.keypair3
|
||||
@JvmStatic val ORACLE_PUBKEY: PublicKey get() = ORACLE_KEY.public
|
||||
|
||||
val DUMMY_PUBKEY_1 = DummyPublicKey("x1")
|
||||
val DUMMY_PUBKEY_2 = DummyPublicKey("x2")
|
||||
@JvmStatic val DUMMY_PUBKEY_1: PublicKey get() = DummyPublicKey("x1")
|
||||
@JvmStatic val DUMMY_PUBKEY_2: PublicKey get() = DummyPublicKey("x2")
|
||||
|
||||
val ALICE_KEY = generateKeyPair()
|
||||
val ALICE_PUBKEY = ALICE_KEY.public
|
||||
val ALICE = Party("Alice", ALICE_PUBKEY)
|
||||
@JvmStatic val ALICE_KEY: KeyPair by lazy { generateKeyPair() }
|
||||
@JvmStatic val ALICE_PUBKEY: PublicKey get() = ALICE_KEY.public
|
||||
@JvmStatic val ALICE: Party get() = Party("Alice", ALICE_PUBKEY)
|
||||
|
||||
val BOB_KEY = generateKeyPair()
|
||||
val BOB_PUBKEY = BOB_KEY.public
|
||||
val BOB = Party("Bob", BOB_PUBKEY)
|
||||
@JvmStatic val BOB_KEY: KeyPair by lazy { generateKeyPair() }
|
||||
@JvmStatic val BOB_PUBKEY: PublicKey get() = BOB_KEY.public
|
||||
@JvmStatic val BOB: Party get() = Party("Bob", BOB_PUBKEY)
|
||||
|
||||
val MEGA_CORP = Party("MegaCorp", MEGA_CORP_PUBKEY)
|
||||
val MINI_CORP = Party("MiniCorp", MINI_CORP_PUBKEY)
|
||||
@JvmStatic val MEGA_CORP: Party get() = Party("MegaCorp", MEGA_CORP_PUBKEY)
|
||||
@JvmStatic val MINI_CORP: Party get() = Party("MiniCorp", MINI_CORP_PUBKEY)
|
||||
|
||||
val DUMMY_NOTARY_KEY = generateKeyPair()
|
||||
val DUMMY_NOTARY = Party("Notary Service", DUMMY_NOTARY_KEY.public)
|
||||
@JvmStatic val DUMMY_NOTARY_KEY: KeyPair by lazy { generateKeyPair() }
|
||||
@JvmStatic val DUMMY_NOTARY: Party get() = Party("Notary Service", DUMMY_NOTARY_KEY.public)
|
||||
|
||||
val ALL_TEST_KEYS = listOf(MEGA_CORP_KEY, MINI_CORP_KEY, ALICE_KEY, BOB_KEY, DUMMY_NOTARY_KEY)
|
||||
@JvmStatic val ALL_TEST_KEYS: List<KeyPair> get() = listOf(MEGA_CORP_KEY, MINI_CORP_KEY, ALICE_KEY, BOB_KEY, DUMMY_NOTARY_KEY)
|
||||
|
||||
val MOCK_IDENTITY_SERVICE = MockIdentityService(listOf(MEGA_CORP, MINI_CORP, DUMMY_NOTARY))
|
||||
@JvmStatic val MOCK_IDENTITY_SERVICE: MockIdentityService get() = MockIdentityService(listOf(MEGA_CORP, MINI_CORP, DUMMY_NOTARY))
|
||||
|
||||
fun generateStateRef() = StateRef(SecureHash.randomSHA256(), 0)
|
||||
@JvmStatic fun generateStateRef() = StateRef(SecureHash.randomSHA256(), 0)
|
||||
|
||||
@JvmStatic fun transaction(body: TransactionForTest.() -> LastLineShouldTestForAcceptOrFailure): LastLineShouldTestForAcceptOrFailure {
|
||||
return body(TransactionForTest())
|
||||
}
|
||||
}
|
||||
|
||||
val TEST_TX_TIME = JavaTestHelpers.TEST_TX_TIME
|
||||
val MEGA_CORP_KEY = JavaTestHelpers.MEGA_CORP_KEY
|
||||
val MEGA_CORP_PUBKEY = JavaTestHelpers.MEGA_CORP_PUBKEY
|
||||
val MINI_CORP_KEY = JavaTestHelpers.MINI_CORP_KEY
|
||||
val MINI_CORP_PUBKEY = JavaTestHelpers.MINI_CORP_PUBKEY
|
||||
val ORACLE_KEY = JavaTestHelpers.ORACLE_KEY
|
||||
val ORACLE_PUBKEY = JavaTestHelpers.ORACLE_PUBKEY
|
||||
val DUMMY_PUBKEY_1 = JavaTestHelpers.DUMMY_PUBKEY_1
|
||||
val DUMMY_PUBKEY_2 = JavaTestHelpers.DUMMY_PUBKEY_2
|
||||
val ALICE_KEY = JavaTestHelpers.ALICE_KEY
|
||||
val ALICE_PUBKEY = JavaTestHelpers.ALICE_PUBKEY
|
||||
val ALICE = JavaTestHelpers.ALICE
|
||||
val BOB_KEY = JavaTestHelpers.BOB_KEY
|
||||
val BOB_PUBKEY = JavaTestHelpers.BOB_PUBKEY
|
||||
val BOB = JavaTestHelpers.BOB
|
||||
val MEGA_CORP = JavaTestHelpers.MEGA_CORP
|
||||
val MINI_CORP = JavaTestHelpers.MINI_CORP
|
||||
val DUMMY_NOTARY_KEY = JavaTestHelpers.DUMMY_NOTARY_KEY
|
||||
val DUMMY_NOTARY = JavaTestHelpers.DUMMY_NOTARY
|
||||
val ALL_TEST_KEYS = JavaTestHelpers.ALL_TEST_KEYS
|
||||
val MOCK_IDENTITY_SERVICE = JavaTestHelpers.MOCK_IDENTITY_SERVICE
|
||||
|
||||
fun generateStateRef() = JavaTestHelpers.generateStateRef()
|
||||
|
||||
fun transaction(body: TransactionForTest.() -> LastLineShouldTestForAcceptOrFailure) = JavaTestHelpers.transaction(body)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -94,8 +145,6 @@ fun generateStateRef() = StateRef(SecureHash.randomSHA256(), 0)
|
||||
// contract `fails requirement` "some substring of the error message"
|
||||
// }
|
||||
//
|
||||
// TODO: Make it impossible to forget to test either a failure or an accept for each transaction{} block
|
||||
|
||||
class LabeledOutput(val label: String?, val state: TransactionState<*>) {
|
||||
override fun toString() = state.toString() + (if (label != null) " ($label)" else "")
|
||||
override fun equals(other: Any?) = other is LabeledOutput && state.equals(other.state)
|
||||
@ -111,7 +160,10 @@ abstract class AbstractTransactionForTest {
|
||||
protected val signers = LinkedHashSet<PublicKey>()
|
||||
protected val type = TransactionType.General()
|
||||
|
||||
@JvmOverloads
|
||||
open fun output(label: String? = null, s: () -> ContractState) = LabeledOutput(label, TransactionState(s(), DUMMY_NOTARY)).apply { outStates.add(this) }
|
||||
@JvmOverloads
|
||||
open fun output(label: String? = null, s: ContractState) = output(label) { s }
|
||||
|
||||
protected fun commandsToAuthenticatedObjects(): List<AuthenticatedObject<CommandData>> {
|
||||
return commands.map { AuthenticatedObject(it.signers, it.signers.mapNotNull { MOCK_IDENTITY_SERVICE.partyFromKey(it) }, it.value) }
|
||||
@ -121,10 +173,11 @@ abstract class AbstractTransactionForTest {
|
||||
attachments.add(attachmentID)
|
||||
}
|
||||
|
||||
fun arg(vararg key: PublicKey, c: () -> CommandData) {
|
||||
val keys = listOf(*key)
|
||||
addCommand(Command(c(), keys))
|
||||
fun arg(vararg keys: PublicKey, c: () -> CommandData) {
|
||||
val keysList = listOf(*keys)
|
||||
addCommand(Command(c(), keysList))
|
||||
}
|
||||
fun arg(key: PublicKey, c: CommandData) = arg(key) { c }
|
||||
|
||||
fun timestamp(time: Instant) {
|
||||
val data = TimestampCommand(time, 30.seconds)
|
||||
@ -156,12 +209,15 @@ sealed class LastLineShouldTestForAcceptOrFailure {
|
||||
}
|
||||
|
||||
// Corresponds to the args to Contract.verify
|
||||
// Note on defaults: try to avoid Kotlin defaults as they don't work from Java. Instead define overloads
|
||||
open class TransactionForTest : AbstractTransactionForTest() {
|
||||
private val inStates = arrayListOf<TransactionState<ContractState>>()
|
||||
|
||||
fun input(s: () -> ContractState) {
|
||||
signers.add(DUMMY_NOTARY.owningKey)
|
||||
inStates.add(TransactionState(s(), DUMMY_NOTARY))
|
||||
}
|
||||
fun input(s: ContractState) = input { s }
|
||||
|
||||
protected fun runCommandsAndVerify(time: Instant) {
|
||||
val cmds = commandsToAuthenticatedObjects()
|
||||
@ -169,11 +225,14 @@ open class TransactionForTest : AbstractTransactionForTest() {
|
||||
tx.verify()
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun accepts(time: Instant = TEST_TX_TIME): LastLineShouldTestForAcceptOrFailure {
|
||||
runCommandsAndVerify(time)
|
||||
return LastLineShouldTestForAcceptOrFailure.Token
|
||||
}
|
||||
fun rejects(withMessage: String? = null, time: Instant = TEST_TX_TIME) {
|
||||
|
||||
@JvmOverloads
|
||||
fun rejects(withMessage: String? = null, time: Instant = TEST_TX_TIME): LastLineShouldTestForAcceptOrFailure {
|
||||
val r = try {
|
||||
runCommandsAndVerify(time)
|
||||
false
|
||||
@ -186,17 +245,14 @@ open class TransactionForTest : AbstractTransactionForTest() {
|
||||
true
|
||||
}
|
||||
if (!r) throw AssertionError("Expected exception but didn't get one")
|
||||
return LastLineShouldTestForAcceptOrFailure.Token
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to confirm that the test, when (implicitly) run against the .verify() method, fails with the text of the message
|
||||
*/
|
||||
infix fun `fails requirement`(msg: String): LastLineShouldTestForAcceptOrFailure {
|
||||
rejects(msg)
|
||||
return LastLineShouldTestForAcceptOrFailure.Token
|
||||
}
|
||||
|
||||
fun fails_requirement(msg: String) = this.`fails requirement`(msg)
|
||||
infix fun `fails requirement`(msg: String): LastLineShouldTestForAcceptOrFailure = rejects(msg)
|
||||
fun failsRequirement(msg: String) = this.`fails requirement`(msg)
|
||||
|
||||
// Use this to create transactions where the output of this transaction is automatically used as an input of
|
||||
// the next.
|
||||
@ -244,10 +300,6 @@ open class TransactionForTest : AbstractTransactionForTest() {
|
||||
}
|
||||
}
|
||||
|
||||
fun transaction(body: TransactionForTest.() -> LastLineShouldTestForAcceptOrFailure): LastLineShouldTestForAcceptOrFailure {
|
||||
return body(TransactionForTest())
|
||||
}
|
||||
|
||||
class TransactionGroupDSL<T : ContractState>(private val stateType: Class<T>) {
|
||||
open inner class WireTransactionDSL : AbstractTransactionForTest() {
|
||||
private val inStates = ArrayList<StateRef>()
|
||||
@ -328,6 +380,7 @@ class TransactionGroupDSL<T : ContractState>(private val stateType: Class<T>) {
|
||||
val txns = ArrayList<WireTransaction>()
|
||||
private val txnToLabelMap = HashMap<SecureHash, String>()
|
||||
|
||||
@JvmOverloads
|
||||
fun transaction(label: String? = null, body: WireTransactionDSL.() -> Unit): WireTransaction {
|
||||
val forTest = InternalWireTransactionDSL()
|
||||
forTest.body()
|
||||
|
@ -1,24 +0,0 @@
|
||||
package com.r3corda.contracts.testing
|
||||
|
||||
import com.r3corda.contracts.Obligation
|
||||
import com.r3corda.contracts.cash.Cash
|
||||
import com.r3corda.core.contracts.Amount
|
||||
import com.r3corda.core.contracts.Issued
|
||||
import com.r3corda.core.crypto.NullPublicKey
|
||||
import com.r3corda.core.crypto.Party
|
||||
import com.r3corda.core.testing.MINI_CORP
|
||||
import com.r3corda.core.utilities.nonEmptySetOf
|
||||
import java.security.PublicKey
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
|
||||
infix fun <T> Obligation.State<T>.`at`(dueBefore: Instant) = copy(template = template.copy(dueBefore = dueBefore))
|
||||
infix fun <T> Obligation.State<T>.`between`(parties: Pair<Party, PublicKey>) = copy(issuer = parties.first, owner = parties.second)
|
||||
infix fun <T> Obligation.State<T>.`owned by`(owner: PublicKey) = copy(owner = owner)
|
||||
infix fun <T> Obligation.State<T>.`issued by`(party: Party) = copy(issuer = party)
|
||||
|
||||
// Allows you to write 100.DOLLARS.OBLIGATION
|
||||
val Issued<Currency>.OBLIGATION_DEF: Obligation.StateTemplate<Currency> get() = Obligation.StateTemplate(nonEmptySetOf(Cash().legalContractReference),
|
||||
nonEmptySetOf(this), Instant.parse("2020-01-01T17:00:00Z"))
|
||||
val Amount<Issued<Currency>>.OBLIGATION: Obligation.State<Currency> get() = Obligation.State(Obligation.Lifecycle.NORMAL, MINI_CORP,
|
||||
this.token.OBLIGATION_DEF, this.quantity, NullPublicKey)
|
@ -0,0 +1,33 @@
|
||||
package com.r3corda.contracts.testing
|
||||
|
||||
import com.r3corda.contracts.Obligation
|
||||
import com.r3corda.contracts.cash.Cash
|
||||
import com.r3corda.core.contracts.Amount
|
||||
import com.r3corda.core.contracts.Issued
|
||||
import com.r3corda.core.crypto.NullPublicKey
|
||||
import com.r3corda.core.crypto.Party
|
||||
import com.r3corda.core.testing.MINI_CORP
|
||||
import com.r3corda.core.utilities.nonEmptySetOf
|
||||
import java.security.PublicKey
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
|
||||
object JavaExperimental {
|
||||
@JvmStatic fun <T> at(state: Obligation.State<T>, dueBefore: Instant) = state.copy(template = state.template.copy(dueBefore = dueBefore))
|
||||
@JvmStatic fun <T> between(state: Obligation.State<T>, parties: Pair<Party, PublicKey>) = state.copy(issuer = parties.first, owner = parties.second)
|
||||
@JvmStatic fun <T> ownedBy(state: Obligation.State<T>, owner: PublicKey) = state.copy(owner = owner)
|
||||
@JvmStatic fun <T> issuedBy(state: Obligation.State<T>, party: Party) = state.copy(issuer = party)
|
||||
|
||||
@JvmStatic fun OBLIGATION_DEF(issued: Issued<Currency>)
|
||||
= Obligation.StateTemplate(nonEmptySetOf(Cash().legalContractReference), nonEmptySetOf(issued), Instant.parse("2020-01-01T17:00:00Z"))
|
||||
@JvmStatic fun OBLIGATION(amount: Amount<Issued<Currency>>) = Obligation.State(Obligation.Lifecycle.NORMAL, MINI_CORP,
|
||||
OBLIGATION_DEF(amount.token), amount.quantity, NullPublicKey)
|
||||
}
|
||||
infix fun <T> Obligation.State<T>.`at`(dueBefore: Instant) = JavaExperimental.at(this, dueBefore)
|
||||
infix fun <T> Obligation.State<T>.`between`(parties: Pair<Party, PublicKey>) = JavaExperimental.between(this, parties)
|
||||
infix fun <T> Obligation.State<T>.`owned by`(owner: PublicKey) = JavaExperimental.ownedBy(this, owner)
|
||||
infix fun <T> Obligation.State<T>.`issued by`(party: Party) = JavaExperimental.issuedBy(this, party)
|
||||
|
||||
// Allows you to write 100.DOLLARS.OBLIGATION
|
||||
val Issued<Currency>.OBLIGATION_DEF: Obligation.StateTemplate<Currency> get() = JavaExperimental.OBLIGATION_DEF(this)
|
||||
val Amount<Issued<Currency>>.OBLIGATION: Obligation.State<Currency> get() = JavaExperimental.OBLIGATION(this)
|
Loading…
x
Reference in New Issue
Block a user