OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
9 #include "net/http/http_util.h" | 9 #include "net/http/http_util.h" |
10 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
11 | 11 |
12 using net::HttpUtil; | 12 using net::HttpUtil; |
13 | 13 |
14 namespace { | 14 namespace { |
15 class HttpUtilTest : public testing::Test {}; | 15 class HttpUtilTest : public testing::Test {}; |
16 } | 16 } |
17 | 17 |
18 TEST(HttpUtilTest, IsSafeHeader) { | 18 TEST(HttpUtilTest, IsSafeHeader) { |
19 static const char* unsafe_headers[] = { | 19 static const char* unsafe_headers[] = { |
20 "sec-", | 20 "sec-", "sEc-", |
21 "sEc-", | 21 "sec-foo", "sEc-FoO", |
22 "sec-foo", | 22 "proxy-", "pRoXy-", |
23 "sEc-FoO", | 23 "proxy-foo", "pRoXy-FoO", |
24 "proxy-", | 24 "accept-charset", "accept-encoding", |
25 "pRoXy-", | 25 "access-control-request-headers", "access-control-request-method", |
26 "proxy-foo", | 26 "connection", "content-length", |
27 "pRoXy-FoO", | 27 "cookie", "cookie2", |
28 "accept-charset", | 28 "content-transfer-encoding", "date", |
29 "accept-encoding", | 29 "expect", "host", |
30 "access-control-request-headers", | 30 "keep-alive", "origin", |
31 "access-control-request-method", | 31 "referer", "te", |
32 "connection", | 32 "trailer", "transfer-encoding", |
33 "content-length", | 33 "upgrade", "user-agent", |
34 "cookie", | 34 "via", |
35 "cookie2", | |
36 "content-transfer-encoding", | |
37 "date", | |
38 "expect", | |
39 "host", | |
40 "keep-alive", | |
41 "origin", | |
42 "referer", | |
43 "te", | |
44 "trailer", | |
45 "transfer-encoding", | |
46 "upgrade", | |
47 "user-agent", | |
48 "via", | |
49 }; | 35 }; |
50 for (size_t i = 0; i < arraysize(unsafe_headers); ++i) { | 36 for (size_t i = 0; i < arraysize(unsafe_headers); ++i) { |
51 EXPECT_FALSE(HttpUtil::IsSafeHeader(unsafe_headers[i])) | 37 EXPECT_FALSE(HttpUtil::IsSafeHeader(unsafe_headers[i])) |
52 << unsafe_headers[i]; | 38 << unsafe_headers[i]; |
53 EXPECT_FALSE(HttpUtil::IsSafeHeader(StringToUpperASCII(std::string( | 39 EXPECT_FALSE(HttpUtil::IsSafeHeader( |
54 unsafe_headers[i])))) << unsafe_headers[i]; | 40 StringToUpperASCII(std::string(unsafe_headers[i])))) |
| 41 << unsafe_headers[i]; |
55 } | 42 } |
56 static const char* safe_headers[] = { | 43 static const char* safe_headers[] = { |
57 "foo", | 44 "foo", "x-", |
58 "x-", | 45 "x-foo", "content-disposition", |
59 "x-foo", | 46 "update", "accept-charseta", |
60 "content-disposition", | 47 "accept_charset", "accept-encodinga", |
61 "update", | 48 "accept_encoding", "access-control-request-headersa", |
62 "accept-charseta", | 49 "access-control-request-header", "access_control_request_header", |
63 "accept_charset", | 50 "access-control-request-methoda", "access_control_request_method", |
64 "accept-encodinga", | 51 "connectiona", "content-lengtha", |
65 "accept_encoding", | 52 "content_length", "cookiea", |
66 "access-control-request-headersa", | 53 "cookie2a", "cookie3", |
67 "access-control-request-header", | 54 "content-transfer-encodinga", "content_transfer_encoding", |
68 "access_control_request_header", | 55 "datea", "expecta", |
69 "access-control-request-methoda", | 56 "hosta", "keep-alivea", |
70 "access_control_request_method", | 57 "keep_alive", "origina", |
71 "connectiona", | 58 "referera", "referrer", |
72 "content-lengtha", | 59 "tea", "trailera", |
73 "content_length", | 60 "transfer-encodinga", "transfer_encoding", |
74 "cookiea", | 61 "upgradea", "user-agenta", |
75 "cookie2a", | 62 "user_agent", "viaa", |
76 "cookie3", | |
77 "content-transfer-encodinga", | |
78 "content_transfer_encoding", | |
79 "datea", | |
80 "expecta", | |
81 "hosta", | |
82 "keep-alivea", | |
83 "keep_alive", | |
84 "origina", | |
85 "referera", | |
86 "referrer", | |
87 "tea", | |
88 "trailera", | |
89 "transfer-encodinga", | |
90 "transfer_encoding", | |
91 "upgradea", | |
92 "user-agenta", | |
93 "user_agent", | |
94 "viaa", | |
95 }; | 63 }; |
96 for (size_t i = 0; i < arraysize(safe_headers); ++i) { | 64 for (size_t i = 0; i < arraysize(safe_headers); ++i) { |
97 EXPECT_TRUE(HttpUtil::IsSafeHeader(safe_headers[i])) << safe_headers[i]; | 65 EXPECT_TRUE(HttpUtil::IsSafeHeader(safe_headers[i])) << safe_headers[i]; |
98 EXPECT_TRUE(HttpUtil::IsSafeHeader(StringToUpperASCII(std::string( | 66 EXPECT_TRUE(HttpUtil::IsSafeHeader( |
99 safe_headers[i])))) << safe_headers[i]; | 67 StringToUpperASCII(std::string(safe_headers[i])))) |
| 68 << safe_headers[i]; |
100 } | 69 } |
101 } | 70 } |
102 | 71 |
103 TEST(HttpUtilTest, HasHeader) { | 72 TEST(HttpUtilTest, HasHeader) { |
104 static const struct { | 73 static const struct { |
105 const char* headers; | 74 const char* headers; |
106 const char* name; | 75 const char* name; |
107 bool expected_result; | 76 bool expected_result; |
108 } tests[] = { | 77 } tests[] = { |
109 { "", "foo", false }, | 78 {"", "foo", false}, |
110 { "foo\r\nbar", "foo", false }, | 79 {"foo\r\nbar", "foo", false}, |
111 { "ffoo: 1", "foo", false }, | 80 {"ffoo: 1", "foo", false}, |
112 { "foo: 1", "foo", true }, | 81 {"foo: 1", "foo", true}, |
113 { "foo: 1\r\nbar: 2", "foo", true }, | 82 {"foo: 1\r\nbar: 2", "foo", true}, |
114 { "fOO: 1\r\nbar: 2", "foo", true }, | 83 {"fOO: 1\r\nbar: 2", "foo", true}, |
115 { "g: 0\r\nfoo: 1\r\nbar: 2", "foo", true }, | 84 {"g: 0\r\nfoo: 1\r\nbar: 2", "foo", true}, |
116 }; | 85 }; |
117 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 86 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
118 bool result = HttpUtil::HasHeader(tests[i].headers, tests[i].name); | 87 bool result = HttpUtil::HasHeader(tests[i].headers, tests[i].name); |
119 EXPECT_EQ(tests[i].expected_result, result); | 88 EXPECT_EQ(tests[i].expected_result, result); |
120 } | 89 } |
121 } | 90 } |
122 | 91 |
123 TEST(HttpUtilTest, StripHeaders) { | 92 TEST(HttpUtilTest, StripHeaders) { |
124 static const char* headers = | 93 static const char* headers = |
125 "Origin: origin\r\n" | 94 "Origin: origin\r\n" |
126 "Content-Type: text/plain\r\n" | 95 "Content-Type: text/plain\r\n" |
127 "Cookies: foo1\r\n" | 96 "Cookies: foo1\r\n" |
128 "Custom: baz\r\n" | 97 "Custom: baz\r\n" |
129 "COOKIES: foo2\r\n" | 98 "COOKIES: foo2\r\n" |
130 "Server: Apache\r\n" | 99 "Server: Apache\r\n" |
131 "OrIGin: origin2\r\n"; | 100 "OrIGin: origin2\r\n"; |
132 | 101 |
133 static const char* header_names[] = { | 102 static const char* header_names[] = {"origin", "content-type", "cookies"}; |
134 "origin", "content-type", "cookies" | |
135 }; | |
136 | 103 |
137 static const char* expected_stripped_headers = | 104 static const char* expected_stripped_headers = |
138 "Custom: baz\r\n" | 105 "Custom: baz\r\n" |
139 "Server: Apache\r\n"; | 106 "Server: Apache\r\n"; |
140 | 107 |
141 EXPECT_EQ(expected_stripped_headers, | 108 EXPECT_EQ( |
142 HttpUtil::StripHeaders(headers, header_names, | 109 expected_stripped_headers, |
143 arraysize(header_names))); | 110 HttpUtil::StripHeaders(headers, header_names, arraysize(header_names))); |
144 } | 111 } |
145 | 112 |
146 TEST(HttpUtilTest, HeadersIterator) { | 113 TEST(HttpUtilTest, HeadersIterator) { |
147 std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n"; | 114 std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n"; |
148 | 115 |
149 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); | 116 HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); |
150 | 117 |
151 ASSERT_TRUE(it.GetNext()); | 118 ASSERT_TRUE(it.GetNext()); |
152 EXPECT_EQ(std::string("foo"), it.name()); | 119 EXPECT_EQ(std::string("foo"), it.name()); |
153 EXPECT_EQ(std::string("1"), it.values()); | 120 EXPECT_EQ(std::string("1"), it.values()); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 | 225 |
259 // Replace <backslash> X with X | 226 // Replace <backslash> X with X |
260 EXPECT_STREQ("\"xyzXabc\"", HttpUtil::Quote("xyzXabc").c_str()); | 227 EXPECT_STREQ("\"xyzXabc\"", HttpUtil::Quote("xyzXabc").c_str()); |
261 } | 228 } |
262 | 229 |
263 TEST(HttpUtilTest, LocateEndOfHeaders) { | 230 TEST(HttpUtilTest, LocateEndOfHeaders) { |
264 struct { | 231 struct { |
265 const char* input; | 232 const char* input; |
266 int expected_result; | 233 int expected_result; |
267 } tests[] = { | 234 } tests[] = { |
268 { "foo\r\nbar\r\n\r\n", 12 }, | 235 {"foo\r\nbar\r\n\r\n", 12}, |
269 { "foo\nbar\n\n", 9 }, | 236 {"foo\nbar\n\n", 9}, |
270 { "foo\r\nbar\r\n\r\njunk", 12 }, | 237 {"foo\r\nbar\r\n\r\njunk", 12}, |
271 { "foo\nbar\n\njunk", 9 }, | 238 {"foo\nbar\n\njunk", 9}, |
272 { "foo\nbar\n\r\njunk", 10 }, | 239 {"foo\nbar\n\r\njunk", 10}, |
273 { "foo\nbar\r\n\njunk", 10 }, | 240 {"foo\nbar\r\n\njunk", 10}, |
274 }; | 241 }; |
275 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 242 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
276 int input_len = static_cast<int>(strlen(tests[i].input)); | 243 int input_len = static_cast<int>(strlen(tests[i].input)); |
277 int eoh = HttpUtil::LocateEndOfHeaders(tests[i].input, input_len); | 244 int eoh = HttpUtil::LocateEndOfHeaders(tests[i].input, input_len); |
278 EXPECT_EQ(tests[i].expected_result, eoh); | 245 EXPECT_EQ(tests[i].expected_result, eoh); |
279 } | 246 } |
280 } | 247 } |
281 | 248 |
282 TEST(HttpUtilTest, AssembleRawHeaders) { | 249 TEST(HttpUtilTest, AssembleRawHeaders) { |
283 struct { | 250 struct { |
284 const char* input; // with '|' representing '\0' | 251 const char* input; // with '|' representing '\0' |
285 const char* expected_result; // with '\0' changed to '|' | 252 const char* expected_result; // with '\0' changed to '|' |
286 } tests[] = { | 253 } tests[] = { |
287 { "HTTP/1.0 200 OK\r\nFoo: 1\r\nBar: 2\r\n\r\n", | 254 {"HTTP/1.0 200 OK\r\nFoo: 1\r\nBar: 2\r\n\r\n", |
288 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" }, | 255 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||"}, |
289 | 256 {"HTTP/1.0 200 OK\nFoo: 1\nBar: 2\n\n", |
290 { "HTTP/1.0 200 OK\nFoo: 1\nBar: 2\n\n", | 257 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||"}, |
291 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" }, | 258 |
292 | 259 // Valid line continuation (single SP). |
293 // Valid line continuation (single SP). | 260 {"HTTP/1.0 200 OK\n" |
294 { | 261 "Foo: 1\n" |
295 "HTTP/1.0 200 OK\n" | 262 " continuation\n" |
296 "Foo: 1\n" | 263 "Bar: 2\n\n", |
297 " continuation\n" | 264 "HTTP/1.0 200 OK|" |
298 "Bar: 2\n\n", | 265 "Foo: 1 continuation|" |
299 | 266 "Bar: 2||"}, |
300 "HTTP/1.0 200 OK|" | 267 |
301 "Foo: 1 continuation|" | 268 // Valid line continuation (single HT). |
302 "Bar: 2||" | 269 {"HTTP/1.0 200 OK\n" |
303 }, | 270 "Foo: 1\n" |
304 | 271 "\tcontinuation\n" |
305 // Valid line continuation (single HT). | 272 "Bar: 2\n\n", |
306 { | 273 "HTTP/1.0 200 OK|" |
307 "HTTP/1.0 200 OK\n" | 274 "Foo: 1 continuation|" |
308 "Foo: 1\n" | 275 "Bar: 2||"}, |
309 "\tcontinuation\n" | 276 |
310 "Bar: 2\n\n", | 277 // Valid line continuation (multiple SP). |
311 | 278 {"HTTP/1.0 200 OK\n" |
312 "HTTP/1.0 200 OK|" | 279 "Foo: 1\n" |
313 "Foo: 1 continuation|" | 280 " continuation\n" |
314 "Bar: 2||" | 281 "Bar: 2\n\n", |
315 }, | 282 "HTTP/1.0 200 OK|" |
316 | 283 "Foo: 1 continuation|" |
317 // Valid line continuation (multiple SP). | 284 "Bar: 2||"}, |
318 { | 285 |
319 "HTTP/1.0 200 OK\n" | 286 // Valid line continuation (multiple HT). |
320 "Foo: 1\n" | 287 {"HTTP/1.0 200 OK\n" |
321 " continuation\n" | 288 "Foo: 1\n" |
322 "Bar: 2\n\n", | 289 "\t\t\tcontinuation\n" |
323 | 290 "Bar: 2\n\n", |
324 "HTTP/1.0 200 OK|" | 291 "HTTP/1.0 200 OK|" |
325 "Foo: 1 continuation|" | 292 "Foo: 1 continuation|" |
326 "Bar: 2||" | 293 "Bar: 2||"}, |
327 }, | 294 |
328 | 295 // Valid line continuation (mixed HT, SP). |
329 // Valid line continuation (multiple HT). | 296 {"HTTP/1.0 200 OK\n" |
330 { | 297 "Foo: 1\n" |
331 "HTTP/1.0 200 OK\n" | 298 " \t \t continuation\n" |
332 "Foo: 1\n" | 299 "Bar: 2\n\n", |
333 "\t\t\tcontinuation\n" | 300 "HTTP/1.0 200 OK|" |
334 "Bar: 2\n\n", | 301 "Foo: 1 continuation|" |
335 | 302 "Bar: 2||"}, |
336 "HTTP/1.0 200 OK|" | 303 |
337 "Foo: 1 continuation|" | 304 // Valid multi-line continuation |
338 "Bar: 2||" | 305 {"HTTP/1.0 200 OK\n" |
339 }, | 306 "Foo: 1\n" |
340 | 307 " continuation1\n" |
341 // Valid line continuation (mixed HT, SP). | 308 "\tcontinuation2\n" |
342 { | 309 " continuation3\n" |
343 "HTTP/1.0 200 OK\n" | 310 "Bar: 2\n\n", |
344 "Foo: 1\n" | 311 "HTTP/1.0 200 OK|" |
345 " \t \t continuation\n" | 312 "Foo: 1 continuation1 continuation2 continuation3|" |
346 "Bar: 2\n\n", | 313 "Bar: 2||"}, |
347 | 314 |
348 "HTTP/1.0 200 OK|" | 315 // Continuation of quoted value. |
349 "Foo: 1 continuation|" | 316 // This is different from what Firefox does, since it |
350 "Bar: 2||" | 317 // will preserve the LWS. |
351 }, | 318 {"HTTP/1.0 200 OK\n" |
352 | 319 "Etag: \"34534-d3\n" |
353 // Valid multi-line continuation | 320 " 134q\"\n" |
354 { | 321 "Bar: 2\n\n", |
355 "HTTP/1.0 200 OK\n" | 322 "HTTP/1.0 200 OK|" |
356 "Foo: 1\n" | 323 "Etag: \"34534-d3 134q\"|" |
357 " continuation1\n" | 324 "Bar: 2||"}, |
358 "\tcontinuation2\n" | 325 |
359 " continuation3\n" | 326 // Valid multi-line continuation, full LWS lines |
360 "Bar: 2\n\n", | 327 {"HTTP/1.0 200 OK\n" |
361 | 328 "Foo: 1\n" |
362 "HTTP/1.0 200 OK|" | 329 " \n" |
363 "Foo: 1 continuation1 continuation2 continuation3|" | 330 "\t\t\t\t\n" |
364 "Bar: 2||" | 331 "\t continuation\n" |
365 }, | 332 "Bar: 2\n\n", |
366 | 333 |
367 // Continuation of quoted value. | 334 // One SP per continued line = 3. |
368 // This is different from what Firefox does, since it | 335 "HTTP/1.0 200 OK|" |
369 // will preserve the LWS. | 336 "Foo: 1 continuation|" |
370 { | 337 "Bar: 2||"}, |
371 "HTTP/1.0 200 OK\n" | 338 |
372 "Etag: \"34534-d3\n" | 339 // Valid multi-line continuation, all LWS |
373 " 134q\"\n" | 340 {"HTTP/1.0 200 OK\n" |
374 "Bar: 2\n\n", | 341 "Foo: 1\n" |
375 | 342 " \n" |
376 "HTTP/1.0 200 OK|" | 343 "\t\t\t\t\n" |
377 "Etag: \"34534-d3 134q\"|" | 344 "\t \n" |
378 "Bar: 2||" | 345 "Bar: 2\n\n", |
379 }, | 346 |
380 | 347 // One SP per continued line = 3. |
381 // Valid multi-line continuation, full LWS lines | 348 "HTTP/1.0 200 OK|" |
382 { | 349 "Foo: 1 |" |
383 "HTTP/1.0 200 OK\n" | 350 "Bar: 2||"}, |
384 "Foo: 1\n" | 351 |
385 " \n" | 352 // Valid line continuation (No value bytes in first line). |
386 "\t\t\t\t\n" | 353 {"HTTP/1.0 200 OK\n" |
387 "\t continuation\n" | 354 "Foo:\n" |
388 "Bar: 2\n\n", | 355 " value\n" |
389 | 356 "Bar: 2\n\n", |
390 // One SP per continued line = 3. | 357 "HTTP/1.0 200 OK|" |
391 "HTTP/1.0 200 OK|" | 358 "Foo: value|" |
392 "Foo: 1 continuation|" | 359 "Bar: 2||"}, |
393 "Bar: 2||" | 360 |
394 }, | 361 // Not a line continuation (can't continue status line). |
395 | 362 {"HTTP/1.0 200 OK\n" |
396 // Valid multi-line continuation, all LWS | 363 " Foo: 1\n" |
397 { | 364 "Bar: 2\n\n", |
398 "HTTP/1.0 200 OK\n" | 365 "HTTP/1.0 200 OK|" |
399 "Foo: 1\n" | 366 " Foo: 1|" |
400 " \n" | 367 "Bar: 2||"}, |
401 "\t\t\t\t\n" | 368 |
402 "\t \n" | 369 // Not a line continuation (can't continue status line). |
403 "Bar: 2\n\n", | 370 {"HTTP/1.0\n" |
404 | 371 " 200 OK\n" |
405 // One SP per continued line = 3. | 372 "Foo: 1\n" |
406 "HTTP/1.0 200 OK|" | 373 "Bar: 2\n\n", |
407 "Foo: 1 |" | 374 "HTTP/1.0|" |
408 "Bar: 2||" | 375 " 200 OK|" |
409 }, | 376 "Foo: 1|" |
410 | 377 "Bar: 2||"}, |
411 // Valid line continuation (No value bytes in first line). | 378 |
412 { | 379 // Not a line continuation (can't continue status line). |
413 "HTTP/1.0 200 OK\n" | 380 {"HTTP/1.0 404\n" |
414 "Foo:\n" | 381 " Not Found\n" |
415 " value\n" | 382 "Foo: 1\n" |
416 "Bar: 2\n\n", | 383 "Bar: 2\n\n", |
417 | 384 "HTTP/1.0 404|" |
418 "HTTP/1.0 200 OK|" | 385 " Not Found|" |
419 "Foo: value|" | 386 "Foo: 1|" |
420 "Bar: 2||" | 387 "Bar: 2||"}, |
421 }, | 388 |
422 | 389 // Unterminated status line. |
423 // Not a line continuation (can't continue status line). | 390 {"HTTP/1.0 200 OK", "HTTP/1.0 200 OK||"}, |
424 { | 391 |
425 "HTTP/1.0 200 OK\n" | 392 // Single terminated, with headers |
426 " Foo: 1\n" | 393 {"HTTP/1.0 200 OK\n" |
427 "Bar: 2\n\n", | 394 "Foo: 1\n" |
428 | 395 "Bar: 2\n", |
429 "HTTP/1.0 200 OK|" | 396 "HTTP/1.0 200 OK|" |
430 " Foo: 1|" | 397 "Foo: 1|" |
431 "Bar: 2||" | 398 "Bar: 2||"}, |
432 }, | 399 |
433 | 400 // Not terminated, with headers |
434 // Not a line continuation (can't continue status line). | 401 {"HTTP/1.0 200 OK\n" |
435 { | 402 "Foo: 1\n" |
436 "HTTP/1.0\n" | 403 "Bar: 2", |
437 " 200 OK\n" | 404 "HTTP/1.0 200 OK|" |
438 "Foo: 1\n" | 405 "Foo: 1|" |
439 "Bar: 2\n\n", | 406 "Bar: 2||"}, |
440 | 407 |
441 "HTTP/1.0|" | 408 // Not a line continuation (VT) |
442 " 200 OK|" | 409 {"HTTP/1.0 200 OK\n" |
443 "Foo: 1|" | 410 "Foo: 1\n" |
444 "Bar: 2||" | 411 "\vInvalidContinuation\n" |
445 }, | 412 "Bar: 2\n\n", |
446 | 413 "HTTP/1.0 200 OK|" |
447 // Not a line continuation (can't continue status line). | 414 "Foo: 1|" |
448 { | 415 "\vInvalidContinuation|" |
449 "HTTP/1.0 404\n" | 416 "Bar: 2||"}, |
450 " Not Found\n" | 417 |
451 "Foo: 1\n" | 418 // Not a line continuation (formfeed) |
452 "Bar: 2\n\n", | 419 {"HTTP/1.0 200 OK\n" |
453 | 420 "Foo: 1\n" |
454 "HTTP/1.0 404|" | 421 "\fInvalidContinuation\n" |
455 " Not Found|" | 422 "Bar: 2\n\n", |
456 "Foo: 1|" | 423 "HTTP/1.0 200 OK|" |
457 "Bar: 2||" | 424 "Foo: 1|" |
458 }, | 425 "\fInvalidContinuation|" |
459 | 426 "Bar: 2||"}, |
460 // Unterminated status line. | 427 |
461 { | 428 // Not a line continuation -- can't continue header names. |
462 "HTTP/1.0 200 OK", | 429 {"HTTP/1.0 200 OK\n" |
463 | 430 "Serv\n" |
464 "HTTP/1.0 200 OK||" | 431 " er: Apache\n" |
465 }, | 432 "\tInvalidContinuation\n" |
466 | 433 "Bar: 2\n\n", |
467 // Single terminated, with headers | 434 "HTTP/1.0 200 OK|" |
468 { | 435 "Serv|" |
469 "HTTP/1.0 200 OK\n" | 436 " er: Apache|" |
470 "Foo: 1\n" | 437 "\tInvalidContinuation|" |
471 "Bar: 2\n", | 438 "Bar: 2||"}, |
472 | 439 |
473 "HTTP/1.0 200 OK|" | 440 // Not a line continuation -- no value to continue. |
474 "Foo: 1|" | 441 { |
475 "Bar: 2||" | 442 "HTTP/1.0 200 OK\n" |
476 }, | 443 "Foo: 1\n" |
477 | 444 "garbage\n" |
478 // Not terminated, with headers | 445 " not-a-continuation\n" |
479 { | 446 "Bar: 2\n\n", |
480 "HTTP/1.0 200 OK\n" | 447 "HTTP/1.0 200 OK|" |
481 "Foo: 1\n" | 448 "Foo: 1|" |
482 "Bar: 2", | 449 "garbage|" |
483 | 450 " not-a-continuation|" |
484 "HTTP/1.0 200 OK|" | 451 "Bar: 2||", |
485 "Foo: 1|" | 452 }, |
486 "Bar: 2||" | 453 |
487 }, | 454 // Not a line continuation -- no valid name. |
488 | 455 { |
489 // Not a line continuation (VT) | 456 "HTTP/1.0 200 OK\n" |
490 { | 457 ": 1\n" |
491 "HTTP/1.0 200 OK\n" | 458 " garbage\n" |
492 "Foo: 1\n" | 459 "Bar: 2\n\n", |
493 "\vInvalidContinuation\n" | 460 "HTTP/1.0 200 OK|" |
494 "Bar: 2\n\n", | 461 ": 1|" |
495 | 462 " garbage|" |
496 "HTTP/1.0 200 OK|" | 463 "Bar: 2||", |
497 "Foo: 1|" | 464 }, |
498 "\vInvalidContinuation|" | 465 |
499 "Bar: 2||" | 466 // Not a line continuation -- no valid name (whitespace) |
500 }, | 467 { |
501 | 468 "HTTP/1.0 200 OK\n" |
502 // Not a line continuation (formfeed) | 469 " : 1\n" |
503 { | 470 " garbage\n" |
504 "HTTP/1.0 200 OK\n" | 471 "Bar: 2\n\n", |
505 "Foo: 1\n" | 472 "HTTP/1.0 200 OK|" |
506 "\fInvalidContinuation\n" | 473 " : 1|" |
507 "Bar: 2\n\n", | 474 " garbage|" |
508 | 475 "Bar: 2||", |
509 "HTTP/1.0 200 OK|" | 476 }, |
510 "Foo: 1|" | 477 |
511 "\fInvalidContinuation|" | 478 // Embed NULLs in the status line. They should not be understood |
512 "Bar: 2||" | 479 // as line separators. |
513 }, | 480 {"HTTP/1.0 200 OK|Bar2:0|Baz2:1\r\nFoo: 1\r\nBar: 2\r\n\r\n", |
514 | 481 "HTTP/1.0 200 OKBar2:0Baz2:1|Foo: 1|Bar: 2||"}, |
515 // Not a line continuation -- can't continue header names. | 482 |
516 { | 483 // Embed NULLs in a header line. They should not be understood as |
517 "HTTP/1.0 200 OK\n" | 484 // line separators. |
518 "Serv\n" | 485 {"HTTP/1.0 200 OK\nFoo: 1|Foo2: 3\nBar: 2\n\n", |
519 " er: Apache\n" | 486 "HTTP/1.0 200 OK|Foo: 1Foo2: 3|Bar: 2||"}, |
520 "\tInvalidContinuation\n" | 487 }; |
521 "Bar: 2\n\n", | |
522 | |
523 "HTTP/1.0 200 OK|" | |
524 "Serv|" | |
525 " er: Apache|" | |
526 "\tInvalidContinuation|" | |
527 "Bar: 2||" | |
528 }, | |
529 | |
530 // Not a line continuation -- no value to continue. | |
531 { | |
532 "HTTP/1.0 200 OK\n" | |
533 "Foo: 1\n" | |
534 "garbage\n" | |
535 " not-a-continuation\n" | |
536 "Bar: 2\n\n", | |
537 | |
538 "HTTP/1.0 200 OK|" | |
539 "Foo: 1|" | |
540 "garbage|" | |
541 " not-a-continuation|" | |
542 "Bar: 2||", | |
543 }, | |
544 | |
545 // Not a line continuation -- no valid name. | |
546 { | |
547 "HTTP/1.0 200 OK\n" | |
548 ": 1\n" | |
549 " garbage\n" | |
550 "Bar: 2\n\n", | |
551 | |
552 "HTTP/1.0 200 OK|" | |
553 ": 1|" | |
554 " garbage|" | |
555 "Bar: 2||", | |
556 }, | |
557 | |
558 // Not a line continuation -- no valid name (whitespace) | |
559 { | |
560 "HTTP/1.0 200 OK\n" | |
561 " : 1\n" | |
562 " garbage\n" | |
563 "Bar: 2\n\n", | |
564 | |
565 "HTTP/1.0 200 OK|" | |
566 " : 1|" | |
567 " garbage|" | |
568 "Bar: 2||", | |
569 }, | |
570 | |
571 // Embed NULLs in the status line. They should not be understood | |
572 // as line separators. | |
573 { | |
574 "HTTP/1.0 200 OK|Bar2:0|Baz2:1\r\nFoo: 1\r\nBar: 2\r\n\r\n", | |
575 "HTTP/1.0 200 OKBar2:0Baz2:1|Foo: 1|Bar: 2||" | |
576 }, | |
577 | |
578 // Embed NULLs in a header line. They should not be understood as | |
579 // line separators. | |
580 { | |
581 "HTTP/1.0 200 OK\nFoo: 1|Foo2: 3\nBar: 2\n\n", | |
582 "HTTP/1.0 200 OK|Foo: 1Foo2: 3|Bar: 2||" | |
583 }, | |
584 }; | |
585 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 488 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
586 std::string input = tests[i].input; | 489 std::string input = tests[i].input; |
587 std::replace(input.begin(), input.end(), '|', '\0'); | 490 std::replace(input.begin(), input.end(), '|', '\0'); |
588 std::string raw = HttpUtil::AssembleRawHeaders(input.data(), input.size()); | 491 std::string raw = HttpUtil::AssembleRawHeaders(input.data(), input.size()); |
589 std::replace(raw.begin(), raw.end(), '\0', '|'); | 492 std::replace(raw.begin(), raw.end(), '\0', '|'); |
590 EXPECT_EQ(tests[i].expected_result, raw); | 493 EXPECT_EQ(tests[i].expected_result, raw); |
591 } | 494 } |
592 } | 495 } |
593 | 496 |
594 // Test SpecForRequest() and PathForRequest(). | 497 // Test SpecForRequest() and PathForRequest(). |
595 TEST(HttpUtilTest, RequestUrlSanitize) { | 498 TEST(HttpUtilTest, RequestUrlSanitize) { |
596 struct { | 499 struct { |
597 const char* url; | 500 const char* url; |
598 const char* expected_spec; | 501 const char* expected_spec; |
599 const char* expected_path; | 502 const char* expected_path; |
600 } tests[] = { | 503 } tests[] = {{// Check that #hash is removed. |
601 { // Check that #hash is removed. | 504 "http://www.google.com:78/foobar?query=1#hash", |
602 "http://www.google.com:78/foobar?query=1#hash", | 505 "http://www.google.com:78/foobar?query=1", "/foobar?query=1"}, |
603 "http://www.google.com:78/foobar?query=1", | 506 {// The reference may itself contain # -- strip all of it. |
604 "/foobar?query=1" | 507 "http://192.168.0.1?query=1#hash#10#11#13#14", |
605 }, | 508 "http://192.168.0.1/?query=1", "/?query=1"}, |
606 { // The reference may itself contain # -- strip all of it. | 509 {// Strip username/password. |
607 "http://192.168.0.1?query=1#hash#10#11#13#14", | 510 "http://user:pass@google.com", "http://google.com/", "/"}, |
608 "http://192.168.0.1/?query=1", | 511 {// https scheme |
609 "/?query=1" | 512 "https://www.google.com:78/foobar?query=1#hash", |
610 }, | 513 "https://www.google.com:78/foobar?query=1", "/foobar?query=1"}, |
611 { // Strip username/password. | 514 {// WebSocket's ws scheme |
612 "http://user:pass@google.com", | 515 "ws://www.google.com:78/foobar?query=1#hash", |
613 "http://google.com/", | 516 "ws://www.google.com:78/foobar?query=1", "/foobar?query=1"}, |
614 "/" | 517 {// WebSocket's wss scheme |
615 }, | 518 "wss://www.google.com:78/foobar?query=1#hash", |
616 { // https scheme | 519 "wss://www.google.com:78/foobar?query=1", "/foobar?query=1"}}; |
617 "https://www.google.com:78/foobar?query=1#hash", | |
618 "https://www.google.com:78/foobar?query=1", | |
619 "/foobar?query=1" | |
620 }, | |
621 { // WebSocket's ws scheme | |
622 "ws://www.google.com:78/foobar?query=1#hash", | |
623 "ws://www.google.com:78/foobar?query=1", | |
624 "/foobar?query=1" | |
625 }, | |
626 { // WebSocket's wss scheme | |
627 "wss://www.google.com:78/foobar?query=1#hash", | |
628 "wss://www.google.com:78/foobar?query=1", | |
629 "/foobar?query=1" | |
630 } | |
631 }; | |
632 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 520 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
633 GURL url(GURL(tests[i].url)); | 521 GURL url(GURL(tests[i].url)); |
634 std::string expected_spec(tests[i].expected_spec); | 522 std::string expected_spec(tests[i].expected_spec); |
635 std::string expected_path(tests[i].expected_path); | 523 std::string expected_path(tests[i].expected_path); |
636 | 524 |
637 EXPECT_EQ(expected_spec, HttpUtil::SpecForRequest(url)); | 525 EXPECT_EQ(expected_spec, HttpUtil::SpecForRequest(url)); |
638 EXPECT_EQ(expected_path, HttpUtil::PathForRequest(url)); | 526 EXPECT_EQ(expected_path, HttpUtil::PathForRequest(url)); |
639 } | 527 } |
640 } | 528 } |
641 | 529 |
642 // Test SpecForRequest() for "ftp" scheme. | 530 // Test SpecForRequest() for "ftp" scheme. |
643 TEST(HttpUtilTest, SpecForRequestForUrlWithFtpScheme) { | 531 TEST(HttpUtilTest, SpecForRequestForUrlWithFtpScheme) { |
644 GURL ftp_url("ftp://user:pass@google.com/pub/chromium/"); | 532 GURL ftp_url("ftp://user:pass@google.com/pub/chromium/"); |
645 EXPECT_EQ("ftp://google.com/pub/chromium/", | 533 EXPECT_EQ("ftp://google.com/pub/chromium/", |
646 HttpUtil::SpecForRequest(ftp_url)); | 534 HttpUtil::SpecForRequest(ftp_url)); |
647 } | 535 } |
648 | 536 |
649 TEST(HttpUtilTest, GenerateAcceptLanguageHeader) { | 537 TEST(HttpUtilTest, GenerateAcceptLanguageHeader) { |
650 EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"), | 538 EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"), |
651 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de")); | 539 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de")); |
652 EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6,ko;q=0.4,zh-CN;q=0.2," | 540 EXPECT_EQ(std::string( |
653 "ja;q=0.2"), | 541 "en-US,fr;q=0.8,de;q=0.6,ko;q=0.4,zh-CN;q=0.2," |
| 542 "ja;q=0.2"), |
654 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja")); | 543 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja")); |
655 } | 544 } |
656 | 545 |
657 // HttpResponseHeadersTest.GetMimeType also tests ParseContentType. | 546 // HttpResponseHeadersTest.GetMimeType also tests ParseContentType. |
658 TEST(HttpUtilTest, ParseContentType) { | 547 TEST(HttpUtilTest, ParseContentType) { |
659 const struct { | 548 const struct { |
660 const char* content_type; | 549 const char* content_type; |
661 const char* expected_mime_type; | 550 const char* expected_mime_type; |
662 const char* expected_charset; | 551 const char* expected_charset; |
663 const bool expected_had_charset; | 552 const bool expected_had_charset; |
664 const char* expected_boundary; | 553 const char* expected_boundary; |
665 } tests[] = { | 554 } tests[] = { |
666 { "text/html; charset=utf-8", | 555 {"text/html; charset=utf-8", "text/html", "utf-8", true, ""}, |
667 "text/html", | 556 {"text/html; charset =utf-8", "text/html", "utf-8", true, ""}, |
668 "utf-8", | 557 {"text/html; charset= utf-8", "text/html", "utf-8", true, ""}, |
669 true, | 558 {"text/html; charset=utf-8 ", "text/html", "utf-8", true, ""}, |
670 "" | 559 {"text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs\"", "text/html", "", |
671 }, | 560 false, "\"WebKit-ada-df-dsf-adsfadsfs\""}, |
672 { "text/html; charset =utf-8", | 561 {"text/html; boundary =\"WebKit-ada-df-dsf-adsfadsfs\"", "text/html", |
673 "text/html", | 562 "", false, "\"WebKit-ada-df-dsf-adsfadsfs\""}, |
674 "utf-8", | 563 {"text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\"", "text/html", |
675 true, | 564 "", false, "\"WebKit-ada-df-dsf-adsfadsfs\""}, |
676 "" | 565 {"text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\" ", "text/html", |
677 }, | 566 "", false, "\"WebKit-ada-df-dsf-adsfadsfs\""}, |
678 { "text/html; charset= utf-8", | 567 {"text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs \"", "text/html", |
679 "text/html", | 568 "", false, "\"WebKit-ada-df-dsf-adsfadsfs \""}, |
680 "utf-8", | 569 {"text/html; boundary=WebKit-ada-df-dsf-adsfadsfs", "text/html", "", |
681 true, | 570 false, "WebKit-ada-df-dsf-adsfadsfs"}, |
682 "" | 571 // TODO(abarth): Add more interesting test cases. |
683 }, | 572 }; |
684 { "text/html; charset=utf-8 ", | |
685 "text/html", | |
686 "utf-8", | |
687 true, | |
688 "" | |
689 }, | |
690 { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs\"", | |
691 "text/html", | |
692 "", | |
693 false, | |
694 "\"WebKit-ada-df-dsf-adsfadsfs\"" | |
695 }, | |
696 { "text/html; boundary =\"WebKit-ada-df-dsf-adsfadsfs\"", | |
697 "text/html", | |
698 "", | |
699 false, | |
700 "\"WebKit-ada-df-dsf-adsfadsfs\"" | |
701 }, | |
702 { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\"", | |
703 "text/html", | |
704 "", | |
705 false, | |
706 "\"WebKit-ada-df-dsf-adsfadsfs\"" | |
707 }, | |
708 { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\" ", | |
709 "text/html", | |
710 "", | |
711 false, | |
712 "\"WebKit-ada-df-dsf-adsfadsfs\"" | |
713 }, | |
714 { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs \"", | |
715 "text/html", | |
716 "", | |
717 false, | |
718 "\"WebKit-ada-df-dsf-adsfadsfs \"" | |
719 }, | |
720 { "text/html; boundary=WebKit-ada-df-dsf-adsfadsfs", | |
721 "text/html", | |
722 "", | |
723 false, | |
724 "WebKit-ada-df-dsf-adsfadsfs" | |
725 }, | |
726 // TODO(abarth): Add more interesting test cases. | |
727 }; | |
728 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 573 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
729 std::string mime_type; | 574 std::string mime_type; |
730 std::string charset; | 575 std::string charset; |
731 bool had_charset = false; | 576 bool had_charset = false; |
732 std::string boundary; | 577 std::string boundary; |
733 net::HttpUtil::ParseContentType(tests[i].content_type, &mime_type, | 578 net::HttpUtil::ParseContentType( |
734 &charset, &had_charset, &boundary); | 579 tests[i].content_type, &mime_type, &charset, &had_charset, &boundary); |
735 EXPECT_EQ(tests[i].expected_mime_type, mime_type) << "i=" << i; | 580 EXPECT_EQ(tests[i].expected_mime_type, mime_type) << "i=" << i; |
736 EXPECT_EQ(tests[i].expected_charset, charset) << "i=" << i; | 581 EXPECT_EQ(tests[i].expected_charset, charset) << "i=" << i; |
737 EXPECT_EQ(tests[i].expected_had_charset, had_charset) << "i=" << i; | 582 EXPECT_EQ(tests[i].expected_had_charset, had_charset) << "i=" << i; |
738 EXPECT_EQ(tests[i].expected_boundary, boundary) << "i=" << i; | 583 EXPECT_EQ(tests[i].expected_boundary, boundary) << "i=" << i; |
739 } | 584 } |
740 } | 585 } |
741 | 586 |
742 TEST(HttpUtilTest, ParseRanges) { | 587 TEST(HttpUtilTest, ParseRanges) { |
743 const struct { | 588 const struct { |
744 const char* headers; | 589 const char* headers; |
745 bool expected_return_value; | 590 bool expected_return_value; |
746 size_t expected_ranges_size; | 591 size_t expected_ranges_size; |
747 const struct { | 592 const struct { |
748 int64 expected_first_byte_position; | 593 int64 expected_first_byte_position; |
749 int64 expected_last_byte_position; | 594 int64 expected_last_byte_position; |
750 int64 expected_suffix_length; | 595 int64 expected_suffix_length; |
751 } expected_ranges[10]; | 596 } expected_ranges[10]; |
752 } tests[] = { | 597 } tests[] = { |
753 { "Range: bytes=0-10", | 598 {"Range: bytes=0-10", |
754 true, | 599 true, |
755 1, | 600 1, |
756 { {0, 10, -1}, } | 601 { |
757 }, | 602 {0, 10, -1}, |
758 { "Range: bytes=10-0", | 603 }}, |
759 false, | 604 {"Range: bytes=10-0", false, 0, {}}, |
760 0, | 605 {"Range: BytES=0-10", |
761 {} | 606 true, |
762 }, | 607 1, |
763 { "Range: BytES=0-10", | 608 { |
764 true, | 609 {0, 10, -1}, |
765 1, | 610 }}, |
766 { {0, 10, -1}, } | 611 {"Range: megabytes=0-10", false, 0, {}}, |
767 }, | 612 {"Range: bytes0-10", false, 0, {}}, |
768 { "Range: megabytes=0-10", | 613 {"Range: bytes=0-0,0-10,10-20,100-200,100-,-200", |
769 false, | 614 true, |
770 0, | 615 6, |
771 {} | 616 { |
772 }, | 617 {0, 0, -1}, |
773 { "Range: bytes0-10", | 618 {0, 10, -1}, |
774 false, | 619 {10, 20, -1}, |
775 0, | 620 {100, 200, -1}, |
776 {} | 621 {100, -1, -1}, |
777 }, | 622 {-1, -1, 200}, |
778 { "Range: bytes=0-0,0-10,10-20,100-200,100-,-200", | 623 }}, |
779 true, | 624 {"Range: bytes=0-10\r\n" |
780 6, | 625 "Range: bytes=0-10,10-20,100-200,100-,-200", |
781 { {0, 0, -1}, | 626 true, |
782 {0, 10, -1}, | 627 1, |
783 {10, 20, -1}, | 628 {{0, 10, -1}}}, |
784 {100, 200, -1}, | 629 {"Range: bytes=", false, 0, {}}, |
785 {100, -1, -1}, | 630 {"Range: bytes=-", false, 0, {}}, |
786 {-1, -1, 200}, | 631 {"Range: bytes=0-10-", false, 0, {}}, |
787 } | 632 {"Range: bytes=-0-10", false, 0, {}}, |
788 }, | 633 {"Range: bytes =0-10\r\n", true, 1, {{0, 10, -1}}}, |
789 { "Range: bytes=0-10\r\n" | 634 {"Range: bytes= 0-10 \r\n", true, 1, {{0, 10, -1}}}, |
790 "Range: bytes=0-10,10-20,100-200,100-,-200", | 635 {"Range: bytes = 0 - 10 \r\n", true, 1, {{0, 10, -1}}}, |
791 true, | 636 {"Range: bytes= 0-1 0\r\n", false, 0, {}}, |
792 1, | 637 {"Range: bytes= 0- -10\r\n", false, 0, {}}, |
793 { {0, 10, -1} | 638 {"Range: bytes= 0 - 1 , 10 -20, 100- 200 , 100-, -200 \r\n", |
794 } | 639 true, |
795 }, | 640 5, |
796 { "Range: bytes=", | 641 { |
797 false, | 642 {0, 1, -1}, |
798 0, | 643 {10, 20, -1}, |
799 {} | 644 {100, 200, -1}, |
800 }, | 645 {100, -1, -1}, |
801 { "Range: bytes=-", | 646 {-1, -1, 200}, |
802 false, | 647 }}, |
803 0, | 648 }; |
804 {} | |
805 }, | |
806 { "Range: bytes=0-10-", | |
807 false, | |
808 0, | |
809 {} | |
810 }, | |
811 { "Range: bytes=-0-10", | |
812 false, | |
813 0, | |
814 {} | |
815 }, | |
816 { "Range: bytes =0-10\r\n", | |
817 true, | |
818 1, | |
819 { {0, 10, -1} | |
820 } | |
821 }, | |
822 { "Range: bytes= 0-10 \r\n", | |
823 true, | |
824 1, | |
825 { {0, 10, -1} | |
826 } | |
827 }, | |
828 { "Range: bytes = 0 - 10 \r\n", | |
829 true, | |
830 1, | |
831 { {0, 10, -1} | |
832 } | |
833 }, | |
834 { "Range: bytes= 0-1 0\r\n", | |
835 false, | |
836 0, | |
837 {} | |
838 }, | |
839 { "Range: bytes= 0- -10\r\n", | |
840 false, | |
841 0, | |
842 {} | |
843 }, | |
844 { "Range: bytes= 0 - 1 , 10 -20, 100- 200 , 100-, -200 \r\n", | |
845 true, | |
846 5, | |
847 { {0, 1, -1}, | |
848 {10, 20, -1}, | |
849 {100, 200, -1}, | |
850 {100, -1, -1}, | |
851 {-1, -1, 200}, | |
852 } | |
853 }, | |
854 }; | |
855 | 649 |
856 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | 650 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
857 std::vector<net::HttpByteRange> ranges; | 651 std::vector<net::HttpByteRange> ranges; |
858 bool return_value = HttpUtil::ParseRanges(std::string(tests[i].headers), | 652 bool return_value = |
859 &ranges); | 653 HttpUtil::ParseRanges(std::string(tests[i].headers), &ranges); |
860 EXPECT_EQ(tests[i].expected_return_value, return_value); | 654 EXPECT_EQ(tests[i].expected_return_value, return_value); |
861 if (return_value) { | 655 if (return_value) { |
862 EXPECT_EQ(tests[i].expected_ranges_size, ranges.size()); | 656 EXPECT_EQ(tests[i].expected_ranges_size, ranges.size()); |
863 for (size_t j = 0; j < ranges.size(); ++j) { | 657 for (size_t j = 0; j < ranges.size(); ++j) { |
864 EXPECT_EQ(tests[i].expected_ranges[j].expected_first_byte_position, | 658 EXPECT_EQ(tests[i].expected_ranges[j].expected_first_byte_position, |
865 ranges[j].first_byte_position()); | 659 ranges[j].first_byte_position()); |
866 EXPECT_EQ(tests[i].expected_ranges[j].expected_last_byte_position, | 660 EXPECT_EQ(tests[i].expected_ranges[j].expected_last_byte_position, |
867 ranges[j].last_byte_position()); | 661 ranges[j].last_byte_position()); |
868 EXPECT_EQ(tests[i].expected_ranges[j].expected_suffix_length, | 662 EXPECT_EQ(tests[i].expected_ranges[j].expected_suffix_length, |
869 ranges[j].suffix_length()); | 663 ranges[j].suffix_length()); |
(...skipping 11 matching lines...) Expand all Loading... |
881 if (!expect_valid) { | 675 if (!expect_valid) { |
882 return; | 676 return; |
883 } | 677 } |
884 | 678 |
885 // Let's make sure that these never change (i.e., when a quoted value is | 679 // Let's make sure that these never change (i.e., when a quoted value is |
886 // unquoted, it should be cached on the first calls and not regenerated | 680 // unquoted, it should be cached on the first calls and not regenerated |
887 // later). | 681 // later). |
888 std::string::const_iterator first_value_begin = parser->value_begin(); | 682 std::string::const_iterator first_value_begin = parser->value_begin(); |
889 std::string::const_iterator first_value_end = parser->value_end(); | 683 std::string::const_iterator first_value_end = parser->value_end(); |
890 | 684 |
891 ASSERT_EQ(expected_name, std::string(parser->name_begin(), | 685 ASSERT_EQ(expected_name, |
892 parser->name_end())); | 686 std::string(parser->name_begin(), parser->name_end())); |
893 ASSERT_EQ(expected_name, parser->name()); | 687 ASSERT_EQ(expected_name, parser->name()); |
894 ASSERT_EQ(expected_value, std::string(parser->value_begin(), | 688 ASSERT_EQ(expected_value, |
895 parser->value_end())); | 689 std::string(parser->value_begin(), parser->value_end())); |
896 ASSERT_EQ(expected_value, parser->value()); | 690 ASSERT_EQ(expected_value, parser->value()); |
897 | 691 |
898 // Make sure they didn't/don't change. | 692 // Make sure they didn't/don't change. |
899 ASSERT_TRUE(first_value_begin == parser->value_begin()); | 693 ASSERT_TRUE(first_value_begin == parser->value_begin()); |
900 ASSERT_TRUE(first_value_end == parser->value_end()); | 694 ASSERT_TRUE(first_value_end == parser->value_end()); |
901 } | 695 } |
902 | 696 |
903 void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator* parser, | 697 void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator* parser, |
904 bool expect_next, | 698 bool expect_next, |
905 bool expect_valid, | 699 bool expect_valid, |
906 std::string expected_name, | 700 std::string expected_name, |
907 std::string expected_value) { | 701 std::string expected_value) { |
908 ASSERT_EQ(expect_next, parser->GetNext()); | 702 ASSERT_EQ(expect_next, parser->GetNext()); |
909 ASSERT_EQ(expect_valid, parser->valid()); | 703 ASSERT_EQ(expect_valid, parser->valid()); |
910 if (!expect_next || !expect_valid) { | 704 if (!expect_next || !expect_valid) { |
911 return; | 705 return; |
912 } | 706 } |
913 | 707 |
914 CheckCurrentNameValuePair(parser, | 708 CheckCurrentNameValuePair( |
915 expect_valid, | 709 parser, expect_valid, expected_name, expected_value); |
916 expected_name, | |
917 expected_value); | |
918 } | 710 } |
919 | 711 |
920 void CheckInvalidNameValuePair(std::string valid_part, | 712 void CheckInvalidNameValuePair(std::string valid_part, |
921 std::string invalid_part) { | 713 std::string invalid_part) { |
922 std::string whole_string = valid_part + invalid_part; | 714 std::string whole_string = valid_part + invalid_part; |
923 | 715 |
924 HttpUtil::NameValuePairsIterator valid_parser(valid_part.begin(), | 716 HttpUtil::NameValuePairsIterator valid_parser( |
925 valid_part.end(), | 717 valid_part.begin(), valid_part.end(), ';'); |
926 ';'); | 718 HttpUtil::NameValuePairsIterator invalid_parser( |
927 HttpUtil::NameValuePairsIterator invalid_parser(whole_string.begin(), | 719 whole_string.begin(), whole_string.end(), ';'); |
928 whole_string.end(), | |
929 ';'); | |
930 | 720 |
931 ASSERT_TRUE(valid_parser.valid()); | 721 ASSERT_TRUE(valid_parser.valid()); |
932 ASSERT_TRUE(invalid_parser.valid()); | 722 ASSERT_TRUE(invalid_parser.valid()); |
933 | 723 |
934 // Both parsers should return all the same values until "valid_parser" is | 724 // Both parsers should return all the same values until "valid_parser" is |
935 // exhausted. | 725 // exhausted. |
936 while (valid_parser.GetNext()) { | 726 while (valid_parser.GetNext()) { |
937 ASSERT_TRUE(invalid_parser.GetNext()); | 727 ASSERT_TRUE(invalid_parser.GetNext()); |
938 ASSERT_TRUE(valid_parser.valid()); | 728 ASSERT_TRUE(valid_parser.valid()); |
939 ASSERT_TRUE(invalid_parser.valid()); | 729 ASSERT_TRUE(invalid_parser.valid()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 TEST(HttpUtilTest, NameValuePairsIteratorEmptyInput) { | 780 TEST(HttpUtilTest, NameValuePairsIteratorEmptyInput) { |
991 std::string data; | 781 std::string data; |
992 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); | 782 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); |
993 | 783 |
994 EXPECT_TRUE(parser.valid()); | 784 EXPECT_TRUE(parser.valid()); |
995 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( | 785 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( |
996 &parser, false, true, std::string(), std::string())); | 786 &parser, false, true, std::string(), std::string())); |
997 } | 787 } |
998 | 788 |
999 TEST(HttpUtilTest, NameValuePairsIterator) { | 789 TEST(HttpUtilTest, NameValuePairsIterator) { |
1000 std::string data = "alpha=1; beta= 2 ;cappa =' 3; ';" | 790 std::string data = |
1001 "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;" | 791 "alpha=1; beta= 2 ;cappa =' 3; ';" |
1002 "f='\\'\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\'';" | 792 "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;" |
1003 "g=''; h='hello'"; | 793 "f='\\'\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\'';" |
| 794 "g=''; h='hello'"; |
1004 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); | 795 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); |
1005 EXPECT_TRUE(parser.valid()); | 796 EXPECT_TRUE(parser.valid()); |
1006 | 797 |
1007 ASSERT_NO_FATAL_FAILURE( | 798 ASSERT_NO_FATAL_FAILURE( |
1008 CheckNextNameValuePair(&parser, true, true, "alpha", "1")); | 799 CheckNextNameValuePair(&parser, true, true, "alpha", "1")); |
1009 ASSERT_NO_FATAL_FAILURE( | 800 ASSERT_NO_FATAL_FAILURE( |
1010 CheckNextNameValuePair(&parser, true, true, "beta", "2")); | 801 CheckNextNameValuePair(&parser, true, true, "beta", "2")); |
1011 ASSERT_NO_FATAL_FAILURE( | 802 ASSERT_NO_FATAL_FAILURE( |
1012 CheckNextNameValuePair(&parser, true, true, "cappa", " 3; ")); | 803 CheckNextNameValuePair(&parser, true, true, "cappa", " 3; ")); |
1013 ASSERT_NO_FATAL_FAILURE( | 804 ASSERT_NO_FATAL_FAILURE( |
(...skipping 12 matching lines...) Expand all Loading... |
1026 &parser, false, true, std::string(), std::string())); | 817 &parser, false, true, std::string(), std::string())); |
1027 } | 818 } |
1028 | 819 |
1029 TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) { | 820 TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) { |
1030 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; beta")); | 821 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; beta")); |
1031 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "beta")); | 822 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "beta")); |
1032 | 823 |
1033 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; 'beta'=2")); | 824 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; 'beta'=2")); |
1034 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "'beta'=2")); | 825 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "'beta'=2")); |
1035 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta=")); | 826 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta=")); |
1036 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", | 827 ASSERT_NO_FATAL_FAILURE( |
1037 ";beta=;cappa=2")); | 828 CheckInvalidNameValuePair("alpha=1", ";beta=;cappa=2")); |
1038 | 829 |
1039 // According to the spec this is an error, but it doesn't seem appropriate to | 830 // According to the spec this is an error, but it doesn't seem appropriate to |
1040 // change our behaviour to be less permissive at this time. | 831 // change our behaviour to be less permissive at this time. |
1041 // See NameValuePairsIteratorExtraSeparators test | 832 // See NameValuePairsIteratorExtraSeparators test |
1042 // ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";; beta=2")); | 833 // ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";; beta=2")); |
1043 } | 834 } |
1044 | 835 |
1045 // If we are going to support extra separators against the spec, let's just make | 836 // If we are going to support extra separators against the spec, let's just make |
1046 // sure they work rationally. | 837 // sure they work rationally. |
1047 TEST(HttpUtilTest, NameValuePairsIteratorExtraSeparators) { | 838 TEST(HttpUtilTest, NameValuePairsIteratorExtraSeparators) { |
(...skipping 16 matching lines...) Expand all Loading... |
1064 TEST(HttpUtilTest, NameValuePairsIteratorMissingEndQuote) { | 855 TEST(HttpUtilTest, NameValuePairsIteratorMissingEndQuote) { |
1065 std::string data = "name='value"; | 856 std::string data = "name='value"; |
1066 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); | 857 HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';'); |
1067 EXPECT_TRUE(parser.valid()); | 858 EXPECT_TRUE(parser.valid()); |
1068 | 859 |
1069 ASSERT_NO_FATAL_FAILURE( | 860 ASSERT_NO_FATAL_FAILURE( |
1070 CheckNextNameValuePair(&parser, true, true, "name", "value")); | 861 CheckNextNameValuePair(&parser, true, true, "name", "value")); |
1071 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( | 862 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( |
1072 &parser, false, true, std::string(), std::string())); | 863 &parser, false, true, std::string(), std::string())); |
1073 } | 864 } |
OLD | NEW |