@Test
public void lifecycleEvents() {

    try (ModuleInterpretation moduleInterpretation = testCaseBuilder("lifecycleEvents", INLINE_CONTEXT).build()) {
        Props props = moduleInterpretation.toCompositeModuleInterpreterProps(3, bitSetOf(), bitSetOf(2));
        long timestampLowerBound = System.currentTimeMillis();
        TestActorRef<CompositeModuleInterpreterActor> actorRef
            = TestActorRef.create(moduleInterpretation.getActorSystem(), props);
        // Verify start message
        TestProbe eventProbe = moduleInterpretation.getEventProbe();
        BeginExecutionTraceEvent beginExecutionTraceEvent
            = eventProbe.expectMsgClass(BeginExecutionTraceEvent.class);
        LocalInterpreterProperties localInterpreterProperties
            = moduleInterpretation.getLocalInterpreterProperties();
        Assert.assertEquals(
            beginExecutionTraceEvent,
            BeginExecutionTraceEvent.of(
                localInterpreterProperties.getExecutionId(),
                beginExecutionTraceEvent.getTimestamp(),
                moduleInterpretation.getStagingArea().getAnnotatedExecutionTrace()
            )
        );
        Assert.assertTrue(timestampLowerBound <= beginExecutionTraceEvent.getTimestamp()
            && beginExecutionTraceEvent.getTimestamp() <= System.currentTimeMillis());
        Assert.assertFalse(eventProbe.msgAvailable());
        // Verify that the submodule interpreter has not yet been started (pending the check whether the out-port
        // "r" already has a value). Then process events so that the ComputeResumeState algorithm finishes. Verify
        // that the submodule interpreter has been started then.
        CompositeModuleInterpreterActor actor = actorRef.underlyingActor();
        int dId = submodule(moduleInterpretation, "d").getIndex();
        Assert.assertNull(actor.getChildExecutor(dId));
        moduleInterpretation.getAsyncTaskExecutor().executeAll();
        Assert.assertNotNull(actor.getChildExecutor(dId));
        // Verify EndExecutionTraceEvent message in case that actor is stopped abruptly
        actorRef.stop();
        EndExecutionTraceEvent endExecutionTraceEvent = eventProbe.expectMsgClass(EndExecutionTraceEvent.class);
        Assert.assertEquals(
            endExecutionTraceEvent,
            EndExecutionTraceEvent.of(
                localInterpreterProperties.getExecutionId(),
                endExecutionTraceEvent.getTimestamp(),
                moduleInterpretation.getStagingArea().getAnnotatedExecutionTrace(),
                false
            )
        );
        Assert.assertTrue(beginExecutionTraceEvent.getTimestamp() <= endExecutionTraceEvent.getTimestamp()
            && endExecutionTraceEvent.getTimestamp() <= System.currentTimeMillis());
        Assert.assertFalse(eventProbe.msgAvailable());
    }
}