Merge remote-tracking branch 'open/master' into colljos-os-merge-rc01

This commit is contained in:
josecoll
2017-12-18 10:24:38 +00:00
215 changed files with 4624 additions and 1717 deletions

View File

@ -288,11 +288,13 @@ class FlowStackSnapshotTest {
@Test
fun `flowStackSnapshot object is serializable`() {
val mockNet = MockNetwork(threadPerNode = true)
val mockNet = MockNetwork(emptyList(), threadPerNode = true)
val node = mockNet.createPartyNode()
node.registerInitiatedFlow(DummyFlow::class.java)
node.services.startFlow(FlowStackSnapshotSerializationTestingFlow()).resultFuture.get()
val thrown = try {
// Due to the [MockNetwork] implementation, the easiest way to trigger object serialization process is at
// the network stopping stage.
mockNet.stopNodes()
null
} catch (exception: Exception) {

View File

@ -45,8 +45,8 @@ import kotlin.concurrent.thread
* a service is addressed.
*/
@ThreadSafe
class InMemoryMessagingNetwork(
val sendManuallyPumped: Boolean,
class InMemoryMessagingNetwork internal constructor(
private val sendManuallyPumped: Boolean,
private val servicePeerAllocationStrategy: ServicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random(),
private val messagesInFlight: ReusableLatch = ReusableLatch()
) : SingletonSerializeAsToken() {
@ -94,7 +94,7 @@ class InMemoryMessagingNetwork(
/**
* Creates a node at the given address: useful if you want to recreate a node to simulate a restart.
*
* @param manuallyPumped if set to true, then you are expected to call the [InMemoryMessaging.pump] method on the [InMemoryMessaging]
* @param manuallyPumped if set to true, then you are expected to call [InMemoryMessaging.pumpReceive]
* in order to cause the delivery of a single message, which will occur on the thread of the caller. If set to false
* then this class will set up a background thread to deliver messages asynchronously, if the handler specifies no
* executor.
@ -153,9 +153,6 @@ class InMemoryMessagingNetwork(
}
}
val everyoneOnline: AllPossibleRecipients = object : AllPossibleRecipients {}
fun stop() {
val nodes = synchronized(this) {
counter = -1
@ -226,7 +223,7 @@ class InMemoryMessagingNetwork(
return transfer
}
fun pumpSendInternal(transfer: MessageTransfer) {
private fun pumpSendInternal(transfer: MessageTransfer) {
when (transfer.recipients) {
is PeerHandle -> getQueueForPeerHandle(transfer.recipients).add(transfer)
is ServiceHandle -> {
@ -271,7 +268,8 @@ class InMemoryMessagingNetwork(
private val peerHandle: PeerHandle,
private val executor: AffinityExecutor,
private val database: CordaPersistence) : SingletonSerializeAsToken(), MessagingService {
inner class Handler(val topicSession: String, val callback: MessageHandler) : MessageHandlerRegistration
privateinner class Handler(val topicSession: String,
val callback: MessageHandler) : MessageHandlerRegistration
@Volatile
private var running = true

View File

@ -1,39 +0,0 @@
package net.corda.testing.node
import net.corda.core.concurrent.CordaFuture
import net.corda.core.crypto.entropyToKeyPair
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.concurrent.doneFuture
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.NetworkMapCache
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.network.PersistentNetworkMapCache
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.testing.getTestPartyAndCertificate
import rx.Observable
import rx.subjects.PublishSubject
import java.math.BigInteger
/**
* Network map cache with no backing map service.
*/
class MockNetworkMapCache(database: CordaPersistence) : PersistentNetworkMapCache(database, emptyList()) {
private companion object {
val BANK_C = getTestPartyAndCertificate(CordaX500Name(organisation = "Bank C", locality = "London", country = "GB"), entropyToKeyPair(BigInteger.valueOf(1000)).public)
val BANK_D = getTestPartyAndCertificate(CordaX500Name(organisation = "Bank D", locality = "London", country = "GB"), entropyToKeyPair(BigInteger.valueOf(2000)).public)
val BANK_C_ADDR = NetworkHostAndPort("bankC", 8080)
val BANK_D_ADDR = NetworkHostAndPort("bankD", 8080)
}
override val changed: Observable<NetworkMapCache.MapChange> = PublishSubject.create<NetworkMapCache.MapChange>()
override val nodeReady: CordaFuture<Void?> get() = doneFuture(null)
init {
val mockNodeA = NodeInfo(listOf(BANK_C_ADDR), listOf(BANK_C), 1, serial = 1L)
val mockNodeB = NodeInfo(listOf(BANK_D_ADDR), listOf(BANK_D), 1, serial = 1L)
addNode(mockNodeA)
addNode(mockNodeB)
}
}

View File

@ -22,14 +22,14 @@ import net.corda.core.node.services.KeyManagementService
import net.corda.core.serialization.SerializationWhitelist
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.seconds
import net.corda.node.VersionInfo
import net.corda.node.internal.AbstractNode
import net.corda.node.internal.StartedNode
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.services.api.SchemaService
import net.corda.node.services.config.BFTSMaRtConfiguration
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.config.NotaryConfig
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.node.services.api.SchemaService
import net.corda.node.services.config.*
import net.corda.node.services.keys.E2ETestKeyManagementService
import net.corda.node.services.messaging.MessagingService
import net.corda.node.services.transactions.BFTNonValidatingNotaryService
@ -37,12 +37,15 @@ import net.corda.node.services.transactions.BFTSMaRt
import net.corda.node.services.transactions.InMemoryTransactionVerifierService
import net.corda.node.utilities.AffinityExecutor
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.ServiceIdentityGenerator
import net.corda.nodeapi.internal.NotaryInfo
import net.corda.nodeapi.internal.NetworkParametersCopier
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.nodeapi.internal.config.User
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.nodeapi.internal.network.NotaryInfo
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.DUMMY_NOTARY_NAME
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.testThreadFactory
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
@ -71,13 +74,13 @@ data class MockNetworkParameters(
val servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random(),
val defaultFactory: (MockNodeArgs) -> MockNetwork.MockNode = MockNetwork::MockNode,
val initialiseSerialization: Boolean = true,
val cordappPackages: List<String> = emptyList()) {
val notarySpecs: List<MockNetwork.NotarySpec> = listOf(MockNetwork.NotarySpec(DUMMY_NOTARY_NAME))) {
fun setNetworkSendManuallyPumped(networkSendManuallyPumped: Boolean) = copy(networkSendManuallyPumped = networkSendManuallyPumped)
fun setThreadPerNode(threadPerNode: Boolean) = copy(threadPerNode = threadPerNode)
fun setServicePeerAllocationStrategy(servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy) = copy(servicePeerAllocationStrategy = servicePeerAllocationStrategy)
fun setDefaultFactory(defaultFactory: (MockNodeArgs) -> MockNetwork.MockNode) = copy(defaultFactory = defaultFactory)
fun setInitialiseSerialization(initialiseSerialization: Boolean) = copy(initialiseSerialization = initialiseSerialization)
fun setCordappPackages(cordappPackages: List<String>) = copy(cordappPackages = cordappPackages)
fun setNotarySpecs(notarySpecs: List<MockNetwork.NotarySpec>) = copy(notarySpecs = notarySpecs)
}
/**
@ -90,7 +93,8 @@ data class MockNodeParameters(
val forcedID: Int? = null,
val legalName: CordaX500Name? = null,
val entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
val configOverrides: (NodeConfiguration) -> Any? = {}) {
val configOverrides: (NodeConfiguration) -> Any? = {},
val version: VersionInfo = MOCK_VERSION_INFO) {
fun setForcedID(forcedID: Int?) = copy(forcedID = forcedID)
fun setLegalName(legalName: CordaX500Name?) = copy(legalName = legalName)
fun setEntropyRoot(entropyRoot: BigInteger) = copy(entropyRoot = entropyRoot)
@ -101,7 +105,8 @@ data class MockNodeArgs(
val config: NodeConfiguration,
val network: MockNetwork,
val id: Int,
val entropyRoot: BigInteger
val entropyRoot: BigInteger,
val version: VersionInfo = MOCK_VERSION_INFO
)
/**
@ -120,16 +125,17 @@ data class MockNodeArgs(
* By default a single notary node is automatically started, which forms part of the network parameters for all the nodes.
* This node is available by calling [defaultNotaryNode].
*/
class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParameters(),
class MockNetwork(private val cordappPackages: List<String>,
defaultParameters: MockNetworkParameters = MockNetworkParameters(),
private val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped,
private val threadPerNode: Boolean = defaultParameters.threadPerNode,
servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy,
private val defaultFactory: (MockNodeArgs) -> MockNode = defaultParameters.defaultFactory,
initialiseSerialization: Boolean = defaultParameters.initialiseSerialization,
private val notarySpecs: List<NotarySpec> = listOf(NotarySpec(DUMMY_NOTARY_NAME)),
private val cordappPackages: List<String> = defaultParameters.cordappPackages) {
private val notarySpecs: List<NotarySpec> = defaultParameters.notarySpecs) {
/** Helper constructor for creating a [MockNetwork] with custom parameters from Java. */
constructor(parameters: MockNetworkParameters) : this(defaultParameters = parameters)
@JvmOverloads
constructor(cordappPackages: List<String>, parameters: MockNetworkParameters = MockNetworkParameters()) : this(cordappPackages, defaultParameters = parameters)
init {
// Apache SSHD for whatever reason registers a SFTP FileSystemProvider - which gets loaded by JimFS.
@ -147,9 +153,13 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
private val networkId = random63BitValue()
private val networkParameters: NetworkParametersCopier
private val _nodes = mutableListOf<MockNode>()
private val serializationEnv = setGlobalSerialization(initialiseSerialization)
private val serializationEnv = try {
setGlobalSerialization(initialiseSerialization)
} catch (e: IllegalStateException) {
throw IllegalStateException("Using more than one MockNetwork simultaneously is not supported.", e)
}
private val sharedUserCount = AtomicInteger(0)
/** A read only view of the current set of executing nodes. */
/** A read only view of the current set of nodes. */
val nodes: List<MockNode> get() = _nodes
/**
@ -220,12 +230,12 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
}
private fun generateNotaryIdentities(): List<NotaryInfo> {
return notarySpecs.mapIndexed { index, spec ->
return notarySpecs.mapIndexed { index, (name, validating) ->
val identity = ServiceIdentityGenerator.generateToDisk(
dirs = listOf(baseDirectory(nextNodeId + index)),
serviceName = spec.name,
serviceName = name,
serviceId = "identity")
NotaryInfo(identity, spec.validating)
NotaryInfo(identity, validating)
}
}
@ -240,7 +250,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
open class MockNode(args: MockNodeArgs) : AbstractNode(
args.config,
TestClock(Clock.systemUTC()),
MOCK_VERSION_INFO,
args.version,
CordappLoader.createDefaultWithTestPackages(args.config, args.network.cordappPackages),
args.network.busyLatch
) {
@ -385,14 +395,14 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete
private fun <N : MockNode> createNodeImpl(parameters: MockNodeParameters, nodeFactory: (MockNodeArgs) -> N, start: Boolean): N {
val id = parameters.forcedID ?: nextNodeId++
val config = testNodeConfiguration(
baseDirectory = baseDirectory(id).createDirectories(),
myLegalName = parameters.legalName ?: CordaX500Name(organisation = "Mock Company $id", locality = "London", country = "GB")).also {
val config = mockNodeConfiguration().also {
doReturn(baseDirectory(id).createDirectories()).whenever(it).baseDirectory
doReturn(parameters.legalName ?: CordaX500Name("Mock Company $id", "London", "GB")).whenever(it).myLegalName
doReturn(makeTestDataSourceProperties("node_$id", "net_$networkId")).whenever(it).dataSourceProperties
doReturn(makeTestDatabaseProperties("node_$id")).whenever(it).database
parameters.configOverrides(it)
}
val node = nodeFactory(MockNodeArgs(config, this, id, parameters.entropyRoot))
val node = nodeFactory(MockNodeArgs(config, this, id, parameters.entropyRoot, parameters.version))
_nodes += node
if (start) {
node.start()
@ -474,3 +484,24 @@ open class MessagingServiceSpy(val messagingService: MessagingService) : Messagi
fun StartedNode<MockNetwork.MockNode>.setMessagingServiceSpy(messagingServiceSpy: MessagingServiceSpy) {
internals.setMessagingServiceSpy(messagingServiceSpy)
}
private fun mockNodeConfiguration(): NodeConfiguration {
abstract class AbstractNodeConfiguration : NodeConfiguration
return rigorousMock<AbstractNodeConfiguration>().also {
doReturn("cordacadevpass").whenever(it).keyStorePassword
doReturn("trustpass").whenever(it).trustStorePassword
doReturn(emptyList<User>()).whenever(it).rpcUsers
doReturn(null).whenever(it).notary
doReturn(DatabaseConfig()).whenever(it).database
doReturn("").whenever(it).emailAddress
doReturn("").whenever(it).exportJMXto
doReturn(true).whenever(it).devMode
doReturn(null).whenever(it).compatibilityZoneURL
doReturn(emptyList<CertChainPolicyConfig>()).whenever(it).certificateChainCheckPolicies
doReturn(VerifierType.InMemory).whenever(it).verifierType
doReturn(5).whenever(it).messageRedeliveryDelaySeconds
doReturn(5.seconds.toMillis()).whenever(it).additionalNodeInfoPollingFrequencyMsec
doReturn(null).whenever(it).devModeOptions
doReturn(true).whenever(it).useAMQPBridges
}
}

View File

@ -59,7 +59,7 @@ import java.sql.Connection
import java.time.Clock
import java.util.*
fun makeTestIdentityService(identities: Iterable<PartyAndCertificate> = emptySet()) = InMemoryIdentityService(identities, DEV_TRUST_ROOT)
fun makeTestIdentityService(vararg identities: PartyAndCertificate) = InMemoryIdentityService(identities, DEV_TRUST_ROOT)
/**
* A singleton utility that only provides a mock identity, key and storage service. However, this is sufficient for
* building chains of transactions and verifying them. It isn't sufficient for testing flows however.
@ -68,8 +68,8 @@ open class MockServices private constructor(
cordappLoader: CordappLoader,
override val validatedTransactions: WritableTransactionStorage,
override val identityService: IdentityServiceInternal,
private val initialIdentityName: CordaX500Name,
val keys: Array<out KeyPair>
private val initialIdentity: TestIdentity,
private val moreKeys: Array<out KeyPair>
) : ServiceHub, StateLoader by validatedTransactions {
companion object {
@JvmStatic
@ -144,22 +144,22 @@ open class MockServices private constructor(
/**
* Makes database and mock services appropriate for unit tests.
* @param keys a list of [KeyPair] instances to be used by [MockServices].
* @param moreKeys a list of additional [KeyPair] instances to be used by [MockServices].
* @param identityService an instance of [IdentityServiceInternal], see [makeTestIdentityService].
* @param initialIdentityName the name of the first (typically sole) identity the services will represent.
* @param initialIdentity the first (typically sole) identity the services will represent.
* @return a pair where the first element is the instance of [CordaPersistence] and the second is [MockServices].
*/
@JvmStatic
fun makeTestDatabaseAndMockServices(keys: List<KeyPair>,
fun makeTestDatabaseAndMockServices(cordappPackages: List<String>,
identityService: IdentityServiceInternal,
cordappPackages: List<String> = emptyList(),
initialIdentityName: CordaX500Name): Pair<CordaPersistence, MockServices> {
initialIdentity: TestIdentity,
vararg moreKeys: KeyPair): Pair<CordaPersistence, MockServices> {
val cordappLoader = CordappLoader.createWithTestPackages(cordappPackages)
val dataSourceProps = makeTestDataSourceProperties(initialIdentityName.organisation)
val schemaService = NodeSchemaService(cordappLoader.cordappSchemas)
val database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(initialIdentityName.organisation), identityService, schemaService)
val mockService = database.transaction {
object : MockServices(cordappLoader, identityService, initialIdentityName, keys.toTypedArray()) {
object : MockServices(cordappLoader, identityService, initialIdentity, moreKeys) {
override val vaultService: VaultServiceInternal = makeVaultService(database.hibernateConfig, schemaService)
override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) {
@ -175,13 +175,18 @@ open class MockServices private constructor(
}
}
private constructor(cordappLoader: CordappLoader, identityService: IdentityServiceInternal, initialIdentityName: CordaX500Name, keys: Array<out KeyPair>) : this(cordappLoader, MockTransactionStorage(), identityService, initialIdentityName, keys)
constructor(cordappPackages: List<String>, identityService: IdentityServiceInternal, initialIdentityName: CordaX500Name, vararg keys: KeyPair) : this(CordappLoader.createWithTestPackages(cordappPackages), identityService, initialIdentityName, keys)
constructor(cordappPackages: List<String>, identityService: IdentityServiceInternal, initialIdentity: TestIdentity, vararg moreKeys: KeyPair) : this(CordappLoader.createWithTestPackages(cordappPackages), identityService, initialIdentity.name, arrayOf(initialIdentity.key) + moreKeys)
constructor(identityService: IdentityServiceInternal, initialIdentityName: CordaX500Name, vararg keys: KeyPair) : this(emptyList(), identityService, initialIdentityName, *keys)
constructor(identityService: IdentityServiceInternal, initialIdentityName: CordaX500Name) : this(identityService, initialIdentityName, generateKeyPair())
private constructor(cordappLoader: CordappLoader, identityService: IdentityServiceInternal, initialIdentity: TestIdentity, moreKeys: Array<out KeyPair>) : this(cordappLoader, MockTransactionStorage(), identityService, initialIdentity, moreKeys)
@JvmOverloads
constructor(cordappPackages: List<String>, identityService: IdentityServiceInternal = makeTestIdentityService(), initialIdentity: TestIdentity, vararg moreKeys: KeyPair) : this(CordappLoader.createWithTestPackages(cordappPackages), identityService, initialIdentity, moreKeys)
val key: KeyPair get() = keys.first()
@JvmOverloads
constructor(cordappPackages: List<String>, identityService: IdentityServiceInternal = makeTestIdentityService(), initialIdentityName: CordaX500Name, key: KeyPair, vararg moreKeys: KeyPair) : this(cordappPackages, identityService, TestIdentity(initialIdentityName, key), *moreKeys)
@JvmOverloads
constructor(cordappPackages: List<String>, identityService: IdentityServiceInternal = makeTestIdentityService(), initialIdentityName: CordaX500Name) : this(cordappPackages, identityService, TestIdentity(initialIdentityName))
@JvmOverloads
constructor(cordappPackages: List<String>, identityService: IdentityServiceInternal = makeTestIdentityService(), vararg moreKeys: KeyPair) : this(cordappPackages, identityService, TestIdentity.fresh("MockServices"), *moreKeys)
override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable<SignedTransaction>) {
txs.forEach {
@ -190,16 +195,14 @@ open class MockServices private constructor(
}
final override val attachments = MockAttachmentStorage()
override val keyManagementService: KeyManagementService by lazy { MockKeyManagementService(identityService, *keys) }
override val keyManagementService: KeyManagementService by lazy { MockKeyManagementService(identityService, *arrayOf(initialIdentity.keyPair) + moreKeys) }
override val vaultService: VaultService get() = throw UnsupportedOperationException()
override val contractUpgradeService: ContractUpgradeService get() = throw UnsupportedOperationException()
override val networkMapCache: NetworkMapCache get() = throw UnsupportedOperationException()
override val clock: Clock get() = Clock.systemUTC()
override val myInfo: NodeInfo
get() {
val identity = getTestPartyAndCertificate(initialIdentityName, key.public)
return NodeInfo(emptyList(), listOf(identity), 1, serial = 1L)
return NodeInfo(emptyList(), listOf(initialIdentity.identity), 1, serial = 1L)
}
override val transactionVerifierService: TransactionVerifierService get() = InMemoryTransactionVerifierService(2)
val mockCordappProvider = MockCordappProvider(cordappLoader, attachments)

View File

@ -2,8 +2,6 @@
package net.corda.testing.node
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.context.Actor
import net.corda.core.context.AuthServiceId
import net.corda.core.context.InvocationContext
@ -13,26 +11,34 @@ import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.internal.FlowStateMachine
import net.corda.core.node.ServiceHub
import net.corda.core.serialization.internal.effectiveSerializationEnv
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.seconds
import net.corda.node.services.api.StartedNodeServices
import net.corda.node.services.config.*
import net.corda.nodeapi.internal.config.User
import net.corda.testing.*
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.node.makeTestIdentityService
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
import java.nio.file.Path
import net.corda.testing.dsl.*
/**
* Creates and tests a ledger built by the passed in dsl.
*/
@JvmOverloads
fun ServiceHub.ledger(
notary: Party,
dsl: LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.() -> Unit
notary: Party = TestIdentity.fresh("ledger notary").party,
script: LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.() -> Unit
): LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter> {
return LedgerDSL(TestLedgerDSLInterpreter(this), notary).apply(dsl)
val serializationExists = try {
effectiveSerializationEnv
true
} catch (e: IllegalStateException) {
false
}
return LedgerDSL(TestLedgerDSLInterpreter(this), notary).apply {
if (serializationExists) {
script()
} else {
SerializationEnvironmentRule.run("ledger") { script() }
}
}
}
/**
@ -40,37 +46,12 @@ fun ServiceHub.ledger(
*
* @see LedgerDSLInterpreter._transaction
*/
@JvmOverloads
fun ServiceHub.transaction(
notary: Party,
dsl: TransactionDSL<TransactionDSLInterpreter>.() -> EnforceVerifyOrFail
notary: Party = TestIdentity.fresh("transaction notary").party,
script: TransactionDSL<TransactionDSLInterpreter>.() -> EnforceVerifyOrFail
) = ledger(notary) {
dsl(TransactionDSL(TestTransactionDSLInterpreter(interpreter, TransactionBuilder(notary)), notary))
}
fun testNodeConfiguration(
baseDirectory: Path,
myLegalName: CordaX500Name): NodeConfiguration {
abstract class MockableNodeConfiguration : NodeConfiguration // Otherwise Mockito is defeated by val getters.
return rigorousMock<MockableNodeConfiguration>().also {
doReturn(baseDirectory).whenever(it).baseDirectory
doReturn(myLegalName).whenever(it).myLegalName
doReturn("cordacadevpass").whenever(it).keyStorePassword
doReturn("trustpass").whenever(it).trustStorePassword
doReturn(emptyList<User>()).whenever(it).rpcUsers
doReturn(null).whenever(it).notary
doReturn(makeTestDataSourceProperties(myLegalName.organisation)).whenever(it).dataSourceProperties
doReturn(makeTestDatabaseProperties(myLegalName.organisation)).whenever(it).database
doReturn("").whenever(it).emailAddress
doReturn("").whenever(it).exportJMXto
doReturn(true).whenever(it).devMode
doReturn(null).whenever(it).compatibilityZoneURL
doReturn(emptyList<CertChainPolicyConfig>()).whenever(it).certificateChainCheckPolicies
doReturn(VerifierType.InMemory).whenever(it).verifierType
doReturn(5).whenever(it).messageRedeliveryDelaySeconds
doReturn(5.seconds.toMillis()).whenever(it).additionalNodeInfoPollingFrequencyMsec
doReturn(null).whenever(it).devModeOptions
doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000))).whenever(it).enterpriseConfiguration //Enterprise only
}
TransactionDSL(TestTransactionDSLInterpreter(interpreter, TransactionBuilder(notary)), notary).script()
}
fun testActor(owningLegalIdentity: CordaX500Name = CordaX500Name("Test Company Inc.", "London", "GB")) = Actor(Actor.Id("Only For Testing"), AuthServiceId("TEST"), owningLegalIdentity)

View File

@ -10,6 +10,7 @@ import net.corda.cordform.CordformContext
import net.corda.cordform.CordformNode
import net.corda.core.concurrent.CordaFuture
import net.corda.core.concurrent.firstOf
import net.corda.core.crypto.random63BitValue
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.ThreadBox
import net.corda.core.internal.concurrent.*
@ -34,7 +35,8 @@ import net.corda.node.services.transactions.RaftNonValidatingNotaryService
import net.corda.node.services.transactions.RaftValidatingNotaryService
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
import net.corda.node.utilities.registration.NetworkRegistrationHelper
import net.corda.nodeapi.internal.*
import net.corda.nodeapi.internal.ServiceIdentityGenerator
import net.corda.nodeapi.internal.addShutdownHook
import net.corda.nodeapi.internal.config.User
import net.corda.nodeapi.internal.config.parseAs
import net.corda.nodeapi.internal.config.toConfig
@ -42,8 +44,13 @@ import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.crypto.addOrReplaceCertificate
import net.corda.nodeapi.internal.crypto.loadOrCreateKeyStore
import net.corda.nodeapi.internal.crypto.save
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
import net.corda.nodeapi.internal.network.NotaryInfo
import net.corda.testing.ALICE_NAME
import net.corda.testing.BOB_NAME
import net.corda.testing.DUMMY_BANK_A_NAME
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.*
import net.corda.testing.driver.*
import net.corda.testing.node.ClusterSpec
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
@ -244,6 +251,7 @@ class DriverDSLImpl(
}
internal fun startCordformNodes(cordforms: List<CordformNode>): CordaFuture<*> {
check(compatibilityZone == null) { "Cordform nodes should be run without compatibilityZone configuration" }
val clusterNodes = HashMultimap.create<ClusterType, CordaX500Name>()
val notaryInfos = ArrayList<NotaryInfo>()
@ -353,7 +361,7 @@ class DriverDSLImpl(
}
val notaryInfos = generateNotaryIdentities()
// The network parameters must be serialised before starting any of the nodes
networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
if (compatibilityZone == null) networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos))
val nodeHandles = startNotaries()
_notaries = notaryInfos.zip(nodeHandles) { (identity, validating), nodes -> NotaryHandle(identity, validating, nodes) }
}
@ -514,7 +522,7 @@ class DriverDSLImpl(
val configuration = config.parseAsNodeConfiguration()
val baseDirectory = configuration.baseDirectory.createDirectories()
nodeInfoFilesCopier?.addConfig(baseDirectory)
networkParameters!!.install(baseDirectory)
networkParameters?.install(baseDirectory)
val onNodeExit: () -> Unit = {
nodeInfoFilesCopier?.removeConfig(baseDirectory)
countObservables.remove(configuration.myLegalName)
@ -889,7 +897,8 @@ fun <A> internalDriver(
}
fun getTimestampAsDirectoryName(): String {
return DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneOffset.UTC).format(Instant.now())
// Add a random number in case 2 tests are started in the same instant.
return DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneOffset.UTC).format(Instant.now()) + random63BitValue()
}
fun writeConfig(path: Path, filename: String, config: Config) {

View File

@ -12,10 +12,10 @@ import net.corda.node.internal.Node
import net.corda.node.internal.StartedNode
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.services.config.*
import net.corda.nodeapi.internal.NetworkParametersCopier
import net.corda.nodeapi.internal.config.User
import net.corda.testing.IntegrationTest
import net.corda.testing.SerializationEnvironmentRule
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.getFreeLocalPorts
import net.corda.testing.internal.testThreadFactory

View File

@ -17,7 +17,6 @@ import net.corda.core.internal.uncheckedCast
import net.corda.core.messaging.RPCOps
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.internal.security.RPCSecurityManagerImpl
import net.corda.node.services.messaging.ArtemisMessagingServer
import net.corda.node.services.messaging.RPCServer
import net.corda.node.services.messaging.RPCServerConfiguration
import net.corda.nodeapi.ArtemisTcpTransport
@ -25,6 +24,7 @@ import net.corda.nodeapi.ConnectionDirection
import net.corda.nodeapi.RPCApi
import net.corda.nodeapi.internal.config.User
import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT
import net.corda.testing.MAX_MESSAGE_SIZE
import net.corda.testing.driver.JmxPolicy
import net.corda.testing.driver.PortAllocation
import net.corda.testing.node.NotarySpec
@ -46,7 +46,7 @@ import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy
import org.apache.activemq.artemis.core.settings.impl.AddressSettings
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection
import org.apache.activemq.artemis.spi.core.remoting.Connection
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager3
import java.lang.reflect.Method
import java.nio.file.Path
@ -133,11 +133,11 @@ fun <A> rpcDriver(
private class SingleUserSecurityManager(val rpcUser: User) : ActiveMQSecurityManager3 {
override fun validateUser(user: String?, password: String?) = isValid(user, password)
override fun validateUserAndRole(user: String?, password: String?, roles: MutableSet<Role>?, checkType: CheckType?) = isValid(user, password)
override fun validateUser(user: String?, password: String?, remotingConnection: RemotingConnection?): String? {
override fun validateUser(user: String?, password: String?, connection: Connection?): String? {
return validate(user, password)
}
override fun validateUserAndRole(user: String?, password: String?, roles: MutableSet<Role>?, checkType: CheckType?, address: String?, connection: RemotingConnection?): String? {
override fun validateUserAndRole(user: String?, password: String?, roles: MutableSet<Role>?, checkType: CheckType?, address: String?, connection: Connection?): String? {
return validate(user, password)
}
@ -226,8 +226,8 @@ data class RPCDriverDSL(
fun <I : RPCOps> startInVmRpcServer(
rpcUser: User = rpcTestUser,
nodeLegalName: CordaX500Name = fakeNodeLegalName,
maxFileSize: Int = ArtemisMessagingServer.MAX_FILE_SIZE,
maxBufferedBytesPerClient: Long = 10L * ArtemisMessagingServer.MAX_FILE_SIZE,
maxFileSize: Int = MAX_MESSAGE_SIZE,
maxBufferedBytesPerClient: Long = 10L * MAX_MESSAGE_SIZE,
configuration: RPCServerConfiguration = RPCServerConfiguration.default,
ops: I
): CordaFuture<RpcServerHandle> {
@ -294,8 +294,8 @@ data class RPCDriverDSL(
serverName: String = "driver-rpc-server-${random63BitValue()}",
rpcUser: User = rpcTestUser,
nodeLegalName: CordaX500Name = fakeNodeLegalName,
maxFileSize: Int = ArtemisMessagingServer.MAX_FILE_SIZE,
maxBufferedBytesPerClient: Long = 10L * ArtemisMessagingServer.MAX_FILE_SIZE,
maxFileSize: Int = MAX_MESSAGE_SIZE,
maxBufferedBytesPerClient: Long = 10L * MAX_MESSAGE_SIZE,
configuration: RPCServerConfiguration = RPCServerConfiguration.default,
customPort: NetworkHostAndPort? = null,
ops: I
@ -377,8 +377,8 @@ data class RPCDriverDSL(
fun startRpcBroker(
serverName: String = "driver-rpc-server-${random63BitValue()}",
rpcUser: User = rpcTestUser,
maxFileSize: Int = ArtemisMessagingServer.MAX_FILE_SIZE,
maxBufferedBytesPerClient: Long = 10L * ArtemisMessagingServer.MAX_FILE_SIZE,
maxFileSize: Int = MAX_MESSAGE_SIZE,
maxBufferedBytesPerClient: Long = 10L * MAX_MESSAGE_SIZE,
customPort: NetworkHostAndPort? = null
): CordaFuture<RpcBrokerHandle> {
val hostAndPort = customPort ?: driverDSL.portAllocation.nextHostAndPort()
@ -401,8 +401,8 @@ data class RPCDriverDSL(
fun startInVmRpcBroker(
rpcUser: User = rpcTestUser,
maxFileSize: Int = ArtemisMessagingServer.MAX_FILE_SIZE,
maxBufferedBytesPerClient: Long = 10L * ArtemisMessagingServer.MAX_FILE_SIZE
maxFileSize: Int = MAX_MESSAGE_SIZE,
maxBufferedBytesPerClient: Long = 10L * MAX_MESSAGE_SIZE
): CordaFuture<RpcBrokerHandle> {
return driverDSL.executorService.fork {
val artemisConfig = createInVmRpcServerArtemisConfig(maxFileSize, maxBufferedBytesPerClient)
@ -430,7 +430,7 @@ data class RPCDriverDSL(
brokerHandle: RpcBrokerHandle
): RpcServerHandle {
val locator = ActiveMQClient.createServerLocatorWithoutHA(brokerHandle.clientTransportConfiguration).apply {
minLargeMessageSize = ArtemisMessagingServer.MAX_FILE_SIZE
minLargeMessageSize = MAX_MESSAGE_SIZE
isUseGlobalPools = false
}
val rpcSecurityManager = RPCSecurityManagerImpl.fromUserList(users = listOf(rpcUser), id = AuthServiceId("TEST_SECURITY_MANAGER"))

View File

@ -1,20 +1,17 @@
package net.corda.testing.node.network
package net.corda.testing.node.internal.network
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.SignedData
import net.corda.core.crypto.sha256
import net.corda.core.crypto.*
import net.corda.core.internal.cert
import net.corda.core.internal.toX509CertHolder
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.hours
import net.corda.nodeapi.internal.DigitalSignatureWithCert
import net.corda.nodeapi.internal.NetworkMap
import net.corda.nodeapi.internal.NetworkParameters
import net.corda.nodeapi.internal.SignedNetworkMap
import net.corda.nodeapi.internal.network.DigitalSignatureWithCert
import net.corda.nodeapi.internal.network.NetworkMap
import net.corda.nodeapi.internal.network.NetworkParameters
import net.corda.nodeapi.internal.network.SignedNetworkMap
import net.corda.nodeapi.internal.*
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities
@ -39,9 +36,11 @@ import javax.ws.rs.core.Response.ok
class NetworkMapServer(cacheTimeout: Duration,
hostAndPort: NetworkHostAndPort,
root_ca: CertificateAndKeyPair = ROOT_CA, // Default to ROOT_CA for testing.
vararg additionalServices: Any) : Closeable {
companion object {
val stubNetworkParameter = NetworkParameters(1, emptyList(), 1.hours, 10, 10, Instant.now(), 10)
val stubNetworkParameter = NetworkParameters(1, emptyList(), 10485760, 40000, Instant.now(), 10)
private val serializedParameters = stubNetworkParameter.serialize()
private fun networkMapKeyAndCert(rootCAKeyAndCert: CertificateAndKeyPair): CertificateAndKeyPair {
val networkMapKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
@ -56,9 +55,7 @@ class NetworkMapServer(cacheTimeout: Duration,
}
private val server: Server
// Default to ROOT_CA for testing.
// TODO: make this configurable?
private val service = InMemoryNetworkMapService(cacheTimeout, networkMapKeyAndCert(ROOT_CA))
private val service = InMemoryNetworkMapService(cacheTimeout, networkMapKeyAndCert(root_ca))
init {
server = Server(InetSocketAddress(hostAndPort.host, hostAndPort.port)).apply {
@ -99,13 +96,18 @@ class NetworkMapServer(cacheTimeout: Duration,
@Path("network-map")
class InMemoryNetworkMapService(private val cacheTimeout: Duration, private val networkMapKeyAndCert: CertificateAndKeyPair) {
private val nodeInfoMap = mutableMapOf<SecureHash, SignedData<NodeInfo>>()
private val nodeInfoMap = mutableMapOf<SecureHash, SignedNodeInfo>()
private val parametersHash = serializedParameters.hash
private val signedParameters = SignedData(
serializedParameters,
DigitalSignature.WithKey(networkMapKeyAndCert.keyPair.public, Crypto.doSign(networkMapKeyAndCert.keyPair.private, serializedParameters.bytes))
)
@POST
@Path("publish")
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
fun publishNodeInfo(input: InputStream): Response {
val registrationData = input.readBytes().deserialize<SignedData<NodeInfo>>()
val registrationData = input.readBytes().deserialize<SignedNodeInfo>()
val nodeInfo = registrationData.verified()
val nodeInfoHash = nodeInfo.serialize().sha256()
nodeInfoMap.put(nodeInfoHash, registrationData)
@ -115,7 +117,7 @@ class NetworkMapServer(cacheTimeout: Duration,
@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
fun getNetworkMap(): Response {
val networkMap = NetworkMap(nodeInfoMap.keys.map { it }, SecureHash.randomSHA256())
val networkMap = NetworkMap(nodeInfoMap.keys.toList(), parametersHash)
val serializedNetworkMap = networkMap.serialize()
val signature = Crypto.doSign(networkMapKeyAndCert.keyPair.private, serializedNetworkMap.bytes)
val signedNetworkMap = SignedNetworkMap(networkMap.serialize(), DigitalSignatureWithCert(networkMapKeyAndCert.certificate.cert, signature))
@ -143,7 +145,7 @@ class NetworkMapServer(cacheTimeout: Duration,
@Path("network-parameter/{var}")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
fun getNetworkParameter(@PathParam("var") networkParameterHash: String): Response {
return Response.ok(stubNetworkParameter.serialize().bytes).build()
return Response.ok(signedParameters.serialize().bytes).build()
}
@GET

View File

@ -2,6 +2,8 @@ package net.corda.testing.node;
import org.jetbrains.annotations.NotNull;
import static java.util.Collections.emptyList;
@SuppressWarnings("unused")
public class MockNodeFactoryInJavaTest {
private static class CustomNode extends MockNetwork.MockNode {
@ -16,10 +18,10 @@ public class MockNodeFactoryInJavaTest {
@SuppressWarnings("unused")
private static void factoryIsEasyToPassInUsingJava() {
//noinspection Convert2MethodRef
new MockNetwork(new MockNetworkParameters().setDefaultFactory(args -> new CustomNode(args)));
new MockNetwork(new MockNetworkParameters().setDefaultFactory(CustomNode::new));
new MockNetwork(emptyList(), new MockNetworkParameters().setDefaultFactory(args -> new CustomNode(args)));
new MockNetwork(emptyList(), new MockNetworkParameters().setDefaultFactory(CustomNode::new));
//noinspection Convert2MethodRef
new MockNetwork().createNode(new MockNodeParameters(), args -> new CustomNode(args));
new MockNetwork().createNode(new MockNodeParameters(), CustomNode::new);
new MockNetwork(emptyList()).createNode(new MockNodeParameters(), args -> new CustomNode(args));
new MockNetwork(emptyList()).createNode(new MockNodeParameters(), CustomNode::new);
}
}