]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Add Unit-Tests for HttpReply
authorAmos Jeffries <squid3@treenet.co.nz>
Sun, 26 Jul 2009 09:24:07 +0000 (21:24 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Sun, 26 Jul 2009 09:24:07 +0000 (21:24 +1200)
Just the basics for some needed right now. This needs to be expanded.

Also, required to break some of the mime header parsing calls out into
mime_header.cc in preparation for splitting the icon handling from the
header handling and reduce dependencies on the new tests.

src/Makefile.am
src/mime.cc
src/mime_header.cc [new file with mode: 0644]
src/tests/stub_StatHist.cc [new file with mode: 0644]
src/tests/stub_store.cc
src/tests/testHttpReply.cc [new file with mode: 0644]
src/tests/testHttpReply.h [new file with mode: 0644]
src/tests/testHttpRequest.cc
src/tests/testHttpRequest.h

index 6838eaff77dd128e381c3890b919feac95b4c7d5..393c334b0c7a1516e2a65662f2d0602e9b1c2bf1 100644 (file)
@@ -402,6 +402,7 @@ squid_SOURCES = \
        MemObject.cc \
        MemObject.h \
        mime.cc \
+       mime_header.cc \
        multicast.cc \
        neighbors.cc \
        Packer.cc \
@@ -835,6 +836,7 @@ check_PROGRAMS+= tests/testAuth \
        tests/testEvent \
        tests/testEventLoop \
        tests/test_http_range \
+       tests/testHttpReply \
        tests/testHttpRequest \
        tests/testStore \
        tests/testString \
@@ -867,6 +869,61 @@ TESTS += $(check_PROGRAMS)
 #tests_testX_DEPENDENCIES= @SQUID_CPPUNIT_LA@ \
 #      $(top_builddir)/lib/libmiscutil.a
 
+
+# - add other component .(h|cc) files needed to link and run tests
+tests_testHttpReply_SOURCES=\
+       tests/testHttpReply.h \
+       tests/testHttpReply.cc \
+       tests/testMain.cc \
+       cbdata.h \
+       cbdata.cc \
+       ETag.cc \
+       HttpBody.cc \
+       HttpHdrCc.cc \
+       HttpHdrContRange.h \
+       HttpHdrContRange.cc \
+       HttpHdrRange.cc \
+       HttpHdrSc.h \
+       HttpHdrSc.cc \
+       HttpHdrScTarget.h \
+       HttpHdrScTarget.cc \
+       HttpHeader.h \
+       HttpHeader.cc \
+       HttpHeaderMask.h \
+       HttpHeaderTools.cc \
+       HttpMsg.h \
+       HttpMsg.cc \
+       HttpReply.h \
+       HttpReply.cc \
+       HttpStatusLine.h \
+       HttpStatusLine.cc \
+       mem.cc \
+       MemBuf.h \
+       MemBuf.cc \
+       mime_header.cc \
+       Packer.h \
+       Packer.cc \
+       tests/stub_cache_manager.cc \
+       tests/stub_StatHist.cc \
+       tests/stub_store.cc \
+       SquidString.h \
+       String.cc \
+       SquidTime.h \
+       time.cc
+nodist_tests_testHttpReply_SOURCES=\
+       $(TESTSOURCES)
+tests_testHttpReply_LDFLAGS = $(LIBADD_DL)
+tests_testHttpReply_LDADD=\
+       acl/libapi.la \
+       acl/libstate.la \
+       auth/libauth.la \
+       ip/libip.la \
+       @SQUID_CPPUNIT_LIBS@ \
+       @SQUID_CPPUNIT_LA@ \
+       -L../lib -lmiscutil
+tests_testHttpReply_DEPENDENCIES= @SQUID_CPPUNIT_LA@ \
+       $(top_builddir)/lib/libmiscutil.a
+
 tests_testAuth_SOURCES = \
        tests/testAuth.cc tests/testMain.cc  tests/testAuth.h \
        ConfigParser.cc \
@@ -1058,6 +1115,7 @@ tests_testCacheManager_SOURCES = \
        MemBuf.cc \
        MemObject.cc \
        mime.cc \
+       mime_header.cc \
        neighbors.cc \
        Packer.cc \
        Parsing.cc \
@@ -1227,6 +1285,7 @@ tests_testEvent_SOURCES = \
        MemBuf.cc \
        MemObject.cc \
        mime.cc \
+       mime_header.cc \
        neighbors.cc \
        Packer.cc \
        Parsing.cc \
@@ -1374,6 +1433,7 @@ tests_testEventLoop_SOURCES = \
        MemBuf.cc \
        MemObject.cc \
        mime.cc \
+       mime_header.cc \
        neighbors.cc \
        Packer.cc \
        Parsing.cc \
@@ -1511,6 +1571,7 @@ tests_test_http_range_SOURCES = \
        mem_node.cc \
        MemObject.cc \
        mime.cc \
+       mime_header.cc \
        multicast.cc \
        neighbors.cc \
        Parsing.cc \
@@ -1662,6 +1723,7 @@ tests_testHttpRequest_SOURCES = \
        MemBuf.cc \
        MemObject.cc \
        mime.cc \
+       mime_header.cc \
        neighbors.cc \
        Packer.cc \
        Parsing.cc \
@@ -2013,6 +2075,7 @@ tests_testURL_SOURCES = \
        MemBuf.cc \
        MemObject.cc \
        mime.cc \
+       mime_header.cc \
        neighbors.cc \
        Packer.cc \
        Parsing.cc \
index c08201c9f5fbe76aeebd874b34e451575022c919..eed3108fb205108855a7170a852b25f82b987d1b 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * $Id$
  *
- * DEBUG: section 25    MIME Parsing
+ * DEBUG: section 25    MIME Parsing and Internal Icons
  * AUTHOR: Harvest Derived
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -96,132 +96,6 @@ mimeEntry::operator delete (void *address)
     safe_free (address);
 }
 
-/* returns a pointer to a field-value of the first matching field-name */
-char *
-mime_get_header(const char *mime, const char *name)
-{
-    return mime_get_header_field(mime, name, NULL);
-}
-
-/*
- * returns a pointer to a field-value of the first matching field-name where
- * field-value matches prefix if any
- */
-char *
-mime_get_header_field(const char *mime, const char *name, const char *prefix)
-{
-    LOCAL_ARRAY(char, header, GET_HDR_SZ);
-    const char *p = NULL;
-    char *q = NULL;
-    char got = 0;
-    const int namelen = name ? strlen(name) : 0;
-    const int preflen = prefix ? strlen(prefix) : 0;
-    int l;
-
-    if (NULL == mime)
-        return NULL;
-
-    assert(NULL != name);
-
-    debugs(25, 5, "mime_get_header: looking for '" << name << "'");
-
-    for (p = mime; *p; p += strcspn(p, "\n\r")) {
-        if (strcmp(p, "\r\n\r\n") == 0 || strcmp(p, "\n\n") == 0)
-            return NULL;
-
-        while (xisspace(*p))
-            p++;
-
-        if (strncasecmp(p, name, namelen))
-            continue;
-
-        if (!xisspace(p[namelen]) && p[namelen] != ':')
-            continue;
-
-        l = strcspn(p, "\n\r") + 1;
-
-        if (l > GET_HDR_SZ)
-            l = GET_HDR_SZ;
-
-        xstrncpy(header, p, l);
-
-        debugs(25, 5, "mime_get_header: checking '" << header << "'");
-
-        q = header;
-
-        q += namelen;
-
-        if (*q == ':')
-            q++, got = 1;
-
-        while (xisspace(*q))
-            q++, got = 1;
-
-        if (got && prefix) {
-            /* we could process list entries here if we had strcasestr(). */
-            /* make sure we did not match a part of another field-value */
-            got = !strncasecmp(q, prefix, preflen) && !xisalpha(q[preflen]);
-        }
-
-        if (got) {
-            debugs(25, 5, "mime_get_header: returning '" << q << "'");
-            return q;
-        }
-    }
-
-    return NULL;
-}
-
-size_t
-headersEnd(const char *mime, size_t l)
-{
-    size_t e = 0;
-    int state = 1;
-
-    PROF_start(headersEnd);
-
-    while (e < l && state < 3) {
-        switch (state) {
-
-        case 0:
-
-            if ('\n' == mime[e])
-                state = 1;
-
-            break;
-
-        case 1:
-            if ('\r' == mime[e])
-                state = 2;
-            else if ('\n' == mime[e])
-                state = 3;
-            else
-                state = 0;
-
-            break;
-
-        case 2:
-            if ('\n' == mime[e])
-                state = 3;
-            else
-                state = 0;
-
-            break;
-
-        default:
-            break;
-        }
-
-        e++;
-    }
-    PROF_stop(headersEnd);
-
-    if (3 == state)
-        return e;
-
-    return 0;
-}
-
 static mimeEntry *
 mimeGetEntry(const char *fn, int skip_encodings)
 {
diff --git a/src/mime_header.cc b/src/mime_header.cc
new file mode 100644 (file)
index 0000000..02decf9
--- /dev/null
@@ -0,0 +1,164 @@
+
+/*
+ * $Id$
+ *
+ * DEBUG: section 25    MiME Header Parsing
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+
+#define GET_HDR_SZ 1024
+
+/* returns a pointer to a field-value of the first matching field-name */
+char *
+mime_get_header(const char *mime, const char *name)
+{
+    return mime_get_header_field(mime, name, NULL);
+}
+
+/*
+ * returns a pointer to a field-value of the first matching field-name where
+ * field-value matches prefix if any
+ */
+char *
+mime_get_header_field(const char *mime, const char *name, const char *prefix)
+{
+    LOCAL_ARRAY(char, header, GET_HDR_SZ);
+    const char *p = NULL;
+    char *q = NULL;
+    char got = 0;
+    const int namelen = name ? strlen(name) : 0;
+    const int preflen = prefix ? strlen(prefix) : 0;
+    int l;
+
+    if (NULL == mime)
+        return NULL;
+
+    assert(NULL != name);
+
+    debugs(25, 5, "mime_get_header: looking for '" << name << "'");
+
+    for (p = mime; *p; p += strcspn(p, "\n\r")) {
+        if (strcmp(p, "\r\n\r\n") == 0 || strcmp(p, "\n\n") == 0)
+            return NULL;
+
+        while (xisspace(*p))
+            p++;
+
+        if (strncasecmp(p, name, namelen))
+            continue;
+
+        if (!xisspace(p[namelen]) && p[namelen] != ':')
+            continue;
+
+        l = strcspn(p, "\n\r") + 1;
+
+        if (l > GET_HDR_SZ)
+            l = GET_HDR_SZ;
+
+        xstrncpy(header, p, l);
+
+        debugs(25, 5, "mime_get_header: checking '" << header << "'");
+
+        q = header;
+
+        q += namelen;
+
+        if (*q == ':')
+            q++, got = 1;
+
+        while (xisspace(*q))
+            q++, got = 1;
+
+        if (got && prefix) {
+            /* we could process list entries here if we had strcasestr(). */
+            /* make sure we did not match a part of another field-value */
+            got = !strncasecmp(q, prefix, preflen) && !xisalpha(q[preflen]);
+        }
+
+        if (got) {
+            debugs(25, 5, "mime_get_header: returning '" << q << "'");
+            return q;
+        }
+    }
+
+    return NULL;
+}
+
+size_t
+headersEnd(const char *mime, size_t l)
+{
+    size_t e = 0;
+    int state = 1;
+
+    PROF_start(headersEnd);
+
+    while (e < l && state < 3) {
+        switch (state) {
+
+        case 0:
+
+            if ('\n' == mime[e])
+                state = 1;
+
+            break;
+
+        case 1:
+            if ('\r' == mime[e])
+                state = 2;
+            else if ('\n' == mime[e])
+                state = 3;
+            else
+                state = 0;
+
+            break;
+
+        case 2:
+            if ('\n' == mime[e])
+                state = 3;
+            else
+                state = 0;
+
+            break;
+
+        default:
+            break;
+        }
+
+        e++;
+    }
+    PROF_stop(headersEnd);
+
+    if (3 == state)
+        return e;
+
+    return 0;
+}
diff --git a/src/tests/stub_StatHist.cc b/src/tests/stub_StatHist.cc
new file mode 100644 (file)
index 0000000..9bcc585
--- /dev/null
@@ -0,0 +1,22 @@
+#include "squid.h"
+
+// for StatHist definitions
+#include "protos.h"
+
+void
+statHistDump(const StatHist * H, StoreEntry * sentry, StatHistBinDumper * bd)
+{
+    fatal("statHistDump: Not implemented");
+}
+
+void
+statHistCount(StatHist * H, double val)
+{
+    fatal("statHistCount: Not implemented");
+}
+
+void
+statHistEnumInit(StatHist * H, int last_enum)
+{
+//NO-OP    fatal("statHistEnumInit: Not implemented");
+}
index b433feaa6a0491c80a458541cac8ffb9062dd492..6756f1e4878300bdd6c5b33532c2c80fd39b4f64 100644 (file)
@@ -40,13 +40,13 @@ StorePointer Store::CurrentRoot = NULL;
 extern "C" void
     storeAppendPrintf(StoreEntry * e, const char *fmt,...)
 {
-    fatal("Not implemented");
+    fatal("storeAppendPrintf: Not implemented");
 }
 
 extern "C" void
     storeAppendVPrintf(StoreEntry * e, const char *fmt, va_list vargs)
 {
-    fatal("Not implemented");
+    fatal("storeAppendVPrintf: Not implemented");
 }
 
 #ifndef _USE_INLINE_
diff --git a/src/tests/testHttpReply.cc b/src/tests/testHttpReply.cc
new file mode 100644 (file)
index 0000000..81fa94e
--- /dev/null
@@ -0,0 +1,183 @@
+#include "config.h"
+#include <cppunit/TestAssert.h>
+
+#include "testHttpReply.h"
+#include "HttpReply.h"
+#include "Mem.h"
+
+/* to avoid libsquid.la and its comm stuff */
+#include "TextException.cc"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( testHttpReply );
+
+struct SquidConfig Config;
+
+/* stub functions to link successfully */
+
+#include "Store.h"
+void
+StoreEntry::timestampsSet()
+{
+    fatal("StoreEntry::timestampsSet. Not implemented.");
+}
+
+void
+StoreEntry::setPublicKey()
+{
+    fatal("StoreEntry::setPulicKey. Not implemented.");
+}
+
+#include "MemObject.h"
+int64_t
+MemObject::endOffset() const
+{
+    return 0;
+}
+
+#include "ConfigParser.h"
+void
+ConfigParser::destruct()
+{
+// CALLED as shutdown no-op
+//    fatal("ConfigParser::destruct. Not implemented.");
+}
+
+void
+eventAdd(const char *name, EVH * func, void *arg, double when, int, bool cbdata)
+{
+// CALLED as setUp no-op
+//    fatal("eventAdd. Not implemented.");
+}
+
+/* end */
+
+void
+testHttpReply::setUp()
+{
+    Mem::Init();
+    httpHeaderInitModule();
+}
+
+void
+testHttpReply::testSanityCheckFirstLine()
+{
+    MemBuf input;
+    HttpReply engine;
+    http_status error = HTTP_STATUS_NONE;
+    size_t hdr_len;
+    input.init();
+
+    // a valid status line
+    input.append("HTTP/1.1 200 Okay\n\n", 19);
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT( 1 && engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_STATUS_NONE);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    input.append("HTTP/1.1    200  Okay     \n\n", 28);
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT( 2 && engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_STATUS_NONE);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+#if TODO // these cases are only checked after parse...
+    // invalid status line
+    input.append("HTTP/1.1 999 Okay\n\n", 19);
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT( 3 && !engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    input.append("HTTP/1.1    2000  Okay     \n\n", 29);
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT( 4 && engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_STATUS_NONE);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+#endif
+
+    // empty status line
+    input.append("\n\n", 2);
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT( 5 && !engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    input.append("      \n\n", 8);
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT( 6 && !engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    // status line with no message
+    input.append("HTTP/1.1 200\n\n", 14); /* real case seen */
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT(engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_STATUS_NONE);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    input.append("HTTP/1.1 200 \n\n", 15); /* real case seen */
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT(engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_STATUS_NONE);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+#if FUTURE
+
+    // status line with no status
+    input.append("HTTP/1.1 \n\n", 11);
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT(!engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    input.append("HTTP/1.1     \n\n", 15);
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT(!engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    input.append("HTTP/1.1  Okay\n\n", 16); /* real case seen */
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT(!engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    // status line with nul-byte
+    input.append("HTTP/1.1\0200 Okay\n\n", 19); /* real case seen */
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT(!engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    // status line with negative status
+    input.append("HTTP/1.1 -000\n\n", 15); /* real case seen */
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    CPPUNIT_ASSERT(!engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    // status line with non-HTTP protocol
+    input.append("ICY/1.1 200 Okay\n\n", 18); /* real case seen */
+    hdr_len = headersEnd(input.content(),input.contentSize());
+    /* NP: for nw ICY is handled as a pass-thru */
+    /*     Squid-3 will ignore it (and mangle the headers as per HTTP). */
+    CPPUNIT_ASSERT(!engine.sanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+#endif
+
+}
diff --git a/src/tests/testHttpReply.h b/src/tests/testHttpReply.h
new file mode 100644 (file)
index 0000000..cdaba09
--- /dev/null
@@ -0,0 +1,25 @@
+
+#ifndef SQUID_SRC_TEST_HTTP_REPLY_H
+#define SQUID_SRC_TEST_HTTP_REPLY_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+/*
+ * test HttpReply
+ */
+
+class testHttpReply : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( testHttpReply );
+    CPPUNIT_TEST( testSanityCheckFirstLine );
+    CPPUNIT_TEST_SUITE_END();
+
+public:
+    void setUp();
+
+protected:
+    void testSanityCheckFirstLine();
+};
+
+#endif
+
index 1e0c2f4556b362835ae4c655e24c476b6c3afa8a..a958be927926b1c7407ef9a9ddc943d3a4394a91 100644 (file)
@@ -9,6 +9,13 @@
 
 CPPUNIT_TEST_SUITE_REGISTRATION( testHttpRequest );
 
+/** wrapper for testing HttpRequest object private and protected functions */
+class PrivateHttpRequest : public HttpRequest
+{
+public:
+    bool doSanityCheckStartLine(MemBuf *b, const size_t h, http_status *e) { return sanityCheckStartLine(b,h,e); };
+};
+
 /* stub functions to link successfully */
 void
 shut_down(int)
@@ -26,6 +33,7 @@ void
 testHttpRequest::setUp()
 {
     Mem::Init();
+    httpHeaderInitModule();
 }
 
 /*
@@ -150,3 +158,60 @@ testHttpRequest::testIPv6HostColonBug()
     CPPUNIT_ASSERT_EQUAL(String("http://2000:800::45/foo"), String(url));
     xfree(url);
 }
+
+void
+testHttpRequest::testSanityCheckStartLine()
+{
+    MemBuf input;
+    PrivateHttpRequest engine;
+    http_status error = HTTP_STATUS_NONE;
+    size_t hdr_len;
+    input.init();
+
+    // a valid request line
+    input.append("GET / HTTP/1.1\n\n", 16);
+    hdr_len = headersEnd(input.content(), input.contentSize());
+    CPPUNIT_ASSERT(engine.doSanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_STATUS_NONE);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    input.append("GET  /  HTTP/1.1\n\n", 18);
+    hdr_len = headersEnd(input.content(), input.contentSize());
+    CPPUNIT_ASSERT(engine.doSanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_STATUS_NONE);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    // strange but valid methods
+    input.append(". / HTTP/1.1\n\n", 14);
+    hdr_len = headersEnd(input.content(), input.contentSize());
+    CPPUNIT_ASSERT(engine.doSanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_STATUS_NONE);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+    input.append("OPTIONS * HTTP/1.1\n\n", 20);
+    hdr_len = headersEnd(input.content(), input.contentSize());
+    CPPUNIT_ASSERT(engine.doSanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_STATUS_NONE);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+
+// TODO no method
+
+// TODO binary code in method
+
+// TODO no URL
+
+// TODO no status (okay)
+
+// TODO non-HTTP protocol
+
+    input.append("      \n\n", 8);
+    hdr_len = headersEnd(input.content(), input.contentSize());
+    CPPUNIT_ASSERT(!engine.doSanityCheckStartLine(&input, hdr_len, &error) );
+    CPPUNIT_ASSERT_EQUAL(error, HTTP_INVALID_HEADER);
+    input.reset();
+    error = HTTP_STATUS_NONE;
+}
index 9e0735f34fdff99a1045d1b1ad680a76de9b0284..efdec613a6247a581d11380327cdb7db6af3f4e1 100644 (file)
@@ -14,6 +14,7 @@ class testHttpRequest : public CPPUNIT_NS::TestFixture
     CPPUNIT_TEST( testCreateFromUrlAndMethod );
     CPPUNIT_TEST( testCreateFromUrl );
     CPPUNIT_TEST( testIPv6HostColonBug );
+    CPPUNIT_TEST( testSanityCheckStartLine );
     CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -23,6 +24,7 @@ protected:
     void testCreateFromUrlAndMethod();
     void testCreateFromUrl();
     void testIPv6HostColonBug();
+    void testSanityCheckStartLine();
 };
 
 #endif