From 51dfbef1056931b736c79a10e2488602c866fcd2 Mon Sep 17 00:00:00 2001 From: markt Date: Tue, 16 Jun 2009 20:18:14 +0000 Subject: [PATCH] Test case for bug 37794. The generic code will move out of this class if it turns out to be useful for other test cases git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@785369 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/catalina/connector/TestRequest.java | 299 +++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 test/org/apache/catalina/connector/TestRequest.java diff --git a/test/org/apache/catalina/connector/TestRequest.java b/test/org/apache/catalina/connector/TestRequest.java new file mode 100644 index 000000000..6f828b6b4 --- /dev/null +++ b/test/org/apache/catalina/connector/TestRequest.java @@ -0,0 +1,299 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.catalina.connector; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.startup.Tomcat; + +import junit.framework.TestCase; + +/** + * Test case for {@link Request}. + */ +public class TestRequest extends TestCase { + /** + * Test case for https://issues.apache.org/bugzilla/show_bug.cgi?id=37794 + * POST parameters are not returned from a call to + * any of the {@link HttpServletRequest} getParameterXXX() methods. + * @throws Exception + */ + public void testBug37794() throws Exception { + Bug37794Client client = new Bug37794Client(); + + // Edge cases around zero + client.doRequest(-1); // Unlimited + assertTrue(client.isResponse200()); + assertTrue(client.isResponseBodyOK()); + client.reset(); + client.doRequest(0); // Unlimited + assertTrue(client.isResponse200()); + assertTrue(client.isResponseBodyOK()); + client.reset(); + client.doRequest(1); // 1 byte - too small should fail + assertTrue(client.isResponse500()); + + client.reset(); + + // Edge cases around actual content length + client.reset(); + client.doRequest(6); // Too small should fail + assertTrue(client.isResponse500()); + client.reset(); + client.doRequest(7); // Just enough should pass + assertTrue(client.isResponse200()); + assertTrue(client.isResponseBodyOK()); + client.reset(); + client.doRequest(8); // 1 extra - should pass + assertTrue(client.isResponse200()); + assertTrue(client.isResponseBodyOK()); + + // Much larger + client.reset(); + client.doRequest(8096); // Plenty of space - should pass + assertTrue(client.isResponse200()); + assertTrue(client.isResponseBodyOK()); + } + + private static class Bug37794Servlet extends HttpServlet { + + /** + * Only interested in the parameters and values for POST requests. + */ + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + // Just echo the parameters and values back as plain text + resp.setContentType("text/plain"); + + PrintWriter out = resp.getWriter(); + + // Assume one value per attribute + Enumeration names = req.getParameterNames(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + out.println(name + "=" + req.getParameter(name)); + } + } + } + + /** + * Bug 37794 test client. + */ + private static class Bug37794Client extends SimpleHttpClient { + private Exception doRequest(int postLimit) { + Tomcat tomcat = new Tomcat(); + try { + StandardContext root = tomcat.addContext("", TEMP_DIR); + Tomcat.addServlet(root, "Bug37794", new Bug37794Servlet()); + root.addServletMapping("/test", "Bug37794"); + tomcat.getConnector().setMaxPostSize(postLimit); + tomcat.start(); + + // Open connection + connect(); + + // Send request in two parts + String[] request = new String[2]; + request[0] = + "POST http://localhost:8080/test HTTP/1.1" + CRLF + + "content-type: application/x-www-form-urlencoded" + CRLF + + "Transfer-Encoding: chunked" + CRLF + + "Connection: close" + CRLF + + CRLF + + "3" + CRLF + + "a=1" + CRLF; + request[1] = + "4" + CRLF + + "&b=2" + CRLF + + "0" + CRLF + + CRLF; + + setRequest(request); + processRequest(); // blocks until response has been read + + // Close the connection + disconnect(); + } catch (Exception e) { + return e; + } finally { + try { + tomcat.stop(); + } catch (Exception e) { + // Ignore + } + } + return null; + } + + public boolean isResponseBodyOK() { + if (getResponseBody() == null) { + return false; + } + if (!getResponseBody().contains("a=1")) { + return false; + } + if (!getResponseBody().contains("b=2")) { + return false; + } + return true; + } + + } + + /** + * Simple client for unit testing. It isn't robust, it isn't secure and + * should not be used as the basis for production code. Its only purpose + * is to do the bare minimum for the unit tests. + */ + private abstract static class SimpleHttpClient { + public static final String TEMP_DIR = + System.getProperty("java.io.tmpdir"); + + public static final String CRLF = "\r\n"; + + public static final String OK_200 = "HTTP/1.1 200"; + public static final String FAIL_500 = "HTTP/1.1 500"; + + private Socket socket; + private Writer writer; + private BufferedReader reader; + + private String[] request; + private int requestPause = 1000; + + private String responseLine; + private List responseHeaders = new ArrayList(); + private String responseBody; + + public void setRequest(String[] theRequest) { + request = theRequest; + } + + public void setRequestPause(int theRequestPause) { + requestPause = theRequestPause; + } + + public String getResponseLine() { + return responseLine; + } + + public List getResponseHeaders() { + return responseHeaders; + } + + public String getResponseBody() { + return responseBody; + } + + public void connect() throws UnknownHostException, IOException { + socket = new Socket("localhost", 8080); + OutputStream os = socket.getOutputStream(); + writer = new OutputStreamWriter(os); + InputStream is = socket.getInputStream(); + Reader r = new InputStreamReader(is); + reader = new BufferedReader(r); + } + + public void processRequest() throws IOException, InterruptedException { + // Send the request + boolean first = true; + for (String requestPart : request) { + if (first) { + first = false; + } else { + Thread.sleep(requestPause); + } + writer.write(requestPart); + writer.flush(); + } + + // Read the response + responseLine = readLine(); + + // Put the headers into the map + String line = readLine(); + while (line.length() > 0) { + responseHeaders.add(line); + line = readLine(); + } + + // Read the body, if any + StringBuilder builder = new StringBuilder(); + line = readLine(); + while (line != null && line.length() > 0) { + builder.append(line); + line = readLine(); + } + responseBody = builder.toString(); + + } + + public String readLine() throws IOException { + return reader.readLine(); + } + + public void disconnect() throws IOException { + writer.close(); + reader.close(); + socket.close(); + } + + public void reset() { + socket = null; + writer = null; + reader = null; + + request = null; + requestPause = 1000; + + responseLine = null; + responseHeaders = new ArrayList(); + responseBody = null; + } + + public boolean isResponse200() { + return getResponseLine().startsWith(OK_200); + } + + public boolean isResponse500() { + return getResponseLine().startsWith(FAIL_500); + } + + public abstract boolean isResponseBodyOK(); + } +} -- 2.11.0