Serialization of large contract attachments causes OOM exception (#1991)

* Don't serialize contract attachment, only hash and contract class name if we are checkpointing
This commit is contained in:
cburlinchon
2017-11-10 10:21:36 +00:00
committed by GitHub
parent 6b71c6cf75
commit 4c1d1733a5
2 changed files with 135 additions and 6 deletions

View File

@ -0,0 +1,103 @@
package net.corda.nodeapi.internal.serialization
import net.corda.core.contracts.ContractAttachment
import net.corda.core.serialization.*
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.contracts.DummyContract
import net.corda.testing.node.MockServices
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Assert.assertArrayEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import kotlin.test.assertEquals
class ContractAttachmentSerializerTest {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
private lateinit var factory: SerializationFactory
private lateinit var context: SerializationContext
private lateinit var contextWithToken: SerializationContext
private val mockServices = MockServices()
@Before
fun setup() {
factory = testSerialization.env.SERIALIZATION_FACTORY
context = testSerialization.env.CHECKPOINT_CONTEXT
contextWithToken = context.withTokenContext(SerializeAsTokenContextImpl(Any(), factory, context, mockServices))
}
@Test
fun `write contract attachment and read it back`() {
val contractAttachment = ContractAttachment(GeneratedAttachment(ByteArray(0)), DummyContract.PROGRAM_ID)
// no token context so will serialize the whole attachment
val serialized = contractAttachment.serialize(factory, context)
val deserialized = serialized.deserialize(factory, context)
assertEquals(contractAttachment.id, deserialized.attachment.id)
assertEquals(contractAttachment.contract, deserialized.contract)
assertArrayEquals(contractAttachment.open().readBytes(), deserialized.open().readBytes())
}
@Test
fun `write contract attachment and read it back using token context`() {
val attachment = GeneratedAttachment("test".toByteArray())
mockServices.attachments.importAttachment(attachment.open())
val contractAttachment = ContractAttachment(attachment, DummyContract.PROGRAM_ID)
val serialized = contractAttachment.serialize(factory, contextWithToken)
val deserialized = serialized.deserialize(factory, contextWithToken)
assertEquals(contractAttachment.id, deserialized.attachment.id)
assertEquals(contractAttachment.contract, deserialized.contract)
assertArrayEquals(contractAttachment.open().readBytes(), deserialized.open().readBytes())
}
@Test
fun `check only serialize attachment id and contract class name when using token context`() {
val largeAttachmentSize = 1024 * 1024
val attachment = GeneratedAttachment(ByteArray(largeAttachmentSize))
mockServices.attachments.importAttachment(attachment.open())
val contractAttachment = ContractAttachment(attachment, DummyContract.PROGRAM_ID)
val serialized = contractAttachment.serialize(factory, contextWithToken)
assertThat(serialized.size).isLessThan(largeAttachmentSize)
}
@Test
fun `throws when missing attachment when using token context`() {
val attachment = GeneratedAttachment("test".toByteArray())
// don't importAttachment in mockService
val contractAttachment = ContractAttachment(attachment, DummyContract.PROGRAM_ID)
val serialized = contractAttachment.serialize(factory, contextWithToken)
val deserialized = serialized.deserialize(factory, contextWithToken)
assertThatThrownBy { deserialized.attachment.open() }.isInstanceOf(MissingAttachmentsException::class.java)
}
@Test
fun `check attachment in deserialize is lazy loaded when using token context`() {
val attachment = GeneratedAttachment(ByteArray(0))
// don't importAttachment in mockService
val contractAttachment = ContractAttachment(attachment, DummyContract.PROGRAM_ID)
val serialized = contractAttachment.serialize(factory, contextWithToken)
serialized.deserialize(factory, contextWithToken)
// MissingAttachmentsException thrown if we try to open attachment
}
}