/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.view.worker;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.opengamma.core.id.ExternalSchemes;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.marketdata.MarketDataProvider;
import com.opengamma.engine.marketdata.resolver.MarketDataProviderResolver;
import com.opengamma.engine.marketdata.spec.LiveMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.id.UniqueId;
import com.opengamma.livedata.UserPrincipal;
import com.opengamma.util.test.TestGroup;
/**
* Tests for the subscription tracking logic of the {@link MarketDataManager}.
*/
@Test(groups = TestGroup.UNIT)
public class MarketDataManagerTest {
private MarketDataManager _manager;
@BeforeMethod
public void setUp() throws Exception {
_manager = new MarketDataManager(createChangeListener(), createResolver(), null, null);
List<MarketDataSpecification> spec = Lists.newArrayList();
spec.add(LiveMarketDataSpecification.LIVE_SPEC);
_manager.createSnapshotManagerForCycle(new UserPrincipal("bloggs", "127.0.0.1"), ImmutableList.copyOf(spec));
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testConstructionWithNullListenerFails() {
new MarketDataManager(null, createResolver(), null, null);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testConstructionWithNullResolverFails() {
new MarketDataManager(createChangeListener(), null, null, null);
}
@Test
public void testQueryForNonExistentSub() {
_manager.requestMarketDataSubscriptions(ImmutableSet.of(createValueSpecForMarketValue("AAPL.")));
assertThat(_manager.querySubscriptionState("BOGUS").size(), is(0));
}
@Test
public void testMarketDataRequestIsInitiallyPending() {
_manager.requestMarketDataSubscriptions(ImmutableSet.of(createValueSpecForMarketValue("AAPL.")));
checkSingleSubscriptionState("AAPL.", SubscriptionStateQuery.SubscriptionState.PENDING);
}
@Test
public void testMarketDataSubscriptionSucceeding() {
ImmutableSet<ValueSpecification> valueSpecs = ImmutableSet.of(createValueSpecForMarketValue("AAPL."));
_manager.requestMarketDataSubscriptions(valueSpecs);
_manager.subscriptionsSucceeded(valueSpecs);
checkSingleSubscriptionState("AAPL.", SubscriptionStateQuery.SubscriptionState.ACTIVE);
}
@Test
public void testMarketDataSubscriptionFailing() {
ValueSpecification valueSpec = createValueSpecForMarketValue("AAPL.");
_manager.requestMarketDataSubscriptions(ImmutableSet.of(valueSpec));
_manager.subscriptionFailed(valueSpec, "Que?");
checkSingleSubscriptionState("AAPL.", SubscriptionStateQuery.SubscriptionState.FAILED);
}
@Test
public void testMarketDataSubscriptionRemoval() {
ImmutableSet<ValueSpecification> valueSpecs1 = ImmutableSet.of(createValueSpecForMarketValue("AAPL."));
_manager.requestMarketDataSubscriptions(valueSpecs1);
_manager.subscriptionsSucceeded(valueSpecs1);
Set<ValueSpecification> valueSpecs2 = createMarketDataValueSpecs("GOOG.");
_manager.requestMarketDataSubscriptions(valueSpecs2);
_manager.subscriptionsSucceeded(valueSpecs2);
checkSingleSubscriptionState("AAPL.", SubscriptionStateQuery.SubscriptionState.REMOVED);
checkSingleSubscriptionState("GOOG.", SubscriptionStateQuery.SubscriptionState.ACTIVE);
}
@Test
public void testMarketDataLifecycle() {
ValueSpecification spec = createValueSpecForMarketValue("AAPL.");
ImmutableSet<ValueSpecification> valueSpecs = ImmutableSet.of(spec);
_manager.requestMarketDataSubscriptions(valueSpecs);
checkSingleSubscriptionState("AAPL.", SubscriptionStateQuery.SubscriptionState.PENDING);
_manager.subscriptionsSucceeded(valueSpecs);
checkSingleSubscriptionState("AAPL.", SubscriptionStateQuery.SubscriptionState.ACTIVE);
_manager.requestMarketDataSubscriptions(ImmutableSet.<ValueSpecification>of());
checkSingleSubscriptionState("AAPL.", SubscriptionStateQuery.SubscriptionState.REMOVED);
_manager.requestMarketDataSubscriptions(valueSpecs);
checkSingleSubscriptionState("AAPL.", SubscriptionStateQuery.SubscriptionState.PENDING);
_manager.subscriptionFailed(spec, "Why?");
checkSingleSubscriptionState("AAPL.", SubscriptionStateQuery.SubscriptionState.FAILED);
}
@Test
public void testAllMatchingTickersAreReturned() {
Set<ValueSpecification> valueSpecs =
createMarketDataValueSpecs("AAPL.", "AAPL/G4NHG.O", "AAPL/G4G3F.", "GOOG.", "GOOG/GsG~K.");
_manager.requestMarketDataSubscriptions(valueSpecs);
assertThat(_manager.querySubscriptionState("AAPL").size(), is(3));
assertThat(_manager.querySubscriptionState("AAPL.").size(), is(1));
assertThat(_manager.querySubscriptionState("GOOG").size(), is(2));
assertThat(_manager.querySubscriptionState("GOOG.").size(), is(1));
}
@Test
public void testNullQueryResultsInAllMatchingTickersReturned() {
Set<ValueSpecification> valueSpecs =
createMarketDataValueSpecs("AAPL.", "AAPL/G4NHG.O", "AAPL/G4G3F.", "GOOG.", "GOOG/GsG~K.");
_manager.requestMarketDataSubscriptions(valueSpecs);
assertThat(_manager.querySubscriptionState(null).size(), is(5));
}
@Test
public void testEmptyQueryResultsInAllMatchingTickersReturned() {
Set<ValueSpecification> valueSpecs =
createMarketDataValueSpecs("AAPL.", "AAPL/G4NHG.O", "AAPL/G4G3F.", "GOOG.", "GOOG/GsG~K.");
_manager.requestMarketDataSubscriptions(valueSpecs);
assertThat(_manager.querySubscriptionState("").size(), is(5));
}
@Test
public void testQueryByType() {
Set<ValueSpecification> appleSpec = createMarketDataValueSpecs("AAPL.");
Set<ValueSpecification> appleOptions = createMarketDataValueSpecs("AAPL/G4NHG.O", "AAPL/G4G3F.");
Set <ValueSpecification> googleOptions = createMarketDataValueSpecs("GOOG.", "GOOG/GsG~K.");
_manager.requestMarketDataSubscriptions(
ImmutableSet.<ValueSpecification>builder()
.addAll(appleOptions)
.addAll(appleSpec)
.build());
assertThat(_manager.getFailedSubscriptionCount(), is(0));
assertThat(_manager.getPendingSubscriptionCount(), is(3));
// Drop the AAPL request
_manager.requestMarketDataSubscriptions(
ImmutableSet.<ValueSpecification>builder()
.addAll(appleOptions)
.addAll(googleOptions)
.build());
_manager.subscriptionFailed(createValueSpecForMarketValue("AAPL/G4NHG.O"), "oops");
_manager.subscriptionsSucceeded(createMarketDataValueSpecs("AAPL/G4G3F."));
assertThat(_manager.getFailedSubscriptionCount(), is(1));
assertThat(_manager.getPendingSubscriptionCount(), is(2));
assertThat(_manager.getRemovedSubscriptionCount(), is(1));
assertThat(_manager.getActiveSubscriptionCount(), is(1));
}
@Test
public void testValueSpecsOnSameTickerAreDistinguishedByGet() {
Set<ValueSpecification> specs = ImmutableSet.of(createValueSpecForMarketValue("AAPL."),
createValueSpecForDividendYield("AAPL."));
_manager.requestMarketDataSubscriptions(specs);
assertThat(_manager.getPendingSubscriptionCount(), is(2));
Set<String> keys = _manager.queryPendingSubscriptions().keySet();
assertThat(keys.size(), is(2));
checkKeyMatches(keys);
}
@Test
public void testValueSpecsOnSameTickerAreDistinguishedByQuery() {
Set<ValueSpecification> specs = ImmutableSet.of(createValueSpecForMarketValue("AAPL."), createValueSpecForDividendYield("AAPL."));
_manager.requestMarketDataSubscriptions(specs);
Set<String> keys = _manager.querySubscriptionState("").keySet();
assertThat(keys.size(), is(2));
checkKeyMatches(keys);
}
@Test
public void testUnexpectedSubscriptionNotificationsIgnored() {
Set<ValueSpecification> specs1 = ImmutableSet.of(createValueSpecForMarketValue("AAPL."));
_manager.subscriptionsSucceeded(specs1);
assertThat(_manager.querySubscriptionState("AAPL.").size(), is(0));
assertThat(_manager.getFailedSubscriptionCount(), is(0));
assertThat(_manager.getPendingSubscriptionCount(), is(0));
assertThat(_manager.getRemovedSubscriptionCount(), is(0));
assertThat(_manager.getActiveSubscriptionCount(), is(0));
ValueSpecification spec2 = createValueSpecForMarketValue("GOOG.");
_manager.subscriptionFailed(spec2, "Not authorized");
assertThat(_manager.querySubscriptionState("GOOG.").size(), is(0));
assertThat(_manager.getFailedSubscriptionCount(), is(0));
assertThat(_manager.getPendingSubscriptionCount(), is(0));
assertThat(_manager.getRemovedSubscriptionCount(), is(0));
assertThat(_manager.getActiveSubscriptionCount(), is(0));
}
@Test
public void testUnexpectedChangeOfSubscriptionState() {
ValueSpecification spec = createValueSpecForMarketValue("AAPL.");
Set<ValueSpecification> specs = ImmutableSet.of(spec);
_manager.requestMarketDataSubscriptions(specs);
assertThat(_manager.getFailedSubscriptionCount(), is(0));
assertThat(_manager.getPendingSubscriptionCount(), is(1));
assertThat(_manager.getRemovedSubscriptionCount(), is(0));
assertThat(_manager.getActiveSubscriptionCount(), is(0));
_manager.subscriptionsSucceeded(specs);
assertThat(_manager.getFailedSubscriptionCount(), is(0));
assertThat(_manager.getPendingSubscriptionCount(), is(0));
assertThat(_manager.getRemovedSubscriptionCount(), is(0));
assertThat(_manager.getActiveSubscriptionCount(), is(1));
_manager.subscriptionFailed(spec, "Not authorized");
assertThat(_manager.getFailedSubscriptionCount(), is(1));
assertThat(_manager.getPendingSubscriptionCount(), is(0));
assertThat(_manager.getRemovedSubscriptionCount(), is(0));
assertThat(_manager.getActiveSubscriptionCount(), is(0));
}
private void checkKeyMatches(Set<String> keys) {
boolean mvMatch = false;
boolean dyMatch = false;
for (String key : keys) {
assertThat(key.contains("AAPL"), is(true));
mvMatch = mvMatch || key.contains("Market_Value");
dyMatch = dyMatch || key.contains("Dividend_Yield");
}
assertThat(mvMatch, is(true));
assertThat(dyMatch, is(true));
}
private void checkSingleSubscriptionState(String ticker, MarketDataManager.SubscriptionState expectedState) {
Map<String, MarketDataManager.SubscriptionStatus> stateMap = _manager.querySubscriptionState(ticker);
assertThat(Iterables.getOnlyElement(stateMap.values()).getState(), is(expectedState.name()));
}
private Set<ValueSpecification> createMarketDataValueSpecs(String... tickers) {
ImmutableSet.Builder<ValueSpecification> builder = ImmutableSet.builder();
for (String ticker : tickers) {
builder.add(createValueSpecForMarketValue(ticker));
}
return builder.build();
}
private ValueSpecification createValueSpecForMarketValue(String ticker) {
return createValueSpec(ticker, "Market_Value");
}
private ValueSpecification createValueSpecForDividendYield(String ticker) {
return createValueSpec(ticker, "Dividend_Yield");
}
private ValueSpecification createValueSpec(String ticker, String valueName) {
UniqueId uniqueId = UniqueId.of(ExternalSchemes.ACTIVFEED_TICKER.getName(), ticker);
ValueProperties properties = ValueProperties.builder()
.with(ValuePropertyNames.FUNCTION, "MarketDataSourcingFunction")
.get();
ComputationTargetSpecification targetSpecification =
new ComputationTargetSpecification(ComputationTargetType.PRIMITIVE, uniqueId);
return new ValueSpecification(valueName, targetSpecification, properties);
}
private MarketDataChangeListener createChangeListener() {
return new MarketDataChangeListener() {
@Override
public void onMarketDataValuesChanged(Collection<ValueSpecification> valueSpecifications) { }
};
}
private MarketDataProviderResolver createResolver() {
return new MarketDataProviderResolver() {
@Override
public MarketDataProvider resolve(UserPrincipal marketDataUser, MarketDataSpecification snapshotSpec) {
MarketDataProvider mock = mock(MarketDataProvider.class);
when(mock.snapshot(any(MarketDataSpecification.class))).thenReturn(mock(CompositeMarketDataSnapshot.class));
return mock;
}
};
}
}