/*
* Copyright (c) 2009-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.eclipse.jetty.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Arrays;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* @version $Revision: 889 $ $Date: 2009-09-14 14:52:16 +1000 (Mon, 14 Sep 2009) $
*/
public class AsyncRequestReadTest
{
private static Server server;
private static Connector connector;
private final static Exchanger<Long> __total=new Exchanger<Long>();
@BeforeClass
public static void startServer() throws Exception
{
server = new Server();
connector = new SelectChannelConnector();
connector.setMaxIdleTime(10000);
server.addConnector(connector);
server.setHandler(new EmptyHandler());
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
server.join();
}
@Test
public void test() throws Exception
{
final Socket socket = new Socket("localhost",connector.getLocalPort());
byte[] content = new byte[16*4096];
Arrays.fill(content, (byte)120);
OutputStream out = socket.getOutputStream();
String header=
"POST / HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"Content-Length: "+content.length+"\r\n"+
"Content-Type: bytes\r\n"+
"Connection: close\r\n"+
"\r\n";
byte[] h=header.getBytes(StringUtil.__ISO_8859_1);
out.write(h);
out.flush();
out.write(content,0,4*4096);
Thread.sleep(100);
out.write(content,8192,4*4096);
Thread.sleep(100);
out.write(content,8*4096,content.length-8*4096);
out.flush();
InputStream in = socket.getInputStream();
String response = IO.toString(in);
assertTrue(response.indexOf("200 OK")>0);
long total=__total.exchange(0L,30,TimeUnit.SECONDS);
assertEquals(content.length, total);
}
@Test
public void tests() throws Exception
{
runTest(64,4,4,20);
runTest(256,16,16,50);
runTest(256,1,128,10);
runTest(128*1024,1,64,10);
runTest(256*1024,5321,10,100);
runTest(512*1024,32*1024,10,10);
}
public void runTest(int contentSize, int chunkSize, int chunks, int delayMS) throws Exception
{
String tst=contentSize+","+chunkSize+","+chunks+","+delayMS;
//System.err.println(tst);
final Socket socket = new Socket("localhost",connector.getLocalPort());
byte[] content = new byte[contentSize];
Arrays.fill(content, (byte)120);
OutputStream out = socket.getOutputStream();
out.write("POST / HTTP/1.1\r\n".getBytes());
out.write("Host: localhost\r\n".getBytes());
out.write(("Content-Length: "+content.length+"\r\n").getBytes());
out.write("Content-Type: bytes\r\n".getBytes());
out.write("Connection: close\r\n".getBytes());
out.write("\r\n".getBytes());
out.flush();
int offset=0;
for (int i=0;i<chunks;i++)
{
out.write(content,offset,chunkSize);
offset+=chunkSize;
Thread.sleep(delayMS);
}
out.write(content,offset,content.length-offset);
out.flush();
InputStream in = socket.getInputStream();
String response = IO.toString(in);
assertTrue(tst,response.indexOf("200 OK")>0);
long total=__total.exchange(0L,30,TimeUnit.SECONDS);
assertEquals(tst,content.length, total);
}
private static class EmptyHandler extends AbstractHandler
{
public void handle(String path, final Request request, HttpServletRequest httpRequest, final HttpServletResponse httpResponse) throws IOException, ServletException
{
final Continuation continuation = ContinuationSupport.getContinuation(request);
httpResponse.setStatus(500);
request.setHandled(true);
new Thread()
{
@Override
public void run()
{
long total=0;
try
{
InputStream in = request.getInputStream();
byte[] b = new byte[4*4096];
int read;
while((read =in.read(b))>=0)
total += read;
}
catch(Exception e)
{
e.printStackTrace();
total =-1;
}
finally
{
httpResponse.setStatus(200);
continuation.complete();
try
{
__total.exchange(total);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}.start();
continuation.suspend();
}
}
}