]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Fix testHttpParser compile error 'variable tracking size limit exceeded'
authorAmos Jeffries <squid3@treenet.co.nz>
Tue, 19 Jun 2012 05:18:04 +0000 (23:18 -0600)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 19 Jun 2012 05:18:04 +0000 (23:18 -0600)
This can occur due to long lists of unit tests needing a lot of local
variable state tracking. Essentially 'function too long' after CPPUNIT
macros have been expanded.

Break the large set of request-line unit tests into groups related to
sub-parts of the request-line.

src/tests/testHttpParser.cc
src/tests/testHttpParser.h

index 7625cc55ee67b93dc6cf2e802173e152ee37e883..0946c39706c705a23134ee52a7ac25e19b9f80bc 100644 (file)
@@ -23,7 +23,7 @@ testHttpParser::globalSetup()
 }
 
 void
-testHttpParser::testParseRequestLine()
+testHttpParser::testParseRequestLineProtocols()
 {
     // ensure MemPools etc exist
     globalSetup();
@@ -55,7 +55,29 @@ testHttpParser::testParseRequestLine()
     CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
     input.reset();
 
-    // RFC 1945 and 2616 : HTTP/1.0 full-request
+    // RFC 1945 : invalid HTTP/0.9 simple-request (only GET is valid)
+#if 0
+    input.append("POST /\r\n", 7);
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("GET /\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
+    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start], (output.req.m_end-output.req.m_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start], (output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
+    input.reset();
+#endif
+
+    // RFC 1945 and 2616 : HTTP/1.0 request
     input.append("GET / HTTP/1.0\r\n", 16);
     output.reset(input.content(), input.contentSize());
     CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output));
@@ -76,8 +98,7 @@ testHttpParser::testParseRequestLine()
     CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
     input.reset();
 
-
-    // RFC 2616 : HTTP/1.1 full-request
+    // RFC 2616 : HTTP/1.1 request
     input.append("GET / HTTP/1.1\r\n", 16);
     output.reset(input.content(), input.contentSize());
     CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output));
@@ -99,6 +120,29 @@ testHttpParser::testParseRequestLine()
     input.reset();
 
     // RFC 2616 : future version full-request
+    input.append("GET / HTTP/1.2\r\n", 16);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("GET / HTTP/1.2\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
+    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(13, output.req.v_end);
+    CPPUNIT_ASSERT(memcmp("HTTP/1.2", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.v_min);
+    input.reset();
+
+    // RFC 2616 : future version full-request
+    // XXX: IETF HTTPbis WG has made this two-digits format invalid.
     input.append("GET / HTTP/10.12\r\n", 18);
     //printf("TEST: '%s'\n",input.content());
     output.reset(input.content(), input.contentSize());
@@ -120,51 +164,203 @@ testHttpParser::testParseRequestLine()
     CPPUNIT_ASSERT_EQUAL(12, output.req.v_min);
     input.reset();
 
-    // space padded URL
-    input.append("GET  /     HTTP/1.1\r\n", 21);
+    // This stage of the parser does not yet accept non-HTTP protocol names.
+    // violations mode treats them as HTTP/0.9 requests!
+    input.append("GET / FOO/1.0\n", 14);
     //printf("TEST: '%s'\n",input.content());
     output.reset(input.content(), input.contentSize());
+#if USE_HTTP_VIOLATIONS
     CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output));
     CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(12, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/ FOO/1.0", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
+#else
+    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+#endif
     CPPUNIT_ASSERT_EQUAL(0, output.req.start);
     CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("GET  /     HTTP/1.1\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT(memcmp("GET / FOO/1.0\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
     CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
     CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
     CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(5, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(5, output.req.u_end);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
+    CPPUNIT_ASSERT(memcmp("FOO/1.0", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
+    input.reset();
+
+    // no version
+    input.append("GET / HTTP/\n", 12);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("GET / HTTP/\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
+    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
     CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(11, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(18, output.req.v_end);
-    CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
+    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(10, output.req.v_end);
+    CPPUNIT_ASSERT(memcmp("HTTP/", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
     input.reset();
 
-    // space padded version
-    // RFC 1945 and 2616 specify version is followed by CRLF. No intermediary bytes.
-    // NP: the terminal whitespace is a special case: invalid for even HTTP/0.9 with no version tag
-    input.append("GET / HTTP/1.1 \n", 16);
+    // no major version
+    input.append("GET / HTTP/.1\n", 14);
     //printf("TEST: '%s'\n",input.content());
     output.reset(input.content(), input.contentSize());
     CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
     CPPUNIT_ASSERT_EQUAL(0, output.req.start);
     CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("GET / HTTP/1.1 \n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT(memcmp("GET / HTTP/.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
     CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
     CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
     CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
     CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(13, output.req.u_end);
-    CPPUNIT_ASSERT(memcmp("/ HTTP/1.1", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
+    CPPUNIT_ASSERT(memcmp("HTTP/.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+
+    // no version dot
+    input.append("GET / HTTP/11\n", 14);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("GET / HTTP/11\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
+    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
+    CPPUNIT_ASSERT(memcmp("HTTP/11", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+
+    // negative major version (bug 3062)
+    input.append("GET / HTTP/-999999.1\n", 21);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("GET / HTTP/-999999.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
+    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(19, output.req.v_end);
+    CPPUNIT_ASSERT(memcmp("HTTP/-999999.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
     CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
     CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
     input.reset();
 
+    // no minor version
+    input.append("GET / HTTP/1.\n", 14);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("GET / HTTP/1.\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
+    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
+    CPPUNIT_ASSERT(memcmp("HTTP/1.", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+
+    // negative major version (bug 3062 corollary)
+    input.append("GET / HTTP/1.-999999\n", 21);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("GET / HTTP/1.-999999\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
+    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(19, output.req.v_end);
+    CPPUNIT_ASSERT(memcmp("HTTP/1.-999999", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+}
+
+void
+testHttpParser::testParseRequestLineStrange()
+{
+    // ensure MemPools etc exist
+    globalSetup();
+
+    MemBuf input;
+    HttpParser output;
+    input.init();
+
+    // space padded URL
+    input.append("GET  /     HTTP/1.1\r\n", 21);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("GET  /     HTTP/1.1\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
+    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(5, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(5, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(11, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(18, output.req.v_end);
+    CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
+    input.reset();
+
     // whitespace inside URI. (nasty but happens)
     input.append("GET /fo o/ HTTP/1.1\n", 20);
     //printf("TEST: '%s'\n",input.content());
@@ -208,6 +404,17 @@ testHttpParser::testParseRequestLine()
     CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
     CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
     input.reset();
+}
+
+void
+testHttpParser::testParseRequestLineTerminators()
+{
+    // ensure MemPools etc exist
+    globalSetup();
+
+    MemBuf input;
+    HttpParser output;
+    input.init();
 
     // alternative EOL sequence: NL-only
     input.append("GET / HTTP/1.1\n", 15);
@@ -297,6 +504,110 @@ testHttpParser::testParseRequestLine()
     CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
     input.reset();
 
+    // space padded version
+    // RFC 1945 and 2616 specify version is followed by CRLF. No intermediary bytes.
+    // NP: the terminal whitespace is a special case: invalid for even HTTP/0.9 with no version tag
+    input.append("GET / HTTP/1.1 \n", 16);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("GET / HTTP/1.1 \n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
+    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(13, output.req.u_end);
+    CPPUNIT_ASSERT(memcmp("/ HTTP/1.1", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+
+    // incomplete line at various positions
+
+    input.append("GET", 3);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+
+    input.append("GET ", 4);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+
+    input.append("GET / HT", 8);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+
+    input.append("GET / HTTP/1.1", 14);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+}
+
+void
+testHttpParser::testParseRequestLineMethods()
+{
+    // ensure MemPools etc exist
+    globalSetup();
+
+    MemBuf input;
+    HttpParser output;
+    input.init();
+
     // RFC 2616 : . method
     input.append(". / HTTP/1.1\n", 13);
     //printf("TEST: '%s'\n",input.content());
@@ -363,36 +674,41 @@ testHttpParser::testParseRequestLine()
     CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
     input.reset();
 
-    // This stage of the parser does not yet accept non-HTTP protocol names.
-    // violations mode treats them as HTTP/0.9 requests!
-    input.append("GET / FOO/1.0\n", 14);
+    // method-only
+    input.append("A\n", 2);
+    //printf("TEST: '%s'\n",input.content());
+    output.reset(input.content(), input.contentSize());
+    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
+    CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
+    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
+    CPPUNIT_ASSERT(memcmp("A\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
+    input.reset();
+
+    input.append("GET\n", 4);
     //printf("TEST: '%s'\n",input.content());
     output.reset(input.content(), input.contentSize());
-#if USE_HTTP_VIOLATIONS
-    CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(12, output.req.u_end);
-    CPPUNIT_ASSERT(memcmp("/ FOO/1.0", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
-#else
     CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
-    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-#endif
+    CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
     CPPUNIT_ASSERT_EQUAL(0, output.req.start);
     CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("GET / FOO/1.0\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
+    CPPUNIT_ASSERT(memcmp("GET\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
     CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
-    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
-    CPPUNIT_ASSERT(memcmp("FOO/1.0", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
+    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
+    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
     input.reset();
 
     // RELAXED space padded method (in strict mode SP is reserved so invalid as a method byte)
@@ -459,95 +775,20 @@ testHttpParser::testParseRequestLine()
     CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
     CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
     input.reset();
+}
 
-    input.append("GET", 3);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
-
-    input.append("GET ", 4);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
-
-    input.append("GET / HT", 8);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
-
-    input.append("GET / HTTP/1.1", 14);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
+void
+testHttpParser::testParseRequestLineInvalid()
+{
+    // ensure MemPools etc exist
+    globalSetup();
 
-    // method-only
-    input.append("A\n", 2);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("A\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
+    MemBuf input;
+    HttpParser output;
+    input.init();
 
     // no method (but in a form which is ambiguous with HTTP/0.9 simple-request)
+    // XXX: Bug: HTTP/0.9 requires method to be "GET"
     input.append("/ HTTP/1.0\n", 11);
     //printf("TEST: '%s'\n",input.content());
     output.reset(input.content(), input.contentSize());
@@ -717,138 +958,6 @@ testHttpParser::testParseRequestLine()
     CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
     input.reset();
 
-    // no version
-    input.append("GET / HTTP/\n", 12);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("GET / HTTP/\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
-    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
-    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(10, output.req.v_end);
-    CPPUNIT_ASSERT(memcmp("HTTP/", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
-
-    // no major version
-    input.append("GET / HTTP/.1\n", 14);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("GET / HTTP/.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
-    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
-    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
-    CPPUNIT_ASSERT(memcmp("HTTP/.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
-
-    // no version dot
-    input.append("GET / HTTP/11\n", 14);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("GET / HTTP/11\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
-    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
-    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
-    CPPUNIT_ASSERT(memcmp("HTTP/11", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
-
-    // negative major version (bug 3062)
-    input.append("GET / HTTP/-999999.1\n", 21);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("GET / HTTP/-999999.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
-    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
-    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(19, output.req.v_end);
-    CPPUNIT_ASSERT(memcmp("HTTP/-999999.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
-
-    // no minor version
-    input.append("GET / HTTP/1.\n", 14);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("GET / HTTP/1.\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
-    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
-    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
-    CPPUNIT_ASSERT(memcmp("HTTP/1.", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
-
-    // negative major version (bug 3062 corollary)
-    input.append("GET / HTTP/1.-999999\n", 21);
-    //printf("TEST: '%s'\n",input.content());
-    output.reset(input.content(), input.contentSize());
-    CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output));
-    CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.start);
-    CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
-    CPPUNIT_ASSERT(memcmp("GET / HTTP/1.-999999\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
-    CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
-    CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
-    CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
-    CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
-    CPPUNIT_ASSERT_EQUAL(19, output.req.v_end);
-    CPPUNIT_ASSERT(memcmp("HTTP/1.-999999", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0);
-    CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
-    CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
-    input.reset();
-
     // binary line
     input.append("\xB\xC\xE\xF\n", 5);
     //printf("TEST: binary-line\n");
index bba2eb648646e9e6f75bfde06d28e049dc06a1df..d557e915b78d1d36368871ec1dce34a48f941260 100644 (file)
@@ -6,12 +6,22 @@
 class testHttpParser : public CPPUNIT_NS::TestFixture
 {
     CPPUNIT_TEST_SUITE( testHttpParser );
-    CPPUNIT_TEST( testParseRequestLine );
+    CPPUNIT_TEST( testParseRequestLineTerminators );
+    CPPUNIT_TEST( testParseRequestLineMethods );
+    CPPUNIT_TEST( testParseRequestLineProtocols );
+    CPPUNIT_TEST( testParseRequestLineStrange );
+    CPPUNIT_TEST( testParseRequestLineInvalid );
     CPPUNIT_TEST_SUITE_END();
 
 protected:
     void globalSetup(); // MemPools init etc.
-    void testParseRequestLine();
+
+    // request-line unit tests
+    void testParseRequestLineTerminators(); // terminator detection correct
+    void testParseRequestLineMethods();     // methoid detection correct
+    void testParseRequestLineProtocols();   // protocol tokens handled correctly
+    void testParseRequestLineStrange();     // strange but valid lines accepted
+    void testParseRequestLineInvalid();     // rejection of invalid lines happens
 };
 
 #endif