/jetty/modules/jetty/src/test/java/org/mortbay/jetty/AsyncStressTest.java
Java | 371 lines | 324 code | 35 blank | 12 comment | 41 complexity | 462c437ee9062351c250e42673074bb0 MD5 | raw file
- // ========================================================================
- // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
- // ------------------------------------------------------------------------
- // All rights reserved. This program and the accompanying materials
- // are made available under the terms of the Eclipse Public License v1.0
- // and Apache License v2.0 which accompanies this distribution.
- // The Eclipse Public License is available at
- // http://www.eclipse.org/legal/epl-v10.html
- // The Apache License v2.0 is available at
- // http://www.opensource.org/licenses/apache2.0.php
- // You may elect to redistribute this code under either of these licenses.
- // ========================================================================
- package org.mortbay.jetty;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.Inet4Address;
- import java.net.InetAddress;
- import java.net.Socket;
- import java.util.Random;
- import java.util.Timer;
- import java.util.TimerTask;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.mortbay.jetty.handler.AbstractHandler;
- import org.mortbay.jetty.handler.HandlerWrapper;
- import org.mortbay.jetty.nio.SelectChannelConnector;
- import org.mortbay.log.Log;
- import org.mortbay.thread.QueuedThreadPool;
- import org.mortbay.util.IO;
- import org.mortbay.util.StringUtil;
- import org.mortbay.util.ajax.Continuation;
- import org.mortbay.util.ajax.ContinuationSupport;
- import junit.framework.TestCase;
- public class AsyncStressTest extends TestCase
- {
- protected Server _server = new Server();
- protected SuspendHandler _handler = new SuspendHandler();
- protected SelectChannelConnector _connector;
- protected InetAddress _addr;
- protected int _port;
- protected Random _random = new Random();
- protected int[] _loops;
- protected QueuedThreadPool _threads=new QueuedThreadPool();
- protected boolean _stress;
-
- protected void setUp() throws Exception
- {
- _stress= Boolean.getBoolean("STRESS");
- _threads.setMaxThreads(50);
- if (_stress)
- _threads.setMaxThreads(200);
- _server.setThreadPool(_threads);
- _connector = new SelectChannelConnector();
- _server.setConnectors(new Connector[]{ _connector });
- _server.setHandler(_handler);
- _server.start();
- _port=_connector.getLocalPort();
- _addr=Inet4Address.getLocalHost();
- }
- protected void tearDown() throws Exception
- {
- _server.stop();
- }
- final static String[][] __tests =
- {
- {"/path","NORMAL"},
- {"/path?sleep=<TIMEOUT>","SLEPT"},
- {"/path?suspend=<TIMEOUT>","TIMEOUT"},
- {"/path?suspend=1000&resume=<TIMEOUT>","RESUMED"},
- {"/path?suspend=1000&complete=<TIMEOUT>","COMPLETED"},
- };
-
-
- public void doPaths(String name) throws Exception
- {
- for (int i=0;i<__tests.length;i++)
- {
- int timeout = _random.nextInt(200)+1;
- String uri=StringUtil.replace(__tests[i][0],"<TIMEOUT>",Integer.toString(timeout));
-
- long start=System.currentTimeMillis();
- Socket socket = new Socket(_addr,_port);
- socket.setSoTimeout(30000);
- String request = "GET "+uri+" HTTP/1.0\r\n\r\n";
- socket.getOutputStream().write(request.getBytes());
- socket.getOutputStream().flush();
- String response = IO.toString(socket.getInputStream());
- socket.close();
- long end=System.currentTimeMillis();
-
- response=response.substring(response.indexOf("\r\n\r\n")+4);
-
- String test=name+"-"+i+" "+uri+" "+__tests[i][1];
- assertEquals(test,__tests[i][1],response);
- if (!response.equals("NORMAL"))
- {
- long duration=end-start;
- assertTrue(test+" "+duration,duration+50>=timeout);
- }
- }
- }
-
- public void doLoops(int thread, String name, int loops) throws Exception
- {
- try
- {
- for (int i=0;i<loops;i++)
- {
- _loops[thread]=i;
- doPaths(name+"-"+i);
- Thread.sleep(_random.nextInt(100));
- }
- _loops[thread]=loops;
- }
- catch(Exception e)
- {
- _loops[thread]=-_loops[thread];
- throw e;
- }
- }
-
- public void doThreads(int threads,final int loops) throws Throwable
- {
- final Throwable[] throwable=new Throwable[threads];
- final Thread[] thread=new Thread[threads];
- for (int i=0;i<threads;i++)
- {
- final int id=i;
- final String name = "T"+i;
- thread[i]=new Thread()
- {
- public void run()
- {
- try
- {
- doLoops(id,name,loops);
- }
- catch(Throwable th)
- {
- th.printStackTrace();
- throwable[id]=th;
- }
- finally
- {
- }
- }
- };
- }
- _loops=new int[threads];
- for (int i=0;i<threads;i++)
- thread[i].start();
-
- while(true)
- {
- Thread.sleep(1000L);
- int finished=0;
- int errors=0;
- int min=loops;
- int max=0;
- int total=0;
- for (int i=0;i<threads;i++)
- {
- int l=_loops[i];
- if (l<0)
- {
- errors++;
- total-=l;
- }
- else
- {
- if (l<min)
- min=l;
- if (l>max)
- max=l;
- total+=l;
- if (l==loops)
- finished++;
- }
- }
-
- Log.info("min/ave/max/target="+min+"/"+(total/threads)+"/"+max+"/"+loops+" errors/finished/loops="+errors+"/"+finished+"/"+threads+" idle/threads="+_threads.getIdleThreads()+"/"+_threads.getThreads());
- if ((finished+errors)==threads)
- break;
- }
-
- for (int i=0;i<threads;i++)
- thread[i].join();
-
- for (int i=0;i<threads;i++)
- if (throwable[i]!=null)
- throw throwable[i];
- }
- public void testAsync() throws Throwable
- {
- if (_stress)
- {
- System.err.println("STRESS! ");
- doThreads(40,100);
- }
- else
- doThreads(20,20);
- Thread.sleep(1000);
- }
-
- private static class SuspendHandler extends AbstractHandler
- {
- private Timer _timer;
-
- public SuspendHandler()
- {
- _timer=new Timer();
- }
- public void handle(String target, HttpServletRequest request, final HttpServletResponse response, int dispatch) throws IOException, ServletException
- {
- final Request base_request = (request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
- int read_before=0;
- long sleep_for=-1;
- long suspend_for=-1;
- long resume_after=-1;
- long complete_after=-1;
-
- if (request.getParameter("read")!=null)
- read_before=Integer.parseInt(request.getParameter("read"));
- if (request.getParameter("sleep")!=null)
- sleep_for=Integer.parseInt(request.getParameter("sleep"));
- if (request.getParameter("suspend")!=null)
- suspend_for=Integer.parseInt(request.getParameter("suspend"));
- if (request.getParameter("resume")!=null)
- resume_after=Integer.parseInt(request.getParameter("resume"));
- if (request.getParameter("complete")!=null)
- complete_after=Integer.parseInt(request.getParameter("complete"));
-
- final Continuation continuation = ContinuationSupport.getContinuation(request,this);
- if (!(continuation.isPending() || continuation.isResumed()))
- {
- if (read_before>0)
- {
- byte[] buf=new byte[read_before];
- request.getInputStream().read(buf);
- }
- else if (read_before<0)
- {
- InputStream in = request.getInputStream();
- int b=in.read();
- while(b!=-1)
- b=in.read();
- }
- if (suspend_for>=0)
- {
- try
- {
- if (suspend_for>0)
- continuation.suspend(suspend_for);
- else
- continuation.suspend(100L);
- }
- finally
- {
- if (complete_after>0)
- {
- TimerTask complete = new TimerTask()
- {
- public void run()
- {
- try
- {
- response.setStatus(200);
- response.getOutputStream().print("COMPLETED");
- response.flushBuffer();
- continuation.resume();
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
- };
- synchronized (_timer)
- {
- _timer.schedule(complete,complete_after);
- }
- }
- else if (complete_after==0)
- {
- response.setStatus(200);
- response.getOutputStream().print("COMPLETED");
- response.flushBuffer();
- continuation.resume();
- }
-
- if (resume_after>0)
- {
- TimerTask resume = new TimerTask()
- {
- public void run()
- {
- continuation.resume();
- }
- };
- synchronized (_timer)
- {
- _timer.schedule(resume,resume_after);
- }
- }
- else if (resume_after==0)
- {
- continuation.resume();
- }
- }
- }
- else if (sleep_for>=0)
- {
- try
- {
- Thread.sleep(sleep_for);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- response.setStatus(200);
- response.getOutputStream().print("SLEPT");
- base_request.setHandled(true);
- return;
- }
- else
- {
- response.setStatus(200);
- response.getOutputStream().print("NORMAL");
- base_request.setHandled(true);
- return;
- }
-
-
-
- }
- else if (response.isCommitted())
- {
- base_request.setHandled(true);
- }
- else if (continuation.isResumed())
- {
- response.setStatus(200);
- response.getOutputStream().print("RESUMED");
- base_request.setHandled(true);
- }
- else
- {
- response.setStatus(200);
- response.getOutputStream().print("TIMEOUT");
- base_request.setHandled(true);
- }
- }
- }
-
- }