package org.marketcetera.client.utils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.marketcetera.client.ClientManager; import org.marketcetera.client.ConnectionException; import org.marketcetera.client.MockClient; import org.marketcetera.core.LoggerConfiguration; import org.marketcetera.marketdata.MarketDataFeedTestBase; import org.marketcetera.module.ExpectedFailure; import org.marketcetera.trade.*; import org.marketcetera.trade.utils.OrderHistoryManagerTest; /* $License$ */ /** * Tests {@link LiveOrderHistoryManager}. * * @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a> * @version $Id: LiveOrderHistoryManagerTest.java 16841 2014-02-20 19:59:04Z colin $ * @since 2.1.4 */ public class LiveOrderHistoryManagerTest { /** * Run once before all tests. * * @throws Exception if an unexpected error occurs */ @BeforeClass public static void once() throws Exception { LoggerConfiguration.logSetup(); ClientManager.setClientFactory(new MockClient.MockClientFactory()); ClientManager.init(null); client = (MockClient)ClientManager.getInstance(); OrderHistoryManagerTest.once(); } /** * Run before each test. * * @throws Exception if an unexpected error occurs */ @Before public void setup() throws Exception { client.reset(); } /** * Tests {@link LiveOrderHistoryManager#LiveOrderHistoryManager(java.util.Date)}. * * @throws Exception if an unexpected error occurs */ @Test public void testConstructor() throws Exception { LiveOrderHistoryManager manager = new LiveOrderHistoryManager(null); assertEquals(new Date(0), manager.getReportHistoryOrigin()); manager = new LiveOrderHistoryManager(new Date(Long.MIN_VALUE)); assertEquals(new Date(Long.MIN_VALUE), manager.getReportHistoryOrigin()); manager = new LiveOrderHistoryManager(new Date(Long.MAX_VALUE)); assertEquals(new Date(Long.MAX_VALUE), manager.getReportHistoryOrigin()); manager = new LiveOrderHistoryManager(new Date(0)); assertEquals(new Date(0), manager.getReportHistoryOrigin()); } /** * Tests {@link LiveOrderHistoryManager#getOpenOrders()}. * * @throws Exception if an unexpected error occurs */ @Test public void testGetOpenOrders() throws Exception { final LiveOrderHistoryManager manager = new LiveOrderHistoryManager(null); assertFalse(manager.isRunning()); new ExpectedFailure<IllegalStateException>(org.marketcetera.client.Messages.OPEN_ORDER_LIST_NOT_READY.getText()) { @Override protected void run() throws Exception { manager.getOpenOrders(); } }; manager.start(); final Map<OrderID,ExecutionReport> openOrders = manager.getOpenOrders(); final Set<OrderID> orderIds = manager.getOrderIds(); assertTrue(openOrders.isEmpty()); assertTrue(openOrders.isEmpty()); // add a non-open report ReportBase report1 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.Filled); assertFalse(report1.getOrderStatus().isCancellable()); manager.add(report1); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return !orderIds.isEmpty(); } }); // there's a non-zero chance of a race-condition here because the orderIds collection is populated // before the openOrder collection is updated. we're in trouble because we're trying to show // a negative - there's no deterministic way to wait for a lack of update. instead, add an open order, which // is deterministically detectable and make sure it is the only one received. ReportBase report2 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.PartiallyFilled); assertTrue(report2.getOrderStatus().isCancellable()); manager.add(report2); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return !openOrders.isEmpty(); } }); assertEquals(1, openOrders.size()); assertEquals(report2, openOrders.get(report2.getOrderID())); new ExpectedFailure<UnsupportedOperationException>() { @Override protected void run() throws Exception { openOrders.clear(); } }; new ExpectedFailure<UnsupportedOperationException>() { @Override protected void run() throws Exception { openOrders.put(new OrderID("orderID"), OrderHistoryManagerTest.generateExecutionReport("orderID", null, OrderStatus.PartiallyFilled)); } }; new ExpectedFailure<UnsupportedOperationException>() { @Override protected void run() throws Exception { openOrders.keySet().iterator().remove(); } }; } /** * Tests that the open orders collection picks up existing open orders. * * @throws Exception if an unexpected error occurs */ @Test public void testOpenOrdersPopulatedFromSnapshot() throws Exception { final LiveOrderHistoryManager manager = new LiveOrderHistoryManager(null); Set<ReportBase> historicalReports = client.getReports(); assertTrue(historicalReports.isEmpty()); // generate a few open orders and a few non-open orders ReportBase report1 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.New); Thread.sleep(250); ReportBase report2 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.Canceled); Thread.sleep(250); ReportBase report3 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.Replaced); Thread.sleep(250); ReportBase report4 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.Filled); historicalReports.add(report1); historicalReports.add(report2); historicalReports.add(report3); historicalReports.add(report4); manager.start(); Map<OrderID,ExecutionReport> openOrders = manager.getOpenOrders(); assertEquals(2, openOrders.size()); assertEquals(4, manager.getOrderIds().size()); assertEquals(report1, openOrders.get(report1.getOrderID())); assertEquals(report3, openOrders.get(report3.getOrderID())); } /** * Tests that the open order collection is updated when an order closes. * * @throws Exception if an unexpected error occurs */ @Test public void testOpenOrderCloses() throws Exception { final LiveOrderHistoryManager manager = new LiveOrderHistoryManager(null); manager.start(); final Map<OrderID,ExecutionReport> openOrders = manager.getOpenOrders(); assertTrue(openOrders.isEmpty()); ReportBase report1 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.New); manager.add(report1); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return !openOrders.isEmpty(); } }); ReportBase report2 = OrderHistoryManagerTest.generateExecutionReport(report1.getOrderID().getValue(), null, OrderStatus.Filled); manager.add(report2); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return openOrders.isEmpty(); } }); } /** * Tests the order lifecycle. * * @throws Exception if an unexpected error occurs */ @Test public void testOrderLifecycle() throws Exception { final LiveOrderHistoryManager manager = new LiveOrderHistoryManager(null); manager.start(); final Map<OrderID,ExecutionReport> openOrders = manager.getOpenOrders(); assertTrue(openOrders.isEmpty()); final ReportBase report1 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.New); manager.add(report1); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return !openOrders.isEmpty(); } }); ReportBase report2 = OrderHistoryManagerTest.generateExecutionReport(report1.getOrderID().getValue(), null, OrderStatus.PendingReplace); manager.add(report2); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { ReportBase report = openOrders.get(report1.getOrderID()); if(report == null) { return false; } return report.getOrderStatus().equals(OrderStatus.PendingReplace); } }); assertEquals(1, openOrders.size()); assertEquals(report2, openOrders.get(report1.getOrderID())); final ReportBase report3 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), report1.getOrderID().getValue(), OrderStatus.Replaced); manager.add(report3); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { ReportBase report = openOrders.get(report3.getOrderID()); if(report == null) { return false; } return report.getOrderStatus().equals(OrderStatus.Replaced) && openOrders.size() == 1; } }); assertEquals(1, openOrders.size()); assertEquals(report3, openOrders.get(report3.getOrderID())); final ReportBase report4 = OrderHistoryManagerTest.generateExecutionReport(report3.getOrderID().getValue(), null, OrderStatus.PartiallyFilled); manager.add(report4); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { ReportBase report = openOrders.get(report4.getOrderID()); if(report == null) { return false; } return report.getOrderStatus().equals(OrderStatus.PartiallyFilled); } }); assertEquals(1, openOrders.size()); assertEquals(report4, openOrders.get(report4.getOrderID())); final ReportBase report5 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), report4.getOrderID().getValue(), OrderStatus.PendingReplace); manager.add(report5); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { ReportBase report = openOrders.get(report5.getOrderID()); if(report == null) { return false; } return report.getOrderStatus().equals(OrderStatus.PendingReplace) && openOrders.size() == 1; } }); assertEquals(1, openOrders.size()); assertEquals(report5, openOrders.get(report5.getOrderID())); final ReportBase report6 = OrderHistoryManagerTest.generateExecutionReport(report5.getOrderID().getValue(), report4.getOrderID().getValue(), OrderStatus.Replaced); manager.add(report6); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { ReportBase report = openOrders.get(report6.getOrderID()); if(report == null) { return false; } return report.getOrderStatus().equals(OrderStatus.Replaced) && openOrders.size() == 1; } }); assertEquals(1, openOrders.size()); assertEquals(report6, openOrders.get(report6.getOrderID())); final ReportBase report7 = OrderHistoryManagerTest.generateExecutionReport(report6.getOrderID().getValue(), null, OrderStatus.PendingCancel); manager.add(report7); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { ReportBase report = openOrders.get(report7.getOrderID()); if(report == null) { return false; } return report.getOrderStatus().equals(OrderStatus.PendingCancel); } }); assertEquals(1, openOrders.size()); assertEquals(report7, openOrders.get(report7.getOrderID())); final ReportBase report8 = OrderHistoryManagerTest.generateOrderCancelReject("order-" + counter.incrementAndGet(), report7.getOrderID().getValue()); manager.add(report8); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return openOrders.isEmpty(); } }); } /** * Tests open orders before the origin history date. * * @throws Exception if an unexpected error occurs */ @Test public void testOpenOrders() throws Exception { Set<ReportBase> historicalReports = client.getReports(); List<ReportBaseImpl> setupOpenOrders = client.getOpenOrders(); assertTrue(historicalReports.isEmpty()); assertTrue(setupOpenOrders.isEmpty()); // generate a few open orders and a few non-open orders ReportBaseImpl report1 = (ReportBaseImpl)OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.New); Thread.sleep(250); ReportBase report2 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.Filled); Thread.sleep(250); ReportBase report3 = OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.Canceled); Thread.sleep(250); ReportBaseImpl report4 = (ReportBaseImpl)OrderHistoryManagerTest.generateExecutionReport("order-" + counter.incrementAndGet(), null, OrderStatus.PartiallyFilled); assertTrue(report1.getOrderStatus().isCancellable()); assertFalse(report2.getOrderStatus().isCancellable()); assertFalse(report3.getOrderStatus().isCancellable()); assertTrue(report4.getOrderStatus().isCancellable()); setupOpenOrders.add(report1); setupOpenOrders.add(report4); historicalReports.add(report2); historicalReports.add(report3); historicalReports.add(report4); // set the origin time to 1ms before report3's time - this will make report1 an open order that precedes the origin final LiveOrderHistoryManager manager = new LiveOrderHistoryManager(new Date(report3.getSendingTime().getTime()-1)); manager.start(); Map<OrderID,ExecutionReport> openOrders = manager.getOpenOrders(); assertEquals(2, openOrders.size()); assertEquals(3, manager.getOrderIds().size()); assertEquals(report1, openOrders.get(report1.getOrderID())); assertEquals(report4, openOrders.get(report4.getOrderID())); } /** * Tests what happens if an error occurs connecting to the client. * * @throws Exception if an unexpected error occurs */ @Test public void clientExceptionTest() throws Exception { ConnectionException exception = new ConnectionException(org.marketcetera.client.Messages.DONT_ADD_REPORTS); client.setGetReportsSinceException(exception); final LiveOrderHistoryManager manager = new LiveOrderHistoryManager(null); new ExpectedFailure<RuntimeException>(ConnectionException.class.getCanonicalName() + ": " + org.marketcetera.client.Messages.DONT_ADD_REPORTS.getText()) { @Override protected void run() throws Exception { manager.start(); } }; } /** * Tests start and stop cycles. * * @throws Exception if an unexpected error occurs */ @Test public void startAndStopTest() throws Exception { final LiveOrderHistoryManager manager = new LiveOrderHistoryManager(null); assertFalse(manager.isRunning()); assertNotNull(manager.toString()); manager.stop(); assertFalse(manager.isRunning()); assertNotNull(manager.toString()); manager.start(); assertTrue(manager.isRunning()); assertNotNull(manager.toString()); manager.start(); assertTrue(manager.isRunning()); assertNotNull(manager.toString()); } /** * test client used to simulate connections to the server */ private static MockClient client; /** * counter used for unique identifiers */ private static final AtomicInteger counter = new AtomicInteger(0); }