Initial work towards integrating the serializer with the carpenter

Unit tests that pull out the envelope from a deserialsed object (which
we have already serialised) then using the AMQP schema contained within
convert that to a carpenter schema and build an object

Currently testing only simple classes with a single type member

Squashed merge commits:
	* Fix for the type issue in the SerializerFactory

  	  Needs to pull in the actual Java types otherwise we use the Kotlin types
	  as the map keys which will never correspond to the java types that the
	  wrapper wraps around the primitive before doing a map lookup

	  Boolean just doesn't seem to work as pulling that in starts breaking
	  Kotlin and Character also seems broken. There is a fix for this also on
	  Rick's branch so pushing this in for now and can use his actual changes
	  when they're available on Master

	* Better tests

	* Add support for sub classes known to the JVM

	* Initial work towards integrating serializer with the carpenter

	  Unit tests that pull out the envelope from a deserialsed object (which
	  we have already serialized) then using the AMQP schema contained within
	  convert that to a carpenter schema and build an object

	  Currently testing only simple classes with a single type member
This commit is contained in:
Katelyn Baker 2017-06-15 14:49:18 +01:00
parent 5be63adae0
commit 4cbf31681b
6 changed files with 724 additions and 0 deletions

View File

@ -168,6 +168,25 @@ data class Field(val name: String, val type: String, val requires: List<String>,
sb.append("/>")
return sb.toString()
}
fun getPrimType() = 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" -> Double::class.javaPrimitiveType!!
else -> {
try {
ClassLoader.getSystemClassLoader().loadClass(type)
}
catch (e: ClassNotFoundException) {
throw IllegalArgumentException ("pants")
}
}
}
}
sealed class TypeNotation : DescribedType {
@ -233,6 +252,14 @@ data class CompositeType(override val name: String, override val label: String?,
sb.append("</type>")
return sb.toString()
}
fun carpenterSchema() : Map<String, Class<out Any?>> {
var m : MutableMap<String, Class<out Any?>> = mutableMapOf()
fields.forEach { m[it.name] = it.getPrimType() }
return m
}
}
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

@ -12,6 +12,12 @@ import java.lang.reflect.GenericArrayType
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.lang.reflect.WildcardType
import java.lang.Float
import java.lang.Long
import java.lang.Short
import java.lang.Double
import java.lang.Character
//import java.lang.Boolean
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArrayList
@ -269,6 +275,7 @@ class SerializerFactory(val whitelist: ClassWhitelist = AllWhitelist) {
}
private val primitiveTypeNames: Map<Class<*>, String> = mapOf(
Character::class.java to "char",
Boolean::class.java to "boolean",
Byte::class.java to "byte",
UnsignedByte::class.java to "ubyte",

View File

@ -0,0 +1,263 @@
package net.corda.carpenter
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.*
import org.junit.Test
import kotlin.test.assertEquals
class ClassCarpenterScehmaTestsSingleMemberComposite {
private var factory = SerializerFactory()
fun serialise (clazz : Any) = SerializationOutput(factory).serialize(clazz)
@Test
fun singleInteger() {
val test = 10
@CordaSerializable
data class A(val a : Int)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("int", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
@Test
fun singleString() {
val test = "ten"
@CordaSerializable
data class A(val a : String)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("string", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
/*
@Test
fun singleChar () {
val test = 'c'
@CordaSerializable
data class A(val a : Char)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("char", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
*/
@Test
fun singleLong() {
val test = 10L
@CordaSerializable
data class A(val a : Long)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("long", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
@Test
fun singleShort() {
val test = 10.toShort()
@CordaSerializable
data class A(val a : Short)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("short", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
/*
@Test
fun singleBool() {
val test = true
@CordaSerializable
data class A(val a : Boolean)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("boolean", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
*/
@Test
fun singleDouble() {
val test = 10.0
@CordaSerializable
data class A(val a : Double)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("double", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
@Test
fun singleFloat() {
val test = 10.0F
@CordaSerializable
data class A(val a : Float)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("float", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
// assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
}

View File

@ -0,0 +1,78 @@
package net.corda.carpenter
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.*
import org.junit.Test
import kotlin.test.assertEquals
class CompositeMemberCompositeSchemaToClassCarpenterTests {
private var factory = SerializerFactory()
fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz)
@Test
fun nestedInts() {
val testA = 10
val testB = 20
@CordaSerializable
data class A(val a: Int)
@CordaSerializable
class B (val a: A, var b: Int)
var b = B(A(testA), testB)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise(b))
assert(obj.first is B)
val amqpObj = obj.first as B
assertEquals(testB, amqpObj.b)
assertEquals(testA, amqpObj.a.a)
assertEquals(2, obj.second.schema.types.size)
assert(obj.second.schema.types[0] is CompositeType)
assert(obj.second.schema.types[1] is CompositeType)
var amqpSchemaA : CompositeType? = null
var amqpSchemaB : CompositeType? = null
for (type in obj.second.schema.types) {
when (type.name.split ("$").last()) {
"A" -> amqpSchemaA = type as CompositeType
"B" -> amqpSchemaB = type as CompositeType
}
}
assert (amqpSchemaA != null)
assert (amqpSchemaB != null)
assertEquals(1, amqpSchemaA?.fields?.size)
assertEquals("a", amqpSchemaA!!.fields[0].name)
assertEquals("int", amqpSchemaA!!.fields[0].type)
assertEquals(2, amqpSchemaB?.fields?.size)
assertEquals("a", amqpSchemaB!!.fields[0].name)
assertEquals("net.corda.carpenter.CompositeMemberCompositeSchemaToClassCarpenterTests\$nestedInts\$A",
amqpSchemaB!!.fields[0].type)
assertEquals("b", amqpSchemaB!!.fields[1].name)
assertEquals("int", amqpSchemaB!!.fields[1].type)
var ccA = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchemaA.name, amqpSchemaA.carpenterSchema()))
var ccB = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchemaB.name, amqpSchemaB.carpenterSchema()))
/*
* Since A is known to the JVM we can't constuct B with and instance of the carpented A but
* need to use the defined one above
*/
val instanceA = ccA.constructors[0].newInstance(testA)
val instanceB = ccB.constructors[0].newInstance(A (testA), testB)
assertEquals (ccA.getMethod("getA").invoke(instanceA), amqpObj.a.a)
assertEquals ((ccB.getMethod("getA").invoke(instanceB) as A).a, amqpObj.a.a)
assertEquals (ccB.getMethod("getB").invoke(instanceB), amqpObj.b)
}
}

View File

@ -0,0 +1,86 @@
package net.corda.carpenter
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.*
import org.junit.Test
import kotlin.test.assertEquals
class MultiMemberCompositeSchemaToClassCarpenterTests {
private var factory = SerializerFactory()
fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz)
@Test
fun twoInts() {
val testA = 10
val testB = 20
@CordaSerializable
data class A(val a: Int, val b: Int)
var a = A(testA, testB)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise(a))
assert(obj.first is A)
val amqpObj = obj.first as A
assertEquals(testA, amqpObj.a)
assertEquals(testB, amqpObj.b)
assertEquals(1, obj.second.schema.types.size)
assert(obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals(2, amqpSchema.fields.size)
assertEquals("a", amqpSchema.fields[0].name)
assertEquals("int", amqpSchema.fields[0].type)
assertEquals("b", amqpSchema.fields[1].name)
assertEquals("int", amqpSchema.fields[1].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance(testA, testB)
assertEquals(pinochio.getMethod("getA").invoke(p), amqpObj.a)
assertEquals(pinochio.getMethod("getB").invoke(p), amqpObj.b)
}
@Test
fun intAndStr() {
val testA = 10
val testB = "twenty"
@CordaSerializable
data class A(val a: Int, val b: String)
var a = A(testA, testB)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise(a))
assert(obj.first is A)
val amqpObj = obj.first as A
assertEquals(testA, amqpObj.a)
assertEquals(testB, amqpObj.b)
assertEquals(1, obj.second.schema.types.size)
assert(obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals(2, amqpSchema.fields.size)
assertEquals("a", amqpSchema.fields[0].name)
assertEquals("int", amqpSchema.fields[0].type)
assertEquals("b", amqpSchema.fields[1].name)
assertEquals("string", amqpSchema.fields[1].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance(testA, testB)
assertEquals(pinochio.getMethod("getA").invoke(p), amqpObj.a)
assertEquals(pinochio.getMethod("getB").invoke(p), amqpObj.b)
}
}

View File

@ -0,0 +1,263 @@
package net.corda.carpenter
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.amqp.*
import org.junit.Test
import kotlin.test.assertEquals
class SingleMemberCompositeSchemaToClassCarpenterTests {
private var factory = SerializerFactory()
fun serialise (clazz : Any) = SerializationOutput(factory).serialize(clazz)
@Test
fun singleInteger() {
val test = 10
@CordaSerializable
data class A(val a : Int)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("int", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
@Test
fun singleString() {
val test = "ten"
@CordaSerializable
data class A(val a : String)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("string", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
/*
@Test
fun singleChar () {
val test = 'c'
@CordaSerializable
data class A(val a : Char)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("char", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
*/
@Test
fun singleLong() {
val test = 10L
@CordaSerializable
data class A(val a : Long)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("long", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
@Test
fun singleShort() {
val test = 10.toShort()
@CordaSerializable
data class A(val a : Short)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("short", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
/*
@Test
fun singleBool() {
val test = true
@CordaSerializable
data class A(val a : Boolean)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("boolean", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
*/
@Test
fun singleDouble() {
val test = 10.0
@CordaSerializable
data class A(val a : Double)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("double", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
@Test
fun singleFloat() {
val test = 10.0F
@CordaSerializable
data class A(val a : Float)
var a = A (test)
val obj = DeserializationInput(factory).deserializeRtnEnvelope(serialise (a))
assert (obj.first is A)
val amqpObj = obj.first as A
assertEquals (test, amqpObj.a)
assertEquals (1, obj.second.schema.types.size)
assert (obj.second.schema.types[0] is CompositeType)
var amqpSchema = obj.second.schema.types[0] as CompositeType
assertEquals (1, amqpSchema.fields.size)
assertEquals ("a", amqpSchema.fields[0].name)
assertEquals ("float", amqpSchema.fields[0].type)
var pinochio = ClassCarpenter().build(ClassCarpenter.Schema(amqpSchema.name, amqpSchema.carpenterSchema()))
val p = pinochio.constructors[0].newInstance (test)
// assertEquals (pinochio.getMethod("getA").invoke (p), amqpObj.a)
}
}