final CountDownLatch signalCheckpointed = new CountDownLatch(1);
        CoreTestUtils.watchAndSignalCreation("/checkpointed", signalCheckpointed, zk);
        Injector injector = CoreTestUtils.createInjectorWithNonFailFastZKClients();
        TCPEmitter emitter = injector.getInstance(TCPEmitter.class);
        Event event = new Event();
        event.put("command", String.class, "setValue1");
        event.put("value", String.class, "message1");
        emitter.send(0, new EventMessage("-1", "inputStream", injector.getInstance(SerializerDeserializer.class)
                .serialize(event)));
        if (manualCheckpointing) {
            insertCheckpointInstruction(injector, emitter);
        }
        Assert.assertTrue(signalCheckpointed.await(10, TimeUnit.SECONDS));
        forkedS4App.destroy();
        zk.delete("/data", -1);
        signalConsumerReady = getConsumerReadySignal("inputStream");
        forkedS4App = CoreTestUtils.forkS4Node(new String[] { "-c", "cluster1", "-appClass",
                S4AppWithManualCheckpointing.class.getName(), "-extraModulesClasses", backendModuleClass.getName() });
        Assert.assertTrue(signalConsumerReady.await(20, TimeUnit.SECONDS));
        // // trigger recovery by sending application event to set value 2
        CountDownLatch signalValue2Set = new CountDownLatch(1);
        CoreTestUtils.watchAndSignalCreation("/value2Set", signalValue2Set, zk);
        event = new Event();
        event.put("command", String.class, "setValue2");
        event.put("value", String.class, "message2");
        emitter.send(0, new EventMessage("-1", "inputStream", injector.getInstance(SerializerDeserializer.class)
                .serialize(event)));
        Assert.assertTrue(signalValue2Set.await(10, TimeUnit.SECONDS));
        Assert.assertEquals(expectedFinalResult, new String(zk.getData("/data", false, null)));