mirror of
https://github.com/corda/corda.git
synced 2025-04-07 11:27:01 +00:00
Testing: make the ledger DSL take a ServiceHub rather than individual services.
It defaults to a fresh UnitTestServices(). Also clear up a few other areas.
This commit is contained in:
parent
ba05b90b8f
commit
1c3379f508
@ -4,14 +4,12 @@ package com.r3corda.core.testing
|
||||
|
||||
import com.google.common.base.Throwables
|
||||
import com.google.common.net.HostAndPort
|
||||
import com.r3corda.core.contracts.Attachment
|
||||
import com.r3corda.core.contracts.StateRef
|
||||
import com.r3corda.core.contracts.TransactionBuilder
|
||||
import com.r3corda.core.crypto.*
|
||||
import com.r3corda.core.node.services.IdentityService
|
||||
import com.r3corda.core.node.services.StorageService
|
||||
import com.r3corda.core.node.ServiceHub
|
||||
import com.r3corda.core.node.services.testing.MockIdentityService
|
||||
import com.r3corda.core.node.services.testing.MockStorageService
|
||||
import com.r3corda.core.node.services.testing.UnitTestServices
|
||||
import java.math.BigInteger
|
||||
import java.net.ServerSocket
|
||||
import java.security.KeyPair
|
||||
@ -95,17 +93,14 @@ fun freeLocalHostAndPort(): HostAndPort {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and tests a ledger built by the passed in dsl.
|
||||
* @param identityService: The [IdentityService] to be used while building the ledger.
|
||||
* @param storageService: The [StorageService] to be used for storing e.g. [Attachment]s.
|
||||
* @param dsl: The dsl building the ledger.
|
||||
* Creates and tests a ledger built by the passed in dsl. The provided services can be customised, otherwise a default
|
||||
* of a freshly built [UnitTestServices] is used.
|
||||
*/
|
||||
@JvmOverloads fun ledger(
|
||||
identityService: IdentityService = MOCK_IDENTITY_SERVICE,
|
||||
storageService: StorageService = MockStorageService(),
|
||||
services: ServiceHub = UnitTestServices(),
|
||||
dsl: LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.() -> Unit
|
||||
): LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter> {
|
||||
val ledgerDsl = LedgerDSL(TestLedgerDSLInterpreter(identityService, storageService))
|
||||
val ledgerDsl = LedgerDSL(TestLedgerDSLInterpreter(services))
|
||||
dsl(ledgerDsl)
|
||||
return ledgerDsl
|
||||
}
|
||||
|
@ -40,11 +40,13 @@ interface Verifies {
|
||||
val exceptionMessage = exception.message
|
||||
if (exceptionMessage == null) {
|
||||
throw AssertionError(
|
||||
"Expected exception containing '$expectedMessage' but raised exception had no message"
|
||||
"Expected exception containing '$expectedMessage' but raised exception had no message",
|
||||
exception
|
||||
)
|
||||
} else if (!exceptionMessage.toLowerCase().contains(expectedMessage.toLowerCase())) {
|
||||
throw AssertionError(
|
||||
"Expected exception containing '$expectedMessage' but raised exception was '$exception'"
|
||||
"Expected exception containing '$expectedMessage' but raised exception was '$exception'",
|
||||
exception
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,7 @@ import com.r3corda.core.crypto.DigitalSignature
|
||||
import com.r3corda.core.crypto.Party
|
||||
import com.r3corda.core.crypto.SecureHash
|
||||
import com.r3corda.core.crypto.signWithECDSA
|
||||
import com.r3corda.core.node.services.IdentityService
|
||||
import com.r3corda.core.node.services.StorageService
|
||||
import com.r3corda.core.node.ServiceHub
|
||||
import com.r3corda.core.serialization.serialize
|
||||
import java.io.InputStream
|
||||
import java.security.KeyPair
|
||||
@ -95,6 +94,10 @@ data class TestTransactionDSLInterpreter private constructor(
|
||||
transactionBuilder: TransactionBuilder
|
||||
) : this(ledgerInterpreter, transactionBuilder, HashMap())
|
||||
|
||||
val services = object : ServiceHub by ledgerInterpreter.services {
|
||||
override fun loadState(stateRef: StateRef) = ledgerInterpreter.resolveStateRef<ContractState>(stateRef)
|
||||
}
|
||||
|
||||
private fun copy(): TestTransactionDSLInterpreter =
|
||||
TestTransactionDSLInterpreter(
|
||||
ledgerInterpreter = ledgerInterpreter,
|
||||
@ -141,18 +144,15 @@ data class TestTransactionDSLInterpreter private constructor(
|
||||
}
|
||||
|
||||
data class TestLedgerDSLInterpreter private constructor (
|
||||
private val identityService: IdentityService,
|
||||
private val storageService: StorageService,
|
||||
val services: ServiceHub,
|
||||
internal val labelToOutputStateAndRefs: HashMap<String, StateAndRef<ContractState>> = HashMap(),
|
||||
private val transactionWithLocations: HashMap<SecureHash, WireTransactionWithLocation> = HashMap(),
|
||||
private val transactionWithLocations: HashMap<SecureHash, WireTransactionWithLocation> = LinkedHashMap(),
|
||||
private val nonVerifiedTransactionWithLocations: HashMap<SecureHash, WireTransactionWithLocation> = HashMap()
|
||||
) : LedgerDSLInterpreter<TestTransactionDSLInterpreter> {
|
||||
val wireTransactions: List<WireTransaction> get() = transactionWithLocations.values.map { it.transaction }
|
||||
|
||||
// We specify [labelToOutputStateAndRefs] just so that Kotlin picks the primary constructor instead of cycling
|
||||
constructor(identityService: IdentityService, storageService: StorageService) : this(
|
||||
identityService, storageService, labelToOutputStateAndRefs = HashMap()
|
||||
)
|
||||
constructor(services: ServiceHub) : this(services, labelToOutputStateAndRefs = HashMap())
|
||||
|
||||
companion object {
|
||||
private fun getCallerLocation(): String? {
|
||||
@ -179,8 +179,7 @@ data class TestLedgerDSLInterpreter private constructor (
|
||||
|
||||
internal fun copy(): TestLedgerDSLInterpreter =
|
||||
TestLedgerDSLInterpreter(
|
||||
identityService,
|
||||
storageService,
|
||||
services,
|
||||
labelToOutputStateAndRefs = HashMap(labelToOutputStateAndRefs),
|
||||
transactionWithLocations = HashMap(transactionWithLocations),
|
||||
nonVerifiedTransactionWithLocations = HashMap(nonVerifiedTransactionWithLocations)
|
||||
@ -189,7 +188,7 @@ data class TestLedgerDSLInterpreter private constructor (
|
||||
internal fun resolveWireTransaction(wireTransaction: WireTransaction): TransactionForVerification {
|
||||
return wireTransaction.run {
|
||||
val authenticatedCommands = commands.map {
|
||||
AuthenticatedObject(it.signers, it.signers.mapNotNull { identityService.partyFromKey(it) }, it.value)
|
||||
AuthenticatedObject(it.signers, it.signers.mapNotNull { services.identityService.partyFromKey(it) }, it.value)
|
||||
}
|
||||
val resolvedInputStates = inputs.map { resolveStateRef<ContractState>(it) }
|
||||
val resolvedAttachments = attachments.map { resolveAttachment(it) }
|
||||
@ -220,7 +219,7 @@ data class TestLedgerDSLInterpreter private constructor (
|
||||
}
|
||||
|
||||
internal fun resolveAttachment(attachmentId: SecureHash): Attachment =
|
||||
storageService.attachments.openAttachment(attachmentId) ?: throw AttachmentResolutionException(attachmentId)
|
||||
services.storageService.attachments.openAttachment(attachmentId) ?: throw AttachmentResolutionException(attachmentId)
|
||||
|
||||
private fun <R> interpretTransactionDsl(
|
||||
transactionBuilder: TransactionBuilder,
|
||||
@ -233,10 +232,10 @@ data class TestLedgerDSLInterpreter private constructor (
|
||||
|
||||
fun toTransactionGroup(): TransactionGroup {
|
||||
val ledgerTransactions = transactionWithLocations.map {
|
||||
it.value.transaction.toLedgerTransaction(identityService, storageService.attachments)
|
||||
it.value.transaction.toLedgerTransaction(services.identityService, services.storageService.attachments)
|
||||
}
|
||||
val nonVerifiedLedgerTransactions = nonVerifiedTransactionWithLocations.map {
|
||||
it.value.transaction.toLedgerTransaction(identityService, storageService.attachments)
|
||||
it.value.transaction.toLedgerTransaction(services.identityService, services.storageService.attachments)
|
||||
}
|
||||
return TransactionGroup(ledgerTransactions.toSet(), nonVerifiedLedgerTransactions.toSet())
|
||||
}
|
||||
@ -295,7 +294,7 @@ data class TestLedgerDSLInterpreter private constructor (
|
||||
dsl(LedgerDSL(copy()))
|
||||
|
||||
override fun attachment(attachment: InputStream): SecureHash {
|
||||
return storageService.attachments.importAttachment(attachment)
|
||||
return services.storageService.attachments.importAttachment(attachment)
|
||||
}
|
||||
|
||||
override fun verifies(): EnforceVerifyOrFail {
|
||||
@ -322,6 +321,9 @@ data class TestLedgerDSLInterpreter private constructor (
|
||||
return stateAndRef as StateAndRef<S>
|
||||
}
|
||||
}
|
||||
|
||||
val transactionsToVerify: List<WireTransaction> get() = transactionWithLocations.values.map { it.transaction }
|
||||
val transactionsUnverified: List<WireTransaction> get() = nonVerifiedTransactionWithLocations.values.map { it.transaction }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -330,7 +332,7 @@ data class TestLedgerDSLInterpreter private constructor (
|
||||
* @param extraKeys extra keys to sign transactions with.
|
||||
* @return List of [SignedTransaction]s.
|
||||
*/
|
||||
fun signAll(transactionsToSign: List<WireTransaction>, extraKeys: Array<out KeyPair>) = transactionsToSign.map { wtx ->
|
||||
fun signAll(transactionsToSign: List<WireTransaction>, extraKeys: List<KeyPair>) = transactionsToSign.map { wtx ->
|
||||
val allPubKeys = wtx.signers.toMutableSet()
|
||||
val bits = wtx.serialize()
|
||||
require(bits == wtx.serialized)
|
||||
@ -350,4 +352,4 @@ fun signAll(transactionsToSign: List<WireTransaction>, extraKeys: Array<out KeyP
|
||||
* @return List of [SignedTransaction]s.
|
||||
*/
|
||||
fun LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.signAll(
|
||||
vararg extraKeys: KeyPair) = signAll(this.interpreter.wireTransactions, extraKeys)
|
||||
vararg extraKeys: KeyPair) = signAll(this.interpreter.wireTransactions, extraKeys.toList())
|
||||
|
@ -246,7 +246,7 @@ class TwoPartyTradeProtocolTests {
|
||||
val aliceNode = makeNodeWithTracking(notaryNode.info, ALICE.name, ALICE_KEY)
|
||||
val bobNode = makeNodeWithTracking(notaryNode.info, BOB.name, BOB_KEY)
|
||||
|
||||
ledger(storageService = aliceNode.storage) {
|
||||
ledger(aliceNode.services) {
|
||||
|
||||
// Insert a prospectus type attachment into the commercial paper transaction.
|
||||
val stream = ByteArrayOutputStream()
|
||||
@ -413,7 +413,7 @@ class TwoPartyTradeProtocolTests {
|
||||
wtxToSign: List<WireTransaction>,
|
||||
services: ServiceHub,
|
||||
vararg extraKeys: KeyPair): Map<SecureHash, SignedTransaction> {
|
||||
val signed: List<SignedTransaction> = signAll(wtxToSign, extraKeys)
|
||||
val signed: List<SignedTransaction> = signAll(wtxToSign, extraKeys.toList())
|
||||
services.recordTransactions(signed)
|
||||
val validatedTransactions = services.storageService.validatedTransactions
|
||||
if (validatedTransactions is RecordingTransactionStorage) {
|
||||
|
@ -17,13 +17,13 @@ class GraphVisualiser(val dsl: LedgerDSL<TestTransactionDSLInterpreter, TestLedg
|
||||
}
|
||||
|
||||
fun convert(): SingleGraph {
|
||||
val tg = dsl.interpreter.toTransactionGroup()
|
||||
val testLedger: TestLedgerDSLInterpreter = dsl.interpreter
|
||||
val graph = createGraph("Transaction group", css)
|
||||
|
||||
// Map all the transactions, including the bogus non-verified ones (with no inputs) to graph nodes.
|
||||
for ((txIndex, tx) in (tg.transactions + tg.nonVerifiedRoots).withIndex()) {
|
||||
for ((txIndex, tx) in (testLedger.transactionsToVerify + testLedger.transactionsUnverified).withIndex()) {
|
||||
val txNode = graph.addNode<Node>("tx$txIndex")
|
||||
if (tx !in tg.nonVerifiedRoots)
|
||||
if (tx !in testLedger.transactionsUnverified)
|
||||
txNode.label = dsl.interpreter.transactionName(tx.id).let { it ?: "TX[${tx.id.prefixChars()}]" }
|
||||
txNode.styleClass = "tx"
|
||||
|
||||
@ -48,7 +48,7 @@ class GraphVisualiser(val dsl: LedgerDSL<TestTransactionDSLInterpreter, TestLedg
|
||||
}
|
||||
}
|
||||
// And now all states and transactions were mapped to graph nodes, hook up the input edges.
|
||||
for ((txIndex, tx) in tg.transactions.withIndex()) {
|
||||
for ((txIndex, tx) in testLedger.transactionsToVerify.withIndex()) {
|
||||
for ((inputIndex, ref) in tx.inputs.withIndex()) {
|
||||
val edge = graph.addEdge<Edge>("tx$txIndex-in$inputIndex", ref.toString(), "tx$txIndex", true)
|
||||
edge.weight = 1.2
|
||||
|
Loading…
x
Reference in New Issue
Block a user