/*
* StreamCruncher: Copyright (c) 2006-2008, Ashwin Jayaprakash. All Rights Reserved.
* Contact: ashwin {dot} jayaprakash {at} gmail {dot} com
* Web: http://www.StreamCruncher.com
*
* This file is part of StreamCruncher.
*
* StreamCruncher is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* StreamCruncher is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with StreamCruncher. If not, see <http://www.gnu.org/licenses/>.
*/
package streamcruncher.test.func;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import streamcruncher.api.InputSession;
import streamcruncher.api.OutputSession;
import streamcruncher.api.ParsedQuery;
import streamcruncher.api.ParserParameters;
import streamcruncher.api.QueryConfig;
import streamcruncher.api.StreamCruncher;
import streamcruncher.api.StreamCruncherException;
import streamcruncher.api.QueryConfig.QuerySchedulePolicy;
import streamcruncher.api.artifact.RowSpec;
/*
* Author: Ashwin Jayaprakash Date: Sep 10, 2006 Time: 4:18:54 PM
*/
/**
* <p>
* Test Case parent Class for single Stream Tests. It generates Orders using
* random values.
* </p>
* <p>
* <b>Note:</b> Some of the "Time based Window" Tests may fail occassionally,
* because the expiry times of Events and hence the expected results are
* dependent on the Hardware's performance. A slight delay in scheduling the
* Query might cause the Test case to fail. In such cases, try running the Test
* again or correct the expected behaviour.
* </p>
*/
public abstract class OrderGenenerator {
protected StreamCruncher cruncher;
protected OrderGenenerator() {
cruncher = new StreamCruncher();
}
protected void init() throws Exception {
String[] columnNames = { "country", "state", "city", "item_sku", "item_qty", "order_time",
"order_id" };
String[] columnTypes = getColumnTypes();
RowSpec rowSpec = new RowSpec(columnNames, columnTypes, 6, 5);
cruncher.registerInStream("test", rowSpec, 4096);
// ---------
beforeQueryParse();
// ---------
String rql = getRQL();
columnTypes = getResultColumnTypes();
String queryName = "test_res_rql";
ParserParameters parameters = new ParserParameters();
parameters.setQuery(rql);
parameters.setQueryName(queryName);
parameters.setResultColumnTypes(columnTypes);
ParsedQuery parsedQuery = cruncher.parseQuery(parameters);
QueryConfig config = parsedQuery.getQueryConfig();
config.setQuerySchedulePolicy(new QueryConfig.QuerySchedulePolicyValue(
QuerySchedulePolicy.ATLEAST_OR_SOONER, Integer.MAX_VALUE));
modifyQueryConfig(config);
cruncher.registerQuery(parsedQuery);
}
protected void beforeQueryParse() {
}
protected void modifyQueryConfig(QueryConfig config) {
}
protected abstract String[] getColumnTypes();
protected abstract String getRQL();
protected abstract String[] getResultColumnNames();
protected abstract String[] getResultColumnTypes();
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;
}
protected int getMaxDataRows() {
return 30;
}
protected static class Node {
protected final String name;
protected Node[] children;
protected final boolean leaf;
public Node(String name, Node[] children, boolean leaf) {
this.name = name;
this.children = children;
this.leaf = leaf;
}
public String getName() {
return name;
}
public void setChildren(Node[] children) {
this.children = children;
}
public Node[] getChildren() {
return children;
}
public boolean isLeaf() {
return leaf;
}
}
protected Iterator<Object[]> getData() {
Iterator<Object[]> iter = new Iterator<Object[]>() {
private final Random random = new Random();
private final Node[] countries = init();
private final String[] itemSKUs = { "warp-drive", "force-field", "eva-suit" };
private int counter = 1;
public boolean hasNext() {
return counter <= getMaxDataRows();
}
private Node[] init() {
Node country1 = new Node("US", null, false);
Node state1 = new Node("California", null, false);
Node city1 = new Node("San Jose", null, true);
Node city2 = new Node("San Francisco", null, true);
Node city3 = new Node("San Diego", null, true);
state1.setChildren(new Node[] { city1, city2, city3 });
Node state2 = new Node("New York", null, false);
city1 = new Node("Brooklyn", null, true);
city2 = new Node("New York City", null, true);
city3 = new Node("Buffalo", null, true);
state2.setChildren(new Node[] { city1, city2, city3 });
Node state3 = new Node("Florida", null, false);
city1 = new Node("Jacksonville", null, true);
city2 = new Node("Miami", null, true);
city3 = new Node("Orlando", null, true);
state3.setChildren(new Node[] { city1, city2, city3 });
country1.setChildren(new Node[] { state1, state2, state3 });
Node country2 = new Node("India", null, false);
state1 = new Node("Karnataka", null, false);
city1 = new Node("Bangalore", null, true);
city2 = new Node("Mangalore", null, true);
city3 = new Node("Mysore", null, true);
state1.setChildren(new Node[] { city1, city2, city3 });
state2 = new Node("Maharashtra", null, false);
city1 = new Node("Mumbai", null, true);
city2 = new Node("Pune", null, true);
state2.setChildren(new Node[] { city1, city2 });
state3 = new Node("Delhi", null, false);
city1 = new Node("Delhi", null, true);
state3.setChildren(new Node[] { city1 });
country2.setChildren(new Node[] { state1, state2, state3 });
Node country3 = new Node("China", null, false);
state1 = new Node("Shanghai", null, false);
city1 = new Node("Shanghai", null, true);
state1.setChildren(new Node[] { city1 });
state2 = new Node("Tibet", null, false);
city1 = new Node("Lhasa", null, true);
state2.setChildren(new Node[] { city1 });
state3 = new Node("Hong Kong", null, false);
city1 = new Node("Hong Kong", null, true);
state3.setChildren(new Node[] { city1 });
country3.setChildren(new Node[] { state1, state2, state3 });
return new Node[] { country1, country2, country3 };
}
public Object[] next() {
/*
* "country", "state", "city", "item_sku", "item_qty",
* "order_time", "order_id"
*/
Object[] data = new Object[7];
Node node = countries[random.nextInt(countries.length)];
data[0] = node.getName();
Node[] children = node.getChildren();
node = children[random.nextInt(children.length)];
data[1] = node.getName();
children = node.getChildren();
node = children[random.nextInt(children.length)];
data[2] = node.getName();
data[3] = itemSKUs[random.nextInt(itemSKUs.length)];
data[4] = random.nextInt(50) + 1;
data[5] = new Timestamp(OrderGenenerator.this.getEventTimeStamp(counter));
data[6] = new Long(counter);
System.out.println(Arrays.asList(data));
counter++;
return data;
}
/**
* @throws UnsupportedOperationException
*/
public void remove() {
throw new UnsupportedOperationException();
}
};
return iter;
}
protected List<BatchResult> test() throws Exception {
InputSession inputSession = cruncher.createInputSession("test");
inputSession.start();
generateEvents(inputSession);
OutputSession outputSession = cruncher.createOutputSession("test_res_rql");
List<BatchResult> results = fetchResults(outputSession);
// --------------
verify(results);
return results;
}
protected void generateEvents(InputSession inputSession) throws StreamCruncherException {
Iterator<Object[]> iter = getData();
for (int counter = 0; iter.hasNext();) {
Object[] data = iter.next();
inputSession.submitEvent(data);
counter++;
afterEvent(counter);
}
inputSession.close();
}
protected long getEventTimeStamp(int counter) {
return System.currentTimeMillis();
}
protected void afterEvent(int counter) {
}
/**
* Throw exception to stop waiting.
*
* @param resultsSoFar
* @throws InterruptedException
*/
protected void waitForMoreResults(List<BatchResult> resultsSoFar) throws InterruptedException {
if (resultsSoFar.size() > 0) {
throw new InterruptedException("Timed out!");
}
}
protected List<BatchResult> fetchResults(OutputSession outputSession) throws Exception {
outputSession.start();
int pollTimeSec = 10;
List<BatchResult> results = new LinkedList<BatchResult>();
while (true) {
try {
List<Object[]> events = outputSession.readEvents(pollTimeSec, TimeUnit.SECONDS);
if (events.size() == 0) {
System.err.println("Attempting to retrieve results.");
waitForMoreResults(results);
continue;
}
BatchResult batchResult = new BatchResult();
for (Object[] row : events) {
batchResult.addRow(row);
}
results.add(batchResult);
System.err.println("Got result batch.");
}
catch (InterruptedException e) {
if (pollTimeSec == 10) {
pollTimeSec = 5;
}
else if (pollTimeSec > 1) {
pollTimeSec--;
}
else {
break;
}
System.err.println("Retrying for more results...");
}
}
outputSession.close();
return results;
}
protected abstract void verify(List<BatchResult> results);
protected void discard() {
try {
cruncher.unregisterQuery("test_res_rql");
}
catch (RuntimeException e) {
e.printStackTrace(System.err);
}
try {
cruncher.unregisterInStream("test");
}
catch (StreamCruncherException e) {
e.printStackTrace(System.err);
}
cruncher = null;
}
}