mirror of
https://github.com/corda/corda.git
synced 2025-04-29 15:30:10 +00:00
testdsl: Add failsWith to Ledger
This commit is contained in:
parent
cd0299f650
commit
9bb8439dc3
@ -85,7 +85,7 @@ class CommercialPaperTestsGeneric {
|
|||||||
input("paper")
|
input("paper")
|
||||||
input("alice's $900")
|
input("alice's $900")
|
||||||
output("borrowed $900") { 900.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY }
|
output("borrowed $900") { 900.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY }
|
||||||
output("alice's paper") { "paper".output<ICommercialPaperState>().data `owned by` ALICE_PUBKEY }
|
output("alice's paper") { "paper".output<ICommercialPaperState>() `owned by` ALICE_PUBKEY }
|
||||||
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
command(ALICE_PUBKEY) { Cash.Commands.Move() }
|
||||||
command(MEGA_CORP_PUBKEY) { thisTest.getMoveCommand() }
|
command(MEGA_CORP_PUBKEY) { thisTest.getMoveCommand() }
|
||||||
this.verifies()
|
this.verifies()
|
||||||
@ -120,7 +120,7 @@ class CommercialPaperTestsGeneric {
|
|||||||
timestamp(TEST_TX_TIME + 8.days)
|
timestamp(TEST_TX_TIME + 8.days)
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
output { "paper".output<ICommercialPaperState>().data }
|
output { "paper".output<ICommercialPaperState>() }
|
||||||
this `fails with` "must be destroyed"
|
this `fails with` "must be destroyed"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,11 +377,11 @@ class IRSTests {
|
|||||||
input("irs post agreement")
|
input("irs post agreement")
|
||||||
val postAgreement = "irs post agreement".output<InterestRateSwap.State>()
|
val postAgreement = "irs post agreement".output<InterestRateSwap.State>()
|
||||||
output("irs post first fixing") {
|
output("irs post first fixing") {
|
||||||
postAgreement.data.copy(
|
postAgreement.copy(
|
||||||
postAgreement.data.fixedLeg,
|
postAgreement.fixedLeg,
|
||||||
postAgreement.data.floatingLeg,
|
postAgreement.floatingLeg,
|
||||||
postAgreement.data.calculation.applyFixing(ld, FixedRate(RatioUnit(bd))),
|
postAgreement.calculation.applyFixing(ld, FixedRate(RatioUnit(bd))),
|
||||||
postAgreement.data.common
|
postAgreement.common
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
command(ORACLE_PUBKEY) {
|
command(ORACLE_PUBKEY) {
|
||||||
@ -693,20 +693,20 @@ class IRSTests {
|
|||||||
input("irs post agreement2")
|
input("irs post agreement2")
|
||||||
val postAgreement1 = "irs post agreement1".output<InterestRateSwap.State>()
|
val postAgreement1 = "irs post agreement1".output<InterestRateSwap.State>()
|
||||||
output("irs post first fixing1") {
|
output("irs post first fixing1") {
|
||||||
postAgreement1.data.copy(
|
postAgreement1.copy(
|
||||||
postAgreement1.data.fixedLeg,
|
postAgreement1.fixedLeg,
|
||||||
postAgreement1.data.floatingLeg,
|
postAgreement1.floatingLeg,
|
||||||
postAgreement1.data.calculation.applyFixing(ld1, FixedRate(RatioUnit(bd1))),
|
postAgreement1.calculation.applyFixing(ld1, FixedRate(RatioUnit(bd1))),
|
||||||
postAgreement1.data.common.copy(tradeID = "t1")
|
postAgreement1.common.copy(tradeID = "t1")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val postAgreement2 = "irs post agreement2".output<InterestRateSwap.State>()
|
val postAgreement2 = "irs post agreement2".output<InterestRateSwap.State>()
|
||||||
output("irs post first fixing2") {
|
output("irs post first fixing2") {
|
||||||
postAgreement2.data.copy(
|
postAgreement2.copy(
|
||||||
postAgreement2.data.fixedLeg,
|
postAgreement2.fixedLeg,
|
||||||
postAgreement2.data.floatingLeg,
|
postAgreement2.floatingLeg,
|
||||||
postAgreement2.data.calculation.applyFixing(ld1, FixedRate(RatioUnit(bd1))),
|
postAgreement2.calculation.applyFixing(ld1, FixedRate(RatioUnit(bd1))),
|
||||||
postAgreement2.data.common.copy(tradeID = "t2")
|
postAgreement2.common.copy(tradeID = "t2")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,225 @@
|
|||||||
|
package com.r3corda.contracts.asset;
|
||||||
|
|
||||||
|
import kotlin.Unit;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static com.r3corda.core.testing.JavaTestHelpers.*;
|
||||||
|
import static com.r3corda.core.contracts.JavaTestHelpers.*;
|
||||||
|
|
||||||
|
public class TmpTest {
|
||||||
|
|
||||||
|
public static class Asd {
|
||||||
|
@Test
|
||||||
|
public void emptyLedger() {
|
||||||
|
ledger(l -> {
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void simpleCashDoesntCompile() {
|
||||||
|
// Cash.State inState = new Cash.State(
|
||||||
|
// issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
|
||||||
|
// getDUMMY_PUBKEY_1()
|
||||||
|
// );
|
||||||
|
// ledger(l -> {
|
||||||
|
// l.transaction(tx -> {
|
||||||
|
// tx.input(inState);
|
||||||
|
// });
|
||||||
|
// return Unit.INSTANCE;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleCash() {
|
||||||
|
Cash.State inState = new Cash.State(
|
||||||
|
issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
|
||||||
|
getDUMMY_PUBKEY_1()
|
||||||
|
);
|
||||||
|
ledger(l -> {
|
||||||
|
l.transaction(tx -> {
|
||||||
|
tx.input(inState);
|
||||||
|
return tx.verifies();
|
||||||
|
});
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleCashFailsWith() {
|
||||||
|
Cash.State inState = new Cash.State(
|
||||||
|
issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
|
||||||
|
getDUMMY_PUBKEY_1()
|
||||||
|
);
|
||||||
|
ledger(l -> {
|
||||||
|
l.transaction(tx -> {
|
||||||
|
tx.input(inState);
|
||||||
|
return tx.failsWith("the amounts balance");
|
||||||
|
});
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleCashSuccess() {
|
||||||
|
Cash.State inState = new Cash.State(
|
||||||
|
issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
|
||||||
|
getDUMMY_PUBKEY_1()
|
||||||
|
);
|
||||||
|
ledger(l -> {
|
||||||
|
l.transaction(tx -> {
|
||||||
|
tx.input(inState);
|
||||||
|
tx.failsWith("the amounts balance");
|
||||||
|
tx.output(inState.copy(inState.getAmount(), getDUMMY_PUBKEY_2()));
|
||||||
|
tx.command(getDUMMY_PUBKEY_1(), new Cash.Commands.Move());
|
||||||
|
return tx.verifies();
|
||||||
|
});
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleCashTweakSuccess() {
|
||||||
|
Cash.State inState = new Cash.State(
|
||||||
|
issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
|
||||||
|
getDUMMY_PUBKEY_1()
|
||||||
|
);
|
||||||
|
ledger(l -> {
|
||||||
|
l.transaction(tx -> {
|
||||||
|
tx.input(inState);
|
||||||
|
tx.failsWith("the amounts balance");
|
||||||
|
tx.output(inState.copy(inState.getAmount(), getDUMMY_PUBKEY_2()));
|
||||||
|
|
||||||
|
tx.tweak(tw -> {
|
||||||
|
tw.command(getDUMMY_PUBKEY_2(), new Cash.Commands.Move());
|
||||||
|
return tw.failsWith("the owning keys are the same as the signing keys");
|
||||||
|
});
|
||||||
|
tx.command(getDUMMY_PUBKEY_1(), new Cash.Commands.Move());
|
||||||
|
return tx.verifies();
|
||||||
|
});
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleCashTweakSuccessTopLevelTransaction() {
|
||||||
|
Cash.State inState = new Cash.State(
|
||||||
|
issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
|
||||||
|
getDUMMY_PUBKEY_1()
|
||||||
|
);
|
||||||
|
transaction(tx -> {
|
||||||
|
tx.input(inState);
|
||||||
|
tx.failsWith("the amounts balance");
|
||||||
|
tx.output(inState.copy(inState.getAmount(), getDUMMY_PUBKEY_2()));
|
||||||
|
|
||||||
|
tx.tweak(tw -> {
|
||||||
|
tw.command(getDUMMY_PUBKEY_2(), new Cash.Commands.Move());
|
||||||
|
return tw.failsWith("the owning keys are the same as the signing keys");
|
||||||
|
});
|
||||||
|
tx.command(getDUMMY_PUBKEY_1(), new Cash.Commands.Move());
|
||||||
|
return tx.verifies();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void chainCash() {
|
||||||
|
ledger(l -> {
|
||||||
|
l.unverifiedTransaction(tx -> {
|
||||||
|
tx.output("MEGA_CORP cash",
|
||||||
|
new Cash.State(
|
||||||
|
issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
|
||||||
|
getMEGA_CORP_PUBKEY()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
l.transaction(tx -> {
|
||||||
|
tx.input("MEGA_CORP cash");
|
||||||
|
Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
|
||||||
|
tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_1()));
|
||||||
|
tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
|
||||||
|
return tx.verifies();
|
||||||
|
});
|
||||||
|
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void chainCashDoubleSpend() {
|
||||||
|
ledger(l -> {
|
||||||
|
l.unverifiedTransaction(tx -> {
|
||||||
|
tx.output("MEGA_CORP cash",
|
||||||
|
new Cash.State(
|
||||||
|
issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
|
||||||
|
getMEGA_CORP_PUBKEY()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
l.transaction(tx -> {
|
||||||
|
tx.input("MEGA_CORP cash");
|
||||||
|
Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
|
||||||
|
tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_1()));
|
||||||
|
tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
|
||||||
|
return tx.verifies();
|
||||||
|
});
|
||||||
|
|
||||||
|
l.transaction(tx -> {
|
||||||
|
tx.input("MEGA_CORP cash");
|
||||||
|
Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
|
||||||
|
// We send it to another pubkey so that the transaction is not identical to the previous one
|
||||||
|
tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_2()));
|
||||||
|
tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
|
||||||
|
return tx.verifies();
|
||||||
|
});
|
||||||
|
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void chainCashDoubleSpendFailsWith() {
|
||||||
|
ledger(l -> {
|
||||||
|
l.unverifiedTransaction(tx -> {
|
||||||
|
tx.output("MEGA_CORP cash",
|
||||||
|
new Cash.State(
|
||||||
|
issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
|
||||||
|
getMEGA_CORP_PUBKEY()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
l.transaction(tx -> {
|
||||||
|
tx.input("MEGA_CORP cash");
|
||||||
|
Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
|
||||||
|
tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_1()));
|
||||||
|
tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
|
||||||
|
return tx.verifies();
|
||||||
|
});
|
||||||
|
|
||||||
|
l.tweak(lw -> {
|
||||||
|
lw.transaction(tx -> {
|
||||||
|
tx.input("MEGA_CORP cash");
|
||||||
|
Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
|
||||||
|
// We send it to another pubkey so that the transaction is not identical to the previous one
|
||||||
|
tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_2()));
|
||||||
|
tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
|
||||||
|
return tx.verifies();
|
||||||
|
});
|
||||||
|
lw.fails();
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
l.verifies();
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
209
contracts/src/test/kotlin/com/r3corda/contracts/asset/TmpTest.kt
Normal file
209
contracts/src/test/kotlin/com/r3corda/contracts/asset/TmpTest.kt
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
package com.r3corda.contracts.asset
|
||||||
|
|
||||||
|
import com.r3corda.core.contracts.DOLLARS
|
||||||
|
import com.r3corda.core.contracts.`issued by`
|
||||||
|
import com.r3corda.core.testing.*
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
||||||
|
class Asd {
|
||||||
|
|
||||||
|
class Asd {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun emptyLedger() {
|
||||||
|
ledger {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// fun simpleCashFails() {
|
||||||
|
// ledger {
|
||||||
|
// transaction {
|
||||||
|
// input(Cash.State(
|
||||||
|
// amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||||
|
// owner = DUMMY_PUBKEY_1
|
||||||
|
// ))
|
||||||
|
// this.verifies()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simpleCash() {
|
||||||
|
val inState = Cash.State(
|
||||||
|
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||||
|
owner = DUMMY_PUBKEY_1
|
||||||
|
)
|
||||||
|
ledger {
|
||||||
|
transaction {
|
||||||
|
input(inState)
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simpleCashFailsWith() {
|
||||||
|
val inState = Cash.State(
|
||||||
|
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||||
|
owner = DUMMY_PUBKEY_1
|
||||||
|
)
|
||||||
|
ledger {
|
||||||
|
transaction {
|
||||||
|
input(inState)
|
||||||
|
this `fails with` "the amounts balance"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simpleCashSuccess() {
|
||||||
|
val inState = Cash.State(
|
||||||
|
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||||
|
owner = DUMMY_PUBKEY_1
|
||||||
|
)
|
||||||
|
ledger {
|
||||||
|
transaction {
|
||||||
|
input(inState)
|
||||||
|
this `fails with` "the amounts balance"
|
||||||
|
output(inState.copy(owner = DUMMY_PUBKEY_2))
|
||||||
|
command(DUMMY_PUBKEY_1) { Cash.Commands.Move() }
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simpleCashTweakSuccess() {
|
||||||
|
val inState = Cash.State(
|
||||||
|
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||||
|
owner = DUMMY_PUBKEY_1
|
||||||
|
)
|
||||||
|
ledger {
|
||||||
|
transaction {
|
||||||
|
input(inState)
|
||||||
|
this `fails with` "the amounts balance"
|
||||||
|
output(inState.copy(owner = DUMMY_PUBKEY_2))
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
command(DUMMY_PUBKEY_2) { Cash.Commands.Move() }
|
||||||
|
this `fails with` "the owning keys are the same as the signing keys"
|
||||||
|
}
|
||||||
|
|
||||||
|
command(DUMMY_PUBKEY_1) { Cash.Commands.Move() }
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simpleCashTweakSuccessTopLevelTransaction() {
|
||||||
|
val inState = Cash.State(
|
||||||
|
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||||
|
owner = DUMMY_PUBKEY_1
|
||||||
|
)
|
||||||
|
transaction {
|
||||||
|
input(inState)
|
||||||
|
this `fails with` "the amounts balance"
|
||||||
|
output(inState.copy(owner = DUMMY_PUBKEY_2))
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
command(DUMMY_PUBKEY_2) { Cash.Commands.Move() }
|
||||||
|
this `fails with` "the owning keys are the same as the signing keys"
|
||||||
|
}
|
||||||
|
|
||||||
|
command(DUMMY_PUBKEY_1) { Cash.Commands.Move() }
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun chainCash() {
|
||||||
|
ledger {
|
||||||
|
unverifiedTransaction {
|
||||||
|
output("MEGA_CORP cash") {
|
||||||
|
Cash.State(
|
||||||
|
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||||
|
owner = MEGA_CORP_PUBKEY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction {
|
||||||
|
input("MEGA_CORP cash")
|
||||||
|
output("MEGA_CORP cash".output<Cash.State>().copy(owner = DUMMY_PUBKEY_1))
|
||||||
|
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun chainCashDoubleSpend() {
|
||||||
|
ledger {
|
||||||
|
unverifiedTransaction {
|
||||||
|
output("MEGA_CORP cash") {
|
||||||
|
Cash.State(
|
||||||
|
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||||
|
owner = MEGA_CORP_PUBKEY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction {
|
||||||
|
input("MEGA_CORP cash")
|
||||||
|
output("MEGA_CORP cash".output<Cash.State>().copy(owner = DUMMY_PUBKEY_1))
|
||||||
|
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction {
|
||||||
|
input("MEGA_CORP cash")
|
||||||
|
// We send it to another pubkey so that the transaction is not identical to the previous one
|
||||||
|
output("MEGA_CORP cash".output<Cash.State>().copy(owner = DUMMY_PUBKEY_1))
|
||||||
|
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun chainCashDoubleSpendFailsWith() {
|
||||||
|
ledger {
|
||||||
|
unverifiedTransaction {
|
||||||
|
output("MEGA_CORP cash") {
|
||||||
|
Cash.State(
|
||||||
|
amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
|
||||||
|
owner = MEGA_CORP_PUBKEY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction {
|
||||||
|
input("MEGA_CORP cash")
|
||||||
|
output("MEGA_CORP cash".output<Cash.State>().copy(owner = DUMMY_PUBKEY_1))
|
||||||
|
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
transaction {
|
||||||
|
input("MEGA_CORP cash")
|
||||||
|
// We send it to another pubkey so that the transaction is not identical to the previous one
|
||||||
|
output("MEGA_CORP cash".output<Cash.State>().copy(owner = DUMMY_PUBKEY_2))
|
||||||
|
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
this.fails()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -169,4 +169,4 @@ operator fun KeyPair.component1() = this.private
|
|||||||
operator fun KeyPair.component2() = this.public
|
operator fun KeyPair.component2() = this.public
|
||||||
|
|
||||||
/** A simple wrapper that will make it easier to swap out the EC algorithm we use in future */
|
/** A simple wrapper that will make it easier to swap out the EC algorithm we use in future */
|
||||||
fun generateKeyPair() = EddsaKeyPairGenerator().generateKeyPair()!!
|
fun generateKeyPair(): KeyPair = EddsaKeyPairGenerator().generateKeyPair()
|
||||||
|
@ -61,6 +61,12 @@ interface LedgerDSLInterpreter<R, out T : TransactionDSLInterpreter<R>> : Output
|
|||||||
* Verifies the ledger using [TransactionGroup.verify], throws if the verification fails.
|
* Verifies the ledger using [TransactionGroup.verify], throws if the verification fails.
|
||||||
*/
|
*/
|
||||||
fun verifies()
|
fun verifies()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the ledger, expecting an exception to be thrown.
|
||||||
|
* @param expectedMessage: An optional string to be searched for in the raised exception.
|
||||||
|
*/
|
||||||
|
fun failsWith(expectedMessage: String?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,12 +103,28 @@ class LedgerDSL<R, out T : TransactionDSLInterpreter<R>, out L : LedgerDSLInterp
|
|||||||
* Retrieves the output [TransactionState] based on the label.
|
* Retrieves the output [TransactionState] based on the label.
|
||||||
* @see OutputStateLookup.retrieveOutputStateAndRef
|
* @see OutputStateLookup.retrieveOutputStateAndRef
|
||||||
*/
|
*/
|
||||||
inline fun <reified S : ContractState> String.output(): TransactionState<S> =
|
inline fun <reified S : ContractState> String.output(): S =
|
||||||
outputStateAndRef<S>().state
|
outputStateAndRef<S>().state.data
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the output [StateRef] based on the label.
|
* Retrieves the output [StateRef] based on the label.
|
||||||
* @see OutputStateLookup.retrieveOutputStateAndRef
|
* @see OutputStateLookup.retrieveOutputStateAndRef
|
||||||
*/
|
*/
|
||||||
fun String.outputRef(): StateRef = outputStateAndRef<ContractState>().ref
|
fun String.outputRef(): StateRef = outputStateAndRef<ContractState>().ref
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OutputStateLookup.retrieveOutputStateAndRef
|
||||||
|
*/
|
||||||
|
fun <S : ContractState> retrieveOutput(clazz: Class<S>, label: String) =
|
||||||
|
retrieveOutputStateAndRef(clazz, label).state.data
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the transaction will fail verification
|
||||||
|
*/
|
||||||
|
fun fails() = failsWith(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TransactionDSLInterpreter.failsWith
|
||||||
|
*/
|
||||||
|
infix fun `fails with`(msg: String) = failsWith(msg)
|
||||||
}
|
}
|
||||||
|
@ -161,27 +161,8 @@ data class TestTransactionDSLInterpreter private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun failsWith(expectedMessage: String?): EnforceVerifyOrFail {
|
override fun failsWith(expectedMessage: String?): EnforceVerifyOrFail {
|
||||||
val exceptionThrown = try {
|
expectExceptionContainingString(expectedMessage) {
|
||||||
this.verifies()
|
this.verifies()
|
||||||
false
|
|
||||||
} catch (exception: Exception) {
|
|
||||||
if (expectedMessage != null) {
|
|
||||||
val exceptionMessage = exception.message
|
|
||||||
if (exceptionMessage == null) {
|
|
||||||
throw AssertionError(
|
|
||||||
"Expected exception containing '$expectedMessage' but raised exception had no message"
|
|
||||||
)
|
|
||||||
} else if (!exceptionMessage.toLowerCase().contains(expectedMessage.toLowerCase())) {
|
|
||||||
throw AssertionError(
|
|
||||||
"Expected exception containing '$expectedMessage' but raised exception was '$exception'"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!exceptionThrown) {
|
|
||||||
throw AssertionError("Expected exception but didn't get one")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EnforceVerifyOrFail.Token
|
return EnforceVerifyOrFail.Token
|
||||||
@ -202,7 +183,6 @@ data class TestLedgerDSLInterpreter private constructor (
|
|||||||
private val transactionWithLocations: HashMap<SecureHash, WireTransactionWithLocation> = HashMap(),
|
private val transactionWithLocations: HashMap<SecureHash, WireTransactionWithLocation> = HashMap(),
|
||||||
private val nonVerifiedTransactionWithLocations: HashMap<SecureHash, WireTransactionWithLocation> = HashMap()
|
private val nonVerifiedTransactionWithLocations: HashMap<SecureHash, WireTransactionWithLocation> = HashMap()
|
||||||
) : LedgerDSLInterpreter<EnforceVerifyOrFail, TestTransactionDSLInterpreter> {
|
) : LedgerDSLInterpreter<EnforceVerifyOrFail, TestTransactionDSLInterpreter> {
|
||||||
|
|
||||||
val wireTransactions: List<WireTransaction> get() = transactionWithLocations.values.map { it.transaction }
|
val wireTransactions: List<WireTransaction> get() = transactionWithLocations.values.map { it.transaction }
|
||||||
|
|
||||||
// We specify [labelToOutputStateAndRefs] just so that Kotlin picks the primary constructor instead of cycling
|
// We specify [labelToOutputStateAndRefs] just so that Kotlin picks the primary constructor instead of cycling
|
||||||
@ -211,19 +191,25 @@ data class TestLedgerDSLInterpreter private constructor (
|
|||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun getCallerLocation(offset: Int): String {
|
private fun getCallerLocation(): String? {
|
||||||
val stackTraceElement = Thread.currentThread().stackTrace[3 + offset]
|
val stackTrace = Thread.currentThread().stackTrace
|
||||||
|
for (i in 1 .. stackTrace.size) {
|
||||||
|
val stackTraceElement = stackTrace[i]
|
||||||
|
if (!stackTraceElement.fileName.contains("DSL")) {
|
||||||
return stackTraceElement.toString()
|
return stackTraceElement.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal data class WireTransactionWithLocation(
|
internal data class WireTransactionWithLocation(
|
||||||
val label: String?,
|
val label: String?,
|
||||||
val transaction: WireTransaction,
|
val transaction: WireTransaction,
|
||||||
val location: String
|
val location: String?
|
||||||
)
|
)
|
||||||
class VerifiesFailed(transactionLocation: String, cause: Throwable) :
|
class VerifiesFailed(transactionName: String, cause: Throwable) :
|
||||||
Exception("Transaction defined at ($transactionLocation) didn't verify: $cause", cause)
|
Exception("Transaction ($transactionName) didn't verify: $cause", cause)
|
||||||
class TypeMismatch(requested: Class<*>, actual: Class<*>) :
|
class TypeMismatch(requested: Class<*>, actual: Class<*>) :
|
||||||
Exception("Actual type $actual is not a subtype of requested type $requested")
|
Exception("Actual type $actual is not a subtype of requested type $requested")
|
||||||
|
|
||||||
@ -309,7 +295,7 @@ data class TestLedgerDSLInterpreter private constructor (
|
|||||||
dsl: TransactionDSL<EnforceVerifyOrFail, TestTransactionDSLInterpreter>.() -> R,
|
dsl: TransactionDSL<EnforceVerifyOrFail, TestTransactionDSLInterpreter>.() -> R,
|
||||||
transactionMap: HashMap<SecureHash, WireTransactionWithLocation> = HashMap()
|
transactionMap: HashMap<SecureHash, WireTransactionWithLocation> = HashMap()
|
||||||
): WireTransaction {
|
): WireTransaction {
|
||||||
val transactionLocation = getCallerLocation(3)
|
val transactionLocation = getCallerLocation()
|
||||||
val transactionInterpreter = interpretTransactionDsl(transactionBuilder, dsl)
|
val transactionInterpreter = interpretTransactionDsl(transactionBuilder, dsl)
|
||||||
// Create the WireTransaction
|
// Create the WireTransaction
|
||||||
val wireTransaction = transactionInterpreter.toWireTransaction()
|
val wireTransaction = transactionInterpreter.toWireTransaction()
|
||||||
@ -353,7 +339,15 @@ data class TestLedgerDSLInterpreter private constructor (
|
|||||||
try {
|
try {
|
||||||
transactionGroup.verify()
|
transactionGroup.verify()
|
||||||
} catch (exception: TransactionVerificationException) {
|
} catch (exception: TransactionVerificationException) {
|
||||||
throw VerifiesFailed(transactionWithLocations[exception.tx.origHash]?.location ?: "<unknown>", exception)
|
val transactionWithLocation = transactionWithLocations[exception.tx.origHash]
|
||||||
|
val transactionName = transactionWithLocation?.label ?: transactionWithLocation?.location ?: "<unknown>"
|
||||||
|
throw VerifiesFailed(transactionName, exception)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun failsWith(expectedMessage: String?) {
|
||||||
|
expectExceptionContainingString(expectedMessage) {
|
||||||
|
this.verifies()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,3 +391,28 @@ fun signAll(transactionsToSign: List<WireTransaction>, extraKeys: Array<out KeyP
|
|||||||
*/
|
*/
|
||||||
fun LedgerDSL<EnforceVerifyOrFail, TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.signAll(
|
fun LedgerDSL<EnforceVerifyOrFail, TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.signAll(
|
||||||
vararg extraKeys: KeyPair) = signAll(this.interpreter.wireTransactions, extraKeys)
|
vararg extraKeys: KeyPair) = signAll(this.interpreter.wireTransactions, extraKeys)
|
||||||
|
|
||||||
|
internal inline fun expectExceptionContainingString(string: String?, body:() -> Unit) {
|
||||||
|
val exceptionThrown = try {
|
||||||
|
body()
|
||||||
|
false
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
if (string != null) {
|
||||||
|
val exceptionMessage = exception.message
|
||||||
|
if (exceptionMessage == null) {
|
||||||
|
throw AssertionError(
|
||||||
|
"Expected exception containing '$string' but raised exception had no message"
|
||||||
|
)
|
||||||
|
} else if (!exceptionMessage.toLowerCase().contains(string.toLowerCase())) {
|
||||||
|
throw AssertionError(
|
||||||
|
"Expected exception containing '$string' but raised exception was '$exception'"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exceptionThrown) {
|
||||||
|
throw AssertionError("Expected exception but didn't get one")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -96,10 +96,12 @@ class TransactionDSL<R, out T : TransactionDSLInterpreter<R>> (val interpreter:
|
|||||||
/**
|
/**
|
||||||
* @see TransactionDSLInterpreter._output
|
* @see TransactionDSLInterpreter._output
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
fun output(label: String, contractState: ContractState) =
|
||||||
fun output(label: String? = null, contractState: ContractState) =
|
|
||||||
_output(label, DUMMY_NOTARY, contractState)
|
_output(label, DUMMY_NOTARY, contractState)
|
||||||
|
|
||||||
|
fun output(contractState: ContractState) =
|
||||||
|
_output(null, DUMMY_NOTARY, contractState)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TransactionDSLInterpreter._command
|
* @see TransactionDSLInterpreter._command
|
||||||
*/
|
*/
|
||||||
|
@ -88,7 +88,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateKeyPair(): KeyPair? = keyPair ?: super.generateKeyPair()
|
override fun generateKeyPair(): KeyPair = keyPair ?: super.generateKeyPair()
|
||||||
|
|
||||||
// It's OK to not have a network map service in the mock network.
|
// It's OK to not have a network map service in the mock network.
|
||||||
override fun noNetworkMapConfigured() = Futures.immediateFuture(Unit)
|
override fun noNetworkMapConfigured() = Futures.immediateFuture(Unit)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user