/*
* Author: cbedford
* Date: 10/22/13
* Time: 8:50 PM
*/
import backtype.storm.generated.StormTopology;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
/**
* This test builds on StormKafkaSpoutGetsInputViaAdaptedExternalFeedTest. Our ExternalFeedToKafkaAdapterSpout
* pushes messages into a topic. These messages are then routed into an EsperBolt which uses the Esper query
* language to do some simple filtering, We then route the filtered messages to a KafkaOutputBolt which
* dumps the filtered messages on a second topic. We use an instance of Kafka MessageConsumer to pull those
* messages off the second topic, and we verify that what we got is equal to what we expect.
*/
public class ExternalFeedRoutedToEsperAndThenToKakfaOutputBoltTest extends AbstractStormWithKafkaTest {
public static final int EXPECTED_COUNT = 6;
protected static volatile boolean finishedCollecting = false;
protected static final int MAX_ALLOWED_TO_RUN_MILLISECS = 1000 * 25 /* seconds */;
protected static final int SECOND = 1000;
private final String secondTopic = this.getClass().getSimpleName() + "topic" + getRandomInteger(1000);
private volatile boolean testPassed = true; // assume the best
@BeforeClass
protected void deleteFiles() {
deleteSentinelFile("/tmp/before.storm");
deleteSentinelFile("/tmp/after.storm");
}
private void deleteSentinelFile(String pathname) {
File sentinel = new File(pathname);
sentinel.delete();
if (sentinel.exists()) {
throw new RuntimeException("Could not delete sentinel file");
}
}
@Test
public void runTestWithTopology() throws IOException {
System.out.println("topic: " + getTopicName() + "second topic:" + getSecondTopicName());
//ServerAndThreadCoordinationUtils.pauseUntil("/tmp/before.storm");
submitTopology(); // The last bolt in this topology will write to second topic
//ServerAndThreadCoordinationUtils.pauseUntil("/tmp/after.storm");
Thread verifyThread = setupVerifyThreadToListenOnSecondTopic();
try {
verifyThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!testPassed) {
throw new RuntimeException("Test did not pass. Got messages: ");
}
}
@Override
public String getSecondTopicName() {
return secondTopic;
}
@Override
protected StormTopology createTopology() {
return TopologyInitializer.
createTopology(
getZkConnect(),
BROKER_CONNECT_STRING,
getTopicName(),
getSecondTopicName(),
new TestFeedItemProvider(getTestSentences()), false);
}
protected int getMaxAllowedToRunMillisecs() {
return ExternalFeedRoutedToEsperAndThenToKakfaOutputBoltTest.MAX_ALLOWED_TO_RUN_MILLISECS;
}
private void waitForResultsFromStormKafkaSpoutToAppearInCollectorBolt() {
while (!finishedCollecting) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("DONE");
}
// EXPECTED_COUNT - consumer will see 6 occurrences of cat out of 6 batches of 2
// The shutdown will trigger when we see the first 'cat - SHUTDOWN'. That's why the
// consumer does not see 7 cats.
private String[] getTestSentences() {
return new String[]{
"cat",
"pig",
"pig",
"pig",
"pig",
"cat",
"cat",
"pig",
"cat",
"cat",
"cat - SHUTDOWN",
"cat - SHUTDOWN",
};
}
private Thread setupVerifyThreadToListenOnSecondTopic() {
Thread.UncaughtExceptionHandler uncaughtHandler = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread th, Throwable ex) {
testPassed = false;
}
};
Thread verifyThread = new Thread(
new Runnable() {
@Override
public void run() {
verifyResults(getSecondTopicName(), EXPECTED_COUNT);
}
},
"verifyThread"
);
verifyThread.setUncaughtExceptionHandler(uncaughtHandler);
verifyThread.start();
return verifyThread;
}
}