package com.yahoo.dtf.junit;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import org.junit.BeforeClass;
import org.junit.Test;
import junit.framework.JUnit4TestAdapter;
import junit.framework.TestCase;
import com.yahoo.dtf.DTFConstants;
import com.yahoo.dtf.DTFNode;
import com.yahoo.dtf.actions.Action;
import com.yahoo.dtf.recorder.Attribute;
import com.yahoo.dtf.exception.DTFException;
import com.yahoo.dtf.exception.StorageException;
import com.yahoo.dtf.query.QueryFactory;
import com.yahoo.dtf.query.QueryIntf;
import com.yahoo.dtf.recorder.Event;
import com.yahoo.dtf.recorder.RecorderBase;
import com.yahoo.dtf.recorder.RecorderFactory;
import com.yahoo.dtf.storage.StorageFactory;
/**
* Event Suite takes care of validating that any recorder or query created is
* valid and behaves in accordance with the way the recorder/query tags are
* suppose to work with eachother.
*
* The tests involve validating that any event recorded can always be read back
* as well as the performance of recording small events vs large events.
*
* @author rlgomes
*/
public class EventSuite extends DTFJUnitTest {
@BeforeClass
public static void startUpNode() throws StorageException {
System.setProperty("dtf.node.type", "dtfa");
System.setProperty("dtf.node.name", "dummy");
try {
DTFNode.init();
} catch (DTFException e) {
e.printStackTrace();
TestCase.fail("Unable to initialize DTF teststack.");
}
checkAndCreateJunitStorage();
}
private static void checkAndCreateJunitStorage() throws StorageException {
StorageFactory sf = Action.getStorageFactory();
String tmp = System.getProperty("java.io.tmpdir");
if ( !sf.checkStorage("JUNIT") ) {
String junitoutput = tmp + File.separatorChar + "junit";
Action.getStorageFactory().createStorage("JUNIT",junitoutput,false);
}
}
/**
* Validate that for all recorders that have equivalent query mechanism
* that you can store and retrieve an event correctly.
*
* @throws DTFException
*/
@Test(timeout=600000)
public void simpleRecordAndQuery() throws DTFException {
ArrayList<String> recorders = RecorderFactory.getRecorderNames();
ArrayList<String> queries = QueryFactory.getQueryNames();
try {
for (int r = 0; r < recorders.size(); r++) {
String name = recorders.get(r);
// skip the console and object recorders.
if ( name.equals("object") || name.equals("console") )
continue;
// skip those that don't have the query counterpart ready.
if ( !queries.contains(name) )
continue;
URI uri = new URI("storage://JUNIT/events_" + name + ".txt");
getLogger().info("Validating recorder [" + name + "]");
RecorderBase recorder =
RecorderFactory.getRecorder(name,
uri,
false,
DTFConstants.DEFAULT_ENCODING);
recorder.start();
try {
for (int i = 0; i < 1000; i++) {
Event event = new Event("test.event");
event.start();
event.stop();
event.addAttribute("iteration", i);
recorder.record(event);
}
} finally {
recorder.stop();
}
QueryIntf query = QueryFactory.getQuery(name);
query.open(uri, null, null, "test.event", null);
try {
for (int i = 0; i < 1000; i++) {
HashMap<String, String> result = query.next(false);
long iteration = Long.valueOf(result.get("test.event.iteration"));
if ( iteration != i )
throw new DTFException("Events should be returned in the same order :(");
}
if ( query.next(false) != null )
throw new DTFException("There shouldn't be any more results.");
} finally {
query.close();
}
}
} catch (URISyntaxException e) {
throw new DTFException("Bad URI.",e);
}
}
@Test(timeout=600000)
public void smallEventsRecordQueryPerformance() throws DTFException {
ArrayList<String> recorders = RecorderFactory.getRecorderNames();
ArrayList<String> queries = QueryFactory.getQueryNames();
long iterations = getConfig().getPropertyAsInt("iterations",200000);
try {
for (int r = 0; r < recorders.size(); r++) {
String name = recorders.get(r);
// skip the console and object recorders.
if ( name.equals("object") || name.equals("console") )
continue;
URI uri = new URI("storage://JUNIT/events_" + name + ".txt");
RecorderBase recorder =
RecorderFactory.getRecorder(name,
uri,
false,
DTFConstants.DEFAULT_ENCODING);
recorder.start();
try {
long start = System.currentTimeMillis();
for (long i = 0; i < iterations; i++) {
Event event = new Event("test.event");
event.start();
event.stop();
event.addAttribute("iteration", i);
recorder.record(event);
}
long stop = System.currentTimeMillis();
double duration = (stop-start)/1000.0f;
long ops_per_sec = (long)(iterations/duration);
getLogger().info("Record [" + name + "] Op/sec: " + ops_per_sec);
} finally {
recorder.stop();
}
if ( !queries.contains(name) ) {
getLogger().warn("No query handler for [" + name + "]");
continue;
}
QueryIntf query = QueryFactory.getQuery(name);
query.open(uri, null, null, "test.event", null);
try {
long start = System.currentTimeMillis();
for (long i = 0; i < iterations; i++) {
query.next(false);
}
long stop = System.currentTimeMillis();
double duration = (stop-start)/1000.0f;
long ops_per_sec = (long)(iterations/duration);
getLogger().info("Query [" + name + "] Op/sec: " + ops_per_sec);
} finally {
query.close();
}
}
} catch (URISyntaxException e) {
throw new DTFException("Bad URI.",e);
}
}
@Test(timeout=600000)
public void largeEventsRecordQueryPerformance() throws DTFException {
ArrayList<String> recorders = RecorderFactory.getRecorderNames();
ArrayList<String> queries = QueryFactory.getQueryNames();
long iterations = getConfig().getPropertyAsInt("iterations",20000);
try {
for (int r = 0; r < recorders.size(); r++) {
String name = recorders.get(r);
// skip the console and object recorders.
if ( name.equals("object") || name.equals("console") )
continue;
URI uri = new URI("storage://JUNIT/events_" + name + ".txt");
RecorderBase recorder =
RecorderFactory.getRecorder(name,
uri,
false,
DTFConstants.DEFAULT_ENCODING);
StringBuffer data = new StringBuffer();
for (int i = 0; i < 5*1024; i++)
data.append("X");
Event moch = new Event("test.event");
moch.addAttribute("timestamp", System.currentTimeMillis());
moch.addAttribute("data1", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
moch.addAttribute("data2", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
moch.addAttribute("data3", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
moch.addAttribute("bigdata", data.toString());
long length = 0;
ArrayList<Attribute> attribs = moch.findActions(Attribute.class);
for (int i = 0; i < attribs.size(); i++) {
Attribute attrib = attribs.get(i);
length += attrib.getName().length() + attrib.getValue().length();
}
getLogger().info("Event size " + length + " bytes.");
recorder.start();
try {
long start = System.currentTimeMillis();
for (long i = 0; i < iterations; i++) {
Event event = new Event("test.event");
event.start();
event.addAttribute("iteration", i);
event.addActions(moch.children());
event.stop();
recorder.record(event);
}
long stop = System.currentTimeMillis();
double duration = (stop-start)/1000.0f;
long ops_per_sec = (long)(iterations/duration);
long mb_per_sec = (length * ops_per_sec)/(1024*1024);
getLogger().info("Record [" + name + "] Op/sec: " + ops_per_sec);
getLogger().info("Record [" + name + "] MB/sec: " + mb_per_sec);
} finally {
recorder.stop();
}
if ( !queries.contains(name) ) {
getLogger().warn("No query handler for [" + name + "]");
continue;
}
QueryIntf query = QueryFactory.getQuery(name);
query.open(uri, null, null, "test.event", null);
try {
long start = System.currentTimeMillis();
for (long i = 0; i < iterations; i++) {
query.next(false);
}
long stop = System.currentTimeMillis();
double duration = (stop-start)/1000.0f;
long ops_per_sec = (long)(iterations/duration);
long mb_per_sec = (length * ops_per_sec)/(1024*1024);
getLogger().info("Query [" + name + "] Op/sec: " + ops_per_sec);
getLogger().info("Query [" + name + "] MB/sec: " + mb_per_sec);
} finally {
query.close();
}
}
} catch (URISyntaxException e) {
throw new DTFException("Bad URI.",e);
}
}
public static junit.framework.Test suite() {
return new JUnit4TestAdapter(EventSuite.class);
}
}