package org.marketcetera.module;
import org.marketcetera.util.misc.ClassVersion;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
import static org.junit.Assert.*;
import javax.management.JMX;
import java.lang.management.ManagementFactory;
import java.util.Map;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.math.BigInteger;
import java.math.BigDecimal;
/* $License$ */
/**
* Tests sink module features.
*
* @author anshul@marketcetera.com
*/
@ClassVersion("$Id: SinkModuleTest.java 16154 2012-07-14 16:34:05Z colin $")
public class SinkModuleTest extends ModuleTestBase {
@BeforeClass
public static void setup() throws Exception {
sManager = new ModuleManager();
sManager.init();
sSinkBean = JMX.newMXBeanProxy(
ManagementFactory.getPlatformMBeanServer(),
SinkModuleFactory.INSTANCE_URN.toObjectName(),
SinkModuleMXBean.class);
}
@AfterClass
public static void cleanup() throws Exception {
sManager.stop();
}
/**
* Tests sink module reset feature.
*
* @throws Exception if there were unexpected errors.
*/
@Test
public void reset() throws Exception {
sSinkBean.resetStats();
Map<DataFlowID,Integer> flowStats = sSinkBean.getDataFlowStats();
assertTrue(flowStats.toString(), flowStats.isEmpty());
Map<String, Integer> typeStats = sSinkBean.getTypeStats();
assertTrue(typeStats.toString(), typeStats.isEmpty());
}
/**
* Tests sink module functionality within a data flow.
*
* @throws Exception if there were unexpected errors.
*/
@Test
public void flow() throws Exception {
Sink sink1 = new Sink();
//Get sink1 to throw exceptions to verify that any exceptions
//thrown by it are ignored and do not affect delivery to other
//listeners.
sink1.setThrowException(true);
Sink sink2 = new Sink();
Sink sink3 = new Sink();
sManager.addSinkListener(sink1);
sManager.addSinkListener(sink2);
sManager.addSinkListener(sink3);
assertTrue(sManager.removeSinkListener(sink2));
assertFalse(sManager.removeSinkListener(sink2));
Object[] data = new Object[]{
(byte)123,
'e',
(short)3432,
543423,
3423.43f,
34324239849l,
4323422.342343,
new Date(),
new BigInteger("34234234234234"),
new BigDecimal("23423423432690809.234890734"),
"This is a test string",
true,
false
};
ModuleURN procURN = new ModuleURN(ProcessorModuleFactory.PROVIDER_URN,
"sink");
sManager.start(EmitterModuleFactory.INSTANCE_URN);
final DataRequest[] requests = {
new DataRequest(EmitterModuleFactory.INSTANCE_URN, data),
new DataRequest(procURN, "passThru")
};
DataFlowID flowID = sManager.createDataFlow(requests);
//wait for the data to reach the first listener
sink1.waitUntilTerminator();
sManager.cancel(flowID);
//verify that the listener that was removed didn't receive any data
assertEquals(0, sink2.getData().length);
//verify the data received by each of the listeners
verify(flowID, data, sink1.getData());
verify(flowID, data, sink3.getData());
verifyJMXStats(data, flowID);
sink1.clear();
sink3.clear();
sSinkBean.resetStats();
//now remove the other and carry out the data flow again
sManager.removeSinkListener(sink3);
flowID = sManager.createDataFlow(requests);
sink1.waitUntilTerminator();
sManager.cancel(flowID);
assertEquals(0, sink2.getData().length);
assertEquals(0, sink3.getData().length);
verify(flowID, data, sink1.getData());
verifyJMXStats(data, flowID);
}
/**
* Tests {@link BlockingSinkDataListener}.
*
* @throws Exception if there was an error.
*/
@Test(timeout = 10000)
public void blockingSinkListenerTest() throws Exception {
final BlockingSinkDataListener listener = new BlockingSinkDataListener();
assertEquals(0 ,listener.size());
final List<Object> list = new ArrayList<Object>();
Thread thread = new Thread("testThread"){
@Override
public void run() {
try {
list.add(listener.getNextData());
} catch (InterruptedException ignore) {
}
}
};
thread.start();
//wait until thread is blocked
while(thread.getState() != Thread.State.WAITING) {
Thread.sleep(1000);
}
assertTrue(list.isEmpty());
//Add an item to the listener
Object data = "data";
listener.receivedData(null, data);
//wait for the thread to terminate
while(thread.getState() != Thread.State.TERMINATED) {
Thread.sleep(1000);
}
//verify that the data is received.
assertFalse(list.toString(), list.isEmpty());
assertEquals(1, list.size());
assertEquals(data, list.get(0));
assertEquals(0 ,listener.size());
//Now test it with the sink
sManager.addSinkListener(listener);
DataFlowID flowID = sManager.createDataFlow(new DataRequest[]{
new DataRequest(CopierModuleFactory.INSTANCE_URN, data)
});
//wait until the data is received
assertEquals(data, listener.getNextData());
//Terminate the data flow
sManager.cancel(flowID);
sManager.removeSinkListener(listener);
}
private void verifyJMXStats(Object[] inData, DataFlowID inFlowID) {
Map<DataFlowID, Integer> flowStats = sSinkBean.getDataFlowStats();
assertEquals(1, flowStats.size());
assertEquals(inData.length, (int)flowStats.get(inFlowID));
Map<String, Integer> typeStats = sSinkBean.getTypeStats();
assertEquals(inData.length - 1 , typeStats.size());
for(String c: typeStats.keySet()) {
assertEquals(c,
Boolean.class.getName().equals(c)
? 2
: 1,
(int)typeStats.get(c));
}
}
private void verify(DataFlowID inID, Object[] inExpected, FlowData[] inData) {
assertEquals(inExpected.length - 1, inData.length);
for(int i = 0; i < inData.length; i++) {
assertEquals(inID, inData[i].getFirstMember());
assertEquals(inExpected[i], inData[i].getSecondMember());
}
}
private static ModuleManager sManager;
private static SinkModuleMXBean sSinkBean;
}