mirror of
https://github.com/corda/corda.git
synced 2025-06-18 23:28:21 +00:00
Refactor KryoAMQPSerializer to go through generic APIs to access AMQP serialization (#1225)
This commit is contained in:
@ -5,8 +5,8 @@ import com.esotericsoftware.kryo.io.Input
|
||||
import com.esotericsoftware.kryo.io.Output
|
||||
import com.esotericsoftware.kryo.util.MapReferenceResolver
|
||||
import net.corda.core.node.services.AttachmentStorage
|
||||
import net.corda.core.serialization.AttachmentsClassLoader
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.core.utilities.ByteSequence
|
||||
import net.corda.nodeapi.AttachmentClassLoaderTests
|
||||
import net.corda.testing.node.MockAttachmentStorage
|
||||
import org.junit.Rule
|
||||
@ -76,71 +76,84 @@ class DefaultSerializableSerializer : Serializer<DefaultSerializable>() {
|
||||
}
|
||||
|
||||
class CordaClassResolverTests {
|
||||
val factory: SerializationFactory = object : SerializationFactory {
|
||||
override fun <T : Any> deserialize(byteSequence: ByteSequence, clazz: Class<T>, context: SerializationContext): T {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
override fun <T : Any> serialize(obj: T, context: SerializationContext): SerializedBytes<T> {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val emptyWhitelistContext: SerializationContext = SerializationContextImpl(KryoHeaderV0_1, this.javaClass.classLoader, EmptyWhitelist, emptyMap(), true, SerializationContext.UseCase.P2P)
|
||||
val allButBlacklistedContext: SerializationContext = SerializationContextImpl(KryoHeaderV0_1, this.javaClass.classLoader, AllButBlacklisted, emptyMap(), true, SerializationContext.UseCase.P2P)
|
||||
|
||||
@Test
|
||||
fun `Annotation on enum works for specialised entries`() {
|
||||
// TODO: Remove this suppress when we upgrade to kotlin 1.1 or when JetBrain fixes the bug.
|
||||
@Suppress("UNSUPPORTED_FEATURE")
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(Foo.Bar::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(Foo.Bar::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Annotation on array element works`() {
|
||||
val values = arrayOf(Element())
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(values.javaClass)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(values.javaClass)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Annotation not needed on abstract class`() {
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(AbstractClass::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(AbstractClass::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Annotation not needed on interface`() {
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(Interface::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(Interface::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Calling register method on modified Kryo does not consult the whitelist`() {
|
||||
val kryo = CordaKryo(CordaClassResolver(EmptyWhitelist))
|
||||
val kryo = CordaKryo(CordaClassResolver(factory, emptyWhitelistContext))
|
||||
kryo.register(NotSerializable::class.java)
|
||||
}
|
||||
|
||||
@Test(expected = KryoException::class)
|
||||
fun `Calling register method on unmodified Kryo does consult the whitelist`() {
|
||||
val kryo = Kryo(CordaClassResolver(EmptyWhitelist), MapReferenceResolver())
|
||||
val kryo = Kryo(CordaClassResolver(factory, emptyWhitelistContext), MapReferenceResolver())
|
||||
kryo.register(NotSerializable::class.java)
|
||||
}
|
||||
|
||||
@Test(expected = KryoException::class)
|
||||
fun `Annotation is needed without whitelisting`() {
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(NotSerializable::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(NotSerializable::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Annotation is not needed with whitelisting`() {
|
||||
val resolver = CordaClassResolver(GlobalTransientClassWhiteList(EmptyWhitelist))
|
||||
(resolver.whitelist as MutableClassWhitelist).add(NotSerializable::class.java)
|
||||
val resolver = CordaClassResolver(factory, emptyWhitelistContext.withWhitelisted(NotSerializable::class.java))
|
||||
resolver.getRegistration(NotSerializable::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Annotation not needed on Object`() {
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(Object::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(Object::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Annotation not needed on primitive`() {
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(Integer.TYPE)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(Integer.TYPE)
|
||||
}
|
||||
|
||||
@Test(expected = KryoException::class)
|
||||
fun `Annotation does not work for custom serializable`() {
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(CustomSerializable::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(CustomSerializable::class.java)
|
||||
}
|
||||
|
||||
@Test(expected = KryoException::class)
|
||||
fun `Annotation does not work in conjunction with Kryo annotation`() {
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(DefaultSerializable::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(DefaultSerializable::class.java)
|
||||
}
|
||||
|
||||
private fun importJar(storage: AttachmentStorage) = AttachmentClassLoaderTests.ISOLATED_CONTRACTS_JAR_PATH.openStream().use { storage.importAttachment(it) }
|
||||
@ -151,20 +164,20 @@ class CordaClassResolverTests {
|
||||
val attachmentHash = importJar(storage)
|
||||
val classLoader = AttachmentsClassLoader(arrayOf(attachmentHash).map { storage.openAttachment(it)!! })
|
||||
val attachedClass = Class.forName("net.corda.contracts.isolated.AnotherDummyContract", true, classLoader)
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(attachedClass)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(attachedClass)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Annotation is inherited from interfaces`() {
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(SerializableViaInterface::class.java)
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(SerializableViaSubInterface::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(SerializableViaInterface::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(SerializableViaSubInterface::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Annotation is inherited from superclass`() {
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(SubElement::class.java)
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(SubSubElement::class.java)
|
||||
CordaClassResolver(EmptyWhitelist).getRegistration(SerializableViaSuperSubInterface::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(SubElement::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(SubSubElement::class.java)
|
||||
CordaClassResolver(factory, emptyWhitelistContext).getRegistration(SerializableViaSuperSubInterface::class.java)
|
||||
}
|
||||
|
||||
// Blacklist tests.
|
||||
@ -175,7 +188,7 @@ class CordaClassResolverTests {
|
||||
fun `Check blacklisted class`() {
|
||||
expectedEx.expect(IllegalStateException::class.java)
|
||||
expectedEx.expectMessage("Class java.util.HashSet is blacklisted, so it cannot be used in serialization.")
|
||||
val resolver = CordaClassResolver(AllButBlacklisted)
|
||||
val resolver = CordaClassResolver(factory, allButBlacklistedContext)
|
||||
// HashSet is blacklisted.
|
||||
resolver.getRegistration(HashSet::class.java)
|
||||
}
|
||||
@ -185,7 +198,7 @@ class CordaClassResolverTests {
|
||||
fun `Check blacklisted subclass`() {
|
||||
expectedEx.expect(IllegalStateException::class.java)
|
||||
expectedEx.expectMessage("The superclass java.util.HashSet of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$SubHashSet is blacklisted, so it cannot be used in serialization.")
|
||||
val resolver = CordaClassResolver(AllButBlacklisted)
|
||||
val resolver = CordaClassResolver(factory, allButBlacklistedContext)
|
||||
// SubHashSet extends the blacklisted HashSet.
|
||||
resolver.getRegistration(SubHashSet::class.java)
|
||||
}
|
||||
@ -195,7 +208,7 @@ class CordaClassResolverTests {
|
||||
fun `Check blacklisted subsubclass`() {
|
||||
expectedEx.expect(IllegalStateException::class.java)
|
||||
expectedEx.expectMessage("The superclass java.util.HashSet of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$SubSubHashSet is blacklisted, so it cannot be used in serialization.")
|
||||
val resolver = CordaClassResolver(AllButBlacklisted)
|
||||
val resolver = CordaClassResolver(factory, allButBlacklistedContext)
|
||||
// SubSubHashSet extends SubHashSet, which extends the blacklisted HashSet.
|
||||
resolver.getRegistration(SubSubHashSet::class.java)
|
||||
}
|
||||
@ -205,7 +218,7 @@ class CordaClassResolverTests {
|
||||
fun `Check blacklisted interface impl`() {
|
||||
expectedEx.expect(IllegalStateException::class.java)
|
||||
expectedEx.expectMessage("The superinterface java.sql.Connection of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$ConnectionImpl is blacklisted, so it cannot be used in serialization.")
|
||||
val resolver = CordaClassResolver(AllButBlacklisted)
|
||||
val resolver = CordaClassResolver(factory, allButBlacklistedContext)
|
||||
// ConnectionImpl implements blacklisted Connection.
|
||||
resolver.getRegistration(ConnectionImpl::class.java)
|
||||
}
|
||||
@ -216,14 +229,14 @@ class CordaClassResolverTests {
|
||||
fun `Check blacklisted super-interface impl`() {
|
||||
expectedEx.expect(IllegalStateException::class.java)
|
||||
expectedEx.expectMessage("The superinterface java.sql.Connection of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$SubConnectionImpl is blacklisted, so it cannot be used in serialization.")
|
||||
val resolver = CordaClassResolver(AllButBlacklisted)
|
||||
val resolver = CordaClassResolver(factory, allButBlacklistedContext)
|
||||
// SubConnectionImpl implements SubConnection, which extends the blacklisted Connection.
|
||||
resolver.getRegistration(SubConnectionImpl::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Check forcibly allowed`() {
|
||||
val resolver = CordaClassResolver(AllButBlacklisted)
|
||||
val resolver = CordaClassResolver(factory, allButBlacklistedContext)
|
||||
// LinkedHashSet is allowed for serialization.
|
||||
resolver.getRegistration(LinkedHashSet::class.java)
|
||||
}
|
||||
@ -234,7 +247,7 @@ class CordaClassResolverTests {
|
||||
fun `Check blacklist precedes CordaSerializable`() {
|
||||
expectedEx.expect(IllegalStateException::class.java)
|
||||
expectedEx.expectMessage("The superclass java.util.HashSet of net.corda.nodeapi.internal.serialization.CordaClassResolverTests\$CordaSerializableHashSet is blacklisted, so it cannot be used in serialization.")
|
||||
val resolver = CordaClassResolver(AllButBlacklisted)
|
||||
val resolver = CordaClassResolver(factory, allButBlacklistedContext)
|
||||
// CordaSerializableHashSet is @CordaSerializable, but extends the blacklisted HashSet.
|
||||
resolver.getRegistration(CordaSerializableHashSet::class.java)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import net.corda.core.utilities.sequence
|
||||
import net.corda.node.serialization.KryoServerSerializationScheme
|
||||
import net.corda.node.services.persistence.NodeAttachmentService
|
||||
import net.corda.testing.ALICE_PUBKEY
|
||||
import net.corda.testing.TestDependencyInjectionBase
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Before
|
||||
@ -23,13 +24,13 @@ import java.time.Instant
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class KryoTests {
|
||||
class KryoTests : TestDependencyInjectionBase() {
|
||||
private lateinit var factory: SerializationFactory
|
||||
private lateinit var context: SerializationContext
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
factory = SerializationFactoryImpl().apply { registerScheme(KryoServerSerializationScheme()) }
|
||||
factory = SerializationFactoryImpl().apply { registerScheme(KryoServerSerializationScheme(this)) }
|
||||
context = SerializationContextImpl(KryoHeaderV0_1,
|
||||
javaClass.classLoader,
|
||||
AllWhitelist,
|
||||
@ -199,7 +200,7 @@ class KryoTests {
|
||||
}
|
||||
}
|
||||
Tmp()
|
||||
val factory = SerializationFactoryImpl().apply { registerScheme(KryoServerSerializationScheme()) }
|
||||
val factory = SerializationFactoryImpl().apply { registerScheme(KryoServerSerializationScheme(this)) }
|
||||
val context = SerializationContextImpl(KryoHeaderV0_1,
|
||||
javaClass.classLoader,
|
||||
AllWhitelist,
|
||||
|
@ -8,19 +8,20 @@ import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.serialization.*
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.node.serialization.KryoServerSerializationScheme
|
||||
import net.corda.testing.TestDependencyInjectionBase
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
class SerializationTokenTest {
|
||||
class SerializationTokenTest : TestDependencyInjectionBase() {
|
||||
|
||||
lateinit var factory: SerializationFactory
|
||||
lateinit var context: SerializationContext
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
factory = SerializationFactoryImpl().apply { registerScheme(KryoServerSerializationScheme()) }
|
||||
factory = SerializationFactoryImpl().apply { registerScheme(KryoServerSerializationScheme(this)) }
|
||||
context = SerializationContextImpl(KryoHeaderV0_1,
|
||||
javaClass.classLoader,
|
||||
AllWhitelist,
|
||||
@ -96,7 +97,7 @@ class SerializationTokenTest {
|
||||
val context = serializeAsTokenContext(tokenizableBefore)
|
||||
val testContext = this.context.withTokenContext(context)
|
||||
|
||||
val kryo: Kryo = DefaultKryoCustomizer.customize(CordaKryo(makeNoWhitelistClassResolver()))
|
||||
val kryo: Kryo = DefaultKryoCustomizer.customize(CordaKryo(CordaClassResolver(factory, this.context)))
|
||||
val stream = ByteArrayOutputStream()
|
||||
Output(stream).use {
|
||||
it.write(KryoHeaderV0_1.bytes)
|
||||
|
@ -11,8 +11,8 @@ import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
import net.corda.nodeapi.RPCException
|
||||
import net.corda.nodeapi.internal.serialization.AbstractAMQPSerializationScheme
|
||||
import net.corda.nodeapi.internal.serialization.EmptyWhitelist
|
||||
import net.corda.nodeapi.internal.serialization.KryoAMQPSerializer
|
||||
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.isPrimitive
|
||||
import net.corda.nodeapi.internal.serialization.amqp.custom.*
|
||||
import net.corda.testing.MEGA_CORP
|
||||
@ -528,10 +528,10 @@ class SerializationOutputTests {
|
||||
val state = TransactionState<FooState>(FooState(), MEGA_CORP)
|
||||
|
||||
val factory = SerializerFactory()
|
||||
KryoAMQPSerializer.registerCustomSerializers(factory)
|
||||
AbstractAMQPSerializationScheme.registerCustomSerializers(factory)
|
||||
|
||||
val factory2 = SerializerFactory()
|
||||
KryoAMQPSerializer.registerCustomSerializers(factory2)
|
||||
AbstractAMQPSerializationScheme.registerCustomSerializers(factory2)
|
||||
|
||||
val desState = serdes(state, factory, factory2, expectedEqual = false, expectDeserializedEqual = false)
|
||||
assertTrue(desState is TransactionState<*>)
|
||||
|
Reference in New Issue
Block a user