package org.marketcetera.event.impl; import static org.junit.Assert.*; import java.math.BigDecimal; import java.util.Date; import java.util.concurrent.atomic.AtomicLong; import org.junit.Before; import org.junit.Test; import org.marketcetera.event.*; import org.marketcetera.event.Messages; import org.marketcetera.marketdata.DateUtils; import org.marketcetera.module.ExpectedFailure; import org.marketcetera.options.ExpirationType; import org.marketcetera.trade.*; import org.marketcetera.util.test.EqualityAssert; /* $License$ */ /** * Tests {@link QuoteEventBuilder}, {@link EquityAskEventImpl}, {@link EquityBidEventImpl}, * {@link OptionAskEventImpl}, and {@link OptionBidEventImpl}. * {@link CurrencyAskEventImpl}, and {@link CurrencyBidEventImpl}. * * @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a> * @version $Id: QuoteEventTest.java 16395 2012-12-10 16:29:14Z colin $ * @since 2.0.0 */ public class QuoteEventTest implements Messages { /** * Run before each test. * * @throws Exception if an error occurs */ @Before public void setup() throws Exception { instrument = equity; useAsk = true; useInstrument = false; } /** * Tests the ability to create various types of {@link QuoteEventBuilder} objects. * * @throws Exception if an unexpected error occurs */ @Test public void builderTypes() throws Exception { instrument = option; useInstrument = false; useAsk = false; verify(setDefaults(getBuilder())); instrument = option; useInstrument = false; useAsk = true; verify(setDefaults(getBuilder())); instrument = option; useInstrument = true; useAsk = false; verify(setDefaults(getBuilder())); instrument = option; useInstrument = true; useAsk = true; verify(setDefaults(getBuilder())); instrument = equity; useInstrument = false; useAsk = false; verify(setDefaults(getBuilder())); instrument = equity; useInstrument = false; useAsk = true; verify(setDefaults(getBuilder())); instrument = equity; useInstrument = true; useAsk = false; verify(setDefaults(getBuilder())); instrument = equity; useInstrument = true; useAsk = true; verify(setDefaults(getBuilder())); instrument = future; useInstrument = false; useAsk = false; verify(setDefaults(getBuilder())); instrument = future; useInstrument = false; useAsk = true; verify(setDefaults(getBuilder())); instrument = future; useInstrument = true; useAsk = false; verify(setDefaults(getBuilder())); instrument = future; useInstrument = true; useAsk = true; verify(setDefaults(getBuilder())); instrument = currency; useInstrument = false; useAsk = false; verify(setDefaults(getBuilder())); instrument = currency; useInstrument = false; useAsk = true; verify(setDefaults(getBuilder())); instrument = currency; useInstrument = true; useAsk = false; verify(setDefaults(getBuilder())); instrument = currency; useInstrument = true; useAsk = true; verify(setDefaults(getBuilder())); // create a new kind of instrument final Instrument unsupportedInstrument = EventTestBase.generateUnsupportedInstrument(); new ExpectedFailure<UnsupportedOperationException>() { @Override protected void run() throws Exception { QuoteEventBuilder.askEvent(unsupportedInstrument); } }; new ExpectedFailure<UnsupportedOperationException>() { @Override protected void run() throws Exception { QuoteEventBuilder.bidEvent(unsupportedInstrument); } }; } /** * Tests that the builder checks the instrument type when creating a builder. * * @throws Exception if an unexpected error occurs */ @Test public void wrongInstrumentType() throws Exception { // create equity builders and supply an option instrument new ExpectedFailure<IllegalArgumentException>(VALIDATION_EQUITY_REQUIRED.getText()) { @Override protected void run() throws Exception { setDefaults(QuoteEventBuilder.equityAskEvent()).withInstrument(option).create(); } }; assertNotNull(setDefaults(QuoteEventBuilder.equityAskEvent()).withInstrument(equity).create()); new ExpectedFailure<IllegalArgumentException>(VALIDATION_EQUITY_REQUIRED.getText()) { @Override protected void run() throws Exception { setDefaults(QuoteEventBuilder.equityBidEvent()).withInstrument(option).create(); } }; assertNotNull(setDefaults(QuoteEventBuilder.equityBidEvent()).withInstrument(equity).create()); // now check option builders with an equity instrument new ExpectedFailure<IllegalArgumentException>(VALIDATION_OPTION_REQUIRED.getText()) { @Override protected void run() throws Exception { setDefaults(QuoteEventBuilder.optionAskEvent()).withInstrument(equity).create(); } }; assertNotNull(setDefaults(QuoteEventBuilder.optionAskEvent()).withInstrument(option).create()); new ExpectedFailure<IllegalArgumentException>(VALIDATION_OPTION_REQUIRED.getText()) { @Override protected void run() throws Exception { setDefaults(QuoteEventBuilder.optionBidEvent()).withInstrument(equity).create(); } }; assertNotNull(setDefaults(QuoteEventBuilder.optionBidEvent()).withInstrument(option).create()); } /** * Tests {@link QuoteEventBuilder#add(QuoteEvent)}, {@link QuoteEventBuilder#change(QuoteEvent, Date, BigDecimal)}, and * {@link QuoteEventBuilder#delete(QuoteEvent)}. * * @throws Exception if an unexpected error occurs */ @Test public void quoteCreators() throws Exception { // generate a quote event of various types (equity vs option && ask vs bid) // all the following events are of action ADD (using various actions as the source) // then make sure the generated event is the same in all ways except the action, which must be ADD instrument = option; useAsk = false; QuoteEvent sourceEvent = generateQuote(QuoteAction.ADD); QuoteEvent generatedEvent = QuoteEventBuilder.add(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.ADD, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = option; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.add(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.ADD, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = equity; useAsk = false; sourceEvent = generateQuote(QuoteAction.DELETE); generatedEvent = QuoteEventBuilder.add(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.ADD, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = equity; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.add(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.ADD, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = future; useAsk = false; sourceEvent = generateQuote(QuoteAction.DELETE); generatedEvent = QuoteEventBuilder.add(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.ADD, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = future; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.add(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.ADD, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = currency; useAsk = false; sourceEvent = generateQuote(QuoteAction.DELETE); generatedEvent = QuoteEventBuilder.add(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.ADD, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = currency; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.add(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.ADD, sourceEvent.getSize(), sourceEvent.getTimestamp()); // repeat the tests generating CHANGE events Date timestamp = new Date(); BigDecimal size = new BigDecimal(100); instrument = option; useAsk = false; sourceEvent = generateQuote(QuoteAction.ADD); generatedEvent = QuoteEventBuilder.change(sourceEvent, timestamp, size); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.CHANGE, size, timestamp); instrument = option; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.change(sourceEvent, timestamp, size); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.CHANGE, size, timestamp); instrument = equity; useAsk = false; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.change(sourceEvent, timestamp, size); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.CHANGE, size, timestamp); instrument = equity; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.change(sourceEvent, timestamp, size); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.CHANGE, size, timestamp); instrument = future; useAsk = false; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.change(sourceEvent, timestamp, size); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.CHANGE, size, timestamp); instrument = future; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.change(sourceEvent, timestamp, size); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.CHANGE, size, timestamp); instrument = currency; useAsk = false; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.change(sourceEvent, timestamp, size); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.CHANGE, size, timestamp); instrument = currency; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.change(sourceEvent, timestamp, size); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.CHANGE, size, timestamp); // repeat the tests generating DELETE events instrument = option; useAsk = false; sourceEvent = generateQuote(QuoteAction.ADD); generatedEvent = QuoteEventBuilder.delete(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.DELETE, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = option; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.delete(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.DELETE, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = equity; useAsk = false; sourceEvent = generateQuote(QuoteAction.DELETE); generatedEvent = QuoteEventBuilder.delete(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.DELETE, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = equity; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.delete(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.DELETE, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = future; useAsk = false; sourceEvent = generateQuote(QuoteAction.DELETE); generatedEvent = QuoteEventBuilder.delete(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.DELETE, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = future; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.delete(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.DELETE, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = currency; useAsk = false; sourceEvent = generateQuote(QuoteAction.DELETE); generatedEvent = QuoteEventBuilder.delete(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.DELETE, sourceEvent.getSize(), sourceEvent.getTimestamp()); instrument = currency; useAsk = true; sourceEvent = generateQuote(QuoteAction.CHANGE); generatedEvent = QuoteEventBuilder.delete(sourceEvent); verifyQuoteEvent(sourceEvent, generatedEvent, QuoteAction.DELETE, sourceEvent.getSize(), sourceEvent.getTimestamp()); } /** * Tests {@link QuoteEventBuilder#hasDeliverable(boolean)}. * * @throws Exception if an unexpected error occurs */ @Test public void hasDeliverable() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); builder.hasDeliverable(false); assertEquals(false, builder.getOption().hasDeliverable()); builder.hasDeliverable(true); assertEquals(true, builder.getOption().hasDeliverable()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withAction(QuoteAction)}. * * @throws Exception if an unexpected error occurs */ @Test public void withAction() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); builder.withAction(null); assertNull(builder.getQuote().getAction()); for(QuoteAction action : QuoteAction.values()) { builder.withAction(action); assertEquals(action, builder.getQuote().getAction()); } verify(builder); } /** * Tests {@link QuoteEventBuilder#withExchange(String)}. * * @throws Exception if an unexpected error occurs */ @Test public void withExchange() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); String exchange = null; builder.withExchange(exchange); assertEquals(exchange, builder.getQuote().getExchange()); exchange = ""; builder.withExchange(exchange); assertEquals(exchange, builder.getQuote().getExchange()); exchange = "exchange"; builder.withExchange(exchange); assertEquals(exchange, builder.getQuote().getExchange()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withExpirationType(ExpirationType)}. * * @throws Exception if an unexpected error occurs */ @Test public void withExpirationType() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); builder.withExpirationType(null); assertNull(builder.getOption().getExpirationType()); for(ExpirationType expirationType : ExpirationType.values()) { builder.withExpirationType(expirationType); assertEquals(expirationType, builder.getOption().getExpirationType()); } verify(builder); } /** * Tests {@link QuoteEventBuilder#withProviderSymbol(String)}. * * @throws Exception if an unexpected error occurs */ @Test public void withProviderSymbol() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); String symbol = null; builder.withProviderSymbol(symbol); assertEquals(symbol, builder.getOption().getProviderSymbol()); assertEquals(symbol, builder.getFuture().getProviderSymbol()); symbol = ""; builder.withProviderSymbol(symbol); assertEquals(symbol, builder.getOption().getProviderSymbol()); assertEquals(symbol, builder.getFuture().getProviderSymbol()); symbol = "MSQ/W/X"; builder.withProviderSymbol(symbol); assertEquals(symbol, builder.getOption().getProviderSymbol()); assertEquals(symbol, builder.getFuture().getProviderSymbol()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withEventType(org.marketcetera.event.EventType)}. * * @throws Exception if an unexpected error occurs */ @Test public void withEventType() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); EventType type = null; builder.withEventType(type); assertEquals(type, builder.getQuote().getEventType()); type = EventType.UNKNOWN; builder.withEventType(type); assertEquals(type, builder.getQuote().getEventType()); type = EventType.SNAPSHOT_PART; builder.withEventType(type); assertEquals(type, builder.getQuote().getEventType()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withContractSize(int)}. * * @throws Exception if an unexpected error occurs */ @Test public void withContractSize() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); builder.withContractSize(Integer.MIN_VALUE); assertEquals(Integer.MIN_VALUE, builder.getFuture().getContractSize()); builder.withContractSize(0); assertEquals(0, builder.getFuture().getContractSize()); builder.withContractSize(Integer.MAX_VALUE); assertEquals(Integer.MAX_VALUE, builder.getFuture().getContractSize()); verify(builder); } /** * Tests {@link QuoteEventBuilder<?>#withInstrument(Instrument)}. * * @throws Exception if an unexpected error occurs */ @Test public void withInstrument() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); instrument = null; builder.withInstrument(instrument); assertEquals(instrument, builder.getQuote().getInstrument()); assertEquals(instrument, builder.getQuote().getInstrumentAsString()); assertEquals(instrument, builder.getOption().getInstrument()); instrument = equity; builder.withInstrument(instrument); assertEquals(instrument, builder.getQuote().getInstrument()); assertEquals(instrument.getSymbol(), builder.getQuote().getInstrumentAsString()); assertFalse(instrument.equals(builder.getOption().getInstrument())); instrument = option; builder = setDefaults(getBuilder()); builder.withInstrument(instrument); assertEquals(instrument, builder.getQuote().getInstrument()); assertEquals(instrument.getSymbol(), builder.getQuote().getInstrumentAsString()); assertEquals(instrument, builder.getOption().getInstrument()); verify(builder); instrument = future; builder = setDefaults(getBuilder()); builder.withInstrument(instrument); assertEquals(instrument, builder.getQuote().getInstrument()); assertEquals(instrument.getSymbol(), builder.getQuote().getInstrumentAsString()); verify(builder); instrument = currency; builder = setDefaults(getBuilder()); builder.withInstrument(instrument); assertEquals(instrument, builder.getQuote().getInstrument()); assertEquals(instrument.getSymbol(), builder.getQuote().getInstrumentAsString()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withMessageId(long)}. * * @throws Exception if an unexpected error occurs */ @Test public void withMessageId() throws Exception { QuoteEventBuilder<?> builder = getBuilder(); setDefaults(builder); builder.withMessageId(Long.MIN_VALUE); assertEquals(Long.MIN_VALUE, builder.getQuote().getMessageId()); builder.withMessageId(-1); assertEquals(-1, builder.getQuote().getMessageId()); builder.withMessageId(Long.MAX_VALUE); assertEquals(Long.MAX_VALUE, builder.getQuote().getMessageId()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withMultiplier(int)}. * * @throws Exception if an unexpected error occurs */ @Test public void withMultiplier() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); builder.withMultiplier(new BigDecimal(Integer.MIN_VALUE)); assertEquals(new BigDecimal(Integer.MIN_VALUE), builder.getOption().getMultiplier()); builder.withMultiplier(BigDecimal.ZERO); assertEquals(BigDecimal.ZERO, builder.getOption().getMultiplier()); builder.withMultiplier(new BigDecimal(Integer.MAX_VALUE)); assertEquals(new BigDecimal(Integer.MAX_VALUE), builder.getOption().getMultiplier()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withPrice(BigDecimal)}. * * @throws Exception if an unexpected error occurs */ @Test public void withPrice() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); BigDecimal price = null; builder.withPrice(price); assertNull(builder.getQuote().getPrice()); price = new BigDecimal(-10); builder.withPrice(price); assertEquals(price, builder.getQuote().getPrice()); price = BigDecimal.ZERO; builder.withPrice(price); assertEquals(price, builder.getQuote().getPrice()); price = BigDecimal.TEN; builder.withPrice(price); assertEquals(price, builder.getQuote().getPrice()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withQuoteDate(String)}. * * @throws Exception if an unexpected error occurs */ @Test public void withQuoteDate() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); String date = null; builder.withQuoteDate(date); assertEquals(date, builder.getQuote().getExchangeTimestamp()); date = ""; builder.withQuoteDate(date); assertEquals(date, builder.getQuote().getExchangeTimestamp()); date = "not-a-date"; builder.withQuoteDate(date); assertEquals(date, builder.getQuote().getExchangeTimestamp()); date = DateUtils.dateToString(new Date()); builder.withQuoteDate(date); assertEquals(date, builder.getQuote().getExchangeTimestamp()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withSize(BigDecimal)}. * * @throws Exception if an unexpected error occurs */ @Test public void withSize() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); BigDecimal size = null; builder.withSize(size); assertNull(builder.getQuote().getSize()); size = new BigDecimal(-10); builder.withSize(size); assertEquals(size, builder.getQuote().getSize()); size = BigDecimal.ZERO; builder.withSize(size); assertEquals(size, builder.getQuote().getSize()); size = BigDecimal.TEN; builder.withSize(size); assertEquals(size, builder.getQuote().getSize()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withSource(Object)}. * * @throws Exception if an unexpected error occurs */ @Test public void withSource() throws Exception { QuoteEventBuilder<?> builder = getBuilder(); setDefaults(builder); // null source builder.withSource(null); assertEquals(null, builder.getQuote().getSource()); // non-null source builder.withSource(this); assertEquals(this, builder.getQuote().getSource()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withTimestamp(Date)}. * * @throws Exception if an unexpected error occurs */ @Test public void withTimestamp() throws Exception { QuoteEventBuilder<?> builder = getBuilder(); setDefaults(builder); // null timestamp builder.withTimestamp(null); assertEquals(null, builder.getQuote().getTimestamp()); // regular timestamp Date timestamp = new Date(); builder.withTimestamp(timestamp); assertEquals(timestamp, builder.getQuote().getTimestamp()); // make a weird timestamp timestamp = new Date(-1); builder.withTimestamp(timestamp); assertEquals(timestamp, builder.create().getTimestamp()); verify(builder); } /** * Tests {@link QuoteEventBuilder#withUnderlyingInstrument(Instrument)}. * * @throws Exception if an unexpected error occurs */ @Test public void withUnderylingInstrument() throws Exception { QuoteEventBuilder<?> builder = setDefaults(getBuilder()); Instrument instrument = null; builder.withUnderlyingInstrument(instrument); assertEquals(instrument, builder.getOption().getUnderlyingInstrument()); instrument = equity; builder.withUnderlyingInstrument(instrument); assertEquals(instrument, builder.getOption().getUnderlyingInstrument()); instrument = future; builder.withUnderlyingInstrument(instrument); assertEquals(instrument, builder.getOption().getUnderlyingInstrument()); instrument = option; builder = setDefaults(getBuilder()); builder.withUnderlyingInstrument(instrument); assertEquals(instrument, builder.getOption().getUnderlyingInstrument()); verify(builder); instrument = currency; builder = setDefaults(getBuilder()); builder.withUnderlyingInstrument(instrument); assertEquals(instrument, builder.getOption().getUnderlyingInstrument()); verify(builder); } /** * Tests event <code>hashCode</code> and <code>equals</code>. * * @throws Exception if an unexpected error occurs */ @Test public void hashCodeAndEquals() throws Exception { QuoteEventBuilder<?> builder = getBuilder(); QuoteEvent event1 = setDefaults(builder).create(); QuoteEvent event2 = builder.create(); QuoteEvent event3 = setDefaults(builder).create(); assertEquals(event1.getMessageId(), event2.getMessageId()); assertFalse(event2.getMessageId() == event3.getMessageId()); EqualityAssert.assertEquality(event1, event2, event3, null, this); } /** * Tests {@link DividendEventImpl} validation. * * @throws Exception if an unexpected error occurs */ @Test public void validation() throws Exception { final QuoteEventBuilder<?> builder = setDefaults(getBuilder()); // check messageId builder.withMessageId(-1); new ExpectedFailure<IllegalArgumentException>(VALIDATION_INVALID_MESSAGEID.getText(builder.getQuote().getMessageId())) { @Override protected void run() throws Exception { builder.create(); } }; setDefaults(builder); // 0 is ok builder.withMessageId(0); verify(builder); // minimum value is ok (asks for a generated id) setDefaults(builder).withMessageId(Long.MIN_VALUE); verify(builder); // maximum value is ok setDefaults(builder).withMessageId(Long.MAX_VALUE); verify(builder); // timestamp // negative timestamp ok (not even sure what this means, maybe 1ms before epoch?) builder.withTimestamp(new Date(-1)); verify(builder); // 0 timestamp setDefaults(builder).withTimestamp(new Date(0)); verify(builder); // null timestamp (requests a new timestamp) setDefaults(builder).withTimestamp(null); verify(builder); // normal timestamp setDefaults(builder).withTimestamp(new Date()); verify(builder); // add validation for other attributes setDefaults(builder).withAction(null); // this is ok - a default is supplied verify(builder); setDefaults(builder).withExchange(null); new ExpectedFailure<IllegalArgumentException>(VALIDATION_NULL_EXCHANGE.getText()) { @Override protected void run() throws Exception { builder.create(); } }; setDefaults(builder).withExchange(""); new ExpectedFailure<IllegalArgumentException>(VALIDATION_NULL_EXCHANGE.getText()) { @Override protected void run() throws Exception { builder.create(); } }; setDefaults(builder).withExchange("exchange"); verify(builder); setDefaults(builder).withQuoteDate(null); new ExpectedFailure<IllegalArgumentException>(VALIDATION_NULL_EXCHANGE_TIMESTAMP.getText()) { @Override protected void run() throws Exception { builder.create(); } }; setDefaults(builder).withQuoteDate(""); new ExpectedFailure<IllegalArgumentException>(VALIDATION_NULL_EXCHANGE_TIMESTAMP.getText()) { @Override protected void run() throws Exception { builder.create(); } }; // this value is ok setDefaults(builder).withQuoteDate("not-a-date"); verify(builder); setDefaults(builder).withQuoteDate(DateUtils.dateToString(new Date())); verify(builder); // instrument setDefaults(builder).withInstrument(null); new ExpectedFailure<IllegalArgumentException>(VALIDATION_EQUITY_REQUIRED.getText()) { @Override protected void run() throws Exception { builder.create(); } }; setDefaults(builder).withInstrument(option); new ExpectedFailure<IllegalArgumentException>(VALIDATION_EQUITY_REQUIRED.getText()) { @Override protected void run() throws Exception { builder.create(); } }; final QuoteEventBuilder<?> optionBuilder = QuoteEventBuilder.optionAskEvent(); instrument = option; setDefaults(optionBuilder).withInstrument(null); new ExpectedFailure<IllegalArgumentException>(VALIDATION_OPTION_REQUIRED.getText()) { @Override protected void run() throws Exception { optionBuilder.create(); } }; setDefaults(optionBuilder).withInstrument(equity); new ExpectedFailure<IllegalArgumentException>(VALIDATION_OPTION_REQUIRED.getText()) { @Override protected void run() throws Exception { optionBuilder.create(); } }; final QuoteEventBuilder<?> futureAskBuilder = QuoteEventBuilder.futureAskEvent(); instrument = future; setDefaults(futureAskBuilder).withInstrument(null); new ExpectedFailure<IllegalArgumentException>(VALIDATION_FUTURE_REQUIRED.getText()) { @Override protected void run() throws Exception { futureAskBuilder.create(); } }; setDefaults(futureAskBuilder).withInstrument(equity); new ExpectedFailure<IllegalArgumentException>(VALIDATION_FUTURE_REQUIRED.getText()) { @Override protected void run() throws Exception { futureAskBuilder.create(); } }; final QuoteEventBuilder<?> futureBidBuilder = QuoteEventBuilder.futureBidEvent(); setDefaults(futureBidBuilder).withInstrument(null); new ExpectedFailure<IllegalArgumentException>(VALIDATION_FUTURE_REQUIRED.getText()) { @Override protected void run() throws Exception { futureBidBuilder.create(); } }; setDefaults(futureBidBuilder).withInstrument(equity); new ExpectedFailure<IllegalArgumentException>(VALIDATION_FUTURE_REQUIRED.getText()) { @Override protected void run() throws Exception { futureBidBuilder.create(); } }; new ExpectedFailure<IllegalArgumentException>(VALIDATION_OPTION_REQUIRED.getText()) { @Override protected void run() throws Exception { optionBuilder.create(); } }; final QuoteEventBuilder<?> currencyAskBuilder = QuoteEventBuilder.currencyAskEvent(); instrument = currency; setDefaults(currencyAskBuilder).withInstrument(null); new ExpectedFailure<IllegalArgumentException>(VALIDATION_CURRENCY_REQUIRED.getText()) { @Override protected void run() throws Exception { currencyAskBuilder.create(); } }; setDefaults(currencyAskBuilder).withInstrument(equity); new ExpectedFailure<IllegalArgumentException>(VALIDATION_CURRENCY_REQUIRED.getText()) { @Override protected void run() throws Exception { currencyAskBuilder.create(); } }; final QuoteEventBuilder<?> currencyBidBuilder = QuoteEventBuilder.currencyBidEvent(); setDefaults(currencyBidBuilder).withInstrument(null); new ExpectedFailure<IllegalArgumentException>(VALIDATION_CURRENCY_REQUIRED.getText()) { @Override protected void run() throws Exception { currencyBidBuilder.create(); } }; setDefaults(currencyBidBuilder).withInstrument(equity); new ExpectedFailure<IllegalArgumentException>(VALIDATION_CURRENCY_REQUIRED.getText()) { @Override protected void run() throws Exception { currencyBidBuilder.create(); } }; } /** * Verifies that the given builder can produce an event of the * correct type with the builder's attributes. * * <p>Note that the builder is assumed to be in a state that * can produce an event without error. * * @param inBuilder a <code>QuoteEventBuilder</code> value * @return a <code>QuoteEvent</code> value * @throws Exception if an unexpected error occurs */ private QuoteEvent verify(QuoteEventBuilder<?> inBuilder) throws Exception { assertNotNull(inBuilder); assertNotNull(inBuilder.toString()); QuoteEvent event = inBuilder.create(); assertNotNull(event); assertNotNull(event.toString()); // special case for action due to setDefaults if(inBuilder.getQuote().getAction() == null) { assertEquals(QuoteAction.ADD, event.getAction()); } else { assertEquals(inBuilder.getQuote().getAction(), event.getAction()); } assertEquals(inBuilder.getQuote().getExchange(), event.getExchange()); assertEquals(inBuilder.getQuote().getExchangeTimestamp(), event.getExchangeTimestamp()); assertEquals(inBuilder.getQuote().getExchangeTimestamp(), event.getQuoteDate()); assertEquals(inBuilder.getQuote().getInstrument(), event.getInstrument()); // check the instrumentAsString method assertEquals(inBuilder.getQuote().getInstrumentAsString(), event.getInstrumentAsString()); // there is a special case for messageId - if equal to Long.MIN_VALUE // then it will be some value >= 0 if(inBuilder.getQuote().getMessageId() == Long.MIN_VALUE) { assertTrue(event.getMessageId() >= 0); } else { assertEquals(inBuilder.getQuote().getMessageId(), event.getMessageId()); } assertEquals(inBuilder.getQuote().getPrice(), event.getPrice()); assertEquals(inBuilder.getQuote().getSize(), event.getSize()); assertEquals(inBuilder.getQuote().getSource(), event.getSource()); assertEquals(inBuilder.getQuote().getEventType(), event.getEventType()); assertFalse(event.getEventType() == EventType.SNAPSHOT_FINAL); event.setEventType(EventType.SNAPSHOT_FINAL); assertEquals(EventType.SNAPSHOT_FINAL, event.getEventType()); // there's a special case for timestamp, too if(inBuilder.getQuote().getTimestamp() == null) { assertNotNull(event.getTimestamp()); assertEquals(event.getTimestamp().getTime(), event.getTimeMillis()); } else { assertEquals(inBuilder.getQuote().getTimestamp(), event.getTimestamp()); assertEquals(inBuilder.getQuote().getTimeMillis(), event.getTimeMillis()); } if(event instanceof OptionEvent) { OptionEvent optionEvent = (OptionEvent)event; assertEquals(inBuilder.getOption().getExpirationType(), optionEvent.getExpirationType()); assertEquals(inBuilder.getOption().getInstrument(), optionEvent.getInstrument()); assertEquals(inBuilder.getOption().getInstrument().getSymbol(), optionEvent.getInstrumentAsString()); assertEquals(inBuilder.getOption().getMultiplier(), optionEvent.getMultiplier()); assertEquals(inBuilder.getOption().getUnderlyingInstrument(), optionEvent.getUnderlyingInstrument()); assertEquals(inBuilder.getOption().hasDeliverable(), optionEvent.hasDeliverable()); assertEquals(inBuilder.getOption().getProviderSymbol(), optionEvent.getProviderSymbol()); } if(event instanceof FutureEvent) { FutureEvent futureEvent = (FutureEvent)event; assertEquals(inBuilder.getFuture().getProviderSymbol(), futureEvent.getProviderSymbol()); assertEquals(inBuilder.getFuture().getContractSize(), futureEvent.getContractSize()); } Object newSource = new Object(); event.setSource(newSource); assertEquals(newSource, event.getSource()); return event; } /** * Sets valid defaults in the given builder. * * @param inBuilder a <code>QuoteEventBuilder</code> value * @return a <code>QuoteEventBuilder</code> value * @throws Exception if an unexpected error occurs */ private QuoteEventBuilder<?> setDefaults(QuoteEventBuilder<?> inBuilder) throws Exception { long millis = System.currentTimeMillis(); long millisInADay = 1000 * 60 * 60 * 24; int counter = 0; inBuilder.hasDeliverable(false); inBuilder.withAction(QuoteAction.ADD); inBuilder.withExchange("exchange"); inBuilder.withExpirationType(ExpirationType.AMERICAN); inBuilder.withProviderSymbol("MSQ/K/X"); inBuilder.withEventType(EventType.UPDATE_FINAL); inBuilder.withInstrument(instrument); inBuilder.withMessageId(idCounter.incrementAndGet()); inBuilder.withMultiplier(BigDecimal.ZERO); inBuilder.withPrice(BigDecimal.ONE); inBuilder.withQuoteDate(DateUtils.dateToString(new Date(millis + (millisInADay * counter++)))); inBuilder.withSize(BigDecimal.TEN); inBuilder.withTimestamp(new Date()); inBuilder.withUnderlyingInstrument(instrument); inBuilder.withContractSize(3600); return inBuilder; } /** * Gets the builder to use for testing. * * @return a <code>QuoteEventBuilder<?></code> value */ private QuoteEventBuilder<?> getBuilder() { if(useInstrument) { if(useAsk) { return QuoteEventBuilder.askEvent(instrument); } else { return QuoteEventBuilder.bidEvent(instrument); } } else { if(instrument instanceof Equity) { if(useAsk) { return QuoteEventBuilder.equityAskEvent(); } else { return QuoteEventBuilder.equityBidEvent(); } } else if(instrument instanceof Option) { if(useAsk) { return QuoteEventBuilder.optionAskEvent(); } else { return QuoteEventBuilder.optionBidEvent(); } } else if(instrument instanceof Future) { if(useAsk) { return QuoteEventBuilder.futureAskEvent(); } else { return QuoteEventBuilder.futureBidEvent(); } } else if(instrument instanceof Currency) { if(useAsk) { return QuoteEventBuilder.currencyAskEvent(); } else { return QuoteEventBuilder.currencyBidEvent(); } } else { throw new UnsupportedOperationException(); } } } /** * Verifies that the given generated event matches the source event using the given * action, size, and timestamp. * * @param inSourceEvent a <code>QuoteEvent</code> value * @param inGeneratedEvent a <code>QuoteEvent</code> value * @param inExpectedAction a <code>QuoteAction</code> value * @param inExpectedSize a <code>BigDecimal</code> value * @param inExpectedTimestamp a <code>Date</code> value */ private void verifyQuoteEvent(QuoteEvent inSourceEvent, QuoteEvent inGeneratedEvent, QuoteAction inExpectedAction, BigDecimal inExpectedSize, Date inExpectedTimestamp) { assertEquals(inExpectedAction, inGeneratedEvent.getAction()); assertEquals(inSourceEvent.getExchange(), inGeneratedEvent.getExchange()); assertEquals(inSourceEvent.getExchangeTimestamp(), inGeneratedEvent.getExchangeTimestamp()); assertEquals(inSourceEvent.getInstrument(), inGeneratedEvent.getInstrument()); assertEquals(inSourceEvent.getMessageId(), inGeneratedEvent.getMessageId()); assertEquals(inSourceEvent.getPrice(), inGeneratedEvent.getPrice()); assertEquals(inExpectedSize, inGeneratedEvent.getSize()); assertEquals(inSourceEvent.getSource(), inGeneratedEvent.getSource()); assertEquals(inExpectedTimestamp, inGeneratedEvent.getTimestamp()); assertEquals(inSourceEvent.getEventType(), inGeneratedEvent.getEventType()); if(inSourceEvent instanceof OptionEvent) { OptionEvent expectedOptionEvent = (OptionEvent)inSourceEvent; OptionEvent actualOptionEvent = (OptionEvent)inGeneratedEvent; assertEquals(expectedOptionEvent.getExpirationType(), actualOptionEvent.getExpirationType()); assertEquals(expectedOptionEvent.getInstrument(), actualOptionEvent.getInstrument()); assertEquals(expectedOptionEvent.getMultiplier(), actualOptionEvent.getMultiplier()); assertEquals(expectedOptionEvent.getUnderlyingInstrument(), actualOptionEvent.getUnderlyingInstrument()); assertEquals(expectedOptionEvent.getProviderSymbol(), actualOptionEvent.getProviderSymbol()); } if(inSourceEvent instanceof FutureEvent) { FutureEvent expectedFutureEvent = (FutureEvent)inSourceEvent; FutureEvent actualFutureEvent = (FutureEvent)inGeneratedEvent; assertEquals(expectedFutureEvent.getProviderSymbol(), actualFutureEvent.getProviderSymbol()); assertEquals(expectedFutureEvent.getContractSize(), actualFutureEvent.getContractSize()); } if(inSourceEvent instanceof CurrencyEvent) { CurrencyEvent expectedCurrencyEvent = (CurrencyEvent)inSourceEvent; CurrencyEvent actualCurrencyEvent = (CurrencyEvent)inGeneratedEvent; assertEquals(expectedCurrencyEvent.getInstrument().getSymbol(), actualCurrencyEvent.getInstrument().getSymbol()); assertEquals(expectedCurrencyEvent.getContractSize(), actualCurrencyEvent.getContractSize()); } } /** * Generates a <code>QuoteEvent<?></code> value. * * @param inAction a <code>QuoteAction</code> value * @return a <code>QuoteEvent<?></code> value */ private QuoteEvent generateQuote(QuoteAction inAction) { if(instrument instanceof Equity) { if(useAsk) { return EventTestBase.generateEquityAskEvent(equity, inAction); } else { return EventTestBase.generateEquityBidEvent(equity, inAction); } } else if(instrument instanceof Option) { if(useAsk) { return EventTestBase.generateOptionAskEvent(option, inAction); } else { return EventTestBase.generateOptionBidEvent(option, inAction); } } else if(instrument instanceof Future) { if(useAsk) { return EventTestBase.generateFutureAskEvent(future, inAction); } else { return EventTestBase.generateFutureBidEvent(future, inAction); } } else if(instrument instanceof Currency) { if(useAsk) { return EventTestBase.generateCurrencyAskEvent(currency, inAction); } else { return EventTestBase.generateCurrencyBidEvent(currency, inAction); } } else { throw new UnsupportedOperationException(); } } /** * indicates whether to use Bid or Ask events to create builders */ private boolean useAsk = true; /** * indicates whether to use the instrument constructor or not */ private boolean useInstrument = false; /** * test instrument */ private final Equity equity = new Equity("METC"); /** * test option */ private final Option option = new Option("MSFT", "20100319", BigDecimal.ONE, OptionType.Call); /** * test future */ private final Future future = new Future("GOOG", FutureExpirationMonth.DECEMBER, 2015); /** * test currency */ private final Currency currency = new Currency("USD","INR","",""); /** * indicates the test instrument to use */ private Instrument instrument = equity; /** * counter used to guarantee unique events */ private static final AtomicLong idCounter = new AtomicLong(0); }