CORDA-716 Make serialization init less static (#1996)

This commit is contained in:
Andrzej Cichocki
2017-11-10 15:44:43 +00:00
committed by GitHub
parent cc4c732a48
commit 052124bbe0
29 changed files with 463 additions and 346 deletions

View File

@ -17,26 +17,21 @@ import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.loggerFor
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.internal.cordapp.CordappProviderImpl
import net.corda.testing.*
import net.corda.testing.DUMMY_BANK_A
import net.corda.testing.DUMMY_NOTARY
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.driver.DriverDSLExposedInterface
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver
import net.corda.testing.node.MockServices
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.net.URLClassLoader
import java.nio.file.Files
import kotlin.test.assertFailsWith
class AttachmentLoadingTests {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
private class Services : MockServices() {
private val provider = CordappProviderImpl(CordappLoader.createDevMode(listOf(isolatedJAR)), attachments)
private val cordapp get() = provider.cordapps.first()
@ -83,7 +78,7 @@ class AttachmentLoadingTests {
}
@Test
fun `test a wire transaction has loaded the correct attachment`() {
fun `test a wire transaction has loaded the correct attachment`() = withTestSerialization {
val appClassLoader = services.appContext.classLoader
val contractClass = appClassLoader.loadClass(ISOLATED_CONTRACT_ID).asSubclass(Contract::class.java)
val generateInitialMethod = contractClass.getDeclaredMethod("generateInitial", PartyAndReference::class.java, Integer.TYPE, Party::class.java)
@ -101,7 +96,7 @@ class AttachmentLoadingTests {
@Test
fun `test that attachments retrieved over the network are not used for code`() {
driver(initialiseSerialization = false) {
driver {
installIsolatedCordappTo(bankAName)
val (bankA, bankB) = createTwoNodes()
assertFailsWith<UnexpectedFlowEndException>("Party C=CH,L=Zurich,O=BankB rejected session request: Don't know net.corda.finance.contracts.isolated.IsolatedDummyFlow\$Initiator") {
@ -112,7 +107,7 @@ class AttachmentLoadingTests {
@Test
fun `tests that if the attachment is loaded on both sides already that a flow can run`() {
driver(initialiseSerialization = false) {
driver {
installIsolatedCordappTo(bankAName)
installIsolatedCordappTo(bankBName)
val (bankA, bankB) = createTwoNodes()

View File

@ -10,11 +10,13 @@ import net.corda.nodeapi.NodeInfoFilesCopier
import net.corda.testing.ALICE
import net.corda.testing.ALICE_KEY
import net.corda.testing.getTestPartyAndCertificate
import net.corda.testing.internal.NodeBasedTest
import net.corda.testing.*
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.contentOf
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import rx.observers.TestSubscriber
import rx.schedulers.TestScheduler
import java.nio.file.Path
@ -22,11 +24,17 @@ import java.util.concurrent.TimeUnit
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class NodeInfoWatcherTest : NodeBasedTest() {
class NodeInfoWatcherTest {
companion object {
val nodeInfo = NodeInfo(listOf(), listOf(getTestPartyAndCertificate(ALICE)), 0, 0)
}
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
@Rule
@JvmField
val tempFolder = TemporaryFolder()
private lateinit var nodeInfoPath: Path
private val scheduler = TestScheduler()
private val testSubscriber = TestSubscriber<NodeInfo>()

View File

@ -9,9 +9,10 @@ import net.corda.core.internal.concurrent.thenMatch
import net.corda.core.internal.uncheckedCast
import net.corda.core.messaging.RPCOps
import net.corda.core.node.ServiceHub
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.loggerFor
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
import net.corda.core.serialization.internal.nodeSerializationEnv
import net.corda.node.VersionInfo
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.serialization.KryoServerSerializationScheme
@ -25,7 +26,6 @@ import net.corda.node.services.messaging.NodeMessagingClient
import net.corda.node.utilities.AddressUtils
import net.corda.node.utilities.AffinityExecutor
import net.corda.node.utilities.DemoClock
import net.corda.nodeapi.ArtemisMessagingComponent
import net.corda.nodeapi.internal.ShutdownHook
import net.corda.nodeapi.internal.addShutdownHook
import net.corda.nodeapi.internal.serialization.*
@ -274,14 +274,15 @@ open class Node(configuration: NodeConfiguration,
private fun initialiseSerialization() {
val classloader = cordappLoader.appClassLoader
SerializationDefaults.SERIALIZATION_FACTORY = SerializationFactoryImpl().apply {
registerScheme(KryoServerSerializationScheme())
registerScheme(AMQPServerSerializationScheme())
}
SerializationDefaults.P2P_CONTEXT = KRYO_P2P_CONTEXT.withClassLoader(classloader)
SerializationDefaults.RPC_SERVER_CONTEXT = KRYO_RPC_SERVER_CONTEXT.withClassLoader(classloader)
SerializationDefaults.STORAGE_CONTEXT = KRYO_STORAGE_CONTEXT.withClassLoader(classloader)
SerializationDefaults.CHECKPOINT_CONTEXT = KRYO_CHECKPOINT_CONTEXT.withClassLoader(classloader)
nodeSerializationEnv = SerializationEnvironmentImpl(
SerializationFactoryImpl().apply {
registerScheme(KryoServerSerializationScheme())
registerScheme(AMQPServerSerializationScheme())
},
KRYO_P2P_CONTEXT.withClassLoader(classloader),
rpcServerContext = KRYO_RPC_SERVER_CONTEXT.withClassLoader(classloader),
storageContext = KRYO_STORAGE_CONTEXT.withClassLoader(classloader),
checkpointContext = KRYO_CHECKPOINT_CONTEXT.withClassLoader(classloader))
}
/** Starts a blocking event loop for message dispatch. */

View File

@ -11,6 +11,7 @@ import net.corda.core.node.services.PartyInfo
import net.corda.core.node.services.TransactionVerifierService
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.internal.nodeSerializationEnv
import net.corda.core.serialization.serialize
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.utilities.NetworkHostAndPort
@ -217,6 +218,7 @@ class NodeMessagingClient(override val config: NodeConfiguration,
locator.connectionTTL = -1
locator.clientFailureCheckPeriod = -1
locator.minLargeMessageSize = ArtemisMessagingServer.MAX_FILE_SIZE
locator.isUseGlobalPools = nodeSerializationEnv != null
sessionFactory = locator.createSessionFactory()
// Login using the node username. The broker will authentiate us as its node (as opposed to another peer)

View File

@ -60,7 +60,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
val testSerialization = SerializationEnvironmentRule(true)
private val realClock: Clock = Clock.systemUTC()
private val stoppedClock: Clock = Clock.fixed(realClock.instant(), realClock.zone)
private val testClock = TestClock(stoppedClock)

View File

@ -41,7 +41,7 @@ import kotlin.test.assertEquals
class HTTPNetworkMapClientTest {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
val testSerialization = SerializationEnvironmentRule(true)
private lateinit var server: Server
private lateinit var networkMapClient: NetworkMapClient

View File

@ -30,7 +30,7 @@ class DistributedImmutableMapTests {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
val testSerialization = SerializationEnvironmentRule(true)
lateinit var cluster: List<Member>
lateinit var transaction: DatabaseTransaction
private val databases: MutableList<CordaPersistence> = mutableListOf()

View File

@ -1,9 +1,12 @@
package net.corda.node.services.vault
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.InsufficientBalanceException
import net.corda.core.contracts.LinearState
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.identity.AnonymousParty
import net.corda.core.internal.concurrent.fork
import net.corda.core.internal.concurrent.transpose
import net.corda.core.internal.packageName
import net.corda.core.node.services.Vault
import net.corda.core.node.services.VaultService
@ -11,6 +14,7 @@ import net.corda.core.node.services.queryBy
import net.corda.core.node.services.vault.QueryCriteria
import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow
import net.corda.finance.*
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER
@ -29,9 +33,9 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.util.*
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import kotlin.test.assertEquals
import kotlin.test.fail
// TODO: Move this to the cash contract tests once mock services are further split up.
@ -42,7 +46,7 @@ class VaultWithCashTest {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
val testSerialization = SerializationEnvironmentRule(true)
lateinit var services: MockServices
lateinit var issuerServices: MockServices
val vaultService: VaultService get() = services.vaultService
@ -150,82 +154,74 @@ class VaultWithCashTest {
}
val backgroundExecutor = Executors.newFixedThreadPool(2)
val countDown = CountDownLatch(2)
// 1st tx that spends our money.
backgroundExecutor.submit {
val first = backgroundExecutor.fork {
database.transaction {
try {
val txn1Builder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, txn1Builder, 60.DOLLARS, BOB)
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
val txn1 = services.addSignature(ptxn1, freshKey)
println("txn1: ${txn1.id} spent ${((txn1.tx.outputs[0].data) as Cash.State).amount}")
val unconsumedStates1 = vaultService.queryBy<Cash.State>()
val consumedStates1 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
val lockedStates1 = vaultService.queryBy<Cash.State>(criteriaLocked).states
println("""txn1 states:
val txn1Builder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, txn1Builder, 60.DOLLARS, BOB)
val ptxn1 = notaryServices.signInitialTransaction(txn1Builder)
val txn1 = services.addSignature(ptxn1, freshKey)
println("txn1: ${txn1.id} spent ${((txn1.tx.outputs[0].data) as Cash.State).amount}")
val unconsumedStates1 = vaultService.queryBy<Cash.State>()
val consumedStates1 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
val lockedStates1 = vaultService.queryBy<Cash.State>(criteriaLocked).states
println("""txn1 states:
UNCONSUMED: ${unconsumedStates1.totalStatesAvailable} : $unconsumedStates1,
CONSUMED: ${consumedStates1.totalStatesAvailable} : $consumedStates1,
LOCKED: ${lockedStates1.count()} : $lockedStates1
""")
services.recordTransactions(txn1)
println("txn1: Cash balance: ${services.getCashBalance(USD)}")
val unconsumedStates2 = vaultService.queryBy<Cash.State>()
val consumedStates2 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
val lockedStates2 = vaultService.queryBy<Cash.State>(criteriaLocked).states
println("""txn1 states:
services.recordTransactions(txn1)
println("txn1: Cash balance: ${services.getCashBalance(USD)}")
val unconsumedStates2 = vaultService.queryBy<Cash.State>()
val consumedStates2 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
val lockedStates2 = vaultService.queryBy<Cash.State>(criteriaLocked).states
println("""txn1 states:
UNCONSUMED: ${unconsumedStates2.totalStatesAvailable} : $unconsumedStates2,
CONSUMED: ${consumedStates2.totalStatesAvailable} : $consumedStates2,
LOCKED: ${lockedStates2.count()} : $lockedStates2
""")
txn1
} catch (e: Exception) {
println(e)
}
txn1
}
println("txn1 COMMITTED!")
countDown.countDown()
}
// 2nd tx that attempts to spend same money
backgroundExecutor.submit {
val second = backgroundExecutor.fork {
database.transaction {
try {
val txn2Builder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, txn2Builder, 80.DOLLARS, BOB)
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
val txn2 = services.addSignature(ptxn2, freshKey)
println("txn2: ${txn2.id} spent ${((txn2.tx.outputs[0].data) as Cash.State).amount}")
val unconsumedStates1 = vaultService.queryBy<Cash.State>()
val consumedStates1 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
val lockedStates1 = vaultService.queryBy<Cash.State>(criteriaLocked).states
println("""txn2 states:
val txn2Builder = TransactionBuilder(DUMMY_NOTARY)
Cash.generateSpend(services, txn2Builder, 80.DOLLARS, BOB)
val ptxn2 = notaryServices.signInitialTransaction(txn2Builder)
val txn2 = services.addSignature(ptxn2, freshKey)
println("txn2: ${txn2.id} spent ${((txn2.tx.outputs[0].data) as Cash.State).amount}")
val unconsumedStates1 = vaultService.queryBy<Cash.State>()
val consumedStates1 = vaultService.queryBy<Cash.State>(VaultQueryCriteria(status = Vault.StateStatus.CONSUMED))
val lockedStates1 = vaultService.queryBy<Cash.State>(criteriaLocked).states
println("""txn2 states:
UNCONSUMED: ${unconsumedStates1.totalStatesAvailable} : $unconsumedStates1,
CONSUMED: ${consumedStates1.totalStatesAvailable} : $consumedStates1,
LOCKED: ${lockedStates1.count()} : $lockedStates1
""")
services.recordTransactions(txn2)
println("txn2: Cash balance: ${services.getCashBalance(USD)}")
val unconsumedStates2 = vaultService.queryBy<Cash.State>()
val consumedStates2 = vaultService.queryBy<Cash.State>()
val lockedStates2 = vaultService.queryBy<Cash.State>(criteriaLocked).states
println("""txn2 states:
services.recordTransactions(txn2)
println("txn2: Cash balance: ${services.getCashBalance(USD)}")
val unconsumedStates2 = vaultService.queryBy<Cash.State>()
val consumedStates2 = vaultService.queryBy<Cash.State>()
val lockedStates2 = vaultService.queryBy<Cash.State>(criteriaLocked).states
println("""txn2 states:
UNCONSUMED: ${unconsumedStates2.totalStatesAvailable} : $unconsumedStates2,
CONSUMED: ${consumedStates2.totalStatesAvailable} : $consumedStates2,
LOCKED: ${lockedStates2.count()} : $lockedStates2
""")
txn2
} catch (e: Exception) {
println(e)
}
txn2
}
println("txn2 COMMITTED!")
countDown.countDown()
}
countDown.await()
val both = listOf(first, second).transpose()
try {
both.getOrThrow()
fail("Expected insufficient balance.")
} catch (e: InsufficientBalanceException) {
assertEquals(0, e.suppressed.size) // One should succeed.
}
database.transaction {
println("Cash balance: ${services.getCashBalance(USD)}")
assertThat(services.getCashBalance(USD)).isIn(DOLLARS(20), DOLLARS(40))