Tests. Note that you need to have watchdog checked out and built (if it can still...
authorcostin <costin@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 26 Nov 2009 06:55:49 +0000 (06:55 +0000)
committercostin <costin@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 26 Nov 2009 06:55:49 +0000 (06:55 +0000)
There are a bunch of useful tests in watchdog - I'm not running watchdog, but turned it into JUnit test cases, we just
need the web apps and golden files from there.

At the moment there are about 12 failures (out of ~1000 tests - there are several dups because same tests are run against
different targets )

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@884421 13f79535-47bb-0310-9956-ffa450edef68

47 files changed:
modules/tomcat-lite/test/org/apache/coyote/lite/TomcatLiteCoyoteTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/coyote/servlet/LiteTestHelper.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/coyote/servlet/LiteWatchdogJspTests.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/coyote/servlet/LiteWatchdogServletTests.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/coyote/servlet/TomcatLiteSimpleTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/HexDump.java [deleted file]
modules/tomcat-lite/test/org/apache/tomcat/lite/LiteTestHelper.java [deleted file]
modules/tomcat-lite/test/org/apache/tomcat/lite/LiteWatchdogJspTests.java [deleted file]
modules/tomcat-lite/test/org/apache/tomcat/lite/LiteWatchdogServletTests.java [deleted file]
modules/tomcat-lite/test/org/apache/tomcat/lite/TestMain.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/TomcatLiteSimpleTest.java [deleted file]
modules/tomcat-lite/test/org/apache/tomcat/lite/http/DispatcherTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelInMemoryTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpsTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/http/LiveHttp1Test.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/http/MultiMapTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/EchoCallback.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/SleepCallback.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/http/test.keystore [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/io/BBufferTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/io/CBufferTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/io/OneTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/io/SocksTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/io/UEncoderTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/io/test.properties [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttp5Test.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttpThreadedTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/load/MicroTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/LiveProxyHttp1Test.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/ProxyTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/SmallProxyTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/AnnotationTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/JspWatchdogTests.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/LiteTestHelper.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/PropertiesSpiTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/ServletTests.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/TomcatLiteNoConnectorTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/TomcatLiteSimpleTest.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/TomcatLiteWatchdog.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/lite/test.properties [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/GTest.java [deleted file]
modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogClient.java
modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogHttpClient.java
modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTest.java [deleted file]
modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestCase.java [new file with mode: 0644]
modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java [new file with mode: 0644]

diff --git a/modules/tomcat-lite/test/org/apache/coyote/lite/TomcatLiteCoyoteTest.java b/modules/tomcat-lite/test/org/apache/coyote/lite/TomcatLiteCoyoteTest.java
new file mode 100644 (file)
index 0000000..07efc2a
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ */
+package org.apache.coyote.lite;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.coyote.lite.LiteProtocolHandler;
+import org.apache.tomcat.lite.http.DefaultHttpConnector;
+import org.apache.tomcat.lite.http.HttpChannel;
+import org.apache.tomcat.lite.http.HttpConnector;
+import org.apache.tomcat.lite.io.BBuffer;
+
+public class TomcatLiteCoyoteTest extends TestCase {
+
+    static Tomcat tomcat;
+    LiteProtocolHandler litePH; 
+    
+    public void setUp() {
+        if (tomcat == null) {
+            try {
+                tomcat = new Tomcat();
+                tomcat.setPort(8885);
+                tomcat.setBaseDir("output/build");
+                
+                tomcat.addWebapp("/examples", "examples");
+                tomcat.addWebapp("/", "ROOT");
+
+                
+                //tomcat.addServlet(ctx, "name", "class");
+                // ctx.addServletMapping("/foo/*", "name");
+                
+                litePH = setUp(tomcat);
+                
+                tomcat.start();
+            } catch (LifecycleException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            } catch (ServletException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+    }
+    
+    public static LiteProtocolHandler setUp(Tomcat tomcat) {
+        Connector connector = new Connector(LiteProtocolHandler.class.getName());
+        tomcat.getService().addConnector(connector);
+        connector.setPort(8885);
+        tomcat.setConnector(connector);
+        LiteProtocolHandler ph = 
+            (LiteProtocolHandler) connector.getProtocolHandler();
+        return ph;
+    }
+
+    
+    public void testSimple() throws IOException {
+        HttpConnector clientCon = DefaultHttpConnector.get();
+        HttpChannel ch = clientCon.get("localhost", 8885);
+        ch.getRequest().setRequestURI("/examples/servlets/servlet/HelloWorldExample");
+        ch.sendRequest();
+        BBuffer res = ch.readAll(null, 0);
+        
+        assertTrue(res.toString().indexOf("<title>Hello World!</title>") >= 0);
+    }
+    
+    
+}
diff --git a/modules/tomcat-lite/test/org/apache/coyote/servlet/LiteTestHelper.java b/modules/tomcat-lite/test/org/apache/coyote/servlet/LiteTestHelper.java
new file mode 100644 (file)
index 0000000..c2f989e
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.coyote.servlet;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.coyote.OutputBuffer;
+import org.apache.coyote.Response;
+import org.apache.tomcat.lite.SimpleServlet;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class LiteTestHelper {
+
+    public static void addContext(TomcatLite lite) throws ServletException {
+        ServletContextImpl ctx = 
+            (ServletContextImpl) lite.addServletContext(null, null, "/test1");
+          
+          ctx.addServlet("test", new SimpleServlet());
+          ctx.addMapping("/1stTest", "test");
+
+          ctx.addServlet("testException", new HttpServlet() {
+              public void doGet(HttpServletRequest req, HttpServletResponse res) 
+                throws IOException {
+                throw new NullPointerException();
+              }
+            });
+            ctx.addMapping("/testException", "testException");
+    }
+    
+    public static void initServletsAndRun(TomcatLite lite, int port) throws ServletException, IOException {
+        addContext(lite);
+        lite.init();
+        lite.start(); 
+
+
+        if (port > 0) {
+            // This should be added after all local initialization to avoid
+            // the server from responding.
+            // Alternatively, you can load this early but set it to return
+            // 'unavailable' if load balancers depend on this.
+            addConnector(lite, port, true);
+            
+            // At this point we can add contexts and inject requests, if we want to 
+            // do it over HTTP need to start the connector as well.
+            lite.startConnector(); 
+        }
+    }
+    
+    public static void addConnector(TomcatLite lite, 
+                                    int port, boolean daemon) { 
+        CoyoteConnector coyoteAdapter = (CoyoteConnector) lite.getConnector();
+        coyoteAdapter.setPort(port);
+        coyoteAdapter.setDaemon(daemon);
+    }
+    
+    /**
+     *  Get url using URLConnection.
+     */
+    public static ByteChunk getUrl(String path) throws IOException {
+    
+        ByteChunk out = new ByteChunk();
+        
+        URL url = new URL(path);
+        URLConnection connection = url.openConnection();
+        connection.setReadTimeout(5000);
+        connection.connect();
+        InputStream is = connection.getInputStream();
+        BufferedInputStream bis = new BufferedInputStream(is);
+        byte[] buf = new byte[2048];
+        int rd = 0;
+        while((rd = bis.read(buf)) > 0) {
+            out.append(buf, 0, rd);
+        }
+        return out;
+    }
+    
+    static class ByteChunkOutputBuffer implements OutputBuffer {
+        
+        protected ByteChunk output = null;
+    
+        public ByteChunkOutputBuffer(ByteChunk output) {
+          this.output = output;
+        }
+    
+        public int doWrite(ByteChunk chunk, Response response) 
+            throws IOException {
+          output.append(chunk);
+          return chunk.getLength();
+        }
+    }
+    
+        
+}
diff --git a/modules/tomcat-lite/test/org/apache/coyote/servlet/LiteWatchdogJspTests.java b/modules/tomcat-lite/test/org/apache/coyote/servlet/LiteWatchdogJspTests.java
new file mode 100644 (file)
index 0000000..77ac8d9
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.coyote.servlet;
+
+
+import junit.framework.Test;
+
+public class LiteWatchdogJspTests  extends LiteWatchdogServletTests {
+    
+    public LiteWatchdogJspTests() {
+        super();
+        port = 8017;
+        testMatch = 
+            //"precompileNegativeTest";
+            null;
+        // Test we know are failing - need to fix at some point.
+        exclude = new String[] {
+                "negativeDuplicateExtendsFatalTranslationErrorTest",
+                "negativeDuplicateErrorPageFatalTranslationErrorTest",
+                "negativeDuplicateInfoFatalTranslationErrorTest",
+                "negativeDuplicateLanguageFatalTranslationErrorTest",
+                "negativeDuplicateSessionFatalTranslationErrorTest",
+                "positiveIncludeCtxRelativeHtmlTest",
+                "precompileNegativeTest"
+            }; 
+        file = getWatchdogdir() + "/src/conf/jsp-gtest.xml";
+        goldenDir = 
+            getWatchdogdir() + "/src/clients/org/apache/jcheck/jsp/client/";
+        targetMatch = "jsp-test";
+        
+    }
+    
+    public static Test suite() {
+        return new LiteWatchdogJspTests().getSuite(8017);
+    }
+    
+}
+
diff --git a/modules/tomcat-lite/test/org/apache/coyote/servlet/LiteWatchdogServletTests.java b/modules/tomcat-lite/test/org/apache/coyote/servlet/LiteWatchdogServletTests.java
new file mode 100644 (file)
index 0000000..2ef2177
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.coyote.servlet;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.tomcat.test.watchdog.WatchdogClient;
+
+
+public class LiteWatchdogServletTests extends WatchdogClient {
+  
+  
+  public LiteWatchdogServletTests() {
+      port = 8115;      
+      goldenDir = getWatchdogdir() + "/src/clients/org/apache/jcheck/servlet/client/";
+      testMatch = 
+          //"HttpServletResponseWrapperSetStatusMsgTest";
+          //"ServletContextAttributeAddedEventTest";
+          null;
+          // ex: "ServletToJSP";
+      file = getWatchdogdir() + "/src/conf/servlet-gtest.xml";
+      targetMatch = "gtestservlet-test";
+  }
+  
+  protected void beforeSuite() {
+      // required for the tests
+      System.setProperty("org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER",
+              "true");
+      
+      try {
+          initServerWithWatchdog(getWatchdogdir());
+      } catch (ServletException e) {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
+      } catch (IOException e) {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
+      }
+  }
+  
+  int port = 8115;
+  
+  protected void addConnector(TomcatLite liteServer) {
+      LiteTestHelper.addConnector(liteServer, port, true);      
+  }
+  
+  public void initServerWithWatchdog(String wdDir) throws ServletException, 
+          IOException {
+
+      File f = new File(wdDir + "/build/webapps");
+      
+      //CoyoteServer connector = new CoyoteServer();
+      //connector.addAdapter("/", new MapperAdapter());
+
+      TomcatLite liteServer = new TomcatLite();
+      addConnector(liteServer);
+      liteServer.init("webapps/ROOT", "/");
+
+      for (String s : new String[] {      
+              "servlet-compat", 
+              "servlet-tests",
+              "jsp-tests"} ) {
+          liteServer.init(f.getCanonicalPath() + "/" + s, 
+                        "/" + s);
+      }
+
+      //connector.init();
+      liteServer.init();
+      liteServer.start();
+
+      liteServer.startConnector();
+  }
+
+  
+  
+  protected void afterSuite(TestResult res) {
+      // no need to stop it - using daemon threads.
+      System.err.println("DONE");
+  }
+  
+  
+  /** 
+   * Magic JUnit method 
+   */
+  public static Test suite() {
+      // The individual targets are dups - and bad ones, 
+      // RequestWrapper are missing part of the URL
+      return new LiteWatchdogServletTests().getSuite(8115);
+  }
+}
diff --git a/modules/tomcat-lite/test/org/apache/coyote/servlet/TomcatLiteSimpleTest.java b/modules/tomcat-lite/test/org/apache/coyote/servlet/TomcatLiteSimpleTest.java
new file mode 100644 (file)
index 0000000..ea4081c
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.coyote.servlet;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class TomcatLiteSimpleTest extends TestCase {
+
+  protected TomcatLite lite = new TomcatLite(); 
+  
+  public void setUp() throws Exception {
+      LiteTestHelper.initServletsAndRun(lite, 8804);
+  }
+  
+  public void tearDown() throws Exception {
+    lite.stop();
+  }
+  
+  public void testSimpleRequest() throws Exception {
+    ByteChunk resb = 
+        LiteTestHelper.getUrl("http://localhost:8804/test1/1stTest");
+    assertTrue(resb.getLength() > 0);
+    assertEquals("Hello world", resb.toString());
+  }
+
+  
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/HexDump.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/HexDump.java
deleted file mode 100644 (file)
index 9ded5d9..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.tomcat.lite;
-
-import java.io.ByteArrayOutputStream;
-
-import org.apache.tomcat.util.res.StringManager;
-
-/**
- * Tables useful when converting byte arrays to and from strings of hexadecimal
- * digits.
- * Code from Ajp11, from Apache's JServ.
- *
- * @author Craig R. McClanahan
- */
-
-public final class HexDump {
-
-
-    // -------------------------------------------------------------- Constants
-    static final StringManager sm;
-
-    /**
-     *  Table for HEX to DEC byte translation.
-     */
-    public static final int[] DEC = {
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        00, 01, 02, 03, 04, 05, 06, 07,  8,  9, -1, -1, -1, -1, -1, -1,
-        -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    };
-
-
-    /**
-     * Table for DEC to HEX byte translation.
-     */
-    public static final byte[] HEX = 
-    { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', 
-      (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', 
-      (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' };
-
-
-    // --------------------------------------------------------- Static Methods
-
-
-    /**
-     * Convert a String of hexadecimal digits into the corresponding
-     * byte array by encoding each two hexadecimal digits as a byte.
-     *
-     * @param digits Hexadecimal digits representation
-     *
-     * @exception IllegalArgumentException if an invalid hexadecimal digit
-     *  is found, or the input string contains an odd number of hexadecimal
-     *  digits
-     */
-    public static byte[] convert(String digits) {
-
-       ByteArrayOutputStream baos = new ByteArrayOutputStream();
-       for (int i = 0; i < digits.length(); i += 2) {
-           char c1 = digits.charAt(i);
-           if ((i+1) >= digits.length())
-               throw new IllegalArgumentException
-                   (sm.getString("hexUtil.odd"));
-           char c2 = digits.charAt(i + 1);
-           byte b = 0;
-           if ((c1 >= '0') && (c1 <= '9'))
-               b += ((c1 - '0') * 16);
-           else if ((c1 >= 'a') && (c1 <= 'f'))
-               b += ((c1 - 'a' + 10) * 16);
-           else if ((c1 >= 'A') && (c1 <= 'F'))
-               b += ((c1 - 'A' + 10) * 16);
-           else
-               throw new IllegalArgumentException
-                   (sm.getString("hexUtil.bad"));
-           if ((c2 >= '0') && (c2 <= '9'))
-               b += (c2 - '0');
-           else if ((c2 >= 'a') && (c2 <= 'f'))
-               b += (c2 - 'a' + 10);
-           else if ((c2 >= 'A') && (c2 <= 'F'))
-               b += (c2 - 'A' + 10);
-           else
-               throw new IllegalArgumentException
-                   (sm.getString("hexUtil.bad"));
-           baos.write(b);
-       }
-       return (baos.toByteArray());
-
-    }
-
-
-    /**
-     * Convert a byte array into a printable format containing a
-     * String of hexadecimal digit characters (two per byte).
-     *
-     * @param bytes Byte array representation
-     */
-    public static String convert(byte bytes[]) {
-
-       StringBuilder sb = new StringBuilder(bytes.length * 2);
-       for (int i = 0; i < bytes.length; i++) {
-           sb.append(convertDigit((bytes[i] >> 4)));
-           sb.append(convertDigit((bytes[i] & 0x0f)));
-       }
-       return (sb.toString());
-
-    }
-
-    
-    /**
-     * Convert 4 hex digits to an int, and return the number of converted
-     * bytes.
-     *
-     * @param hex Byte array containing exactly four hexadecimal digits
-     *
-     * @exception IllegalArgumentException if an invalid hexadecimal digit
-     *  is included
-     */
-    public static int convert2Int( byte[] hex ) {
-       // Code from Ajp11, from Apache's JServ
-    
-       // assert b.length==4
-       // assert valid data
-       int len;
-       if(hex.length < 4 ) return 0;
-       if( DEC[hex[0]]<0 )
-           throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
-       len = DEC[hex[0]];
-       len = len << 4;
-       if( DEC[hex[1]]<0 )
-           throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
-       len += DEC[hex[1]];
-       len = len << 4;
-       if( DEC[hex[2]]<0 )
-           throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
-       len += DEC[hex[2]];
-       len = len << 4;
-       if( DEC[hex[3]]<0 )
-           throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
-       len += DEC[hex[3]];
-       return len;
-    }
-
-
-
-    /**
-     * Provide a mechanism for ensuring this class is loaded. 
-     */
-    public static void load() {
-        // Nothing to do
-    }
-
-    /**
-     * [Private] Convert the specified value (0 .. 15) to the corresponding
-     * hexadecimal digit.
-     *
-     * @param value Value to be converted
-     */
-    private static char convertDigit(int value) {
-
-       value &= 0x0f;
-       if (value >= 10)
-           return ((char) (value - 10 + 'a'));
-       else
-           return ((char) (value + '0'));
-
-    }
-
-    /**
-     * <code>getHexValue</code> displays a formatted hex
-     * representation of the passed byte array.  It also
-     * allows for only a specified offset and length of 
-     * a particular array to be returned.
-     *
-     * @param bytes <code>byte[]</code> array to process.
-     * @param pos offset to begin processing.
-     * @param len number of bytes to process.
-     * @return <code>String</code> formatted hex representation of processed 
-     *         array.
-     */
-    public static String getHexDump(byte[] bytes, int pos, int len,
-                                     boolean displayOffset) {
-        StringBuilder out = new StringBuilder( len * 2 );
-
-        for (int j = 0; j < len; j += 16) {
-            hexLine(out, bytes, pos + j, pos + len, displayOffset);
-        }
-     
-        return out.toString();
-    }
-    
-    private static void hexLine(StringBuilder out, 
-                                byte[] bytes, int start, int end,
-                                boolean displayOffset) {
-
-        if ( displayOffset ) {
-            out.append(convertDigit((int) (start >> 12)));
-            out.append(convertDigit((int) (start >> 8)));
-            out.append(convertDigit((int) (start >> 4)));
-            out.append(convertDigit(start & 0x0F));
-            out.append(": ");
-        }
-        for (int i = start; i < start + 16; i++) {
-
-            if (i < end) {
-                out.append(convertDigit((int) (bytes[i] >> 4)));
-                out.append(convertDigit(bytes[i] & 0x0F));
-                out.append(" ");
-            } else { 
-                out.append("   ");
-            }
-        }
-        
-        out.append(" | ");
-        
-        for (int i = start; i < start + 16 && i < end; i++) {
-            if( ! Character.isISOControl( (char)bytes[i] )) {
-                out.append( new Character((char)bytes[i]) );
-            } else {
-                out.append( "." );
-            }
-        }
-        
-        out.append("\n");
-    }
-}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/LiteTestHelper.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/LiteTestHelper.java
deleted file mode 100644 (file)
index 80994db..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.tomcat.lite;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.coyote.OutputBuffer;
-import org.apache.coyote.Response;
-import org.apache.tomcat.lite.coyote.CoyoteConnector;
-import org.apache.tomcat.util.buf.ByteChunk;
-
-public class LiteTestHelper {
-
-    public static void addContext(TomcatLite lite) throws ServletException {
-        ServletContextImpl ctx = 
-            (ServletContextImpl) lite.addServletContext(null, null, "/test1");
-          
-          ctx.addServlet("test", new SimpleServlet());
-          ctx.addMapping("/1stTest", "test");
-
-          ctx.addServlet("testException", new HttpServlet() {
-              public void doGet(HttpServletRequest req, HttpServletResponse res) 
-                throws IOException {
-                throw new NullPointerException();
-              }
-            });
-            ctx.addMapping("/testException", "testException");
-    }
-    
-    public static void initServletsAndRun(TomcatLite lite, int port) throws ServletException, IOException {
-        addContext(lite);
-        lite.init();
-        lite.start(); 
-
-
-        if (port > 0) {
-            // This should be added after all local initialization to avoid
-            // the server from responding.
-            // Alternatively, you can load this early but set it to return
-            // 'unavailable' if load balancers depend on this.
-            addConnector(lite, port, true);
-            
-            // At this point we can add contexts and inject requests, if we want to 
-            // do it over HTTP need to start the connector as well.
-            lite.startConnector(); 
-        }
-    }
-    
-    public static void addConnector(TomcatLite lite, 
-                                    int port, boolean daemon) { 
-        CoyoteConnector coyoteAdapter = (CoyoteConnector) lite.getConnector();
-        coyoteAdapter.setPort(port);
-        coyoteAdapter.setDaemon(daemon);
-    }
-    
-    /**
-     *  Get url using URLConnection.
-     */
-    public static ByteChunk getUrl(String path) throws IOException {
-    
-        ByteChunk out = new ByteChunk();
-        
-        URL url = new URL(path);
-        URLConnection connection = url.openConnection();
-        connection.setReadTimeout(5000);
-        connection.connect();
-        InputStream is = connection.getInputStream();
-        BufferedInputStream bis = new BufferedInputStream(is);
-        byte[] buf = new byte[2048];
-        int rd = 0;
-        while((rd = bis.read(buf)) > 0) {
-            out.append(buf, 0, rd);
-        }
-        return out;
-    }
-    
-    static class ByteChunkOutputBuffer implements OutputBuffer {
-        
-        protected ByteChunk output = null;
-    
-        public ByteChunkOutputBuffer(ByteChunk output) {
-          this.output = output;
-        }
-    
-        public int doWrite(ByteChunk chunk, Response response) 
-            throws IOException {
-          output.append(chunk);
-          return chunk.getLength();
-        }
-    }
-    
-        
-}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/LiteWatchdogJspTests.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/LiteWatchdogJspTests.java
deleted file mode 100644 (file)
index b14dfca..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.lite;
-
-
-import junit.framework.Test;
-
-public class LiteWatchdogJspTests  extends LiteWatchdogServletTests {
-    
-    public LiteWatchdogJspTests() {
-        super();
-        testMatch = 
-            //"precompileNegativeTest";
-            null;
-        // Test we know are failing - need to fix at some point.
-        exclude = new String[] {
-                "negativeDuplicateExtendsFatalTranslationErrorTest",
-                "negativeDuplicateErrorPageFatalTranslationErrorTest",
-                "negativeDuplicateInfoFatalTranslationErrorTest",
-                "negativeDuplicateLanguageFatalTranslationErrorTest",
-                "negativeDuplicateSessionFatalTranslationErrorTest",
-                "positiveIncludeCtxRelativeHtmlTest",
-                "precompileNegativeTest"
-            }; 
-        file = base + "/src/conf/jsp-gtest.xml";
-        goldenDir = 
-            base + "/src/clients/org/apache/jcheck/jsp/client/";
-        targetMatch = "jsp-test";
-        
-    }
-    
-    public static Test suite() {
-        return new LiteWatchdogJspTests().getSuite();
-    }
-    
-}
-
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/LiteWatchdogServletTests.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/LiteWatchdogServletTests.java
deleted file mode 100644 (file)
index ebfd7e5..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.lite;
-
-import java.io.File;
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-
-import junit.framework.Test;
-import junit.framework.TestResult;
-
-import org.apache.tomcat.test.watchdog.WatchdogClient;
-
-
-public class LiteWatchdogServletTests extends WatchdogClient {
-  
-  
-  public LiteWatchdogServletTests() {
-      goldenDir = base + "/src/clients/org/apache/jcheck/servlet/client/";
-      testMatch = 
-          //"HttpServletResponseWrapperSetStatusMsgTest";
-          //"ServletContextAttributeAddedEventTest";
-          null;
-          // ex: "ServletToJSP";
-      file = base + "/src/conf/servlet-gtest.xml";
-      targetMatch = "gtestservlet-test";
-  }
-  
-  protected void beforeSuite() {
-      // required for the tests
-      System.setProperty("org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER",
-              "true");
-      String path = System.getProperty("watchdog.home");
-      if (path != null) {
-          base = path;
-      }
-      
-      try {
-          initServerWithWatchdog(base);
-      } catch (ServletException e) {
-          // TODO Auto-generated catch block
-          e.printStackTrace();
-      } catch (IOException e) {
-          // TODO Auto-generated catch block
-          e.printStackTrace();
-      }
-  }
-  
-  protected void addConnector(TomcatLite liteServer) {
-      LiteTestHelper.addConnector(liteServer, 8080, true);      
-  }
-  
-  public void initServerWithWatchdog(String wdDir) throws ServletException, 
-          IOException {
-
-      File f = new File(wdDir + "/build/webapps");
-      
-      //CoyoteServer connector = new CoyoteServer();
-      //connector.addAdapter("/", new MapperAdapter());
-
-      TomcatLite liteServer = new TomcatLite();
-      addConnector(liteServer);
-      liteServer.init("webapps/ROOT", "/");
-
-      for (String s : new String[] {      
-              "servlet-compat", 
-              "servlet-tests",
-              "jsp-tests"} ) {
-          liteServer.init(f.getCanonicalPath() + "/" + s, 
-                        "/" + s);
-      }
-
-      //connector.init();
-      liteServer.init();
-      liteServer.start();
-
-      liteServer.startConnector();
-  }
-
-  
-  
-  protected void afterSuite(TestResult res) {
-      // no need to stop it - using daemon threads.
-      System.err.println("DONE");
-  }
-  
-  
-  /** 
-   * Magic JUnit method 
-   */
-  public static Test suite() {
-      // The individual targets are dups - and bad ones, 
-      // RequestWrapper are missing part of the URL
-      return new LiteWatchdogServletTests().getSuite();
-  }
-}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/TestMain.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/TestMain.java
new file mode 100644 (file)
index 0000000..32affa2
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ */
+package org.apache.tomcat.lite;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.tomcat.integration.simple.Main;
+import org.apache.tomcat.integration.simple.SimpleObjectManager;
+import org.apache.tomcat.lite.http.BaseMapper;
+import org.apache.tomcat.lite.http.DefaultHttpConnector;
+import org.apache.tomcat.lite.http.Dispatcher;
+import org.apache.tomcat.lite.http.HttpChannel;
+import org.apache.tomcat.lite.http.HttpConnector;
+import org.apache.tomcat.lite.http.BaseMapper.ContextMapping;
+import org.apache.tomcat.lite.http.HttpConnector.HttpChannelEvents;
+import org.apache.tomcat.lite.http.services.EchoCallback;
+import org.apache.tomcat.lite.http.services.SleepCallback;
+import org.apache.tomcat.lite.io.BBuffer;
+import org.apache.tomcat.lite.io.SocketConnector;
+import org.apache.tomcat.lite.io.SslConnector;
+import org.apache.tomcat.lite.proxy.HttpProxyService;
+import org.apache.tomcat.lite.proxy.StaticContentService;
+import org.apache.tomcat.lite.service.IOStatus;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+/**
+ * Server with lost of test servlets.
+ * 
+ * Used in tests - one is running for the entire suite.
+ * 
+ * @author Costin Manolache
+ */
+public class TestMain {
+    static TestMain defaultServer;
+    
+    SimpleObjectManager om;
+
+    static SocketConnector serverCon = new SocketConnector();
+    
+    public static HttpConnector testClient = DefaultHttpConnector.get();
+    public static HttpConnector testServer = new HttpConnector(serverCon);
+    public static HttpConnector testProxy = new HttpConnector(serverCon);
+    
+    static Dispatcher mcb;
+    static HttpProxyService proxy;
+
+   
+    public static HttpConnector getTestServer() {
+        if (defaultServer == null) {
+            defaultServer = new TestMain();
+            defaultServer.run();
+        }
+        return defaultServer.testServer;
+    }
+
+
+    public static void initTestCallback(Dispatcher d) {
+        BaseMapper.ContextMapping mCtx = d.addContext(null, "", null, null, null, null);
+//      testServer.setDebugHttp(true);
+//      testServer.setDebug(true);
+        
+        d.addWrapper(mCtx, "/", new StaticContentService()
+            .setContentType("text/html")
+            .setData("<a href='/proc/cpool/client'>Client pool</a><br/>" +
+                    "<a href='/proc/cpool/server'>Server pool</a><br/>" +
+                    "<a href='/proc/cpool/proxy'>Proxy pool</a><br/>" +
+                    ""));
+
+        d.addWrapper(mCtx, "/hello", new StaticContentService().setData("Hello world"));
+        d.addWrapper(mCtx, "/2nd", new StaticContentService().setData("Hello world2"));
+        d.addWrapper(mCtx, "/echo/*", new EchoCallback());
+
+        d.addWrapper(mCtx, "/sleep/1", new SleepCallback().setData("sleep 1"));
+        d.addWrapper(mCtx, "/sleep/10", new SleepCallback().sleep(10000).setData(
+                "sleep 1"));
+
+        d.addWrapper(mCtx, "/chunked/*", new StaticContentService().setData("AAAA")
+                .chunked());
+        
+        d.addWrapper(mCtx, "/proc/cpool/client", new IOStatus(testClient.cpool));
+        d.addWrapper(mCtx, "/proc/cpool/proxy", new IOStatus(testProxy.cpool));
+        d.addWrapper(mCtx, "/proc/cpool/server", new IOStatus(testServer.cpool));
+    }
+
+    static boolean RELEASE = true;
+    /**
+     * Blocking get, returns when the body has been read.
+     */
+    public static BBuffer get(String url) throws IOException {
+
+        BBuffer out = BBuffer.allocate();
+
+        HttpChannel aclient = DefaultHttpConnector.get().get(url);
+        aclient.sendRequest();
+        aclient.readAll(out, 
+                //Long.MAX_VALUE);//
+                2000000);
+        if (RELEASE) {
+            aclient.release(); // return connection to pool
+        }
+        return out;
+    }
+
+    public void run() {
+        String cfgFile = "org/apache/tomcat/lite/test.properties";
+        try {
+            startAll(cfgFile, 8000);
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+    } 
+    
+    protected void startAll(String cfgFile, int basePort) {
+        if (om == null) {
+            om = new SimpleObjectManager();
+        }
+
+        om.loadResource(cfgFile);
+
+        //        // Override the port - don't want on 8080, Watchdog may run in same 
+//        // process
+//        om.getProperties().put("org.apache.tomcat.lite.Connector.port", 
+//                Integer.toString(basePort + 800));
+        
+        // From Main:
+        String run = (String) om.getProperty("RUN");
+        String[] runNames = run == null ? new String[] {} : run.split(",");
+        
+        for (String name: runNames) {
+            Object main = om.get(name);
+            
+            if (main instanceof Runnable) {
+                ((Runnable) main).run();
+            }
+        }
+
+        om.bind("HttpConnector-TestServer", testServer);
+        om.bind("HttpConnector", testClient);
+        om.bind("HttpConnector-Proxy", testProxy);
+        
+        testServer.setOnCreate(new HttpChannelEvents() {
+            @Override
+            public void onCreate(HttpChannel data, HttpConnector extraData)
+                    throws IOException {
+                //data.trace("BIND");
+                om.bind("AsyncHttp-" + data.getId(), data);
+            }
+            @Override
+            public void onDestroy(HttpChannel data, HttpConnector extraData)
+                    throws IOException {
+                //data.trace("UNBIND");
+                om.unbind("AsyncHttp-" + data.getId());
+            }
+        });
+        
+//        ioConnector.setOnCreate(new IOConnector.ConnectedCallback() {
+//            AtomicInteger ser = new AtomicInteger();
+//            @Override
+//            public void handleConnected(IOChannel data)
+//                    throws IOException {
+//                data.setId("IOChannel-" + data.getTarget() + "-" + 
+//                        ser.incrementAndGet());
+//                om.bind(data.getId(), data);
+//            }
+//        });
+//        ioConnector.setOnClose(new IOConnector.ClosedCallback() {
+//            @Override
+//            public void handleClosed(IOChannel data)
+//                    throws IOException {
+//               System.err.println("UNBIND " + data.getId() + " " + data);
+//               om.unbind(data.getId());
+//            }
+//        });
+//        ioConnector.onNewWorker = new Callback<NioThread>() {
+//            @Override
+//            public void handle(NioThread data, Object extraData)
+//                    throws IOException {
+//                om.bind((String) extraData, data);
+//            }
+//        };
+        
+        int port = basePort + 903;
+        if (proxy == null) {
+            proxy = new HttpProxyService()
+                .withHttpClient(testClient);
+            testProxy.setPort(port);
+            testProxy.setDebugHttp(true);
+            testProxy.setDebug(true);
+
+            // dispatcher rejects 'http://'
+            testProxy.setHttpService(proxy);
+            try {
+                testProxy.start();
+            } catch (IOException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+            
+            port = basePort + 802;
+            initTestCallback(testServer.getDispatcher());
+            testServer.setPort(port);
+            try {
+                testServer.start();
+            } catch (IOException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+            
+            port = basePort + 443;
+            
+        }   
+        
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            public void run() {
+                System.err.println("Done");
+            }
+            public void start() {
+                System.err.println("Done1");
+            }
+        });
+
+        
+//        try {
+//            ServletContextImpl ctx = (ServletContextImpl) tomcat.addServletContext(null, null, "/jmx");
+//            // tomcat is already started, need to call init explicitely
+//            ((ServletContextImpl) ctx).loadConfig();
+//            
+//            Servlet servlet = new JMXProxyServlet();
+//            ServletRegistration.Dynamic jmxServlet = ctx.addServlet("jmx", 
+//                    servlet);
+//            jmxServlet.addMapping("/jmx");
+//            // TODO: init servlet 
+//            servlet.init(new ServletConfigImpl(ctx, null, null));
+//
+//            ctx.start();
+//            
+//        } catch (ServletException e) {
+//            // TODO Auto-generated catch block
+//            e.printStackTrace();
+//        }
+
+    }
+
+    static {
+        SslConnector.fixUrlConnection();
+    }
+    
+    public static ByteChunk getUrl(String path) throws IOException {
+        ByteChunk out = new ByteChunk();
+        getUrl(path, out, null);
+        return out;
+    }
+
+    public static int getUrl(String path, 
+                             ByteChunk out, 
+                             Map<String, List<String>> resHead) throws IOException {
+        URL url = new URL(path);
+        HttpURLConnection connection = 
+            (HttpURLConnection) url.openConnection();
+       // connection.setReadTimeout(100000);
+        connection.connect();
+        int rc = connection.getResponseCode();
+        if (resHead != null) {
+            Map<String, List<String>> head = connection.getHeaderFields();
+            resHead.putAll(head);
+        }
+        InputStream is = connection.getInputStream();
+        BufferedInputStream bis = new BufferedInputStream(is);
+        byte[] buf = new byte[2048];
+        int rd = 0;
+        while((rd = bis.read(buf)) > 0) {
+            out.append(buf, 0, rd);
+        }
+        return rc;
+    }
+    
+    
+    public static void main(String[] args) throws Exception, IOException {
+        TestMain testMain = new TestMain();
+        TestMain.defaultServer = testMain;
+        testMain.om = new SimpleObjectManager(args);
+        testMain.run();
+        Main.waitStop();
+    }
+
+    
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/TomcatLiteSimpleTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/TomcatLiteSimpleTest.java
deleted file mode 100644 (file)
index 4953eaf..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.tomcat.lite;
-
-import junit.framework.TestCase;
-
-import org.apache.tomcat.util.buf.ByteChunk;
-
-public class TomcatLiteSimpleTest extends TestCase {
-
-  protected TomcatLite lite = new TomcatLite(); 
-  
-  public void setUp() throws Exception {
-      LiteTestHelper.initServletsAndRun(lite, 8804);
-  }
-  
-  public void tearDown() throws Exception {
-    lite.stop();
-  }
-  
-  public void testSimpleRequest() throws Exception {
-    ByteChunk resb = 
-        LiteTestHelper.getUrl("http://localhost:8804/test1/1stTest");
-    assertTrue(resb.length() > 0);
-    assertEquals("Hello world", resb.toString());
-  }
-
-  
-}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/DispatcherTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/DispatcherTest.java
new file mode 100644 (file)
index 0000000..6c90bca
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ */
+package org.apache.tomcat.lite.http;
+
+import org.apache.tomcat.lite.io.CBuffer;
+
+import junit.framework.TestCase;
+
+public class DispatcherTest extends TestCase {
+
+    public void testMapper() throws Exception {
+        BaseMapper mapper = new BaseMapper();
+
+        String[] welcomes = new String[2];
+        welcomes[0] = "index.html";
+        welcomes[1] = "foo.html";
+
+        mapper.addContext("test1.com", "", "context0", new String[0], null, null);
+        mapper.addContext("test1.com", "/foo", "context1", new String[0], null, null);
+        mapper.addContext("test1.com", "/foo/bar", "context2", welcomes, null, null);
+        mapper.addContext("test1.com", "/foo/bar/bla", "context3", new String[0], null, null);
+
+        mapper.addWrapper("test1.com", "/foo/bar", "/fo/*", "wrapper0");
+        mapper.addWrapper("test1.com", "/foo/bar", "/", "wrapper1");
+        mapper.addWrapper("test1.com", "/foo/bar", "/blh", "wrapper2");
+        mapper.addWrapper("test1.com", "/foo/bar", "*.jsp", "wrapper3");
+        mapper.addWrapper("test1.com", "/foo/bar", "/blah/bou/*", "wrapper4");
+        mapper.addWrapper("test1.com", "/foo/bar", "/blah/bobou/*", "wrapper5");
+        mapper.addWrapper("test1.com", "/foo/bar", "*.htm", "wrapper6");
+
+        mapper.addContext("asdf.com", "", "context0", new String[0], null, null);
+
+        MappingData mappingData = new MappingData();
+        
+        CBuffer host = CBuffer.newInstance();
+        host.set("test1.com");
+        
+        CBuffer uri = CBuffer.newInstance();
+        uri.set("/foo/bar/blah/bobou/foo");
+
+        mapper.map(host, uri, mappingData);
+        
+        assertEquals("context2", mappingData.context.toString());
+        assertEquals("/foo/bar", mappingData.contextPath.toString());
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelInMemoryTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelInMemoryTest.java
new file mode 100644 (file)
index 0000000..5ebbf92
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ */
+package org.apache.tomcat.lite.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.lite.http.HttpChannel.HttpService;
+import org.apache.tomcat.lite.http.HttpChannel.RequestCompleted;
+import org.apache.tomcat.lite.io.BBuffer;
+import org.apache.tomcat.lite.io.CBuffer;
+import org.apache.tomcat.lite.io.IOBuffer;
+import org.apache.tomcat.lite.io.IOChannel;
+import org.apache.tomcat.lite.io.IOConnector;
+import org.apache.tomcat.lite.io.MemoryIOConnector;
+import org.apache.tomcat.lite.io.MemoryIOConnector.MemoryIOChannel;
+
+public class HttpChannelInMemoryTest extends TestCase {
+    
+    MemoryIOConnector memoryServerConnector =  new MemoryIOConnector();
+    MemoryIOConnector memoryClientConnector = 
+        new MemoryIOConnector().withServer(memoryServerConnector);
+
+    
+    // Used for pipelined requests - after the first request is 
+    // processed, a new HttpChannel is used ( first may still be 
+    // in use )
+    HttpChannel lastServer;
+    
+    // The server channel will use this for I/O...
+    MemoryIOConnector.MemoryIOChannel net = new MemoryIOChannel();
+
+    HttpConnector serverConnector = new HttpConnector(memoryServerConnector) {
+        @Override
+        public HttpChannel get(CharSequence target) throws IOException {
+            throw new IOException();
+        }
+        public HttpChannel getServer() {
+            lastServer = new HttpChannel().serverMode(true);
+            lastServer.withBuffers(net);
+            lastServer.setConnector(this);
+            //lastServer.withIOConnector(memoryServerConnector);
+            return lastServer;
+        }
+    };
+
+    HttpConnector httpClient = new HttpConnector(memoryClientConnector);
+
+    boolean hasBody = false;
+    boolean bodyDone = false;
+    boolean bodySentDone = false;
+    boolean headersDone = false;
+    boolean allDone = false;
+    
+    
+    HttpChannel http = serverConnector.getServer();
+    
+    public void setUp() throws IOException {
+        serverConnector.setHttpService(null);
+    }
+    
+   
+    public void test2Req() throws IOException {
+        String req = "GET /index.html?q=b&c=d HTTP/1.1\r\n" +
+        "Host:  Foo.com \n" + 
+        "H2:Bar\r\n" + 
+        "H3: Foo \r\n" +
+        " Bar\r\n" +
+        "H4: Foo\n" +
+        "    Bar\n" +
+        "\r\n" + 
+        "HEAD /r2? HTTP/1.1\n" +
+        "Host: Foo.com\r\n" +
+        "H3: Foo \r\n" +
+        "       Bar\r\n" +
+        "H4: Foo\n" +
+        " Bar\n" +
+        "\r\n";
+        net.getIn().append(req);        
+        
+        assertTrue(http.getRequest().method().equals("GET"));
+        assertTrue(http.getRequest().protocol().equals("HTTP/1.1"));
+        assertEquals(http.getRequest().getMimeHeaders().size(), 4);
+        assertEquals(http.getRequest().getMimeHeaders().getHeader("Host").toString(),
+                "Foo.com");
+        assertEquals(http.getRequest().getMimeHeaders().getHeader("H2").toString(),
+                "Bar");
+        
+        http.getOut().append("Response1");
+        http.getOut().close();
+        http.startSending();
+        http.release(); 
+        
+        // now second response must be in. 
+        // the connector will create a new http channel
+        
+        http = lastServer;
+        
+        assertTrue(http.getRequest().method().equals("HEAD"));
+        assertTrue(http.getRequest().protocol().equals("HTTP/1.1"));
+        assertTrue(http.getRequest().getMimeHeaders().size() == 3);
+        assertTrue(http.getRequest().getMimeHeaders().getHeader("Host")
+                .equals("Foo.com"));
+    }
+
+    public void testMultiLineHead() throws IOException {
+        http.getNet().getIn().append("GET / HTTP/1.0\n" +
+                "Cookie: 1234\n" +
+                "  456 \n" +
+                "Connection:   Close\n\n");
+        http.getNet().getIn().close();
+        
+        MultiMap headers = http.getRequest().getMimeHeaders();
+        CBuffer cookie = headers.getHeader("Cookie");
+        CBuffer conn = headers.getHeader("Connection");
+        assertEquals(conn.toString(), "Close");
+        assertEquals(cookie.toString(), "1234 456");
+        
+        assertEquals(http.headRecvBuf.toString(), 
+                "GET / HTTP/1.0\n" +
+                "Cookie: 1234 456   \n" + // \n -> trailing space
+                "Connection:   Close\n\n");
+    }
+
+    public void testCloseSocket() throws IOException {
+        http.getNet().getIn().append("GET / HTTP/1.1\n"
+                + "Host: localhost\n"
+                + "\n");
+        assertTrue(http.keepAlive());
+
+        http.getNet().getIn().close();
+        assertFalse(http.keepAlive());
+    }
+    
+    public void test2ReqByte2Byte() throws IOException {
+        String req = "GET /index.html?q=b&c=d HTTP/1.1\r\n" +
+        "Host:  Foo.com \n" + 
+        "H2:Bar\r\n" + 
+        "H3: Foo \r\n" +
+        " Bar\r\n" +
+        "H4: Foo\n" +
+        "    Bar\n" +
+        "\r\n" + 
+        "HEAD /r2? HTTP/1.1\n" +
+        "Host: Foo1.com\n" +
+        "H3: Foo \r\n" +
+        "       Bar\r\n" +
+        "\r\n";
+        for (int i = 0; i < req.length(); i++) {
+            net.getIn().append(req.charAt(i));        
+        }
+        
+        assertTrue(http.getRequest().method().equals("GET"));
+        assertTrue(http.getRequest().protocol().equals("HTTP/1.1"));
+        assertTrue(http.getRequest().getMimeHeaders().size() == 4);
+        assertTrue(http.getRequest().getMimeHeaders().getHeader("Host")
+                .equals("Foo.com"));
+        
+        // send a response
+        http.sendBody.append("Response1");
+        http.getOut().close();
+        
+        http.startSending(); // This will trigger a pipelined request
+        
+        http.release(); // now second response must be in
+        
+        http = lastServer;
+        assertTrue(http.getRequest().method().equals("HEAD"));
+        assertTrue(http.getRequest().protocol().equals("HTTP/1.1"));
+        assertTrue(http.getRequest().getMimeHeaders().size() == 2);
+        assertTrue(http.getRequest().getMimeHeaders().getHeader("Host")
+                .equals("Foo1.com"));
+
+        // send a response - service method will be called
+        http.sendBody.append("Response2");
+        http.getOut().close();
+        http.release(); // now second response must be in
+        
+        
+    }
+    
+    public void testEndWithoutFlushCallbacks() throws IOException {
+        http.setCompletedCallback(new RequestCompleted() {
+            public void handle(HttpChannel data, Object extra)
+            throws IOException {
+                allDone = true;
+            }
+        });
+        http.getNet().getIn().append(POST);
+        http.getNet().getIn().close();
+        
+        http.sendBody.queue("Hi");
+        http.getOut().close();
+        http.startSending(); // will call handleEndSend
+
+        assertTrue(allDone);
+        
+    }
+
+    public void testCallbacks() throws IOException {
+        http.setCompletedCallback(new RequestCompleted() {
+            public void handle(HttpChannel data, Object extra)
+            throws IOException {
+                allDone = true;
+            }
+        });
+        http.setHttpService(new HttpService() {
+            public void service(HttpRequest httpReq, HttpResponse httpRes)
+            throws IOException {
+                headersDone = true;
+            }
+        });
+        http.setDataReceivedCallback(new IOConnector.DataReceivedCallback() {
+            @Override
+            public void handleReceived(IOChannel ch) throws IOException {
+                if (ch.getIn().isAppendClosed()) {
+                    bodyDone = true;
+                }
+            }
+        });
+        http.setDataFlushedCallback(new IOConnector.DataFlushedCallback() {
+            @Override
+            public void handleFlushed(IOChannel ch) throws IOException {
+                if (ch.getOut().isAppendClosed()) {
+                    bodySentDone = true;
+                }
+            }
+        });
+
+        // Inject the request
+        http.getNet().getIn().append(POST);
+        assertTrue(headersDone);
+        http.getNet().getIn().append("1234");
+        
+        http.getNet().getIn().close();
+        assertTrue(bodyDone);
+        
+        
+        http.sendBody.queue("Hi");
+        http.getOut().close();
+        http.startSending();
+        assertTrue(bodySentDone);
+
+        assertTrue(allDone);
+        
+    }
+    
+    public static String POST = "POST / HTTP/1.0\n" +
+        "Connection: Close\n" +
+        "Content-Length: 4\n\n" +
+        "1234"; 
+
+    public void testClose() throws IOException {
+        http.getNet().getIn().append(POST);
+        http.getNet().getIn().close();
+        
+        HttpBody receiveBody = http.receiveBody;
+        IOBuffer appData = receiveBody;
+        BBuffer res = BBuffer.allocate(1000);
+        appData.readAll(res);
+        
+        assertEquals(res.toString(), "1234");
+        assertFalse(http.keepAlive());
+        assertFalse(http.keepAlive());
+        
+        http.sendBody.queue(res);
+        http.getOut().close();
+        http.startSending();
+        
+        assertTrue(net.getOut().isAppendClosed());
+        assertTrue(net.out.toString().indexOf("\n1234") > 0);
+        
+    }
+    
+    public void testReadLine() throws Exception {
+        http.getNet().getIn().append("POST / HTTP/1.0\n" +
+                       "Content-Length: 28\n\n" +
+                "Line 1\n" +
+                "Line 2\r\n" +
+                "Line 3\r" +
+                "Line 4");
+        http.getNet().getIn().close();
+        
+        BufferedReader r = http.getRequest().getReader();
+        assertEquals("Line 1", r.readLine());
+        assertEquals("Line 2", r.readLine());
+        assertEquals("Line 3", r.readLine());
+        assertEquals("Line 4", r.readLine());
+        assertEquals(null, r.readLine());
+        
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpChannelTest.java
new file mode 100644 (file)
index 0000000..5cda35f
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ */
+package org.apache.tomcat.lite.http;
+
+import java.io.IOException;
+
+import org.apache.tomcat.lite.io.BBuffer;
+import org.apache.tomcat.lite.io.CBuffer;
+
+import junit.framework.TestCase;
+
+public class HttpChannelTest extends TestCase {
+
+    HttpChannel ch = new HttpChannel().serverMode(true);
+    HttpRequest req = ch.getRequest();
+    
+    
+    BBuffer head = BBuffer.allocate();
+    BBuffer line = BBuffer.wrapper();
+    BBuffer name = BBuffer.wrapper();
+    BBuffer value = BBuffer.wrapper();
+    
+    BBuffer statusB = BBuffer.wrapper();
+    BBuffer msgB = BBuffer.wrapper();
+    BBuffer methodB = BBuffer.wrapper();
+    BBuffer queryB = BBuffer.wrapper("");
+    BBuffer requestB = BBuffer.wrapper();
+    BBuffer protoB = BBuffer.wrapper();
+    
+    BBuffer l7 = BBuffer.wrapper("GET \n");
+    BBuffer l8 = BBuffer.wrapper("GET /\n");
+    BBuffer l9 = BBuffer.wrapper("GET /a?b\n");
+    BBuffer l10 = BBuffer.wrapper("GET /a?b HTTP/1.0\n");
+    BBuffer l11 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b");
+    BBuffer l12 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\n");
+    
+    BBuffer f1 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\n\n");
+    BBuffer f2 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\n\r\n");
+    BBuffer f3 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\r");
+    BBuffer f4 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\n\r");
+
+    
+    public void reqTest(String lineS, String method, String req, 
+            String qry, String proto) throws IOException {
+        BBuffer line = BBuffer.wrapper(lineS);
+        queryB.recycle();
+        protoB.recycle();
+        requestB.recycle();
+        methodB.recycle();
+        ch.parseRequestLine(line, methodB, requestB, queryB, protoB);
+        assertEquals(proto, protoB.toString());
+        assertEquals(req, requestB.toString());
+        assertEquals(qry, queryB.toString());
+        assertEquals(method, methodB.toString());
+    }
+
+    public void testParams() throws IOException {
+        MultiMap params = processQry("a=b&c=d");
+        assertEquals("b", params.getString("a"));
+    }
+
+    private MultiMap processQry(String qry) throws IOException {
+        BBuffer head = BBuffer.wrapper("GET /a?" + qry + " HTTP/1.0\n" +
+                       "Host: a\n\n");
+        ch.parseMessage(head);
+        MultiMap params = req.getParameters();
+        return params;
+    }
+    
+    public void testParseReq() throws IOException {
+        reqTest("GET / HTTP/1.0", "GET", "/", "", "HTTP/1.0");
+        reqTest("GET", "GET", "", "", "");
+        reqTest("GET   / HTTP/1.0", "GET", "/", "", "HTTP/1.0");
+        reqTest("GET /     HTTP/1.0", "GET", "/", "", "HTTP/1.0");
+        reqTest("GET /?b HTTP/1.0", "GET", "/", "b", "HTTP/1.0");
+        reqTest("GET ?a HTTP/1.0", "GET", "", "a", "HTTP/1.0");
+        reqTest("GET a HTTP/1.0", "GET", "a", "", "HTTP/1.0");
+        reqTest("GET a? HTTP/1.0", "GET", "a", "", "HTTP/1.0");
+    }
+    
+    public void headTest(String headS, String expName, String expValue, 
+            String expLine, String expRest) throws IOException {
+        head = BBuffer.wrapper(headS);
+        head.readLine(line);
+        ch.parseHeader(head, line, name, value);
+        
+        assertEquals(expName, name.toString());
+        assertEquals(expValue, value.toString());
+
+        assertEquals(expLine, line.toString());
+        assertEquals(expRest, head.toString());
+    }
+    
+    public void testParseHeader() throws IOException {
+        headTest("a:b\n", "a", "b", "", "");
+        headTest("a :b\n", "a", "b", "", "");
+        headTest("a : b\n", "a", "b", "", "");
+        headTest("a :  b\n", "a", "b", "", "");
+        headTest("a :  b c \n", "a", "b c", "", "");
+        headTest("a :  b c\n", "a", "b c", "", "");
+        headTest("a :  b  c\n", "a", "b c", "", "");
+        headTest("a :  b  \n c\n", "a", "b c", "", "");
+        headTest("a :  b  \n  c\n", "a", "b c", "", "");
+        headTest("a :  b  \n  c\nd:", "a", "b c", "", "d:");
+       
+    }
+    
+    public void responseTest(String lineS, String proto, String status, 
+            String msg) throws IOException {
+        protoB.recycle();
+        statusB.recycle();
+        msgB.recycle();
+        BBuffer line = BBuffer.wrapper(lineS);
+        ch.parseResponseLine(line, 
+                protoB, statusB, msgB);
+        assertEquals(proto, protoB.toString());
+        assertEquals(status, statusB.toString());
+        assertEquals(msg, msgB.toString());
+    }
+    
+    public void testResponse() throws Exception {
+        responseTest("HTTP/1.1 200 OK", "HTTP/1.1", "200", "OK");
+        responseTest("HTTP/1.1  200 OK", "HTTP/1.1", "200", "OK");
+        responseTest("HTTP/1.1  200", "HTTP/1.1", "200", "");
+        responseTest("HTTP/1.1", "HTTP/1.1", "", "");
+    }
+    
+    
+
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpsTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/HttpsTest.java
new file mode 100644 (file)
index 0000000..5eb2800
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tomcat.lite.http;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.tomcat.lite.TestMain;
+import org.apache.tomcat.lite.http.HttpChannel.HttpService;
+import org.apache.tomcat.lite.io.BBuffer;
+import org.apache.tomcat.lite.io.SslConnector;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class HttpsTest extends TestCase {
+    
+    static int port = 8443;
+    HttpConnector con;
+    HttpConnector httpClient;
+    
+    public void setUp() {
+        Logger.getLogger("SSL").setLevel(Level.FINEST);
+    }
+
+    public void tearDown() {
+        if (con != null) {
+            con.stop();
+        }
+        if (httpClient != null) {
+            httpClient.stop();
+        }
+    }
+    
+    static HttpConnector initServer(int port) throws IOException {
+        SslConnector sslCon = new SslConnector()
+            .setKeysResource("org/apache/tomcat/lite/http/test.keystore", "changeit");
+        
+        HttpConnector con = new HttpConnector(sslCon);
+        con.setPort(port);
+
+        addService(con);
+        return con;
+    }
+    
+    private static void addService(HttpConnector con) throws IOException {
+        con.setMaxHttpPoolSize(0);
+//        con.setDebug(true);
+//        con.setDebugHttp(true);
+        
+        con.getDispatcher().setDefaultService(new HttpService() {
+            @Override
+            public void service(HttpRequest httpReq, HttpResponse httpRes)
+                    throws IOException {
+                httpRes.setHeader("Connection", "close");
+                httpRes.getBodyWriter().write("Hello");
+            }
+        });
+        con.start();
+    }
+
+    public void testSimpleClient() throws Exception {
+        SslConnector sslCon = new SslConnector();
+        httpClient = new HttpConnector(sslCon);
+//        httpClient.setDebug(true);
+//        httpClient.setDebugHttp(true);
+        httpClient.setMaxHttpPoolSize(0);
+        con = initServer(++port);
+        checkResponse(httpClient);
+    }
+    
+    
+    public void testSimpleServer() throws Exception {
+        con = initServer(++port);
+        ByteChunk res = TestMain.getUrl("https://localhost:" + port +
+            "/examples/servlets/servlet/HelloWorldExample");
+        assertTrue(res.toString().indexOf("Hello") >= 0);
+    }       
+
+    
+    private void checkResponse(HttpConnector httpClient) throws Exception {
+        HttpChannel ch = httpClient.get("localhost", port);
+        ch.getRequest().setRequestURI("/hello");
+        ch.getRequest().setProtocol("HTTP/1.0");
+        // problems with keep alive !!!
+        ch.sendRequest();
+        BBuffer res = ch.readAll(null, 1000000);
+        
+        assertTrue(res.toString().indexOf("Hello") >= 0);
+    }    
+    
+    public void testSimpleClient20() throws Exception {
+        SslConnector sslCon = new SslConnector();
+        httpClient = new HttpConnector(sslCon);
+//        httpClient.setDebug(true);
+//        httpClient.setDebugHttp(true);
+
+        con = initServer(++port);
+        for (int i = 0; i < 20; i++) {
+            checkResponse(httpClient);
+        }
+    }
+    
+    public void testSimpleRequestGoogle() throws Exception {
+        SslConnector sslCon = new SslConnector();
+        httpClient = new HttpConnector(sslCon);
+        HttpChannel client = httpClient.get("www.google.com", 443);
+        client.getRequest().setRequestURI("/accounts/ServiceLogin");
+        client.sendRequest();
+        
+        BBuffer res = BBuffer.allocate(10000);
+        client.readAll(res, 1000000);
+        assertTrue(res.toString().indexOf("<title>Google Accounts</title>") > 0);
+    }
+        
+
+    /** 
+     * Use byte[] for cert - avoids using the store file.
+     * This may be nice for:
+     * - tests without a file
+     * - frameworks managing configs - no need to deal with files 
+     * @throws Exception 
+     * 
+     */
+    public void testSeverWithKeys() throws Exception {
+        Base64 b64 = new Base64();
+
+        
+        byte[] keyBytes = b64.decode(PRIVATE_KEY);
+
+        SslConnector sslCon = new SslConnector()
+            .setKeys(CERTIFICATE, keyBytes);
+            
+        HttpConnector con = new HttpConnector(sslCon);
+        con.setPort(++port);
+        addService(con);
+        
+        ByteChunk res = TestMain.getUrl("https://localhost:" + port +
+            "/examples/servlets/servlet/HelloWorldExample");
+        assertTrue(res.toString().indexOf("Hello") >= 0);
+        
+    }
+    
+    
+    //byte[] encoded = 
+    //            SslConnector.getCertificateFromStore(
+    //                    "test/org/apache/tomcat/lite/http/test.keystore", 
+    //                "changeit");
+    //byte[] encoded = 
+    //            SslConnector.getPrivateKeyFromStore(
+    //        "test/org/apache/tomcat/lite/http/test.keystore", 
+    //        "changeit");
+    //        
+    //byte[] b64b = b64.encode(encoded);
+    //System.out.println(new String(b64b));
+    static String PRIVATE_KEY =
+        "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALGOFqjC4Fefz0oOcfJeS8eLV8jY" +
+        "zA3sHUnTKmASfgfhG8prWUgSEq7O/849MrBysiKpIvTN8R+ykV4QCAxauGURDsNI2ZtAv23YX2Mb" +
+        "cfYfYqD0tgHEn355HKey0ICgmRuq3norlUWAH3hRv5qiQMc0UIhNrmdTs0jyvQ8E8AlZAgMBAAEC" +
+        "gYBybr8P2Tk5gBfbBOBPcpKocpgLLB6nQmvF7sC61nA/p8d/eBw8pNlBrMuVIkAPFHzWdee/mxMy" +
+        "eKXT18U4ISgBdIKLF9LwILhIgR8CwElLucmF2OdXqFe7baBIFI6OaqLvDgOwdHSIS6uZhAWOWIAZ" +
+        "38DhJbHMzPpfeBv1bAIhAQJBAPwhjzWqSWZjAfcED4htKa/ZSbdqMa1iYtveoHdXIcLuj4Ck1DKQ" +
+        "EFpzLnUe2gwul/TDcoW3ZVp85jn7jwnrNDECQQC0R5LgkGdGNMBih4kPU87tHFHUnggSMyIOBnCE" +
+        "XuQEN6i68VOwbdm2F7Rg1XGHD8IIJmVeiTSgLtS/mJRht6WpAkEAqs9VhQbTaTDkEOPIXiWOW1q6" +
+        "rS6dbxg7XzdowNDfx3706zM/qu2clpp3u9Ll5+DdA24xtNM1L+Nz2Y5KLm8Q0QJAQqpxEx/zQNAD" +
+        "EKyEL6nTTHV7gT+LRoeoIT2aYCji8vhOKgtR4l1M8/xiFKj5mXNnUjI4rDPaxR1sSQm4XUZXOQJB" +
+        "AJaCD0AhacU+KaOtk65tBJ7N2dKTbc5gs/CAz1uGgJtoD/jPjELMQwrxdp6AZP6+L6osqy6zDI3W" +
+        "zNHXS+wWAd0=";
+    static String CERTIFICATE = 
+        "-----BEGIN CERTIFICATE-----\n" + 
+        "MIICUzCCAbygAwIBAgIESviASzANBgkqhkiG9w0BAQUFADBuMRAwDgYDVQQGEwdVbmtub3duMRAw" + 
+        "DgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYD" +
+        "VQQLEwdVbmtub3duMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMDkxMTA5MjA0OTE1WhcNMTAwMjA3" +
+        "MjA0OTE1WjBuMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdV" +
+        "bmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRIwEAYDVQQDEwlsb2Nh" +
+        "bGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALGOFqjC4Fefz0oOcfJeS8eLV8jYzA3s" +
+        "HUnTKmASfgfhG8prWUgSEq7O/849MrBysiKpIvTN8R+ykV4QCAxauGURDsNI2ZtAv23YX2MbcfYf" +
+        "YqD0tgHEn355HKey0ICgmRuq3norlUWAH3hRv5qiQMc0UIhNrmdTs0jyvQ8E8AlZAgMBAAEwDQYJ" +
+        "KoZIhvcNAQEFBQADgYEAPHUr1BDENlV28yIQvJOWKYbcNWLd6Cp8xCltSI897xhPpKQ5tDvs+l0g" +
+        "VfdBv5+jou0F5gbCkqgclBuUnUUWsU7r4HYBLVB8FiGSy9v5yuFJWyMMLJkWAfBgzxV1nHsCPhOn" +
+        "rspSB+i6bwag0i3ENXstD/Fg1lN/7l9dRpurneI=\n" +
+        "-----END CERTIFICATE-----\n\n";
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/LiveHttp1Test.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/LiveHttp1Test.java
new file mode 100644 (file)
index 0000000..9f89c8d
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.http;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.lite.TestMain;
+import org.apache.tomcat.lite.io.BBuffer;
+import org.apache.tomcat.lite.io.CBuffer;
+import org.apache.tomcat.lite.io.SocketConnector;
+
+public class LiveHttp1Test extends TestCase {
+    // Proxy tests extend this class, run same tests via proxy on 8903 
+    protected int clientPort = 8802;
+
+    HttpChannel httpClient;
+
+    BBuffer bodyRecvBuffer = BBuffer.allocate(1024);
+
+    int to = 1000;
+
+    public void setUp() throws IOException {
+        // DefaultHttpConnector.get().setDebug(true);
+        // DefaultHttpConnector.get().setDebugHttp(true);
+        TestMain.getTestServer();
+
+        httpClient = DefaultHttpConnector.get().get("localhost", clientPort);
+
+        bodyRecvBuffer.recycle();
+    }
+
+    public void tearDown() throws Exception {
+        if (httpClient != null) {
+            httpClient.release(); // async
+            httpClient = null;
+        }
+    }
+
+    public void testSimpleRequest() throws Exception {
+        httpClient.getRequest().requestURI().set("/hello");
+
+        httpClient.sendRequest();
+        httpClient.readAll(bodyRecvBuffer, to);
+        assertEquals("Hello world", bodyRecvBuffer.toString());
+    }
+
+    public void testPoolGetRelease() throws Exception {
+        HttpConnector con = new HttpConnector(new SocketConnector());
+        con.setMaxHttpPoolSize(10);
+        HttpChannel httpCh = con.get("localhost", clientPort);
+        httpCh.release();
+
+        httpCh = con.get("localhost", clientPort);
+        httpCh.release();
+
+        httpCh = con.get("localhost", clientPort);
+        httpCh.release();
+
+    }
+
+    public void testSimpleChunkedRequest() throws Exception {
+        httpClient.getRequest().requestURI().set("/chunked/foo");
+        httpClient.sendRequest();
+        httpClient.readAll(bodyRecvBuffer, to);
+        assertTrue(bodyRecvBuffer.toString().indexOf("AAA") >= 0);
+    }
+
+    // Check waitResponseHead()
+    public void testRequestHead() throws Exception {
+        httpClient.getRequest().requestURI().set("/echo/foo");
+
+        // Send the request, wait response
+        httpClient.sendRequest();
+
+        httpClient.readAll(bodyRecvBuffer, to);
+        assertTrue(bodyRecvBuffer.toString().indexOf("GET /echo/foo") > 0);
+    }
+
+    public void test10() throws Exception {
+        for (int i = 0; i < 10; i++) {
+            testSimpleRequest();
+            tearDown();
+            setUp();
+
+            notFound();
+            tearDown();
+            setUp();
+
+            testSimpleRequest();
+            tearDown();
+            setUp();
+        }
+    }
+
+    public void notFound() throws Exception {
+        httpClient.getRequest().requestURI().set("/foo");
+        httpClient.sendRequest();
+        httpClient.readAll(bodyRecvBuffer, to);
+    }
+
+    // compression not implemented
+    public void testGzipRequest() throws Exception {
+        httpClient.getRequest().requestURI().set("/hello");
+        httpClient.getRequest().setHeader("accept-encoding",
+            "gzip");
+
+        // Send the request, wait response
+        httpClient.sendRequest();
+        // cstate.waitResponseHead(10000); // headers are received
+        // ByteChunk data = new ByteChunk(1024);
+        // acstate.serializeResponse(acstate.res, data);
+
+        // System.err.println(bodyRecvBuffer.toString());
+
+        httpClient.readAll(bodyRecvBuffer, to);
+        // Done
+    }
+
+    public void testWrongPort() throws Exception {
+        httpClient = DefaultHttpConnector.get().get("localhost", 18904);
+        httpClient.getRequest().requestURI().set("/hello");
+
+        httpClient.sendRequest();
+        
+        try {
+            httpClient.readAll(bodyRecvBuffer, to);
+        } catch (Throwable t) {
+            t.printStackTrace();
+            return;
+        }
+        fail("Error");
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/MultiMapTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/MultiMapTest.java
new file mode 100644 (file)
index 0000000..497f275
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ */
+package org.apache.tomcat.lite.http;
+
+import org.apache.tomcat.lite.http.MultiMap.Entry;
+
+import junit.framework.TestCase;
+
+public class MultiMapTest extends TestCase {
+
+    MultiMap map = new MultiMap();
+    MultiMap lmap = new MultiMap().insensitive();
+    
+    public void testAdd() {
+        map.add("foo", "bar");
+        assertEquals("bar", map.get("foo").toString());
+    }
+
+    public void testRemove() {
+        map.add("foo", "bar");
+        map.add("foo", "bar");
+        map.add("foo1", "bar");
+        assertEquals(3, map.count);
+        map.remove("foo");
+        assertEquals(1, map.count);
+    }
+
+    public void testRemove1() {
+        map.add("foo", "bar");
+        map.add("foo1", "bar");
+        map.add("foo", "bar");
+        assertEquals(3, map.count);
+        map.remove("foo");
+        assertEquals(1, map.count);
+        map.remove("foo1");
+        assertEquals(0, map.count);
+    }
+
+    public void testCase() {
+        lmap.add("foo", "bar1");
+        lmap.add("Foo", "bar2");
+        lmap.add("a", "bar3");
+        lmap.add("B", "bar4");
+        assertEquals(4, lmap.count);
+        assertEquals(3, lmap.map.size());
+        
+        assertEquals("bar3", lmap.getString("a"));
+        assertEquals("bar3", lmap.getString("A"));
+        assertEquals("bar1", lmap.getString("Foo"));
+        Entry entry = lmap.getEntry("FOO");
+        assertEquals(2, entry.values.size());
+    }
+
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/EchoCallback.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/EchoCallback.java
new file mode 100644 (file)
index 0000000..d7b2c34
--- /dev/null
@@ -0,0 +1,60 @@
+/*  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.tomcat.lite.http.services;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import org.apache.tomcat.lite.http.HttpChannel;
+import org.apache.tomcat.lite.http.HttpRequest;
+import org.apache.tomcat.lite.http.HttpResponse;
+import org.apache.tomcat.lite.http.HttpChannel.HttpService;
+import org.apache.tomcat.lite.io.IOBuffer;
+
+/**
+ * Response is plain/text, copy of the received request
+ */
+public class EchoCallback implements HttpService {
+    Logger log = Logger.getLogger("coyote.static");
+    
+    String contentType = "text/plain";
+
+
+    public EchoCallback() {
+    }
+
+    @Override
+    public void service(HttpRequest req, HttpResponse res) throws IOException {
+        HttpChannel sproc = req.getHttpChannel();
+        res.setStatus(200);
+        res.setContentType(contentType);
+        
+        IOBuffer tmp = new IOBuffer(null);
+        req.serialize(tmp);
+        
+        sproc.getOut().append("REQ HEAD:\n");
+        sproc.getOut().append(tmp.readAll(null));
+        IOBuffer reqBuf = sproc.getOut();
+        
+        reqBuf.append("\nCONTENT_LENGTH:")
+            .append(Long.toString(req.getContentLength()))
+            .append("\n");
+//      
+//        sproc.release();
+    }
+
+    
+}
\ No newline at end of file
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/SleepCallback.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/services/SleepCallback.java
new file mode 100644 (file)
index 0000000..b0cce6f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.http.services;
+
+import java.io.IOException;
+
+import org.apache.tomcat.lite.http.HttpRequest;
+import org.apache.tomcat.lite.http.HttpResponse;
+import org.apache.tomcat.lite.io.BBuffer;
+import org.apache.tomcat.lite.proxy.StaticContentService;
+
+/**
+ * Test adapters that sleeps, for load test and for encoding.
+ * REQUIRES THREAD POOL
+ */
+public class SleepCallback extends StaticContentService {
+  long t1;
+  long t2;
+  long t3;
+  long t4;
+  
+  public SleepCallback() {
+  }
+
+  public SleepCallback sleep(long t1, long t2, long t3,
+                            long t4) {
+    this.t1 = t1;
+    this.t2 = t2;
+    this.t3 = t3;
+    this.t4 = t4;
+    return this;
+  }
+    
+  public SleepCallback sleep(long t1) {
+    return sleep(t1, t1, t1, t1);
+  }
+
+  @Override
+  public void service(HttpRequest httpReq, HttpResponse res) throws IOException {
+      // TODO: blocking ! needs thread pool !
+    try {
+
+        Thread.currentThread().sleep(t1);
+        res.setStatus(200);
+        if (!chunked) {
+            res.setContentLength(mb.remaining() * 2);
+        }
+        res.setContentType(contentType);
+
+        res.sendHead();
+
+        Thread.currentThread().sleep(t2);
+
+        res.getBody().queue(BBuffer.wrapper(mb, 0, mb.remaining()));
+        res.flush();
+
+        //res.action(ActionCode.ACTION_CLIENT_FLUSH, res);
+
+        Thread.currentThread().sleep(t3);
+
+        res.getBody().queue(BBuffer.wrapper(mb, 0, mb.remaining()));
+        res.flush();
+
+        Thread.currentThread().sleep(t4);
+    } catch (InterruptedException e) {
+        // TODO Auto-generated catch block
+        e.printStackTrace();
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/http/test.keystore b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/test.keystore
new file mode 100644 (file)
index 0000000..8491841
Binary files /dev/null and b/modules/tomcat-lite/test/org/apache/tomcat/lite/http/test.keystore differ
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/BBufferTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/BBufferTest.java
new file mode 100644 (file)
index 0000000..ae02346
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ */
+package org.apache.tomcat.lite.io;
+
+import org.apache.tomcat.lite.io.BBuffer;
+
+import junit.framework.TestCase;
+
+public class BBufferTest extends TestCase {
+    BBuffer res = BBuffer.wrapper("");
+
+    BBuffer l1 = BBuffer.wrapper("");
+    BBuffer l1a = BBuffer.wrapper("a");
+
+    BBuffer l2 = BBuffer.wrapper("\r");
+    BBuffer l3 = BBuffer.wrapper("\n");
+    BBuffer l4 = BBuffer.wrapper("\r\n");
+    BBuffer l5 = BBuffer.wrapper("\r\na");
+    BBuffer l5_a = BBuffer.wrapper("\ra");
+    BBuffer l5_b = BBuffer.wrapper("\na");
+    BBuffer l6 = BBuffer.wrapper("a\n");
+    BBuffer l7 = BBuffer.wrapper("GET \n");
+    BBuffer l8 = BBuffer.wrapper("GET /\n");
+    BBuffer l9 = BBuffer.wrapper("GET /a?b\n");
+    BBuffer l10 = BBuffer.wrapper("GET /a?b HTTP/1.0\n");
+    BBuffer l11 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b");
+    BBuffer l12 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\n");
+    
+    BBuffer f1 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\n\n");
+    BBuffer f2 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\n\r\n");
+    BBuffer f3 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\r");
+    BBuffer f4 = BBuffer.wrapper("GET /a?b HTTP/1.0\na:b\r\n\r");
+
+    BBuffer s1 = BBuffer.wrapper(" \n");
+    BBuffer s2 = BBuffer.wrapper(" a");
+    BBuffer s3 = BBuffer.wrapper("  ");
+    BBuffer s4 = BBuffer.wrapper("   a");
+
+    BBuffer h1 = BBuffer.wrapper("a");
+    BBuffer h2 = BBuffer.wrapper("a?b");
+    BBuffer h3 = BBuffer.wrapper("a b");
+
+    public void hashTest(String s) {
+        assertEquals(s.hashCode(), BBuffer.wrapper(s).hashCode());
+    }
+    
+    public void testHash() {
+        hashTest("");
+        hashTest("a");
+        hashTest("123abc");
+        hashTest("123abc\0");
+        // Fails for UTF chars - only ascii hashTest("123abc\u12345;");
+    }
+    
+    public void testReadToSpace() {
+        assertEquals(3, l8.readToSpace(res));
+        assertEquals("GET", res.toString());
+        assertEquals(" /\n", l8.toString());        
+
+        assertEquals(0, l1.readToSpace(res));
+        assertEquals("", res.toString());
+        assertEquals("", l1.toString());        
+    }
+    
+    public void testReadToDelim() {
+        assertEquals(1, h1.readToDelimOrSpace((byte)'?', res));
+        assertEquals("a", res.toString());
+        assertEquals("", h1.toString());        
+        
+        assertEquals(1, h2.readToDelimOrSpace((byte)'?', res));
+        assertEquals("a", res.toString());
+        assertEquals("?b", h2.toString());        
+        
+        assertEquals(1, h3.readToDelimOrSpace((byte)'?', res));
+        assertEquals("a", res.toString());
+        assertEquals(" b", h3.toString());        
+    }
+    
+    public void testGet() {
+        assertEquals(0x20, s1.get(0));
+        assertEquals(0x0a, s1.get(1));
+        try {
+            s1.get(2);
+        } catch(ArrayIndexOutOfBoundsException ex) {
+            return;
+        }
+        fail("Exception");
+    }
+    
+    public void testSkipSpace() {
+        assertEquals(1, s1.skipSpace());
+        assertEquals("\n", s1.toString());        
+
+        assertEquals(1, s2.skipSpace());
+        assertEquals("a", s2.toString());        
+        
+        assertEquals(2, s3.skipSpace());
+        assertEquals("", s3.toString());        
+
+        assertEquals(3, s4.skipSpace());
+        assertEquals("a", s4.toString());        
+        
+        assertEquals(0, l1.skipSpace());
+        assertEquals("", l1.toString());        
+    }
+    
+    public void testLFLF() {
+        assertTrue(f1.hasLFLF());
+        assertTrue(f2.hasLFLF());
+        assertTrue(f3.hasLFLF());
+
+        assertFalse(f4.hasLFLF());
+        assertFalse(l1.hasLFLF());
+        assertFalse(l2.hasLFLF());
+        assertFalse(l3.hasLFLF());
+
+        assertFalse(l10.hasLFLF());
+        assertFalse(l11.hasLFLF());
+        assertFalse(l12.hasLFLF());
+    }
+        
+    public void testReadLine() {
+        assertEquals(-1, l1.readLine(res));
+        assertEquals("", res.toString());
+        assertEquals("", l1.toString());        
+        
+        assertEquals(-1, l1a.readLine(res));
+        assertEquals("", res.toString());
+        assertEquals("a", l1a.toString());        
+        
+        assertEquals(0, l2.readLine(res));
+        assertEquals("", l2.toString());        
+        assertEquals("", res.toString());
+        assertEquals(0, l3.readLine(res));
+        assertEquals("", l3.toString());        
+        assertEquals("", res.toString());
+        assertEquals(0, l4.readLine(res));
+        assertEquals("", res.toString());
+
+        assertEquals(0, l5.readLine(res));
+        assertEquals("", res.toString());
+        assertEquals("a", l5.toString());
+        assertEquals(0, l5_b.readLine(res));
+        assertEquals("", res.toString());
+        assertEquals("a", l5_b.toString());
+        assertEquals(0, l5_a.readLine(res));
+        assertEquals("", res.toString());
+        assertEquals("a", l5_a.toString());
+        
+        assertEquals(1, l6.readLine(res));
+        assertEquals("a", res.toString());
+
+        assertEquals(4, l7.readLine(res));
+        assertEquals("GET ", res.toString());
+        assertEquals(5, l8.readLine(res));
+        assertEquals("GET /", res.toString());
+
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/CBufferTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/CBufferTest.java
new file mode 100644 (file)
index 0000000..db0152c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ */
+package org.apache.tomcat.lite.io;
+
+import junit.framework.TestCase;
+
+public class CBufferTest extends TestCase {
+
+    CBuffer ext = CBuffer.newInstance();
+    
+    public void extTest(String path, String exp) {
+        CBuffer.newInstance().append(path).getExtension(ext, '/', '.');
+        assertEquals(exp, ext.toString());
+    }
+    
+    public void testExt() {
+        extTest("foo.jsp", "jsp");
+        extTest("foo.j", "j");
+        extTest("/foo.j", "j");
+        extTest("//foo.j", "j");
+        extTest(".j", "j");
+        extTest(".", "");
+        extTest("/abc", "");
+        extTest("/abc.", "");
+        extTest("/abc/", "");
+        extTest("/abc/d", "");
+    }
+    
+    public void testLastIndexOf() {
+        
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/OneTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/OneTest.java
new file mode 100644 (file)
index 0000000..fedc2db
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ */
+package org.apache.tomcat.lite.io;
+
+import java.io.IOException;
+
+import org.apache.tomcat.lite.TestMain;
+import org.apache.tomcat.lite.http.HttpChannel;
+import org.apache.tomcat.lite.io.MemoryIOConnector;
+import org.apache.tomcat.lite.io.MemoryIOConnector.MemoryIOChannel;
+
+import junit.framework.TestCase;
+
+public class OneTest extends TestCase {
+    MemoryIOConnector.MemoryIOChannel net = new MemoryIOChannel();
+    HttpChannel http = new HttpChannel()
+        .serverMode(true).withBuffers(net);
+    public void setUp() throws Exception {
+        TestMain.getTestServer();
+    }
+    
+    public void tearDown() throws IOException {
+    }
+
+
+    public void testOne() throws Exception {
+        
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/SocksTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/SocksTest.java
new file mode 100644 (file)
index 0000000..a1f9870
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ */
+package org.apache.tomcat.lite.io;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tomcat.lite.proxy.SocksServer;
+
+
+import junit.framework.TestCase;
+
+public class SocksTest extends TestCase {
+
+    public void setUp() { 
+//        SocksServer socks = new SocksServer();
+//        try {
+//            socks.initServer();
+//        } catch (IOException e1) {
+//            // TODO Auto-generated catch block
+//            e1.printStackTrace();
+//        }
+//        
+//        ProxySelector.setDefault(new ProxySelector() {
+//
+//            @Override
+//            public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+//            }
+//
+//            @Override
+//            public List<Proxy> select(URI uri) {
+//                
+//                List<Proxy> res = new ArrayList<Proxy>();
+//                try {
+//                    res.add(new Proxy(Proxy.Type.SOCKS, 
+//                            new InetSocketAddress(InetAddress.getLocalHost(), 1080)));
+//                } catch (UnknownHostException e) {
+//                    // TODO Auto-generated catch block
+//                    e.printStackTrace();
+//                }
+//                return res;
+//            }
+//            
+//        });
+    }
+    
+    public void testSocks() {
+        
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/UEncoderTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/UEncoderTest.java
new file mode 100644 (file)
index 0000000..1bf389a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ */
+package org.apache.tomcat.lite.io;
+
+import junit.framework.TestCase;
+
+
+public class UEncoderTest extends TestCase {
+    IOWriter enc=new IOWriter(null);
+    UrlEncoding dec = new UrlEncoding();
+    CBuffer cc = CBuffer.newInstance();
+    
+    /*
+     * 
+     * Test method for 'org.apache.tomcat.util.buf.UEncoder.encodeURL(String)'
+     * TODO: find the relevant rfc and apache tests and add more 
+     */
+    public void testEncodeURL() {
+
+        String eurl1=encodeURL("test");
+        assertEquals("test", eurl1);
+        
+        eurl1=encodeURL("/test");
+        assertEquals("/test", eurl1);
+
+        // safe ranges
+        eurl1=encodeURL("test$-_.");
+        assertEquals("test$-_.", eurl1);
+
+        eurl1=encodeURL("test$-_.!*'(),");
+        assertEquals("test$-_.!*'(),", eurl1);
+
+        eurl1=encodeURL("//test");
+        assertEquals("//test", eurl1);
+    }
+    
+    public String encodeURL(String uri) {
+        cc.recycle();
+        dec.urlEncode(uri, cc, enc);
+        return cc.toString();
+    }
+    
+    
+
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/io/test.properties b/modules/tomcat-lite/test/org/apache/tomcat/lite/io/test.properties
new file mode 100644 (file)
index 0000000..19ee5e4
--- /dev/null
@@ -0,0 +1,33 @@
+RUN=Log,JMXProxy,Socks
+
+Log.(class)=org.apache.tomcat.integration.simple.LogConfig
+Log.debug=org.apache.tomcat.async.AsyncHttpConnector
+Log.debug=Proxy
+
+JMXProxy.(class)=org.apache.tomcat.integration.simple.JMXProxy
+JMXProxy.port=8003
+
+Socks.(class)=org.apache.tomcat.async.callbacks.SocksServer
+Socks.port=2080
+Socks.idleTimeout=0
+
+HttpConnector-TestServer.debug=true
+#HttpConnector-TestServer.debugHttp=true
+HttpConnector-TestServer.clientKeepAlive=true
+HttpConnector-TestServer.serverKeepAlive=true
+HttpConnector-TestServer.maxHttpPoolSize=10
+
+HttpConnector.debug=true
+#HttpConnector.debugHttp=true
+HttpConnector.clientKeepAlive=true
+HttpConnector.serverKeepAlive=true
+HttpConnector.maxHttpPoolSize=10
+
+HttpConnector-Proxy.debug=true
+#HttpConnector-Proxy.debugHttp=true
+HttpConnector-Proxy.clientKeepAlive=true
+HttpConnector-Proxy.serverKeepAlive=true
+HttpConnector-Proxy.maxHttpPoolSize=10
+
+
+#IOConnector.debug=true
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttp5Test.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttp5Test.java
new file mode 100644 (file)
index 0000000..3bcdb74
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ */
+package org.apache.tomcat.lite.load;
+
+import org.apache.tomcat.lite.http.LiveHttp1Test;
+
+import junit.framework.TestSuite;
+
+public class LiveHttp5Test extends LiveHttp1Test {
+
+    /**
+     * Want to run the same tests few times.
+     */
+    public static TestSuite suite() {
+        TestSuite s = new TestSuite();
+        for (int i = 0; i < 5; i++) {
+            s.addTestSuite(LiveHttp1Test.class);
+        }
+        return s;
+    }
+    
+    public void test100() throws Exception {
+        for (int i = 0; i < 100; i++) {
+            testSimpleRequest();
+            tearDown(); 
+            setUp();
+            
+            notFound();
+            tearDown(); 
+            setUp();
+
+            testSimpleRequest();
+            tearDown(); 
+            setUp();
+        }
+    }
+
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttpThreadedTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/load/LiveHttpThreadedTest.java
new file mode 100644 (file)
index 0000000..64cfc4a
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.load;
+
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.lite.TestMain;
+import org.apache.tomcat.lite.http.DefaultHttpConnector;
+import org.apache.tomcat.lite.http.HttpChannel;
+import org.apache.tomcat.lite.http.HttpConnector;
+import org.apache.tomcat.lite.http.HttpChannel.HttpService;
+import org.apache.tomcat.lite.http.HttpChannel.RequestCompleted;
+
+public class LiveHttpThreadedTest extends TestCase {
+  HttpConnector staticMain = TestMain.getTestServer();
+  
+  
+  int tCount = 1;
+  Thread[] threads = new Thread[tCount];
+  int[] ok = new int[tCount];
+  private int rCount = 100;
+  
+  public void xtestSimpleRequest() throws Exception {
+    long t0 = System.currentTimeMillis();
+    for (int i = 0; i < tCount; i++) {
+      final int j = i;
+      threads[i] = new Thread(new Runnable() {
+        public void run() {
+          makeRequests(j, true);
+        }
+      });
+      threads[i].start();
+    }
+    
+    int res = 0;
+    for (int i = 0; i < tCount; i++) {
+      threads[i].join();
+      res += ok[i];
+    }
+    long t1 = System.currentTimeMillis();
+    System.err.println("Time: " + (t1 - t0) + " " + res);
+  }
+
+  public void testSimpleRequestNB() throws Exception {
+    long t0 = System.currentTimeMillis();
+    for (int i = 0; i < tCount; i++) {
+      final int j = i;
+      threads[i] = new Thread(new Runnable() {
+        public void run() {
+          makeRequests(j, false);
+        }
+      });
+      threads[i].start();
+    }
+    
+    int res = 0;
+    for (int i = 0; i < tCount; i++) {
+      threads[i].join();
+      res += ok[i];
+    }
+    long t1 = System.currentTimeMillis();
+    System.err.println("TimeNB: " + (t1 - t0) + " " + res);
+  }
+  
+  void makeRequests(int t, boolean b) {
+    for (int i = 0; i < rCount ; i++) {
+      try {
+        //System.err.println("MakeReq " + t + " " + i);
+        makeRequest(t, b);
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+    }
+  }
+
+  static RequestCompleted reqCallback = new RequestCompleted() {
+    @Override
+    public void handle(HttpChannel data, Object extraData) 
+        throws IOException {
+        //dumpHead(cstate);  
+        //System.err.println("DATA\n" + cstate.output.toString() + "\n----");
+        //assertTrue(cstate.bodyRecvBuffer.toString().indexOf("AAA") >= 0);
+    
+        data.release();
+    }
+      
+  };
+  
+  void makeRequest(int i, boolean block) throws Exception {
+    HttpChannel cstate = DefaultHttpConnector.get().get("localhost", 8802);
+    
+    cstate.getRequest().requestURI().set("/hello");
+    cstate.setCompletedCallback(reqCallback);
+    
+    // Send the request, wait response
+    cstate.sendRequest();
+  }
+  
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/load/MicroTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/load/MicroTest.java
new file mode 100644 (file)
index 0000000..bbc6a47
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ */
+package org.apache.tomcat.lite.load;
+
+import org.apache.tomcat.lite.http.BaseMapper;
+import org.apache.tomcat.lite.http.MappingData;
+import org.apache.tomcat.lite.io.CBuffer;
+
+import junit.framework.TestCase;
+
+public class MicroTest extends TestCase {
+
+    public void testMapper() throws Exception {
+        BaseMapper mapper = new BaseMapper();
+
+        MappingData mappingData = new MappingData();
+        CBuffer host = CBuffer.newInstance();
+        host.set("test1.com");
+        
+        CBuffer uri = CBuffer.newInstance();
+        uri.set("/foo/bar/blah/bobou/foo");
+
+        String[] welcomes = new String[2];
+        welcomes[0] = "index.html";
+        welcomes[1] = "foo.html";
+
+        for (int i = 0; i < 100; i++) {
+            String hostN = "test" + i + ".com";
+            mapper.addContext(hostN, "", "context0", new String[0], null, null);
+            mapper.addContext(hostN, "/foo", "context1", new String[0], null, null);
+            mapper.addContext(hostN, "/foo/bar", "context2", welcomes, null, null);
+            mapper.addContext(hostN, "/foo/bar/bla", "context3", new String[0], null, null);
+
+            mapper.addWrapper(hostN, "/foo/bar", "/fo/*", "wrapper0");
+        }
+        int N = 10000;
+        for (int i = 0; i < N; i++) {
+            mappingData.recycle();
+            mapper.map(host, uri, mappingData);
+        }
+
+        long time = System.currentTimeMillis();
+        for (int i = 0; i < N; i++) {
+            mappingData.recycle();
+            mapper.map(host, uri, mappingData);
+        }
+        System.out.println("Elapsed:" + (System.currentTimeMillis() - time));        
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/LiveProxyHttp1Test.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/LiveProxyHttp1Test.java
new file mode 100644 (file)
index 0000000..6a1b8e5
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.proxy;
+
+
+import java.io.IOException;
+
+import org.apache.tomcat.lite.http.LiveHttp1Test;
+
+
+public class LiveProxyHttp1Test extends LiveHttp1Test {
+    public void setUp() throws IOException {
+        // All tests in super, but with client pointing to 
+        // the proxy server, which in turn hits the real server.
+        clientPort = 8903;
+        super.setUp();
+  }
+  
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/ProxyTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/ProxyTest.java
new file mode 100644 (file)
index 0000000..1c40a2d
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+n * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.proxy;
+
+import java.io.IOException;
+
+import org.apache.tomcat.lite.TestMain;
+
+import junit.framework.TestCase;
+
+
+public class ProxyTest extends TestCase {
+
+  String resStr;
+    
+  public void setUp() throws Exception {
+      TestMain.getTestServer();
+  }
+  
+  public void tearDown() throws IOException {
+  }
+  
+  public void xtestRequestSlowChunked() throws Exception {
+      resStr = 
+          TestMain.get("http://localhost:8903/sleep/1c").toString();
+      assertEquals("sleep 1csleep 1c", resStr);
+  }
+  
+  public void testSingleRequest() throws Exception {
+      String resStr = 
+          TestMain.get("http://localhost:8903/hello").toString();
+      assertEquals("Hello world", resStr);
+  }
+  
+
+  public void test2Requests() throws Exception {
+      String resStr = 
+          TestMain.get("http://localhost:8903/hello").toString();
+      assertEquals("Hello world", resStr);
+      resStr = 
+          TestMain.get("http://localhost:8903/hello?a=b").toString();
+      assertEquals("Hello world", resStr);
+  }
+
+  public void testRequestSimple() throws Exception {
+      resStr = 
+          TestMain.get("http://localhost:8903/hello").toString();
+      assertEquals("Hello world", resStr);
+      resStr = 
+          TestMain.get("http://localhost:8903/hello").toString();
+      assertEquals("Hello world", resStr);
+      resStr = 
+          TestMain.get("http://localhost:8903/hello").toString();
+      assertEquals(resStr, "Hello world");
+
+  }
+  
+  public void testExtAdapter() throws Exception {
+      String res = 
+              TestMain.get("http://www.apache.org/").toString();
+      assertTrue(res.indexOf("Apache") > 0);
+      
+      Thread.currentThread().sleep(100);
+      // second time - are we reusing ?
+      res = 
+          TestMain.get("http://www.apache.org/").toString();
+      
+      assertTrue(res.indexOf("Apache") > 0);
+      
+  }  
+  
+  public void testStaticAdapter() throws Exception {
+      
+      assertEquals("Hello world", 
+          TestMain.get("http://localhost:8802/hello").toString());
+      assertEquals("Hello world2", 
+          TestMain.get("http://localhost:8802/2nd").toString());
+      
+    }
+    
+  public void testRequestParams() throws Exception {
+      // qry string
+      String resStr = 
+          TestMain.get("http://localhost:8903/echo/foo?q=a&b")
+          .toString();
+      assertTrue(resStr, resStr.indexOf("foo?q=a&b") > 0);
+  }
+
+  
+  public void testRequestChunked() throws Exception {
+      // Chunked encoding
+      String resStr = 
+          TestMain.get("http://localhost:8903/chunked/test")
+          .toString();
+      assertEquals(8, resStr.length());
+      assertTrue(resStr.indexOf("AAA") >= 0);
+  }
+  
+
+  public void testRequestSlow() throws Exception {
+      // Slow
+      String resStr = 
+          TestMain.get("http://localhost:8903/sleep/1").toString();
+      assertEquals("sleep 1sleep 1", resStr.toString());
+  }  
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/SmallProxyTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/proxy/SmallProxyTest.java
new file mode 100644 (file)
index 0000000..3180121
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ */
+package org.apache.tomcat.lite.proxy;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.lite.http.HttpChannel;
+import org.apache.tomcat.lite.http.HttpConnector;
+import org.apache.tomcat.lite.io.MemoryIOConnector;
+import org.apache.tomcat.lite.io.MemoryIOConnector.MemoryIOChannel;
+
+public class SmallProxyTest extends TestCase {
+    
+    MemoryIOConnector memoryServerConnector = 
+        new MemoryIOConnector();
+    
+    MemoryIOConnector memoryClientConnector = 
+        new MemoryIOConnector().withServer(memoryServerConnector);
+
+    
+    HttpConnector httpPool = new HttpConnector(memoryServerConnector) {
+        @Override
+        public HttpChannel get(CharSequence target) throws IOException {
+            throw new IOException();
+        }
+        public HttpChannel getServer() {
+            lastServer = new HttpChannel().serverMode(true);
+            lastServer.withBuffers(net);
+            lastServer.setConnector(this);
+            //lastServer.withIOConnector(memoryServerConnector);
+            return lastServer;
+        }
+    };
+
+    HttpConnector httpClient = new HttpConnector(memoryClientConnector) {
+        @Override
+        public HttpChannel get(CharSequence target) throws IOException {
+            lastClient = new HttpChannel();
+            lastClient.setConnector(this);
+            return lastClient;
+        }
+        public HttpChannel get(String host, int port) throws IOException {
+            lastClient = new HttpChannel();
+            lastClient.setConnector(this);
+            return lastClient;
+        }        
+        public HttpChannel getServer() {
+            throw new RuntimeException();
+        }
+    };
+    
+    HttpChannel lastServer;
+    HttpChannel lastClient;
+
+    boolean hasBody = false;
+    boolean bodyDone = false;
+    boolean bodySentDone = false;
+    boolean headersDone = false;
+    boolean allDone = false;
+    
+    
+    //MemoryIOChannel clientNet = new MemoryIOChannel(); 
+    
+    MemoryIOConnector.MemoryIOChannel net = new MemoryIOChannel();
+    HttpChannel http;
+    
+    public void setUp() throws IOException {
+        http = httpPool.getServer();
+    }
+    /**
+     * More complicated test..
+     * @throws IOException
+     */
+    public void testProxy() throws IOException {
+        http.setHttpService(new HttpProxyService()
+            .withSelector(memoryClientConnector)
+            .withHttpClient(httpClient));
+
+        http.getNet().getIn().append("GET http://www.cyberluca.com/ HTTP/1.0\n" +
+                "Connection: Close\n\n");
+        http.getNet().getIn().close();
+        
+        // lastClient.rawSendBuffers has the request sent by proxy
+        lastClient.getNet().getIn()
+            .append("HTTP/1.0 200 OK\n\nHi\n");
+        lastClient.getNet().getIn()
+            .append("world\n");
+        
+        // TODO: check what the proxy sent
+        // lastClient.getOut();
+    
+        // will also trigger 'release' - both sides are closed. 
+        lastClient.getNet().getIn().close(); 
+        
+        // wait response... 
+        // http.sendBody.close();
+        String res = net.out.toString();
+        assertTrue(res.indexOf("Hi\nworld\n") > 0);
+        assertTrue(res.indexOf("HTTP/1.0 200 OK") == 0);
+        assertTrue(res.indexOf("tomcatproxy") > 0);
+        
+    }    
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/AnnotationTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/AnnotationTest.java
new file mode 100644 (file)
index 0000000..cd3f64d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ */
+package org.apache.tomcat.lite.servlet;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.servlets.config.ServletContextConfig;
+import org.apache.tomcat.servlets.config.deploy.AnnotationsProcessor;
+
+public class AnnotationTest extends TestCase {
+
+    // TODO: fix the build file to find the target dir
+    // you can run this manually until this happens
+    String eclipseBase = "test-webapp/WEB-INF/classes";
+    
+    public void testScanClasses() throws IOException {
+        ServletContextConfig cfg = new ServletContextConfig();
+        AnnotationsProcessor scanner = new AnnotationsProcessor(cfg);
+//        scanner.processDir(eclipseBase);
+//        
+//        dump(cfg);
+        
+    }
+    
+    public void testScanClass() throws IOException {
+        ServletContextConfig cfg = new ServletContextConfig();
+        AnnotationsProcessor scanner = new AnnotationsProcessor(cfg);
+            
+        String path = eclipseBase + "/org/apache/tomcat/lite/Annotated2Servlet.class";
+//        scanner.processClass(new FileInputStream(path), eclipseBase, path);
+//        
+//        dump(cfg);
+        
+    }
+
+    private void dump(ServletContextConfig cfg) {
+//        ObjectMapper jackson = new ObjectMapper();
+//        try {
+//            jackson.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+//            jackson.configure(SerializationConfig.Feature.WRITE_NULL_PROPERTIES, 
+//                    false);
+//
+//            ByteArrayOutputStream out = new ByteArrayOutputStream();
+//            jackson.writeValue(out, cfg);
+//            System.err.println(out.toString());
+//        } catch (Throwable t) {
+//            t.printStackTrace();
+//        }
+    }
+    
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/JspWatchdogTests.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/JspWatchdogTests.java
new file mode 100644 (file)
index 0000000..ac7e9a3
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.servlet;
+
+
+import org.apache.tomcat.lite.servlet.TomcatLite;
+
+import junit.framework.Test;
+
+public class JspWatchdogTests  extends TomcatLiteWatchdog {
+    
+    public JspWatchdogTests() {
+        super();
+        testMatch = 
+            //"precompileNegativeTest";
+            null;
+        // Test we know are failing - need to fix at some point.
+        exclude = new String[] {
+                "negativeDuplicateExtendsFatalTranslationErrorTest",
+                "negativeDuplicateErrorPageFatalTranslationErrorTest",
+                "negativeDuplicateInfoFatalTranslationErrorTest",
+                "negativeDuplicateLanguageFatalTranslationErrorTest",
+                "negativeDuplicateSessionFatalTranslationErrorTest",
+                "positiveIncludeCtxRelativeHtmlTest",
+                "precompileNegativeTest"
+            }; 
+        file = getWatchdogdir() + "/src/conf/jsp-gtest.xml";
+        goldenDir = 
+            getWatchdogdir() + "/src/clients/org/apache/jcheck/jsp/client/";
+        targetMatch = "jsp-test";
+        
+    }
+    
+    protected void addConnector(TomcatLite lite) {
+        lite.setPort(8019);
+    }
+    
+    public static Test suite() {
+        return new JspWatchdogTests().getSuite(8019);
+    }
+    
+}
+
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/LiteTestHelper.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/LiteTestHelper.java
new file mode 100644 (file)
index 0000000..2df27f7
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ */
+package org.apache.tomcat.lite.servlet;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tomcat.lite.io.BBuffer;
+import org.apache.tomcat.lite.servlet.ServletContextImpl;
+import org.apache.tomcat.lite.servlet.TomcatLite;
+
+public class LiteTestHelper {
+    static TomcatLite lite;
+
+    public static ServletContextImpl addContext(TomcatLite lite) throws ServletException {
+        ServletContextImpl ctx = 
+            (ServletContextImpl) lite.addServletContext(null, null, "/test1");
+          
+
+          ctx.add("testException", new HttpServlet() {
+              public void doGet(HttpServletRequest req, HttpServletResponse res) 
+                throws IOException {
+                throw new NullPointerException();
+              }
+            });
+            ctx.addMapping("/testException", "testException");
+
+            
+            ctx.add("test", new HttpServlet() {
+                public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
+                    res.addHeader("Foo", "Bar");
+                    res.getWriter().write("Hello world");
+                }
+            });
+            
+            ctx.addMapping("/1stTest", "test");
+            
+            
+            return ctx;
+    }
+    
+    public static void startLite() throws IOException, ServletException {
+        if (lite == null) {
+            lite = new TomcatLite();
+
+            LiteTestHelper.addContext(lite);
+            lite.start();
+
+            lite.startConnector();
+        }
+    }
+    
+    public static void initServletsAndRun(TomcatLite lite, int port) throws ServletException, IOException {
+        addContext(lite);
+        lite.init();
+        lite.start(); 
+
+
+        if (port > 0) {
+            // This should be added after all local initialization to avoid
+            // the server from responding.
+            // Alternatively, you can load this early but set it to return
+            // 'unavailable' if load balancers depend on this.
+            addConnector(lite, port, true);
+            
+            // At this point we can add contexts and inject requests, if we want to 
+            // do it over HTTP need to start the connector as well.
+            lite.startConnector(); 
+        }
+    }
+    
+    public static void addConnector(TomcatLite lite, 
+                                    int port, boolean daemon) { 
+        lite.setPort(port);
+    }
+    
+    /**
+     *  Get url using URLConnection.
+     */
+    public static BBuffer getUrl(String path) throws IOException {
+    
+        BBuffer out = BBuffer.allocate(4096);
+        
+        URL url = new URL(path);
+        URLConnection connection = url.openConnection();
+        connection.setReadTimeout(5000);
+        connection.connect();
+        InputStream is = connection.getInputStream();
+        out.readAll(is);
+        return out;
+    }
+    
+//    static class ByteChunkOutputBuffer implements OutputBuffer {
+//        
+//        protected ByteChunk output = null;
+//    
+//        public ByteChunkOutputBuffer(ByteChunk output) {
+//          this.output = output;
+//        }
+//    
+//        public int doWrite(ByteChunk chunk, Response response) 
+//            throws IOException {
+//          output.append(chunk);
+//          return chunk.getLength();
+//        }
+//    }
+    
+        
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/PropertiesSpiTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/PropertiesSpiTest.java
new file mode 100644 (file)
index 0000000..a331dfb
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ */
+package org.apache.tomcat.lite.servlet;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.integration.simple.SimpleObjectManager;
+
+
+public class PropertiesSpiTest extends TestCase {
+
+    SimpleObjectManager spi;
+    
+    public void setUp() {
+        spi = new SimpleObjectManager();
+        
+        spi.getProperties().put("obj1.name", "foo");
+        spi.getProperties().put("obj1.(class)", BoundObj.class.getName());
+        
+    }
+    
+    public void testArgs() throws IOException { 
+        spi = new SimpleObjectManager(new String[] {
+            "-a=1", "-b", "2"});
+        Properties res = spi.getProperties();
+        
+        assertEquals("1", res.get("a"));
+        assertEquals("2", res.get("b"));
+        
+        
+    }
+    
+    public static class BoundObj {
+        String name;
+        
+        public void setName(String n) {
+            this.name = n;
+        }
+    }
+    
+    public void testBind() throws Exception {
+        BoundObj bo = new BoundObj();
+        spi.bind("obj1", bo);
+        assertEquals(bo.name, "foo");        
+    }
+    
+    public void testCreate() throws Exception {
+        BoundObj bo = (BoundObj) spi.get("obj1");
+        assertEquals(bo.name, "foo");
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/ServletTests.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/ServletTests.java
new file mode 100644 (file)
index 0000000..03d717c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ */
+package org.apache.tomcat.lite.servlet;
+
+import org.apache.tomcat.lite.servlet.TomcatLite;
+
+import junit.framework.Test;
+
+public class ServletTests extends TomcatLiteWatchdog {
+    
+    public ServletTests() {
+        super();
+        exclude = new String[] {
+                "ServletToJSPErrorPageTest",
+                "ServletToJSPError502PageTest",
+        };
+    }
+    
+    protected void addConnector(TomcatLite connector) {
+        connector.setPort(7074);    
+    }
+    
+    /** 
+     * Magic JUnit method 
+     */
+    public static Test suite() {
+        return new ServletTests().getSuite(7074);
+    }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/TomcatLiteNoConnectorTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/TomcatLiteNoConnectorTest.java
new file mode 100644 (file)
index 0000000..a6621e3
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.servlet;
+
+
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.lite.http.HttpChannel;
+import org.apache.tomcat.lite.http.HttpConnector;
+import org.apache.tomcat.lite.http.HttpRequest;
+import org.apache.tomcat.lite.http.HttpResponse;
+import org.apache.tomcat.lite.io.BBuffer;
+import org.apache.tomcat.lite.io.MemoryIOConnector;
+import org.apache.tomcat.lite.io.MemoryIOConnector.MemoryIOChannel;
+import org.apache.tomcat.lite.servlet.TomcatLite;
+
+/**
+ * Example of testing servlets without using sockets.
+ * 
+ * @author Costin Manolache
+ */
+public class TomcatLiteNoConnectorTest extends TestCase {
+
+  TomcatLite lite;
+  MemoryIOConnector net;
+  HttpConnector con;
+  
+  public void setUp() throws Exception {
+      net = new MemoryIOConnector();
+      con = new HttpConnector(net);
+      
+      lite = new TomcatLite();
+      lite.setHttpConnector(con);
+      
+      // Load all servlets we need to test
+      LiteTestHelper.initServletsAndRun(lite, 0);
+  }
+  
+  public void tearDown() throws Exception {
+    lite.stop();
+  }
+  
+
+  public void testSimpleRequest() throws Exception {
+      MemoryIOConnector.MemoryIOChannel ch = new MemoryIOChannel();
+      
+      HttpChannel httpCh = con.getServer();
+      httpCh.withBuffers(ch);
+      
+      HttpRequest req = httpCh.getRequest();
+      req.setURI("/test1/1stTest");
+
+      HttpResponse res = httpCh.getResponse();
+      
+      lite.getHttpConnector().getDispatcher().service(req, res, true);
+      // req/res will be recycled
+      
+      // parse out to a response
+      BBuffer out = ch.out;
+      MemoryIOChannel clientCh = new MemoryIOChannel();
+      clientCh.getIn().append(out);
+      
+      HttpChannel client = con.get("localhost", 80);
+      client.withBuffers(clientCh);
+      clientCh.handleReceived(clientCh);
+      
+      
+      HttpResponse cres = client.getResponse();
+      assertEquals(res.getStatus(), 200);
+    
+      BBuffer resBody = BBuffer.allocate(200);
+      cres.getBody().readAll(resBody);
+      assertEquals("Hello world", resBody.toString());
+      assertEquals(cres.getHeader("Foo"), "Bar");
+      assertEquals(cres.getStatus(), 200);
+  }
+  
+//
+//  public void testPostRequest() throws Exception {
+//    ByteChunk out = new ByteChunk();
+//    ServletRequestImpl req = 
+//      LiteTestHelper.createMessage(lite, "/test1/1stTest", out);
+//    req.setMethod("POST");
+//
+//    ServletResponseImpl res = lite.service(req);
+//
+//    assertEquals("Hello post world", out.toString());
+//    // Headers are still in the response
+//    assertEquals(res.getHeader("Foo"), "Post");
+//    assertEquals(res.getStatus(), 200);
+//  }
+//  
+//  public void testException() throws IOException, Exception {
+//    ByteChunk out = new ByteChunk();
+//    ServletRequestImpl req = 
+//        LiteTestHelper.createMessage(lite, "/test1/testException", out);
+//    ServletResponseImpl res = lite.service(req);
+//    assertEquals(res.getStatus(), 500);
+//  }
+  
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/TomcatLiteSimpleTest.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/TomcatLiteSimpleTest.java
new file mode 100644 (file)
index 0000000..8f4d8b5
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.servlet;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.lite.io.IOBuffer;
+
+/** 
+ * TODO: convert to new API
+ * 
+ */
+public class TomcatLiteSimpleTest extends TestCase {
+
+  protected TomcatLite lite = new TomcatLite(); 
+  
+  public void setUp() throws Exception {
+      LiteTestHelper.addContext(lite);
+      
+      lite.init();
+      
+      lite.setPort(8884);
+      lite.start();
+      lite.startConnector();
+  }
+    
+  public void testSimpleRequest() throws Exception {
+      URL url = new URL("http://localhost:8884/test1/1stTest");
+      URLConnection connection = url.openConnection();
+      InputStream is = connection.getInputStream();
+      String res = new IOBuffer().append(is).readAll(null).toString();
+      assertEquals("Hello world", res);
+  }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/TomcatLiteWatchdog.java b/modules/tomcat-lite/test/org/apache/tomcat/lite/servlet/TomcatLiteWatchdog.java
new file mode 100644 (file)
index 0000000..4b75826
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.servlet;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestResult;
+
+import org.apache.tomcat.lite.servlet.TomcatLite;
+import org.apache.tomcat.test.watchdog.WatchdogClient;
+
+
+public abstract class TomcatLiteWatchdog extends WatchdogClient {
+  
+  public TomcatLiteWatchdog() {
+      goldenDir = getWatchdogdir() + "/src/clients/org/apache/jcheck/servlet/client/";
+      testMatch = 
+          //"HttpServletResponseWrapperSetStatusMsgTest";
+          //"ServletContextAttributeAddedEventTest";
+          null;
+          // ex: "ServletToJSP";
+      file = getWatchdogdir() + "/src/conf/servlet-gtest.xml";
+      targetMatch = "gtestservlet-test";
+  }
+  
+  protected void beforeSuite() {
+      // required for the tests
+      System.setProperty("org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER",
+              "true");
+      
+      try {
+          initServerWithWatchdog(getWatchdogdir());
+      } catch (ServletException e) {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
+      } catch (IOException e) {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
+      }
+  }
+  
+  protected abstract void addConnector(TomcatLite liteServer);
+  
+  TomcatLite tomcatForWatchdog;
+  
+  public void initServerWithWatchdog(String wdDir) throws ServletException, 
+          IOException {
+      File f = new File(wdDir + "/build/webapps");
+      
+      tomcatForWatchdog = new TomcatLite();
+
+      addConnector(tomcatForWatchdog);
+//      tomcatForWatchdog.getHttpConnector().setDebug(true);
+//      tomcatForWatchdog.getHttpConnector().setDebugHttp(true);
+      
+      tomcatForWatchdog.addServletContext(null, "webapps/ROOT", "/").loadConfig();
+
+      for (String s : new String[] {      
+              "servlet-compat", 
+              "servlet-tests",
+              "jsp-tests"} ) {
+          tomcatForWatchdog.addServletContext(null, f.getCanonicalPath() + "/" + s, 
+                        "/" + s).loadConfig();
+      }
+
+      tomcatForWatchdog.init();
+      tomcatForWatchdog.start();
+
+      tomcatForWatchdog.startConnector();
+  }
+
+  
+  
+  protected void afterSuite(TestResult res) {
+      // no need to stop it - using daemon threads.
+  }
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/lite/test.properties b/modules/tomcat-lite/test/org/apache/tomcat/lite/test.properties
new file mode 100644 (file)
index 0000000..8c60706
--- /dev/null
@@ -0,0 +1,63 @@
+RUN=Log,JMXProxy,Socks,TomcatLite
+
+Log.(class)=org.apache.tomcat.lite.service.LogConfig
+Log.debug=org.apache.tomcat.lite.http.HttpConnector
+Log.debug=Proxy
+
+JMXProxy.(class)=org.apache.tomcat.lite.service.JMXProxy
+JMXProxy.port=8003
+
+Socks.(class)=org.apache.tomcat.lite.proxy.SocksServer
+Socks.port=2080
+Socks.idleTimeout=0
+
+#HttpConnector-TestServer.debug=true
+#HttpConnector-TestServer.debugHttp=true
+xHttpConnector-TestServer.clientKeepAlive=true
+xHttpConnector-TestServer.serverKeepAlive=true
+xHttpConnector-TestServer.maxHttpPoolSize=0
+
+#HttpConnector.debug=true
+#HttpConnector.debugHttp=true
+xHttpConnector.clientKeepAlive=true
+xHttpConnector.serverKeepAlive=true
+xHttpConnector.maxHttpPoolSize=0
+
+#HttpConnector-Proxy.debug=true
+#HttpConnector-Proxy.debugHttp=true
+xHttpConnector-Proxy.clientKeepAlive=true
+xHttpConnector-Proxy.serverKeepAlive=true
+xHttpConnector-Proxy.maxHttpPoolSize=0
+
+
+#IOConnector.debug=true
+
+# Tomcat-lite config
+# include:
+# config=org/apache/tomcat/lite/config.properties
+TomcatLite.(class)=org.apache.tomcat.lite.servlet.TomcatLite
+# TomcatLite.deployListener=org.apache.tomcat.servlets.config.deploy.WebXmlContextListener
+
+# Tomcat-lite plugins
+org.apache.tomcat.lite.WebappServletMapper.(class)=org.apache.tomcat.lite.WebappServletMapper
+org.apache.tomcat.lite.WebappFilterMapper.(class)=org.apache.tomcat.lite.WebappFilterMapper
+org.apache.tomcat.servlets.session.UserSessionManager.(class)=org.apache.tomcat.servlets.session.SimpleSessionManager
+org.apache.tomcat.servlets.jsp.UserTemplateClassMapper.(class)=org.apache.tomcat.servlets.jsp.JasperCompilerTemplateClassMapper
+org.apache.tomcat.servlets.file.Filesystem.(class)=org.apache.tomcat.file.LocalFilesystem
+default-servlet.(class)=org.apache.tomcat.servlets.file.WebdavServlet
+jspwildcard-servlet.(class)=org.apache.tomcat.servlets.jsp.WildcardTemplateServlet
+filetemplate-servlet.(class)=org.apache.tomcat.servlets.jsp.JspFileTemplateServlet
+
+org.apache.tomcat.lite.Connector.(class)=org.apache.tomcat.lite.AsyncConnector
+org.apache.tomcat.lite.Connector.port=8800
+
+
+
+TomcatLite.context.1=/examples:./webapps/examples
+TomcatLite.context.2=/:./webapps/ROOT
+TomcatLite.context.3=/lite:./modules/tomcat-lite/test-webapp
+// No base dir
+TomcatLite.context.4=/dynamic:
+
+
+JMXProxyServlet.(class)=org.apache.tomcat.integration.jmx.JMXProxyServlet
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/GTest.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/GTest.java
deleted file mode 100644 (file)
index 0e5bfbf..0000000
+++ /dev/null
@@ -1,1091 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
-* @Author Costin, Ramesh.Mandava
-*/
-
-package org.apache.tomcat.test.watchdog;
-
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import org.apache.tomcat.lite.HexDump;
-import org.apache.tools.ant.BuildException;
-
-
-// derived from Jsp
-
-public class GTest {
-
-    int failureCount = 0;
-    int passCount = 0;
-    Throwable lastError;
-    boolean hasFailed = false;
-
-    String prefix = "http";
-    String host = "localhost";
-    String localHost = null;
-    String localIP = null;
-    int port = 8080;
-    int debug = 0;
-
-    String description = "No description";
-
-    String request;
-    HashMap requestHeaders = new HashMap();
-    String content;
-    
-    // true if task is nested
-    private boolean nested = false;
-
-    // Expected response
-    boolean magnitude = true;
-    boolean exactMatch = false;
-
-    // expect a response body
-    boolean expectResponseBody = true;
-
-    // Match the body against a golden file
-    String goldenFile;
-    // Match the body against a string
-    String responseMatch;
-    // the response should include the following headers
-    HashMap expectHeaders = new HashMap();
-
-    // Headers that should not be found in response
-    HashMap unexpectedHeaders = new HashMap();
-
-    // Match request line
-    String returnCode = "";
-    String returnCodeMsg = "";
-
-    // Actual response
-    String responseLine;
-    byte[] responseBody;
-    HashMap headers;
-
-
-    // For Report generation
-    StringBuilder resultOut = new StringBuilder();
-    
-    boolean firstTask = false;
-    boolean lastTask = false;
-    String expectedString;
-    String actualString;
-
-    String testName;
-    String assertion;
-    String testStrategy;
-
-    // For Session Tracking
-    static Hashtable sessionHash;
-    static Hashtable cookieHash;
-
-    String testSession;
-    Vector cookieVector;
-    URL requestURL;
-    CookieController cookieController ;
-
-    /**
-     * Creates a new <code>GTest</code> instance.
-     *
-     */
-    public GTest() {
-    }
-
-    /**
-     * <code>setTestSession</code> adds a 
-     * CookieController for the value of sessionName
-     *
-     * @param sessionName a <code>String</code> value
-     */
-    public void setTestSession( String sessionName ) {
-        testSession = sessionName;
-
-        if ( sessionHash == null ) {
-            sessionHash = new Hashtable();
-        } else if ( sessionHash.get( sessionName ) == null ) {
-            sessionHash.put ( sessionName, new CookieController() );
-        }
-    }
-
-    /**
-     * <code>setTestName</code> sets the current test name.
-     *
-     * @param tn current testname.
-     */
-    public void setTestName ( String tn ) {
-        testName = tn;
-    }
-
-    /**
-     * <code>setAssertion</code> sets the assertion text
-     * for the current test.
-     *
-     * @param assertion assertion text
-     */
-    public void setAssertion ( String assertion ) {
-        this.assertion = assertion;
-    }
-    /**
-     * <code>setTestStrategy</code> sets the test strategy
-     * for the current test.
-     *
-     * @param strategy test strategy text
-     */
-    public void setTestStrategy ( String strategy ) {
-        testStrategy = strategy;
-    }
-
-    /**
-     * <code>getTestName</code> returns the current 
-     * test name.
-     *
-     * @return a <code>String</code> value
-     */
-    public String getTestName( ) {
-        return testName;
-    }
-
-    /**
-     * <code>getAssertion</code> returns the current
-     * assertion text.
-     *
-     * @return a <code>String</code> value
-     */
-    public String getAssertion( ) {
-        return assertion;
-    }
-
-    /**
-     * <code>getTestStrategy</code> returns the current
-     * test strategy test.
-     *
-     * @return a <code>String</code> value
-     */
-    public String getTestStrategy( ) {
-        return testStrategy;
-    }
-
-    /**
-     * <code>setFirstTask</code> denotes that current task
-     * being executed is the first task within the list.
-     *
-     * @param a <code>boolean</code> value
-     */    
-    public void setFirstTask( boolean val ) {
-        firstTask = val;
-    }
-   
-
-    /**
-     * <code>setLastTask</code> denotes that the current task
-     * being executed is the last task within the list.
-     *
-     * @param a <code>boolean</code> value
-     */ 
-    public void setLastTask ( boolean val ) {
-        lastTask = val;
-    }
-
-    /**
-     * <code>setPrefix</code> sets the protocol
-     * prefix.  Defaults to "http"
-     *
-     * @param prefix Either http or https
-     */
-    public void setPrefix( String prefix ) {
-        this.prefix = prefix;
-    }
-
-    /**
-     * <code>setHost</code> sets hostname where
-     * the target server is running. Defaults to
-     * "localhost"
-     *
-     * @param h a <code>String</code> value
-     */
-    public void setHost( String h ) {
-        this.host = h;
-    }
-
-    /**
-     * <code>setPort</code> sets the port
-     * that the target server is listening on.
-     * Defaults to "8080"
-     *
-     * @param portS a <code>String</code> value
-     */
-    public void setPort( String portS ) {
-        this.port = Integer.valueOf( portS ).intValue();
-    }
-
-    /**
-     * <code>setExactMatch</code> determines if a
-     * byte-by-byte comparsion is made of the server's
-     * response and the test's goldenFile, or if
-     * a token comparison is made.  By default, only
-     * a token comparison is made ("false").
-     *
-     * @param exact a <code>String</code> value
-     */
-    public void setExactMatch( String exact ) {
-        exactMatch = Boolean.valueOf( exact ).booleanValue();
-    }
-
-    /**
-     * <code>setContent</code> String value upon which
-     * the request header Content-Length is based upon.
-     *
-     * @param s a <code>String</code> value
-     */
-    public void setContent( String s ) {
-        this.content = s;
-    }
-
-    /**
-     * <code>setDebug</code> enables debug output.
-     * By default, this is disabled ( value of "0" ).
-     *
-     * @param debugS a <code>String</code> value
-     */
-    public void setDebug( String debugS ) {
-        debug = Integer.valueOf( debugS ).intValue();
-    }
-
-    /**
-     * <code>setMagnitude</code> Expected return
-     * value of the test execution.
-     * Defaults to "true"
-     *
-     * @param magnitudeS a <code>String</code> value
-     */
-    public void setMagnitude( String magnitudeS ) {
-        magnitude = Boolean.valueOf( magnitudeS ).booleanValue();
-    }
-
-    /**
-     * <code>setGoldenFile</code> Sets the goldenfile
-     * that will be used to validate the server's response.
-     *
-     * @param s fully qualified path and filename
-     */
-    public void setGoldenFile( String s ) {
-        this.goldenFile = s;
-    }
-
-    /**
-     * <code>setExpectResponseBody</code> sets a flag
-     * to indicate if a response body is expected from the
-     * server or not
-     *
-     * @param b a <code>boolean</code> value
-     */
-    public void setExpectResponseBody( boolean b ) {
-        this.expectResponseBody = b;
-    }
-
-    /**
-     * <code>setExpectHeaders</code> Configures GTest
-     * to look for the header passed in the server's
-     * response.  
-     *
-     * @param s a <code>String</code> value in the 
-     *          format of <header-field>:<header-value>
-     */
-    public void setExpectHeaders( String s ) {
-        this.expectHeaders = new HashMap();
-        StringTokenizer tok = new StringTokenizer( s, "|" );
-        while ( tok.hasMoreElements() ) {
-            String header = (String) tok.nextElement();
-            setHeaderDetails( header, expectHeaders, false );
-        }
-    }
-
-    /**
-     * <code>setUnexpectedHeaders</code> Configures GTest
-     * to look for the header passed to validate that it
-     * doesn't exist in the server's response.
-     *
-     * @param s a <code>String</code> value in the
-     *          format of <header-field>:<header-value>
-     */
-    public void setUnexpectedHeaders( String s ) {
-        this.unexpectedHeaders = new HashMap();
-        setHeaderDetails( s, unexpectedHeaders, false );
-    }
-
-    public void setNested( String s ) {
-        nested = Boolean.valueOf( s ).booleanValue();
-    }
-
-    /**
-     * <code>setResponseMatch</code> Match the
-     * passed value in the server's response.
-     *
-     * @param s a <code>String</code> value
-     */
-    public void setResponseMatch( String s ) {
-        this.responseMatch = s;
-    }
-
-    /**
-     * <code>setRequest</code> Sets the HTTP/HTTPS
-     * request to be sent to the target server
-     * Ex.
-     *    GET /servlet_path/val HTTP/1.0
-     *
-     * @param s a <code>String</code> value in the form
-     *          of METHOD PATH HTTP_VERSION
-     */
-    public void setRequest ( String s ) {
-        this.request = s;
-    }
-
-    /**
-     * <code>setReturnCode</code> Sets the expected
-     * return code from the server's response.
-     *
-     * @param code a valid HTTP response status code
-     */
-    public void setReturnCode( String code ) {
-        this.returnCode = code;
-    }
-
-    /**
-     * Describe <code>setReturnCodeMsg</code> Sets the expected
-     * return message to be found in the server's
-     * response.
-     *
-     * @param code a valid HTTP resonse status code
-     * @param message a <code>String</code> value
-     */
-    public void setReturnCodeMsg( String message ) {
-        this.returnCodeMsg = message;
-    }
-
-    /**
-     * <code>setRequestHeaders</code> Configures the request
-     * headers GTest should send to the target server.
-     *
-     * @param s a <code>String</code> value in for format
-     *          of <field-name>:<field-value>
-     */
-    public void setRequestHeaders( String s ) {
-        requestHeaders = new HashMap();
-        StringTokenizer tok = new StringTokenizer( s, "|" );
-        while ( tok.hasMoreElements() ) {
-            String header = (String) tok.nextElement();
-            setHeaderDetails( header, requestHeaders, true );
-        }
-    }
-
-    // Inner tests are not used currently, can be reworked
-    
-//    /**
-//     * Add a Task to this container
-//     *
-//     * @param Task to add
-//     */
-//    public void addTask(Task task) {
-//        children.add(task);
-//    }
-
-    /**
-     * <code>execute</code> Executes the test.
-     *
-     * @exception BuildException if an error occurs
-     */
-    public void execute()  {
-
-        try {
-
-            if ( resultOut != null && !nested ) {
-                resultOut.append("\ntestName: " + testName);
-                resultOut.append("\nreq: " + request);
-                resultOut.append("\nassertion: " + assertion);
-                resultOut.append("\ntestStrategy: " + testStrategy);
-            }
-
-            WatchdogHttpClient.dispatch(this);
-
-            hasFailed = !checkResponse( magnitude );
-
-
-//            if ( !children.isEmpty() ) {
-//                Iterator iter = children.iterator();
-//                while (iter.hasNext()) {
-//                    Task task = (Task) iter.next();
-//                    task.perform();
-//                }
-//            }
-
-            if ( !hasFailed && !nested ) {
-                passCount++;
-                if ( resultOut != null ) {
-                    resultOut.append( "<result>PASS</result>\n" );
-                }
-                System.out.println( " PASSED " + testName + "\n        (" + request + ")" );
-            } else if ( hasFailed && !nested ){
-                       failureCount++;
-                if ( resultOut != null ) {
-                    resultOut.append( "<result>FAIL</result>\n" );
-                }
-                System.out.println( " FAILED " + testName + "\n        (" + request + ")\n" +
-                        resultOut.toString());
-            }
-
-        } catch ( Exception ex ) {
-            failureCount++;
-            System.out.println( " FAIL " + description + " (" + request + ")" );
-            lastError = ex;
-            ex.printStackTrace();
-        } finally {
-            if ( !nested ) {
-                hasFailed = false;
-            }
-        }
-    }
-
-    /**
-     * <code>checkResponse</code> Executes various response
-     * checking mechanisms against the server's response.
-     * Checks include:
-     * <ul>
-     *    <li>expected headers
-     *    <li>unexpected headers
-     *    <li>return codes and messages in the Status-Line
-     *    <li>response body comparison againt a goldenfile
-     * </ul>
-     *
-     * @param testCondition a <code>boolean</code> value
-     * @return a <code>boolean</code> value
-     * @exception Exception if an error occurs
-     */
-    private boolean checkResponse( boolean testCondition )
-    throws Exception {
-       boolean match = false;
-
-       if ( responseLine != null ) {
-        // If returnCode doesn't match
-           if ( responseLine.indexOf( "HTTP/1." ) > -1 ) {
-
-                   if ( !returnCode.equals( "" ) ) {
-                       boolean resCode = ( responseLine.indexOf( returnCode ) > -1 );
-                       boolean resMsg  = ( responseLine.indexOf( returnCodeMsg ) > -1 );
-
-                       if ( returnCodeMsg.equals( "" ) ) {
-                               match = resCode;
-                       } else {
-                               match = ( resCode && resMsg );
-                       }
-
-                       if ( match != testCondition ) {
-
-                               if ( resultOut != null ) {
-                                  String expectedStatusCode = "<expectedStatusCode>" + returnCode + "</expectedReturnCode>\n";
-                                  String expectedReasonPhrase = "<expectedReasonPhrase>" + returnCodeMsg + "</expectedReasonPhrase>";
-                                  actualString = "<actualStatusLine>" + responseLine + "</actualStatusLine>\n";
-                                   resultOut.append( expectedStatusCode );
-                                   resultOut.append( expectedReasonPhrase );
-                                   resultOut.append( actualString );
-                               }
-
-                               return false;
-                       }
-                   }
-           } else {
-               resultOut.append("\n<failure>Wrong Http version: " + responseLine +
-                       "</failure>");
-               return false;
-           }
-       } else {
-           resultOut.append("\n<failure>No response from server</failure>" );
-           return false;
-       }
-
-       /* 
-        * Check for headers the test expects to be in the server's response
-        */
-
-       // Duplicate set of response headers
-       HashMap copiedHeaders = cloneHeaders( headers );
-
-       // used for error reporting
-       String currentHeaderField = null;
-       String currentHeaderValue = null;
-
-        if ( !expectHeaders.isEmpty() ) {
-           boolean found = false;
-           String expHeader = null;
-
-           if ( !headers.isEmpty() ) {
-               Iterator expectIterator = expectHeaders.keySet().iterator();
-                while ( expectIterator.hasNext() ) {
-                    found = false;
-                    String expFieldName = (String) expectIterator.next();
-                    currentHeaderField = expFieldName;
-                    ArrayList expectValues = (ArrayList) expectHeaders.get( expFieldName );
-                    Iterator headersIterator = copiedHeaders.keySet().iterator();
-
-                    while( headersIterator.hasNext() ) {
-                        String headerFieldName = (String) headersIterator.next();
-                        ArrayList headerValues = (ArrayList) copiedHeaders.get( headerFieldName );
-              
-                        // compare field names and values in an HTTP 1.x compliant fashion
-                        if ( ( headerFieldName.equalsIgnoreCase( expFieldName ) ) ) {
-                            int hSize = headerValues.size();
-                            int eSize = expectValues.size();
-
-                            // number of expected headers found in server response
-                            int numberFound = 0;
-             
-                            for ( int i = 0; i < eSize; i++ ) {
-                                currentHeaderValue = (String) expectValues.get( i );
-                                               
-                                /*
-                                 * Handle the Content-Type header appropriately
-                                 * based on the the test is configured to look for.
-                                 */
-                                if ( currentHeaderField.equalsIgnoreCase( "content-type" ) ) {
-                                    String resVal = (String) headerValues.get( 0 );
-                                    if ( currentHeaderValue.indexOf( ';' ) > -1 ) {
-                                        if ( currentHeaderValue.equals( resVal ) ) {
-                                            numberFound++;
-                                            headerValues.remove( 0 );
-                                        }
-                                    } else if ( resVal.indexOf( currentHeaderValue ) > -1 ) {
-                                        numberFound++;
-                                        headerValues.remove( 0 );
-                                    }
-                                } else if ( currentHeaderField.equalsIgnoreCase( "location" ) ) {
-                                    String resVal = (String) headerValues.get( 0 );
-                                    int idx = currentHeaderValue.indexOf( ":80/" );
-                                    if ( idx > -1 ) {
-                                        String tempValue = currentHeaderValue.substring( 0, idx ) +
-                                                           currentHeaderValue.substring( idx + 3 );
-                                        if ( currentHeaderValue.equals( resVal ) || 
-                                             tempValue.equals( resVal ) ) {
-                                            numberFound++;
-                                            headerValues.remove( 0 );
-                                        }
-                                    } else {
-                                        if ( currentHeaderValue.equals( resVal ) ) {
-                                            numberFound++;
-                                            headerValues.remove( 0 );
-                                        }
-                                    }
-                                } else if ( headerValues.contains( currentHeaderValue ) ) {
-                                    numberFound++;
-                                    headerValues.remove( headerValues.indexOf( currentHeaderValue ) );
-                                }
-                            }
-                            if ( numberFound == eSize ) {
-                                found = true;
-                            }
-                        }
-                    }
-                    if ( !found ) {
-                        /*
-                         * Expected headers not found in server response.
-                         * Break the processing loop.
-                         */
-                        break;
-                    }
-                }
-            }
-
-           if ( !found ) {
-               StringBuilder actualBuffer = new StringBuilder( 128 );
-               if ( resultOut != null ) {
-                   expectedString = "<expectedHeaderNotFound>" + currentHeaderField + ": " + currentHeaderValue + "</expectedHeader>\n";
-               }
-                if ( !headers.isEmpty() ) {
-                    Iterator iter = headers.keySet().iterator();
-                    while ( iter.hasNext() ) {
-                        String headerName = (String) iter.next();
-                        ArrayList vals = (ArrayList) headers.get( headerName );
-                        String[] val = (String[]) vals.toArray( new String[ vals.size() ] );
-                        for ( int i = 0; i < val.length; i++ ) {
-                           if ( resultOut != null ) {
-                               actualBuffer.append( "<actualHeader>" + headerName + ": " + val[ i ] + "</actualHeader>\n" );
-                           }
-                        }
-                    }
-                   if ( resultOut != null ) {
-                       resultOut.append( expectedString );
-                       resultOut.append( actualBuffer.toString() );
-                   }
-                }
-                return false;
-            }
-        }
-
-       /*
-         * Check to see if we're looking for unexpected headers.
-         * If we are, compare the values in the unexectedHeaders
-         * ArrayList against the headers from the server response.
-         * if the unexpected header is found, then return false.
-         */
-
-        if ( !unexpectedHeaders.isEmpty() ) {
-            boolean found = false;
-            String unExpHeader = null;
-            // Check if we got any unexpected headers
-
-            if ( !copiedHeaders.isEmpty() ) {
-                Iterator unexpectedIterator = unexpectedHeaders.keySet().iterator();
-                while ( unexpectedIterator.hasNext() ) {
-                    found = false;
-                    String unexpectedFieldName = (String) unexpectedIterator.next();
-                    ArrayList unexpectedValues = (ArrayList) unexpectedHeaders.get( unexpectedFieldName );
-                    Iterator headersIterator = copiedHeaders.keySet().iterator();
-
-                    while ( headersIterator.hasNext() ) {
-                        String headerFieldName = (String) headersIterator.next();
-                        ArrayList headerValues = (ArrayList) copiedHeaders.get( headerFieldName );
-                        
-                        // compare field names and values in an HTTP 1.x compliant fashion
-                        if ( ( headerFieldName.equalsIgnoreCase( unexpectedFieldName ) ) ) {
-                            int hSize = headerValues.size();
-                            int eSize = unexpectedValues.size();
-                            int numberFound = 0;
-                            for ( int i = 0; i < eSize; i++ ) {
-                                if ( headerValues.contains( unexpectedValues.get( i ) ) ) {
-                                    numberFound++;
-                                    if (headerValues.indexOf(headerFieldName) >= 0) {
-                                        headerValues.remove( headerValues.indexOf( headerFieldName ) );
-                                    }
-                                }
-                            }
-                            if ( numberFound == eSize ) {
-                                found = true;
-                            }
-                        }
-                    }
-                    if ( !found ) {
-                        /*
-                         * Expected headers not found in server response.
-                         * Break the processing loop.
-                         */
-                        break;
-                    }
-                }
-            }
-
-            if ( found ) {
-                resultOut.append( "\n Unexpected header received from server: " + unExpHeader );
-                return false;
-            }
-       }
-
-           
-
-        if ( responseMatch != null ) {
-            // check if we got the string we wanted
-            if ( expectResponseBody && responseBody == null ) {
-                resultOut.append( "\n ERROR: got no response, expecting " + responseMatch );
-                return false;
-            }
-           String responseBodyString = new String( responseBody );
-            if ( responseBodyString.indexOf( responseMatch ) < 0 ) {
-                resultOut.append( "\n ERROR: expecting match on " + responseMatch );
-                resultOut.append( "\n Received: \n" + responseBodyString );
-            }
-        }
-
-       if ( !expectResponseBody && responseBody != null ) {
-           resultOut.append("Received a response body from the server where none was expected" );
-           return false;
-       }
-
-        // compare the body
-        if ( goldenFile == null )
-            return true;
-
-        // Get the expected result from the "golden" file.
-        byte[] expResult = getExpectedResult();
-        String expResultS = (expResult == null) ? "" : new String(expResult);
-        // Compare the results and set the status
-        boolean cmp = true;
-
-        if ( exactMatch ) {
-            cmp = compare( responseBody, expResult );
-       } else {
-            cmp = compareWeak( responseBody, expResult );
-       }
-
-        if ( cmp != testCondition ) {
-
-            if ( resultOut != null ) {
-              expectedString = "<expectedBody>" + new String(expResult) + "</expectedBody>\n";
-              actualString = "<actualBody>" + 
-              (responseBody != null ? new String(responseBody) : "null" ) + 
-              "</actualBody>\n";
-                resultOut.append( expectedString );
-                resultOut.append( actualString );
-            }
-           return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Replaces any |client.ip| and |client.host| parameter marks
-     * with the host and IP values of the host upon which Watchdog
-     * is running.
-     *
-     * @param request An HTTP request. 
-     */
-     String replaceMarkers( String req, Socket socket ) {
-        
-        final String CLIENT_IP = "client.ip";
-        final String CLIENT_HOME = "client.host";
-
-        if (localIP == null || localHost == null) {
-            InetAddress addr = socket.getLocalAddress(); 
-            localHost = addr.getHostName();
-            localIP = addr.getHostAddress();
-        }
-
-        if (req.indexOf('|') > -1) {
-            StringTokenizer tok = new StringTokenizer( request, "|" );
-            StringBuilder sb = new StringBuilder( 50 );
-        
-            while ( tok.hasMoreElements() ) {
-                String token = tok.nextToken();
-                if ( token.equals( CLIENT_IP ) ) {
-                    sb.append( localIP );
-                } else if ( token.equals( CLIENT_HOME ) ) {
-                    sb.append( localHost );
-                } else {
-                    sb.append( token );
-                }
-            }
-            return sb.toString(); 
-        } else {
-            return req;
-        }
-    }
-            
-
-    
-    /**
-     * <code>getExpectedResult</code> returns a byte array
-     * containing the content of the configured goldenfile
-     *
-     * @return goldenfile as a byte[]
-     * @exception IOException if an error occurs
-     */
-    private byte[] getExpectedResult()
-    throws IOException {
-        byte[] expResult = { 'N','O',' ',
-                             'G','O','L','D','E','N','F','I','L','E',' ',
-                             'F','O','U','N','D' };
-                            
-        try {
-            InputStream in = new BufferedInputStream(
-                                new FileInputStream( goldenFile ) );
-            return readBody ( in );
-        } catch ( Exception ex ) {
-            System.out.println( "Golden file not found: " + goldenFile );
-            return expResult;
-        }
-    }
-
-    /**
-     * <code>compare</code> compares the two byte arrays passed
-     * in to verify that the lengths of the arrays are equal, and
-     * that the content of the two arrays, byte for byte are equal.
-     *
-     * @param fromServer a <code>byte[]</code> value
-     * @param fromGoldenFile a <code>byte[]</code> value
-     * @return <code>boolean</code> true if equal, otherwise false
-     */
-    private boolean compare( byte[] fromServer, byte[] fromGoldenFile ) {
-        if ( fromServer == null || fromGoldenFile == null ) {
-            return false;
-       }
-
-       /*
-         * Check to see that the respose and golden file lengths
-         * are equal.  If they are not, dump the hex and don't
-         * bother comparing the bytes.  If they are equal,
-         * iterate through the byte arrays and compare each byte.
-         * If the bytes don't match, dump the hex representation
-         * of the server response and the goldenfile and return
-         * false.
-         */
-       if ( fromServer.length != fromGoldenFile.length ) {
-            StringBuilder sb = new StringBuilder( 50 );
-            sb.append( " Response and golden files lengths do not match!\n" );
-            sb.append( " Server response length: " );
-            sb.append( fromServer.length );
-            sb.append( "\n Goldenfile length: " );
-            sb.append( fromGoldenFile.length );
-            resultOut.append( sb.toString() );
-            sb = null;
-            // dump the hex representation of the byte arrays
-            dumpHex( fromServer, fromGoldenFile );
-
-            return false;
-        } else {
-
-            int i = 0;
-            int j = 0;
-
-            while ( ( i < fromServer.length ) && ( j < fromGoldenFile.length ) ) {
-                if ( fromServer[ i ] != fromGoldenFile[ j ] ) {
-                    resultOut.append( "\n Error at position " + ( i + 1 ) );
-                    // dump the hex representation of the byte arrays
-                    dumpHex( fromServer, fromGoldenFile );
-
-                    return false;
-                }
-
-                i++;
-                j++;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * <code>compareWeak</code> creates new Strings from the passed arrays
-     * and then uses a StringTokenizer to compare non-whitespace tokens.
-     *
-     * @param fromServer a <code>byte[]</code> value
-     * @param fromGoldenFile a <code>byte[]</code> value
-     * @return a <code>boolean</code> value
-     */
-    private boolean compareWeak( byte[] fromServer, byte[] fromGoldenFile ) {
-        if ( fromServer == null || fromGoldenFile == null ) {
-            return false;
-           }
-
-        boolean status = true;
-
-        String server = new String( fromServer );
-        String golden = new String( fromGoldenFile );
-
-        StringTokenizer st1 = new StringTokenizer( server );
-
-        StringTokenizer st2 = new StringTokenizer( golden );
-
-        while ( st1.hasMoreTokens() && st2.hasMoreTokens() ) {
-            String tok1 = st1.nextToken();
-            String tok2 = st2.nextToken();
-
-            if ( !tok1.equals( tok2 ) ) {
-                resultOut.append( "\t FAIL*** : Rtok1 = " + tok1
-                                    + ", Etok2 = " + tok2 );
-                status = false;
-            }
-        }
-
-        if ( st1.hasMoreTokens() || st2.hasMoreTokens() ) {
-             status = false;
-        }
-
-        if ( !status ) {
-            StringBuilder sb = new StringBuilder( 255 );
-            sb.append( "ERROR: Server's response and configured goldenfile do not match!\n" );
-            sb.append( "Response received from server:\n" );
-            sb.append( "---------------------------------------------------------\n" );
-            sb.append( server );
-            sb.append( "\nContent of Goldenfile:\n" );
-            sb.append( "---------------------------------------------------------\n" );
-            sb.append( golden );
-            sb.append( "\n" );
-            resultOut.append( sb.toString() );
-        }
-        return status;
-    }
-
-    /**
-     * <code>readBody</code> reads the body of the response
-     * from the InputStream.
-     *
-     * @param input an <code>InputStream</code>
-     * @return a <code>byte[]</code> representation of the response
-     */
-    private byte[] readBody( InputStream input ) {
-        StringBuilder sb = new StringBuilder( 255 );
-        while ( true ) {
-            try {
-                int ch = input.read();
-
-                if ( ch < 0 ) {
-                    if ( sb.length() == 0 ) {
-                        return ( null );
-                    } else {
-                        break;
-                    }
-                }
-                sb.append( ( char ) ch );
-                 
-            } catch ( IOException ex ) {
-                return null;
-            }
-        }
-        return sb.toString().getBytes();
-    }
-
-    /**
-     * <code>setHeaderDetails</code> Wrapper method for parseHeader.
-     * Allows easy addition of headers to the specified
-     * HashMap
-     *
-     * @param line a <code>String</code> value
-     * @param headerMap a <code>HashMap</code> value
-     * @param isRequest a <code>boolean</code> indicating if the passed Header 
-     *                  HashMap is for request headers
-     */
-    void setHeaderDetails( String line, HashMap headerHash, boolean isRequest ) {
-        StringTokenizer stk = new StringTokenizer( line, "##" );
-
-        while ( stk.hasMoreElements( ) ) {
-            String presentHeader = stk.nextToken();
-            parseHeader( presentHeader, headerHash, isRequest );
-        }
-    }
-
-    /**
-     * <code>parseHeader</code> parses input headers in format of "key:value"
-     * The parsed header field-name will be used as a key in the passed 
-     * HashMap object, and the values found will be stored in an ArrayList
-     * associated with the field-name key.
-     *
-     * @param line String representation of an HTTP header line.
-     * @param headers a<code>HashMap</code> to store key/value header objects.
-     * @param isRequest set to true if the headers being processed are 
-     *        requestHeaders.
-     */
-    void parseHeader( String line, HashMap headerMap, boolean isRequest ) {
-        // Parse the header name and value
-        int colon = line.indexOf( ":" );
-
-        if ( colon < 0 ) {
-            resultOut.append( "\n ERROR: Header is in incorrect format: " + line );
-            return ;
-        }
-
-        String name = line.substring( 0, colon ).trim();
-        String value = line.substring( colon + 1 ).trim();
-
-        if ( ( cookieVector != null ) && ( name.equalsIgnoreCase( "Set-Cookie" ) ) ) {
-            cookieVector.addElement( value );
-            /*
-            if ( ( value.indexOf("JSESSIONID") > -1 ) || (value.indexOf("jsessionid")  > -1 ) )
-        {
-                 String sessionId= value.substring( value.indexOf("=")+1);
-                 if ( testSession != null )
-                 {
-                       sessionHash.put( testSession, sessionId );
-                 }
-                 System.out.println("Got Session-ID : " + sessionId );
-        }
-            */
-        }
-
-        //     System.out.println("HEADER: " +name + " " + value);
-
-       ArrayList values = (ArrayList) headerMap.get( name );
-       if ( values == null ) {
-           values = new ArrayList();
-       }
-       // HACK
-       if ( value.indexOf( ',' ) > -1 && !isRequest && !name.equalsIgnoreCase( "Date" ) ) {
-           StringTokenizer st = new StringTokenizer( value, "," );
-           while ( st.hasMoreElements() ) {
-               values.add( st.nextToken() );
-           }
-       } else {
-           values.add( value );
-       }
-       
-        headerMap.put( name, values );
-    }
-
-    /**
-     * <code>dumpHex</code> helper method to dump formatted
-     * hex output of the server response and the goldenfile.
-     *
-     * @param serverResponse a <code>byte[]</code> value
-     * @param goldenFile a <code>byte[]</code> value
-     */
-    private void dumpHex( byte[] serverResponse, byte[] goldenFile ) {
-        StringBuilder outBuf = new StringBuilder( ( serverResponse.length + goldenFile.length ) * 2 );
-
-        String fromServerString = HexDump.getHexDump( serverResponse, 0, serverResponse.length, true );
-        String fromGoldenFileString = HexDump.getHexDump( goldenFile, 0, goldenFile.length, true );
-
-        outBuf.append( " Hex dump of server response and goldenfile below.\n\n### RESPONSE FROM SERVER ###\n" );
-        outBuf.append( "----------------------------\n" );
-        outBuf.append( fromServerString );
-        outBuf.append( "\n\n### GOLDEN FILE ###\n" );
-        outBuf.append( "-------------------\n" );
-        outBuf.append( fromGoldenFileString );
-        outBuf.append( "\n\n### END OF DUMP ###\n" );
-
-        resultOut.append( outBuf.toString() );
-
-    }
-
-    /**
-     * <code>cloneHeaders</code> returns a "cloned"
-     * HashMap of the map passed in.
-     *
-     * @param map a <code>HashMap</code> value
-     * @return a <code>HashMap</code> value
-     */
-    private HashMap cloneHeaders( HashMap map ) {
-       HashMap dupMap = new HashMap();
-       Iterator iter = map.keySet().iterator();
-       
-       while ( iter.hasNext() ) {
-           String key = new String( (String) iter.next() );
-           ArrayList origValues = (ArrayList) map.get( key );
-           ArrayList dupValues = new ArrayList();
-
-           String[] dupVal = (String[]) origValues.toArray( new String[ origValues.size() ] );
-           for ( int i = 0; i < dupVal.length; i++ ) {
-               dupValues.add( new String( dupVal[ i ] ) );
-           }
-           
-           dupMap.put( key, dupValues );
-       }
-       return dupMap;
-    }
-
-}
index 21f4276..ac10f84 100644 (file)
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.test.watchdog;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.Properties;
@@ -26,15 +27,13 @@ import junit.framework.Test;
 import junit.framework.TestResult;
 import junit.framework.TestSuite;
 
-import org.apache.tomcat.util.DomUtil;
+import org.apache.tomcat.servlets.config.deploy.DomUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
 public class WatchdogClient {
-
-  protected String base = "../watchdog";
         
   protected String goldenDir; 
   protected String testMatch;
@@ -51,11 +50,13 @@ public class WatchdogClient {
   Properties props = new Properties();
   
   protected void beforeSuite() {
-      
   }
   
   protected void afterSuite(TestResult res) {
-      
+  }
+  
+  public Test getSuite() {
+      return getSuite(8080);
   }
   
   /** 
@@ -66,11 +67,11 @@ public class WatchdogClient {
    * @param testMatch Prefix of tests to be run
    * @return
    */
-  public Test getSuite() {
+  public Test getSuite(int port) {
     TestSuite tests = new WatchdogTests();
     tests.setName(this.getClass().getSimpleName());
     
-    props.setProperty("port", "8080");
+    props.setProperty("port", Integer.toString(port));
     props.setProperty("host", "localhost");
     props.setProperty("wgdir", 
         goldenDir);
@@ -112,22 +113,16 @@ public class WatchdogClient {
               }
           }
           testName = testName + ";" + this.getClass().getName();
-          WatchdogTest test = new WatchdogTest(watchE, props, testName);
+          WatchdogTestCase test = new WatchdogTestCase(watchE, props, testName);
           tests.addTest(test);
         }
-        
-        //        if (targetSuite.countTestCases() > 0) { 
-        //          tests.addTest(targetSuite);
-        //              }
       }
       
     } catch (IOException e) {
-      e.printStackTrace();
+        e.printStackTrace();
     } catch (SAXException e) {
-        // TODO Auto-generated catch block
         e.printStackTrace();
     } catch (ParserConfigurationException e) {
-        // TODO Auto-generated catch block
         e.printStackTrace();
     }
     return tests;
@@ -135,6 +130,22 @@ public class WatchdogClient {
   
   // --------- Inner classes -------------
 
+  protected String getWatchdogdir() {
+      String path = System.getProperty("watchdog.home");
+      if (path != null) {
+          return path;
+      }
+      path = "..";
+      for (int i = 0; i < 10; i++) {
+          File f = new File(path + "/watchdog");
+          if (f.exists()) {
+              return f.getAbsolutePath();
+          }
+          path = path + "/..";
+      }
+      return null;
+  }
+
   public class WatchdogTests extends TestSuite {
       public void run(TestResult res) {
           beforeSuite();
@@ -142,5 +153,5 @@ public class WatchdogClient {
           afterSuite(res);
       }
   }
-  
+
 }
index 62d5663..f49dd75 100644 (file)
@@ -37,7 +37,7 @@ public class WatchdogHttpClient {
     
     static int debug = 0;
     
-    public static void dispatch(GTest client) throws Exception {
+    public static void dispatch(WatchdogTestImpl client) throws Exception {
         HashMap requestHeaders = client.requestHeaders;
         String host = client.host;
         int port = client.port;
@@ -45,7 +45,14 @@ public class WatchdogHttpClient {
         String request = client.request;
         
         // XXX headers are ignored
-        Socket socket = new Socket( host, port );
+        Socket socket;
+        try {
+            socket = new Socket( host, port );
+        } catch (IOException ex) {
+            System.out.println( " Socket Exception: " + ex );
+            return;
+        }
+        //socket.setSoTimeout(10000);
         
         //socket obtained, rebuild the request.
         rebuildRequest(client, client.request, socket);
@@ -57,7 +64,7 @@ public class WatchdogHttpClient {
 
         OutputStream out = new BufferedOutputStream( 
                                socket.getOutputStream() );
-        StringBuilder reqbuf = new StringBuilder( 128 );
+        StringBuffer reqbuf = new StringBuffer( 128 );
 
         // set the Host header
         client.setHeaderDetails( "Host:" + host + ":" + port, requestHeaders, true );
@@ -92,7 +99,7 @@ public class WatchdogHttpClient {
             Iterator iter = requestHeaders.keySet().iterator();
                         
             while ( iter.hasNext() ) {
-                StringBuilder tmpBuf = new StringBuilder(32);
+                StringBuffer tmpBuf = new StringBuffer(32);
                 String headerKey = ( String ) iter.next();
                         ArrayList values = (ArrayList) requestHeaders.get( headerKey );
                         String[] value = (String[]) values.toArray( new String[ values.size() ] );
@@ -168,7 +175,6 @@ public class WatchdogHttpClient {
                 
         } catch ( SocketException ex ) {
             System.out.println( " Socket Exception: " + ex );
-            ex.printStackTrace();
         } finally {
                 if ( debug > 0 ) {
                         System.out.println( " closing socket" );
@@ -187,7 +193,7 @@ public class WatchdogHttpClient {
      * @return a <code>byte[]</code> representation of the response
      */
     private static byte[] readBody( InputStream input ) {
-        StringBuilder sb = new StringBuilder( 255 );
+        StringBuffer sb = new StringBuffer( 255 );
         while ( true ) {
             try {
                 int ch = input.read();
@@ -222,7 +228,7 @@ public class WatchdogHttpClient {
      */
     private static String read( InputStream input ) throws IOException {
         // Read the next line from the input stream
-        StringBuilder sb = new StringBuilder();
+        StringBuffer sb = new StringBuffer();
 
         while ( true ) {
             try {
@@ -265,7 +271,7 @@ public class WatchdogHttpClient {
      *
      * @exception IOException if an input/output error occurs
      */
-    private static HashMap parseHeaders( GTest client, InputStream is ) throws IOException {
+    private static HashMap parseHeaders( WatchdogTestImpl client, InputStream is ) throws IOException {
         HashMap headers = new HashMap();
         client.cookieVector = new Vector();
 
@@ -307,7 +313,7 @@ public class WatchdogHttpClient {
      *
      * @exception Exception if an error occurs
      */
-    private static void rebuildRequest(GTest client, String req, Socket socket) throws Exception {
+    private static void rebuildRequest(WatchdogTestImpl client, String req, Socket socket) throws Exception {
         client.request = client.replaceMarkers(req, socket );
         String addressString = client.request.substring( client.request.indexOf( "/" ), client.request.indexOf( "HTTP" ) ).trim();
 
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTest.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTest.java
deleted file mode 100644 (file)
index d5b7067..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package org.apache.tomcat.test.watchdog;
-
-import java.util.Properties;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-import junit.framework.TestResult;
-import junit.framework.TestSuite;
-
-import org.apache.tomcat.util.IntrospectionUtils;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-public class WatchdogTest extends TestCase {
-    String testName;
-
-    Element watchE;
-
-    private Properties props;
-
-    private WatchdogTest delegate;
-    private WatchdogClient wc;
-    
-    public WatchdogTest(String s) throws Throwable {
-        String[] comp = s.split(";");
-        Class c = Class.forName(comp[1]);
-        wc = (WatchdogClient) c.newInstance();
-        TestSuite suite = (TestSuite) wc.getSuite();
-        // need to encode the base, file, etc in the test name
-
-        System.err.println(s);
-
-        for (int i = 0; i < suite.testCount(); i++) {
-            WatchdogTest t = (WatchdogTest) suite.testAt(i);
-            if (s.equals(t.getName())) {
-                delegate = t;
-                return;
-            }
-        }
-    }
-
-    public WatchdogTest(Element watchE, Properties props, String testName) {
-        this.testName = testName;
-        this.watchE = watchE;
-        this.props = props;
-    }
-
-    public int countTestCases() {
-        return 1;
-    }
-
-    public String getName() {
-        return testName;
-    }
-
-    public void run(TestResult res) {
-        if (delegate != null) {
-            // Single method run
-            wc.beforeSuite();
-            delegate.run(res);
-            wc.afterSuite(res);
-            return;
-        }
-        GTest test = new GTest();
-        NamedNodeMap attrs = watchE.getAttributes();
-
-        for (int i = 0; i < attrs.getLength(); i++) {
-            Node n = attrs.item(i);
-            String name = n.getNodeName();
-            String value = n.getNodeValue();
-            value = IntrospectionUtils.replaceProperties(value, props, null);
-            try {
-                IntrospectionUtils.setProperty(test, name, value);
-            } catch (Exception e) {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-        }
-
-        try {
-            res.startTest(this);
-            IntrospectionUtils.execute(test, "execute");
-        } catch (Throwable e) {
-            res.addError(this, e);
-            // res.stop();
-        }
-
-        if (test.passCount == 1) {
-            res.endTest(this);
-            return;
-        } else {
-            if (test.lastError == null) {
-                res.addFailure(this, new AssertionFailedError(test.request
-                        + " " + test.description + "\n" + test.resultOut));
-            } else {
-                res.addError(this, test.lastError);
-            }
-        }
-        res.endTest(this);
-    }
-
-}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestCase.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestCase.java
new file mode 100644 (file)
index 0000000..3486a80
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ */
+package org.apache.tomcat.test.watchdog;
+
+import java.util.Properties;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.apache.tomcat.integration.DynamicObject;
+import org.apache.tomcat.integration.simple.AntProperties;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class WatchdogTestCase implements Test {
+    String testName;
+
+    Element watchE;
+
+    private Properties props;
+
+    private WatchdogTestCase delegate;
+    private WatchdogClient wc;
+    
+    public WatchdogTestCase(String s) throws Throwable {
+        String[] comp = s.split(";");
+        if (comp.length < 2) {
+            return;
+        }
+        Class c = Class.forName(comp[1]);
+        wc = (WatchdogClient) c.newInstance();
+        TestSuite suite = (TestSuite) wc.getSuite();
+        // need to encode the base, file, etc in the test name
+
+        System.err.println(s);
+
+        for (int i = 0; i < suite.testCount(); i++) {
+            WatchdogTestCase t = (WatchdogTestCase) suite.testAt(i);
+            if (s.equals(t.getName())) {
+                delegate = t;
+                return;
+            }
+        }
+    }
+
+    public WatchdogTestCase(Element watchE, Properties props, String testName) {
+        this.testName = testName;
+        this.watchE = watchE;
+        this.props = props;
+    }
+
+    public int countTestCases() {
+        return 1;
+    }
+
+    public String getName() {
+        return testName;
+    }
+
+    public void testDummy() {
+    }
+    
+    public void run(TestResult res) {
+        if (delegate != null) {
+            // Single method run
+            wc.beforeSuite();
+            delegate.run(res);
+            wc.afterSuite(res);
+            return;
+        }
+        if (watchE == null) {
+            res.endTest(this);
+            return;
+        }
+        WatchdogTestImpl test = new WatchdogTestImpl();
+        NamedNodeMap attrs = watchE.getAttributes();
+
+        for (int i = 0; i < attrs.getLength(); i++) {
+            Node n = attrs.item(i);
+            String name = n.getNodeName();
+            String value = n.getNodeValue();
+            value = AntProperties.replaceProperties(value, props, null);
+            try {
+                new DynamicObject(test.getClass()).setProperty(test, 
+                        name, value);
+            } catch (Exception e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+
+        try {
+            res.startTest(this);
+            new DynamicObject(test.getClass()).invoke(test, "execute");
+        } catch (Throwable e) {
+            res.addError(this, e);
+            // res.stop();
+        }
+
+        if (test.passCount == 1) {
+            res.endTest(this);
+            return;
+        } else {
+            if (test.lastError == null) {
+                res.addFailure(this, new AssertionFailedError(test.request
+                        + " " + test.description + "\n" + test.resultOut));
+            } else {
+                res.addError(this, test.lastError);
+            }
+        }
+        res.endTest(this);
+    }
+
+}
diff --git a/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java b/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java
new file mode 100644 (file)
index 0000000..8f92a82
--- /dev/null
@@ -0,0 +1,1172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @Author Costin, Ramesh.Mandava
+ */
+
+package org.apache.tomcat.test.watchdog;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.tomcat.lite.io.Hex;
+
+// derived from Jsp
+
+public class WatchdogTestImpl {
+
+    int failureCount = 0;
+
+    int passCount = 0;
+
+    Throwable lastError;
+
+    boolean hasFailed = false;
+
+    String prefix = "http";
+
+    String host = "localhost";
+
+    String localHost = null;
+
+    String localIP = null;
+
+    int port = 8080;
+
+    int debug = 0;
+
+    String description = "No description";
+
+    String request;
+
+    HashMap requestHeaders = new HashMap();
+
+    String content;
+
+    // true if task is nested
+    private boolean nested = false;
+
+    // Expected response
+    boolean magnitude = true;
+
+    boolean exactMatch = false;
+
+    // expect a response body
+    boolean expectResponseBody = true;
+
+    // Match the body against a golden file
+    String goldenFile;
+
+    // Match the body against a string
+    String responseMatch;
+
+    // the response should include the following headers
+    HashMap expectHeaders = new HashMap();
+
+    // Headers that should not be found in response
+    HashMap unexpectedHeaders = new HashMap();
+
+    // Match request line
+    String returnCode = "";
+
+    String returnCodeMsg = "";
+
+    // Actual response
+    String responseLine;
+
+    byte[] responseBody;
+
+    HashMap headers;
+
+    // For Report generation
+    StringBuffer resultOut = new StringBuffer();
+
+    boolean firstTask = false;
+
+    boolean lastTask = false;
+
+    String expectedString;
+
+    String actualString;
+
+    String testName;
+
+    String assertion;
+
+    String testStrategy;
+
+    // For Session Tracking
+    static Hashtable sessionHash;
+
+    static Hashtable cookieHash;
+
+    String testSession;
+
+    Vector cookieVector;
+
+    URL requestURL;
+
+    CookieController cookieController;
+
+    /**
+     * Creates a new <code>GTest</code> instance.
+     * 
+     */
+    public WatchdogTestImpl() {
+    }
+
+    /**
+     * <code>setTestSession</code> adds a CookieController for the value of
+     * sessionName
+     * 
+     * @param sessionName
+     *            a <code>String</code> value
+     */
+    public void setTestSession(String sessionName) {
+        testSession = sessionName;
+
+        if (sessionHash == null) {
+            sessionHash = new Hashtable();
+        } else if (sessionHash.get(sessionName) == null) {
+            sessionHash.put(sessionName, new CookieController());
+        }
+    }
+
+    /**
+     * <code>setTestName</code> sets the current test name.
+     * 
+     * @param tn
+     *            current testname.
+     */
+    public void setTestName(String tn) {
+        testName = tn;
+    }
+
+    /**
+     * <code>setAssertion</code> sets the assertion text for the current test.
+     * 
+     * @param assertion
+     *            assertion text
+     */
+    public void setAssertion(String assertion) {
+        this.assertion = assertion;
+    }
+
+    /**
+     * <code>setTestStrategy</code> sets the test strategy for the current test.
+     * 
+     * @param strategy
+     *            test strategy text
+     */
+    public void setTestStrategy(String strategy) {
+        testStrategy = strategy;
+    }
+
+    /**
+     * <code>getTestName</code> returns the current test name.
+     * 
+     * @return a <code>String</code> value
+     */
+    public String getTestName() {
+        return testName;
+    }
+
+    /**
+     * <code>getAssertion</code> returns the current assertion text.
+     * 
+     * @return a <code>String</code> value
+     */
+    public String getAssertion() {
+        return assertion;
+    }
+
+    /**
+     * <code>getTestStrategy</code> returns the current test strategy test.
+     * 
+     * @return a <code>String</code> value
+     */
+    public String getTestStrategy() {
+        return testStrategy;
+    }
+
+    /**
+     * <code>setFirstTask</code> denotes that current task being executed is the
+     * first task within the list.
+     * 
+     * @param a
+     *            <code>boolean</code> value
+     */
+    public void setFirstTask(boolean val) {
+        firstTask = val;
+    }
+
+    /**
+     * <code>setLastTask</code> denotes that the current task being executed is
+     * the last task within the list.
+     * 
+     * @param a
+     *            <code>boolean</code> value
+     */
+    public void setLastTask(boolean val) {
+        lastTask = val;
+    }
+
+    /**
+     * <code>setPrefix</code> sets the protocol prefix. Defaults to "http"
+     * 
+     * @param prefix
+     *            Either http or https
+     */
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+    }
+
+    /**
+     * <code>setHost</code> sets hostname where the target server is running.
+     * Defaults to "localhost"
+     * 
+     * @param h
+     *            a <code>String</code> value
+     */
+    public void setHost(String h) {
+        this.host = h;
+    }
+
+    /**
+     * <code>setPort</code> sets the port that the target server is listening
+     * on. Defaults to "8080"
+     * 
+     * @param portS
+     *            a <code>String</code> value
+     */
+    public void setPort(String portS) {
+        this.port = Integer.valueOf(portS).intValue();
+    }
+
+    /**
+     * <code>setExactMatch</code> determines if a byte-by-byte comparsion is
+     * made of the server's response and the test's goldenFile, or if a token
+     * comparison is made. By default, only a token comparison is made
+     * ("false").
+     * 
+     * @param exact
+     *            a <code>String</code> value
+     */
+    public void setExactMatch(String exact) {
+        exactMatch = Boolean.valueOf(exact).booleanValue();
+    }
+
+    /**
+     * <code>setContent</code> String value upon which the request header
+     * Content-Length is based upon.
+     * 
+     * @param s
+     *            a <code>String</code> value
+     */
+    public void setContent(String s) {
+        this.content = s;
+    }
+
+    /**
+     * <code>setDebug</code> enables debug output. By default, this is disabled
+     * ( value of "0" ).
+     * 
+     * @param debugS
+     *            a <code>String</code> value
+     */
+    public void setDebug(String debugS) {
+        debug = Integer.valueOf(debugS).intValue();
+    }
+
+    /**
+     * <code>setMagnitude</code> Expected return value of the test execution.
+     * Defaults to "true"
+     * 
+     * @param magnitudeS
+     *            a <code>String</code> value
+     */
+    public void setMagnitude(String magnitudeS) {
+        magnitude = Boolean.valueOf(magnitudeS).booleanValue();
+    }
+
+    /**
+     * <code>setGoldenFile</code> Sets the goldenfile that will be used to
+     * validate the server's response.
+     * 
+     * @param s
+     *            fully qualified path and filename
+     */
+    public void setGoldenFile(String s) {
+        this.goldenFile = s;
+    }
+
+    /**
+     * <code>setExpectResponseBody</code> sets a flag to indicate if a response
+     * body is expected from the server or not
+     * 
+     * @param b
+     *            a <code>boolean</code> value
+     */
+    public void setExpectResponseBody(boolean b) {
+        this.expectResponseBody = b;
+    }
+
+    /**
+     * <code>setExpectHeaders</code> Configures GTest to look for the header
+     * passed in the server's response.
+     * 
+     * @param s
+     *            a <code>String</code> value in the format of
+     *            <header-field>:<header-value>
+     */
+    public void setExpectHeaders(String s) {
+        this.expectHeaders = new HashMap();
+        StringTokenizer tok = new StringTokenizer(s, "|");
+        while (tok.hasMoreElements()) {
+            String header = (String) tok.nextElement();
+            setHeaderDetails(header, expectHeaders, false);
+        }
+    }
+
+    /**
+     * <code>setUnexpectedHeaders</code> Configures GTest to look for the header
+     * passed to validate that it doesn't exist in the server's response.
+     * 
+     * @param s
+     *            a <code>String</code> value in the format of
+     *            <header-field>:<header-value>
+     */
+    public void setUnexpectedHeaders(String s) {
+        this.unexpectedHeaders = new HashMap();
+        setHeaderDetails(s, unexpectedHeaders, false);
+    }
+
+    public void setNested(String s) {
+        nested = Boolean.valueOf(s).booleanValue();
+    }
+
+    /**
+     * <code>setResponseMatch</code> Match the passed value in the server's
+     * response.
+     * 
+     * @param s
+     *            a <code>String</code> value
+     */
+    public void setResponseMatch(String s) {
+        this.responseMatch = s;
+    }
+
+    /**
+     * <code>setRequest</code> Sets the HTTP/HTTPS request to be sent to the
+     * target server Ex. GET /servlet_path/val HTTP/1.0
+     * 
+     * @param s
+     *            a <code>String</code> value in the form of METHOD PATH
+     *            HTTP_VERSION
+     */
+    public void setRequest(String s) {
+        this.request = s;
+    }
+
+    /**
+     * <code>setReturnCode</code> Sets the expected return code from the
+     * server's response.
+     * 
+     * @param code
+     *            a valid HTTP response status code
+     */
+    public void setReturnCode(String code) {
+        this.returnCode = code;
+    }
+
+    /**
+     * Describe <code>setReturnCodeMsg</code> Sets the expected return message
+     * to be found in the server's response.
+     * 
+     * @param code
+     *            a valid HTTP resonse status code
+     * @param message
+     *            a <code>String</code> value
+     */
+    public void setReturnCodeMsg(String message) {
+        this.returnCodeMsg = message;
+    }
+
+    /**
+     * <code>setRequestHeaders</code> Configures the request headers GTest
+     * should send to the target server.
+     * 
+     * @param s
+     *            a <code>String</code> value in for format of
+     *            <field-name>:<field-value>
+     */
+    public void setRequestHeaders(String s) {
+        requestHeaders = new HashMap();
+        StringTokenizer tok = new StringTokenizer(s, "|");
+        while (tok.hasMoreElements()) {
+            String header = (String) tok.nextElement();
+            setHeaderDetails(header, requestHeaders, true);
+        }
+    }
+
+    // Inner tests are not used currently, can be reworked
+
+    // /**
+    // * Add a Task to this container
+    // *
+    // * @param Task to add
+    // */
+    // public void addTask(Task task) {
+    // children.add(task);
+    // }
+
+    /**
+     * <code>execute</code> Executes the test.
+     * 
+     * @exception BuildException
+     *                if an error occurs
+     */
+    public void execute() {
+
+        try {
+
+            if (resultOut != null && !nested) {
+                resultOut.append("\ntestName: " + testName);
+                resultOut.append("\nreq: " + request);
+                resultOut.append("\nassertion: " + assertion);
+                resultOut.append("\ntestStrategy: " + testStrategy);
+            }
+
+            WatchdogHttpClient.dispatch(this);
+
+            hasFailed = !checkResponse(magnitude);
+
+            // if ( !children.isEmpty() ) {
+            // Iterator iter = children.iterator();
+            // while (iter.hasNext()) {
+            // Task task = (Task) iter.next();
+            // task.perform();
+            // }
+            // }
+
+            if (!hasFailed && !nested) {
+                passCount++;
+                if (resultOut != null) {
+                    resultOut.append("<result>PASS</result>\n");
+                }
+//                System.out.println(" PASSED " + testName + "        ("
+//                        + request + ")");
+            } else if (hasFailed && !nested) {
+                failureCount++;
+                if (resultOut != null) {
+                    resultOut.append("<result>FAIL</result>\n");
+                }
+                System.out.println(" FAILED " + testName + "\n        ("
+                        + request + ")\n" + resultOut.toString());
+            }
+
+        } catch (Exception ex) {
+            failureCount++;
+            System.out.println(" FAIL " + description + " (" + request + ")");
+            lastError = ex;
+            ex.printStackTrace();
+        } finally {
+            if (!nested) {
+                hasFailed = false;
+            }
+        }
+    }
+
+    /**
+     * <code>checkResponse</code> Executes various response checking mechanisms
+     * against the server's response. Checks include:
+     * <ul>
+     * <li>expected headers
+     * <li>unexpected headers
+     * <li>return codes and messages in the Status-Line
+     * <li>response body comparison againt a goldenfile
+     * </ul>
+     * 
+     * @param testCondition
+     *            a <code>boolean</code> value
+     * @return a <code>boolean</code> value
+     * @exception Exception
+     *                if an error occurs
+     */
+    private boolean checkResponse(boolean testCondition) throws Exception {
+        boolean match = false;
+
+        if (responseLine != null) {
+            // If returnCode doesn't match
+            if (responseLine.indexOf("HTTP/1.") > -1) {
+
+                if (!returnCode.equals("")) {
+                    boolean resCode = (responseLine.indexOf(returnCode) > -1);
+                    boolean resMsg = (responseLine.indexOf(returnCodeMsg) > -1);
+
+                    if (returnCodeMsg.equals("")) {
+                        match = resCode;
+                    } else {
+                        match = (resCode && resMsg);
+                    }
+
+                    if (match != testCondition) {
+
+                        if (resultOut != null) {
+                            String expectedStatusCode = "<expectedStatusCode>"
+                                    + returnCode + "</expectedReturnCode>\n";
+                            String expectedReasonPhrase = "<expectedReasonPhrase>"
+                                    + returnCodeMsg + "</expectedReasonPhrase>";
+                            actualString = "<actualStatusLine>" + responseLine
+                                    + "</actualStatusLine>\n";
+                            resultOut.append(expectedStatusCode);
+                            resultOut.append(expectedReasonPhrase);
+                            resultOut.append(actualString);
+                        }
+
+                        return false;
+                    }
+                }
+            } else {
+                resultOut.append("\n<failure>Wrong Http version: "
+                        + responseLine + "</failure>");
+                return false;
+            }
+        } else {
+            resultOut.append("\n<failure>No response from server</failure>");
+            return false;
+        }
+
+        /*
+         * Check for headers the test expects to be in the server's response
+         */
+
+        // Duplicate set of response headers
+        HashMap copiedHeaders = cloneHeaders(headers);
+
+        // used for error reporting
+        String currentHeaderField = null;
+        String currentHeaderValue = null;
+
+        if (!expectHeaders.isEmpty()) {
+            boolean found = false;
+            String expHeader = null;
+
+            if (!headers.isEmpty()) {
+                Iterator expectIterator = expectHeaders.keySet().iterator();
+                while (expectIterator.hasNext()) {
+                    found = false;
+                    String expFieldName = (String) expectIterator.next();
+                    currentHeaderField = expFieldName;
+                    ArrayList expectValues = (ArrayList) expectHeaders
+                            .get(expFieldName);
+                    Iterator headersIterator = copiedHeaders.keySet()
+                            .iterator();
+
+                    while (headersIterator.hasNext()) {
+                        String headerFieldName = (String) headersIterator
+                                .next();
+                        ArrayList headerValues = (ArrayList) copiedHeaders
+                                .get(headerFieldName);
+
+                        // compare field names and values in an HTTP 1.x
+                        // compliant fashion
+                        if ((headerFieldName.equalsIgnoreCase(expFieldName))) {
+                            int hSize = headerValues.size();
+                            int eSize = expectValues.size();
+
+                            // number of expected headers found in server
+                            // response
+                            int numberFound = 0;
+
+                            for (int i = 0; i < eSize; i++) {
+                                currentHeaderValue = (String) expectValues
+                                        .get(i);
+
+                                /*
+                                 * Handle the Content-Type header appropriately
+                                 * based on the the test is configured to look
+                                 * for.
+                                 */
+                                if (currentHeaderField
+                                        .equalsIgnoreCase("content-type")) {
+                                    String resVal = (String) headerValues
+                                            .get(0);
+                                    if (currentHeaderValue.indexOf(';') > -1) {
+                                        if (currentHeaderValue.equals(resVal)) {
+                                            numberFound++;
+                                            headerValues.remove(0);
+                                        }
+                                    } else if (resVal
+                                            .indexOf(currentHeaderValue) > -1) {
+                                        numberFound++;
+                                        headerValues.remove(0);
+                                    }
+                                } else if (currentHeaderField
+                                        .equalsIgnoreCase("location")) {
+                                    String resVal = (String) headerValues
+                                            .get(0);
+                                    int idx = currentHeaderValue
+                                            .indexOf(":80/");
+                                    if (idx > -1) {
+                                        String tempValue = currentHeaderValue
+                                                .substring(0, idx)
+                                                + currentHeaderValue
+                                                        .substring(idx + 3);
+                                        if (currentHeaderValue.equals(resVal)
+                                                || tempValue.equals(resVal)) {
+                                            numberFound++;
+                                            headerValues.remove(0);
+                                        }
+                                    } else {
+                                        if (currentHeaderValue.equals(resVal)) {
+                                            numberFound++;
+                                            headerValues.remove(0);
+                                        }
+                                    }
+                                } else if (headerValues
+                                        .contains(currentHeaderValue)) {
+                                    numberFound++;
+                                    headerValues.remove(headerValues
+                                            .indexOf(currentHeaderValue));
+                                }
+                            }
+                            if (numberFound == eSize) {
+                                found = true;
+                            }
+                        }
+                    }
+                    if (!found) {
+                        /*
+                         * Expected headers not found in server response. Break
+                         * the processing loop.
+                         */
+                        break;
+                    }
+                }
+            }
+
+            if (!found) {
+                StringBuffer actualBuffer = new StringBuffer(128);
+                if (resultOut != null) {
+                    expectedString = "<expectedHeaderNotFound>"
+                            + currentHeaderField + ": " + currentHeaderValue
+                            + "</expectedHeader>\n";
+                }
+                if (!headers.isEmpty()) {
+                    Iterator iter = headers.keySet().iterator();
+                    while (iter.hasNext()) {
+                        String headerName = (String) iter.next();
+                        ArrayList vals = (ArrayList) headers.get(headerName);
+                        String[] val = (String[]) vals.toArray(new String[vals
+                                .size()]);
+                        for (int i = 0; i < val.length; i++) {
+                            if (resultOut != null) {
+                                actualBuffer.append("<actualHeader>"
+                                        + headerName + ": " + val[i]
+                                        + "</actualHeader>\n");
+                            }
+                        }
+                    }
+                    if (resultOut != null) {
+                        resultOut.append(expectedString);
+                        resultOut.append(actualBuffer.toString());
+                    }
+                }
+                return false;
+            }
+        }
+
+        /*
+         * Check to see if we're looking for unexpected headers. If we are,
+         * compare the values in the unexectedHeaders ArrayList against the
+         * headers from the server response. if the unexpected header is found,
+         * then return false.
+         */
+
+        if (!unexpectedHeaders.isEmpty()) {
+            boolean found = false;
+            String unExpHeader = null;
+            // Check if we got any unexpected headers
+
+            if (!copiedHeaders.isEmpty()) {
+                Iterator unexpectedIterator = unexpectedHeaders.keySet()
+                        .iterator();
+                while (unexpectedIterator.hasNext()) {
+                    found = false;
+                    String unexpectedFieldName = (String) unexpectedIterator
+                            .next();
+                    ArrayList unexpectedValues = (ArrayList) unexpectedHeaders
+                            .get(unexpectedFieldName);
+                    Iterator headersIterator = copiedHeaders.keySet()
+                            .iterator();
+
+                    while (headersIterator.hasNext()) {
+                        String headerFieldName = (String) headersIterator
+                                .next();
+                        ArrayList headerValues = (ArrayList) copiedHeaders
+                                .get(headerFieldName);
+
+                        // compare field names and values in an HTTP 1.x
+                        // compliant fashion
+                        if ((headerFieldName
+                                .equalsIgnoreCase(unexpectedFieldName))) {
+                            int hSize = headerValues.size();
+                            int eSize = unexpectedValues.size();
+                            int numberFound = 0;
+                            for (int i = 0; i < eSize; i++) {
+                                if (headerValues.contains(unexpectedValues
+                                        .get(i))) {
+                                    numberFound++;
+                                    if (headerValues.indexOf(headerFieldName) >= 0) {
+                                        headerValues.remove(headerValues
+                                                .indexOf(headerFieldName));
+                                    }
+                                }
+                            }
+                            if (numberFound == eSize) {
+                                found = true;
+                            }
+                        }
+                    }
+                    if (!found) {
+                        /*
+                         * Expected headers not found in server response. Break
+                         * the processing loop.
+                         */
+                        break;
+                    }
+                }
+            }
+
+            if (found) {
+                resultOut.append("\n Unexpected header received from server: "
+                        + unExpHeader);
+                return false;
+            }
+        }
+
+        if (responseMatch != null) {
+            // check if we got the string we wanted
+            if (expectResponseBody && responseBody == null) {
+                resultOut.append("\n ERROR: got no response, expecting "
+                        + responseMatch);
+                return false;
+            }
+            String responseBodyString = new String(responseBody);
+            if (responseBodyString.indexOf(responseMatch) < 0) {
+                resultOut.append("\n ERROR: expecting match on "
+                        + responseMatch);
+                resultOut.append("\n Received: \n" + responseBodyString);
+            }
+        }
+
+        if (!expectResponseBody && responseBody != null) {
+            resultOut
+                    .append("Received a response body from the server where none was expected");
+            return false;
+        }
+
+        // compare the body
+        if (goldenFile == null)
+            return true;
+
+        // Get the expected result from the "golden" file.
+        byte[] expResult = getExpectedResult();
+        String expResultS = (expResult == null) ? "" : new String(expResult);
+        // Compare the results and set the status
+        boolean cmp = true;
+
+        if (exactMatch) {
+            cmp = compare(responseBody, expResult);
+        } else {
+            cmp = compareWeak(responseBody, expResult);
+        }
+
+        if (cmp != testCondition) {
+
+            if (resultOut != null) {
+                expectedString = "<expectedBody>" + new String(expResult)
+                        + "</expectedBody>\n";
+                actualString = "<actualBody>"
+                        + (responseBody != null ? new String(responseBody)
+                                : "null") + "</actualBody>\n";
+                resultOut.append(expectedString);
+                resultOut.append(actualString);
+            }
+
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Replaces any |client.ip| and |client.host| parameter marks with the host
+     * and IP values of the host upon which Watchdog is running.
+     * 
+     * @param request
+     *            An HTTP request.
+     */
+    String replaceMarkers(String req, Socket socket) {
+
+        final String CLIENT_IP = "client.ip";
+        final String CLIENT_HOME = "client.host";
+
+        if (localIP == null || localHost == null) {
+            InetAddress addr = socket.getLocalAddress();
+            localHost = addr.getHostName();
+            localIP = addr.getHostAddress();
+        }
+
+        if (req.indexOf('|') > -1) {
+            StringTokenizer tok = new StringTokenizer(request, "|");
+            StringBuffer sb = new StringBuffer(50);
+
+            while (tok.hasMoreElements()) {
+                String token = tok.nextToken();
+                if (token.equals(CLIENT_IP)) {
+                    sb.append(localIP);
+                } else if (token.equals(CLIENT_HOME)) {
+                    sb.append(localHost);
+                } else {
+                    sb.append(token);
+                }
+            }
+            return sb.toString();
+        } else {
+            return req;
+        }
+    }
+
+    /**
+     * <code>getExpectedResult</code> returns a byte array containing the
+     * content of the configured goldenfile
+     * 
+     * @return goldenfile as a byte[]
+     * @exception IOException
+     *                if an error occurs
+     */
+    private byte[] getExpectedResult() throws IOException {
+        byte[] expResult = { 'N', 'O', ' ', 'G', 'O', 'L', 'D', 'E', 'N', 'F',
+                'I', 'L', 'E', ' ', 'F', 'O', 'U', 'N', 'D' };
+
+        try {
+            InputStream in = new BufferedInputStream(new FileInputStream(
+                    goldenFile));
+            return readBody(in);
+        } catch (Exception ex) {
+            System.out.println("Golden file not found: " + goldenFile);
+            return expResult;
+        }
+    }
+
+    /**
+     * <code>compare</code> compares the two byte arrays passed in to verify
+     * that the lengths of the arrays are equal, and that the content of the two
+     * arrays, byte for byte are equal.
+     * 
+     * @param fromServer
+     *            a <code>byte[]</code> value
+     * @param fromGoldenFile
+     *            a <code>byte[]</code> value
+     * @return <code>boolean</code> true if equal, otherwise false
+     */
+    private boolean compare(byte[] fromServer, byte[] fromGoldenFile) {
+        if (fromServer == null || fromGoldenFile == null) {
+            return false;
+        }
+
+        /*
+         * Check to see that the respose and golden file lengths are equal. If
+         * they are not, dump the hex and don't bother comparing the bytes. If
+         * they are equal, iterate through the byte arrays and compare each
+         * byte. If the bytes don't match, dump the hex representation of the
+         * server response and the goldenfile and return false.
+         */
+        if (fromServer.length != fromGoldenFile.length) {
+            StringBuffer sb = new StringBuffer(50);
+            sb.append(" Response and golden files lengths do not match!\n");
+            sb.append(" Server response length: ");
+            sb.append(fromServer.length);
+            sb.append("\n Goldenfile length: ");
+            sb.append(fromGoldenFile.length);
+            resultOut.append(sb.toString());
+            sb = null;
+            // dump the hex representation of the byte arrays
+            dumpHex(fromServer, fromGoldenFile);
+
+            return false;
+        } else {
+
+            int i = 0;
+            int j = 0;
+
+            while ((i < fromServer.length) && (j < fromGoldenFile.length)) {
+                if (fromServer[i] != fromGoldenFile[j]) {
+                    resultOut.append("\n Error at position " + (i + 1));
+                    // dump the hex representation of the byte arrays
+                    dumpHex(fromServer, fromGoldenFile);
+
+                    return false;
+                }
+
+                i++;
+                j++;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * <code>compareWeak</code> creates new Strings from the passed arrays and
+     * then uses a StringTokenizer to compare non-whitespace tokens.
+     * 
+     * @param fromServer
+     *            a <code>byte[]</code> value
+     * @param fromGoldenFile
+     *            a <code>byte[]</code> value
+     * @return a <code>boolean</code> value
+     */
+    private boolean compareWeak(byte[] fromServer, byte[] fromGoldenFile) {
+        if (fromServer == null || fromGoldenFile == null) {
+            return false;
+        }
+
+        boolean status = true;
+
+        String server = new String(fromServer);
+        String golden = new String(fromGoldenFile);
+
+        StringTokenizer st1 = new StringTokenizer(server);
+
+        StringTokenizer st2 = new StringTokenizer(golden);
+
+        while (st1.hasMoreTokens() && st2.hasMoreTokens()) {
+            String tok1 = st1.nextToken();
+            String tok2 = st2.nextToken();
+
+            if (!tok1.equals(tok2)) {
+                resultOut.append("\t FAIL*** : Rtok1 = " + tok1 + ", Etok2 = "
+                        + tok2);
+                status = false;
+            }
+        }
+
+        if (st1.hasMoreTokens() || st2.hasMoreTokens()) {
+            status = false;
+        }
+
+        if (!status) {
+            StringBuffer sb = new StringBuffer(255);
+            sb
+                    .append("ERROR: Server's response and configured goldenfile do not match!\n");
+            sb.append("Response received from server:\n");
+            sb
+                    .append("---------------------------------------------------------\n");
+            sb.append(server);
+            sb.append("\nContent of Goldenfile:\n");
+            sb
+                    .append("---------------------------------------------------------\n");
+            sb.append(golden);
+            sb.append("\n");
+            resultOut.append(sb.toString());
+        }
+        return status;
+    }
+
+    /**
+     * <code>readBody</code> reads the body of the response from the
+     * InputStream.
+     * 
+     * @param input
+     *            an <code>InputStream</code>
+     * @return a <code>byte[]</code> representation of the response
+     */
+    private byte[] readBody(InputStream input) {
+        StringBuffer sb = new StringBuffer(255);
+        while (true) {
+            try {
+                int ch = input.read();
+
+                if (ch < 0) {
+                    if (sb.length() == 0) {
+                        return (null);
+                    } else {
+                        break;
+                    }
+                }
+                sb.append((char) ch);
+
+            } catch (IOException ex) {
+                return null;
+            }
+        }
+        return sb.toString().getBytes();
+    }
+
+    /**
+     * <code>setHeaderDetails</code> Wrapper method for parseHeader. Allows easy
+     * addition of headers to the specified HashMap
+     * 
+     * @param line
+     *            a <code>String</code> value
+     * @param headerMap
+     *            a <code>HashMap</code> value
+     * @param isRequest
+     *            a <code>boolean</code> indicating if the passed Header HashMap
+     *            is for request headers
+     */
+    void setHeaderDetails(String line, HashMap headerHash, boolean isRequest) {
+        StringTokenizer stk = new StringTokenizer(line, "##");
+
+        while (stk.hasMoreElements()) {
+            String presentHeader = stk.nextToken();
+            parseHeader(presentHeader, headerHash, isRequest);
+        }
+    }
+
+    /**
+     * <code>parseHeader</code> parses input headers in format of "key:value"
+     * The parsed header field-name will be used as a key in the passed HashMap
+     * object, and the values found will be stored in an ArrayList associated
+     * with the field-name key.
+     * 
+     * @param line
+     *            String representation of an HTTP header line.
+     * @param headers
+     *            a<code>HashMap</code> to store key/value header objects.
+     * @param isRequest
+     *            set to true if the headers being processed are requestHeaders.
+     */
+    void parseHeader(String line, HashMap headerMap, boolean isRequest) {
+        // Parse the header name and value
+        int colon = line.indexOf(":");
+
+        if (colon < 0) {
+            resultOut
+                    .append("\n ERROR: Header is in incorrect format: " + line);
+            return;
+        }
+
+        String name = line.substring(0, colon).trim();
+        String value = line.substring(colon + 1).trim();
+
+        if ((cookieVector != null) && (name.equalsIgnoreCase("Set-Cookie"))) {
+            cookieVector.addElement(value);
+            /*
+             * if ( ( value.indexOf("JSESSIONID") > -1 ) ||
+             * (value.indexOf("jsessionid") > -1 ) ) { String sessionId=
+             * value.substring( value.indexOf("=")+1); if ( testSession != null
+             * ) { sessionHash.put( testSession, sessionId ); }
+             * System.out.println("Got Session-ID : " + sessionId ); }
+             */
+        }
+
+        // System.out.println("HEADER: " +name + " " + value);
+
+        ArrayList values = (ArrayList) headerMap.get(name);
+        if (values == null) {
+            values = new ArrayList();
+        }
+        // HACK
+        if (value.indexOf(',') > -1 && !isRequest
+                && !name.equalsIgnoreCase("Date")) {
+            StringTokenizer st = new StringTokenizer(value, ",");
+            while (st.hasMoreElements()) {
+                values.add(st.nextToken());
+            }
+        } else {
+            values.add(value);
+        }
+
+        headerMap.put(name, values);
+    }
+
+    /**
+     * <code>dumpHex</code> helper method to dump formatted hex output of the
+     * server response and the goldenfile.
+     * 
+     * @param serverResponse
+     *            a <code>byte[]</code> value
+     * @param goldenFile
+     *            a <code>byte[]</code> value
+     */
+    private void dumpHex(byte[] serverResponse, byte[] goldenFile) {
+        StringBuffer outBuf = new StringBuffer(
+                (serverResponse.length + goldenFile.length) * 2);
+
+        String fromServerString = Hex.getHexDump(serverResponse, 0,
+                serverResponse.length, true);
+        String fromGoldenFileString = Hex.getHexDump(goldenFile, 0,
+                goldenFile.length, true);
+
+        outBuf
+                .append(" Hex dump of server response and goldenfile below.\n\n### RESPONSE FROM SERVER ###\n");
+        outBuf.append("----------------------------\n");
+        outBuf.append(fromServerString);
+        outBuf.append("\n\n### GOLDEN FILE ###\n");
+        outBuf.append("-------------------\n");
+        outBuf.append(fromGoldenFileString);
+        outBuf.append("\n\n### END OF DUMP ###\n");
+
+        resultOut.append(outBuf.toString());
+
+    }
+
+    /**
+     * <code>cloneHeaders</code> returns a "cloned" HashMap of the map passed
+     * in.
+     * 
+     * @param map
+     *            a <code>HashMap</code> value
+     * @return a <code>HashMap</code> value
+     */
+    private HashMap cloneHeaders(HashMap map) {
+        HashMap dupMap = new HashMap();
+        Iterator iter = map.keySet().iterator();
+
+        while (iter.hasNext()) {
+            String key = new String((String) iter.next());
+            ArrayList origValues = (ArrayList) map.get(key);
+            ArrayList dupValues = new ArrayList();
+
+            String[] dupVal = (String[]) origValues
+                    .toArray(new String[origValues.size()]);
+            for (int i = 0; i < dupVal.length; i++) {
+                dupValues.add(new String(dupVal[i]));
+            }
+
+            dupMap.put(key, dupValues);
+        }
+        return dupMap;
+    }
+
+}