| /* |
| * Copyright 1999, 2000 ,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.tester; |
| |
| |
| import java.io.FileNotFoundException; |
| import java.io.InputStream; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| import java.net.ConnectException; |
| import java.net.HttpURLConnection; |
| import java.net.Socket; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.Task; |
| |
| |
| /** |
| * <p>This class contains a <strong>Task</strong> for Ant that is used to |
| * send HTTP requests to a servlet container, and examine the responses. |
| * It is similar in purpose to the <code>GTest</code> task in Watchdog, |
| * but uses the JDK's HttpURLConnection for underlying connectivity.</p> |
| * |
| * <p>The task is registered with Ant using a <code>taskdef</code> directive: |
| * <pre> |
| * <taskdef name="tester" classname="org.apache.tester.TestClient"> |
| * </pre> |
| * and accepts the following configuration properties:</p> |
| * <ul> |
| * <li><strong>golden</strong> - The server-relative path of the static |
| * resource containing the golden file for this request.</li> |
| * <li><strong>host</strong> - The server name to which this request will be |
| * sent. Defaults to <code>localhost</code> if not specified.</li> |
| * <li><strong>inContent</strong> - The data content that will be submitted |
| * with this request. The test client will transparently add a carriage |
| * return and line feed, and set the content length header, if this is |
| * specified. Otherwise, no content will be included in the request.</li> |
| * <li><strong>inHeaders</strong> - The set of one or more HTTP headers that |
| * will be included on the request.</li> |
| * <li><strong>message</strong> - The HTTP response message that is expected |
| * in the response from the server. No check is made if no message |
| * is specified.</li> |
| * <li><strong>method</strong> - The HTTP request method to be used on this |
| * request. Defaults to <ocde>GET</code> if not specified.</li> |
| * <li><strong>outContent</strong> - The first line of the response data |
| * content that we expect to receive. No check is made if no content is |
| * specified.</li> |
| * <li><strong>outHeaders</strong> - The set of one or more HTTP headers that |
| * are expected in the response (order independent).</li> |
| * <li><strong>port</strong> - The port number to which this request will be |
| * sent. Defaults to <code>8080</code> if not specified.</li> |
| * <li><strong>redirect</strong> - If set to true, follow any redirect that |
| * is returned by the server. (Only works when using HttpURLConnection). |
| * </li> |
| * <li><strong>request</strong> - The request URI to be transmitted for this |
| * request. This value should start with a slash character ("/"), and |
| * be the server-relative URI of the requested resource.</li> |
| * <li><strong>status</strong> - The HTTP status code that is expected in the |
| * response from the server. Defaults to <code>200</code> if not |
| * specified. Set to zero to disable checking the return value.</li> |
| * </ul> |
| * |
| * @author Craig R. McClanahan |
| * @version $Revision$ $Date$ |
| */ |
| |
| public class TestClient extends Task { |
| |
| |
| // ----------------------------------------------------- Instance Variables |
| |
| |
| /** |
| * The saved golden file we will compare to the response. Each element |
| * contains a line of text without any line delimiters. |
| */ |
| protected ArrayList saveGolden = new ArrayList(); |
| |
| |
| /** |
| * The saved headers we received in our response. The key is the header |
| * name (converted to lower case), and the value is an ArrayList of the |
| * string value(s) received for that header. |
| */ |
| protected HashMap saveHeaders = new HashMap(); |
| |
| |
| /** |
| * The response file to be compared to the golden file. Each element |
| * contains a line of text without any line delimiters. |
| */ |
| protected ArrayList saveResponse = new ArrayList(); |
| |
| |
| // ------------------------------------------------------------- Properties |
| |
| |
| /** |
| * The debugging detail level for this execution. |
| */ |
| protected int debug = 0; |
| |
| public int getDebug() { |
| return (this.debug); |
| } |
| |
| public void setDebug(int debug) { |
| this.debug = debug; |
| } |
| |
| |
| /** |
| * The server-relative request URI of the golden file for this request. |
| */ |
| protected String golden = null; |
| |
| public String getGolden() { |
| return (this.golden); |
| } |
| |
| public void setGolden(String golden) { |
| this.golden = golden; |
| } |
| |
| |
| /** |
| * The host name to which we will connect. |
| */ |
| protected String host = "localhost"; |
| |
| public String getHost() { |
| return (this.host); |
| } |
| |
| public void setHost(String host) { |
| this.host = host; |
| } |
| |
| |
| /** |
| * The first line of the request data that will be included on this |
| * request. |
| */ |
| protected String inContent = null; |
| |
| public String getInContent() { |
| return (this.inContent); |
| } |
| |
| public void setInContent(String inContent) { |
| this.inContent = inContent; |
| } |
| |
| |
| /** |
| * The HTTP headers to be included on the request. Syntax is |
| * <code>{name}:{value}[##{name}:{value}] ...</code>. |
| */ |
| protected String inHeaders = null; |
| |
| public String getInHeaders() { |
| return (this.inHeaders); |
| } |
| |
| public void setInHeaders(String inHeaders) { |
| this.inHeaders = inHeaders; |
| } |
| |
| |
| /** |
| * Should we join the session whose session identifier was returned |
| * on the previous request. |
| */ |
| protected boolean joinSession = false; |
| |
| public boolean getJoinSession() { |
| return (this.joinSession); |
| } |
| |
| public void setJoinSession(boolean joinSession) { |
| this.joinSession = true; |
| } |
| |
| |
| /** |
| * The HTTP response message to be expected in the response. |
| */ |
| protected String message = null; |
| |
| public String getMessage() { |
| return (this.message); |
| } |
| |
| public void setMessage(String message) { |
| this.message = message; |
| } |
| |
| |
| /** |
| * The HTTP request method that will be used. |
| */ |
| protected String method = "GET"; |
| |
| public String getMethod() { |
| return (this.method); |
| } |
| |
| public void setMethod(String method) { |
| this.method = method; |
| } |
| |
| |
| /** |
| * The first line of the response data content that we expect to receive. |
| */ |
| protected String outContent = null; |
| |
| public String getOutContent() { |
| return (this.outContent); |
| } |
| |
| public void setOutContent(String outContent) { |
| this.outContent = outContent; |
| } |
| |
| |
| /** |
| * The HTTP headers to be checked on the response. Syntax is |
| * <code>{name}:{value}[##{name}:{value}] ...</code>. |
| */ |
| protected String outHeaders = null; |
| |
| public String getOutHeaders() { |
| return (this.outHeaders); |
| } |
| |
| public void setOutHeaders(String outHeaders) { |
| this.outHeaders = outHeaders; |
| } |
| |
| |
| /** |
| * The port number to which we will connect. |
| */ |
| protected int port = 8080; |
| |
| public int getPort() { |
| return (this.port); |
| } |
| |
| public void setPort(int port) { |
| this.port = port; |
| } |
| |
| |
| /** |
| * The protocol and version to include in the request, if executed as |
| * a direct socket connection. Lack of a value here indicates that an |
| * HttpURLConnection should be used instead. |
| */ |
| protected String protocol = null; |
| |
| public String getProtocol() { |
| return (this.protocol); |
| } |
| |
| public void setProtocol(String protocol) { |
| this.protocol = protocol; |
| } |
| |
| |
| /** |
| * Should we follow redirects returned by the server? |
| */ |
| protected boolean redirect = false; |
| |
| public boolean getRedirect() { |
| return (this.redirect); |
| } |
| |
| public void setRedirect(boolean redirect) { |
| this.redirect = redirect; |
| } |
| |
| |
| /** |
| * The request URI to be sent to the server. This value is required. |
| */ |
| protected String request = null; |
| |
| public String getRequest() { |
| return (this.request); |
| } |
| |
| public void setRequest(String request) { |
| this.request = request; |
| } |
| |
| |
| /** |
| * The HTTP status code expected on the response. |
| */ |
| protected int status = 200; |
| |
| public int getStatus() { |
| return (this.status); |
| } |
| |
| public void setStatus(int status) { |
| this.status = status; |
| } |
| |
| |
| // ------------------------------------------------------- Static Variables |
| |
| |
| /** |
| * The session identifier returned by the most recent request, or |
| * <code>null</code> if the previous request did not specify a session |
| * identifier. |
| */ |
| protected static String sessionId = null; |
| |
| |
| // --------------------------------------------------------- Public Methods |
| |
| |
| /** |
| * Execute the test that has been configured by our property settings. |
| * |
| * @exception BuildException if an exception occurs |
| */ |
| public void execute() throws BuildException { |
| |
| saveHeaders.clear(); |
| try { |
| readGolden(); |
| } catch (IOException e) { |
| log("FAIL: readGolden(" + golden + ")"); |
| e.printStackTrace(System.out); |
| } |
| if ((protocol == null) || (protocol.length() == 0)) |
| executeHttp(); |
| else |
| executeSocket(); |
| |
| } |
| |
| |
| // ------------------------------------------------------ Protected Methods |
| |
| |
| /** |
| * Execute the test via use of an HttpURLConnection. |
| * |
| * @exception BuildException if an exception occurs |
| */ |
| protected void executeHttp() throws BuildException { |
| |
| // Construct a summary of the request we will be sending |
| String summary = "[" + method + " " + request + "]"; |
| if (debug >= 1) |
| log("RQST: " + summary); |
| boolean success = true; |
| String result = null; |
| Throwable throwable = null; |
| HttpURLConnection conn = null; |
| |
| try { |
| |
| // Configure an HttpURLConnection for this request |
| URL url = new URL("http", host, port, request); |
| conn = (HttpURLConnection) url.openConnection(); |
| conn.setAllowUserInteraction(false); |
| conn.setDoInput(true); |
| if (inContent != null) { |
| conn.setDoOutput(true); |
| conn.setRequestProperty("Content-Length", |
| "" + inContent.length()); |
| if (debug >= 1) |
| log("INPH: Content-Length: " + |
| inContent.length()); |
| } else { |
| conn.setDoOutput(false); |
| } |
| |
| // Send the session id cookie (if any) |
| if (joinSession && (sessionId != null)) { |
| conn.setRequestProperty("Cookie", |
| "JSESSIONID=" + sessionId); |
| if (debug >= 1) |
| log("INPH: Cookie: JSESSIONID=" + |
| sessionId); |
| } |
| |
| if (this.redirect && (debug >= 1)) |
| log("FLAG: setInstanceFollowRedirects(" + |
| this.redirect + ")"); |
| conn.setInstanceFollowRedirects(this.redirect); |
| conn.setRequestMethod(method); |
| if (inHeaders != null) { |
| String headers = inHeaders; |
| while (headers.length() > 0) { |
| int delimiter = headers.indexOf("##"); |
| String header = null; |
| if (delimiter < 0) { |
| header = headers; |
| headers = ""; |
| } else { |
| header = headers.substring(0, delimiter); |
| headers = headers.substring(delimiter + 2); |
| } |
| int colon = header.indexOf(":"); |
| if (colon < 0) |
| break; |
| String name = header.substring(0, colon).trim(); |
| String value = header.substring(colon + 1).trim(); |
| conn.setRequestProperty(name, value); |
| if (debug >= 1) |
| log("INPH: " + name + ": " + value); |
| } |
| } |
| |
| // Connect to the server and send our output if necessary |
| conn.connect(); |
| if (inContent != null) { |
| if (debug >= 1) |
| log("INPD: " + inContent); |
| OutputStream os = conn.getOutputStream(); |
| for (int i = 0; i < inContent.length(); i++) |
| os.write(inContent.charAt(i)); |
| os.close(); |
| } |
| |
| // Acquire the response data, if there is any |
| String outData = ""; |
| String outText = ""; |
| boolean eol = false; |
| InputStream is = conn.getInputStream(); |
| int lines = 0; |
| while (true) { |
| String line = read(is); |
| if (line == null) |
| break; |
| if (lines == 0) |
| outData = line; |
| else |
| outText += line + "\r\n"; |
| saveResponse.add(line); |
| lines++; |
| } |
| is.close(); |
| |
| // Dump out the response stuff |
| if (debug >= 1) |
| log("RESP: " + conn.getResponseCode() + " " + |
| conn.getResponseMessage()); |
| for (int i = 1; i < 1000; i++) { |
| String name = conn.getHeaderFieldKey(i); |
| String value = conn.getHeaderField(i); |
| if ((name == null) || (value == null)) |
| break; |
| if (debug >= 1) |
| log("HEAD: " + name + ": " + value); |
| save(name, value); |
| if ("Set-Cookie".equals(name)) |
| parseSession(value); |
| } |
| if (debug >= 1) { |
| log("DATA: " + outData); |
| if (outText.length() > 2) |
| log("TEXT: " + outText); |
| } |
| |
| // Validate the response against our criteria |
| if (success) { |
| result = validateStatus(conn.getResponseCode()); |
| if (result != null) |
| success = false; |
| } |
| if (success) { |
| result = validateMessage(conn.getResponseMessage()); |
| if (result != null) |
| success = false; |
| } |
| if (success) { |
| result = validateHeaders(); |
| if (result != null) |
| success = false; |
| } |
| if (success) { |
| result = validateData(outData); |
| if (result != null) |
| success = false; |
| } |
| if (success) { |
| result = validateGolden(); |
| if (result != null) |
| success = false; |
| } |
| |
| } catch (Throwable t) { |
| if (t instanceof FileNotFoundException) { |
| if (status == 404) { |
| success = true; |
| result = "Not Found"; |
| throwable = null; |
| } else { |
| success = false; |
| try { |
| result = "Status=" + conn.getResponseCode() + |
| ", Message=" + conn.getResponseMessage(); |
| } catch (IOException e) { |
| result = e.toString(); |
| } |
| throwable = null; |
| } |
| } else if (t instanceof ConnectException) { |
| success = false; |
| result = t.getMessage(); |
| throwable = null; |
| } else { |
| success = false; |
| result = t.getMessage(); |
| throwable = t; |
| } |
| } |
| |
| // Log the results of executing this request |
| if (success) |
| log("OK " + summary); |
| else { |
| log("FAIL " + summary + " " + result); |
| if (throwable != null) |
| throwable.printStackTrace(System.out); |
| } |
| |
| } |
| |
| |
| /** |
| * Execute the test via use of a socket with direct input/output. |
| * |
| * @exception BuildException if an exception occurs |
| */ |
| protected void executeSocket() throws BuildException { |
| |
| // Construct a summary of the request we will be sending |
| String command = method + " " + request + " " + protocol; |
| String summary = "[" + command + "]"; |
| if (debug >= 1) |
| log("RQST: " + summary); |
| boolean success = true; |
| String result = null; |
| Socket socket = null; |
| OutputStream os = null; |
| PrintWriter pw = null; |
| InputStream is = null; |
| Throwable throwable = null; |
| int outStatus = 0; |
| String outMessage = null; |
| |
| try { |
| |
| // Open a client socket for this request |
| socket = new Socket(host, port); |
| os = socket.getOutputStream(); |
| pw = new PrintWriter(os); |
| is = socket.getInputStream(); |
| |
| // Send the command and content length header (if any) |
| pw.print(command + "\r\n"); |
| if (inContent != null) { |
| if (debug >= 1) |
| log("INPH: " + "Content-Length: " + |
| inContent.length()); |
| pw.print("Content-Length: " + inContent.length() + "\r\n"); |
| } |
| |
| // Send the session id cookie (if any) |
| if (joinSession && (sessionId != null)) { |
| pw.println("Cookie: JSESSIONID=" + sessionId); |
| if (debug >= 1) |
| log("INPH: Cookie: JSESSIONID=" + |
| sessionId); |
| } |
| |
| // Send the specified headers (if any) |
| if (inHeaders != null) { |
| String headers = inHeaders; |
| while (headers.length() > 0) { |
| int delimiter = headers.indexOf("##"); |
| String header = null; |
| if (delimiter < 0) { |
| header = headers; |
| headers = ""; |
| } else { |
| header = headers.substring(0, delimiter); |
| headers = headers.substring(delimiter + 2); |
| } |
| int colon = header.indexOf(":"); |
| if (colon < 0) |
| break; |
| String name = header.substring(0, colon).trim(); |
| String value = header.substring(colon + 1).trim(); |
| if (debug >= 1) |
| log("INPH: " + name + ": " + value); |
| pw.print(name + ": " + value + "\r\n"); |
| } |
| } |
| pw.print("\r\n"); |
| |
| // Send our content (if any) |
| if (inContent != null) { |
| if (debug >= 1) |
| log("INPD: " + inContent); |
| for (int i = 0; i < inContent.length(); i++) |
| pw.print(inContent.charAt(i)); |
| } |
| pw.flush(); |
| |
| // Read the response status and associated message |
| String line = read(is); |
| if (line == null) { |
| outStatus = -1; |
| outMessage = "NO RESPONSE"; |
| } else { |
| line = line.trim(); |
| if (debug >= 1) |
| System.out.println("RESP: " + line); |
| int space = line.indexOf(" "); |
| if (space >= 0) { |
| line = line.substring(space + 1).trim(); |
| space = line.indexOf(" "); |
| } |
| try { |
| if (space < 0) { |
| outStatus = Integer.parseInt(line); |
| outMessage = ""; |
| } else { |
| outStatus = Integer.parseInt(line.substring(0, space)); |
| outMessage = line.substring(space + 1).trim(); |
| } |
| } catch (NumberFormatException e) { |
| outStatus = -1; |
| outMessage = "NUMBER FORMAT EXCEPTION"; |
| } |
| } |
| if (debug >= 1) |
| System.out.println("STAT: " + outStatus + " MESG: " + |
| outMessage); |
| |
| // Read the response headers (if any) |
| String headerName = null; |
| String headerValue = null; |
| while (true) { |
| line = read(is); |
| if ((line == null) || (line.length() == 0)) |
| break; |
| int colon = line.indexOf(":"); |
| if (colon < 0) { |
| if (debug >= 1) |
| System.out.println("????: " + line); |
| } else { |
| headerName = line.substring(0, colon).trim(); |
| headerValue = line.substring(colon + 1).trim(); |
| if (debug >= 1) |
| System.out.println("HEAD: " + headerName + ": " + |
| headerValue); |
| save(headerName, headerValue); |
| if ("Set-Cookie".equals(headerName)) |
| parseSession(headerValue); |
| } |
| } |
| |
| // Acquire the response data (if any) |
| String outData = ""; |
| String outText = ""; |
| int lines = 0; |
| while (true) { |
| line = read(is); |
| if (line == null) |
| break; |
| if (lines == 0) |
| outData = line; |
| else |
| outText += line + "\r\n"; |
| saveResponse.add(line); |
| lines++; |
| } |
| is.close(); |
| if (debug >= 1) { |
| System.out.println("DATA: " + outData); |
| if (outText.length() > 2) |
| System.out.println("TEXT: " + outText); |
| } |
| |
| // Validate the response against our criteria |
| if (success) { |
| result = validateStatus(outStatus); |
| if (result != null) |
| success = false; |
| } |
| if (success) { |
| result = validateMessage(message); |
| if (result != null) |
| success = false; |
| } |
| if (success) { |
| result = validateHeaders(); |
| if (result != null) |
| success = false; |
| } |
| if (success) { |
| result = validateData(outData); |
| if (result != null) |
| success = false; |
| } |
| if (success) { |
| result = validateGolden(); |
| if (result != null) |
| success = false; |
| } |
| |
| } catch (Throwable t) { |
| success = false; |
| result = "Status=" + outStatus + |
| ", Message=" + outMessage; |
| throwable = null; |
| } finally { |
| if (pw != null) { |
| try { |
| pw.close(); |
| } catch (Throwable w) { |
| ; |
| } |
| } |
| if (os != null) { |
| try { |
| os.close(); |
| } catch (Throwable w) { |
| ; |
| } |
| } |
| if (is != null) { |
| try { |
| is.close(); |
| } catch (Throwable w) { |
| ; |
| } |
| } |
| if (socket != null) { |
| try { |
| socket.close(); |
| } catch (Throwable w) { |
| ; |
| } |
| } |
| } |
| |
| if (success) |
| System.out.println("OK " + summary); |
| else { |
| System.out.println("FAIL " + summary + " " + result); |
| if (throwable != null) |
| throwable.printStackTrace(System.out); |
| } |
| |
| } |
| |
| |
| /** |
| * Parse the session identifier from the specified Set-Cookie value. |
| * |
| * @param value The Set-Cookie value to parse |
| */ |
| protected void parseSession(String value) { |
| |
| if (value == null) |
| return; |
| int equals = value.indexOf("JSESSIONID="); |
| if (equals < 0) |
| return; |
| value = value.substring(equals + "JSESSIONID=".length()); |
| int semi = value.indexOf(";"); |
| if (semi >= 0) |
| value = value.substring(0, semi); |
| |
| if (debug >= 1) |
| System.out.println("SESSION ID: " + value); |
| sessionId = value; |
| |
| } |
| |
| |
| /** |
| * Read and return the next line from the specified input stream, with |
| * no carriage return or line feed delimiters. If |
| * end of file is reached, return <code>null</code> instead. |
| * |
| * @param stream The input stream to read from |
| * |
| * @exception IOException if an input/output error occurs |
| */ |
| protected String read(InputStream stream) throws IOException { |
| |
| StringBuffer result = new StringBuffer(); |
| while (true) { |
| int b = stream.read(); |
| if (b < 0) { |
| if (result.length() == 0) |
| return (null); |
| else |
| break; |
| } |
| char c = (char) b; |
| if (c == '\r') |
| continue; |
| else if (c == '\n') |
| break; |
| else |
| result.append(c); |
| } |
| return (result.toString()); |
| |
| } |
| |
| |
| /** |
| * Read and save the contents of the golden file for this test, if any. |
| * Otherwise, the <code>saveGolden</code> list will be empty. |
| * |
| * @exception IOException if an input/output error occurs |
| */ |
| protected void readGolden() throws IOException { |
| |
| // Was a golden file specified? |
| saveGolden.clear(); |
| if (golden == null) |
| return; |
| |
| // Create a connection to receive the golden file contents |
| URL url = new URL("http", host, port, golden); |
| HttpURLConnection conn = |
| (HttpURLConnection) url.openConnection(); |
| conn.setAllowUserInteraction(false); |
| conn.setDoInput(true); |
| conn.setDoOutput(false); |
| conn.setFollowRedirects(true); |
| conn.setRequestMethod("GET"); |
| |
| // Connect to the server and retrieve the golden file |
| conn.connect(); |
| InputStream is = conn.getInputStream(); |
| while (true) { |
| String line = read(is); |
| if (line == null) |
| break; |
| saveGolden.add(line); |
| } |
| is.close(); |
| conn.disconnect(); |
| |
| } |
| |
| |
| /** |
| * Save the specified header name and value in our collection. |
| * |
| * @param name Header name to save |
| * @param value Header value to save |
| */ |
| protected void save(String name, String value) { |
| |
| String key = name.toLowerCase(); |
| ArrayList list = (ArrayList) saveHeaders.get(key); |
| if (list == null) { |
| list = new ArrayList(); |
| saveHeaders.put(key, list); |
| } |
| list.add(value); |
| |
| } |
| |
| |
| /** |
| * Validate the output data against what we expected. Return |
| * <code>null</code> for no problems, or an error message. |
| * |
| * @param data The output data to be tested |
| */ |
| protected String validateData(String data) { |
| |
| if (outContent == null) |
| return (null); |
| else if (data.startsWith(outContent)) |
| return (null); |
| else |
| return ("Expected data '" + outContent + "', got data '" + |
| data + "'"); |
| |
| } |
| |
| |
| /** |
| * Validate the response against the golden file (if any). Return |
| * <code>null</code> for no problems, or an error message. |
| */ |
| protected String validateGolden() { |
| |
| if (golden == null) |
| return (null); |
| boolean ok = true; |
| if (saveGolden.size() != saveResponse.size()) |
| ok = false; |
| if (ok) { |
| for (int i = 0; i < saveGolden.size(); i++) { |
| String golden = (String) saveGolden.get(i); |
| String response = (String) saveResponse.get(i); |
| if (!golden.equals(response)) { |
| ok = false; |
| break; |
| } |
| } |
| } |
| if (ok) |
| return (null); |
| System.out.println("EXPECTED: ======================================"); |
| for (int i = 0; i < saveGolden.size(); i++) |
| System.out.println((String) saveGolden.get(i)); |
| System.out.println("================================================"); |
| System.out.println("RECEIVED: ======================================"); |
| for (int i = 0; i < saveResponse.size(); i++) |
| System.out.println((String) saveResponse.get(i)); |
| System.out.println("================================================"); |
| return ("Failed Golden File Comparison"); |
| |
| } |
| |
| |
| /** |
| * Validate the saved headers against the <code>outHeaders</code> |
| * property, and return an error message if there is anything missing. |
| * If all of the expected headers are present, return <code>null</code>. |
| */ |
| protected String validateHeaders() { |
| |
| // Do we have any headers to check for? |
| if (outHeaders == null) |
| return (null); |
| |
| // Check each specified name:value combination |
| String headers = outHeaders; |
| while (headers.length() > 0) { |
| // Parse the next name:value combination |
| int delimiter = headers.indexOf("##"); |
| String header = null; |
| if (delimiter < 0) { |
| header = headers; |
| headers = ""; |
| } else { |
| header = headers.substring(0, delimiter); |
| headers = headers.substring(delimiter + 2); |
| } |
| int colon = header.indexOf(":"); |
| String name = header.substring(0, colon).trim(); |
| String value = header.substring(colon + 1).trim(); |
| // Check for the occurrence of this header |
| ArrayList list = (ArrayList) saveHeaders.get(name.toLowerCase()); |
| if (list == null) |
| return ("Missing header name '" + name + "'"); |
| boolean found = false; |
| for (int i = 0; i < list.size(); i++) { |
| if (value.equals((String) list.get(i))) { |
| found = true; |
| break; |
| } |
| } |
| if (!found) |
| return ("Missing header name '" + name + "' with value '" + |
| value + "'"); |
| } |
| |
| // Everything was found successfully |
| return (null); |
| |
| } |
| |
| |
| /** |
| * Validate the returned response message against what we expected. |
| * Return <code>null</code> for no problems, or an error message. |
| * |
| * @param message The returned response message |
| */ |
| protected String validateMessage(String message) { |
| |
| if (this.message == null) |
| return (null); |
| else if (this.message.equals(message)) |
| return (null); |
| else |
| return ("Expected message='" + this.message + "', got message='" + |
| message + "'"); |
| |
| } |
| |
| |
| /** |
| * Validate the returned status code against what we expected. Return |
| * <code>null</code> for no problems, or an error message. |
| * |
| * @param status The returned status code |
| */ |
| protected String validateStatus(int status) { |
| |
| if (this.status == 0) |
| return (null); |
| if (this.status == status) |
| return (null); |
| else |
| return ("Expected status=" + this.status + ", got status=" + |
| status); |
| |
| } |
| |
| |
| } |