/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.livedata.client; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; import java.util.Collection; import java.util.HashMap; import java.util.Map; import net.sf.ehcache.CacheManager; import org.fudgemsg.FudgeMsg; import org.fudgemsg.MutableFudgeMsg; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.common.collect.Sets; import com.opengamma.id.ExternalId; import com.opengamma.id.ExternalScheme; import com.opengamma.livedata.LiveDataSpecification; import com.opengamma.livedata.LiveDataValueUpdate; import com.opengamma.livedata.UserPrincipal; import com.opengamma.livedata.msg.LiveDataSubscriptionResponse; import com.opengamma.livedata.msg.LiveDataSubscriptionResult; import com.opengamma.livedata.normalization.StandardRules; import com.opengamma.livedata.server.MockLiveDataServer; import com.opengamma.livedata.test.CollectingLiveDataListener; import com.opengamma.livedata.test.LiveDataClientTestUtils; import com.opengamma.util.ehcache.EHCacheUtils; import com.opengamma.util.fudgemsg.OpenGammaFudgeContext; import com.opengamma.util.test.TestGroup; import com.opengamma.util.test.TestLifecycle; import com.opengamma.util.test.Timeout; /** * Test. */ @Test(groups = {TestGroup.UNIT, "ehcache" }) public class DistributedLiveDataClientTest { public static final ExternalScheme TEST_IDENTIFICATION_SCHEME = ExternalScheme.of("bar"); public static final LiveDataSpecification TEST_LIVE_DATA_SPEC = new LiveDataSpecification("Foo", ExternalId.of(TEST_IDENTIFICATION_SCHEME, "baz")); private static final long TIMEOUT = 3 * Timeout.standardTimeoutMillis(); private static String TEST_ID_1 = "id1"; private static String TEST_ID_2 = "id2"; private static UserPrincipal TEST_USER = new UserPrincipal("alice", "127.0.0.1"); private MockLiveDataServer _server; private MutableFudgeMsg[] _testMsgs; private CacheManager _cacheManager; @BeforeClass public void setUpClass() { _cacheManager = EHCacheUtils.createTestCacheManager(getClass()); } @AfterClass public void tearDownClass() { EHCacheUtils.shutdownQuiet(_cacheManager); } @BeforeMethod public void initialize() { MutableFudgeMsg testMsg1 = OpenGammaFudgeContext.getInstance().newMessage(); testMsg1.add("LAST", 9.86); MutableFudgeMsg testMsg2 = OpenGammaFudgeContext.getInstance().newMessage(); testMsg2.add("BID", 10.00); testMsg2.add("ASK", 10.05); _testMsgs = new MutableFudgeMsg[] {testMsg1, testMsg2 }; Map<String, FudgeMsg> uniqueId2TestMsg = new HashMap<String, FudgeMsg>(); uniqueId2TestMsg.put(TEST_LIVE_DATA_SPEC.getIdentifier(TEST_IDENTIFICATION_SCHEME), testMsg1); uniqueId2TestMsg.put(TEST_ID_1, testMsg1); uniqueId2TestMsg.put(TEST_ID_2, testMsg2); _server = new MockLiveDataServer(TEST_IDENTIFICATION_SCHEME, uniqueId2TestMsg, _cacheManager); } private DistributedLiveDataClient createClient(final int threads) { return LiveDataClientTestUtils.getInMemoryConduitClient(_server, threads); } @Test(dataProvider = "threads") public void connectionToMarketDataApiDown(final int threads) { TestLifecycle.begin(); try { // don't start server final DistributedLiveDataClient client = createClient(threads); try { LiveDataSubscriptionResponse response = client.snapshot(TEST_USER, TEST_LIVE_DATA_SPEC, 1000); assertNotNull(response); assertEquals(LiveDataSubscriptionResult.INTERNAL_ERROR, response.getSubscriptionResult()); assertEquals(true, response.getUserMessage().contains("Connection to market data API down")); } finally { client.close(); } } finally { TestLifecycle.end(); } } @Test(dataProvider = "threads") public void singleSnapshot(final int threads) { TestLifecycle.begin(); try { _server.start(); final DistributedLiveDataClient client = createClient(threads); try { LiveDataSubscriptionResponse response = client.snapshot(TEST_USER, TEST_LIVE_DATA_SPEC, 1000); assertNotNull(response); assertEquals(LiveDataSubscriptionResult.SUCCESS, response.getSubscriptionResult()); assertNotNull(response.getSnapshot()); assertEquals(0, response.getSnapshot().getSequenceNumber()); assertEquals(_testMsgs[0], response.getSnapshot().getFields()); } finally { client.close(); } } finally { TestLifecycle.end(); } } @Test(dataProvider = "threads") public void multipleSnapshots(final int threads) { TestLifecycle.begin(); try { _server.start(); final DistributedLiveDataClient client = createClient(threads); try { LiveDataSpecification spec1 = new LiveDataSpecification(StandardRules.getNoNormalization().getId(), ExternalId.of(TEST_IDENTIFICATION_SCHEME, TEST_ID_1)); LiveDataSpecification spec2 = new LiveDataSpecification(StandardRules.getNoNormalization().getId(), ExternalId.of(TEST_IDENTIFICATION_SCHEME, TEST_ID_2)); Collection<LiveDataSubscriptionResponse> responses = client.snapshot(TEST_USER, Sets.newHashSet(spec1, spec2), 1000); assertNotNull(responses); assertEquals(2, responses.size()); for (LiveDataSubscriptionResponse response : responses) { assertEquals(LiveDataSubscriptionResult.SUCCESS, response.getSubscriptionResult()); assertNotNull(response.getSnapshot()); if (response.getRequestedSpecification().equals(spec1)) { assertEquals(_testMsgs[0], response.getSnapshot().getFields()); } else if (response.getRequestedSpecification().equals(spec2)) { assertEquals(_testMsgs[1], response.getSnapshot().getFields()); } else { Assert.fail("Response for non-existent spec received"); } } } finally { client.close(); } } finally { TestLifecycle.end(); } } @Test(dataProvider = "threads") public void singleSubscribe(final int threads) { TestLifecycle.begin(); try { _server.start(); final DistributedLiveDataClient client = createClient(threads); try { CollectingLiveDataListener listener = new CollectingLiveDataListener(); client.subscribe(TEST_USER, TEST_LIVE_DATA_SPEC, listener); listener.waitForResponses(1, TIMEOUT); assertEquals(1, listener.getSubscriptionResponses().size()); assertEquals(LiveDataSubscriptionResult.SUCCESS, listener.getSubscriptionResponses().get(0).getSubscriptionResult()); // As part of subscribe(), the client does a snapshot and sends it to the listener. listener.waitForUpdates(1, TIMEOUT); assertEquals(1, listener.getValueUpdates().size()); assertEquals(_testMsgs[0], listener.getValueUpdates().get(0).getFields()); _server.sendLiveDataToClient(); // Normal data received. listener.waitForUpdates(1, TIMEOUT); assertEquals(2, listener.getValueUpdates().size()); assertEquals(_testMsgs[0], listener.getValueUpdates().get(1).getFields()); } finally { client.close(); } } finally { TestLifecycle.end(); } } @Test(dataProvider = "threads") public void multipleSubscribes(final int threads) { TestLifecycle.begin(); try { _server.start(); final DistributedLiveDataClient client = createClient(threads); try { LiveDataSpecification spec1 = new LiveDataSpecification(StandardRules.getNoNormalization().getId(), ExternalId.of(TEST_IDENTIFICATION_SCHEME, TEST_ID_1)); LiveDataSpecification spec2 = new LiveDataSpecification(StandardRules.getNoNormalization().getId(), ExternalId.of(TEST_IDENTIFICATION_SCHEME, TEST_ID_2)); CollectingLiveDataListener listener = new CollectingLiveDataListener(); client.subscribe(TEST_USER, Sets.newHashSet(spec1, spec2), listener); listener.waitForResponses(2, TIMEOUT); assertEquals(2, listener.getSubscriptionResponses().size()); assertEquals(LiveDataSubscriptionResult.SUCCESS, listener.getSubscriptionResponses().get(0).getSubscriptionResult()); assertEquals(LiveDataSubscriptionResult.SUCCESS, listener.getSubscriptionResponses().get(1).getSubscriptionResult()); // Snapshot x 2 listener.waitForUpdates(2, TIMEOUT); assertEquals(2, listener.getValueUpdates().size()); _server.sendLiveDataToClient(); // Snapshot x 2, subscription data x 2 = 4 overall listener.waitForUpdates(2, TIMEOUT); assertEquals(4, listener.getValueUpdates().size()); for (int i = 0; i < listener.getValueUpdates().size(); i++) { LiveDataValueUpdate update = listener.getValueUpdates().get(i); if (update.getSpecification().equals(spec1)) { assertEquals(_testMsgs[0], update.getFields()); } else if (update.getSpecification().equals(spec2)) { assertEquals(_testMsgs[1], update.getFields()); } else { Assert.fail("Response for non-existent spec received"); } } } finally { client.close(); } } finally { TestLifecycle.end(); } } @Test(dataProvider = "threads") public void subscribeUnsubscribeCycle(final int threads) { TestLifecycle.begin(); try { _server.start(); final DistributedLiveDataClient client = createClient(threads); try { assertEquals(0, _server.getSubscriptions().size()); CollectingLiveDataListener listener = new CollectingLiveDataListener(); client.subscribe(TEST_USER, TEST_LIVE_DATA_SPEC, listener); listener.waitForResponses(1, TIMEOUT); assertEquals(1, _server.getSubscriptions().size()); client.unsubscribe(TEST_USER, TEST_LIVE_DATA_SPEC, listener); // there would need to be a timeout before actual unsubscribe happens assertEquals(1, _server.getSubscriptions().size()); assertEquals(1, listener.getSubscriptionResponses().size()); listener.waitForUpdates(1, TIMEOUT); assertEquals(1, listener.getStoppedSubscriptions().size()); } finally { client.close(); } } finally { TestLifecycle.end(); } } @DataProvider(name = "threads") public Object[][] getThreadCounts() { return new Object[][] { {0 }, {1 }, {2 }, {16 } }; } }