CORDA-1603: Class carpenter able to synthesis Cash.State objects (#3400)

This requires the class carpenter to be able to run in a "lenient" mode where it permits synthesised classes to implement interfaces with unimplemented methods.
This commit is contained in:
Shams Asari
2018-06-25 11:33:37 +01:00
committed by GitHub
parent 68d4ed0cd9
commit b97af477b2
32 changed files with 307 additions and 303 deletions

View File

@ -50,7 +50,7 @@ class AMQPClientSerializationScheme(
target == SerializationContext.UseCase.RPCClient || target == SerializationContext.UseCase.P2P) target == SerializationContext.UseCase.RPCClient || target == SerializationContext.UseCase.P2P)
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory { override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
return SerializerFactory(context.whitelist, ClassLoader.getSystemClassLoader()).apply { return SerializerFactory(context.whitelist, ClassLoader.getSystemClassLoader(), context.lenientCarpenterEnabled).apply {
register(RpcClientObservableSerializer) register(RpcClientObservableSerializer)
register(RpcClientCordaFutureSerializer(this)) register(RpcClientCordaFutureSerializer(this))
register(RxNotificationSerializer(this)) register(RxNotificationSerializer(this))

View File

@ -142,6 +142,14 @@ interface SerializationContext {
* otherwise they appear as new copies of the object. * otherwise they appear as new copies of the object.
*/ */
val objectReferencesEnabled: Boolean val objectReferencesEnabled: Boolean
/**
* If true the carpenter will happily synthesis classes that implement interfaces containing methods that are not
* getters for any AMQP fields. Invoking these methods will throw an [AbstractMethodError]. If false then an exception
* will be thrown during deserialization instead.
*
* The default is false.
*/
val lenientCarpenterEnabled: Boolean
/** /**
* The use case we are serializing or deserializing for. See [UseCase]. * The use case we are serializing or deserializing for. See [UseCase].
*/ */
@ -157,6 +165,12 @@ interface SerializationContext {
*/ */
fun withoutReferences(): SerializationContext fun withoutReferences(): SerializationContext
/**
* Return a new context based on this one but with a lenient carpenter.
* @see lenientCarpenterEnabled
*/
fun withLenientCarpenter(): 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.
*/ */

View File

@ -7,6 +7,10 @@ release, see :doc:`upgrade-notes`.
Unreleased Unreleased
---------- ----------
* The class carpenter has a "lenient" mode where it will, during deserialisation, happily synthesis classes that implement
interfaces that will have unimplemented methods. This is useful, for example, for object viewers. This can be turned on
with ``SerializationContext.withLenientCarpenter``.
* Introduced a grace period before the initial node registration fails if the node cannot connect to the Doorman. * Introduced a grace period before the initial node registration fails if the node cannot connect to the Doorman.
It retries 10 times with a 1 minute interval in between each try. At the moment this is not configurable. It retries 10 times with a 1 minute interval in between each try. At the moment this is not configurable.

View File

@ -557,6 +557,11 @@ without the supporting classes being present on the classpath. This can be usef
be able to use reflection over the deserialized data, for scripting languages that run on the JVM, and also for be able to use reflection over the deserialized data, for scripting languages that run on the JVM, and also for
ensuring classes not on the classpath can be deserialized without loading potentially malicious code. ensuring classes not on the classpath can be deserialized without loading potentially malicious code.
If the original class implements some interfaces then the carpenter will make sure that all of the interface methods are
backed by feilds. If that's not the case then an exception will be thrown during deserialization. This check can
be turned off with ``SerializationContext.withLenientCarpenter``. This can be useful if only the field getters are needed,
say in an object viewer.
Possible future enhancements include: Possible future enhancements include:
#. Java singleton support. We will add support for identifying classes which are singletons and identifying the #. Java singleton support. We will add support for identifying classes which are singletons and identifying the

View File

@ -26,15 +26,13 @@ class AMQPServerSerializationScheme(
throw UnsupportedOperationException() throw UnsupportedOperationException()
} }
override fun rpcServerSerializerFactory(context: SerializationContext) = override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory {
SerializerFactory( return SerializerFactory(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled).apply {
context.whitelist,
context.deserializationClassLoader
).apply {
register(RpcServerObservableSerializer()) register(RpcServerObservableSerializer())
register(RpcServerCordaFutureSerializer(this)) register(RpcServerCordaFutureSerializer(this))
register(RxNotificationSerializer(this)) register(RxNotificationSerializer(this))
} }
}
override fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean { override fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean {
return canDeserializeVersion(magic) && return canDeserializeVersion(magic) &&

View File

@ -30,7 +30,8 @@ data class SerializationContextImpl @JvmOverloads constructor(override val prefe
override val objectReferencesEnabled: Boolean, override val objectReferencesEnabled: Boolean,
override val useCase: SerializationContext.UseCase, override val useCase: SerializationContext.UseCase,
override val encoding: SerializationEncoding?, override val encoding: SerializationEncoding?,
override val encodingWhitelist: EncodingWhitelist = NullEncodingWhitelist) : SerializationContext { override val encodingWhitelist: EncodingWhitelist = NullEncodingWhitelist,
override val lenientCarpenterEnabled: Boolean = false) : SerializationContext {
private val builder = AttachmentsClassLoaderBuilder(properties, deserializationClassLoader) private val builder = AttachmentsClassLoaderBuilder(properties, deserializationClassLoader)
/** /**
@ -52,6 +53,8 @@ data class SerializationContextImpl @JvmOverloads constructor(override val prefe
return copy(objectReferencesEnabled = false) return copy(objectReferencesEnabled = false)
} }
override fun withLenientCarpenter(): SerializationContext = copy(lenientCarpenterEnabled = true)
override fun withClassLoader(classLoader: ClassLoader): SerializationContext { override fun withClassLoader(classLoader: ClassLoader): SerializationContext {
return copy(deserializationClassLoader = classLoader) return copy(deserializationClassLoader = classLoader)
} }

View File

@ -7,6 +7,7 @@ import net.corda.core.serialization.SerializationContext
fun createSerializerFactoryFactory(): SerializerFactoryFactory = SerializerFactoryFactoryImpl() fun createSerializerFactoryFactory(): SerializerFactoryFactory = SerializerFactoryFactoryImpl()
open class SerializerFactoryFactoryImpl : SerializerFactoryFactory { open class SerializerFactoryFactoryImpl : SerializerFactoryFactory {
override fun make(context: SerializationContext) = override fun make(context: SerializationContext): SerializerFactory {
SerializerFactory(context.whitelist, context.deserializationClassLoader) return SerializerFactory(context.whitelist, context.deserializationClassLoader, context.lenientCarpenterEnabled)
}
} }

View File

@ -7,6 +7,8 @@ import net.corda.serialization.internal.amqp.SerializerFactory.Companion.nameFor
import org.apache.qpid.proton.amqp.Symbol import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException import java.io.NotSerializableException
import java.lang.reflect.Constructor
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Type import java.lang.reflect.Type
import kotlin.reflect.jvm.javaConstructor import kotlin.reflect.jvm.javaConstructor
@ -29,8 +31,7 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
private val typeName = nameForType(clazz) private val typeName = nameForType(clazz)
override val typeDescriptor = Symbol.valueOf( override val typeDescriptor: Symbol = Symbol.valueOf("$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}")
"$DESCRIPTOR_DOMAIN:${factory.fingerPrinter.fingerprint(type)}")!!
// We restrict to only those annotated or whitelisted // We restrict to only those annotated or whitelisted
private val interfaces = interfacesForSerialization(clazz, factory) private val interfaces = interfacesForSerialization(clazz, factory)
@ -119,7 +120,7 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
context: SerializationContext): Any = ifThrowsAppend({ clazz.typeName }) { context: SerializationContext): Any = ifThrowsAppend({ clazz.typeName }) {
logger.trace { "Calling setter based construction for ${clazz.typeName}" } logger.trace { "Calling setter based construction for ${clazz.typeName}" }
val instance: Any = javaConstructor?.newInstance() ?: throw NotSerializableException( val instance: Any = javaConstructor?.newInstanceUnwrapped() ?: throw NotSerializableException(
"Failed to instantiate instance of object $clazz") "Failed to instantiate instance of object $clazz")
// read the properties out of the serialised form, since we're invoking the setters the order we // read the properties out of the serialised form, since we're invoking the setters the order we
@ -153,7 +154,15 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS
+ "serialized properties.") + "serialized properties.")
} }
return javaConstructor?.newInstance(*properties.toTypedArray()) return javaConstructor?.newInstanceUnwrapped(*properties.toTypedArray())
?: throw NotSerializableException("Attempt to deserialize an interface: $clazz. Serialized form is invalid.") ?: throw NotSerializableException("Attempt to deserialize an interface: $clazz. Serialized form is invalid.")
} }
private fun <T> Constructor<T>.newInstanceUnwrapped(vararg args: Any?): T {
try {
return newInstance(*args)
} catch (e: InvocationTargetException) {
throw e.cause!!
}
}
} }

View File

@ -8,6 +8,7 @@ import net.corda.core.StubOutForDJVM
import net.corda.core.internal.kotlinObjectInstance import net.corda.core.internal.kotlinObjectInstance
import net.corda.core.internal.uncheckedCast import net.corda.core.internal.uncheckedCast
import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.ClassWhitelist
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.debug import net.corda.core.utilities.debug
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.trace import net.corda.core.utilities.trace
@ -53,40 +54,43 @@ open class SerializerFactory(
private val serializersByType: MutableMap<Type, AMQPSerializer<Any>>, private val serializersByType: MutableMap<Type, AMQPSerializer<Any>>,
val serializersByDescriptor: MutableMap<Any, AMQPSerializer<Any>>, val serializersByDescriptor: MutableMap<Any, AMQPSerializer<Any>>,
private val customSerializers: MutableList<SerializerFor>, private val customSerializers: MutableList<SerializerFor>,
val transformsCache: MutableMap<String, EnumMap<TransformTypes, MutableList<Transform>>>) { val transformsCache: MutableMap<String, EnumMap<TransformTypes, MutableList<Transform>>>
) {
@DeleteForDJVM @DeleteForDJVM
constructor(whitelist: ClassWhitelist, constructor(whitelist: ClassWhitelist,
classCarpenter: ClassCarpenter, classCarpenter: ClassCarpenter,
evolutionSerializerGetter: EvolutionSerializerGetterBase = EvolutionSerializerGetter(), evolutionSerializerGetter: EvolutionSerializerGetterBase = EvolutionSerializerGetter(),
fingerPrinter: FingerPrinter = SerializerFingerPrinter() fingerPrinter: FingerPrinter = SerializerFingerPrinter()
) : this(whitelist, classCarpenter, evolutionSerializerGetter, fingerPrinter, ) : this(
serializersByType = ConcurrentHashMap(), whitelist,
serializersByDescriptor = ConcurrentHashMap(), classCarpenter,
customSerializers = CopyOnWriteArrayList(), evolutionSerializerGetter,
transformsCache = ConcurrentHashMap()) fingerPrinter,
ConcurrentHashMap(),
ConcurrentHashMap(),
CopyOnWriteArrayList(),
ConcurrentHashMap()
)
@DeleteForDJVM @DeleteForDJVM
constructor(whitelist: ClassWhitelist, constructor(whitelist: ClassWhitelist,
classLoader: ClassLoader, classLoader: ClassLoader,
lenientCarpenter: Boolean = false,
evolutionSerializerGetter: EvolutionSerializerGetterBase = EvolutionSerializerGetter(), evolutionSerializerGetter: EvolutionSerializerGetterBase = EvolutionSerializerGetter(),
fingerPrinter: FingerPrinter = SerializerFingerPrinter() fingerPrinter: FingerPrinter = SerializerFingerPrinter()
) : this(whitelist, ClassCarpenterImpl(classLoader, whitelist), evolutionSerializerGetter, fingerPrinter, ) : this(whitelist, ClassCarpenterImpl(classLoader, whitelist, lenientCarpenter), evolutionSerializerGetter, fingerPrinter)
serializersByType = ConcurrentHashMap(),
serializersByDescriptor = ConcurrentHashMap(),
customSerializers = CopyOnWriteArrayList(),
transformsCache = ConcurrentHashMap())
init { init {
fingerPrinter.setOwner(this) fingerPrinter.setOwner(this)
} }
val classloader: ClassLoader val classloader: ClassLoader get() = classCarpenter.classloader
get() = classCarpenter.classloader
private fun getEvolutionSerializer(typeNotation: TypeNotation, newSerializer: AMQPSerializer<Any>, private fun getEvolutionSerializer(typeNotation: TypeNotation,
schemas: SerializationSchemas) = evolutionSerializerGetter.getEvolutionSerializer(this, typeNotation, newSerializer, schemas) newSerializer: AMQPSerializer<Any>,
schemas: SerializationSchemas): AMQPSerializer<Any> {
private val logger = loggerFor<SerializerFactory>() return evolutionSerializerGetter.getEvolutionSerializer(this, typeNotation, newSerializer, schemas)
}
/** /**
* Look up, and manufacture if necessary, a serializer for the given type. * Look up, and manufacture if necessary, a serializer for the given type.
@ -380,6 +384,8 @@ open class SerializerFactory(
} }
companion object { companion object {
private val logger = contextLogger()
fun isPrimitive(type: Type): Boolean = primitiveTypeName(type) != null fun isPrimitive(type: Type): Boolean = primitiveTypeName(type) != null
fun primitiveTypeName(type: Type): String? { fun primitiveTypeName(type: Type): String? {
@ -469,4 +475,3 @@ open class SerializerFactory(
override fun toString(): String = "?" override fun toString(): String = "?"
} }
} }

View File

@ -63,7 +63,7 @@ fun CompositeType.carpenterSchema(classloader: ClassLoader,
} }
try { try {
providesList.add(classloader.loadClass(it)) providesList.add(classloader.loadClass(it.stripGenerics()))
} catch (e: ClassNotFoundException) { } catch (e: ClassNotFoundException) {
carpenterSchemas.addDepPair(this, name, it) carpenterSchemas.addDepPair(this, name, it)
isCreatable = false isCreatable = false

View File

@ -6,6 +6,8 @@ import net.corda.core.DeleteForDJVM
import net.corda.core.KeepForDJVM import net.corda.core.KeepForDJVM
import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.debug
import org.objectweb.asm.ClassWriter import org.objectweb.asm.ClassWriter
import org.objectweb.asm.MethodVisitor import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes.* import org.objectweb.asm.Opcodes.*
@ -102,8 +104,9 @@ interface ClassCarpenter {
* Equals/hashCode methods are not yet supported. * Equals/hashCode methods are not yet supported.
*/ */
@DeleteForDJVM @DeleteForDJVM
class ClassCarpenterImpl(cl: ClassLoader, override val whitelist: ClassWhitelist) : ClassCarpenter { class ClassCarpenterImpl(cl: ClassLoader = Thread.currentThread().contextClassLoader,
constructor(whitelist: ClassWhitelist) : this(Thread.currentThread().contextClassLoader, whitelist) override val whitelist: ClassWhitelist,
private val lenient: Boolean = false) : ClassCarpenter {
// TODO: Generics. // TODO: Generics.
// TODO: Sandbox the generated code when a security manager is in use. // TODO: Sandbox the generated code when a security manager is in use.
@ -439,25 +442,36 @@ class ClassCarpenterImpl(cl: ClassLoader, override val whitelist: ClassWhitelist
// actually called, which is a bit too dynamic for my tastes. // actually called, which is a bit too dynamic for my tastes.
val allFields = schema.fieldsIncludingSuperclasses() val allFields = schema.fieldsIncludingSuperclasses()
for (itf in schema.interfaces) { for (itf in schema.interfaces) {
itf.methods.forEach { methodLoop@
val fieldNameFromItf = when { for (method in itf.methods) {
it.name.startsWith("get") -> it.name.substring(3).decapitalize() val fieldNameFromItf = if (method.name.startsWith("get")) {
else -> throw InterfaceMismatchNonGetterException(itf, it) method.name.substring(3).decapitalize()
} else if (lenient) {
logger.debug { "Ignoring interface $method which is not a getter" }
continue@methodLoop
} else {
throw InterfaceMismatchNonGetterException(itf, method)
} }
// If we're trying to carpent a class that prior to serialisation / deserialization // If we're trying to carpent a class that prior to serialisation / deserialization
// was made by a carpenter then we can ignore this (it will implement a plain get // was made by a carpenter then we can ignore this (it will implement a plain get
// method from SimpleFieldAccess). // method from SimpleFieldAccess).
if (fieldNameFromItf.isEmpty() && SimpleFieldAccess::class.java in schema.interfaces) return@forEach if (fieldNameFromItf.isEmpty() && SimpleFieldAccess::class.java in schema.interfaces) continue@methodLoop
if ((schema is ClassSchema) and (fieldNameFromItf !in allFields)) { if ((schema is ClassSchema) and (fieldNameFromItf !in allFields)) {
throw InterfaceMismatchMissingAMQPFieldException(itf, fieldNameFromItf) if (lenient) {
logger.debug { "Ignoring interface $method which is not backed by an AMQP field" }
} else {
throw InterfaceMismatchMissingAMQPFieldException(itf, fieldNameFromItf)
}
} }
} }
} }
} }
companion object { companion object {
private val logger = contextLogger()
@JvmStatic @JvmStatic
@Suppress("UNUSED") @Suppress("UNUSED")
fun getField(obj: Any, name: String): Any? = obj.javaClass.getMethod("get" + name.capitalize()).invoke(obj) fun getField(obj: Any, name: String): Any? = obj.javaClass.getMethod("get" + name.capitalize()).invoke(obj)

View File

@ -8,6 +8,9 @@ import org.junit.Test;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
import static org.assertj.core.api.Assertions.*;
@Ignore("Current behaviour allows for the serialization of objects with private members, this will be disallowed at some point in the future") @Ignore("Current behaviour allows for the serialization of objects with private members, this will be disallowed at some point in the future")
public class ErrorMessageTests { public class ErrorMessageTests {
private String errMsg(String property, String testname) { private String errMsg(String property, String testname) {
@ -32,19 +35,10 @@ public class ErrorMessageTests {
@Test @Test
public void testJavaConstructorAnnotations() { public void testJavaConstructorAnnotations() {
EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); SerializationOutput ser = new SerializationOutput(testDefaultFactory());
FingerPrinter fingerPrinter = new SerializerFingerPrinter();
SerializerFactory factory1 = new SerializerFactory(
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
evolutionSerialiserGetter,
fingerPrinter);
SerializationOutput ser = new SerializationOutput(factory1); assertThatThrownBy(() -> ser.serialize(new C(1), TestSerializationContext.testSerializationContext))
Assertions.assertThatThrownBy(() -> ser.serialize(new C(1), TestSerializationContext.testSerializationContext))
.isInstanceOf(NotSerializableException.class) .isInstanceOf(NotSerializableException.class)
.hasMessage(errMsg("a", getClass().getName())); .hasMessage(errMsg("a", getClass().getName()));
} }
} }

View File

@ -1,7 +1,6 @@
package net.corda.serialization.internal.amqp; package net.corda.serialization.internal.amqp;
import net.corda.core.serialization.SerializationCustomSerializer; import net.corda.core.serialization.SerializationCustomSerializer;
import net.corda.serialization.internal.AllWhitelist;
import net.corda.serialization.internal.amqp.testutils.TestSerializationContext; import net.corda.serialization.internal.amqp.testutils.TestSerializationContext;
import org.junit.Test; import org.junit.Test;
@ -9,6 +8,8 @@ import java.io.NotSerializableException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
public class JavaCustomSerializerTests { public class JavaCustomSerializerTests {
/** /**
* The class lacks a public constructor that takes parameters it can associate * The class lacks a public constructor that takes parameters it can associate
@ -87,10 +88,8 @@ public class JavaCustomSerializerTests {
} }
@Test @Test
public void serializeExample() throws NotSerializableException, NoSuchFieldException, IllegalAccessException { public void serializeExample() throws NotSerializableException {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
List<Integer> l = new ArrayList<Integer>(2); List<Integer> l = new ArrayList<Integer>(2);
@ -102,7 +101,5 @@ public class JavaCustomSerializerTests {
factory.registerExternal(ccs); factory.registerExternal(ccs);
ser.serialize(e, TestSerializationContext.testSerializationContext); ser.serialize(e, TestSerializationContext.testSerializationContext);
} }
} }

View File

@ -1,11 +1,11 @@
package net.corda.serialization.internal.amqp; package net.corda.serialization.internal.amqp;
import net.corda.core.serialization.SerializedBytes; import net.corda.core.serialization.SerializedBytes;
import net.corda.serialization.internal.AllWhitelist;
import net.corda.serialization.internal.amqp.testutils.TestSerializationContext; import net.corda.serialization.internal.amqp.testutils.TestSerializationContext;
import org.junit.Test; import org.junit.Test;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
import static org.jgroups.util.Util.assertEquals; import static org.jgroups.util.Util.assertEquals;
public class JavaGenericsTest { public class JavaGenericsTest {
@ -27,11 +27,7 @@ public class JavaGenericsTest {
public void basicGeneric() throws NotSerializableException { public void basicGeneric() throws NotSerializableException {
A a1 = new A(1); A a1 = new A(1);
SerializerFactory factory = new SerializerFactory( SerializerFactory factory = testDefaultFactory();
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
SerializedBytes<?> bytes = ser.serialize(a1, TestSerializationContext.testSerializationContext); SerializedBytes<?> bytes = ser.serialize(a1, TestSerializationContext.testSerializationContext);
@ -43,13 +39,9 @@ public class JavaGenericsTest {
} }
private SerializedBytes<?> forceWildcardSerialize(A<?> a) throws NotSerializableException { private SerializedBytes<?> forceWildcardSerialize(A<?> a) throws NotSerializableException {
SerializerFactory factory = new SerializerFactory( SerializerFactory factory = testDefaultFactory();
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
return (new SerializationOutput(factory)).serialize(a, TestSerializationContext.testSerializationContext); return (new SerializationOutput(factory)).serialize(a, TestSerializationContext.testSerializationContext);
} }
private SerializedBytes<?> forceWildcardSerializeFactory( private SerializedBytes<?> forceWildcardSerializeFactory(
@ -59,11 +51,7 @@ public class JavaGenericsTest {
} }
private A<?> forceWildcardDeserialize(SerializedBytes<?> bytes) throws NotSerializableException { private A<?> forceWildcardDeserialize(SerializedBytes<?> bytes) throws NotSerializableException {
SerializerFactory factory = new SerializerFactory( SerializerFactory factory = testDefaultFactory();
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
DeserializationInput des = new DeserializationInput(factory); DeserializationInput des = new DeserializationInput(factory);
return des.deserialize(bytes, A.class, TestSerializationContext.testSerializationContext); return des.deserialize(bytes, A.class, TestSerializationContext.testSerializationContext);
@ -85,11 +73,7 @@ public class JavaGenericsTest {
@Test @Test
public void forceWildcardSharedFactory() throws NotSerializableException { public void forceWildcardSharedFactory() throws NotSerializableException {
SerializerFactory factory = new SerializerFactory( SerializerFactory factory = testDefaultFactory();
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializedBytes<?> bytes = forceWildcardSerializeFactory(new A(new Inner(29)), factory); SerializedBytes<?> bytes = forceWildcardSerializeFactory(new A(new Inner(29)), factory);
Inner i = (Inner)forceWildcardDeserializeFactory(bytes, factory).getT(); Inner i = (Inner)forceWildcardDeserializeFactory(bytes, factory).getT();

View File

@ -4,28 +4,25 @@ import com.google.common.collect.ImmutableList;
import net.corda.core.contracts.ContractState; import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty; import net.corda.core.identity.AbstractParty;
import net.corda.core.serialization.SerializedBytes; import net.corda.core.serialization.SerializedBytes;
import net.corda.serialization.internal.AllWhitelist;
import net.corda.serialization.internal.amqp.testutils.TestSerializationContext; import net.corda.serialization.internal.amqp.testutils.TestSerializationContext;
import org.assertj.core.api.Assertions;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.junit.Test; import org.junit.Test;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import java.util.List; import java.util.List;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
class OuterClass1 { class OuterClass1 {
protected SerializationOutput ser; protected SerializationOutput ser;
DeserializationInput desExisting; DeserializationInput desExisting;
DeserializationInput desRegen; DeserializationInput desRegen;
OuterClass1() { OuterClass1() {
SerializerFactory factory1 = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory1 = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializerFactory factory2 = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory2 = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
this.ser = new SerializationOutput(factory1); this.ser = new SerializationOutput(factory1);
this.desExisting = new DeserializationInput(factory1); this.desExisting = new DeserializationInput(factory1);
@ -59,13 +56,9 @@ class OuterClass2 {
DeserializationInput desRegen; DeserializationInput desRegen;
OuterClass2() { OuterClass2() {
SerializerFactory factory1 = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory1 = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializerFactory factory2 = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory2 = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
this.ser = new SerializationOutput(factory1); this.ser = new SerializationOutput(factory1);
this.desExisting = new DeserializationInput(factory1); this.desExisting = new DeserializationInput(factory1);
@ -104,9 +97,7 @@ abstract class AbstractClass2 {
protected SerializationOutput ser; protected SerializationOutput ser;
AbstractClass2() { AbstractClass2() {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
this.ser = new SerializationOutput(factory); this.ser = new SerializationOutput(factory);
} }
@ -134,9 +125,7 @@ abstract class AbstractClass3 {
class Inherator5 extends AbstractClass3 { class Inherator5 extends AbstractClass3 {
public void run() throws NotSerializableException { public void run() throws NotSerializableException {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
ser.serialize(new DummyState(), TestSerializationContext.testSerializationContext); ser.serialize(new DummyState(), TestSerializationContext.testSerializationContext);
@ -154,9 +143,7 @@ class Inherator6 extends AbstractClass3 {
} }
public void run() throws NotSerializableException { public void run() throws NotSerializableException {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
ser.serialize(new Wrapper(new DummyState()), TestSerializationContext.testSerializationContext); ser.serialize(new Wrapper(new DummyState()), TestSerializationContext.testSerializationContext);
@ -166,57 +153,57 @@ class Inherator6 extends AbstractClass3 {
public class JavaNestedClassesTests { public class JavaNestedClassesTests {
@Test @Test
public void publicNested() { public void publicNested() {
Assertions.assertThatThrownBy(() -> new OuterClass1().run()).isInstanceOf( assertThatThrownBy(() -> new OuterClass1().run()).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }
@Test @Test
public void privateNested() { public void privateNested() {
Assertions.assertThatThrownBy(() -> new OuterClass2().run()).isInstanceOf( assertThatThrownBy(() -> new OuterClass2().run()).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }
@Test @Test
public void publicNestedInherited() { public void publicNestedInherited() {
Assertions.assertThatThrownBy(() -> new Inherator1().run()).isInstanceOf( assertThatThrownBy(() -> new Inherator1().run()).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
Assertions.assertThatThrownBy(() -> new Inherator1().iRun()).isInstanceOf( assertThatThrownBy(() -> new Inherator1().iRun()).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }
@Test @Test
public void protectedNestedInherited() { public void protectedNestedInherited() {
Assertions.assertThatThrownBy(() -> new Inherator2().run()).isInstanceOf( assertThatThrownBy(() -> new Inherator2().run()).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
Assertions.assertThatThrownBy(() -> new Inherator2().iRun()).isInstanceOf( assertThatThrownBy(() -> new Inherator2().iRun()).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }
@Test @Test
public void abstractNested() { public void abstractNested() {
Assertions.assertThatThrownBy(() -> new Inherator4().run()).isInstanceOf( assertThatThrownBy(() -> new Inherator4().run()).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }
@Test @Test
public void abstractNestedFactoryOnNested() { public void abstractNestedFactoryOnNested() {
Assertions.assertThatThrownBy(() -> new Inherator5().run()).isInstanceOf( assertThatThrownBy(() -> new Inherator5().run()).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }
@Test @Test
public void abstractNestedFactoryOnNestedInWrapper() { public void abstractNestedFactoryOnNestedInWrapper() {
Assertions.assertThatThrownBy(() -> new Inherator6().run()).isInstanceOf( assertThatThrownBy(() -> new Inherator6().run()).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }

View File

@ -3,15 +3,16 @@ package net.corda.serialization.internal.amqp;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import net.corda.core.contracts.ContractState; import net.corda.core.contracts.ContractState;
import net.corda.core.identity.AbstractParty; import net.corda.core.identity.AbstractParty;
import net.corda.serialization.internal.AllWhitelist;
import net.corda.serialization.internal.amqp.testutils.TestSerializationContext; import net.corda.serialization.internal.amqp.testutils.TestSerializationContext;
import org.assertj.core.api.Assertions;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.junit.Test; import org.junit.Test;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import java.util.List; import java.util.List;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
abstract class JavaNestedInheritenceTestsBase { abstract class JavaNestedInheritenceTestsBase {
class DummyState implements ContractState { class DummyState implements ContractState {
@Override @NotNull public List<AbstractParty> getParticipants() { @Override @NotNull public List<AbstractParty> getParticipants() {
@ -33,38 +34,32 @@ class TemplateWrapper<T> {
public class JavaNestedInheritenceTests extends JavaNestedInheritenceTestsBase { public class JavaNestedInheritenceTests extends JavaNestedInheritenceTestsBase {
@Test @Test
public void serializeIt() { public void serializeIt() {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
Assertions.assertThatThrownBy(() -> ser.serialize(new DummyState(), TestSerializationContext.testSerializationContext)).isInstanceOf( assertThatThrownBy(() -> ser.serialize(new DummyState(), TestSerializationContext.testSerializationContext)).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }
@Test @Test
public void serializeIt2() { public void serializeIt2() {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
Assertions.assertThatThrownBy(() -> ser.serialize(new Wrapper (new DummyState()), TestSerializationContext.testSerializationContext)).isInstanceOf( assertThatThrownBy(() -> ser.serialize(new Wrapper (new DummyState()), TestSerializationContext.testSerializationContext)).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }
@Test @Test
public void serializeIt3() throws NotSerializableException { public void serializeIt3() {
SerializerFactory factory1 = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory1 = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory1); SerializationOutput ser = new SerializationOutput(factory1);
Assertions.assertThatThrownBy(() -> ser.serialize(new TemplateWrapper<ContractState> (new DummyState()), TestSerializationContext.testSerializationContext)).isInstanceOf( assertThatThrownBy(() -> ser.serialize(new TemplateWrapper<ContractState> (new DummyState()), TestSerializationContext.testSerializationContext)).isInstanceOf(
NotSerializableException.class).hasMessageContaining( NotSerializableException.class).hasMessageContaining(
"has synthetic fields and is likely a nested inner class"); "has synthetic fields and is likely a nested inner class");
} }

View File

@ -1,14 +1,15 @@
package net.corda.serialization.internal.amqp; package net.corda.serialization.internal.amqp;
import net.corda.serialization.internal.AllWhitelist;
import net.corda.serialization.internal.amqp.testutils.TestSerializationContext; import net.corda.serialization.internal.amqp.testutils.TestSerializationContext;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Map; import java.util.Map;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
import static org.junit.Assert.*;
public class JavaPrivatePropertyTests { public class JavaPrivatePropertyTests {
static class C { static class C {
private String a; private String a;
@ -76,10 +77,8 @@ public class JavaPrivatePropertyTests {
} }
@Test @Test
public void singlePrivateBooleanWithConstructor() throws NotSerializableException, NoSuchFieldException, IllegalAccessException { public void singlePrivateBooleanWithConstructor() throws NotSerializableException {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
DeserializationInput des = new DeserializationInput(factory); DeserializationInput des = new DeserializationInput(factory);
@ -89,10 +88,8 @@ public class JavaPrivatePropertyTests {
} }
@Test @Test
public void singlePrivateBooleanWithNoConstructor() throws NotSerializableException, NoSuchFieldException, IllegalAccessException { public void singlePrivateBooleanWithNoConstructor() throws NotSerializableException {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
DeserializationInput des = new DeserializationInput(factory); DeserializationInput des = new DeserializationInput(factory);
@ -104,10 +101,8 @@ public class JavaPrivatePropertyTests {
} }
@Test @Test
public void testCapitilsationOfIs() throws NotSerializableException, NoSuchFieldException, IllegalAccessException { public void testCapitilsationOfIs() throws NotSerializableException {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
DeserializationInput des = new DeserializationInput(factory); DeserializationInput des = new DeserializationInput(factory);
@ -120,10 +115,8 @@ public class JavaPrivatePropertyTests {
} }
@Test @Test
public void singlePrivateIntWithBoolean() throws NotSerializableException, NoSuchFieldException, IllegalAccessException { public void singlePrivateIntWithBoolean() throws NotSerializableException {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
DeserializationInput des = new DeserializationInput(factory); DeserializationInput des = new DeserializationInput(factory);
@ -136,9 +129,7 @@ public class JavaPrivatePropertyTests {
@Test @Test
public void singlePrivateWithConstructor() throws NotSerializableException, NoSuchFieldException, IllegalAccessException { public void singlePrivateWithConstructor() throws NotSerializableException, NoSuchFieldException, IllegalAccessException {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializerFactory factory = testDefaultFactory();
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
DeserializationInput des = new DeserializationInput(factory); DeserializationInput des = new DeserializationInput(factory);
@ -166,10 +157,7 @@ public class JavaPrivatePropertyTests {
@Test @Test
public void singlePrivateWithConstructorAndGetter() public void singlePrivateWithConstructorAndGetter()
throws NotSerializableException, NoSuchFieldException, IllegalAccessException { throws NotSerializableException, NoSuchFieldException, IllegalAccessException {
SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, SerializerFactory factory = testDefaultFactory();
ClassLoader.getSystemClassLoader(),
new EvolutionSerializerGetter(),
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory); SerializationOutput ser = new SerializationOutput(factory);
DeserializationInput des = new DeserializationInput(factory); DeserializationInput des = new DeserializationInput(factory);

View File

@ -1,13 +1,13 @@
package net.corda.serialization.internal.amqp; package net.corda.serialization.internal.amqp;
import net.corda.core.serialization.SerializedBytes;
import net.corda.serialization.internal.amqp.testutils.TestSerializationContext; import net.corda.serialization.internal.amqp.testutils.TestSerializationContext;
import org.junit.Test; import org.junit.Test;
import net.corda.serialization.internal.AllWhitelist;
import net.corda.core.serialization.SerializedBytes;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
public class JavaSerialiseEnumTests { public class JavaSerialiseEnumTests {
public enum Bras { public enum Bras {
@ -30,10 +30,7 @@ public class JavaSerialiseEnumTests {
public void testJavaConstructorAnnotations() throws NotSerializableException { public void testJavaConstructorAnnotations() throws NotSerializableException {
Bra bra = new Bra(Bras.UNDERWIRE); Bra bra = new Bra(Bras.UNDERWIRE);
SerializerFactory factory1 = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(), SerializationOutput ser = new SerializationOutput(testDefaultFactory());
new EvolutionSerializerGetter(), ser.serialize(bra, TestSerializationContext.testSerializationContext);
new SerializerFingerPrinter());
SerializationOutput ser = new SerializationOutput(factory1);
SerializedBytes<Object> bytes = ser.serialize(bra, TestSerializationContext.testSerializationContext);
} }
} }

View File

@ -1,7 +1,6 @@
package net.corda.serialization.internal.amqp; package net.corda.serialization.internal.amqp;
import net.corda.core.serialization.ConstructorForDeserialization; import net.corda.core.serialization.ConstructorForDeserialization;
import net.corda.serialization.internal.AllWhitelist;
import net.corda.core.serialization.SerializedBytes; import net.corda.core.serialization.SerializedBytes;
import net.corda.serialization.internal.amqp.testutils.TestSerializationContext; import net.corda.serialization.internal.amqp.testutils.TestSerializationContext;
import org.apache.qpid.proton.codec.DecoderImpl; import org.apache.qpid.proton.codec.DecoderImpl;
@ -13,6 +12,7 @@ import java.io.NotSerializableException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Objects; import java.util.Objects;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
public class JavaSerializationOutputTests { public class JavaSerializationOutputTests {
@ -176,14 +176,8 @@ public class JavaSerializationOutputTests {
} }
private Object serdes(Object obj) throws NotSerializableException { private Object serdes(Object obj) throws NotSerializableException {
EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); SerializerFactory factory1 = testDefaultFactory();
FingerPrinter fingerPrinter = new SerializerFingerPrinter(); SerializerFactory factory2 = testDefaultFactory();
SerializerFactory factory1 = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(),
evolutionSerialiserGetter,
fingerPrinter);
SerializerFactory factory2 = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(),
evolutionSerialiserGetter,
fingerPrinter);
SerializationOutput ser = new SerializationOutput(factory1); SerializationOutput ser = new SerializationOutput(factory1);
SerializedBytes<Object> bytes = ser.serialize(obj, TestSerializationContext.testSerializationContext); SerializedBytes<Object> bytes = ser.serialize(obj, TestSerializationContext.testSerializationContext);

View File

@ -2,7 +2,6 @@ package net.corda.serialization.internal.amqp;
import net.corda.core.serialization.CordaSerializable; import net.corda.core.serialization.CordaSerializable;
import net.corda.core.serialization.SerializedBytes; import net.corda.core.serialization.SerializedBytes;
import net.corda.serialization.internal.AllWhitelist;
import net.corda.serialization.internal.amqp.testutils.TestSerializationContext; import net.corda.serialization.internal.amqp.testutils.TestSerializationContext;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -10,6 +9,8 @@ import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
public class ListsSerializationJavaTest { public class ListsSerializationJavaTest {
@CordaSerializable @CordaSerializable
@ -126,12 +127,7 @@ public class ListsSerializationJavaTest {
// Have to have own version as Kotlin inline functions cannot be easily called from Java // Have to have own version as Kotlin inline functions cannot be easily called from Java
private static <T> void assertEqualAfterRoundTripSerialization(T container, Class<T> clazz) throws Exception { private static <T> void assertEqualAfterRoundTripSerialization(T container, Class<T> clazz) throws Exception {
EvolutionSerializerGetterBase evolutionSerializerGetter = new EvolutionSerializerGetter(); SerializerFactory factory1 = testDefaultFactory();
FingerPrinter fingerPrinter = new SerializerFingerPrinter();
SerializerFactory factory1 = new SerializerFactory(
AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader(),
evolutionSerializerGetter,
fingerPrinter);
SerializationOutput ser = new SerializationOutput(factory1); SerializationOutput ser = new SerializationOutput(factory1);
SerializedBytes<Object> bytes = ser.serialize(container, TestSerializationContext.testSerializationContext); SerializedBytes<Object> bytes = ser.serialize(container, TestSerializationContext.testSerializationContext);
DeserializationInput des = new DeserializationInput(factory1); DeserializationInput des = new DeserializationInput(factory1);

View File

@ -1,16 +1,17 @@
package net.corda.serialization.internal.amqp; package net.corda.serialization.internal.amqp;
import net.corda.core.serialization.SerializedBytes; import net.corda.core.serialization.SerializedBytes;
import net.corda.serialization.internal.AllWhitelist;
import net.corda.serialization.internal.amqp.testutils.TestSerializationContext; import net.corda.serialization.internal.amqp.testutils.TestSerializationContext;
import org.assertj.core.api.Assertions;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static net.corda.serialization.internal.amqp.testutils.AMQPTestUtilsKt.testDefaultFactory;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertEquals;
public class SetterConstructorTests { public class SetterConstructorTests {
static class C { static class C {
@ -119,13 +120,7 @@ public class SetterConstructorTests {
// despite having no constructor we should still be able to serialise an instance of C // despite having no constructor we should still be able to serialise an instance of C
@Test @Test
public void serialiseC() throws NotSerializableException { public void serialiseC() throws NotSerializableException {
EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); SerializerFactory factory1 = testDefaultFactory();
FingerPrinter fingerPrinter = new SerializerFingerPrinter();
SerializerFactory factory1 = new SerializerFactory(
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
evolutionSerialiserGetter,
fingerPrinter);
SerializationOutput ser = new SerializationOutput(factory1); SerializationOutput ser = new SerializationOutput(factory1);
@ -195,13 +190,7 @@ public class SetterConstructorTests {
@Test @Test
public void deserialiseC() throws NotSerializableException { public void deserialiseC() throws NotSerializableException {
EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); SerializerFactory factory1 = testDefaultFactory();
FingerPrinter fingerPrinter = new SerializerFingerPrinter();
SerializerFactory factory1 = new SerializerFactory(
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
evolutionSerialiserGetter,
fingerPrinter);
C cPre1 = new C(); C cPre1 = new C();
@ -268,13 +257,7 @@ public class SetterConstructorTests {
@Test @Test
public void serialiseOuterAndInner() throws NotSerializableException { public void serialiseOuterAndInner() throws NotSerializableException {
EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); SerializerFactory factory1 = testDefaultFactory();
FingerPrinter fingerPrinter = new SerializerFingerPrinter();
SerializerFactory factory1 = new SerializerFactory(
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
evolutionSerialiserGetter,
fingerPrinter);
Inner1 i1 = new Inner1("Hello"); Inner1 i1 = new Inner1("Hello");
Inner2 i2 = new Inner2(); Inner2 i2 = new Inner2();
@ -298,38 +281,26 @@ public class SetterConstructorTests {
@Test @Test
public void typeMistmatch() { public void typeMistmatch() {
EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); SerializerFactory factory1 = testDefaultFactory();
FingerPrinter fingerPrinter = new SerializerFingerPrinter();
SerializerFactory factory1 = new SerializerFactory(
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
evolutionSerialiserGetter,
fingerPrinter);
TypeMismatch tm = new TypeMismatch(); TypeMismatch tm = new TypeMismatch();
tm.setA(10); tm.setA(10);
assertEquals("10", tm.getA()); assertEquals("10", tm.getA());
Assertions.assertThatThrownBy(() -> new SerializationOutput(factory1).serialize(tm, assertThatThrownBy(() -> new SerializationOutput(factory1).serialize(tm,
TestSerializationContext.testSerializationContext)).isInstanceOf ( TestSerializationContext.testSerializationContext)).isInstanceOf (
NotSerializableException.class); NotSerializableException.class);
} }
@Test @Test
public void typeMistmatch2() { public void typeMistmatch2() {
EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); SerializerFactory factory1 = testDefaultFactory();
FingerPrinter fingerPrinter = new SerializerFingerPrinter();
SerializerFactory factory1 = new SerializerFactory(
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
evolutionSerialiserGetter,
fingerPrinter);
TypeMismatch2 tm = new TypeMismatch2(); TypeMismatch2 tm = new TypeMismatch2();
tm.setA("10"); tm.setA("10");
assertEquals((Integer)10, tm.getA()); assertEquals((Integer)10, tm.getA());
Assertions.assertThatThrownBy(() -> new SerializationOutput(factory1).serialize(tm, assertThatThrownBy(() -> new SerializationOutput(factory1).serialize(tm,
TestSerializationContext.testSerializationContext)).isInstanceOf( TestSerializationContext.testSerializationContext)).isInstanceOf(
NotSerializableException.class); NotSerializableException.class);
} }
@ -346,13 +317,7 @@ public class SetterConstructorTests {
cil.setL(l); cil.setL(l);
EvolutionSerializerGetterBase evolutionSerialiserGetter = new EvolutionSerializerGetter(); SerializerFactory factory1 = testDefaultFactory();
FingerPrinter fingerPrinter = new SerializerFingerPrinter();
SerializerFactory factory1 = new SerializerFactory(
AllWhitelist.INSTANCE,
ClassLoader.getSystemClassLoader(),
evolutionSerialiserGetter,
fingerPrinter);
// if we've got super / sub types on the setter vs the underlying type the wrong way around this will // if we've got super / sub types on the setter vs the underlying type the wrong way around this will
// explode. See CORDA-1229 (https://r3-cev.atlassian.net/browse/CORDA-1229) // explode. See CORDA-1229 (https://r3-cev.atlassian.net/browse/CORDA-1229)

View File

@ -1,11 +1,8 @@
package net.corda.serialization.internal.amqp package net.corda.serialization.internal.amqp
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.testutils.*
import net.corda.serialization.internal.carpenter.* import net.corda.serialization.internal.carpenter.*
import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput
import net.corda.serialization.internal.amqp.testutils.deserialize
import net.corda.serialization.internal.amqp.testutils.serialize
import net.corda.serialization.internal.amqp.testutils.testDefaultFactoryNoEvolution
import org.junit.Test import org.junit.Test
import kotlin.test.* import kotlin.test.*

View File

@ -1,15 +1,13 @@
package net.corda.serialization.internal.amqp package net.corda.serialization.internal.amqp
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.serialization.internal.carpenter.*
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.amqp.testutils.TestSerializationOutput import net.corda.serialization.internal.amqp.testutils.*
import net.corda.serialization.internal.amqp.testutils.testDefaultFactoryNoEvolution import net.corda.serialization.internal.carpenter.*
import net.corda.serialization.internal.amqp.testutils.testDefaultFactoryWithWhitelist
import net.corda.serialization.internal.amqp.testutils.serialize
import net.corda.serialization.internal.amqp.testutils.deserialize
import org.junit.Test import org.junit.Test
import kotlin.test.* import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.assertTrue
@CordaSerializable @CordaSerializable
interface I { interface I {

View File

@ -46,8 +46,8 @@ class FingerPrinterTestingTests {
val factory = SerializerFactory( val factory = SerializerFactory(
AllWhitelist, AllWhitelist,
ClassLoader.getSystemClassLoader(), ClassLoader.getSystemClassLoader(),
EvolutionSerializerGetterTesting(), evolutionSerializerGetter = EvolutionSerializerGetterTesting(),
FingerPrinterTesting()) fingerPrinter = FingerPrinterTesting())
val blob = TestSerializationOutput(VERBOSE, factory).serializeAndReturnSchema(C(1, 2L)) val blob = TestSerializationOutput(VERBOSE, factory).serializeAndReturnSchema(C(1, 2L))

View File

@ -7,13 +7,7 @@ import com.nhaarman.mockito_kotlin.whenever
import net.corda.client.rpc.RPCException import net.corda.client.rpc.RPCException
import net.corda.core.CordaException import net.corda.core.CordaException
import net.corda.core.CordaRuntimeException import net.corda.core.CordaRuntimeException
import net.corda.core.contracts.Amount import net.corda.core.contracts.*
import net.corda.core.contracts.Contract
import net.corda.core.contracts.ContractAttachment
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.PrivacySalt
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TransactionState
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.secureRandomBytes import net.corda.core.crypto.secureRandomBytes
@ -22,48 +16,25 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.AbstractAttachment import net.corda.core.internal.AbstractAttachment
import net.corda.core.internal.x500Name import net.corda.core.internal.x500Name
import net.corda.core.serialization.ConstructorForDeserialization import net.corda.core.serialization.*
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.EncodingWhitelist
import net.corda.core.serialization.MissingAttachmentsException
import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationFactory
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
import net.corda.node.serialization.amqp.AMQPServerSerializationScheme import net.corda.node.serialization.amqp.AMQPServerSerializationScheme
import net.corda.nodeapi.internal.DEV_INTERMEDIATE_CA import net.corda.nodeapi.internal.DEV_INTERMEDIATE_CA
import net.corda.nodeapi.internal.crypto.ContentSignerBuilder import net.corda.nodeapi.internal.crypto.ContentSignerBuilder
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.*
import net.corda.serialization.internal.CordaSerializationEncoding
import net.corda.serialization.internal.EmptyWhitelist
import net.corda.serialization.internal.GeneratedAttachment
import net.corda.serialization.internal.amqp.SerializerFactory.Companion.isPrimitive import net.corda.serialization.internal.amqp.SerializerFactory.Companion.isPrimitive
import net.corda.serialization.internal.amqp.testutils.deserialize import net.corda.serialization.internal.amqp.testutils.*
import net.corda.serialization.internal.amqp.testutils.serialize
import net.corda.serialization.internal.amqp.testutils.testDefaultFactory
import net.corda.serialization.internal.amqp.testutils.testDefaultFactoryNoEvolution
import net.corda.serialization.internal.amqp.testutils.testSerializationContext
import net.corda.serialization.internal.encodingNotPermittedFormat
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.core.BOB_NAME import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.core.TestIdentity import net.corda.testing.core.TestIdentity
import net.corda.testing.internal.rigorousMock import net.corda.testing.internal.rigorousMock
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
import org.apache.qpid.proton.amqp.Decimal128 import org.apache.qpid.proton.amqp.*
import org.apache.qpid.proton.amqp.Decimal32
import org.apache.qpid.proton.amqp.Decimal64
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.amqp.UnsignedByte
import org.apache.qpid.proton.amqp.UnsignedInteger
import org.apache.qpid.proton.amqp.UnsignedLong
import org.apache.qpid.proton.amqp.UnsignedShort
import org.apache.qpid.proton.codec.DecoderImpl import org.apache.qpid.proton.codec.DecoderImpl
import org.apache.qpid.proton.codec.EncoderImpl import org.apache.qpid.proton.codec.EncoderImpl
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.*
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.assertj.core.api.Assertions.catchThrowable
import org.bouncycastle.cert.X509v2CRLBuilder import org.bouncycastle.cert.X509v2CRLBuilder
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter import org.bouncycastle.cert.jcajce.JcaX509CRLConverter
import org.bouncycastle.jce.provider.BouncyCastleProvider import org.bouncycastle.jce.provider.BouncyCastleProvider
@ -79,20 +50,7 @@ import java.io.NotSerializableException
import java.math.BigDecimal import java.math.BigDecimal
import java.math.BigInteger import java.math.BigInteger
import java.security.cert.X509CRL import java.security.cert.X509CRL
import java.time.DayOfWeek import java.time.*
import java.time.Duration
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.Month
import java.time.MonthDay
import java.time.OffsetDateTime
import java.time.OffsetTime
import java.time.Period
import java.time.Year
import java.time.YearMonth
import java.time.ZonedDateTime
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
import java.util.* import java.util.*
import kotlin.reflect.full.superclasses import kotlin.reflect.full.superclasses
@ -249,9 +207,13 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
if (compression != null) doReturn(true).whenever(it).acceptEncoding(compression) if (compression != null) doReturn(true).whenever(it).acceptEncoding(compression)
} }
private fun defaultFactory() = SerializerFactory( private fun defaultFactory(): SerializerFactory {
AllWhitelist, ClassLoader.getSystemClassLoader(), return SerializerFactory(
EvolutionSerializerGetterTesting()) AllWhitelist,
ClassLoader.getSystemClassLoader(),
evolutionSerializerGetter = EvolutionSerializerGetterTesting()
)
}
private inline fun <reified T : Any> serdes(obj: T, private inline fun <reified T : Any> serdes(obj: T,
factory: SerializerFactory = defaultFactory(), factory: SerializerFactory = defaultFactory(),

View File

@ -1,16 +1,25 @@
package net.corda.serialization.internal.amqp.testutils package net.corda.serialization.internal.amqp.testutils
import net.corda.core.internal.copyTo
import net.corda.core.internal.div
import net.corda.core.internal.packageName
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.SerializedBytes
import org.apache.qpid.proton.codec.Data import net.corda.core.utilities.OpaqueBytes
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import net.corda.serialization.internal.EmptyWhitelist import net.corda.serialization.internal.EmptyWhitelist
import net.corda.serialization.internal.amqp.* import net.corda.serialization.internal.amqp.*
import net.corda.testing.common.internal.ProjectStructure
import org.apache.qpid.proton.codec.Data
import org.junit.Test
import java.io.File.separatorChar
import java.io.NotSerializableException import java.io.NotSerializableException
import java.nio.file.StandardCopyOption.REPLACE_EXISTING
fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
fun testDefaultFactoryNoEvolution() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader(), fun testDefaultFactoryNoEvolution(): SerializerFactory {
EvolutionSerializerGetterTesting()) return SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader(), evolutionSerializerGetter = EvolutionSerializerGetterTesting())
}
fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()) fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())
class TestSerializationOutput( class TestSerializationOutput(
@ -41,8 +50,25 @@ class TestSerializationOutput(
} }
} }
fun testName(): String = Thread.currentThread().stackTrace[2].methodName fun testName(): String {
val classLoader = Thread.currentThread().contextClassLoader
return Thread.currentThread().stackTrace.first {
try {
classLoader.loadClass(it.className).getMethod(it.methodName).isAnnotationPresent(Test::class.java)
} catch (e: Exception) {
false
}
}.methodName
}
fun Any.testResourceName(): String = "${javaClass.simpleName}.${testName()}"
fun Any.writeTestResource(bytes: OpaqueBytes) {
val dir = ProjectStructure.projectRootDir / "serialization" / "src" / "test" / "resources" / javaClass.packageName.replace('.', separatorChar)
bytes.open().copyTo(dir / testResourceName(), REPLACE_EXISTING)
}
fun Any.readTestResource(): ByteArray = javaClass.getResourceAsStream(testResourceName()).readBytes()
@Throws(NotSerializableException::class) @Throws(NotSerializableException::class)
inline fun <reified T : Any> DeserializationInput.deserializeAndReturnEnvelope( inline fun <reified T : Any> DeserializationInput.deserializeAndReturnEnvelope(

View File

@ -2,6 +2,7 @@ package net.corda.serialization.internal.carpenter
import net.corda.core.internal.uncheckedCast import net.corda.core.internal.uncheckedCast
import net.corda.serialization.internal.AllWhitelist import net.corda.serialization.internal.AllWhitelist
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.junit.Test import org.junit.Test
import java.beans.Introspector import java.beans.Introspector
import java.lang.reflect.Field import java.lang.reflect.Field
@ -145,21 +146,40 @@ class ClassCarpenterTest {
assertEquals(1, i.b) assertEquals(1, i.b)
} }
@Test(expected = InterfaceMismatchException::class) @Test
fun `mismatched interface`() { fun `unimplemented interface method with lenient = false`() {
val schema1 = ClassSchema( val schemaA = ClassSchema(
"gen.A", "gen.A",
mapOf("a" to NonNullableField(String::class.java))) mapOf("a" to NonNullableField(String::class.java)))
val schema2 = ClassSchema( val schemaB = ClassSchema(
"gen.B", "gen.B",
mapOf("c" to NonNullableField(Int::class.java)), mapOf("c" to NonNullableField(Int::class.java)),
schema1, schemaA,
interfaces = listOf(DummyInterface::class.java)) interfaces = listOf(DummyInterface::class.java))
val clazz = cc.build(schema2) assertThatExceptionOfType(InterfaceMismatchException::class.java).isThrownBy { cc.build(schemaB) }
val i = clazz.constructors[0].newInstance("xa", 1) as DummyInterface }
assertEquals(1, i.b)
@Test
fun `unimplemented interface method with lenient = true`() {
val cc = ClassCarpenterImpl(whitelist = AllWhitelist, lenient = true)
val schemaA = ClassSchema(
"gen.A",
mapOf("a" to NonNullableField(String::class.java)))
val schemaB = ClassSchema(
"gen.B",
mapOf("c" to NonNullableField(Int::class.java)),
schemaA,
interfaces = listOf(DummyInterface::class.java))
val classB = cc.build(schemaB)
val b = classB.constructors[0].newInstance("xa", 1) as DummyInterface
assertEquals("xa", b.a)
assertEquals(1, classB.getMethod("getC").invoke(b))
assertThatExceptionOfType(AbstractMethodError::class.java).isThrownBy { b.b }
} }
@Test @Test

View File

@ -5,6 +5,7 @@ import net.corda.serialization.internal.amqp.*
import net.corda.serialization.internal.amqp.Field import net.corda.serialization.internal.amqp.Field
import net.corda.serialization.internal.amqp.Schema import net.corda.serialization.internal.amqp.Schema
import net.corda.serialization.internal.amqp.testutils.serialize import net.corda.serialization.internal.amqp.testutils.serialize
import net.corda.serialization.internal.amqp.testutils.testName
fun mangleName(name: String) = "${name}__carpenter" fun mangleName(name: String) = "${name}__carpenter"
@ -47,7 +48,6 @@ open class AmqpCarpenterBase(whitelist: ClassWhitelist) {
var factory = SerializerFactoryExternalCarpenter(cc) var factory = SerializerFactoryExternalCarpenter(cc)
fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz) fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz)
fun testName(): String = Thread.currentThread().stackTrace[2].methodName
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
inline fun classTestName(clazz: String) = "${this.javaClass.name}\$${testName()}\$$clazz" inline fun classTestName(clazz: String) = "${this.javaClass.name}\$${testName()}\$$clazz"
} }

View File

@ -0,0 +1,49 @@
package net.corda.serialization.internal.carpenter
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializationFactory
import net.corda.core.serialization.deserialize
import net.corda.serialization.internal.amqp.testutils.readTestResource
import net.corda.testing.core.SerializationEnvironmentRule
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.junit.Rule
import org.junit.Test
class SerDeserCarpentryTest {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
@Test
fun implementingGenericInterface() {
// Original class that was serialised
// data class GenericData(val a: Int) : GenericInterface<String>
// writeTestResource(GenericData(123).serialize())
val data = readTestResource().deserialize<GenericInterface<*>>()
assertThat(data.javaClass.getMethod("getA").invoke(data)).isEqualTo(123)
}
@Test
fun lenientCarpenter() {
// Original class that was serialised
// data class Data(val b: Int) : AInterface {
// override val a: Int get() = b
// }
// writeTestResource(Data(123).serialize())
val data = readTestResource().deserialize<AInterface>(context = SerializationFactory.defaultFactory.defaultContext.withLenientCarpenter())
assertThat(data.javaClass.getMethod("getB").invoke(data)).isEqualTo(123)
assertThatExceptionOfType(AbstractMethodError::class.java).isThrownBy { data.a }
}
@Suppress("unused")
@CordaSerializable
interface GenericInterface<T>
@CordaSerializable
interface AInterface {
val a: Int
}
}

View File

@ -7,6 +7,7 @@ import net.corda.client.jackson.JacksonSupport
import net.corda.core.internal.isRegularFile import net.corda.core.internal.isRegularFile
import net.corda.core.internal.rootMessage import net.corda.core.internal.rootMessage
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationFactory
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
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
@ -33,7 +34,7 @@ fun main(args: Array<String>) {
if (main.verbose) { if (main.verbose) {
throwable.printStackTrace() throwable.printStackTrace()
} else { } else {
System.err.println("*ERROR*: ${throwable.rootMessage ?: "Use --verbose for more details"}") System.err.println("*ERROR*: ${throwable.rootMessage}. Use --verbose for more details")
} }
exitProcess(1) exitProcess(1)
} }
@ -91,7 +92,8 @@ class Main : Runnable {
} }
val mapper = JacksonSupport.createNonRpcMapper(factory, fullParties) val mapper = JacksonSupport.createNonRpcMapper(factory, fullParties)
val deserialized = bytes.deserialize<Any>() // Deserialise with the lenient carpenter as we only care for the AMQP field getters
val deserialized = bytes.deserialize<Any>(context = SerializationFactory.defaultFactory.defaultContext.withLenientCarpenter())
println(deserialized.javaClass.name) println(deserialized.javaClass.name)
mapper.writeValue(System.out, deserialized) mapper.writeValue(System.out, deserialized)
} }