package org.ggp.base.util.http; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; /** * Unit tests for the HttpReader/HttpWriter pair, which are the way that * game players and game servers communicate. Please update these tests * as needed when bugs are discovered, to prevent regressions. * * @author Sam */ public class HttpTest extends Assert { @Test public void testSimpleEcho() throws IOException { SocketPair testPair = new SocketPair(); doSimpleEchoCheck(testPair, "Hello World", "SamplePlayer"); } @SuppressWarnings("serial") @Test public void testSimpleEchoWithHeaders() throws IOException { SocketPair testPair = new SocketPair(); doSimpleEchoCheckPlusHeaders(testPair, "Hello World", "SamplePlayer", new HashMap<String, String>() {{ put("Foo", "Que"); put("Bar", "Quux"); put("Baz", "Quuu"); }}); } @Test public void testPathologicalEchos() throws IOException { SocketPair testPair = new SocketPair(); doSimpleEchoCheck(testPair, "", ""); doSimpleEchoCheck(testPair, "", "SamplePlayer"); doSimpleEchoCheck(testPair, "123 456 ^&!*! // 2198725 !@#$%^&*() DATA", "SamplePlayer"); doSimpleEchoCheck(testPair, "abcdefgijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", "SamplePlayer"); doSimpleEchoCheck(testPair, "Test String", ""); doSimpleEchoCheck(testPair, "Test String", "!@#$%^&*()1234567890"); doSimpleEchoCheck(testPair, "Test String", "abcdefgijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); } @Test public void testGenericPOSTs() throws IOException { SocketPair testPair = new SocketPair(); doClientEchoCheckOverPOST(testPair, "", ""); doClientEchoCheckOverPOST(testPair, "Test String", ""); doClientEchoCheckOverPOST(testPair, "Test String", "Accept: text/delim\nSender: GAMESERVER"); doClientEchoCheckOverPOST(testPair, "1234567890abcdefgijklmnopqrstuvwxyz!@#$%^&*()1234567890", ""); } @Ignore @Test public void testGenericPOSTsWithoutContentLength() throws IOException { SocketPair testPair = new SocketPair(); doClientEchoCheckOverPOSTWithoutContentLength(testPair, "", ""); doClientEchoCheckOverPOSTWithoutContentLength(testPair, "Test String", ""); doClientEchoCheckOverPOSTWithoutContentLength(testPair, "Test String", "Accept: text/delim\nSender: GAMESERVER"); doClientEchoCheckOverPOSTWithoutContentLength(testPair, "1234567890abcdefgijklmnopqrstuvwxyz!@#$%^&*()1234567890", ""); } @Test public void testGenericGETs() throws IOException { SocketPair testPair = new SocketPair(); doClientEchoCheckOverGET(testPair, "", ""); doClientEchoCheckOverGET(testPair, "Test String", ""); doClientEchoCheckOverGET(testPair, "Test String", "Accept: text/delim\nSender: GAMESERVER"); doClientEchoCheckOverGET(testPair, "1234567890abcdefgijklmnopqrstuvwxyz!@#$%^&*()1234567890", ""); } // Helper functions for running specific checks. private void doSimpleEchoCheck(SocketPair p, String data, String playerName) throws IOException { HttpWriter.writeAsClient(p.client, "", data, playerName, null); String readData = HttpReader.readAsServer(p.server); assertEquals(readData.toUpperCase(), data.toUpperCase()); HttpWriter.writeAsServer(p.server, data); readData = HttpReader.readAsClient(p.client); assertEquals(readData.toUpperCase(), data.toUpperCase()); } private void doSimpleEchoCheckPlusHeaders(SocketPair p, String data, String playerName, Map<String, String> extraHeaders) throws IOException { HttpWriter.writeAsClient(p.client, "", data, playerName, extraHeaders); String readData = HttpReader.readAsServer(p.server); assertEquals(readData.toUpperCase(), data.toUpperCase()); HttpWriter.writeAsServer(p.server, data); readData = HttpReader.readAsClient(p.client); assertEquals(readData.toUpperCase(), data.toUpperCase()); } private void doClientEchoCheckOverPOST(SocketPair p, String data, String headers) throws IOException { writeClientPostHTTP(p.client, headers, data, true); String readData = HttpReader.readAsServer(p.server); assertEquals(readData.toUpperCase(), data.toUpperCase()); } private void doClientEchoCheckOverPOSTWithoutContentLength(SocketPair p, String data, String headers) throws IOException { writeClientPostHTTP(p.client, headers, data, false); p.client.close(); String readData = HttpReader.readAsServer(p.server); assertEquals(readData.toUpperCase(), data.toUpperCase()); } private void doClientEchoCheckOverGET(SocketPair p, String data, String headers) throws IOException { writeClientGetHTTP(p.client, headers, data); String readData = HttpReader.readAsServer(p.server); assertEquals(readData.toUpperCase(), data.toUpperCase()); } // Helper functions for testing different types of HTTP interactions. private void writeClientPostHTTP(Socket writeOutTo, String headers, String data, boolean includeContentLength) throws IOException { BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(writeOutTo.getOutputStream())); PrintWriter pw = new PrintWriter(bw); pw.println("POST / HTTP/1.0"); if(headers.length() > 0) pw.println(headers); if(includeContentLength) pw.println("Content-length: " + data.length()); pw.println(); pw.println(data); pw.flush(); } private void writeClientGetHTTP(Socket writeOutTo, String headers, String data) throws IOException { BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(writeOutTo.getOutputStream())); PrintWriter pw = new PrintWriter(bw); pw.println("GET /" + URLEncoder.encode(data, "UTF-8") + " HTTP/1.0"); if(headers.length() > 0) pw.println(headers); pw.println("Content-length: 0"); pw.println(); pw.println(); pw.flush(); } // Utility class to create a pair of client/server sockets // on the local machine that are connected to each other. private class SocketPair { public Socket client; public Socket server; public SocketPair() { // Create a server socket on the first available port. int defaultTestingPort = 13174; ServerSocket ss = null; do { try { ss = new ServerSocket(defaultTestingPort); } catch(Exception e) { ss = null; defaultTestingPort++; } } while(ss == null); try { client = new Socket("127.0.0.1", defaultTestingPort); server = ss.accept(); } catch(Exception e) { fail("Could not establish connection: " + e); e.printStackTrace(); } assertNotNull(client); assertNotNull(server); } } }