Review comments

* Move all alterations on the amqp schema object out of the actual
  amqp/Schema file and have them live in the carpenter as extension
  functions
* Move carpenter exceptions to their own file
* Rename the schema name corrupter to the name mangler
* reduce whitespace
* alter comment style
This commit is contained in:
Katelyn Baker 2017-07-12 10:37:23 +01:00
parent 5ab26dd275
commit 86902e6356
11 changed files with 283 additions and 417 deletions

View File

@ -15,11 +15,8 @@ import java.lang.reflect.Type
import java.lang.reflect.TypeVariable import java.lang.reflect.TypeVariable
import java.util.* import java.util.*
import net.corda.core.serialization.carpenter.CarpenterSchemas
import net.corda.core.serialization.carpenter.Schema as CarpenterSchema import net.corda.core.serialization.carpenter.Schema as CarpenterSchema
import net.corda.core.serialization.carpenter.Field as CarpenterField import net.corda.core.serialization.carpenter.Field as CarpenterField
import net.corda.core.serialization.carpenter.CarpenterSchemaFactory
import net.corda.core.serialization.carpenter.FieldFactory
// TODO: get an assigned number as per AMQP spec // TODO: get an assigned number as per AMQP spec
val DESCRIPTOR_TOP_32BITS: Long = 0xc0da0000 val DESCRIPTOR_TOP_32BITS: Long = 0xc0da0000
@ -29,24 +26,6 @@ val DESCRIPTOR_DOMAIN: String = "net.corda"
// "corda" + majorVersionByte + minorVersionMSB + minorVersionLSB // "corda" + majorVersionByte + minorVersionMSB + minorVersionLSB
val AmqpHeaderV1_0: OpaqueBytes = OpaqueBytes("corda\u0001\u0000\u0000".toByteArray()) val AmqpHeaderV1_0: OpaqueBytes = OpaqueBytes("corda\u0001\u0000\u0000".toByteArray())
private fun List<ClassLoader>.exists (clazz: String) =
this.find { try { it.loadClass(clazz); true } catch (e: ClassNotFoundException) { false } } != null
private fun List<ClassLoader>.loadIfExists (clazz: String) : Class<*> {
this.forEach {
try {
return it.loadClass(clazz)
} catch (e: ClassNotFoundException) {
return@forEach
}
}
throw ClassNotFoundException(clazz)
}
class UncarpentableException (name: String, field: String, type: String) :
Throwable ("Class $name is loadable yet contains field $field of unknown type $type")
/** /**
* This class wraps all serialized data, so that the schema can be carried along with it. We will provide various internal utilities * This class wraps all serialized data, so that the schema can be carried along with it. We will provide various internal utilities
* to decompose and recompose with/without schema etc so that e.g. we can store objects with a (relationally) normalised out schema to * to decompose and recompose with/without schema etc so that e.g. we can store objects with a (relationally) normalised out schema to
@ -111,18 +90,6 @@ data class Schema(val types: List<TypeNotation>) : DescribedType {
override fun getDescribed(): Any = listOf(types) override fun getDescribed(): Any = listOf(types)
override fun toString(): String = types.joinToString("\n") override fun toString(): String = types.joinToString("\n")
fun carpenterSchema(loaders : List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader()))
: CarpenterSchemas
{
val rtn = CarpenterSchemas.newInstance()
types.filterIsInstance<CompositeType>().forEach {
it.carpenterSchema(classLoaders = loaders, carpenterSchemas = rtn)
}
return rtn
}
} }
data class Descriptor(val name: String?, val code: UnsignedLong? = null) : DescribedType { data class Descriptor(val name: String?, val code: UnsignedLong? = null) : DescribedType {
@ -205,29 +172,6 @@ data class Field(val name: String, val type: String, val requires: List<String>,
return sb.toString() return sb.toString()
} }
fun getTypeAsClass(
classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader())
) = when (type) {
"int" -> Int::class.javaPrimitiveType!!
"string" -> String::class.java
"short" -> Short::class.javaPrimitiveType!!
"long" -> Long::class.javaPrimitiveType!!
"char" -> Char::class.javaPrimitiveType!!
"boolean" -> Boolean::class.javaPrimitiveType!!
"double" -> Double::class.javaPrimitiveType!!
"float" -> Float::class.javaPrimitiveType!!
"*" -> classLoaders.loadIfExists(requires[0])
else -> classLoaders.loadIfExists(type)
}
fun validateType(
classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader())
) = when (type) {
"int", "string", "short", "long", "char", "boolean", "double", "float" -> true
"*" -> classLoaders.exists(requires[0])
else -> classLoaders.exists (type)
}
fun typeAsString() = if (type =="*") requires[0] else type fun typeAsString() = if (type =="*") requires[0] else type
} }
@ -294,85 +238,6 @@ data class CompositeType(override val name: String, override val label: String?,
sb.append("</type>") sb.append("</type>")
return sb.toString() return sb.toString()
} }
/**
* if we can load the class then we MUST know about all of it's composite elements
*/
private fun validateKnown (
classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader()))
{
fields.forEach {
if (!it.validateType(classLoaders)) throw UncarpentableException (name, it.name, it.type)
}
}
/**
* based upon this AMQP schema either
* a) add the corespending carpenter schema to the [carpenterSchemas] param
* b) add the class to the dependency tree in [carpenterSchemas] if it cannot be instantiated
* at this time
*
* @param classLoaders list of classLoaders, defaulting toe the system class loader, that might
* be used to load objects
* @param carpenterSchemas structure that holds the dependency tree and list of classes that
* need constructing
* @param force by default a schema is not added to [carpenterSchemas] if it already exists
* on the class path. For testing purposes schema generation can be forced
*/
fun carpenterSchema(
classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader()),
carpenterSchemas : CarpenterSchemas,
force : Boolean = false)
{
/* first question, do we know about this type or not */
if (classLoaders.exists(name)) {
validateKnown(classLoaders)
if (!force) return
}
val providesList = mutableListOf<Class<*>>()
var isInterface = false
var isCreatable = true
provides.forEach {
if (name == it) {
isInterface = true
return@forEach
}
try {
providesList.add (classLoaders.loadIfExists(it))
}
catch (e: ClassNotFoundException) {
carpenterSchemas.addDepPair(this, name, it)
isCreatable = false
}
}
val m : MutableMap<String, CarpenterField> = mutableMapOf()
fields.forEach {
try {
m[it.name] = FieldFactory.newInstance(it.mandatory, it.name, it.getTypeAsClass(classLoaders))
}
catch (e: ClassNotFoundException) {
carpenterSchemas.addDepPair(this, name, it.typeAsString())
isCreatable = false
}
}
if (isCreatable) {
carpenterSchemas.carpenterSchemas.add (CarpenterSchemaFactory.newInstance(
name = name,
fields = m,
interfaces = providesList,
isInterface = isInterface))
}
}
} }
data class RestrictedType(override val name: String, override val label: String?, override val provides: List<String>, val source: String, override val descriptor: Descriptor, val choices: List<Choice>) : TypeNotation() { data class RestrictedType(override val name: String, override val label: String?, override val provides: List<String>, val source: String, override val descriptor: Descriptor, val choices: List<Choice>) : TypeNotation() {

View File

@ -0,0 +1,127 @@
package net.corda.core.serialization.carpenter
import net.corda.core.serialization.amqp.Schema as AMQPSchema
import net.corda.core.serialization.amqp.Field as AMQPField
import net.corda.core.serialization.amqp.CompositeType
fun AMQPSchema.carpenterSchema(
loaders : List<ClassLoader> = listOf<ClassLoader>(ClassLoader.getSystemClassLoader()))
: CarpenterSchemas {
val rtn = CarpenterSchemas.newInstance()
types.filterIsInstance<CompositeType>().forEach {
it.carpenterSchema(classLoaders = loaders, carpenterSchemas = rtn)
}
return rtn
}
/**
* if we can load the class then we MUST know about all of it's composite elements
*/
private fun CompositeType.validateKnown (
classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader())){
fields.forEach {
if (!it.validateType(classLoaders)) throw UncarpentableException (name, it.name, it.type)
}
}
/**
* based upon this AMQP schema either
* a) add the corresponding carpenter schema to the [carpenterSchemas] param
* b) add the class to the dependency tree in [carpenterSchemas] if it cannot be instantiated
* at this time
*
* @param classLoaders list of classLoaders, defaulting toe the system class loader, that might
* be used to load objects
* @param carpenterSchemas structure that holds the dependency tree and list of classes that
* need constructing
* @param force by default a schema is not added to [carpenterSchemas] if it already exists
* on the class path. For testing purposes schema generation can be forced
*/
fun CompositeType.carpenterSchema(
classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader()),
carpenterSchemas : CarpenterSchemas,
force : Boolean = false) {
if (classLoaders.exists(name)) {
validateKnown(classLoaders)
if (!force) return
}
val providesList = mutableListOf<Class<*>>()
var isInterface = false
var isCreatable = true
provides.forEach {
if (name == it) {
isInterface = true
return@forEach
}
try {
providesList.add (classLoaders.loadIfExists(it))
}
catch (e: ClassNotFoundException) {
carpenterSchemas.addDepPair(this, name, it)
isCreatable = false
}
}
val m : MutableMap<String, Field> = mutableMapOf()
fields.forEach {
try {
m[it.name] = FieldFactory.newInstance(it.mandatory, it.name, it.getTypeAsClass(classLoaders))
}
catch (e: ClassNotFoundException) {
carpenterSchemas.addDepPair(this, name, it.typeAsString())
isCreatable = false
}
}
if (isCreatable) {
carpenterSchemas.carpenterSchemas.add (CarpenterSchemaFactory.newInstance(
name = name,
fields = m,
interfaces = providesList,
isInterface = isInterface))
}
}
fun AMQPField.getTypeAsClass(
classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader())
) = when (type) {
"int" -> Int::class.javaPrimitiveType!!
"string" -> String::class.java
"short" -> Short::class.javaPrimitiveType!!
"long" -> Long::class.javaPrimitiveType!!
"char" -> Char::class.javaPrimitiveType!!
"boolean" -> Boolean::class.javaPrimitiveType!!
"double" -> Double::class.javaPrimitiveType!!
"float" -> Float::class.javaPrimitiveType!!
"*" -> classLoaders.loadIfExists(requires[0])
else -> classLoaders.loadIfExists(type)
}
fun AMQPField.validateType(
classLoaders: List<ClassLoader> = listOf<ClassLoader> (ClassLoader.getSystemClassLoader())
) = when (type) {
"int", "string", "short", "long", "char", "boolean", "double", "float" -> true
"*" -> classLoaders.exists(requires[0])
else -> classLoaders.exists (type)
}
private fun List<ClassLoader>.exists (clazz: String) =
this.find { try { it.loadClass(clazz); true } catch (e: ClassNotFoundException) { false } } != null
private fun List<ClassLoader>.loadIfExists (clazz: String) : Class<*> {
this.forEach {
try {
return it.loadClass(clazz)
} catch (e: ClassNotFoundException) {
return@forEach
}
}
throw ClassNotFoundException(clazz)
}

View File

@ -9,8 +9,6 @@ import java.lang.Character.isJavaIdentifierStart
import java.util.* import java.util.*
/**********************************************************************************************************************/
/** /**
* Any object that implements this interface is expected to expose its own fields via the [get] method, exactly * Any object that implements this interface is expected to expose its own fields via the [get] method, exactly
* as if `this.class.getMethod("get" + name.capitalize()).invoke(this)` had been called. It is intended as a more * as if `this.class.getMethod("get" + name.capitalize()).invoke(this)` had been called. It is intended as a more
@ -20,14 +18,10 @@ interface SimpleFieldAccess {
operator fun get(name: String): Any? operator fun get(name: String): Any?
} }
/**********************************************************************************************************************/
class CarpenterClassLoader : ClassLoader(Thread.currentThread().contextClassLoader) { class CarpenterClassLoader : ClassLoader(Thread.currentThread().contextClassLoader) {
fun load(name: String, bytes: ByteArray) = defineClass(name, bytes, 0, bytes.size) fun load(name: String, bytes: ByteArray) = defineClass(name, bytes, 0, bytes.size)
} }
/**********************************************************************************************************************/
/** /**
* A class carpenter generates JVM bytecodes for a class given a schema and then loads it into a sub-classloader. * A class carpenter generates JVM bytecodes for a class given a schema and then loads it into a sub-classloader.
* The generated classes have getters, a toString method and implement a simple property access interface. The * The generated classes have getters, a toString method and implement a simple property access interface. The
@ -91,7 +85,8 @@ class ClassCarpenter {
* Generate bytecode for the given schema and load into the JVM. The returned class object can be used to * Generate bytecode for the given schema and load into the JVM. The returned class object can be used to
* construct instances of the generated class. * construct instances of the generated class.
* *
* @throws DuplicateNameException if the schema's name is already taken in this namespace (you can create a new ClassCarpenter if you're OK with ambiguous names) * @throws DuplicateNameException if the schema's name is already taken in this namespace (you can create a
* new ClassCarpenter if you're OK with ambiguous names)
*/ */
fun build(schema: Schema): Class<*> { fun build(schema: Schema): Class<*> {
validateSchema(schema) validateSchema(schema)
@ -257,9 +252,7 @@ class ClassCarpenter {
visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false) visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false)
} else { } else {
var slot = 1 var slot = 1
for (fieldType in superclassFields.values) superclassFields.values.forEach { slot += load(slot, it) }
slot += load(slot, fieldType)
//val superDesc = schema.superclass.descriptorsIncludingSuperclasses().values.joinToString("")
val superDesc = sc.descriptorsIncludingSuperclasses().values.joinToString("") val superDesc = sc.descriptorsIncludingSuperclasses().values.joinToString("")
visitMethodInsn(INVOKESPECIAL, sc.name.jvm, "<init>", "($superDesc)V", false) visitMethodInsn(INVOKESPECIAL, sc.name.jvm, "<init>", "($superDesc)V", false)
} }

View File

@ -1,9 +1,11 @@
package net.corda.core.serialization.carpenter package net.corda.core.serialization.carpenter
class DuplicateNameException : RuntimeException ( class DuplicateNameException : RuntimeException (
"An attempt was made to register two classes with the same name within the same ClassCarpenter namespace.") "An attempt was made to register two classes with the same name within the same ClassCarpenter namespace.")
class InterfaceMismatchException(msg: String) : RuntimeException(msg) class InterfaceMismatchException(msg: String) : RuntimeException(msg)
class NullablePrimitiveException(msg: String) : RuntimeException(msg) class NullablePrimitiveException(msg: String) : RuntimeException(msg)
class UncarpentableException (name: String, field: String, type: String) :
Exception ("Class $name is loadable yet contains field $field of unknown type $type")

View File

@ -3,8 +3,6 @@ package net.corda.core.serialization.carpenter
import net.corda.core.serialization.amqp.CompositeType import net.corda.core.serialization.amqp.CompositeType
import net.corda.core.serialization.amqp.TypeNotation import net.corda.core.serialization.amqp.TypeNotation
/**********************************************************************************************************************/
/** /**
* Generated from an AMQP schema this class represents the classes unknown to the deserialiser and that thusly * Generated from an AMQP schema this class represents the classes unknown to the deserialiser and that thusly
* require carpenting up in bytecode form. This is a multi step process as carpenting one object may be depedent * require carpenting up in bytecode form. This is a multi step process as carpenting one object may be depedent
@ -27,8 +25,7 @@ import net.corda.core.serialization.amqp.TypeNotation
data class CarpenterSchemas ( data class CarpenterSchemas (
val carpenterSchemas : MutableList<Schema>, val carpenterSchemas : MutableList<Schema>,
val dependencies : MutableMap<String, Pair<TypeNotation, MutableList<String>>>, val dependencies : MutableMap<String, Pair<TypeNotation, MutableList<String>>>,
val dependsOn : MutableMap<String, MutableList<String>>) val dependsOn : MutableMap<String, MutableList<String>>) {
{
companion object CarpenterSchemaConstructor { companion object CarpenterSchemaConstructor {
fun newInstance(): CarpenterSchemas { fun newInstance(): CarpenterSchemas {
return CarpenterSchemas( return CarpenterSchemas(
@ -47,8 +44,6 @@ data class CarpenterSchemas (
get() = carpenterSchemas.size get() = carpenterSchemas.size
} }
/**********************************************************************************************************************/
/** /**
* Take a dependency tree of [CarpenterSchemas] and reduce it to zero by carpenting those classes that * Take a dependency tree of [CarpenterSchemas] and reduce it to zero by carpenting those classes that
* require it. As classes are carpented check for depdency resolution, if now free generate a [Schema] for * require it. As classes are carpented check for depdency resolution, if now free generate a [Schema] for
@ -65,15 +60,15 @@ abstract class MetaCarpenterBase (val schemas : CarpenterSchemas) {
fun step (newObject : Schema) { fun step (newObject : Schema) {
objects[newObject.name] = cc.build (newObject) objects[newObject.name] = cc.build (newObject)
/* go over the list of everything that had a dependency on the newly // go over the list of everything that had a dependency on the newly
carpented class existing and remove it from their dependency list, If that // carpented class existing and remove it from their dependency list, If that
list is now empty we have no impediment to carpenting that class up */ // list is now empty we have no impediment to carpenting that class up
schemas.dependsOn.remove(newObject.name)?.forEach { dependent -> schemas.dependsOn.remove(newObject.name)?.forEach { dependent ->
assert (newObject.name in schemas.dependencies[dependent]!!.second) assert (newObject.name in schemas.dependencies[dependent]!!.second)
schemas.dependencies[dependent]?.second?.remove(newObject.name) schemas.dependencies[dependent]?.second?.remove(newObject.name)
/* we're out of blockers so we can now create the type */ // we're out of blockers so we can now create the type
if (schemas.dependencies[dependent]?.second?.isEmpty() ?: false) { if (schemas.dependencies[dependent]?.second?.isEmpty() ?: false) {
(schemas.dependencies.remove (dependent)?.first as CompositeType).carpenterSchema ( (schemas.dependencies.remove (dependent)?.first as CompositeType).carpenterSchema (
classLoaders = listOf<ClassLoader> ( classLoaders = listOf<ClassLoader> (
@ -87,8 +82,6 @@ abstract class MetaCarpenterBase (val schemas : CarpenterSchemas) {
abstract fun build() abstract fun build()
} }
/**********************************************************************************************************************/
class MetaCarpenter (schemas : CarpenterSchemas) : MetaCarpenterBase (schemas) { class MetaCarpenter (schemas : CarpenterSchemas) : MetaCarpenterBase (schemas) {
override fun build() { override fun build() {
while (schemas.carpenterSchemas.isNotEmpty()) { while (schemas.carpenterSchemas.isNotEmpty()) {
@ -98,8 +91,6 @@ class MetaCarpenter (schemas : CarpenterSchemas) : MetaCarpenterBase (schemas) {
} }
} }
/**********************************************************************************************************************/
class TestMetaCarpenter (schemas : CarpenterSchemas) : MetaCarpenterBase (schemas) { class TestMetaCarpenter (schemas : CarpenterSchemas) : MetaCarpenterBase (schemas) {
override fun build() { override fun build() {
if (schemas.carpenterSchemas.isEmpty()) return if (schemas.carpenterSchemas.isEmpty()) return
@ -107,4 +98,3 @@ class TestMetaCarpenter (schemas : CarpenterSchemas) : MetaCarpenterBase (schema
} }
} }
/**********************************************************************************************************************/

View File

@ -264,7 +264,6 @@ class ClassCarpenterTest {
mapOf("a" to NonNullableField (Int::class.java))) mapOf("a" to NonNullableField (Int::class.java)))
val clazz = cc.build(schema) val clazz = cc.build(schema)
val a : Int? = null val a : Int? = null
clazz.constructors[0].newInstance(a) clazz.constructors[0].newInstance(a)
} }
@ -364,7 +363,6 @@ class ClassCarpenterTest {
val clazz = cc.build(schema) val clazz = cc.build(schema)
val i = clazz.constructors[0].newInstance(arrayOf(1, 2, 3)) as SimpleFieldAccess val i = clazz.constructors[0].newInstance(arrayOf(1, 2, 3)) as SimpleFieldAccess
val arr = clazz.getMethod("getA").invoke(i) val arr = clazz.getMethod("getA").invoke(i)
assertEquals(1, (arr as Array<Int>)[0]) assertEquals(1, (arr as Array<Int>)[0])
@ -384,14 +382,12 @@ class ClassCarpenterTest {
"c" to Int::class.java).mapValues { NonNullableField(it.value) }) "c" to Int::class.java).mapValues { NonNullableField(it.value) })
val clazz = cc.build(schema) val clazz = cc.build(schema)
val i = clazz.constructors[0].newInstance(2, intArrayOf(4, 8), 16) as SimpleFieldAccess val i = clazz.constructors[0].newInstance(2, intArrayOf(4, 8), 16) as SimpleFieldAccess
assertEquals(2, clazz.getMethod("getA").invoke(i)) assertEquals(2, clazz.getMethod("getA").invoke(i))
assertEquals(4, (clazz.getMethod("getB").invoke(i) as IntArray)[0]) assertEquals(4, (clazz.getMethod("getB").invoke(i) as IntArray)[0])
assertEquals(8, (clazz.getMethod("getB").invoke(i) as IntArray)[1]) assertEquals(8, (clazz.getMethod("getB").invoke(i) as IntArray)[1])
assertEquals(16, clazz.getMethod("getC").invoke(i)) assertEquals(16, clazz.getMethod("getC").invoke(i))
assertEquals("$className{a=2, b=[4, 8], c=16}", i.toString()) assertEquals("$className{a=2, b=[4, 8], c=16}", i.toString())
} }
@ -414,7 +410,6 @@ class ClassCarpenterTest {
assertEquals(4, (clazz.getMethod("getC").invoke(i) as IntArray)[0]) assertEquals(4, (clazz.getMethod("getC").invoke(i) as IntArray)[0])
assertEquals(5, (clazz.getMethod("getC").invoke(i) as IntArray)[1]) assertEquals(5, (clazz.getMethod("getC").invoke(i) as IntArray)[1])
assertEquals(6, (clazz.getMethod("getC").invoke(i) as IntArray)[2]) assertEquals(6, (clazz.getMethod("getC").invoke(i) as IntArray)[2])
assertEquals("$className{a=[1, 2], b=3, c=[4, 5, 6]}", i.toString()) assertEquals("$className{a=[1, 2], b=3, c=[4, 5, 6]}", i.toString())
} }
@ -454,7 +449,6 @@ class ClassCarpenterTest {
"and on the side", "and on the side",
arrayOf("some pickles", "some fries")) arrayOf("some pickles", "some fries"))
val arr1 = clazz.getMethod("getA").invoke(i) as Array<String> val arr1 = clazz.getMethod("getA").invoke(i) as Array<String>
val arr2 = clazz.getMethod("getC").invoke(i) as Array<String> val arr2 = clazz.getMethod("getC").invoke(i) as Array<String>
@ -477,16 +471,12 @@ class ClassCarpenterTest {
val clazz = cc.build(schema) val clazz = cc.build(schema)
assertEquals (2, clazz.declaredFields.size) assertEquals (2, clazz.declaredFields.size)
assertEquals (1, clazz.getDeclaredField("a").annotations.size) assertEquals (1, clazz.getDeclaredField("a").annotations.size)
assertEquals (javax.annotation.Nullable::class.java, clazz.getDeclaredField("a").annotations[0].annotationClass.java) assertEquals (javax.annotation.Nullable::class.java, clazz.getDeclaredField("a").annotations[0].annotationClass.java)
assertEquals (1, clazz.getDeclaredField("b").annotations.size) assertEquals (1, clazz.getDeclaredField("b").annotations.size)
assertEquals (javax.annotation.Nonnull::class.java, clazz.getDeclaredField("b").annotations[0].annotationClass.java) assertEquals (javax.annotation.Nonnull::class.java, clazz.getDeclaredField("b").annotations[0].annotationClass.java)
assertEquals (1, clazz.getMethod("getA").annotations.size) assertEquals (1, clazz.getMethod("getA").annotations.size)
assertEquals (javax.annotation.Nullable::class.java, clazz.getMethod("getA").annotations[0].annotationClass.java) assertEquals (javax.annotation.Nullable::class.java, clazz.getMethod("getA").annotations[0].annotationClass.java)
assertEquals (1, clazz.getMethod("getB").annotations.size) assertEquals (1, clazz.getMethod("getB").annotations.size)
assertEquals (javax.annotation.Nonnull::class.java, clazz.getMethod("getB").annotations[0].annotationClass.java) assertEquals (javax.annotation.Nonnull::class.java, clazz.getMethod("getB").annotations[0].annotationClass.java)
} }
@ -503,5 +493,4 @@ class ClassCarpenterTest {
assertNotEquals(null, descriptors.find { it.name == "a" }) assertNotEquals(null, descriptors.find { it.name == "a" })
assertNotEquals(null, descriptors.find { it.name == "class" }) assertNotEquals(null, descriptors.find { it.name == "class" })
} }
} }

View File

@ -7,32 +7,25 @@ import net.corda.core.serialization.amqp.TypeNotation
import net.corda.core.serialization.amqp.SerializerFactory import net.corda.core.serialization.amqp.SerializerFactory
import net.corda.core.serialization.amqp.SerializationOutput import net.corda.core.serialization.amqp.SerializationOutput
/**********************************************************************************************************************/ fun mangleName(name: String) = "${name}__carpenter"
fun corruptName(name: String) = "${name}__carpenter" /**
* given a list of class names work through the amqp envelope schema and alter any that
/**********************************************************************************************************************/ * match in the fashion defined above
*/
/* given a list of class names work through the amqp envelope schema and alter any that fun Schema.mangleName(names: List<String>): Schema {
match in the fashion defined above */
fun Schema.corruptName(names: List<String>): Schema {
val newTypes: MutableList<TypeNotation> = mutableListOf() val newTypes: MutableList<TypeNotation> = mutableListOf()
for (type in types) { for (type in types) {
val newName = if (type.name in names) corruptName(type.name) else type.name val newName = if (type.name in names) mangleName(type.name) else type.name
val newProvides = type.provides.map { it -> if (it in names) mangleName(it) else it }
val newProvides = type.provides.map {
it ->
if (it in names) corruptName(it) else it
}
val newFields = mutableListOf<Field>() val newFields = mutableListOf<Field>()
(type as CompositeType).fields.forEach { (type as CompositeType).fields.forEach {
val fieldType = if (it.type in names) corruptName(it.type) else it.type val fieldType = if (it.type in names) mangleName(it.type) else it.type
val requires =
val requires = if (it.requires.isNotEmpty() && (it.requires[0] in names)) if (it.requires.isNotEmpty() && (it.requires[0] in names)) listOf(mangleName(it.requires[0]))
listOf(corruptName(it.requires[0])) else it.requires else it.requires
newFields.add(it.copy(type = fieldType, requires = requires)) newFields.add(it.copy(type = fieldType, requires = requires))
} }
@ -43,8 +36,6 @@ fun Schema.corruptName(names: List<String>): Schema {
return Schema(types = newTypes) return Schema(types = newTypes)
} }
/**********************************************************************************************************************/
open class AmqpCarpenterBase { open class AmqpCarpenterBase {
var factory = SerializerFactory() var factory = SerializerFactory()

View File

@ -14,11 +14,7 @@ interface I_ {
val a: Int val a: Int
} }
/*
* Where a class has a member that is also a composite type or interface
*/
class CompositeMembers : AmqpCarpenterBase() { class CompositeMembers : AmqpCarpenterBase() {
@Test @Test
fun bothKnown() { fun bothKnown() {
val testA = 10 val testA = 10
@ -31,7 +27,6 @@ class CompositeMembers : AmqpCarpenterBase() {
data class B(val a: A, var b: Int) data class B(val a: A, var b: Int)
val b = B(A(testA), testB) val b = B(A(testA), testB)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
assert(obj.obj is B) assert(obj.obj is B)
@ -57,10 +52,8 @@ class CompositeMembers : AmqpCarpenterBase() {
assert(amqpSchemaA != null) assert(amqpSchemaA != null)
assert(amqpSchemaB != null) assert(amqpSchemaB != null)
/* // Just ensure the amqp schema matches what we want before we go messing
* Just ensure the amqp schema matches what we want before we go messing // around with the internals
* around with the internals
*/
assertEquals(1, amqpSchemaA?.fields?.size) assertEquals(1, amqpSchemaA?.fields?.size)
assertEquals("a", amqpSchemaA!!.fields[0].name) assertEquals("a", amqpSchemaA!!.fields[0].name)
assertEquals("int", amqpSchemaA.fields[0].type) assertEquals("int", amqpSchemaA.fields[0].type)
@ -73,15 +66,15 @@ class CompositeMembers : AmqpCarpenterBase() {
val metaSchema = obj.envelope.schema.carpenterSchema() val metaSchema = obj.envelope.schema.carpenterSchema()
/* if we know all the classes there is nothing to really achieve here */ // if we know all the classes there is nothing to really achieve here
assert(metaSchema.carpenterSchemas.isEmpty()) assert(metaSchema.carpenterSchemas.isEmpty())
assert(metaSchema.dependsOn.isEmpty()) assert(metaSchema.dependsOn.isEmpty())
assert(metaSchema.dependencies.isEmpty()) assert(metaSchema.dependencies.isEmpty())
} }
/* you cannot have an element of a composite class we know about // you cannot have an element of a composite class we know about
that is unknown as that should be impossible. If we have the containing // that is unknown as that should be impossible. If we have the containing
class in the class path then we must have all of it's constituent elements */ // class in the class path then we must have all of it's constituent elements
@Test(expected = UncarpentableException::class) @Test(expected = UncarpentableException::class)
fun nestedIsUnknown() { fun nestedIsUnknown() {
val testA = 10 val testA = 10
@ -96,7 +89,7 @@ class CompositeMembers : AmqpCarpenterBase() {
val b = B(A(testA), testB) val b = B(A(testA), testB)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
val amqpSchema = obj.envelope.schema.corruptName(listOf (classTestName ("A"))) val amqpSchema = obj.envelope.schema.mangleName(listOf (classTestName ("A")))
assert(obj.obj is B) assert(obj.obj is B)
@ -115,13 +108,11 @@ class CompositeMembers : AmqpCarpenterBase() {
data class B(val a: A, var b: Int) data class B(val a: A, var b: Int)
val b = B(A(testA), testB) val b = B(A(testA), testB)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
assert(obj.obj is B) assert(obj.obj is B)
val amqpSchema = obj.envelope.schema.corruptName(listOf(classTestName("B"))) val amqpSchema = obj.envelope.schema.mangleName(listOf(classTestName("B")))
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema()
assertEquals(1, carpenterSchema.size) assertEquals(1, carpenterSchema.size)
@ -130,11 +121,11 @@ class CompositeMembers : AmqpCarpenterBase() {
metaCarpenter.build() metaCarpenter.build()
assert(corruptName(classTestName("B")) in metaCarpenter.objects) assert(mangleName(classTestName("B")) in metaCarpenter.objects)
} }
@Test @Test
fun BothUnkown() { fun BothUnknown() {
val testA = 10 val testA = 10
val testB = 20 val testB = 20
@ -145,52 +136,50 @@ class CompositeMembers : AmqpCarpenterBase() {
data class B(val a: A, var b: Int) data class B(val a: A, var b: Int)
val b = B(A(testA), testB) val b = B(A(testA), testB)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
assert(obj.obj is B) assert(obj.obj is B)
val amqpSchema = obj.envelope.schema.corruptName(listOf(classTestName("A"), classTestName("B"))) val amqpSchema = obj.envelope.schema.mangleName(listOf(classTestName("A"), classTestName("B")))
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema()
/* just verify we're in the expected initial state, A is carpentable, B is not because // just verify we're in the expected initial state, A is carpentable, B is not because
it depends on A and the dependency chains are in place */ // it depends on A and the dependency chains are in place
assertEquals(1, carpenterSchema.size) assertEquals(1, carpenterSchema.size)
assertEquals(corruptName(classTestName("A")), carpenterSchema.carpenterSchemas.first().name) assertEquals(mangleName(classTestName("A")), carpenterSchema.carpenterSchemas.first().name)
assertEquals(1, carpenterSchema.dependencies.size) assertEquals(1, carpenterSchema.dependencies.size)
assert(corruptName(classTestName("B")) in carpenterSchema.dependencies) assert(mangleName(classTestName("B")) in carpenterSchema.dependencies)
assertEquals(1, carpenterSchema.dependsOn.size) assertEquals(1, carpenterSchema.dependsOn.size)
assert(corruptName(classTestName("A")) in carpenterSchema.dependsOn) assert(mangleName(classTestName("A")) in carpenterSchema.dependsOn)
/* test meta carpenter lets us single step over the creation */
val metaCarpenter = TestMetaCarpenter(carpenterSchema) val metaCarpenter = TestMetaCarpenter(carpenterSchema)
/* we've built nothing so nothing should be there */
assertEquals(0, metaCarpenter.objects.size) assertEquals(0, metaCarpenter.objects.size)
/* first iteration, carpent A, resolve deps and mark B as carpentable */ // first iteration, carpent A, resolve deps and mark B as carpentable
metaCarpenter.build() metaCarpenter.build()
/* one build iteration should have carpetned up A and worked out that B is now buildable // one build iteration should have carpetned up A and worked out that B is now buildable
given it's depedencies have been satisfied */ // given it's depedencies have been satisfied
assertTrue(corruptName(classTestName("A")) in metaCarpenter.objects) assertTrue(mangleName(classTestName("A")) in metaCarpenter.objects)
assertFalse(corruptName(classTestName("B")) in metaCarpenter.objects) assertFalse(mangleName(classTestName("B")) in metaCarpenter.objects)
assertEquals(1, carpenterSchema.carpenterSchemas.size) assertEquals(1, carpenterSchema.carpenterSchemas.size)
assertEquals(corruptName(classTestName("B")), carpenterSchema.carpenterSchemas.first().name) assertEquals(mangleName(classTestName("B")), carpenterSchema.carpenterSchemas.first().name)
assertTrue(carpenterSchema.dependencies.isEmpty()) assertTrue(carpenterSchema.dependencies.isEmpty())
assertTrue(carpenterSchema.dependsOn.isEmpty()) assertTrue(carpenterSchema.dependsOn.isEmpty())
/* second manual iteration, will carpent B */ // second manual iteration, will carpent B
metaCarpenter.build() metaCarpenter.build()
assert(corruptName(classTestName("A")) in metaCarpenter.objects) assert(mangleName(classTestName("A")) in metaCarpenter.objects)
assert(corruptName(classTestName("B")) in metaCarpenter.objects) assert(mangleName(classTestName("B")) in metaCarpenter.objects)
// and we must be finished
assertTrue(carpenterSchema.carpenterSchemas.isEmpty()) assertTrue(carpenterSchema.carpenterSchemas.isEmpty())
} }
@Test(expected = UncarpentableException::class) @Test(expected = UncarpentableException::class)
@Suppress("UNUSED")
fun nestedIsUnkownInherited() { fun nestedIsUnkownInherited() {
val testA = 10 val testA = 10
val testB = 20 val testB = 20
@ -206,18 +195,18 @@ class CompositeMembers : AmqpCarpenterBase() {
data class C(val b: B, var c: Int) data class C(val b: B, var c: Int)
val c = C(B(testA, testB), testC) val c = C(B(testA, testB), testC)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(c)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(c))
assert(obj.obj is C) assert(obj.obj is C)
val amqpSchema = obj.envelope.schema.corruptName(listOf(classTestName("A"), classTestName("B"))) val amqpSchema = obj.envelope.schema.mangleName(listOf(classTestName("A"), classTestName("B")))
amqpSchema.carpenterSchema() amqpSchema.carpenterSchema()
} }
@Test(expected = UncarpentableException::class) @Test(expected = UncarpentableException::class)
fun nestedIsUnknownInheritedUnkown() { @Suppress("UNUSED")
fun nestedIsUnknownInheritedUnknown() {
val testA = 10 val testA = 10
val testB = 20 val testB = 20
val testC = 30 val testC = 30
@ -232,16 +221,16 @@ class CompositeMembers : AmqpCarpenterBase() {
data class C(val b: B, var c: Int) data class C(val b: B, var c: Int)
val c = C(B(testA, testB), testC) val c = C(B(testA, testB), testC)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(c)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(c))
assert(obj.obj is C) assert(obj.obj is C)
val amqpSchema = obj.envelope.schema.corruptName(listOf(classTestName("A"), classTestName("B"))) val amqpSchema = obj.envelope.schema.mangleName(listOf(classTestName("A"), classTestName("B")))
amqpSchema.carpenterSchema() amqpSchema.carpenterSchema()
} }
@Suppress("UNUSED")
@Test(expected = UncarpentableException::class) @Test(expected = UncarpentableException::class)
fun parentsIsUnknownWithUnknownInheritedMember() { fun parentsIsUnknownWithUnknownInheritedMember() {
val testA = 10 val testA = 10
@ -258,18 +247,14 @@ class CompositeMembers : AmqpCarpenterBase() {
data class C(val b: B, var c: Int) data class C(val b: B, var c: Int)
val c = C(B(testA, testB), testC) val c = C(B(testA, testB), testC)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(c)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(c))
assert(obj.obj is C) assert(obj.obj is C)
val carpenterSchema = obj.envelope.schema.corruptName(listOf(classTestName("A"), classTestName("B"))) val carpenterSchema = obj.envelope.schema.mangleName(listOf(classTestName("A"), classTestName("B")))
TestMetaCarpenter(carpenterSchema.carpenterSchema()) TestMetaCarpenter(carpenterSchema.carpenterSchema())
} }
/* /*
* TODO serializer doesn't support inheritnace at the moment, when it does this should work * TODO serializer doesn't support inheritnace at the moment, when it does this should work
@Test @Test
@ -284,19 +269,17 @@ class CompositeMembers : AmqpCarpenterBase() {
class B(override val a: Int, val b: Int) : A (a) class B(override val a: Int, val b: Int) : A (a)
val b = B(testA, testB) val b = B(testA, testB)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
assert(obj.obj is B) assert(obj.obj is B)
val carpenterSchema = obj.envelope.schema.corruptName(listOf(classTestName("A"), classTestName("B"))) val carpenterSchema = obj.envelope.schema.mangleName(listOf(classTestName("A"), classTestName("B")))
val metaCarpenter = TestMetaCarpenter(carpenterSchema.carpenterSchema()) val metaCarpenter = TestMetaCarpenter(carpenterSchema.carpenterSchema())
assertEquals(1, metaCarpenter.schemas.carpenterSchemas.size) assertEquals(1, metaCarpenter.schemas.carpenterSchemas.size)
assertEquals(corruptName(classTestName("B")), metaCarpenter.schemas.carpenterSchemas.first().name) assertEquals(mangleName(classTestName("B")), metaCarpenter.schemas.carpenterSchemas.first().name)
assertEquals(1, metaCarpenter.schemas.dependencies.size) assertEquals(1, metaCarpenter.schemas.dependencies.size)
assertTrue(corruptName(classTestName("A")) in metaCarpenter.schemas.dependencies) assertTrue(mangleName(classTestName("A")) in metaCarpenter.schemas.dependencies)
} }
*/ */
} }

View File

@ -8,15 +8,11 @@ import net.corda.core.serialization.amqp.*
import org.junit.Test import org.junit.Test
import kotlin.test.* import kotlin.test.*
/*******************************************************************************************************/
@CordaSerializable @CordaSerializable
interface J { interface J {
val j: Int val j: Int
} }
/*******************************************************************************************************/
@CordaSerializable @CordaSerializable
interface I { interface I {
val i: Int val i: Int
@ -39,49 +35,36 @@ interface IIII {
val i: I val i: I
} }
/*******************************************************************************************************/
class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() { class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun interfaceParent1() { fun interfaceParent1() {
val testJ = 20
class A(override val j: Int) : J class A(override val j: Int) : J
val testJ = 20
val a = A(testJ) val a = A(testJ)
assertEquals(testJ, a.j) assertEquals(testJ, a.j)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assert(obj.obj is A)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
assertEquals(2, serSchema.types.size) assertEquals(2, serSchema.types.size)
val l1 = serSchema.carpenterSchema() val l1 = serSchema.carpenterSchema()
/* since we're using an envelope generated by seilaising classes defined locally // since we're using an envelope generated by seilaising classes defined locally
it's extremely unlikely we'd need to carpent any classes */ // it's extremely unlikely we'd need to carpent any classes
assertEquals(0, l1.size) assertEquals(0, l1.size)
val corruptSchema = serSchema.corruptName(listOf(classTestName("A"))) val mangleSchema = serSchema.mangleName(listOf(classTestName("A")))
val l2 = mangleSchema.carpenterSchema()
val l2 = corruptSchema.carpenterSchema()
assertEquals(1, l2.size) assertEquals(1, l2.size)
val aSchema = l2.carpenterSchemas.find { it.name == corruptName(classTestName("A")) }
val aSchema = l2.carpenterSchemas.find { it.name == mangleName(classTestName("A")) }
assertNotEquals(null, aSchema) assertNotEquals(null, aSchema)
assertEquals(mangleName(classTestName("A")), aSchema!!.name)
assertEquals(corruptName(classTestName("A")), aSchema!!.name)
assertEquals(1, aSchema.interfaces.size) assertEquals(1, aSchema.interfaces.size)
assertEquals(net.corda.core.serialization.carpenter.J::class.java, aSchema.interfaces[0]) assertEquals(net.corda.core.serialization.carpenter.J::class.java, aSchema.interfaces[0])
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
val objJ = aBuilder.constructors[0].newInstance(testJ) val objJ = aBuilder.constructors[0].newInstance(testJ)
val j = objJ as J val j = objJ as J
@ -89,14 +72,12 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(a.j, j.j) assertEquals(a.j, j.j)
} }
@Test @Test
fun interfaceParent2() { fun interfaceParent2() {
val testJ = 20
val testJJ = 40
class A(override val j: Int, val jj: Int) : J class A(override val j: Int, val jj: Int) : J
val testJ = 20
val testJJ = 40
val a = A(testJ, testJJ) val a = A(testJ, testJJ)
assertEquals(testJ, a.j) assertEquals(testJ, a.j)
@ -112,14 +93,12 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val l1 = serSchema.carpenterSchema() val l1 = serSchema.carpenterSchema()
/* since we're using an envelope generated by seilaising classes defined locally
it's extremely unlikely we'd need to carpent any classes */
assertEquals(0, l1.size) assertEquals(0, l1.size)
val corruptSchema = serSchema.corruptName(listOf(classTestName("A"))) val mangleSchema = serSchema.mangleName(listOf(classTestName("A")))
val aName = corruptName(classTestName("A")) val aName = mangleName(classTestName("A"))
val l2 = corruptSchema.carpenterSchema() val l2 = mangleSchema.carpenterSchema()
assertEquals(1, l2.size) assertEquals(1, l2.size)
@ -160,48 +139,43 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val l1 = serSchema.carpenterSchema() val l1 = serSchema.carpenterSchema()
/* since we're using an envelope generated by seilaising classes defined locally // since we're using an envelope generated by serialising classes defined locally
it's extremely unlikely we'd need to carpent any classes */ // it's extremely unlikely we'd need to carpent any classes
assertEquals(0, l1.size) assertEquals(0, l1.size)
/* pretend we don't know the class we've been sent, i.e. it's unknown to the class loader, and thus // pretend we don't know the class we've been sent, i.e. it's unknown to the class loader, and thus
needs some carpentry */ // needs some carpentry
val mangleSchema = serSchema.mangleName(listOf(classTestName("A")))
val corruptSchema = serSchema.corruptName(listOf(classTestName("A"))) val l2 = mangleSchema.carpenterSchema()
val l2 = corruptSchema.carpenterSchema() val aName = mangleName(classTestName("A"))
val aName = corruptName(classTestName("A"))
assertEquals(1, l2.size) assertEquals(1, l2.size)
val aSchema = l2.carpenterSchemas.find { it.name == aName } val aSchema = l2.carpenterSchemas.find { it.name == aName }
assertNotEquals(null, aSchema) assertNotEquals(null, aSchema)
assertEquals(aName, aSchema!!.name) assertEquals(aName, aSchema!!.name)
assertEquals(2, aSchema.interfaces.size) assertEquals(2, aSchema.interfaces.size)
assert(net.corda.core.serialization.carpenter.I::class.java in aSchema.interfaces) assert(net.corda.core.serialization.carpenter.I::class.java in aSchema.interfaces)
assert(net.corda.core.serialization.carpenter.II::class.java in aSchema.interfaces) assert(net.corda.core.serialization.carpenter.II::class.java in aSchema.interfaces)
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
val objA = aBuilder.constructors[0].newInstance(testI, testII) val objA = aBuilder.constructors[0].newInstance(testI, testII)
val i = objA as I val i = objA as I
val ii = objA as II val ii = objA as II
assertEquals(aBuilder.getMethod("getI").invoke(objA), testI) assertEquals(aBuilder.getMethod("getI").invoke(objA), testI)
assertEquals(aBuilder.getMethod("getIi").invoke(objA), testII) assertEquals(aBuilder.getMethod("getIi").invoke(objA), testII)
assertEquals(a.i, i.i) assertEquals(a.i, i.i)
assertEquals(a.ii, ii.ii) assertEquals(a.ii, ii.ii)
} }
@Test @Test
fun nestedInterfaces() { fun nestedInterfaces() {
val testI = 20
val testIII = 60
class A(override val i: Int, override val iii: Int) : III class A(override val i: Int, override val iii: Int) : III
val testI = 20
val testIII = 60
val a = A(testI, testIII) val a = A(testI, testIII)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
@ -213,34 +187,31 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val l1 = serSchema.carpenterSchema() val l1 = serSchema.carpenterSchema()
/* since we're using an envelope generated by seilaising classes defined locally // since we're using an envelope generated by serialising classes defined locally
it's extremely unlikely we'd need to carpent any classes */ // it's extremely unlikely we'd need to carpent any classes
assertEquals(0, l1.size) assertEquals(0, l1.size)
val corruptSchema = serSchema.corruptName(listOf(classTestName("A"))) val mangleSchema = serSchema.mangleName(listOf(classTestName("A")))
val l2 = corruptSchema.carpenterSchema() val l2 = mangleSchema.carpenterSchema()
val aName = corruptName(classTestName("A")) val aName = mangleName(classTestName("A"))
assertEquals(1, l2.size) assertEquals(1, l2.size)
val aSchema = l2.carpenterSchemas.find { it.name == aName } val aSchema = l2.carpenterSchemas.find { it.name == aName }
assertNotEquals(null, aSchema) assertNotEquals(null, aSchema)
assertEquals(aName, aSchema!!.name) assertEquals(aName, aSchema!!.name)
assertEquals(2, aSchema.interfaces.size) assertEquals(2, aSchema.interfaces.size)
assert(net.corda.core.serialization.carpenter.I::class.java in aSchema.interfaces) assert(net.corda.core.serialization.carpenter.I::class.java in aSchema.interfaces)
assert(net.corda.core.serialization.carpenter.III::class.java in aSchema.interfaces) assert(net.corda.core.serialization.carpenter.III::class.java in aSchema.interfaces)
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
val objA = aBuilder.constructors[0].newInstance(testI, testIII) val objA = aBuilder.constructors[0].newInstance(testI, testIII)
val i = objA as I val i = objA as I
val iii = objA as III val iii = objA as III
assertEquals(aBuilder.getMethod("getI").invoke(objA), testI) assertEquals(aBuilder.getMethod("getI").invoke(objA), testI)
assertEquals(aBuilder.getMethod("getIii").invoke(objA), testIII) assertEquals(aBuilder.getMethod("getIii").invoke(objA), testIII)
assertEquals(a.i, i.i) assertEquals(a.i, i.i)
assertEquals(a.i, iii.i) assertEquals(a.i, iii.i)
assertEquals(a.iii, iii.iii) assertEquals(a.iii, iii.iii)
@ -248,33 +219,30 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun memberInterface() { fun memberInterface() {
val testI = 25
val testIIII = 50
class A(override val i: Int) : I class A(override val i: Int) : I
class B(override val i: I, override val iiii: Int) : IIII class B(override val i: I, override val iiii: Int) : IIII
val testI = 25
val testIIII = 50
val a = A(testI) val a = A(testI)
val b = B(a, testIIII) val b = B(a, testIIII)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
assert(obj.obj is B) assert(obj.obj is B)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
/* // Expected classes are
* class A // * class A
* class A's interface (class I) // * class A's interface (class I)
* class B // * class B
* class B's interface (class IIII) // * class B's interface (class IIII)
*/
assertEquals(4, serSchema.types.size) assertEquals(4, serSchema.types.size)
val corruptSchema = serSchema.corruptName(listOf(classTestName("A"), classTestName("B"))) val mangleSchema = serSchema.mangleName(listOf(classTestName("A"), classTestName("B")))
val cSchema = corruptSchema.carpenterSchema() val cSchema = mangleSchema.carpenterSchema()
val aName = corruptName(classTestName("A")) val aName = mangleName(classTestName("A"))
val bName = corruptName(classTestName("B")) val bName = mangleName(classTestName("B"))
assertEquals(2, cSchema.size) assertEquals(2, cSchema.size)
@ -286,102 +254,90 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val cc = ClassCarpenter() val cc = ClassCarpenter()
val cc2 = ClassCarpenter() val cc2 = ClassCarpenter()
val bBuilder = cc.build(bCarpenterSchema!!) val bBuilder = cc.build(bCarpenterSchema!!)
bBuilder.constructors[0].newInstance(a, testIIII) bBuilder.constructors[0].newInstance(a, testIIII)
val aBuilder = cc.build(aCarpenterSchema!!) val aBuilder = cc.build(aCarpenterSchema!!)
val objA = aBuilder.constructors[0].newInstance(testI) val objA = aBuilder.constructors[0].newInstance(testI)
/* build a second B this time using our constructed instane of A and not the // build a second B this time using our constructed instance of A and not the
local one we pre defined */ // local one we pre defined
bBuilder.constructors[0].newInstance(objA, testIIII) bBuilder.constructors[0].newInstance(objA, testIIII)
/* whittle and instantiate a different A with a new class loader */ // whittle and instantiate a different A with a new class loader
val aBuilder2 = cc2.build(aCarpenterSchema) val aBuilder2 = cc2.build(aCarpenterSchema)
val objA2 = aBuilder2.constructors[0].newInstance(testI) val objA2 = aBuilder2.constructors[0].newInstance(testI)
bBuilder.constructors[0].newInstance(objA2, testIIII) bBuilder.constructors[0].newInstance(objA2, testIIII)
} }
/* if we remove the neted interface we should get an error as it's impossible // if we remove the nested interface we should get an error as it's impossible
to have a concrete class loaded without having access to all of it's elements */ // to have a concrete class loaded without having access to all of it's elements
@Test(expected = UncarpentableException::class) @Test(expected = UncarpentableException::class)
fun memberInterface2() { fun memberInterface2() {
val testI = 25
val testIIII = 50
class A(override val i: Int) : I class A(override val i: Int) : I
class B(override val i: I, override val iiii: Int) : IIII class B(override val i: I, override val iiii: Int) : IIII
val testI = 25
val testIIII = 50
val a = A(testI) val a = A(testI)
val b = B(a, testIIII) val b = B(a, testIIII)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(b))
assert(obj.obj is B) assert(obj.obj is B)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
/* // The classes we're expecting to find:
* The classes we're expecting to find: // * class A
* class A // * class A's interface (class I)
* class A's interface (class I) // * class B
* class B // * class B's interface (class IIII)
* class B's interface (class IIII)
*/
assertEquals(4, serSchema.types.size) assertEquals(4, serSchema.types.size)
/* ignore the return as we expect this to throw */ // ignore the return as we expect this to throw
serSchema.corruptName(listOf( serSchema.mangleName(listOf(
classTestName("A"), "${this.javaClass.`package`.name}.I")).carpenterSchema() classTestName("A"), "${this.javaClass.`package`.name}.I")).carpenterSchema()
} }
@Test @Test
fun interfaceAndImplementation() { fun interfaceAndImplementation() {
val testI = 25
class A(override val i: Int) : I class A(override val i: Int) : I
val testI = 25
val a = A(testI) val a = A(testI)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assert(obj.obj is A)
val serSchema = obj.envelope.schema val serSchema = obj.envelope.schema
/* // The classes we're expecting to find:
* The classes we're expecting to find: // * class A
* class A // * class A's interface (class I)
* class A's interface (class I)
*/
assertEquals(2, serSchema.types.size) assertEquals(2, serSchema.types.size)
val amqpSchema = serSchema.corruptName(listOf(classTestName("A"), "${this.javaClass.`package`.name}.I")) val amqpSchema = serSchema.mangleName(listOf(classTestName("A"), "${this.javaClass.`package`.name}.I"))
val aName = mangleName(classTestName("A"))
val aName = corruptName(classTestName("A")) val iName = mangleName("${this.javaClass.`package`.name}.I")
val iName = corruptName("${this.javaClass.`package`.name}.I")
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema()
/* whilst there are two unknown classes within the envelope A depends on I so we can't construct a // whilst there are two unknown classes within the envelope A depends on I so we can't construct a
schema for A until we have for I */ // schema for A until we have for I
assertEquals(1, carpenterSchema.size) assertEquals(1, carpenterSchema.size)
assertNotEquals(null, carpenterSchema.carpenterSchemas.find { it.name == iName }) assertNotEquals(null, carpenterSchema.carpenterSchemas.find { it.name == iName })
/* since we can't build A it should list I as a dependency*/ // since we can't build A it should list I as a dependency
assert(aName in carpenterSchema.dependencies) assert(aName in carpenterSchema.dependencies)
assertEquals(1, carpenterSchema.dependencies[aName]!!.second.size) assertEquals(1, carpenterSchema.dependencies[aName]!!.second.size)
assertEquals(iName, carpenterSchema.dependencies[aName]!!.second[0]) assertEquals(iName, carpenterSchema.dependencies[aName]!!.second[0])
/* and conversly I should have A listed as a dependent */ // and conversly I should have A listed as a dependent
assert(iName in carpenterSchema.dependsOn) assert(iName in carpenterSchema.dependsOn)
assertEquals(1, carpenterSchema.dependsOn[iName]!!.size) assertEquals(1, carpenterSchema.dependsOn[iName]!!.size)
assertEquals(aName, carpenterSchema.dependsOn[iName]!![0]) assertEquals(aName, carpenterSchema.dependsOn[iName]!![0])
val mc = MetaCarpenter(carpenterSchema) val mc = MetaCarpenter(carpenterSchema)
mc.build() mc.build()
assertEquals(0, mc.schemas.carpenterSchemas.size) assertEquals(0, mc.schemas.carpenterSchemas.size)
@ -396,29 +352,26 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun twoInterfacesAndImplementation() { fun twoInterfacesAndImplementation() {
val testI = 69
val testII = 96
class A(override val i: Int, override val ii: Int) : I, II class A(override val i: Int, override val ii: Int) : I, II
val testI = 69
val testII = 96
val a = A(testI, testII) val a = A(testI, testII)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
val amqpSchema = obj.envelope.schema.corruptName(listOf( val amqpSchema = obj.envelope.schema.mangleName(listOf(
classTestName("A"), classTestName("A"),
"${this.javaClass.`package`.name}.I", "${this.javaClass.`package`.name}.I",
"${this.javaClass.`package`.name}.II")) "${this.javaClass.`package`.name}.II"))
val aName = corruptName(classTestName("A")) val aName = mangleName(classTestName("A"))
val iName = corruptName("${this.javaClass.`package`.name}.I") val iName = mangleName("${this.javaClass.`package`.name}.I")
val iiName = corruptName("${this.javaClass.`package`.name}.II") val iiName = mangleName("${this.javaClass.`package`.name}.II")
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema()
/* there is nothing preventing us from carpenting up the two interfaces so // there is nothing preventing us from carpenting up the two interfaces so
our initial list should contain both interface with A being dependent on both // our initial list should contain both interface with A being dependent on both
and each having A as a dependent */ // and each having A as a dependent
assertEquals(2, carpenterSchema.carpenterSchemas.size) assertEquals(2, carpenterSchema.carpenterSchemas.size)
assertNotNull(carpenterSchema.carpenterSchemas.find { it.name == iName }) assertNotNull(carpenterSchema.carpenterSchemas.find { it.name == iName })
assertNotNull(carpenterSchema.carpenterSchemas.find { it.name == iiName }) assertNotNull(carpenterSchema.carpenterSchemas.find { it.name == iiName })
@ -438,8 +391,8 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iiName }) assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iiName })
val mc = MetaCarpenter(carpenterSchema) val mc = MetaCarpenter(carpenterSchema)
mc.build() mc.build()
assertEquals(0, mc.schemas.carpenterSchemas.size) assertEquals(0, mc.schemas.carpenterSchemas.size)
assertEquals(0, mc.schemas.dependencies.size) assertEquals(0, mc.schemas.dependencies.size)
assertEquals(0, mc.schemas.dependsOn.size) assertEquals(0, mc.schemas.dependsOn.size)
@ -451,58 +404,56 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun nestedInterfacesAndImplementation() { fun nestedInterfacesAndImplementation() {
val testI = 7
val testIII = 11
class A(override val i: Int, override val iii: Int) : III class A(override val i: Int, override val iii: Int) : III
val testI = 7
val testIII = 11
val a = A(testI, testIII) val a = A(testI, testIII)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
val amqpSchema = obj.envelope.schema.corruptName(listOf( val amqpSchema = obj.envelope.schema.mangleName(listOf(
classTestName("A"), classTestName("A"),
"${this.javaClass.`package`.name}.I", "${this.javaClass.`package`.name}.I",
"${this.javaClass.`package`.name}.III")) "${this.javaClass.`package`.name}.III"))
val aName = corruptName(classTestName("A")) val aName = mangleName(classTestName("A"))
val iName = corruptName("${this.javaClass.`package`.name}.I") val iName = mangleName("${this.javaClass.`package`.name}.I")
val iiiName = corruptName("${this.javaClass.`package`.name}.III") val iiiName = mangleName("${this.javaClass.`package`.name}.III")
val carpenterSchema = amqpSchema.carpenterSchema() val carpenterSchema = amqpSchema.carpenterSchema()
/* Since A depends on III and III extends I we will have to construct them // Since A depends on III and III extends I we will have to construct them
* in that reverse order (I -> III -> A) */ // in that reverse order (I -> III -> A)
assertEquals(1, carpenterSchema.carpenterSchemas.size) assertEquals(1, carpenterSchema.carpenterSchemas.size)
assertNotNull(carpenterSchema.carpenterSchemas.find { it.name == iName }) assertNotNull(carpenterSchema.carpenterSchemas.find { it.name == iName })
assertNull(carpenterSchema.carpenterSchemas.find { it.name == iiiName }) assertNull(carpenterSchema.carpenterSchemas.find { it.name == iiiName })
assertNull(carpenterSchema.carpenterSchemas.find { it.name == aName }) assertNull(carpenterSchema.carpenterSchemas.find { it.name == aName })
/* I has III as a direct dependent and A as an indirect one */ // I has III as a direct dependent and A as an indirect one
assert(iName in carpenterSchema.dependsOn) assert(iName in carpenterSchema.dependsOn)
assertEquals(2, carpenterSchema.dependsOn[iName]?.size) assertEquals(2, carpenterSchema.dependsOn[iName]?.size)
assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == iiiName })) assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == iiiName }))
assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == aName })) assertNotNull(carpenterSchema.dependsOn[iName]?.find({ it == aName }))
/* III has A as a dependent */ // III has A as a dependent
assert(iiiName in carpenterSchema.dependsOn) assert(iiiName in carpenterSchema.dependsOn)
assertEquals(1, carpenterSchema.dependsOn[iiiName]?.size) assertEquals(1, carpenterSchema.dependsOn[iiiName]?.size)
assertNotNull(carpenterSchema.dependsOn[iiiName]?.find { it == aName }) assertNotNull(carpenterSchema.dependsOn[iiiName]?.find { it == aName })
/* converly III depends on I */ // conversly III depends on I
assert(iiiName in carpenterSchema.dependencies) assert(iiiName in carpenterSchema.dependencies)
assertEquals(1, carpenterSchema.dependencies[iiiName]!!.second.size) assertEquals(1, carpenterSchema.dependencies[iiiName]!!.second.size)
assertNotNull(carpenterSchema.dependencies[iiiName]!!.second.find { it == iName }) assertNotNull(carpenterSchema.dependencies[iiiName]!!.second.find { it == iName })
/* and A depends on III and I*/ // and A depends on III and I
assert(aName in carpenterSchema.dependencies) assert(aName in carpenterSchema.dependencies)
assertEquals(2, carpenterSchema.dependencies[aName]!!.second.size) assertEquals(2, carpenterSchema.dependencies[aName]!!.second.size)
assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iiiName }) assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iiiName })
assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iName }) assertNotNull(carpenterSchema.dependencies[aName]!!.second.find { it == iName })
val mc = MetaCarpenter(carpenterSchema) val mc = MetaCarpenter(carpenterSchema)
mc.build() mc.build()
assertEquals(0, mc.schemas.carpenterSchemas.size) assertEquals(0, mc.schemas.carpenterSchemas.size)
assertEquals(0, mc.schemas.dependencies.size) assertEquals(0, mc.schemas.dependencies.size)
assertEquals(0, mc.schemas.dependsOn.size) assertEquals(0, mc.schemas.dependsOn.size)
@ -512,5 +463,3 @@ class InheritanceSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assert(iiiName in mc.objects) assert(iiiName in mc.objects)
} }
} }

View File

@ -1,7 +1,6 @@
package net.corda.core.serialization.carpenter package net.corda.core.serialization.carpenter
import net.corda.core.serialization.carpenter.test.AmqpCarpenterBase import net.corda.core.serialization.carpenter.test.AmqpCarpenterBase
import net.corda.core.serialization.carpenter.CarpenterSchemas
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.* import net.corda.core.serialization.amqp.*
@ -13,14 +12,12 @@ class MultiMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun twoInts() { fun twoInts() {
val testA = 10
val testB = 20
@CordaSerializable @CordaSerializable
data class A(val a: Int, val b: Int) data class A(val a: Int, val b: Int)
var a = A(testA, testB) val testA = 10
val testB = 20
val a = A(testA, testB)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assert(obj.obj is A)
@ -31,7 +28,7 @@ class MultiMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertEquals(1, obj.envelope.schema.types.size) assertEquals(1, obj.envelope.schema.types.size)
assert(obj.envelope.schema.types[0] is CompositeType) assert(obj.envelope.schema.types[0] is CompositeType)
var amqpSchema = obj.envelope.schema.types[0] as CompositeType val amqpSchema = obj.envelope.schema.types[0] as CompositeType
assertEquals(2, amqpSchema.fields.size) assertEquals(2, amqpSchema.fields.size)
assertEquals("a", amqpSchema.fields[0].name) assertEquals("a", amqpSchema.fields[0].name)
@ -48,7 +45,6 @@ class MultiMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertNotEquals(null, aSchema) assertNotEquals(null, aSchema)
val pinochio = ClassCarpenter().build(aSchema!!) val pinochio = ClassCarpenter().build(aSchema!!)
val p = pinochio.constructors[0].newInstance(testA, testB) val p = pinochio.constructors[0].newInstance(testA, testB)
assertEquals(pinochio.getMethod("getA").invoke(p), amqpObj.a) assertEquals(pinochio.getMethod("getA").invoke(p), amqpObj.a)
@ -57,14 +53,12 @@ class MultiMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun intAndStr() { fun intAndStr() {
val testA = 10
val testB = "twenty"
@CordaSerializable @CordaSerializable
data class A(val a: Int, val b: String) data class A(val a: Int, val b: String)
val testA = 10
val testB = "twenty"
val a = A(testA, testB) val a = A(testA, testB)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assert(obj.obj is A)
@ -92,7 +86,6 @@ class MultiMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assertNotEquals(null, aSchema) assertNotEquals(null, aSchema)
val pinochio = ClassCarpenter().build(aSchema!!) val pinochio = ClassCarpenter().build(aSchema!!)
val p = pinochio.constructors[0].newInstance(testA, testB) val p = pinochio.constructors[0].newInstance(testA, testB)
assertEquals(pinochio.getMethod("getA").invoke(p), amqpObj.a) assertEquals(pinochio.getMethod("getA").invoke(p), amqpObj.a)

View File

@ -1,23 +1,19 @@
package net.corda.core.serialization.carpenter package net.corda.core.serialization.carpenter
import net.corda.core.serialization.carpenter.test.AmqpCarpenterBase import net.corda.core.serialization.carpenter.test.AmqpCarpenterBase
import net.corda.core.serialization.carpenter.CarpenterSchemas
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.* import net.corda.core.serialization.amqp.*
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() { class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun singleInteger() { fun singleInteger() {
val test = 10
@CordaSerializable @CordaSerializable
data class A(val a: Int) data class A(val a: Int)
val test = 10
val a = A(test) val a = A(test)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
@ -39,7 +35,6 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!! val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!!
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
val p = aBuilder.constructors[0].newInstance(test) val p = aBuilder.constructors[0].newInstance(test)
assertEquals(aBuilder.getMethod("getA").invoke(p), amqpObj.a) assertEquals(aBuilder.getMethod("getA").invoke(p), amqpObj.a)
@ -47,11 +42,10 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun singleString() { fun singleString() {
val test = "ten"
@CordaSerializable @CordaSerializable
data class A(val a: String) data class A(val a: String)
val test = "ten"
val a = A(test) val a = A(test)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
@ -64,13 +58,11 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
assert(obj.envelope.schema.types[0] is CompositeType) assert(obj.envelope.schema.types[0] is CompositeType)
val amqpSchema = obj.envelope.schema.types[0] as CompositeType val amqpSchema = obj.envelope.schema.types[0] as CompositeType
val carpenterSchema = CarpenterSchemas.newInstance() val carpenterSchema = CarpenterSchemas.newInstance()
amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true) amqpSchema.carpenterSchema(carpenterSchemas = carpenterSchema, force = true)
val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!! val aSchema = carpenterSchema.carpenterSchemas.find { it.name == classTestName("A") }!!
val aBuilder = ClassCarpenter().build(aSchema) val aBuilder = ClassCarpenter().build(aSchema)
val p = aBuilder.constructors[0].newInstance(test) val p = aBuilder.constructors[0].newInstance(test)
assertEquals(aBuilder.getMethod("getA").invoke(p), amqpObj.a) assertEquals(aBuilder.getMethod("getA").invoke(p), amqpObj.a)
@ -78,13 +70,11 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun singleLong() { fun singleLong() {
val test = 10L
@CordaSerializable @CordaSerializable
data class A(val a: Long) data class A(val a: Long)
val test = 10L
val a = A(test) val a = A(test)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assert(obj.obj is A)
@ -112,13 +102,11 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun singleShort() { fun singleShort() {
val test = 10.toShort()
@CordaSerializable @CordaSerializable
data class A(val a: Short) data class A(val a: Short)
val test = 10.toShort()
val a = A(test) val a = A(test)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assert(obj.obj is A)
@ -146,13 +134,11 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun singleDouble() { fun singleDouble() {
val test = 10.0
@CordaSerializable @CordaSerializable
data class A(val a: Double) data class A(val a: Double)
val test = 10.0
val a = A(test) val a = A(test)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assert(obj.obj is A)
@ -180,13 +166,11 @@ class SingleMemberCompositeSchemaToClassCarpenterTests : AmqpCarpenterBase() {
@Test @Test
fun singleFloat() { fun singleFloat() {
val test: Float = 10.0F
@CordaSerializable @CordaSerializable
data class A(val a: Float) data class A(val a: Float)
val test: Float = 10.0F
val a = A(test) val a = A(test)
val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a)) val obj = DeserializationInput(factory).deserializeAndReturnEnvelope(serialise(a))
assert(obj.obj is A) assert(obj.obj is A)