mirror of
https://github.com/corda/corda.git
synced 2025-06-21 16:49:45 +00:00
CORDA-1747 - Client RPC classloader and Java Generics fixes (#3553)
* fix for spring boot rpc and it work with deterministic serialization * really really fix tests * up log level * reenable allWarningsAsErrors
This commit is contained in:
12
build.gradle
12
build.gradle
@ -382,20 +382,20 @@ artifactory {
|
|||||||
|
|
||||||
defaults {
|
defaults {
|
||||||
// Root project applies the plugin (for this block) but does not need to be published
|
// Root project applies the plugin (for this block) but does not need to be published
|
||||||
if(project != rootProject) {
|
if (project != rootProject) {
|
||||||
publications(project.extensions.publish.name())
|
publications(project.extensions.publish.name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task generateApi(type: net.corda.plugins.GenerateApi){
|
task generateApi(type: net.corda.plugins.GenerateApi) {
|
||||||
baseName = "api-corda"
|
baseName = "api-corda"
|
||||||
}
|
}
|
||||||
|
|
||||||
// This exists to reduce CI build time when the envvar is set (can save up to 40 minutes)
|
// This exists to reduce CI build time when the envvar is set (can save up to 40 minutes)
|
||||||
if(file('corda-docs-only-build').exists() || (System.getenv('CORDA_DOCS_ONLY_BUILD') != null)) {
|
if (file('corda-docs-only-build').exists() || (System.getenv('CORDA_DOCS_ONLY_BUILD') != null)) {
|
||||||
if(file('corda-docs-only-build').exists()) {
|
if (file('corda-docs-only-build').exists()) {
|
||||||
logger.info("Tests are disabled due to presence of file 'corda-docs-only-build' in the project root")
|
logger.info("Tests are disabled due to presence of file 'corda-docs-only-build' in the project root")
|
||||||
} else {
|
} else {
|
||||||
logger.info("Tests are disabled due to the presence of envvar CORDA_DOCS_ONLY_BUILD")
|
logger.info("Tests are disabled due to the presence of envvar CORDA_DOCS_ONLY_BUILD")
|
||||||
@ -407,7 +407,7 @@ if(file('corda-docs-only-build').exists() || (System.getenv('CORDA_DOCS_ONLY_BUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
it.afterEvaluate {
|
it.afterEvaluate {
|
||||||
if(it.tasks.findByName("integrationTest") != null) {
|
if (it.tasks.findByName("integrationTest") != null) {
|
||||||
integrationTest {
|
integrationTest {
|
||||||
exclude '*/**'
|
exclude '*/**'
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ if(file('corda-docs-only-build').exists() || (System.getenv('CORDA_DOCS_ONLY_BUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
it.afterEvaluate {
|
it.afterEvaluate {
|
||||||
if(it.tasks.findByName("smokeTest") != null) {
|
if (it.tasks.findByName("smokeTest") != null) {
|
||||||
smokeTest {
|
smokeTest {
|
||||||
exclude '*/**'
|
exclude '*/**'
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import net.corda.core.serialization.internal.SerializationEnvironmentImpl
|
|||||||
import net.corda.core.serialization.internal.nodeSerializationEnv
|
import net.corda.core.serialization.internal.nodeSerializationEnv
|
||||||
import net.corda.serialization.internal.*
|
import net.corda.serialization.internal.*
|
||||||
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
||||||
|
import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap
|
||||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
import net.corda.serialization.internal.amqp.amqpMagic
|
import net.corda.serialization.internal.amqp.amqpMagic
|
||||||
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
|
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
|
||||||
@ -21,12 +22,12 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
*/
|
*/
|
||||||
class AMQPClientSerializationScheme(
|
class AMQPClientSerializationScheme(
|
||||||
cordappCustomSerializers: Set<SerializationCustomSerializer<*,*>>,
|
cordappCustomSerializers: Set<SerializationCustomSerializer<*,*>>,
|
||||||
serializerFactoriesForContexts: MutableMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>
|
serializerFactoriesForContexts: AccessOrderLinkedHashMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>
|
||||||
) : AbstractAMQPSerializationScheme(cordappCustomSerializers, serializerFactoriesForContexts) {
|
) : AbstractAMQPSerializationScheme(cordappCustomSerializers, serializerFactoriesForContexts) {
|
||||||
constructor(cordapps: List<Cordapp>) : this(cordapps.customSerializers, ConcurrentHashMap())
|
constructor(cordapps: List<Cordapp>) : this(cordapps.customSerializers, AccessOrderLinkedHashMap { 128 })
|
||||||
|
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
constructor() : this(emptySet(), ConcurrentHashMap())
|
constructor() : this(emptySet(), AccessOrderLinkedHashMap { 128 })
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** Call from main only. */
|
/** Call from main only. */
|
||||||
@ -52,7 +53,7 @@ class AMQPClientSerializationScheme(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
|
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
|
||||||
return SerializerFactory(context.whitelist, ClassLoader.getSystemClassLoader(), context.lenientCarpenterEnabled).apply {
|
return SerializerFactory(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply {
|
||||||
register(RpcClientObservableSerializer)
|
register(RpcClientObservableSerializer)
|
||||||
register(RpcClientCordaFutureSerializer(this))
|
register(RpcClientCordaFutureSerializer(this))
|
||||||
register(RxNotificationSerializer(this))
|
register(RxNotificationSerializer(this))
|
||||||
|
@ -2,12 +2,13 @@ package net.corda.deterministic.common
|
|||||||
|
|
||||||
import net.corda.core.serialization.ClassWhitelist
|
import net.corda.core.serialization.ClassWhitelist
|
||||||
import net.corda.core.serialization.SerializationContext
|
import net.corda.core.serialization.SerializationContext
|
||||||
import net.corda.core.serialization.SerializationContext.UseCase.*
|
import net.corda.core.serialization.SerializationContext.UseCase.P2P
|
||||||
import net.corda.core.serialization.SerializationCustomSerializer
|
import net.corda.core.serialization.SerializationCustomSerializer
|
||||||
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
|
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
|
||||||
import net.corda.core.serialization.internal._contextSerializationEnv
|
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||||
import net.corda.serialization.internal.*
|
import net.corda.serialization.internal.*
|
||||||
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
||||||
|
import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap
|
||||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
import net.corda.serialization.internal.amqp.amqpMagic
|
import net.corda.serialization.internal.amqp.amqpMagic
|
||||||
import org.junit.rules.TestRule
|
import org.junit.rules.TestRule
|
||||||
@ -21,13 +22,13 @@ class LocalSerializationRule(private val label: String) : TestRule {
|
|||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private val AMQP_P2P_CONTEXT = SerializationContextImpl(
|
private val AMQP_P2P_CONTEXT = SerializationContextImpl(
|
||||||
amqpMagic,
|
amqpMagic,
|
||||||
LocalSerializationRule::class.java.classLoader,
|
LocalSerializationRule::class.java.classLoader,
|
||||||
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
||||||
emptyMap(),
|
emptyMap(),
|
||||||
true,
|
true,
|
||||||
P2P,
|
P2P,
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ class LocalSerializationRule(private val label: String) : TestRule {
|
|||||||
|
|
||||||
private fun createTestSerializationEnv(): SerializationEnvironmentImpl {
|
private fun createTestSerializationEnv(): SerializationEnvironmentImpl {
|
||||||
val factory = SerializationFactoryImpl(mutableMapOf()).apply {
|
val factory = SerializationFactoryImpl(mutableMapOf()).apply {
|
||||||
registerScheme(AMQPSerializationScheme(emptySet(), mutableMapOf()))
|
registerScheme(AMQPSerializationScheme(emptySet(), AccessOrderLinkedHashMap(128)))
|
||||||
}
|
}
|
||||||
return object : SerializationEnvironmentImpl(factory, AMQP_P2P_CONTEXT) {
|
return object : SerializationEnvironmentImpl(factory, AMQP_P2P_CONTEXT) {
|
||||||
override fun toString() = "testSerializationEnv($label)"
|
override fun toString() = "testSerializationEnv($label)"
|
||||||
@ -67,8 +68,8 @@ class LocalSerializationRule(private val label: String) : TestRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class AMQPSerializationScheme(
|
private class AMQPSerializationScheme(
|
||||||
cordappCustomSerializers: Set<SerializationCustomSerializer<*, *>>,
|
cordappCustomSerializers: Set<SerializationCustomSerializer<*, *>>,
|
||||||
serializerFactoriesForContexts: MutableMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>
|
serializerFactoriesForContexts: AccessOrderLinkedHashMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>
|
||||||
) : AbstractAMQPSerializationScheme(cordappCustomSerializers, serializerFactoriesForContexts) {
|
) : AbstractAMQPSerializationScheme(cordappCustomSerializers, serializerFactoriesForContexts) {
|
||||||
override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory {
|
override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory {
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
|
@ -174,7 +174,6 @@ interface SerializationContext {
|
|||||||
/**
|
/**
|
||||||
* Helper method to return a new context based on this context with the deserialization class loader changed.
|
* Helper method to return a new context based on this context with the deserialization class loader changed.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
fun withClassLoader(classLoader: ClassLoader): SerializationContext
|
fun withClassLoader(classLoader: ClassLoader): SerializationContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,6 +6,7 @@ import net.corda.core.serialization.SerializationContext
|
|||||||
import net.corda.core.serialization.SerializationCustomSerializer
|
import net.corda.core.serialization.SerializationCustomSerializer
|
||||||
import net.corda.serialization.internal.CordaSerializationMagic
|
import net.corda.serialization.internal.CordaSerializationMagic
|
||||||
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
||||||
|
import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap
|
||||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
|
import net.corda.serialization.internal.amqp.custom.RxNotificationSerializer
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
@ -16,11 +17,11 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
*/
|
*/
|
||||||
class AMQPServerSerializationScheme(
|
class AMQPServerSerializationScheme(
|
||||||
cordappCustomSerializers: Set<SerializationCustomSerializer<*, *>>,
|
cordappCustomSerializers: Set<SerializationCustomSerializer<*, *>>,
|
||||||
serializerFactoriesForContexts: MutableMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>
|
serializerFactoriesForContexts: AccessOrderLinkedHashMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>
|
||||||
) : AbstractAMQPSerializationScheme(cordappCustomSerializers, serializerFactoriesForContexts) {
|
) : AbstractAMQPSerializationScheme(cordappCustomSerializers, serializerFactoriesForContexts) {
|
||||||
constructor(cordapps: List<Cordapp>) : this(cordapps.customSerializers, ConcurrentHashMap())
|
constructor(cordapps: List<Cordapp>) : this(cordapps.customSerializers, AccessOrderLinkedHashMap { 128 })
|
||||||
|
|
||||||
constructor() : this(emptySet(), ConcurrentHashMap())
|
constructor() : this(emptySet(), AccessOrderLinkedHashMap { 128 })
|
||||||
|
|
||||||
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
|
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
|
@ -13,6 +13,7 @@ import net.corda.node.internal.serialization.testutils.serializationContext
|
|||||||
import net.corda.node.serialization.amqp.RpcServerObservableSerializer
|
import net.corda.node.serialization.amqp.RpcServerObservableSerializer
|
||||||
import net.corda.node.services.messaging.ObservableSubscription
|
import net.corda.node.services.messaging.ObservableSubscription
|
||||||
import net.corda.nodeapi.RPCApi
|
import net.corda.nodeapi.RPCApi
|
||||||
|
import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap
|
||||||
import net.corda.serialization.internal.amqp.DeserializationInput
|
import net.corda.serialization.internal.amqp.DeserializationInput
|
||||||
import net.corda.serialization.internal.amqp.SerializationOutput
|
import net.corda.serialization.internal.amqp.SerializationOutput
|
||||||
import org.apache.activemq.artemis.api.core.SimpleString
|
import org.apache.activemq.artemis.api.core.SimpleString
|
||||||
@ -59,7 +60,7 @@ class RoundTripObservableSerializerTests {
|
|||||||
@Test
|
@Test
|
||||||
fun roundTripTest1() {
|
fun roundTripTest1() {
|
||||||
val serializationScheme = AMQPRoundTripRPCSerializationScheme(
|
val serializationScheme = AMQPRoundTripRPCSerializationScheme(
|
||||||
serializationContext, emptySet(), ConcurrentHashMap())
|
serializationContext, emptySet(), AccessOrderLinkedHashMap { 128 })
|
||||||
|
|
||||||
// Fake up a message ID, needs to be used on both "sides". The server setting it in the subscriptionMap,
|
// Fake up a message ID, needs to be used on both "sides". The server setting it in the subscriptionMap,
|
||||||
// the client as a property of the deserializer which, in the actual RPC client, is pulled off of
|
// the client as a property of the deserializer which, in the actual RPC client, is pulled off of
|
||||||
|
@ -11,6 +11,7 @@ import net.corda.serialization.internal.CordaSerializationMagic
|
|||||||
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
||||||
import net.corda.serialization.internal.amqp.SerializerFactory
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
import net.corda.serialization.internal.AllWhitelist
|
import net.corda.serialization.internal.AllWhitelist
|
||||||
|
import net.corda.serialization.internal.amqp.AccessOrderLinkedHashMap
|
||||||
import net.corda.client.rpc.internal.ObservableContext as ClientObservableContext
|
import net.corda.client.rpc.internal.ObservableContext as ClientObservableContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,7 +23,7 @@ import net.corda.client.rpc.internal.ObservableContext as ClientObservableContex
|
|||||||
class AMQPRoundTripRPCSerializationScheme(
|
class AMQPRoundTripRPCSerializationScheme(
|
||||||
private val serializationContext: SerializationContext,
|
private val serializationContext: SerializationContext,
|
||||||
cordappCustomSerializers: Set<SerializationCustomSerializer<*, *>>,
|
cordappCustomSerializers: Set<SerializationCustomSerializer<*, *>>,
|
||||||
serializerFactoriesForContexts: MutableMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>)
|
serializerFactoriesForContexts: AccessOrderLinkedHashMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>)
|
||||||
: AbstractAMQPSerializationScheme(
|
: AbstractAMQPSerializationScheme(
|
||||||
cordappCustomSerializers, serializerFactoriesForContexts
|
cordappCustomSerializers, serializerFactoriesForContexts
|
||||||
) {
|
) {
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package net.corda.serialization.internal.amqp.custom
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import org.hamcrest.CoreMatchers.`is`
|
||||||
|
import org.hamcrest.CoreMatchers.nullValue
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mockito.Mockito
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class OptionalSerializerTest {
|
||||||
|
@Test
|
||||||
|
fun `should convert optional with item to proxy`() {
|
||||||
|
val opt = Optional.of("GenericTestString")
|
||||||
|
val proxy = OptionalSerializer(Mockito.mock(SerializerFactory::class.java)).toProxy(opt)
|
||||||
|
Assert.assertThat(proxy.item, `is`<Any>("GenericTestString"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should convert optional without item to empty proxy`() {
|
||||||
|
val opt = Optional.ofNullable<String>(null)
|
||||||
|
val proxy = OptionalSerializer(Mockito.mock(SerializerFactory::class.java)).toProxy(opt)
|
||||||
|
Assert.assertThat(proxy.item, `is`(nullValue()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should convert proxy without item to empty optional `() {
|
||||||
|
val proxy = OptionalSerializer.OptionalProxy(null)
|
||||||
|
val opt = OptionalSerializer(Mockito.mock(SerializerFactory::class.java)).fromProxy(proxy)
|
||||||
|
Assert.assertThat(opt.isPresent, `is`(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should convert proxy with item to empty optional `() {
|
||||||
|
val proxy = OptionalSerializer.OptionalProxy("GenericTestString")
|
||||||
|
val opt = OptionalSerializer(Mockito.mock(SerializerFactory::class.java)).fromProxy(proxy)
|
||||||
|
Assert.assertThat(opt.get(), `is`<Any>("GenericTestString"))
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,7 @@ task patchSerialization(type: Zip, dependsOn: serializationJarTask) {
|
|||||||
exclude 'net/corda/serialization/internal/DefaultWhitelist*'
|
exclude 'net/corda/serialization/internal/DefaultWhitelist*'
|
||||||
exclude 'net/corda/serialization/internal/amqp/AMQPSerializerFactories*'
|
exclude 'net/corda/serialization/internal/amqp/AMQPSerializerFactories*'
|
||||||
exclude 'net/corda/serialization/internal/amqp/AMQPStreams*'
|
exclude 'net/corda/serialization/internal/amqp/AMQPStreams*'
|
||||||
|
exclude 'net/corda/serialization/internal/amqp/AMQPSerializationThreadContext*'
|
||||||
}
|
}
|
||||||
|
|
||||||
reproducibleFileOrder = true
|
reproducibleFileOrder = true
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
@file:JvmName("AMQPSerializationThreadContext")
|
||||||
|
package net.corda.serialization.internal.amqp
|
||||||
|
|
||||||
|
fun getContextClassLoader(): ClassLoader {
|
||||||
|
return ClassLoader.getSystemClassLoader()
|
||||||
|
}
|
@ -12,10 +12,12 @@ import net.corda.core.internal.uncheckedCast
|
|||||||
import net.corda.core.serialization.*
|
import net.corda.core.serialization.*
|
||||||
import net.corda.core.utilities.ByteSequence
|
import net.corda.core.utilities.ByteSequence
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.serialization.internal.*
|
import net.corda.serialization.internal.CordaSerializationMagic
|
||||||
|
import net.corda.serialization.internal.DefaultWhitelist
|
||||||
|
import net.corda.serialization.internal.MutableClassWhitelist
|
||||||
|
import net.corda.serialization.internal.SerializationScheme
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
|
|
||||||
val AMQP_ENABLED get() = SerializationDefaults.P2P_CONTEXT.preferredSerializationVersion == amqpMagic
|
val AMQP_ENABLED get() = SerializationDefaults.P2P_CONTEXT.preferredSerializationVersion == amqpMagic
|
||||||
|
|
||||||
@ -37,12 +39,12 @@ interface SerializerFactoryFactory {
|
|||||||
|
|
||||||
@KeepForDJVM
|
@KeepForDJVM
|
||||||
abstract class AbstractAMQPSerializationScheme(
|
abstract class AbstractAMQPSerializationScheme(
|
||||||
private val cordappCustomSerializers: Set<SerializationCustomSerializer<*,*>>,
|
private val cordappCustomSerializers: Set<SerializationCustomSerializer<*, *>>,
|
||||||
private val serializerFactoriesForContexts: MutableMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>,
|
private val serializerFactoriesForContexts: AccessOrderLinkedHashMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>,
|
||||||
val sff: SerializerFactoryFactory = createSerializerFactoryFactory()
|
val sff: SerializerFactoryFactory = createSerializerFactoryFactory()
|
||||||
) : SerializationScheme {
|
) : SerializationScheme {
|
||||||
@DeleteForDJVM
|
@DeleteForDJVM
|
||||||
constructor(cordapps: List<Cordapp>) : this(cordapps.customSerializers, ConcurrentHashMap())
|
constructor(cordapps: List<Cordapp>) : this(cordapps.customSerializers, AccessOrderLinkedHashMap(128))
|
||||||
|
|
||||||
// TODO: This method of initialisation for the Whitelist and plugin serializers will have to change
|
// TODO: This method of initialisation for the Whitelist and plugin serializers will have to change
|
||||||
// when we have per-cordapp contexts and dynamic app reloading but for now it's the easiest way
|
// when we have per-cordapp contexts and dynamic app reloading but for now it's the easiest way
|
||||||
@ -59,26 +61,27 @@ abstract class AbstractAMQPSerializationScheme(
|
|||||||
val scanSpec: String? = System.getProperty(SCAN_SPEC_PROP_NAME)
|
val scanSpec: String? = System.getProperty(SCAN_SPEC_PROP_NAME)
|
||||||
|
|
||||||
if (scanSpec == null) {
|
if (scanSpec == null) {
|
||||||
logger.info ("scanSpec not set, not scanning for Custom Serializers")
|
logger.debug("scanSpec not set, not scanning for Custom Serializers")
|
||||||
emptyList()
|
emptyList()
|
||||||
} else {
|
} else {
|
||||||
logger.info ("scanSpec = \"$scanSpec\", scanning for Custom Serializers")
|
logger.debug("scanSpec = \"$scanSpec\", scanning for Custom Serializers")
|
||||||
scanClasspathForSerializers(scanSpec)
|
scanClasspathForSerializers(scanSpec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@StubOutForDJVM
|
@StubOutForDJVM
|
||||||
private fun scanClasspathForSerializers(scanSpec: String): List<SerializationCustomSerializer<*, *>> =
|
private fun scanClasspathForSerializers(scanSpec: String): List<SerializationCustomSerializer<*, *>> =
|
||||||
this::class.java.classLoader.let { cl ->
|
this::class.java.classLoader.let { cl ->
|
||||||
FastClasspathScanner(scanSpec).addClassLoader(cl).scan()
|
FastClasspathScanner(scanSpec).addClassLoader(cl).scan()
|
||||||
.getNamesOfClassesImplementing(SerializationCustomSerializer::class.java)
|
.getNamesOfClassesImplementing(SerializationCustomSerializer::class.java)
|
||||||
.map { cl.loadClass(it).asSubclass(SerializationCustomSerializer::class.java) }
|
.map { cl.loadClass(it).asSubclass(SerializationCustomSerializer::class.java) }
|
||||||
.filterNot { Modifier.isAbstract(it.modifiers) }
|
.filterNot { Modifier.isAbstract(it.modifiers) }
|
||||||
.map { it.kotlin.objectOrNewInstance() }
|
.map { it.kotlin.objectOrNewInstance() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteForDJVM
|
@DeleteForDJVM
|
||||||
val List<Cordapp>.customSerializers get() = flatMap { it.serializationCustomSerializers }.toSet()
|
val List<Cordapp>.customSerializers
|
||||||
|
get() = flatMap { it.serializationCustomSerializers }.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameter "context" is unused directly but passed in by reflection. Removing it will cause failures.
|
// Parameter "context" is unused directly but passed in by reflection. Removing it will cause failures.
|
||||||
@ -100,6 +103,7 @@ abstract class AbstractAMQPSerializationScheme(
|
|||||||
register(net.corda.serialization.internal.amqp.custom.ZoneIdSerializer(this))
|
register(net.corda.serialization.internal.amqp.custom.ZoneIdSerializer(this))
|
||||||
register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(this))
|
register(net.corda.serialization.internal.amqp.custom.OffsetTimeSerializer(this))
|
||||||
register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(this))
|
register(net.corda.serialization.internal.amqp.custom.OffsetDateTimeSerializer(this))
|
||||||
|
register(net.corda.serialization.internal.amqp.custom.OptionalSerializer(this))
|
||||||
register(net.corda.serialization.internal.amqp.custom.YearSerializer(this))
|
register(net.corda.serialization.internal.amqp.custom.YearSerializer(this))
|
||||||
register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(this))
|
register(net.corda.serialization.internal.amqp.custom.YearMonthSerializer(this))
|
||||||
register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(this))
|
register(net.corda.serialization.internal.amqp.custom.MonthDaySerializer(this))
|
||||||
@ -126,7 +130,7 @@ abstract class AbstractAMQPSerializationScheme(
|
|||||||
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
|
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info("Custom Serializer list loaded - not scanning classpath")
|
logger.debug("Custom Serializer list loaded - not scanning classpath")
|
||||||
cordappCustomSerializers.forEach { customSerializer ->
|
cordappCustomSerializers.forEach { customSerializer ->
|
||||||
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
|
factory.registerExternal(CorDappCustomSerializer(customSerializer, factory))
|
||||||
}
|
}
|
||||||
@ -153,32 +157,41 @@ abstract class AbstractAMQPSerializationScheme(
|
|||||||
protected abstract fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory
|
protected abstract fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory
|
||||||
|
|
||||||
// Not used as a simple direct import to facilitate testing
|
// Not used as a simple direct import to facilitate testing
|
||||||
open val publicKeySerializer : CustomSerializer<*> = net.corda.serialization.internal.amqp.custom.PublicKeySerializer
|
open val publicKeySerializer: CustomSerializer<*> = net.corda.serialization.internal.amqp.custom.PublicKeySerializer
|
||||||
|
|
||||||
private fun getSerializerFactory(context: SerializationContext): SerializerFactory {
|
private fun getSerializerFactory(context: SerializationContext): SerializerFactory {
|
||||||
return serializerFactoriesForContexts.computeIfAbsent(Pair(context.whitelist, context.deserializationClassLoader)) {
|
return synchronized(serializerFactoriesForContexts) {
|
||||||
when (context.useCase) {
|
serializerFactoriesForContexts.computeIfAbsent(Pair(context.whitelist, context.deserializationClassLoader)) {
|
||||||
SerializationContext.UseCase.Checkpoint ->
|
when (context.useCase) {
|
||||||
throw IllegalStateException("AMQP should not be used for checkpoint serialization.")
|
SerializationContext.UseCase.Checkpoint ->
|
||||||
SerializationContext.UseCase.RPCClient ->
|
throw IllegalStateException("AMQP should not be used for checkpoint serialization.")
|
||||||
rpcClientSerializerFactory(context)
|
SerializationContext.UseCase.RPCClient ->
|
||||||
SerializationContext.UseCase.RPCServer ->
|
rpcClientSerializerFactory(context)
|
||||||
rpcServerSerializerFactory(context)
|
SerializationContext.UseCase.RPCServer ->
|
||||||
else -> sff.make(context)
|
rpcServerSerializerFactory(context)
|
||||||
}.also {
|
else -> sff.make(context)
|
||||||
registerCustomSerializers(context, it)
|
}.also {
|
||||||
|
registerCustomSerializers(context, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any> deserialize(byteSequence: ByteSequence, clazz: Class<T>, context: SerializationContext): T {
|
override fun <T : Any> deserialize(byteSequence: ByteSequence, clazz: Class<T>, context: SerializationContext): T {
|
||||||
val serializerFactory = getSerializerFactory(context)
|
var contextToUse = context
|
||||||
|
if (context.useCase == SerializationContext.UseCase.RPCClient) {
|
||||||
|
contextToUse = context.withClassLoader(getContextClassLoader())
|
||||||
|
}
|
||||||
|
val serializerFactory = getSerializerFactory(contextToUse)
|
||||||
return DeserializationInput(serializerFactory).deserialize(byteSequence, clazz, context)
|
return DeserializationInput(serializerFactory).deserialize(byteSequence, clazz, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any> serialize(obj: T, context: SerializationContext): SerializedBytes<T> {
|
override fun <T : Any> serialize(obj: T, context: SerializationContext): SerializedBytes<T> {
|
||||||
val serializerFactory = getSerializerFactory(context)
|
var contextToUse = context
|
||||||
|
if (context.useCase == SerializationContext.UseCase.RPCClient) {
|
||||||
|
contextToUse = context.withClassLoader(getContextClassLoader())
|
||||||
|
}
|
||||||
|
val serializerFactory = getSerializerFactory(contextToUse)
|
||||||
return SerializationOutput(serializerFactory).serialize(obj, context)
|
return SerializationOutput(serializerFactory).serialize(obj, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
@file:JvmName("AMQPSerializationThreadContext")
|
||||||
|
package net.corda.serialization.internal.amqp
|
||||||
|
|
||||||
|
fun getContextClassLoader(): ClassLoader {
|
||||||
|
return Thread.currentThread().contextClassLoader
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.serialization.internal.amqp
|
||||||
|
import net.corda.core.KeepForDJVM
|
||||||
|
|
||||||
|
@KeepForDJVM
|
||||||
|
class AccessOrderLinkedHashMap<K, V>(private val maxSize: Int) : LinkedHashMap<K, V>(16, 0.75f, true) {
|
||||||
|
constructor(loader: () -> Int) : this(loader.invoke())
|
||||||
|
|
||||||
|
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>?): Boolean {
|
||||||
|
return this.size > maxSize
|
||||||
|
}
|
||||||
|
}
|
@ -276,7 +276,7 @@ internal fun <T : Any> propertiesForSerializationFromConstructor(
|
|||||||
"in the Java compiler. Alternately, provide a proxy serializer " +
|
"in the Java compiler. Alternately, provide a proxy serializer " +
|
||||||
"(SerializationCustomSerializer) if recompiling isn't an option")
|
"(SerializationCustomSerializer) if recompiling isn't an option")
|
||||||
|
|
||||||
Pair(PrivatePropertyReader(field, type), field.genericType)
|
Pair(PrivatePropertyReader(field, type), resolveTypeVariables(field.genericType, type))
|
||||||
}
|
}
|
||||||
|
|
||||||
this += PropertyAccessorConstructor(
|
this += PropertyAccessorConstructor(
|
||||||
|
@ -140,7 +140,7 @@ open class SerializerFactory(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Enum::class.java.isAssignableFrom(actualClass ?: declaredClass) -> {
|
Enum::class.java.isAssignableFrom(actualClass ?: declaredClass) -> {
|
||||||
logger.debug("class=[${actualClass?.simpleName} | $declaredClass] is an enumeration "
|
logger.info("class=[${actualClass?.simpleName} | $declaredClass] is an enumeration "
|
||||||
+ "declaredType=${declaredType.typeName} "
|
+ "declaredType=${declaredType.typeName} "
|
||||||
+ "isEnum=${declaredType::class.java.isEnum}")
|
+ "isEnum=${declaredType::class.java.isEnum}")
|
||||||
|
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package net.corda.serialization.internal.amqp.custom
|
||||||
|
|
||||||
|
import net.corda.core.KeepForDJVM
|
||||||
|
import net.corda.serialization.internal.amqp.CustomSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.SerializerFactory
|
||||||
|
import java.time.OffsetTime
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A serializer for [OffsetTime] that uses a proxy object to write out the time and zone offset.
|
||||||
|
*/
|
||||||
|
class OptionalSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Optional<*>, OptionalSerializer.OptionalProxy>(Optional::class.java, OptionalProxy::class.java, factory) {
|
||||||
|
|
||||||
|
public override fun toProxy(obj: java.util.Optional<*>): OptionalProxy {
|
||||||
|
return OptionalProxy(obj.orElse(null))
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun fromProxy(proxy: OptionalProxy): Optional<*> {
|
||||||
|
return Optional.ofNullable(proxy.item)
|
||||||
|
}
|
||||||
|
|
||||||
|
@KeepForDJVM
|
||||||
|
data class OptionalProxy(val item: Any?)
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package net.corda.serialization.internal.amqp;
|
||||||
|
|
||||||
|
import net.corda.core.serialization.CordaSerializable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
public class DummyOptional<T> {
|
||||||
|
|
||||||
|
private final T item;
|
||||||
|
|
||||||
|
public boolean isPresent() {
|
||||||
|
return item != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T get() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DummyOptional(T item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
DummyOptional<?> that = (DummyOptional<?>) o;
|
||||||
|
return Objects.equals(item, that.item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
|
||||||
|
return Objects.hash(item);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package net.corda.serialization.internal.amqp
|
||||||
|
|
||||||
|
import net.corda.core.serialization.ClassWhitelist
|
||||||
|
import net.corda.core.serialization.SerializationContext
|
||||||
|
import net.corda.core.serialization.deserialize
|
||||||
|
import net.corda.core.utilities.ByteSequence
|
||||||
|
import net.corda.serialization.internal.AllWhitelist
|
||||||
|
import net.corda.serialization.internal.CordaSerializationMagic
|
||||||
|
import net.corda.serialization.internal.SerializationContextImpl
|
||||||
|
import net.corda.serialization.internal.amqp.testutils.serializationProperties
|
||||||
|
import net.corda.testing.core.SerializationEnvironmentRule
|
||||||
|
import org.hamcrest.CoreMatchers
|
||||||
|
import org.hamcrest.CoreMatchers.`is`
|
||||||
|
import org.hamcrest.Matchers
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import java.net.URLClassLoader
|
||||||
|
import java.util.concurrent.ThreadLocalRandom
|
||||||
|
import java.util.stream.IntStream
|
||||||
|
|
||||||
|
class AbstractAMQPSerializationSchemeTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
@JvmField
|
||||||
|
val testSerialization = SerializationEnvironmentRule()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `number of cached factories must be bounded by maxFactories`() {
|
||||||
|
val genesisContext = SerializationContextImpl(
|
||||||
|
ByteSequence.of(byteArrayOf('c'.toByte(), 'o'.toByte(), 'r'.toByte(), 'd'.toByte(), 'a'.toByte(), 0.toByte(), 0.toByte(), 1.toByte())),
|
||||||
|
ClassLoader.getSystemClassLoader(),
|
||||||
|
AllWhitelist,
|
||||||
|
serializationProperties,
|
||||||
|
false,
|
||||||
|
SerializationContext.UseCase.RPCClient,
|
||||||
|
null)
|
||||||
|
|
||||||
|
|
||||||
|
val factory = TestSerializerFactory(TESTING_CONTEXT.whitelist, TESTING_CONTEXT.deserializationClassLoader)
|
||||||
|
val maxFactories = 512
|
||||||
|
val backingMap = AccessOrderLinkedHashMap<Pair<ClassWhitelist, ClassLoader>, SerializerFactory>({ maxFactories })
|
||||||
|
val scheme = object : AbstractAMQPSerializationScheme(emptySet(), backingMap, createSerializerFactoryFactory()) {
|
||||||
|
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory {
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IntStream.range(0, 2048).parallel().forEach {
|
||||||
|
val context = if (ThreadLocalRandom.current().nextBoolean()) {
|
||||||
|
genesisContext.withClassLoader(URLClassLoader(emptyArray()))
|
||||||
|
} else {
|
||||||
|
genesisContext
|
||||||
|
}
|
||||||
|
val testString = "TEST${ThreadLocalRandom.current().nextInt()}"
|
||||||
|
val serialized = scheme.serialize(testString, context)
|
||||||
|
val deserialized = serialized.deserialize(context = context, serializationFactory = testSerialization.serializationFactory)
|
||||||
|
Assert.assertThat(testString, `is`(deserialized))
|
||||||
|
Assert.assertThat(backingMap.size, `is`(Matchers.lessThanOrEqualTo(maxFactories)))
|
||||||
|
}
|
||||||
|
Assert.assertThat(backingMap.size, CoreMatchers.`is`(Matchers.lessThanOrEqualTo(maxFactories)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,15 +1,11 @@
|
|||||||
package net.corda.serialization.internal.amqp
|
package net.corda.serialization.internal.amqp
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import net.corda.core.serialization.ClassWhitelist
|
import net.corda.core.serialization.ClassWhitelist
|
||||||
import net.corda.core.serialization.SerializationCustomSerializer
|
import net.corda.core.serialization.SerializationCustomSerializer
|
||||||
import net.corda.serialization.internal.AllWhitelist
|
import net.corda.serialization.internal.AllWhitelist
|
||||||
import net.corda.serialization.internal.amqp.testutils.deserializeAndReturnEnvelope
|
import net.corda.serialization.internal.amqp.testutils.*
|
||||||
import net.corda.serialization.internal.amqp.testutils.deserialize
|
|
||||||
import net.corda.serialization.internal.amqp.testutils.serializeAndReturnSchema
|
|
||||||
import net.corda.serialization.internal.amqp.testutils.serialize
|
|
||||||
import net.corda.serialization.internal.amqp.testutils.testDefaultFactory
|
|
||||||
import org.assertj.core.api.Assertions
|
import org.assertj.core.api.Assertions
|
||||||
|
import org.junit.Test
|
||||||
import java.io.NotSerializableException
|
import java.io.NotSerializableException
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package net.corda.serialization.internal.amqp
|
||||||
|
|
||||||
|
import net.corda.serialization.internal.AllWhitelist
|
||||||
|
import net.corda.serialization.internal.amqp.custom.OptionalSerializer
|
||||||
|
import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput
|
||||||
|
import net.corda.serialization.internal.amqp.testutils.deserialize
|
||||||
|
import net.corda.serialization.internal.amqp.testutils.testDefaultFactory
|
||||||
|
import org.hamcrest.Matchers.`is`
|
||||||
|
import org.hamcrest.Matchers.equalTo
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class OptionalSerializationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setupEnclosedSerializationTest() {
|
||||||
|
@Test
|
||||||
|
fun `java optionals should serialize`() {
|
||||||
|
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||||
|
factory.register(OptionalSerializer(factory))
|
||||||
|
val obj = Optional.ofNullable("YES")
|
||||||
|
val bytes = TestSerializationOutput(true, factory).serialize(obj)
|
||||||
|
val deserializerFactory = testDefaultFactory().apply {
|
||||||
|
register(OptionalSerializer(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
val deserialized = DeserializationInput(factory).deserialize(bytes)
|
||||||
|
val deserialized2 = DeserializationInput(deserializerFactory).deserialize(bytes)
|
||||||
|
Assert.assertThat(deserialized, `is`(equalTo(deserialized2)))
|
||||||
|
Assert.assertThat(obj, `is`(equalTo(deserialized2)))
|
||||||
|
}
|
||||||
|
|
||||||
|
`java optionals should serialize`()
|
||||||
|
}
|
||||||
|
}
|
@ -510,6 +510,12 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
|
|||||||
serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()))
|
serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `generics from java are supported`() {
|
||||||
|
val obj = DummyOptional<String>("YES")
|
||||||
|
serdes(obj, SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test throwables serialize`() {
|
fun `test throwables serialize`() {
|
||||||
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||||
@ -969,6 +975,7 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
|
|||||||
|
|
||||||
class Spike private constructor(val a: String) {
|
class Spike private constructor(val a: String) {
|
||||||
constructor() : this("a")
|
constructor() : this("a")
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean = other is Spike && other.a == this.a
|
override fun equals(other: Any?): Boolean = other is Spike && other.a == this.a
|
||||||
override fun hashCode(): Int = a.hashCode()
|
override fun hashCode(): Int = a.hashCode()
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ package net.corda.serialization.internal.amqp
|
|||||||
|
|
||||||
import net.corda.core.serialization.*
|
import net.corda.core.serialization.*
|
||||||
import net.corda.core.utilities.ByteSequence
|
import net.corda.core.utilities.ByteSequence
|
||||||
import net.corda.serialization.internal.*
|
|
||||||
import net.corda.serialization.internal.BuiltInExceptionsWhitelist
|
import net.corda.serialization.internal.BuiltInExceptionsWhitelist
|
||||||
|
import net.corda.serialization.internal.CordaSerializationMagic
|
||||||
import net.corda.serialization.internal.GlobalTransientClassWhiteList
|
import net.corda.serialization.internal.GlobalTransientClassWhiteList
|
||||||
|
import net.corda.serialization.internal.SerializationContextImpl
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
// Make sure all serialization calls in this test don't get stomped on by anything else
|
// Make sure all serialization calls in this test don't get stomped on by anything else
|
||||||
@ -46,7 +46,7 @@ class TestSerializerFactoryFactory : SerializerFactoryFactoryImpl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AMQPTestSerializationScheme : AbstractAMQPSerializationScheme(emptySet(), ConcurrentHashMap(), TestSerializerFactoryFactory()) {
|
class AMQPTestSerializationScheme : AbstractAMQPSerializationScheme(emptySet(), AccessOrderLinkedHashMap { 128 }, TestSerializerFactoryFactory()) {
|
||||||
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
|
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ class SerializationSchemaTests {
|
|||||||
|
|
||||||
val c = C(1)
|
val c = C(1)
|
||||||
val testSerializationFactory = TestSerializationFactory()
|
val testSerializationFactory = TestSerializationFactory()
|
||||||
val expectedCustomSerializerCount = 40
|
val expectedCustomSerializerCount = 41
|
||||||
|
|
||||||
assertEquals(0, testFactory.registerCount)
|
assertEquals(0, testFactory.registerCount)
|
||||||
c.serialize(testSerializationFactory, TESTING_CONTEXT)
|
c.serialize(testSerializationFactory, TESTING_CONTEXT)
|
||||||
|
Reference in New Issue
Block a user