summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/test/TestHttpHeader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/test/TestHttpHeader.cpp')
-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 @@
1/*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#include "utils/HttpHeader.h"
10
11#include <string.h>
12
13#include <gtest/gtest.h>
14
15#define CHECK_CNT_TYPE_NAME "Content-Type"
16#define CHECK_CONTENT_TYPE_HTML "text/html"
17#define CHECK_CONTENT_TYPE_HTML_CHRS "text/html; charset=WINDOWS-1251"
18#define CHECK_CONTENT_TYPE_XML_CHRS "text/xml; charset=uTf-8"
19#define CHECK_CONTENT_TYPE_TEXT "text/plain"
20#define CHECK_DATE_NAME "Date"
21#define CHECK_DATE_VALUE1 "Thu, 09 Jan 2014 17:58:30 GMT"
22#define CHECK_DATE_VALUE2 "Thu, 09 Jan 2014 20:21:20 GMT"
23#define CHECK_DATE_VALUE3 "Thu, 09 Jan 2014 20:25:02 GMT"
24#define CHECK_PROT_LINE_200 "HTTP/1.1 200 OK"
25#define CHECK_PROT_LINE_301 "HTTP/1.1 301 Moved Permanently"
26
27#define CHECK_HEADER_SMPL CHECK_PROT_LINE_200 "\r\n" \
28 CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n" \
29 "\r\n"
30
31#define CHECK_HEADER_L1 CHECK_PROT_LINE_200 "\r\n" \
32 "Server: nginx/1.4.4\r\n" \
33 CHECK_DATE_NAME ": " CHECK_DATE_VALUE1 "\r\n" \
34 CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML_CHRS "\r\n" \
35 "Transfer-Encoding: chunked\r\n" \
36 "Connection: close\r\n" \
37 "Set-Cookie: PHPSESSID=90857d437518db8f0944ca012761048a; path=/; domain=example.com\r\n" \
38 "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n" \
39 "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n" \
40 "Pragma: no-cache\r\n" \
41 "Set-Cookie: user_country=ot; expires=Thu, 09-Jan-2014 18:58:30 GMT; path=/; domain=.example.com\r\n" \
42 "\r\n"
43
44#define CHECK_HEADER_R CHECK_PROT_LINE_301 "\r\n" \
45 "Server: nginx/1.4.4\r\n" \
46 CHECK_DATE_NAME ": " CHECK_DATE_VALUE2 "\r\n" \
47 CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n" \
48 "Content-Length: 150\r\n" \
49 "Connection: close\r\n" \
50 "Location: http://www.Example.Com\r\n" \
51 "\r\n"
52
53#define CHECK_HEADER_L2 CHECK_PROT_LINE_200 "\r\n" \
54 CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n" \
55 "Server: Apache/2.4.7 (Unix) mod_wsgi/3.4 Python/2.7.5 OpenSSL/1.0.1e\r\n" \
56 "Last-Modified: Thu, 09 Jan 2014 20:10:28 GMT\r\n" \
57 "ETag: \"9a97-4ef8f335ebd10\"\r\n" \
58 "Accept-Ranges: bytes\r\n" \
59 "Content-Length: 33355\r\n" \
60 "Vary: Accept-Encoding\r\n" \
61 "Cache-Control: max-age=3600\r\n" \
62 "Expires: Thu, 09 Jan 2014 21:25:02 GMT\r\n" \
63 "Connection: close\r\n" \
64 CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_XML_CHRS "\r\n" \
65 "\r\n"
66
67// local helper function: replace substrings
68std::string strReplace(const std::string& str, const std::string& from, const std::string& to)
69{
70 std::string result;
71 size_t prevPos = 0;
72 size_t pos;
73 const size_t len = str.length();
74
75 do
76 {
77 pos = str.find(from, prevPos);
78 result.append(str, prevPos, pos - prevPos);
79 if (pos >= len)
80 break;
81 result.append(to);
82 prevPos = pos + from.length();
83 } while (true);
84
85 return result;
86}
87
88TEST(TestHttpHeader, General)
89{
90 /* check freshly created object */
91 CHttpHeader testHdr;
92 EXPECT_TRUE(testHdr.GetHeader().empty()) << "Newly created object is not empty";
93 EXPECT_TRUE(testHdr.GetProtoLine().empty()) << "Newly created object has non-empty protocol line";
94 EXPECT_TRUE(testHdr.GetMimeType().empty()) << "Newly created object has non-empty MIME-type";
95 EXPECT_TRUE(testHdr.GetCharset().empty()) << "Newly created object has non-empty charset";
96 EXPECT_TRUE(testHdr.GetValue("foo").empty()) << "Newly created object has some parameter";
97 EXPECT_TRUE(testHdr.GetValues("bar").empty()) << "Newly created object has some parameters";
98 EXPECT_FALSE(testHdr.IsHeaderDone()) << "Newly created object has \"parsing finished\" state";
99
100 /* check general functions in simple case */
101 testHdr.Parse(CHECK_HEADER_SMPL);
102 EXPECT_FALSE(testHdr.GetHeader().empty()) << "Parsed header is empty";
103 EXPECT_FALSE(testHdr.GetProtoLine().empty()) << "Parsed header has empty protocol line";
104 EXPECT_FALSE(testHdr.GetMimeType().empty()) << "Parsed header has empty MIME-type";
105 EXPECT_FALSE(testHdr.GetValue(CHECK_CNT_TYPE_NAME).empty()) << "Parsed header has empty \"" CHECK_CNT_TYPE_NAME "\" parameter";
106 EXPECT_FALSE(testHdr.GetValues(CHECK_CNT_TYPE_NAME).empty()) << "Parsed header has no \"" CHECK_CNT_TYPE_NAME "\" parameters";
107 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Parsed header has \"parsing not finished\" state";
108
109 /* check clearing of object */
110 testHdr.Clear();
111 EXPECT_TRUE(testHdr.GetHeader().empty()) << "Cleared object is not empty";
112 EXPECT_TRUE(testHdr.GetProtoLine().empty()) << "Cleared object has non-empty protocol line";
113 EXPECT_TRUE(testHdr.GetMimeType().empty()) << "Cleared object has non-empty MIME-type";
114 EXPECT_TRUE(testHdr.GetCharset().empty()) << "Cleared object has non-empty charset";
115 EXPECT_TRUE(testHdr.GetValue(CHECK_CNT_TYPE_NAME).empty()) << "Cleared object has some parameter";
116 EXPECT_TRUE(testHdr.GetValues(CHECK_CNT_TYPE_NAME).empty()) << "Cleared object has some parameters";
117 EXPECT_FALSE(testHdr.IsHeaderDone()) << "Cleared object has \"parsing finished\" state";
118
119 /* check general functions after object clearing */
120 testHdr.Parse(CHECK_HEADER_R);
121 EXPECT_FALSE(testHdr.GetHeader().empty()) << "Parsed header is empty";
122 EXPECT_FALSE(testHdr.GetProtoLine().empty()) << "Parsed header has empty protocol line";
123 EXPECT_FALSE(testHdr.GetMimeType().empty()) << "Parsed header has empty MIME-type";
124 EXPECT_FALSE(testHdr.GetValue(CHECK_CNT_TYPE_NAME).empty()) << "Parsed header has empty \"" CHECK_CNT_TYPE_NAME "\" parameter";
125 EXPECT_FALSE(testHdr.GetValues(CHECK_CNT_TYPE_NAME).empty()) << "Parsed header has no \"" CHECK_CNT_TYPE_NAME "\" parameters";
126 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Parsed header has \"parsing not finished\" state";
127}
128
129TEST(TestHttpHeader, Parse)
130{
131 CHttpHeader testHdr;
132
133 /* check parsing line-by-line */
134 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
135 EXPECT_FALSE(testHdr.IsHeaderDone()) << "Not completed header has \"parsing finished\" state";
136 testHdr.Parse(CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n");
137 EXPECT_FALSE(testHdr.IsHeaderDone()) << "Not completed header has \"parsing finished\" state";
138 testHdr.Parse("\r\n");
139 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
140 EXPECT_STREQ(CHECK_PROT_LINE_200, testHdr.GetProtoLine().c_str()) << "Wrong protocol line";
141 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
142
143 /* check autoclearing when new header is parsed */
144 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
145 EXPECT_FALSE(testHdr.IsHeaderDone()) << "Not completed header has \"parsing finished\" state";
146 EXPECT_TRUE(testHdr.GetValues(CHECK_CNT_TYPE_NAME).empty()) << "Cleared header has some parameters";
147 testHdr.Clear();
148 EXPECT_TRUE(testHdr.GetHeader().empty()) << "Cleared object is not empty";
149
150 /* general check parsing */
151 testHdr.Parse(CHECK_HEADER_SMPL);
152 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
153 EXPECT_STRCASEEQ(CHECK_HEADER_SMPL, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
154 testHdr.Parse(CHECK_HEADER_L1);
155 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
156 EXPECT_STRCASEEQ(CHECK_HEADER_L1, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
157 EXPECT_STREQ("Thu, 09 Jan 2014 17:58:30 GMT", testHdr.GetValue("Date").c_str()); // case-sensitive match of value
158 testHdr.Parse(CHECK_HEADER_L2);
159 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
160 EXPECT_STRCASEEQ(CHECK_HEADER_L2, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
161 EXPECT_STREQ("Thu, 09 Jan 2014 20:10:28 GMT", testHdr.GetValue("Last-Modified").c_str()); // case-sensitive match of value
162 testHdr.Parse(CHECK_HEADER_R);
163 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
164 EXPECT_STRCASEEQ(CHECK_HEADER_R, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
165 EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("Location").c_str()); // case-sensitive match of value
166
167 /* check support for '\n' line endings */
168 testHdr.Parse(strReplace(CHECK_HEADER_SMPL, "\r\n", "\n"));
169 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
170 EXPECT_STRCASEEQ(CHECK_HEADER_SMPL, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
171 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
172 testHdr.Parse(strReplace(CHECK_HEADER_L1, "\r\n", "\n"));
173 EXPECT_STRCASEEQ(CHECK_HEADER_L1, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
174 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
175 testHdr.Parse(strReplace(CHECK_HEADER_L2, "\r\n", "\n"));
176 EXPECT_STRCASEEQ(CHECK_HEADER_L2, testHdr.GetHeader().c_str()) << "Parsed header mismatch the original header";
177 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
178 testHdr.Parse(CHECK_PROT_LINE_200 "\n" CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n"); // mixed "\n" and "\r\n"
179 testHdr.Parse("\n");
180 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
181 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";
182 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
183
184 /* check trimming of whitespaces for parameter name and value */
185 testHdr.Clear();
186 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML "\r\n\r\n");
187 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
188 testHdr.Clear();
189 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_HTML " \r\n\r\n");
190 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
191 testHdr.Clear();
192 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ":" CHECK_CONTENT_TYPE_HTML " \r\n\r\n");
193 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
194 testHdr.Clear();
195 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ":\t" CHECK_CONTENT_TYPE_HTML " \t \r\n\r\n");
196 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
197 testHdr.Clear();
198 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME ":\t " CHECK_CONTENT_TYPE_HTML " \t \r\n\r\n");
199 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
200 testHdr.Clear();
201 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME "\t:" CHECK_CONTENT_TYPE_HTML " \t \r\n\r\n");
202 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
203 testHdr.Clear();
204 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n" CHECK_CNT_TYPE_NAME " \t : " CHECK_CONTENT_TYPE_HTML " \t \r\n\r\n");
205 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong value of parameter \"" CHECK_CNT_TYPE_NAME "\"";
206}
207
208TEST(TestHttpHeader, Parse_Multiline)
209{
210 CHttpHeader testHdr;
211
212 /* Check multiline parameter parsing line-by-line */
213 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
214 testHdr.Parse(CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n");
215 testHdr.Parse("X-Comment: This\r\n"); // between singleline parameters
216 testHdr.Parse(" is\r\n");
217 testHdr.Parse(" multi\r\n");
218 testHdr.Parse(" line\r\n");
219 testHdr.Parse(" value\r\n");
220 testHdr.Parse(CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_TEXT "\r\n");
221 testHdr.Parse("\r\n");
222 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
223 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
224
225 testHdr.Clear();
226 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
227 testHdr.Parse("X-Comment: This\r\n"); // first parameter
228 testHdr.Parse(" is\r\n");
229 testHdr.Parse(" multi\r\n");
230 testHdr.Parse(" line\r\n");
231 testHdr.Parse(" value\r\n");
232 testHdr.Parse(CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_TEXT "\r\n");
233 testHdr.Parse("\r\n");
234 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
235 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
236
237 testHdr.Clear();
238 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
239 testHdr.Parse(CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n");
240 testHdr.Parse("X-Comment: This\r\n"); // last parameter
241 testHdr.Parse(" is\r\n");
242 testHdr.Parse(" multi\r\n");
243 testHdr.Parse(" line\r\n");
244 testHdr.Parse(" value\r\n");
245 testHdr.Parse("\r\n");
246 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
247 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
248
249 testHdr.Clear();
250 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
251 testHdr.Parse("X-Comment: This\r\n"); // the only parameter
252 testHdr.Parse(" is\r\n");
253 testHdr.Parse(" multi\r\n");
254 testHdr.Parse(" line\r\n");
255 testHdr.Parse(" value\r\n");
256 testHdr.Parse("\r\n");
257 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
258 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
259
260 testHdr.Clear();
261 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
262 testHdr.Parse("X-Comment: This\n"); // the only parameter with mixed ending style
263 testHdr.Parse(" is\r\n");
264 testHdr.Parse(" multi\n");
265 testHdr.Parse(" line\r\n");
266 testHdr.Parse(" value\n");
267 testHdr.Parse("\r\n");
268 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
269 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
270
271 /* Check multiline parameter parsing as one line */
272 testHdr.Clear();
273 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" \
274 CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_TEXT "\r\n\r\n"); // between singleline parameters
275 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
276 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
277
278 testHdr.Clear();
279 testHdr.Parse(CHECK_PROT_LINE_200 "\r\nX-Comment: This\r\n is\r\n multi\r\n line\r\n value\r\n" \
280 CHECK_CNT_TYPE_NAME ": " CHECK_CONTENT_TYPE_TEXT "\r\n\r\n"); // first parameter
281 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
282 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
283
284 testHdr.Clear();
285 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
286 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
287 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
288
289 testHdr.Clear();
290 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
291 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
292 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
293
294 testHdr.Clear();
295 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
296 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
297 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
298
299 /* Check multiline parameter parsing as mixed one/many lines */
300 testHdr.Clear();
301 testHdr.Parse(CHECK_PROT_LINE_200 "\r\nX-Comment: This\n is\r\n multi\r\n");
302 testHdr.Parse(" line\n value\r\n\n"); // the only parameter with mixed ending style
303 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
304 EXPECT_STREQ("This is multi line value", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
305
306 /* Check parsing of multiline parameter with ':' in value */
307 testHdr.Clear();
308 testHdr.Parse(CHECK_PROT_LINE_200 "\r\nX-Comment: This\r\n is:\r\n mul:ti\r\n");
309 testHdr.Parse(" :line\r\n valu:e\r\n\n"); // the only parameter
310 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
311 EXPECT_STREQ("This is: mul:ti :line valu:e", testHdr.GetValue("X-Comment").c_str()) << "Wrong multiline value";
312
313 /* Check multiline parameter parsing with trimming */
314 testHdr.Clear();
315 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
316 testHdr.Parse(CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n");
317 testHdr.Parse("Server: Apache/2.4.7 (Unix)\r\n"); // last parameter, line-by-line parsing
318 testHdr.Parse(" mod_wsgi/3.4 \r\n");
319 testHdr.Parse("\tPython/2.7.5\r\n");
320 testHdr.Parse("\t \t \tOpenSSL/1.0.1e\r\n");
321 testHdr.Parse("\r\n");
322 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
323 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";
324 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";
325 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";
326
327 testHdr.Clear();
328 testHdr.Parse(CHECK_PROT_LINE_200 "\r\n");
329 testHdr.Parse(CHECK_DATE_NAME ": " CHECK_DATE_VALUE3 "\r\n");
330 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
331 testHdr.Parse("\tPython/2.7.5\n\t \t \tOpenSSL/1.0.1e\r\n");
332 testHdr.Parse("\r\n");
333 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
334 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";
335 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";
336 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";
337}
338
339TEST(TestHttpHeader, GetValue)
340{
341 CHttpHeader testHdr;
342
343 /* Check that all parameters values can be retrieved */
344 testHdr.Parse(CHECK_HEADER_R);
345 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
346 EXPECT_STREQ("nginx/1.4.4", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
347 EXPECT_STREQ(CHECK_DATE_VALUE2, testHdr.GetValue(CHECK_DATE_NAME).c_str()) << "Wrong parameter value";
348 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong parameter value";
349 EXPECT_STREQ("150", testHdr.GetValue("Content-Length").c_str()) << "Wrong parameter value";
350 EXPECT_STREQ("close", testHdr.GetValue("Connection").c_str()) << "Wrong parameter value";
351 EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("Location").c_str()) << "Wrong parameter value";
352 EXPECT_TRUE(testHdr.GetValue("foo").empty()) << "Some value is returned for non-existed parameter";
353
354 /* Check that all parameters values can be retrieved in random order */
355 testHdr.Parse(CHECK_HEADER_R);
356 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Completed header has \"parsing not finished\" state";
357 EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("Location").c_str()) << "Wrong parameter value";
358 EXPECT_STREQ(CHECK_CONTENT_TYPE_HTML, testHdr.GetValue(CHECK_CNT_TYPE_NAME).c_str()) << "Wrong parameter value";
359 EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("Location").c_str()) << "Wrong parameter value";
360 EXPECT_STREQ("close", testHdr.GetValue("Connection").c_str()) << "Wrong parameter value";
361 EXPECT_STREQ("nginx/1.4.4", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
362 EXPECT_STREQ("150", testHdr.GetValue("Content-Length").c_str()) << "Wrong parameter value";
363 EXPECT_STREQ(CHECK_DATE_VALUE2, testHdr.GetValue(CHECK_DATE_NAME).c_str()) << "Wrong parameter value";
364 EXPECT_STREQ("nginx/1.4.4", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
365 EXPECT_TRUE(testHdr.GetValue("foo").empty()) << "Some value is returned for non-existed parameter";
366
367 /* Check that parameters name is case-insensitive and value is case-sensitive*/
368 EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("location").c_str()) << "Wrong parameter value for lowercase name";
369 EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("LOCATION").c_str()) << "Wrong parameter value for UPPERCASE name";
370 EXPECT_STREQ("http://www.Example.Com", testHdr.GetValue("LoCAtIOn").c_str()) << "Wrong parameter value for MiXEdcASe name";
371
372 /* Check value of last added parameter with the same name is returned */
373 testHdr.Parse(CHECK_HEADER_L1);
374 EXPECT_STREQ("close", testHdr.GetValue("Connection").c_str()) << "Wrong parameter value";
375 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";
376 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";
377}
378
379TEST(TestHttpHeader, GetValues)
380{
381 CHttpHeader testHdr;
382
383 /* Check that all parameter values can be retrieved and order of values is correct */
384 testHdr.Parse(CHECK_HEADER_L1);
385 EXPECT_EQ(1U, testHdr.GetValues("Server").size()) << "Wrong number of values for parameter \"Server\"";
386 EXPECT_STREQ("nginx/1.4.4", testHdr.GetValues("Server")[0].c_str()) << "Wrong parameter value";
387 EXPECT_EQ(2U, testHdr.GetValues("Set-Cookie").size()) << "Wrong number of values for parameter \"Set-Cookie\"";
388 EXPECT_STREQ("PHPSESSID=90857d437518db8f0944ca012761048a; path=/; domain=example.com", testHdr.GetValues("Set-Cookie")[0].c_str()) << "Wrong parameter value";
389 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";
390 EXPECT_TRUE(testHdr.GetValues("foo").empty()) << "Some values are returned for non-existed parameter";
391}
392
393TEST(TestHttpHeader, AddParam)
394{
395 CHttpHeader testHdr;
396
397 /* General functionality */
398 testHdr.AddParam("server", "Microsoft-IIS/8.0");
399 EXPECT_STREQ("Microsoft-IIS/8.0", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
400
401 /* Interfere with parsing */
402 EXPECT_FALSE(testHdr.IsHeaderDone()) << "\"AddParam\" set \"parsing finished\" state";
403 testHdr.Parse(CHECK_PROT_LINE_200 "\r\nServer: nginx/1.4.4\r\n\r\n");
404 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Parsed header has \"parsing not finished\" state";
405 EXPECT_STREQ("nginx/1.4.4", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
406 testHdr.AddParam("server", "Apache/2.4.7");
407 EXPECT_STREQ("Apache/2.4.7", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
408 EXPECT_EQ(3U, testHdr.GetValues("Server").size()) << "Wrong number of values for parameter \"Server\"";
409
410 /* Multiple values */
411 testHdr.AddParam("X-foo", "bar1");
412 testHdr.AddParam("x-foo", "bar2");
413 testHdr.AddParam("x-fOO", "bar3");
414 EXPECT_EQ(3U, testHdr.GetValues("X-FOO").size()) << "Wrong number of values for parameter \"X-foo\"";
415 EXPECT_STREQ("bar1", testHdr.GetValues("X-FOo")[0].c_str()) << "Wrong parameter value";
416 EXPECT_STREQ("bar2", testHdr.GetValues("X-fOo")[1].c_str()) << "Wrong parameter value";
417 EXPECT_STREQ("bar3", testHdr.GetValues("x-fOo")[2].c_str()) << "Wrong parameter value";
418 EXPECT_STREQ("bar3", testHdr.GetValue("x-foo").c_str()) << "Wrong parameter value";
419
420 /* Overwrite value */
421 EXPECT_TRUE(testHdr.IsHeaderDone()) << "Parsed header has \"parsing not finished\" state";
422 testHdr.AddParam("x-fOO", "superbar", true);
423 EXPECT_EQ(1U, testHdr.GetValues("X-FoO").size()) << "Wrong number of values for parameter \"X-foo\"";
424 EXPECT_STREQ("superbar", testHdr.GetValue("x-foo").c_str()) << "Wrong parameter value";
425
426 /* Check name trimming */
427 testHdr.AddParam("\tx-fOO\t ", "bar");
428 EXPECT_EQ(2U, testHdr.GetValues("X-FoO").size()) << "Wrong number of values for parameter \"X-foo\"";
429 EXPECT_STREQ("bar", testHdr.GetValue("x-foo").c_str()) << "Wrong parameter value";
430 testHdr.AddParam(" SerVer \t ", "fakeSrv", true);
431 EXPECT_EQ(1U, testHdr.GetValues("serveR").size()) << "Wrong number of values for parameter \"Server\"";
432 EXPECT_STREQ("fakeSrv", testHdr.GetValue("Server").c_str()) << "Wrong parameter value";
433
434 /* Check value trimming */
435 testHdr.AddParam("X-TestParam", " testValue1");
436 EXPECT_STREQ("testValue1", testHdr.GetValue("X-TestParam").c_str()) << "Wrong parameter value";
437 testHdr.AddParam("X-TestParam", "\ttestValue2 and more \t ");
438 EXPECT_STREQ("testValue2 and more", testHdr.GetValue("X-TestParam").c_str()) << "Wrong parameter value";
439
440 /* Empty name or value */
441 testHdr.Clear();
442 testHdr.AddParam("X-TestParam", " ");
443 EXPECT_TRUE(testHdr.GetHeader().empty()) << "Parameter with empty value was added";
444 testHdr.AddParam("\t\t", "value");
445 EXPECT_TRUE(testHdr.GetHeader().empty());
446 testHdr.AddParam(" ", "\t");
447 EXPECT_TRUE(testHdr.GetHeader().empty());
448}
449
450TEST(TestHttpHeader, GetMimeType)
451{
452 CHttpHeader testHdr;
453
454 /* General functionality */
455 EXPECT_TRUE(testHdr.GetMimeType().empty()) << "Newly created object has non-empty MIME-type";
456 testHdr.Parse(CHECK_PROT_LINE_200 "\r\nServer: nginx/1.4.4\r\n\r\n");
457 EXPECT_TRUE(testHdr.GetMimeType().empty()) << "Non-empty MIME-type for header without MIME-type";
458 testHdr.Parse(CHECK_HEADER_SMPL);
459 EXPECT_STREQ("text/html", testHdr.GetMimeType().c_str()) << "Wrong MIME-type";
460 testHdr.Parse(CHECK_HEADER_L1);
461 EXPECT_STREQ("text/html", testHdr.GetMimeType().c_str()) << "Wrong MIME-type";
462 testHdr.Parse(CHECK_HEADER_L2);
463 EXPECT_STREQ("text/xml", testHdr.GetMimeType().c_str()) << "Wrong MIME-type";
464 testHdr.Parse(CHECK_HEADER_R);
465 EXPECT_STREQ("text/html", testHdr.GetMimeType().c_str()) << "Wrong MIME-type";
466
467 /* Overwrite by AddParam */
468 testHdr.AddParam(CHECK_CNT_TYPE_NAME, CHECK_CONTENT_TYPE_TEXT);
469 EXPECT_STREQ(CHECK_CONTENT_TYPE_TEXT, testHdr.GetMimeType().c_str()) << "MIME-type was not overwritten by \"AddParam\"";
470
471 /* Correct trimming */
472 testHdr.AddParam(CHECK_CNT_TYPE_NAME, " " CHECK_CONTENT_TYPE_TEXT " \t ;foo=bar");
473 EXPECT_STREQ(CHECK_CONTENT_TYPE_TEXT, testHdr.GetMimeType().c_str()) << "MIME-type is not trimmed correctly";
474}
475
476
477TEST(TestHttpHeader, GetCharset)
478{
479 CHttpHeader testHdr;
480
481 /* General functionality */
482 EXPECT_TRUE(testHdr.GetCharset().empty()) << "Newly created object has non-empty charset";
483 testHdr.Parse(CHECK_PROT_LINE_200 "\r\nServer: nginx/1.4.4\r\n\r\n");
484 EXPECT_TRUE(testHdr.GetCharset().empty()) << "Non-empty charset for header without charset";
485 testHdr.Parse(CHECK_HEADER_SMPL);
486 EXPECT_TRUE(testHdr.GetCharset().empty()) << "Non-empty charset for header without charset";
487 testHdr.Parse(CHECK_HEADER_L1);
488 EXPECT_STREQ("WINDOWS-1251", testHdr.GetCharset().c_str()) << "Wrong charset value";
489 testHdr.Parse(CHECK_HEADER_L2);
490 EXPECT_STREQ("UTF-8", testHdr.GetCharset().c_str()) << "Wrong charset value";
491
492 /* Overwrite by AddParam */
493 testHdr.AddParam(CHECK_CNT_TYPE_NAME, CHECK_CONTENT_TYPE_TEXT "; charset=WINDOWS-1252");
494 EXPECT_STREQ("WINDOWS-1252", testHdr.GetCharset().c_str()) << "Charset was not overwritten by \"AddParam\"";
495
496 /* Correct trimming */
497 testHdr.AddParam(CHECK_CNT_TYPE_NAME, "text/plain;charset=WINDOWS-1251");
498 EXPECT_STREQ("WINDOWS-1251", testHdr.GetCharset().c_str()) << "Wrong charset value";
499 testHdr.AddParam(CHECK_CNT_TYPE_NAME, "text/plain ;\tcharset=US-AScII\t");
500 EXPECT_STREQ("US-ASCII", testHdr.GetCharset().c_str()) << "Wrong charset value";
501 testHdr.AddParam(CHECK_CNT_TYPE_NAME, "text/html ; \tcharset=\"uTF-8\"\t");
502 EXPECT_STREQ("UTF-8", testHdr.GetCharset().c_str()) << "Wrong charset value";
503 testHdr.AddParam(CHECK_CNT_TYPE_NAME, " \ttext/xml\t;\tcharset=uTF-16 ");
504 EXPECT_STREQ("UTF-16", testHdr.GetCharset().c_str()) << "Wrong charset value";
505}