summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/test/TestHttpHeader.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xbmc/utils/test/TestHttpHeader.cpp505
1 files changed, 505 insertions, 0 deletions
diff --git a/xbmc/utils/test/TestHttpHeader.cpp b/xbmc/utils/test/TestHttpHeader.cpp
new file mode 100644
index 0000000..1aeecc7
--- /dev/null
+++ b/xbmc/utils/test/TestHttpHeader.cpp
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "utils/HttpHeader.h"
+
+#include <string.h>
+
+#include <gtest/gtest.h>
+
+#define CHECK_CNT_TYPE_NAME "Content-Type"
+#define CHECK_CONTENT_TYPE_HTML "text/html"
+#define CHECK_CONTENT_TYPE_HTML_CHRS "text/html; charset=WINDOWS-1251"
+#define CHECK_CONTENT_TYPE_XML_CHRS "text/xml; charset=uTf-8"
+#define CHECK_CONTENT_TYPE_TEXT "text/plain"
+#define CHECK_DATE_NAME "Date"
+#define CHECK_DATE_VALUE1 "Thu, 09 Jan 2014 17:58:30 GMT"
+#define CHECK_DATE_VALUE2 "Thu, 09 Jan 2014 20:21:20 GMT"
+#define CHECK_DATE_VALUE3 "Thu, 09 Jan 2014 20:25:02 GMT"
+#define CHECK_PROT_LINE_200 "HTTP/1.1 200 OK"
+#define CHECK_PROT_LINE_301 "HTTP/1.1 301 Moved Permanently"
+
+#define CHECK_HEADER_SMPL CHECK_PROT_LINE_200 "\r\n" \
+ CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n" \
+ "\r\n"
+
+#define CHECK_HEADER_L1 CHECK_PROT_LINE_200 "\r\n" \
+ "Server: nginx/1.4.4\r\n" \
+ CHECK_DATE_NAME ": " CHECK_DATE_VALUE1 "\r\n" \
+ CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML_CHRS "\r\n" \
+ "Transfer-Encoding: chunked\r\n" \
+ "Connection: close\r\n" \
+ "Set-Cookie: PHPSESSID=90857d437518db8f0944ca012761048a; path=/; domain=example.com\r\n" \
+ "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n" \
+ "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n" \
+ "Pragma: no-cache\r\n" \
+ "Set-Cookie: user_country=ot; expires=Thu, 09-Jan-2014 18:58:30 GMT; path=/; domain=.example.com\r\n" \
+ "\r\n"
+
+#define CHECK_HEADER_R CHECK_PROT_LINE_301 "\r\n" \
+ "Server: nginx/1.4.4\r\n" \
+ CHECK_DATE_NAME ": " CHECK_DATE_VALUE2 "\r\n" \
+ CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n" \
+ "Content-Length: 150\r\n" \
+ "Connection: close\r\n" \
+ "Location: http://www.Example.Com\r\n" \
+ "\r\n"
+
+#define CHECK_HEADER_L2 CHECK_PROT_LINE_200 "\r\n" \
+ CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n" \
+ "Server: Apache/2.4.7 (Unix) mod_wsgi/3.4 Python/2.7.5 OpenSSL/1.0.1e\r\n" \
+ "Last-Modified: Thu, 09 Jan 2014 20:10:28 GMT\r\n" \
+ "ETag: \"9a97-4ef8f335ebd10\"\r\n" \
+ "Accept-Ranges: bytes\r\n" \
+ "Content-Length: 33355\r\n" \
+ "Vary: Accept-Encoding\r\n" \
+ "Cache-Control: max-age=3600\r\n" \
+ "Expires: Thu, 09 Jan 2014 21:25:02 GMT\r\n" \
+ "Connection: close\r\n" \
+ CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_XML_CHRS "\r\n" \
+ "\r\n"
+
+// local helper function: replace substrings
+std::string strReplace(const std::string& str, const std::string& from, const std::string& to)
+{
+ std::string result;
+ size_t prevPos = 0;
+ size_t pos;
+ const size_t len = str.length();
+
+ do
+ {
+ pos = str.find(from, prevPos);
+ result.append(str, prevPos, pos - prevPos);
+ if (pos >= len)
+ break;
+ result.append(to);
+ prevPos = pos + from.length();
+ } while (true);
+
+ return result;
+}
+
+TEST(TestHttpHeader, General)
+{
+ /* check freshly created object */
+ CHttpHeader testHdr;
+ EXPECT_TRUE(testHdr.GetHeader().empty()) << "Newly created object is not empty";
+ EXPECT_TRUE(testHdr.GetProtoLine().empty()) << "Newly created object has non-empty protocol line";
+ EXPECT_TRUE(testHdr.GetMimeType().empty()) << "Newly created object has non-empty MIME-type";
+ EXPECT_TRUE(testHdr.GetCharset().empty()) << "Newly created object has non-empty charset";
+ EXPECT_TRUE(testHdr.GetValue("foo").empty()) << "Newly created object has some parameter";
+ EXPECT_TRUE(testHdr.GetValues("bar").empty()) << "Newly created object has some parameters";
+ EXPECT_FALSE(testHdr.IsHeaderDone()) << "Newly created object has \"parsing finished\" state";
+
+ /* check general functions in simple case */
+ testHdr.Parse(CHECK_HEADER_SMPL);
+ EXPECT_FALSE(testHdr.GetHeader().empty()) << "Parsed header is empty";
+ EXPECT_FALSE(testHdr.GetProtoLine().empty()) << "Parsed header has empty protocol line";
+ EXPECT_FALSE(testHdr.GetMimeType().empty()) << "Parsed header has empty MIME-type";
+ EXPECT_FALSE(testHdr.GetValue(CHECK_CNT_TYPE_NAME).empty()) << "Parsed header has empty \"" CHECK_CNT_TYPE_NAME "\" parameter";
+ EXPECT_FALSE(testHdr.GetValues(CHECK_CNT_TYPE_NAME).empty()) << "Parsed header has no \"" CHECK_CNT_TYPE_NAME "\" parameters";
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Parsed header has \"parsing not finished\" state";
+
+ /* check clearing of object */
+ testHdr.Clear();
+ EXPECT_TRUE(testHdr.GetHeader().empty()) << "Cleared object is not empty";
+ EXPECT_TRUE(testHdr.GetProtoLine().empty()) << "Cleared object has non-empty protocol line";
+ EXPECT_TRUE(testHdr.GetMimeType().empty()) << "Cleared object has non-empty MIME-type";
+ EXPECT_TRUE(testHdr.GetCharset().empty()) << "Cleared object has non-empty charset";
+ EXPECT_TRUE(testHdr.GetValue(CHECK_CNT_TYPE_NAME).empty()) << "Cleared object has some parameter";
+ EXPECT_TRUE(testHdr.GetValues(CHECK_CNT_TYPE_NAME).empty()) << "Cleared object has some parameters";
+ EXPECT_FALSE(testHdr.IsHeaderDone()) << "Cleared object has \"parsing finished\" state";
+
+ /* check general functions after object clearing */
+ testHdr.Parse(CHECK_HEADER_R);
+ EXPECT_FALSE(testHdr.GetHeader().empty()) << "Parsed header is empty";
+ EXPECT_FALSE(testHdr.GetProtoLine().empty()) << "Parsed header has empty protocol line";
+ EXPECT_FALSE(testHdr.GetMimeType().empty()) << "Parsed header has empty MIME-type";
+ EXPECT_FALSE(testHdr.GetValue(CHECK_CNT_TYPE_NAME).empty()) << "Parsed header has empty \"" CHECK_CNT_TYPE_NAME "\" parameter";
+ EXPECT_FALSE(testHdr.GetValues(CHECK_CNT_TYPE_NAME).empty()) << "Parsed header has no \"" CHECK_CNT_TYPE_NAME "\" parameters";
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Parsed header has \"parsing not finished\" state";
+}
+
+TEST(TestHttpHeader, Parse)
+{
+ CHttpHeader testHdr;
+
+ /* check parsing line-by-line */
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
+ EXPECT_FALSE(testHdr.IsHeaderDone()) << "Not completed header has \"parsing finished\" state";
+ testHdr.Parse(CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n");
+ EXPECT_FALSE(testHdr.IsHeaderDone()) << "Not completed header has \"parsing finished\" state";
+ testHdr.Parse("\r\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ(CHECK_PROT_LINE_200, testHdr.GetProtoLine().c_str()) << "Wrong protocol line";
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
+
+ /* check autoclearing when new header is parsed */
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
+ EXPECT_FALSE(testHdr.IsHeaderDone()) << "Not completed header has \"parsing finished\" state";
+ EXPECT_TRUE(testHdr.GetValues(CHECK_CNT_TYPE_NAME).empty()) << "Cleared header has some parameters";
+ testHdr.Clear();
+ EXPECT_TRUE(testHdr.GetHeader().empty()) << "Cleared object is not empty";
+
+ /* general check parsing */
+ testHdr.Parse(CHECK_HEADER_SMPL);
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STRCASEEQ(CHECK_HEADER_SMPL, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
+ testHdr.Parse(CHECK_HEADER_L1);
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STRCASEEQ(CHECK_HEADER_L1, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
+ EXPECT_STREQ("Thu, 09 Jan 2014 17:58:30 GMT", testHdr.GetValue("Date").c_str()); // case-sensitive match of value
+ testHdr.Parse(CHECK_HEADER_L2);
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STRCASEEQ(CHECK_HEADER_L2, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
+ EXPECT_STREQ("Thu, 09 Jan 2014 20:10:28 GMT", testHdr.GetValue("Last-Modified").c_str()); // case-sensitive match of value
+ testHdr.Parse(CHECK_HEADER_R);
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STRCASEEQ(CHECK_HEADER_R, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
+ EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("Location").c_str()); // case-sensitive match of value
+
+ /* check support for '\n' line endings */
+ testHdr.Parse(strReplace(CHECK_HEADER_SMPL, "\r\n", "\n"));
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STRCASEEQ(CHECK_HEADER_SMPL, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ testHdr.Parse(strReplace(CHECK_HEADER_L1, "\r\n", "\n"));
+ EXPECT_STRCASEEQ(CHECK_HEADER_L1, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ testHdr.Parse(strReplace(CHECK_HEADER_L2, "\r\n", "\n"));
+ EXPECT_STRCASEEQ(CHECK_HEADER_L2, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ testHdr.Parse(CHECK_PROT_LINE_200 "\n" CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n"); // mixed "\n" and "\r\n"
+ testHdr.Parse("\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STRCASEEQ(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n\r\n", testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
+
+ /* check trimming of whitespaces for parameter name and value */
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n\r\n");
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML " \r\n\r\n");
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ":" CHECK_CONTENT_TYPE_HTML " \r\n\r\n");
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ":\t" CHECK_CONTENT_TYPE_HTML " \t \r\n\r\n");
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ":\t " CHECK_CONTENT_TYPE_HTML " \t \r\n\r\n");
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME "\t:" CHECK_CONTENT_TYPE_HTML " \t \r\n\r\n");
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME " \t : " CHECK_CONTENT_TYPE_HTML " \t \r\n\r\n");
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
+}
+
+TEST(TestHttpHeader, Parse_Multiline)
+{
+ CHttpHeader testHdr;
+
+ /* Check multiline parameter parsing line-by-line */
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
+ testHdr.Parse(CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n");
+ testHdr.Parse("X-Comment: This\r\n"); // between singleline parameters
+ testHdr.Parse(" is\r\n");
+ testHdr.Parse(" multi\r\n");
+ testHdr.Parse(" line\r\n");
+ testHdr.Parse(" value\r\n");
+ testHdr.Parse(CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_TEXT "\r\n");
+ testHdr.Parse("\r\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
+ testHdr.Parse("X-Comment: This\r\n"); // first parameter
+ testHdr.Parse(" is\r\n");
+ testHdr.Parse(" multi\r\n");
+ testHdr.Parse(" line\r\n");
+ testHdr.Parse(" value\r\n");
+ testHdr.Parse(CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_TEXT "\r\n");
+ testHdr.Parse("\r\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
+ testHdr.Parse(CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n");
+ testHdr.Parse("X-Comment: This\r\n"); // last parameter
+ testHdr.Parse(" is\r\n");
+ testHdr.Parse(" multi\r\n");
+ testHdr.Parse(" line\r\n");
+ testHdr.Parse(" value\r\n");
+ testHdr.Parse("\r\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
+ testHdr.Parse("X-Comment: This\r\n"); // the only parameter
+ testHdr.Parse(" is\r\n");
+ testHdr.Parse(" multi\r\n");
+ testHdr.Parse(" line\r\n");
+ testHdr.Parse(" value\r\n");
+ testHdr.Parse("\r\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
+ testHdr.Parse("X-Comment: This\n"); // the only parameter with mixed ending style
+ testHdr.Parse(" is\r\n");
+ testHdr.Parse(" multi\n");
+ testHdr.Parse(" line\r\n");
+ testHdr.Parse(" value\n");
+ testHdr.Parse("\r\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ /* Check multiline parameter parsing as one line */
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\nX-Comment: This\r\n is\r\n multi\r\n line\r\n value\r\n" \
+ CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_TEXT "\r\n\r\n"); // between singleline parameters
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\nX-Comment: This\r\n is\r\n multi\r\n line\r\n value\r\n" \
+ CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_TEXT "\r\n\r\n"); // first parameter
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\nX-Comment: This\r\n is\r\n multi\r\n line\r\n value\r\n\r\n"); // last parameter
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\nX-Comment: This\r\n is\r\n multi\r\n line\r\n value\r\n\r\n"); // the only parameter
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\nX-Comment: This\n is\r\n multi\r\n line\n value\r\n\n"); // the only parameter with mixed ending style
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ /* Check multiline parameter parsing as mixed one/many lines */
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\nX-Comment: This\n is\r\n multi\r\n");
+ testHdr.Parse(" line\n value\r\n\n"); // the only parameter with mixed ending style
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ /* Check parsing of multiline parameter with ':' in value */
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\nX-Comment: This\r\n is:\r\n mul:ti\r\n");
+ testHdr.Parse(" :line\r\n valu:e\r\n\n"); // the only parameter
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("This is: mul:ti :line valu:e", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
+
+ /* Check multiline parameter parsing with trimming */
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
+ testHdr.Parse(CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n");
+ testHdr.Parse("Server: Apache/2.4.7 (Unix)\r\n"); // last parameter, line-by-line parsing
+ testHdr.Parse(" mod_wsgi/3.4 \r\n");
+ testHdr.Parse("\tPython/2.7.5\r\n");
+ testHdr.Parse("\t \t \tOpenSSL/1.0.1e\r\n");
+ testHdr.Parse("\r\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_GE(strlen("Apache/2.4.7 (Unix) mod_wsgi/3.4 \tPython/2.7.5\t \t \tOpenSSL/1.0.1e"), testHdr.GetValue("Server").length()) << "Length of miltiline value is greater than length of original string";
+ EXPECT_LE(strlen("Apache/2.4.7 (Unix) mod_wsgi/3.4 Python/2.7.5 OpenSSL/1.0.1e"), testHdr.GetValue("Server").length()) << "Length of miltiline value is less than length of trimmed original string";
+ EXPECT_STREQ("Apache/2.4.7(Unix)mod_wsgi/3.4Python/2.7.5OpenSSL/1.0.1e", strReplace(strReplace(testHdr.GetValue("Server"), " ", ""), "\t", "").c_str()) << "Multiline value with removed whitespaces does not match original string with removed whitespaces";
+
+ testHdr.Clear();
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
+ testHdr.Parse(CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n");
+ testHdr.Parse("Server: Apache/2.4.7 (Unix)\r\n mod_wsgi/3.4 \n"); // last parameter, mixed line-by-line/one line parsing, mixed line ending
+ testHdr.Parse("\tPython/2.7.5\n\t \t \tOpenSSL/1.0.1e\r\n");
+ testHdr.Parse("\r\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_GE(strlen("Apache/2.4.7 (Unix) mod_wsgi/3.4 \tPython/2.7.5\t \t \tOpenSSL/1.0.1e"), testHdr.GetValue("Server").length()) << "Length of miltiline value is greater than length of original string";
+ EXPECT_LE(strlen("Apache/2.4.7 (Unix) mod_wsgi/3.4 Python/2.7.5 OpenSSL/1.0.1e"), testHdr.GetValue("Server").length()) << "Length of miltiline value is less than length of trimmed original string";
+ EXPECT_STREQ("Apache/2.4.7(Unix)mod_wsgi/3.4Python/2.7.5OpenSSL/1.0.1e", strReplace(strReplace(testHdr.GetValue("Server"), " ", ""), "\t", "").c_str()) << "Multiline value with removed whitespaces does not match original string with removed whitespaces";
+}
+
+TEST(TestHttpHeader, GetValue)
+{
+ CHttpHeader testHdr;
+
+ /* Check that all parameters values can be retrieved */
+ testHdr.Parse(CHECK_HEADER_R);
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("nginx/1.4.4", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ(CHECK_DATE_VALUE2, testHdr.GetValue(CHECK_DATE_NAME).c_str()) << "Wrong parameter value";
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("150", testHdr.GetValue("Content-Length").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("close", testHdr.GetValue("Connection").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("Location").c_str()) << "Wrong parameter value";
+ EXPECT_TRUE(testHdr.GetValue("foo").empty()) << "Some value is returned for non-existed parameter";
+
+ /* Check that all parameters values can be retrieved in random order */
+ testHdr.Parse(CHECK_HEADER_R);
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
+ EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("Location").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("Location").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("close", testHdr.GetValue("Connection").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("nginx/1.4.4", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("150", testHdr.GetValue("Content-Length").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ(CHECK_DATE_VALUE2, testHdr.GetValue(CHECK_DATE_NAME).c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("nginx/1.4.4", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
+ EXPECT_TRUE(testHdr.GetValue("foo").empty()) << "Some value is returned for non-existed parameter";
+
+ /* Check that parameters name is case-insensitive and value is case-sensitive*/
+ EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("location").c_str()) << "Wrong parameter value for lowercase name";
+ EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("LOCATION").c_str()) << "Wrong parameter value for UPPERCASE name";
+ EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("LoCAtIOn").c_str()) << "Wrong parameter value for MiXEdcASe name";
+
+ /* Check value of last added parameter with the same name is returned */
+ testHdr.Parse(CHECK_HEADER_L1);
+ EXPECT_STREQ("close", testHdr.GetValue("Connection").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("user_country=ot; expires=Thu, 09-Jan-2014 18:58:30 GMT; path=/; domain=.example.com", testHdr.GetValue("Set-Cookie").c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("user_country=ot; expires=Thu, 09-Jan-2014 18:58:30 GMT; path=/; domain=.example.com", testHdr.GetValue("set-cookie").c_str()) << "Wrong parameter value for lowercase name";
+}
+
+TEST(TestHttpHeader, GetValues)
+{
+ CHttpHeader testHdr;
+
+ /* Check that all parameter values can be retrieved and order of values is correct */
+ testHdr.Parse(CHECK_HEADER_L1);
+ EXPECT_EQ(1U, testHdr.GetValues("Server").size()) << "Wrong number of values for parameter \"Server\"";
+ EXPECT_STREQ("nginx/1.4.4", testHdr.GetValues("Server")[0].c_str()) << "Wrong parameter value";
+ EXPECT_EQ(2U, testHdr.GetValues("Set-Cookie").size()) << "Wrong number of values for parameter \"Set-Cookie\"";
+ EXPECT_STREQ("PHPSESSID=90857d437518db8f0944ca012761048a; path=/; domain=example.com", testHdr.GetValues("Set-Cookie")[0].c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("user_country=ot; expires=Thu, 09-Jan-2014 18:58:30 GMT; path=/; domain=.example.com", testHdr.GetValues("Set-Cookie")[1].c_str()) << "Wrong parameter value";
+ EXPECT_TRUE(testHdr.GetValues("foo").empty()) << "Some values are returned for non-existed parameter";
+}
+
+TEST(TestHttpHeader, AddParam)
+{
+ CHttpHeader testHdr;
+
+ /* General functionality */
+ testHdr.AddParam("server", "Microsoft-IIS/8.0");
+ EXPECT_STREQ("Microsoft-IIS/8.0", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
+
+ /* Interfere with parsing */
+ EXPECT_FALSE(testHdr.IsHeaderDone()) << "\"AddParam\" set \"parsing finished\" state";
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\nServer: nginx/1.4.4\r\n\r\n");
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Parsed header has \"parsing not finished\" state";
+ EXPECT_STREQ("nginx/1.4.4", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
+ testHdr.AddParam("server", "Apache/2.4.7");
+ EXPECT_STREQ("Apache/2.4.7", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
+ EXPECT_EQ(3U, testHdr.GetValues("Server").size()) << "Wrong number of values for parameter \"Server\"";
+
+ /* Multiple values */
+ testHdr.AddParam("X-foo", "bar1");
+ testHdr.AddParam("x-foo", "bar2");
+ testHdr.AddParam("x-fOO", "bar3");
+ EXPECT_EQ(3U, testHdr.GetValues("X-FOO").size()) << "Wrong number of values for parameter \"X-foo\"";
+ EXPECT_STREQ("bar1", testHdr.GetValues("X-FOo")[0].c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("bar2", testHdr.GetValues("X-fOo")[1].c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("bar3", testHdr.GetValues("x-fOo")[2].c_str()) << "Wrong parameter value";
+ EXPECT_STREQ("bar3", testHdr.GetValue("x-foo").c_str()) << "Wrong parameter value";
+
+ /* Overwrite value */
+ EXPECT_TRUE(testHdr.IsHeaderDone()) << "Parsed header has \"parsing not finished\" state";
+ testHdr.AddParam("x-fOO", "superbar", true);
+ EXPECT_EQ(1U, testHdr.GetValues("X-FoO").size()) << "Wrong number of values for parameter \"X-foo\"";
+ EXPECT_STREQ("superbar", testHdr.GetValue("x-foo").c_str()) << "Wrong parameter value";
+
+ /* Check name trimming */
+ testHdr.AddParam("\tx-fOO\t ", "bar");
+ EXPECT_EQ(2U, testHdr.GetValues("X-FoO").size()) << "Wrong number of values for parameter \"X-foo\"";
+ EXPECT_STREQ("bar", testHdr.GetValue("x-foo").c_str()) << "Wrong parameter value";
+ testHdr.AddParam(" SerVer \t ", "fakeSrv", true);
+ EXPECT_EQ(1U, testHdr.GetValues("serveR").size()) << "Wrong number of values for parameter \"Server\"";
+ EXPECT_STREQ("fakeSrv", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
+
+ /* Check value trimming */
+ testHdr.AddParam("X-TestParam", " testValue1");
+ EXPECT_STREQ("testValue1", testHdr.GetValue("X-TestParam").c_str()) << "Wrong parameter value";
+ testHdr.AddParam("X-TestParam", "\ttestValue2 and more \t ");
+ EXPECT_STREQ("testValue2 and more", testHdr.GetValue("X-TestParam").c_str()) << "Wrong parameter value";
+
+ /* Empty name or value */
+ testHdr.Clear();
+ testHdr.AddParam("X-TestParam", " ");
+ EXPECT_TRUE(testHdr.GetHeader().empty()) << "Parameter with empty value was added";
+ testHdr.AddParam("\t\t", "value");
+ EXPECT_TRUE(testHdr.GetHeader().empty());
+ testHdr.AddParam(" ", "\t");
+ EXPECT_TRUE(testHdr.GetHeader().empty());
+}
+
+TEST(TestHttpHeader, GetMimeType)
+{
+ CHttpHeader testHdr;
+
+ /* General functionality */
+ EXPECT_TRUE(testHdr.GetMimeType().empty()) << "Newly created object has non-empty MIME-type";
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\nServer: nginx/1.4.4\r\n\r\n");
+ EXPECT_TRUE(testHdr.GetMimeType().empty()) << "Non-empty MIME-type for header without MIME-type";
+ testHdr.Parse(CHECK_HEADER_SMPL);
+ EXPECT_STREQ("text/html", testHdr.GetMimeType().c_str()) << "Wrong MIME-type";
+ testHdr.Parse(CHECK_HEADER_L1);
+ EXPECT_STREQ("text/html", testHdr.GetMimeType().c_str()) << "Wrong MIME-type";
+ testHdr.Parse(CHECK_HEADER_L2);
+ EXPECT_STREQ("text/xml", testHdr.GetMimeType().c_str()) << "Wrong MIME-type";
+ testHdr.Parse(CHECK_HEADER_R);
+ EXPECT_STREQ("text/html", testHdr.GetMimeType().c_str()) << "Wrong MIME-type";
+
+ /* Overwrite by AddParam */
+ testHdr.AddParam(CHECK_CNT_TYPE_NAME, CHECK_CONTENT_TYPE_TEXT);
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_TEXT, testHdr.GetMimeType().c_str()) << "MIME-type was not overwritten by \"AddParam\"";
+
+ /* Correct trimming */
+ testHdr.AddParam(CHECK_CNT_TYPE_NAME, " " CHECK_CONTENT_TYPE_TEXT " \t ;foo=bar");
+ EXPECT_STREQ(CHECK_CONTENT_TYPE_TEXT, testHdr.GetMimeType().c_str()) << "MIME-type is not trimmed correctly";
+}
+
+
+TEST(TestHttpHeader, GetCharset)
+{
+ CHttpHeader testHdr;
+
+ /* General functionality */
+ EXPECT_TRUE(testHdr.GetCharset().empty()) << "Newly created object has non-empty charset";
+ testHdr.Parse(CHECK_PROT_LINE_200 "\r\nServer: nginx/1.4.4\r\n\r\n");
+ EXPECT_TRUE(testHdr.GetCharset().empty()) << "Non-empty charset for header without charset";
+ testHdr.Parse(CHECK_HEADER_SMPL);
+ EXPECT_TRUE(testHdr.GetCharset().empty()) << "Non-empty charset for header without charset";
+ testHdr.Parse(CHECK_HEADER_L1);
+ EXPECT_STREQ("WINDOWS-1251", testHdr.GetCharset().c_str()) << "Wrong charset value";
+ testHdr.Parse(CHECK_HEADER_L2);
+ EXPECT_STREQ("UTF-8", testHdr.GetCharset().c_str()) << "Wrong charset value";
+
+ /* Overwrite by AddParam */
+ testHdr.AddParam(CHECK_CNT_TYPE_NAME, CHECK_CONTENT_TYPE_TEXT "; charset=WINDOWS-1252");
+ EXPECT_STREQ("WINDOWS-1252", testHdr.GetCharset().c_str()) << "Charset was not overwritten by \"AddParam\"";
+
+ /* Correct trimming */
+ testHdr.AddParam(CHECK_CNT_TYPE_NAME, "text/plain;charset=WINDOWS-1251");
+ EXPECT_STREQ("WINDOWS-1251", testHdr.GetCharset().c_str()) << "Wrong charset value";
+ testHdr.AddParam(CHECK_CNT_TYPE_NAME, "text/plain ;\tcharset=US-AScII\t");
+ EXPECT_STREQ("US-ASCII", testHdr.GetCharset().c_str()) << "Wrong charset value";
+ testHdr.AddParam(CHECK_CNT_TYPE_NAME, "text/html ; \tcharset=\"uTF-8\"\t");
+ EXPECT_STREQ("UTF-8", testHdr.GetCharset().c_str()) << "Wrong charset value";
+ testHdr.AddParam(CHECK_CNT_TYPE_NAME, " \ttext/xml\t;\tcharset=uTF-16 ");
+ EXPECT_STREQ("UTF-16", testHdr.GetCharset().c_str()) << "Wrong charset value";
+}