package org.simpleframework.http.core;
import java.io.Closeable;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import junit.framework.TestCase;
import org.simpleframework.http.Request;
import org.simpleframework.http.Response;
import org.simpleframework.transport.connect.Connection;
import org.simpleframework.transport.connect.SocketConnection;
import org.simpleframework.util.thread.PoolExecutor;
public class StopTest extends TestCase {
private static final int ITERATIONS = 20;
public void testStop() throws Exception {
ThreadDumper dumper = new ThreadDumper();
dumper.start();
dumper.waitUntilStarted();
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
int initialThreads = threadBean.getThreadCount();
for(int i = 0; i < ITERATIONS; i++) {
try {
ServerCriteria criteria = createServer();
InetSocketAddress address = criteria.getAddress();
Connection connection = criteria.getConnection();
Client client = createClient(address, String.format("[%s of %s]", i, ITERATIONS));
Thread.sleep(2000); // allow some requests to execute
connection.close();
Thread.sleep(100); // ensure client keeps executing
client.close();
Thread.sleep(1000); // wait for threads to terminate
}catch(Exception e) {
e.printStackTrace();
}
assertEquals(initialThreads, threadBean.getThreadCount());
}
dumper.kill();
}
public static Client createClient(InetSocketAddress address, String tag) throws Exception {
PoolExecutor executor = new PoolExecutor(Runnable.class, 20);
int port = address.getPort();
Client client = new Client(executor, port, tag);
client.start();
return client;
}
public static ServerCriteria createServer() throws Exception {
Container container = new Container() {
public void handle(Request request, Response response) {
try {
PrintStream out = response.getPrintStream();
response.set("Content-Type", "text/plain");
response.set("Connection", "close");
out.print("TEST " + new Date());
response.close();
}catch(Exception e) {
e.printStackTrace();
try {
response.close();
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
};
ContainerServer server = new ContainerServer(container);
Connection connection = new SocketConnection(server);
InetSocketAddress address = (InetSocketAddress)connection.connect(null); // ephemeral port
return new ServerCriteria(connection, address);
}
private static class Client extends Thread implements Closeable {
private PoolExecutor executor;
private RequestTask task;
private volatile boolean dead;
public Client(PoolExecutor executor, int port, String tag) {
this.task = new RequestTask(port, tag);
this.executor = executor;
}
public void run() {
try {
while(!dead) {
executor.execute(task);
Thread.sleep(10);
}
}catch(Exception e) {
e.printStackTrace();
}
}
public void close() {
dead = true;
executor.stop();
}
}
private static class RequestTask implements Runnable {
private String tag;
private int port;
public RequestTask(int port, String tag) {
this.port = port;
this.tag = tag;
}
public void run() {
try {
URL target = new URL("http://localhost:"+port+"/");
URLConnection connection = target.openConnection();
// set a timeout
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
InputStream stream = connection.getInputStream();
StringBuilder builder = new StringBuilder();
int octet = 0;
while((octet = stream.read()) != -1) {
builder.append((char)octet);
}
stream.close();
System.out.println(tag + " " + Thread.currentThread() + ": " + builder);
}catch(Exception e) {
e.printStackTrace();
}
}
}
private static class ServerCriteria {
private Connection connection;
private InetSocketAddress address;
public ServerCriteria(Connection connection, InetSocketAddress address){
this.connection = connection;
this.address = address;
}
public Connection getConnection() {
return connection;
}
public InetSocketAddress getAddress() {
return address;
}
}
}