Index: net/http/http_response_headers_unittest.cc |
diff --git a/net/http/http_response_headers_unittest.cc b/net/http/http_response_headers_unittest.cc |
index 76790e3e69e526bdb60ba15cb6c0fd35cf68ce84..409a6bddd8a92d2e47428b604db1d2808591c25e 100644 |
--- a/net/http/http_response_headers_unittest.cc |
+++ b/net/http/http_response_headers_unittest.cc |
@@ -24,15 +24,6 @@ struct TestData { |
net::HttpVersion expected_version; |
}; |
-struct ContentTypeTestData { |
- const std::string raw_headers; |
- const std::string mime_type; |
- const bool has_mimetype; |
- const std::string charset; |
- const bool has_charset; |
- const std::string all_content_type; |
-}; |
- |
class HttpResponseHeadersTest : public testing::Test { |
}; |
@@ -91,7 +82,14 @@ class HttpResponseHeadersCacheControlTest : public HttpResponseHeadersTest { |
TimeDelta delta_; |
}; |
-void TestCommon(const TestData& test) { |
+class CommonHttpResponseHeadersTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<TestData> { |
+}; |
+ |
+TEST_P(CommonHttpResponseHeadersTest, TestCommon) { |
+ const TestData test = GetParam(); |
+ |
std::string raw_headers(test.raw_headers); |
HeadersToRaw(&raw_headers); |
std::string expected_headers(test.expected_headers); |
@@ -115,11 +113,10 @@ void TestCommon(const TestData& test) { |
EXPECT_TRUE(test.expected_version == parsed->GetHttpVersion()); |
} |
-} // end namespace |
+TestData response_headers_tests[] = { |
+ { |
+ // Normalise whitespace. |
-// Check that we normalize headers properly. |
-TEST(HttpResponseHeadersTest, NormalizeHeadersWhitespace) { |
- TestData test = { |
"HTTP/1.1 202 Accepted \n" |
"Content-TYPE : text/html; charset=utf-8 \n" |
"Set-Cookie: a \n" |
@@ -132,14 +129,10 @@ TEST(HttpResponseHeadersTest, NormalizeHeadersWhitespace) { |
202, |
net::HttpVersion(1,1), |
net::HttpVersion(1,1) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Normalize leading whitespace. |
-// Check that we normalize headers properly (header name is invalid if starts |
-// with LWS). |
-TEST(HttpResponseHeadersTest, NormalizeHeadersLeadingWhitespace) { |
- TestData test = { |
"HTTP/1.1 202 Accepted \n" |
// Starts with space -- will be skipped as invalid. |
" Content-TYPE : text/html; charset=utf-8 \n" |
@@ -152,12 +145,10 @@ TEST(HttpResponseHeadersTest, NormalizeHeadersLeadingWhitespace) { |
202, |
net::HttpVersion(1,1), |
net::HttpVersion(1,1) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Normalize blank headers. |
-TEST(HttpResponseHeadersTest, BlankHeaders) { |
- TestData test = { |
"HTTP/1.1 200 OK\n" |
"Header1 : \n" |
"Header2: \n" |
@@ -174,13 +165,10 @@ TEST(HttpResponseHeadersTest, BlankHeaders) { |
200, |
net::HttpVersion(1,1), |
net::HttpVersion(1,1) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Don't believe the http/0.9 version if there are headers! |
-TEST(HttpResponseHeadersTest, NormalizeHeadersVersion) { |
- // Don't believe the http/0.9 version if there are headers! |
- TestData test = { |
"hTtP/0.9 201\n" |
"Content-TYPE: text/html; charset=utf-8\n", |
@@ -190,14 +178,12 @@ TEST(HttpResponseHeadersTest, NormalizeHeadersVersion) { |
201, |
net::HttpVersion(0,9), |
net::HttpVersion(1,0) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Accept the HTTP/0.9 version number if there are no headers. |
+ // This is how HTTP/0.9 responses get constructed from |
+ // HttpNetworkTransaction. |
-TEST(HttpResponseHeadersTest, PreserveHttp09) { |
- // Accept the HTTP/0.9 version number if there are no headers. |
- // This is how HTTP/0.9 responses get constructed from HttpNetworkTransaction. |
- TestData test = { |
"hTtP/0.9 200 OK\n", |
"HTTP/0.9 200 OK\n", |
@@ -205,12 +191,10 @@ TEST(HttpResponseHeadersTest, PreserveHttp09) { |
200, |
net::HttpVersion(0,9), |
net::HttpVersion(0,9) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Add missing OK. |
-TEST(HttpResponseHeadersTest, NormalizeHeadersMissingOK) { |
- TestData test = { |
"HTTP/1.1 201\n" |
"Content-TYPE: text/html; charset=utf-8\n", |
@@ -220,12 +204,10 @@ TEST(HttpResponseHeadersTest, NormalizeHeadersMissingOK) { |
201, |
net::HttpVersion(1,1), |
net::HttpVersion(1,1) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Normalize bad status line. |
-TEST(HttpResponseHeadersTest, NormalizeHeadersBadStatus) { |
- TestData test = { |
"SCREWED_UP_STATUS_LINE\n" |
"Content-TYPE: text/html; charset=utf-8\n", |
@@ -233,14 +215,12 @@ TEST(HttpResponseHeadersTest, NormalizeHeadersBadStatus) { |
"Content-TYPE: text/html; charset=utf-8\n", |
200, |
- net::HttpVersion(0,0), // Parse error |
+ net::HttpVersion(0,0), // Parse error. |
net::HttpVersion(1,0) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Normalize invalid status code. |
-TEST(HttpResponseHeadersTest, NormalizeHeadersInvalidStatusCode) { |
- TestData test = { |
"HTTP/1.1 -1 Unknown\n", |
"HTTP/1.1 200 OK\n", |
@@ -248,25 +228,21 @@ TEST(HttpResponseHeadersTest, NormalizeHeadersInvalidStatusCode) { |
200, |
net::HttpVersion(1,1), |
net::HttpVersion(1,1) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Normalize empty header. |
-TEST(HttpResponseHeadersTest, NormalizeHeadersEmpty) { |
- TestData test = { |
"", |
"HTTP/1.0 200 OK\n", |
200, |
- net::HttpVersion(0,0), // Parse Error |
+ net::HttpVersion(0,0), // Parse Error. |
net::HttpVersion(1,0) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Normalize headers that start with a colon. |
-TEST(HttpResponseHeadersTest, NormalizeHeadersStartWithColon) { |
- TestData test = { |
"HTTP/1.1 202 Accepted \n" |
"foo: bar\n" |
": a \n" |
@@ -280,12 +256,10 @@ TEST(HttpResponseHeadersTest, NormalizeHeadersStartWithColon) { |
202, |
net::HttpVersion(1,1), |
net::HttpVersion(1,1) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Normalize headers that end with a colon. |
-TEST(HttpResponseHeadersTest, NormalizeHeadersStartWithColonAtEOL) { |
- TestData test = { |
"HTTP/1.1 202 Accepted \n" |
"foo: \n" |
"bar:\n" |
@@ -301,25 +275,21 @@ TEST(HttpResponseHeadersTest, NormalizeHeadersStartWithColonAtEOL) { |
202, |
net::HttpVersion(1,1), |
net::HttpVersion(1,1) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Normalize whitespace headers. |
-TEST(HttpResponseHeadersTest, NormalizeHeadersOfWhitepace) { |
- TestData test = { |
"\n \n", |
"HTTP/1.0 200 OK\n", |
200, |
- net::HttpVersion(0,0), // Parse error |
+ net::HttpVersion(0,0), // Parse error. |
net::HttpVersion(1,0) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+ { |
+ // Consolidate Set-Cookie headers. |
-TEST(HttpResponseHeadersTest, RepeatedSetCookie) { |
- TestData test = { |
"HTTP/1.1 200 OK\n" |
"Set-Cookie: x=1\n" |
"Set-Cookie: y=2\n", |
@@ -330,9 +300,12 @@ TEST(HttpResponseHeadersTest, RepeatedSetCookie) { |
200, |
net::HttpVersion(1,1), |
net::HttpVersion(1,1) |
- }; |
- TestCommon(test); |
-} |
+ }, |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ CommonHttpResponseHeadersTest, |
+ testing::ValuesIn(response_headers_tests)); |
TEST(HttpResponseHeadersTest, GetNormalizedHeader) { |
std::string headers = |
@@ -348,197 +321,208 @@ TEST(HttpResponseHeadersTest, GetNormalizedHeader) { |
EXPECT_EQ("private, no-store", value); |
} |
-TEST(HttpResponseHeadersTest, Persist) { |
- const struct { |
- net::HttpResponseHeaders::PersistOptions options; |
- const char* raw_headers; |
- const char* expected_headers; |
- } tests[] = { |
- { net::HttpResponseHeaders::PERSIST_ALL, |
- "HTTP/1.1 200 OK\n" |
- "Cache-control:private\n" |
- "cache-Control:no-store\n", |
+struct PersistData { |
+ net::HttpResponseHeaders::PersistOptions options; |
+ const char* raw_headers; |
+ const char* expected_headers; |
+}; |
- "HTTP/1.1 200 OK\n" |
- "Cache-control: private, no-store\n" |
- }, |
- { net::HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP, |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "server: blah\n", |
+class PersistenceTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<PersistData> { |
+}; |
- "HTTP/1.1 200 OK\n" |
- "server: blah\n" |
- }, |
- { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE | |
- net::HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP, |
- "HTTP/1.1 200 OK\n" |
- "fOo: 1\n" |
- "Foo: 2\n" |
- "Transfer-Encoding: chunked\n" |
- "CoNnection: keep-alive\n" |
- "cache-control: private, no-cache=\"foo\"\n", |
+TEST_P(PersistenceTest, Persist) { |
+ const PersistData test = GetParam(); |
- "HTTP/1.1 200 OK\n" |
- "cache-control: private, no-cache=\"foo\"\n" |
- }, |
- { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private,no-cache=\"foo, bar\"\n" |
- "bar", |
+ std::string headers = test.raw_headers; |
+ HeadersToRaw(&headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed1( |
+ new net::HttpResponseHeaders(headers)); |
- "HTTP/1.1 200 OK\n" |
- "Cache-Control: private,no-cache=\"foo, bar\"\n" |
- }, |
- // ignore bogus no-cache value |
- { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private,no-cache=foo\n", |
+ Pickle pickle; |
+ parsed1->Persist(&pickle, test.options); |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private,no-cache=foo\n" |
- }, |
- // ignore bogus no-cache value |
- { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private, no-cache=\n", |
+ PickleIterator iter(pickle); |
+ scoped_refptr<net::HttpResponseHeaders> parsed2( |
+ new net::HttpResponseHeaders(pickle, &iter)); |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private, no-cache=\n" |
- }, |
- // ignore empty no-cache value |
- { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private, no-cache=\"\"\n", |
+ std::string h2; |
+ parsed2->GetNormalizedHeaders(&h2); |
+ EXPECT_EQ(std::string(test.expected_headers), h2); |
+} |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private, no-cache=\"\"\n" |
- }, |
- // ignore wrong quotes no-cache value |
- { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private, no-cache=\'foo\'\n", |
+const struct PersistData persistence_tests[] = { |
+ { net::HttpResponseHeaders::PERSIST_ALL, |
+ "HTTP/1.1 200 OK\n" |
+ "Cache-control:private\n" |
+ "cache-Control:no-store\n", |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private, no-cache=\'foo\'\n" |
- }, |
- // ignore unterminated quotes no-cache value |
- { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private, no-cache=\"foo\n", |
+ "HTTP/1.1 200 OK\n" |
+ "Cache-control: private, no-store\n" |
+ }, |
+ { net::HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP, |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "server: blah\n", |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private, no-cache=\"foo\n" |
- }, |
- // accept sloppy LWS |
- { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
- "HTTP/1.1 200 OK\n" |
- "Foo: 2\n" |
- "Cache-Control: private, no-cache=\" foo\t, bar\"\n", |
+ "HTTP/1.1 200 OK\n" |
+ "server: blah\n" |
+ }, |
+ { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE | |
+ net::HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP, |
+ "HTTP/1.1 200 OK\n" |
+ "fOo: 1\n" |
+ "Foo: 2\n" |
+ "Transfer-Encoding: chunked\n" |
+ "CoNnection: keep-alive\n" |
+ "cache-control: private, no-cache=\"foo\"\n", |
- "HTTP/1.1 200 OK\n" |
- "Cache-Control: private, no-cache=\" foo\t, bar\"\n" |
- }, |
- // header name appears twice, separated by another header |
- { net::HttpResponseHeaders::PERSIST_ALL, |
- "HTTP/1.1 200 OK\n" |
- "Foo: 1\n" |
- "Bar: 2\n" |
- "Foo: 3\n", |
+ "HTTP/1.1 200 OK\n" |
+ "cache-control: private, no-cache=\"foo\"\n" |
+ }, |
+ { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private,no-cache=\"foo, bar\"\n" |
+ "bar", |
- "HTTP/1.1 200 OK\n" |
- "Foo: 1, 3\n" |
- "Bar: 2\n" |
- }, |
- // header name appears twice, separated by another header (type 2) |
- { net::HttpResponseHeaders::PERSIST_ALL, |
- "HTTP/1.1 200 OK\n" |
- "Foo: 1, 3\n" |
- "Bar: 2\n" |
- "Foo: 4\n", |
+ "HTTP/1.1 200 OK\n" |
+ "Cache-Control: private,no-cache=\"foo, bar\"\n" |
+ }, |
+ // Ignore bogus no-cache value. |
+ { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private,no-cache=foo\n", |
- "HTTP/1.1 200 OK\n" |
- "Foo: 1, 3, 4\n" |
- "Bar: 2\n" |
- }, |
- // Test filtering of cookie headers. |
- { net::HttpResponseHeaders::PERSIST_SANS_COOKIES, |
- "HTTP/1.1 200 OK\n" |
- "Set-Cookie: foo=bar; httponly\n" |
- "Set-Cookie: bar=foo\n" |
- "Bar: 1\n" |
- "Set-Cookie2: bar2=foo2\n", |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private,no-cache=foo\n" |
+ }, |
+ // Ignore bogus no-cache value. |
+ { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private, no-cache=\n", |
- "HTTP/1.1 200 OK\n" |
- "Bar: 1\n" |
- }, |
- // Test LWS at the end of a header. |
- { net::HttpResponseHeaders::PERSIST_ALL, |
- "HTTP/1.1 200 OK\n" |
- "Content-Length: 450 \n" |
- "Content-Encoding: gzip\n", |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private, no-cache=\n" |
+ }, |
+ // Ignore empty no-cache value. |
+ { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private, no-cache=\"\"\n", |
- "HTTP/1.1 200 OK\n" |
- "Content-Length: 450\n" |
- "Content-Encoding: gzip\n" |
- }, |
- // Test LWS at the end of a header. |
- { net::HttpResponseHeaders::PERSIST_RAW, |
- "HTTP/1.1 200 OK\n" |
- "Content-Length: 450 \n" |
- "Content-Encoding: gzip\n", |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private, no-cache=\"\"\n" |
+ }, |
+ // Ignore wrong quotes no-cache value. |
+ { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private, no-cache=\'foo\'\n", |
- "HTTP/1.1 200 OK\n" |
- "Content-Length: 450\n" |
- "Content-Encoding: gzip\n" |
- }, |
- // Test filtering of transport security state headers. |
- { net::HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE, |
- "HTTP/1.1 200 OK\n" |
- "Strict-Transport-Security: max-age=1576800\n" |
- "Bar: 1\n" |
- "Public-Key-Pins: max-age=100000; " |
- "pin-sha1=\"ObT42aoSpAqWdY9WfRfL7i0HsVk=\";" |
- "pin-sha1=\"7kW49EVwZG0hSNx41ZO/fUPN0ek=\"", |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private, no-cache=\'foo\'\n" |
+ }, |
+ // Ignore unterminated quotes no-cache value. |
+ { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private, no-cache=\"foo\n", |
- "HTTP/1.1 200 OK\n" |
- "Bar: 1\n" |
- }, |
- }; |
- |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string headers = tests[i].raw_headers; |
- HeadersToRaw(&headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed1( |
- new net::HttpResponseHeaders(headers)); |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private, no-cache=\"foo\n" |
+ }, |
+ // Accept sloppy LWS. |
+ { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 2\n" |
+ "Cache-Control: private, no-cache=\" foo\t, bar\"\n", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ "Cache-Control: private, no-cache=\" foo\t, bar\"\n" |
+ }, |
+ // Header name appears twice, separated by another header. |
+ { net::HttpResponseHeaders::PERSIST_ALL, |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 1\n" |
+ "Bar: 2\n" |
+ "Foo: 3\n", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 1, 3\n" |
+ "Bar: 2\n" |
+ }, |
+ // Header name appears twice, separated by another header (type 2). |
+ { net::HttpResponseHeaders::PERSIST_ALL, |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 1, 3\n" |
+ "Bar: 2\n" |
+ "Foo: 4\n", |
- Pickle pickle; |
- parsed1->Persist(&pickle, tests[i].options); |
+ "HTTP/1.1 200 OK\n" |
+ "Foo: 1, 3, 4\n" |
+ "Bar: 2\n" |
+ }, |
+ // Test filtering of cookie headers. |
+ { net::HttpResponseHeaders::PERSIST_SANS_COOKIES, |
+ "HTTP/1.1 200 OK\n" |
+ "Set-Cookie: foo=bar; httponly\n" |
+ "Set-Cookie: bar=foo\n" |
+ "Bar: 1\n" |
+ "Set-Cookie2: bar2=foo2\n", |
- PickleIterator iter(pickle); |
- scoped_refptr<net::HttpResponseHeaders> parsed2( |
- new net::HttpResponseHeaders(pickle, &iter)); |
+ "HTTP/1.1 200 OK\n" |
+ "Bar: 1\n" |
+ }, |
+ // Test LWS at the end of a header. |
+ { net::HttpResponseHeaders::PERSIST_ALL, |
+ "HTTP/1.1 200 OK\n" |
+ "Content-Length: 450 \n" |
+ "Content-Encoding: gzip\n", |
- std::string h2; |
- parsed2->GetNormalizedHeaders(&h2); |
- EXPECT_EQ(std::string(tests[i].expected_headers), h2); |
- } |
-} |
+ "HTTP/1.1 200 OK\n" |
+ "Content-Length: 450\n" |
+ "Content-Encoding: gzip\n" |
+ }, |
+ // Test LWS at the end of a header. |
+ { net::HttpResponseHeaders::PERSIST_RAW, |
+ "HTTP/1.1 200 OK\n" |
+ "Content-Length: 450 \n" |
+ "Content-Encoding: gzip\n", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ "Content-Length: 450\n" |
+ "Content-Encoding: gzip\n" |
+ }, |
+ // Test filtering of transport security state headers. |
+ { net::HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE, |
+ "HTTP/1.1 200 OK\n" |
+ "Strict-Transport-Security: max-age=1576800\n" |
+ "Bar: 1\n" |
+ "Public-Key-Pins: max-age=100000; " |
+ "pin-sha1=\"ObT42aoSpAqWdY9WfRfL7i0HsVk=\";" |
+ "pin-sha1=\"7kW49EVwZG0hSNx41ZO/fUPN0ek=\"", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ "Bar: 1\n" |
+ }, |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ PersistenceTest, |
+ testing::ValuesIn(persistence_tests)); |
TEST(HttpResponseHeadersTest, EnumerateHeader_Coalesced) { |
// Ensure that commas in quoted strings are not regarded as value separators. |
- // Ensure that whitespace following a value is trimmed properly |
+ // Ensure that whitespace following a value is trimmed properly. |
std::string headers = |
"HTTP/1.1 200 OK\n" |
"Cache-control:private , no-cache=\"set-cookie,server\" \n" |
@@ -580,7 +564,7 @@ TEST(HttpResponseHeadersTest, EnumerateHeader_Challenge) { |
TEST(HttpResponseHeadersTest, EnumerateHeader_DateValued) { |
// The comma in a date valued header should not be treated as a |
- // field-value separator |
+ // field-value separator. |
std::string headers = |
"HTTP/1.1 200 OK\n" |
"Date: Tue, 07 Aug 2007 23:10:55 GMT\n" |
@@ -626,1011 +610,1129 @@ TEST(HttpResponseHeadersTest, DefaultDateToGMT) { |
EXPECT_EQ(expected_value, value); |
} |
-TEST(HttpResponseHeadersTest, GetMimeType) { |
- const ContentTypeTestData tests[] = { |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html\n", |
- "text/html", true, |
- "", false, |
- "text/html" }, |
- // Multiple content-type headers should give us the last one. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html\n" |
- "Content-type: text/html\n", |
- "text/html", true, |
- "", false, |
- "text/html, text/html" }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/plain\n" |
- "Content-type: text/html\n" |
- "Content-type: text/plain\n" |
- "Content-type: text/html\n", |
- "text/html", true, |
- "", false, |
- "text/plain, text/html, text/plain, text/html" }, |
- // Test charset parsing. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html\n" |
- "Content-type: text/html; charset=ISO-8859-1\n", |
- "text/html", true, |
- "iso-8859-1", true, |
- "text/html, text/html; charset=ISO-8859-1" }, |
- // Test charset in double quotes. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html\n" |
- "Content-type: text/html; charset=\"ISO-8859-1\"\n", |
- "text/html", true, |
- "iso-8859-1", true, |
- "text/html, text/html; charset=\"ISO-8859-1\"" }, |
- // If there are multiple matching content-type headers, we carry |
- // over the charset value. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html;charset=utf-8\n" |
- "Content-type: text/html\n", |
- "text/html", true, |
- "utf-8", true, |
- "text/html;charset=utf-8, text/html" }, |
- // Test single quotes. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html;charset='utf-8'\n" |
- "Content-type: text/html\n", |
- "text/html", true, |
- "utf-8", true, |
- "text/html;charset='utf-8', text/html" }, |
- // Last charset wins if matching content-type. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html;charset=utf-8\n" |
- "Content-type: text/html;charset=iso-8859-1\n", |
- "text/html", true, |
- "iso-8859-1", true, |
- "text/html;charset=utf-8, text/html;charset=iso-8859-1" }, |
- // Charset is ignored if the content types change. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/plain;charset=utf-8\n" |
- "Content-type: text/html\n", |
- "text/html", true, |
- "", false, |
- "text/plain;charset=utf-8, text/html" }, |
- // Empty content-type |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: \n", |
- "", false, |
- "", false, |
- "" }, |
- // Emtpy charset |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html;charset=\n", |
- "text/html", true, |
- "", false, |
- "text/html;charset=" }, |
- // Multiple charsets, last one wins. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html;charset=utf-8; charset=iso-8859-1\n", |
- "text/html", true, |
- "iso-8859-1", true, |
- "text/html;charset=utf-8; charset=iso-8859-1" }, |
- // Multiple params. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html; foo=utf-8; charset=iso-8859-1\n", |
- "text/html", true, |
- "iso-8859-1", true, |
- "text/html; foo=utf-8; charset=iso-8859-1" }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html ; charset=utf-8 ; bar=iso-8859-1\n", |
- "text/html", true, |
- "utf-8", true, |
- "text/html ; charset=utf-8 ; bar=iso-8859-1" }, |
- // Comma embeded in quotes. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html ; charset='utf-8,text/plain' ;\n", |
- "text/html", true, |
- "utf-8,text/plain", true, |
- "text/html ; charset='utf-8,text/plain' ;" }, |
- // Charset with leading spaces. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html ; charset= 'utf-8' ;\n", |
- "text/html", true, |
- "utf-8", true, |
- "text/html ; charset= 'utf-8' ;" }, |
- // Media type comments in mime-type. |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html (html)\n", |
- "text/html", true, |
- "", false, |
- "text/html (html)" }, |
- // Incomplete charset= param |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: text/html; char=\n", |
- "text/html", true, |
- "", false, |
- "text/html; char=" }, |
- // Invalid media type: no slash |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: texthtml\n", |
- "", false, |
- "", false, |
- "texthtml" }, |
- // Invalid media type: */* |
- { "HTTP/1.1 200 OK\n" |
- "Content-type: */*\n", |
- "", false, |
- "", false, |
- "*/*" }, |
- }; |
- |
- for (size_t i = 0; i < arraysize(tests); ++i) { |
- std::string headers(tests[i].raw_headers); |
- HeadersToRaw(&headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(headers)); |
+struct ContentTypeTestData { |
+ const std::string raw_headers; |
+ const std::string mime_type; |
+ const bool has_mimetype; |
+ const std::string charset; |
+ const bool has_charset; |
+ const std::string all_content_type; |
+}; |
- std::string value; |
- EXPECT_EQ(tests[i].has_mimetype, parsed->GetMimeType(&value)); |
- EXPECT_EQ(tests[i].mime_type, value); |
- value.clear(); |
- EXPECT_EQ(tests[i].has_charset, parsed->GetCharset(&value)); |
- EXPECT_EQ(tests[i].charset, value); |
- EXPECT_TRUE(parsed->GetNormalizedHeader("content-type", &value)); |
- EXPECT_EQ(tests[i].all_content_type, value); |
- } |
+class ContentTypeTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<ContentTypeTestData> { |
+}; |
+ |
+TEST_P(ContentTypeTest, GetMimeType) { |
+ const ContentTypeTestData test = GetParam(); |
+ |
+ std::string headers(test.raw_headers); |
+ HeadersToRaw(&headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(headers)); |
+ |
+ std::string value; |
+ EXPECT_EQ(test.has_mimetype, parsed->GetMimeType(&value)); |
+ EXPECT_EQ(test.mime_type, value); |
+ value.clear(); |
+ EXPECT_EQ(test.has_charset, parsed->GetCharset(&value)); |
+ EXPECT_EQ(test.charset, value); |
+ EXPECT_TRUE(parsed->GetNormalizedHeader("content-type", &value)); |
+ EXPECT_EQ(test.all_content_type, value); |
} |
-TEST(HttpResponseHeadersTest, RequiresValidation) { |
- const struct { |
- const char* headers; |
- bool requires_validation; |
- } tests[] = { |
- // no expiry info: expires immediately |
- { "HTTP/1.1 200 OK\n" |
- "\n", |
- true |
- }, |
- // valid for a little while |
- { "HTTP/1.1 200 OK\n" |
- "cache-control: max-age=10000\n" |
- "\n", |
- false |
- }, |
- // expires in the future |
- { "HTTP/1.1 200 OK\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "expires: Wed, 28 Nov 2007 01:00:00 GMT\n" |
- "\n", |
- false |
- }, |
- // expired already |
- { "HTTP/1.1 200 OK\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "expires: Wed, 28 Nov 2007 00:00:00 GMT\n" |
- "\n", |
- true |
- }, |
- // max-age trumps expires |
- { "HTTP/1.1 200 OK\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "expires: Wed, 28 Nov 2007 00:00:00 GMT\n" |
- "cache-control: max-age=10000\n" |
- "\n", |
- false |
- }, |
- // last-modified heuristic: modified a while ago |
- { "HTTP/1.1 200 OK\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "last-modified: Wed, 27 Nov 2007 08:00:00 GMT\n" |
- "\n", |
- false |
- }, |
- { "HTTP/1.1 203 Non-Authoritative Information\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "last-modified: Wed, 27 Nov 2007 08:00:00 GMT\n" |
- "\n", |
- false |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "last-modified: Wed, 27 Nov 2007 08:00:00 GMT\n" |
- "\n", |
- false |
- }, |
- // last-modified heuristic: modified recently |
- { "HTTP/1.1 200 OK\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "last-modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
- "\n", |
- true |
- }, |
- { "HTTP/1.1 203 Non-Authoritative Information\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "last-modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
- "\n", |
- true |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "last-modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
- "\n", |
- true |
- }, |
- // cached permanent redirect |
- { "HTTP/1.1 301 Moved Permanently\n" |
- "\n", |
- false |
- }, |
- // another cached permanent redirect |
- { "HTTP/1.1 308 Permanent Redirect\n" |
- "\n", |
- false |
- }, |
- // cached redirect: not reusable even though by default it would be |
- { "HTTP/1.1 300 Multiple Choices\n" |
- "Cache-Control: no-cache\n" |
- "\n", |
- true |
- }, |
- // cached forever by default |
- { "HTTP/1.1 410 Gone\n" |
- "\n", |
- false |
- }, |
- // cached temporary redirect: not reusable |
- { "HTTP/1.1 302 Found\n" |
- "\n", |
- true |
- }, |
- // cached temporary redirect: reusable |
- { "HTTP/1.1 302 Found\n" |
- "cache-control: max-age=10000\n" |
- "\n", |
- false |
- }, |
- // cache-control: max-age=N overrides expires: date in the past |
- { "HTTP/1.1 200 OK\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "expires: Wed, 28 Nov 2007 00:20:11 GMT\n" |
- "cache-control: max-age=10000\n" |
- "\n", |
- false |
- }, |
- // cache-control: no-store overrides expires: in the future |
- { "HTTP/1.1 200 OK\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "expires: Wed, 29 Nov 2007 00:40:11 GMT\n" |
- "cache-control: no-store,private,no-cache=\"foo\"\n" |
- "\n", |
- true |
- }, |
- // pragma: no-cache overrides last-modified heuristic |
- { "HTTP/1.1 200 OK\n" |
- "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
- "last-modified: Wed, 27 Nov 2007 08:00:00 GMT\n" |
- "pragma: no-cache\n" |
- "\n", |
- true |
- }, |
- // TODO(darin): add many many more tests here |
- }; |
+const ContentTypeTestData mimetype_tests[] = { |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html\n", |
+ "text/html", true, |
+ "", false, |
+ "text/html" }, |
+ // Multiple content-type headers should give us the last one. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html\n" |
+ "Content-type: text/html\n", |
+ "text/html", true, |
+ "", false, |
+ "text/html, text/html" }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/plain\n" |
+ "Content-type: text/html\n" |
+ "Content-type: text/plain\n" |
+ "Content-type: text/html\n", |
+ "text/html", true, |
+ "", false, |
+ "text/plain, text/html, text/plain, text/html" }, |
+ // Test charset parsing. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html\n" |
+ "Content-type: text/html; charset=ISO-8859-1\n", |
+ "text/html", true, |
+ "iso-8859-1", true, |
+ "text/html, text/html; charset=ISO-8859-1" }, |
+ // Test charset in double quotes. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html\n" |
+ "Content-type: text/html; charset=\"ISO-8859-1\"\n", |
+ "text/html", true, |
+ "iso-8859-1", true, |
+ "text/html, text/html; charset=\"ISO-8859-1\"" }, |
+ // If there are multiple matching content-type headers, we carry |
+ // over the charset value. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html;charset=utf-8\n" |
+ "Content-type: text/html\n", |
+ "text/html", true, |
+ "utf-8", true, |
+ "text/html;charset=utf-8, text/html" }, |
+ // Test single quotes. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html;charset='utf-8'\n" |
+ "Content-type: text/html\n", |
+ "text/html", true, |
+ "utf-8", true, |
+ "text/html;charset='utf-8', text/html" }, |
+ // Last charset wins if matching content-type. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html;charset=utf-8\n" |
+ "Content-type: text/html;charset=iso-8859-1\n", |
+ "text/html", true, |
+ "iso-8859-1", true, |
+ "text/html;charset=utf-8, text/html;charset=iso-8859-1" }, |
+ // Charset is ignored if the content types change. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/plain;charset=utf-8\n" |
+ "Content-type: text/html\n", |
+ "text/html", true, |
+ "", false, |
+ "text/plain;charset=utf-8, text/html" }, |
+ // Empty content-type. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: \n", |
+ "", false, |
+ "", false, |
+ "" }, |
+ // Emtpy charset. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html;charset=\n", |
+ "text/html", true, |
+ "", false, |
+ "text/html;charset=" }, |
+ // Multiple charsets, last one wins. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html;charset=utf-8; charset=iso-8859-1\n", |
+ "text/html", true, |
+ "iso-8859-1", true, |
+ "text/html;charset=utf-8; charset=iso-8859-1" }, |
+ // Multiple params. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html; foo=utf-8; charset=iso-8859-1\n", |
+ "text/html", true, |
+ "iso-8859-1", true, |
+ "text/html; foo=utf-8; charset=iso-8859-1" }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html ; charset=utf-8 ; bar=iso-8859-1\n", |
+ "text/html", true, |
+ "utf-8", true, |
+ "text/html ; charset=utf-8 ; bar=iso-8859-1" }, |
+ // Comma embeded in quotes. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html ; charset='utf-8,text/plain' ;\n", |
+ "text/html", true, |
+ "utf-8,text/plain", true, |
+ "text/html ; charset='utf-8,text/plain' ;" }, |
+ // Charset with leading spaces. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html ; charset= 'utf-8' ;\n", |
+ "text/html", true, |
+ "utf-8", true, |
+ "text/html ; charset= 'utf-8' ;" }, |
+ // Media type comments in mime-type. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html (html)\n", |
+ "text/html", true, |
+ "", false, |
+ "text/html (html)" }, |
+ // Incomplete charset= param. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: text/html; char=\n", |
+ "text/html", true, |
+ "", false, |
+ "text/html; char=" }, |
+ // Invalid media type: no slash. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: texthtml\n", |
+ "", false, |
+ "", false, |
+ "texthtml" }, |
+ // Invalid media type: "*/*". |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-type: */*\n", |
+ "", false, |
+ "", false, |
+ "*/*" }, |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ ContentTypeTest, |
+ testing::ValuesIn(mimetype_tests)); |
+ |
+struct RequiresValidationTestData { |
+ const char* headers; |
+ bool requires_validation; |
+}; |
+ |
+class RequiresValidationTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<RequiresValidationTestData> { |
+}; |
+ |
+TEST_P(RequiresValidationTest, RequiresValidation) { |
+ const RequiresValidationTestData test = GetParam(); |
+ |
base::Time request_time, response_time, current_time; |
base::Time::FromString("Wed, 28 Nov 2007 00:40:09 GMT", &request_time); |
base::Time::FromString("Wed, 28 Nov 2007 00:40:12 GMT", &response_time); |
base::Time::FromString("Wed, 28 Nov 2007 00:45:20 GMT", ¤t_time); |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string headers(tests[i].headers); |
- HeadersToRaw(&headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(headers)); |
+ std::string headers(test.headers); |
+ HeadersToRaw(&headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(headers)); |
- bool requires_validation = |
- parsed->RequiresValidation(request_time, response_time, current_time); |
- EXPECT_EQ(tests[i].requires_validation, requires_validation); |
- } |
+ bool requires_validation = |
+ parsed->RequiresValidation(request_time, response_time, current_time); |
+ EXPECT_EQ(test.requires_validation, requires_validation); |
} |
-TEST(HttpResponseHeadersTest, Update) { |
- const struct { |
- const char* orig_headers; |
- const char* new_headers; |
- const char* expected_headers; |
- } tests[] = { |
- { "HTTP/1.1 200 OK\n", |
+const struct RequiresValidationTestData requires_validation_tests[] = { |
+ // No expiry info: expires immediately. |
+ { "HTTP/1.1 200 OK\n" |
+ "\n", |
+ true |
+ }, |
+ // No expiry info: expires immediately. |
+ { "HTTP/1.1 200 OK\n" |
+ "\n", |
+ true |
+ }, |
+ // Valid for a little while. |
+ { "HTTP/1.1 200 OK\n" |
+ "cache-control: max-age=10000\n" |
+ "\n", |
+ false |
+ }, |
+ // Expires in the future. |
+ { "HTTP/1.1 200 OK\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "expires: Wed, 28 Nov 2007 01:00:00 GMT\n" |
+ "\n", |
+ false |
+ }, |
+ // Already expired. |
+ { "HTTP/1.1 200 OK\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "expires: Wed, 28 Nov 2007 00:00:00 GMT\n" |
+ "\n", |
+ true |
+ }, |
+ // Max-age trumps expires. |
+ { "HTTP/1.1 200 OK\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "expires: Wed, 28 Nov 2007 00:00:00 GMT\n" |
+ "cache-control: max-age=10000\n" |
+ "\n", |
+ false |
+ }, |
+ // Last-modified heuristic: modified a while ago. |
+ { "HTTP/1.1 200 OK\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "last-modified: Wed, 27 Nov 2007 08:00:00 GMT\n" |
+ "\n", |
+ false |
+ }, |
+ { "HTTP/1.1 203 Non-Authoritative Information\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "last-modified: Wed, 27 Nov 2007 08:00:00 GMT\n" |
+ "\n", |
+ false |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "last-modified: Wed, 27 Nov 2007 08:00:00 GMT\n" |
+ "\n", |
+ false |
+ }, |
+ // Last-modified heuristic: modified recently. |
+ { "HTTP/1.1 200 OK\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "last-modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
+ "\n", |
+ true |
+ }, |
+ { "HTTP/1.1 203 Non-Authoritative Information\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "last-modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
+ "\n", |
+ true |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "last-modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
+ "\n", |
+ true |
+ }, |
+ // Cached permanent redirect. |
+ { "HTTP/1.1 301 Moved Permanently\n" |
+ "\n", |
+ false |
+ }, |
+ // Another cached permanent redirect. |
+ { "HTTP/1.1 308 Permanent Redirect\n" |
+ "\n", |
+ false |
+ }, |
+ // Cached redirect: not reusable even though by default it would be. |
+ { "HTTP/1.1 300 Multiple Choices\n" |
+ "Cache-Control: no-cache\n" |
+ "\n", |
+ true |
+ }, |
+ // Cached forever by default. |
+ { "HTTP/1.1 410 Gone\n" |
+ "\n", |
+ false |
+ }, |
+ // Cached temporary redirect: not reusable. |
+ { "HTTP/1.1 302 Found\n" |
+ "\n", |
+ true |
+ }, |
+ // Cached temporary redirect: reusable. |
+ { "HTTP/1.1 302 Found\n" |
+ "cache-control: max-age=10000\n" |
+ "\n", |
+ false |
+ }, |
+ // Cache-control: max-age=N overrides expires: date in the past. |
+ { "HTTP/1.1 200 OK\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "expires: Wed, 28 Nov 2007 00:20:11 GMT\n" |
+ "cache-control: max-age=10000\n" |
+ "\n", |
+ false |
+ }, |
+ // Cache-control: no-store overrides expires: in the future. |
+ { "HTTP/1.1 200 OK\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "expires: Wed, 29 Nov 2007 00:40:11 GMT\n" |
+ "cache-control: no-store,private,no-cache=\"foo\"\n" |
+ "\n", |
+ true |
+ }, |
+ // Pragma: no-cache overrides last-modified heuristic. |
+ { "HTTP/1.1 200 OK\n" |
+ "date: Wed, 28 Nov 2007 00:40:11 GMT\n" |
+ "last-modified: Wed, 27 Nov 2007 08:00:00 GMT\n" |
+ "pragma: no-cache\n" |
+ "\n", |
+ true |
+ }, |
+ |
+ // TODO(darin): Add many many more tests here. |
+}; |
- "HTTP/1/1 304 Not Modified\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n", |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ RequiresValidationTest, |
+ testing::ValuesIn(requires_validation_tests)); |
- "HTTP/1.1 200 OK\n" |
- "Cache-control: max-age=10000\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Foo: 1\n" |
- "Cache-control: private\n", |
+struct UpdateTestData { |
+ const char* orig_headers; |
+ const char* new_headers; |
+ const char* expected_headers; |
+}; |
- "HTTP/1/1 304 Not Modified\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n", |
+class UpdateTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<UpdateTestData> { |
+}; |
- "HTTP/1.1 200 OK\n" |
- "Cache-control: max-age=10000\n" |
- "Foo: 1\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Foo: 1\n" |
- "Cache-control: private\n", |
+TEST_P(UpdateTest, Update) { |
+ const UpdateTestData test = GetParam(); |
- "HTTP/1/1 304 Not Modified\n" |
- "connection: keep-alive\n" |
- "Cache-CONTROL: max-age=10000\n", |
+ std::string orig_headers(test.orig_headers); |
+ HeadersToRaw(&orig_headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(orig_headers)); |
- "HTTP/1.1 200 OK\n" |
- "Cache-CONTROL: max-age=10000\n" |
- "Foo: 1\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 450\n", |
+ std::string new_headers(test.new_headers); |
+ HeadersToRaw(&new_headers); |
+ scoped_refptr<net::HttpResponseHeaders> new_parsed( |
+ new net::HttpResponseHeaders(new_headers)); |
- "HTTP/1/1 304 Not Modified\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10001 \n", |
+ parsed->Update(*new_parsed.get()); |
- "HTTP/1.1 200 OK\n" |
- "Cache-control: max-age=10001\n" |
- "Content-Length: 450\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "X-Frame-Options: DENY\n", |
+ std::string resulting_headers; |
+ parsed->GetNormalizedHeaders(&resulting_headers); |
+ EXPECT_EQ(std::string(test.expected_headers), resulting_headers); |
+} |
- "HTTP/1/1 304 Not Modified\n" |
- "X-Frame-Options: ALLOW\n", |
+const UpdateTestData update_tests[] = { |
+ { "HTTP/1.1 200 OK\n", |
- "HTTP/1.1 200 OK\n" |
- "X-Frame-Options: DENY\n", |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "X-WebKit-CSP: default-src 'none'\n", |
+ "HTTP/1/1 304 Not Modified\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n", |
- "HTTP/1/1 304 Not Modified\n" |
- "X-WebKit-CSP: default-src *\n", |
+ "HTTP/1.1 200 OK\n" |
+ "Cache-control: max-age=10000\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Foo: 1\n" |
+ "Cache-control: private\n", |
- "HTTP/1.1 200 OK\n" |
- "X-WebKit-CSP: default-src 'none'\n", |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "X-XSS-Protection: 1\n", |
+ "HTTP/1/1 304 Not Modified\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n", |
- "HTTP/1/1 304 Not Modified\n" |
- "X-XSS-Protection: 0\n", |
+ "HTTP/1.1 200 OK\n" |
+ "Cache-control: max-age=10000\n" |
+ "Foo: 1\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Foo: 1\n" |
+ "Cache-control: private\n", |
- "HTTP/1.1 200 OK\n" |
- "X-XSS-Protection: 1\n", |
- }, |
- { "HTTP/1.1 200 OK\n", |
+ "HTTP/1/1 304 Not Modified\n" |
+ "connection: keep-alive\n" |
+ "Cache-CONTROL: max-age=10000\n", |
- "HTTP/1/1 304 Not Modified\n" |
- "X-Content-Type-Options: nosniff\n", |
+ "HTTP/1.1 200 OK\n" |
+ "Cache-CONTROL: max-age=10000\n" |
+ "Foo: 1\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 450\n", |
- "HTTP/1.1 200 OK\n" |
- }, |
- }; |
+ "HTTP/1/1 304 Not Modified\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10001 \n", |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string orig_headers(tests[i].orig_headers); |
- HeadersToRaw(&orig_headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(orig_headers)); |
+ "HTTP/1.1 200 OK\n" |
+ "Cache-control: max-age=10001\n" |
+ "Content-Length: 450\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "X-Frame-Options: DENY\n", |
- std::string new_headers(tests[i].new_headers); |
- HeadersToRaw(&new_headers); |
- scoped_refptr<net::HttpResponseHeaders> new_parsed( |
- new net::HttpResponseHeaders(new_headers)); |
+ "HTTP/1/1 304 Not Modified\n" |
+ "X-Frame-Options: ALLOW\n", |
- parsed->Update(*new_parsed.get()); |
+ "HTTP/1.1 200 OK\n" |
+ "X-Frame-Options: DENY\n", |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "X-WebKit-CSP: default-src 'none'\n", |
- std::string resulting_headers; |
- parsed->GetNormalizedHeaders(&resulting_headers); |
- EXPECT_EQ(std::string(tests[i].expected_headers), resulting_headers); |
- } |
-} |
+ "HTTP/1/1 304 Not Modified\n" |
+ "X-WebKit-CSP: default-src *\n", |
-TEST(HttpResponseHeadersTest, EnumerateHeaderLines) { |
- const struct { |
- const char* headers; |
- const char* expected_lines; |
- } tests[] = { |
- { "HTTP/1.1 200 OK\n", |
- |
- "" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Foo: 1\n", |
- |
- "Foo: 1\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Foo: 1\n" |
- "Bar: 2\n" |
- "Foo: 3\n", |
- |
- "Foo: 1\nBar: 2\nFoo: 3\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Foo: 1, 2, 3\n", |
- |
- "Foo: 1, 2, 3\n" |
- }, |
- }; |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string headers(tests[i].headers); |
- HeadersToRaw(&headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(headers)); |
+ "HTTP/1.1 200 OK\n" |
+ "X-WebKit-CSP: default-src 'none'\n", |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "X-XSS-Protection: 1\n", |
+ |
+ "HTTP/1/1 304 Not Modified\n" |
+ "X-XSS-Protection: 0\n", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ "X-XSS-Protection: 1\n", |
+ }, |
+ { "HTTP/1.1 200 OK\n", |
+ |
+ "HTTP/1/1 304 Not Modified\n" |
+ "X-Content-Type-Options: nosniff\n", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ }, |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ UpdateTest, |
+ testing::ValuesIn(update_tests)); |
- std::string name, value, lines; |
+struct EnumerateHeaderTestData { |
+ const char* headers; |
+ const char* expected_lines; |
+}; |
+ |
+class EnumerateHeaderLinesTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<EnumerateHeaderTestData> { |
+}; |
+ |
+TEST_P(EnumerateHeaderLinesTest, EnumerateHeaderLines) { |
+ const EnumerateHeaderTestData test = GetParam(); |
+ |
+ std::string headers(test.headers); |
+ HeadersToRaw(&headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(headers)); |
- void* iter = NULL; |
- while (parsed->EnumerateHeaderLines(&iter, &name, &value)) { |
- lines.append(name); |
- lines.append(": "); |
- lines.append(value); |
- lines.append("\n"); |
- } |
+ std::string name, value, lines; |
- EXPECT_EQ(std::string(tests[i].expected_lines), lines); |
+ void* iter = NULL; |
+ while (parsed->EnumerateHeaderLines(&iter, &name, &value)) { |
+ lines.append(name); |
+ lines.append(": "); |
+ lines.append(value); |
+ lines.append("\n"); |
} |
+ |
+ EXPECT_EQ(std::string(test.expected_lines), lines); |
} |
-TEST(HttpResponseHeadersTest, IsRedirect) { |
- const struct { |
- const char* headers; |
- const char* location; |
- bool is_redirect; |
- } tests[] = { |
- { "HTTP/1.1 200 OK\n", |
- "", |
- false |
- }, |
- { "HTTP/1.1 301 Moved\n" |
- "Location: http://foopy/\n", |
- "http://foopy/", |
- true |
- }, |
- { "HTTP/1.1 301 Moved\n" |
- "Location: \t \n", |
- "", |
- false |
- }, |
- // we use the first location header as the target of the redirect |
- { "HTTP/1.1 301 Moved\n" |
- "Location: http://foo/\n" |
- "Location: http://bar/\n", |
- "http://foo/", |
- true |
- }, |
- // we use the first _valid_ location header as the target of the redirect |
- { "HTTP/1.1 301 Moved\n" |
- "Location: \n" |
- "Location: http://bar/\n", |
- "http://bar/", |
- true |
- }, |
- // bug 1050541 (location header w/ an unescaped comma) |
- { "HTTP/1.1 301 Moved\n" |
- "Location: http://foo/bar,baz.html\n", |
- "http://foo/bar,baz.html", |
- true |
- }, |
- // bug 1224617 (location header w/ non-ASCII bytes) |
- { "HTTP/1.1 301 Moved\n" |
- "Location: http://foo/bar?key=\xE4\xF6\xFC\n", |
- "http://foo/bar?key=%E4%F6%FC", |
- true |
- }, |
- // Shift_JIS, Big5, and GBK contain multibyte characters with the trailing |
- // byte falling in the ASCII range. |
- { "HTTP/1.1 301 Moved\n" |
- "Location: http://foo/bar?key=\x81\x5E\xD8\xBF\n", |
- "http://foo/bar?key=%81^%D8%BF", |
- true |
- }, |
- { "HTTP/1.1 301 Moved\n" |
- "Location: http://foo/bar?key=\x82\x40\xBD\xC4\n", |
- "http://foo/bar?key=%82@%BD%C4", |
- true |
- }, |
- { "HTTP/1.1 301 Moved\n" |
- "Location: http://foo/bar?key=\x83\x5C\x82\x5D\xCB\xD7\n", |
- "http://foo/bar?key=%83\\%82]%CB%D7", |
- true |
- }, |
- }; |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string headers(tests[i].headers); |
- HeadersToRaw(&headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(headers)); |
+const EnumerateHeaderTestData enumerate_header_tests[] = { |
+ { "HTTP/1.1 200 OK\n", |
- std::string location; |
- EXPECT_EQ(parsed->IsRedirect(&location), tests[i].is_redirect); |
- EXPECT_EQ(location, tests[i].location); |
- } |
+ "" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Foo: 1\n", |
+ |
+ "Foo: 1\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Foo: 1\n" |
+ "Bar: 2\n" |
+ "Foo: 3\n", |
+ |
+ "Foo: 1\nBar: 2\nFoo: 3\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Foo: 1, 2, 3\n", |
+ |
+ "Foo: 1, 2, 3\n" |
+ }, |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ EnumerateHeaderLinesTest, |
+ testing::ValuesIn(enumerate_header_tests)); |
+ |
+struct IsRedirectTestData { |
+ const char* headers; |
+ const char* location; |
+ bool is_redirect; |
+}; |
+ |
+class IsRedirectTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<IsRedirectTestData> { |
+}; |
+ |
+TEST_P(IsRedirectTest, IsRedirect) { |
+ const IsRedirectTestData test = GetParam(); |
+ |
+ std::string headers(test.headers); |
+ HeadersToRaw(&headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(headers)); |
+ |
+ std::string location; |
+ EXPECT_EQ(parsed->IsRedirect(&location), test.is_redirect); |
+ EXPECT_EQ(location, test.location); |
} |
-TEST(HttpResponseHeadersTest, GetContentLength) { |
- const struct { |
- const char* headers; |
- int64 expected_len; |
- } tests[] = { |
- { "HTTP/1.1 200 OK\n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 10\n", |
- 10 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: \n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: abc\n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: -10\n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: +10\n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 23xb5\n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 0xA\n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 010\n", |
- 10 |
- }, |
- // Content-Length too big, will overflow an int64 |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 40000000000000000000\n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 10\n", |
- 10 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 10 \n", |
- 10 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: \t10\n", |
- 10 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: \v10\n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: \f10\n", |
- -1 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "cOnTeNt-LENgth: 33\n", |
- 33 |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 34\r\n", |
- -1 |
- }, |
- }; |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string headers(tests[i].headers); |
- HeadersToRaw(&headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(headers)); |
+const IsRedirectTestData is_redirect_tests[] = { |
+ { "HTTP/1.1 200 OK\n", |
+ "", |
+ false |
+ }, |
+ { "HTTP/1.1 301 Moved\n" |
+ "Location: http://foopy/\n", |
+ "http://foopy/", |
+ true |
+ }, |
+ { "HTTP/1.1 301 Moved\n" |
+ "Location: \t \n", |
+ "", |
+ false |
+ }, |
+ // We use the first location header as the target of the redirect. |
+ { "HTTP/1.1 301 Moved\n" |
+ "Location: http://foo/\n" |
+ "Location: http://bar/\n", |
+ "http://foo/", |
+ true |
+ }, |
+ // We use the first _valid_ location header as the target of the redirect. |
+ { "HTTP/1.1 301 Moved\n" |
+ "Location: \n" |
+ "Location: http://bar/\n", |
+ "http://bar/", |
+ true |
+ }, |
+ // Bug 1050541 (location header with an unescaped comma). |
+ { "HTTP/1.1 301 Moved\n" |
+ "Location: http://foo/bar,baz.html\n", |
+ "http://foo/bar,baz.html", |
+ true |
+ }, |
+ // Bug 1224617 (location header with non-ASCII bytes). |
+ { "HTTP/1.1 301 Moved\n" |
+ "Location: http://foo/bar?key=\xE4\xF6\xFC\n", |
+ "http://foo/bar?key=%E4%F6%FC", |
+ true |
+ }, |
+ // Shift_JIS, Big5, and GBK contain multibyte characters with the trailing |
+ // byte falling in the ASCII range. |
+ { "HTTP/1.1 301 Moved\n" |
+ "Location: http://foo/bar?key=\x81\x5E\xD8\xBF\n", |
+ "http://foo/bar?key=%81^%D8%BF", |
+ true |
+ }, |
+ { "HTTP/1.1 301 Moved\n" |
+ "Location: http://foo/bar?key=\x82\x40\xBD\xC4\n", |
+ "http://foo/bar?key=%82@%BD%C4", |
+ true |
+ }, |
+ { "HTTP/1.1 301 Moved\n" |
+ "Location: http://foo/bar?key=\x83\x5C\x82\x5D\xCB\xD7\n", |
+ "http://foo/bar?key=%83\\%82]%CB%D7", |
+ true |
+ }, |
+}; |
- EXPECT_EQ(tests[i].expected_len, parsed->GetContentLength()); |
- } |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ IsRedirectTest, |
+ testing::ValuesIn(is_redirect_tests)); |
+ |
+struct ContentLengthTestData { |
+ const char* headers; |
+ int64 expected_len; |
+}; |
+ |
+class GetContentLengthTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<ContentLengthTestData> { |
+}; |
+ |
+TEST_P(GetContentLengthTest, GetContentLength) { |
+ const ContentLengthTestData test = GetParam(); |
+ |
+ std::string headers(test.headers); |
+ HeadersToRaw(&headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(headers)); |
+ |
+ EXPECT_EQ(test.expected_len, parsed->GetContentLength()); |
} |
-TEST(HttpResponseHeaders, GetContentRange) { |
- const struct { |
- const char* headers; |
- bool expected_return_value; |
- int64 expected_first_byte_position; |
- int64 expected_last_byte_position; |
- int64 expected_instance_size; |
- } tests[] = { |
- { "HTTP/1.1 206 Partial Content", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range:", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: megabytes 0-10/50", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: 0-10/50", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: Bytes 0-50/51", |
- true, |
- 0, |
- 50, |
- 51 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-50/51", |
- true, |
- 0, |
- 50, |
- 51 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes\t0-50/51", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-50/51", |
- true, |
- 0, |
- 50, |
- 51 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0 - 50 \t / \t51", |
- true, |
- 0, |
- 50, |
- 51 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0\t-\t50\t/\t51\t", |
- true, |
- 0, |
- 50, |
- 51 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: \tbytes\t\t\t 0\t-\t50\t/\t51\t", |
- true, |
- 0, |
- 50, |
- 51 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: \t bytes \t 0 - 50 / 5 1", |
- false, |
- 0, |
- 50, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: \t bytes \t 0 - 5 0 / 51", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 50-0/51", |
- false, |
- 50, |
- 0, |
- -1 |
- }, |
- { "HTTP/1.1 416 Requested range not satisfiable\n" |
- "Content-Range: bytes * /*", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 416 Requested range not satisfiable\n" |
- "Content-Range: bytes * / * ", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-50/*", |
- false, |
- 0, |
- 50, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-50 / * ", |
- false, |
- 0, |
- 50, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-10000000000/10000000001", |
- true, |
- 0, |
- 10000000000ll, |
- 10000000001ll |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-10000000000/10000000000", |
- false, |
- 0, |
- 10000000000ll, |
- 10000000000ll |
- }, |
- // 64 bits wraparound. |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0 - 9223372036854775807 / 100", |
- false, |
- 0, |
- kint64max, |
- 100 |
- }, |
- // 64 bits wraparound. |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0 - 100 / -9223372036854775808", |
- false, |
- 0, |
- 100, |
- kint64min |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes */50", |
- false, |
- -1, |
- -1, |
- 50 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-50/10", |
- false, |
- 0, |
- 50, |
- 10 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 40-50/45", |
- false, |
- 40, |
- 50, |
- 45 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-50/-10", |
- false, |
- 0, |
- 50, |
- -10 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-0/1", |
- true, |
- 0, |
- 0, |
- 1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-40000000000000000000/40000000000000000001", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 1-/100", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes -/100", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes -1/100", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 0-1233/*", |
- false, |
- 0, |
- 1233, |
- -1 |
- }, |
- { "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes -123 - -1/100", |
- false, |
- -1, |
- -1, |
- -1 |
- }, |
- }; |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string headers(tests[i].headers); |
- HeadersToRaw(&headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(headers)); |
+const ContentLengthTestData content_length_tests[] = { |
+ { "HTTP/1.1 200 OK\n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 10\n", |
+ 10 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: \n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: abc\n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: -10\n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: +10\n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 23xb5\n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 0xA\n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 010\n", |
+ 10 |
+ }, |
+ // Content-Length too big, will overflow an int64. |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 40000000000000000000\n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 10\n", |
+ 10 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 10 \n", |
+ 10 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: \t10\n", |
+ 10 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: \v10\n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: \f10\n", |
+ -1 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "cOnTeNt-LENgth: 33\n", |
+ 33 |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 34\r\n", |
+ -1 |
+ }, |
+}; |
- int64 first_byte_position; |
- int64 last_byte_position; |
- int64 instance_size; |
- bool return_value = parsed->GetContentRange(&first_byte_position, |
- &last_byte_position, |
- &instance_size); |
- EXPECT_EQ(tests[i].expected_return_value, return_value); |
- EXPECT_EQ(tests[i].expected_first_byte_position, first_byte_position); |
- EXPECT_EQ(tests[i].expected_last_byte_position, last_byte_position); |
- EXPECT_EQ(tests[i].expected_instance_size, instance_size); |
- } |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ GetContentLengthTest, |
+ testing::ValuesIn(content_length_tests)); |
+ |
+struct ContentRangeTestData { |
+ const char* headers; |
+ bool expected_return_value; |
+ int64 expected_first_byte_position; |
+ int64 expected_last_byte_position; |
+ int64 expected_instance_size; |
+}; |
+ |
+class ContentRangeTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<ContentRangeTestData> { |
+}; |
+ |
+TEST_P(ContentRangeTest, GetContentRange) { |
+ const ContentRangeTestData test = GetParam(); |
+ |
+ std::string headers(test.headers); |
+ HeadersToRaw(&headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(headers)); |
+ |
+ int64 first_byte_position; |
+ int64 last_byte_position; |
+ int64 instance_size; |
+ bool return_value = parsed->GetContentRange(&first_byte_position, |
+ &last_byte_position, |
+ &instance_size); |
+ EXPECT_EQ(test.expected_return_value, return_value); |
+ EXPECT_EQ(test.expected_first_byte_position, first_byte_position); |
+ EXPECT_EQ(test.expected_last_byte_position, last_byte_position); |
+ EXPECT_EQ(test.expected_instance_size, instance_size); |
} |
-TEST(HttpResponseHeadersTest, IsKeepAlive) { |
- const struct { |
- const char* headers; |
- bool expected_keep_alive; |
- } tests[] = { |
- // The status line fabricated by HttpNetworkTransaction for a 0.9 response. |
- // Treated as 0.9. |
- { "HTTP/0.9 200 OK", |
- false |
- }, |
- // This could come from a broken server. Treated as 1.0 because it has a |
- // header. |
- { "HTTP/0.9 200 OK\n" |
- "connection: keep-alive\n", |
- true |
- }, |
- { "HTTP/1.1 200 OK\n", |
- true |
- }, |
- { "HTTP/1.0 200 OK\n", |
- false |
- }, |
- { "HTTP/1.0 200 OK\n" |
- "connection: close\n", |
- false |
- }, |
- { "HTTP/1.0 200 OK\n" |
- "connection: keep-alive\n", |
- true |
- }, |
- { "HTTP/1.0 200 OK\n" |
- "connection: kEeP-AliVe\n", |
- true |
- }, |
- { "HTTP/1.0 200 OK\n" |
- "connection: keep-aliveX\n", |
- false |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: close\n", |
- false |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n", |
- true |
- }, |
- { "HTTP/1.0 200 OK\n" |
- "proxy-connection: close\n", |
- false |
- }, |
- { "HTTP/1.0 200 OK\n" |
- "proxy-connection: keep-alive\n", |
- true |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "proxy-connection: close\n", |
- false |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "proxy-connection: keep-alive\n", |
- true |
- }, |
- }; |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string headers(tests[i].headers); |
- HeadersToRaw(&headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(headers)); |
+const ContentRangeTestData content_range_tests[] = { |
+ { "HTTP/1.1 206 Partial Content", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range:", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: megabytes 0-10/50", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: 0-10/50", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: Bytes 0-50/51", |
+ true, |
+ 0, |
+ 50, |
+ 51 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-50/51", |
+ true, |
+ 0, |
+ 50, |
+ 51 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes\t0-50/51", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-50/51", |
+ true, |
+ 0, |
+ 50, |
+ 51 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0 - 50 \t / \t51", |
+ true, |
+ 0, |
+ 50, |
+ 51 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0\t-\t50\t/\t51\t", |
+ true, |
+ 0, |
+ 50, |
+ 51 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: \tbytes\t\t\t 0\t-\t50\t/\t51\t", |
+ true, |
+ 0, |
+ 50, |
+ 51 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: \t bytes \t 0 - 50 / 5 1", |
+ false, |
+ 0, |
+ 50, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: \t bytes \t 0 - 5 0 / 51", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 50-0/51", |
+ false, |
+ 50, |
+ 0, |
+ -1 |
+ }, |
+ { "HTTP/1.1 416 Requested range not satisfiable\n" |
+ "Content-Range: bytes * /*", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 416 Requested range not satisfiable\n" |
+ "Content-Range: bytes * / * ", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-50/*", |
+ false, |
+ 0, |
+ 50, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-50 / * ", |
+ false, |
+ 0, |
+ 50, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-10000000000/10000000001", |
+ true, |
+ 0, |
+ 10000000000ll, |
+ 10000000001ll |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-10000000000/10000000000", |
+ false, |
+ 0, |
+ 10000000000ll, |
+ 10000000000ll |
+ }, |
+ // 64 bit wraparound. |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0 - 9223372036854775807 / 100", |
+ false, |
+ 0, |
+ kint64max, |
+ 100 |
+ }, |
+ // 64 bit wraparound. |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0 - 100 / -9223372036854775808", |
+ false, |
+ 0, |
+ 100, |
+ kint64min |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes */50", |
+ false, |
+ -1, |
+ -1, |
+ 50 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-50/10", |
+ false, |
+ 0, |
+ 50, |
+ 10 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 40-50/45", |
+ false, |
+ 40, |
+ 50, |
+ 45 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-50/-10", |
+ false, |
+ 0, |
+ 50, |
+ -10 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-0/1", |
+ true, |
+ 0, |
+ 0, |
+ 1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-40000000000000000000/40000000000000000001", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 1-/100", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes -/100", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes -1/100", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 0-1233/*", |
+ false, |
+ 0, |
+ 1233, |
+ -1 |
+ }, |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes -123 - -1/100", |
+ false, |
+ -1, |
+ -1, |
+ -1 |
+ }, |
+}; |
- EXPECT_EQ(tests[i].expected_keep_alive, parsed->IsKeepAlive()); |
- } |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ ContentRangeTest, |
+ testing::ValuesIn(content_range_tests)); |
+ |
+struct KeepAliveTestData { |
+ const char* headers; |
+ bool expected_keep_alive; |
+}; |
+ |
+class IsKeepAliveTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<KeepAliveTestData> { |
+}; |
+ |
+TEST_P(IsKeepAliveTest, IsKeepAlive) { |
+ const KeepAliveTestData test = GetParam(); |
+ |
+ std::string headers(test.headers); |
+ HeadersToRaw(&headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(headers)); |
+ |
+ EXPECT_EQ(test.expected_keep_alive, parsed->IsKeepAlive()); |
} |
-TEST(HttpResponseHeadersTest, HasStrongValidators) { |
- const struct { |
- const char* headers; |
- bool expected_result; |
- } tests[] = { |
- { "HTTP/0.9 200 OK", |
- false |
- }, |
- { "HTTP/1.0 200 OK\n" |
- "Date: Wed, 28 Nov 2007 01:40:10 GMT\n" |
- "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
- "ETag: \"foo\"\n", |
- false |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Date: Wed, 28 Nov 2007 01:40:10 GMT\n" |
- "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
- "ETag: \"foo\"\n", |
- true |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Date: Wed, 28 Nov 2007 00:41:10 GMT\n" |
- "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT\n", |
- true |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Date: Wed, 28 Nov 2007 00:41:09 GMT\n" |
- "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT\n", |
- false |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "ETag: \"foo\"\n", |
- true |
- }, |
- // This is not really a weak etag: |
- { "HTTP/1.1 200 OK\n" |
- "etag: \"w/foo\"\n", |
- true |
- }, |
- // This is a weak etag: |
- { "HTTP/1.1 200 OK\n" |
- "etag: w/\"foo\"\n", |
- false |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "etag: W / \"foo\"\n", |
- false |
- } |
- }; |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string headers(tests[i].headers); |
- HeadersToRaw(&headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(headers)); |
+const KeepAliveTestData keepalive_tests[] = { |
+ // The status line fabricated by HttpNetworkTransaction for a 0.9 response. |
+ // Treated as 0.9. |
+ { "HTTP/0.9 200 OK", |
+ false |
+ }, |
+ // This could come from a broken server. Treated as 1.0 because it has a |
+ // header. |
+ { "HTTP/0.9 200 OK\n" |
+ "connection: keep-alive\n", |
+ true |
+ }, |
+ { "HTTP/1.1 200 OK\n", |
+ true |
+ }, |
+ { "HTTP/1.0 200 OK\n", |
+ false |
+ }, |
+ { "HTTP/1.0 200 OK\n" |
+ "connection: close\n", |
+ false |
+ }, |
+ { "HTTP/1.0 200 OK\n" |
+ "connection: keep-alive\n", |
+ true |
+ }, |
+ { "HTTP/1.0 200 OK\n" |
+ "connection: kEeP-AliVe\n", |
+ true |
+ }, |
+ { "HTTP/1.0 200 OK\n" |
+ "connection: keep-aliveX\n", |
+ false |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: close\n", |
+ false |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n", |
+ true |
+ }, |
+ { "HTTP/1.0 200 OK\n" |
+ "proxy-connection: close\n", |
+ false |
+ }, |
+ { "HTTP/1.0 200 OK\n" |
+ "proxy-connection: keep-alive\n", |
+ true |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "proxy-connection: close\n", |
+ false |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "proxy-connection: keep-alive\n", |
+ true |
+ }, |
+}; |
- EXPECT_EQ(tests[i].expected_result, parsed->HasStrongValidators()) << |
- "Failed test case " << i; |
- } |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ IsKeepAliveTest, |
+ testing::ValuesIn(keepalive_tests)); |
+ |
+struct HasStrongValidatorsTestData { |
+ const char* headers; |
+ bool expected_result; |
+}; |
+ |
+class HasStrongValidatorsTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<HasStrongValidatorsTestData> { |
+}; |
+ |
+TEST_P(HasStrongValidatorsTest, HasStrongValidators) { |
+ const HasStrongValidatorsTestData test = GetParam(); |
+ |
+ std::string headers(test.headers); |
+ HeadersToRaw(&headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(headers)); |
+ |
+ EXPECT_EQ(test.expected_result, parsed->HasStrongValidators()); |
} |
+const HasStrongValidatorsTestData strong_validators_tests[] = { |
+ { "HTTP/0.9 200 OK", |
+ false |
+ }, |
+ { "HTTP/1.0 200 OK\n" |
+ "Date: Wed, 28 Nov 2007 01:40:10 GMT\n" |
+ "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
+ "ETag: \"foo\"\n", |
+ false |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Date: Wed, 28 Nov 2007 01:40:10 GMT\n" |
+ "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT\n" |
+ "ETag: \"foo\"\n", |
+ true |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Date: Wed, 28 Nov 2007 00:41:10 GMT\n" |
+ "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT\n", |
+ true |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Date: Wed, 28 Nov 2007 00:41:09 GMT\n" |
+ "Last-Modified: Wed, 28 Nov 2007 00:40:10 GMT\n", |
+ false |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "ETag: \"foo\"\n", |
+ true |
+ }, |
+ // This is not really a weak etag: |
+ { "HTTP/1.1 200 OK\n" |
+ "etag: \"w/foo\"\n", |
+ true |
+ }, |
+ // This is a weak etag: |
+ { "HTTP/1.1 200 OK\n" |
+ "etag: w/\"foo\"\n", |
+ false |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "etag: W / \"foo\"\n", |
+ false |
+ } |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ HasStrongValidatorsTest, |
+ testing::ValuesIn(strong_validators_tests)); |
+ |
TEST(HttpResponseHeadersTest, GetStatusText) { |
std::string headers("HTTP/1.1 404 Not Found"); |
HeadersToRaw(&headers); |
@@ -1644,7 +1746,7 @@ TEST(HttpResponseHeadersTest, GetStatusTextMissing) { |
HeadersToRaw(&headers); |
scoped_refptr<net::HttpResponseHeaders> parsed( |
new net::HttpResponseHeaders(headers)); |
- // Since the status line gets normalized, we have OK |
+ // Since the status line gets normalized, we have OK. |
EXPECT_EQ(std::string("OK"), parsed->GetStatusText()); |
} |
@@ -1666,297 +1768,353 @@ TEST(HttpResponseHeadersTest, GetStatusBadStatusLine) { |
EXPECT_EQ(std::string("OK"), parsed->GetStatusText()); |
} |
-TEST(HttpResponseHeadersTest, AddHeader) { |
- const struct { |
- const char* orig_headers; |
- const char* new_header; |
- const char* expected_headers; |
- } tests[] = { |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n", |
+struct AddHeaderTestData { |
+ const char* orig_headers; |
+ const char* new_header; |
+ const char* expected_headers; |
+}; |
- "Content-Length: 450", |
+class AddHeaderTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<AddHeaderTestData> { |
+}; |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- "Content-Length: 450\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000 \n", |
+TEST_P(AddHeaderTest, AddHeader) { |
+ const AddHeaderTestData test = GetParam(); |
- "Content-Length: 450 ", |
+ std::string orig_headers(test.orig_headers); |
+ HeadersToRaw(&orig_headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(orig_headers)); |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- "Content-Length: 450\n" |
- }, |
- }; |
- |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string orig_headers(tests[i].orig_headers); |
- HeadersToRaw(&orig_headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(orig_headers)); |
+ std::string new_header(test.new_header); |
+ parsed->AddHeader(new_header); |
- std::string new_header(tests[i].new_header); |
- parsed->AddHeader(new_header); |
+ std::string resulting_headers; |
+ parsed->GetNormalizedHeaders(&resulting_headers); |
+ EXPECT_EQ(std::string(test.expected_headers), resulting_headers); |
+} |
- std::string resulting_headers; |
- parsed->GetNormalizedHeaders(&resulting_headers); |
- EXPECT_EQ(std::string(tests[i].expected_headers), resulting_headers); |
- } |
+const AddHeaderTestData add_header_tests[] = { |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n", |
+ |
+ "Content-Length: 450", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ "Content-Length: 450\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000 \n", |
+ |
+ "Content-Length: 450 ", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ "Content-Length: 450\n" |
+ }, |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ AddHeaderTest, |
+ testing::ValuesIn(add_header_tests)); |
+ |
+struct RemoveHeaderTestData { |
+ const char* orig_headers; |
+ const char* to_remove; |
+ const char* expected_headers; |
+}; |
+ |
+class RemoveHeaderTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<RemoveHeaderTestData> { |
+}; |
+ |
+TEST_P(RemoveHeaderTest, RemoveHeader) { |
+ const RemoveHeaderTestData test = GetParam(); |
+ |
+ std::string orig_headers(test.orig_headers); |
+ HeadersToRaw(&orig_headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(orig_headers)); |
+ |
+ std::string name(test.to_remove); |
+ parsed->RemoveHeader(name); |
+ |
+ std::string resulting_headers; |
+ parsed->GetNormalizedHeaders(&resulting_headers); |
+ EXPECT_EQ(std::string(test.expected_headers), resulting_headers); |
} |
-TEST(HttpResponseHeadersTest, RemoveHeader) { |
- const struct { |
- const char* orig_headers; |
- const char* to_remove; |
- const char* expected_headers; |
- } tests[] = { |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- "Content-Length: 450\n", |
+const RemoveHeaderTestData remove_header_tests[] = { |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ "Content-Length: 450\n", |
- "Content-Length", |
+ "Content-Length", |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive \n" |
- "Content-Length : 450 \n" |
- "Cache-control: max-age=10000\n", |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive \n" |
+ "Content-Length : 450 \n" |
+ "Cache-control: max-age=10000\n", |
- "Content-Length", |
+ "Content-Length", |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- }, |
- }; |
- |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string orig_headers(tests[i].orig_headers); |
- HeadersToRaw(&orig_headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(orig_headers)); |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ }, |
+}; |
- std::string name(tests[i].to_remove); |
- parsed->RemoveHeader(name); |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ RemoveHeaderTest, |
+ testing::ValuesIn(remove_header_tests)); |
- std::string resulting_headers; |
- parsed->GetNormalizedHeaders(&resulting_headers); |
- EXPECT_EQ(std::string(tests[i].expected_headers), resulting_headers); |
- } |
+struct RemoveIndividualHeaderTestData { |
+ const char* orig_headers; |
+ const char* to_remove_name; |
+ const char* to_remove_value; |
+ const char* expected_headers; |
+}; |
+ |
+class RemoveIndividualHeaderTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<RemoveIndividualHeaderTestData> { |
+}; |
+ |
+TEST_P(RemoveIndividualHeaderTest, RemoveIndividualHeader) { |
+ const RemoveIndividualHeaderTestData test = GetParam(); |
+ |
+ std::string orig_headers(test.orig_headers); |
+ HeadersToRaw(&orig_headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(orig_headers)); |
+ |
+ std::string name(test.to_remove_name); |
+ std::string value(test.to_remove_value); |
+ parsed->RemoveHeaderLine(name, value); |
+ |
+ std::string resulting_headers; |
+ parsed->GetNormalizedHeaders(&resulting_headers); |
+ EXPECT_EQ(std::string(test.expected_headers), resulting_headers); |
} |
-TEST(HttpResponseHeadersTest, RemoveIndividualHeader) { |
- const struct { |
- const char* orig_headers; |
- const char* to_remove_name; |
- const char* to_remove_value; |
- const char* expected_headers; |
- } tests[] = { |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- "Content-Length: 450\n", |
+const RemoveIndividualHeaderTestData remove_individual_header_tests[] = { |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ "Content-Length: 450\n", |
- "Content-Length", |
+ "Content-Length", |
- "450", |
+ "450", |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive \n" |
- "Content-Length : 450 \n" |
- "Cache-control: max-age=10000\n", |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive \n" |
+ "Content-Length : 450 \n" |
+ "Cache-control: max-age=10000\n", |
- "Content-Length", |
+ "Content-Length", |
- "450", |
+ "450", |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive \n" |
- "Content-Length: 450\n" |
- "Cache-control: max-age=10000\n", |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive \n" |
+ "Content-Length: 450\n" |
+ "Cache-control: max-age=10000\n", |
- "Content-Length", // Matching name. |
+ "Content-Length", // Matching name. |
- "999", // Mismatching value. |
+ "999", // Mismatching value. |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Content-Length: 450\n" |
- "Cache-control: max-age=10000\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive \n" |
- "Foo: bar, baz\n" |
- "Foo: bar\n" |
- "Cache-control: max-age=10000\n", |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Content-Length: 450\n" |
+ "Cache-control: max-age=10000\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive \n" |
+ "Foo: bar, baz\n" |
+ "Foo: bar\n" |
+ "Cache-control: max-age=10000\n", |
- "Foo", |
+ "Foo", |
- "bar, baz", // Space in value. |
+ "bar, baz", // Space in value. |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Foo: bar\n" |
- "Cache-control: max-age=10000\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive \n" |
- "Foo: bar, baz\n" |
- "Cache-control: max-age=10000\n", |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Foo: bar\n" |
+ "Cache-control: max-age=10000\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive \n" |
+ "Foo: bar, baz\n" |
+ "Cache-control: max-age=10000\n", |
- "Foo", |
+ "Foo", |
- "baz", // Only partial match -> ignored. |
+ "baz", // Only partial match -> ignored. |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Foo: bar, baz\n" |
- "Cache-control: max-age=10000\n" |
- }, |
- }; |
- |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string orig_headers(tests[i].orig_headers); |
- HeadersToRaw(&orig_headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(orig_headers)); |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Foo: bar, baz\n" |
+ "Cache-control: max-age=10000\n" |
+ }, |
+}; |
- std::string name(tests[i].to_remove_name); |
- std::string value(tests[i].to_remove_value); |
- parsed->RemoveHeaderLine(name, value); |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ RemoveIndividualHeaderTest, |
+ testing::ValuesIn(remove_individual_header_tests)); |
- std::string resulting_headers; |
- parsed->GetNormalizedHeaders(&resulting_headers); |
- EXPECT_EQ(std::string(tests[i].expected_headers), resulting_headers); |
- } |
-} |
+struct ReplaceStatusTestData { |
+ const char* orig_headers; |
+ const char* new_status; |
+ const char* expected_headers; |
+}; |
-TEST(HttpResponseHeadersTest, ReplaceStatus) { |
- const struct { |
- const char* orig_headers; |
- const char* new_status; |
- const char* expected_headers; |
- } tests[] = { |
- { "HTTP/1.1 206 Partial Content\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- "Content-Length: 450\n", |
+class ReplaceStatusTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<ReplaceStatusTestData> { |
+}; |
- "HTTP/1.1 200 OK", |
+TEST_P(ReplaceStatusTest, ReplaceStatus) { |
+ const ReplaceStatusTestData test = GetParam(); |
- "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n" |
- "Cache-control: max-age=10000\n" |
- "Content-Length: 450\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive\n", |
- |
- "HTTP/1.1 304 Not Modified", |
- |
- "HTTP/1.1 304 Not Modified\n" |
- "connection: keep-alive\n" |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "connection: keep-alive \n" |
- "Content-Length : 450 \n" |
- "Cache-control: max-age=10000\n", |
- |
- "HTTP/1//1 304 Not Modified", |
- |
- "HTTP/1.0 304 Not Modified\n" |
- "connection: keep-alive\n" |
- "Content-Length: 450\n" |
- "Cache-control: max-age=10000\n" |
- }, |
- }; |
- |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string orig_headers(tests[i].orig_headers); |
- HeadersToRaw(&orig_headers); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(orig_headers)); |
+ std::string orig_headers(test.orig_headers); |
+ HeadersToRaw(&orig_headers); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(orig_headers)); |
- std::string name(tests[i].new_status); |
- parsed->ReplaceStatusLine(name); |
+ std::string name(test.new_status); |
+ parsed->ReplaceStatusLine(name); |
- std::string resulting_headers; |
- parsed->GetNormalizedHeaders(&resulting_headers); |
- EXPECT_EQ(std::string(tests[i].expected_headers), resulting_headers); |
- } |
+ std::string resulting_headers; |
+ parsed->GetNormalizedHeaders(&resulting_headers); |
+ EXPECT_EQ(std::string(test.expected_headers), resulting_headers); |
} |
-TEST(HttpResponseHeadersTest, UpdateWithNewRange) { |
- const struct { |
- const char* orig_headers; |
- const char* expected_headers; |
- const char* expected_headers_with_replaced_status; |
- } tests[] = { |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 450\n", |
+const ReplaceStatusTestData replace_status_tests[] = { |
+ { "HTTP/1.1 206 Partial Content\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ "Content-Length: 450\n", |
- "HTTP/1.1 200 OK\n" |
- "Content-Range: bytes 3-5/450\n" |
- "Content-Length: 3\n", |
+ "HTTP/1.1 200 OK", |
- "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 3-5/450\n" |
- "Content-Length: 3\n", |
- }, |
- { "HTTP/1.1 200 OK\n" |
- "Content-Length: 5\n", |
+ "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n" |
+ "Cache-control: max-age=10000\n" |
+ "Content-Length: 450\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive\n", |
+ |
+ "HTTP/1.1 304 Not Modified", |
+ |
+ "HTTP/1.1 304 Not Modified\n" |
+ "connection: keep-alive\n" |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "connection: keep-alive \n" |
+ "Content-Length : 450 \n" |
+ "Cache-control: max-age=10000\n", |
+ |
+ "HTTP/1//1 304 Not Modified", |
+ |
+ "HTTP/1.0 304 Not Modified\n" |
+ "connection: keep-alive\n" |
+ "Content-Length: 450\n" |
+ "Cache-control: max-age=10000\n" |
+ }, |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ ReplaceStatusTest, |
+ testing::ValuesIn(replace_status_tests)); |
+ |
+struct UpdateWithNewRangeTestData { |
+ const char* orig_headers; |
+ const char* expected_headers; |
+ const char* expected_headers_with_replaced_status; |
+}; |
+ |
+class UpdateWithNewRangeTest |
+ : public HttpResponseHeadersTest, |
+ public ::testing::WithParamInterface<UpdateWithNewRangeTestData> { |
+}; |
+ |
+TEST_P(UpdateWithNewRangeTest, UpdateWithNewRange) { |
+ const UpdateWithNewRangeTestData test = GetParam(); |
- "HTTP/1.1 200 OK\n" |
- "Content-Range: bytes 3-5/5\n" |
- "Content-Length: 3\n", |
- |
- "HTTP/1.1 206 Partial Content\n" |
- "Content-Range: bytes 3-5/5\n" |
- "Content-Length: 3\n", |
- }, |
- }; |
const net::HttpByteRange range = net::HttpByteRange::Bounded(3, 5); |
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |
- std::string orig_headers(tests[i].orig_headers); |
- std::replace(orig_headers.begin(), orig_headers.end(), '\n', '\0'); |
- scoped_refptr<net::HttpResponseHeaders> parsed( |
- new net::HttpResponseHeaders(orig_headers + '\0')); |
- int64 content_size = parsed->GetContentLength(); |
- std::string resulting_headers; |
- |
- // Update headers without replacing status line. |
- parsed->UpdateWithNewRange(range, content_size, false); |
- parsed->GetNormalizedHeaders(&resulting_headers); |
- EXPECT_EQ(std::string(tests[i].expected_headers), resulting_headers); |
- |
- // Replace status line too. |
- parsed->UpdateWithNewRange(range, content_size, true); |
- parsed->GetNormalizedHeaders(&resulting_headers); |
- EXPECT_EQ(std::string(tests[i].expected_headers_with_replaced_status), |
- resulting_headers); |
- } |
+ std::string orig_headers(test.orig_headers); |
+ std::replace(orig_headers.begin(), orig_headers.end(), '\n', '\0'); |
+ scoped_refptr<net::HttpResponseHeaders> parsed( |
+ new net::HttpResponseHeaders(orig_headers + '\0')); |
+ int64 content_size = parsed->GetContentLength(); |
+ std::string resulting_headers; |
+ |
+ // Update headers without replacing status line. |
+ parsed->UpdateWithNewRange(range, content_size, false); |
+ parsed->GetNormalizedHeaders(&resulting_headers); |
+ EXPECT_EQ(std::string(test.expected_headers), resulting_headers); |
+ |
+ // Replace status line too. |
+ parsed->UpdateWithNewRange(range, content_size, true); |
+ parsed->GetNormalizedHeaders(&resulting_headers); |
+ EXPECT_EQ(std::string(test.expected_headers_with_replaced_status), |
+ resulting_headers); |
} |
+const UpdateWithNewRangeTestData update_range_tests[] = { |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 450\n", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ "Content-Range: bytes 3-5/450\n" |
+ "Content-Length: 3\n", |
+ |
+ "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 3-5/450\n" |
+ "Content-Length: 3\n", |
+ }, |
+ { "HTTP/1.1 200 OK\n" |
+ "Content-Length: 5\n", |
+ |
+ "HTTP/1.1 200 OK\n" |
+ "Content-Range: bytes 3-5/5\n" |
+ "Content-Length: 3\n", |
+ |
+ "HTTP/1.1 206 Partial Content\n" |
+ "Content-Range: bytes 3-5/5\n" |
+ "Content-Length: 3\n", |
+ }, |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, |
+ UpdateWithNewRangeTest, |
+ testing::ValuesIn(update_range_tests)); |
+ |
TEST(HttpResponseHeadersTest, ToNetLogParamAndBackAgain) { |
std::string headers("HTTP/1.1 404\n" |
"Content-Length: 450\n" |
@@ -2011,8 +2169,8 @@ TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeFirstMatchUsed) { |
} |
TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeBogusFirstMatchUsed) { |
- // max-age10 isn't parsed as max-age; max-age=now is parsed as max-age=0 and |
- // so max-age=20 is not used. |
+ // "max-age10" isn't parsed as "max-age"; "max-age=now" is parsed as |
+ // "max-age=0" and so "max-age=20" is not used. |
InitializeHeadersWithCacheControl("max-age10, max-age=now, max-age=20"); |
EXPECT_EQ(TimeDelta::FromSeconds(0), GetMaxAgeValue()); |
} |
@@ -2022,40 +2180,49 @@ TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeCaseInsensitive) { |
EXPECT_EQ(TimeDelta::FromSeconds(15), GetMaxAgeValue()); |
} |
-TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeEdgeCases) { |
- // This test doesn't use TEST_P() for consistency with the rest of the tests |
- // in this file. |
- // TODO(ricea): Port the tests in this file to use TEST_P(). |
- const struct { |
- const char* max_age_string; |
- int64 expected_seconds; |
- } tests[] = { |
- {" 1 ", 1}, // Spaces are ignored |
- {"-1", -1}, // Negative numbers are passed through |
- {"--1", 0}, // Leading junk gives 0 |
- {"2s", 2}, // trailing junk is ignored |
- {"3 days", 3}, |
- {"'4'", 0}, // single quotes don't work |
- {"\"5\"", 0}, // double quotes don't work |
- {"0x6", 0}, // hex not parsed as hex |
- {"7F", 7}, // hex without 0x still not parsed as hex |
- {"010", 10}, // octal not parsed as octal |
- {"9223372036854", 9223372036854}, |
- // {"9223372036855", -9223372036854}, // undefined behaviour |
- // {"9223372036854775806", -2}, // undefined behaviour |
- {"9223372036854775807", 9223372036854775807}, |
- {"20000000000000000000", |
- std::numeric_limits<int64>::max()}, // overflow int64 |
- }; |
+struct MaxAgeTestData { |
+ const char* max_age_string; |
+ const int64 expected_seconds; |
+}; |
+ |
+class MaxAgeEdgeCasesTest |
+ : public HttpResponseHeadersCacheControlTest, |
+ public ::testing::WithParamInterface<MaxAgeTestData> { |
+}; |
+ |
+TEST_P(MaxAgeEdgeCasesTest, MaxAgeEdgeCases) { |
+ const MaxAgeTestData test = GetParam(); |
+ |
std::string max_age = "max-age="; |
- for (size_t i = 0; i < arraysize(tests); ++i) { |
- InitializeHeadersWithCacheControl( |
- (max_age + tests[i].max_age_string).c_str()); |
- EXPECT_EQ(tests[i].expected_seconds, GetMaxAgeValue().InSeconds()) |
- << " for max-age=" << tests[i].max_age_string; |
- } |
+ InitializeHeadersWithCacheControl( |
+ (max_age + test.max_age_string).c_str()); |
+ EXPECT_EQ(test.expected_seconds, GetMaxAgeValue().InSeconds()) |
+ << " for max-age=" << test.max_age_string; |
} |
+const MaxAgeTestData max_age_tests[] = { |
+ {" 1 ", 1}, // Spaces are ignored. |
+ {"-1", -1}, // Negative numbers are passed through. |
+ {"--1", 0}, // Leading junk gives 0. |
+ {"2s", 2}, // Trailing junk is ignored. |
+ {"3 days", 3}, |
+ {"'4'", 0}, // Single quotes don't work. |
+ {"\"5\"", 0}, // Double quotes don't work. |
+ {"0x6", 0}, // Hex not parsed as hex. |
+ {"7F", 7}, // Hex without 0x still not parsed as hex. |
+ {"010", 10}, // Octal not parsed as octal. |
+ {"9223372036854", 9223372036854}, |
+ // {"9223372036855", -9223372036854}, // Undefined behaviour. |
+ // {"9223372036854775806", -2}, // Undefined behaviour. |
+ {"9223372036854775807", 9223372036854775807}, |
+ {"20000000000000000000", |
+ std::numeric_limits<int64>::max()}, // Overflow int64. |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(HttpResponseHeadersCacheControl, |
+ MaxAgeEdgeCasesTest, |
+ testing::ValuesIn(max_age_tests)); |
+ |
TEST_F(HttpResponseHeadersCacheControlTest, |
AbsentStaleWhileRevalidateReturnsFalse) { |
InitializeHeadersWithCacheControl("max-age=3600"); |
@@ -2085,3 +2252,5 @@ TEST_F(HttpResponseHeadersCacheControlTest, |
"stale-while-revalidate=1,stale-while-revalidate=7200"); |
EXPECT_EQ(TimeDelta::FromSeconds(1), GetStaleWhileRevalidateValue()); |
} |
+ |
+} // end namespace |