package org.marketcetera.modules.csv; import org.marketcetera.util.misc.ClassVersion; import org.marketcetera.module.*; import org.marketcetera.core.LoggerConfiguration; import org.junit.Before; import org.junit.BeforeClass; import org.junit.After; import org.junit.Test; import static org.junit.Assert.*; import java.io.File; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.regex.Pattern; import java.net.URL; import java.net.MalformedURLException; /* $License$ */ /** * Tests the {@link CSVEmitter} module. * * @author anshul@marketcetera.com */ @ClassVersion("$Id: EmitterTest.java 16841 2014-02-20 19:59:04Z colin $") //$NON-NLS-1$ public class EmitterTest extends ModuleTestBase { @BeforeClass public static void logSetup() { LoggerConfiguration.logSetup(); } /** * Verifies failures when incorrect request parameters are provided. * * @throws Exception if there were unexpected failures. */ @Test public void invalidRequests() throws Exception { new ExpectedFailure<IllegalRequestParameterValue>( org.marketcetera.module.Messages.ILLEGAL_REQ_PARM_VALUE, CSVEmitterFactory.INSTANCE_URN.toString(), null){ protected void run() throws Exception { mManager.createDataFlow(new DataRequest[]{ new DataRequest(CSVEmitterFactory.INSTANCE_URN,null) }); } }; final Object invalidParam = new Object(); new ExpectedFailure<UnsupportedRequestParameterType>( org.marketcetera.module.Messages.UNSUPPORTED_REQ_PARM_TYPE, CSVEmitterFactory.INSTANCE_URN.toString(), invalidParam.getClass().getName()){ protected void run() throws Exception { mManager.createDataFlow(new DataRequest[]{ new DataRequest(CSVEmitterFactory.INSTANCE_URN,invalidParam) }); } }; } /** * Tests the error when invalid input file is provided. * * @throws Exception if there were unexpected errors. */ @Test(timeout = 60000) public void invalidFile() throws Exception { assertTrue(mManager.getDataFlows(true).isEmpty()); File csv = new File("does/not/exist"); assertFalse(csv.exists()); DataFlowID id = mManager.createDataFlow(new DataRequest[]{ new DataRequest(CSVEmitterFactory.INSTANCE_URN, csv.getAbsolutePath()) }); while(!mManager.getDataFlows(true).isEmpty()) { Thread.sleep(1000); } List<DataFlowInfo> history = mManager.getDataFlowHistory(); assertEquals(1, history.size()); DataFlowInfo info = history.get(0); assertFlowInfo(info, id, 2, true, true, null, CSVEmitterFactory.INSTANCE_URN); DataFlowStep flowStep = info.getFlowSteps()[0]; assertEquals(CSVEmitterFactory.INSTANCE_URN, flowStep.getModuleURN()); assertEquals(true, flowStep.isEmitter()); assertEquals(0, flowStep.getNumEmitted()); assertEquals(1, flowStep.getNumEmitErrors()); Pattern p = Pattern.compile(Messages.UNEXPECTED_ERROR.getText(".*")); assertTrue(flowStep.getLastEmitError(), p.matcher(flowStep.getLastEmitError()).matches()); assertEquals(false, flowStep.isReceiver()); assertEquals(0, flowStep.getNumReceived()); assertEquals(0, flowStep.getNumReceiveErrors()); assertEquals(null, flowStep.getLastReceiveError()); assertEquals(CSVEmitterFactory.INSTANCE_URN, flowStep.getRequest().getRequestURN()); assertEquals(csv.getAbsolutePath(), flowStep.getRequest().getData()); assertFlowStep(info.getFlowSteps()[1], SinkModuleFactory.INSTANCE_URN, false, 0, 0, null, true, 0, 0, null, SinkModuleFactory.INSTANCE_URN, null); } /** * Verifies the failure when there's insufficient input. * * @throws Exception if there were unexpected errors */ @Test(timeout = 60000) public void insufficientInput() throws Exception { assertTrue(INVALID_CSV_FILE.getAbsolutePath(), INVALID_CSV_FILE.exists()); DataFlowID id = mManager.createDataFlow(new DataRequest[]{ new DataRequest(CSVEmitterFactory.INSTANCE_URN, INVALID_CSV_FILE.getAbsolutePath()) }); //wait for data flow to complete while(!mManager.getDataFlows(true).isEmpty()) { Thread.sleep(1000); } List<DataFlowInfo> history = mManager.getDataFlowHistory(); assertEquals(1, history.size()); DataFlowInfo info = history.get(0); assertFlowInfo(info, id, 2, true, true, null, CSVEmitterFactory.INSTANCE_URN); assertFlowStep(info.getFlowSteps()[0], CSVEmitterFactory.INSTANCE_URN, true, 0, 1, Messages.INSUFFICIENT_DATA.getText(1), false, 0, 0, null, CSVEmitterFactory.INSTANCE_URN, INVALID_CSV_FILE.getAbsolutePath()); assertFlowStep(info.getFlowSteps()[1], SinkModuleFactory.INSTANCE_URN, false, 0, 0, null, true, 0, 0, null, SinkModuleFactory.INSTANCE_URN, null); } /** * Verifies a data flow request with a file path string parameter. * * @throws Exception if there unexpected errors. */ @Test(timeout = 60000) public void emitCSVStringFile() throws Exception { assertTrue(VALID_CSV_FILE.getAbsolutePath(), VALID_CSV_FILE.exists()); //verify that creating a URL out of file path fails new ExpectedFailure<MalformedURLException>(){ protected void run() throws Exception { new URL(VALID_CSV_FILE.getAbsolutePath()); } }; //Try the file path checkEmitCSV(VALID_CSV_FILE.getAbsolutePath(), false); } /** * Verifies a reverse data flow request with a file path string parameter. * * @throws Exception if there unexpected errors. */ @Test(timeout = 60000) public void emitCSVStringFileReverse() throws Exception { assertTrue(VALID_CSV_FILE.getAbsolutePath(), VALID_CSV_FILE.exists()); //verify that creating a URL out of file path, with reverse prefix, fails new ExpectedFailure<MalformedURLException>(){ protected void run() throws Exception { new URL(CSVEmitter.PREFIX_REVERSE + VALID_CSV_FILE.getAbsolutePath()); } }; //Try reverse checkEmitCSV(CSVEmitter.PREFIX_REVERSE + VALID_CSV_FILE.getAbsolutePath(), true); } /** * Verifies a data flow request with a URL string parameter. * * @throws Exception if there unexpected errors. */ @Test(timeout = 60000) public void emitCSVStringURL() throws Exception { assertTrue(VALID_CSV_FILE.getAbsolutePath(), VALID_CSV_FILE.exists()); //Try the URL checkEmitCSV(VALID_CSV_FILE.toURI().toURL().toString(), false); } /** * Verifies a reverse data flow request with a URL string parameter. * * @throws Exception if there unexpected errors. */ @Test(timeout = 60000) public void emitCSVStringURLReverse() throws Exception { assertTrue(VALID_CSV_FILE.getAbsolutePath(), VALID_CSV_FILE.exists()); //Try reverse checkEmitCSV(CSVEmitter.PREFIX_REVERSE + VALID_CSV_FILE.toURI(). toURL().toString(), true); } /** * Verifies a data flow request with a File parameter. * * @throws Exception if there are unexpected errors. */ @Test(timeout = 60000) public void emitCSVFile() throws Exception { assertTrue(VALID_CSV_FILE.getAbsolutePath(), VALID_CSV_FILE.exists()); checkEmitCSV(VALID_CSV_FILE, false); } /** * Verifies a data flow request with a URL parameter. * * @throws Exception if there are unexpected errors. */ @Test(timeout = 60000) public void emitCSVURL() throws Exception { assertTrue(VALID_CSV_FILE.getAbsolutePath(), VALID_CSV_FILE.exists()); checkEmitCSV(VALID_CSV_FILE.toURI().toURL(), false); } /** * Verifies the provider and module infos. * * @throws Exception if there were unexpected errors */ @Test public void info() throws Exception { assertProviderInfo(mManager, CSVEmitterFactory.PROVIDER_URN, new String[0], new Class[0], Messages.PROVIDER_DESCRIPTION.getText(),false, false); assertModuleInfo(mManager, CSVEmitterFactory.INSTANCE_URN, ModuleState.STARTED, null, null, false, true, false, true, false); } @Before public void setup() throws Exception { mManager = new ModuleManager(); mManager.init(); } @After public void cleanup() throws Exception { mManager.stop(); mManager = null; } /** * Runs a data flow with the supplied request parameter and verifies * that data is correctly emitted by the csv emitter. * * @param inRequestParam the request parameter to the emitter. * * @param inReverse if the data flow is expected to emit data in reverse. * @throws Exception if there were errors */ private void checkEmitCSV(Object inRequestParam, boolean inReverse) throws Exception { assertTrue(mManager.getDataFlows(true).isEmpty()); FirstAndLastTracker tracker = new FirstAndLastTracker(); mManager.addSinkListener(tracker); DataFlowID flowID = mManager.createDataFlow(new DataRequest[]{ new DataRequest(CSVEmitterFactory.INSTANCE_URN, inRequestParam) }); //Wait until data flow ends as we cannot deterministically test //data flow status while it's active. while(!mManager.getDataFlows(true).isEmpty()) { Thread.sleep(1000); } List<DataFlowInfo> history = mManager.getDataFlowHistory(); assertEquals(1, history.size()); DataFlowInfo info = history.get(0); assertFlowInfo(info, flowID, 2, true, true, null, CSVEmitterFactory.INSTANCE_URN); assertFlowStep(info.getFlowSteps()[0], CSVEmitterFactory.INSTANCE_URN, true, NUM_ROWS, 1, Messages.NO_MORE_DATA.getText(), false, 0, 0, null, CSVEmitterFactory.INSTANCE_URN, inRequestParam.toString()); assertFlowStep(info.getFlowSteps()[1], SinkModuleFactory.INSTANCE_URN, false, 0, 0, null, true, NUM_ROWS, 0, null, SinkModuleFactory.INSTANCE_URN, null); assertNotNull(tracker.getFirst()); assertTrue(tracker.getFirst() instanceof Map); assertEquals(createMap("2008-10-02","16.77","16.85","15.54", "15.58","23416200","15.58"),inReverse? tracker.getLast(): tracker.getFirst()); assertNotNull(tracker.getLast()); assertTrue(tracker.getLast() instanceof Map); assertEquals(createMap("1996-04-12","25.25","43.00","24.50", "33.00","408720000","1.38"),inReverse? tracker.getFirst(): tracker.getLast()); } /** * Creates a map with expected key value pairs in the test csv file. * * @return the map with expected key value pairs. */ private Map<String,String> createMap(String inDate, String inOpen, String inHigh, String inLow, String inClose, String inVolume, String inAdjClose) { Map<String,String> map = new HashMap<String,String>(); map.put("Date",inDate); map.put("Open",inOpen); map.put("High",inHigh); map.put("Low",inLow); map.put("Close",inClose); map.put("Volume",inVolume); map.put("Adj Close",inAdjClose); return map; } /** * A listener that tracks the first and the last objects that it * receives. */ private static class FirstAndLastTracker implements SinkDataListener { public void receivedData(DataFlowID inFlowID, Object inData) { mLast = inData; if(mFirst == null) { mFirst = inData; } } public Object getFirst() { return mFirst; } public Object getLast() { return mLast; } private volatile Object mFirst; private volatile Object mLast; } private ModuleManager mManager; //Number or records in the csv file. private static final int NUM_ROWS = 3141; private static final File INPUTS_DIR = new File("src/test/sample_data","inputs"); private static final File VALID_CSV_FILE = new File(INPUTS_DIR,"table.csv"); private static final File INVALID_CSV_FILE = new File(INPUTS_DIR,"insufficient_rows.csv"); }