/*
* Copyright (C) 2012 - present by Yann Le Tallec.
* Please see distribution for license.
*/
package com.assylias.jbloomberg;
import com.bloomberglp.blpapi.Session;
import com.bloomberglp.blpapi.SessionOptions;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import mockit.Mocked;
import mockit.Verifications;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class DefaultBloombergSessionTest {
private static final OffsetDateTime TIME_NOW = OffsetDateTime.now();
private static final LocalDate DATE_NOW = LocalDate.now();
@BeforeClass
public void beforeClass() {
}
@Test(groups = "unit", expectedExceptions = {BloombergException.class},
expectedExceptionsMessageRegExp = ".*bbcom.*")
public void testStart_noBbComm() throws Exception {
final DefaultBloombergSession session = new DefaultBloombergSession();
new MockBloombergUtils(false);
session.start();
}
@Test(groups = "unit", expectedExceptions = IllegalStateException.class,
expectedExceptionsMessageRegExp = ".*start.*")
public void testStart_calledTwiceOpensOneSession(@Mocked final Session s) throws Exception {
final DefaultBloombergSession session = new DefaultBloombergSession();
new MockBloombergUtils(true);
session.start();
session.start();
new Verifications() {
{
s.startAsync();
maxTimes = 1;
}
};
}
@Test(groups = "unit")
public void testStart_allGoodMock(@Mocked final Session s) throws Exception {
new MockBloombergUtils(true);
final DefaultBloombergSession session = new DefaultBloombergSession();
session.start();
new Verifications() {
{
s.startAsync();
times = 1;
}
};
}
@Test(groups = "requires-bloomberg")
public void testStart_allGood() throws Exception {
final DefaultBloombergSession session = new DefaultBloombergSession();
session.start();
session.stop();
}
@Test(groups = "requires-bloomberg")
public void testStart_allGood_withSessionOptions() throws Exception {
SessionOptions so = new SessionOptions();
so.setServerPort(0); //checking that our options are taken into account: this port should throw an exception
final DefaultBloombergSession session = new DefaultBloombergSession(so);
CountDownLatch exceptionRaised = new CountDownLatch(1);
try {
session.start(e -> exceptionRaised.countDown());
assertTrue(exceptionRaised.await(10, TimeUnit.SECONDS));
} finally {
session.stop();
}
}
@Test(groups = "requires-bloomberg", timeOut = 1000)
public void testStart_allGood_withListener() throws Exception {
AtomicReference<SessionState> lastState = new AtomicReference<> ();
List<SessionState> states = new CopyOnWriteArrayList<>();
DefaultBloombergSession session = new DefaultBloombergSession(new SessionOptions(), s -> {
lastState.set(s);
states.add(s);
});
try {
assertEquals(lastState.get(), SessionState.NEW);
assertEquals(session.getSessionState(), SessionState.NEW);
session.start();
assertEquals(lastState.get(), SessionState.STARTING);
assertEquals(session.getSessionState(), SessionState.STARTING);
while(lastState.get() != SessionState.STARTED) Thread.sleep(10);
assertEquals(session.getSessionState(), SessionState.STARTED);
} finally {
session.stop();
assertEquals(lastState.get(), SessionState.TERMINATED);
assertEquals(session.getSessionState(), SessionState.TERMINATED);
}
assertTrue(states.contains(SessionState.CONNECTION_UP));
assertTrue(states.contains(SessionState.CONNECTION_DOWN));
assertEquals(states.size(), 6);
}
@Test(groups = "unit")
public void testClose_doesNothingIfSessionNotStarted(@Mocked final Session s) throws Exception {
final DefaultBloombergSession session = new DefaultBloombergSession();
session.stop();
new Verifications() {
{
s.stop();
times = 0;
}
};
}
@Test(groups = "unit", expectedExceptions = NullPointerException.class,
expectedExceptionsMessageRegExp = ".*request.*")
public void testSubmit_NullRequest() throws Exception {
DefaultBloombergSession session = new DefaultBloombergSession();
session.submit(null);
}
@Test(groups = "unit", expectedExceptions = IllegalStateException.class,
expectedExceptionsMessageRegExp = ".*session.*")
public void testSubmit_SessionNotStarted() throws Exception {
MockRequestBuilder<?> mock = new MockRequestBuilder<>().serviceType(BloombergServiceType.PAGE_DATA);
DefaultBloombergSession session = new DefaultBloombergSession();
session.submit(mock.getMockInstance()).get(2, TimeUnit.SECONDS);
}
@Test(groups = "unit", expectedExceptions = BloombergException.class,
expectedExceptionsMessageRegExp = ".*session.*")
public void testSubmit_SessionStartupFailure() throws Exception {
MockRequestBuilder<?> request = new MockRequestBuilder<>().serviceType(BloombergServiceType.PAGE_DATA);
new MockSession().simulateSessionStartupFailure();
DefaultBloombergSession session = new DefaultBloombergSession();
session.start();
try {
session.submit(request.getMockInstance()).get(2, TimeUnit.SECONDS);
} catch (ExecutionException e) {
throw (Exception) e.getCause();
}
}
@Test(groups = "unit", expectedExceptions = BloombergException.class)
public void testSubmit_SessionThrows() throws Exception {
new MockBloombergUtils(true);
new MockSession();
DefaultBloombergSession session = new DefaultBloombergSession();
session.start();
}
@Test(groups = "unit", expectedExceptions = BloombergException.class)
public void testSubmit_ServiceThrows() throws Exception {
new MockBloombergUtils(true);
MockRequestBuilder<?> request = new MockRequestBuilder<>().serviceType(BloombergServiceType.PAGE_DATA);
new MockSession().simulateStartAsyncOk();
DefaultBloombergSession session = new DefaultBloombergSession();
session.start();
try {
session.submit(request.getMockInstance()).get(2, TimeUnit.SECONDS);
} catch (ExecutionException e) {
throw (Exception) e.getCause();
}
}
@Test(groups = "unit", expectedExceptions = CancellationException.class)
public void testSubmit_RequestCancelled() throws Exception {
new MockBloombergUtils(true);
MockRequestBuilder<?> request = new MockRequestBuilder<>().serviceType(BloombergServiceType.PAGE_DATA);
DefaultBloombergSession session = new DefaultBloombergSession();
session.start();
try {
final Future<?> f = session.submit(request.getMockInstance());
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(100);
f.cancel(true);
} catch (Exception ignore) {
}
}
}).start();
f.get(2, TimeUnit.SECONDS);
} catch (ExecutionException e) {
throw (Exception) e.getCause();
}
}
@Test(groups = "requires-bloomberg")
public void testOpenService_allGood() throws Exception {
final DefaultBloombergSession session = new DefaultBloombergSession();
RequestBuilder<?> request = new HistoricalRequestBuilder("a", "a", DATE_NOW, DATE_NOW);
session.start();
session.submit(request).get(2, TimeUnit.SECONDS);
session.stop();
}
@Test(groups = "requires-bloomberg")
public void testSubscribe() throws Exception {
final DefaultBloombergSession session = new DefaultBloombergSession();
session.start();
session.subscribe(new SubscriptionBuilder().addSecurity("EUR Curncy").addField(RealtimeField.BID));
Thread.sleep(3000);
session.stop();
}
@Test(groups = "requires-bloomberg")
public void testSubscribeWhileLongSubmit() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final DefaultBloombergSession session1 = new DefaultBloombergSession();
final DefaultBloombergSession session2 = new DefaultBloombergSession();
session1.start();
session2.start();
session1.subscribe(new SubscriptionBuilder()
.addSecurity("ESA Index")
.addSecurity("EUR Curncy")
.addSecurity("GBP Curncy")
.addField(RealtimeField.BID_SIZE)
.addField(RealtimeField.BID)
.addField(RealtimeField.ASK_SIZE)
.addField(RealtimeField.ASK)
.addListener(new DataChangeListener() {
@Override
public void dataChanged(DataChangeEvent e) {
latch.countDown();
}
}));
latch.await(); //wait until the real time data starts coming in
Future<IntradayBarData> future = session2.submit(new IntradayBarRequestBuilder("ESA Index", TIME_NOW.minusDays(6), TIME_NOW));
IntradayBarData result = future.get();
session1.stop();
session2.stop();
}
}