public inbox for mauve-patches@sourceware.org
 help / color / mirror / Atom feed
* FYI: Rewrite some HttpURLConnection tests.
@ 2006-08-11 20:05 David Daney
  0 siblings, 0 replies; only message in thread
From: David Daney @ 2006-08-11 20:05 UTC (permalink / raw)
  To: Mauve Patch List

[-- Attachment #1: Type: text/plain, Size: 820 bytes --]

I just committed this change to the TestHttpServer to make it a bit more 
flexable.  The two tests that use it were changed so that they work with 
the changed version.  All this in preperation for a new test to be 
committed real soon now.


2006-08-11  David Daney  <ddaney@avtrex.com>

	* gnu/testlet/java/net/HttpURLConnection/TestHttpServer.java: Rewrote.
	* gnu/testlet/java/net/HttpURLConnection/responseCodeTest.java (test):
	Rewrote to use new TestHttpServer.
	(Factory): New inner class.
	(Handler): New inner class.
	(test_ResponseCode): Use new server.
	* gnu/testlet/java/net/HttpURLConnection/responseHeadersTest.java
	(test):	Rewrote to use new TestHttpServer.
	(Factory): New inner class.
	(Handler): New inner class.
	(test_MultiHeaders): Use new server.
	(test_LowerUpperCaseHeaders): Use new server.


[-- Attachment #2: mauve.d --]
[-- Type: text/plain, Size: 20835 bytes --]

Index: gnu/testlet/java/net/HttpURLConnection/TestHttpServer.java
===================================================================
RCS file: /cvs/mauve/mauve/gnu/testlet/java/net/HttpURLConnection/TestHttpServer.java,v
retrieving revision 1.1
diff -u -p -r1.1 TestHttpServer.java
--- gnu/testlet/java/net/HttpURLConnection/TestHttpServer.java	6 Mar 2006 18:48:44 -0000	1.1
+++ gnu/testlet/java/net/HttpURLConnection/TestHttpServer.java	11 Aug 2006 19:40:20 -0000
@@ -22,7 +22,6 @@
 
 package gnu.testlet.java.net.HttpURLConnection;
 
-
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -30,6 +29,8 @@ import java.io.OutputStream;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 
 
@@ -46,108 +47,95 @@ import java.util.List;
  */
 public final class TestHttpServer implements Runnable
 { 
-  /**
-   * The interface to be implemented if checking
-   * of the serverside received headers and body
-   * is desired.
-   */
-  interface CheckReceivedRequest 
+  
+  public interface ConnectionHandlerFactory
   {
-    /**
-     * Will be called with a List of headers in 
-     * the sequence received by the test server.
-     * 
-     * @param headers List of headers
-     */
-    public void checkHeaders(List headers);
-    
-    /**
-     * Will be called with the body if one was
-     * received.
-     * 
-     * @param body the body
-     */
-    public void checkBody(byte[] body);    
+    ConnectionHandler newConnectionHandler(Socket s) throws IOException;
   }
   
   /**
-   * The actual request handler.
-   * It always returns what is set in the TestHttpServer
-   * for the response headers and response body.
+   * The request handler skeleton.
    */
-  class TestHttpRequestHandler implements Runnable
+  public static abstract class ConnectionHandler implements Runnable
   {  
-    Socket socket;
-    OutputStream output;
-    InputStream input;
-  
-    public TestHttpRequestHandler(Socket socket) throws Exception
+    protected Socket socket;
+    protected OutputStream output;
+    protected InputStream input;
+
+    ConnectionHandler(Socket socket) throws IOException
     {
       this.socket = socket;
       output = socket.getOutputStream();
       input = socket.getInputStream();
     }
-  
+
+    /**
+     * Process one request on the connection.
+     * 
+     * @param headers
+     * @param body
+     * @return true if another request should be read from the connection.
+     * @throws IOException
+     */
+    protected abstract boolean processConnection(List headers, byte[] body)
+      throws IOException;
+    
     public void run()
     {
       try
         {
-          // Read the whole request into a byte array
-          ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-          
-          byte[] b = new byte[1024];
-          int bytes = 0 ;
-          while ((bytes = input.read(b)) != -1)
-            { 
-              buffer.write(b, 0, bytes);
-              if (bytes < 1024)
-                break;
-            }
-          
-          byte[] request = buffer.toByteArray();
-
-          // Parse the request headers from the byte array          
-          List headerList = new ArrayList();
-          
-          ByteArrayOutputStream line;
-          int i = 0;
-          line = new ByteArrayOutputStream();
-          for (; i < request.length; i++)
+          List headerList;
+          int contentLength = -1;
+          byte[] body;
+          do
             {
-              if (request[i] != (byte) 0x0a) // LF
-                line.write(request[i]);
-              else
+              headerList = new ArrayList();
+
+              ByteArrayOutputStream line;
+              line = new ByteArrayOutputStream();
+              for (;;)
                 {
-                  byte[] array = line.toByteArray();
-                  if (array.length == 1) // the last is only a LF
-                    break;
-
-                  String headerLine = new String(array);
-                  headerList.add(headerLine);
-                  line = new ByteArrayOutputStream();
+                  int ch = input.read();
+                  if (-1 == ch)
+                    break; // EOF
+              
+                  if (ch !=  0x0a) // LF
+                    line.write(ch);
+                  else
+                    {
+                      byte[] array = line.toByteArray();
+                      if (array.length == 1) // the last is only a LF
+                        break;
+        	
+                      String headerLine = new String(array);
+                      if (headerLine.length() > 15 &&
+                          "Content-Length:".equalsIgnoreCase(headerLine.substring(0,15)))
+                        {
+                          contentLength = Integer.parseInt(headerLine.substring(15).trim());
+                        }
+                      headerList.add(headerLine);
+                      line = new ByteArrayOutputStream();
+                    }
                 }
-            }
 
-          // Put the remaining bytes into the request body 
-          byte[] body = new byte[(request.length - (i + 1))];
-          System.arraycopy(request, i + 1, body, 0, body.length);
-          
-          // Check everything          
-          if (check != null)
-            {
-              check.checkHeaders(headerList);
-              if (body.length > 0)
-                check.checkBody(body);
-            }         
-             
-          // Response writing          
-          // write the response headers
-          output.write(responseHeader);
-          
-          // write the body 
-          if (responseBody != null)
-            output.write(responseBody);
-          
+              if (contentLength > 0) 
+                {
+                  body = new byte[contentLength];
+                  int pos = 0;
+                  while (pos < contentLength)
+                    {
+                      int nr = input.read(body, pos, body.length - pos);
+                      if (-1 == nr)
+                        break;
+                      pos += nr;
+                    }
+                }
+              else
+                body = null;
+              contentLength = -1;
+              // Check everything
+            } while (processConnection(headerList, body));
+
           // Clean up
           output.close();
           input.close();
@@ -158,52 +146,46 @@ public final class TestHttpServer implem
           // ignore
         }
     }
+
+    protected void forceClosed()
+    {
+      try
+        {
+          socket.close();
+        }
+      catch (IOException ioe)
+        {
+          // Ignore.
+        }
+    }
   }
 
-  int port;
-  byte[] responseHeader;
-  byte[] responseBody;
-  CheckReceivedRequest check;
   boolean kill = false;
   ServerSocket serverSocket;  
-
-  /**
-   * Create a TestHttpServer on given port
-   * @param port the port to use.
-   */
-  public TestHttpServer(int port)
-  {
-    this.port = port;
-  }
+  ConnectionHandlerFactory connectionHandlerFactory;
   
   /**
-   * An object implementing the CheckReceivedRequest
-   * interface. The methods will be called to enable
-   * checks of the serverside received request.
-   * 
-   * @param responseBody the byte[] of the body
+   * Create a TestHttpServer on an unused port.
    */
-  public void setCheckReceivedRequest(CheckReceivedRequest object)
+  public TestHttpServer() throws IOException
   {
-    this.check = object;
+    serverSocket = new ServerSocket(0);
+    Thread t = new Thread(this, "TestHttpServer");
+    t.start();
   }
   
   /**
-   * The bytes which should be sent as the response body.
-   * @param responseBody the byte[] of the body
+   * The local port on which the test server is listening for connections.
+   * @return the port
    */
-  public void setResponseBody(byte[] responseBody)
+  public int getPort()
   {
-    this.responseBody = responseBody;
+    return serverSocket.getLocalPort();
   }
   
-  /**
-   * The bytes which should be sent as the response headers. 
-   * @param responseHeaders the byte[] of the headers
-   */
-  public void setResponseHeaders(byte[] responseHeaders)
+  public synchronized void setConnectionHandlerFactory(ConnectionHandlerFactory f)
   {
-    this.responseHeader = responseHeaders;
+    connectionHandlerFactory = f;
   }
   
   /**
@@ -213,6 +195,7 @@ public final class TestHttpServer implem
   public void killTestServer()
   {
     kill = true;
+    closeAllConnections();
     try
       {
         serverSocket.close();
@@ -223,6 +206,8 @@ public final class TestHttpServer implem
       }
   }
   
+  private List activeConnections = new LinkedList();
+  
   /**
    * Listens on the port and creates a Handler for
    * incoming connections.
@@ -231,17 +216,23 @@ public final class TestHttpServer implem
   {   
     try
       {
-        serverSocket = new ServerSocket(port);
         while (! kill)
           {
             Socket socket = serverSocket.accept();
             try
               {
-                TestHttpRequestHandler request = 
-                  new TestHttpRequestHandler(socket);
+                ConnectionHandlerFactory f;
+                synchronized(this)
+                  {
+                    f = connectionHandlerFactory;
+                  }
+                ConnectionHandler request = f.newConnectionHandler(socket);
                 Thread thread = new Thread(request);
-                
                 thread.start();
+                synchronized(activeConnections)
+                  {
+                    activeConnections.add(request);
+                  }
               }
             catch (Exception e)
               {
@@ -254,4 +245,18 @@ public final class TestHttpServer implem
         // ignore
       }
   }
+  
+  public void closeAllConnections()
+  {
+    synchronized (activeConnections)
+      {
+        Iterator it = activeConnections.iterator();
+        while (it.hasNext())
+          {
+            ConnectionHandler request = (ConnectionHandler)it.next();
+            request.forceClosed();
+            it.remove();
+          }
+      }
+  }
 }
Index: gnu/testlet/java/net/HttpURLConnection/responseCodeTest.java
===================================================================
RCS file: /cvs/mauve/mauve/gnu/testlet/java/net/HttpURLConnection/responseCodeTest.java,v
retrieving revision 1.1
diff -u -p -r1.1 responseCodeTest.java
--- gnu/testlet/java/net/HttpURLConnection/responseCodeTest.java	6 Mar 2006 18:48:44 -0000	1.1
+++ gnu/testlet/java/net/HttpURLConnection/responseCodeTest.java	11 Aug 2006 19:40:20 -0000
@@ -25,12 +25,16 @@ package gnu.testlet.java.net.HttpURLConn
 
 import gnu.testlet.TestHarness;
 import gnu.testlet.Testlet;
-import java.io.ByteArrayOutputStream;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.net.HttpURLConnection;
+import java.net.Socket;
 import java.net.URL;
+import java.util.List;
 
 /**
  * Tests correct behaviour of getInputStream(), getErrorStream()
@@ -39,7 +43,7 @@ import java.net.URL;
 public class responseCodeTest implements Testlet
 {
   /**
-   * Starts an HTTP server on port 8080 and calls
+   * Starts an HTTP server and calls
    * the test_ResponseCode for the error codes.
    */
   public void test(TestHarness h) 
@@ -47,18 +51,17 @@ public class responseCodeTest implements
     TestHttpServer server = null;
     try
       {
-        server = new TestHttpServer(8080);
-        Thread thread = new Thread(server);
-        thread.start();
-        try
-          {
-//          SUN JDK needs some time to open sockets
-            Thread.sleep(100);
-          }
-        catch (InterruptedException e1)
-          {
-          }
-        
+      	try
+      	  {
+            server = new TestHttpServer();
+      	  }
+      	catch (IOException ioe)
+      	  {
+      	    h.debug(ioe);
+      	    h.fail("Could not start server");
+      	    return;
+      	  }
+
         for (int i=400; i < 418; i++)
           test_ResponseCode(i, h, server);
         
@@ -67,30 +70,60 @@ public class responseCodeTest implements
       }
     finally
       {
-        server.killTestServer();
-      }   
+        if (server != null)
+          server.killTestServer();
+      }
+  }
+  
+  static class Factory implements TestHttpServer.ConnectionHandlerFactory
+  {
+    private int responseCode;
+    Factory(int responseCode)
+    {
+      this.responseCode = responseCode;
+    }
+    
+    public TestHttpServer.ConnectionHandler newConnectionHandler(Socket s)
+      throws IOException
+    {
+       return new Handler(s, responseCode);
+    }
+  }
+  
+  static class Handler extends TestHttpServer.ConnectionHandler
+  {
+    private int responseCode;
+    private Writer sink;
+    
+    Handler(Socket socket, int responseCode) throws IOException
+    {
+      super(socket);
+      this.responseCode = responseCode;
+      sink = new OutputStreamWriter(output,"US-ASCII");
+    }
+
+    protected boolean processConnection(List headers, byte[] body)
+      throws IOException
+    {
+      sink.write("HTTP/1.0 " + responseCode + " OK\r\n");
+      sink.write("Server: TestServer\r\n\r\n");
+      sink.close();
+      return false;
+    }
   }
   
   public void test_ResponseCode(int responseCode, 
       TestHarness h, TestHttpServer server)
   {    
     try
-      {        
-        URL url = new URL("http://localhost:8080/");        
-        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        
+      {
+        server.setConnectionHandlerFactory(new Factory(responseCode));
+        URL url = new URL("http://localhost:" + server.getPort() + "/");
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
         conn.setRequestMethod("GET");
         
         h.checkPoint("Test " + responseCode + " response");
 
-        // construct what should be returned by the test server as headers        
-        ByteArrayOutputStream headers = new ByteArrayOutputStream();
-
-        // status line (the responsecode encoded for the test)
-        headers.write(new String("HTTP/1.0 " + responseCode + " OK\r\n").getBytes());
-        headers.write("Server: TestServer\r\n\r\n".getBytes());
-
-        server.setResponseHeaders(headers.toByteArray());
-        
         // test the responsecode
         int code = conn.getResponseCode();
         h.check(code == responseCode);
Index: gnu/testlet/java/net/HttpURLConnection/responseHeadersTest.java
===================================================================
RCS file: /cvs/mauve/mauve/gnu/testlet/java/net/HttpURLConnection/responseHeadersTest.java,v
retrieving revision 1.1
diff -u -p -r1.1 responseHeadersTest.java
--- gnu/testlet/java/net/HttpURLConnection/responseHeadersTest.java	6 Mar 2006 18:48:44 -0000	1.1
+++ gnu/testlet/java/net/HttpURLConnection/responseHeadersTest.java	11 Aug 2006 19:40:20 -0000
@@ -26,65 +26,100 @@ package gnu.testlet.java.net.HttpURLConn
 import gnu.testlet.TestHarness;
 import gnu.testlet.Testlet;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.net.HttpURLConnection;
+import java.net.Socket;
 import java.net.URL;
 import java.util.List;
 import java.util.Map;
 
 public class responseHeadersTest implements Testlet
 {
-
   public void test(TestHarness harness)
   {
     TestHttpServer server = null;
     try
       {
-        server = new TestHttpServer(8080);
-        Thread thread = new Thread(server);
-        thread.start();
-        try
-          {
-            // SUN JDK needs some time to open sockets
-            Thread.sleep(100);
-          }
-        catch (InterruptedException e1)
-          {
-          }
-        
+    	try
+    	  {
+            server = new TestHttpServer();
+    	  }
+    	catch (IOException ioe)
+    	  {
+    	    harness.debug(ioe);
+    	    harness.fail("Could not start server");
+    	    return;
+    	  }
         test_MultiHeaders(harness, server);
         test_LowerUpperCaseHeaders(harness, server);
       }
     finally
       {
         server.killTestServer();
-      }   
+      }
   }
-  
+
+  static class Factory implements TestHttpServer.ConnectionHandlerFactory
+  {
+    private String headers;
+    Factory(String headers)
+    {
+      this.headers = headers;
+    }
+
+    public TestHttpServer.ConnectionHandler newConnectionHandler(Socket s)
+      throws IOException
+    {
+       return new Handler(s, headers);
+    }
+  }
+
+  static class Handler extends TestHttpServer.ConnectionHandler
+  {
+    private String responseHeaders;
+    private Writer sink;
+
+    Handler(Socket socket, String headers) throws IOException
+    {
+      super(socket);
+      this.responseHeaders = headers;
+      sink = new OutputStreamWriter(output,"US-ASCII");
+    }
+
+    protected boolean processConnection(List headers, byte[] body)
+      throws IOException
+    {
+      sink.write(responseHeaders);
+      sink.close();
+      return false;
+    }
+  }
+
   public void test_MultiHeaders(TestHarness h, TestHttpServer server)
   {    
     try
-      {        
-        URL url = new URL("http://localhost:8080/");
+      {
+        Factory f = new Factory(
+           "HTTP/1.0 200 OK\r\n" +
+           "Server: TestServer\r\n" +
+           "Key1: value, value2\r\n" +
+           // set the header a second time with different values
+           // these values must be prepended to key1
+           "Key1: value3\r\n" +
+           "IntHeader: 1234\r\n" +
+           "IntHeaderMalformed: 1234XY\r\n" +
+           "DateHeader: Thu, 02 Mar 2006 14:34:55 +0000\r\n" +
+           "DateHeaderMalformed: Thu, 02 Mar 2006V 14:13:07 +0000\r\n\r\n"
+           );
+
+        server.setConnectionHandlerFactory(f);
+
+        URL url = new URL("http://localhost:" + server.getPort() + "/");
         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
         conn.setRequestMethod("GET");
 
-        // construct what should be returned by the test server as headers
-        ByteArrayOutputStream headers = new ByteArrayOutputStream();
-        headers.write("HTTP/1.0 200 OK\r\n".getBytes());
-        headers.write("Server: TestServer\r\n".getBytes());
-        headers.write("Key1: value, value2\r\n".getBytes());
-        // set the header a second time with different values
-        // these values must be prepended to key1
-        headers.write("Key1: value3\r\n".getBytes());
-        headers.write("IntHeader: 1234\r\n".getBytes());
-        headers.write("IntHeaderMalformed: 1234XY\r\n".getBytes());
-        headers.write("DateHeader: Thu, 02 Mar 2006 14:34:55 +0000\r\n".getBytes());
-        headers.write("DateHeaderMalformed: Thu, 02 Mar 2006V 14:13:07 +0000\r\n\r\n".getBytes());
-
-        server.setResponseHeaders(headers.toByteArray());
-        
         h.checkPoint("getHeaderFields()");
         Map fields = conn.getHeaderFields();
         
@@ -226,23 +261,22 @@ public class responseHeadersTest impleme
   public void test_LowerUpperCaseHeaders(TestHarness h, TestHttpServer server)
   {    
     try
-      {        
-        URL url = new URL("http://localhost:8080/");
+      {
+        Factory f = new Factory(
+           "HTTP/1.0 200 OK\r\n" +
+           "Server: TestServer\r\n" +
+           "AnotherKey: value\r\n" +
+           "Key: value\r\n" +
+           "Key: value1\r\n" +
+           "key: value2\r\n" +
+           "key: value3\r\n\r\n"
+        );
+        server.setConnectionHandlerFactory(f);
+      
+        URL url = new URL("http://localhost:" + server.getPort() + "/");        
         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
         conn.setRequestMethod("GET");
 
-        // construct what should be returned by the test server as headers
-        ByteArrayOutputStream headers = new ByteArrayOutputStream();
-        headers.write("HTTP/1.0 200 OK\r\n".getBytes());
-        headers.write("Server: TestServer\r\n".getBytes());  
-        headers.write("AnotherKey: value\r\n".getBytes());
-        headers.write("Key: value\r\n".getBytes());
-        headers.write("Key: value1\r\n".getBytes());
-        headers.write("key: value2\r\n".getBytes());
-        headers.write("key: value3\r\n\r\n".getBytes());
-        
-        server.setResponseHeaders(headers.toByteArray());
-        
         h.checkPoint("LowerUpperCase header fields tests");
         
         Map fields = conn.getHeaderFields();  

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2006-08-11 20:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-08-11 20:05 FYI: Rewrite some HttpURLConnection tests David Daney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).