Added: 
tomcat/trunk/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java?rev=884421&view=auto
==============================================================================
--- 
tomcat/trunk/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java
 (added)
+++ 
tomcat/trunk/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java
 Thu Nov 26 06:55:49 2009
@@ -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;
+    }
+
+}

Propchange: 
tomcat/trunk/modules/tomcat-lite/test/org/apache/tomcat/test/watchdog/WatchdogTestImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to