[CORDA-2364] Make the class carpenter for RPC lenient by default. (#4467)

This commit is contained in:
Florian Friemel 2019-01-02 17:18:31 +00:00 committed by GitHub
parent 87adc1c831
commit a1a5a429cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 2 deletions

View File

@ -21,5 +21,6 @@ val AMQP_RPC_CLIENT_CONTEXT = SerializationContextImpl(
emptyMap(),
true,
SerializationContext.UseCase.RPCClient,
null
null,
lenientCarpenterEnabled = true
)

View File

@ -36,5 +36,6 @@ val AMQP_RPC_SERVER_CONTEXT = SerializationContextImpl(
emptyMap(),
true,
SerializationContext.UseCase.RPCServer,
null
null,
lenientCarpenterEnabled = true
)

View File

@ -0,0 +1,64 @@
package net.corda.serialization.internal.amqp
import net.corda.client.rpc.internal.serialization.amqp.AMQPClientSerializationScheme
import net.corda.core.identity.AbstractParty
import net.corda.core.schemas.MappedSchema
import net.corda.core.schemas.PersistentState
import net.corda.core.schemas.QueryableState
import net.corda.core.serialization.SerializedBytes
import net.corda.node.serialization.amqp.AMQPServerSerializationScheme
import net.corda.serialization.internal.AMQP_RPC_CLIENT_CONTEXT
import net.corda.serialization.internal.AMQP_RPC_SERVER_CONTEXT
import net.corda.serialization.internal.AllWhitelist
import net.corda.testing.core.DUMMY_BANK_A_NAME
import net.corda.testing.core.TestIdentity
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
data class TestState(override val participants: List<AbstractParty>): QueryableState {
override fun generateMappedObject(schema: MappedSchema): PersistentState {
throw NotImplementedError()
}
override fun supportedSchemas(): Iterable<MappedSchema> {
// return dummy value
return listOf(MappedSchema(TestState::class.java, 432, listOf()))
}
}
/**
* A class loader that excludes [TestState].
*/
class ClassLoaderWithoutTestState(classLoader: ClassLoader) : ClassLoader(classLoader) {
override fun loadClass(name: String?, resolve: Boolean): Class<*> {
if (name != null && name == TestState::class.java.name) {
throw ClassNotFoundException()
}
return super.loadClass(name, resolve)
}
}
class DeserializeQueryableStateTest {
/**
* https://r3-cev.atlassian.net/browse/CORDA-2330
*/
@Test
fun `should deserialize subclass of QueryableState that is not present in the class loader`() {
val testParty = TestIdentity(DUMMY_BANK_A_NAME).identity.party
val instance = TestState(listOf(testParty))
val scheme = AMQPServerSerializationScheme(emptyList())
val serialized = scheme.serialize(instance, AMQP_RPC_SERVER_CONTEXT)
val clientContext = AMQP_RPC_CLIENT_CONTEXT.copy(whitelist = AllWhitelist, deserializationClassLoader = ClassLoaderWithoutTestState(ClassLoader.getSystemClassLoader()))
val serializedBytes = SerializedBytes<QueryableState>(serialized.bytes)
val clientScheme = AMQPClientSerializationScheme(emptyList())
// this operation used to fail because AMQP_RPC_CLIENT_CONTEXT.lenientCarpenterEnabled was false
val deserialized = clientScheme.deserialize(serializedBytes, QueryableState::class.java, clientContext)
assertFailsWith<AbstractMethodError> { deserialized.supportedSchemas() }
assertEquals(deserialized.participants.first(), testParty)
}
}