CORDA-3390: Allow EvolutionSerializer to handle primitive types becoming nullable. (#5661)

This commit is contained in:
Chris Rankin 2019-11-04 16:19:46 +00:00 committed by Matthew Nesbit
parent 43856319bd
commit b2c944bb0e
4 changed files with 34 additions and 3 deletions

View File

@ -39,7 +39,8 @@ dependencies {
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}" testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}" testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
testRuntimeOnly "org.slf4j:slf4j-simple:$slf4j_version"
testCompile "org.assertj:assertj-core:$assertj_version" testCompile "org.assertj:assertj-core:$assertj_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile "org.mockito:mockito-core:$mockito_version" testCompile "org.mockito:mockito-core:$mockito_version"

View File

@ -105,7 +105,13 @@ class DefaultEvolutionSerializerFactory(
evolverProperties.all { (name, evolverProperty) -> evolverProperties.all { (name, evolverProperty) ->
val propertyType = propertyTypes[name] val propertyType = propertyTypes[name]
if (propertyType == null) !evolverProperty.isMandatory if (propertyType == null) !evolverProperty.isMandatory
else evolverProperty.type.observedType.asClass().isAssignableFrom(propertyType) else {
// Check that we can assign the remote property value to its local equivalent.
// This includes assigning a primitive type to its equivalent "boxed" type.
val evolverPropertyType = evolverProperty.type.observedType.asClass()
evolverPropertyType.isAssignableFrom(propertyType)
|| (propertyType.isPrimitive && evolverPropertyType.isAssignableFrom(propertyType.kotlin.javaObjectType))
}
} }
} }
} }

View File

@ -23,6 +23,7 @@ import kotlin.test.assertEquals
import net.corda.serialization.internal.amqp.custom.InstantSerializer import net.corda.serialization.internal.amqp.custom.InstantSerializer
import net.corda.serialization.internal.amqp.testutils.ProjectStructure.projectRootDir import net.corda.serialization.internal.amqp.testutils.ProjectStructure.projectRootDir
import java.math.BigInteger import java.math.BigInteger
import kotlin.test.fail
// To regenerate any of the binary test files do the following // To regenerate any of the binary test files do the following
// //
@ -36,7 +37,7 @@ class EvolvabilityTests {
// When regenerating the test files this needs to be set to the file system location of the resource files // When regenerating the test files this needs to be set to the file system location of the resource files
@Suppress("UNUSED") @Suppress("UNUSED")
var localPath: URI = projectRootDir.toUri().resolve( var localPath: URI = projectRootDir.toUri().resolve(
"serialization-test/src/test/resources/net/corda/serialization/internal/amqp") "serialization/src/test/resources/net/corda/serialization/internal/amqp")
companion object { companion object {
private val DUMMY_NOTARY_NAME = CordaX500Name("Notary Service", "Zurich", "CH") private val DUMMY_NOTARY_NAME = CordaX500Name("Notary Service", "Zurich", "CH")
@ -744,4 +745,27 @@ class EvolvabilityTests {
assertEquals(10, deserialized.parameterized?.a) assertEquals(10, deserialized.parameterized?.a)
} }
@Test
fun addMandatoryFieldWithAltConstructorAndMakeExistingIntFieldNullable() {
val sf = testDefaultFactory()
val resource = "EvolvabilityTests.addMandatoryFieldWithAltConstructorAndMakeExistingIntFieldNullable"
// Original version of the class as it was serialised
// data class CC(val a: Int)
// File(URI("$localPath/$resource")).writeBytes(SerializationOutput(sf).serialize(CC(1)).bytes)
data class CC(val a: Int?, val b: Int) {
@DeprecatedConstructorForDeserialization(1)
@Suppress("unused")
constructor(a: Int) : this(a, 42)
}
val url = EvolvabilityTests::class.java.getResource(resource) ?: fail("Not found!")
val sc2 = url.readBytes()
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
assertEquals(1, deserializedCC.a)
assertEquals(42, deserializedCC.b)
}
} }