Merge commit 'e879de7' into chrisr3-os-merge

This commit is contained in:
Chris Rankin
2018-07-17 22:47:24 +01:00
67 changed files with 2205 additions and 442 deletions

View File

@ -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

View File

@ -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

View File

@ -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}")
}
}