/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.master.marketdatasnapshot.impl; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.AssertJUnit.assertEquals; import java.util.ArrayList; import java.util.List; import org.mockito.Matchers; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; import com.opengamma.DataNotFoundException; import com.opengamma.core.marketdatasnapshot.NamedSnapshot; import com.opengamma.core.marketdatasnapshot.impl.ManageableMarketDataSnapshot; import com.opengamma.id.UniqueId; import com.opengamma.id.VersionCorrection; import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotDocument; import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotMaster; import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotSearchRequest; import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotSearchResult; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.test.TestGroup; /** * Test {@link MasterSnapshotSource}. */ @Test(groups = TestGroup.UNIT) public class MasterSnapshotSourceTest { private static final UniqueId UID = UniqueId.of("A", "B"); private final MasterSnapshotSource _populatedSource = createPopulatedSource(); @Test(expectedExceptions = IllegalArgumentException.class) public void test_constructor_1arg_nullMaster() throws Exception { new MasterSnapshotSource(null); } //------------------------------------------------------------------------- public void test_getSnapshot_noOverride_found() throws Exception { MarketDataSnapshotMaster mock = mock(MarketDataSnapshotMaster.class); MarketDataSnapshotDocument doc = new MarketDataSnapshotDocument(example()); when(mock.get(UID)).thenReturn(doc); MasterSnapshotSource test = new MasterSnapshotSource(mock); NamedSnapshot testResult = test.get(UID); verify(mock, times(1)).get(UID); assertEquals(example(), testResult); } //------------------------------------------------------------------------- @Test(expectedExceptions = DataNotFoundException.class, expectedExceptionsMessageRegExp = "Some message") public void test_getSnapshot_noOverride_notFound() throws Exception { MarketDataSnapshotMaster mock = mock(MarketDataSnapshotMaster.class); new MarketDataSnapshotDocument(example()); when(mock.get(UID)).thenThrow(new DataNotFoundException("Some message")); MasterSnapshotSource test = new MasterSnapshotSource(mock); test.get(UID); } //------------------------------------------------------------------------- protected ManageableMarketDataSnapshot example() { ManageableMarketDataSnapshot snapshotDocument = new ManageableMarketDataSnapshot(); snapshotDocument.setUniqueId(UID); return snapshotDocument; } @Test(expectedExceptions = DataNotFoundException.class) public void testGetSingleWithNoMatchGivesException() { MarketDataSnapshotMaster mock = mock(MarketDataSnapshotMaster.class); when(mock.search(Matchers.<MarketDataSnapshotSearchRequest>anyObject())) .thenReturn(new MarketDataSnapshotSearchResult(ImmutableList.<MarketDataSnapshotDocument>of())); new MasterSnapshotSource(mock).getSingle(NamedSnapshot.class, "I dont exist", VersionCorrection.LATEST); } @Test public void testMatchByTypeAndNameSucceeds() { NamedSnapshot snapshot = _populatedSource.getSingle(NamedSnapshot.class, "snap1", VersionCorrection.LATEST); assertThat(snapshot.getName(), is("snap1")); } @Test public void testTypeUnmatchedAndNameMatchedStillSucceeds() { // Snap 2 is referenced as type SpecialSnapshot so type name won't match NamedSnapshot snapshot = _populatedSource.getSingle(NamedSnapshot.class, "snap2", VersionCorrection.LATEST); assertThat(snapshot.getName(), is("snap2")); } @Test public void testSnapshotHasCorrectType() { // Snap 3 is referenced as type SpecialSnapshot so type name won't match ExtraSpecialSnapshot snapshot = _populatedSource.getSingle(ExtraSpecialSnapshot.class, "snap3", VersionCorrection.LATEST); assertThat(snapshot.getName(), is("snap3")); } @Test public void testWrongTypeIsAvoided() { // Snap 4 is referenced twice with different types ExtraSpecialSnapshot snapshot = _populatedSource.getSingle(ExtraSpecialSnapshot.class, "snap4", VersionCorrection.LATEST); assertThat(snapshot.getName(), is("snap4")); assertThat(snapshot.getId(), is(42)); } @Test public void testWithMultipleMatchesFirstIsReturned() { // Snap 4 is referenced twice with different types SpecialSnapshot snapshot = _populatedSource.getSingle(SpecialSnapshot.class, "snap4", VersionCorrection.LATEST); assertThat(snapshot.getName(), is("snap4")); // We get the first one (41 not 42) assertThat(snapshot.getId(), is(41)); } /** * Show that even if the master has been told the type is X, if the * actual object is not compatible with X it is not returned. */ @Test(expectedExceptions = DataNotFoundException.class) public void testObjectMatchingCriteriaIsNotReturnedIfWrongType() { // Snap 5 is mistyped in the master _populatedSource.getSingle(ExtraSpecialSnapshot.class, "snap5", VersionCorrection.LATEST); } private MasterSnapshotSource createPopulatedSource() { return new MasterSnapshotSource(createPopulatedMock()); } private MarketDataSnapshotMaster createPopulatedMock() { final SearchResponder responder = new SearchResponder(); responder.add(NamedSnapshot.class, createNamedSnapshot("snap1")); responder.add(SpecialSnapshot.class, new SpecialSnapshot("snap2", 2)); responder.add(SpecialSnapshot.class, new ExtraSpecialSnapshot("snap3", 3)); responder.add(SpecialSnapshot.class, new SpecialSnapshot("snap4", 41)); responder.add(SpecialSnapshot.class, new ExtraSpecialSnapshot("snap4", 42)); // Entry is deliberately wrong - master has been misinformed about the type responder.add(SpecialSnapshot.class, createNamedSnapshot("snap5")); MarketDataSnapshotMaster mock = mock(MarketDataSnapshotMaster.class); when(mock.search(Matchers.<MarketDataSnapshotSearchRequest>anyObject())) .thenAnswer(new Answer<MarketDataSnapshotSearchResult>() { @Override public MarketDataSnapshotSearchResult answer(InvocationOnMock invocation) throws Throwable { // Examine the request and use the responder to get matching data MarketDataSnapshotSearchRequest request = (MarketDataSnapshotSearchRequest) invocation.getArguments()[0]; List<MarketDataSnapshotDocument> docs = new ArrayList<>(); final List<NamedSnapshot> matches = responder.getMatches(request.getType(), request.getName()); for (NamedSnapshot match : matches) { docs.add(new MarketDataSnapshotDocument(match)); } return new MarketDataSnapshotSearchResult(docs); } }); return mock; } private NamedSnapshot createNamedSnapshot(final String name) { return new NamedSnapshot() { @Override public String getName() { return name; } @Override public UniqueId getUniqueId() { return null; } @Override public NamedSnapshot withUniqueId(UniqueId uniqueId) { return this; } }; } /** * Holds a set of snapshots and responds appropriately as a * master would. */ private class SearchResponder { /** * The values which are held. */ private final List<SnapshotRecord> values = new ArrayList<>(); /** * Add a new snapshot, recording a type and name. * * @param type the type held for the snapshot, not null * @param snapshot the snapshot, not null */ public void add(Class<? extends NamedSnapshot> type, NamedSnapshot snapshot) { values.add(new SnapshotRecord(type, snapshot)); } public List<NamedSnapshot> getMatches(Class<? extends NamedSnapshot> type, String name) { List<NamedSnapshot> matches = new ArrayList<>(); for (SnapshotRecord value : values) { if (value._name.equals(name) && (type == null || value._type.equals(type))) { matches.add(value._snapshot); } } return matches; } } /** * Simple value class representing a stored snapshot with its name and type. */ private static final class SnapshotRecord { public final Class<? extends NamedSnapshot> _type; public final String _name; public final NamedSnapshot _snapshot; private SnapshotRecord(Class<? extends NamedSnapshot> type, NamedSnapshot snapshot) { this._type = ArgumentChecker.notNull(type, "type"); this._snapshot = ArgumentChecker.notNull(snapshot, "snapshot"); this._name = snapshot.getName(); } } /** * Test implementation of a snapshot. */ private class SpecialSnapshot implements NamedSnapshot { private final String _name; private final int _id; private SpecialSnapshot(String name, int id) { _name = name; _id = id; } @Override public String getName() { return _name; } public int getId() { return _id; } @Override public UniqueId getUniqueId() { return null; } @Override public NamedSnapshot withUniqueId(UniqueId uniqueId) { return this; } } /** * Test subclass implementation of a snapshot. */ private class ExtraSpecialSnapshot extends SpecialSnapshot { private ExtraSpecialSnapshot(String name, int id) { super(name, id); } } }