1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_cookie_indices.h"
6
7 #include "net/cookies/cookie_util.h"
8 #include "net/http/http_response_headers.h"
9 #include "testing/gmock/include/gmock/gmock.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace net {
13 namespace {
14
15 using cookie_util::ParsedRequestCookies;
16 using ::testing::ElementsAre;
17 using ::testing::Optional;
18
19 constexpr std::string_view kCookieIndicesHeader = "Cookie-Indices";
20
TEST(CookieIndicesTest,Absent)21 TEST(CookieIndicesTest, Absent) {
22 auto headers =
23 HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK").Build();
24 auto result = ParseCookieIndices(*headers);
25 EXPECT_FALSE(result.has_value());
26 }
27
TEST(CookieIndicesTest,PresentButEmpty)28 TEST(CookieIndicesTest, PresentButEmpty) {
29 auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK")
30 .AddHeader(kCookieIndicesHeader, "")
31 .Build();
32 auto result = ParseCookieIndices(*headers);
33 EXPECT_THAT(result, Optional(ElementsAre()));
34 }
35
TEST(CookieIndicesTest,OneCookie)36 TEST(CookieIndicesTest, OneCookie) {
37 auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK")
38 .AddHeader(kCookieIndicesHeader, R"("alpha")")
39 .Build();
40 auto result = ParseCookieIndices(*headers);
41 EXPECT_THAT(result, Optional(ElementsAre("alpha")));
42 }
43
TEST(CookieIndicesTest,SeveralCookies)44 TEST(CookieIndicesTest, SeveralCookies) {
45 auto headers =
46 HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK")
47 .AddHeader(kCookieIndicesHeader, R"("alpha", "bravo")")
48 .AddHeader(kCookieIndicesHeader, R"("charlie", "delta", "echo")")
49 .Build();
50 auto result = ParseCookieIndices(*headers);
51 EXPECT_THAT(result, Optional(ElementsAre("alpha", "bravo", "charlie", "delta",
52 "echo")));
53 }
54
TEST(CookieIndicesTest,NonRfc6265Cookie)55 TEST(CookieIndicesTest, NonRfc6265Cookie) {
56 auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK")
57 .AddHeader(kCookieIndicesHeader, R"("text/html")")
58 .Build();
59 auto result = ParseCookieIndices(*headers);
60 EXPECT_THAT(result, Optional(ElementsAre()));
61 }
62
TEST(CookieIndicesTest,NotAList)63 TEST(CookieIndicesTest, NotAList) {
64 auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK")
65 .AddHeader(kCookieIndicesHeader, ",,,")
66 .Build();
67 auto result = ParseCookieIndices(*headers);
68 EXPECT_FALSE(result.has_value());
69 }
70
TEST(CookieIndicesTest,InnerList)71 TEST(CookieIndicesTest, InnerList) {
72 auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK")
73 .AddHeader(kCookieIndicesHeader, R"(("foo"))")
74 .Build();
75 auto result = ParseCookieIndices(*headers);
76 EXPECT_FALSE(result.has_value());
77 }
78
TEST(CookieIndicesTest,Token)79 TEST(CookieIndicesTest, Token) {
80 auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK")
81 .AddHeader(kCookieIndicesHeader, R"(alpha)")
82 .Build();
83 auto result = ParseCookieIndices(*headers);
84 EXPECT_FALSE(result.has_value());
85 }
86
TEST(CookieIndicesTest,StringWithUnrecognizedParam)87 TEST(CookieIndicesTest, StringWithUnrecognizedParam) {
88 auto headers = HttpResponseHeaders::Builder(HttpVersion(1, 1), "200 OK")
89 .AddHeader(kCookieIndicesHeader, R"("session"; secure)")
90 .Build();
91 auto result = ParseCookieIndices(*headers);
92 EXPECT_THAT(result, Optional(ElementsAre("session")));
93 }
94
TEST(CookieIndicesTest,HashIgnoresCookieOrder)95 TEST(CookieIndicesTest, HashIgnoresCookieOrder) {
96 const std::string cookie_indices[] = {"fruit", "vegetable"};
97 EXPECT_EQ(HashCookieIndices(cookie_indices,
98 ParsedRequestCookies{{"fruit", "apple"},
99 {"vegetable", "tomato"}}),
100 HashCookieIndices(cookie_indices,
101 ParsedRequestCookies{{"vegetable", "tomato"},
102 {"fruit", "apple"}}));
103 }
104
TEST(CookieIndicesTest,HashCaseSensitive)105 TEST(CookieIndicesTest, HashCaseSensitive) {
106 const std::string cookie_indices[] = {"fruit", "vegetable"};
107 EXPECT_NE(HashCookieIndices(cookie_indices,
108 ParsedRequestCookies{{"fruit", "apple"},
109 {"vegetable", "tomato"}}),
110 HashCookieIndices(cookie_indices,
111 ParsedRequestCookies{{"Fruit", "apple"},
112 {"vegetable", "tomato"}}));
113 EXPECT_NE(HashCookieIndices(cookie_indices,
114 ParsedRequestCookies{{"fruit", "apple"},
115 {"vegetable", "tomato"}}),
116 HashCookieIndices(cookie_indices,
117 ParsedRequestCookies{{"fruit", "Apple"},
118 {"vegetable", "tomato"}}));
119 }
120
TEST(CookieIndicesTest,HashNotJustConcatenated)121 TEST(CookieIndicesTest, HashNotJustConcatenated) {
122 // Any other simple delimiter would also be bad, but this is the most likely
123 // case to result by accident.
124 const std::string cookie_indices[] = {"fruit", "vegetable"};
125 EXPECT_NE(HashCookieIndices(cookie_indices,
126 ParsedRequestCookies{{"fruit", "apple"},
127 {"vegetable", "tomato"}}),
128 HashCookieIndices(cookie_indices,
129 ParsedRequestCookies{{"fruit", "app"},
130 {"vegetable", "letomato"}}));
131 }
132
TEST(CookieIndicesTest,HashDisregardsOtherCookies)133 TEST(CookieIndicesTest, HashDisregardsOtherCookies) {
134 const std::string cookie_indices[] = {"fruit"};
135 EXPECT_EQ(HashCookieIndices(cookie_indices,
136 ParsedRequestCookies{{"fruit", "apple"},
137 {"vegetable", "tomato"}}),
138 HashCookieIndices(cookie_indices,
139 ParsedRequestCookies{{"bread", "pumpernickel"},
140 {"fruit", "apple"}}));
141 }
142
TEST(CookieIndicesTest,HashDistinguishesEmptyAndAbsentCookies)143 TEST(CookieIndicesTest, HashDistinguishesEmptyAndAbsentCookies) {
144 const std::string cookie_indices[] = {"fruit"};
145 EXPECT_NE(
146 HashCookieIndices(cookie_indices, ParsedRequestCookies{{"fruit", ""}}),
147 HashCookieIndices(cookie_indices, ParsedRequestCookies{}));
148 }
149
TEST(CookieIndicesTest,IgnoresOrderOfDuplicateCookies)150 TEST(CookieIndicesTest, IgnoresOrderOfDuplicateCookies) {
151 const std::string cookie_indices[] = {"fruit"};
152 EXPECT_EQ(HashCookieIndices(
153 cookie_indices,
154 ParsedRequestCookies{{"fruit", "lime"}, {"fruit", "pear"}}),
155 HashCookieIndices(
156 cookie_indices,
157 ParsedRequestCookies{{"fruit", "pear"}, {"fruit", "lime"}}));
158 }
159
160 } // namespace
161 } // namespace net
162