mirror of
https://github.com/corda/corda.git
synced 2024-12-22 06:17:55 +00:00
CORDA-553 - Cope with future transforms
This commit is contained in:
parent
bc12f87a24
commit
3350605536
@ -57,6 +57,7 @@ data class Envelope(val obj: Any?, val schema: Schema, val transformsSchema: Tra
|
||||
ENVELOPE_WITH_TRANSFORMS -> list[TRANSFORMS_SCHEMA_IDX] as TransformsSchema
|
||||
else -> throw NotSerializableException("Malformed list, bad length of ${list.size} (should be 2 or 3)")
|
||||
}
|
||||
|
||||
return Envelope(list[BLOB_IDX], list[SCHEMA_IDX] as Schema, transformSchema)
|
||||
}
|
||||
|
||||
|
@ -36,11 +36,17 @@ private val wrapperExtract = { x: Annotation ->
|
||||
*/
|
||||
private val singleExtract = { x: Annotation -> listOf(x) }
|
||||
|
||||
// Transform annotation used to test the handling of transforms the de-serialising node doesn't understand. At
|
||||
// some point test cases will have been created with this transform applied.
|
||||
//@Target(AnnotationTarget.CLASS)
|
||||
//@Retention(AnnotationRetention.RUNTIME)
|
||||
//annotation class UnknownTransformAnnotation(val a: Int, val b: Int, val c: Int)
|
||||
|
||||
/**
|
||||
* Utility list of all transforms we support that simplifies our generation code
|
||||
* Utility list of all transforms we support that simplifies our generation code.
|
||||
*
|
||||
* NOTE: We have to support single instances of the transform annotations as well as the wrapping annotation
|
||||
* when many instances are repeated
|
||||
* when many instances are repeated.
|
||||
*/
|
||||
val supportedTransforms = listOf(
|
||||
SupportedTransform(
|
||||
@ -63,4 +69,8 @@ val supportedTransforms = listOf(
|
||||
TransformTypes.Rename,
|
||||
singleExtract
|
||||
)
|
||||
//,SupportedTransform(
|
||||
// UnknownTransformAnnotation::class.java,
|
||||
// TransformTypes.UnknownTest,
|
||||
// singleExtract)
|
||||
)
|
||||
|
@ -14,11 +14,21 @@ import java.io.NotSerializableException
|
||||
* @property build should be a function that takes a transform [Annotation] (currently one of
|
||||
* [CordaSerializationTransformRename] or [CordaSerializationTransformEnumDefaults])
|
||||
* and constructs an instance of the corresponding [Transform] type
|
||||
*
|
||||
* DO NOT REORDER THE CONSTANTS!!! Please append any new entries to the end
|
||||
*/
|
||||
// TODO: it would be awesome to auto build this list by scanning for transform annotations themselves
|
||||
// TODO: annotated with some annotation
|
||||
enum class TransformTypes(val build: (Annotation) -> Transform) : DescribedType {
|
||||
EnumDefault({ a -> EnumDefaultSchemeTransform((a as CordaSerializationTransformEnumDefault).old, a.new) }) {
|
||||
/**
|
||||
* Placeholder entry for future transforms where a node receives a transform we've subsequently
|
||||
* added and thus the de-serialising node doesn't know about that transform.
|
||||
*/
|
||||
Unknown({ UnknownTransform() }) {
|
||||
override fun getDescriptor(): Any = DESCRIPTOR
|
||||
override fun getDescribed(): Any = ordinal
|
||||
},
|
||||
EnumDefault({ a -> EnumDefaultSchemaTransform((a as CordaSerializationTransformEnumDefault).old, a.new) }) {
|
||||
override fun getDescriptor(): Any = DESCRIPTOR
|
||||
override fun getDescribed(): Any = ordinal
|
||||
},
|
||||
@ -26,6 +36,13 @@ enum class TransformTypes(val build: (Annotation) -> Transform) : DescribedType
|
||||
override fun getDescriptor(): Any = DESCRIPTOR
|
||||
override fun getDescribed(): Any = ordinal
|
||||
};
|
||||
// Transform used to test the unknown handler, leave this at as the final constant, uncomment
|
||||
// when regenerating test cases - if Java had a pre-processor this would be much neater
|
||||
//
|
||||
//UnknownTest({ a -> UnknownTestTransform((a as UnknownTransformAnnotation).a, a.b, a.c)}) {
|
||||
// override fun getDescriptor(): Any = DESCRIPTOR
|
||||
// override fun getDescribed(): Any = ordinal
|
||||
//};
|
||||
|
||||
companion object : DescribedTypeConstructor<TransformTypes> {
|
||||
val DESCRIPTOR = AMQPDescriptorRegistry.TRANSFORM_ELEMENT_KEY.amqpDescriptor
|
||||
@ -42,10 +59,10 @@ enum class TransformTypes(val build: (Annotation) -> Transform) : DescribedType
|
||||
throw NotSerializableException("Unexpected descriptor ${describedType.descriptor}.")
|
||||
}
|
||||
|
||||
try {
|
||||
return values()[describedType.described as Int]
|
||||
return try {
|
||||
values()[describedType.described as Int]
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
throw NotSerializableException("Bad ordinal value ${describedType.described}.")
|
||||
values()[0]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,15 +37,18 @@ abstract class Transform : DescribedType {
|
||||
* the schema as a list of class name and parameters.Using the class name (list element 0)
|
||||
* create the appropriate class instance
|
||||
*
|
||||
* For future proofing any unknown transform types are not treated as errors, rather we
|
||||
* simply create a placeholder object so we can ignore it
|
||||
*
|
||||
* @param obj: a serialized instance of a described type, should be one of the
|
||||
* descendants of this class
|
||||
*/
|
||||
override fun newInstance(obj: Any?): Transform {
|
||||
val described = Transform.checkDescribed(obj) as List<*>
|
||||
return when (described[0]) {
|
||||
EnumDefaultSchemeTransform.typeName -> EnumDefaultSchemeTransform.newInstance(described)
|
||||
EnumDefaultSchemaTransform.typeName -> EnumDefaultSchemaTransform.newInstance(described)
|
||||
RenameSchemaTransform.typeName -> RenameSchemaTransform.newInstance(described)
|
||||
else -> throw NotSerializableException("Unexpected transform type ${described[0]}")
|
||||
else -> UnknownTransform()
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,27 +66,64 @@ abstract class Transform : DescribedType {
|
||||
abstract val name: String
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform type placeholder that allows for backward compatibility. Should a noce recieve
|
||||
* a transform type it doesn't recognise, we can will use this as a placeholder
|
||||
*/
|
||||
class UnknownTransform : Transform() {
|
||||
companion object : DescribedTypeConstructor<UnknownTransform> {
|
||||
val typeName = "UnknownTransform"
|
||||
|
||||
override fun newInstance(obj: Any?) = UnknownTransform()
|
||||
|
||||
override fun getTypeClass(): Class<*> = UnknownTransform::class.java
|
||||
}
|
||||
|
||||
override fun getDescribed(): Any = emptyList<Any>()
|
||||
override fun params() = ""
|
||||
|
||||
override val name: String get() = typeName
|
||||
}
|
||||
|
||||
class UnknownTestTransform(val a: Int, val b: Int, val c: Int) : Transform() {
|
||||
companion object : DescribedTypeConstructor<UnknownTestTransform> {
|
||||
val typeName = "UnknownTest"
|
||||
|
||||
override fun newInstance(obj: Any?) : UnknownTestTransform {
|
||||
val described = obj as List<*>
|
||||
return UnknownTestTransform(described[1] as Int, described[2] as Int, described[3] as Int)
|
||||
}
|
||||
|
||||
override fun getTypeClass(): Class<*> = UnknownTransform::class.java
|
||||
}
|
||||
|
||||
override fun getDescribed(): Any = listOf(name, a, b, c)
|
||||
override fun params() = ""
|
||||
|
||||
override val name: String get() = typeName
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform to be used on an Enumerated Type whenever a new element is added
|
||||
*
|
||||
* @property old The value the [new] instance should default to when not available
|
||||
* @property new the value (as a String) that has been added
|
||||
*/
|
||||
class EnumDefaultSchemeTransform(val old: String, val new: String) : Transform() {
|
||||
companion object : DescribedTypeConstructor<EnumDefaultSchemeTransform> {
|
||||
class EnumDefaultSchemaTransform(val old: String, val new: String) : Transform() {
|
||||
companion object : DescribedTypeConstructor<EnumDefaultSchemaTransform> {
|
||||
/**
|
||||
* Value encoded into the schema that identifies a transform as this type
|
||||
*/
|
||||
val typeName = "EnumDefault"
|
||||
|
||||
override fun newInstance(obj: Any?): EnumDefaultSchemeTransform {
|
||||
override fun newInstance(obj: Any?): EnumDefaultSchemaTransform {
|
||||
val described = obj as List<*>
|
||||
val old = described[1] as? String ?: throw IllegalStateException("Was expecting \"old\" as a String")
|
||||
val new = described[2] as? String ?: throw IllegalStateException("Was expecting \"new\" as a String")
|
||||
return EnumDefaultSchemeTransform(old, new)
|
||||
return EnumDefaultSchemaTransform(old, new)
|
||||
}
|
||||
|
||||
override fun getTypeClass(): Class<*> = EnumDefaultSchemeTransform::class.java
|
||||
override fun getTypeClass(): Class<*> = EnumDefaultSchemaTransform::class.java
|
||||
}
|
||||
|
||||
@Suppress("UNUSED")
|
||||
@ -93,7 +133,7 @@ class EnumDefaultSchemeTransform(val old: String, val new: String) : Transform()
|
||||
override fun params() = "old=${old.esc()} new=${new.esc()}"
|
||||
|
||||
override fun equals(other: Any?) = (
|
||||
(other is EnumDefaultSchemeTransform && other.new == new && other.old == old) || super.equals(other))
|
||||
(other is EnumDefaultSchemaTransform && other.new == new && other.old == old) || super.equals(other))
|
||||
|
||||
override fun hashCode() = (17 * new.hashCode()) + old.hashCode()
|
||||
|
||||
@ -138,7 +178,6 @@ class RenameSchemaTransform(val from: String, val to: String) : Transform() {
|
||||
override val name: String get() = typeName
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents the set of all transforms that can be a applied to all classes represented as part of
|
||||
* an AMQP schema. It forms a part of the AMQP envelope alongside the [Schema] and the serialized bytes
|
||||
|
@ -1,16 +1,19 @@
|
||||
package net.corda.nodeapi.internal.serialization.amqp
|
||||
|
||||
import net.corda.core.serialization.CordaSerializationTransformEnumDefault
|
||||
import net.corda.core.serialization.CordaSerializationTransformEnumDefaults
|
||||
import net.corda.core.serialization.CordaSerializationTransformRename
|
||||
import net.corda.core.serialization.CordaSerializationTransformRenames
|
||||
import net.corda.core.serialization.*
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.io.NotSerializableException
|
||||
import java.net.URI
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class EnumEvolvabilityTests {
|
||||
// var localPath = "file:///Users/katelynbaker/srcs-ide/corda/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp"
|
||||
var localPath = "file:///home/katelyn/srcs/corda/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp"
|
||||
|
||||
|
||||
companion object {
|
||||
val VERBOSE = false
|
||||
}
|
||||
@ -104,9 +107,9 @@ class EnumEvolvabilityTests {
|
||||
assertEquals(1, schema.size)
|
||||
assertTrue (schema.keys.contains(TransformTypes.EnumDefault))
|
||||
assertEquals (1, schema[TransformTypes.EnumDefault]!!.size)
|
||||
assertTrue (schema[TransformTypes.EnumDefault]!![0] is EnumDefaultSchemeTransform)
|
||||
assertEquals ("D", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemeTransform).new)
|
||||
assertEquals ("A", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemeTransform).old)
|
||||
assertTrue (schema[TransformTypes.EnumDefault]!![0] is EnumDefaultSchemaTransform)
|
||||
assertEquals ("D", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemaTransform).new)
|
||||
assertEquals ("A", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemaTransform).old)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -125,12 +128,12 @@ class EnumEvolvabilityTests {
|
||||
assertEquals(1, schema.size)
|
||||
assertTrue (schema.keys.contains(TransformTypes.EnumDefault))
|
||||
assertEquals (2, schema[TransformTypes.EnumDefault]!!.size)
|
||||
assertTrue (schema[TransformTypes.EnumDefault]!![0] is EnumDefaultSchemeTransform)
|
||||
assertEquals ("E", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemeTransform).new)
|
||||
assertEquals ("D", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemeTransform).old)
|
||||
assertTrue (schema[TransformTypes.EnumDefault]!![1] is EnumDefaultSchemeTransform)
|
||||
assertEquals ("D", (schema[TransformTypes.EnumDefault]!![1] as EnumDefaultSchemeTransform).new)
|
||||
assertEquals ("A", (schema[TransformTypes.EnumDefault]!![1] as EnumDefaultSchemeTransform).old)
|
||||
assertTrue (schema[TransformTypes.EnumDefault]!![0] is EnumDefaultSchemaTransform)
|
||||
assertEquals ("E", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemaTransform).new)
|
||||
assertEquals ("D", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemaTransform).old)
|
||||
assertTrue (schema[TransformTypes.EnumDefault]!![1] is EnumDefaultSchemaTransform)
|
||||
assertEquals ("D", (schema[TransformTypes.EnumDefault]!![1] as EnumDefaultSchemaTransform).new)
|
||||
assertEquals ("A", (schema[TransformTypes.EnumDefault]!![1] as EnumDefaultSchemaTransform).old)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -157,9 +160,9 @@ class EnumEvolvabilityTests {
|
||||
|
||||
assertTrue (schema!!.keys.contains(TransformTypes.EnumDefault))
|
||||
assertEquals (1, schema[TransformTypes.EnumDefault]!!.size)
|
||||
assertTrue (schema[TransformTypes.EnumDefault]!![0] is EnumDefaultSchemeTransform)
|
||||
assertEquals ("D", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemeTransform).new)
|
||||
assertEquals ("A", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemeTransform).old)
|
||||
assertTrue (schema[TransformTypes.EnumDefault]!![0] is EnumDefaultSchemaTransform)
|
||||
assertEquals ("D", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemaTransform).new)
|
||||
assertEquals ("A", (schema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemaTransform).old)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -183,10 +186,10 @@ class EnumEvolvabilityTests {
|
||||
|
||||
val enumDefaults = transforms[AnnotatedEnumTwice::class.java.name]!![TransformTypes.EnumDefault]!!
|
||||
|
||||
assertEquals("E", (enumDefaults[0] as EnumDefaultSchemeTransform).new)
|
||||
assertEquals("D", (enumDefaults[0] as EnumDefaultSchemeTransform).old)
|
||||
assertEquals("D", (enumDefaults[1] as EnumDefaultSchemeTransform).new)
|
||||
assertEquals("A", (enumDefaults[1] as EnumDefaultSchemeTransform).old)
|
||||
assertEquals("E", (enumDefaults[0] as EnumDefaultSchemaTransform).new)
|
||||
assertEquals("D", (enumDefaults[0] as EnumDefaultSchemaTransform).old)
|
||||
assertEquals("D", (enumDefaults[1] as EnumDefaultSchemaTransform).new)
|
||||
assertEquals("A", (enumDefaults[1] as EnumDefaultSchemaTransform).old)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -299,8 +302,8 @@ class EnumEvolvabilityTests {
|
||||
assertEquals("X", (serialisedSchema[TransformTypes.Rename]!![0] as RenameSchemaTransform).to)
|
||||
|
||||
assertEquals(1, serialisedSchema[TransformTypes.EnumDefault]!!.size)
|
||||
assertEquals("E", (serialisedSchema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemeTransform).new)
|
||||
assertEquals("X", (serialisedSchema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemeTransform).old)
|
||||
assertEquals("E", (serialisedSchema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemaTransform).new)
|
||||
assertEquals("X", (serialisedSchema[TransformTypes.EnumDefault]!![0] as EnumDefaultSchemaTransform).old)
|
||||
}
|
||||
|
||||
@CordaSerializationTransformEnumDefaults (
|
||||
@ -402,6 +405,32 @@ class EnumEvolvabilityTests {
|
||||
|
||||
assertEquals (sb1.transformsSchema.types[AnnotatedEnumOnce::class.java.name],
|
||||
sb2.transformsSchema.types[AnnotatedEnumOnce::class.java.name])
|
||||
}
|
||||
|
||||
|
||||
// @UnknownTransformAnnotation (10, 20, 30)
|
||||
enum class WithUnknownTest {
|
||||
A, B, C, D
|
||||
}
|
||||
|
||||
data class WrapsUnknown(val unknown: WithUnknownTest)
|
||||
|
||||
// To regenerate the types for this test uncomment the UnknownTransformAnnotation from
|
||||
// TransformTypes.kt and SupportedTransforms.kt
|
||||
@Test
|
||||
fun testUnknownTransform() {
|
||||
val resource = "EnumEvolvabilityTests.testUnknownTransform"
|
||||
val sf = testDefaultFactory()
|
||||
|
||||
//File(URI("$localPath/$resource")).writeBytes(
|
||||
// SerializationOutput(sf).serialize(WrapsUnknown(WithUnknownTest.D)).bytes)
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
||||
val sb1 = File(path.toURI()).readBytes()
|
||||
|
||||
val envelope = DeserializationInput(sf).deserializeAndReturnEnvelope(SerializedBytes<WrapsUnknown>(sb1)).envelope
|
||||
|
||||
assertTrue(envelope.transformsSchema.types.containsKey(WithUnknownTest::class.java.name))
|
||||
assertTrue(envelope.transformsSchema.types[WithUnknownTest::class.java.name]!!.containsKey(TransformTypes.Unknown))
|
||||
}
|
||||
}
|
||||
|
@ -5,36 +5,40 @@ import net.corda.core.serialization.SerializedBytes
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.io.NotSerializableException
|
||||
import java.net.URI
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
// To regenerate any of the binary test files do the following
|
||||
//
|
||||
// 0. set localPath accordingly
|
||||
// 1. Uncomment the code where the original form of the class is defined in the test
|
||||
// 2. Comment out the rest of the test
|
||||
// 3. Run the test
|
||||
// 4. Using the printed path copy that file to the resources directory
|
||||
// 5. Comment back out the generation code and uncomment the actual test
|
||||
class EvolvabilityTests {
|
||||
// When regenerating the test files this needs to be set to the file system location of the resource files
|
||||
var localPath = "file:///<path>/<to>/<toplevel of>/corda/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp"
|
||||
|
||||
@Test
|
||||
fun simpleOrderSwapSameType() {
|
||||
val sf = testDefaultFactory()
|
||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.simpleOrderSwapSameType")
|
||||
val f = File(path.toURI())
|
||||
val resource= "EvolvabilityTests.simpleOrderSwapSameType"
|
||||
|
||||
val A = 1
|
||||
val B = 2
|
||||
|
||||
// Original version of the class for the serialised version of this class
|
||||
//
|
||||
// data class C (val a: Int, val b: Int)
|
||||
// val sc = SerializationOutput(sf).serialize(C(A, B))
|
||||
// f.writeBytes(sc.bytes)
|
||||
// println (path)
|
||||
// File(URI("$localPath/$resource")).writeBytes(sc.bytes)
|
||||
|
||||
// new version of the class, in this case the order of the parameters has been swapped
|
||||
data class C(val b: Int, val a: Int)
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
||||
val f = File(path.toURI())
|
||||
|
||||
val sc2 = f.readBytes()
|
||||
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
||||
|
||||
@ -45,21 +49,20 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun simpleOrderSwapDifferentType() {
|
||||
val sf = testDefaultFactory()
|
||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.simpleOrderSwapDifferentType")
|
||||
val f = File(path.toURI())
|
||||
val A = 1
|
||||
val B = "two"
|
||||
val resource = "EvolvabilityTests.simpleOrderSwapDifferentType"
|
||||
|
||||
// Original version of the class as it was serialised
|
||||
//
|
||||
// data class C (val a: Int, val b: String)
|
||||
// val sc = SerializationOutput(sf).serialize(C(A, B))
|
||||
// f.writeBytes(sc.bytes)
|
||||
// println (path)
|
||||
// File(URI("$localPath/$resource")).writeBytes(sc.bytes)
|
||||
|
||||
// new version of the class, in this case the order of the parameters has been swapped
|
||||
data class C(val b: String, val a: Int)
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
||||
val f = File(path.toURI())
|
||||
val sc2 = f.readBytes()
|
||||
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
||||
|
||||
@ -70,18 +73,18 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun addAdditionalParamNotMandatory() {
|
||||
val sf = testDefaultFactory()
|
||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.addAdditionalParamNotMandatory")
|
||||
val f = File(path.toURI())
|
||||
val A = 1
|
||||
val resource = "EvolvabilityTests.addAdditionalParamNotMandatory"
|
||||
|
||||
// Original version of the class as it was serialised
|
||||
//
|
||||
// data class C(val a: Int)
|
||||
// val sc = SerializationOutput(sf).serialize(C(A))
|
||||
// f.writeBytes(sc.bytes)
|
||||
// println ("Path = $path")
|
||||
// File(URI("$localPath/$resource")).writeBytes(sc.bytes)
|
||||
|
||||
data class C(val a: Int, val b: Int?)
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
||||
val f = File(path.toURI())
|
||||
val sc2 = f.readBytes()
|
||||
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
||||
|
||||
@ -119,22 +122,21 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun removeParameters() {
|
||||
val sf = testDefaultFactory()
|
||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.removeParameters")
|
||||
val f = File(path.toURI())
|
||||
val resource = "EvolvabilityTests.removeParameters"
|
||||
val A = 1
|
||||
val B = "two"
|
||||
val C = "three"
|
||||
val D = 4
|
||||
|
||||
// Original version of the class as it was serialised
|
||||
//
|
||||
// data class CC(val a: Int, val b: String, val c: String, val d: Int)
|
||||
// val scc = SerializationOutput(sf).serialize(CC(A, B, C, D))
|
||||
// f.writeBytes(scc.bytes)
|
||||
// println ("Path = $path")
|
||||
// File(URI("$localPath/$resource")).writeBytes(scc.bytes)
|
||||
|
||||
data class CC(val b: String, val d: Int)
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.removeParameters")
|
||||
val f = File(path.toURI())
|
||||
val sc2 = f.readBytes()
|
||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||
|
||||
@ -146,23 +148,23 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun addAndRemoveParameters() {
|
||||
val sf = testDefaultFactory()
|
||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.addAndRemoveParameters")
|
||||
val f = File(path.toURI())
|
||||
val A = 1
|
||||
val B = "two"
|
||||
val C = "three"
|
||||
val D = 4
|
||||
val E = null
|
||||
|
||||
val resource = "EvolvabilityTests.addAndRemoveParameters"
|
||||
|
||||
// Original version of the class as it was serialised
|
||||
//
|
||||
// data class CC(val a: Int, val b: String, val c: String, val d: Int)
|
||||
// val scc = SerializationOutput(sf).serialize(CC(A, B, C, D))
|
||||
// f.writeBytes(scc.bytes)
|
||||
// println ("Path = $path")
|
||||
// File(URI("$localPath/$resource")).writeBytes(scc.bytes)
|
||||
|
||||
data class CC(val a: Int, val e: Boolean?, val d: Int)
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
||||
val f = File(path.toURI())
|
||||
val sc2 = f.readBytes()
|
||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||
|
||||
@ -174,16 +176,13 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun addMandatoryFieldWithAltConstructor() {
|
||||
val sf = testDefaultFactory()
|
||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.addMandatoryFieldWithAltConstructor")
|
||||
val f = File(path.toURI())
|
||||
val A = 1
|
||||
val resource = "EvolvabilityTests.addMandatoryFieldWithAltConstructor"
|
||||
|
||||
// Original version of the class as it was serialised
|
||||
//
|
||||
// data class CC(val a: Int)
|
||||
// val scc = SerializationOutput(sf).serialize(CC(A))
|
||||
// f.writeBytes(scc.bytes)
|
||||
// println ("Path = $path")
|
||||
// File(URI("$localPath/$resource")).writeBytes(scc.bytes)
|
||||
|
||||
@Suppress("UNUSED")
|
||||
data class CC(val a: Int, val b: String) {
|
||||
@ -191,6 +190,8 @@ class EvolvabilityTests {
|
||||
constructor (a: Int) : this(a, "hello")
|
||||
}
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
||||
val f = File(path.toURI())
|
||||
val sc2 = f.readBytes()
|
||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||
|
||||
@ -228,19 +229,15 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun addMandatoryFieldWithAltReorderedConstructor() {
|
||||
val sf = testDefaultFactory()
|
||||
val path = EvolvabilityTests::class.java.getResource(
|
||||
"EvolvabilityTests.addMandatoryFieldWithAltReorderedConstructor")
|
||||
val f = File(path.toURI())
|
||||
val resource = "EvolvabilityTests.addMandatoryFieldWithAltReorderedConstructor"
|
||||
val A = 1
|
||||
val B = 100
|
||||
val C = "This is not a banana"
|
||||
|
||||
// Original version of the class as it was serialised
|
||||
//
|
||||
// data class CC(val a: Int, val b: Int, val c: String)
|
||||
// val scc = SerializationOutput(sf).serialize(CC(A, B, C))
|
||||
// f.writeBytes(scc.bytes)
|
||||
// println ("Path = $path")
|
||||
// File(URI("$localPath/$resource")).writeBytes(scc.bytes)
|
||||
|
||||
@Suppress("UNUSED")
|
||||
data class CC(val a: Int, val b: Int, val c: String, val d: String) {
|
||||
@ -250,6 +247,8 @@ class EvolvabilityTests {
|
||||
constructor (c: String, a: Int, b: Int) : this(a, b, c, "wibble")
|
||||
}
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
||||
val f = File(path.toURI())
|
||||
val sc2 = f.readBytes()
|
||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||
|
||||
@ -262,20 +261,15 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun addMandatoryFieldWithAltReorderedConstructorAndRemoval() {
|
||||
val sf = testDefaultFactory()
|
||||
val path = EvolvabilityTests::class.java.getResource(
|
||||
"EvolvabilityTests.addMandatoryFieldWithAltReorderedConstructorAndRemoval")
|
||||
val f = File(path.toURI())
|
||||
val resource = "EvolvabilityTests.addMandatoryFieldWithAltReorderedConstructorAndRemoval"
|
||||
val A = 1
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
val B = 100
|
||||
val C = "This is not a banana"
|
||||
|
||||
// Original version of the class as it was serialised
|
||||
//
|
||||
// data class CC(val a: Int, val b: Int, val c: String)
|
||||
// val scc = SerializationOutput(sf).serialize(CC(A, B, C))
|
||||
// f.writeBytes(scc.bytes)
|
||||
// println ("Path = $path")
|
||||
// File(URI("$localPath/$resource")).writeBytes(SerializationOutput(sf).serialize(CC(A, B, C)).bytes)
|
||||
|
||||
// b is removed, d is added
|
||||
data class CC(val a: Int, val c: String, val d: String) {
|
||||
@ -286,6 +280,8 @@ class EvolvabilityTests {
|
||||
constructor (c: String, a: Int) : this(a, c, "wibble")
|
||||
}
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
||||
val f = File(path.toURI())
|
||||
val sc2 = f.readBytes()
|
||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||
|
||||
@ -297,9 +293,9 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun multiVersion() {
|
||||
val sf = testDefaultFactory()
|
||||
val path1 = EvolvabilityTests::class.java.getResource("EvolvabilityTests.multiVersion.1")
|
||||
val path2 = EvolvabilityTests::class.java.getResource("EvolvabilityTests.multiVersion.2")
|
||||
val path3 = EvolvabilityTests::class.java.getResource("EvolvabilityTests.multiVersion.3")
|
||||
val resource1 = "EvolvabilityTests.multiVersion.1"
|
||||
val resource2 = "EvolvabilityTests.multiVersion.2"
|
||||
val resource3 = "EvolvabilityTests.multiVersion.3"
|
||||
|
||||
val a = 100
|
||||
val b = 200
|
||||
@ -310,24 +306,15 @@ class EvolvabilityTests {
|
||||
//
|
||||
// Version 1:
|
||||
// data class C (val a: Int, val b: Int)
|
||||
//
|
||||
// val scc = SerializationOutput(sf).serialize(C(a, b))
|
||||
// File(path1.toURI()).writeBytes(scc.bytes)
|
||||
// println ("Path = $path1")
|
||||
// File(URI("$localPath/$resource1")).writeBytes(SerializationOutput(sf).serialize(C(a, b)).bytes)
|
||||
//
|
||||
// Version 2 - add param c
|
||||
// data class C (val c: Int, val b: Int, val a: Int)
|
||||
//
|
||||
// val scc = SerializationOutput(sf).serialize(C(c, b, a))
|
||||
// File(path2.toURI()).writeBytes(scc.bytes)
|
||||
// println ("Path = $path2")
|
||||
// File(URI("$localPath/$resource2")).writeBytes(SerializationOutput(sf).serialize(C(c, b, a)).bytes)
|
||||
//
|
||||
// Version 3 - add param d
|
||||
// data class C (val b: Int, val c: Int, val d: Int, val a: Int)
|
||||
//
|
||||
// val scc = SerializationOutput(sf).serialize(C(b, c, d, a))
|
||||
// File(path3.toURI()).writeBytes(scc.bytes)
|
||||
// println ("Path = $path3")
|
||||
// File(URI("$localPath/$resource3")).writeBytes(SerializationOutput(sf).serialize(C(b, c, d, a)).bytes)
|
||||
|
||||
@Suppress("UNUSED")
|
||||
data class C(val e: Int, val c: Int, val b: Int, val a: Int, val d: Int) {
|
||||
@ -341,6 +328,10 @@ class EvolvabilityTests {
|
||||
constructor (a: Int, b: Int, c: Int, d: Int) : this(-1, c, b, a, d)
|
||||
}
|
||||
|
||||
val path1 = EvolvabilityTests::class.java.getResource(resource1)
|
||||
val path2 = EvolvabilityTests::class.java.getResource(resource2)
|
||||
val path3 = EvolvabilityTests::class.java.getResource(resource3)
|
||||
|
||||
val sb1 = File(path1.toURI()).readBytes()
|
||||
val db1 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb1))
|
||||
|
||||
@ -372,24 +363,21 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun changeSubType() {
|
||||
val sf = testDefaultFactory()
|
||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.changeSubType")
|
||||
val f = File(path.toURI())
|
||||
val resource = "EvolvabilityTests.changeSubType"
|
||||
val oa = 100
|
||||
val ia = 200
|
||||
|
||||
// Original version of the class as it was serialised
|
||||
//
|
||||
// data class Inner (val a: Int)
|
||||
// data class Outer (val a: Int, val b: Inner)
|
||||
// val scc = SerializationOutput(sf).serialize(Outer(oa, Inner (ia)))
|
||||
// f.writeBytes(scc.bytes)
|
||||
// println ("Path = $path")
|
||||
// File(URI("$localPath/$resource")).writeBytes(SerializationOutput(sf).serialize(Outer(oa, Inner (ia))).bytes)
|
||||
|
||||
// Add a parameter to inner but keep outer unchanged
|
||||
data class Inner(val a: Int, val b: String?)
|
||||
|
||||
data class Outer(val a: Int, val b: Inner)
|
||||
|
||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
||||
val f = File(path.toURI())
|
||||
val sc2 = f.readBytes()
|
||||
val outer = DeserializationInput(sf).deserialize(SerializedBytes<Outer>(sc2))
|
||||
|
||||
@ -401,9 +389,10 @@ class EvolvabilityTests {
|
||||
@Test
|
||||
fun multiVersionWithRemoval() {
|
||||
val sf = testDefaultFactory()
|
||||
val path1 = EvolvabilityTests::class.java.getResource("EvolvabilityTests.multiVersionWithRemoval.1")
|
||||
val path2 = EvolvabilityTests::class.java.getResource("EvolvabilityTests.multiVersionWithRemoval.2")
|
||||
val path3 = EvolvabilityTests::class.java.getResource("EvolvabilityTests.multiVersionWithRemoval.3")
|
||||
|
||||
val resource1 = "EvolvabilityTests.multiVersionWithRemoval.1"
|
||||
val resource2 = "EvolvabilityTests.multiVersionWithRemoval.2"
|
||||
val resource3 = "EvolvabilityTests.multiVersionWithRemoval.3"
|
||||
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
val a = 100
|
||||
@ -417,24 +406,15 @@ class EvolvabilityTests {
|
||||
//
|
||||
// Version 1:
|
||||
// data class C (val a: Int, val b: Int, val c: Int)
|
||||
// File(URI("$localPath/$resource1")).writeBytes(SerializationOutput(sf).serialize(C(a, b, c)).bytes)
|
||||
//
|
||||
// val scc = SerializationOutput(sf).serialize(C(a, b, c))
|
||||
// File(path1.toURI()).writeBytes(scc.bytes)
|
||||
// println ("Path = $path1")
|
||||
//
|
||||
// Version 2 - add param c
|
||||
// Version 2 - remove property a, add property e
|
||||
// data class C (val b: Int, val c: Int, val d: Int, val e: Int)
|
||||
//
|
||||
// val scc = SerializationOutput(sf).serialize(C(b, c, d, e))
|
||||
// File(path2.toURI()).writeBytes(scc.bytes)
|
||||
// println ("Path = $path2")
|
||||
// File(URI("$localPath/$resource2")).writeBytes(SerializationOutput(sf).serialize(C(b, c, d, e)).bytes)
|
||||
//
|
||||
// Version 3 - add param d
|
||||
// data class C (val b: Int, val c: Int, val d: Int, val e: Int, val f: Int)
|
||||
//
|
||||
// val scc = SerializationOutput(sf).serialize(C(b, c, d, e, f))
|
||||
// File(path3.toURI()).writeBytes(scc.bytes)
|
||||
// println ("Path = $path3")
|
||||
// File(URI("$localPath/$resource3")).writeBytes(SerializationOutput(sf).serialize(C(b, c, d, e, f)).bytes)
|
||||
|
||||
@Suppress("UNUSED")
|
||||
data class C(val b: Int, val c: Int, val d: Int, val e: Int, val f: Int, val g: Int) {
|
||||
@ -451,6 +431,10 @@ class EvolvabilityTests {
|
||||
constructor (b: Int, c: Int, d: Int, e: Int, f: Int) : this(b, c, d, e, f, -1)
|
||||
}
|
||||
|
||||
val path1 = EvolvabilityTests::class.java.getResource(resource1)
|
||||
val path2 = EvolvabilityTests::class.java.getResource(resource2)
|
||||
val path3 = EvolvabilityTests::class.java.getResource(resource3)
|
||||
|
||||
val sb1 = File(path1.toURI()).readBytes()
|
||||
val db1 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb1))
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user