package org.marketcetera.saclient.rpc; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.net.DatagramSocket; import java.net.ServerSocket; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.io.FileUtils; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.marketcetera.core.LoggerConfiguration; import org.marketcetera.marketdata.MarketDataFeedTestBase; import org.marketcetera.module.DataFlowID; import org.marketcetera.module.ExpectedFailure; import org.marketcetera.module.ModuleInfo; import org.marketcetera.module.ModuleState; import org.marketcetera.module.ModuleURN; import org.marketcetera.saclient.ConnectionException; import org.marketcetera.saclient.ConnectionStatusListener; import org.marketcetera.saclient.CreateStrategyParameters; import org.marketcetera.saclient.SAClientParameters; import org.marketcetera.trade.TradeContextClassProvider; import org.marketcetera.util.log.SLF4JLoggerProxy; import org.marketcetera.util.rpc.RpcServer; import org.marketcetera.util.ws.stateful.SessionManager; /* $License$ */ /** * Tests {@link RpcSAClientImpl}. * * @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a> * @version $Id: RpcSAClientImplTest.java 16901 2014-05-11 16:14:11Z colin $ * @since 2.4.0 */ public class RpcSAClientImplTest { /** * Runs once before all tests. * * @throws Exception if an unexpected error occurs */ @BeforeClass public static void once() throws Exception { LoggerConfiguration.logSetup(); } /** * Runs before each test. * * @throws Exception if an unexpected error occurs */ @Before public void setup() throws Exception { stopClientServer(); hostname = "127.0.0.1"; port = -1; sessionManager = new SessionManager<MockSession>(); authenticator = new MockAuthenticator(); serviceAdapter = new MockSAClientServiceAdapter(); startClientServer(); assertTrue(server.isRunning()); assertTrue(client.isRunning()); } /** * Runs after each test. * * @throws Exception if an unexpected error occurs */ @After public void after() throws Exception { stopClientServer(); } /** * Tests disconnection and reconnection. * * @throws Exception if an unexpected error occurs */ @Test public void testDisconnection() throws Exception { final AtomicBoolean status = new AtomicBoolean(false); ConnectionStatusListener statusListener = new ConnectionStatusListener() { @Override public void receiveConnectionStatus(boolean inStatus) { status.set(inStatus); } }; client.addConnectionStatusListener(statusListener); assertTrue(status.get()); // kill the server server.stop(); assertFalse(server.isRunning()); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return !client.isRunning(); } }); assertFalse(status.get()); server.start(); assertTrue(server.isRunning()); MarketDataFeedTestBase.wait(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return client.isRunning(); } }); assertTrue(status.get()); } /** * Tests {@link RpcSAClientImpl#getProviders()}. * * @throws Exception if an unexpected error occurs */ @Test public void testGetProviders() throws Exception { List<ModuleURN> providersToReturn = serviceAdapter.getProvidersToReturn(); assertTrue(providersToReturn.isEmpty()); assertEquals(0, serviceAdapter.getProvidersCount().get()); List<ModuleURN> providers = client.getProviders(); assertEquals(providersToReturn, providers); assertEquals(1, serviceAdapter.getProvidersCount().get()); providersToReturn.add(new ModuleURN("this:is:provider")); providersToReturn.add(new ModuleURN("this:is:otherprovider")); providers = client.getProviders(); assertEquals(providersToReturn, providers); assertEquals(2, serviceAdapter.getProvidersCount().get()); } /** * Tests {@link RpcSAClientImpl#getInstances()}. * * @throws Exception if an unexpected error occurs */ @Test public void testGetInstances() throws Exception { List<ModuleURN> instancesToReturn = serviceAdapter.getInstancesToReturn(); assertTrue(instancesToReturn.isEmpty()); assertTrue(serviceAdapter.getInstancesRequests().isEmpty()); ModuleURN provider = new ModuleURN("this:is:provider"); List<ModuleURN> instances = client.getInstances(provider); assertEquals(instancesToReturn, instances); assertEquals(1, serviceAdapter.getInstancesRequests().size()); instancesToReturn.add(new ModuleURN("this:is:instance:first")); instancesToReturn.add(new ModuleURN("this:is:instance:second")); instances = client.getInstances(provider); assertEquals(instancesToReturn, instances); assertEquals(2, serviceAdapter.getInstancesRequests().size()); } /** * Tests {@link RpcSAClientImpl#getModuleInfo(ModuleURN)}. * * @throws Exception if an unexpected error occurs */ @Test public void testGetModuleInfo() throws Exception { assertNull(serviceAdapter.getModuleInfoToReturn()); assertTrue(serviceAdapter.getModuleInfoRequests().isEmpty()); ModuleURN instance = new ModuleURN("this:is:instance:first"); ModuleInfo info = client.getModuleInfo(instance); assertNull(info); ModuleInfo infoToReturn = new ModuleInfo(instance, ModuleState.CREATED, new DataFlowID[0], new DataFlowID[] { new DataFlowID("some-data-flow-id"), new DataFlowID("some-other-data-flow-id") }, new Date(), new Date(), new Date(), true, false, true, false, true, null, "some failure", Integer.MAX_VALUE, true, 0); serviceAdapter.setModuleInfoToReturn(infoToReturn); ModuleInfo returnedInfo = client.getModuleInfo(instance); assertNotNull(returnedInfo); } /** * Tests {@link RpcSAClientImpl#start(ModuleURN)}. * * @throws Exception if an unexpected error occurs */ @Test public void testStart() throws Exception { assertTrue(serviceAdapter.getStartRequests().isEmpty()); ModuleURN instance = new ModuleURN("this:is:instance:first"); client.start(instance); assertEquals(1, serviceAdapter.getStartRequests().size()); } /** * Tests {@link RpcSAClientImpl#stop(ModuleURN)}. * * @throws Exception if an unexpected error occurs */ @Test public void testStop() throws Exception { assertTrue(serviceAdapter.getStopRequests().isEmpty()); ModuleURN instance = new ModuleURN("this:is:instance:first"); client.stop(instance); assertEquals(1, serviceAdapter.getStopRequests().size()); } /** * Tests {@link RpcSAClientImpl#delete(ModuleURN)}. * * @throws Exception if an unexpected error occurs */ @Test public void testDelete() throws Exception { assertTrue(serviceAdapter.getDeleteRequests().isEmpty()); ModuleURN instance = new ModuleURN("this:is:instance:first"); client.delete(instance); assertEquals(1, serviceAdapter.getDeleteRequests().size()); } /** * Tests {@link RpcSAClientImpl#getProperties(ModuleURN)}. * * @throws Exception if an unexpected error occurs */ @Test public void testGetProperties() throws Exception { Map<String,Object> propertiesToReturn = serviceAdapter.getPropertiesToReturn(); assertTrue(propertiesToReturn.isEmpty()); ModuleURN instance = new ModuleURN("this:is:instance:first"); Map<String,Object> returnedProperties = client.getProperties(instance); assertEquals(propertiesToReturn, returnedProperties); propertiesToReturn.put("key1", "value1"); propertiesToReturn.put("key2", "value2"); returnedProperties = client.getProperties(instance); assertEquals(propertiesToReturn, returnedProperties); } /** * Tests {@link RpcSAClientImpl#setProperties(ModuleURN, Map)}. * * @throws Exception if an unexpected error occurs */ @Test public void testSetProperties() throws Exception { Map<String,Object> propertiesToReturn = serviceAdapter.getPropertiesToReturn(); assertTrue(propertiesToReturn.isEmpty()); ModuleURN instance = new ModuleURN("this:is:instance:first"); Map<String,Object> returnedProperties = client.setProperties(instance, propertiesToReturn); assertEquals(propertiesToReturn, returnedProperties); propertiesToReturn.put("key1", "value1"); propertiesToReturn.put("key2", "value2"); returnedProperties = client.setProperties(instance, propertiesToReturn); assertEquals(propertiesToReturn, returnedProperties); } /** * Tests {@link RpcSAClientImpl#createStrategy(org.marketcetera.saclient.CreateStrategyParameters)}. * * @throws Exception if an unexpected error occurs */ @Test public void testCreateStrategy() throws Exception { assertTrue(serviceAdapter.getCreateStrategyRequests().isEmpty()); CreateStrategyParameters parameters = new CreateStrategyParameters("instance", "strategy", "language", generateStrategySource(), "key=value:key1=value1:key2=value2", true); ModuleURN instance = new ModuleURN("this:is:my:instance"); serviceAdapter.setCreateModuleURNToReturn(instance); instance = client.createStrategy(parameters); assertNotNull(instance); } /** * Tests {@link RpcSAClientImpl#getStrategyCreateParms(ModuleURN)}. * * @throws Exception if an unexpected error occurs */ @Test public void testGetStrategyCreateParms() throws Exception { ModuleURN instance = new ModuleURN("this:is:my:instance"); CreateStrategyParameters parameters = new CreateStrategyParameters("instance", "strategy", "language", generateStrategySource(), "key=value:key1=value1:key2=value2", true); serviceAdapter.setParametersToReturn(parameters); parameters = client.getStrategyCreateParms(instance); assertNotNull(parameters); } /** * Tests {@link RpcSAClientImpl#sendData(Object)}. * * @throws Exception if an unexpected error occurs */ @Test public void testSendData() throws Exception { assertNull(serviceAdapter.getSentData()); new ExpectedFailure<ConnectionException>() { @Override protected void run() throws Exception { client.sendData(this); } }; String data = "Lorum ipsum"; client.sendData(data); assertEquals(data, serviceAdapter.getSentData()); } /** * Generates a file with strategy source. * * @return a <code>File</cod> value * @throws IOException if an error occurs */ private File generateStrategySource() throws IOException { File tmpFile = File.createTempFile("src", "txt"); tmpFile.deleteOnExit(); FileUtils.writeStringToFile(tmpFile, "Lorum ipsum"); return tmpFile; } /** * Stops the test client and server. * * @throws Exception if an unexpected error occurs */ private void stopClientServer() throws Exception { if(client != null && client.isRunning()) { try { client.stop(); } catch (Exception e) { SLF4JLoggerProxy.warn(this, e); } } client = null; if(server != null && server.isRunning()) { try { server.stop(); } catch (Exception e) { SLF4JLoggerProxy.warn(this, e); } } server = null; } /** * Starts the test client server and client. * * @throws Exception if an unexpected error occurs */ private void startClientServer() throws Exception { server = new RpcServer<MockSession>(); server.setHostname(hostname); if(port == -1) { port = assignPort(); } server.setPort(port); server.setSessionManager(sessionManager); server.setAuthenticator(authenticator); server.setContextClassProvider(TradeContextClassProvider.INSTANCE); SAClientRpcService<MockSession> service = new SAClientRpcService<>(); server.getServiceSpecs().add(service); service.setServiceAdapter(serviceAdapter); server.setContextClassProvider(SAClientContextClassProvider.INSTANCE); server.start(); client = new RpcSAClientFactory().create(new SAClientParameters("username", "password".toCharArray(), "", hostname, port, null, false)); client.setContextClassProvider(SAClientContextClassProvider.INSTANCE); client.start(); } /** * Assigns a port value that is not in use. * * @return an <code>int</code> value */ private int assignPort() { for(int i=MIN_PORT_NUMBER;i<=MAX_PORT_NUMBER;i++) { try(ServerSocket ss = new ServerSocket(i)) { ss.setReuseAddress(true); try(DatagramSocket ds = new DatagramSocket(i)) { ds.setReuseAddress(true); return i; } } catch (IOException e) {} } throw new IllegalArgumentException("No available ports"); } /** * test service adapter value */ private MockSAClientServiceAdapter serviceAdapter; /** * test authenticator value */ private MockAuthenticator authenticator; /** * test session manager value */ private SessionManager<MockSession> sessionManager; /** * test hostname */ private String hostname; /** * test port */ private int port; /** * minimum test port value */ private static final int MIN_PORT_NUMBER = 10000; /** * maximum test port value */ private static final int MAX_PORT_NUMBER = 65535; /** * test client value */ private RpcSAClientImpl client; /** * tests server value */ private RpcServer<MockSession> server; }