mirror of
https://github.com/corda/corda.git
synced 2024-12-30 17:57:02 +00:00
Merge commit 'ad23bb875482b7b8e17c64fb37342d0d6a5ce94d' into feature/test-merge-szymon
# Conflicts: # node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt
This commit is contained in:
commit
f701bc1b9a
@ -12,7 +12,6 @@ import java.util.*
|
|||||||
* Defines a simple domain specific language for the specification of financial contracts. Currently covers:
|
* Defines a simple domain specific language for the specification of financial contracts. Currently covers:
|
||||||
*
|
*
|
||||||
* - Some utilities for working with commands.
|
* - Some utilities for working with commands.
|
||||||
* - An Amount type that represents a positive quantity of a specific token.
|
|
||||||
* - A simple language extension for specifying requirements in English, along with logic to enforce them.
|
* - A simple language extension for specifying requirements in English, along with logic to enforce them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -30,37 +29,44 @@ inline fun <R> requireThat(body: Requirements.() -> R) = Requirements.body()
|
|||||||
|
|
||||||
//// Authenticated commands ///////////////////////////////////////////////////////////////////////////////////////////
|
//// Authenticated commands ///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO: Provide a version of select that interops with Java
|
|
||||||
|
|
||||||
/** Filters the command list by type, party and public key all at once. */
|
/** Filters the command list by type, party and public key all at once. */
|
||||||
inline fun <reified T : CommandData> Collection<CommandWithParties<CommandData>>.select(signer: PublicKey? = null,
|
inline fun <reified T : CommandData> Collection<CommandWithParties<CommandData>>.select(signer: PublicKey? = null,
|
||||||
party: AbstractParty? = null) =
|
party: AbstractParty? = null) =
|
||||||
filter { it.value is T }.
|
select(T::class.java, signer, party)
|
||||||
|
|
||||||
|
/** Filters the command list by type, party and public key all at once. */
|
||||||
|
fun <C : CommandData> Collection<CommandWithParties<CommandData>>.select(klass: Class<C>,
|
||||||
|
signer: PublicKey? = null,
|
||||||
|
party: AbstractParty? = null) =
|
||||||
|
mapNotNull { if (klass.isInstance(it.value)) uncheckedCast<CommandWithParties<CommandData>, CommandWithParties<C>>(it) else null }.
|
||||||
filter { if (signer == null) true else signer in it.signers }.
|
filter { if (signer == null) true else signer in it.signers }.
|
||||||
filter { if (party == null) true else party in it.signingParties }.
|
filter { if (party == null) true else party in it.signingParties }.
|
||||||
map { CommandWithParties(it.signers, it.signingParties, it.value as T) }
|
map { CommandWithParties(it.signers, it.signingParties, it.value) }
|
||||||
|
|
||||||
// TODO: Provide a version of select that interops with Java
|
|
||||||
|
|
||||||
/** Filters the command list by type, parties and public keys all at once. */
|
/** Filters the command list by type, parties and public keys all at once. */
|
||||||
inline fun <reified T : CommandData> Collection<CommandWithParties<CommandData>>.select(signers: Collection<PublicKey>?,
|
inline fun <reified T : CommandData> Collection<CommandWithParties<CommandData>>.select(signers: Collection<PublicKey>?,
|
||||||
parties: Collection<Party>?) =
|
parties: Collection<Party>?) =
|
||||||
filter { it.value is T }.
|
select(T::class.java, signers, parties)
|
||||||
|
|
||||||
|
/** Filters the command list by type, parties and public keys all at once. */
|
||||||
|
fun <C : CommandData> Collection<CommandWithParties<CommandData>>.select(klass: Class<C>,
|
||||||
|
signers: Collection<PublicKey>?,
|
||||||
|
parties: Collection<Party>?) =
|
||||||
|
mapNotNull { if (klass.isInstance(it.value)) uncheckedCast<CommandWithParties<CommandData>, CommandWithParties<C>>(it) else null }.
|
||||||
filter { if (signers == null) true else it.signers.containsAll(signers) }.
|
filter { if (signers == null) true else it.signers.containsAll(signers) }.
|
||||||
filter { if (parties == null) true else it.signingParties.containsAll(parties) }.
|
filter { if (parties == null) true else it.signingParties.containsAll(parties) }.
|
||||||
map { CommandWithParties(it.signers, it.signingParties, it.value as T) }
|
map { CommandWithParties(it.signers, it.signingParties, it.value) }
|
||||||
|
|
||||||
/** Ensures that a transaction has only one command that is of the given type, otherwise throws an exception. */
|
/** Ensures that a transaction has only one command that is of the given type, otherwise throws an exception. */
|
||||||
inline fun <reified T : CommandData> Collection<CommandWithParties<CommandData>>.requireSingleCommand() = try {
|
inline fun <reified T : CommandData> Collection<CommandWithParties<CommandData>>.requireSingleCommand() = requireSingleCommand(T::class.java)
|
||||||
select<T>().single()
|
|
||||||
|
/** Ensures that a transaction has only one command that is of the given type, otherwise throws an exception. */
|
||||||
|
fun <C : CommandData> Collection<CommandWithParties<CommandData>>.requireSingleCommand(klass: Class<C>) = try {
|
||||||
|
select(klass).single()
|
||||||
} catch (e: NoSuchElementException) {
|
} catch (e: NoSuchElementException) {
|
||||||
throw IllegalStateException("Required ${T::class.qualifiedName} command") // Better error message.
|
throw IllegalStateException("Required ${klass.kotlin.qualifiedName} command") // Better error message.
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ensures that a transaction has only one command that is of the given type, otherwise throws an exception. */
|
|
||||||
fun <C : CommandData> Collection<CommandWithParties<CommandData>>.requireSingleCommand(klass: Class<C>) =
|
|
||||||
mapNotNull { if (klass.isInstance(it.value)) uncheckedCast<CommandWithParties<CommandData>, CommandWithParties<C>>(it) else null }.single()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple functionality for verifying a move command. Verifies that each input has a signature from its owning key.
|
* Simple functionality for verifying a move command. Verifies that each input has a signature from its owning key.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,179 @@
|
|||||||
|
package net.corda.core.contracts
|
||||||
|
|
||||||
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.testing.TestIdentity
|
||||||
|
import org.assertj.core.api.Assertions
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.Parameterized
|
||||||
|
import java.security.PublicKey
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFalse
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class ContractsDSLTests {
|
||||||
|
class UnwantedCommand : CommandData
|
||||||
|
|
||||||
|
interface TestCommands : CommandData {
|
||||||
|
class CommandOne : TypeOnlyCommandData(), TestCommands
|
||||||
|
class CommandTwo : TypeOnlyCommandData(), TestCommands
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
val megaCorp = TestIdentity(CordaX500Name("MegaCorp", "London", "GB"))
|
||||||
|
val miniCorp = TestIdentity(CordaX500Name("MiniCorp", "London", "GB"))
|
||||||
|
|
||||||
|
val validCommandOne = CommandWithParties(listOf(megaCorp.publicKey, miniCorp.publicKey), listOf(megaCorp.party, miniCorp.party), TestCommands.CommandOne())
|
||||||
|
val validCommandTwo = CommandWithParties(listOf(megaCorp.publicKey), listOf(megaCorp.party), TestCommands.CommandTwo())
|
||||||
|
val invalidCommand = CommandWithParties(emptyList(), emptyList(), UnwantedCommand())
|
||||||
|
}
|
||||||
|
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
class RequireSingleCommandTests(private val testFunction: (Collection<CommandWithParties<CommandData>>) -> CommandWithParties<CommandData>, description: String) {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
@Parameterized.Parameters(name = "{1}")
|
||||||
|
fun data(): Collection<Array<Any>> = listOf(
|
||||||
|
arrayOf<Any>({ commands: Collection<CommandWithParties<CommandData>> -> commands.requireSingleCommand<TestCommands>() }, "Inline version"),
|
||||||
|
arrayOf<Any>({ commands: Collection<CommandWithParties<CommandData>> -> commands.requireSingleCommand(TestCommands::class.java) }, "Interop version")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check function returns one value`() {
|
||||||
|
val commands = listOf(validCommandOne, invalidCommand)
|
||||||
|
val returnedCommand = testFunction(commands)
|
||||||
|
assertEquals(returnedCommand, validCommandOne, "they should be the same")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException::class)
|
||||||
|
fun `check error is thrown if more than one valid command`() {
|
||||||
|
val commands = listOf(validCommandOne, validCommandTwo)
|
||||||
|
testFunction(commands)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check error is thrown when command is of wrong type`() {
|
||||||
|
val commands = listOf(invalidCommand)
|
||||||
|
Assertions.assertThatThrownBy { testFunction(commands) }
|
||||||
|
.isInstanceOf(IllegalStateException::class.java)
|
||||||
|
.hasMessage("Required net.corda.core.contracts.ContractsDSLTests.TestCommands command")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
class SelectWithSingleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, PublicKey?, AbstractParty?) -> Iterable<CommandWithParties<CommandData>>, description: String) {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
@Parameterized.Parameters(name = "{1}")
|
||||||
|
fun data(): Collection<Array<Any>> = listOf(
|
||||||
|
arrayOf<Any>({ commands: Collection<CommandWithParties<CommandData>>, signer: PublicKey?, party: AbstractParty? -> commands.select<TestCommands>(signer, party) }, "Inline version"),
|
||||||
|
arrayOf<Any>({ commands: Collection<CommandWithParties<CommandData>>, signer: PublicKey?, party: AbstractParty? -> commands.select(TestCommands::class.java, signer, party) }, "Interop version")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function returns all values`() {
|
||||||
|
val commands = listOf(validCommandOne, validCommandTwo)
|
||||||
|
testFunction(commands, null, null)
|
||||||
|
assertEquals(2, commands.size)
|
||||||
|
assertTrue(commands.contains(validCommandOne))
|
||||||
|
assertTrue(commands.contains(validCommandTwo))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function does not return invalid command types`() {
|
||||||
|
val commands = listOf(validCommandOne, invalidCommand)
|
||||||
|
val filteredCommands = testFunction(commands, null, null).toList()
|
||||||
|
assertEquals(1, filteredCommands.size)
|
||||||
|
assertTrue(filteredCommands.contains(validCommandOne))
|
||||||
|
assertFalse(filteredCommands.contains(invalidCommand))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function returns commands from valid signers`() {
|
||||||
|
val commands = listOf(validCommandOne, validCommandTwo)
|
||||||
|
val filteredCommands = testFunction(commands, miniCorp.publicKey, null).toList()
|
||||||
|
assertEquals(1, filteredCommands.size)
|
||||||
|
assertTrue(filteredCommands.contains(validCommandOne))
|
||||||
|
assertFalse(filteredCommands.contains(validCommandTwo))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function returns commands from valid parties`() {
|
||||||
|
val commands = listOf(validCommandOne, validCommandTwo)
|
||||||
|
val filteredCommands = testFunction(commands, null, miniCorp.party).toList()
|
||||||
|
assertEquals(1, filteredCommands.size)
|
||||||
|
assertTrue(filteredCommands.contains(validCommandOne))
|
||||||
|
assertFalse(filteredCommands.contains(validCommandTwo))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
class SelectWithMultipleInputsTests(private val testFunction: (Collection<CommandWithParties<CommandData>>, Collection<PublicKey>?, Collection<Party>?) -> Iterable<CommandWithParties<CommandData>>, description: String) {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
@Parameterized.Parameters(name = "{1}")
|
||||||
|
fun data(): Collection<Array<Any>> = listOf(
|
||||||
|
arrayOf<Any>({ commands: Collection<CommandWithParties<CommandData>>, signers: Collection<PublicKey>?, party: Collection<Party>? -> commands.select<TestCommands>(signers, party) }, "Inline version"),
|
||||||
|
arrayOf<Any>({ commands: Collection<CommandWithParties<CommandData>>, signers: Collection<PublicKey>?, party: Collection<Party>? -> commands.select(TestCommands::class.java, signers, party) }, "Interop version")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function returns all values`() {
|
||||||
|
val commands = listOf(validCommandOne, validCommandTwo)
|
||||||
|
testFunction(commands, null, null)
|
||||||
|
assertEquals(2, commands.size)
|
||||||
|
assertTrue(commands.contains(validCommandOne))
|
||||||
|
assertTrue(commands.contains(validCommandTwo))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function does not return invalid command types`() {
|
||||||
|
val commands = listOf(validCommandOne, invalidCommand)
|
||||||
|
val filteredCommands = testFunction(commands, null, null).toList()
|
||||||
|
assertEquals(1, filteredCommands.size)
|
||||||
|
assertTrue(filteredCommands.contains(validCommandOne))
|
||||||
|
assertFalse(filteredCommands.contains(invalidCommand))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function returns commands from valid signers`() {
|
||||||
|
val commands = listOf(validCommandOne, validCommandTwo)
|
||||||
|
val filteredCommands = testFunction(commands, listOf(megaCorp.publicKey), null).toList()
|
||||||
|
assertEquals(2, filteredCommands.size)
|
||||||
|
assertTrue(filteredCommands.contains(validCommandOne))
|
||||||
|
assertTrue(filteredCommands.contains(validCommandTwo))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function returns commands from all valid signers`() {
|
||||||
|
val commands = listOf(validCommandOne, validCommandTwo)
|
||||||
|
val filteredCommands = testFunction(commands, listOf(miniCorp.publicKey, megaCorp.publicKey), null).toList()
|
||||||
|
assertEquals(1, filteredCommands.size)
|
||||||
|
assertTrue(filteredCommands.contains(validCommandOne))
|
||||||
|
assertFalse(filteredCommands.contains(validCommandTwo))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function returns commands from valid parties`() {
|
||||||
|
val commands = listOf(validCommandOne, validCommandTwo)
|
||||||
|
val filteredCommands = testFunction(commands, null, listOf(megaCorp.party)).toList()
|
||||||
|
assertEquals(2, filteredCommands.size)
|
||||||
|
assertTrue(filteredCommands.contains(validCommandOne))
|
||||||
|
assertTrue(filteredCommands.contains(validCommandTwo))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `check that function returns commands from all valid parties`() {
|
||||||
|
val commands = listOf(validCommandOne, validCommandTwo)
|
||||||
|
val filteredCommands = testFunction(commands, null, listOf(miniCorp.party, megaCorp.party)).toList()
|
||||||
|
assertEquals(1, filteredCommands.size)
|
||||||
|
assertTrue(filteredCommands.contains(validCommandOne))
|
||||||
|
assertFalse(filteredCommands.contains(validCommandTwo))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -50,6 +50,7 @@ class BFTNotaryServiceTests : IntegrationTest() {
|
|||||||
val databaseSchemas = IntegrationTestSchemas("node_0", "node_1", "node_2", "node_3", "node_4", "node_5",
|
val databaseSchemas = IntegrationTestSchemas("node_0", "node_1", "node_2", "node_3", "node_4", "node_5",
|
||||||
"node_6", "node_7", "node_8", "node_9")
|
"node_6", "node_7", "node_8", "node_9")
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var mockNet: MockNetwork
|
private lateinit var mockNet: MockNetwork
|
||||||
private lateinit var notary: Party
|
private lateinit var notary: Party
|
||||||
private lateinit var node: StartedNode<MockNode>
|
private lateinit var node: StartedNode<MockNode>
|
||||||
@ -58,6 +59,7 @@ class BFTNotaryServiceTests : IntegrationTest() {
|
|||||||
fun before() {
|
fun before() {
|
||||||
mockNet = MockNetwork(emptyList())
|
mockNet = MockNetwork(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun stopNodes() {
|
fun stopNodes() {
|
||||||
mockNet.stopNodes()
|
mockNet.stopNodes()
|
||||||
|
Loading…
Reference in New Issue
Block a user