package org.marketcetera.modules.cep.esper; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.math.BigDecimal; import java.util.Calendar; import javax.management.JMX; import org.apache.log4j.Level; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.marketcetera.core.ClassVersion; import org.marketcetera.core.LoggerConfiguration; import org.marketcetera.event.AskEvent; import org.marketcetera.event.EventTestBase; import org.marketcetera.module.*; import org.marketcetera.trade.Equity; import org.marketcetera.trade.Factory; import org.marketcetera.trade.Suggestion; import org.marketcetera.util.test.LogTestAssist; /** * Test the external time functionality * * @author toli kuznets * @version $Id: ExternalTimeTest.java 16841 2014-02-20 19:59:04Z colin $ */ @ClassVersion("$Id: ExternalTimeTest.java 16841 2014-02-20 19:59:04Z colin $") public class ExternalTimeTest extends ModuleTestBase { protected ModuleManager sManager; protected static BlockingSinkDataListener sSink; protected static Factory sFactory; private static ModuleURN TEST_URN = new ModuleURN(CEPEsperFactory.PROVIDER_URN, "toli"); @BeforeClass public static void logSetup() { LoggerConfiguration.logSetup(); } @Before public void before() throws Exception { sSink = new BlockingSinkDataListener(); sManager = new ModuleManager(); sManager.init(); sManager.addSinkListener(sSink); sLogAssist.resetAppender(); } @After public void after() throws Exception { sManager.removeSinkListener(sSink); sManager.stop(); } /** Setup an esper query with a time window of 10 days that gives the size of events in the window: * Send in 5 events, with different times apart * We should have the following output: * t+0: start of window, 1 event * t+5: 2 events (initial + 2nd event) * t+year: 0 events (window reset), immediately followed by 1 events (3rd event only in window) * t+year+1day: 2 events (3rd and 4th) * t+year+15days: 0 events (window reset), followed by 1 event (new window established) * */ @Test(timeout = 2*60*1000) public void testExternalTime() throws Exception { Calendar cal = Calendar.getInstance(); cal.set(2977, 7, 8, 10, 30, 40); // first time event on 2977-7-8 AskEvent ask1 = EventTestBase.generateEquityAskEvent(1, cal.getTimeInMillis(), new Equity("AB1"), "nyse", new BigDecimal("23"), new BigDecimal("23")); cal.set(2977, 7, 13, 10, 30, 40); // next time event on 2977-7-13 AskEvent ask2 = EventTestBase.generateEquityAskEvent(1, cal.getTimeInMillis(), new Equity("AB2"), "nyse", new BigDecimal("23"), new BigDecimal("23")); cal.set(2978, 7, 13, 10, 30, 40); // 3rd event year later on 2978-7-13, should reset window AskEvent ask3 = EventTestBase.generateEquityAskEvent(1, cal.getTimeInMillis(), new Equity("AB3"), "nyse", new BigDecimal("23"), new BigDecimal("23")); cal.set(2978, 7, 14, 10, 30, 40); // 4th event day later than 3rd - should cause a hit AskEvent ask4 = EventTestBase.generateEquityAskEvent(1, cal.getTimeInMillis(), new Equity("AB4"), "nyse", new BigDecimal("23"), new BigDecimal("23")); cal.set(2978, 7, 29, 11, 15, 40); // 5th event 15 days later - window should be empty, reset to 1 AskEvent ask5 = EventTestBase.generateEquityAskEvent(1, cal.getTimeInMillis(), new Equity("AB5"), "nyse", new BigDecimal("23"), new BigDecimal("23")); sManager.createModule(CEPEsperFactory.PROVIDER_URN, TEST_URN); CEPEsperProcessorMXBean esperBean = JMX.newMXBeanProxy( ModuleTestBase.getMBeanServer(), TEST_URN.toObjectName(), CEPEsperProcessorMXBean.class); sManager.stop(TEST_URN); esperBean.setUseExternalTime(true); assertTrue("accessor doesn't return right value", esperBean.isUseExternalTime()); sManager.start(TEST_URN); Suggestion sug1 = Factory.getInstance().createOrderSingleSuggestion(); sug1.setIdentifier("acura"); DataFlowID flow = sManager.createDataFlow(new DataRequest[] { // Copier -> Esper: send 2 events new DataRequest(CopierModuleFactory.INSTANCE_URN, new Object[] { ask1, ask2, ask3, ask4, ask5}), // ESPER -> Sink: pattern new DataRequest(TEST_URN, new String[] {"select * from ask.win:time(10 days).std:size()"}) }); assertEquals("wrong size event", 1L, sSink.getNextData()); // AB1 assertEquals("wrong size event", 2L, sSink.getNextData()); // AB1 + AB2 assertEquals("wrong size event", 0L, sSink.getNextData()); // AB3 comes in to reset clock 1 year later and gives 0 size assertEquals("wrong size event", 1L, sSink.getNextData()); // AB3 also triggers new window/size of 1 assertEquals("wrong size event", 2L, sSink.getNextData()); // AB4 comes in after AB3 to give 2 assertEquals("wrong size event", 0L, sSink.getNextData()); // AB5 comes in 15 days later, resets window -> 0 size assertEquals("wrong size event", 1L, sSink.getNextData()); // AB5 sets new window of size 1 sManager.cancel(flow); } @Test(timeout = 2*60*1000) public void testCancelBeforeFlowIsOver() throws Exception { sManager.createModule(CEPEsperFactory.PROVIDER_URN, TEST_URN); CEPEsperProcessorMXBean esperBean = JMX.newMXBeanProxy( ModuleTestBase.getMBeanServer(), TEST_URN.toObjectName(), CEPEsperProcessorMXBean.class); sManager.stop(TEST_URN); esperBean.setUseExternalTime(true); sManager.start(TEST_URN); DataFlowID flow = sManager.createDataFlow(new DataRequest[] { // Copier -> Esper: send events new DataRequest(CopierModuleFactory.INSTANCE_URN, new Object[] { 1, 2, 3, 4, 5, "vishel zaichik pogulyat"}), // ESPER -> Sink: pattern new DataRequest(TEST_URN, new String[] {"select * bid"}) }); sManager.cancel(flow); assertEquals("shouldn't have any statements", 0, esperBean.getStatementNames().length); } @Test public void testCancelWithoutData() throws Exception { sManager.createModule(CEPEsperFactory.PROVIDER_URN, TEST_URN); CEPEsperProcessorMXBean esperBean = JMX.newMXBeanProxy( ModuleTestBase.getMBeanServer(), TEST_URN.toObjectName(), CEPEsperProcessorMXBean.class); sManager.stop(TEST_URN); esperBean.setUseExternalTime(true); sManager.start(TEST_URN); String[] query = {"select * bid"}; DataFlowID flowID = sManager.createDataFlow(new DataRequest[] { //don't send any data so that we remove unprocessed statements. new DataRequest(CopierModuleFactory.INSTANCE_URN, new Object[0]), new DataRequest(TEST_URN, query) }); sManager.cancel(flowID); //There should be no warning when canceling the data flow. sLogAssist.assertNoEvents(); } private static final LogTestAssist sLogAssist = new LogTestAssist( "org.marketcetera.module.SyncCoupler", Level.WARN); }