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 net.corda.client.jackson.JacksonSupport
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowStackSnapshot
import net.corda.core.flows.StartableByRPC
import net.corda.core.flows.StateMachineRunId
import net.corda.core.flows.*
import net.corda.core.internal.div
import net.corda.core.internal.list
import net.corda.core.internal.read
import net.corda.core.messaging.startFlow
import net.corda.core.serialization.CordaSerializable
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.internal.ServiceInfo
import net.corda.testing.driver.driver
import net.corda.testing.node.MockNetwork
import org.junit.Ignore
import org.junit.Test
import java.nio.file.Path
import java.time.LocalDate
import kotlin.test.assertEquals
import kotlin.test.assertNull
import kotlin.test.assertTrue
@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 {
val snapshotFile = flowSnapshotDir(baseDir, flowId) / "flowStackSnapshot.json"
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
fun `persistFlowStackSnapshot stack traces are aligned with stack objects`() {
driver(startNodesInProcess = true) {

View File

@ -54,7 +54,8 @@ class FlowStackSnapshotFactoryImpl : FlowStackSnapshotFactory {
val objectStack = getObjectStack(stack).toList()
val frameOffsets = getFrameOffsets(stack)
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
val relevantStackTrace = removeConstructorStackTraceElements(stackTrace).drop(1)