15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::HttpUtil;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HttpUtilTest : public testing::Test {};
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, IsSafeHeader) {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* unsafe_headers[] = {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "sec-",
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "sEc-",
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "sec-foo",
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "sEc-FoO",
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "proxy-",
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "pRoXy-",
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "proxy-foo",
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "pRoXy-FoO",
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "accept-charset",
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "accept-encoding",
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "access-control-request-headers",
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "access-control-request-method",
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "connection",
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "content-length",
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "cookie",
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "cookie2",
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "content-transfer-encoding",
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "date",
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "expect",
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "host",
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "keep-alive",
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "origin",
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "referer",
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "te",
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "trailer",
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "transfer-encoding",
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "upgrade",
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "user-agent",
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "via",
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(unsafe_headers); ++i) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(HttpUtil::IsSafeHeader(unsafe_headers[i]))
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << unsafe_headers[i];
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(HttpUtil::IsSafeHeader(StringToUpperASCII(std::string(
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unsafe_headers[i])))) << unsafe_headers[i];
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* safe_headers[] = {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "foo",
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "x-",
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "x-foo",
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "content-disposition",
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "update",
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "accept-charseta",
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "accept_charset",
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "accept-encodinga",
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "accept_encoding",
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "access-control-request-headersa",
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "access-control-request-header",
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "access_control_request_header",
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "access-control-request-methoda",
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "access_control_request_method",
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "connectiona",
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "content-lengtha",
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "content_length",
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "cookiea",
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "cookie2a",
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "cookie3",
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "content-transfer-encodinga",
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "content_transfer_encoding",
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "datea",
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "expecta",
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "hosta",
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "keep-alivea",
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "keep_alive",
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "origina",
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "referera",
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "referrer",
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "tea",
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "trailera",
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "transfer-encodinga",
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "transfer_encoding",
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "upgradea",
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "user-agenta",
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "user_agent",
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "viaa",
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(safe_headers); ++i) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(HttpUtil::IsSafeHeader(safe_headers[i])) << safe_headers[i];
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(HttpUtil::IsSafeHeader(StringToUpperASCII(std::string(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        safe_headers[i])))) << safe_headers[i];
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, HasHeader) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const struct {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* headers;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* name;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool expected_result;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } tests[] = {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "", "foo", false },
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "foo\r\nbar", "foo", false },
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "ffoo: 1", "foo", false },
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "foo: 1", "foo", true },
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "foo: 1\r\nbar: 2", "foo", true },
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "fOO: 1\r\nbar: 2", "foo", true },
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "g: 0\r\nfoo: 1\r\nbar: 2", "foo", true },
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = HttpUtil::HasHeader(tests[i].headers, tests[i].name);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].expected_result, result);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, StripHeaders) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* headers =
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Origin: origin\r\n"
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Content-Type: text/plain\r\n"
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Cookies: foo1\r\n"
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Custom: baz\r\n"
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "COOKIES: foo2\r\n"
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Server: Apache\r\n"
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "OrIGin: origin2\r\n";
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* header_names[] = {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "origin", "content-type", "cookies"
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* expected_stripped_headers =
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Custom: baz\r\n"
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Server: Apache\r\n";
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(expected_stripped_headers,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            HttpUtil::StripHeaders(headers, header_names,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   arraysize(header_names)));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, HeadersIterator) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n";
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(it.GetNext());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("foo"), it.name());
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("1"), it.values());
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(it.GetNext());
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("bar"), it.name());
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("hello world"), it.values());
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(it.GetNext());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("baz"), it.name());
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("3"), it.values());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(it.GetNext());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, HeadersIterator_MalformedLine) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string headers = "foo: 1\n: 2\n3\nbar: 4";
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(it.GetNext());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("foo"), it.name());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("1"), it.values());
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(it.GetNext());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("bar"), it.name());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("4"), it.values());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(it.GetNext());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, HeadersIterator_AdvanceTo) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string headers = "foo: 1\r\n: 2\r\n3\r\nbar: 4";
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it.AdvanceTo("foo"));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("foo", it.name());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it.AdvanceTo("bar"));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("bar", it.name());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(it.AdvanceTo("blat"));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(it.GetNext());  // should be at end of headers
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, HeadersIterator_Reset) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string headers = "foo: 1\r\n: 2\r\n3\r\nbar: 4";
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n");
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Search past "foo".
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it.AdvanceTo("bar"));
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now try advancing to "foo".  This time it should fail since the iterator
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position is past it.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(it.AdvanceTo("foo"));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it.Reset();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now that we reset the iterator position, we should find 'foo'
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it.AdvanceTo("foo"));
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, ValuesIterator) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string values = " must-revalidate,   no-cache=\"foo, bar\"\t, private ";
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::ValuesIterator it(values.begin(), values.end(), ',');
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(it.GetNext());
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("must-revalidate"), it.value());
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(it.GetNext());
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("no-cache=\"foo, bar\""), it.value());
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(it.GetNext());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("private"), it.value());
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(it.GetNext());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, ValuesIterator_Blanks) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string values = " \t ";
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::ValuesIterator it(values.begin(), values.end(), ',');
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(it.GetNext());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, Unquote) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace <backslash> " with ".
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("xyz\"abc", HttpUtil::Unquote("\"xyz\\\"abc\"").c_str());
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace <backslash> <backslash> with <backslash>
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("xyz\\abc", HttpUtil::Unquote("\"xyz\\\\abc\"").c_str());
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("xyz\\\\\\abc",
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               HttpUtil::Unquote("\"xyz\\\\\\\\\\\\abc\"").c_str());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace <backslash> X with X
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("xyzXabc", HttpUtil::Unquote("\"xyz\\Xabc\"").c_str());
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Act as identity function on unquoted inputs.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("X", HttpUtil::Unquote("X").c_str());
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("\"", HttpUtil::Unquote("\"").c_str());
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow single quotes to act as quote marks.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not part of RFC 2616.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("x\"", HttpUtil::Unquote("'x\"'").c_str());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, Quote) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("\"xyz\\\"abc\"", HttpUtil::Quote("xyz\"abc").c_str());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace <backslash> <backslash> with <backslash>
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("\"xyz\\\\abc\"", HttpUtil::Quote("xyz\\abc").c_str());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace <backslash> X with X
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("\"xyzXabc\"", HttpUtil::Quote("xyzXabc").c_str());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, LocateEndOfHeaders) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* input;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int expected_result;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } tests[] = {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "foo\r\nbar\r\n\r\n", 12 },
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "foo\nbar\n\n", 9 },
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "foo\r\nbar\r\n\r\njunk", 12 },
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "foo\nbar\n\njunk", 9 },
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "foo\nbar\n\r\njunk", 10 },
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "foo\nbar\r\n\njunk", 10 },
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int input_len = static_cast<int>(strlen(tests[i].input));
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int eoh = HttpUtil::LocateEndOfHeaders(tests[i].input, input_len);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].expected_result, eoh);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, AssembleRawHeaders) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* input;  // with '|' representing '\0'
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_result;  // with '\0' changed to '|'
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } tests[] = {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "HTTP/1.0 200 OK\r\nFoo: 1\r\nBar: 2\r\n\r\n",
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" },
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "HTTP/1.0 200 OK\nFoo: 1\nBar: 2\n\n",
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" },
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid line continuation (single SP).
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " continuation\n"
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1 continuation|"
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid line continuation (single HT).
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\tcontinuation\n"
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1 continuation|"
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid line continuation (multiple SP).
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "   continuation\n"
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1 continuation|"
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid line continuation (multiple HT).
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\t\t\tcontinuation\n"
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1 continuation|"
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid line continuation (mixed HT, SP).
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " \t \t continuation\n"
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1 continuation|"
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid multi-line continuation
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " continuation1\n"
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\tcontinuation2\n"
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  continuation3\n"
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1 continuation1 continuation2 continuation3|"
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Continuation of quoted value.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is different from what Firefox does, since it
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // will preserve the LWS.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Etag: \"34534-d3\n"
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    134q\"\n"
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Etag: \"34534-d3 134q\"|"
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid multi-line continuation, full LWS lines
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "         \n"
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\t\t\t\t\n"
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\t  continuation\n"
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // One SP per continued line = 3.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1   continuation|"
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid multi-line continuation, all LWS
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "         \n"
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\t\t\t\t\n"
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\t  \n"
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // One SP per continued line = 3.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1   |"
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid line continuation (No value bytes in first line).
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo:\n"
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " value\n"
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: value|"
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a line continuation (can't continue status line).
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " Foo: 1\n"
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " Foo: 1|"
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a line continuation (can't continue status line).
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0\n"
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " 200 OK\n"
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0|"
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " 200 OK|"
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1|"
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a line continuation (can't continue status line).
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 404\n"
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " Not Found\n"
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 404|"
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " Not Found|"
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1|"
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Unterminated status line.
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK",
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK||"
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Single terminated, with headers
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n",
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1|"
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not terminated, with headers
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2",
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1|"
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a line continuation (VT)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\vInvalidContinuation\n"
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1|"
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\vInvalidContinuation|"
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a line continuation (formfeed)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\fInvalidContinuation\n"
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1|"
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\fInvalidContinuation|"
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a line continuation -- can't continue header names.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Serv\n"
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " er: Apache\n"
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\tInvalidContinuation\n"
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Serv|"
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " er: Apache|"
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\tInvalidContinuation|"
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||"
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a line continuation -- no value to continue.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1\n"
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "garbage\n"
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  not-a-continuation\n"
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Foo: 1|"
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "garbage|"
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  not-a-continuation|"
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||",
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a line continuation -- no valid name.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ": 1\n"
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  garbage\n"
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ": 1|"
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  garbage|"
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||",
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not a line continuation -- no valid name (whitespace)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\n"
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "   : 1\n"
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  garbage\n"
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2\n\n",
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|"
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "   : 1|"
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  garbage|"
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Bar: 2||",
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Embed NULLs in the status line. They should not be understood
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // as line separators.
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|Bar2:0|Baz2:1\r\nFoo: 1\r\nBar: 2\r\n\r\n",
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OKBar2:0Baz2:1|Foo: 1|Bar: 2||"
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Embed NULLs in a header line. They should not be understood as
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // line separators.
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK\nFoo: 1|Foo2: 3\nBar: 2\n\n",
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.0 200 OK|Foo: 1Foo2: 3|Bar: 2||"
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string input = tests[i].input;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::replace(input.begin(), input.end(), '|', '\0');
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string raw = HttpUtil::AssembleRawHeaders(input.data(), input.size());
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::replace(raw.begin(), raw.end(), '\0', '|');
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].expected_result, raw);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test SpecForRequest() and PathForRequest().
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, RequestUrlSanitize) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* url;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_spec;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_path;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } tests[] = {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { // Check that #hash is removed.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "http://www.google.com:78/foobar?query=1#hash",
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "http://www.google.com:78/foobar?query=1",
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "/foobar?query=1"
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { // The reference may itself contain # -- strip all of it.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "http://192.168.0.1?query=1#hash#10#11#13#14",
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "http://192.168.0.1/?query=1",
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "/?query=1"
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { // Strip username/password.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "http://user:pass@google.com",
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "http://google.com/",
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "/"
615a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    },
616a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    { // https scheme
617a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "https://www.google.com:78/foobar?query=1#hash",
618a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "https://www.google.com:78/foobar?query=1",
619a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "/foobar?query=1"
620a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    },
621a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    { // WebSocket's ws scheme
622a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "ws://www.google.com:78/foobar?query=1#hash",
623a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "ws://www.google.com:78/foobar?query=1",
624a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "/foobar?query=1"
625a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    },
626a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    { // WebSocket's wss scheme
627a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "wss://www.google.com:78/foobar?query=1#hash",
628a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "wss://www.google.com:78/foobar?query=1",
629a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "/foobar?query=1"
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL url(GURL(tests[i].url));
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string expected_spec(tests[i].expected_spec);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string expected_path(tests[i].expected_path);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(expected_spec, HttpUtil::SpecForRequest(url));
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(expected_path, HttpUtil::PathForRequest(url));
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
642a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Test SpecForRequest() for "ftp" scheme.
643a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST(HttpUtilTest, SpecForRequestForUrlWithFtpScheme) {
644a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  GURL ftp_url("ftp://user:pass@google.com/pub/chromium/");
645a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ("ftp://google.com/pub/chromium/",
646a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            HttpUtil::SpecForRequest(ftp_url));
647a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, GenerateAcceptLanguageHeader) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"),
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de"));
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6,ko;q=0.4,zh-CN;q=0.2,"
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        "ja;q=0.2"),
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja"));
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HttpResponseHeadersTest.GetMimeType also tests ParseContentType.
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, ParseContentType) {
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const struct {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* content_type;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_mime_type;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_charset;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool expected_had_charset;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_boundary;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } tests[] = {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; charset=utf-8",
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "utf-8",
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ""
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; charset =utf-8",
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "utf-8",
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ""
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; charset= utf-8",
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "utf-8",
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ""
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; charset=utf-8 ",
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "utf-8",
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ""
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs\"",
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "",
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\"WebKit-ada-df-dsf-adsfadsfs\""
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; boundary =\"WebKit-ada-df-dsf-adsfadsfs\"",
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "",
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\"WebKit-ada-df-dsf-adsfadsfs\""
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\"",
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "",
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\"WebKit-ada-df-dsf-adsfadsfs\""
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; boundary= \"WebKit-ada-df-dsf-adsfadsfs\"   ",
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "",
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\"WebKit-ada-df-dsf-adsfadsfs\""
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; boundary=\"WebKit-ada-df-dsf-adsfadsfs  \"",
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "",
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\"WebKit-ada-df-dsf-adsfadsfs  \""
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "text/html; boundary=WebKit-ada-df-dsf-adsfadsfs",
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "text/html",
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "",
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "WebKit-ada-df-dsf-adsfadsfs"
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(abarth): Add more interesting test cases.
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string mime_type;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string charset;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool had_charset = false;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string boundary;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpUtil::ParseContentType(tests[i].content_type, &mime_type,
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &charset, &had_charset, &boundary);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].expected_mime_type, mime_type) << "i=" << i;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].expected_charset, charset) << "i=" << i;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].expected_had_charset, had_charset) << "i=" << i;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].expected_boundary, boundary) << "i=" << i;
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, ParseRanges) {
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const struct {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* headers;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool expected_return_value;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expected_ranges_size;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 expected_first_byte_position;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 expected_last_byte_position;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 expected_suffix_length;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } expected_ranges[10];
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } tests[] = {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=0-10",
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1,
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { {0, 10, -1}, }
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=10-0",
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {}
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: BytES=0-10",
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1,
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { {0, 10, -1}, }
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: megabytes=0-10",
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {}
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes0-10",
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {}
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=0-0,0-10,10-20,100-200,100-,-200",
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      6,
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { {0, 0, -1},
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {0, 10, -1},
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {10, 20, -1},
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {100, 200, -1},
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {100, -1, -1},
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {-1, -1, 200},
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=0-10\r\n"
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Range: bytes=0-10,10-20,100-200,100-,-200",
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1,
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { {0, 10, -1}
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=",
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {}
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=-",
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {}
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=0-10-",
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {}
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=-0-10",
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {}
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes =0-10\r\n",
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1,
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { {0, 10, -1}
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=  0-10      \r\n",
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1,
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { {0, 10, -1}
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes  =   0  -   10      \r\n",
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1,
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { {0, 10, -1}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=   0-1   0\r\n",
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=   0-     -10\r\n",
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {}
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Range: bytes=   0  -  1   ,   10 -20,   100- 200 ,  100-,  -200 \r\n",
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      5,
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { {0, 1, -1},
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {10, 20, -1},
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {100, 200, -1},
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {100, -1, -1},
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {-1, -1, 200},
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<net::HttpByteRange> ranges;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool return_value = HttpUtil::ParseRanges(std::string(tests[i].headers),
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              &ranges);
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].expected_return_value, return_value);
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (return_value) {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(tests[i].expected_ranges_size, ranges.size());
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t j = 0; j < ranges.size(); ++j) {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(tests[i].expected_ranges[j].expected_first_byte_position,
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  ranges[j].first_byte_position());
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(tests[i].expected_ranges[j].expected_last_byte_position,
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  ranges[j].last_byte_position());
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(tests[i].expected_ranges[j].expected_suffix_length,
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  ranges[j].suffix_length());
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckCurrentNameValuePair(HttpUtil::NameValuePairsIterator* parser,
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               bool expect_valid,
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               std::string expected_name,
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               std::string expected_value) {
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expect_valid, parser->valid());
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!expect_valid) {
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Let's make sure that these never change (i.e., when a quoted value is
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unquoted, it should be cached on the first calls and not regenerated
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // later).
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator first_value_begin = parser->value_begin();
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator first_value_end = parser->value_end();
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected_name, std::string(parser->name_begin(),
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       parser->name_end()));
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected_name, parser->name());
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected_value, std::string(parser->value_begin(),
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        parser->value_end()));
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected_value, parser->value());
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure they didn't/don't change.
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(first_value_begin == parser->value_begin());
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(first_value_end == parser->value_end());
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckNextNameValuePair(HttpUtil::NameValuePairsIterator* parser,
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool expect_next,
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool expect_valid,
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            std::string expected_name,
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            std::string expected_value) {
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expect_next, parser->GetNext());
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expect_valid, parser->valid());
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!expect_next || !expect_valid) {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckCurrentNameValuePair(parser,
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            expect_valid,
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            expected_name,
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            expected_value);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckInvalidNameValuePair(std::string valid_part,
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               std::string invalid_part) {
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string whole_string = valid_part + invalid_part;
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::NameValuePairsIterator valid_parser(valid_part.begin(),
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                valid_part.end(),
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                ';');
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::NameValuePairsIterator invalid_parser(whole_string.begin(),
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  whole_string.end(),
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  ';');
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(valid_parser.valid());
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(invalid_parser.valid());
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Both parsers should return all the same values until "valid_parser" is
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exhausted.
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (valid_parser.GetNext()) {
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(invalid_parser.GetNext());
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(valid_parser.valid());
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(invalid_parser.valid());
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(valid_parser.name(), invalid_parser.name());
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(valid_parser.value(), invalid_parser.value());
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // valid_parser is exhausted and remains 'valid'
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(valid_parser.valid());
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invalid_parser's corresponding call to GetNext also returns false...
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(invalid_parser.GetNext());
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ...but the parser is in an invalid state.
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(invalid_parser.valid());
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, NameValuePairsIteratorCopyAndAssign) {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data = "alpha='\\'a\\''; beta=\" b \"; cappa='c;'; delta=\"d\"";
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::NameValuePairsIterator parser_a(data.begin(), data.end(), ';');
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(parser_a.valid());
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser_a, true, true, "alpha", "'a'"));
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::NameValuePairsIterator parser_b(parser_a);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a and b now point to same location
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckCurrentNameValuePair(&parser_b, true, "alpha", "'a'"));
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckCurrentNameValuePair(&parser_a, true, "alpha", "'a'"));
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // advance a, no effect on b
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser_a, true, true, "beta", " b "));
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckCurrentNameValuePair(&parser_b, true, "alpha", "'a'"));
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // assign b the current state of a, no effect on a
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser_b = parser_a;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckCurrentNameValuePair(&parser_b, true, "beta", " b "));
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // advance b, no effect on a
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser_b, true, true, "cappa", "c;"));
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckCurrentNameValuePair(&parser_a, true, "beta", " b "));
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, NameValuePairsIteratorEmptyInput) {
991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string data;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(parser.valid());
995c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
996c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &parser, false, true, std::string(), std::string()));
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, NameValuePairsIterator) {
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data = "alpha=1; beta= 2 ;cappa =' 3; ';"
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "delta= \" \\\"4\\\" \"; e= \" '5'\"; e=6;"
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "f='\\'\\h\\e\\l\\l\\o\\ \\w\\o\\r\\l\\d\\'';"
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "g=''; h='hello'";
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(parser.valid());
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "beta", "2"));
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "cappa", " 3; "));
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "delta", " \"4\" "));
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "e", " '5'"));
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "e", "6"));
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "f", "'hello world'"));
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
1022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "g", std::string()));
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "h", "hello"));
1025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1026c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &parser, false, true, std::string(), std::string()));
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) {
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; beta"));
1031c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "beta"));
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; 'beta'=2"));
1034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "'beta'=2"));
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";beta="));
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1",
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    ";beta=;cappa=2"));
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // According to the spec this is an error, but it doesn't seem appropriate to
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // change our behaviour to be less permissive at this time.
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See NameValuePairsIteratorExtraSeparators test
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", ";; beta=2"));
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If we are going to support extra separators against the spec, let's just make
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sure they work rationally.
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, NameValuePairsIteratorExtraSeparators) {
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data = " ; ;;alpha=1; ;; ; beta= 2;cappa=3;;; ; ";
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(parser.valid());
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "alpha", "1"));
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "beta", "2"));
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "cappa", "3"));
1058c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1059c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &parser, false, true, std::string(), std::string()));
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See comments on the implementation of NameValuePairsIterator::GetNext
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// regarding this derogation from the spec.
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpUtilTest, NameValuePairsIteratorMissingEndQuote) {
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data = "name='value";
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::NameValuePairsIterator parser(data.begin(), data.end(), ';');
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(parser.valid());
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckNextNameValuePair(&parser, true, true, "name", "value"));
1071c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(
1072c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &parser, false, true, std::string(), std::string()));
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1074