From f831ffdf3d73859fbf8e92194d96a0f1740177e7 Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Wed, 15 Jun 2016 14:33:42 +0100 Subject: [PATCH] Add tests for TransactionGraphSearch --- .../r3corda/contracts/testing/TestUtils.kt | 1 + .../com/r3corda/contracts/cash/CashTests.kt | 2 +- .../r3corda/core}/contracts/DummyContract.kt | 4 +- .../core/contracts/TransactionGraphSearch.kt | 3 +- .../node/services/testing/MockServices.kt | 2 +- .../contracts/TransactionGraphSearchTests.kt | 73 +++++++++++++++++++ .../node/internal/testing/TestUtils.kt | 2 +- 7 files changed, 80 insertions(+), 7 deletions(-) rename {contracts/src/main/kotlin/com/r3corda => core/src/main/kotlin/com/r3corda/core}/contracts/DummyContract.kt (91%) create mode 100644 core/src/test/kotlin/com/r3corda/core/contracts/TransactionGraphSearchTests.kt diff --git a/contracts/src/main/kotlin/com/r3corda/contracts/testing/TestUtils.kt b/contracts/src/main/kotlin/com/r3corda/contracts/testing/TestUtils.kt index 5e27d7ae51..1ebf87d512 100644 --- a/contracts/src/main/kotlin/com/r3corda/contracts/testing/TestUtils.kt +++ b/contracts/src/main/kotlin/com/r3corda/contracts/testing/TestUtils.kt @@ -5,6 +5,7 @@ import com.r3corda.contracts.cash.Cash import com.r3corda.contracts.cash.CASH_PROGRAM_ID import com.r3corda.core.contracts.Amount import com.r3corda.core.contracts.Contract +import com.r3corda.core.contracts.DummyContract import com.r3corda.core.crypto.NullPublicKey import com.r3corda.core.crypto.Party import com.r3corda.core.testing.DUMMY_NOTARY diff --git a/contracts/src/test/kotlin/com/r3corda/contracts/cash/CashTests.kt b/contracts/src/test/kotlin/com/r3corda/contracts/cash/CashTests.kt index 9abe855298..221af73de4 100644 --- a/contracts/src/test/kotlin/com/r3corda/contracts/cash/CashTests.kt +++ b/contracts/src/test/kotlin/com/r3corda/contracts/cash/CashTests.kt @@ -1,6 +1,6 @@ package com.r3corda.contracts.cash -import com.r3corda.contracts.DummyContract +import com.r3corda.core.contracts.DummyContract import com.r3corda.contracts.testing.`issued by` import com.r3corda.contracts.testing.`owned by` import com.r3corda.core.contracts.* diff --git a/contracts/src/main/kotlin/com/r3corda/contracts/DummyContract.kt b/core/src/main/kotlin/com/r3corda/core/contracts/DummyContract.kt similarity index 91% rename from contracts/src/main/kotlin/com/r3corda/contracts/DummyContract.kt rename to core/src/main/kotlin/com/r3corda/core/contracts/DummyContract.kt index 9e7210645a..d2c1cf75e2 100644 --- a/contracts/src/main/kotlin/com/r3corda/contracts/DummyContract.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/DummyContract.kt @@ -1,7 +1,5 @@ -package com.r3corda.contracts +package com.r3corda.core.contracts -import com.r3corda.core.* -import com.r3corda.core.contracts.* import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.SecureHash diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionGraphSearch.kt b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionGraphSearch.kt index d43e69ebec..32682e6285 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/TransactionGraphSearch.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/TransactionGraphSearch.kt @@ -13,7 +13,8 @@ import java.util.concurrent.Callable * * In future, this should support restricting the search by time, and other types of useful query. * - * TODO: Write unit tests for this. + * @param transactions map of transaction id to [SignedTransaction] + * @param startPoints transactions to use as starting points for the search */ class TransactionGraphSearch(val transactions: TransactionStorage, val startPoints: List) : Callable> { diff --git a/core/src/main/kotlin/com/r3corda/core/node/services/testing/MockServices.kt b/core/src/main/kotlin/com/r3corda/core/node/services/testing/MockServices.kt index db90aa5eef..4ec33f9acb 100644 --- a/core/src/main/kotlin/com/r3corda/core/node/services/testing/MockServices.kt +++ b/core/src/main/kotlin/com/r3corda/core/node/services/testing/MockServices.kt @@ -77,7 +77,7 @@ class MockAttachmentStorage : AttachmentStorage { } } -class MockTransactionStorage : TransactionStorage { +open class MockTransactionStorage : TransactionStorage { private val txns = HashMap() override fun addTransaction(transaction: SignedTransaction) { txns[transaction.id] = transaction diff --git a/core/src/test/kotlin/com/r3corda/core/contracts/TransactionGraphSearchTests.kt b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionGraphSearchTests.kt new file mode 100644 index 0000000000..247e5e05c8 --- /dev/null +++ b/core/src/test/kotlin/com/r3corda/core/contracts/TransactionGraphSearchTests.kt @@ -0,0 +1,73 @@ +package com.r3corda.core.contracts + +import com.r3corda.core.node.services.testing.MockTransactionStorage +import com.r3corda.core.testing.DUMMY_NOTARY +import com.r3corda.core.testing.MEGA_CORP_KEY +import org.junit.Test +import java.security.KeyPair +import java.security.SecureRandom +import kotlin.test.assertEquals + +class TransactionGraphSearchTests { + class GraphTransactionStorage(val originTx: SignedTransaction, val inputTx: SignedTransaction): MockTransactionStorage() { + init { + addTransaction(originTx) + addTransaction(inputTx) + } + } + + fun random31BitValue(): Int = Math.abs(SecureRandom.getInstanceStrong().nextInt()) + + /** + * Build a pair of transactions. The first issues a dummy output state, and has a command applied, the second then + * references that state. + * + * @param command the command to add to the origin transaction. + * @param signer signer for the two transactions and their commands. + */ + fun buildTransactions(command: CommandData, signer: KeyPair): GraphTransactionStorage { + val originTx = TransactionBuilder().apply { + addOutputState(DummyContract.State(random31BitValue(), DUMMY_NOTARY)) + addCommand(command, signer.public) + signWith(signer) + }.toSignedTransaction(false) + val inputTx = TransactionBuilder().apply { + addInputState(originTx.tx.outRef(0).ref) + signWith(signer) + }.toSignedTransaction(false) + return GraphTransactionStorage(originTx, inputTx) + } + + @Test + fun `return empty from empty`() { + val storage = buildTransactions(DummyContract.Commands.Create(), MEGA_CORP_KEY) + val search = TransactionGraphSearch(storage, emptyList()) + search.query = TransactionGraphSearch.Query() + val expected = emptyList() + val actual = search.call() + + assertEquals(expected, actual) + } + + @Test + fun `return empty from no match`() { + val storage = buildTransactions(DummyContract.Commands.Create(), MEGA_CORP_KEY) + val search = TransactionGraphSearch(storage, listOf(storage.inputTx.tx)) + search.query = TransactionGraphSearch.Query() + val expected = emptyList() + val actual = search.call() + + assertEquals(expected, actual) + } + + @Test + fun `return origin on match`() { + val storage = buildTransactions(DummyContract.Commands.Create(), MEGA_CORP_KEY) + val search = TransactionGraphSearch(storage, listOf(storage.inputTx.tx)) + search.query = TransactionGraphSearch.Query(DummyContract.Commands.Create::class.java) + val expected = listOf(storage.originTx.tx) + val actual = search.call() + + assertEquals(expected, actual) + } +} \ No newline at end of file diff --git a/node/src/main/kotlin/com/r3corda/node/internal/testing/TestUtils.kt b/node/src/main/kotlin/com/r3corda/node/internal/testing/TestUtils.kt index b3a01ad868..05966b6540 100644 --- a/node/src/main/kotlin/com/r3corda/node/internal/testing/TestUtils.kt +++ b/node/src/main/kotlin/com/r3corda/node/internal/testing/TestUtils.kt @@ -1,6 +1,6 @@ package com.r3corda.node.internal.testing -import com.r3corda.contracts.DummyContract +import com.r3corda.core.contracts.DummyContract import com.r3corda.core.contracts.StateRef import com.r3corda.core.crypto.Party import com.r3corda.core.seconds