[CORDA-2278]: KillFlow RPC operation is not releasing soft locks. (#4332)

* [CORDA-2278]: Seems to be working. Leaving the test to ensure no future regressions.

* [CORDA-2278]: Seems to be working. Leaving the test to ensure no future regressions.

* [CORDA-2278]: Seems to be working. Leaving the test to ensure no future regressions.

* [CORDA-2278]: Seems to be working. Leaving the test to ensure no future regressions.
This commit is contained in:
Michele Sollecito 2018-11-30 13:10:19 +00:00 committed by GitHub
parent 3444d6c075
commit a9ff8a0818
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 8 deletions

View File

@ -8,6 +8,7 @@ import net.corda.core.context.InvocationContext
import net.corda.core.contracts.Amount
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.Issued
import net.corda.core.contracts.StateRef
import net.corda.core.crypto.isFulfilledBy
import net.corda.core.crypto.keys
import net.corda.core.flows.FlowLogic
@ -16,12 +17,14 @@ import net.corda.core.flows.StateMachineRunId
import net.corda.core.identity.Party
import net.corda.core.internal.uncheckedCast
import net.corda.core.messaging.*
import net.corda.core.node.services.StatesNotAvailableException
import net.corda.core.node.services.Vault
import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.AttachmentQueryCriteria
import net.corda.core.node.services.vault.ColumnPredicate
import net.corda.core.node.services.vault.EqualityComparisonOperator
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.NonEmptySet
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.unwrap
@ -32,6 +35,7 @@ import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.flows.CashPaymentFlow
import net.corda.node.internal.security.AuthorizingSubject
import net.corda.node.internal.security.RPCSecurityManagerImpl
import net.corda.node.services.Permissions.Companion.all
import net.corda.node.services.Permissions.Companion.invokeRpc
import net.corda.node.services.Permissions.Companion.startFlow
import net.corda.node.services.messaging.CURRENT_RPC_CONTEXT
@ -56,6 +60,7 @@ import org.junit.Before
import org.junit.Test
import rx.Observable
import java.io.ByteArrayOutputStream
import java.time.Duration
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNull
@ -385,6 +390,39 @@ class CordaRPCOpsImplTest {
}
}
@Test
fun `killing a flow releases soft lock`() {
withPermissions(all()) {
val issuerRef = OpaqueBytes("BankOfMars".toByteArray())
val cash = rpc.startFlow(::CashIssueFlow, 10.DOLLARS, issuerRef, notary).returnValue.getOrThrow().stx.tx.outRefsOfType<Cash.State>().single()
val flow = rpc.startFlow(::SoftLock, cash.ref, Duration.ofMinutes(5))
var locked = false
while (!locked) {
try {
rpc.startFlow(::SoftLock, cash.ref, Duration.ofSeconds(1)).returnValue.getOrThrow()
} catch (e: StatesNotAvailableException) {
locked = true
}
}
val killed = rpc.killFlow(flow.id)
assertThat(killed).isTrue()
assertThatCode { rpc.startFlow(::SoftLock, cash.ref, Duration.ofSeconds(1)).returnValue.getOrThrow() }.doesNotThrowAnyException()
}
}
@StartableByRPC
class SoftLock(private val stateRef: StateRef, private val duration: Duration) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
logger.info("Soft locking state with hash $stateRef...")
serviceHub.vaultService.softLockReserve(runId.uuid, NonEmptySet.of(stateRef))
sleep(duration)
}
}
@Test
fun `kill a nonexistent flow through RPC`() {
withPermissions(invokeRpc(CordaRPCOps::killFlow)) {

View File

@ -5,6 +5,14 @@ apply plugin: 'com.jfrog.artifactory'
dependencies {
compile project(':core')
compile project(':node-api')
// Unit testing helpers.
compile "junit:junit:$junit_version"
compile 'org.hamcrest:hamcrest-library:1.3'
compile "com.nhaarman:mockito-kotlin:$mockito_kotlin_version"
compile "org.mockito:mockito-core:$mockito_version"
compile "org.assertj:assertj-core:$assertj_version"
compile "com.natpryce:hamkrest:$hamkrest_version"
}
jar {

View File

@ -1,5 +1,7 @@
package net.corda.testing.common.internal
import org.assertj.core.api.AbstractThrowableAssert
inline fun checkNotOnClasspath(className: String, errorMessage: () -> Any) {
try {
Class.forName(className)
@ -8,3 +10,5 @@ inline fun checkNotOnClasspath(className: String, errorMessage: () -> Any) {
// If the class can't be found then we're good!
}
}
inline fun <reified TYPE : Throwable> AbstractThrowableAssert<*, *>.isInstanceOf(): AbstractThrowableAssert<*, *> = isInstanceOf(TYPE::class.java)

View File

@ -21,14 +21,6 @@ dependencies {
compile "com.google.guava:guava:$guava_version"
// Unit testing helpers.
compile "junit:junit:$junit_version"
compile 'org.hamcrest:hamcrest-library:1.3'
compile "com.nhaarman:mockito-kotlin:$mockito_kotlin_version"
compile "org.mockito:mockito-core:$mockito_version"
compile "org.assertj:assertj-core:$assertj_version"
compile "com.natpryce:hamkrest:$hamkrest_version"
// Guava: Google test library (collections test suite)
compile "com.google.guava:guava-testlib:$guava_version"