mirror of
https://github.com/corda/corda.git
synced 2025-06-22 17:09:00 +00:00
Merge commit 'e879de7' into chrisr3-os-merge
This commit is contained in:
@ -15,6 +15,7 @@ import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
|
||||
// DOCSTART FlowAsyncOperation
|
||||
/**
|
||||
* Interface for arbitrary operations that can be invoked in a flow asynchronously - the flow will suspend until the
|
||||
* operation completes. Operation parameters are expected to be injected via constructor.
|
||||
@ -24,10 +25,13 @@ interface FlowAsyncOperation<R : Any> {
|
||||
/** Performs the operation in a non-blocking fashion. */
|
||||
fun execute(): CordaFuture<R>
|
||||
}
|
||||
// DOCEND FlowAsyncOperation
|
||||
|
||||
// DOCSTART executeAsync
|
||||
/** Executes the specified [operation] and suspends until operation completion. */
|
||||
@Suspendable
|
||||
fun <T, R : Any> FlowLogic<T>.executeAsync(operation: FlowAsyncOperation<R>, maySkipCheckpoint: Boolean = false): R {
|
||||
val request = FlowIORequest.ExecuteAsyncOperation(operation)
|
||||
return stateMachine.suspend(request, maySkipCheckpoint)
|
||||
}
|
||||
// DOCEND executeAsync
|
||||
|
@ -19,6 +19,7 @@ import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.NonEmptySet
|
||||
import java.time.Instant
|
||||
|
||||
// DOCSTART FlowIORequest
|
||||
/**
|
||||
* A [FlowIORequest] represents an IO request of a flow when it suspends. It is persisted in checkpoints.
|
||||
*/
|
||||
@ -103,3 +104,4 @@ sealed class FlowIORequest<out R : Any> {
|
||||
// TODO: consider using an empty FlowAsyncOperation instead
|
||||
object ForceCheckpoint : FlowIORequest<Unit>()
|
||||
}
|
||||
// DOCSEND FlowIORequest
|
||||
|
@ -15,6 +15,8 @@ import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertNull
|
||||
|
||||
import java.lang.Character.MIN_VALUE as NULLCHAR
|
||||
|
||||
class CordaX500NameTest {
|
||||
@Test
|
||||
fun `service name with organisational unit`() {
|
||||
@ -70,17 +72,128 @@ class CordaX500NameTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rejects name with wrong organisation name format`() {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=B, L=New York, C=US, OU=Org Unit, CN=Service Name")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rejects name with unsupported attribute`() {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=Bank A, L=New York, C=US, SN=blah")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rejects organisation (but not other attributes) with non-latin letters`() {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=Bཛྷa, L=New York, C=DE, OU=Org Unit, CN=Service Name")
|
||||
}
|
||||
// doesn't throw
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("Bཛྷa")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `organisation (but not other attributes) must have at least two letters`() {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=B, L=New York, C=DE, OU=Org Unit, CN=Service Name")
|
||||
}
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=, L=New York, C=DE, OU=Org Unit, CN=Service Name")
|
||||
}
|
||||
// doesn't throw
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("B")
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `accepts attributes starting with lower case letter`() {
|
||||
CordaX500Name.parse("O=bank A, L=New York, C=DE, OU=Org Unit, CN=Service Name")
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("bank")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `accepts attributes starting with numeric character`() {
|
||||
CordaX500Name.parse("O=8Bank A, L=New York, C=DE, OU=Org Unit, CN=Service Name")
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("8bank")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `accepts attributes with leading whitespace`() {
|
||||
CordaX500Name.parse("O= VALID, L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
validateLocalityAndOrganisationalUnitAndCommonName(" VALID")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `accepts attributes with trailing whitespace`() {
|
||||
CordaX500Name.parse("O=VALID , L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("VALID ")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rejects attributes with comma`() {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=IN,VALID, L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
}
|
||||
checkLocalityAndOrganisationalUnitAndCommonNameReject("IN,VALID")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `accepts org with equals sign`() {
|
||||
CordaX500Name.parse("O=IN=VALID, L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `accepts organisation with dollar sign`() {
|
||||
CordaX500Name.parse("O=VA\$LID, L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("VA\$LID")
|
||||
}
|
||||
@Test
|
||||
fun `rejects attributes with double quotation mark`() {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=IN\"VALID, L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
}
|
||||
checkLocalityAndOrganisationalUnitAndCommonNameReject("IN\"VALID")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `accepts organisation with single quotation mark`() {
|
||||
CordaX500Name.parse("O=VA'LID, L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("VA'LID")
|
||||
}
|
||||
@Test
|
||||
fun `rejects organisation with backslash`() {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=IN\\VALID, L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
}
|
||||
checkLocalityAndOrganisationalUnitAndCommonNameReject("IN\\VALID")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rejects double spacing only in the organisation attribute`() {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=IN VALID , L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
}
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("VA LID")
|
||||
}
|
||||
@Test
|
||||
fun `rejects organisation (but not other attributes) containing the null character`() {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=IN${NULLCHAR}VALID , L=VALID, C=DE, OU=VALID, CN=VALID")
|
||||
}
|
||||
validateLocalityAndOrganisationalUnitAndCommonName("VA${NULLCHAR}LID")
|
||||
}
|
||||
|
||||
fun checkLocalityAndOrganisationalUnitAndCommonNameReject(invalid: String) {
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=VALID, L=${invalid}, C=DE, OU=VALID, CN=VALID")
|
||||
}
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=VALID, L=VALID, C=DE, OU=${invalid}, CN=VALID")
|
||||
}
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
CordaX500Name.parse("O=VALID, L=VALID, C=DE, OU=VALID, CN=${invalid}")
|
||||
}
|
||||
}
|
||||
|
||||
fun validateLocalityAndOrganisationalUnitAndCommonName(valid: String) {
|
||||
CordaX500Name.parse("O=VALID, L=${valid}, C=DE, OU=VALID, CN=VALID")
|
||||
CordaX500Name.parse("O=VALID, L=VALID, C=DE, OU=${valid}, CN=VALID")
|
||||
CordaX500Name.parse("O=VALID, L=VALID, C=DE, OU=VALID, CN=${valid}")
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user