package dk.kb.yggdrasil;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mortbay.component.LifeCycle;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.bio.SocketConnector;
import org.mortbay.jetty.servlet.ServletHandler;
/**
* Trivial tests to check if the put/get methods work as intended.
*/
@RunWith(JUnit4.class)
public class HttpCommunicationTest {
protected static File testFileDir = new File("temporarydir");
private HttpCommunication httpCommunication = new HttpCommunication(testFileDir);
@BeforeClass
public static void beforeClass() throws Exception {
testFileDir.mkdirs();
}
@Test
public void testAllSuccess() throws Exception{
HttpPayload httpPayload = null;
byte[] contentBody;
boolean bSuccess;
WebServer server = null;
try {
/*
* Test invalid url. Assuming that port 65535 is not running a webserver.
*/
httpPayload = httpCommunication.get("http://localhost:65535/get");
Assert.assertNull(httpPayload);
contentBody = "the body".getBytes();
bSuccess = httpCommunication.post("http://localhost:65535/post", contentBody, "text/plain");
Assert.assertFalse(bSuccess);
/*
* Start webserver.
*/
server = new WebServer();
server.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*
* Invalid requests.
*/
httpPayload = httpCommunication.get("http://localhost:" + server.port + "/gett");
Assert.assertNull(httpPayload);
contentBody = "the body".getBytes();
bSuccess = httpCommunication.post("http://localhost:" + server.port + "/postt", contentBody, "text/plain");
Assert.assertFalse(bSuccess);
/*
* Valid requests.
*/
httpPayload = httpCommunication.get("http://localhost:" + server.port + "/get");
Assert.assertNotNull(httpPayload);
int read;
byte[] tmpArr = new byte[1024];
InputStream in = httpPayload.getContentBody();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
while ((read = in.read(tmpArr)) != -1) {
bout.write(tmpArr, 0, read);
}
in.close();
Assert.assertNull(httpPayload.getContentEncoding());
Assert.assertEquals("application/x-monkey", httpPayload.getContentType());
Assert.assertEquals(new Long("I am Jettyman.".getBytes().length), httpPayload.getContentLength());
Assert.assertArrayEquals("I am Jettyman.".getBytes(), bout.toByteArray());
contentBody = "the body".getBytes();
bSuccess = httpCommunication.post("http://localhost:" + server.port + "/post", contentBody, "text/plain");
Assert.assertTrue(bSuccess);
// Test the post with Http Entity element
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("uuid", "UUID");
builder.addTextBody("type", "RandomType");
builder.addBinaryBody("file", contentBody);
httpCommunication.post("http://localhost:" + server.port + "/post", builder.build());
} finally {
if (httpPayload != null) {
try {
httpPayload.close();
} catch (IOException e) {
e.printStackTrace();
Assert.fail("Unexpected exception!");
}
httpPayload = null;
}
if (server != null) {
server.stop();
server = null;
}
}
}
/**
* Defines a simple <code>HttpServlet</code> to validate our get/put methods.
*/
public static class Servlet extends HttpServlet {
/**
* UID.
*/
private static final long serialVersionUID = -7223254916357089420L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pathInfo = req.getPathInfo();
String method = req.getMethod();
if ("/get".equals(pathInfo) && "GET".equals(method)) {
resp.setStatus(200);
resp.setContentType("application/x-monkey");
byte[] contentBody = "I am Jettyman.".getBytes();
resp.setContentLength(contentBody.length);
OutputStream out = resp.getOutputStream();
out.write(contentBody);
out.flush();
out.close();
} else if ("/post".equals(pathInfo) && "POST".equals(method)) {
int read;
byte[] tmpArr = new byte[1024];
InputStream in = req.getInputStream();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
while ((read = in.read(tmpArr)) != -1) {
bout.write(tmpArr, 0, read);
}
in.close();
String payload = new String(bout.toByteArray());
if ("the body".equals(payload)) {
resp.setStatus(200);
} else {
resp.sendError(501);
}
} else {
resp.sendError(404);
}
}
}
/**
* Set up a small webserver to test HTTP get/put.
*/
public static class WebServer implements Runnable {
/** Jetty webserver instance. */
public Server webServer;
/** Connector used to get random bind port. */
public Connector connector;
/** Random connector port. */
public int port = -1;
/**
* Stop webserver.
*/
public void stop() {
try {
webServer.stop();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Start webserver.
*/
public void start() {
new Thread(this, "web-server").start();
}
@Override
public void run() {
webServer = new Server();
connector = new SocketConnector();
webServer.setConnectors(new Connector[] {connector});
ServletHandler h = new ServletHandler();
h.addServletWithMapping(Servlet.class, "/*");
webServer.addHandler(h);
webServer.addLifeCycleListener(new LifeCycle.Listener() {
@Override
public void lifeCycleStarting(LifeCycle lifeCycle) {
}
@Override
public void lifeCycleStarted(LifeCycle lifeCycle) {
}
@Override
public void lifeCycleFailure(LifeCycle lifeCycle, Throwable throwable) {
}
@Override
public void lifeCycleStopping(LifeCycle lifeCycle) {
}
@Override
public void lifeCycleStopped(LifeCycle lifeCycle) {
}
});
try {
webServer.start();
port = connector.getLocalPort();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}