PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/jetty-8.1.5.v20120716/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java

#
Java | 451 lines | 328 code | 85 blank | 38 comment | 24 complexity | ab4d136c4d85cce80f86236fb93a4a1f MD5 | raw file
Possible License(s): Apache-2.0
  1. package org.eclipse.jetty.io.nio;
  2. //========================================================================
  3. //Copyright 2011-2012 Mort Bay Consulting Pty. Ltd.
  4. //------------------------------------------------------------------------
  5. //All rights reserved. This program and the accompanying materials
  6. //are made available under the terms of the Eclipse Public License v1.0
  7. //and Apache License v2.0 which accompanies this distribution.
  8. //The Eclipse Public License is available at
  9. //http://www.eclipse.org/legal/epl-v10.html
  10. //The Apache License v2.0 is available at
  11. //http://www.opensource.org/licenses/apache2.0.php
  12. //You may elect to redistribute this code under either of these licenses.
  13. //========================================================================
  14. import static org.hamcrest.Matchers.greaterThanOrEqualTo;
  15. import static org.hamcrest.Matchers.greaterThan;
  16. import static org.junit.Assert.assertEquals;
  17. import static org.junit.Assert.assertFalse;
  18. import static org.junit.Assert.assertThat;
  19. import static org.junit.Assert.assertTrue;
  20. import java.io.BufferedInputStream;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.io.OutputStream;
  24. import java.net.Socket;
  25. import java.net.SocketTimeoutException;
  26. import java.nio.channels.SelectionKey;
  27. import java.nio.channels.ServerSocketChannel;
  28. import java.nio.channels.SocketChannel;
  29. import java.util.concurrent.CountDownLatch;
  30. import java.util.concurrent.TimeUnit;
  31. import org.eclipse.jetty.io.AbstractConnection;
  32. import org.eclipse.jetty.io.AsyncEndPoint;
  33. import org.eclipse.jetty.io.ConnectedEndPoint;
  34. import org.eclipse.jetty.io.EndPoint;
  35. import org.eclipse.jetty.util.thread.QueuedThreadPool;
  36. import org.hamcrest.Matchers;
  37. import org.junit.After;
  38. import org.junit.Assert;
  39. import org.junit.Before;
  40. import org.junit.Test;
  41. public class SelectChannelEndPointTest
  42. {
  43. protected SelectChannelEndPoint _lastEndp;
  44. protected ServerSocketChannel _connector;
  45. protected QueuedThreadPool _threadPool = new QueuedThreadPool();
  46. protected SelectorManager _manager = new SelectorManager()
  47. {
  48. @Override
  49. public boolean dispatch(Runnable task)
  50. {
  51. return _threadPool.dispatch(task);
  52. }
  53. @Override
  54. protected void endPointClosed(SelectChannelEndPoint endpoint)
  55. {
  56. }
  57. @Override
  58. protected void endPointOpened(SelectChannelEndPoint endpoint)
  59. {
  60. }
  61. @Override
  62. protected void endPointUpgraded(ConnectedEndPoint endpoint, org.eclipse.jetty.io.Connection oldConnection)
  63. {
  64. }
  65. @Override
  66. public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment)
  67. {
  68. return SelectChannelEndPointTest.this.newConnection(channel,endpoint);
  69. }
  70. @Override
  71. protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
  72. {
  73. SelectChannelEndPoint endp = new SelectChannelEndPoint(channel,selectSet,key,2000);
  74. endp.setConnection(selectSet.getManager().newConnection(channel,endp, key.attachment()));
  75. _lastEndp=endp;
  76. return endp;
  77. }
  78. };
  79. // Must be volatile or the test may fail spuriously
  80. private volatile int _blockAt=0;
  81. @Before
  82. public void startManager() throws Exception
  83. {
  84. _connector = ServerSocketChannel.open();
  85. _connector.socket().bind(null);
  86. _threadPool.start();
  87. _manager.start();
  88. }
  89. @After
  90. public void stopManager() throws Exception
  91. {
  92. _manager.stop();
  93. _threadPool.stop();
  94. _connector.close();
  95. }
  96. protected Socket newClient() throws IOException
  97. {
  98. return new Socket(_connector.socket().getInetAddress(),_connector.socket().getLocalPort());
  99. }
  100. protected AsyncConnection newConnection(SocketChannel channel, EndPoint endpoint)
  101. {
  102. return new TestConnection(endpoint);
  103. }
  104. public class TestConnection extends AbstractConnection implements AsyncConnection
  105. {
  106. NIOBuffer _in = new IndirectNIOBuffer(32*1024);
  107. NIOBuffer _out = new IndirectNIOBuffer(32*1024);
  108. public TestConnection(EndPoint endp)
  109. {
  110. super(endp);
  111. }
  112. public org.eclipse.jetty.io.Connection handle() throws IOException
  113. {
  114. boolean progress=true;
  115. while(progress)
  116. {
  117. progress=false;
  118. _in.compact();
  119. if (_in.space()>0 && _endp.fill(_in)>0)
  120. progress=true;
  121. while (_blockAt>0 && _in.length()>0 && _in.length()<_blockAt)
  122. {
  123. _endp.blockReadable(10000);
  124. if (_in.space()>0 && _endp.fill(_in)>0)
  125. progress=true;
  126. }
  127. if (_in.hasContent() && _in.skip(_out.put(_in))>0)
  128. progress=true;
  129. if (_out.hasContent() && _endp.flush(_out)>0)
  130. progress=true;
  131. _out.compact();
  132. if (!_out.hasContent() && _endp.isInputShutdown())
  133. _endp.shutdownOutput();
  134. }
  135. return this;
  136. }
  137. public boolean isIdle()
  138. {
  139. return false;
  140. }
  141. public boolean isSuspended()
  142. {
  143. return false;
  144. }
  145. public void onClose()
  146. {
  147. // System.err.println("onClose");
  148. }
  149. public void onInputShutdown() throws IOException
  150. {
  151. // System.err.println("onInputShutdown");
  152. }
  153. }
  154. @Test
  155. public void testEcho() throws Exception
  156. {
  157. Socket client = newClient();
  158. client.setSoTimeout(500);
  159. SocketChannel server = _connector.accept();
  160. server.configureBlocking(false);
  161. _manager.register(server);
  162. // Write client to server
  163. client.getOutputStream().write("HelloWorld".getBytes("UTF-8"));
  164. // Verify echo server to client
  165. for (char c : "HelloWorld".toCharArray())
  166. {
  167. int b = client.getInputStream().read();
  168. assertTrue(b>0);
  169. assertEquals(c,(char)b);
  170. }
  171. // wait for read timeout
  172. long start=System.currentTimeMillis();
  173. try
  174. {
  175. client.getInputStream().read();
  176. Assert.fail();
  177. }
  178. catch(SocketTimeoutException e)
  179. {
  180. long duration = System.currentTimeMillis()-start;
  181. Assert.assertThat("timeout duration", duration, greaterThanOrEqualTo(400L));
  182. }
  183. // write then shutdown
  184. client.getOutputStream().write("Goodbye Cruel TLS".getBytes("UTF-8"));
  185. // Verify echo server to client
  186. for (char c : "Goodbye Cruel TLS".toCharArray())
  187. {
  188. int b = client.getInputStream().read();
  189. Assert.assertThat("expect valid char integer", b, greaterThan(0));
  190. assertEquals("expect characters to be same", c,(char)b);
  191. }
  192. client.close();
  193. int i=0;
  194. while (server.isOpen())
  195. {
  196. assert(i++<10);
  197. Thread.sleep(10);
  198. }
  199. }
  200. @Test
  201. public void testShutdown() throws Exception
  202. {
  203. Socket client = newClient();
  204. client.setSoTimeout(500);
  205. SocketChannel server = _connector.accept();
  206. server.configureBlocking(false);
  207. _manager.register(server);
  208. // Write client to server
  209. client.getOutputStream().write("HelloWorld".getBytes("UTF-8"));
  210. // Verify echo server to client
  211. for (char c : "HelloWorld".toCharArray())
  212. {
  213. int b = client.getInputStream().read();
  214. assertTrue(b>0);
  215. assertEquals(c,(char)b);
  216. }
  217. // wait for read timeout
  218. long start=System.currentTimeMillis();
  219. try
  220. {
  221. client.getInputStream().read();
  222. Assert.fail();
  223. }
  224. catch(SocketTimeoutException e)
  225. {
  226. assertTrue(System.currentTimeMillis()-start>=400);
  227. }
  228. // write then shutdown
  229. client.getOutputStream().write("Goodbye Cruel TLS".getBytes("UTF-8"));
  230. client.shutdownOutput();
  231. // Verify echo server to client
  232. for (char c : "Goodbye Cruel TLS".toCharArray())
  233. {
  234. int b = client.getInputStream().read();
  235. assertTrue(b>0);
  236. assertEquals(c,(char)b);
  237. }
  238. // Read close
  239. assertEquals(-1,client.getInputStream().read());
  240. }
  241. @Test
  242. public void testBlockIn() throws Exception
  243. {
  244. Socket client = newClient();
  245. SocketChannel server = _connector.accept();
  246. server.configureBlocking(false);
  247. _manager.register(server);
  248. OutputStream clientOutputStream = client.getOutputStream();
  249. InputStream clientInputStream = client.getInputStream();
  250. int specifiedTimeout = 400;
  251. client.setSoTimeout(specifiedTimeout);
  252. // Write 8 and cause block for 10
  253. _blockAt=10;
  254. clientOutputStream.write("12345678".getBytes("UTF-8"));
  255. clientOutputStream.flush();
  256. Thread.sleep(2 * specifiedTimeout);
  257. // No echo as blocking for 10
  258. long start=System.currentTimeMillis();
  259. try
  260. {
  261. int b = clientInputStream.read();
  262. Assert.fail("Should have timed out waiting for a response, but read "+b);
  263. }
  264. catch(SocketTimeoutException e)
  265. {
  266. int elapsed = Long.valueOf(System.currentTimeMillis() - start).intValue();
  267. System.err.println("blocked for " + elapsed+ "ms");
  268. Assert.assertThat("Expected timeout", elapsed, greaterThanOrEqualTo(3*specifiedTimeout/4));
  269. }
  270. // write remaining characters
  271. clientOutputStream.write("90ABCDEF".getBytes("UTF-8"));
  272. clientOutputStream.flush();
  273. // Verify echo server to client
  274. for (char c : "1234567890ABCDEF".toCharArray())
  275. {
  276. int b = clientInputStream.read();
  277. assertTrue(b>0);
  278. assertEquals(c,(char)b);
  279. }
  280. }
  281. @Test
  282. public void testIdle() throws Exception
  283. {
  284. Socket client = newClient();
  285. client.setSoTimeout(3000);
  286. SocketChannel server = _connector.accept();
  287. server.configureBlocking(false);
  288. _manager.register(server);
  289. // Write client to server
  290. client.getOutputStream().write("HelloWorld".getBytes("UTF-8"));
  291. // Verify echo server to client
  292. for (char c : "HelloWorld".toCharArray())
  293. {
  294. int b = client.getInputStream().read();
  295. assertTrue(b>0);
  296. assertEquals(c,(char)b);
  297. }
  298. // Set Max idle
  299. _lastEndp.setMaxIdleTime(500);
  300. // read until idle shutdown received
  301. long start=System.currentTimeMillis();
  302. int b=client.getInputStream().read();
  303. assertEquals(-1,b);
  304. long idle=System.currentTimeMillis()-start;
  305. assertThat(idle,Matchers.greaterThan(400L));
  306. assertThat(idle,Matchers.lessThan(3000L));
  307. if (_lastEndp.isOpen())
  308. {
  309. // half close so wait another idle period
  310. assertTrue(_lastEndp.isOutputShutdown());
  311. Thread.sleep(2000);
  312. }
  313. // endpoint is closed.
  314. assertFalse(_lastEndp.isOpen());
  315. }
  316. @Test
  317. public void testStress() throws Exception
  318. {
  319. Socket client = newClient();
  320. client.setSoTimeout(30000);
  321. SocketChannel server = _connector.accept();
  322. server.configureBlocking(false);
  323. _manager.register(server);
  324. int writes = 100000;
  325. final byte[] bytes="HelloWorld".getBytes("UTF-8");
  326. final CountDownLatch latch = new CountDownLatch(writes);
  327. final InputStream in = new BufferedInputStream(client.getInputStream());
  328. final long start = System.currentTimeMillis();
  329. client.getOutputStream().write(bytes);
  330. client.getOutputStream().flush();
  331. new Thread()
  332. {
  333. public void run()
  334. {
  335. try
  336. {
  337. while (latch.getCount()>0)
  338. {
  339. // Verify echo server to client
  340. for (byte b0 : bytes)
  341. {
  342. int b = in.read();
  343. assertTrue(b>0);
  344. assertEquals(0xff&b0,b);
  345. }
  346. latch.countDown();
  347. }
  348. }
  349. catch(Throwable e)
  350. {
  351. System.err.println("latch="+latch.getCount());
  352. System.err.println("time="+(System.currentTimeMillis()-start));
  353. e.printStackTrace();
  354. }
  355. }
  356. }.start();
  357. // Write client to server
  358. for (int i=1;i<writes;i++)
  359. {
  360. client.getOutputStream().write(bytes);
  361. Thread.yield();
  362. }
  363. client.getOutputStream().flush();
  364. assertTrue(latch.await(100,TimeUnit.SECONDS));
  365. }
  366. }