| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/http/http_cookie_indices.h" |
| |
| #include "net/cookies/cookie_util.h" |
| #include "net/http/http_response_headers.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace net { |
| namespace { |
| |
| using cookie_util::ParsedRequestCookies; |
| using ::testing::ElementsAre; |
| using ::testing::Optional; |
| |
| constexpr std::string_view kCookieIndicesHeader = "Cookie-Indices"; |
| |
| TEST(CookieIndicesTest, Absent) { |
| auto headers = |
| HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK").Build(); |
| auto result = ParseCookieIndices(*headers); |
| EXPECT_FALSE(result.has_value()); |
| } |
| |
| TEST(CookieIndicesTest, PresentButEmpty) { |
| auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK") |
| .AddHeader(kCookieIndicesHeader, "") |
| .Build(); |
| auto result = ParseCookieIndices(*headers); |
| EXPECT_THAT(result, Optional(ElementsAre())); |
| } |
| |
| TEST(CookieIndicesTest, OneCookie) { |
| auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK") |
| .AddHeader(kCookieIndicesHeader, R"("alpha")") |
| .Build(); |
| auto result = ParseCookieIndices(*headers); |
| EXPECT_THAT(result, Optional(ElementsAre("alpha"))); |
| } |
| |
| TEST(CookieIndicesTest, SeveralCookies) { |
| auto headers = |
| HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK") |
| .AddHeader(kCookieIndicesHeader, R"("alpha", "bravo")") |
| .AddHeader(kCookieIndicesHeader, R"("charlie", "delta", "echo")") |
| .Build(); |
| auto result = ParseCookieIndices(*headers); |
| EXPECT_THAT(result, Optional(ElementsAre("alpha", "bravo", "charlie", "delta", |
| "echo"))); |
| } |
| |
| TEST(CookieIndicesTest, NonRfc6265Cookie) { |
| auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK") |
| .AddHeader(kCookieIndicesHeader, R"("text/html")") |
| .Build(); |
| auto result = ParseCookieIndices(*headers); |
| EXPECT_THAT(result, Optional(ElementsAre())); |
| } |
| |
| TEST(CookieIndicesTest, NotAList) { |
| auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK") |
| .AddHeader(kCookieIndicesHeader, ",,,") |
| .Build(); |
| auto result = ParseCookieIndices(*headers); |
| EXPECT_FALSE(result.has_value()); |
| } |
| |
| TEST(CookieIndicesTest, InnerList) { |
| auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK") |
| .AddHeader(kCookieIndicesHeader, R"(("foo"))") |
| .Build(); |
| auto result = ParseCookieIndices(*headers); |
| EXPECT_FALSE(result.has_value()); |
| } |
| |
| TEST(CookieIndicesTest, Token) { |
| auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK") |
| .AddHeader(kCookieIndicesHeader, R"(alpha)") |
| .Build(); |
| auto result = ParseCookieIndices(*headers); |
| EXPECT_FALSE(result.has_value()); |
| } |
| |
| TEST(CookieIndicesTest, StringWithUnrecognizedParam) { |
| auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK") |
| .AddHeader(kCookieIndicesHeader, R"("session"; secure)") |
| .Build(); |
| auto result = ParseCookieIndices(*headers); |
| EXPECT_THAT(result, Optional(ElementsAre("session"))); |
| } |
| |
| TEST(CookieIndicesTest, HashIgnoresCookieOrder) { |
| const std::string cookie_indices[] = {"fruit", "vegetable"}; |
| EXPECT_EQ(HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"fruit", "apple"}, |
| {"vegetable", "tomato"}}), |
| HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"vegetable", "tomato"}, |
| {"fruit", "apple"}})); |
| } |
| |
| TEST(CookieIndicesTest, HashCaseSensitive) { |
| const std::string cookie_indices[] = {"fruit", "vegetable"}; |
| EXPECT_NE(HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"fruit", "apple"}, |
| {"vegetable", "tomato"}}), |
| HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"Fruit", "apple"}, |
| {"vegetable", "tomato"}})); |
| EXPECT_NE(HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"fruit", "apple"}, |
| {"vegetable", "tomato"}}), |
| HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"fruit", "Apple"}, |
| {"vegetable", "tomato"}})); |
| } |
| |
| TEST(CookieIndicesTest, HashNotJustConcatenated) { |
| // Any other simple delimiter would also be bad, but this is the most likely |
| // case to result by accident. |
| const std::string cookie_indices[] = {"fruit", "vegetable"}; |
| EXPECT_NE(HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"fruit", "apple"}, |
| {"vegetable", "tomato"}}), |
| HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"fruit", "app"}, |
| {"vegetable", "letomato"}})); |
| } |
| |
| TEST(CookieIndicesTest, HashDisregardsOtherCookies) { |
| const std::string cookie_indices[] = {"fruit"}; |
| EXPECT_EQ(HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"fruit", "apple"}, |
| {"vegetable", "tomato"}}), |
| HashCookieIndices(cookie_indices, |
| ParsedRequestCookies{{"bread", "pumpernickel"}, |
| {"fruit", "apple"}})); |
| } |
| |
| TEST(CookieIndicesTest, HashDistinguishesEmptyAndAbsentCookies) { |
| const std::string cookie_indices[] = {"fruit"}; |
| EXPECT_NE( |
| HashCookieIndices(cookie_indices, ParsedRequestCookies{{"fruit", ""}}), |
| HashCookieIndices(cookie_indices, ParsedRequestCookies{})); |
| } |
| |
| TEST(CookieIndicesTest, IgnoresOrderOfDuplicateCookies) { |
| const std::string cookie_indices[] = {"fruit"}; |
| EXPECT_EQ(HashCookieIndices( |
| cookie_indices, |
| ParsedRequestCookies{{"fruit", "lime"}, {"fruit", "pear"}}), |
| HashCookieIndices( |
| cookie_indices, |
| ParsedRequestCookies{{"fruit", "pear"}, {"fruit", "lime"}})); |
| } |
| |
| } // namespace |
| } // namespace net |