mirror of
https://github.com/corda/corda.git
synced 2025-02-20 09:26:41 +00:00
contracts, core, node: Port TransactionForTest tests to new DSL
This commit is contained in:
parent
a27f195b4f
commit
e3d6f51049
@ -76,6 +76,7 @@ class CommercialPaperTestsGeneric {
|
||||
output("paper") { thisTest.getPaper() }
|
||||
command(MEGA_CORP_PUBKEY) { thisTest.getIssueCommand() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
// The CP is sold to alice for her $900, $100 less than the face value. At 10% interest after only 7 days,
|
||||
@ -87,6 +88,7 @@ class CommercialPaperTestsGeneric {
|
||||
output("alice's paper") { "paper".output<ICommercialPaperState>().data `owned by` ALICE_PUBKEY }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||
command(MEGA_CORP_PUBKEY) { thisTest.getMoveCommand() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
// Time passes, and Alice redeem's her CP for $1000, netting a $100 profit. MegaCorp has received $1200
|
||||
@ -95,7 +97,7 @@ class CommercialPaperTestsGeneric {
|
||||
input("alice's paper")
|
||||
input("some profits")
|
||||
|
||||
fun TransactionDsl<TransactionDslInterpreter>.outputs(aliceGetsBack: Amount<Issued<Currency>>) {
|
||||
fun TransactionDsl<LastLineShouldTestForVerifiesOrFails, TransactionDslInterpreter<LastLineShouldTestForVerifiesOrFails>>.outputs(aliceGetsBack: Amount<Issued<Currency>>) {
|
||||
output("Alice's profit") { aliceGetsBack.STATE `owned by` ALICE_PUBKEY }
|
||||
output("Change") { (someProfits - aliceGetsBack).STATE `owned by` MEGA_CORP_PUBKEY }
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ class IRSTests {
|
||||
/**
|
||||
* Generates a typical transactional history for an IRS.
|
||||
*/
|
||||
fun trade(): LedgerDsl<TestTransactionDslInterpreter, TestLedgerDslInterpreter> {
|
||||
fun trade(): LedgerDsl<LastLineShouldTestForVerifiesOrFails, TestTransactionDslInterpreter, TestLedgerDslInterpreter> {
|
||||
|
||||
val ld = LocalDate.of(2016, 3, 8)
|
||||
val bd = BigDecimal("0.0063518")
|
||||
@ -370,6 +370,7 @@ class IRSTests {
|
||||
output("irs post agreement") { singleIRS() }
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
transaction("Fix") {
|
||||
@ -390,82 +391,93 @@ class IRSTests {
|
||||
Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
|
||||
}
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure failure occurs when there are inbound states for an agreement command`() {
|
||||
transaction {
|
||||
input() { singleIRS() }
|
||||
output("irs post agreement") { singleIRS() }
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "There are no in states for an agreement"
|
||||
ledger {
|
||||
transaction {
|
||||
input() { singleIRS() }
|
||||
output("irs post agreement") { singleIRS() }
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "There are no in states for an agreement"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure failure occurs when no events in fix schedule`() {
|
||||
val irs = singleIRS()
|
||||
val emptySchedule = HashMap<LocalDate, FixedRatePaymentEvent>()
|
||||
transaction {
|
||||
output() {
|
||||
irs.copy(calculation = irs.calculation.copy(fixedLegPaymentSchedule = emptySchedule))
|
||||
ledger {
|
||||
val irs = singleIRS()
|
||||
val emptySchedule = HashMap<LocalDate, FixedRatePaymentEvent>()
|
||||
transaction {
|
||||
output() {
|
||||
irs.copy(calculation = irs.calculation.copy(fixedLegPaymentSchedule = emptySchedule))
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "There are events in the fix schedule"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "There are events in the fix schedule"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure failure occurs when no events in floating schedule`() {
|
||||
val irs = singleIRS()
|
||||
val emptySchedule = HashMap<LocalDate, FloatingRatePaymentEvent>()
|
||||
transaction {
|
||||
output() {
|
||||
irs.copy(calculation = irs.calculation.copy(floatingLegPaymentSchedule = emptySchedule))
|
||||
ledger {
|
||||
val irs = singleIRS()
|
||||
val emptySchedule = HashMap<LocalDate, FloatingRatePaymentEvent>()
|
||||
transaction {
|
||||
output() {
|
||||
irs.copy(calculation = irs.calculation.copy(floatingLegPaymentSchedule = emptySchedule))
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "There are events in the float schedule"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "There are events in the float schedule"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure notionals are non zero`() {
|
||||
val irs = singleIRS()
|
||||
transaction {
|
||||
output() {
|
||||
irs.copy(irs.fixedLeg.copy(notional = irs.fixedLeg.notional.copy(quantity = 0)))
|
||||
ledger {
|
||||
val irs = singleIRS()
|
||||
transaction {
|
||||
output() {
|
||||
irs.copy(irs.fixedLeg.copy(notional = irs.fixedLeg.notional.copy(quantity = 0)))
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "All notionals must be non zero"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "All notionals must be non zero"
|
||||
}
|
||||
|
||||
transaction {
|
||||
output() {
|
||||
irs.copy(irs.fixedLeg.copy(notional = irs.floatingLeg.notional.copy(quantity = 0)))
|
||||
transaction {
|
||||
output() {
|
||||
irs.copy(irs.fixedLeg.copy(notional = irs.floatingLeg.notional.copy(quantity = 0)))
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "All notionals must be non zero"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "All notionals must be non zero"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure positive rate on fixed leg`() {
|
||||
val irs = singleIRS()
|
||||
val modifiedIRS = irs.copy(fixedLeg = irs.fixedLeg.copy(fixedRate = FixedRate(PercentageRatioUnit("-0.1"))))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS
|
||||
ledger {
|
||||
val irs = singleIRS()
|
||||
val modifiedIRS = irs.copy(fixedLeg = irs.fixedLeg.copy(fixedRate = FixedRate(PercentageRatioUnit("-0.1"))))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "The fixed leg rate must be positive"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "The fixed leg rate must be positive"
|
||||
}
|
||||
}
|
||||
|
||||
@ -474,173 +486,183 @@ class IRSTests {
|
||||
*/
|
||||
@Test
|
||||
fun `ensure same currency notionals`() {
|
||||
val irs = singleIRS()
|
||||
val modifiedIRS = irs.copy(fixedLeg = irs.fixedLeg.copy(notional = Amount(irs.fixedLeg.notional.quantity, Currency.getInstance("JPY"))))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS
|
||||
ledger {
|
||||
val irs = singleIRS()
|
||||
val modifiedIRS = irs.copy(fixedLeg = irs.fixedLeg.copy(notional = Amount(irs.fixedLeg.notional.quantity, Currency.getInstance("JPY"))))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "The currency of the notionals must be the same"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "The currency of the notionals must be the same"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure notional amounts are equal`() {
|
||||
val irs = singleIRS()
|
||||
val modifiedIRS = irs.copy(fixedLeg = irs.fixedLeg.copy(notional = Amount(irs.floatingLeg.notional.quantity + 1, irs.floatingLeg.notional.token)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS
|
||||
ledger {
|
||||
val irs = singleIRS()
|
||||
val modifiedIRS = irs.copy(fixedLeg = irs.fixedLeg.copy(notional = Amount(irs.floatingLeg.notional.quantity + 1, irs.floatingLeg.notional.token)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "All leg notionals must be the same"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "All leg notionals must be the same"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure trade date and termination date checks are done pt1`() {
|
||||
val irs = singleIRS()
|
||||
val modifiedIRS1 = irs.copy(fixedLeg = irs.fixedLeg.copy(terminationDate = irs.fixedLeg.effectiveDate.minusDays(1)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS1
|
||||
ledger {
|
||||
val irs = singleIRS()
|
||||
val modifiedIRS1 = irs.copy(fixedLeg = irs.fixedLeg.copy(terminationDate = irs.fixedLeg.effectiveDate.minusDays(1)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS1
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "The effective date is before the termination date for the fixed leg"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "The effective date is before the termination date for the fixed leg"
|
||||
}
|
||||
|
||||
val modifiedIRS2 = irs.copy(floatingLeg = irs.floatingLeg.copy(terminationDate = irs.floatingLeg.effectiveDate.minusDays(1)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS2
|
||||
val modifiedIRS2 = irs.copy(floatingLeg = irs.floatingLeg.copy(terminationDate = irs.floatingLeg.effectiveDate.minusDays(1)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS2
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "The effective date is before the termination date for the floating leg"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "The effective date is before the termination date for the floating leg"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure trade date and termination date checks are done pt2`() {
|
||||
val irs = singleIRS()
|
||||
ledger {
|
||||
val irs = singleIRS()
|
||||
|
||||
val modifiedIRS3 = irs.copy(floatingLeg = irs.floatingLeg.copy(terminationDate = irs.fixedLeg.terminationDate.minusDays(1)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS3
|
||||
val modifiedIRS3 = irs.copy(floatingLeg = irs.floatingLeg.copy(terminationDate = irs.fixedLeg.terminationDate.minusDays(1)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS3
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "The termination dates are aligned"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "The termination dates are aligned"
|
||||
}
|
||||
|
||||
|
||||
val modifiedIRS4 = irs.copy(floatingLeg = irs.floatingLeg.copy(effectiveDate = irs.fixedLeg.effectiveDate.minusDays(1)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS4
|
||||
val modifiedIRS4 = irs.copy(floatingLeg = irs.floatingLeg.copy(effectiveDate = irs.fixedLeg.effectiveDate.minusDays(1)))
|
||||
transaction {
|
||||
output() {
|
||||
modifiedIRS4
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails with` "The effective dates are aligned"
|
||||
}
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this `fails requirement` "The effective dates are aligned"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `various fixing tests`() {
|
||||
ledger {
|
||||
|
||||
val ld = LocalDate.of(2016, 3, 8)
|
||||
val bd = BigDecimal("0.0063518")
|
||||
|
||||
transaction {
|
||||
output("irs post agreement") { singleIRS() }
|
||||
arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.accepts()
|
||||
}
|
||||
|
||||
val oldIRS = singleIRS(1)
|
||||
val newIRS = oldIRS.copy(oldIRS.fixedLeg,
|
||||
oldIRS.floatingLeg,
|
||||
oldIRS.calculation.applyFixing(ld, FixedRate(RatioUnit(bd))),
|
||||
oldIRS.common)
|
||||
|
||||
transaction {
|
||||
input() {
|
||||
oldIRS
|
||||
val ld = LocalDate.of(2016, 3, 8)
|
||||
val bd = BigDecimal("0.0063518")
|
||||
|
||||
transaction {
|
||||
output("irs post agreement") { singleIRS() }
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
// Templated tweak for reference. A corrent fixing applied should be ok
|
||||
tweak {
|
||||
arg(ORACLE_PUBKEY) {
|
||||
InterestRateSwap.Commands.Fix()
|
||||
}
|
||||
timestamp(TEST_TX_TIME)
|
||||
arg(ORACLE_PUBKEY) {
|
||||
Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
|
||||
}
|
||||
output() { newIRS }
|
||||
this.accepts()
|
||||
}
|
||||
val oldIRS = singleIRS(1)
|
||||
val newIRS = oldIRS.copy(oldIRS.fixedLeg,
|
||||
oldIRS.floatingLeg,
|
||||
oldIRS.calculation.applyFixing(ld, FixedRate(RatioUnit(bd))),
|
||||
oldIRS.common)
|
||||
|
||||
// This test makes sure that verify confirms the fixing was applied and there is a difference in the old and new
|
||||
tweak {
|
||||
arg(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
arg(ORACLE_PUBKEY) { Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd) }
|
||||
output() { oldIRS }
|
||||
this`fails requirement` "There is at least one difference in the IRS floating leg payment schedules"
|
||||
}
|
||||
transaction {
|
||||
input() {
|
||||
oldIRS
|
||||
|
||||
// This tests tries to sneak in a change to another fixing (which may or may not be the latest one)
|
||||
tweak {
|
||||
arg(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
arg(ORACLE_PUBKEY) {
|
||||
Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
|
||||
}
|
||||
|
||||
val firstResetKey = newIRS.calculation.floatingLegPaymentSchedule.keys.first()
|
||||
val firstResetValue = newIRS.calculation.floatingLegPaymentSchedule[firstResetKey]
|
||||
val modifiedFirstResetValue = firstResetValue!!.copy(notional = Amount(firstResetValue.notional.quantity, Currency.getInstance("JPY")))
|
||||
|
||||
output() {
|
||||
newIRS.copy(
|
||||
newIRS.fixedLeg,
|
||||
newIRS.floatingLeg,
|
||||
newIRS.calculation.copy(floatingLegPaymentSchedule = newIRS.calculation.floatingLegPaymentSchedule.plus(
|
||||
Pair(firstResetKey, modifiedFirstResetValue))),
|
||||
newIRS.common
|
||||
)
|
||||
// Templated tweak for reference. A corrent fixing applied should be ok
|
||||
tweak {
|
||||
command(ORACLE_PUBKEY) {
|
||||
InterestRateSwap.Commands.Fix()
|
||||
}
|
||||
timestamp(TEST_TX_TIME)
|
||||
command(ORACLE_PUBKEY) {
|
||||
Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
|
||||
}
|
||||
output() { newIRS }
|
||||
this.verifies()
|
||||
}
|
||||
this`fails requirement` "There is only one change in the IRS floating leg payment schedule"
|
||||
}
|
||||
|
||||
// This tests modifies the payment currency for the fixing
|
||||
tweak {
|
||||
arg(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
arg(ORACLE_PUBKEY) { Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd) }
|
||||
|
||||
val latestReset = newIRS.calculation.floatingLegPaymentSchedule.filter { it.value.rate is FixedRate }.maxBy { it.key }
|
||||
val modifiedLatestResetValue = latestReset!!.value.copy(notional = Amount(latestReset.value.notional.quantity, Currency.getInstance("JPY")))
|
||||
|
||||
output() {
|
||||
newIRS.copy(
|
||||
newIRS.fixedLeg,
|
||||
newIRS.floatingLeg,
|
||||
newIRS.calculation.copy(floatingLegPaymentSchedule = newIRS.calculation.floatingLegPaymentSchedule.plus(
|
||||
Pair(latestReset.key, modifiedLatestResetValue))),
|
||||
newIRS.common
|
||||
)
|
||||
// This test makes sure that verify confirms the fixing was applied and there is a difference in the old and new
|
||||
tweak {
|
||||
command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
command(ORACLE_PUBKEY) { Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd) }
|
||||
output() { oldIRS }
|
||||
this `fails with` "There is at least one difference in the IRS floating leg payment schedules"
|
||||
}
|
||||
|
||||
// This tests tries to sneak in a change to another fixing (which may or may not be the latest one)
|
||||
tweak {
|
||||
command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
command(ORACLE_PUBKEY) {
|
||||
Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
|
||||
}
|
||||
|
||||
val firstResetKey = newIRS.calculation.floatingLegPaymentSchedule.keys.first()
|
||||
val firstResetValue = newIRS.calculation.floatingLegPaymentSchedule[firstResetKey]
|
||||
val modifiedFirstResetValue = firstResetValue!!.copy(notional = Amount(firstResetValue.notional.quantity, Currency.getInstance("JPY")))
|
||||
|
||||
output() {
|
||||
newIRS.copy(
|
||||
newIRS.fixedLeg,
|
||||
newIRS.floatingLeg,
|
||||
newIRS.calculation.copy(floatingLegPaymentSchedule = newIRS.calculation.floatingLegPaymentSchedule.plus(
|
||||
Pair(firstResetKey, modifiedFirstResetValue))),
|
||||
newIRS.common
|
||||
)
|
||||
}
|
||||
this `fails with` "There is only one change in the IRS floating leg payment schedule"
|
||||
}
|
||||
|
||||
// This tests modifies the payment currency for the fixing
|
||||
tweak {
|
||||
command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
command(ORACLE_PUBKEY) { Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd) }
|
||||
|
||||
val latestReset = newIRS.calculation.floatingLegPaymentSchedule.filter { it.value.rate is FixedRate }.maxBy { it.key }
|
||||
val modifiedLatestResetValue = latestReset!!.value.copy(notional = Amount(latestReset.value.notional.quantity, Currency.getInstance("JPY")))
|
||||
|
||||
output() {
|
||||
newIRS.copy(
|
||||
newIRS.fixedLeg,
|
||||
newIRS.floatingLeg,
|
||||
newIRS.calculation.copy(floatingLegPaymentSchedule = newIRS.calculation.floatingLegPaymentSchedule.plus(
|
||||
Pair(latestReset.key, modifiedLatestResetValue))),
|
||||
newIRS.common
|
||||
)
|
||||
}
|
||||
this `fails with` "The fix payment has the same currency as the notional"
|
||||
}
|
||||
this`fails requirement` "The fix payment has the same currency as the notional"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -652,7 +674,7 @@ class IRSTests {
|
||||
* result and the grouping won't work either.
|
||||
* In reality, the only fields that should be in common will be the next fixing date and the reference rate.
|
||||
*/
|
||||
fun tradegroups(): LedgerDsl<TestTransactionDslInterpreter, TestLedgerDslInterpreter> {
|
||||
fun tradegroups(): LedgerDsl<LastLineShouldTestForVerifiesOrFails, TestTransactionDslInterpreter, TestLedgerDslInterpreter> {
|
||||
val ld1 = LocalDate.of(2016, 3, 8)
|
||||
val bd1 = BigDecimal("0.0063518")
|
||||
|
||||
@ -670,6 +692,7 @@ class IRSTests {
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
transaction("Agreement") {
|
||||
@ -683,6 +706,7 @@ class IRSTests {
|
||||
}
|
||||
command(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
transaction("Fix") {
|
||||
@ -714,6 +738,7 @@ class IRSTests {
|
||||
Fix(FixOf("ICE LIBOR", ld1, Tenor("3M")), bd1)
|
||||
}
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,9 @@ class ObligationTests {
|
||||
)
|
||||
val outState = inState.copy(beneficiary = DUMMY_PUBKEY_2)
|
||||
|
||||
private fun obligationTestRoots(group: LedgerDsl<TestTransactionDslInterpreter, TestLedgerDslInterpreter>) = group.apply {
|
||||
private fun obligationTestRoots(
|
||||
group: LedgerDsl<LastLineShouldTestForVerifiesOrFails, TestTransactionDslInterpreter, TestLedgerDslInterpreter>
|
||||
) = group.apply {
|
||||
nonVerifiedTransaction {
|
||||
output("Alice's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION `between` Pair(ALICE, BOB_PUBKEY))
|
||||
output("Bob's $1,000,000 obligation to Alice", oneMillionDollars.OBLIGATION `between` Pair(BOB, ALICE_PUBKEY))
|
||||
@ -341,6 +343,7 @@ class ObligationTests {
|
||||
// Note we can sign with either key here
|
||||
command(ALICE_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
this.verifies()
|
||||
}
|
||||
@ -356,6 +359,7 @@ class ObligationTests {
|
||||
output("change") { oneMillionDollars.OBLIGATION `between` Pair(MEGA_CORP, BOB_PUBKEY) }
|
||||
command(BOB_PUBKEY, MEGA_CORP_PUBKEY) { Obligation.Commands.Net(NetType.CLOSE_OUT) }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
this.verifies()
|
||||
}
|
||||
@ -397,6 +401,7 @@ class ObligationTests {
|
||||
input("Bob's $1,000,000 obligation to Alice")
|
||||
command(ALICE_PUBKEY, BOB_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
this.verifies()
|
||||
}
|
||||
@ -423,6 +428,7 @@ class ObligationTests {
|
||||
output("MegaCorp's $1,000,000 obligation to Alice") { oneMillionDollars.OBLIGATION `between` Pair(MEGA_CORP, ALICE_PUBKEY) }
|
||||
command(ALICE_PUBKEY, BOB_PUBKEY, MEGA_CORP_PUBKEY) { Obligation.Commands.Net(NetType.PAYMENT) }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
this.verifies()
|
||||
}
|
||||
@ -452,6 +458,7 @@ class ObligationTests {
|
||||
output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
||||
command(ALICE_PUBKEY) { Obligation.Commands.Settle(Obligation.IssuanceDefinition(ALICE, defaultUsd.OBLIGATION_DEF), Amount(oneMillionDollars.quantity, USD)) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
||||
this.verifies()
|
||||
}
|
||||
this.verifies()
|
||||
}
|
||||
@ -496,6 +503,7 @@ class ObligationTests {
|
||||
output("Alice's defaulted $1,000,000 obligation to Bob") { (oneMillionDollars.OBLIGATION `between` Pair(ALICE, BOB_PUBKEY) `at` pastTestTime).copy(lifecycle = Lifecycle.DEFAULTED) }
|
||||
command(BOB_PUBKEY) { Obligation.Commands.SetLifecycle(Obligation.IssuanceDefinition(ALICE, defaultUsd.OBLIGATION_DEF) `at` pastTestTime, Lifecycle.DEFAULTED) }
|
||||
timestamp(TEST_TX_TIME)
|
||||
this.verifies()
|
||||
}
|
||||
this.verifies()
|
||||
}
|
||||
|
@ -10,16 +10,10 @@ import com.r3corda.core.node.services.IdentityService
|
||||
import com.r3corda.core.node.services.StorageService
|
||||
import com.r3corda.core.node.services.testing.MockIdentityService
|
||||
import com.r3corda.core.node.services.testing.MockStorageService
|
||||
import com.r3corda.core.seconds
|
||||
import com.r3corda.core.serialization.serialize
|
||||
import java.net.ServerSocket
|
||||
import java.security.KeyPair
|
||||
import java.security.PublicKey
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.fail
|
||||
|
||||
/** If an exception is thrown by the body, rethrows the root cause exception. */
|
||||
inline fun <R> rootCauseExceptions(body: () -> R): R {
|
||||
@ -132,27 +126,6 @@ val MOCK_IDENTITY_SERVICE = JavaTestHelpers.MOCK_IDENTITY_SERVICE
|
||||
|
||||
fun generateStateRef() = JavaTestHelpers.generateStateRef()
|
||||
|
||||
fun transaction(body: TransactionForTest.() -> LastLineShouldTestForAcceptOrFailure) = JavaTestHelpers.transaction(body)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Defines a simple DSL for building pseudo-transactions (not the same as the wire protocol) for testing purposes.
|
||||
//
|
||||
// Define a transaction like this:
|
||||
//
|
||||
// transaction {
|
||||
// input { someExpression }
|
||||
// output { someExpression }
|
||||
// arg { someExpression }
|
||||
//
|
||||
// tweak {
|
||||
// ... same thing but works with a copy of the parent, can add inputs/outputs/args just within this scope.
|
||||
// }
|
||||
//
|
||||
// contract.accepts() -> should pass
|
||||
// contract `fails requirement` "some substring of the error message"
|
||||
// }
|
||||
//
|
||||
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)
|
||||
@ -161,148 +134,3 @@ class LabeledOutput(val label: String?, val state: TransactionState<*>) {
|
||||
|
||||
infix fun TransactionState<*>.label(label: String) = LabeledOutput(label, this)
|
||||
|
||||
abstract class AbstractTransactionForTest {
|
||||
protected val attachments = ArrayList<SecureHash>()
|
||||
protected val outStates = ArrayList<LabeledOutput>()
|
||||
protected val commands = ArrayList<Command>()
|
||||
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) }
|
||||
}
|
||||
|
||||
fun attachment(attachmentID: SecureHash) {
|
||||
attachments.add(attachmentID)
|
||||
}
|
||||
|
||||
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)
|
||||
timestamp(data)
|
||||
}
|
||||
|
||||
fun timestamp(data: TimestampCommand) {
|
||||
addCommand(Command(data, DUMMY_NOTARY.owningKey))
|
||||
}
|
||||
|
||||
fun addCommand(cmd: Command) {
|
||||
signers.addAll(cmd.signers)
|
||||
commands.add(cmd)
|
||||
}
|
||||
|
||||
// Forbid patterns like: transaction { ... transaction { ... } }
|
||||
@Deprecated("Cannot nest transactions, use tweak", level = DeprecationLevel.ERROR)
|
||||
fun transaction(body: TransactionForTest.() -> LastLineShouldTestForAcceptOrFailure) {
|
||||
}
|
||||
}
|
||||
|
||||
/** If you jumped here from a compiler error make sure the last line of your test tests for a transaction accept or fail
|
||||
* This is a dummy type that can only be instantiated by functions in this module. This way we can ensure that all tests
|
||||
* will have as the last line either an accept or a failure test. The name is deliberately long to help make sense of
|
||||
* the triggered diagnostic
|
||||
*/
|
||||
sealed class LastLineShouldTestForAcceptOrFailure {
|
||||
internal object Token: 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() {
|
||||
val cmds = commandsToAuthenticatedObjects()
|
||||
val tx = TransactionForVerification(inStates, outStates.map { it.state }, emptyList(), cmds, SecureHash.Companion.randomSHA256(), signers.toList(), type)
|
||||
tx.verify()
|
||||
}
|
||||
|
||||
fun accepts(): LastLineShouldTestForAcceptOrFailure {
|
||||
runCommandsAndVerify()
|
||||
return LastLineShouldTestForAcceptOrFailure.Token
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun rejects(withMessage: String? = null): LastLineShouldTestForAcceptOrFailure {
|
||||
val r = try {
|
||||
runCommandsAndVerify()
|
||||
false
|
||||
} catch (e: Exception) {
|
||||
val m = e.message
|
||||
if (m == null)
|
||||
fail("Threw exception without a message")
|
||||
else
|
||||
if (withMessage != null && !m.toLowerCase().contains(withMessage.toLowerCase())) throw AssertionError("Error was actually: $m", e)
|
||||
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)
|
||||
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.
|
||||
fun chain(vararg outputLabels: String, body: TransactionForTest.() -> LastLineShouldTestForAcceptOrFailure): TransactionForTest {
|
||||
val states = outStates.mapNotNull {
|
||||
val l = it.label
|
||||
if (l != null && outputLabels.contains(l))
|
||||
it.state
|
||||
else
|
||||
null
|
||||
}
|
||||
val tx = TransactionForTest()
|
||||
tx.inStates.addAll(states)
|
||||
tx.body()
|
||||
return tx
|
||||
}
|
||||
|
||||
// Allow customisation of partial transactions.
|
||||
fun tweak(body: TransactionForTest.() -> LastLineShouldTestForAcceptOrFailure): LastLineShouldTestForAcceptOrFailure {
|
||||
val tx = TransactionForTest()
|
||||
tx.inStates.addAll(inStates)
|
||||
tx.outStates.addAll(outStates)
|
||||
tx.commands.addAll(commands)
|
||||
|
||||
tx.signers.addAll(tx.inStates.map { it.notary.owningKey })
|
||||
tx.signers.addAll(commands.flatMap { it.signers })
|
||||
return tx.body()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return """transaction {
|
||||
inputs: $inStates
|
||||
outputs: $outStates
|
||||
commands $commands
|
||||
}"""
|
||||
}
|
||||
|
||||
override fun equals(other: Any?) = this === other || (other is TransactionForTest && inStates == other.inStates && outStates == other.outStates && commands == other.commands)
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = inStates.hashCode()
|
||||
result += 31 * result + outStates.hashCode()
|
||||
result += 31 * result + commands.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
@ -56,15 +56,17 @@ class TransactionGroupTests {
|
||||
input("£1000")
|
||||
output("alice's £1000") { A_THOUSAND_POUNDS `owned by` ALICE_PUBKEY }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
transaction {
|
||||
input("alice's £1000")
|
||||
command(ALICE_PUBKEY) { TestCash.Commands.Move() }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Exit(1000.POUNDS) }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
verifies()
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,6 +76,7 @@ class TransactionGroupTests {
|
||||
val t = transaction {
|
||||
output("cash") { A_THOUSAND_POUNDS }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Issue() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
val conflict1 = transaction {
|
||||
@ -82,6 +85,7 @@ class TransactionGroupTests {
|
||||
output { HALF }
|
||||
output { HALF }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
verifies()
|
||||
@ -93,6 +97,7 @@ class TransactionGroupTests {
|
||||
output { HALF }
|
||||
output { HALF }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
assertNotEquals(conflict1, conflict2)
|
||||
@ -112,11 +117,13 @@ class TransactionGroupTests {
|
||||
transaction {
|
||||
output("cash") { A_THOUSAND_POUNDS }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Issue() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
transaction {
|
||||
input("cash")
|
||||
output { A_THOUSAND_POUNDS `owned by` BOB_PUBKEY }
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,6 +133,7 @@ class TransactionGroupTests {
|
||||
assertFailsWith(TransactionResolutionException::class) {
|
||||
input(input.ref)
|
||||
}
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,6 +151,7 @@ class TransactionGroupTests {
|
||||
input("£1000")
|
||||
output { A_THOUSAND_POUNDS.copy(amount = A_THOUSAND_POUNDS.amount * 2) }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
assertFailsWith(TransactionConflictException::class) {
|
||||
@ -157,18 +166,21 @@ class TransactionGroupTests {
|
||||
transaction {
|
||||
output("£1000") { A_THOUSAND_POUNDS }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Issue() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
transaction {
|
||||
input("£1000")
|
||||
output("alice's £1000") { A_THOUSAND_POUNDS `owned by` ALICE_PUBKEY }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
transaction {
|
||||
input("alice's £1000")
|
||||
command(ALICE_PUBKEY) { TestCash.Commands.Move() }
|
||||
command(MINI_CORP_PUBKEY) { TestCash.Commands.Exit(1000.POUNDS) }
|
||||
this.verifies()
|
||||
}
|
||||
}.interpreter.wireTransactions.let { signAll(it) }
|
||||
|
||||
|
@ -17,6 +17,7 @@ import com.r3corda.core.node.services.ServiceType
|
||||
import com.r3corda.core.node.services.TransactionStorage
|
||||
import com.r3corda.core.node.services.Wallet
|
||||
import com.r3corda.core.random63BitValue
|
||||
import com.r3corda.core.contracts.Attachment
|
||||
import com.r3corda.core.seconds
|
||||
import com.r3corda.core.testing.*
|
||||
import com.r3corda.core.utilities.BriefLogFormatter
|
||||
@ -249,10 +250,11 @@ class TwoPartyTradeProtocolTests {
|
||||
|
||||
@Test
|
||||
fun `check dependencies of sale asset are resolved`() {
|
||||
ledger {
|
||||
val notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
||||
val aliceNode = makeNodeWithTracking(notaryNode.info, ALICE.name, ALICE_KEY)
|
||||
val bobNode = makeNodeWithTracking(notaryNode.info, BOB.name, BOB_KEY)
|
||||
val notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
||||
val aliceNode = makeNodeWithTracking(notaryNode.info, ALICE.name, ALICE_KEY)
|
||||
val bobNode = makeNodeWithTracking(notaryNode.info, BOB.name, BOB_KEY)
|
||||
|
||||
ledger(storageService = aliceNode.storage) {
|
||||
|
||||
// Insert a prospectus type attachment into the commercial paper transaction.
|
||||
val stream = ByteArrayOutputStream()
|
||||
@ -261,7 +263,7 @@ class TwoPartyTradeProtocolTests {
|
||||
it.write("Our commercial paper is top notch stuff".toByteArray())
|
||||
it.closeEntry()
|
||||
}
|
||||
val attachmentID = aliceNode.storage.attachments.importAttachment(ByteArrayInputStream(stream.toByteArray()))
|
||||
val attachmentID = attachment(ByteArrayInputStream(stream.toByteArray()))
|
||||
|
||||
val issuer = MEGA_CORP.ref(1)
|
||||
val bobsFakeCash = fillUpForBuyer(false, bobNode.keyManagement.freshKey().public, issuer).second
|
||||
@ -365,8 +367,11 @@ class TwoPartyTradeProtocolTests {
|
||||
}
|
||||
}
|
||||
|
||||
private fun LedgerDsl<TransactionDslInterpreter, LedgerDslInterpreter<TransactionDslInterpreter>>.runWithError(bobError: Boolean, aliceError: Boolean,
|
||||
expectedMessageSubstring: String) {
|
||||
private fun LedgerDsl<LastLineShouldTestForVerifiesOrFails, TestTransactionDslInterpreter, TestLedgerDslInterpreter>.runWithError(
|
||||
bobError: Boolean,
|
||||
aliceError: Boolean,
|
||||
expectedMessageSubstring: String
|
||||
) {
|
||||
val notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
||||
val aliceNode = net.createPartyNode(notaryNode.info, ALICE.name, ALICE_KEY)
|
||||
val bobNode = net.createPartyNode(notaryNode.info, BOB.name, BOB_KEY)
|
||||
@ -427,7 +432,7 @@ class TwoPartyTradeProtocolTests {
|
||||
return signed.associateBy { it.id }
|
||||
}
|
||||
|
||||
private fun LedgerDsl<TransactionDslInterpreter, LedgerDslInterpreter<TransactionDslInterpreter>>.fillUpForBuyer(
|
||||
private fun LedgerDsl<LastLineShouldTestForVerifiesOrFails, TestTransactionDslInterpreter, TestLedgerDslInterpreter>.fillUpForBuyer(
|
||||
withError: Boolean,
|
||||
owner: PublicKey = BOB_PUBKEY,
|
||||
issuer: PartyAndReference = MEGA_CORP.ref(1)): Pair<Wallet, List<WireTransaction>> {
|
||||
@ -441,6 +446,11 @@ class TwoPartyTradeProtocolTests {
|
||||
if (!withError)
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Issue() }
|
||||
timestamp(TEST_TX_TIME)
|
||||
if (withError) {
|
||||
this.fails()
|
||||
} else {
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
|
||||
// Bob gets some cash onto the ledger from BoE
|
||||
@ -448,6 +458,7 @@ class TwoPartyTradeProtocolTests {
|
||||
input("elbonian money 1")
|
||||
output("bob cash 1") { 800.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
val bc2 = transaction {
|
||||
@ -455,13 +466,14 @@ class TwoPartyTradeProtocolTests {
|
||||
output("bob cash 2") { 300.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
||||
output { 700.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY } // Change output.
|
||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||
this.verifies()
|
||||
}
|
||||
|
||||
val wallet = Wallet(listOf("bob cash 1".outputStateAndRef(), "bob cash 2".outputStateAndRef()))
|
||||
return Pair(wallet, listOf(eb1, bc1, bc2))
|
||||
}
|
||||
|
||||
private fun LedgerDsl<TransactionDslInterpreter, LedgerDslInterpreter<TransactionDslInterpreter>>.fillUpForSeller(
|
||||
private fun LedgerDsl<LastLineShouldTestForVerifiesOrFails, TestTransactionDslInterpreter, TestLedgerDslInterpreter>.fillUpForSeller(
|
||||
withError: Boolean,
|
||||
owner: PublicKey,
|
||||
amount: Amount<Issued<Currency>>,
|
||||
@ -476,6 +488,11 @@ class TwoPartyTradeProtocolTests {
|
||||
command(notary.owningKey) { TimestampCommand(TEST_TX_TIME, 30.seconds) }
|
||||
if (attachmentID != null)
|
||||
attachment(attachmentID)
|
||||
if (withError) {
|
||||
this.fails()
|
||||
} else {
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
|
||||
val wallet = Wallet(listOf("alice's paper".outputStateAndRef()))
|
||||
|
@ -9,7 +9,7 @@ import org.graphstream.graph.Node
|
||||
import org.graphstream.graph.implementations.SingleGraph
|
||||
import kotlin.reflect.memberProperties
|
||||
|
||||
class GraphVisualiser(val dsl: LedgerDsl<TestTransactionDslInterpreter, TestLedgerDslInterpreter>) {
|
||||
class GraphVisualiser(val dsl: LedgerDsl<LastLineShouldTestForVerifiesOrFails, TestTransactionDslInterpreter, TestLedgerDslInterpreter>) {
|
||||
companion object {
|
||||
val css = GraphVisualiser::class.java.getResourceAsStream("graph.css").bufferedReader().readText()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user