Merged in rnicoll-simulations (pull request #314)

Move test code from node to test-utils
This commit is contained in:
Ross Nicoll 2016-09-01 15:21:34 +01:00
commit b913b18e02
35 changed files with 95 additions and 85 deletions

View File

@ -102,6 +102,8 @@ mainClassName = 'com.r3corda.demos.TraderDemoKt'
dependencies { dependencies {
compile project(':node') compile project(':node')
// TODO: Demos should not depend on test code, but only use production APIs
compile project(':test-utils')
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

View File

@ -2,13 +2,15 @@ apply plugin: 'kotlin'
apply plugin: CanonicalizerPlugin apply plugin: CanonicalizerPlugin
repositories { repositories {
mavenCentral()
mavenLocal() mavenLocal()
mavenCentral() mavenCentral()
jcenter()
maven { maven {
url 'http://oss.sonatype.org/content/repositories/snapshots' url 'http://oss.sonatype.org/content/repositories/snapshots'
} }
jcenter()
maven {
url 'https://dl.bintray.com/kotlin/exposed'
}
} }
dependencies { dependencies {

View File

@ -7,7 +7,7 @@ import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.SecureHash import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.serialization.opaque import com.r3corda.core.serialization.opaque
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.protocols.ResolveTransactionsProtocol import com.r3corda.protocols.ResolveTransactionsProtocol
import com.r3corda.testing.* import com.r3corda.testing.*
import org.junit.After import org.junit.After

View File

@ -6,7 +6,15 @@ apply plugin: 'kotlin'
sourceCompatibility = 1.5 sourceCompatibility = 1.5
repositories { repositories {
mavenLocal()
mavenCentral() mavenCentral()
maven {
url 'http://oss.sonatype.org/content/repositories/snapshots'
}
jcenter()
maven {
url 'https://dl.bintray.com/kotlin/exposed'
}
} }
compileKotlin { compileKotlin {

View File

@ -34,7 +34,7 @@ sourceSets {
dependencies { dependencies {
compile project(':contracts') compile project(':contracts')
compile project(':test-utils') testCompile project(':test-utils')
compile "com.google.code.findbugs:jsr305:3.0.1" compile "com.google.code.findbugs:jsr305:3.0.1"

View File

@ -6,7 +6,7 @@ import com.r3corda.core.crypto.sha256
import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.ServiceType import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.serialization.OpaqueBytes import com.r3corda.core.serialization.OpaqueBytes
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.config.NodeConfiguration import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.network.NetworkMapService import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.persistence.NodeAttachmentService import com.r3corda.node.services.persistence.NodeAttachmentService

View File

@ -5,7 +5,7 @@ package com.r3corda.node.messaging
import com.r3corda.core.messaging.Message import com.r3corda.core.messaging.Message
import com.r3corda.core.messaging.TopicStringValidator import com.r3corda.core.messaging.TopicStringValidator
import com.r3corda.core.node.services.DEFAULT_SESSION_ID import com.r3corda.core.node.services.DEFAULT_SESSION_ID
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*

View File

@ -18,9 +18,9 @@ import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
import com.r3corda.core.utilities.LogHelper import com.r3corda.core.utilities.LogHelper
import com.r3corda.core.utilities.TEST_TX_TIME import com.r3corda.core.utilities.TEST_TX_TIME
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.config.NodeConfiguration import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.network.InMemoryMessagingNetwork import com.r3corda.testing.node.InMemoryMessagingNetwork
import com.r3corda.node.services.persistence.NodeAttachmentService import com.r3corda.node.services.persistence.NodeAttachmentService
import com.r3corda.node.services.persistence.PerFileTransactionStorage import com.r3corda.node.services.persistence.PerFileTransactionStorage
import com.r3corda.node.services.persistence.StorageServiceImpl import com.r3corda.node.services.persistence.StorageServiceImpl

View File

@ -1,6 +1,6 @@
package com.r3corda.node.services package com.r3corda.node.services
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test

View File

@ -5,7 +5,7 @@ import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.NodeInfo
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.random63BitValue import com.r3corda.core.random63BitValue
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.network.InMemoryNetworkMapService import com.r3corda.node.services.network.InMemoryNetworkMapService
import com.r3corda.node.services.network.NetworkMapService import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.network.NodeRegistration import com.r3corda.node.services.network.NodeRegistration

View File

@ -10,7 +10,7 @@ import com.r3corda.node.serialization.NodeClock
import com.r3corda.node.services.api.MessagingServiceInternal import com.r3corda.node.services.api.MessagingServiceInternal
import com.r3corda.node.services.api.MonitoringService import com.r3corda.node.services.api.MonitoringService
import com.r3corda.node.services.api.ServiceHubInternal import com.r3corda.node.services.api.ServiceHubInternal
import com.r3corda.node.services.network.MockNetworkMapCache import com.r3corda.testing.node.MockNetworkMapCache
import com.r3corda.node.services.network.NetworkMapService import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.persistence.DataVending import com.r3corda.node.services.persistence.DataVending
import com.r3corda.node.services.statemachine.StateMachineManager import com.r3corda.node.services.statemachine.StateMachineManager

View File

@ -13,7 +13,7 @@ import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.generateKeyPair import com.r3corda.core.crypto.generateKeyPair
import com.r3corda.core.utilities.DUMMY_NOTARY import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.core.utilities.LogHelper import com.r3corda.core.utilities.LogHelper
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.clientapi.NodeInterestRates import com.r3corda.node.services.clientapi.NodeInterestRates
import com.r3corda.protocols.RatesFixProtocol import com.r3corda.protocols.RatesFixProtocol
import com.r3corda.testing.ALICE_PUBKEY import com.r3corda.testing.ALICE_PUBKEY

View File

@ -11,9 +11,9 @@ import com.r3corda.core.protocols.ProtocolLogicRef
import com.r3corda.core.protocols.ProtocolLogicRefFactory import com.r3corda.core.protocols.ProtocolLogicRefFactory
import com.r3corda.core.serialization.SingletonSerializeAsToken import com.r3corda.core.serialization.SingletonSerializeAsToken
import com.r3corda.core.utilities.DUMMY_NOTARY import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.node.internal.testing.TestClock import com.r3corda.testing.node.TestClock
import com.r3corda.node.services.events.NodeSchedulerService import com.r3corda.node.services.events.NodeSchedulerService
import com.r3corda.node.services.network.InMemoryMessagingNetwork import com.r3corda.testing.node.InMemoryMessagingNetwork
import com.r3corda.node.services.persistence.PerFileCheckpointStorage import com.r3corda.node.services.persistence.PerFileCheckpointStorage
import com.r3corda.node.services.statemachine.StateMachineManager import com.r3corda.node.services.statemachine.StateMachineManager
import com.r3corda.node.utilities.AffinityExecutor import com.r3corda.node.utilities.AffinityExecutor

View File

@ -7,7 +7,7 @@ import com.r3corda.core.seconds
import com.r3corda.core.utilities.DUMMY_NOTARY import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
import com.r3corda.node.internal.AbstractNode import com.r3corda.node.internal.AbstractNode
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.network.NetworkMapService import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.transactions.SimpleNotaryService import com.r3corda.node.services.transactions.SimpleNotaryService
import com.r3corda.protocols.NotaryChangeProtocol import com.r3corda.protocols.NotaryChangeProtocol

View File

@ -5,7 +5,7 @@ import com.r3corda.core.contracts.TransactionType
import com.r3corda.core.seconds import com.r3corda.core.seconds
import com.r3corda.core.utilities.DUMMY_NOTARY import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.network.NetworkMapService import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.transactions.SimpleNotaryService import com.r3corda.node.services.transactions.SimpleNotaryService
import com.r3corda.protocols.NotaryError import com.r3corda.protocols.NotaryError

View File

@ -5,7 +5,7 @@ import com.r3corda.core.contracts.DummyContract
import com.r3corda.core.contracts.TransactionType import com.r3corda.core.contracts.TransactionType
import com.r3corda.core.utilities.DUMMY_NOTARY import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.network.NetworkMapService import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.transactions.ValidatingNotaryService import com.r3corda.node.services.transactions.ValidatingNotaryService
import com.r3corda.protocols.NotaryError import com.r3corda.protocols.NotaryError

View File

@ -16,7 +16,7 @@ import com.r3corda.core.serialization.deserialize
import com.r3corda.core.serialization.serialize import com.r3corda.core.serialization.serialize
import com.r3corda.core.utilities.DUMMY_NOTARY import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.core.utilities.DUMMY_PUBKEY_1 import com.r3corda.core.utilities.DUMMY_PUBKEY_1
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.monitor.* import com.r3corda.node.services.monitor.*
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test

View File

@ -6,7 +6,7 @@ import com.r3corda.core.contracts.Issued
import com.r3corda.core.contracts.TransactionType import com.r3corda.core.contracts.TransactionType
import com.r3corda.core.contracts.USD import com.r3corda.core.contracts.USD
import com.r3corda.core.utilities.DUMMY_NOTARY import com.r3corda.core.utilities.DUMMY_NOTARY
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.testing.MEGA_CORP import com.r3corda.testing.MEGA_CORP
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test

View File

@ -7,7 +7,7 @@ import com.r3corda.node.services.MockServiceHubInternal
import com.r3corda.node.services.api.Checkpoint import com.r3corda.node.services.api.Checkpoint
import com.r3corda.node.services.api.CheckpointStorage import com.r3corda.node.services.api.CheckpointStorage
import com.r3corda.node.services.api.MessagingServiceInternal import com.r3corda.node.services.api.MessagingServiceInternal
import com.r3corda.node.services.network.InMemoryMessagingNetwork import com.r3corda.testing.node.InMemoryMessagingNetwork
import com.r3corda.node.utilities.AffinityExecutor import com.r3corda.node.utilities.AffinityExecutor
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After

View File

@ -5,7 +5,7 @@ import co.paralleluniverse.fibers.FiberExecutorScheduler
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import co.paralleluniverse.strands.Strand import co.paralleluniverse.strands.Strand
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
import com.r3corda.node.internal.testing.TestClock import com.r3corda.testing.node.TestClock
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test

View File

@ -5,7 +5,7 @@ import co.paralleluniverse.fibers.FiberExecutorScheduler
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import co.paralleluniverse.strands.Strand import co.paralleluniverse.strands.Strand
import com.r3corda.core.RetryableException import com.r3corda.core.RetryableException
import com.r3corda.node.internal.testing.TestClock import com.r3corda.testing.node.TestClock
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test

View File

@ -19,7 +19,7 @@ import com.r3corda.demos.utilities.putJson
import com.r3corda.demos.utilities.uploadFile import com.r3corda.demos.utilities.uploadFile
import com.r3corda.node.internal.AbstractNode import com.r3corda.node.internal.AbstractNode
import com.r3corda.node.internal.Node import com.r3corda.node.internal.Node
import com.r3corda.node.internal.testing.MockNetwork import com.r3corda.testing.node.MockNetwork
import com.r3corda.node.services.clientapi.NodeInterestRates import com.r3corda.node.services.clientapi.NodeInterestRates
import com.r3corda.node.services.config.NodeConfiguration import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.config.NodeConfigurationFromConfig import com.r3corda.node.services.config.NodeConfigurationFromConfig

View File

@ -8,7 +8,7 @@ import com.r3corda.core.node.services.DEFAULT_SESSION_ID
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.serialization.deserialize import com.r3corda.core.serialization.deserialize
import com.r3corda.node.services.api.ServiceHubInternal import com.r3corda.node.services.api.ServiceHubInternal
import com.r3corda.node.services.network.MockNetworkMapCache import com.r3corda.testing.node.MockNetworkMapCache
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit

View File

@ -10,7 +10,7 @@ import com.r3corda.core.utilities.ProgressTracker
import com.r3corda.demos.DemoClock import com.r3corda.demos.DemoClock
import com.r3corda.node.internal.Node import com.r3corda.node.internal.Node
import com.r3corda.node.services.api.ServiceHubInternal import com.r3corda.node.services.api.ServiceHubInternal
import com.r3corda.node.services.network.MockNetworkMapCache import com.r3corda.testing.node.MockNetworkMapCache
import java.time.LocalDate import java.time.LocalDate
/** /**

View File

@ -1,4 +1,4 @@
package com.r3corda.node.internal.testing package com.r3corda.simulation
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.google.common.util.concurrent.FutureCallback import com.google.common.util.concurrent.FutureCallback
@ -12,12 +12,11 @@ import com.r3corda.core.contracts.StateAndRef
import com.r3corda.core.contracts.UniqueIdentifier import com.r3corda.core.contracts.UniqueIdentifier
import com.r3corda.core.failure import com.r3corda.core.failure
import com.r3corda.core.node.services.linearHeadsOfType import com.r3corda.core.node.services.linearHeadsOfType
import com.r3corda.testing.node.MockIdentityService
import com.r3corda.core.random63BitValue import com.r3corda.core.random63BitValue
import com.r3corda.core.success import com.r3corda.core.success
import com.r3corda.node.services.network.InMemoryMessagingNetwork
import com.r3corda.node.utilities.JsonSupport
import com.r3corda.protocols.TwoPartyDealProtocol import com.r3corda.protocols.TwoPartyDealProtocol
import com.r3corda.testing.node.InMemoryMessagingNetwork
import com.r3corda.testing.node.MockIdentityService
import java.security.KeyPair import java.security.KeyPair
import java.time.LocalDate import java.time.LocalDate
import java.util.* import java.util.*
@ -27,7 +26,7 @@ import java.util.*
* A simulation in which banks execute interest rate swaps with each other, including the fixing events. * A simulation in which banks execute interest rate swaps with each other, including the fixing events.
*/ */
class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, latencyInjector: InMemoryMessagingNetwork.LatencyCalculator?) : Simulation(networkSendManuallyPumped, runAsync, latencyInjector) { class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, latencyInjector: InMemoryMessagingNetwork.LatencyCalculator?) : Simulation(networkSendManuallyPumped, runAsync, latencyInjector) {
val om = JsonSupport.createDefaultMapper(MockIdentityService(network.identities)) val om = com.r3corda.node.utilities.JsonSupport.createDefaultMapper(MockIdentityService(network.identities))
init { init {
currentDateAndTime = LocalDate.of(2016, 3, 8).atStartOfDay() currentDateAndTime = LocalDate.of(2016, 3, 8).atStartOfDay()
@ -80,7 +79,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
val node1: SimulatedNode = banks[i] val node1: SimulatedNode = banks[i]
val node2: SimulatedNode = banks[j] val node2: SimulatedNode = banks[j]
val swaps: Map<UniqueIdentifier, StateAndRef<InterestRateSwap.State>> = node1.services.walletService.linearHeadsOfType<InterestRateSwap.State>() val swaps: Map<UniqueIdentifier, StateAndRef<InterestRateSwap.State>> = node1.services.walletService.linearHeadsOfType<com.r3corda.contracts.InterestRateSwap.State>()
val theDealRef: StateAndRef<InterestRateSwap.State> = swaps.values.single() val theDealRef: StateAndRef<InterestRateSwap.State> = swaps.values.single()
// Do we have any more days left in this deal's lifetime? If not, return. // Do we have any more days left in this deal's lifetime? If not, return.
@ -118,7 +117,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
// We load the IRS afresh each time because the leg parts of the structure aren't data classes so they don't // We load the IRS afresh each time because the leg parts of the structure aren't data classes so they don't
// have the convenient copy() method that'd let us make small adjustments. Instead they're partly mutable. // have the convenient copy() method that'd let us make small adjustments. Instead they're partly mutable.
// TODO: We should revisit this in post-Excalibur cleanup and fix, e.g. by introducing an interface. // TODO: We should revisit this in post-Excalibur cleanup and fix, e.g. by introducing an interface.
val irs = om.readValue<InterestRateSwap.State>(javaClass.getResource("trade.json")) val irs = om.readValue<com.r3corda.contracts.InterestRateSwap.State>(javaClass.getResource("trade.json"))
irs.fixedLeg.fixedRatePayer = node1.info.identity irs.fixedLeg.fixedRatePayer = node1.info.identity
irs.floatingLeg.floatingRatePayer = node2.info.identity irs.floatingLeg.floatingRatePayer = node2.info.identity

View File

@ -1,4 +1,4 @@
package com.r3corda.node.internal.testing package com.r3corda.simulation
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
@ -11,10 +11,13 @@ import com.r3corda.core.then
import com.r3corda.core.utilities.ProgressTracker import com.r3corda.core.utilities.ProgressTracker
import com.r3corda.node.services.clientapi.NodeInterestRates import com.r3corda.node.services.clientapi.NodeInterestRates
import com.r3corda.node.services.config.NodeConfiguration import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.network.InMemoryMessagingNetwork
import com.r3corda.node.services.network.NetworkMapService import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.transactions.SimpleNotaryService import com.r3corda.node.services.transactions.SimpleNotaryService
import com.r3corda.node.utilities.AddOrRemove import com.r3corda.node.utilities.AddOrRemove
import com.r3corda.testing.node.InMemoryMessagingNetwork
import com.r3corda.testing.node.MockNetwork
import com.r3corda.testing.node.TestClock
import com.r3corda.testing.node.setTo
import rx.Observable import rx.Observable
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
import java.nio.file.Path import java.nio.file.Path
@ -54,7 +57,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode { advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
val letter = 'A' + counter val letter = 'A' + counter
val city = bankLocations[counter++ % bankLocations.size] val city = bankLocations[counter++ % bankLocations.size]
val cfg = object : NodeConfiguration { val cfg = object : com.r3corda.node.services.config.NodeConfiguration {
// TODO: Set this back to "Bank of $city" after video day. // TODO: Set this back to "Bank of $city" after video day.
override val myLegalName: String = "Bank $letter" override val myLegalName: String = "Bank $letter"
override val exportJMXto: String = "" override val exportJMXto: String = ""
@ -72,10 +75,10 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
val bankFactory = BankFactory() val bankFactory = BankFactory()
object NetworkMapNodeFactory : MockNetwork.Factory { object NetworkMapNodeFactory : MockNetwork.Factory {
override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork, override fun create(dir: Path, config: com.r3corda.node.services.config.NodeConfiguration, network: MockNetwork,
networkMapAddr: NodeInfo?, advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode { networkMapAddr: NodeInfo?, advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
require(advertisedServices.contains(NetworkMapService.Type)) require(advertisedServices.contains(com.r3corda.node.services.network.NetworkMapService.Type))
val cfg = object : NodeConfiguration { val cfg = object : com.r3corda.node.services.config.NodeConfiguration {
override val myLegalName: String = "Network coordination center" override val myLegalName: String = "Network coordination center"
override val exportJMXto: String = "" override val exportJMXto: String = ""
override val nearestCity: String = "Amsterdam" override val nearestCity: String = "Amsterdam"
@ -88,10 +91,10 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
} }
object NotaryNodeFactory : MockNetwork.Factory { object NotaryNodeFactory : MockNetwork.Factory {
override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork, networkMapAddr: NodeInfo?, override fun create(dir: Path, config: com.r3corda.node.services.config.NodeConfiguration, network: MockNetwork, networkMapAddr: NodeInfo?,
advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode { advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
require(advertisedServices.contains(SimpleNotaryService.Type)) require(advertisedServices.contains(com.r3corda.node.services.transactions.SimpleNotaryService.Type))
val cfg = object : NodeConfiguration { val cfg = object : com.r3corda.node.services.config.NodeConfiguration {
override val myLegalName: String = "Notary Service" override val myLegalName: String = "Notary Service"
override val exportJMXto: String = "" override val exportJMXto: String = ""
override val nearestCity: String = "Zurich" override val nearestCity: String = "Zurich"
@ -103,10 +106,10 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
} }
object RatesOracleFactory : MockNetwork.Factory { object RatesOracleFactory : MockNetwork.Factory {
override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork, networkMapAddr: NodeInfo?, override fun create(dir: Path, config: com.r3corda.node.services.config.NodeConfiguration, network: MockNetwork, networkMapAddr: NodeInfo?,
advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode { advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
require(advertisedServices.contains(NodeInterestRates.Type)) require(advertisedServices.contains(com.r3corda.node.services.clientapi.NodeInterestRates.Type))
val cfg = object : NodeConfiguration { val cfg = object : com.r3corda.node.services.config.NodeConfiguration {
override val myLegalName: String = "Rates Service Provider" override val myLegalName: String = "Rates Service Provider"
override val exportJMXto: String = "" override val exportJMXto: String = ""
override val nearestCity: String = "Madrid" override val nearestCity: String = "Madrid"
@ -117,7 +120,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
return object : SimulatedNode(dir, cfg, network, networkMapAddr, advertisedServices, id, keyPair) { return object : SimulatedNode(dir, cfg, network, networkMapAddr, advertisedServices, id, keyPair) {
override fun start(): MockNetwork.MockNode { override fun start(): MockNetwork.MockNode {
super.start() super.start()
findService<NodeInterestRates.Service>().upload(javaClass.getResourceAsStream("example.rates.txt")) findService<com.r3corda.node.services.clientapi.NodeInterestRates.Service>().upload(javaClass.getResourceAsStream("example.rates.txt"))
return this return this
} }
} }
@ -125,9 +128,9 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
} }
object RegulatorFactory : MockNetwork.Factory { object RegulatorFactory : MockNetwork.Factory {
override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork, networkMapAddr: NodeInfo?, override fun create(dir: Path, config: com.r3corda.node.services.config.NodeConfiguration, network: MockNetwork, networkMapAddr: NodeInfo?,
advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode { advertisedServices: Set<ServiceType>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
val cfg = object : NodeConfiguration { val cfg = object : com.r3corda.node.services.config.NodeConfiguration {
override val myLegalName: String = "Regulator A" override val myLegalName: String = "Regulator A"
override val exportJMXto: String = "" override val exportJMXto: String = ""
override val nearestCity: String = "Paris" override val nearestCity: String = "Paris"
@ -147,12 +150,12 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
val network = MockNetwork(networkSendManuallyPumped, runAsync) val network = MockNetwork(networkSendManuallyPumped, runAsync)
// This one must come first. // This one must come first.
val networkMap: SimulatedNode val networkMap: SimulatedNode
= network.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = NetworkMapService.Type) as SimulatedNode = network.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = com.r3corda.node.services.network.NetworkMapService.Type) as SimulatedNode
val notary: SimulatedNode val notary: SimulatedNode
= network.createNode(networkMap.info, nodeFactory = NotaryNodeFactory, advertisedServices = SimpleNotaryService.Type) as SimulatedNode = network.createNode(networkMap.info, nodeFactory = NotaryNodeFactory, advertisedServices = com.r3corda.node.services.transactions.SimpleNotaryService.Type) as SimulatedNode
val regulators: List<SimulatedNode> = listOf(network.createNode(networkMap.info, start = false, nodeFactory = RegulatorFactory) as SimulatedNode) val regulators: List<SimulatedNode> = listOf(network.createNode(networkMap.info, start = false, nodeFactory = RegulatorFactory) as SimulatedNode)
val ratesOracle: SimulatedNode val ratesOracle: SimulatedNode
= network.createNode(networkMap.info, start = false, nodeFactory = RatesOracleFactory, advertisedServices = NodeInterestRates.Type) as SimulatedNode = network.createNode(networkMap.info, start = false, nodeFactory = RatesOracleFactory, advertisedServices = com.r3corda.node.services.clientapi.NodeInterestRates.Type) as SimulatedNode
// All nodes must be in one of these two lists for the purposes of the visualiser tool. // All nodes must be in one of these two lists for the purposes of the visualiser tool.
val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap) val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap)
@ -226,7 +229,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
protected fun showProgressFor(nodes: List<SimulatedNode>) { protected fun showProgressFor(nodes: List<SimulatedNode>) {
nodes.forEach { node -> nodes.forEach { node ->
node.smm.changes.filter { it.second == AddOrRemove.ADD }.first().subscribe { node.smm.changes.filter { it.second == com.r3corda.node.utilities.AddOrRemove.ADD }.first().subscribe {
linkProtocolProgress(node, it.first) linkProtocolProgress(node, it.first)
} }
} }
@ -245,7 +248,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
protected fun showConsensusFor(nodes: List<SimulatedNode>) { protected fun showConsensusFor(nodes: List<SimulatedNode>) {
val node = nodes.first() val node = nodes.first()
node.smm.changes.filter { it.second == AddOrRemove.ADD }.first().subscribe { node.smm.changes.filter { it.second == com.r3corda.node.utilities.AddOrRemove.ADD }.first().subscribe {
linkConsensus(nodes, it.first) linkConsensus(nodes, it.first)
} }
} }

View File

@ -1,4 +1,4 @@
package com.r3corda.node.internal.testing package com.r3corda.simulation
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
@ -12,8 +12,8 @@ import com.r3corda.core.contracts.`issued by`
import com.r3corda.core.days import com.r3corda.core.days
import com.r3corda.core.random63BitValue import com.r3corda.core.random63BitValue
import com.r3corda.core.seconds import com.r3corda.core.seconds
import com.r3corda.node.services.network.InMemoryMessagingNetwork
import com.r3corda.protocols.TwoPartyTradeProtocol import com.r3corda.protocols.TwoPartyTradeProtocol
import com.r3corda.testing.node.InMemoryMessagingNetwork
import java.time.Instant import java.time.Instant
/** /**

View File

@ -2,7 +2,7 @@ package com.r3corda.core.testing
import com.google.common.base.Throwables import com.google.common.base.Throwables
import com.r3corda.core.utilities.LogHelper import com.r3corda.core.utilities.LogHelper
import com.r3corda.node.internal.testing.IRSSimulation import com.r3corda.simulation.IRSSimulation
import org.junit.Test import org.junit.Test
class IRSSimulationTest { class IRSSimulationTest {

View File

@ -1,4 +1,5 @@
apply plugin: 'kotlin' apply plugin: 'kotlin'
apply plugin: QuasarPlugin
repositories { repositories {
mavenLocal() mavenLocal()
@ -20,7 +21,9 @@ configurations {
} }
dependencies { dependencies {
compile project(':contracts')
compile project(':core') compile project(':core')
compile project(':node')
// Log4J: logging framework (with SLF4J bindings) // Log4J: logging framework (with SLF4J bindings)
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}" compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
@ -38,3 +41,5 @@ dependencies {
// Unit testing helpers. // Unit testing helpers.
compile 'junit:junit:4.12' compile 'junit:junit:4.12'
} }
quasarScan.dependsOn('classes', ':core:classes', ':contracts:classes')

View File

@ -1,4 +1,4 @@
package com.r3corda.node.services.network package com.r3corda.testing.node
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
@ -12,7 +12,7 @@ import com.r3corda.core.utilities.loggerFor
import com.r3corda.core.utilities.trace import com.r3corda.core.utilities.trace
import com.r3corda.node.services.api.MessagingServiceBuilder import com.r3corda.node.services.api.MessagingServiceBuilder
import com.r3corda.node.services.api.MessagingServiceInternal import com.r3corda.node.services.api.MessagingServiceInternal
import com.r3corda.node.services.network.InMemoryMessagingNetwork.InMemoryMessaging import com.r3corda.testing.node.InMemoryMessagingNetwork.InMemoryMessaging
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import rx.Observable import rx.Observable
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
@ -80,7 +80,7 @@ class InMemoryMessagingNetwork(val sendManuallyPumped: Boolean) : SingletonSeria
* executor. * executor.
*/ */
@Synchronized @Synchronized
fun createNode(manuallyPumped: Boolean): Pair<Handle, MessagingServiceBuilder<InMemoryMessaging>> { fun createNode(manuallyPumped: Boolean): Pair<Handle, com.r3corda.node.services.api.MessagingServiceBuilder<InMemoryMessaging>> {
check(counter >= 0) { "In memory network stopped: please recreate." } check(counter >= 0) { "In memory network stopped: please recreate." }
val builder = createNodeWithID(manuallyPumped, counter) as Builder val builder = createNodeWithID(manuallyPumped, counter) as Builder
counter++ counter++
@ -95,7 +95,7 @@ class InMemoryMessagingNetwork(val sendManuallyPumped: Boolean) : SingletonSeria
* @param id the numeric ID to use, e.g. set to whatever ID the node used last time. * @param id the numeric ID to use, e.g. set to whatever ID the node used last time.
* @param description text string that identifies this node for message logging (if is enabled) or null to autogenerate. * @param description text string that identifies this node for message logging (if is enabled) or null to autogenerate.
*/ */
fun createNodeWithID(manuallyPumped: Boolean, id: Int, description: String? = null): MessagingServiceBuilder<InMemoryMessaging> { fun createNodeWithID(manuallyPumped: Boolean, id: Int, description: String? = null): com.r3corda.node.services.api.MessagingServiceBuilder<InMemoryMessaging> {
return Builder(manuallyPumped, Handle(id, description ?: "In memory node $id")) return Builder(manuallyPumped, Handle(id, description ?: "In memory node $id"))
} }
@ -136,7 +136,7 @@ class InMemoryMessagingNetwork(val sendManuallyPumped: Boolean) : SingletonSeria
messageReceiveQueues.clear() messageReceiveQueues.clear()
} }
inner class Builder(val manuallyPumped: Boolean, val id: Handle) : MessagingServiceBuilder<InMemoryMessaging> { inner class Builder(val manuallyPumped: Boolean, val id: Handle) : com.r3corda.node.services.api.MessagingServiceBuilder<InMemoryMessaging> {
override fun start(): ListenableFuture<InMemoryMessaging> { override fun start(): ListenableFuture<InMemoryMessaging> {
synchronized(this@InMemoryMessagingNetwork) { synchronized(this@InMemoryMessagingNetwork) {
val node = InMemoryMessaging(manuallyPumped, id) val node = InMemoryMessaging(manuallyPumped, id)
@ -200,7 +200,7 @@ class InMemoryMessagingNetwork(val sendManuallyPumped: Boolean) : SingletonSeria
* An instance can be obtained by creating a builder and then using the start method. * An instance can be obtained by creating a builder and then using the start method.
*/ */
@ThreadSafe @ThreadSafe
inner class InMemoryMessaging(private val manuallyPumped: Boolean, private val handle: Handle) : SingletonSerializeAsToken(), MessagingServiceInternal { inner class InMemoryMessaging(private val manuallyPumped: Boolean, private val handle: Handle) : SingletonSerializeAsToken(), com.r3corda.node.services.api.MessagingServiceInternal {
inner class Handler(val executor: Executor?, val topicSession: TopicSession, inner class Handler(val executor: Executor?, val topicSession: TopicSession,
val callback: (Message, MessageHandlerRegistration) -> Unit) : MessageHandlerRegistration val callback: (Message, MessageHandlerRegistration) -> Unit) : MessageHandlerRegistration

View File

@ -1,4 +1,4 @@
package com.r3corda.node.services.network package com.r3corda.testing.node
import co.paralleluniverse.common.util.VisibleForTesting import co.paralleluniverse.common.util.VisibleForTesting
import com.r3corda.core.crypto.DummyPublicKey import com.r3corda.core.crypto.DummyPublicKey
@ -12,7 +12,7 @@ import rx.subjects.PublishSubject
/** /**
* Network map cache with no backing map service. * Network map cache with no backing map service.
*/ */
class MockNetworkMapCache() : InMemoryNetworkMapCache() { class MockNetworkMapCache() : com.r3corda.node.services.network.InMemoryNetworkMapCache() {
override val changed: Observable<NetworkMapCache.MapChange> = PublishSubject.create<NetworkMapCache.MapChange>() override val changed: Observable<NetworkMapCache.MapChange> = PublishSubject.create<NetworkMapCache.MapChange>()
data class MockAddress(val id: String): SingleMessageRecipient data class MockAddress(val id: String): SingleMessageRecipient

View File

@ -1,6 +1,5 @@
package com.r3corda.node.internal.testing package com.r3corda.testing.node
import com.google.common.jimfs.Configuration
import com.google.common.jimfs.Jimfs import com.google.common.jimfs.Jimfs
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
@ -9,18 +8,10 @@ import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.PhysicalLocation import com.r3corda.core.node.PhysicalLocation
import com.r3corda.core.node.services.ServiceType import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.WalletService import com.r3corda.core.node.services.WalletService
import com.r3corda.testing.node.MockIdentityService
import com.r3corda.testing.node.makeTestDataSourceProperties
import com.r3corda.core.testing.InMemoryWalletService import com.r3corda.core.testing.InMemoryWalletService
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
import com.r3corda.core.utilities.loggerFor import com.r3corda.core.utilities.loggerFor
import com.r3corda.node.internal.AbstractNode
import com.r3corda.node.services.api.MessagingServiceInternal
import com.r3corda.node.services.config.NodeConfiguration import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.network.InMemoryMessagingNetwork
import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.transactions.SimpleNotaryService
import com.r3corda.node.utilities.AffinityExecutor
import org.slf4j.Logger import org.slf4j.Logger
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
@ -43,7 +34,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
private val threadPerNode: Boolean = false, private val threadPerNode: Boolean = false,
private val defaultFactory: Factory = MockNetwork.DefaultFactory) { private val defaultFactory: Factory = MockNetwork.DefaultFactory) {
private var counter = 0 private var counter = 0
val filesystem = Jimfs.newFileSystem(Configuration.unix()) val filesystem = com.google.common.jimfs.Jimfs.newFileSystem(com.google.common.jimfs.Configuration.unix())
val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped) val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped)
val identities = ArrayList<Party>() val identities = ArrayList<Party>()
@ -70,18 +61,18 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
} }
open class MockNode(dir: Path, config: NodeConfiguration, val mockNet: MockNetwork, networkMapAddr: NodeInfo?, open class MockNode(dir: Path, config: NodeConfiguration, val mockNet: MockNetwork, networkMapAddr: NodeInfo?,
advertisedServices: Set<ServiceType>, val id: Int, val keyPair: KeyPair?) : AbstractNode(dir, config, networkMapAddr, advertisedServices, TestClock()) { advertisedServices: Set<ServiceType>, val id: Int, val keyPair: KeyPair?) : com.r3corda.node.internal.AbstractNode(dir, config, networkMapAddr, advertisedServices, TestClock()) {
override val log: Logger = loggerFor<MockNode>() override val log: Logger = loggerFor<MockNode>()
override val serverThread: AffinityExecutor = override val serverThread: com.r3corda.node.utilities.AffinityExecutor =
if (mockNet.threadPerNode) if (mockNet.threadPerNode)
AffinityExecutor.ServiceAffinityExecutor("Mock node thread", 1) com.r3corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor("Mock node thread", 1)
else else
AffinityExecutor.SAME_THREAD com.r3corda.node.utilities.AffinityExecutor.Companion.SAME_THREAD
// We only need to override the messaging service here, as currently everything that hits disk does so // We only need to override the messaging service here, as currently everything that hits disk does so
// through the java.nio API which we are already mocking via Jimfs. // through the java.nio API which we are already mocking via Jimfs.
override fun makeMessagingService(): MessagingServiceInternal { override fun makeMessagingService(): com.r3corda.node.services.api.MessagingServiceInternal {
require(id >= 0) { "Node ID must be zero or positive, was passed: " + id } require(id >= 0) { "Node ID must be zero or positive, was passed: " + id }
return mockNet.messagingNetwork.createNodeWithID(!mockNet.threadPerNode, id, configuration.myLegalName).start().get() return mockNet.messagingNetwork.createNodeWithID(!mockNet.threadPerNode, id, configuration.myLegalName).start().get()
} }
@ -169,7 +160,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
fun createTwoNodes(nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = null): Pair<MockNode, MockNode> { fun createTwoNodes(nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = null): Pair<MockNode, MockNode> {
require(nodes.isEmpty()) require(nodes.isEmpty())
return Pair( return Pair(
createNode(null, -1, nodeFactory, true, null, notaryKeyPair, false, NetworkMapService.Type, SimpleNotaryService.Type), createNode(null, -1, nodeFactory, true, null, notaryKeyPair, false, com.r3corda.node.services.network.NetworkMapService.Type, com.r3corda.node.services.transactions.SimpleNotaryService.Type),
createNode(nodes[0].info, -1, nodeFactory, true, null) createNode(nodes[0].info, -1, nodeFactory, true, null)
) )
} }
@ -186,9 +177,9 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
*/ */
fun createSomeNodes(numPartyNodes: Int = 2, nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = DUMMY_NOTARY_KEY): BasketOfNodes { fun createSomeNodes(numPartyNodes: Int = 2, nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = DUMMY_NOTARY_KEY): BasketOfNodes {
require(nodes.isEmpty()) require(nodes.isEmpty())
val mapNode = createNode(null, nodeFactory = nodeFactory, advertisedServices = NetworkMapService.Type) val mapNode = createNode(null, nodeFactory = nodeFactory, advertisedServices = com.r3corda.node.services.network.NetworkMapService.Type)
val notaryNode = createNode(mapNode.info, nodeFactory = nodeFactory, keyPair = notaryKeyPair, val notaryNode = createNode(mapNode.info, nodeFactory = nodeFactory, keyPair = notaryKeyPair,
advertisedServices = SimpleNotaryService.Type) advertisedServices = com.r3corda.node.services.transactions.SimpleNotaryService.Type)
val nodes = ArrayList<MockNode>() val nodes = ArrayList<MockNode>()
repeat(numPartyNodes) { repeat(numPartyNodes) {
nodes += createPartyNode(mapNode.info) nodes += createPartyNode(mapNode.info)
@ -197,7 +188,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
} }
fun createNotaryNode(legalName: String? = null, keyPair: KeyPair? = null): MockNode { fun createNotaryNode(legalName: String? = null, keyPair: KeyPair? = null): MockNode {
return createNode(null, -1, defaultFactory, true, legalName, keyPair, false, NetworkMapService.Type, SimpleNotaryService.Type) return createNode(null, -1, defaultFactory, true, legalName, keyPair, false, com.r3corda.node.services.network.NetworkMapService.Type, com.r3corda.node.services.transactions.SimpleNotaryService.Type)
} }
fun createPartyNode(networkMapAddr: NodeInfo, legalName: String? = null, keyPair: KeyPair? = null): MockNode { fun createPartyNode(networkMapAddr: NodeInfo, legalName: String? = null, keyPair: KeyPair? = null): MockNode {

View File

@ -1,4 +1,4 @@
package com.r3corda.node.internal.testing package com.r3corda.testing.node
import com.r3corda.core.serialization.SerializeAsToken import com.r3corda.core.serialization.SerializeAsToken
import com.r3corda.core.serialization.SerializeAsTokenContext import com.r3corda.core.serialization.SerializeAsTokenContext
@ -15,7 +15,7 @@ import javax.annotation.concurrent.ThreadSafe
* A [Clock] that can have the time advanced for use in testing. * A [Clock] that can have the time advanced for use in testing.
*/ */
@ThreadSafe @ThreadSafe
class TestClock(private var delegateClock: Clock = Clock.systemUTC()) : MutableClock(), SerializeAsToken { class TestClock(private var delegateClock: Clock = Clock.systemUTC()) : com.r3corda.node.utilities.MutableClock(), SerializeAsToken {
private val token = SingletonSerializationToken(this) private val token = SingletonSerializationToken(this)