ENT-12709: Replace uses of assert with correct assertion methods (#7902)

The Kotlin `assert` is only active if the `-ea` JVM flag is specified,
which it isn't. Replaced all uses with the correct assertj assertion.
This commit is contained in:
Shams Asari 2025-02-25 14:09:58 +00:00 committed by GitHub
parent 781aaba649
commit df8f4fa3e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 222 additions and 273 deletions

View File

@ -36,6 +36,7 @@ import net.corda.testing.driver.driver
import net.corda.testing.node.User
import net.corda.testing.node.internal.findCordapp
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Assert
import org.junit.Test
@ -411,7 +412,7 @@ class VaultObserverExceptionTest {
testControlFuture.complete(true)
}
startNode(providedName = ALICE_NAME, rpcUsers = listOf(aliceUser), startInSameProcess = true).getOrThrow()
assert(testControlFuture.getOrThrow(waitForFlowDuration))
assertThat(testControlFuture.getOrThrow(waitForFlowDuration)).isTrue()
} else {
throw IllegalStateException("Out of process node is still up and running!")
}
@ -900,4 +901,4 @@ class VaultObserverExceptionTest {
}
}
}
}
}

View File

@ -360,7 +360,7 @@ class NetworkMapUpdaterTest {
Thread.sleep(2L * cacheExpiryMs)
val newHash = newParameters.serialize().hash
val updateFile = baseDir / NETWORK_PARAMS_UPDATE_FILE_NAME
assert(!updateFile.exists()) { "network parameters should not be auto accepted" }
assertThat(updateFile).describedAs("network parameters should not be auto accepted").doesNotExist()
updater!!.acceptNewNetworkParameters(newHash) { it.serialize().sign(ourKeyPair) }
verify(networkParametersStorage, times(1)).saveParameters(any())
val signedNetworkParams = updateFile.readObject<SignedNetworkParameters>()
@ -398,7 +398,7 @@ class NetworkMapUpdaterTest {
//TODO: Remove sleep in unit test.
Thread.sleep(2L * cacheExpiryMs)
val updateFile = baseDir / NETWORK_PARAMS_UPDATE_FILE_NAME
assert(!updateFile.exists()) { "network parameters should not be auto accepted" }
assertThat(updateFile).describedAs("network parameters should not be auto accepted").doesNotExist()
}
@Test(timeout=300_000)
@ -412,7 +412,7 @@ class NetworkMapUpdaterTest {
//TODO: Remove sleep in unit test.
Thread.sleep(2L * cacheExpiryMs)
val updateFile = baseDir / NETWORK_PARAMS_UPDATE_FILE_NAME
assert(!updateFile.exists()) { "network parameters should not be auto accepted" }
assertThat(updateFile).describedAs("network parameters should not be auto accepted").doesNotExist()
}
@Test(timeout=300_000)
@ -592,16 +592,16 @@ class NetworkMapUpdaterTest {
//TODO: Remove sleep in unit test.
Thread.sleep(2L * cacheExpiryMs)
assert(networkMapCache.allNodeHashes.size == 1)
assert(networkMapCache.allNodeHashes.first() == signedNodeInfo1.raw.hash)
assertThat(networkMapCache.allNodeHashes).hasSize(1)
assertThat(networkMapCache.allNodeHashes.first()).isEqualTo(signedNodeInfo1.raw.hash)
verify(networkMapCache, times(1)).addOrUpdateNodes(listOf(signedNodeInfo1.verified()))
networkMapClient.publish(signedNodeInfo2)
Thread.sleep(2L * cacheExpiryMs)
advanceTime()
verify(networkMapCache, times(1)).addOrUpdateNodes(listOf(signedNodeInfo1.verified()))
assert(networkMapCache.allNodeHashes.size == 1)
assert(networkMapCache.allNodeHashes.first() == signedNodeInfo2.raw.hash)
assertThat(networkMapCache.allNodeHashes).hasSize(1)
assertThat(networkMapCache.allNodeHashes.first()).isEqualTo(signedNodeInfo2.raw.hash)
}
@Test(timeout=300_000)

View File

@ -44,14 +44,13 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.time.Clock
import java.util.*
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
internal fun CheckpointStorage.checkpoints(): List<Checkpoint.Serialized> {
return getCheckpoints().use {
it.map { it.second }.toList()
return getCheckpoints().use { stream ->
stream.map { it.second }.toList()
}
}
@ -454,9 +453,8 @@ class DBCheckpointStorageTests {
val deserializedException = exceptionDetails.value?.let { SerializedBytes<Any>(it) }?.deserialize(context = SerializationDefaults.STORAGE_CONTEXT)
// IllegalStateException does not implement [CordaThrowable] therefore gets deserialized as a [CordaRuntimeException]
assertTrue(deserializedException is CordaRuntimeException)
val cordaRuntimeException = deserializedException
assertEquals(IllegalStateException::class.java.name, cordaRuntimeException.originalExceptionClassName)
assertEquals("I am a naughty exception", cordaRuntimeException.originalMessage!!)
assertEquals(IllegalStateException::class.java.name, deserializedException.originalExceptionClassName)
assertEquals("I am a naughty exception", deserializedException.originalMessage!!)
}
}
@ -624,12 +622,12 @@ class DBCheckpointStorageTests {
}
}
private fun iterationsBasedOnLineSeparatorLength() = when {
System.getProperty("line.separator").length == 1 -> // Linux or Mac
78
System.getProperty("line.separator").length == 2 -> // Windows
75
else -> throw IllegalStateException("Unknown line.separator")
private fun iterationsBasedOnLineSeparatorLength(): Int {
return when (System.lineSeparator().length) {
1 -> 78 // Linux or Mac
2 -> 75 // Windows
else -> throw IllegalStateException("Unknown line.separator")
}
}
@Test(timeout = 300_000)
@ -720,7 +718,7 @@ class DBCheckpointStorageTests {
database.transaction {
val dbFlowCheckpoint= checkpointStorage.getDBCheckpoint(id)
assert(dbFlowCheckpoint!!.blob != null)
assertThat(dbFlowCheckpoint!!.blob).isNotNull
}
}

View File

@ -25,6 +25,7 @@ import net.corda.testing.core.dummyCommand
import net.corda.testing.core.singleIdentity
import net.corda.testing.node.MockNetworkNotarySpec
import net.corda.testing.node.internal.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Assume
import org.junit.Before
@ -144,14 +145,14 @@ class NotaryWhitelistTests(
val ex = assertFailsWith(NotaryException::class) {
future.getOrThrow()
}
assert(ex.error is NotaryError.TransactionInvalid)
assertThat(ex.error).isInstanceOf(NotaryError.TransactionInvalid::class.java)
assertEquals(validStx.id, ex.txId)
}
private fun removeOldNotary(parameters: NetworkParameters): NetworkParameters {
val newParameters = parameters.copy(notaries = parameters.notaries.drop(1))
assert(newParameters.notaries.none { it.identity == oldNotary })
assert(newParameters.notaries.any { it.identity == newNotary })
assertThat(newParameters.notaries).noneMatch { it.identity == oldNotary }
assertThat(newParameters.notaries).anyMatch { it.identity == newNotary }
return newParameters
}
@ -202,7 +203,7 @@ class NotaryWhitelistTests(
val ex = assertFailsWith(NotaryException::class) {
future.getOrThrow()
}
assert(ex.error is NotaryError.TransactionInvalid)
assertThat(ex.error).isInstanceOf(NotaryError.TransactionInvalid::class.java)
assertEquals(validStx.id, ex.txId)
}
@ -216,7 +217,7 @@ class NotaryWhitelistTests(
return fakeStx.tx.outRef(0)
}
/** Changes the notary service to [notary]. Does not actually communicate with a notary. */
/** Changes the notary service to [fakeNotaryParty]. Does not actually communicate with a notary. */
private fun changeNotary(inputState: StateAndRef<DummyContract.State>, fakeNotaryParty: Party, fakeNotaryKeyPair: KeyPair): NotaryChangeLedgerTransaction {
val notaryChangeTx = NotaryChangeTransactionBuilder(
listOf(inputState.ref),
@ -254,4 +255,4 @@ class NotaryWhitelistTests(
val data = SignableData(fakeStx.id, metadata)
return fakeNotaryKeyPair.sign(data)
}
}
}

View File

@ -1,6 +1,14 @@
package net.corda.node.services.transactions
import net.corda.core.contracts.*
import net.corda.core.contracts.BelongsToContract
import net.corda.core.contracts.Command
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.LinearPointer
import net.corda.core.contracts.LinearState
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StatePointer
import net.corda.core.contracts.StaticPointer
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.node.NotaryInfo
@ -12,6 +20,7 @@ import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.core.TestIdentity
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestIdentityService
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -79,7 +88,7 @@ class ResolveStatePointersTest {
}
// Check the StateRef for the pointed-to state is not added as a reference.
assert(tx.referenceStates().none { it == stateAndRef.ref })
assertThat(tx.referenceStates()).noneMatch { it == stateAndRef.ref }
// Resolve the StateRef to the actual state.
val ltx = tx.toLedgerTransaction(services)
@ -119,7 +128,7 @@ class ResolveStatePointersTest {
}
// Check the StateRef for the pointed-to state is not added as a reference.
assert(tx.referenceStates().none { it == stateAndRef.ref })
assertThat(tx.referenceStates()).noneMatch { it == stateAndRef.ref }
// Resolve the StateRef to the actual state.
val ltx = tx.toLedgerTransaction(services)
@ -223,4 +232,4 @@ class ResolveStatePointersTest {
val foo = ltx.outputs.single().data as Foo<Bar>
assertEquals(stateAndRef, foo.baz.resolve(ltx))
}
}
}

View File

@ -1,6 +1,8 @@
package net.corda.node.services.transactions
import com.codahale.metrics.MetricRegistry
import net.corda.core.concurrent.CordaFuture
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TimeWindow
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.DigestService
@ -14,9 +16,12 @@ import net.corda.core.crypto.randomHash
import net.corda.core.flows.NotarisationRequestSignature
import net.corda.core.flows.NotaryError
import net.corda.core.flows.StateConsumptionDetails
import net.corda.core.flows.StateConsumptionDetails.ConsumedStateType.INPUT_STATE
import net.corda.core.flows.StateConsumptionDetails.ConsumedStateType.REFERENCE_INPUT_STATE
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.HashAgility
import net.corda.core.internal.notary.UniquenessProvider
import net.corda.core.internal.notary.UniquenessProvider.Result
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.minutes
import net.corda.coretesting.internal.configureTestSSL
@ -41,6 +46,7 @@ import net.corda.testing.node.MockServices.Companion.makeTestDataSourcePropertie
import net.corda.testing.node.TestClock
import net.corda.testing.node.internal.MockKeyManagementService
import net.corda.testing.node.makeTestIdentityService
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
@ -49,7 +55,6 @@ import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import java.security.KeyPair
import java.time.Clock
import kotlin.test.assertEquals
@RunWith(Parameterized::class)
class UniquenessProviderTests(
@ -58,18 +63,19 @@ class UniquenessProviderTests(
) {
companion object {
@JvmStatic
@Parameterized.Parameters
fun data(): Collection<Array<Any>> = listOf(
arrayOf(JPAUniquenessProviderFactory(DigestService.sha2_256), DigestService.sha2_256),
arrayOf(RaftUniquenessProviderFactory(), DigestService.sha2_256)
// arrayOf(JPAUniquenessProviderFactory(DigestService.sha2_512), DigestService.sha2_512),
// arrayOf(RaftUniquenessProviderFactory(), DigestService.sha2_512)
)
@Parameterized.Parameters(name = "{0} {1}")
fun data(): Collection<Array<Any>> {
return listOf(
arrayOf(JPAUniquenessProviderFactory(DigestService.sha2_256), DigestService.sha2_256),
arrayOf(RaftUniquenessProviderFactory(), DigestService.sha2_256)
)
}
}
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule(inheritable = true)
private val identity = TestIdentity(CordaX500Name("MegaCorp", "London", "GB")).party
private val txID = digestService.randomHash()
private val requestSignature = NotarisationRequestSignature(DigitalSignature.WithKey(NullKeys.NullPublicKey, ByteArray(32)), 0)
@ -112,11 +118,7 @@ class UniquenessProviderTests(
val timeWindow = TimeWindow.between(
Clock.systemUTC().instant().plus(30.minutes),
Clock.systemUTC().instant().plus(60.minutes))
val result = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, timeWindow).get()
assert(result is UniquenessProvider.Result.Failure)
val error = (result as UniquenessProvider.Result.Failure).error as NotaryError.TimeWindowInvalid
assertEquals(timeWindow, error.txTimeWindow)
expectInvalidTimeWindow(emptyList(), firstTxId, timeWindow)
// Once time window behaviour has changed, we should add an additional test case here to check
// that retry within time window still fails. We can't do that now because currently it will
@ -124,51 +126,34 @@ class UniquenessProviderTests(
// Retry still fails after advancing past time window
testClock.advanceBy(90.minutes)
val result2 = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, timeWindow).get()
assert(result2 is UniquenessProvider.Result.Failure)
val error2 = (result2 as UniquenessProvider.Result.Failure).error as NotaryError.TimeWindowInvalid
assertEquals(timeWindow, error2.txTimeWindow)
expectInvalidTimeWindow(emptyList(), firstTxId, timeWindow)
}
@Test(timeout=300_000)
fun `commits transaction within time window`() {
val firstTxId = digestService.randomHash()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val result = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, timeWindow).get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(emptyList(), firstTxId, timeWindow)
// Retry is successful whilst still within time window
testClock.advanceBy(10.minutes)
val result2 = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, timeWindow).get()
assert(result2 is UniquenessProvider.Result.Success)
expectCommitSuccess(emptyList(), firstTxId, timeWindow)
// Retry is successful after time window has expired
testClock.advanceBy(80.minutes)
val result3 = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, timeWindow).get()
assert(result3 is UniquenessProvider.Result.Success)
expectCommitSuccess(emptyList(), firstTxId, timeWindow)
}
@Test(timeout=300_000)
fun `rejects transaction after time window has expired`() {
val firstTxId = digestService.randomHash()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().minus(30.minutes))
val result = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, timeWindow).get()
assert(result is UniquenessProvider.Result.Failure)
val error = (result as UniquenessProvider.Result.Failure).error as NotaryError.TimeWindowInvalid
assertEquals(timeWindow, error.txTimeWindow)
expectInvalidTimeWindow(emptyList(), firstTxId, timeWindow)
// Retry still fails at a later time
testClock.advanceBy(10.minutes)
val result2 = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, timeWindow).get()
assert(result2 is UniquenessProvider.Result.Failure)
val error2 = (result2 as UniquenessProvider.Result.Failure).error as NotaryError.TimeWindowInvalid
assertEquals(timeWindow, error2.txTimeWindow)
expectInvalidTimeWindow(emptyList(), firstTxId, timeWindow)
}
@Test(timeout=300_000)
@ -178,56 +163,42 @@ class UniquenessProviderTests(
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val invalidTimeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().minus(30.minutes))
val validFuture1 = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, timeWindow)
val validFuture2 = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, timeWindow)
val invalidFuture1 = uniquenessProvider.commit(
emptyList(), secondTxId, identity, requestSignature, invalidTimeWindow)
val invalidFuture2 = uniquenessProvider.commit(
emptyList(), secondTxId, identity, requestSignature, invalidTimeWindow)
val validFuture1 = commit(emptyList(), firstTxId, timeWindow)
val validFuture2 = commit(emptyList(), firstTxId, timeWindow)
val invalidFuture1 = commit(emptyList(), secondTxId, invalidTimeWindow)
val invalidFuture2 = commit(emptyList(), secondTxId, invalidTimeWindow)
// Ensure that transactions are processed correctly and duplicates get the same responses to original
assert(validFuture1.get() is UniquenessProvider.Result.Success)
assert(validFuture2.get() is UniquenessProvider.Result.Success)
assert(invalidFuture1.get() is UniquenessProvider.Result.Failure)
assert(invalidFuture2.get() is UniquenessProvider.Result.Failure)
assertThat(validFuture1.get()).isInstanceOf(Result.Success::class.java)
assertThat(validFuture2.get()).isInstanceOf(Result.Success::class.java)
assertThat(invalidFuture1.get()).isInstanceOf(Result.Failure::class.java)
assertThat(invalidFuture2.get()).isInstanceOf(Result.Failure::class.java)
}
/* Group B: only reference states */
@Test(timeout=300_000)
fun `commits transaction with unused reference states`() {
fun `commits transaction with unused reference states`() {
val firstTxId = digestService.randomHash()
val referenceState = generateStateRef()
val result = uniquenessProvider.commit(emptyList(), firstTxId, identity, requestSignature, references = listOf(referenceState))
.get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(emptyList(), firstTxId, references = listOf(referenceState))
// Idempotency: can re-notarise successfully.
val result2 = uniquenessProvider.commit(emptyList(), firstTxId, identity, requestSignature, references = listOf(referenceState))
.get()
assert(result2 is UniquenessProvider.Result.Success)
expectCommitSuccess(emptyList(), firstTxId, references = listOf(referenceState))
}
@Test(timeout=300_000)
fun `rejects transaction with previously used reference states`() {
fun `rejects transaction with previously used reference states`() {
val firstTxId = digestService.randomHash()
val referenceState = generateStateRef()
val result = uniquenessProvider.commit(listOf(referenceState), firstTxId, identity, requestSignature, references = emptyList())
.get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(referenceState), firstTxId, references = emptyList())
// Transaction referencing the spent sate fails.
val secondTxId = digestService.randomHash()
val result2 = uniquenessProvider.commit(emptyList(), secondTxId, identity, requestSignature, references = listOf(referenceState))
.get()
val error = (result2 as UniquenessProvider.Result.Failure).error as NotaryError.Conflict
val conflictCause = error.consumedStates[referenceState]!!
assertEquals(conflictCause.hashOfTransactionId, firstTxId.reHash(), "${conflictCause.hashOfTransactionId} != ${firstTxId.reHash()}")
assertEquals(StateConsumptionDetails.ConsumedStateType.REFERENCE_INPUT_STATE, conflictCause.type)
val consumedStates = expectConflict(emptyList(), secondTxId, references = listOf(referenceState))
assertThat(consumedStates[referenceState]).isEqualTo(StateConsumptionDetails(firstTxId.reHash(), REFERENCE_INPUT_STATE))
}
@Test(timeout=300_000)
@ -235,23 +206,14 @@ class UniquenessProviderTests(
val firstTxId = digestService.randomHash()
val referenceState = generateStateRef()
val result = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, references = listOf(referenceState))
.get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(emptyList(), firstTxId, references = listOf(referenceState))
// Spend reference state
val secondTxId = digestService.randomHash()
val result2 = uniquenessProvider.commit(
listOf(referenceState), secondTxId, identity, requestSignature, references = emptyList())
.get()
assert(result2 is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(referenceState), secondTxId, references = emptyList())
// Retry referencing the now spent state still succeeds
val result3 = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, references = listOf(referenceState))
.get()
assert(result3 is UniquenessProvider.Result.Success)
expectCommitSuccess(emptyList(), firstTxId, references = listOf(referenceState))
}
@Test(timeout=300_000)
@ -260,128 +222,97 @@ class UniquenessProviderTests(
val secondTxId = digestService.randomHash()
val referenceState = generateStateRef()
val validFuture3 = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, references = listOf(referenceState))
val validFuture4 = uniquenessProvider.commit(
emptyList(), firstTxId, identity, requestSignature, references = listOf(referenceState))
val validFuture1 = uniquenessProvider.commit(
emptyList(), secondTxId, identity, requestSignature, references = listOf(referenceState))
val validFuture2 = uniquenessProvider.commit(
emptyList(), secondTxId, identity, requestSignature, references = listOf(referenceState))
val validFuture3 = commit(emptyList(), firstTxId, references = listOf(referenceState))
val validFuture4 = commit(emptyList(), firstTxId, references = listOf(referenceState))
val validFuture1 = commit(emptyList(), secondTxId, references = listOf(referenceState))
val validFuture2 = commit(emptyList(), secondTxId, references = listOf(referenceState))
// Ensure that transactions are processed correctly and duplicates get the same responses to original
assert(validFuture1.get() is UniquenessProvider.Result.Success)
assert(validFuture2.get() is UniquenessProvider.Result.Success)
assert(validFuture3.get() is UniquenessProvider.Result.Success)
assert(validFuture4.get() is UniquenessProvider.Result.Success)
assertThat(validFuture1.get()).isInstanceOf(Result.Success::class.java)
assertThat(validFuture2.get()).isInstanceOf(Result.Success::class.java)
assertThat(validFuture3.get()).isInstanceOf(Result.Success::class.java)
assertThat(validFuture4.get()).isInstanceOf(Result.Success::class.java)
}
/* Group C: reference states & time window */
@Test(timeout=300_000)
fun `commits transaction with unused reference states and valid time window`() {
fun `commits transaction with unused reference states and valid time window`() {
val firstTxId = digestService.randomHash()
val referenceState = generateStateRef()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val result = uniquenessProvider.commit(emptyList(), firstTxId, identity, requestSignature, timeWindow, references = listOf(referenceState))
.get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(emptyList(), firstTxId, timeWindow, references = listOf(referenceState))
// The reference state gets consumed.
val result2 = uniquenessProvider.commit(listOf(referenceState), digestService.randomHash(), identity, requestSignature, timeWindow)
.get()
assert(result2 is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(referenceState), digestService.randomHash(), timeWindow)
// Idempotency: can re-notarise successfully.
testClock.advanceBy(90.minutes)
val result3 = uniquenessProvider.commit(emptyList(), firstTxId, identity, requestSignature, timeWindow, references = listOf(referenceState))
.get()
assert(result3 is UniquenessProvider.Result.Success)
expectCommitSuccess(emptyList(), firstTxId, timeWindow, references = listOf(referenceState))
}
@Test(timeout=300_000)
fun `rejects transaction with unused reference states and invalid time window`() {
fun `rejects transaction with unused reference states and invalid time window`() {
val firstTxId = digestService.randomHash()
val referenceState = generateStateRef()
val invalidTimeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().minus(30.minutes))
val result = uniquenessProvider.commit(emptyList(), firstTxId, identity, requestSignature, invalidTimeWindow, references = listOf(referenceState))
.get()
val error = (result as UniquenessProvider.Result.Failure).error as NotaryError.TimeWindowInvalid
assertEquals(invalidTimeWindow, error.txTimeWindow)
expectInvalidTimeWindow(emptyList(), firstTxId, invalidTimeWindow, references = listOf(referenceState))
}
@Test(timeout=300_000)
fun `rejects transaction with previously used reference states and valid time window`() {
fun `rejects transaction with previously used reference states and valid time window`() {
val firstTxId = digestService.randomHash()
val referenceState = generateStateRef()
val result = uniquenessProvider.commit(listOf(referenceState), firstTxId, identity, requestSignature, references = emptyList())
.get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(referenceState), firstTxId, references = emptyList())
// Transaction referencing the spent sate fails.
val secondTxId = digestService.randomHash()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val result2 = uniquenessProvider.commit(emptyList(), secondTxId, identity, requestSignature, timeWindow, references = listOf(referenceState))
.get()
val error = (result2 as UniquenessProvider.Result.Failure).error as NotaryError.Conflict
val conflictCause = error.consumedStates[referenceState]!!
assertEquals(conflictCause.hashOfTransactionId, firstTxId.reHash())
assertEquals(StateConsumptionDetails.ConsumedStateType.REFERENCE_INPUT_STATE, conflictCause.type)
val consumedStates = expectConflict(emptyList(), secondTxId, timeWindow, references = listOf(referenceState))
assertThat(consumedStates[referenceState]).isEqualTo(StateConsumptionDetails(firstTxId.reHash(), REFERENCE_INPUT_STATE))
}
@Test(timeout=300_000)
fun `rejects transaction with previously used reference states and invalid time window`() {
fun `rejects transaction with previously used reference states and invalid time window`() {
val firstTxId = digestService.randomHash()
val referenceState = generateStateRef()
val result = uniquenessProvider.commit(listOf(referenceState), firstTxId, identity, requestSignature, references = emptyList())
.get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(referenceState), firstTxId, references = emptyList())
// Transaction referencing the spent sate fails.
val secondTxId = digestService.randomHash()
val invalidTimeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().minus(30.minutes))
val result2 = uniquenessProvider.commit(emptyList(), secondTxId, identity, requestSignature, invalidTimeWindow, references = listOf(referenceState))
.get()
val error = (result2 as UniquenessProvider.Result.Failure).error as NotaryError.Conflict
val conflictCause = error.consumedStates[referenceState]!!
assertEquals(conflictCause.hashOfTransactionId, firstTxId.reHash())
assertEquals(StateConsumptionDetails.ConsumedStateType.REFERENCE_INPUT_STATE, conflictCause.type)
val consumedStates = expectConflict(emptyList(), secondTxId, invalidTimeWindow, references = listOf(referenceState))
assertThat(consumedStates[referenceState]).isEqualTo(StateConsumptionDetails(firstTxId.reHash(), REFERENCE_INPUT_STATE))
}
/* Group D: only input states */
@Test(timeout=300_000)
fun `commits transaction with unused inputs`() {
fun `commits transaction with unused inputs`() {
val inputState = generateStateRef()
val result = uniquenessProvider.commit(listOf(inputState), txID, identity, requestSignature).get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(inputState), txID)
// Idempotency: can re-notarise successfully.
val result2 = uniquenessProvider.commit(listOf(inputState), txID, identity, requestSignature).get()
assert(result2 is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(inputState), txID)
}
@Test(timeout=300_000)
fun `rejects transaction with previously used inputs`() {
fun `rejects transaction with previously used inputs`() {
val inputState = generateStateRef()
val inputs = listOf(inputState)
val firstTxId = txID
val result = uniquenessProvider.commit(inputs, firstTxId, identity, requestSignature).get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(inputs, firstTxId)
val secondTxId = digestService.randomHash()
val response: UniquenessProvider.Result = uniquenessProvider.commit(inputs, secondTxId, identity, requestSignature).get()
val error = (response as UniquenessProvider.Result.Failure).error as NotaryError.Conflict
val conflictCause = error.consumedStates[inputState]!!
assertEquals(firstTxId.reHash(), conflictCause.hashOfTransactionId)
val consumedStates = expectConflict(inputs, secondTxId)
assertThat(consumedStates[inputState]).isEqualTo(StateConsumptionDetails(firstTxId.reHash(), INPUT_STATE))
}
@Test(timeout=300_000)
@ -390,104 +321,82 @@ class UniquenessProviderTests(
val secondTxId = digestService.randomHash()
val inputState = generateStateRef()
val validFuture1 = uniquenessProvider.commit(
listOf(inputState), firstTxId, identity, requestSignature)
val validFuture2 = uniquenessProvider.commit(
listOf(inputState), firstTxId, identity, requestSignature)
val invalidFuture1 = uniquenessProvider.commit(
listOf(inputState), secondTxId, identity, requestSignature)
val invalidFuture2 = uniquenessProvider.commit(
listOf(inputState), secondTxId, identity, requestSignature)
val validFuture1 = commit(listOf(inputState), firstTxId)
val validFuture2 = commit(listOf(inputState), firstTxId)
val invalidFuture1 = commit(listOf(inputState), secondTxId)
val invalidFuture2 = commit(listOf(inputState), secondTxId)
// Ensure that transactions are processed correctly and duplicates get the same responses to original
assert(validFuture1.get() is UniquenessProvider.Result.Success)
assert(validFuture2.get() is UniquenessProvider.Result.Success)
assert(invalidFuture1.get() is UniquenessProvider.Result.Failure)
assert(invalidFuture2.get() is UniquenessProvider.Result.Failure)
assertThat(validFuture1.get()).isInstanceOf(Result.Success::class.java)
assertThat(validFuture2.get()).isInstanceOf(Result.Success::class.java)
assertThat(invalidFuture1.get()).isInstanceOf(Result.Failure::class.java)
assertThat(invalidFuture2.get()).isInstanceOf(Result.Failure::class.java)
}
/* Group E: input states & time window */
@Test(timeout=300_000)
fun `commits transaction with unused inputs and valid time window`() {
fun `commits transaction with unused inputs and valid time window`() {
val inputState = generateStateRef()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val result = uniquenessProvider.commit(listOf(inputState), txID, identity, requestSignature, timeWindow).get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(inputState), txID, timeWindow)
// Idempotency: can re-notarise successfully later.
testClock.advanceBy(90.minutes)
val result2 = uniquenessProvider.commit(listOf(inputState), txID, identity, requestSignature, timeWindow).get()
assert(result2 is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(inputState), txID, timeWindow)
}
@Test(timeout=300_000)
fun `rejects transaction with unused inputs and invalid time window`() {
fun `rejects transaction with unused inputs and invalid time window`() {
val inputState = generateStateRef()
val invalidTimeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().minus(30.minutes))
val result = uniquenessProvider.commit(listOf(inputState), txID, identity, requestSignature, invalidTimeWindow).get()
val error = (result as UniquenessProvider.Result.Failure).error as NotaryError.TimeWindowInvalid
assertEquals(invalidTimeWindow, error.txTimeWindow)
expectInvalidTimeWindow(listOf(inputState), txID, invalidTimeWindow)
}
@Test(timeout=300_000)
fun `rejects transaction with previously used inputs and valid time window`() {
fun `rejects transaction with previously used inputs and valid time window`() {
val inputState = generateStateRef()
val inputs = listOf(inputState)
val firstTxId = txID
val result = uniquenessProvider.commit(inputs, firstTxId, identity, requestSignature).get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(inputs, firstTxId)
val secondTxId = digestService.randomHash()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val response: UniquenessProvider.Result = uniquenessProvider.commit(inputs, secondTxId, identity, requestSignature, timeWindow)
.get()
val error = (response as UniquenessProvider.Result.Failure).error as NotaryError.Conflict
val conflictCause = error.consumedStates[inputState]!!
assertEquals(firstTxId.reHash(), conflictCause.hashOfTransactionId)
val consumedStates = expectConflict(inputs, secondTxId, timeWindow)
assertThat(consumedStates[inputState]).isEqualTo(StateConsumptionDetails(firstTxId.reHash(), INPUT_STATE))
}
@Test(timeout=300_000)
fun `rejects transaction with previously used inputs and invalid time window`() {
fun `rejects transaction with previously used inputs and invalid time window`() {
val inputState = generateStateRef()
val inputs = listOf(inputState)
val firstTxId = txID
val result = uniquenessProvider.commit(inputs, firstTxId, identity, requestSignature).get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(inputs, firstTxId)
val secondTxId = digestService.randomHash()
val invalidTimeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().minus(30.minutes))
val response: UniquenessProvider.Result = uniquenessProvider.commit(inputs, secondTxId, identity, requestSignature, invalidTimeWindow)
.get()
val error = (response as UniquenessProvider.Result.Failure).error as NotaryError.Conflict
val conflictCause = error.consumedStates[inputState]!!
assertEquals(firstTxId.reHash(), conflictCause.hashOfTransactionId)
val consumedStates = expectConflict(inputs, secondTxId, invalidTimeWindow)
assertThat(consumedStates[inputState]).isEqualTo(StateConsumptionDetails(firstTxId.reHash(), INPUT_STATE))
}
/* Group F: input & reference states */
@Test(timeout=300_000)
fun `commits transaction with unused input & reference states`() {
fun `commits transaction with unused input & reference states`() {
val firstTxId = digestService.randomHash()
val inputState = generateStateRef()
val referenceState = generateStateRef()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val result = uniquenessProvider.commit(listOf(inputState), firstTxId, identity, requestSignature, timeWindow, references = listOf(referenceState))
.get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(inputState), firstTxId, timeWindow, references = listOf(referenceState))
// Idempotency: can re-notarise successfully.
testClock.advanceBy(90.minutes)
val result2 = uniquenessProvider.commit(listOf(inputState), firstTxId, identity, requestSignature, timeWindow, references = listOf(referenceState))
.get()
assert(result2 is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(inputState), firstTxId, timeWindow, references = listOf(referenceState))
}
@Test(timeout=300_000)
@ -497,69 +406,46 @@ class UniquenessProviderTests(
val referenceState = generateStateRef()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val result = uniquenessProvider.commit(
listOf(inputState), firstTxId, identity, requestSignature, timeWindow, references = listOf(referenceState))
.get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(inputState), firstTxId, timeWindow, references = listOf(referenceState))
// Spend the reference state.
val referenceSpend = uniquenessProvider.commit(
listOf(referenceState),
digestService.randomHash(),
identity,
requestSignature,
timeWindow,
emptyList()).get()
assert(referenceSpend is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(referenceState), digestService.randomHash(), timeWindow)
// Idempotency: can re-notarise successfully
testClock.advanceBy(90.minutes)
val result2 = uniquenessProvider.commit(
listOf(inputState), firstTxId, identity, requestSignature, timeWindow, references = listOf(referenceState))
.get()
val result = commit(listOf(inputState), firstTxId, timeWindow, references = listOf(referenceState)).get()
// Known failure - this should return success. Will be fixed in a future release.
assert(result2 is UniquenessProvider.Result.Failure)
assertThat(result).isInstanceOf(Result.Failure::class.java)
}
@Test(timeout=300_000)
fun `rejects transaction with unused reference states and used input states`() {
fun `rejects transaction with unused reference states and used input states`() {
val firstTxId = digestService.randomHash()
val inputState = generateStateRef()
val referenceState = generateStateRef()
val result = uniquenessProvider.commit(listOf(inputState), firstTxId, identity, requestSignature, references = emptyList()).get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(inputState), firstTxId, references = emptyList())
// Transaction referencing the spent sate fails.
val secondTxId = digestService.randomHash()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val result2 = uniquenessProvider.commit(listOf(inputState), secondTxId, identity, requestSignature, timeWindow, references = listOf(referenceState))
.get()
val error = (result2 as UniquenessProvider.Result.Failure).error as NotaryError.Conflict
val conflictCause = error.consumedStates[inputState]!!
assertEquals(conflictCause.hashOfTransactionId, firstTxId.reHash())
assertEquals(StateConsumptionDetails.ConsumedStateType.INPUT_STATE, conflictCause.type)
val consumedStates = expectConflict(listOf(inputState), secondTxId, timeWindow, references = listOf(referenceState))
assertThat(consumedStates[inputState]).isEqualTo(StateConsumptionDetails(firstTxId.reHash(), INPUT_STATE))
}
@Test(timeout=300_000)
fun `rejects transaction with used reference states and unused input states`() {
fun `rejects transaction with used reference states and unused input states`() {
val firstTxId = digestService.randomHash()
val inputState = generateStateRef()
val referenceState = generateStateRef()
val result = uniquenessProvider.commit(listOf(referenceState), firstTxId, identity, requestSignature, references = emptyList())
.get()
assert(result is UniquenessProvider.Result.Success)
expectCommitSuccess(listOf(referenceState), firstTxId, references = emptyList())
// Transaction referencing the spent sate fails.
val secondTxId = digestService.randomHash()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
val result2 = uniquenessProvider.commit(listOf(inputState), secondTxId, identity, requestSignature, timeWindow, references = listOf(referenceState))
.get()
val error = (result2 as UniquenessProvider.Result.Failure).error as NotaryError.Conflict
val conflictCause = error.consumedStates[referenceState]!!
assertEquals(conflictCause.hashOfTransactionId, firstTxId.reHash())
assertEquals(StateConsumptionDetails.ConsumedStateType.REFERENCE_INPUT_STATE, conflictCause.type)
val consumedStates = expectConflict(listOf(inputState), secondTxId, timeWindow, references = listOf(referenceState))
assertThat(consumedStates[referenceState]).isEqualTo(StateConsumptionDetails(firstTxId.reHash(), REFERENCE_INPUT_STATE))
}
@Test(timeout=300_000)
@ -569,41 +455,93 @@ class UniquenessProviderTests(
val referenceState = generateStateRef()
// Ensure batch contains duplicates
val validFuture1 = uniquenessProvider.commit(
emptyList(), secondTxId, identity, requestSignature, references = listOf(referenceState))
val validFuture2 = uniquenessProvider.commit(
emptyList(), secondTxId, identity, requestSignature, references = listOf(referenceState))
val validFuture3 = uniquenessProvider.commit(
listOf(referenceState), firstTxId, identity, requestSignature)
val validFuture1 = commit(emptyList(), secondTxId, references = listOf(referenceState))
val validFuture2 = commit(emptyList(), secondTxId, references = listOf(referenceState))
val validFuture3 = commit(listOf(referenceState), firstTxId)
// Attempt to use the reference state after it has been consumed
val validFuture4 = uniquenessProvider.commit(
emptyList(), digestService.randomHash(), identity, requestSignature, references = listOf(referenceState))
val validFuture4 = commit(emptyList(), digestService.randomHash(), references = listOf(referenceState))
// Ensure that transactions are processed correctly and duplicates get the same responses to original
assert(validFuture1.get() is UniquenessProvider.Result.Success)
assert(validFuture2.get() is UniquenessProvider.Result.Success)
assert(validFuture3.get() is UniquenessProvider.Result.Success)
assert(validFuture4.get() is UniquenessProvider.Result.Failure)
assertThat(validFuture1.get()).isInstanceOf(Result.Success::class.java)
assertThat(validFuture2.get()).isInstanceOf(Result.Success::class.java)
assertThat(validFuture3.get()).isInstanceOf(Result.Success::class.java)
assertThat(validFuture4.get()).isInstanceOf(Result.Failure::class.java)
}
/* Group G: input, reference states and time window covered by previous tests. */
/* Transaction signing tests. */
@Test(timeout=300_000)
fun `signs transactions correctly`() {
fun `signs transactions correctly`() {
(1..10).map {
val inputState1 = generateStateRef()
val firstTxId = digestService.randomHash()
val timeWindow = TimeWindow.untilOnly(Clock.systemUTC().instant().plus(30.minutes))
Pair(firstTxId, uniquenessProvider.commit(listOf(inputState1), firstTxId, identity, requestSignature, timeWindow))
}.forEach {
val result = it.second.get()
assert(result is UniquenessProvider.Result.Success)
val signature = (result as UniquenessProvider.Result.Success).signature
assert(signature.verify(it.first))
Pair(firstTxId, commit(listOf(inputState1), firstTxId, timeWindow))
}.forEach { (txId, future) ->
val result = future.get()
assertThat(result).isInstanceOf(Result.Success::class.java)
val signature = (result as Result.Success).signature
signature.verify(txId)
}
}
private fun commit(
states: List<StateRef>,
txId: SecureHash,
timeWindow: TimeWindow? = null,
references: List<StateRef> = emptyList()
): CordaFuture<Result> {
return uniquenessProvider.commit(states, txId, identity, requestSignature, timeWindow, references)
}
private fun expectCommitSuccess(
states: List<StateRef>,
txId: SecureHash,
timeWindow: TimeWindow? = null,
references: List<StateRef> = emptyList()
) {
val result = commit(states, txId, timeWindow, references).get()
assertThat(result).isInstanceOf(Result.Success::class.java)
result as Result.Success
result.signature.verify(txId)
}
private fun expectCommitFailure(
states: List<StateRef>,
txId: SecureHash,
timeWindow: TimeWindow? = null,
references: List<StateRef> = emptyList()
): NotaryError {
val result = commit(states, txId, timeWindow, references).get()
assertThat(result).isInstanceOf(Result.Failure::class.java)
return (result as Result.Failure).error
}
private fun expectInvalidTimeWindow(
states: List<StateRef>,
txId: SecureHash,
timeWindow: TimeWindow,
references: List<StateRef> = emptyList()
) {
val notaryError = expectCommitFailure(states, txId, timeWindow, references)
assertThat(notaryError).isInstanceOf(NotaryError.TimeWindowInvalid::class.java)
assertThat((notaryError as NotaryError.TimeWindowInvalid).txTimeWindow).isEqualTo(timeWindow)
}
private fun expectConflict(
states: List<StateRef>,
txId: SecureHash,
timeWindow: TimeWindow? = null,
references: List<StateRef> = emptyList()
): Map<StateRef, StateConsumptionDetails> {
val notaryError = expectCommitFailure(states, txId, timeWindow, references)
assertThat(notaryError).isInstanceOf(NotaryError.Conflict::class.java)
val conflict = notaryError as NotaryError.Conflict
assertThat(conflict.txId).isEqualTo(txId)
return conflict.consumedStates
}
}
interface UniquenessProviderFactory {
@ -644,7 +582,7 @@ class RaftUniquenessProviderFactory : UniquenessProviderFactory {
}
class JPAUniquenessProviderFactory(val digestService: DigestService) : UniquenessProviderFactory {
class JPAUniquenessProviderFactory(private val digestService: DigestService) : UniquenessProviderFactory {
private var database: CordaPersistence? = null
private val notaryConfig = JPANotaryConfiguration(maxInputStates = 10)
private val notaryWorkerName = CordaX500Name.parse("CN=NotaryWorker, O=Corda, L=London, C=GB")

View File

@ -25,6 +25,7 @@ dependencies {
testImplementation "junit:junit:$junit_version"
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockito_kotlin_version"
testImplementation "org.mockito:mockito-core:$mockito_version"
testImplementation "org.assertj:assertj-core:$assertj_version"
}
processResources {

View File

@ -10,6 +10,7 @@ import net.corda.nodeapi.internal.network.PackageOwner
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.internal.JarSignatureTestUtils.generateKey
import net.corda.testing.core.internal.JarSignatureTestUtils.getPublicKey
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.AfterClass
import org.junit.Before
@ -251,7 +252,7 @@ class NetworkBootstrapperRunnerTests {
runner.networkParametersFile = conf
val exitCode = runner.runProgram()
val output = errContent.toString()
assert(output.contains("Error parsing packageOwnership: Package namespaces must not overlap"))
assertThat(output).contains("Error parsing packageOwnership: Package namespaces must not overlap")
assertEquals(1, exitCode)
}
@ -260,6 +261,6 @@ class NetworkBootstrapperRunnerTests {
val (runner, _) = getRunner()
runner.networkParametersFile = dirAlice / "filename-that-doesnt-exist"
val exception = assertFailsWith<FileNotFoundException> { runner.runProgram() }
assert(exception.message!!.startsWith("Unable to find specified network parameters config file at"))
assertThat(exception.message).startsWith("Unable to find specified network parameters config file at")
}
}