Author: rjung
Date: Tue Dec 16 10:58:46 2014
New Revision: 1645908

URL: http://svn.apache.org/r1645908
Log:
Add more thorough tests for AJP.

Unfortunately request attributes as sent
by mod_jk JkEnvVars can not be tested,
because request.getAttributeNames() does
not return the names of Coyote request
attributes. Only getAttribute(String)
checks Coyote request attributes.

Backport of r1645488 from trunk.

Modified:
    tomcat/tc8.0.x/trunk/   (props changed)
    tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java
    
tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java
    tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java
    tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc8.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Dec 16 10:58:46 2014
@@ -1 +1 @@
-/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640083-1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1642766,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643536,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644529,1644535,1644730,1644768,1644784-1644785,1644790,1644793,1644815,1644884,1644886,1644890,1644892
 
,1644910,1644924,1644929-1644930,1644935,1644989,1645011,1645247,1645355,1645357-1645358,1645455,1645465,1645469,1645471,1645473,1645475,1645486-1645487,1645626,1645641,1645685
+/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640083-1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1642766,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643536,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644529,1644535,1644730,1644768,1644784-1644785,1644790,1644793,1644815,1644884,1644886,1644890,1644892
 
,1644910,1644924,1644929-1644930,1644935,1644989,1645011,1645247,1645355,1645357-1645358,1645455,1645465,1645469,1645471,1645473,1645475,1645486-1645488,1645626,1645641,1645685

Modified: tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java?rev=1645908&r1=1645907&r2=1645908&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java 
(original)
+++ tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/SimpleAjpClient.java Tue 
Dec 16 10:58:46 2014
@@ -44,6 +44,15 @@ public class SimpleAjpClient {
 
     private String host = "localhost";
     private int port = -1;
+    /* GET == 2 */
+    private int method = 2;
+    private String protocol = "http";
+    private String uri = "/";
+    private String remoteAddr = "192.168.0.1";
+    private String remoteHost = "client.example.com";
+    private String serverName = "www.example.com";
+    private int serverPort = 80;
+    private boolean ssl = false;
     private Socket socket = null;
 
     public void setPort(int port) {
@@ -54,6 +63,212 @@ public class SimpleAjpClient {
         return port;
     }
 
+    public void setMethod(String method) {
+        method = method.toUpperCase();
+        switch (method) {
+            case "OPTIONS":
+                this.method = 1;
+                break;
+            case "GET":
+                this.method = 2;
+                break;
+            case "HEAD":
+                this.method = 3;
+                break;
+            case "POST":
+                this.method = 4;
+                break;
+            case "PUT":
+                this.method = 5;
+                break;
+            case "DELETE":
+                this.method = 6;
+                break;
+            case "TRACE":
+                this.method = 7;
+                break;
+            case "PROPFIND":
+                this.method = 8;
+                break;
+            case "PROPPATCH":
+                this.method = 9;
+                break;
+            case "MKCOL":
+                this.method = 10;
+                break;
+            case "COPY":
+                this.method = 11;
+                break;
+            case "MOVE":
+                this.method = 12;
+                break;
+            case "LOCK":
+                this.method = 13;
+                break;
+            case "UNLOCK":
+                this.method = 14;
+                break;
+            case "ACL":
+                this.method = 15;
+                break;
+            case "REPORT":
+                this.method = 16;
+                break;
+            case "VERSION-CONTROL":
+                this.method = 17;
+                break;
+            case "CHECKIN":
+                this.method = 18;
+                break;
+            case "CHECKOUT":
+                this.method = 19;
+                break;
+            case "UNCHECKOUT":
+                this.method = 20;
+                break;
+            case "SEARCH":
+                this.method = 21;
+                break;
+            case "MKWORKSPACE":
+                this.method = 22;
+                break;
+            case "UPDATE":
+                this.method = 23;
+                break;
+            case "LABEL":
+                this.method = 24;
+                break;
+            case "MERGE":
+                this.method = 25;
+                break;
+            case "BASELINE-CONTROL":
+                this.method = 26;
+                break;
+            case "MKACTIVITY":
+                this.method = 27;
+                break;
+            default:
+                this.method = 99;
+        }
+    }
+
+    public String getMethod() {
+        switch (method) {
+            case 1:
+                return "OPTIONS";
+            case 2:
+                return "GET";
+            case 3:
+                return "HEAD";
+            case 4:
+                return "POST";
+            case 5:
+                return "PUT";
+            case 6:
+                return "DELETE";
+            case 7:
+                return "TRACE";
+            case 8:
+                return "PROPFIND";
+            case 9:
+                return "PROPPATCH";
+            case 10:
+                return "MKCOL";
+            case 11:
+                return "COPY";
+            case 12:
+                return "MOVE";
+            case 13:
+                return "LOCK";
+            case 14:
+                return "UNLOCK";
+            case 15:
+                return "ACL";
+            case 16:
+                return "REPORT";
+            case 17:
+                return "VERSION-CONTROL";
+            case 18:
+                return "CHECKIN";
+            case 19:
+                return "CHECKOUT";
+            case 20:
+                return "UNCHECKOUT";
+            case 21:
+                return "SEARCH";
+            case 22:
+                return "MKWORKSPACE";
+            case 23:
+                return "UPDATE";
+            case 24:
+                return "LABEL";
+            case 25:
+                return "MERGE";
+            case 26:
+                return "BASELINE-CONTROL";
+            case 27:
+                return "MKACTIVITY";
+            default:
+                return "UNKNOWN";
+        }
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public void setRemoteAddr(String remoteAddr) {
+        this.remoteAddr = remoteAddr;
+    }
+
+    public String getRemoteAddr() {
+        return remoteAddr;
+    }
+
+    public void setRemoteHost(String remoteHost) {
+        this.remoteHost = remoteHost;
+    }
+
+    public String getRemoteHost() {
+        return remoteHost;
+    }
+
+    public void setServerName(String serverName) {
+        this.serverName = serverName;
+    }
+
+    public String getServerName() {
+        return serverName;
+    }
+
+    public void setServerPort(int serverPort) {
+        this.serverPort = serverPort;
+    }
+
+    public int getServerPort() {
+        return serverPort;
+    }
+
+    public void setSsl(boolean ssl) {
+        this.ssl = ssl;
+    }
+
+    public boolean isSsl() {
+        return ssl;
+    }
+
     public void connect() throws IOException {
         socket = SocketFactory.getDefault().createSocket(host, port);
     }
@@ -66,11 +281,7 @@ public class SimpleAjpClient {
     /*
      * Create a message to request the given URL.
      */
-    public TesterAjpMessage createForwardMessage(String url) {
-        return createForwardMessage(url, 2);
-    }
-
-    public TesterAjpMessage createForwardMessage(String url, int method) {
+    public TesterAjpMessage createForwardMessage() {
 
         TesterAjpMessage message = new TesterAjpMessage(AJP_PACKET_SIZE);
         message.reset();
@@ -86,30 +297,29 @@ public class SimpleAjpClient {
         message.appendByte(method);
 
         // Protocol
-        message.appendString("http");
+        message.appendString(protocol);
 
         // Request URI
-        message.appendString(url);
+        message.appendString(uri);
 
-        // Remote address
-        message.appendString("10.0.0.1");
+        // Client address
+        message.appendString(remoteAddr);
 
-        // Remote host
-        message.appendString("client.dev.local");
+        // Client host
+        message.appendString(remoteHost);
 
         // Server name
-        message.appendString(host);
+        message.appendString(serverName);
 
-        // Port
-        message.appendInt(port);
+        // Server port
+        message.appendInt(serverPort);
 
         // Is ssl
-        message.appendByte(0x00);
+        message.appendByte(ssl ? 0x01 : 0x00);
 
         return message;
     }
 
-
     public TesterAjpMessage createBodyMessage(byte[] data) {
 
         TesterAjpMessage message = new TesterAjpMessage(AJP_PACKET_SIZE);

Modified: 
tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java?rev=1645908&r1=1645907&r2=1645908&view=diff
==============================================================================
--- 
tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java 
(original)
+++ 
tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java 
Tue Dec 16 10:58:46 2014
@@ -20,9 +20,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 
+import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -62,6 +64,387 @@ public class TestAbstractAjpProcessor ex
         return protocol;
     }
 
+    private void doSnoopTest(RequestDescriptor desc) throws Exception {
+
+        HashMap<String, String> requestInfo = desc.getRequestInfo();
+        HashMap<String, String> contextInitParameters = 
desc.getContextInitParameters();
+        HashMap<String, String> contextAttributes = 
desc.getContextAttributes();
+        HashMap<String, String> headers = desc.getHeaders();
+        HashMap<String, String> attributes = desc.getAttributes();
+        HashMap<String, String> params = desc.getParams();
+
+        Tomcat tomcat = getTomcatInstance();
+
+        // No file system docBase required
+        Context ctx = tomcat.addContext("", null);
+
+        Tomcat.addServlet(ctx, "snoop", new SnoopServlet());
+        ctx.addServletMapping("/", "snoop");
+
+        SimpleAjpClient ajpClient = new SimpleAjpClient();
+
+        if (requestInfo.get("REQUEST-QUERY-STRING") != null &&
+            params.size() > 0) {
+            throw(new IllegalArgumentException("Request setting " +
+                "'REQUEST-QUERY-STRING' and explicit params not allowed " +
+                "together"));
+        }
+
+        String value;
+        HashMap<String, String> savedRequestInfo = new HashMap<String, 
String>();
+        for (String name: requestInfo.keySet()) {
+            value = requestInfo.get(name);
+            switch (name) {
+                case "REQUEST-METHOD":
+                    ajpClient.setMethod(value);
+                    break;
+                case "REQUEST-PROTOCOL":
+                    ajpClient.setProtocol(value);
+                    break;
+                case "REQUEST-URI":
+                    ajpClient.setUri(value);
+                    break;
+                case "REQUEST-REMOTE-HOST":
+                    /* request.getRemoteHost() will default to
+                     * request.getRemoteAddr() unless enableLookups is set. */
+                    tomcat.getConnector().setEnableLookups(true);
+                    ajpClient.setRemoteHost(value);
+                    break;
+                case "REQUEST-REMOTE-ADDR":
+                    ajpClient.setRemoteAddr(value);
+                    break;
+                case "REQUEST-SERVER-NAME":
+                    ajpClient.setServerName(value);
+                    break;
+                case "REQUEST-SERVER-PORT":
+                    ajpClient.setServerPort(Integer.valueOf(value));
+                    break;
+                case "REQUEST-IS-SECURE":
+                    ajpClient.setSsl(Boolean.parseBoolean(value));
+                    break;
+                case "REQUEST-LOCAL-ADDR":
+                    savedRequestInfo.put(name, value);
+                    break;
+                case "REQUEST-REMOTE-PORT":
+                    savedRequestInfo.put(name, value);
+                    break;
+                case "REQUEST-REMOTE-USER":
+                case "REQUEST-ROUTE":
+                case "REQUEST-SECRET":
+                case "REQUEST-AUTH-TYPE":
+                case "REQUEST-QUERY-STRING":
+                    savedRequestInfo.put(name, value);
+                    break;
+                case "REQUEST-CONTENT-LENGTH":
+                    headers.put("CONTENT-LENGTH", value);
+                    break;
+                case "REQUEST-CONTENT-TYPE":
+                    headers.put("CONTENT-TYPE", value);
+                    break;
+                /* Not yet implemented or not (easily) possible to implement */
+                case "REQUEST-LOCAL-NAME":          //request.getLocalName()
+                case "REQUEST-LOCAL-PORT":          //request.getLocalPort()
+                case "REQUEST-SCHEME":              //request.getScheme()
+                case "REQUEST-URL":                 //request.getRequestURL()
+                case "REQUEST-CONTEXT-PATH":        //request.getContextPath()
+                case "REQUEST-SERVLET-PATH":        //request.getServletPath()
+                case "REQUEST-PATH-INFO":           //request.getPathInfo()
+                case "REQUEST-PATH-TRANSLATED":     
//request.getPathTranslated()
+                case "REQUEST-USER-PRINCIPAL":      
//request.getUserPrincipal()
+                case "REQUEST-CHARACTER-ENCODING":  
//request.getCharacterEncoding()
+                case "REQUEST-LOCALE":              //request.getLocale()
+                case "SESSION-REQUESTED-ID":        
//request.getRequestedSessionId()
+                case "SESSION-REQUESTED-ID-COOKIE": 
//request.isRequestedSessionIdFromCookie()
+                case "SESSION-REQUESTED-ID-URL":    
//request.isRequestedSessionIdFromUrl()
+                case "SESSION-REQUESTED-ID-VALID":  
//request.isRequestedSessionIdValid()
+                default:
+                    throw(new IllegalArgumentException("Request setting '" + 
name + "' not supported"));
+            }
+        }
+
+        ServletContext sc = ctx.getServletContext();
+        for (String name: contextInitParameters.keySet()) {
+            sc.setInitParameter(name, contextInitParameters.get(name));
+        }
+        for (String name: contextAttributes.keySet()) {
+            sc.setAttribute(name, contextAttributes.get(name));
+        }
+
+        /* Basic request properties must be set before this call */
+        TesterAjpMessage forwardMessage = ajpClient.createForwardMessage();
+
+        for (String name: savedRequestInfo.keySet()) {
+            value = savedRequestInfo.get(name);
+            switch (name) {
+                case "REQUEST-LOCAL-ADDR":
+                    forwardMessage.addAttribute("AJP_LOCAL_ADDR", value);
+                    break;
+                case "REQUEST-REMOTE-PORT":
+                    forwardMessage.addAttribute("AJP_REMOTE_PORT", value);
+                    break;
+                case "REQUEST-REMOTE-USER":
+                    /* request.getRemoteUser() will not trust the AJP
+                     * info if tomcatAuthentication is set. */
+                    tomcat.getConnector().setProperty("tomcatAuthentication", 
"false");
+                    forwardMessage.addAttribute(0x03, value);
+                    break;
+                case "REQUEST-AUTH-TYPE":
+                    /* request.getAuthType() will not trust the AJP
+                     * info if tomcatAuthentication is set. */
+                    tomcat.getConnector().setProperty("tomcatAuthentication", 
"false");
+                    forwardMessage.addAttribute(0x04, value);
+                    break;
+                case "REQUEST-QUERY-STRING":
+                    forwardMessage.addAttribute(0x05, value);
+                    break;
+                case "REQUEST-ROUTE":
+                    forwardMessage.addAttribute(0x06, value);
+                    break;
+                case "REQUEST-SECRET":
+                    forwardMessage.addAttribute(0x0C, value);
+                    break;
+                default:
+                    throw(new IllegalArgumentException("Request setting '" + 
name + "' not supported"));
+            }
+        }
+
+        if (params.size() > 0) {
+            StringBuilder query = new StringBuilder();
+            boolean sep = false;
+            for (String name: params.keySet()) {
+                if (sep) {
+                    query.append("&");
+                } else {
+                    sep = true;
+                }
+                query.append(name);
+                query.append("=");
+                query.append(params.get(name));
+            }
+            forwardMessage.addAttribute(0x05, query.toString());
+        }
+
+        for (String name: headers.keySet()) {
+            value = headers.get(name);
+            name = name.toUpperCase();
+            switch (name) {
+                case "ACCEPT":
+                    forwardMessage.addHeader(0xA001, value);
+                    break;
+                case "ACCEPT-CHARSET":
+                    forwardMessage.addHeader(0xA002, value);
+                    break;
+                case "ACCEPT-ENCODING":
+                    forwardMessage.addHeader(0xA003, value);
+                    break;
+                case "ACCEPT-LANGUAGE":
+                    forwardMessage.addHeader(0xA004, value);
+                    break;
+                case "AUTHORIZATION":
+                    forwardMessage.addHeader(0xA005, value);
+                    break;
+                case "CONNECTION":
+                    forwardMessage.addHeader(0xA006, value);
+                    break;
+                case "CONTENT-TYPE":
+                    forwardMessage.addHeader(0xA007, value);
+                    break;
+                case "CONTENT-LENGTH":
+                    forwardMessage.addHeader(0xA008, value);
+                    break;
+                case "COOKIE":
+                    forwardMessage.addHeader(0xA009, value);
+                    break;
+                case "COOKIE2":
+                    forwardMessage.addHeader(0xA00A, value);
+                    break;
+                case "HOST":
+                    forwardMessage.addHeader(0xA00B, value);
+                    break;
+                case "PRAGMA":
+                    forwardMessage.addHeader(0xA00C, value);
+                    break;
+                case "REFERER":
+                    forwardMessage.addHeader(0xA00D, value);
+                    break;
+                case "USER-AGENT":
+                    forwardMessage.addHeader(0xA00E, value);
+                    break;
+                default:
+                    forwardMessage.addHeader(name, value);
+                    break;
+            }
+        }
+        for (String name: attributes.keySet()) {
+            value = attributes.get(name);
+            forwardMessage.addAttribute(name, value);
+        }
+        // Complete the message
+        forwardMessage.end();
+
+        tomcat.start();
+        ajpClient.setPort(getPort());
+        ajpClient.connect();
+
+        // Expect 3 packets: headers, body, end
+        TesterAjpMessage responseHeaders = 
ajpClient.sendMessage(forwardMessage);
+        validateResponseHeaders(responseHeaders, 200, "OK");
+
+        String body = extractResponseBody(ajpClient.readMessage());
+        RequestDescriptor result = SnoopResult.parse(body);
+
+        /* AJP attributes result in Coyote Request attributes, which are
+         * not listed by request.getAttributeNames(), so SnoopServlet
+         * does not see them. Delete attributes before result comparison. */
+        desc.getAttributes().clear();
+
+        result.compare(desc);
+
+        validateResponseEnd(ajpClient.readMessage(), true);
+    }
+
+    @Test
+    public void testServerName() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-SERVER-NAME", "MYSERVER");
+        desc.putRequestInfo("REQUEST-URI", "/testServerName");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testServerPort() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-SERVER-PORT", "8888");
+        desc.putRequestInfo("REQUEST-URI", "/testServerPort");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testLocalAddr() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-LOCAL-ADDR", "10.3.2.1");
+        desc.putRequestInfo("REQUEST-URI", "/testLocalAddr");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testRemoteHost() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-REMOTE-HOST", "MYCLIENT");
+        desc.putRequestInfo("REQUEST-URI", "/testRemoteHost");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testRemoteAddr() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-REMOTE-ADDR", "10.1.2.3");
+        desc.putRequestInfo("REQUEST-URI", "/testRemoteAddr");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testRemotePort() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-REMOTE-PORT", "34567");
+        desc.putRequestInfo("REQUEST-URI", "/testRemotePort");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testMethod() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-METHOD", "LOCK");
+        desc.putRequestInfo("REQUEST-URI", "/testMethod");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testUri() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-URI", "/a/b/c");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testProtocol() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-PROTOCOL", "HTTP/1.x");
+        desc.putRequestInfo("REQUEST-URI", "/testProtocol");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testSecure() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-IS-SECURE", "true");
+        desc.putRequestInfo("REQUEST-URI", "/testSecure");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testQueryString() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-QUERY-STRING", "p1=1&p2=12&p3=123");
+        desc.putRequestInfo("REQUEST-URI", "/testQueryString");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testRemoteUser() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-REMOTE-USER", "MYUSER");
+        desc.putRequestInfo("REQUEST-URI", "/testRemoteUser");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testAuthType() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-AUTH-TYPE", "MyAuth");
+        desc.putRequestInfo("REQUEST-URI", "/testAuthType");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testOneHeader() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putHeader("MYHEADER", "MYHEADER-VALUE");
+        desc.putRequestInfo("REQUEST-URI", "/testOneHeader");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testOneAttribute() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putAttribute("MYATTRIBUTE", "MYATTRIBUTE-VALUE");
+        desc.putRequestInfo("REQUEST-URI", "/testOneAttribute");
+        doSnoopTest(desc);
+    }
+
+    @Test
+    public void testMulti() throws Exception {
+        RequestDescriptor desc = new RequestDescriptor();
+        desc.putRequestInfo("REQUEST-SERVER-NAME", "MYSERVER");
+        desc.putRequestInfo("REQUEST-SERVER-PORT", "8888");
+        desc.putRequestInfo("REQUEST-LOCAL-ADDR", "10.3.2.1");
+        desc.putRequestInfo("REQUEST-REMOTE-HOST", "MYCLIENT");
+        desc.putRequestInfo("REQUEST-REMOTE-ADDR", "10.1.2.3");
+        desc.putRequestInfo("REQUEST-REMOTE-PORT", "34567");
+        desc.putRequestInfo("REQUEST-METHOD", "LOCK");
+        desc.putRequestInfo("REQUEST-URI", "/a/b/c");
+        desc.putRequestInfo("REQUEST-PROTOCOL", "HTTP/1.x");
+        desc.putRequestInfo("REQUEST-IS-SECURE", "true");
+        desc.putRequestInfo("REQUEST-QUERY-STRING", "p1=1&p2=12&p3=123");
+        desc.putRequestInfo("REQUEST-REMOTE-USER", "MYUSER");
+        desc.putRequestInfo("REQUEST-AUTH-TYPE", "MyAuth");
+        desc.putHeader("MYHEADER1", "MYHEADER1-VALUE");
+        desc.putHeader("MYHEADER2", "MYHEADER2-VALUE");
+        desc.putAttribute("MYATTRIBUTE1", "MYATTRIBUTE-VALUE1");
+        desc.putAttribute("MYATTRIBUTE2", "MYATTRIBUTE-VALUE2");
+        doSnoopTest(desc);
+    }
+
     @Test
     public void testKeepAlive() throws Exception {
         Tomcat tomcat = getTomcatInstance();
@@ -82,7 +465,8 @@ public class TestAbstractAjpProcessor ex
 
         validateCpong(ajpClient.cping());
 
-        TesterAjpMessage forwardMessage = ajpClient.createForwardMessage("/");
+        TesterAjpMessage forwardMessage = ajpClient.createForwardMessage();
+        forwardMessage.addHeader("X-DUMMY-HEADER", "IGNORE");
         // Complete the message - no extra headers required.
         forwardMessage.end();
 
@@ -90,7 +474,7 @@ public class TestAbstractAjpProcessor ex
         for (int i = 0; i < 2; i++) {
             TesterAjpMessage responseHeaders = 
ajpClient.sendMessage(forwardMessage);
             // Expect 3 packets: headers, body, end
-            validateResponseHeaders(responseHeaders, 200);
+            validateResponseHeaders(responseHeaders, 200, "OK");
             TesterAjpMessage responseBody = ajpClient.readMessage();
             validateResponseBody(responseBody, 
HelloWorldServlet.RESPONSE_TEXT);
             validateResponseEnd(ajpClient.readMessage(), true);
@@ -107,18 +491,19 @@ public class TestAbstractAjpProcessor ex
 
     @Test
     public void testPost() throws Exception {
-        doTestPost(false, HttpServletResponse.SC_OK);
+        doTestPost(false, HttpServletResponse.SC_OK, "OK");
     }
 
 
     @Test
     public void testPostMultipleContentLength() throws Exception {
         // Multiple content lengths
-        doTestPost(true, HttpServletResponse.SC_BAD_REQUEST);
+        doTestPost(true, HttpServletResponse.SC_BAD_REQUEST, "Bad Request");
     }
 
 
-    public void doTestPost(boolean multipleCL, int expectedStatus) throws 
Exception {
+    public void doTestPost(boolean multipleCL, int expectedStatus,
+                           String expectedMessage) throws Exception {
 
         getTomcatInstanceTestWebapp(false, true);
 
@@ -128,8 +513,9 @@ public class TestAbstractAjpProcessor ex
 
         validateCpong(ajpClient.cping());
 
-        TesterAjpMessage forwardMessage =
-                ajpClient.createForwardMessage("/test/echo-params.jsp", 4);
+        ajpClient.setUri("/test/echo-params.jsp");
+        ajpClient.setMethod("POST");
+        TesterAjpMessage forwardMessage = ajpClient.createForwardMessage();
         forwardMessage.addHeader(0xA008, "9");
         if (multipleCL) {
             forwardMessage.addHeader(0xA008, "99");
@@ -143,7 +529,7 @@ public class TestAbstractAjpProcessor ex
         TesterAjpMessage responseHeaders =
                 ajpClient.sendMessage(forwardMessage, bodyMessage);
 
-        validateResponseHeaders(responseHeaders, expectedStatus);
+        validateResponseHeaders(responseHeaders, expectedStatus, 
expectedMessage);
         if (expectedStatus == HttpServletResponse.SC_OK) {
             // Expect 3 messages: headers, body, end for a valid request
             TesterAjpMessage responseBody = ajpClient.readMessage();
@@ -184,14 +570,14 @@ public class TestAbstractAjpProcessor ex
 
         validateCpong(ajpClient.cping());
 
-        TesterAjpMessage forwardMessage = ajpClient.createForwardMessage("/");
+        TesterAjpMessage forwardMessage = ajpClient.createForwardMessage();
         forwardMessage.end();
 
         TesterAjpMessage responseHeaders =
                 ajpClient.sendMessage(forwardMessage, null);
 
         // Expect 2 messages: headers, end
-        validateResponseHeaders(responseHeaders, 304);
+        validateResponseHeaders(responseHeaders, 304, "Not Modified");
         validateResponseEnd(ajpClient.readMessage(), true);
 
         // Double check the connection is still open
@@ -203,25 +589,25 @@ public class TestAbstractAjpProcessor ex
 
     @Test
     public void testZeroLengthRequestBodyGetA() throws Exception {
-        doTestZeroLengthRequestBody(2, true);
+        doTestZeroLengthRequestBody("GET", true);
     }
 
     @Test
     public void testZeroLengthRequestBodyGetB() throws Exception {
-        doTestZeroLengthRequestBody(2, false);
+        doTestZeroLengthRequestBody("GET", false);
     }
 
     @Test
     public void testZeroLengthRequestBodyPostA() throws Exception {
-        doTestZeroLengthRequestBody(4, true);
+        doTestZeroLengthRequestBody("POST", true);
     }
 
     @Test
     public void testZeroLengthRequestBodyPostB() throws Exception {
-        doTestZeroLengthRequestBody(4, false);
+        doTestZeroLengthRequestBody("POST", false);
     }
 
-    private void doTestZeroLengthRequestBody(int method, boolean callAvailable)
+    private void doTestZeroLengthRequestBody(String method, boolean 
callAvailable)
             throws Exception {
 
         Tomcat tomcat = getTomcatInstance();
@@ -241,7 +627,8 @@ public class TestAbstractAjpProcessor ex
 
         validateCpong(ajpClient.cping());
 
-        TesterAjpMessage forwardMessage = ajpClient.createForwardMessage("/", 
method);
+        ajpClient.setMethod(method);
+        TesterAjpMessage forwardMessage = ajpClient.createForwardMessage();
         forwardMessage.addHeader(0xA008, "0");
         forwardMessage.end();
 
@@ -249,7 +636,7 @@ public class TestAbstractAjpProcessor ex
                 ajpClient.sendMessage(forwardMessage, null);
 
         // Expect 3 messages: headers, body, end
-        validateResponseHeaders(responseHeaders, 200);
+        validateResponseHeaders(responseHeaders, 200, "OK");
         validateResponseBody(ajpClient.readMessage(),
                 "Request Body length in bytes: 0");
         validateResponseEnd(ajpClient.readMessage(), true);
@@ -279,7 +666,7 @@ public class TestAbstractAjpProcessor ex
      * ignored.
      */
     private void validateResponseHeaders(TesterAjpMessage message,
-            int expectedStatus) throws Exception {
+            int expectedStatus, String expectedMessage) throws Exception {
         // First two bytes should always be AB
         Assert.assertEquals((byte) 'A', message.buf[0]);
         Assert.assertEquals((byte) 'B', message.buf[1]);
@@ -296,8 +683,8 @@ public class TestAbstractAjpProcessor ex
         // Check status
         Assert.assertEquals(expectedStatus, message.readInt());
 
-        // Read the status message
-        message.readString();
+        // Check the reason phrase
+        Assert.assertEquals(expectedMessage, message.readString());
 
         // Get the number of headers
         int headerCount = message.readInt();
@@ -311,11 +698,10 @@ public class TestAbstractAjpProcessor ex
     }
 
     /**
-     * Validates that the response message is valid and contains the expected
-     * content.
+     * Extract the content from a response message.
      */
-    private void validateResponseBody(TesterAjpMessage message,
-            String expectedBody) throws Exception {
+    private String extractResponseBody(TesterAjpMessage message)
+            throws Exception {
 
         Assert.assertEquals((byte) 'A', message.buf[0]);
         Assert.assertEquals((byte) 'B', message.buf[1]);
@@ -328,8 +714,17 @@ public class TestAbstractAjpProcessor ex
 
         int len = message.readInt();
         Assert.assertTrue(len > 0);
-        String body = message.readString(len);
+        return message.readString(len);
+    }
+
+    /**
+     * Validates that the response message is valid and contains the expected
+     * content.
+     */
+    private void validateResponseBody(TesterAjpMessage message,
+            String expectedBody) throws Exception {
 
+        String body = extractResponseBody(message);
         Assert.assertTrue(body.contains(expectedBody));
     }
 

Modified: tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java?rev=1645908&r1=1645907&r2=1645908&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java 
(original)
+++ tomcat/tc8.0.x/trunk/test/org/apache/coyote/ajp/TesterAjpMessage.java Tue 
Dec 16 10:58:46 2014
@@ -29,6 +29,7 @@ import java.util.List;
 public class TesterAjpMessage extends AjpMessage {
 
     private final List<Header> headers = new ArrayList<>();
+    private final List<Attribute> attributes = new ArrayList<>();
 
 
     public TesterAjpMessage(int packetSize) {
@@ -86,6 +87,16 @@ public class TesterAjpMessage extends Aj
     }
 
 
+    public void addAttribute(int code, String value) {
+        attributes.add(new Attribute(code, value));
+    }
+
+
+    public void addAttribute(String name, String value) {
+        attributes.add(new Attribute(name, value));
+    }
+
+
     @Override
     public void end() {
         // Add the header count
@@ -95,6 +106,10 @@ public class TesterAjpMessage extends Aj
             header.append(this);
         }
 
+        for (Attribute attribute : attributes) {
+            attribute.append(this);
+        }
+
         // Terminator
         appendByte(0xFF);
 
@@ -121,7 +136,6 @@ public class TesterAjpMessage extends Aj
     }
 
 
-
     private static class Header {
         private final int code;
         private final String name;
@@ -147,5 +161,34 @@ public class TesterAjpMessage extends Aj
             }
             message.appendString(value);
         }
+    }
+
+
+    private static class Attribute {
+        private final int code;
+        private final String name;
+        private final String value;
+
+        public Attribute(int code, String value) {
+            this.code = code;
+            this.name = null;
+            this.value = value;
+        }
+
+        public Attribute(String name, String value) {
+            this.code = 0;
+            this.name = name;
+            this.value = value;
+        }
+
+        public void append(TesterAjpMessage message) {
+            if (code == 0) {
+                message.appendByte(0x0A);
+                message.appendString(name);
+            } else {
+                message.appendByte(code);
+            }
+            message.appendString(value);
+        }
     }
 }

Modified: tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml?rev=1645908&r1=1645907&r2=1645908&view=diff
==============================================================================
--- tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Tue Dec 16 10:58:46 2014
@@ -187,6 +187,9 @@
           Add RequestDescriptor class to unit tests. (rjung)
           Adjust TestRewriteValve to use RequestDescriptor.
       </add>
+      <update>
+          Add more AJP unit tests. (rjung)
+      </update>
     </changelog>
   </subsection>
   <subsection name="Coyote">



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

Reply via email to