Fixing flow snapshot feature (#1685)

This commit is contained in:
mkit
2017-09-27 14:03:34 +01:00
committed by josecoll
parent 324804eabc
commit dc0a8fecc4
2 changed files with 53 additions and 5 deletions

View File

@ -2,23 +2,25 @@ package net.corda.testing
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.client.jackson.JacksonSupport import net.corda.client.jackson.JacksonSupport
import net.corda.core.flows.FlowLogic import net.corda.core.flows.*
import net.corda.core.flows.FlowStackSnapshot
import net.corda.core.flows.StartableByRPC
import net.corda.core.flows.StateMachineRunId
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.internal.list import net.corda.core.internal.list
import net.corda.core.internal.read import net.corda.core.internal.read
import net.corda.core.messaging.startFlow import net.corda.core.messaging.startFlow
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
import net.corda.node.services.network.NetworkMapService
import net.corda.node.services.transactions.ValidatingNotaryService
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.nodeapi.internal.ServiceInfo
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.node.MockNetwork
import org.junit.Ignore import org.junit.Ignore
import org.junit.Test import org.junit.Test
import java.nio.file.Path import java.nio.file.Path
import java.time.LocalDate import java.time.LocalDate
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
@CordaSerializable @CordaSerializable
@ -178,6 +180,31 @@ class MultiplePersistingSideEffectFlow(val persistCallCount: Int) : FlowLogic<St
} }
} }
/**
* Flow that tests whether the serialization works correctly.
*/
@StartableByRPC
@InitiatingFlow
class FlowStackSnapshotSerializationTestingFlow : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val flowStackSnapshot = flowStackSnapshot()
val mySession = initiateFlow(ourIdentity)
mySession.sendAndReceive<String>("Ping")
}
}
@InitiatedBy(FlowStackSnapshotSerializationTestingFlow::class)
class DummyFlow(private val otherSideSession: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val message = otherSideSession.receive<String>()
otherSideSession.send("$message Pong")
}
}
fun readFlowStackSnapshotFromDir(baseDir: Path, flowId: StateMachineRunId): FlowStackSnapshot { fun readFlowStackSnapshotFromDir(baseDir: Path, flowId: StateMachineRunId): FlowStackSnapshot {
val snapshotFile = flowSnapshotDir(baseDir, flowId) / "flowStackSnapshot.json" val snapshotFile = flowSnapshotDir(baseDir, flowId) / "flowStackSnapshot.json"
return snapshotFile.read { return snapshotFile.read {
@ -263,6 +290,26 @@ class FlowStackSnapshotTest {
} }
} }
@Test
fun `flowStackSnapshot object is serializable`() {
val mockNet = MockNetwork(threadPerNode = true)
val notaryService = ServiceInfo(ValidatingNotaryService.type)
val notaryNode = mockNet.createNode(
legalName = DUMMY_NOTARY.name,
overrideServices = mapOf(notaryService to DUMMY_NOTARY_KEY),
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), notaryService))
val node = mockNet.createPartyNode(notaryNode.network.myAddress)
node.internals.registerInitiatedFlow(DummyFlow::class.java)
node.services.startFlow(FlowStackSnapshotSerializationTestingFlow()).resultFuture.get()
val thrown = try {
mockNet.stopNodes()
null
} catch (exception: Exception) {
exception
}
assertNull(thrown)
}
@Test @Test
fun `persistFlowStackSnapshot stack traces are aligned with stack objects`() { fun `persistFlowStackSnapshot stack traces are aligned with stack objects`() {
driver(startNodesInProcess = true) { driver(startNodesInProcess = true) {

View File

@ -54,7 +54,8 @@ class FlowStackSnapshotFactoryImpl : FlowStackSnapshotFactory {
val objectStack = getObjectStack(stack).toList() val objectStack = getObjectStack(stack).toList()
val frameOffsets = getFrameOffsets(stack) val frameOffsets = getFrameOffsets(stack)
val frameObjects = frameOffsets.map { (frameOffset, frameSize) -> val frameObjects = frameOffsets.map { (frameOffset, frameSize) ->
objectStack.subList(frameOffset + 1, frameOffset + frameSize + 1) // We need to convert the sublist to a list due to the Kryo lack of support when serializing
objectStack.subList(frameOffset + 1, frameOffset + frameSize + 1).toList()
} }
// We drop the first element as it is corda internal call irrelevant from the perspective of a CordApp developer // We drop the first element as it is corda internal call irrelevant from the perspective of a CordApp developer
val relevantStackTrace = removeConstructorStackTraceElements(stackTrace).drop(1) val relevantStackTrace = removeConstructorStackTraceElements(stackTrace).drop(1)