Merge pull request #1110 from corda/kat-arrayOfArrayTest

Ensure typename is calculated correctly for nested arrays
This commit is contained in:
Katelyn Baker 2017-07-25 17:21:06 +01:00 committed by GitHub
commit 2e480f8420
2 changed files with 89 additions and 15 deletions

View File

@ -15,9 +15,25 @@ open class ArraySerializer(override val type: Type, factory: SerializerFactory)
}
}
// because this might be an array of array of primitives (to any recursive depth) and
// because we care that the lowest type is unboxed we can't rely on the inbuilt type
// id to generate it properly (it will always return [[[Ljava.lang.type -> type[][][]
// for example).
//
// We *need* to retain knowledge for AMQP deserialisation weather that lowest primitive
// was boxed or unboxed so just infer it recursively
private fun calcTypeName(type: Type) : String =
if (type.componentType().isArray()) {
val typeName = calcTypeName(type.componentType()); "$typeName[]"
}
else {
val arrayType = if (type.asClass()!!.componentType.isPrimitive) "[p]" else "[]"
"${type.componentType().typeName}$arrayType"
}
override val typeDescriptor by lazy { "$DESCRIPTOR_DOMAIN:${fingerprintForType(type, factory)}" }
internal val elementType: Type by lazy { type.componentType() }
internal open val typeName by lazy { type.typeName }
internal open val typeName by lazy { calcTypeName(type) }
internal val typeNotation: TypeNotation by lazy {
RestrictedType(typeName, null, emptyList(), "list", Descriptor(typeDescriptor, null), emptyList())
@ -73,13 +89,13 @@ abstract class PrimArraySerializer(type: Type, factory: SerializerFactory) : Arr
// We don't need to handle the unboxed byte type as that is coercible to a byte array, but
// the other 7 primitive types we do
val primTypes: Map<Type, (SerializerFactory) -> PrimArraySerializer> = mapOf(
IntArray::class.java to { f -> PrimIntArraySerializer(f, "int[p]") },
CharArray::class.java to { f -> PrimCharArraySerializer(f, "char[p]") },
BooleanArray::class.java to { f -> PrimBooleanArraySerializer(f, "boolean[p]") },
FloatArray::class.java to { f -> PrimFloatArraySerializer(f, "float[p]") },
ShortArray::class.java to { f -> PrimShortArraySerializer(f, "short[p]") },
DoubleArray::class.java to { f -> PrimDoubleArraySerializer(f, "double[p]") },
LongArray::class.java to { f -> PrimLongArraySerializer(f, "long[p]") }
IntArray::class.java to { f -> PrimIntArraySerializer(f) },
CharArray::class.java to { f -> PrimCharArraySerializer(f) },
BooleanArray::class.java to { f -> PrimBooleanArraySerializer(f) },
FloatArray::class.java to { f -> PrimFloatArraySerializer(f) },
ShortArray::class.java to { f -> PrimShortArraySerializer(f) },
DoubleArray::class.java to { f -> PrimDoubleArraySerializer(f) },
LongArray::class.java to { f -> PrimLongArraySerializer(f) }
// ByteArray::class.java <-> NOT NEEDED HERE (see comment above)
)
@ -91,14 +107,14 @@ abstract class PrimArraySerializer(type: Type, factory: SerializerFactory) : Arr
}
}
class PrimIntArraySerializer(factory: SerializerFactory, override val typeName: String) :
class PrimIntArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(IntArray::class.java, factory) {
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
localWriteObject(data) { (obj as IntArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
}
}
class PrimCharArraySerializer(factory: SerializerFactory, override val typeName: String) :
class PrimCharArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(CharArray::class.java, factory) {
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
localWriteObject(data) { (obj as CharArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
@ -114,35 +130,35 @@ class PrimCharArraySerializer(factory: SerializerFactory, override val typeName:
}
}
class PrimBooleanArraySerializer(factory: SerializerFactory, override val typeName: String) :
class PrimBooleanArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(BooleanArray::class.java, factory) {
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
localWriteObject(data) { (obj as BooleanArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
}
}
class PrimDoubleArraySerializer(factory: SerializerFactory, override val typeName: String) :
class PrimDoubleArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(DoubleArray::class.java, factory) {
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
localWriteObject(data) { (obj as DoubleArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
}
}
class PrimFloatArraySerializer(factory: SerializerFactory, override val typeName: String) :
class PrimFloatArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(FloatArray::class.java, factory) {
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
localWriteObject(data) { (obj as FloatArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
}
}
class PrimShortArraySerializer(factory: SerializerFactory, override val typeName: String) :
class PrimShortArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(ShortArray::class.java, factory) {
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
localWriteObject(data) { (obj as ShortArray).forEach { output.writeObjectOrNull(it, data, elementType) } }
}
}
class PrimLongArraySerializer(factory: SerializerFactory, override val typeName: String) :
class PrimLongArraySerializer(factory: SerializerFactory) :
PrimArraySerializer(LongArray::class.java, factory) {
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
localWriteObject(data) { (obj as LongArray).forEach { output.writeObjectOrNull(it, data, elementType) } }

View File

@ -370,5 +370,63 @@ class DeserializeSimpleTypesTests {
assertEquals(c.c[1], deserializedC.c[1])
assertEquals(c.c[2], deserializedC.c[2])
}
@Test
fun arrayOfArrayOfInt() {
class C(val c: Array<Array<Int>>)
val c = C (arrayOf (arrayOf(1,2,3), arrayOf(4,5,6)))
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
assertEquals(c.c.size, deserializedC.c.size)
assertEquals(c.c[0].size, deserializedC.c[0].size)
assertEquals(c.c[0][0], deserializedC.c[0][0])
assertEquals(c.c[0][1], deserializedC.c[0][1])
assertEquals(c.c[0][2], deserializedC.c[0][2])
assertEquals(c.c[1].size, deserializedC.c[1].size)
assertEquals(c.c[1][0], deserializedC.c[1][0])
assertEquals(c.c[1][1], deserializedC.c[1][1])
assertEquals(c.c[1][2], deserializedC.c[1][2])
}
@Test
fun arrayOfIntArray() {
class C(val c: Array<IntArray>)
val c = C (arrayOf (IntArray(3), IntArray(3)))
c.c[0][0] = 1; c.c[0][1] = 2; c.c[0][2] = 3
c.c[1][0] = 4; c.c[1][1] = 5; c.c[1][2] = 6
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
assertEquals(c.c.size, deserializedC.c.size)
assertEquals(c.c[0].size, deserializedC.c[0].size)
assertEquals(c.c[0][0], deserializedC.c[0][0])
assertEquals(c.c[0][1], deserializedC.c[0][1])
assertEquals(c.c[0][2], deserializedC.c[0][2])
assertEquals(c.c[1].size, deserializedC.c[1].size)
assertEquals(c.c[1][0], deserializedC.c[1][0])
assertEquals(c.c[1][1], deserializedC.c[1][1])
assertEquals(c.c[1][2], deserializedC.c[1][2])
}
@Test
fun arrayOfArrayOfIntArray() {
class C(val c: Array<Array<IntArray>>)
val c = C(arrayOf(arrayOf(IntArray(3), IntArray(3), IntArray(3)),
arrayOf(IntArray(3), IntArray(3), IntArray(3)),
arrayOf(IntArray(3), IntArray(3), IntArray(3))))
for (i in 0..2) { for (j in 0..2) { for (k in 0..2) { c.c[i][j][k] = i + j + k } } }
val serialisedC = TestSerializationOutput(VERBOSE, sf).serialize(c)
val deserializedC = DeserializationInput(sf).deserialize(serialisedC)
for (i in 0..2) { for (j in 0..2) { for (k in 0..2) {
assertEquals(c.c[i][j][k], deserializedC.c[i][j][k])
}}}
}
}