user123959
user123959

Reputation: 1256

Corda Schedulable State caused Flow tests to hang

I have a LoanState that is a ScheduledState. All Flow tests that use the LoanState get hung infinitely. If I set nextScheduledActivity() to return null then the tests run fine. There are no visible errors in the unit test log. This is on Corda 3.2.

This is the last bit of text in the console before it hangs:

[INFO ] 14:39:40,604 [Mock node 1 thread] (FlowStateMachineImpl.kt:419) flow.[742bd708-244d-49a0-91af-8127267029a1].initiateSession - Initiating flow session with party O=Mock Company 2, L=London, C=GB. Session id for tracing purposes is SessionId(toLong=4148369640629821591). {} [INFO ] 14:39:40,619 [Mock node 2 thread] (StateMachineManagerImpl.kt:367) statemachine.StateMachineManagerImpl.onSessionInit - Accepting flow session from party O=Mock Company 1, L=London, C=GB. Session id for tracing purposes is SessionId(toLong=4148369640629821591). {invocation_id=2c33f7e4-63bd-4fad-98a0-6b568a78136d, invocation_timestamp=2020-03-23T19:39:40.619Z, session_id=2c33f7e4-63bd-4fad-98a0-6b568a78136d, session_timestamp=2020-03-23T19:39:40.619Z} [INFO ] 14:39:40,706 [Mock node 1 thread] (FlowStateMachineImpl.kt:419) flow.[742bd708-244d-49a0-91af-8127267029a1].initiateSession - Initiating flow session with party O=Mock Company 2, L=London, C=GB. Session id for tracing purposes is SessionId(toLong=-5160466662167158789). {} [INFO ] 14:39:40,715 [Mock node 2 thread] (StateMachineManagerImpl.kt:367) statemachine.StateMachineManagerImpl.onSessionInit - Accepting flow session from party O=Mock Company 1, L=London, C=GB. Session id for tracing purposes is SessionId(toLong=-5160466662167158789). {invocation_id=af86ddea-0bae-43eb-998c-c2ae3fc91fcf, invocation_timestamp=2020-03-23T19:39:40.715Z, session_id=af86ddea-0bae-43eb-998c-c2ae3fc91fcf, session_timestamp=2020-03-23T19:39:40.715Z} [INFO ] 14:39:40,742 [Mock node 1 thread] (FlowStateMachineImpl.kt:419) flow.[742bd708-244d-49a0-91af-8127267029a1].initiateSession - Initiating flow session with party O=ParentCompany, L=London, C=GB. Session id for tracing purposes is SessionId(toLong=6693667128513799995). {} [INFO ] 14:39:40,750 [Mock node 3 thread] (StateMachineManagerImpl.kt:367) statemachine.StateMachineManagerImpl.onSessionInit - Accepting flow session from party O=Mock Company 1, L=London, C=GB. Session id for tracing purposes is SessionId(toLong=6693667128513799995). {actor_id=Only For Testing, actor_owningIdentity=O=ParentCompany, L=London, C=GB, actor_store_id=TEST, invocation_id=487f4d03-c5b7-4aea-81a6-a000e788e0a2, invocation_timestamp=2020-03-23T19:39:40.750Z, session_id=487f4d03-c5b7-4aea-81a6-a000e788e0a2, session_timestamp=2020-03-23T19:39:40.750Z}

@Nullable
@Override
public ScheduledActivity nextScheduledActivity(@NotNull StateRef thisStateRef, @NotNull 
    FlowLogicRefFactory flowLogicRefFactory) {

    FlowLogicRef flow = flowLogicRefFactory.create(
                "com.myapp.MySchedulableFlow",
                thisStateRef
    );
    return new ScheduledActivity(flow, paymentDueDate);
}

If I set the Flow name to a non-existent flow, then the tests will NOT hang and will report that the Flow couldn't be found.

Update: Confirmed that it is waitQuiscent() that is hanging. If I remove this and replace it with a Thread.sleep() my test will pass.It looks like waitQuiscent waits for all ScheduledActivities to finish. Is there a wait to handle the same type of functionality without waiting for ScheduledActivities to finish?

Upvotes: 0

Views: 178

Answers (1)

Ashutosh Meher
Ashutosh Meher

Reputation: 1841

You may have missed calling the MockNetwork.runNetwork method. Here is an example:

@Test
public void testCreateAuctionFlow() throws Exception {
    CreateAssetFlow assetflow = new CreateAssetFlow("Test Asset", "Dummy Asset", dummy.png");
    CordaFuture<SignedTransaction> future = a.startFlow(assetflow);
    network.runNetwork();
    SignedTransaction signedTransaction = future.get();
    Asset asset = (Asset) signedTransaction.getTx().getOutput(0);
    CreateAuctionFlow.Initiator auctionFlow = new CreateAuctionFlow.Initiator(Amount.parseCurrency("1000 USD"),
            asset.getLinearId().getId(), LocalDateTime.ofInstant(Instant.now().plusMillis(30000), ZoneId.systemDefault()));
    CordaFuture<SignedTransaction> future1 = a.startFlow(auctionFlow);
    network.runNetwork();
    SignedTransaction transaction = future1.get();
    AuctionState auctionState = (AuctionState) transaction.getTx().getOutput(0);
    assertNotNull(auctionState);
}

The runNetwork method should be called after every flow is triggered. This helps the mock network to bounce messages among the nodes properly.

Check the docs here for more details: https://docs.corda.net/docs/corda-os/4.4/flow-testing.html

Have a look at the testCase for the SchedulableState in the samples here: https://github.com/corda/samples/blob/release-V4/auction-cordapp/workflows/src/test/java/net/corda/samples/FlowTests.java#L68

Upvotes: 1

Related Questions