mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
Add alt serialise method that returns the schema and the bytes
For future testing it would be nice, post serialisation, to have easy access to the serialised objects schema so we can check how it was serialised. Adding a helper function to return a data class that does this in the same way we can for deserialize
This commit is contained in:
@ -8,6 +8,7 @@ import java.nio.ByteBuffer
|
||||
import java.util.*
|
||||
import kotlin.collections.LinkedHashSet
|
||||
|
||||
|
||||
/**
|
||||
* Main entry point for serializing an object to AMQP.
|
||||
*
|
||||
@ -18,37 +19,46 @@ open class SerializationOutput(internal val serializerFactory: SerializerFactory
|
||||
// TODO: we're not supporting object refs yet
|
||||
private val objectHistory: MutableMap<Any, Int> = IdentityHashMap()
|
||||
private val serializerHistory: MutableSet<AMQPSerializer<*>> = LinkedHashSet()
|
||||
private val schemaHistory: MutableSet<TypeNotation> = LinkedHashSet()
|
||||
internal val schemaHistory: MutableSet<TypeNotation> = LinkedHashSet()
|
||||
|
||||
|
||||
/**
|
||||
* Serialize the given object to AMQP, wrapped in our [Envelope] wrapper which carries an AMQP 1.0 schema, and prefixed
|
||||
* with a header to indicate that this is serialized with AMQP and not [Kryo], and what version of the Corda implementation
|
||||
* of AMQP serialization contructed the serialized form.
|
||||
* of AMQP serialization constructed the serialized form.
|
||||
*/
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> serialize(obj: T): SerializedBytes<T> {
|
||||
try {
|
||||
val data = Data.Factory.create()
|
||||
data.withDescribed(Envelope.DESCRIPTOR_OBJECT) {
|
||||
withList {
|
||||
// Our object
|
||||
writeObject(obj, this)
|
||||
// The schema
|
||||
writeSchema(Schema(schemaHistory.toList()), this)
|
||||
}
|
||||
}
|
||||
val bytes = ByteArray(data.encodedSize().toInt() + 8)
|
||||
val buf = ByteBuffer.wrap(bytes)
|
||||
buf.put(AmqpHeaderV1_0.bytes)
|
||||
data.encode(buf)
|
||||
return SerializedBytes(bytes)
|
||||
return _serialize(obj)
|
||||
} finally {
|
||||
objectHistory.clear()
|
||||
serializerHistory.clear()
|
||||
schemaHistory.clear()
|
||||
andFinally()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun andFinally() {
|
||||
objectHistory.clear()
|
||||
serializerHistory.clear()
|
||||
schemaHistory.clear()
|
||||
}
|
||||
|
||||
internal fun <T : Any> _serialize(obj: T): SerializedBytes<T> {
|
||||
val data = Data.Factory.create()
|
||||
data.withDescribed(Envelope.DESCRIPTOR_OBJECT) {
|
||||
withList {
|
||||
// Our object
|
||||
writeObject(obj, this)
|
||||
// The schema
|
||||
writeSchema(Schema(schemaHistory.toList()), this)
|
||||
}
|
||||
}
|
||||
val bytes = ByteArray(data.encodedSize().toInt() + 8)
|
||||
val buf = ByteBuffer.wrap(bytes)
|
||||
buf.put(AmqpHeaderV1_0.bytes)
|
||||
data.encode(buf)
|
||||
return SerializedBytes(bytes)
|
||||
}
|
||||
|
||||
internal fun writeObject(obj: Any, data: Data) {
|
||||
writeObject(obj, data, obj.javaClass)
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
||||
import net.corda.nodeapi.internal.serialization.EmptyWhitelist
|
||||
import java.io.NotSerializableException
|
||||
|
||||
|
||||
fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||
fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader())
|
||||
@ -17,3 +20,18 @@ class TestSerializationOutput(
|
||||
super.writeSchema(schema, data)
|
||||
}
|
||||
}
|
||||
|
||||
fun testName(): String = Thread.currentThread().stackTrace[2].methodName
|
||||
|
||||
data class BytesAndSchema<T : Any>(val obj: SerializedBytes<T>, val schema: Schema)
|
||||
|
||||
// Extension for the serialize routine that returns the scheme encoded into the
|
||||
// bytes as well as the bytes for simple testing
|
||||
@Throws(NotSerializableException::class)
|
||||
fun <T : Any> SerializationOutput.serializeRtnSchema(obj: T): BytesAndSchema<T> {
|
||||
try {
|
||||
return BytesAndSchema(_serialize(obj), Schema(schemaHistory.toList()))
|
||||
} finally {
|
||||
andFinally()
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,9 @@ import kotlin.test.assertNotEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class DeserializeAndReturnEnvelopeTests {
|
||||
|
||||
fun testName(): String = Thread.currentThread().stackTrace[2].methodName
|
||||
|
||||
// the 'this' reference means we can't just move this to the common test utils
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun classTestName(clazz: String) = "${this.javaClass.name}\$${testName()}\$$clazz"
|
||||
inline private fun classTestName(clazz: String) = "${this.javaClass.name}\$${testName()}\$$clazz"
|
||||
|
||||
@Test
|
||||
fun oneType() {
|
||||
|
@ -0,0 +1,34 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class SerializeAndReturnSchemaTest {
|
||||
// the 'this' reference means we can't just move this to the common test utils
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline private fun classTestName(clazz: String) = "${this.javaClass.name}\$${testName()}\$$clazz"
|
||||
|
||||
val factory = testDefaultFactory()
|
||||
|
||||
// just a simple test to verify the internal test extension for serialize does
|
||||
// indeed give us the correct schema back. This is more useful in support of other
|
||||
// tests rather than by itself but for those to be reliable this also needs
|
||||
// testing
|
||||
@Test
|
||||
fun getSchema() {
|
||||
data class C(val a: Int, val b: Int)
|
||||
val a = 1
|
||||
val b = 2
|
||||
|
||||
val sc = SerializationOutput(factory).serializeRtnSchema(C(a, b))
|
||||
|
||||
assertEquals(1, sc.schema.types.size)
|
||||
assertEquals(classTestName("C"), sc.schema.types.first().name)
|
||||
assertTrue(sc.schema.types.first() is CompositeType)
|
||||
assertEquals(2, (sc.schema.types.first() as CompositeType).fields.size)
|
||||
assertNotNull((sc.schema.types.first() as CompositeType).fields.find { it.name == "a" })
|
||||
assertNotNull((sc.schema.types.first() as CompositeType).fields.find { it.name == "b" })
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user