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
3 // found in the LICENSE file.
7 #include "base/basictypes.h"
8 #include "base/strings/string_util.h"
9 #include "net/http/http_util.h"
10 #include "testing/gtest/include/gtest/gtest.h"
15 class HttpUtilTest
: public testing::Test
{};
18 TEST(HttpUtilTest
, IsSafeHeader
) {
19 static const char* unsafe_headers
[] = {
30 "access-control-request-headers",
31 "access-control-request-method",
36 "content-transfer-encoding",
50 for (size_t i
= 0; i
< arraysize(unsafe_headers
); ++i
) {
51 EXPECT_FALSE(HttpUtil::IsSafeHeader(unsafe_headers
[i
]))
53 EXPECT_FALSE(HttpUtil::IsSafeHeader(StringToUpperASCII(std::string(
54 unsafe_headers
[i
])))) << unsafe_headers
[i
];
56 static const char* safe_headers
[] = {
60 "content-disposition",
66 "access-control-request-headersa",
67 "access-control-request-header",
68 "access_control_request_header",
69 "access-control-request-methoda",
70 "access_control_request_method",
77 "content-transfer-encodinga",
78 "content_transfer_encoding",
96 for (size_t i
= 0; i
< arraysize(safe_headers
); ++i
) {
97 EXPECT_TRUE(HttpUtil::IsSafeHeader(safe_headers
[i
])) << safe_headers
[i
];
98 EXPECT_TRUE(HttpUtil::IsSafeHeader(StringToUpperASCII(std::string(
99 safe_headers
[i
])))) << safe_headers
[i
];
103 TEST(HttpUtilTest
, HasHeader
) {
104 static const struct {
107 bool expected_result
;
109 { "", "foo", false },
110 { "foo\r\nbar", "foo", false },
111 { "ffoo: 1", "foo", false },
112 { "foo: 1", "foo", true },
113 { "foo: 1\r\nbar: 2", "foo", true },
114 { "fOO: 1\r\nbar: 2", "foo", true },
115 { "g: 0\r\nfoo: 1\r\nbar: 2", "foo", true },
117 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
118 bool result
= HttpUtil::HasHeader(tests
[i
].headers
, tests
[i
].name
);
119 EXPECT_EQ(tests
[i
].expected_result
, result
);
123 TEST(HttpUtilTest
, StripHeaders
) {
124 static const char* headers
=
126 "Content-Type: text/plain\r\n"
131 "OrIGin: origin2\r\n";
133 static const char* header_names
[] = {
134 "origin", "content-type", "cookies"
137 static const char* expected_stripped_headers
=
139 "Server: Apache\r\n";
141 EXPECT_EQ(expected_stripped_headers
,
142 HttpUtil::StripHeaders(headers
, header_names
,
143 arraysize(header_names
)));
146 TEST(HttpUtilTest
, HeadersIterator
) {
147 std::string headers
= "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n";
149 HttpUtil::HeadersIterator
it(headers
.begin(), headers
.end(), "\r\n");
151 ASSERT_TRUE(it
.GetNext());
152 EXPECT_EQ(std::string("foo"), it
.name());
153 EXPECT_EQ(std::string("1"), it
.values());
155 ASSERT_TRUE(it
.GetNext());
156 EXPECT_EQ(std::string("bar"), it
.name());
157 EXPECT_EQ(std::string("hello world"), it
.values());
159 ASSERT_TRUE(it
.GetNext());
160 EXPECT_EQ(std::string("baz"), it
.name());
161 EXPECT_EQ(std::string("3"), it
.values());
163 EXPECT_FALSE(it
.GetNext());
166 TEST(HttpUtilTest
, HeadersIterator_MalformedLine
) {
167 std::string headers
= "foo: 1\n: 2\n3\nbar: 4";
169 HttpUtil::HeadersIterator
it(headers
.begin(), headers
.end(), "\n");
171 ASSERT_TRUE(it
.GetNext());
172 EXPECT_EQ(std::string("foo"), it
.name());
173 EXPECT_EQ(std::string("1"), it
.values());
175 ASSERT_TRUE(it
.GetNext());
176 EXPECT_EQ(std::string("bar"), it
.name());
177 EXPECT_EQ(std::string("4"), it
.values());
179 EXPECT_FALSE(it
.GetNext());
182 TEST(HttpUtilTest
, HeadersIterator_AdvanceTo
) {
183 std::string headers
= "foo: 1\r\n: 2\r\n3\r\nbar: 4";
185 HttpUtil::HeadersIterator
it(headers
.begin(), headers
.end(), "\r\n");
186 EXPECT_TRUE(it
.AdvanceTo("foo"));
187 EXPECT_EQ("foo", it
.name());
188 EXPECT_TRUE(it
.AdvanceTo("bar"));
189 EXPECT_EQ("bar", it
.name());
190 EXPECT_FALSE(it
.AdvanceTo("blat"));
191 EXPECT_FALSE(it
.GetNext()); // should be at end of headers
194 TEST(HttpUtilTest
, HeadersIterator_Reset
) {
195 std::string headers
= "foo: 1\r\n: 2\r\n3\r\nbar: 4";
196 HttpUtil::HeadersIterator
it(headers
.begin(), headers
.end(), "\r\n");
197 // Search past "foo".
198 EXPECT_TRUE(it
.AdvanceTo("bar"));
199 // Now try advancing to "foo". This time it should fail since the iterator
200 // position is past it.
201 EXPECT_FALSE(it
.AdvanceTo("foo"));
203 // Now that we reset the iterator position, we should find 'foo'
204 EXPECT_TRUE(it
.AdvanceTo("foo"));
207 TEST(HttpUtilTest
, ValuesIterator
) {
208 std::string values
= " must-revalidate, no-cache=\"foo, bar\"\t, private ";
210 HttpUtil::ValuesIterator
it(values
.begin(), values
.end(), ',');
212 ASSERT_TRUE(it
.GetNext());
213 EXPECT_EQ(std::string("must-revalidate"), it
.value());
215 ASSERT_TRUE(it
.GetNext());
216 EXPECT_EQ(std::string("no-cache=\"foo, bar\""), it
.value());
218 ASSERT_TRUE(it
.GetNext());
219 EXPECT_EQ(std::string("private"), it
.value());
221 EXPECT_FALSE(it
.GetNext());
224 TEST(HttpUtilTest
, ValuesIterator_Blanks
) {
225 std::string values
= " \t ";
227 HttpUtil::ValuesIterator
it(values
.begin(), values
.end(), ',');
229 EXPECT_FALSE(it
.GetNext());
232 TEST(HttpUtilTest
, Unquote
) {
233 // Replace <backslash> " with ".
234 EXPECT_STREQ("xyz\"abc", HttpUtil::Unquote("\"xyz\\\"abc\"").c_str());
236 // Replace <backslash> <backslash> with <backslash>
237 EXPECT_STREQ("xyz\\abc", HttpUtil::Unquote("\"xyz\\\\abc\"").c_str());
238 EXPECT_STREQ("xyz\\\\\\abc",
239 HttpUtil::Unquote("\"xyz\\\\\\\\\\\\abc\"").c_str());
241 // Replace <backslash> X with X
242 EXPECT_STREQ("xyzXabc", HttpUtil::Unquote("\"xyz\\Xabc\"").c_str());
244 // Act as identity function on unquoted inputs.
245 EXPECT_STREQ("X", HttpUtil::Unquote("X").c_str());
246 EXPECT_STREQ("\"", HttpUtil::Unquote("\"").c_str());
248 // Allow single quotes to act as quote marks.
249 // Not part of RFC 2616.
250 EXPECT_STREQ("x\"", HttpUtil::Unquote("'x\"'").c_str());
253 TEST(HttpUtilTest
, Quote
) {
254 EXPECT_STREQ("\"xyz\\\"abc\"", HttpUtil::Quote("xyz\"abc").c_str());
256 // Replace <backslash> <backslash> with <backslash>
257 EXPECT_STREQ("\"xyz\\\\abc\"", HttpUtil::Quote("xyz\\abc").c_str());
259 // Replace <backslash> X with X
260 EXPECT_STREQ("\"xyzXabc\"", HttpUtil::Quote("xyzXabc").c_str());
263 TEST(HttpUtilTest
, LocateEndOfHeaders
) {
268 { "foo\r\nbar\r\n\r\n", 12 },
269 { "foo\nbar\n\n", 9 },
270 { "foo\r\nbar\r\n\r\njunk", 12 },
271 { "foo\nbar\n\njunk", 9 },
272 { "foo\nbar\n\r\njunk", 10 },
273 { "foo\nbar\r\n\njunk", 10 },
275 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
276 int input_len
= static_cast<int>(strlen(tests
[i
].input
));
277 int eoh
= HttpUtil::LocateEndOfHeaders(tests
[i
].input
, input_len
);
278 EXPECT_EQ(tests
[i
].expected_result
, eoh
);
282 TEST(HttpUtilTest
, AssembleRawHeaders
) {
284 const char* input
; // with '|' representing '\0'
285 const char* expected_result
; // with '\0' changed to '|'
287 { "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||" },
290 { "HTTP/1.0 200 OK\nFoo: 1\nBar: 2\n\n",
291 "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" },
293 // Valid line continuation (single SP).
301 "Foo: 1 continuation|"
305 // Valid line continuation (single HT).
313 "Foo: 1 continuation|"
317 // Valid line continuation (multiple SP).
325 "Foo: 1 continuation|"
329 // Valid line continuation (multiple HT).
333 "\t\t\tcontinuation\n"
337 "Foo: 1 continuation|"
341 // Valid line continuation (mixed HT, SP).
345 " \t \t continuation\n"
349 "Foo: 1 continuation|"
353 // Valid multi-line continuation
363 "Foo: 1 continuation1 continuation2 continuation3|"
367 // Continuation of quoted value.
368 // This is different from what Firefox does, since it
369 // will preserve the LWS.
377 "Etag: \"34534-d3 134q\"|"
381 // Valid multi-line continuation, full LWS lines
390 // One SP per continued line = 3.
392 "Foo: 1 continuation|"
396 // Valid multi-line continuation, all LWS
405 // One SP per continued line = 3.
411 // Valid line continuation (No value bytes in first line).
423 // Not a line continuation (can't continue status line).
434 // Not a line continuation (can't continue status line).
447 // Not a line continuation (can't continue status line).
460 // Unterminated status line.
467 // Single terminated, with headers
478 // Not terminated, with headers
489 // Not a line continuation (VT)
493 "\vInvalidContinuation\n"
498 "\vInvalidContinuation|"
502 // Not a line continuation (formfeed)
506 "\fInvalidContinuation\n"
511 "\fInvalidContinuation|"
515 // Not a line continuation -- can't continue header names.
520 "\tInvalidContinuation\n"
526 "\tInvalidContinuation|"
530 // Not a line continuation -- no value to continue.
535 " not-a-continuation\n"
541 " not-a-continuation|"
545 // Not a line continuation -- no valid name.
558 // Not a line continuation -- no valid name (whitespace)
571 // Embed NULLs in the status line. They should not be understood
572 // as line separators.
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||"
578 // Embed NULLs in a header line. They should not be understood as
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||"
585 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
586 std::string input
= tests
[i
].input
;
587 std::replace(input
.begin(), input
.end(), '|', '\0');
588 std::string raw
= HttpUtil::AssembleRawHeaders(input
.data(), input
.size());
589 std::replace(raw
.begin(), raw
.end(), '\0', '|');
590 EXPECT_EQ(tests
[i
].expected_result
, raw
);
594 // Test SpecForRequest() and PathForRequest().
595 TEST(HttpUtilTest
, RequestUrlSanitize
) {
598 const char* expected_spec
;
599 const char* expected_path
;
601 { // Check that #hash is removed.
602 "http://www.google.com:78/foobar?query=1#hash",
603 "http://www.google.com:78/foobar?query=1",
606 { // The reference may itself contain # -- strip all of it.
607 "http://192.168.0.1?query=1#hash#10#11#13#14",
608 "http://192.168.0.1/?query=1",
611 { // Strip username/password.
612 "http://user:pass@google.com",
613 "http://google.com/",
617 "https://www.google.com:78/foobar?query=1#hash",
618 "https://www.google.com:78/foobar?query=1",
621 { // WebSocket's ws scheme
622 "ws://www.google.com:78/foobar?query=1#hash",
623 "ws://www.google.com:78/foobar?query=1",
626 { // WebSocket's wss scheme
627 "wss://www.google.com:78/foobar?query=1#hash",
628 "wss://www.google.com:78/foobar?query=1",
632 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
633 GURL
url(GURL(tests
[i
].url
));
634 std::string
expected_spec(tests
[i
].expected_spec
);
635 std::string
expected_path(tests
[i
].expected_path
);
637 EXPECT_EQ(expected_spec
, HttpUtil::SpecForRequest(url
));
638 EXPECT_EQ(expected_path
, HttpUtil::PathForRequest(url
));
642 // Test SpecForRequest() for "ftp" scheme.
643 TEST(HttpUtilTest
, SpecForRequestForUrlWithFtpScheme
) {
644 GURL
ftp_url("ftp://user:pass@google.com/pub/chromium/");
645 EXPECT_EQ("ftp://google.com/pub/chromium/",
646 HttpUtil::SpecForRequest(ftp_url
));
649 TEST(HttpUtilTest
, GenerateAcceptLanguageHeader
) {
650 EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"),
651 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,"
654 HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja"));
657 // HttpResponseHeadersTest.GetMimeType also tests ParseContentType.
658 TEST(HttpUtilTest
, ParseContentType
) {
660 const char* content_type
;
661 const char* expected_mime_type
;
662 const char* expected_charset
;
663 const bool expected_had_charset
;
664 const char* expected_boundary
;
666 { "text/html; charset=utf-8",
672 { "text/html; charset =utf-8",
678 { "text/html; charset= utf-8",
684 { "text/html; charset=utf-8 ",
690 { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs\"",
694 "\"WebKit-ada-df-dsf-adsfadsfs\""
696 { "text/html; boundary =\"WebKit-ada-df-dsf-adsfadsfs\"",
700 "\"WebKit-ada-df-dsf-adsfadsfs\""
702 { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\"",
706 "\"WebKit-ada-df-dsf-adsfadsfs\""
708 { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\" ",
712 "\"WebKit-ada-df-dsf-adsfadsfs\""
714 { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs \"",
718 "\"WebKit-ada-df-dsf-adsfadsfs \""
720 { "text/html; boundary=WebKit-ada-df-dsf-adsfadsfs",
724 "WebKit-ada-df-dsf-adsfadsfs"
726 // TODO(abarth): Add more interesting test cases.
728 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
729 std::string mime_type
;
731 bool had_charset
= false;
732 std::string boundary
;
733 net::HttpUtil::ParseContentType(tests
[i
].content_type
, &mime_type
,
734 &charset
, &had_charset
, &boundary
);
735 EXPECT_EQ(tests
[i
].expected_mime_type
, mime_type
) << "i=" << i
;
736 EXPECT_EQ(tests
[i
].expected_charset
, charset
) << "i=" << i
;
737 EXPECT_EQ(tests
[i
].expected_had_charset
, had_charset
) << "i=" << i
;
738 EXPECT_EQ(tests
[i
].expected_boundary
, boundary
) << "i=" << i
;
742 TEST(HttpUtilTest
, ParseRanges
) {
745 bool expected_return_value
;
746 size_t expected_ranges_size
;
748 int64 expected_first_byte_position
;
749 int64 expected_last_byte_position
;
750 int64 expected_suffix_length
;
751 } expected_ranges
[10];
753 { "Range: bytes=0-10",
758 { "Range: bytes=10-0",
763 { "Range: BytES=0-10",
768 { "Range: megabytes=0-10",
773 { "Range: bytes0-10",
778 { "Range: bytes=0-0,0-10,10-20,100-200,100-,-200",
789 { "Range: bytes=0-10\r\n"
790 "Range: bytes=0-10,10-20,100-200,100-,-200",
806 { "Range: bytes=0-10-",
811 { "Range: bytes=-0-10",
816 { "Range: bytes =0-10\r\n",
822 { "Range: bytes= 0-10 \r\n",
828 { "Range: bytes = 0 - 10 \r\n",
834 { "Range: bytes= 0-1 0\r\n",
839 { "Range: bytes= 0- -10\r\n",
844 { "Range: bytes= 0 - 1 , 10 -20, 100- 200 , 100-, -200 \r\n",
856 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
857 std::vector
<net::HttpByteRange
> ranges
;
858 bool return_value
= HttpUtil::ParseRanges(std::string(tests
[i
].headers
),
860 EXPECT_EQ(tests
[i
].expected_return_value
, return_value
);
862 EXPECT_EQ(tests
[i
].expected_ranges_size
, ranges
.size());
863 for (size_t j
= 0; j
< ranges
.size(); ++j
) {
864 EXPECT_EQ(tests
[i
].expected_ranges
[j
].expected_first_byte_position
,
865 ranges
[j
].first_byte_position());
866 EXPECT_EQ(tests
[i
].expected_ranges
[j
].expected_last_byte_position
,
867 ranges
[j
].last_byte_position());
868 EXPECT_EQ(tests
[i
].expected_ranges
[j
].expected_suffix_length
,
869 ranges
[j
].suffix_length());
876 void CheckCurrentNameValuePair(HttpUtil::NameValuePairsIterator
* parser
,
878 std::string expected_name
,
879 std::string expected_value
) {
880 ASSERT_EQ(expect_valid
, parser
->valid());
885 // 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
888 std::string::const_iterator first_value_begin
= parser
->value_begin();
889 std::string::const_iterator first_value_end
= parser
->value_end();
891 ASSERT_EQ(expected_name
, std::string(parser
->name_begin(),
892 parser
->name_end()));
893 ASSERT_EQ(expected_name
, parser
->name());
894 ASSERT_EQ(expected_value
, std::string(parser
->value_begin(),
895 parser
->value_end()));
896 ASSERT_EQ(expected_value
, parser
->value());
898 // Make sure they didn't/don't change.
899 ASSERT_TRUE(first_value_begin
== parser
->value_begin());
900 ASSERT_TRUE(first_value_end
== parser
->value_end());
903 void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator
* parser
,
906 std::string expected_name
,
907 std::string expected_value
) {
908 ASSERT_EQ(expect_next
, parser
->GetNext());
909 ASSERT_EQ(expect_valid
, parser
->valid());
910 if (!expect_next
|| !expect_valid
) {
914 CheckCurrentNameValuePair(parser
,
920 void CheckInvalidNameValuePair(std::string valid_part
,
921 std::string invalid_part
) {
922 std::string whole_string
= valid_part
+ invalid_part
;
924 HttpUtil::NameValuePairsIterator
valid_parser(valid_part
.begin(),
927 HttpUtil::NameValuePairsIterator
invalid_parser(whole_string
.begin(),
931 ASSERT_TRUE(valid_parser
.valid());
932 ASSERT_TRUE(invalid_parser
.valid());
934 // Both parsers should return all the same values until "valid_parser" is
936 while (valid_parser
.GetNext()) {
937 ASSERT_TRUE(invalid_parser
.GetNext());
938 ASSERT_TRUE(valid_parser
.valid());
939 ASSERT_TRUE(invalid_parser
.valid());
940 ASSERT_EQ(valid_parser
.name(), invalid_parser
.name());
941 ASSERT_EQ(valid_parser
.value(), invalid_parser
.value());
944 // valid_parser is exhausted and remains 'valid'
945 ASSERT_TRUE(valid_parser
.valid());
947 // invalid_parser's corresponding call to GetNext also returns false...
948 ASSERT_FALSE(invalid_parser
.GetNext());
949 // ...but the parser is in an invalid state.
950 ASSERT_FALSE(invalid_parser
.valid());
953 } // anonymous namespace
955 TEST(HttpUtilTest
, NameValuePairsIteratorCopyAndAssign
) {
956 std::string data
= "alpha='\\'a\\''; beta=\" b \"; cappa='c;'; delta=\"d\"";
957 HttpUtil::NameValuePairsIterator
parser_a(data
.begin(), data
.end(), ';');
959 EXPECT_TRUE(parser_a
.valid());
960 ASSERT_NO_FATAL_FAILURE(
961 CheckNextNameValuePair(&parser_a
, true, true, "alpha", "'a'"));
963 HttpUtil::NameValuePairsIterator
parser_b(parser_a
);
964 // a and b now point to same location
965 ASSERT_NO_FATAL_FAILURE(
966 CheckCurrentNameValuePair(&parser_b
, true, "alpha", "'a'"));
967 ASSERT_NO_FATAL_FAILURE(
968 CheckCurrentNameValuePair(&parser_a
, true, "alpha", "'a'"));
970 // advance a, no effect on b
971 ASSERT_NO_FATAL_FAILURE(
972 CheckNextNameValuePair(&parser_a
, true, true, "beta", " b "));
973 ASSERT_NO_FATAL_FAILURE(
974 CheckCurrentNameValuePair(&parser_b
, true, "alpha", "'a'"));
976 // assign b the current state of a, no effect on a
978 ASSERT_NO_FATAL_FAILURE(
979 CheckCurrentNameValuePair(&parser_b
, true, "beta", " b "));
980 ASSERT_NO_FATAL_FAILURE(
981 CheckCurrentNameValuePair(&parser_a
, true, "beta", " b "));
983 // advance b, no effect on a
984 ASSERT_NO_FATAL_FAILURE(
985 CheckNextNameValuePair(&parser_b
, true, true, "cappa", "c;"));
986 ASSERT_NO_FATAL_FAILURE(
987 CheckCurrentNameValuePair(&parser_a
, true, "beta", " b "));
990 TEST(HttpUtilTest
, NameValuePairsIteratorEmptyInput
) {
992 HttpUtil::NameValuePairsIterator
parser(data
.begin(), data
.end(), ';');
994 EXPECT_TRUE(parser
.valid());
995 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
996 &parser
, false, true, std::string(), std::string()));
999 TEST(HttpUtilTest
, NameValuePairsIterator
) {
1000 std::string data
= "alpha=1; beta= 2 ;cappa =' 3; ';"
1001 "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;"
1002 "f='\\'\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\'';"
1004 HttpUtil::NameValuePairsIterator
parser(data
.begin(), data
.end(), ';');
1005 EXPECT_TRUE(parser
.valid());
1007 ASSERT_NO_FATAL_FAILURE(
1008 CheckNextNameValuePair(&parser
, true, true, "alpha", "1"));
1009 ASSERT_NO_FATAL_FAILURE(
1010 CheckNextNameValuePair(&parser
, true, true, "beta", "2"));
1011 ASSERT_NO_FATAL_FAILURE(
1012 CheckNextNameValuePair(&parser
, true, true, "cappa", " 3; "));
1013 ASSERT_NO_FATAL_FAILURE(
1014 CheckNextNameValuePair(&parser
, true, true, "delta", " \"4\" "));
1015 ASSERT_NO_FATAL_FAILURE(
1016 CheckNextNameValuePair(&parser
, true, true, "e", " '5'"));
1017 ASSERT_NO_FATAL_FAILURE(
1018 CheckNextNameValuePair(&parser
, true, true, "e", "6"));
1019 ASSERT_NO_FATAL_FAILURE(
1020 CheckNextNameValuePair(&parser
, true, true, "f", "'hello world'"));
1021 ASSERT_NO_FATAL_FAILURE(
1022 CheckNextNameValuePair(&parser
, true, true, "g", std::string()));
1023 ASSERT_NO_FATAL_FAILURE(
1024 CheckNextNameValuePair(&parser
, true, true, "h", "hello"));
1025 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1026 &parser
, false, true, std::string(), std::string()));
1029 TEST(HttpUtilTest
, NameValuePairsIteratorIllegalInputs
) {
1030 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; beta"));
1031 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "beta"));
1033 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; 'beta'=2"));
1034 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "'beta'=2"));
1035 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta="));
1036 ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1",
1039 // 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.
1041 // See NameValuePairsIteratorExtraSeparators test
1042 // ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";; beta=2"));
1045 // If we are going to support extra separators against the spec, let's just make
1046 // sure they work rationally.
1047 TEST(HttpUtilTest
, NameValuePairsIteratorExtraSeparators
) {
1048 std::string data
= " ; ;;alpha=1; ;; ; beta= 2;cappa=3;;; ; ";
1049 HttpUtil::NameValuePairsIterator
parser(data
.begin(), data
.end(), ';');
1050 EXPECT_TRUE(parser
.valid());
1052 ASSERT_NO_FATAL_FAILURE(
1053 CheckNextNameValuePair(&parser
, true, true, "alpha", "1"));
1054 ASSERT_NO_FATAL_FAILURE(
1055 CheckNextNameValuePair(&parser
, true, true, "beta", "2"));
1056 ASSERT_NO_FATAL_FAILURE(
1057 CheckNextNameValuePair(&parser
, true, true, "cappa", "3"));
1058 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1059 &parser
, false, true, std::string(), std::string()));
1062 // See comments on the implementation of NameValuePairsIterator::GetNext
1063 // regarding this derogation from the spec.
1064 TEST(HttpUtilTest
, NameValuePairsIteratorMissingEndQuote
) {
1065 std::string data
= "name='value";
1066 HttpUtil::NameValuePairsIterator
parser(data
.begin(), data
.end(), ';');
1067 EXPECT_TRUE(parser
.valid());
1069 ASSERT_NO_FATAL_FAILURE(
1070 CheckNextNameValuePair(&parser
, true, true, "name", "value"));
1071 ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1072 &parser
, false, true, std::string(), std::string()));