Java tutorial
/* * Copyright (c) 2010-2011, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Eclipse Public License, * tyrex license, freemarker license, dom4j license, mx4j license, * Spice Software License, Common Development and Distribution License * (CDDL), Common Public License (CPL) the licensors of this Program grant * you additional permission to convey the resulting work. */ package mitm.common.net; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.net.URISyntaxException; import java.security.cert.CRLException; import mitm.common.net.HTTPMethodExecutor.ResponseHandler; import mitm.common.scheduler.TaskScheduler; import mitm.test.SimpleSocketServer; import mitm.test.SocketAcceptEvent; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.io.IOUtils; import org.apache.log4j.LogManager; import org.apache.log4j.PropertyConfigurator; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class HTTPMethodExecutorTest { private final static int SERVER_PORT = 61112; private static SimpleSocketServer server; private static class RunawaySocketHandler implements Runnable { private final Socket socket; public RunawaySocketHandler(Socket socket) { this.socket = socket; } @Override public void run() { try { while (true) { OutputStream output = socket.getOutputStream(); try { Thread.sleep(100); } catch (InterruptedException e) { } output.write(new byte[] { 0 }); output.flush(); } } catch (IOException e) { e.printStackTrace(); } } } private static class WaitSocketHandler implements Runnable { @Override public void run() { synchronized (this) { try { this.wait(); } catch (InterruptedException e) { // ignore } } } } private static class HttpReplySocketHandler implements Runnable { private final Socket socket; public HttpReplySocketHandler(Socket socket) { this.socket = socket; } @Override public void run() { try { OutputStream output = socket.getOutputStream(); output.write("HTTP/1.1 200 OK\r\n".getBytes()); output.write("Content-Type: text/html\r\n".getBytes()); output.write("\r\n\r\n".getBytes()); output.flush(); while (true) { Thread.sleep(100); output.write(new byte[] { 'a' }); output.flush(); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } private static class ConsumeResponseHandler implements ResponseHandler { private ByteArrayOutputStream output; @Override public void handleResponse(int statusCode, HttpMethod httpMethod, TaskScheduler watchdog) throws IOException, HttpException { output = new ByteArrayOutputStream(); IOUtils.copy(httpMethod.getResponseBodyAsStream(), output); } } private static class WaitResponseHandler implements ResponseHandler { @Override public void handleResponse(int statusCode, HttpMethod httpMethod, TaskScheduler watchdog) throws IOException, HttpException { synchronized (this) { try { this.wait(); } catch (InterruptedException e) { // ignore } } } } private static class ThrowExceptionResponseHandler implements ResponseHandler { @Override public void handleResponse(int statusCode, HttpMethod httpMethod, TaskScheduler watchdog) throws IOException, HttpException { throw new IOException("Thrown on purpose"); } } @BeforeClass public static void setUpBeforeClass() throws Exception { PropertyConfigurator.configure("conf/log4j.properties"); LogManager.getLogger(HTTPMethodExecutor.class).setLevel(org.apache.log4j.Level.DEBUG); startServer(); } @AfterClass public static void setUpAfterClass() { server.stop(); } @Before public void before() { server.setIncomingEvent(null); } private static void startServer() { server = new SimpleSocketServer(SERVER_PORT); Thread serverThread = new Thread(server); serverThread.setDaemon(true); serverThread.start(); while (!server.isRunning()) { try { Thread.sleep(100); } catch (InterruptedException e) { // ignore } } } @Test(timeout = 10000) public void testConsumeResponseHandlerTimeout() throws URISyntaxException, CRLException, IOException { SocketAcceptEvent event = new SocketAcceptEvent() { @Override public void accept(Socket socket) throws IOException { Runnable runnable = new HttpReplySocketHandler(socket); new Thread(runnable).start(); } }; server.setIncomingEvent(event); int timeout = 2000; HTTPMethodExecutor executor = new HTTPMethodExecutor(timeout, null); HttpMethod httpMethod = new GetMethod("http://127.0.0.1:" + SERVER_PORT); long start = System.currentTimeMillis(); ConsumeResponseHandler responseHandler = new ConsumeResponseHandler(); try { executor.executeMethod(httpMethod, responseHandler); fail(); } catch (IOException e) { // expected } assertNotNull(responseHandler.output); assertTrue(responseHandler.output.size() > 2); assertTrue(responseHandler.output.toString().contains("aa")); long diff = System.currentTimeMillis() - start; assertTrue(diff >= timeout); assertTrue(diff <= timeout * 2); } @Test(timeout = 10000) public void testWaitResponseHandlerTimeout() throws URISyntaxException, CRLException, IOException { SocketAcceptEvent event = new SocketAcceptEvent() { @Override public void accept(Socket socket) throws IOException { Runnable runnable = new HttpReplySocketHandler(socket); new Thread(runnable).start(); } }; server.setIncomingEvent(event); int timeout = 2000; HTTPMethodExecutor executor = new HTTPMethodExecutor(timeout, null); HttpMethod httpMethod = new GetMethod("http://127.0.0.1:" + SERVER_PORT); long start = System.currentTimeMillis(); try { executor.executeMethod(httpMethod, new WaitResponseHandler()); fail(); } catch (IOException e) { // expected } long diff = System.currentTimeMillis() - start; assertTrue(diff >= timeout); assertTrue(diff <= timeout * 2); } @Test(timeout = 10000) public void testWaitSocketHandlerTimeout() throws URISyntaxException, CRLException, IOException { SocketAcceptEvent event = new SocketAcceptEvent() { @Override public void accept(Socket socket) throws IOException { Runnable runnable = new WaitSocketHandler(); new Thread(runnable).start(); } }; server.setIncomingEvent(event); int timeout = 2000; HTTPMethodExecutor executor = new HTTPMethodExecutor(timeout, null); HttpMethod httpMethod = new GetMethod("http://127.0.0.1:" + SERVER_PORT); long start = System.currentTimeMillis(); try { executor.executeMethod(httpMethod, new ThrowExceptionResponseHandler()); fail(); } catch (IOException e) { // expected } long diff = System.currentTimeMillis() - start; assertTrue(diff >= timeout); assertTrue(diff <= timeout * 2); } @Test(timeout = 10000) public void testRunawaySocketHandlerTimeout() throws URISyntaxException, CRLException, IOException { SocketAcceptEvent event = new SocketAcceptEvent() { @Override public void accept(Socket socket) throws IOException { Runnable runnable = new RunawaySocketHandler(socket); new Thread(runnable).start(); } }; server.setIncomingEvent(event); int timeout = 2000; HTTPMethodExecutor executor = new HTTPMethodExecutor(timeout, null); HttpMethod httpMethod = new GetMethod("http://127.0.0.1:" + SERVER_PORT); long start = System.currentTimeMillis(); try { executor.executeMethod(httpMethod, new ThrowExceptionResponseHandler()); fail(); } catch (IOException e) { // expected } long diff = System.currentTimeMillis() - start; assertTrue(diff >= timeout); assertTrue(diff <= timeout * 2); } }