diff --git a/contracts/src/test/java/com/r3corda/contracts/asset/CashTestsJava.java b/contracts/src/test/java/com/r3corda/contracts/asset/CashTestsJava.java index 36fced1951..e3fdbd9acf 100644 --- a/contracts/src/test/java/com/r3corda/contracts/asset/CashTestsJava.java +++ b/contracts/src/test/java/com/r3corda/contracts/asset/CashTestsJava.java @@ -14,7 +14,7 @@ import static com.r3corda.contracts.testing.JavaTestHelpers.*; */ public class CashTestsJava { - private OpaqueBytes defaultRef = new OpaqueBytes(new byte[]{1});; + 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()); diff --git a/contracts/src/test/kotlin/com/r3corda/contracts/CommercialPaperTests.kt b/contracts/src/test/kotlin/com/r3corda/contracts/CommercialPaperTests.kt index 992b76d1a6..7c436e6db2 100644 --- a/contracts/src/test/kotlin/com/r3corda/contracts/CommercialPaperTests.kt +++ b/contracts/src/test/kotlin/com/r3corda/contracts/CommercialPaperTests.kt @@ -97,7 +97,7 @@ class CommercialPaperTestsGeneric { input("alice's paper") input("some profits") - fun TransactionDSL>.outputs(aliceGetsBack: Amount>) { + fun TransactionDSL.outputs(aliceGetsBack: Amount>) { output("Alice's profit") { aliceGetsBack.STATE `owned by` ALICE_PUBKEY } output("Change") { (someProfits - aliceGetsBack).STATE `owned by` MEGA_CORP_PUBKEY } } diff --git a/contracts/src/test/kotlin/com/r3corda/contracts/IRSTests.kt b/contracts/src/test/kotlin/com/r3corda/contracts/IRSTests.kt index ad5e16482f..643d4f7581 100644 --- a/contracts/src/test/kotlin/com/r3corda/contracts/IRSTests.kt +++ b/contracts/src/test/kotlin/com/r3corda/contracts/IRSTests.kt @@ -360,7 +360,7 @@ class IRSTests { /** * Generates a typical transactional history for an IRS. */ - fun trade(): LedgerDSL { + fun trade(): LedgerDSL { val ld = LocalDate.of(2016, 3, 8) val bd = BigDecimal("0.0063518") @@ -653,7 +653,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 { + fun tradegroups(): LedgerDSL { val ld1 = LocalDate.of(2016, 3, 8) val bd1 = BigDecimal("0.0063518") diff --git a/contracts/src/test/kotlin/com/r3corda/contracts/asset/ObligationTests.kt b/contracts/src/test/kotlin/com/r3corda/contracts/asset/ObligationTests.kt index 023f28c34b..a37c250c6d 100644 --- a/contracts/src/test/kotlin/com/r3corda/contracts/asset/ObligationTests.kt +++ b/contracts/src/test/kotlin/com/r3corda/contracts/asset/ObligationTests.kt @@ -5,7 +5,6 @@ import com.r3corda.contracts.testing.* import com.r3corda.core.contracts.* import com.r3corda.core.crypto.SecureHash import com.r3corda.core.testing.* -import com.r3corda.core.testing.JavaTestHelpers import com.r3corda.core.utilities.nonEmptySetOf import org.junit.Test import java.security.PublicKey @@ -35,7 +34,7 @@ class ObligationTests { val outState = inState.copy(beneficiary = DUMMY_PUBKEY_2) private fun obligationTestRoots( - group: LedgerDSL + group: LedgerDSL ) = group.apply { unverifiedTransaction { output("Alice's $1,000,000 obligation to Bob", oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY)) diff --git a/core/src/main/kotlin/com/r3corda/core/testing/LedgerDSLInterpreter.kt b/core/src/main/kotlin/com/r3corda/core/testing/LedgerDSLInterpreter.kt index c80aa84a9d..8b6329956e 100644 --- a/core/src/main/kotlin/com/r3corda/core/testing/LedgerDSLInterpreter.kt +++ b/core/src/main/kotlin/com/r3corda/core/testing/LedgerDSLInterpreter.kt @@ -18,12 +18,64 @@ interface OutputStateLookup { fun retrieveOutputStateAndRef(clazz: Class, label: String): StateAndRef } +/** + * This interface asserts that the DSL at hand is capable of verifying it's underlying construct(ledger/transaction) + */ +interface Verifies { + /** + * Verifies the ledger/transaction, throws if the verification fails. + */ + fun verifies(): EnforceVerifyOrFail + + /** + * Asserts that verifies() throws + * @param expectedMessage: An optional string to be searched for in the raised exception. + */ + fun failsWith(expectedMessage: String?): EnforceVerifyOrFail { + val exceptionThrown = try { + 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 + } + + /** + * Asserts that [verifies] throws, with no condition on the exception message + */ + fun fails() = failsWith(null) + + /** + * @see failsWith + */ + infix fun `fails with`(msg: String) = failsWith(msg) +} + + /** * This interface defines the bare bone functionality that a Ledger DSL interpreter should implement. * * TODO (Kotlin 1.1): Use type synonyms to make the type params less unwieldy */ -interface LedgerDSLInterpreter> : OutputStateLookup { +interface LedgerDSLInterpreter : Verifies, OutputStateLookup { /** * Creates and adds a transaction to the ledger. * @param transactionLabel: Optional label of the transaction, to be used in diagnostic messages. @@ -32,7 +84,7 @@ interface LedgerDSLInterpreter> : Output * @return: The final [WireTransaction] of the built transaction. */ fun _transaction(transactionLabel: String?, transactionBuilder: TransactionBuilder, - dsl: TransactionDSL.() -> R): WireTransaction + dsl: TransactionDSL.() -> EnforceVerifyOrFail): WireTransaction /** * Creates and adds a transaction to the ledger that will not be verified by [verifies]. @@ -42,13 +94,13 @@ interface LedgerDSLInterpreter> : Output * @return: The final [WireTransaction] of the built transaction. */ fun _unverifiedTransaction(transactionLabel: String?, transactionBuilder: TransactionBuilder, - dsl: TransactionDSL.() -> Unit): WireTransaction + dsl: TransactionDSL.() -> Unit): WireTransaction /** * Creates a local scoped copy of the ledger. * @param dsl: The ledger DSL to be interpreted using the copy. */ - fun tweak(dsl: LedgerDSL>.() -> Unit) + fun tweak(dsl: LedgerDSL>.() -> Unit) /** * Adds an attachment to the ledger. @@ -57,16 +109,6 @@ interface LedgerDSLInterpreter> : Output */ fun attachment(attachment: InputStream): SecureHash - /** - * Verifies the ledger using [TransactionGroup.verify], throws if the verification fails. - */ - 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?) } /** @@ -75,22 +117,22 @@ interface LedgerDSLInterpreter> : Output * functionality then first add your primitive to [LedgerDSLInterpreter] and then add the convenience defaults/extension * methods here. */ -class LedgerDSL, out L : LedgerDSLInterpreter> (val interpreter: L) : - LedgerDSLInterpreter> by interpreter { +class LedgerDSL> (val interpreter: L) : + LedgerDSLInterpreter by interpreter { /** * @see LedgerDSLInterpreter._transaction */ @JvmOverloads fun transaction(label: String? = null, transactionBuilder: TransactionBuilder = TransactionBuilder(), - dsl: TransactionDSL>.() -> R) = + dsl: TransactionDSL.() -> EnforceVerifyOrFail) = _transaction(label, transactionBuilder, dsl) /** * @see LedgerDSLInterpreter._unverifiedTransaction */ @JvmOverloads fun unverifiedTransaction(label: String? = null, transactionBuilder: TransactionBuilder = TransactionBuilder(), - dsl: TransactionDSL>.() -> Unit) = + dsl: TransactionDSL.() -> Unit) = _unverifiedTransaction(label, transactionBuilder, dsl) /** @@ -117,14 +159,4 @@ class LedgerDSL, out L : LedgerDSLInterp */ fun retrieveOutput(clazz: Class, 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) } diff --git a/core/src/main/kotlin/com/r3corda/core/testing/TestDSL.kt b/core/src/main/kotlin/com/r3corda/core/testing/TestDSL.kt index 8a820c18a0..d950506da2 100644 --- a/core/src/main/kotlin/com/r3corda/core/testing/TestDSL.kt +++ b/core/src/main/kotlin/com/r3corda/core/testing/TestDSL.kt @@ -47,10 +47,7 @@ import java.util.* fun transaction( transactionLabel: String? = null, transactionBuilder: TransactionBuilder = TransactionBuilder(), - dsl: TransactionDSL< - EnforceVerifyOrFail, - TransactionDSLInterpreter - >.() -> EnforceVerifyOrFail + dsl: TransactionDSL.() -> EnforceVerifyOrFail ) = JavaTestHelpers.transaction(transactionLabel, transactionBuilder, dsl) /** @@ -59,7 +56,7 @@ fun transaction( fun ledger( identityService: IdentityService = MOCK_IDENTITY_SERVICE, storageService: StorageService = MockStorageService(), - dsl: LedgerDSL.() -> Unit + dsl: LedgerDSL.() -> Unit ) = JavaTestHelpers.ledger(identityService, storageService, dsl) @Deprecated( @@ -67,8 +64,8 @@ fun ledger( replaceWith = ReplaceWith("tweak"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") -fun TransactionDSLInterpreter.ledger( - dsl: LedgerDSL.() -> Unit) { +fun TransactionDSLInterpreter.ledger( + dsl: LedgerDSL.() -> Unit) { } @Deprecated( @@ -76,11 +73,8 @@ fun TransactionDSLInterpreter.ledger( replaceWith = ReplaceWith("tweak"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") -fun TransactionDSLInterpreter.transaction( - dsl: TransactionDSL< - EnforceVerifyOrFail, - TransactionDSLInterpreter - >.() -> EnforceVerifyOrFail) { +fun TransactionDSLInterpreter.transaction( + dsl: TransactionDSL.() -> EnforceVerifyOrFail) { } @Deprecated( @@ -88,8 +82,8 @@ fun TransactionDSLInterpreter.transaction( replaceWith = ReplaceWith("tweak"), level = DeprecationLevel.ERROR) @Suppress("UNUSED_PARAMETER") -fun LedgerDSLInterpreter>.ledger( - dsl: LedgerDSL.() -> Unit) { +fun LedgerDSLInterpreter.ledger( + dsl: LedgerDSL.() -> Unit) { } /** @@ -113,7 +107,7 @@ data class TestTransactionDSLInterpreter private constructor( override val ledgerInterpreter: TestLedgerDSLInterpreter, val transactionBuilder: TransactionBuilder, internal val labelToIndexMap: HashMap -) : TransactionDSLInterpreter, OutputStateLookup by ledgerInterpreter { +) : TransactionDSLInterpreter, OutputStateLookup by ledgerInterpreter { constructor( ledgerInterpreter: TestLedgerDSLInterpreter, @@ -160,19 +154,8 @@ data class TestTransactionDSLInterpreter private constructor( return EnforceVerifyOrFail.Token } - override fun failsWith(expectedMessage: String?): EnforceVerifyOrFail { - expectExceptionContainingString(expectedMessage) { - this.verifies() - } - - return EnforceVerifyOrFail.Token - } - override fun tweak( - dsl: TransactionDSL< - EnforceVerifyOrFail, - TransactionDSLInterpreter - >.() -> EnforceVerifyOrFail + dsl: TransactionDSL.() -> EnforceVerifyOrFail ) = dsl(TransactionDSL(copy())) } @@ -182,7 +165,7 @@ data class TestLedgerDSLInterpreter private constructor ( internal val labelToOutputStateAndRefs: HashMap> = HashMap(), private val transactionWithLocations: HashMap = HashMap(), private val nonVerifiedTransactionWithLocations: HashMap = HashMap() -) : LedgerDSLInterpreter { +) : LedgerDSLInterpreter { val wireTransactions: List get() = transactionWithLocations.values.map { it.transaction } // We specify [labelToOutputStateAndRefs] just so that Kotlin picks the primary constructor instead of cycling @@ -260,7 +243,7 @@ data class TestLedgerDSLInterpreter private constructor ( private fun interpretTransactionDsl( transactionBuilder: TransactionBuilder, - dsl: TransactionDSL.() -> R + dsl: TransactionDSL.() -> R ): TestTransactionDSLInterpreter { val transactionInterpreter = TestTransactionDSLInterpreter(this, transactionBuilder) dsl(TransactionDSL(transactionInterpreter)) @@ -292,7 +275,7 @@ data class TestLedgerDSLInterpreter private constructor ( private fun recordTransactionWithTransactionMap( transactionLabel: String?, transactionBuilder: TransactionBuilder, - dsl: TransactionDSL.() -> R, + dsl: TransactionDSL.() -> R, transactionMap: HashMap = HashMap() ): WireTransaction { val transactionLocation = getCallerLocation() @@ -316,25 +299,25 @@ data class TestLedgerDSLInterpreter private constructor ( override fun _transaction( transactionLabel: String?, transactionBuilder: TransactionBuilder, - dsl: TransactionDSL.() -> EnforceVerifyOrFail + dsl: TransactionDSL.() -> EnforceVerifyOrFail ) = recordTransactionWithTransactionMap(transactionLabel, transactionBuilder, dsl, transactionWithLocations) override fun _unverifiedTransaction( transactionLabel: String?, transactionBuilder: TransactionBuilder, - dsl: TransactionDSL.() -> Unit + dsl: TransactionDSL.() -> Unit ) = recordTransactionWithTransactionMap(transactionLabel, transactionBuilder, dsl, nonVerifiedTransactionWithLocations) override fun tweak( - dsl: LedgerDSL>.() -> Unit) = + dsl: LedgerDSL>.() -> Unit) = dsl(LedgerDSL(copy())) override fun attachment(attachment: InputStream): SecureHash { return storageService.attachments.importAttachment(attachment) } - override fun verifies() { + override fun verifies(): EnforceVerifyOrFail { val transactionGroup = toTransactionGroup() try { transactionGroup.verify() @@ -343,12 +326,8 @@ data class TestLedgerDSLInterpreter private constructor ( val transactionName = transactionWithLocation?.label ?: transactionWithLocation?.location ?: "" throw VerifiesFailed(transactionName, exception) } - } - override fun failsWith(expectedMessage: String?) { - expectExceptionContainingString(expectedMessage) { - this.verifies() - } + return EnforceVerifyOrFail.Token } override fun retrieveOutputStateAndRef(clazz: Class, label: String): StateAndRef { @@ -389,30 +368,5 @@ fun signAll(transactionsToSign: List, extraKeys: Array.signAll( +fun LedgerDSL.signAll( 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") - } -} diff --git a/core/src/main/kotlin/com/r3corda/core/testing/TestUtils.kt b/core/src/main/kotlin/com/r3corda/core/testing/TestUtils.kt index b649b0e63e..88e3de34f7 100644 --- a/core/src/main/kotlin/com/r3corda/core/testing/TestUtils.kt +++ b/core/src/main/kotlin/com/r3corda/core/testing/TestUtils.kt @@ -97,8 +97,8 @@ object JavaTestHelpers { @JvmStatic @JvmOverloads fun ledger( identityService: IdentityService = MOCK_IDENTITY_SERVICE, storageService: StorageService = MockStorageService(), - dsl: LedgerDSL.() -> Unit - ): LedgerDSL { + dsl: LedgerDSL.() -> Unit + ): LedgerDSL { val ledgerDsl = LedgerDSL(TestLedgerDSLInterpreter(identityService, storageService)) dsl(ledgerDsl) return ledgerDsl @@ -111,10 +111,7 @@ object JavaTestHelpers { @JvmStatic @JvmOverloads fun transaction( transactionLabel: String? = null, transactionBuilder: TransactionBuilder = TransactionBuilder(), - dsl: TransactionDSL< - EnforceVerifyOrFail, - TransactionDSLInterpreter - >.() -> EnforceVerifyOrFail + dsl: TransactionDSL.() -> EnforceVerifyOrFail ) = ledger { this.transaction(transactionLabel, transactionBuilder, dsl) } } diff --git a/core/src/main/kotlin/com/r3corda/core/testing/TransactionDSLInterpreter.kt b/core/src/main/kotlin/com/r3corda/core/testing/TransactionDSLInterpreter.kt index 2816d77990..0edb41f944 100644 --- a/core/src/main/kotlin/com/r3corda/core/testing/TransactionDSLInterpreter.kt +++ b/core/src/main/kotlin/com/r3corda/core/testing/TransactionDSLInterpreter.kt @@ -13,11 +13,11 @@ import java.time.Instant * @param : The return type of [verifies]/[failsWith] and the like. It is generic so that we have control over whether * we want to enforce users to call these methods (@see [EnforceVerifyOrFail]) or not. */ -interface TransactionDSLInterpreter : OutputStateLookup { +interface TransactionDSLInterpreter : Verifies, OutputStateLookup { /** * A reference to the enclosing ledger{..}'s interpreter. */ - val ledgerInterpreter: LedgerDSLInterpreter> + val ledgerInterpreter: LedgerDSLInterpreter /** * Adds an input reference to the transaction. Note that [verifies] will resolve this reference. @@ -46,31 +46,19 @@ interface TransactionDSLInterpreter : OutputStateLookup { */ fun _command(signers: List, commandData: CommandData) - /** - * Verifies the transaction. - * @return: Possibly a token confirming that [verifies] has been called. - */ - fun verifies(): R - - /** - * Verifies the transaction, expecting an exception to be thrown. - * @param expectedMessage: An optional string to be searched for in the raised exception. - */ - fun failsWith(expectedMessage: String?): R - /** * Creates a local scoped copy of the transaction. * @param dsl: The transaction DSL to be interpreted using the copy. */ - fun tweak(dsl: TransactionDSL>.() -> R): R + fun tweak(dsl: TransactionDSL.() -> EnforceVerifyOrFail): EnforceVerifyOrFail } -class TransactionDSL> (val interpreter: T) : - TransactionDSLInterpreter by interpreter { +class TransactionDSL (val interpreter: T) : + TransactionDSLInterpreter by interpreter { /** * Looks up the output label and adds the found state as an input. - * @param stateLabel: The label of the output state specified when calling [LedgerDSLInterpreter._output] and friends. + * @param stateLabel: The label of the output state specified when calling [TransactionDSLInterpreter._output] and friends. */ fun input(stateLabel: String) = input(retrieveOutputStateAndRef(ContractState::class.java, stateLabel).ref) @@ -128,14 +116,4 @@ class TransactionDSL> (val interpreter: */ @JvmOverloads fun timestamp(data: TimestampCommand, notary: PublicKey = DUMMY_NOTARY.owningKey) = command(notary, data) - - /** - * Asserts that the transaction will fail verification - */ - fun fails() = failsWith(null) - - /** - * @see TransactionDSLInterpreter.failsWith - */ - infix fun `fails with`(msg: String) = failsWith(msg) } diff --git a/node/src/test/kotlin/com/r3corda/node/messaging/TwoPartyTradeProtocolTests.kt b/node/src/test/kotlin/com/r3corda/node/messaging/TwoPartyTradeProtocolTests.kt index 2e25ab1abf..62863f46dc 100644 --- a/node/src/test/kotlin/com/r3corda/node/messaging/TwoPartyTradeProtocolTests.kt +++ b/node/src/test/kotlin/com/r3corda/node/messaging/TwoPartyTradeProtocolTests.kt @@ -17,7 +17,6 @@ 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.seconds import com.r3corda.core.testing.* import com.r3corda.core.utilities.BriefLogFormatter import com.r3corda.node.internal.testing.MockNetwork @@ -366,7 +365,7 @@ class TwoPartyTradeProtocolTests { } } - private fun LedgerDSL.runWithError( + private fun LedgerDSL.runWithError( bobError: Boolean, aliceError: Boolean, expectedMessageSubstring: String @@ -431,7 +430,7 @@ class TwoPartyTradeProtocolTests { return signed.associateBy { it.id } } - private fun LedgerDSL.fillUpForBuyer( + private fun LedgerDSL.fillUpForBuyer( withError: Boolean, owner: PublicKey = BOB_PUBKEY, issuer: PartyAndReference = MEGA_CORP.ref(1)): Pair> { @@ -472,7 +471,7 @@ class TwoPartyTradeProtocolTests { return Pair(wallet, listOf(eb1, bc1, bc2)) } - private fun LedgerDSL.fillUpForSeller( + private fun LedgerDSL.fillUpForSeller( withError: Boolean, owner: PublicKey, amount: Amount>, diff --git a/node/src/test/kotlin/com/r3corda/node/visualiser/GroupToGraphConversion.kt b/node/src/test/kotlin/com/r3corda/node/visualiser/GroupToGraphConversion.kt index 6b61416d5a..e57cffe02d 100644 --- a/node/src/test/kotlin/com/r3corda/node/visualiser/GroupToGraphConversion.kt +++ b/node/src/test/kotlin/com/r3corda/node/visualiser/GroupToGraphConversion.kt @@ -9,7 +9,7 @@ import org.graphstream.graph.Node import org.graphstream.graph.implementations.SingleGraph import kotlin.reflect.memberProperties -class GraphVisualiser(val dsl: LedgerDSL) { +class GraphVisualiser(val dsl: LedgerDSL) { companion object { val css = GraphVisualiser::class.java.getResourceAsStream("graph.css").bufferedReader().readText() }