xref: /aosp_15_r20/external/cronet/net/http/http_no_vary_search_data_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 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_no_vary_search_data.h"
6 
7 #include <string>
8 #include <string_view>
9 
10 #include "base/containers/flat_map.h"
11 #include "base/containers/flat_set.h"
12 #include "base/memory/scoped_refptr.h"
13 #include "base/strings/string_util.h"
14 #include "base/test/gmock_expected_support.h"
15 #include "base/types/expected.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/http/http_util.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "url/gurl.h"
21 
22 namespace net {
23 
24 namespace {
25 
26 using testing::IsEmpty;
27 using testing::UnorderedElementsAreArray;
28 
TEST(HttpNoVarySearchCreateTest,CreateFromNoVaryParamsNonEmptyVaryOnKeyOrder)29 TEST(HttpNoVarySearchCreateTest, CreateFromNoVaryParamsNonEmptyVaryOnKeyOrder) {
30   const auto no_vary_search =
31       HttpNoVarySearchData::CreateFromNoVaryParams({"a"}, true);
32   EXPECT_THAT(no_vary_search.no_vary_params(),
33               UnorderedElementsAreArray({"a"}));
34   EXPECT_THAT(no_vary_search.vary_params(), IsEmpty());
35   EXPECT_TRUE(no_vary_search.vary_on_key_order());
36   EXPECT_TRUE(no_vary_search.vary_by_default());
37 }
38 
TEST(HttpNoVarySearchCreateTest,CreateFromNoVaryParamsNonEmptyNoVaryOnKeyOrder)39 TEST(HttpNoVarySearchCreateTest,
40      CreateFromNoVaryParamsNonEmptyNoVaryOnKeyOrder) {
41   const auto no_vary_search =
42       HttpNoVarySearchData::CreateFromNoVaryParams({"a"}, false);
43   EXPECT_THAT(no_vary_search.no_vary_params(),
44               UnorderedElementsAreArray({"a"}));
45   EXPECT_THAT(no_vary_search.vary_params(), IsEmpty());
46   EXPECT_FALSE(no_vary_search.vary_on_key_order());
47   EXPECT_TRUE(no_vary_search.vary_by_default());
48 }
49 
TEST(HttpNoVarySearchCreateTest,CreateFromNoVaryParamsEmptyNoVaryOnKeyOrder)50 TEST(HttpNoVarySearchCreateTest, CreateFromNoVaryParamsEmptyNoVaryOnKeyOrder) {
51   const auto no_vary_search =
52       HttpNoVarySearchData::CreateFromNoVaryParams({}, false);
53   EXPECT_THAT(no_vary_search.no_vary_params(), IsEmpty());
54   EXPECT_THAT(no_vary_search.vary_params(), IsEmpty());
55   EXPECT_FALSE(no_vary_search.vary_on_key_order());
56   EXPECT_TRUE(no_vary_search.vary_by_default());
57 }
58 
TEST(HttpNoVarySearchCreateTest,CreateFromNoVaryParamsEmptyVaryOnKeyOrder)59 TEST(HttpNoVarySearchCreateTest, CreateFromNoVaryParamsEmptyVaryOnKeyOrder) {
60   const auto no_vary_search =
61       HttpNoVarySearchData::CreateFromNoVaryParams({}, true);
62   EXPECT_THAT(no_vary_search.no_vary_params(), IsEmpty());
63   EXPECT_THAT(no_vary_search.vary_params(), IsEmpty());
64   EXPECT_TRUE(no_vary_search.vary_on_key_order());
65   EXPECT_TRUE(no_vary_search.vary_by_default());
66 }
67 
TEST(HttpNoVarySearchCreateTest,CreateFromVaryParamsNonEmptyVaryOnKeyOrder)68 TEST(HttpNoVarySearchCreateTest, CreateFromVaryParamsNonEmptyVaryOnKeyOrder) {
69   const auto no_vary_search =
70       HttpNoVarySearchData::CreateFromVaryParams({"a"}, true);
71   EXPECT_THAT(no_vary_search.no_vary_params(), IsEmpty());
72   EXPECT_THAT(no_vary_search.vary_params(), UnorderedElementsAreArray({"a"}));
73   EXPECT_TRUE(no_vary_search.vary_on_key_order());
74   EXPECT_FALSE(no_vary_search.vary_by_default());
75 }
76 
TEST(HttpNoVarySearchCreateTest,CreateFromVaryParamsNonEmptyNoVaryOnKeyOrder)77 TEST(HttpNoVarySearchCreateTest, CreateFromVaryParamsNonEmptyNoVaryOnKeyOrder) {
78   const auto no_vary_search =
79       HttpNoVarySearchData::CreateFromVaryParams({"a"}, false);
80   EXPECT_THAT(no_vary_search.no_vary_params(), IsEmpty());
81   EXPECT_THAT(no_vary_search.vary_params(), UnorderedElementsAreArray({"a"}));
82   EXPECT_FALSE(no_vary_search.vary_on_key_order());
83   EXPECT_FALSE(no_vary_search.vary_by_default());
84 }
85 
TEST(HttpNoVarySearchCreateTest,CreateFromVaryParamsEmptyNoVaryOnKeyOrder)86 TEST(HttpNoVarySearchCreateTest, CreateFromVaryParamsEmptyNoVaryOnKeyOrder) {
87   const auto no_vary_search =
88       HttpNoVarySearchData::CreateFromVaryParams({}, false);
89   EXPECT_THAT(no_vary_search.no_vary_params(), IsEmpty());
90   EXPECT_THAT(no_vary_search.vary_params(), IsEmpty());
91   EXPECT_FALSE(no_vary_search.vary_on_key_order());
92   EXPECT_FALSE(no_vary_search.vary_by_default());
93 }
94 
TEST(HttpNoVarySearchCreateTest,CreateFromVaryParamsEmptyVaryOnKeyOrder)95 TEST(HttpNoVarySearchCreateTest, CreateFromVaryParamsEmptyVaryOnKeyOrder) {
96   const auto no_vary_search =
97       HttpNoVarySearchData::CreateFromVaryParams({}, true);
98   EXPECT_THAT(no_vary_search.no_vary_params(), IsEmpty());
99   EXPECT_THAT(no_vary_search.vary_params(), IsEmpty());
100   EXPECT_TRUE(no_vary_search.vary_on_key_order());
101   EXPECT_FALSE(no_vary_search.vary_by_default());
102 }
103 
104 struct TestData {
105   const char* raw_headers;
106   const base::flat_set<std::string> expected_no_vary_params;
107   const base::flat_set<std::string> expected_vary_params;
108   const bool expected_vary_on_key_order;
109   const bool expected_vary_by_default;
110 };
111 
112 class HttpNoVarySearchResponseHeadersTest
113     : public ::testing::Test,
114       public ::testing::WithParamInterface<TestData> {};
115 
TEST_P(HttpNoVarySearchResponseHeadersTest,ParsingSuccess)116 TEST_P(HttpNoVarySearchResponseHeadersTest, ParsingSuccess) {
117   const TestData test = GetParam();
118 
119   const std::string raw_headers =
120       net::HttpUtil::AssembleRawHeaders(test.raw_headers);
121 
122   const auto parsed = base::MakeRefCounted<HttpResponseHeaders>(raw_headers);
123   ASSERT_OK_AND_ASSIGN(const auto no_vary_search_data,
124                        HttpNoVarySearchData::ParseFromHeaders(*parsed));
125 
126   EXPECT_EQ(no_vary_search_data.vary_on_key_order(),
127             test.expected_vary_on_key_order);
128   EXPECT_EQ(no_vary_search_data.vary_by_default(),
129             test.expected_vary_by_default);
130 
131   EXPECT_EQ(no_vary_search_data.no_vary_params(), test.expected_no_vary_params);
132   EXPECT_EQ(no_vary_search_data.vary_params(), test.expected_vary_params);
133 }
134 
135 struct FailureData {
136   const char* raw_headers;
137   const HttpNoVarySearchData::ParseErrorEnum expected_error;
138 };
139 
140 class HttpNoVarySearchResponseHeadersParseFailureTest
141     : public ::testing::Test,
142       public ::testing::WithParamInterface<FailureData> {};
143 
TEST_P(HttpNoVarySearchResponseHeadersParseFailureTest,ParsingFailureOrDefaultValue)144 TEST_P(HttpNoVarySearchResponseHeadersParseFailureTest,
145        ParsingFailureOrDefaultValue) {
146   const std::string raw_headers =
147       net::HttpUtil::AssembleRawHeaders(GetParam().raw_headers);
148 
149   const auto parsed = base::MakeRefCounted<HttpResponseHeaders>(raw_headers);
150   const auto no_vary_search_data =
151       HttpNoVarySearchData::ParseFromHeaders(*parsed);
152 
153   EXPECT_THAT(no_vary_search_data,
154               base::test::ErrorIs(GetParam().expected_error))
155       << "Headers = " << GetParam().raw_headers;
156 }
157 
158 FailureData response_header_failed[] = {
159     {// No No-Vary-Search Header case
160      "HTTP/1.1 200 OK\r\n"
161      "Set-Cookie: a\r\n"
162      "Set-Cookie: b\r\n\r\n",
163      HttpNoVarySearchData::ParseErrorEnum::kOk},
164 
165     {// No-Vary-Search Header doesn't parse as a dictionary.
166      "HTTP/1.1 200 OK\r\n"
167      R"(No-Vary-Search: "a")"
168      "\r\n\r\n",
169      HttpNoVarySearchData::ParseErrorEnum::kNotDictionary},
170 
171     {// No-Vary-Search Header doesn't parse as a dictionary.
172      "HTTP/1.1 200 OK\r\n"
173      "No-Vary-Search: (a)\r\n\r\n",
174      HttpNoVarySearchData::ParseErrorEnum::kNotDictionary},
175 
176     {// When except is specified, params cannot be a list of strings.
177      "HTTP/1.1 200 OK\r\n"
178      R"(No-Vary-Search: params=("b"),except=("a"))"
179      "\r\n\r\n",
180      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
181 
182     {// An unknown dictionary key should behave as if the header was not
183      // specified.
184      "HTTP/1.1 200 OK\r\n"
185      "No-Vary-Search: unknown-key\r\n\r\n",
186      HttpNoVarySearchData::ParseErrorEnum::kUnknownDictionaryKey},
187 
188     {// params not a boolean or a list of strings.
189      "HTTP/1.1 200 OK\r\n"
190      R"(No-Vary-Search: params="a")"
191      "\r\n\r\n",
192      HttpNoVarySearchData::ParseErrorEnum::kParamsNotStringList},
193 
194     {// params not a boolean or a list of strings.
195      "HTTP/1.1 200 OK\r\n"
196      "No-Vary-Search: params=a\r\n\r\n",
197      HttpNoVarySearchData::ParseErrorEnum::kParamsNotStringList},
198 
199     {// params as an empty list of strings should behave as if the header was
200      // not specified.
201      "HTTP/1.1 200 OK\r\n"
202      "No-Vary-Search: params=()\r\n\r\n",
203      HttpNoVarySearchData::ParseErrorEnum::kDefaultValue},
204 
205     {// params not a boolean or a list of strings.
206      "HTTP/1.1 200 OK\r\n"
207      R"(No-Vary-Search: params=("a" b))"
208      "\r\n\r\n",
209      HttpNoVarySearchData::ParseErrorEnum::kParamsNotStringList},
210 
211     {// params defaulting to ?0 which is the same as no header.
212      "HTTP/1.1 200 OK\r\n"
213      R"(No-Vary-Search: params=("a"))"
214      "\r\n"
215      "No-Vary-Search: params=?0\r\n\r\n",
216      HttpNoVarySearchData::ParseErrorEnum::kDefaultValue},
217 
218     {// except without params.
219      "HTTP/1.1 200 OK\r\n"
220      "No-Vary-Search: except=()\r\n\r\n",
221      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
222 
223     {// except without params.
224      "HTTP/1.1 200 OK\r\n"
225      "No-Vary-Search: except=()\r\n"
226      R"(No-Vary-Search: except=("a"))"
227      "\r\n\r\n",
228      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
229 
230     {// except without params.
231      "HTTP/1.1 200 OK\r\n"
232      R"(No-Vary-Search: except=("a" "b"))"
233      "\r\n\r\n",
234      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
235 
236     {// except with params set to a list of strings is incorrect.
237      "HTTP/1.1 200 OK\r\n"
238      R"(No-Vary-Search: params=("a"))"
239      "\r\n"
240      "No-Vary-Search: except=()\r\n\r\n",
241      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
242 
243     {// except with params set to a list of strings is incorrect.
244      "HTTP/1.1 200 OK\r\n"
245      "No-Vary-Search: params=(),except=()\r\n\r\n",
246      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
247 
248     {// except with params set to a list of strings is incorrect.
249      "HTTP/1.1 200 OK\r\n"
250      R"(No-Vary-Search: params,except=(),params=())"
251      "\r\n\r\n",
252      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
253 
254     {// except with params set to a list of strings is incorrect.
255      "HTTP/1.1 200 OK\r\n"
256      R"(No-Vary-Search: except=("a" "b"))"
257      "\r\n"
258      R"(No-Vary-Search: params=("a"))"
259      "\r\n\r\n",
260      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
261 
262     {// except with params set to a list of strings is incorrect.
263      "HTTP/1.1 200 OK\r\n"
264      R"(No-Vary-Search: params=("a"),except=("b"))"
265      "\r\n"
266      "No-Vary-Search: except=()\r\n\r\n",
267      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
268 
269     {// except with params set to false is incorrect.
270      "HTTP/1.1 200 OK\r\n"
271      R"(No-Vary-Search: params=?0,except=("a"))"
272      "\r\n\r\n",
273      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
274 
275     {// except with params set to a list of strings is incorrect.
276      "HTTP/1.1 200 OK\r\n"
277      R"(No-Vary-Search: params,except=("a" "b"))"
278      "\r\n"
279      R"(No-Vary-Search: params=("a"))"
280      "\r\n\r\n",
281      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
282 
283     {// key-order not a boolean
284      "HTTP/1.1 200 OK\r\n"
285      R"(No-Vary-Search: key-order="a")"
286      "\r\n\r\n",
287      HttpNoVarySearchData::ParseErrorEnum::kNonBooleanKeyOrder},
288 
289     {// key-order not a boolean
290      "HTTP/1.1 200 OK\r\n"
291      "No-Vary-Search: key-order=a\r\n\r\n",
292      HttpNoVarySearchData::ParseErrorEnum::kNonBooleanKeyOrder},
293 
294     {// key-order not a boolean
295      "HTTP/1.1 200 OK\r\n"
296      "No-Vary-Search: key-order=()\r\n\r\n",
297      HttpNoVarySearchData::ParseErrorEnum::kNonBooleanKeyOrder},
298 
299     {// key-order not a boolean
300      "HTTP/1.1 200 OK\r\n"
301      "No-Vary-Search: key-order=(a)\r\n\r\n",
302      HttpNoVarySearchData::ParseErrorEnum::kNonBooleanKeyOrder},
303 
304     {// key-order not a boolean
305      "HTTP/1.1 200 OK\r\n"
306      R"(No-Vary-Search: key-order=("a"))"
307      "\r\n\r\n",
308      HttpNoVarySearchData::ParseErrorEnum::kNonBooleanKeyOrder},
309 
310     {// key-order not a boolean
311      "HTTP/1.1 200 OK\r\n"
312      "No-Vary-Search: key-order=(?1)\r\n\r\n",
313      HttpNoVarySearchData::ParseErrorEnum::kNonBooleanKeyOrder},
314 
315     {// key-order set to false should behave as if the
316      // header was not specified at all
317      "HTTP/1.1 200 OK\r\n"
318      "No-Vary-Search: key-order=?0\r\n\r\n",
319      HttpNoVarySearchData::ParseErrorEnum::kDefaultValue},
320 
321     {// params set to false should behave as if the
322      // header was not specified at all
323      "HTTP/1.1 200 OK\r\n"
324      "No-Vary-Search: params=?0\r\n\r\n",
325      HttpNoVarySearchData::ParseErrorEnum::kDefaultValue},
326 
327     {// params set to false should behave as if the
328      // header was not specified at all. except set to
329      // a list of tokens is incorrect.
330      "HTTP/1.1 200 OK\r\n"
331      "No-Vary-Search: params=?0\r\n"
332      "No-Vary-Search: except=(a)\r\n\r\n",
333      HttpNoVarySearchData::ParseErrorEnum::kExceptWithoutTrueParams},
334 
335     {// except set to a list of tokens is incorrect.
336      "HTTP/1.1 200 OK\r\n"
337      "No-Vary-Search: params=?1\r\n"
338      "No-Vary-Search: except=(a)\r\n\r\n",
339      HttpNoVarySearchData::ParseErrorEnum::kExceptNotStringList},
340 
341     {// except set to true
342      "HTTP/1.1 200 OK\r\n"
343      "No-Vary-Search: params=?1\r\n"
344      "No-Vary-Search: except\r\n\r\n",
345      HttpNoVarySearchData::ParseErrorEnum::kExceptNotStringList},
346 
347     {// Fail parsing if an unknown key is in the dictionary.
348      "HTTP/1.1 200 OK\r\n"
349      "No-Vary-Search: params,except=(a)\r\n"
350      "No-Vary-Search: unknown-key\r\n"
351      R"(No-Vary-Search: except=("a"))"
352      "\r\n\r\n",
353      HttpNoVarySearchData::ParseErrorEnum::kUnknownDictionaryKey},
354 };
355 
356 const TestData response_headers_tests[] = {
357     // params set to a list of strings with one element.
358     {
359         "HTTP/1.1 200 OK\r\n"
360         R"(No-Vary-Search: params=("a"))"
361         "\r\n\r\n",  // raw_headers
362         {"a"},       // expected_no_vary_params
363         {},          // expected_vary_params
364         true,        // expected_vary_on_key_order
365         true,        // expected_vary_by_default
366     },
367     // params set to a list of strings with one non-ASCII character.
368     {
369         "HTTP/1.1 200 OK\r\n"
370         R"(No-Vary-Search: params=("%C2%A2"))"
371         "\r\n\r\n",  // raw_headers
372         {"¢"},       // expected_no_vary_params
373         {},          // expected_vary_params
374         true,        // expected_vary_on_key_order
375         true,        // expected_vary_by_default
376     },
377     // params set to a list of strings with one ASCII and one non-ASCII
378     // character.
379     {
380         "HTTP/1.1 200 OK\r\n"
381         R"(No-Vary-Search: params=("c%C2%A2"))"
382         "\r\n\r\n",  // raw_headers
383         {"c¢"},      // expected_no_vary_params
384         {},          // expected_vary_params
385         true,        // expected_vary_on_key_order
386         true,        // expected_vary_by_default
387     },
388     // params set to a list of strings with one space and one non-ASCII
389     // character.
390     {
391         "HTTP/1.1 200 OK\r\n"
392         R"(No-Vary-Search: params=("+%C2%A2"))"
393         "\r\n\r\n",  // raw_headers
394         {" ¢"},      // expected_no_vary_params
395         {},          // expected_vary_params
396         true,        // expected_vary_on_key_order
397         true,        // expected_vary_by_default
398     },
399     // params set to true.
400     {
401         "HTTP/1.1 200 OK\r\n"
402         "No-Vary-Search: params\r\n\r\n",  // raw_headers
403         {},                                // expected_no_vary_params
404         {},                                // expected_vary_params
405         true,                              // expected_vary_on_key_order
406         false,                             // expected_vary_by_default
407     },
408     // params set to true.
409     {
410         "HTTP/1.1 200 OK\r\n"
411         "No-Vary-Search: params=?1\r\n\r\n",  // raw_headers
412         {},                                   // expected_no_vary_params
413         {},                                   // expected_vary_params
414         true,                                 // expected_vary_on_key_order
415         false,                                // expected_vary_by_default
416     },
417     // params overridden by a list of strings.
418     {
419         "HTTP/1.1 200 OK\r\n"
420         R"(No-Vary-Search: params=("a" b))"
421         "\r\n"
422         R"(No-Vary-Search: params=("c"))"
423         "\r\n\r\n",  // raw_headers
424         {"c"},       // expected_no_vary_params
425         {},          // expected_vary_params
426         true,        // expected_vary_on_key_order
427         true,        // expected_vary_by_default
428     },
429     // Vary on all with one excepted search param.
430     {
431         "HTTP/1.1 200 OK\r\n"
432         "No-Vary-Search: params\r\n"
433         "No-Vary-Search: except=()\r\n\r\n",  // raw_headers
434         {},                                   // expected_no_vary_params
435         {},                                   // expected_vary_params
436         true,                                 // expected_vary_on_key_order
437         false,                                // expected_vary_by_default
438     },
439     // Vary on all with one excepted search param.
440     {
441         "HTTP/1.1 200 OK\r\n"
442         "No-Vary-Search: params\r\n"
443         R"(No-Vary-Search: except=("a"))"
444         "\r\n\r\n",  // raw_headers
445         {},          // expected_no_vary_params
446         {"a"},       // expected_vary_params
447         true,        // expected_vary_on_key_order
448         false,       // expected_vary_by_default
449     },
450     // Vary on all with one excepted non-ASCII search param.
451     {
452         "HTTP/1.1 200 OK\r\n"
453         "No-Vary-Search: params\r\n"
454         R"(No-Vary-Search: except=("%C2%A2"))"
455         "\r\n\r\n",  // raw_headers
456         {},          // expected_no_vary_params
457         {"¢"},       // expected_vary_params
458         true,        // expected_vary_on_key_order
459         false,       // expected_vary_by_default
460     },
461     // Vary on all with one excepted search param that includes non-ASCII
462     // character.
463     {
464         "HTTP/1.1 200 OK\r\n"
465         "No-Vary-Search: params\r\n"
466         R"(No-Vary-Search: except=("c+%C2%A2"))"
467         "\r\n\r\n",  // raw_headers
468         {},          // expected_no_vary_params
469         {"c ¢"},     // expected_vary_params
470         true,        // expected_vary_on_key_order
471         false,       // expected_vary_by_default
472     },
473     // Vary on all with one excepted search param. Set params as
474     // part of the same header line.
475     {
476         "HTTP/1.1 200 OK\r\n"
477         R"(No-Vary-Search: params,except=("a"))"
478         "\r\n\r\n",  // raw_headers
479         {},          // expected_no_vary_params
480         {"a"},       // expected_vary_params
481         true,        // expected_vary_on_key_order
482         false,       // expected_vary_by_default
483     },
484     // Vary on all with one excepted search param. Override except
485     // on different header line.
486     {
487         "HTTP/1.1 200 OK\r\n"
488         R"(No-Vary-Search: params,except=("a" b))"
489         "\r\n"
490         R"(No-Vary-Search: except=("c"))"
491         "\r\n\r\n",  // raw_headers
492         {},          // expected_no_vary_params
493         {"c"},       // expected_vary_params
494         true,        // expected_vary_on_key_order
495         false,       // expected_vary_by_default
496     },
497     // Vary on all with more than one excepted search param.
498     {
499         "HTTP/1.1 200 OK\r\n"
500         "No-Vary-Search: params\r\n"
501         R"(No-Vary-Search: except=("a" "b"))"
502         "\r\n\r\n",  // raw_headers
503         {},          // expected_no_vary_params
504         {"a", "b"},  // expected_vary_params
505         true,        // expected_vary_on_key_order
506         false,       // expected_vary_by_default
507     },
508     // Vary on all with more than one excepted search param. params appears
509     // after except in header definition.
510     {
511         "HTTP/1.1 200 OK\r\n"
512         R"(No-Vary-Search: except=("a" "b"))"
513         "\r\n"
514         "No-Vary-Search: params\r\n\r\n",  // raw_headers
515         {},                                // expected_no_vary_params
516         {"a", "b"},                        // expected_vary_params
517         true,                              // expected_vary_on_key_order
518         false,                             // expected_vary_by_default
519     },
520     // Vary on all with more than one excepted search param. Set params as
521     // part of the same header line.
522     {
523         "HTTP/1.1 200 OK\r\n"
524         R"(No-Vary-Search: params,except=("a" "b"))"
525         "\r\n\r\n",  // raw_headers
526         {},          // expected_no_vary_params
527         {"a", "b"},  // expected_vary_params
528         true,        // expected_vary_on_key_order
529         false,       // expected_vary_by_default
530     },
531     // Don't vary on two search params.
532     {
533         "HTTP/1.1 200 OK\r\n"
534         R"(No-Vary-Search: params=("a" "b"))"
535         "\r\n\r\n",  // raw_headers
536         {"a", "b"},  // expected_no_vary_params
537         {},          // expected_vary_params
538         true,        // expected_vary_on_key_order
539         true,        // expected_vary_by_default
540     },
541     // Don't vary on search params order.
542     {
543         "HTTP/1.1 200 OK\r\n"
544         "No-Vary-Search: key-order\r\n\r\n",  // raw_headers
545         {},                                   // expected_no_vary_params
546         {},                                   // expected_vary_params
547         false,                                // expected_vary_on_key_order
548         true,                                 // expected_vary_by_default
549     },
550     // Don't vary on search params order.
551     {
552         "HTTP/1.1 200 OK\r\n"
553         "No-Vary-Search: key-order=?1\r\n\r\n",  // raw_headers
554         {},                                      // expected_no_vary_params
555         {},                                      // expected_vary_params
556         false,                                   // expected_vary_on_key_order
557         true,                                    // expected_vary_by_default
558     },
559     // Don't vary on search params order and on two specific search params.
560     {
561         "HTTP/1.1 200 OK\r\n"
562         R"(No-Vary-Search: params=("a" "b"))"
563         "\r\n"
564         "No-Vary-Search: key-order\r\n\r\n",  // raw_headers
565         {"a", "b"},                           // expected_no_vary_params
566         {},                                   // expected_vary_params
567         false,                                // expected_vary_on_key_order
568         true,                                 // expected_vary_by_default
569     },
570     // Don't vary on search params order and on two specific search params.
571     {
572         "HTTP/1.1 200 OK\r\n"
573         R"(No-Vary-Search: params=("a" "b"))"
574         "\r\n"
575         "No-Vary-Search: key-order=?1\r\n\r\n",  // raw_headers
576         {"a", "b"},                              // expected_no_vary_params
577         {},                                      // expected_vary_params
578         false,                                   // expected_vary_on_key_order
579         true,                                    // expected_vary_by_default
580     },
581     // Vary on search params order and do not vary on two specific search
582     // params.
583     {
584         "HTTP/1.1 200 OK\r\n"
585         R"(No-Vary-Search: params=("a" "b"))"
586         "\r\n"
587         "No-Vary-Search: key-order=?0\r\n\r\n",  // raw_headers
588         {"a", "b"},                              // expected_no_vary_params
589         {},                                      // expected_vary_params
590         true,                                    // expected_vary_on_key_order
591         true,                                    // expected_vary_by_default
592     },
593     // Vary on all search params except one, and do not vary on search params
594     // order.
595     {
596         "HTTP/1.1 200 OK\r\n"
597         "No-Vary-Search: params\r\n"
598         R"(No-Vary-Search: except=("a"))"
599         "\r\n"
600         "No-Vary-Search: key-order\r\n\r\n",  // raw_headers
601         {},                                   // expected_no_vary_params
602         {"a"},                                // expected_vary_params
603         false,                                // expected_vary_on_key_order
604         false,                                // expected_vary_by_default
605     },
606     // Vary on all search params except one, and do not vary on search params
607     // order.
608     {
609         "HTTP/1.1 200 OK\r\n"
610         "No-Vary-Search: params=?1\r\n"
611         R"(No-Vary-Search: except=("a"))"
612         "\r\n"
613         "No-Vary-Search: key-order\r\n\r\n",  // raw_headers
614         {},                                   // expected_no_vary_params
615         {"a"},                                // expected_vary_params
616         false,                                // expected_vary_on_key_order
617         false,                                // expected_vary_by_default
618     },
619     // Vary on all search params except one, and do not vary on search params
620     // order.
621     {
622         "HTTP/1.1 200 OK\r\n"
623         "No-Vary-Search: params\r\n"
624         R"(No-Vary-Search: except=("a"))"
625         "\r\n"
626         "No-Vary-Search: key-order=?1\r\n\r\n",  // raw_headers
627         {},                                      // expected_no_vary_params
628         {"a"},                                   // expected_vary_params
629         false,                                   // expected_vary_on_key_order
630         false,                                   // expected_vary_by_default
631     },
632     // Vary on all search params except one, and vary on search params order.
633     {
634         "HTTP/1.1 200 OK\r\n"
635         "No-Vary-Search: params=?1\r\n"
636         R"(No-Vary-Search: except=("a"))"
637         "\r\n"
638         "No-Vary-Search: key-order=?0\r\n\r\n",  // raw_headers
639         {},                                      // expected_no_vary_params
640         {"a"},                                   // expected_vary_params
641         true,                                    // expected_vary_on_key_order
642         false,                                   // expected_vary_by_default
643     },
644     // Vary on all search params except two, and do not vary on search params
645     // order.
646     {
647         "HTTP/1.1 200 OK\r\n"
648         "No-Vary-Search: params\r\n"
649         R"(No-Vary-Search: except=("a" "b"))"
650         "\r\n"
651         "No-Vary-Search: key-order\r\n\r\n",  // raw_headers
652         {},                                   // expected_no_vary_params
653         {"a", "b"},                           // expected_vary_params
654         false,                                // expected_vary_on_key_order
655         false,                                // expected_vary_by_default
656     },
657     // Do not vary on one search params. Override params on a different header
658     // line.
659     {
660         "HTTP/1.1 200 OK\r\n"
661         R"(No-Vary-Search: params=("a"))"
662         "\r\n"
663         R"(No-Vary-Search: params=("b"))"
664         "\r\n\r\n",  // raw_headers
665         {"b"},       // expected_no_vary_params
666         {},          // expected_vary_params
667         true,        // expected_vary_on_key_order
668         true,        // expected_vary_by_default
669     },
670     // Do not vary on any search params. Override params on a different header
671     // line.
672     {
673         "HTTP/1.1 200 OK\r\n"
674         R"(No-Vary-Search: params=("a"))"
675         "\r\n"
676         "No-Vary-Search: params\r\n\r\n",  // raw_headers
677         {},                                // expected_no_vary_params
678         {},                                // expected_vary_params
679         true,                              // expected_vary_on_key_order
680         false,                             // expected_vary_by_default
681     },
682     // Do not vary on any search params except one. Override except on a
683     // different header line.
684     {
685         "HTTP/1.1 200 OK\r\n"
686         "No-Vary-Search: params\r\n"
687         R"(No-Vary-Search: except=("a"))"
688         "\r\n"
689         R"(No-Vary-Search: except=("b"))"
690         "\r\n\r\n",  // raw_headers
691         {},          // expected_no_vary_params
692         {"b"},       // expected_vary_params
693         true,        // expected_vary_on_key_order
694         false,       // expected_vary_by_default
695     },
696     // Allow extension via parameters.
697     {
698         "HTTP/1.1 200 OK\r\n"
699         "No-Vary-Search: params;unknown\r\n\r\n",  // raw_headers
700         {},                                        // expected_no_vary_params
701         {},                                        // expected_vary_params
702         true,                                      // expected_vary_on_key_order
703         false,                                     // expected_vary_by_default
704     },
705     // Allow extension via parameters.
706     {
707         "HTTP/1.1 200 OK\r\n"
708         R"(No-Vary-Search: params=("a");unknown)"
709         "\r\n\r\n",  // raw_headers
710         {"a"},       // expected_no_vary_params
711         {},          // expected_vary_params
712         true,        // expected_vary_on_key_order
713         true,        // expected_vary_by_default
714     },
715     // Allow extension via parameters.
716     {
717         "HTTP/1.1 200 OK\r\n"
718         R"(No-Vary-Search: params;unknown,except=("a");unknown)"
719         "\r\n\r\n",  // raw_headers
720         {},          // expected_no_vary_params
721         {"a"},       // expected_vary_params
722         true,        // expected_vary_on_key_order
723         false,       // expected_vary_by_default
724     },
725     // Allow extension via parameters.
726     {
727         "HTTP/1.1 200 OK\r\n"
728         "No-Vary-Search: key-order;unknown\r\n\r\n",  // raw_headers
729         {},                                           // expected_no_vary_params
730         {},                                           // expected_vary_params
731         false,  // expected_vary_on_key_order
732         true,   // expected_vary_by_default
733     },
734     // Allow extension via parameters.
735     {
736         "HTTP/1.1 200 OK\r\n"
737         R"(No-Vary-Search: params=("a";unknown))"
738         "\r\n\r\n",  // raw_headers
739         {"a"},       // expected_no_vary_params
740         {},          // expected_vary_params
741         true,        // expected_vary_on_key_order
742         true,        // expected_vary_by_default
743     },
744     // Allow extension via parameters.
745     {
746         "HTTP/1.1 200 OK\r\n"
747         "No-Vary-Search: params\r\n"
748         R"(No-Vary-Search: except=("a";unknown))"
749         "\r\n\r\n",  // raw_headers
750         {},          // expected_no_vary_params
751         {"a"},       // expected_vary_params
752         true,        // expected_vary_on_key_order
753         false,       // expected_vary_by_default
754     },
755     // Vary on all search params except one. Override except on a different
756     // header line.
757     {
758         "HTTP/1.1 200 OK\r\n"
759         "No-Vary-Search: params,except=(a)\r\n"
760         R"(No-Vary-Search: except=("a"))"
761         "\r\n\r\n",  // raw_headers
762         {},          // expected_no_vary_params
763         {"a"},       // expected_vary_params
764         true,        // expected_vary_on_key_order
765         false,       // expected_vary_by_default
766     }};
767 
768 INSTANTIATE_TEST_SUITE_P(HttpNoVarySearchResponseHeadersTest,
769                          HttpNoVarySearchResponseHeadersTest,
770                          testing::ValuesIn(response_headers_tests));
771 
772 INSTANTIATE_TEST_SUITE_P(HttpNoVarySearchResponseHeadersParseFailureTest,
773                          HttpNoVarySearchResponseHeadersParseFailureTest,
774                          testing::ValuesIn(response_header_failed));
775 
776 struct NoVarySearchCompareTestData {
777   const GURL request_url;
778   const GURL cached_url;
779   const std::string_view raw_headers;
780   const bool expected_match;
781 };
782 
TEST(HttpNoVarySearchCompare,CheckUrlEqualityWithSpecialCharacters)783 TEST(HttpNoVarySearchCompare, CheckUrlEqualityWithSpecialCharacters) {
784   // Use special characters in both `keys` and `values`.
785   const base::flat_map<std::string, std::string> percent_encoding = {
786       {"!", "%21"},    {"#", "%23"},    {"$", "%24"},    {"%", "%25"},
787       {"&", "%26"},    {"'", "%27"},    {"(", "%28"},    {")", "%29"},
788       {"*", R"(%2A)"}, {"+", R"(%2B)"}, {",", R"(%2C)"}, {"-", R"(%2D)"},
789       {".", R"(%2E)"}, {"/", R"(%2F)"}, {":", R"(%3A)"}, {";", "%3B"},
790       {"<", R"(%3C)"}, {"=", R"(%3D)"}, {">", R"(%3E)"}, {"?", R"(%3F)"},
791       {"@", "%40"},    {"[", "%5B"},    {"]", R"(%5D)"}, {"^", R"(%5E)"},
792       {"_", R"(%5F)"}, {"`", "%60"},    {"{", "%7B"},    {"|", R"(%7C)"},
793       {"}", R"(%7D)"}, {"~", R"(%7E)"}, {"", ""}};
794   const std::string_view raw_headers =
795       "HTTP/1.1 200 OK\r\n"
796       R"(No-Vary-Search: params=("c"))"
797       "\r\n\r\n";
798   const std::string headers = net::HttpUtil::AssembleRawHeaders(raw_headers);
799   const auto parsed = base::MakeRefCounted<HttpResponseHeaders>(headers);
800 
801   const auto no_vary_search_data =
802       HttpNoVarySearchData::ParseFromHeaders(*parsed).value();
803 
804   for (const auto& [key, value] : percent_encoding) {
805     std::string request_url_template =
806         R"(https://a.test/index.html?$key=$value)";
807     std::string cached_url_template =
808         R"(https://a.test/index.html?c=3&$key=$value)";
809 
810     base::ReplaceSubstringsAfterOffset(&request_url_template, 0, "$key", value);
811     base::ReplaceSubstringsAfterOffset(&request_url_template, 0, "$value",
812                                        value);
813     base::ReplaceSubstringsAfterOffset(&cached_url_template, 0, "$key", value);
814     base::ReplaceSubstringsAfterOffset(&cached_url_template, 0, "$value",
815                                        value);
816 
817     EXPECT_TRUE(no_vary_search_data.AreEquivalent(GURL(request_url_template),
818                                                   GURL(cached_url_template)));
819 
820     std::string header_template =
821         "HTTP/1.1 200 OK\r\n"
822         R"(No-Vary-Search: params, except=("$key"))"
823         "\r\n\r\n";
824     base::ReplaceSubstringsAfterOffset(&header_template, 0, "$key", key);
825 
826     const auto parsed_header = base::MakeRefCounted<HttpResponseHeaders>(
827         net::HttpUtil::AssembleRawHeaders(header_template));
828     const auto no_vary_search_data_special_char =
829         HttpNoVarySearchData::ParseFromHeaders(*parsed_header).value();
830 
831     EXPECT_TRUE(no_vary_search_data_special_char.AreEquivalent(
832         GURL(request_url_template), GURL(cached_url_template)));
833   }
834 }
835 
836 constexpr std::pair<std::string_view, std::string_view>
837     kPercentEncodedNonAsciiKeys[] = {
838         {"¢", R"(%C2%A2)"},
839         {"¢ ¢", R"(%C2%A2+%C2%A2)"},
840         {"é 気", R"(%C3%A9+%E6%B0%97)"},
841         {"é", R"(%C3%A9)"},
842         {"気", R"(%E6%B0%97)"},
843         {"ぁ", R"(%E3%81%81)"},
844         {"��", R"(%F0%90%A8%80)"},
845 };
846 
TEST(HttpNoVarySearchCompare,CheckUrlEqualityWithPercentEncodedNonASCIICharactersExcept)847 TEST(HttpNoVarySearchCompare,
848      CheckUrlEqualityWithPercentEncodedNonASCIICharactersExcept) {
849   for (const auto& [key, value] : kPercentEncodedNonAsciiKeys) {
850     std::string request_url_template = R"(https://a.test/index.html?$key=c)";
851     std::string cached_url_template = R"(https://a.test/index.html?c=3&$key=c)";
852     base::ReplaceSubstringsAfterOffset(&request_url_template, 0, "$key", key);
853     base::ReplaceSubstringsAfterOffset(&cached_url_template, 0, "$key", key);
854     std::string header_template =
855         "HTTP/1.1 200 OK\r\n"
856         R"(No-Vary-Search: params, except=("$key"))"
857         "\r\n\r\n";
858     base::ReplaceSubstringsAfterOffset(&header_template, 0, "$key", value);
859 
860     const auto parsed_header = base::MakeRefCounted<HttpResponseHeaders>(
861         net::HttpUtil::AssembleRawHeaders(header_template));
862     const auto no_vary_search_data_special_char =
863         HttpNoVarySearchData::ParseFromHeaders(*parsed_header).value();
864 
865     EXPECT_TRUE(no_vary_search_data_special_char.AreEquivalent(
866         GURL(request_url_template), GURL(cached_url_template)))
867         << "request_url = " << request_url_template
868         << " cached_url = " << cached_url_template
869         << " headers = " << header_template;
870   }
871 }
872 
TEST(HttpNoVarySearchCompare,CheckUrlEqualityWithPercentEncodedNonASCIICharacters)873 TEST(HttpNoVarySearchCompare,
874      CheckUrlEqualityWithPercentEncodedNonASCIICharacters) {
875   for (const auto& [key, value] : kPercentEncodedNonAsciiKeys) {
876     std::string request_url_template =
877         R"(https://a.test/index.html?a=2&$key=c)";
878     std::string cached_url_template = R"(https://a.test/index.html?$key=d&a=2)";
879     base::ReplaceSubstringsAfterOffset(&request_url_template, 0, "$key", key);
880     base::ReplaceSubstringsAfterOffset(&cached_url_template, 0, "$key", key);
881     std::string header_template =
882         "HTTP/1.1 200 OK\r\n"
883         R"(No-Vary-Search: params=("$key"))"
884         "\r\n\r\n";
885     base::ReplaceSubstringsAfterOffset(&header_template, 0, "$key", value);
886 
887     const auto parsed_header = base::MakeRefCounted<HttpResponseHeaders>(
888         net::HttpUtil::AssembleRawHeaders(header_template));
889     const auto no_vary_search_data_special_char =
890         HttpNoVarySearchData::ParseFromHeaders(*parsed_header).value();
891 
892     EXPECT_TRUE(no_vary_search_data_special_char.AreEquivalent(
893         GURL(request_url_template), GURL(cached_url_template)))
894         << "request_url = " << request_url_template
895         << " cached_url = " << cached_url_template
896         << " headers = " << header_template;
897   }
898 }
899 
900 class HttpNoVarySearchCompare
901     : public ::testing::Test,
902       public ::testing::WithParamInterface<NoVarySearchCompareTestData> {};
903 
TEST_P(HttpNoVarySearchCompare,CheckUrlEqualityByNoVarySearch)904 TEST_P(HttpNoVarySearchCompare, CheckUrlEqualityByNoVarySearch) {
905   const auto& test_data = GetParam();
906 
907   const std::string headers =
908       net::HttpUtil::AssembleRawHeaders(test_data.raw_headers);
909   const auto parsed = base::MakeRefCounted<HttpResponseHeaders>(headers);
910   const auto no_vary_search_data =
911       HttpNoVarySearchData::ParseFromHeaders(*parsed).value();
912 
913   EXPECT_EQ(no_vary_search_data.AreEquivalent(test_data.request_url,
914                                               test_data.cached_url),
915             test_data.expected_match)
916       << "request_url = " << test_data.request_url
917       << " cached_url = " << test_data.cached_url
918       << " headers = " << test_data.raw_headers
919       << " match = " << test_data.expected_match;
920 }
921 
922 const NoVarySearchCompareTestData no_vary_search_compare_tests[] = {
923     // Url's for same page with same username but different passwords.
924     {GURL("https://owner:[email protected]/index.html?a=2&b=3"),
925      GURL("https://owner:[email protected]/index.html?a=2&b=3"),
926      "HTTP/1.1 200 OK\r\n"
927      "No-Vary-Search: params\r\n\r\n",
928      false},
929     // Url's for same page with different username.
930     {GURL("https://[email protected]/index.html?a=2&b=3"),
931      GURL("https://[email protected]/index.html?a=2&b=3"),
932      "HTTP/1.1 200 OK\r\n"
933      "No-Vary-Search: params\r\n\r\n",
934      false},
935     // Url's for same origin with different path.
936     {GURL("https://a.test/index.html?a=2&b=3"),
937      GURL("https://a.test/home.html?a=2&b=3"),
938      "HTTP/1.1 200 OK\r\n"
939      "No-Vary-Search: params\r\n\r\n",
940      false},
941     // Url's for same page with different protocol.
942     {GURL("http://a.test/index.html?a=2&b=3"),
943      GURL("https://a.test/index.html?a=2&b=3"),
944      "HTTP/1.1 200 OK\r\n"
945      "No-Vary-Search: params\r\n\r\n",
946      false},
947     // Url's for different pages without the query and reference part
948     // are not equivalent.
949     {GURL("https://a.test/index.html?a=2&b=3"),
950      GURL("https://b.test/index.html?b=4&c=5"),
951      "HTTP/1.1 200 OK\r\n"
952      "No-Vary-Search: params\r\n\r\n",
953      false},
954     // Cached page requested again with different order of query parameters with
955     // the same values.
956     {GURL("https://a.test/index.html?a=2&b=3"),
957      GURL("https://a.test/index.html?b=3&a=2"),
958      "HTTP/1.1 200 OK\r\n"
959      "No-Vary-Search: key-order\r\n\r\n",
960      true},
961     // Cached page requested again with different order of query parameters but
962     // with different values.
963     {GURL("https://a.test/index.html?a=2&c=5&b=3"),
964      GURL("https://a.test/index.html?c=4&b=3&a=2"),
965      "HTTP/1.1 200 OK\r\n"
966      "No-Vary-Search: key-order\r\n\r\n",
967      false},
968     // Cached page requested again with values in different order for the query
969     // parameters with the same name. Key order is ignored.
970     {GURL("https://a.test/index.html?d=6&a=4&b=5&b=3&c=5&a=3"),
971      GURL("https://a.test/index.html?b=5&a=3&a=4&d=6&c=5&b=3"),
972      "HTTP/1.1 200 OK\r\n"
973      "No-Vary-Search: key-order"
974      "\r\n\r\n",
975      false},
976     // Cached page requested again with values in the same order for the query
977     // parameters with the same name. Key order is ignored.
978     {GURL("https://a.test/index.html?d=6&a=3&b=5&b=3&c=5&a=4"),
979      GURL("https://a.test/index.html?b=5&a=3&a=4&d=6&c=5&b=3"),
980      "HTTP/1.1 200 OK\r\n"
981      "No-Vary-Search: key-order"
982      "\r\n\r\n",
983      true},
984     // Cached page requested again with different order of query parameters but
985     // with one of the query parameters marked to be ignored.
986     {GURL("https://a.test/index.html?a=2&c=3&b=2"),
987      GURL("https://a.test/index.html?a=2&b=2&c=5"),
988      "HTTP/1.1 200 OK\r\n"
989      R"(No-Vary-Search: params=("c"))"
990      "\r\n\r\n",
991      true},
992     // Cached page requested again without any query parameters, but
993     // the cached URL's query parameter marked to be ignored.
994     {GURL("https://a.test/index.html"), GURL("https://a.test/index.html?a=2"),
995      "HTTP/1.1 200 OK\r\n"
996      R"(No-Vary-Search: params=("a"))"
997      "\r\n\r\n",
998      true},
999     // Cached page requested again with different values for the query
1000     // parameters that are marked to be ignored. Same value for the query
1001     // parameter that is marked as to vary.
1002     {GURL("https://a.test/index.html?a=1&b=2&c=3"),
1003      GURL("https://a.test/index.html?b=5&a=3&d=6&c=3"),
1004      "HTTP/1.1 200 OK\r\n"
1005      R"(No-Vary-Search: params, except=("c"))"
1006      "\r\n\r\n",
1007      true},
1008     // Cached page requested again with different values for the query
1009     // parameters that are marked to be ignored. Different value for the query
1010     // parameter that is marked as to vary.
1011     {GURL("https://a.test/index.html?a=1&b=2&c=5"),
1012      GURL("https://a.test/index.html?b=5&a=3&d=6&c=3"),
1013      "HTTP/1.1 200 OK\r\n"
1014      R"(No-Vary-Search: params, except=("c"))"
1015      "\r\n\r\n",
1016      false},
1017     // Cached page requested again with different values for the query
1018     // parameters that are marked to be ignored. Same values for the query
1019     // parameters that are marked as to vary.
1020     {GURL("https://a.test/index.html?d=6&a=1&b=2&c=5"),
1021      GURL("https://a.test/index.html?b=5&a=3&d=6&c=5"),
1022      "HTTP/1.1 200 OK\r\n"
1023      R"(No-Vary-Search: params, except=("c" "d"))"
1024      "\r\n\r\n",
1025      true},
1026     // Cached page requested again with different values for the query
1027     // parameters that are marked to be ignored. Same values for the query
1028     // parameters that are marked as to vary. Some query parameters to be
1029     // ignored appear multiple times in the query.
1030     {GURL("https://a.test/index.html?d=6&a=1&a=2&b=2&b=3&c=5"),
1031      GURL("https://a.test/index.html?b=5&a=3&a=4&d=6&c=5"),
1032      "HTTP/1.1 200 OK\r\n"
1033      R"(No-Vary-Search: params, except=("c" "d"))"
1034      "\r\n\r\n",
1035      true},
1036     // Cached page requested again with query parameters. All query parameters
1037     // are marked as to be ignored.
1038     {GURL("https://a.test/index.html?a=1&b=2&c=5"),
1039      GURL("https://a.test/index.html"),
1040      "HTTP/1.1 200 OK\r\n"
1041      "No-Vary-Search: params\r\n\r\n",
1042      true},
1043     // Cached page requested again with query parameters. All query parameters
1044     // are marked as to be ignored. Both request url and cached url have query
1045     // parameters.
1046     {GURL("https://a.test/index.html?a=1&b=2&c=5"),
1047      GURL("https://a.test/index.html?a=5&b=6&c=8&d=1"),
1048      "HTTP/1.1 200 OK\r\n"
1049      "No-Vary-Search: params\r\n\r\n",
1050      true},
1051     // Add test for when the keys are percent encoded.
1052     {GURL(R"(https://a.test/index.html?c+1=3&b+%202=2&a=1&%63%201=2&a=5)"),
1053      GURL(R"(https://a.test/index.html?a=1&b%20%202=2&%63%201=3&a=5&c+1=2)"),
1054      "HTTP/1.1 200 OK\r\n"
1055      "No-Vary-Search: key-order\r\n\r\n",
1056      true},
1057     // Add test for when there are different representations of a character
1058     {GURL(R"(https://a.test/index.html?%C3%A9=f&a=2&c=4&é=b)"),
1059      GURL(R"(https://a.test/index.html?a=2&é=f&c=4&d=7&é=b)"),
1060      "HTTP/1.1 200 OK\r\n"
1061      R"(No-Vary-Search: params=("d"), key-order)"
1062      "\r\n\r\n",
1063      true},
1064     // Add test for when there are triple code point
1065     {GURL(R"(https://a.test/index.html?%E3%81%81=f&a=2&c=4&%E3%81%81=b)"),
1066      GURL(R"(https://a.test/index.html?a=2&%E3%81%81=f&c=4&d=7&%E3%81%81=b)"),
1067      "HTTP/1.1 200 OK\r\n"
1068      R"(No-Vary-Search: params=("d"), key-order)"
1069      "\r\n\r\n",
1070      true},
1071     // Add test for when there are quadruple code point
1072     {GURL(
1073          R"(https://a.test/index.html?%F0%90%A8%80=%F0%90%A8%80&a=2&c=4&%F0%90%A8%80=b)"),
1074      GURL(
1075          R"(https://a.test/index.html?a=2&%F0%90%A8%80=%F0%90%A8%80&c=4&d=7&%F0%90%A8%80=b)"),
1076      "HTTP/1.1 200 OK\r\n"
1077      R"(No-Vary-Search: params=("d"), key-order)"
1078      "\r\n\r\n",
1079      true},
1080     // Add test for when there are params with empty values / keys.
1081     {GURL("https://a.test/index.html?a&b&c&a=2&d&=5&=1&=3"),
1082      GURL("https://a.test/index.html?c&d&b&a&=5&=1&a=2&=3"),
1083      "HTTP/1.1 200 OK\r\n"
1084      "No-Vary-Search: key-order\r\n\r\n",
1085      true},
1086     // Add test for when there are params with empty values / keys, an empty
1087     // key pair missing.
1088     {GURL("https://a.test/index.html?a&b&c&a=2&d&=5&=1&=3"),
1089      GURL("https://a.test/index.html?c&d&b&a&=5&a=2&=3"),
1090      "HTTP/1.1 200 OK\r\n"
1091      "No-Vary-Search: key-order\r\n\r\n",
1092      false},
1093     // Add test when there are params with keys / values that are wrongly
1094     // escaped.
1095     {GURL(R"(https://a.test/index.html?a=%3&%3=b)"),
1096      GURL(R"(https://a.test/index.html?a=%3&c=3&%3=b)"),
1097      "HTTP/1.1 200 OK\r\n"
1098      R"(No-Vary-Search: params=("c"))"
1099      "\r\n\r\n",
1100      true},
1101     // Add test when there is a param with key starting with a percent encoded
1102     // space (+).
1103     {GURL(R"(https://a.test/index.html?+a=3)"),
1104      GURL(R"(https://a.test/index.html?+a=2)"),
1105      "HTTP/1.1 200 OK\r\n"
1106      R"(No-Vary-Search: params=("+a"))"
1107      "\r\n\r\n",
1108      true},
1109     // Add test when there is a param with key starting with a percent encoded
1110     // space (+) and gets compared with same key without the leading space.
1111     {GURL(R"(https://a.test/index.html?+a=3)"),
1112      GURL(R"(https://a.test/index.html?a=2)"),
1113      "HTTP/1.1 200 OK\r\n"
1114      R"(No-Vary-Search: params=("+a"))"
1115      "\r\n\r\n",
1116      false},
1117     // Add test for when there are different representations of the character é
1118     // and we are ignoring that key.
1119     {GURL(R"(https://a.test/index.html?%C3%A9=g&a=2&c=4&é=b)"),
1120      GURL(R"(https://a.test/index.html?a=2&é=f&c=4&d=7&é=b)"),
1121      "HTTP/1.1 200 OK\r\n"
1122      R"(No-Vary-Search: params=("d" "%C3%A9"))"
1123      "\r\n\r\n",
1124      true},
1125     // Add test for when there are different representations of the character é
1126     // and we are not ignoring that key.
1127     {GURL(R"(https://a.test/index.html?%C3%A9=f&a=2&c=4&é=b)"),
1128      GURL(R"(https://a.test/index.html?a=2&é=f&c=4&d=7&é=b)"),
1129      "HTTP/1.1 200 OK\r\n"
1130      R"(No-Vary-Search: params, except=("%C3%A9"))"
1131      "\r\n\r\n",
1132      true},
1133     // Add test for when there are different representations of the character é
1134     // and we are not ignoring that key.
1135     {GURL(R"(https://a.test/index.html?%C3%A9=g&a=2&c=4&é=b)"),
1136      GURL(R"(https://a.test/index.html?a=2&é=f&c=4&d=7&é=b)"),
1137      "HTTP/1.1 200 OK\r\n"
1138      R"(No-Vary-Search: params, except=("%C3%A9"))"
1139      "\r\n\r\n",
1140      false},
1141 };
1142 
1143 INSTANTIATE_TEST_SUITE_P(HttpNoVarySearchCompare,
1144                          HttpNoVarySearchCompare,
1145                          testing::ValuesIn(no_vary_search_compare_tests));
1146 
1147 }  // namespace
1148 
1149 }  // namespace net
1150