/projects/OG-Util/tests/unit/com/opengamma/transport/socket/SocketFudgeConnectionConduitTest.java

https://github.com/gsteri1/OG-Platform · Java · 291 lines · 248 code · 23 blank · 20 comment · 19 complexity · 38992959cbe6c4cbed09ba94be81f984 MD5 · raw file

  1. /**
  2. * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
  3. *
  4. * Please see distribution for license.
  5. */
  6. package com.opengamma.transport.socket;
  7. import static org.testng.AssertJUnit.assertEquals;
  8. import static org.testng.AssertJUnit.assertNotNull;
  9. import static org.testng.AssertJUnit.assertTrue;
  10. import static org.testng.AssertJUnit.fail;
  11. import java.net.InetAddress;
  12. import java.util.concurrent.ExecutorService;
  13. import java.util.concurrent.Executors;
  14. import java.util.concurrent.atomic.AtomicInteger;
  15. import org.fudgemsg.FudgeContext;
  16. import org.fudgemsg.FudgeMsg;
  17. import org.fudgemsg.FudgeMsgEnvelope;
  18. import org.fudgemsg.MutableFudgeMsg;
  19. import org.testng.annotations.Test;
  20. import com.opengamma.transport.CollectingFudgeMessageReceiver;
  21. import com.opengamma.transport.FudgeConnection;
  22. import com.opengamma.transport.FudgeConnectionReceiver;
  23. import com.opengamma.transport.FudgeMessageReceiver;
  24. import com.opengamma.transport.FudgeMessageSender;
  25. import com.opengamma.util.test.Timeout;
  26. /**
  27. * Tests the SocketFudgeConnection and ServerSocketFudgeConnectionReceiver classes
  28. */
  29. @Test
  30. public class SocketFudgeConnectionConduitTest {
  31. private final AtomicInteger _counter = new AtomicInteger();
  32. private FudgeMsg createMessage() {
  33. final MutableFudgeMsg message = FudgeContext.GLOBAL_DEFAULT.newMessage();
  34. message.add("counter", _counter.incrementAndGet());
  35. return message;
  36. }
  37. public void simpleTest() throws Exception {
  38. final FudgeMsg testMessage1 = createMessage();
  39. final FudgeMsg testMessage2 = createMessage();
  40. // receiver will respond to testMessage1 with testMessage2
  41. final FudgeConnectionReceiver serverReceiver = new FudgeConnectionReceiver() {
  42. @Override
  43. public void connectionReceived(FudgeContext fudgeContext, FudgeMsgEnvelope message, FudgeConnection connection) {
  44. assertNotNull(fudgeContext);
  45. assertNotNull(message);
  46. assertNotNull(connection);
  47. assertEquals(testMessage1, message.getMessage());
  48. connection.getFudgeMessageSender().send(testMessage2);
  49. }
  50. };
  51. final ServerSocketFudgeConnectionReceiver server = new ServerSocketFudgeConnectionReceiver(FudgeContext.GLOBAL_DEFAULT, serverReceiver);
  52. server.start();
  53. final SocketFudgeConnection client = new SocketFudgeConnection(FudgeContext.GLOBAL_DEFAULT);
  54. client.setInetAddress(InetAddress.getLocalHost());
  55. client.setPortNumber(server.getPortNumber());
  56. // connect and send testMessage1, then verify that testMessage2 was sent back
  57. final CollectingFudgeMessageReceiver clientReceiver = new CollectingFudgeMessageReceiver();
  58. client.setFudgeMessageReceiver(clientReceiver);
  59. client.getFudgeMessageSender().send(testMessage1);
  60. final FudgeMsgEnvelope envelope = clientReceiver.waitForMessage(Timeout.standardTimeoutMillis());
  61. assertNotNull(envelope);
  62. assertEquals(testMessage2, envelope.getMessage());
  63. client.stop();
  64. server.stop();
  65. }
  66. public void messageReceiverTest() throws Exception {
  67. final FudgeMsg testMessage1 = createMessage();
  68. final FudgeMsg testMessage2 = createMessage();
  69. final FudgeMsg testMessage3 = createMessage();
  70. final CollectingFudgeMessageReceiver message3Receiver = new CollectingFudgeMessageReceiver();
  71. // receiver will ignore testMessage1
  72. // after receiving testMessage2, will set the message receiver on the connection
  73. // it shouldn't be called again - messages should be dispatched to the connection's receiver
  74. final FudgeConnectionReceiver serverReceiver = new FudgeConnectionReceiver() {
  75. private int _count;
  76. @Override
  77. public void connectionReceived(final FudgeContext fudgeContext, final FudgeMsgEnvelope message, final FudgeConnection connection) {
  78. assertNotNull(fudgeContext);
  79. assertNotNull(message);
  80. assertNotNull(connection);
  81. switch (_count++) {
  82. case 0:
  83. assertEquals(testMessage1, message.getMessage());
  84. break;
  85. case 1:
  86. assertEquals(testMessage2, message.getMessage());
  87. connection.setFudgeMessageReceiver(message3Receiver);
  88. break;
  89. default:
  90. fail("Shouldn't have been called a third time");
  91. break;
  92. }
  93. }
  94. };
  95. final ServerSocketFudgeConnectionReceiver server = new ServerSocketFudgeConnectionReceiver(FudgeContext.GLOBAL_DEFAULT, serverReceiver);
  96. server.start();
  97. final SocketFudgeConnection client = new SocketFudgeConnection(FudgeContext.GLOBAL_DEFAULT);
  98. client.setInetAddress (InetAddress.getLocalHost ());
  99. client.setPortNumber (server.getPortNumber ());
  100. // send messages 1, 2, 3 and verify 3 went to the test receiver
  101. client.getFudgeMessageSender().send(testMessage1);
  102. assertTrue(message3Receiver.getMessages().isEmpty());
  103. client.getFudgeMessageSender().send(testMessage2);
  104. assertTrue(message3Receiver.getMessages().isEmpty());
  105. client.getFudgeMessageSender().send(testMessage3);
  106. final FudgeMsgEnvelope envelope = message3Receiver.waitForMessage(Timeout.standardTimeoutMillis());
  107. assertNotNull(envelope);
  108. assertEquals(testMessage3, envelope.getMessage());
  109. server.stop();
  110. client.stop();
  111. }
  112. private class MessageReadWrite extends Thread implements FudgeMessageReceiver {
  113. private static final int NUM_MESSAGES = 1000;
  114. private FudgeMessageSender _sender;
  115. private int _received;
  116. @Override
  117. public void run() {
  118. for (int i = 0; i < NUM_MESSAGES; i++) {
  119. final FudgeMsg message = createMessage();
  120. _sender.send(message);
  121. }
  122. }
  123. @Override
  124. public synchronized void messageReceived(FudgeContext fudgeContext, FudgeMsgEnvelope msgEnvelope) {
  125. _received++;
  126. if (_received == NUM_MESSAGES) {
  127. notify();
  128. } else if (_received > NUM_MESSAGES) {
  129. fail("Too many messages received");
  130. }
  131. }
  132. public synchronized boolean waitForMessages() throws InterruptedException {
  133. final long period = Timeout.standardTimeoutMillis();
  134. final long timeout = System.currentTimeMillis() + period;
  135. while ((_received < NUM_MESSAGES) && (System.currentTimeMillis() < timeout)) {
  136. wait(period);
  137. }
  138. return _received == NUM_MESSAGES;
  139. }
  140. }
  141. public void parallelIOTest() throws Exception {
  142. final MessageReadWrite serverThread = new MessageReadWrite();
  143. // receiver will attach the serverThread to the connection and start the thread
  144. final FudgeConnectionReceiver serverReceiver = new FudgeConnectionReceiver() {
  145. @Override
  146. public void connectionReceived(final FudgeContext fudgeContext, final FudgeMsgEnvelope envelope, final FudgeConnection connection) {
  147. // pass on the first message
  148. serverThread.messageReceived(fudgeContext, envelope);
  149. // and let it receive all others as they arrive
  150. serverThread._sender = connection.getFudgeMessageSender();
  151. connection.setFudgeMessageReceiver(serverThread);
  152. serverThread.start();
  153. }
  154. };
  155. final ServerSocketFudgeConnectionReceiver server = new ServerSocketFudgeConnectionReceiver(FudgeContext.GLOBAL_DEFAULT, serverReceiver);
  156. server.start();
  157. final SocketFudgeConnection client = new SocketFudgeConnection(FudgeContext.GLOBAL_DEFAULT);
  158. client.setInetAddress(InetAddress.getLocalHost());
  159. client.setPortNumber(server.getPortNumber());
  160. // client thread will send a stream of messages, and receive those back from the server
  161. final MessageReadWrite clientThread = new MessageReadWrite();
  162. clientThread._sender = client.getFudgeMessageSender();
  163. client.setFudgeMessageReceiver(clientThread);
  164. clientThread.start();
  165. // wait to see if both have behaved
  166. assertTrue(serverThread.waitForMessages());
  167. assertTrue(clientThread.waitForMessages());
  168. server.stop();
  169. client.stop();
  170. }
  171. public int[] parallelSendTest(final ExecutorService executorClient, final ExecutorService executorServer, final AtomicInteger concurrencyMax) throws Exception {
  172. final FudgeConnectionReceiver serverReceiver = new FudgeConnectionReceiver() {
  173. @Override
  174. public void connectionReceived(final FudgeContext fudgeContext, final FudgeMsgEnvelope envelope, final FudgeConnection connection) {
  175. connection.setFudgeMessageReceiver(new FudgeMessageReceiver() {
  176. @Override
  177. public void messageReceived(FudgeContext fudgeContext, FudgeMsgEnvelope msgEnvelope) {
  178. MutableFudgeMsg message = fudgeContext.newMessage();
  179. message.add("foo", 1);
  180. connection.getFudgeMessageSender().send(message);
  181. try {
  182. Thread.sleep(Timeout.standardTimeoutMillis());
  183. } catch (InterruptedException e) {
  184. }
  185. message = fudgeContext.newMessage();
  186. message.add("foo", 2);
  187. connection.getFudgeMessageSender().send(message);
  188. }
  189. });
  190. }
  191. };
  192. final ServerSocketFudgeConnectionReceiver server = (executorServer != null) ? new ServerSocketFudgeConnectionReceiver(FudgeContext.GLOBAL_DEFAULT, serverReceiver, executorServer)
  193. : new ServerSocketFudgeConnectionReceiver(FudgeContext.GLOBAL_DEFAULT, serverReceiver);
  194. server.start();
  195. final SocketFudgeConnection client = (executorClient != null) ? new SocketFudgeConnection(FudgeContext.GLOBAL_DEFAULT, executorClient) : new SocketFudgeConnection(FudgeContext.GLOBAL_DEFAULT);
  196. client.setInetAddress(InetAddress.getLocalHost());
  197. client.setPortNumber(server.getPortNumber());
  198. final CollectingFudgeMessageReceiver responses = new CollectingFudgeMessageReceiver () {
  199. private final AtomicInteger _concurrency = new AtomicInteger (0);
  200. @Override
  201. public void messageReceived (final FudgeContext fudgeContext, final FudgeMsgEnvelope envelope) {
  202. final int concurrency = _concurrency.incrementAndGet ();
  203. if (concurrency > concurrencyMax.get ()) {
  204. concurrencyMax.set (concurrency);
  205. }
  206. try {
  207. Thread.sleep(Timeout.standardTimeoutMillis() / 2L);
  208. } catch (InterruptedException e) {
  209. }
  210. _concurrency.decrementAndGet ();
  211. super.messageReceived (fudgeContext, envelope);
  212. }
  213. };
  214. client.setFudgeMessageReceiver(responses);
  215. client.getFudgeMessageSender().send(FudgeContext.EMPTY_MESSAGE);
  216. client.getFudgeMessageSender().send(FudgeContext.EMPTY_MESSAGE);
  217. client.getFudgeMessageSender().send(FudgeContext.EMPTY_MESSAGE);
  218. final int[] result = new int[4];
  219. for (int i = 0; i < 4; i++) {
  220. final FudgeMsgEnvelope envelope = responses.waitForMessage(Timeout.standardTimeoutMillis() * 2L);
  221. assertNotNull (envelope);
  222. result[i] = envelope.getMessage().getInt("foo");
  223. }
  224. return result;
  225. }
  226. public void parallelSendTest_single_single() throws Exception {
  227. final AtomicInteger concurrencyMax = new AtomicInteger(0);
  228. final int[] result = parallelSendTest(null, null, concurrencyMax);
  229. assertEquals(1, concurrencyMax.get());
  230. assertEquals(1, result[0]);
  231. assertEquals(2, result[1]);
  232. assertEquals(1, result[2]);
  233. assertEquals(2, result[3]);
  234. }
  235. public void parallelSendTest_multi_single() throws Exception {
  236. final AtomicInteger concurrencyMax = new AtomicInteger(0);
  237. final int[] result = parallelSendTest(Executors.newCachedThreadPool(), null, concurrencyMax);
  238. assertEquals(2, concurrencyMax.get());
  239. assertEquals(1, result[0]);
  240. // The server might send the messages in order, but the client can receive them out of order
  241. if (result[1] == 2) {
  242. assertEquals(1, result[2]);
  243. } else if (result[1] == 1) {
  244. assertEquals(2, result[2]);
  245. } else {
  246. fail();
  247. }
  248. assertEquals(2, result[3]);
  249. }
  250. public void parallelSendTest_single_multi() throws Exception {
  251. final AtomicInteger concurrencyMax = new AtomicInteger(0);
  252. final int[] result = parallelSendTest(null, Executors.newCachedThreadPool(), concurrencyMax);
  253. assertEquals(1, concurrencyMax.get());
  254. assertEquals(1, result[0]);
  255. assertEquals(1, result[1]);
  256. assertEquals(2, result[2]);
  257. assertEquals(2, result[3]);
  258. }
  259. public void parallelSendTest_multi_multi() throws Exception {
  260. final AtomicInteger concurrencyMax = new AtomicInteger(0);
  261. final int[] result = parallelSendTest(Executors.newCachedThreadPool(), Executors.newCachedThreadPool(), concurrencyMax);
  262. assertEquals(2, concurrencyMax.get());
  263. assertEquals(1, result[0]);
  264. assertEquals(1, result[1]);
  265. assertEquals(2, result[2]);
  266. assertEquals(2, result[3]);
  267. }
  268. }