package streamcruncher.test.func.generic;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.List;
import org.testng.Assert;
import streamcruncher.api.artifact.RowSpec;
import streamcruncher.api.artifact.RowSpec.Info;
import streamcruncher.test.func.BatchResult;
import streamcruncher.test.func.MultiStreamEventGenerator;
/*
* Author: Ashwin Jayaprakash Date: Jul 17, 2007 Time: 6:24:04 PM
*/
/**
* <p>
* This example demonstrates a scenario where there are 3 Event Streams. An
* Event from Stream 1 must be followed by an Event from Stream 2 and 3 within 5
* seconds of occurence of the Stream 1 Event. Stream 2 & 3 Events can arrive in
* any order. But they must arrive after Stream 1's Event.
* </p>
*/
public abstract class ThreeEventOrderTest extends MultiStreamEventGenerator {
@Override
protected Event[] createEventArray() {
return new Event[] {
// Timestamp column will be filled later.
// All 3 together.
new Event(EventType.stg1_event, new Object[] { "One", "Hello", null, 100L }, 3),
new Event(EventType.stg2_event, new Object[] { "Two", "Hi", null, 100L }, 3),
new Event(EventType.stg3_event, new Object[] { "Three", "Howdy", null, 100L }, 3),
new Event(EventType.pause, new Object[] { 2500L }, -1),
// 1 & 2 together. 3 is very late.
new Event(EventType.stg1_event, new Object[] { "One", "Hello", null, 200L }, 3),
new Event(EventType.stg2_event, new Object[] { "Two", "Hi", null, 200L }, 3),
new Event(EventType.pause, new Object[] { 5200L }, -1),
new Event(EventType.stg3_event, new Object[] { "Three", "Howdy", null, 200L }, 3),
new Event(EventType.pause, new Object[] { 2500L }, -1),
// 2 & 3 together. 1 is very late.
new Event(EventType.stg2_event, new Object[] { "Two", "Hi", null, 300L }, 3),
new Event(EventType.stg3_event, new Object[] { "Three", "Howdy", null, 300L }, 3),
new Event(EventType.pause, new Object[] { 5200L }, -1),
new Event(EventType.stg1_event, new Object[] { "One", "Hello", null, 300L }, 3),
new Event(EventType.pause, new Object[] { 2500L }, -1),
// 1 comes first. 2 & 3 together, later.
new Event(EventType.stg1_event, new Object[] { "One", "Hello", null, 400L }, 3),
new Event(EventType.pause, new Object[] { 3000L }, -1),
new Event(EventType.stg2_event, new Object[] { "Two", "Hi", null, 400L }, 3),
new Event(EventType.stg3_event, new Object[] { "Three", "Howdy", null, 400L }, 3),
new Event(EventType.pause, new Object[] { 2500L }, -1),
// 1 comes first, 2 comes later. 3 never comes
new Event(EventType.stg1_event, new Object[] { "One", "Hello", null, 500L }, 3),
new Event(EventType.pause, new Object[] { 2500L }, -1),
new Event(EventType.stg2_event, new Object[] { "Two", "Hi", null, 500L }, 3),
new Event(EventType.pause, new Object[] { 2500L }, -1),
// 2 comes first, 3 comes later. 1 comes after 3.
new Event(EventType.stg2_event, new Object[] { "Two", "Hi", null, 600L }, 3),
new Event(EventType.pause, new Object[] { 1500L }, -1),
new Event(EventType.stg3_event, new Object[] { "Three", "Howdy", null, 600L }, 3),
new Event(EventType.pause, new Object[] { 1500L }, -1),
new Event(EventType.stg1_event, new Object[] { "One", "Hello", null, 600L }, 3),
new Event(EventType.pause, new Object[] { 2500L }, -1),
// 1 comes first, 3 comes later. 2 comes after 3.
new Event(EventType.stg1_event, new Object[] { "One", "Hello", null, 700L }, 3),
new Event(EventType.pause, new Object[] { 1500L }, -1),
new Event(EventType.stg3_event, new Object[] { "Three", "Howdy", null, 700L }, 3),
new Event(EventType.pause, new Object[] { 1500L }, -1),
new Event(EventType.stg2_event, new Object[] { "Two", "Hi", null, 700L }, 3),
new Event(EventType.pause, new Object[] { 2500L }, -1),
// 1 comes first, 2 comes later. 3 comes soon after 2.
new Event(EventType.stg1_event, new Object[] { "One", "Hello", null, 800L }, 3),
new Event(EventType.pause, new Object[] { 1000L }, -1),
new Event(EventType.stg2_event, new Object[] { "Two", "Hi", null, 800L }, 3),
new Event(EventType.pause, new Object[] { 250L }, -1),
new Event(EventType.stg3_event, new Object[] { "Three", "Howdy", null, 800L }, 3)
// End test data.
};
}
@Override
protected String[] getResultColumnTypes() {
return new String[] { java.lang.Long.class.getName(), java.sql.Timestamp.class.getName(),
java.lang.Long.class.getName(), java.sql.Timestamp.class.getName(),
java.lang.Long.class.getName(), java.sql.Timestamp.class.getName() };
}
@Override
protected String[] getStage1ColumnTypes() {
return new String[] { RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 10),
RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 10),
java.sql.Timestamp.class.getName(), java.lang.Long.class.getName() };
}
@Override
protected String[] getStage2ColumnTypes() {
return new String[] { RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 10),
RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 10),
java.sql.Timestamp.class.getName(), java.lang.Long.class.getName() };
}
@Override
protected String[] getStage3ColumnTypes() {
return new String[] { RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 10),
RowSpec.addInfo(java.lang.String.class.getName(), Info.SIZE, 10),
java.sql.Timestamp.class.getName(), java.lang.Long.class.getName() };
}
@Override
protected String[] getResultColumnNames() {
return new String[] { "stg1_id", "stg1_time", "stg2_id", "stg2_time", "stg3_id",
"stg3_time" };
}
@Override
protected String getRQLColumnsCSV() {
String[] columns = getResultColumnNames();
String csv = "";
for (int i = 0; i < columns.length; i++) {
if (csv != "") {
csv = csv + ", ";
}
csv = csv + columns[i];
}
return csv;
}
@Override
protected String getRQL() {
String csv = getRQLColumnsCSV();
String query = "select "
+ csv
+ "\n\n from"
// The columns to spit out.
+ "\n alert one_event.event_id as stg1_id, one_event.event_time as stg1_time,"
+ " two_event.event_id as stg2_id, two_event.event_time as stg2_time,"
+ " three_event.event_id as stg3_id, three_event.event_time as stg3_time"
// The source of the Events.
+ "\n\n using stg1_event (partition store last 5 seconds) as one_event correlate on event_id,"
+ " stg2_event (partition store last 5 seconds) as two_event correlate on event_id,"
+ " stg3_event (partition store last 5 seconds) as three_event correlate on event_id"
/*
* The Conditions that the Query is supposed to watch for. All 3
* Events must arrive within the Window.
*/
+ "\n\n when present(one_event and two_event and three_event)" +
// Post filtering: Stage 1 comes before Stage 2 & 3.
"\n\n where stg1_time < stg2_time and stg1_time < stg3_time;";
System.out.println("========== Query ==========");
System.out.println(query);
System.out.println("===========================");
return query;
}
@Override
protected void verify(List<BatchResult> results) {
HashSet<String> expectedResults = new HashSet<String>();
expectedResults.add("400 400 400");
expectedResults.add("700 700 700");
expectedResults.add("800 800 800");
System.out.println("--Results--");
for (BatchResult result : results) {
System.out.println("Batch created at: " + new Timestamp(result.getTimestamp())
+ ". Rows: " + result.getRows().size());
List<Object[]> rows = result.getRows();
System.out.println(" Batch results");
for (Object[] objects : rows) {
System.out.print(" ");
for (Object object : objects) {
System.out.print(object + " ");
}
/*
* "stg1_id", "stg1_time", "stg2_id", "stg2_time", "stg3_id",
* "stg3_time".
*/
Long stg1Id = objects[0] == null ? null : ((Number) objects[0]).longValue();
Timestamp stg1TS = objects[1] == null ? null : ((Timestamp) objects[1]);
Long stg2Id = objects[2] == null ? null : ((Number) objects[2]).longValue();
Timestamp stg2TS = objects[3] == null ? null : ((Timestamp) objects[3]);
Long stg3Id = objects[4] == null ? null : ((Number) objects[4]).longValue();
Timestamp stg3TS = objects[5] == null ? null : ((Timestamp) objects[5]);
String hash = stg1Id + " " + stg2Id + " " + stg3Id;
boolean exists = expectedResults.remove(hash);
if (exists == false) {
/*
* Sometimes the Stage 1 of the first Event set(Id: 100)
* reaches the Kernel very quickly, even though all 3 are
* sent almost simultaneously. So, this is excusable.
*/
Assert.assertEquals(hash, "100 100 100", "Only Event Id set 100 can arrive");
exists = true;
}
Assert.assertTrue(exists, "Pattern " + hash + " does not match expected results");
Assert.assertTrue((stg1TS.getTime() < stg2TS.getTime()),
"Stage 2 arrived before/with Stage 1");
Assert.assertTrue((stg1TS.getTime() < stg3TS.getTime()),
"Stage 3 arrived before/with Stage 1");
System.out.println();
}
}
Assert.assertEquals(expectedResults.size(), 0, "All expected Patterns did not arrive");
}
}