package org.marketcetera.marketdata; import static org.junit.Assert.assertNotNull; import static org.marketcetera.marketdata.Content.LATEST_TICK; import static org.marketcetera.marketdata.Content.LEVEL_2; import static org.marketcetera.marketdata.Content.OPEN_BOOK; import static org.marketcetera.marketdata.Content.TOP_OF_BOOK; import java.util.*; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.marketcetera.core.CoreException; import org.marketcetera.core.LoggerConfiguration; import org.marketcetera.module.ExpectedFailure; import org.marketcetera.util.log.I18NBoundMessage1P; /* $License$ */ /** * Base class for market data message translator tests. * * @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a> * @version $Id: MarketDataMessageTranslatorTestBase.java 16154 2012-07-14 16:34:05Z colin $ * @since 1.5.0 */ public abstract class MarketDataMessageTranslatorTestBase<ResponseType> implements Messages { /** * Verifies that the actual response matches the expected values. * * @param inActualResponse a <code>ResponseType</code> value * @param inExpectedExchange a <code>String</code> value * @param inExpectedContent a <code>Content[]</code> value * @param inExpectedSymbols a <code>String[]</code> value * @throws Exception if an error occurs */ protected abstract void verifyResponse(ResponseType inActualResponse, String inExpectedExchange, Content[] inExpectedContent, String[] inExpectedSymbols) throws Exception; /** * Gets a translator of the proper type. * * @return a <code>DataRequestTranslator<ResponseType></code> value */ protected abstract DataRequestTranslator<ResponseType> getTranslator(); /** * Gets the capabilities this translator is expected to support and should be tested. * * @return a <code>Set<Content></code> value */ protected abstract Set<Content> getCapabilities(); /** * the translator to use for these tests */ protected DataRequestTranslator<ResponseType> translator; /** * Run once before all tests. */ @BeforeClass public static void once() { LoggerConfiguration.logSetup(); } /** * Sets up data before each test. */ @Before public void setup() { translator = getTranslator(); } /** * Tests that the translator instance is instantiated properly. * * @throws Exception if an error occurs */ @Test public void getInstance() throws Exception { assertNotNull(translator); } /** * Tests the ability of the translator to translate messages. * * @throws Exception if an error occurs */ @Test public void translateMarketDataRequest() throws Exception { new ExpectedFailure<IllegalArgumentException>(new I18NBoundMessage1P(INVALID_SYMBOLS, Arrays.toString(new String[] { "" } )).getText()) { protected void run() throws Exception { doMarketDataTest(null, ""); } }; new ExpectedFailure<IllegalArgumentException>() { protected void run() throws Exception { doMarketDataTest(null, (String[])null); } }; String[][] symbols = new String[][] { { "GOOG" }, { "GOOG","YHOO","JAVA" } }; String[] exchanges = new String[] { null, "", "Q", "METC" }; for(int symbolCounter=0;symbolCounter<symbols.length;symbolCounter++) { for(int exchangeCounter=0;exchangeCounter<exchanges.length;exchangeCounter++) { doMarketDataTest(exchanges[exchangeCounter], symbols[symbolCounter]); } } } /** * Indicates if the underlying adapter supports the given contents. * * <p>Subclasses may override this method. The default implementation indicates * if the given content is part of the capabilities asserted by {@link #getCapabilities()}. * Typically, this method would be overridden if the underlying adapter provides a dynamic * set of capabilities dependent on logging in to the actual source. * * <p>The semantics of this method are that the underlying adapter has to support all of * the given contents. * * @param inContent a <code>Set<Content></code> value * @return a <code>boolean</code> value */ protected boolean supports(Set<Content> inContent) { return getCapabilities().containsAll(inContent); } /** * Executes a test iteration for the given exchange and security list. * * @param inExchange a <code>String</code> value containing an exchange to use or <code>null</code> * @param inSecurityList a <code>String[]</code> value containing symbols * * @throws Exception if an error occurs */ private void doMarketDataTest(String inExchange, String... inSecurityList) throws Exception { List<List<Content>> contents = new ArrayList<List<Content>>(); // first, generate a list of single contents of all types for(Content content : Content.values()) { contents.add(new ArrayList<Content>(EnumSet.of(content))); } // next, generate a few permutations contents.add(Arrays.asList(new Content[] { TOP_OF_BOOK,LATEST_TICK } )); contents.add(Arrays.asList(new Content[] { TOP_OF_BOOK,LATEST_TICK,OPEN_BOOK } )); contents.add(Arrays.asList(new Content[] { TOP_OF_BOOK,LATEST_TICK,OPEN_BOOK,LEVEL_2 } )); for(List<Content> content : contents) { final MarketDataRequestBuilder builder = MarketDataRequestBuilder.newRequest().withSymbols(inSecurityList).withContent(content.toArray(new Content[content.size()])); if(inExchange != null && !inExchange.isEmpty()) { builder.withExchange(inExchange); } if(supports(new HashSet<Content>(content))) { verifyResponse(translator.fromDataRequest(builder.create()), inExchange, content.toArray(new Content[content.size()]), inSecurityList); } else { new ExpectedFailure<CoreException>(UNSUPPORTED_REQUEST) { protected void run() throws Exception { translator.fromDataRequest(builder.create()); } }; } } } }