PageRenderTime 59ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/jetty/modules/jetty/src/test/java/org/mortbay/jetty/AsyncStressTest.java

https://github.com/derickbailey/qedserver
Java | 371 lines | 324 code | 35 blank | 12 comment | 41 complexity | 462c437ee9062351c250e42673074bb0 MD5 | raw file
  1. // ========================================================================
  2. // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
  3. // ------------------------------------------------------------------------
  4. // All rights reserved. This program and the accompanying materials
  5. // are made available under the terms of the Eclipse Public License v1.0
  6. // and Apache License v2.0 which accompanies this distribution.
  7. // The Eclipse Public License is available at
  8. // http://www.eclipse.org/legal/epl-v10.html
  9. // The Apache License v2.0 is available at
  10. // http://www.opensource.org/licenses/apache2.0.php
  11. // You may elect to redistribute this code under either of these licenses.
  12. // ========================================================================
  13. package org.mortbay.jetty;
  14. import java.io.IOException;
  15. import java.io.InputStream;
  16. import java.net.Inet4Address;
  17. import java.net.InetAddress;
  18. import java.net.Socket;
  19. import java.util.Random;
  20. import java.util.Timer;
  21. import java.util.TimerTask;
  22. import javax.servlet.ServletException;
  23. import javax.servlet.http.HttpServletRequest;
  24. import javax.servlet.http.HttpServletResponse;
  25. import org.mortbay.jetty.handler.AbstractHandler;
  26. import org.mortbay.jetty.handler.HandlerWrapper;
  27. import org.mortbay.jetty.nio.SelectChannelConnector;
  28. import org.mortbay.log.Log;
  29. import org.mortbay.thread.QueuedThreadPool;
  30. import org.mortbay.util.IO;
  31. import org.mortbay.util.StringUtil;
  32. import org.mortbay.util.ajax.Continuation;
  33. import org.mortbay.util.ajax.ContinuationSupport;
  34. import junit.framework.TestCase;
  35. public class AsyncStressTest extends TestCase
  36. {
  37. protected Server _server = new Server();
  38. protected SuspendHandler _handler = new SuspendHandler();
  39. protected SelectChannelConnector _connector;
  40. protected InetAddress _addr;
  41. protected int _port;
  42. protected Random _random = new Random();
  43. protected int[] _loops;
  44. protected QueuedThreadPool _threads=new QueuedThreadPool();
  45. protected boolean _stress;
  46. protected void setUp() throws Exception
  47. {
  48. _stress= Boolean.getBoolean("STRESS");
  49. _threads.setMaxThreads(50);
  50. if (_stress)
  51. _threads.setMaxThreads(200);
  52. _server.setThreadPool(_threads);
  53. _connector = new SelectChannelConnector();
  54. _server.setConnectors(new Connector[]{ _connector });
  55. _server.setHandler(_handler);
  56. _server.start();
  57. _port=_connector.getLocalPort();
  58. _addr=Inet4Address.getLocalHost();
  59. }
  60. protected void tearDown() throws Exception
  61. {
  62. _server.stop();
  63. }
  64. final static String[][] __tests =
  65. {
  66. {"/path","NORMAL"},
  67. {"/path?sleep=<TIMEOUT>","SLEPT"},
  68. {"/path?suspend=<TIMEOUT>","TIMEOUT"},
  69. {"/path?suspend=1000&resume=<TIMEOUT>","RESUMED"},
  70. {"/path?suspend=1000&complete=<TIMEOUT>","COMPLETED"},
  71. };
  72. public void doPaths(String name) throws Exception
  73. {
  74. for (int i=0;i<__tests.length;i++)
  75. {
  76. int timeout = _random.nextInt(200)+1;
  77. String uri=StringUtil.replace(__tests[i][0],"<TIMEOUT>",Integer.toString(timeout));
  78. long start=System.currentTimeMillis();
  79. Socket socket = new Socket(_addr,_port);
  80. socket.setSoTimeout(30000);
  81. String request = "GET "+uri+" HTTP/1.0\r\n\r\n";
  82. socket.getOutputStream().write(request.getBytes());
  83. socket.getOutputStream().flush();
  84. String response = IO.toString(socket.getInputStream());
  85. socket.close();
  86. long end=System.currentTimeMillis();
  87. response=response.substring(response.indexOf("\r\n\r\n")+4);
  88. String test=name+"-"+i+" "+uri+" "+__tests[i][1];
  89. assertEquals(test,__tests[i][1],response);
  90. if (!response.equals("NORMAL"))
  91. {
  92. long duration=end-start;
  93. assertTrue(test+" "+duration,duration+50>=timeout);
  94. }
  95. }
  96. }
  97. public void doLoops(int thread, String name, int loops) throws Exception
  98. {
  99. try
  100. {
  101. for (int i=0;i<loops;i++)
  102. {
  103. _loops[thread]=i;
  104. doPaths(name+"-"+i);
  105. Thread.sleep(_random.nextInt(100));
  106. }
  107. _loops[thread]=loops;
  108. }
  109. catch(Exception e)
  110. {
  111. _loops[thread]=-_loops[thread];
  112. throw e;
  113. }
  114. }
  115. public void doThreads(int threads,final int loops) throws Throwable
  116. {
  117. final Throwable[] throwable=new Throwable[threads];
  118. final Thread[] thread=new Thread[threads];
  119. for (int i=0;i<threads;i++)
  120. {
  121. final int id=i;
  122. final String name = "T"+i;
  123. thread[i]=new Thread()
  124. {
  125. public void run()
  126. {
  127. try
  128. {
  129. doLoops(id,name,loops);
  130. }
  131. catch(Throwable th)
  132. {
  133. th.printStackTrace();
  134. throwable[id]=th;
  135. }
  136. finally
  137. {
  138. }
  139. }
  140. };
  141. }
  142. _loops=new int[threads];
  143. for (int i=0;i<threads;i++)
  144. thread[i].start();
  145. while(true)
  146. {
  147. Thread.sleep(1000L);
  148. int finished=0;
  149. int errors=0;
  150. int min=loops;
  151. int max=0;
  152. int total=0;
  153. for (int i=0;i<threads;i++)
  154. {
  155. int l=_loops[i];
  156. if (l<0)
  157. {
  158. errors++;
  159. total-=l;
  160. }
  161. else
  162. {
  163. if (l<min)
  164. min=l;
  165. if (l>max)
  166. max=l;
  167. total+=l;
  168. if (l==loops)
  169. finished++;
  170. }
  171. }
  172. Log.info("min/ave/max/target="+min+"/"+(total/threads)+"/"+max+"/"+loops+" errors/finished/loops="+errors+"/"+finished+"/"+threads+" idle/threads="+_threads.getIdleThreads()+"/"+_threads.getThreads());
  173. if ((finished+errors)==threads)
  174. break;
  175. }
  176. for (int i=0;i<threads;i++)
  177. thread[i].join();
  178. for (int i=0;i<threads;i++)
  179. if (throwable[i]!=null)
  180. throw throwable[i];
  181. }
  182. public void testAsync() throws Throwable
  183. {
  184. if (_stress)
  185. {
  186. System.err.println("STRESS! ");
  187. doThreads(40,100);
  188. }
  189. else
  190. doThreads(20,20);
  191. Thread.sleep(1000);
  192. }
  193. private static class SuspendHandler extends AbstractHandler
  194. {
  195. private Timer _timer;
  196. public SuspendHandler()
  197. {
  198. _timer=new Timer();
  199. }
  200. public void handle(String target, HttpServletRequest request, final HttpServletResponse response, int dispatch) throws IOException, ServletException
  201. {
  202. final Request base_request = (request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
  203. int read_before=0;
  204. long sleep_for=-1;
  205. long suspend_for=-1;
  206. long resume_after=-1;
  207. long complete_after=-1;
  208. if (request.getParameter("read")!=null)
  209. read_before=Integer.parseInt(request.getParameter("read"));
  210. if (request.getParameter("sleep")!=null)
  211. sleep_for=Integer.parseInt(request.getParameter("sleep"));
  212. if (request.getParameter("suspend")!=null)
  213. suspend_for=Integer.parseInt(request.getParameter("suspend"));
  214. if (request.getParameter("resume")!=null)
  215. resume_after=Integer.parseInt(request.getParameter("resume"));
  216. if (request.getParameter("complete")!=null)
  217. complete_after=Integer.parseInt(request.getParameter("complete"));
  218. final Continuation continuation = ContinuationSupport.getContinuation(request,this);
  219. if (!(continuation.isPending() || continuation.isResumed()))
  220. {
  221. if (read_before>0)
  222. {
  223. byte[] buf=new byte[read_before];
  224. request.getInputStream().read(buf);
  225. }
  226. else if (read_before<0)
  227. {
  228. InputStream in = request.getInputStream();
  229. int b=in.read();
  230. while(b!=-1)
  231. b=in.read();
  232. }
  233. if (suspend_for>=0)
  234. {
  235. try
  236. {
  237. if (suspend_for>0)
  238. continuation.suspend(suspend_for);
  239. else
  240. continuation.suspend(100L);
  241. }
  242. finally
  243. {
  244. if (complete_after>0)
  245. {
  246. TimerTask complete = new TimerTask()
  247. {
  248. public void run()
  249. {
  250. try
  251. {
  252. response.setStatus(200);
  253. response.getOutputStream().print("COMPLETED");
  254. response.flushBuffer();
  255. continuation.resume();
  256. }
  257. catch(Exception e)
  258. {
  259. e.printStackTrace();
  260. }
  261. }
  262. };
  263. synchronized (_timer)
  264. {
  265. _timer.schedule(complete,complete_after);
  266. }
  267. }
  268. else if (complete_after==0)
  269. {
  270. response.setStatus(200);
  271. response.getOutputStream().print("COMPLETED");
  272. response.flushBuffer();
  273. continuation.resume();
  274. }
  275. if (resume_after>0)
  276. {
  277. TimerTask resume = new TimerTask()
  278. {
  279. public void run()
  280. {
  281. continuation.resume();
  282. }
  283. };
  284. synchronized (_timer)
  285. {
  286. _timer.schedule(resume,resume_after);
  287. }
  288. }
  289. else if (resume_after==0)
  290. {
  291. continuation.resume();
  292. }
  293. }
  294. }
  295. else if (sleep_for>=0)
  296. {
  297. try
  298. {
  299. Thread.sleep(sleep_for);
  300. }
  301. catch (InterruptedException e)
  302. {
  303. e.printStackTrace();
  304. }
  305. response.setStatus(200);
  306. response.getOutputStream().print("SLEPT");
  307. base_request.setHandled(true);
  308. return;
  309. }
  310. else
  311. {
  312. response.setStatus(200);
  313. response.getOutputStream().print("NORMAL");
  314. base_request.setHandled(true);
  315. return;
  316. }
  317. }
  318. else if (response.isCommitted())
  319. {
  320. base_request.setHandled(true);
  321. }
  322. else if (continuation.isResumed())
  323. {
  324. response.setStatus(200);
  325. response.getOutputStream().print("RESUMED");
  326. base_request.setHandled(true);
  327. }
  328. else
  329. {
  330. response.setStatus(200);
  331. response.getOutputStream().print("TIMEOUT");
  332. base_request.setHandled(true);
  333. }
  334. }
  335. }
  336. }