• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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/dns/host_cache.h"
6 
7 #include <map>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/format_macros.h"
14 #include "base/functional/bind.h"
15 #include "base/functional/callback.h"
16 #include "base/functional/callback_helpers.h"
17 #include "base/json/json_reader.h"
18 #include "base/json/json_writer.h"
19 #include "base/ranges/algorithm.h"
20 #include "base/strings/strcat.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/string_piece.h"
23 #include "base/strings/string_util.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/time/time.h"
26 #include "base/values.h"
27 #include "net/base/connection_endpoint_metadata.h"
28 #include "net/base/host_port_pair.h"
29 #include "net/base/ip_address.h"
30 #include "net/base/ip_endpoint.h"
31 #include "net/base/network_anonymization_key.h"
32 #include "net/base/schemeful_site.h"
33 #include "net/dns/host_resolver_internal_result.h"
34 #include "net/dns/host_resolver_results_test_util.h"
35 #include "net/dns/https_record_rdata.h"
36 #include "net/dns/public/host_resolver_results.h"
37 #include "testing/gmock/include/gmock/gmock.h"
38 #include "testing/gtest/include/gtest/gtest.h"
39 #include "url/gurl.h"
40 #include "url/scheme_host_port.h"
41 #include "url/url_constants.h"
42 
43 using ::testing::_;
44 using ::testing::ElementsAre;
45 using ::testing::ElementsAreArray;
46 using ::testing::IsEmpty;
47 using ::testing::Optional;
48 using ::testing::Pair;
49 using ::testing::Pointee;
50 using ::testing::Property;
51 using ::testing::UnorderedElementsAre;
52 
53 namespace net {
54 
55 namespace {
56 
57 const int kMaxCacheEntries = 10;
58 
59 // Builds a key for |hostname|, defaulting the query type to unspecified.
Key(const std::string & hostname)60 HostCache::Key Key(const std::string& hostname) {
61   return HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, hostname, 443),
62                         DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
63                         NetworkAnonymizationKey());
64 }
65 
FoobarIndexIsOdd(const std::string & foobarx_com)66 bool FoobarIndexIsOdd(const std::string& foobarx_com) {
67   return (foobarx_com[6] - '0') % 2 == 1;
68 }
69 
70 class MockPersistenceDelegate : public HostCache::PersistenceDelegate {
71  public:
ScheduleWrite()72   void ScheduleWrite() override { ++num_changes_; }
73 
num_changes() const74   int num_changes() const { return num_changes_; }
75 
76  private:
77   int num_changes_ = 0;
78 };
79 
80 MATCHER_P(EntryContentsEqual,
81           entry,
82           base::StrCat({"contents ", negation ? "!=" : "==", " contents of ",
83                         testing::PrintToString(entry)})) {
84   return arg.ContentsEqual(entry);
85 }
86 
MakeIP(base::StringPiece literal)87 IPAddress MakeIP(base::StringPiece literal) {
88   IPAddress ret;
89   CHECK(ret.AssignFromIPLiteral(literal));
90   return ret;
91 }
92 
MakeEndpoints(std::vector<std::string> my_addresses)93 std::vector<IPEndPoint> MakeEndpoints(std::vector<std::string> my_addresses) {
94   std::vector<IPEndPoint> out(my_addresses.size());
95   base::ranges::transform(my_addresses, out.begin(),
96                           [](auto& s) { return IPEndPoint(MakeIP(s), 0); });
97   return out;
98 }
99 
100 }  // namespace
101 
TEST(HostCacheTest,Basic)102 TEST(HostCacheTest, Basic) {
103   const base::TimeDelta kTTL = base::Seconds(10);
104 
105   HostCache cache(kMaxCacheEntries);
106 
107   // Start at t=0.
108   base::TimeTicks now;
109 
110   HostCache::Key key1 = Key("foobar.com");
111   HostCache::Key key2 = Key("foobar2.com");
112   HostCache::Entry entry =
113       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{"foobar.com"},
114                        HostCache::Entry::SOURCE_UNKNOWN);
115 
116   EXPECT_EQ(0U, cache.size());
117 
118   // Add an entry for "foobar.com" at t=0.
119   EXPECT_FALSE(cache.Lookup(key1, now));
120   cache.Set(key1, entry, now, kTTL);
121   EXPECT_TRUE(cache.Lookup(key1, now));
122   EXPECT_TRUE(cache.Lookup(key1, now)->second.error() == entry.error());
123 
124   EXPECT_EQ(1U, cache.size());
125 
126   // Advance to t=5.
127   now += base::Seconds(5);
128 
129   // Add an entry for "foobar2.com" at t=5.
130   EXPECT_FALSE(cache.Lookup(key2, now));
131   cache.Set(key2, entry, now, kTTL);
132   EXPECT_TRUE(cache.Lookup(key2, now));
133   EXPECT_EQ(2U, cache.size());
134 
135   // Advance to t=9
136   now += base::Seconds(4);
137 
138   // Verify that the entries we added are still retrievable, and usable.
139   EXPECT_TRUE(cache.Lookup(key1, now));
140   EXPECT_TRUE(cache.Lookup(key2, now));
141   EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now));
142 
143   // Advance to t=10; key is now expired.
144   now += base::Seconds(1);
145 
146   EXPECT_FALSE(cache.Lookup(key1, now));
147   EXPECT_TRUE(cache.Lookup(key2, now));
148 
149   // Update key1, so it is no longer expired.
150   cache.Set(key1, entry, now, kTTL);
151   EXPECT_TRUE(cache.Lookup(key1, now));
152   EXPECT_EQ(2U, cache.size());
153 
154   // Both entries should still be retrievable and usable.
155   EXPECT_TRUE(cache.Lookup(key1, now));
156   EXPECT_TRUE(cache.Lookup(key2, now));
157 
158   // Advance to t=20; both entries are now expired.
159   now += base::Seconds(10);
160 
161   EXPECT_FALSE(cache.Lookup(key1, now));
162   EXPECT_FALSE(cache.Lookup(key2, now));
163 }
164 
TEST(HostCacheTest,GetEndpoints)165 TEST(HostCacheTest, GetEndpoints) {
166   std::vector<IPEndPoint> ip_endpoints = {IPEndPoint(IPAddress(1, 1, 1, 1), 0),
167                                           IPEndPoint(IPAddress(2, 2, 2, 2), 0)};
168   HostCache::Entry entry(OK, ip_endpoints, /*aliases=*/{},
169                          HostCache::Entry::SOURCE_DNS);
170 
171   EXPECT_THAT(entry.GetEndpoints(),
172               Optional(ElementsAre(ExpectEndpointResult(ip_endpoints))));
173 }
174 
TEST(HostCacheTest,GetEmptyEndpoints)175 TEST(HostCacheTest, GetEmptyEndpoints) {
176   HostCache::Entry entry(ERR_NAME_NOT_RESOLVED, /*ip_endpoints=*/{},
177                          /*aliases=*/{}, HostCache::Entry::SOURCE_DNS);
178   EXPECT_THAT(entry.GetEndpoints(), Optional(IsEmpty()));
179 }
180 
TEST(HostCacheTest,GetEmptyEndpointsWithMetadata)181 TEST(HostCacheTest, GetEmptyEndpointsWithMetadata) {
182   HostCache::Entry entry(ERR_NAME_NOT_RESOLVED, /*ip_endpoints=*/{},
183                          /*aliases=*/{}, HostCache::Entry::SOURCE_DNS);
184 
185   // Merge in non-empty metadata.
186   ConnectionEndpointMetadata metadata;
187   metadata.supported_protocol_alpns = {"h3", "h2"};
188   HostCache::Entry metadata_entry(
189       OK,
190       std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>{
191           {1u, metadata}},
192       HostCache::Entry::SOURCE_DNS);
193 
194   auto merged_entry = HostCache::Entry::MergeEntries(entry, metadata_entry);
195 
196   // Result should still be empty.
197   EXPECT_THAT(merged_entry.GetEndpoints(), Optional(IsEmpty()));
198 }
199 
TEST(HostCacheTest,GetMissingEndpoints)200 TEST(HostCacheTest, GetMissingEndpoints) {
201   HostCache::Entry entry(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
202   EXPECT_FALSE(entry.GetEndpoints());
203 }
204 
TEST(HostCacheTest,GetMissingEndpointsWithMetadata)205 TEST(HostCacheTest, GetMissingEndpointsWithMetadata) {
206   HostCache::Entry entry(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
207 
208   // Merge in non-empty metadata.
209   ConnectionEndpointMetadata metadata;
210   metadata.supported_protocol_alpns = {"h3", "h2"};
211   HostCache::Entry metadata_entry(
212       OK,
213       std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>{
214           {1u, metadata}},
215       HostCache::Entry::SOURCE_DNS);
216 
217   auto merged_entry = HostCache::Entry::MergeEntries(entry, metadata_entry);
218 
219   // Result should still be `nullopt`.
220   EXPECT_FALSE(merged_entry.GetEndpoints());
221 }
222 
223 // Test that Keys without scheme are allowed and treated as completely different
224 // from similar Keys with scheme.
TEST(HostCacheTest,HandlesKeysWithoutScheme)225 TEST(HostCacheTest, HandlesKeysWithoutScheme) {
226   const base::TimeDelta kTTL = base::Seconds(10);
227 
228   HostCache cache(kMaxCacheEntries);
229 
230   // t=0.
231   base::TimeTicks now;
232 
233   HostCache::Key key("host1.test", DnsQueryType::UNSPECIFIED, 0,
234                      HostResolverSource::ANY, NetworkAnonymizationKey());
235   HostCache::Key key_with_scheme(
236       url::SchemeHostPort(url::kHttpsScheme, "host1.test", 443),
237       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
238       NetworkAnonymizationKey());
239   ASSERT_NE(key, key_with_scheme);
240   HostCache::Entry entry =
241       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
242                        HostCache::Entry::SOURCE_UNKNOWN);
243 
244   ASSERT_EQ(0U, cache.size());
245   ASSERT_FALSE(cache.Lookup(key, now));
246   ASSERT_FALSE(cache.Lookup(key_with_scheme, now));
247 
248   // Add entry for `key`.
249   cache.Set(key, entry, now, kTTL);
250   EXPECT_EQ(1U, cache.size());
251   EXPECT_TRUE(cache.Lookup(key, now));
252   EXPECT_FALSE(cache.Lookup(key_with_scheme, now));
253 
254   // Add entry for `key_with_scheme`.
255   cache.Set(key_with_scheme, entry, now, kTTL);
256   EXPECT_EQ(2U, cache.size());
257   EXPECT_TRUE(cache.Lookup(key, now));
258   EXPECT_TRUE(cache.Lookup(key_with_scheme, now));
259 
260   // Clear the cache and try adding in reverse order.
261   cache.clear();
262   ASSERT_EQ(0U, cache.size());
263   ASSERT_FALSE(cache.Lookup(key, now));
264   ASSERT_FALSE(cache.Lookup(key_with_scheme, now));
265 
266   // Add entry for `key_with_scheme`.
267   cache.Set(key_with_scheme, entry, now, kTTL);
268   EXPECT_EQ(1U, cache.size());
269   EXPECT_FALSE(cache.Lookup(key, now));
270   EXPECT_TRUE(cache.Lookup(key_with_scheme, now));
271 
272   // Add entry for `key`.
273   cache.Set(key, entry, now, kTTL);
274   EXPECT_EQ(2U, cache.size());
275   EXPECT_TRUE(cache.Lookup(key, now));
276   EXPECT_TRUE(cache.Lookup(key_with_scheme, now));
277 }
278 
279 // Make sure NetworkAnonymizationKey is respected.
TEST(HostCacheTest,NetworkAnonymizationKey)280 TEST(HostCacheTest, NetworkAnonymizationKey) {
281   const url::SchemeHostPort kHost(url::kHttpsScheme, "hostname.test", 443);
282   const base::TimeDelta kTTL = base::Seconds(10);
283 
284   const SchemefulSite kSite1(GURL("https://site1.test/"));
285   const auto kNetworkAnonymizationKey1 =
286       NetworkAnonymizationKey::CreateSameSite(kSite1);
287   const SchemefulSite kSite2(GURL("https://site2.test/"));
288   const auto kNetworkAnonymizationKey2 =
289       NetworkAnonymizationKey::CreateSameSite(kSite2);
290 
291   HostCache::Key key1(kHost, DnsQueryType::UNSPECIFIED, 0,
292                       HostResolverSource::ANY, kNetworkAnonymizationKey1);
293   HostCache::Key key2(kHost, DnsQueryType::UNSPECIFIED, 0,
294                       HostResolverSource::ANY, kNetworkAnonymizationKey2);
295   HostCache::Entry entry1 =
296       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
297                        HostCache::Entry::SOURCE_UNKNOWN);
298   HostCache::Entry entry2 =
299       HostCache::Entry(ERR_FAILED, /*ip_endpoints=*/{}, /*aliases=*/{},
300                        HostCache::Entry::SOURCE_UNKNOWN);
301 
302   HostCache cache(kMaxCacheEntries);
303 
304   // Start at t=0.
305   base::TimeTicks now;
306 
307   EXPECT_EQ(0U, cache.size());
308 
309   // Add an entry for kNetworkAnonymizationKey1.
310   EXPECT_FALSE(cache.Lookup(key1, now));
311   cache.Set(key1, entry1, now, kTTL);
312 
313   const std::pair<const HostCache::Key, HostCache::Entry>* result =
314       cache.Lookup(key1, now);
315   ASSERT_TRUE(result);
316   EXPECT_EQ(kNetworkAnonymizationKey1, result->first.network_anonymization_key);
317   EXPECT_EQ(OK, result->second.error());
318   EXPECT_FALSE(cache.Lookup(key2, now));
319   EXPECT_EQ(1U, cache.size());
320 
321   // Add a different entry for kNetworkAnonymizationKey2.
322   cache.Set(key2, entry2, now, 3 * kTTL);
323   result = cache.Lookup(key1, now);
324   ASSERT_TRUE(result);
325   EXPECT_EQ(kNetworkAnonymizationKey1, result->first.network_anonymization_key);
326   EXPECT_EQ(OK, result->second.error());
327   result = cache.Lookup(key2, now);
328   ASSERT_TRUE(result);
329   EXPECT_EQ(kNetworkAnonymizationKey2, result->first.network_anonymization_key);
330   EXPECT_EQ(ERR_FAILED, result->second.error());
331   EXPECT_EQ(2U, cache.size());
332 
333   // Advance time so that first entry times out. Second entry should remain.
334   now += 2 * kTTL;
335   EXPECT_FALSE(cache.Lookup(key1, now));
336   result = cache.Lookup(key2, now);
337   ASSERT_TRUE(result);
338   EXPECT_EQ(kNetworkAnonymizationKey2, result->first.network_anonymization_key);
339   EXPECT_EQ(ERR_FAILED, result->second.error());
340 }
341 
342 // Try caching entries for a failed resolve attempt -- since we set the TTL of
343 // such entries to 0 it won't store, but it will kick out the previous result.
TEST(HostCacheTest,NoCacheZeroTTL)344 TEST(HostCacheTest, NoCacheZeroTTL) {
345   const base::TimeDelta kSuccessEntryTTL = base::Seconds(10);
346   const base::TimeDelta kFailureEntryTTL = base::Seconds(0);
347 
348   HostCache cache(kMaxCacheEntries);
349 
350   // Set t=0.
351   base::TimeTicks now;
352 
353   HostCache::Key key1 = Key("foobar.com");
354   HostCache::Key key2 = Key("foobar2.com");
355   HostCache::Entry entry =
356       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
357                        HostCache::Entry::SOURCE_UNKNOWN);
358 
359   EXPECT_FALSE(cache.Lookup(key1, now));
360   cache.Set(key1, entry, now, kFailureEntryTTL);
361   EXPECT_EQ(1U, cache.size());
362 
363   // We disallow use of negative entries.
364   EXPECT_FALSE(cache.Lookup(key1, now));
365 
366   // Now overwrite with a valid entry, and then overwrite with negative entry
367   // again -- the valid entry should be kicked out.
368   cache.Set(key1, entry, now, kSuccessEntryTTL);
369   EXPECT_TRUE(cache.Lookup(key1, now));
370   cache.Set(key1, entry, now, kFailureEntryTTL);
371   EXPECT_FALSE(cache.Lookup(key1, now));
372 }
373 
374 // Try caching entries for a failed resolves for 10 seconds.
TEST(HostCacheTest,CacheNegativeEntry)375 TEST(HostCacheTest, CacheNegativeEntry) {
376   const base::TimeDelta kFailureEntryTTL = base::Seconds(10);
377 
378   HostCache cache(kMaxCacheEntries);
379 
380   // Start at t=0.
381   base::TimeTicks now;
382 
383   HostCache::Key key1 = Key("foobar.com");
384   HostCache::Key key2 = Key("foobar2.com");
385   HostCache::Entry entry =
386       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
387                        HostCache::Entry::SOURCE_UNKNOWN);
388 
389   EXPECT_EQ(0U, cache.size());
390 
391   // Add an entry for "foobar.com" at t=0.
392   EXPECT_FALSE(cache.Lookup(key1, now));
393   cache.Set(key1, entry, now, kFailureEntryTTL);
394   EXPECT_TRUE(cache.Lookup(key1, now));
395   EXPECT_EQ(1U, cache.size());
396 
397   // Advance to t=5.
398   now += base::Seconds(5);
399 
400   // Add an entry for "foobar2.com" at t=5.
401   EXPECT_FALSE(cache.Lookup(key2, now));
402   cache.Set(key2, entry, now, kFailureEntryTTL);
403   EXPECT_TRUE(cache.Lookup(key2, now));
404   EXPECT_EQ(2U, cache.size());
405 
406   // Advance to t=9
407   now += base::Seconds(4);
408 
409   // Verify that the entries we added are still retrievable, and usable.
410   EXPECT_TRUE(cache.Lookup(key1, now));
411   EXPECT_TRUE(cache.Lookup(key2, now));
412 
413   // Advance to t=10; key1 is now expired.
414   now += base::Seconds(1);
415 
416   EXPECT_FALSE(cache.Lookup(key1, now));
417   EXPECT_TRUE(cache.Lookup(key2, now));
418 
419   // Update key1, so it is no longer expired.
420   cache.Set(key1, entry, now, kFailureEntryTTL);
421   // Re-uses existing entry storage.
422   EXPECT_TRUE(cache.Lookup(key1, now));
423   EXPECT_EQ(2U, cache.size());
424 
425   // Both entries should still be retrievable and usable.
426   EXPECT_TRUE(cache.Lookup(key1, now));
427   EXPECT_TRUE(cache.Lookup(key2, now));
428 
429   // Advance to t=20; both entries are now expired.
430   now += base::Seconds(10);
431 
432   EXPECT_FALSE(cache.Lookup(key1, now));
433   EXPECT_FALSE(cache.Lookup(key2, now));
434 }
435 
436 // Tests that the same hostname can be duplicated in the cache, so long as
437 // the query type differs.
TEST(HostCacheTest,DnsQueryTypeIsPartOfKey)438 TEST(HostCacheTest, DnsQueryTypeIsPartOfKey) {
439   const base::TimeDelta kSuccessEntryTTL = base::Seconds(10);
440 
441   HostCache cache(kMaxCacheEntries);
442 
443   // t=0.
444   base::TimeTicks now;
445 
446   HostCache::Key key1(url::SchemeHostPort(url::kHttpScheme, "foobar.com", 80),
447                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
448                       NetworkAnonymizationKey());
449   HostCache::Key key2(url::SchemeHostPort(url::kHttpScheme, "foobar.com", 80),
450                       DnsQueryType::A, 0, HostResolverSource::ANY,
451                       NetworkAnonymizationKey());
452   HostCache::Entry entry =
453       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
454                        HostCache::Entry::SOURCE_UNKNOWN);
455 
456   EXPECT_EQ(0U, cache.size());
457 
458   // Add an entry for ("foobar.com", UNSPECIFIED) at t=0.
459   EXPECT_FALSE(cache.Lookup(key1, now));
460   cache.Set(key1, entry, now, kSuccessEntryTTL);
461   EXPECT_TRUE(cache.Lookup(key1, now));
462   EXPECT_EQ(1U, cache.size());
463 
464   // Add an entry for ("foobar.com", IPV4_ONLY) at t=0.
465   EXPECT_FALSE(cache.Lookup(key2, now));
466   cache.Set(key2, entry, now, kSuccessEntryTTL);
467   EXPECT_TRUE(cache.Lookup(key2, now));
468   EXPECT_EQ(2U, cache.size());
469 
470   // Even though the hostnames were the same, we should have two unique
471   // entries (because the address families differ).
472   EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now));
473 }
474 
475 // Tests that the same hostname can be duplicated in the cache, so long as
476 // the HostResolverFlags differ.
TEST(HostCacheTest,HostResolverFlagsArePartOfKey)477 TEST(HostCacheTest, HostResolverFlagsArePartOfKey) {
478   const url::SchemeHostPort kHost(url::kHttpsScheme, "foobar.test", 443);
479   const base::TimeDelta kTTL = base::Seconds(10);
480 
481   HostCache cache(kMaxCacheEntries);
482 
483   // t=0.
484   base::TimeTicks now;
485 
486   HostCache::Key key1(kHost, DnsQueryType::A, 0, HostResolverSource::ANY,
487                       NetworkAnonymizationKey());
488   HostCache::Key key2(kHost, DnsQueryType::A, HOST_RESOLVER_CANONNAME,
489                       HostResolverSource::ANY, NetworkAnonymizationKey());
490   HostCache::Key key3(kHost, DnsQueryType::A, HOST_RESOLVER_LOOPBACK_ONLY,
491                       HostResolverSource::ANY, NetworkAnonymizationKey());
492   HostCache::Entry entry =
493       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
494                        HostCache::Entry::SOURCE_UNKNOWN);
495 
496   EXPECT_EQ(0U, cache.size());
497 
498   // Add an entry for ("foobar.com", IPV4, NONE) at t=0.
499   EXPECT_FALSE(cache.Lookup(key1, now));
500   cache.Set(key1, entry, now, kTTL);
501   EXPECT_TRUE(cache.Lookup(key1, now));
502   EXPECT_EQ(1U, cache.size());
503 
504   // Add an entry for ("foobar.com", IPV4, CANONNAME) at t=0.
505   EXPECT_FALSE(cache.Lookup(key2, now));
506   cache.Set(key2, entry, now, kTTL);
507   EXPECT_TRUE(cache.Lookup(key2, now));
508   EXPECT_EQ(2U, cache.size());
509 
510   // Add an entry for ("foobar.com", IPV4, LOOPBACK_ONLY) at t=0.
511   EXPECT_FALSE(cache.Lookup(key3, now));
512   cache.Set(key3, entry, now, kTTL);
513   EXPECT_TRUE(cache.Lookup(key3, now));
514   EXPECT_EQ(3U, cache.size());
515 
516   // Even though the hostnames were the same, we should have two unique
517   // entries (because the HostResolverFlags differ).
518   EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now));
519   EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key3, now));
520   EXPECT_NE(cache.Lookup(key2, now), cache.Lookup(key3, now));
521 }
522 
523 // Tests that the same hostname can be duplicated in the cache, so long as
524 // the HostResolverSource differs.
TEST(HostCacheTest,HostResolverSourceIsPartOfKey)525 TEST(HostCacheTest, HostResolverSourceIsPartOfKey) {
526   const url::SchemeHostPort kHost(url::kHttpsScheme, "foobar.test", 443);
527   const base::TimeDelta kSuccessEntryTTL = base::Seconds(10);
528 
529   HostCache cache(kMaxCacheEntries);
530 
531   // t=0.
532   base::TimeTicks now;
533 
534   HostCache::Key key1(kHost, DnsQueryType::UNSPECIFIED, 0,
535                       HostResolverSource::ANY, NetworkAnonymizationKey());
536   HostCache::Key key2(kHost, DnsQueryType::UNSPECIFIED, 0,
537                       HostResolverSource::DNS, NetworkAnonymizationKey());
538   HostCache::Entry entry =
539       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
540                        HostCache::Entry::SOURCE_UNKNOWN);
541 
542   EXPECT_EQ(0U, cache.size());
543 
544   // Add an entry for ("foobar.com", UNSPECIFIED, ANY) at t=0.
545   EXPECT_FALSE(cache.Lookup(key1, now));
546   cache.Set(key1, entry, now, kSuccessEntryTTL);
547   EXPECT_TRUE(cache.Lookup(key1, now));
548   EXPECT_EQ(1U, cache.size());
549 
550   // Add an entry for ("foobar.com", UNSPECIFIED, DNS) at t=0.
551   EXPECT_FALSE(cache.Lookup(key2, now));
552   cache.Set(key2, entry, now, kSuccessEntryTTL);
553   EXPECT_TRUE(cache.Lookup(key2, now));
554   EXPECT_EQ(2U, cache.size());
555 
556   // Even though the hostnames were the same, we should have two unique
557   // entries (because the HostResolverSource differs).
558   EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now));
559 }
560 
561 // Tests that the same hostname can be duplicated in the cache, so long as
562 // the secure field in the key differs.
TEST(HostCacheTest,SecureIsPartOfKey)563 TEST(HostCacheTest, SecureIsPartOfKey) {
564   const url::SchemeHostPort kHost(url::kHttpsScheme, "foobar.test", 443);
565   const base::TimeDelta kSuccessEntryTTL = base::Seconds(10);
566 
567   HostCache cache(kMaxCacheEntries);
568 
569   // t=0.
570   base::TimeTicks now;
571   HostCache::EntryStaleness stale;
572 
573   HostCache::Key key1(kHost, DnsQueryType::A, 0, HostResolverSource::ANY,
574                       NetworkAnonymizationKey());
575   key1.secure = true;
576   HostCache::Key key2(kHost, DnsQueryType::A, 0, HostResolverSource::ANY,
577                       NetworkAnonymizationKey());
578   key2.secure = false;
579   HostCache::Entry entry =
580       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
581                        HostCache::Entry::SOURCE_UNKNOWN);
582 
583   EXPECT_EQ(0U, cache.size());
584 
585   // Add an entry for ("foobar.com", IPV4, true /* secure */) at t=0.
586   EXPECT_FALSE(cache.Lookup(key1, now));
587   cache.Set(key1, entry, now, kSuccessEntryTTL);
588   EXPECT_TRUE(cache.Lookup(key1, now));
589   EXPECT_EQ(1U, cache.size());
590 
591   // Lookup a key that is identical to the inserted key except for the secure
592   // field.
593   EXPECT_FALSE(cache.Lookup(key2, now));
594   EXPECT_FALSE(cache.LookupStale(key2, now, &stale));
595   const std::pair<const HostCache::Key, HostCache::Entry>* result;
596   result = cache.Lookup(key2, now, true /* ignore_secure */);
597   EXPECT_TRUE(result);
598   EXPECT_TRUE(result->first.secure);
599   result = cache.LookupStale(key2, now, &stale, true /* ignore_secure */);
600   EXPECT_TRUE(result);
601   EXPECT_TRUE(result->first.secure);
602 
603   // Add an entry for ("foobar.com", IPV4, false */ secure */) at t=0.
604   cache.Set(key2, entry, now, kSuccessEntryTTL);
605   EXPECT_TRUE(cache.Lookup(key2, now));
606   EXPECT_TRUE(cache.LookupStale(key2, now, &stale));
607   EXPECT_EQ(2U, cache.size());
608 }
609 
TEST(HostCacheTest,PreferLessStaleMoreSecure)610 TEST(HostCacheTest, PreferLessStaleMoreSecure) {
611   const url::SchemeHostPort kHost(url::kHttpsScheme, "foobar.test", 443);
612   const base::TimeDelta kSuccessEntryTTL = base::Seconds(10);
613 
614   HostCache cache(kMaxCacheEntries);
615 
616   // t=0.
617   base::TimeTicks now;
618   HostCache::EntryStaleness stale;
619 
620   HostCache::Key insecure_key(kHost, DnsQueryType::A, 0,
621                               HostResolverSource::ANY,
622                               NetworkAnonymizationKey());
623   HostCache::Key secure_key(kHost, DnsQueryType::A, 0, HostResolverSource::ANY,
624                             NetworkAnonymizationKey());
625   secure_key.secure = true;
626   HostCache::Entry entry =
627       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
628                        HostCache::Entry::SOURCE_UNKNOWN);
629 
630   EXPECT_EQ(0U, cache.size());
631 
632   // Add both insecure and secure entries.
633   cache.Set(insecure_key, entry, now, kSuccessEntryTTL);
634   cache.Set(secure_key, entry, now, kSuccessEntryTTL);
635   EXPECT_EQ(insecure_key, cache.Lookup(insecure_key, now)->first);
636   EXPECT_EQ(secure_key, cache.Lookup(secure_key, now)->first);
637   // Secure key is preferred when equally stale.
638   EXPECT_EQ(secure_key,
639             cache.Lookup(insecure_key, now, true /* ignore_secure */)->first);
640   EXPECT_EQ(secure_key,
641             cache.Lookup(insecure_key, now, true /* ignore_secure */)->first);
642 
643   // Simulate network change.
644   cache.Invalidate();
645 
646   // Re-add insecure entry.
647   cache.Set(insecure_key, entry, now, kSuccessEntryTTL);
648   EXPECT_EQ(insecure_key, cache.Lookup(insecure_key, now)->first);
649   EXPECT_FALSE(cache.Lookup(secure_key, now));
650   EXPECT_EQ(secure_key, cache.LookupStale(secure_key, now, &stale)->first);
651   // Result with fewer network changes is preferred.
652   EXPECT_EQ(
653       insecure_key,
654       cache.LookupStale(secure_key, now, &stale, true /* ignore-secure */)
655           ->first);
656 
657   // Add both insecure and secure entries to a cleared cache, still at t=0.
658   cache.clear();
659   cache.Set(insecure_key, entry, now, base::Seconds(20));
660   cache.Set(secure_key, entry, now, kSuccessEntryTTL);
661 
662   // Advance to t=15 to expire the secure entry only.
663   now += base::Seconds(15);
664   EXPECT_EQ(insecure_key, cache.Lookup(insecure_key, now)->first);
665   EXPECT_FALSE(cache.Lookup(secure_key, now));
666   EXPECT_EQ(secure_key, cache.LookupStale(secure_key, now, &stale)->first);
667   // Non-expired result is preferred.
668   EXPECT_EQ(
669       insecure_key,
670       cache.LookupStale(secure_key, now, &stale, true /* ignore-secure */)
671           ->first);
672 }
673 
TEST(HostCacheTest,NoCache)674 TEST(HostCacheTest, NoCache) {
675   const base::TimeDelta kTTL = base::Seconds(10);
676 
677   // Disable caching.
678   HostCache cache(0);
679   EXPECT_TRUE(cache.caching_is_disabled());
680 
681   // Set t=0.
682   base::TimeTicks now;
683 
684   HostCache::Entry entry =
685       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
686                        HostCache::Entry::SOURCE_UNKNOWN);
687 
688   // Lookup and Set should have no effect.
689   EXPECT_FALSE(cache.Lookup(Key("foobar.com"), now));
690   cache.Set(Key("foobar.com"), entry, now, kTTL);
691   EXPECT_FALSE(cache.Lookup(Key("foobar.com"), now));
692 
693   EXPECT_EQ(0U, cache.size());
694 }
695 
TEST(HostCacheTest,Clear)696 TEST(HostCacheTest, Clear) {
697   const base::TimeDelta kTTL = base::Seconds(10);
698 
699   HostCache cache(kMaxCacheEntries);
700 
701   // Set t=0.
702   base::TimeTicks now;
703 
704   HostCache::Entry entry =
705       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
706                        HostCache::Entry::SOURCE_UNKNOWN);
707 
708   EXPECT_EQ(0u, cache.size());
709 
710   // Add three entries.
711   cache.Set(Key("foobar1.com"), entry, now, kTTL);
712   cache.Set(Key("foobar2.com"), entry, now, kTTL);
713   cache.Set(Key("foobar3.com"), entry, now, kTTL);
714 
715   EXPECT_EQ(3u, cache.size());
716 
717   cache.clear();
718 
719   EXPECT_EQ(0u, cache.size());
720 }
721 
TEST(HostCacheTest,ClearForHosts)722 TEST(HostCacheTest, ClearForHosts) {
723   const base::TimeDelta kTTL = base::Seconds(10);
724 
725   HostCache cache(kMaxCacheEntries);
726 
727   // Set t=0.
728   base::TimeTicks now;
729 
730   HostCache::Entry entry =
731       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
732                        HostCache::Entry::SOURCE_UNKNOWN);
733 
734   EXPECT_EQ(0u, cache.size());
735 
736   // Add several entries.
737   cache.Set(Key("foobar1.com"), entry, now, kTTL);
738   cache.Set(Key("foobar2.com"), entry, now, kTTL);
739   cache.Set(Key("foobar3.com"), entry, now, kTTL);
740   cache.Set(Key("foobar4.com"), entry, now, kTTL);
741   cache.Set(Key("foobar5.com"), entry, now, kTTL);
742 
743   EXPECT_EQ(5u, cache.size());
744 
745   // Clear the hosts matching a certain predicate, such as the number being odd.
746   cache.ClearForHosts(base::BindRepeating(&FoobarIndexIsOdd));
747 
748   EXPECT_EQ(2u, cache.size());
749   EXPECT_TRUE(cache.Lookup(Key("foobar2.com"), now));
750   EXPECT_TRUE(cache.Lookup(Key("foobar4.com"), now));
751 
752   // Passing null callback will delete all hosts.
753   cache.ClearForHosts(base::NullCallback());
754 
755   EXPECT_EQ(0u, cache.size());
756 }
757 
758 // Try to add too many entries to cache; it should evict the one with the oldest
759 // expiration time.
TEST(HostCacheTest,Evict)760 TEST(HostCacheTest, Evict) {
761   HostCache cache(2);
762 
763   base::TimeTicks now;
764 
765   HostCache::Key key1 = Key("foobar.com");
766   HostCache::Key key2 = Key("foobar2.com");
767   HostCache::Key key3 = Key("foobar3.com");
768   HostCache::Entry entry =
769       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
770                        HostCache::Entry::SOURCE_UNKNOWN);
771 
772   EXPECT_EQ(0u, cache.size());
773   EXPECT_FALSE(cache.Lookup(key1, now));
774   EXPECT_FALSE(cache.Lookup(key2, now));
775   EXPECT_FALSE(cache.Lookup(key3, now));
776 
777   // |key1| expires in 10 seconds, but |key2| in just 5.
778   cache.Set(key1, entry, now, base::Seconds(10));
779   cache.Set(key2, entry, now, base::Seconds(5));
780   EXPECT_EQ(2u, cache.size());
781   EXPECT_TRUE(cache.Lookup(key1, now));
782   EXPECT_TRUE(cache.Lookup(key2, now));
783   EXPECT_FALSE(cache.Lookup(key3, now));
784 
785   // |key2| should be chosen for eviction, since it expires sooner.
786   cache.Set(key3, entry, now, base::Seconds(10));
787   EXPECT_EQ(2u, cache.size());
788   EXPECT_TRUE(cache.Lookup(key1, now));
789   EXPECT_FALSE(cache.Lookup(key2, now));
790   EXPECT_TRUE(cache.Lookup(key3, now));
791 }
792 
793 // Try to retrieve stale entries from the cache. They should be returned by
794 // |LookupStale()| but not |Lookup()|, with correct |EntryStaleness| data.
TEST(HostCacheTest,Stale)795 TEST(HostCacheTest, Stale) {
796   const base::TimeDelta kTTL = base::Seconds(10);
797 
798   HostCache cache(kMaxCacheEntries);
799 
800   // Start at t=0.
801   base::TimeTicks now;
802   HostCache::EntryStaleness stale;
803 
804   HostCache::Key key = Key("foobar.com");
805   HostCache::Entry entry =
806       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
807                        HostCache::Entry::SOURCE_UNKNOWN);
808 
809   EXPECT_EQ(0U, cache.size());
810 
811   // Add an entry for "foobar.com" at t=0.
812   EXPECT_FALSE(cache.Lookup(key, now));
813   EXPECT_FALSE(cache.LookupStale(key, now, &stale));
814   cache.Set(key, entry, now, kTTL);
815   EXPECT_TRUE(cache.Lookup(key, now));
816   EXPECT_TRUE(cache.LookupStale(key, now, &stale));
817   EXPECT_FALSE(stale.is_stale());
818   EXPECT_EQ(0, stale.stale_hits);
819 
820   EXPECT_EQ(1U, cache.size());
821 
822   // Advance to t=5.
823   now += base::Seconds(5);
824 
825   EXPECT_TRUE(cache.Lookup(key, now));
826   EXPECT_TRUE(cache.LookupStale(key, now, &stale));
827   EXPECT_FALSE(stale.is_stale());
828   EXPECT_EQ(0, stale.stale_hits);
829 
830   // Advance to t=15.
831   now += base::Seconds(10);
832 
833   EXPECT_FALSE(cache.Lookup(key, now));
834   EXPECT_TRUE(cache.LookupStale(key, now, &stale));
835   EXPECT_TRUE(stale.is_stale());
836   EXPECT_EQ(base::Seconds(5), stale.expired_by);
837   EXPECT_EQ(0, stale.network_changes);
838   EXPECT_EQ(1, stale.stale_hits);
839 
840   // Advance to t=20.
841   now += base::Seconds(5);
842 
843   EXPECT_FALSE(cache.Lookup(key, now));
844   EXPECT_TRUE(cache.LookupStale(key, now, &stale));
845   EXPECT_TRUE(stale.is_stale());
846   EXPECT_EQ(base::Seconds(10), stale.expired_by);
847   EXPECT_EQ(0, stale.network_changes);
848   EXPECT_EQ(2, stale.stale_hits);
849 
850   // Simulate network change.
851   cache.Invalidate();
852 
853   EXPECT_FALSE(cache.Lookup(key, now));
854   EXPECT_TRUE(cache.LookupStale(key, now, &stale));
855   EXPECT_TRUE(stale.is_stale());
856   EXPECT_EQ(base::Seconds(10), stale.expired_by);
857   EXPECT_EQ(1, stale.network_changes);
858   EXPECT_EQ(3, stale.stale_hits);
859 }
860 
TEST(HostCacheTest,EvictStale)861 TEST(HostCacheTest, EvictStale) {
862   HostCache cache(2);
863 
864   base::TimeTicks now;
865   HostCache::EntryStaleness stale;
866 
867   HostCache::Key key1 = Key("foobar.com");
868   HostCache::Key key2 = Key("foobar2.com");
869   HostCache::Key key3 = Key("foobar3.com");
870   HostCache::Entry entry =
871       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
872                        HostCache::Entry::SOURCE_UNKNOWN);
873 
874   EXPECT_EQ(0u, cache.size());
875   EXPECT_FALSE(cache.Lookup(key1, now));
876   EXPECT_FALSE(cache.Lookup(key2, now));
877   EXPECT_FALSE(cache.Lookup(key3, now));
878 
879   // |key1| expires in 10 seconds.
880   cache.Set(key1, entry, now, base::Seconds(10));
881   EXPECT_EQ(1u, cache.size());
882   EXPECT_TRUE(cache.Lookup(key1, now));
883   EXPECT_FALSE(cache.Lookup(key2, now));
884   EXPECT_FALSE(cache.Lookup(key3, now));
885 
886   // Simulate network change, expiring the cache.
887   cache.Invalidate();
888 
889   EXPECT_EQ(1u, cache.size());
890   EXPECT_FALSE(cache.Lookup(key1, now));
891   EXPECT_TRUE(cache.LookupStale(key1, now, &stale));
892   EXPECT_EQ(1, stale.network_changes);
893 
894   // Advance to t=1.
895   now += base::Seconds(1);
896 
897   // |key2| expires before |key1| would originally have expired.
898   cache.Set(key2, entry, now, base::Seconds(5));
899   EXPECT_EQ(2u, cache.size());
900   EXPECT_FALSE(cache.Lookup(key1, now));
901   EXPECT_TRUE(cache.LookupStale(key1, now, &stale));
902   EXPECT_TRUE(cache.Lookup(key2, now));
903   EXPECT_FALSE(cache.Lookup(key3, now));
904 
905   // |key1| should be chosen for eviction, since it is stale.
906   cache.Set(key3, entry, now, base::Seconds(1));
907   EXPECT_EQ(2u, cache.size());
908   EXPECT_FALSE(cache.Lookup(key1, now));
909   EXPECT_FALSE(cache.LookupStale(key1, now, &stale));
910   EXPECT_TRUE(cache.Lookup(key2, now));
911   EXPECT_TRUE(cache.Lookup(key3, now));
912 
913   // Advance to t=6.
914   now += base::Seconds(5);
915 
916   // Insert |key1| again. |key3| should be evicted.
917   cache.Set(key1, entry, now, base::Seconds(10));
918   EXPECT_EQ(2u, cache.size());
919   EXPECT_TRUE(cache.Lookup(key1, now));
920   EXPECT_FALSE(cache.Lookup(key2, now));
921   EXPECT_TRUE(cache.LookupStale(key2, now, &stale));
922   EXPECT_FALSE(cache.Lookup(key3, now));
923   EXPECT_FALSE(cache.LookupStale(key3, now, &stale));
924 }
925 
926 // Pinned entries should not be evicted, even if the cache is full and the Entry
927 // has expired.
TEST(HostCacheTest,NoEvictPinned)928 TEST(HostCacheTest, NoEvictPinned) {
929   HostCache cache(2);
930 
931   base::TimeTicks now;
932 
933   HostCache::Key key1 = Key("foobar.com");
934   HostCache::Key key2 = Key("foobar2.com");
935   HostCache::Key key3 = Key("foobar3.com");
936   HostCache::Entry entry =
937       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
938                        HostCache::Entry::SOURCE_UNKNOWN);
939   entry.set_pinning(true);
940 
941   cache.Set(key1, entry, now, base::Seconds(5));
942   now += base::Seconds(10);
943   cache.Set(key2, entry, now, base::Seconds(5));
944   now += base::Seconds(10);
945   cache.Set(key3, entry, now, base::Seconds(5));
946 
947   // There are 3 entries in this cache whose nominal max size is 2.
948   EXPECT_EQ(3u, cache.size());
949   EXPECT_TRUE(cache.LookupStale(key1, now, nullptr));
950   EXPECT_TRUE(cache.LookupStale(key2, now, nullptr));
951   EXPECT_TRUE(cache.Lookup(key3, now));
952 }
953 
954 // Obsolete pinned entries should be evicted normally.
TEST(HostCacheTest,EvictObsoletePinned)955 TEST(HostCacheTest, EvictObsoletePinned) {
956   HostCache cache(2);
957 
958   base::TimeTicks now;
959 
960   HostCache::Key key1 = Key("foobar.com");
961   HostCache::Key key2 = Key("foobar2.com");
962   HostCache::Key key3 = Key("foobar3.com");
963   HostCache::Key key4 = Key("foobar4.com");
964   HostCache::Entry entry =
965       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
966                        HostCache::Entry::SOURCE_UNKNOWN);
967   entry.set_pinning(true);
968 
969   // |key2| should be preserved, since it expires later.
970   cache.Set(key1, entry, now, base::Seconds(5));
971   cache.Set(key2, entry, now, base::Seconds(10));
972   cache.Set(key3, entry, now, base::Seconds(5));
973   // There are 3 entries in this cache whose nominal max size is 2.
974   EXPECT_EQ(3u, cache.size());
975 
976   cache.Invalidate();
977   // |Invalidate()| does not trigger eviction.
978   EXPECT_EQ(3u, cache.size());
979 
980   // |Set()| triggers an eviction, leaving only |key2| in cache,
981   // before adding |key4|
982   cache.Set(key4, entry, now, base::Seconds(2));
983   EXPECT_EQ(2u, cache.size());
984   EXPECT_FALSE(cache.LookupStale(key1, now, nullptr));
985   EXPECT_TRUE(cache.LookupStale(key2, now, nullptr));
986   EXPECT_FALSE(cache.LookupStale(key3, now, nullptr));
987   EXPECT_TRUE(cache.LookupStale(key4, now, nullptr));
988 }
989 
990 // An active pin is preserved if the record is
991 // replaced due to a Set() call without the pin.
TEST(HostCacheTest,PreserveActivePin)992 TEST(HostCacheTest, PreserveActivePin) {
993   HostCache cache(2);
994 
995   base::TimeTicks now;
996 
997   // Make entry1 and entry2, identical except for IP and pinned flag.
998   IPEndPoint endpoint1(IPAddress(192, 0, 2, 1), 0);
999   IPEndPoint endpoint2(IPAddress(192, 0, 2, 2), 0);
1000   HostCache::Entry entry1 = HostCache::Entry(OK, {endpoint1}, /*aliases=*/{},
1001                                              HostCache::Entry::SOURCE_UNKNOWN);
1002   HostCache::Entry entry2 = HostCache::Entry(OK, {endpoint2}, /*aliases=*/{},
1003                                              HostCache::Entry::SOURCE_UNKNOWN);
1004   entry1.set_pinning(true);
1005 
1006   HostCache::Key key = Key("foobar.com");
1007 
1008   // Insert entry1, and verify that it can be retrieved with the
1009   // correct IP and |pinning()| == true.
1010   cache.Set(key, entry1, now, base::Seconds(10));
1011   const auto* pair1 = cache.Lookup(key, now);
1012   ASSERT_TRUE(pair1);
1013   const HostCache::Entry& result1 = pair1->second;
1014   EXPECT_THAT(
1015       result1.GetEndpoints(),
1016       Optional(ElementsAre(ExpectEndpointResult(ElementsAre(endpoint1)))));
1017   EXPECT_THAT(result1.pinning(), Optional(true));
1018 
1019   // Insert |entry2|, and verify that it when it is retrieved, it
1020   // has the new IP, and the "pinned" flag copied from |entry1|.
1021   cache.Set(key, entry2, now, base::Seconds(10));
1022   const auto* pair2 = cache.Lookup(key, now);
1023   ASSERT_TRUE(pair2);
1024   const HostCache::Entry& result2 = pair2->second;
1025   EXPECT_THAT(
1026       result2.GetEndpoints(),
1027       Optional(ElementsAre(ExpectEndpointResult(ElementsAre(endpoint2)))));
1028   EXPECT_THAT(result2.pinning(), Optional(true));
1029 }
1030 
1031 // An obsolete cache pin is not preserved if the record is replaced.
TEST(HostCacheTest,DontPreserveObsoletePin)1032 TEST(HostCacheTest, DontPreserveObsoletePin) {
1033   HostCache cache(2);
1034 
1035   base::TimeTicks now;
1036 
1037   // Make entry1 and entry2, identical except for IP and "pinned" flag.
1038   IPEndPoint endpoint1(IPAddress(192, 0, 2, 1), 0);
1039   IPEndPoint endpoint2(IPAddress(192, 0, 2, 2), 0);
1040   HostCache::Entry entry1 = HostCache::Entry(OK, {endpoint1}, /*aliases=*/{},
1041                                              HostCache::Entry::SOURCE_UNKNOWN);
1042   HostCache::Entry entry2 = HostCache::Entry(OK, {endpoint2}, /*aliases=*/{},
1043                                              HostCache::Entry::SOURCE_UNKNOWN);
1044   entry1.set_pinning(true);
1045 
1046   HostCache::Key key = Key("foobar.com");
1047 
1048   // Insert entry1, and verify that it can be retrieved with the
1049   // correct IP and |pinning()| == true.
1050   cache.Set(key, entry1, now, base::Seconds(10));
1051   const auto* pair1 = cache.Lookup(key, now);
1052   ASSERT_TRUE(pair1);
1053   const HostCache::Entry& result1 = pair1->second;
1054   EXPECT_THAT(
1055       result1.GetEndpoints(),
1056       Optional(ElementsAre(ExpectEndpointResult(ElementsAre(endpoint1)))));
1057   EXPECT_THAT(result1.pinning(), Optional(true));
1058 
1059   // Make entry1 obsolete.
1060   cache.Invalidate();
1061 
1062   // Insert |entry2|, and verify that it when it is retrieved, it
1063   // has the new IP, and the "pinned" flag is not copied from |entry1|.
1064   cache.Set(key, entry2, now, base::Seconds(10));
1065   const auto* pair2 = cache.Lookup(key, now);
1066   ASSERT_TRUE(pair2);
1067   const HostCache::Entry& result2 = pair2->second;
1068   EXPECT_THAT(
1069       result2.GetEndpoints(),
1070       Optional(ElementsAre(ExpectEndpointResult(ElementsAre(endpoint2)))));
1071   EXPECT_THAT(result2.pinning(), Optional(false));
1072 }
1073 
1074 // An active pin is removed if the record is replaced by a Set() call
1075 // with the pin flag set to false.
TEST(HostCacheTest,Unpin)1076 TEST(HostCacheTest, Unpin) {
1077   HostCache cache(2);
1078 
1079   base::TimeTicks now;
1080 
1081   // Make entry1 and entry2, identical except for IP and pinned flag.
1082   IPEndPoint endpoint1(IPAddress(192, 0, 2, 1), 0);
1083   IPEndPoint endpoint2(IPAddress(192, 0, 2, 2), 0);
1084   HostCache::Entry entry1 = HostCache::Entry(OK, {endpoint1}, /*aliases=*/{},
1085                                              HostCache::Entry::SOURCE_UNKNOWN);
1086   HostCache::Entry entry2 = HostCache::Entry(OK, {endpoint2}, /*aliases=*/{},
1087                                              HostCache::Entry::SOURCE_UNKNOWN);
1088   entry1.set_pinning(true);
1089   entry2.set_pinning(false);
1090 
1091   HostCache::Key key = Key("foobar.com");
1092 
1093   // Insert entry1, and verify that it can be retrieved with the
1094   // correct IP and |pinning()| == true.
1095   cache.Set(key, entry1, now, base::Seconds(10));
1096   const auto* pair1 = cache.Lookup(key, now);
1097   ASSERT_TRUE(pair1);
1098   const HostCache::Entry& result1 = pair1->second;
1099   EXPECT_THAT(
1100       result1.GetEndpoints(),
1101       Optional(ElementsAre(ExpectEndpointResult(ElementsAre(endpoint1)))));
1102   EXPECT_THAT(result1.pinning(), Optional(true));
1103 
1104   // Insert |entry2|, and verify that it when it is retrieved, it
1105   // has the new IP, and the "pinned" flag is now false.
1106   cache.Set(key, entry2, now, base::Seconds(10));
1107   const auto* pair2 = cache.Lookup(key, now);
1108   ASSERT_TRUE(pair2);
1109   const HostCache::Entry& result2 = pair2->second;
1110   EXPECT_THAT(
1111       result2.GetEndpoints(),
1112       Optional(ElementsAre(ExpectEndpointResult(ElementsAre(endpoint2)))));
1113   EXPECT_THAT(result2.pinning(), Optional(false));
1114 }
1115 
1116 // Tests the less than and equal operators for HostCache::Key work.
TEST(HostCacheTest,KeyComparators)1117 TEST(HostCacheTest, KeyComparators) {
1118   struct CacheTestParameters {
1119     CacheTestParameters(const HostCache::Key key1,
1120                         const HostCache::Key key2,
1121                         int expected_comparison)
1122         : key1(key1), key2(key2), expected_comparison(expected_comparison) {}
1123 
1124     // Inputs.
1125     HostCache::Key key1;
1126     HostCache::Key key2;
1127 
1128     // Expectation.
1129     //   -1 means key1 is less than key2
1130     //    0 means key1 equals key2
1131     //    1 means key1 is greater than key2
1132     int expected_comparison;
1133   };
1134   std::vector<CacheTestParameters> tests = {
1135       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1136                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1137                       NetworkAnonymizationKey()),
1138        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1139                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1140                       NetworkAnonymizationKey()),
1141        0},
1142       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1143                       DnsQueryType::A, 0, HostResolverSource::ANY,
1144                       NetworkAnonymizationKey()),
1145        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1146                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1147                       NetworkAnonymizationKey()),
1148        1},
1149       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1150                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1151                       NetworkAnonymizationKey()),
1152        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1153                       DnsQueryType::A, 0, HostResolverSource::ANY,
1154                       NetworkAnonymizationKey()),
1155        -1},
1156       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1157                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1158                       NetworkAnonymizationKey()),
1159        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
1160                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1161                       NetworkAnonymizationKey()),
1162        -1},
1163       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1164                       DnsQueryType::A, 0, HostResolverSource::ANY,
1165                       NetworkAnonymizationKey()),
1166        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
1167                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1168                       NetworkAnonymizationKey()),
1169        1},
1170       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1171                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1172                       NetworkAnonymizationKey()),
1173        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
1174                       DnsQueryType::A, 0, HostResolverSource::ANY,
1175                       NetworkAnonymizationKey()),
1176        -1},
1177       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1178                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1179                       NetworkAnonymizationKey()),
1180        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1181                       DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
1182                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1183        -1},
1184       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1185                       DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
1186                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1187        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1188                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1189                       NetworkAnonymizationKey()),
1190        1},
1191       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1192                       DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
1193                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1194        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
1195                       DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
1196                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1197        -1},
1198       // 9: Different host scheme.
1199       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1200                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1201                       NetworkAnonymizationKey()),
1202        HostCache::Key(url::SchemeHostPort(url::kHttpScheme, "host1", 443),
1203                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1204                       NetworkAnonymizationKey()),
1205        1},
1206       // 10: Different host port.
1207       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1208                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1209                       NetworkAnonymizationKey()),
1210        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 1544),
1211                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1212                       NetworkAnonymizationKey()),
1213        -1},
1214       // 11: Same host name without scheme/port.
1215       {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
1216                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1217        HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
1218                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1219        0},
1220       // 12: Different host name without scheme/port.
1221       {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
1222                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1223        HostCache::Key("host2", DnsQueryType::UNSPECIFIED, 0,
1224                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1225        -1},
1226       // 13: Only one with scheme/port.
1227       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1228                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1229                       NetworkAnonymizationKey()),
1230        HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
1231                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1232        -1},
1233   };
1234   HostCache::Key insecure_key =
1235       HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1236                      DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1237                      NetworkAnonymizationKey());
1238   HostCache::Key secure_key =
1239       HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1240                      DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1241                      NetworkAnonymizationKey());
1242   secure_key.secure = true;
1243   tests.emplace_back(insecure_key, secure_key, -1);
1244 
1245   for (size_t i = 0; i < std::size(tests); ++i) {
1246     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
1247 
1248     const HostCache::Key& key1 = tests[i].key1;
1249     const HostCache::Key& key2 = tests[i].key2;
1250 
1251     switch (tests[i].expected_comparison) {
1252       case -1:
1253         EXPECT_TRUE(key1 < key2);
1254         EXPECT_FALSE(key2 < key1);
1255         break;
1256       case 0:
1257         EXPECT_FALSE(key1 < key2);
1258         EXPECT_FALSE(key2 < key1);
1259         break;
1260       case 1:
1261         EXPECT_FALSE(key1 < key2);
1262         EXPECT_TRUE(key2 < key1);
1263         break;
1264       default:
1265         FAIL() << "Invalid expectation. Can be only -1, 0, 1";
1266     }
1267   }
1268 }
1269 
TEST(HostCacheTest,SerializeAndDeserializeWithExpirations)1270 TEST(HostCacheTest, SerializeAndDeserializeWithExpirations) {
1271   const base::TimeDelta kTTL = base::Seconds(10);
1272 
1273   HostCache cache(kMaxCacheEntries);
1274 
1275   // Start at t=0.
1276   base::TimeTicks now;
1277 
1278   HostCache::Key expire_by_time_key = Key("expire.by.time.test");
1279   HostCache::Key expire_by_changes_key = Key("expire.by.changes.test");
1280 
1281   IPEndPoint endpoint(IPAddress(1, 2, 3, 4), 0);
1282   HostCache::Entry entry = HostCache::Entry(OK, {endpoint}, /*aliases=*/{},
1283                                             HostCache::Entry::SOURCE_UNKNOWN);
1284 
1285   EXPECT_EQ(0u, cache.size());
1286 
1287   // Add an entry for `expire_by_time_key` at t=0.
1288   EXPECT_FALSE(cache.Lookup(expire_by_time_key, now));
1289   cache.Set(expire_by_time_key, entry, now, kTTL);
1290   EXPECT_THAT(cache.Lookup(expire_by_time_key, now),
1291               Pointee(Pair(expire_by_time_key, EntryContentsEqual(entry))));
1292 
1293   EXPECT_EQ(1u, cache.size());
1294 
1295   // Advance to t=5.
1296   now += base::Seconds(5);
1297 
1298   // Add entry for `expire_by_changes_key` at t=5.
1299   EXPECT_FALSE(cache.Lookup(expire_by_changes_key, now));
1300   cache.Set(expire_by_changes_key, entry, now, kTTL);
1301   EXPECT_TRUE(cache.Lookup(expire_by_changes_key, now));
1302   EXPECT_EQ(2u, cache.size());
1303 
1304   EXPECT_EQ(0u, cache.last_restore_size());
1305 
1306   // Advance to t=12, and serialize/deserialize the cache.
1307   now += base::Seconds(7);
1308 
1309   base::Value::List serialized_cache;
1310   cache.GetList(serialized_cache, false /* include_staleness */,
1311                 HostCache::SerializationType::kRestorable);
1312   HostCache restored_cache(kMaxCacheEntries);
1313 
1314   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1315 
1316   HostCache::EntryStaleness stale;
1317 
1318   // The `expire_by_time_key` entry is stale due to both network changes and
1319   // expiration time.
1320   EXPECT_FALSE(restored_cache.Lookup(expire_by_time_key, now));
1321   EXPECT_THAT(restored_cache.LookupStale(expire_by_time_key, now, &stale),
1322               Pointee(Pair(expire_by_time_key, EntryContentsEqual(entry))));
1323   EXPECT_EQ(1, stale.network_changes);
1324   // Time to TimeTicks conversion is fuzzy, so just check that expected and
1325   // actual expiration times are close.
1326   EXPECT_GT(base::Milliseconds(100),
1327             (base::Seconds(2) - stale.expired_by).magnitude());
1328 
1329   // The `expire_by_changes_key` entry is stale only due to network changes.
1330   EXPECT_FALSE(restored_cache.Lookup(expire_by_changes_key, now));
1331   EXPECT_THAT(restored_cache.LookupStale(expire_by_changes_key, now, &stale),
1332               Pointee(Pair(expire_by_changes_key, EntryContentsEqual(entry))));
1333   EXPECT_EQ(1, stale.network_changes);
1334   EXPECT_GT(base::Milliseconds(100),
1335             (base::Seconds(-3) - stale.expired_by).magnitude());
1336 
1337   EXPECT_EQ(2u, restored_cache.last_restore_size());
1338 }
1339 
1340 // Test that any changes between serialization and restore are preferred over
1341 // old restored entries.
TEST(HostCacheTest,SerializeAndDeserializeWithChanges)1342 TEST(HostCacheTest, SerializeAndDeserializeWithChanges) {
1343   const base::TimeDelta kTTL = base::Seconds(10);
1344 
1345   HostCache cache(kMaxCacheEntries);
1346 
1347   // Start at t=0.
1348   base::TimeTicks now;
1349 
1350   HostCache::Key to_serialize_key1 = Key("to.serialize1.test");
1351   HostCache::Key to_serialize_key2 = Key("to.serialize2.test");
1352   HostCache::Key other_key = Key("other.test");
1353 
1354   IPEndPoint endpoint(IPAddress(1, 1, 1, 1), 0);
1355   HostCache::Entry serialized_entry = HostCache::Entry(
1356       OK, {endpoint}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1357 
1358   IPEndPoint replacement_endpoint(IPAddress(2, 2, 2, 2), 0);
1359   HostCache::Entry replacement_entry =
1360       HostCache::Entry(OK, {replacement_endpoint}, /*aliases=*/{},
1361                        HostCache::Entry::SOURCE_UNKNOWN);
1362 
1363   IPEndPoint other_endpoint(IPAddress(3, 3, 3, 3), 0);
1364   HostCache::Entry other_entry = HostCache::Entry(
1365       OK, {other_endpoint}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1366 
1367   EXPECT_EQ(0u, cache.size());
1368 
1369   // Add `to_serialize_key1` and `to_serialize_key2`
1370   EXPECT_FALSE(cache.Lookup(to_serialize_key1, now));
1371   cache.Set(to_serialize_key1, serialized_entry, now, kTTL);
1372   EXPECT_THAT(
1373       cache.Lookup(to_serialize_key1, now),
1374       Pointee(Pair(to_serialize_key1, EntryContentsEqual(serialized_entry))));
1375   EXPECT_FALSE(cache.Lookup(to_serialize_key2, now));
1376   cache.Set(to_serialize_key2, serialized_entry, now, kTTL);
1377   EXPECT_THAT(
1378       cache.Lookup(to_serialize_key2, now),
1379       Pointee(Pair(to_serialize_key2, EntryContentsEqual(serialized_entry))));
1380   EXPECT_EQ(2u, cache.size());
1381 
1382   // Serialize the cache.
1383   base::Value::List serialized_cache;
1384   cache.GetList(serialized_cache, false /* include_staleness */,
1385                 HostCache::SerializationType::kRestorable);
1386   HostCache restored_cache(kMaxCacheEntries);
1387 
1388   // Add entries for `to_serialize_key1` and `other_key` to the new cache
1389   // before restoring the serialized one. The `to_serialize_key1` result is
1390   // different from the original.
1391   EXPECT_FALSE(restored_cache.Lookup(to_serialize_key1, now));
1392   restored_cache.Set(to_serialize_key1, replacement_entry, now, kTTL);
1393   EXPECT_THAT(
1394       restored_cache.Lookup(to_serialize_key1, now),
1395       Pointee(Pair(to_serialize_key1, EntryContentsEqual(replacement_entry))));
1396   EXPECT_EQ(1u, restored_cache.size());
1397 
1398   EXPECT_FALSE(restored_cache.Lookup(other_key, now));
1399   restored_cache.Set(other_key, other_entry, now, kTTL);
1400   EXPECT_THAT(restored_cache.Lookup(other_key, now),
1401               Pointee(Pair(other_key, EntryContentsEqual(other_entry))));
1402   EXPECT_EQ(2u, restored_cache.size());
1403 
1404   EXPECT_EQ(0u, restored_cache.last_restore_size());
1405 
1406   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1407   EXPECT_EQ(1u, restored_cache.last_restore_size());
1408 
1409   HostCache::EntryStaleness stale;
1410 
1411   // Expect `to_serialize_key1` has the replacement entry.
1412   EXPECT_THAT(
1413       restored_cache.Lookup(to_serialize_key1, now),
1414       Pointee(Pair(to_serialize_key1, EntryContentsEqual(replacement_entry))));
1415 
1416   // Expect `to_serialize_key2` has the original entry.
1417   EXPECT_THAT(
1418       restored_cache.LookupStale(to_serialize_key2, now, &stale),
1419       Pointee(Pair(to_serialize_key2, EntryContentsEqual(serialized_entry))));
1420 
1421   // Expect no change for `other_key`.
1422   EXPECT_THAT(restored_cache.Lookup(other_key, now),
1423               Pointee(Pair(other_key, EntryContentsEqual(other_entry))));
1424 }
1425 
TEST(HostCacheTest,SerializeAndDeserializeAddresses)1426 TEST(HostCacheTest, SerializeAndDeserializeAddresses) {
1427   const base::TimeDelta kTTL = base::Seconds(10);
1428 
1429   HostCache cache(kMaxCacheEntries);
1430 
1431   // Start at t=0.
1432   base::TimeTicks now;
1433 
1434   HostCache::Key key1 = Key("foobar.com");
1435   key1.secure = true;
1436   HostCache::Key key2 = Key("foobar2.com");
1437   HostCache::Key key3 = Key("foobar3.com");
1438   HostCache::Key key4 = Key("foobar4.com");
1439 
1440   IPAddress address_ipv4(1, 2, 3, 4);
1441   IPAddress address_ipv6(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1442   IPEndPoint endpoint_ipv4(address_ipv4, 0);
1443   IPEndPoint endpoint_ipv6(address_ipv6, 0);
1444 
1445   HostCache::Entry entry1 = HostCache::Entry(
1446       OK, {endpoint_ipv4}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1447   HostCache::Entry entry2 =
1448       HostCache::Entry(OK, {endpoint_ipv6, endpoint_ipv4}, /*aliases=*/{},
1449                        HostCache::Entry::SOURCE_UNKNOWN);
1450   HostCache::Entry entry3 = HostCache::Entry(
1451       OK, {endpoint_ipv6}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1452   HostCache::Entry entry4 = HostCache::Entry(
1453       OK, {endpoint_ipv4}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1454 
1455   EXPECT_EQ(0u, cache.size());
1456 
1457   // Add an entry for "foobar.com" at t=0.
1458   EXPECT_FALSE(cache.Lookup(key1, now));
1459   cache.Set(key1, entry1, now, kTTL);
1460   EXPECT_TRUE(cache.Lookup(key1, now));
1461   EXPECT_TRUE(cache.Lookup(key1, now)->second.error() == entry1.error());
1462 
1463   EXPECT_EQ(1u, cache.size());
1464 
1465   // Advance to t=5.
1466   now += base::Seconds(5);
1467 
1468   // Add entries for "foobar2.com" and "foobar3.com" at t=5.
1469   EXPECT_FALSE(cache.Lookup(key2, now));
1470   cache.Set(key2, entry2, now, kTTL);
1471   EXPECT_TRUE(cache.Lookup(key2, now));
1472   EXPECT_EQ(2u, cache.size());
1473 
1474   EXPECT_FALSE(cache.Lookup(key3, now));
1475   cache.Set(key3, entry3, now, kTTL);
1476   EXPECT_TRUE(cache.Lookup(key3, now));
1477   EXPECT_EQ(3u, cache.size());
1478 
1479   EXPECT_EQ(0u, cache.last_restore_size());
1480 
1481   // Advance to t=12, ansd serialize the cache.
1482   now += base::Seconds(7);
1483 
1484   base::Value::List serialized_cache;
1485   cache.GetList(serialized_cache, false /* include_staleness */,
1486                 HostCache::SerializationType::kRestorable);
1487   HostCache restored_cache(kMaxCacheEntries);
1488 
1489   // Add entries for "foobar3.com" and "foobar4.com" to the cache before
1490   // restoring it. The "foobar3.com" result is different from the original.
1491   EXPECT_FALSE(restored_cache.Lookup(key3, now));
1492   restored_cache.Set(key3, entry1, now, kTTL);
1493   EXPECT_TRUE(restored_cache.Lookup(key3, now));
1494   EXPECT_EQ(1u, restored_cache.size());
1495 
1496   EXPECT_FALSE(restored_cache.Lookup(key4, now));
1497   restored_cache.Set(key4, entry4, now, kTTL);
1498   EXPECT_TRUE(restored_cache.Lookup(key4, now));
1499   EXPECT_EQ(2u, restored_cache.size());
1500 
1501   EXPECT_EQ(0u, restored_cache.last_restore_size());
1502 
1503   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1504 
1505   HostCache::EntryStaleness stale;
1506 
1507   // The "foobar.com" entry is stale due to both network changes and expiration
1508   // time.
1509   EXPECT_FALSE(restored_cache.Lookup(key1, now));
1510   const std::pair<const HostCache::Key, HostCache::Entry>* result1 =
1511       restored_cache.LookupStale(key1, now, &stale);
1512   EXPECT_TRUE(result1);
1513   EXPECT_TRUE(result1->first.secure);
1514   ASSERT_TRUE(result1->second.ip_endpoints());
1515   EXPECT_FALSE(result1->second.text_records());
1516   EXPECT_FALSE(result1->second.hostnames());
1517   EXPECT_EQ(1u, result1->second.ip_endpoints()->size());
1518   EXPECT_EQ(endpoint_ipv4, result1->second.ip_endpoints()->front());
1519   EXPECT_EQ(1, stale.network_changes);
1520   // Time to TimeTicks conversion is fuzzy, so just check that expected and
1521   // actual expiration times are close.
1522   EXPECT_GT(base::Milliseconds(100),
1523             (base::Seconds(2) - stale.expired_by).magnitude());
1524 
1525   // The "foobar2.com" entry is stale only due to network changes.
1526   EXPECT_FALSE(restored_cache.Lookup(key2, now));
1527   const std::pair<const HostCache::Key, HostCache::Entry>* result2 =
1528       restored_cache.LookupStale(key2, now, &stale);
1529   EXPECT_TRUE(result2);
1530   EXPECT_FALSE(result2->first.secure);
1531   ASSERT_TRUE(result2->second.ip_endpoints());
1532   EXPECT_EQ(2u, result2->second.ip_endpoints()->size());
1533   EXPECT_EQ(endpoint_ipv6, result2->second.ip_endpoints()->front());
1534   EXPECT_EQ(endpoint_ipv4, result2->second.ip_endpoints()->back());
1535   EXPECT_EQ(1, stale.network_changes);
1536   EXPECT_GT(base::Milliseconds(100),
1537             (base::Seconds(-3) - stale.expired_by).magnitude());
1538 
1539   // The "foobar3.com" entry is the new one, not the restored one.
1540   const std::pair<const HostCache::Key, HostCache::Entry>* result3 =
1541       restored_cache.Lookup(key3, now);
1542   EXPECT_TRUE(result3);
1543   ASSERT_TRUE(result3->second.ip_endpoints());
1544   EXPECT_EQ(1u, result3->second.ip_endpoints()->size());
1545   EXPECT_EQ(endpoint_ipv4, result3->second.ip_endpoints()->front());
1546 
1547   // The "foobar4.com" entry is still present and usable.
1548   const std::pair<const HostCache::Key, HostCache::Entry>* result4 =
1549       restored_cache.Lookup(key4, now);
1550   EXPECT_TRUE(result4);
1551   ASSERT_TRUE(result4->second.ip_endpoints());
1552   EXPECT_EQ(1u, result4->second.ip_endpoints()->size());
1553   EXPECT_EQ(endpoint_ipv4, result4->second.ip_endpoints()->front());
1554 
1555   EXPECT_EQ(2u, restored_cache.last_restore_size());
1556 }
1557 
TEST(HostCacheTest,SerializeAndDeserializeEntryWithoutScheme)1558 TEST(HostCacheTest, SerializeAndDeserializeEntryWithoutScheme) {
1559   const base::TimeDelta kTTL = base::Seconds(10);
1560 
1561   HostCache::Key key("host.test", DnsQueryType::UNSPECIFIED, 0,
1562                      HostResolverSource::ANY, NetworkAnonymizationKey());
1563   HostCache::Entry entry =
1564       HostCache::Entry(OK, /*ip_endpoints=*/{},
1565                        /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1566 
1567   base::TimeTicks now;
1568   HostCache cache(kMaxCacheEntries);
1569 
1570   cache.Set(key, entry, now, kTTL);
1571   ASSERT_TRUE(cache.Lookup(key, now));
1572   ASSERT_EQ(cache.size(), 1u);
1573 
1574   base::Value::List serialized_cache;
1575   cache.GetList(serialized_cache, /*include_staleness=*/false,
1576                 HostCache::SerializationType::kRestorable);
1577   HostCache restored_cache(kMaxCacheEntries);
1578   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1579   EXPECT_EQ(restored_cache.size(), 1u);
1580 
1581   HostCache::EntryStaleness staleness;
1582   EXPECT_THAT(restored_cache.LookupStale(key, now, &staleness),
1583               Pointee(Pair(key, EntryContentsEqual(entry))));
1584 }
1585 
TEST(HostCacheTest,SerializeAndDeserializeWithNetworkAnonymizationKey)1586 TEST(HostCacheTest, SerializeAndDeserializeWithNetworkAnonymizationKey) {
1587   const url::SchemeHostPort kHost =
1588       url::SchemeHostPort(url::kHttpsScheme, "hostname.test", 443);
1589   const base::TimeDelta kTTL = base::Seconds(10);
1590   const SchemefulSite kSite(GURL("https://site.test/"));
1591   const auto kNetworkAnonymizationKey =
1592       NetworkAnonymizationKey::CreateSameSite(kSite);
1593   const SchemefulSite kOpaqueSite;
1594   const auto kOpaqueNetworkAnonymizationKey =
1595       NetworkAnonymizationKey::CreateSameSite(kOpaqueSite);
1596 
1597   HostCache::Key key1(kHost, DnsQueryType::UNSPECIFIED, 0,
1598                       HostResolverSource::ANY, kNetworkAnonymizationKey);
1599   HostCache::Key key2(kHost, DnsQueryType::UNSPECIFIED, 0,
1600                       HostResolverSource::ANY, kOpaqueNetworkAnonymizationKey);
1601 
1602   IPEndPoint endpoint(IPAddress(1, 2, 3, 4), 0);
1603   HostCache::Entry entry = HostCache::Entry(OK, {endpoint}, /*aliases=*/{},
1604                                             HostCache::Entry::SOURCE_UNKNOWN);
1605 
1606   base::TimeTicks now;
1607   HostCache cache(kMaxCacheEntries);
1608 
1609   cache.Set(key1, entry, now, kTTL);
1610   cache.Set(key2, entry, now, kTTL);
1611 
1612   EXPECT_TRUE(cache.Lookup(key1, now));
1613   EXPECT_EQ(kNetworkAnonymizationKey,
1614             cache.Lookup(key1, now)->first.network_anonymization_key);
1615   EXPECT_TRUE(cache.Lookup(key2, now));
1616   EXPECT_EQ(kOpaqueNetworkAnonymizationKey,
1617             cache.Lookup(key2, now)->first.network_anonymization_key);
1618   EXPECT_EQ(2u, cache.size());
1619 
1620   base::Value::List serialized_cache;
1621   cache.GetList(serialized_cache, false /* include_staleness */,
1622                 HostCache::SerializationType::kRestorable);
1623   HostCache restored_cache(kMaxCacheEntries);
1624   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1625   EXPECT_EQ(1u, restored_cache.size());
1626 
1627   HostCache::EntryStaleness stale;
1628   EXPECT_THAT(restored_cache.LookupStale(key1, now, &stale),
1629               Pointee(Pair(key1, EntryContentsEqual(entry))));
1630   EXPECT_FALSE(restored_cache.Lookup(key2, now));
1631 }
1632 
TEST(HostCacheTest,SerializeForDebugging)1633 TEST(HostCacheTest, SerializeForDebugging) {
1634   const url::SchemeHostPort kHost(url::kHttpsScheme, "hostname.test", 443);
1635   const base::TimeDelta kTTL = base::Seconds(10);
1636   const NetworkAnonymizationKey kNetworkAnonymizationKey =
1637       NetworkAnonymizationKey::CreateTransient();
1638 
1639   HostCache::Key key(kHost, DnsQueryType::UNSPECIFIED, 0,
1640                      HostResolverSource::ANY, kNetworkAnonymizationKey);
1641 
1642   IPEndPoint endpoint(IPAddress(1, 2, 3, 4), 0);
1643   HostCache::Entry entry = HostCache::Entry(OK, {endpoint}, /*aliases=*/{},
1644                                             HostCache::Entry::SOURCE_UNKNOWN);
1645 
1646   base::TimeTicks now;
1647   HostCache cache(kMaxCacheEntries);
1648 
1649   cache.Set(key, entry, now, kTTL);
1650 
1651   EXPECT_TRUE(cache.Lookup(key, now));
1652   EXPECT_EQ(kNetworkAnonymizationKey,
1653             cache.Lookup(key, now)->first.network_anonymization_key);
1654   EXPECT_EQ(1u, cache.size());
1655 
1656   base::Value::List serialized_cache;
1657   cache.GetList(serialized_cache, false /* include_staleness */,
1658                 HostCache::SerializationType::kDebug);
1659   HostCache restored_cache(kMaxCacheEntries);
1660   EXPECT_FALSE(restored_cache.RestoreFromListValue(serialized_cache));
1661 
1662   ASSERT_EQ(1u, serialized_cache.size());
1663   ASSERT_TRUE(serialized_cache[0].is_dict());
1664   const std::string* nik_string =
1665       serialized_cache[0].GetDict().FindString("network_anonymization_key");
1666   ASSERT_TRUE(nik_string);
1667   ASSERT_EQ(kNetworkAnonymizationKey.ToDebugString(), *nik_string);
1668 }
1669 
TEST(HostCacheTest,SerializeAndDeserialize_Text)1670 TEST(HostCacheTest, SerializeAndDeserialize_Text) {
1671   base::TimeTicks now;
1672 
1673   base::TimeDelta ttl = base::Seconds(99);
1674   std::vector<std::string> text_records({"foo", "bar"});
1675   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1676                      DnsQueryType::A, 0, HostResolverSource::DNS,
1677                      NetworkAnonymizationKey());
1678   key.secure = true;
1679   HostCache::Entry entry(OK, text_records, HostCache::Entry::SOURCE_DNS, ttl);
1680   EXPECT_TRUE(entry.text_records());
1681 
1682   HostCache cache(kMaxCacheEntries);
1683   cache.Set(key, entry, now, ttl);
1684   EXPECT_EQ(1u, cache.size());
1685 
1686   base::Value::List serialized_cache;
1687   cache.GetList(serialized_cache, false /* include_staleness */,
1688                 HostCache::SerializationType::kRestorable);
1689   HostCache restored_cache(kMaxCacheEntries);
1690   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1691 
1692   ASSERT_EQ(1u, serialized_cache.size());
1693   ASSERT_EQ(1u, restored_cache.size());
1694   HostCache::EntryStaleness stale;
1695   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1696       restored_cache.LookupStale(key, now, &stale);
1697   EXPECT_THAT(result, Pointee(Pair(key, EntryContentsEqual(entry))));
1698   EXPECT_THAT(result->second.text_records(), Optional(text_records));
1699 }
1700 
TEST(HostCacheTest,SerializeAndDeserialize_Hostname)1701 TEST(HostCacheTest, SerializeAndDeserialize_Hostname) {
1702   base::TimeTicks now;
1703 
1704   base::TimeDelta ttl = base::Seconds(99);
1705   std::vector<HostPortPair> hostnames(
1706       {HostPortPair("example.com", 95), HostPortPair("chromium.org", 122)});
1707   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1708                      DnsQueryType::A, 0, HostResolverSource::DNS,
1709                      NetworkAnonymizationKey());
1710   HostCache::Entry entry(OK, hostnames, HostCache::Entry::SOURCE_DNS, ttl);
1711   EXPECT_TRUE(entry.hostnames());
1712 
1713   HostCache cache(kMaxCacheEntries);
1714   cache.Set(key, entry, now, ttl);
1715   EXPECT_EQ(1u, cache.size());
1716 
1717   base::Value::List serialized_cache;
1718   cache.GetList(serialized_cache, false /* include_staleness */,
1719                 HostCache::SerializationType::kRestorable);
1720   HostCache restored_cache(kMaxCacheEntries);
1721   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1722 
1723   ASSERT_EQ(1u, restored_cache.size());
1724   HostCache::EntryStaleness stale;
1725   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1726       restored_cache.LookupStale(key, now, &stale);
1727   EXPECT_THAT(result, Pointee(Pair(key, EntryContentsEqual(entry))));
1728   EXPECT_THAT(result->second.hostnames(), Optional(hostnames));
1729 }
1730 
TEST(HostCacheTest,SerializeAndDeserializeEndpointResult)1731 TEST(HostCacheTest, SerializeAndDeserializeEndpointResult) {
1732   base::TimeTicks now;
1733 
1734   base::TimeDelta ttl = base::Seconds(99);
1735   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1736                      DnsQueryType::A, 0, HostResolverSource::DNS,
1737                      NetworkAnonymizationKey());
1738   IPEndPoint ipv6_endpoint(
1739       IPAddress(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4), 110);
1740   IPEndPoint ipv4_endpoint1(IPAddress(1, 1, 1, 1), 80);
1741   IPEndPoint ipv4_endpoint2(IPAddress(2, 2, 2, 2), 90);
1742   IPEndPoint other_ipv4_endpoint(IPAddress(3, 3, 3, 3), 100);
1743   std::string ipv6_alias = "ipv6_alias.test";
1744   std::string ipv4_alias = "ipv4_alias.test";
1745   std::string other_alias = "other_alias.test";
1746   std::vector<IPEndPoint> ip_endpoints = {ipv6_endpoint, ipv4_endpoint1,
1747                                           ipv4_endpoint2, other_ipv4_endpoint};
1748   std::set<std::string> aliases = {ipv6_alias, ipv4_alias, other_alias};
1749   HostCache::Entry entry(OK, ip_endpoints, aliases,
1750                          HostCache::Entry::SOURCE_DNS, ttl);
1751 
1752   std::set<std::string> canonical_names = {ipv6_alias, ipv4_alias};
1753   entry.set_canonical_names(canonical_names);
1754 
1755   EXPECT_TRUE(entry.GetEndpoints());
1756 
1757   ConnectionEndpointMetadata metadata1;
1758   metadata1.supported_protocol_alpns = {"h3", "h2"};
1759   metadata1.ech_config_list = {'f', 'o', 'o'};
1760   metadata1.target_name = ipv6_alias;
1761   ConnectionEndpointMetadata metadata2;
1762   metadata2.supported_protocol_alpns = {"h2", "h4"};
1763   metadata2.target_name = ipv4_alias;
1764   HostCache::Entry metadata_entry(
1765       OK,
1766       std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>{
1767           {1u, metadata1}, {2u, metadata2}},
1768       HostCache::Entry::SOURCE_DNS);
1769 
1770   auto merged_entry = HostCache::Entry::MergeEntries(entry, metadata_entry);
1771 
1772   EXPECT_THAT(merged_entry.GetEndpoints(),
1773               Optional(ElementsAre(ExpectEndpointResult(ip_endpoints))));
1774   EXPECT_THAT(
1775       merged_entry.GetMetadatas(),
1776       testing::Optional(testing::ElementsAre(
1777           ExpectConnectionEndpointMetadata(testing::ElementsAre("h3", "h2"),
1778                                            testing::ElementsAre('f', 'o', 'o'),
1779                                            ipv6_alias),
1780           ExpectConnectionEndpointMetadata(testing::ElementsAre("h2", "h4"),
1781                                            IsEmpty(), ipv4_alias))));
1782   EXPECT_THAT(merged_entry.canonical_names(),
1783               testing::Optional(UnorderedElementsAre(ipv4_alias, ipv6_alias)));
1784 
1785   HostCache cache(kMaxCacheEntries);
1786   cache.Set(key, merged_entry, now, ttl);
1787   EXPECT_EQ(1u, cache.size());
1788 
1789   base::Value::List serialized_cache;
1790   cache.GetList(serialized_cache, false /* include_staleness */,
1791                 HostCache::SerializationType::kRestorable);
1792   HostCache restored_cache(kMaxCacheEntries);
1793   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1794 
1795   // Check `serialized_cache` can be encoded as JSON. This ensures it has no
1796   // binary values.
1797   std::string json;
1798   EXPECT_TRUE(base::JSONWriter::Write(serialized_cache, &json));
1799 
1800   ASSERT_EQ(1u, restored_cache.size());
1801   HostCache::EntryStaleness stale;
1802   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1803       restored_cache.LookupStale(key, now, &stale);
1804 
1805   ASSERT_TRUE(result);
1806   EXPECT_THAT(result, Pointee(Pair(key, EntryContentsEqual(merged_entry))));
1807   EXPECT_THAT(result->second.GetEndpoints(),
1808               Optional(ElementsAre(ExpectEndpointResult(ip_endpoints))));
1809   EXPECT_THAT(
1810       result->second.GetMetadatas(),
1811       testing::Optional(testing::ElementsAre(
1812           ExpectConnectionEndpointMetadata(testing::ElementsAre("h3", "h2"),
1813                                            testing::ElementsAre('f', 'o', 'o'),
1814                                            ipv6_alias),
1815           ExpectConnectionEndpointMetadata(testing::ElementsAre("h2", "h4"),
1816                                            IsEmpty(), ipv4_alias))));
1817   EXPECT_THAT(result->second.canonical_names(),
1818               testing::Optional(UnorderedElementsAre(ipv4_alias, ipv6_alias)));
1819 
1820   EXPECT_THAT(result->second.aliases(), Pointee(aliases));
1821 }
1822 
TEST(HostCacheTest,DeserializeNoEndpointNoAliase)1823 TEST(HostCacheTest, DeserializeNoEndpointNoAliase) {
1824   base::TimeDelta ttl = base::Seconds(99);
1825   std::string expiration_time_str = base::NumberToString(
1826       (base::Time::Now() + ttl).since_origin().InMicroseconds());
1827 
1828   auto dict = base::JSONReader::Read(base::StringPrintf(
1829       R"(
1830  [ {
1831    "dns_query_type": 1,
1832    "expiration": "%s",
1833    "flags": 0,
1834    "host_resolver_source": 2,
1835    "hostname": "example.com",
1836    "network_anonymization_key": [  ],
1837    "port": 443,
1838    "scheme": "https",
1839    "secure": false
1840 } ]
1841 )",
1842       expiration_time_str.c_str()));
1843   ASSERT_TRUE(dict);
1844 
1845   HostCache restored_cache(kMaxCacheEntries);
1846   ASSERT_TRUE(dict->is_list());
1847   EXPECT_TRUE(restored_cache.RestoreFromListValue(dict->GetList()));
1848 
1849   ASSERT_EQ(1u, restored_cache.size());
1850 
1851   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1852                      DnsQueryType::A, 0, HostResolverSource::DNS,
1853                      NetworkAnonymizationKey());
1854 
1855   HostCache::EntryStaleness stale;
1856   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1857       restored_cache.LookupStale(key, base::TimeTicks::Now(), &stale);
1858 
1859   ASSERT_TRUE(result);
1860   EXPECT_THAT(result->second.aliases(), Pointee(ElementsAre()));
1861   EXPECT_THAT(result->second.ip_endpoints(), Pointee(ElementsAre()));
1862 }
1863 
TEST(HostCacheTest,DeserializeLegacyAddresses)1864 TEST(HostCacheTest, DeserializeLegacyAddresses) {
1865   base::TimeDelta ttl = base::Seconds(99);
1866   std::string expiration_time_str = base::NumberToString(
1867       (base::Time::Now() + ttl).since_origin().InMicroseconds());
1868 
1869   auto dict = base::JSONReader::Read(base::StringPrintf(
1870       R"(
1871  [ {
1872    "addresses": [ "2000::", "1.2.3.4" ],
1873    "dns_query_type": 1,
1874    "expiration": "%s",
1875    "flags": 0,
1876    "host_resolver_source": 2,
1877    "hostname": "example.com",
1878    "network_anonymization_key": [  ],
1879    "port": 443,
1880    "scheme": "https",
1881    "secure": false
1882 } ]
1883 )",
1884       expiration_time_str.c_str()));
1885   ASSERT_TRUE(dict);
1886 
1887   HostCache restored_cache(kMaxCacheEntries);
1888   ASSERT_TRUE(dict->is_list());
1889   EXPECT_TRUE(restored_cache.RestoreFromListValue(dict->GetList()));
1890 
1891   ASSERT_EQ(1u, restored_cache.size());
1892 
1893   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1894                      DnsQueryType::A, 0, HostResolverSource::DNS,
1895                      NetworkAnonymizationKey());
1896 
1897   HostCache::EntryStaleness stale;
1898   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1899       restored_cache.LookupStale(key, base::TimeTicks::Now(), &stale);
1900 
1901   ASSERT_TRUE(result);
1902   EXPECT_THAT(result->second.ip_endpoints(),
1903               Pointee(ElementsAreArray(MakeEndpoints({"2000::", "1.2.3.4"}))));
1904   EXPECT_THAT(result->second.aliases(), Pointee(ElementsAre()));
1905 }
1906 
TEST(HostCacheTest,DeserializeInvalidQueryTypeIntegrity)1907 TEST(HostCacheTest, DeserializeInvalidQueryTypeIntegrity) {
1908   base::TimeDelta ttl = base::Seconds(99);
1909   std::string expiration_time_str = base::NumberToString(
1910       (base::Time::Now() + ttl).since_origin().InMicroseconds());
1911 
1912   // RestoreFromListValue doesn't support dns_query_type=6 (INTEGRITY).
1913   auto dict = base::JSONReader::Read(base::StringPrintf(
1914       R"(
1915  [ {
1916    "addresses": [ "2000::", "1.2.3.4" ],
1917    "dns_query_type": 6,
1918    "expiration": "%s",
1919    "flags": 0,
1920    "host_resolver_source": 2,
1921    "hostname": "example.com",
1922    "network_isolation_key": [  ],
1923    "port": 443,
1924    "scheme": "https",
1925    "secure": false
1926 } ]
1927 )",
1928       expiration_time_str.c_str()));
1929   ASSERT_TRUE(dict);
1930 
1931   HostCache restored_cache(kMaxCacheEntries);
1932   ASSERT_TRUE(dict->is_list());
1933   EXPECT_FALSE(restored_cache.RestoreFromListValue(dict->GetList()));
1934 
1935   ASSERT_EQ(0u, restored_cache.size());
1936 }
1937 
TEST(HostCacheTest,DeserializeInvalidQueryTypeHttpsExperimental)1938 TEST(HostCacheTest, DeserializeInvalidQueryTypeHttpsExperimental) {
1939   base::TimeDelta ttl = base::Seconds(99);
1940   std::string expiration_time_str = base::NumberToString(
1941       (base::Time::Now() + ttl).since_origin().InMicroseconds());
1942 
1943   // RestoreFromListValue doesn't support dns_query_type=8 (HTTPS_EXPERIMENTAL).
1944   auto dict = base::JSONReader::Read(base::StringPrintf(
1945       R"(
1946  [ {
1947    "addresses": [ "2000::", "1.2.3.4" ],
1948    "dns_query_type": 8,
1949    "expiration": "%s",
1950    "flags": 0,
1951    "host_resolver_source": 2,
1952    "hostname": "example.com",
1953    "network_isolation_key": [  ],
1954    "port": 443,
1955    "scheme": "https",
1956    "secure": false
1957 } ]
1958 )",
1959       expiration_time_str.c_str()));
1960   ASSERT_TRUE(dict);
1961 
1962   HostCache restored_cache(kMaxCacheEntries);
1963   ASSERT_TRUE(dict->is_list());
1964   EXPECT_FALSE(restored_cache.RestoreFromListValue(dict->GetList()));
1965 
1966   ASSERT_EQ(0u, restored_cache.size());
1967 }
1968 
TEST(HostCacheTest,PersistenceDelegate)1969 TEST(HostCacheTest, PersistenceDelegate) {
1970   const base::TimeDelta kTTL = base::Seconds(10);
1971   HostCache cache(kMaxCacheEntries);
1972   MockPersistenceDelegate delegate;
1973   cache.set_persistence_delegate(&delegate);
1974 
1975   HostCache::Key key1 = Key("foobar.com");
1976   HostCache::Key key2 = Key("foobar2.com");
1977 
1978   HostCache::Entry ok_entry =
1979       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
1980                        HostCache::Entry::SOURCE_UNKNOWN);
1981   std::vector<IPEndPoint> other_endpoints = {
1982       IPEndPoint(IPAddress(1, 1, 1, 1), 300)};
1983   HostCache::Entry other_entry(OK, std::move(other_endpoints), /*aliases=*/{},
1984                                HostCache::Entry::SOURCE_UNKNOWN);
1985   HostCache::Entry error_entry =
1986       HostCache::Entry(ERR_NAME_NOT_RESOLVED, /*ip_endpoints=*/{},
1987                        /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1988 
1989   // Start at t=0.
1990   base::TimeTicks now;
1991   EXPECT_EQ(0u, cache.size());
1992 
1993   // Add two entries at t=0.
1994   EXPECT_FALSE(cache.Lookup(key1, now));
1995   cache.Set(key1, ok_entry, now, kTTL);
1996   EXPECT_TRUE(cache.Lookup(key1, now));
1997   EXPECT_EQ(1u, cache.size());
1998   EXPECT_EQ(1, delegate.num_changes());
1999 
2000   EXPECT_FALSE(cache.Lookup(key2, now));
2001   cache.Set(key2, error_entry, now, kTTL);
2002   EXPECT_TRUE(cache.Lookup(key2, now));
2003   EXPECT_EQ(2u, cache.size());
2004   EXPECT_EQ(2, delegate.num_changes());
2005 
2006   // Advance to t=5.
2007   now += base::Seconds(5);
2008 
2009   // Changes that shouldn't trigger a write:
2010   // Add an entry for "foobar.com" with different expiration time.
2011   EXPECT_TRUE(cache.Lookup(key1, now));
2012   cache.Set(key1, ok_entry, now, kTTL);
2013   EXPECT_TRUE(cache.Lookup(key1, now));
2014   EXPECT_EQ(2u, cache.size());
2015   EXPECT_EQ(2, delegate.num_changes());
2016 
2017   // Add an entry for "foobar.com" with different TTL.
2018   EXPECT_TRUE(cache.Lookup(key1, now));
2019   cache.Set(key1, ok_entry, now, kTTL - base::Seconds(5));
2020   EXPECT_TRUE(cache.Lookup(key1, now));
2021   EXPECT_EQ(2u, cache.size());
2022   EXPECT_EQ(2, delegate.num_changes());
2023 
2024   // Changes that should trigger a write:
2025   // Add an entry for "foobar.com" with different address list.
2026   EXPECT_TRUE(cache.Lookup(key1, now));
2027   cache.Set(key1, other_entry, now, kTTL);
2028   EXPECT_TRUE(cache.Lookup(key1, now));
2029   EXPECT_EQ(2u, cache.size());
2030   EXPECT_EQ(3, delegate.num_changes());
2031 
2032   // Add an entry for "foobar2.com" with different error.
2033   EXPECT_TRUE(cache.Lookup(key1, now));
2034   cache.Set(key2, ok_entry, now, kTTL);
2035   EXPECT_TRUE(cache.Lookup(key1, now));
2036   EXPECT_EQ(2u, cache.size());
2037   EXPECT_EQ(4, delegate.num_changes());
2038 }
2039 
TEST(HostCacheTest,MergeEndpointsWithAliases)2040 TEST(HostCacheTest, MergeEndpointsWithAliases) {
2041   const IPAddress kAddressFront(1, 2, 3, 4);
2042   const IPEndPoint kEndpointFront(kAddressFront, 0);
2043   HostCache::Entry front(OK, {kEndpointFront}, {"alias1", "alias2", "alias3"},
2044                          HostCache::Entry::SOURCE_DNS);
2045   front.set_text_records(std::vector<std::string>{"text1"});
2046   const HostPortPair kHostnameFront("host", 1);
2047   front.set_hostnames(std::vector<HostPortPair>{kHostnameFront});
2048 
2049   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2050                                0);
2051   const IPEndPoint kEndpointBack(kAddressBack, 0);
2052   HostCache::Entry back(OK, {kEndpointBack}, {"alias2", "alias4", "alias5"},
2053                         HostCache::Entry::SOURCE_DNS);
2054   back.set_text_records(std::vector<std::string>{"text2"});
2055   const HostPortPair kHostnameBack("host", 2);
2056   back.set_hostnames(std::vector<HostPortPair>{kHostnameBack});
2057 
2058   HostCache::Entry result =
2059       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2060 
2061   EXPECT_EQ(OK, result.error());
2062   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2063 
2064   ASSERT_TRUE(result.ip_endpoints());
2065   EXPECT_THAT(*result.ip_endpoints(),
2066               ElementsAre(kEndpointFront, kEndpointBack));
2067   EXPECT_THAT(result.text_records(), Optional(ElementsAre("text1", "text2")));
2068 
2069   EXPECT_THAT(result.hostnames(),
2070               Optional(ElementsAre(kHostnameFront, kHostnameBack)));
2071 
2072   ASSERT_TRUE(result.aliases());
2073   EXPECT_THAT(
2074       *result.aliases(),
2075       UnorderedElementsAre("alias1", "alias2", "alias3", "alias4", "alias5"));
2076 }
2077 
TEST(HostCacheTest,MergeEndpointsKeepEndpointsOrder)2078 TEST(HostCacheTest, MergeEndpointsKeepEndpointsOrder) {
2079   std::vector<IPEndPoint> front_addresses =
2080       MakeEndpoints({"::1", "0.0.0.2", "0.0.0.4"});
2081   std::vector<IPEndPoint> back_addresses =
2082       MakeEndpoints({"0.0.0.2", "0.0.0.2", "::3", "::3", "0.0.0.4"});
2083 
2084   HostCache::Entry front(OK, front_addresses, /*aliases=*/{"front"},
2085                          HostCache::Entry::SOURCE_DNS);
2086   HostCache::Entry back(OK, back_addresses, /*aliases=*/{"back"},
2087                         HostCache::Entry::SOURCE_DNS);
2088 
2089   HostCache::Entry result =
2090       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2091 
2092   ASSERT_TRUE(result.ip_endpoints());
2093   EXPECT_THAT(
2094       *result.ip_endpoints(),
2095       ElementsAreArray(MakeEndpoints({"::1", "0.0.0.2", "0.0.0.4", "0.0.0.2",
2096                                       "0.0.0.2", "::3", "::3", "0.0.0.4"})));
2097   ASSERT_TRUE(result.aliases());
2098   EXPECT_THAT(*result.aliases(), UnorderedElementsAre("front", "back"));
2099 }
2100 
TEST(HostCacheTest,MergeMetadatas)2101 TEST(HostCacheTest, MergeMetadatas) {
2102   ConnectionEndpointMetadata front_metadata;
2103   front_metadata.supported_protocol_alpns = {"h5", "h6", "monster truck rally"};
2104   front_metadata.ech_config_list = {'h', 'i'};
2105   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2106       front_metadata_map{{4u, front_metadata}};
2107   HostCache::Entry front(OK, front_metadata_map, HostCache::Entry::SOURCE_DNS);
2108 
2109   ConnectionEndpointMetadata back_metadata;
2110   back_metadata.supported_protocol_alpns = {"h5"};
2111   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2112       back_metadata_map{{2u, back_metadata}};
2113   HostCache::Entry back(OK, back_metadata_map, HostCache::Entry::SOURCE_DNS);
2114 
2115   HostCache::Entry result = HostCache::Entry::MergeEntries(front, back);
2116 
2117   // Expect `GetEndpoints()` to ignore metadatas if no `IPEndPoint`s.
2118   EXPECT_FALSE(result.GetEndpoints());
2119 
2120   // Expect order irrelevant for endpoint metadata merging.
2121   result = HostCache::Entry::MergeEntries(back, front);
2122   EXPECT_FALSE(result.GetEndpoints());
2123 }
2124 
TEST(HostCacheTest,MergeMetadatasWithIpEndpointsDifferentCanonicalName)2125 TEST(HostCacheTest, MergeMetadatasWithIpEndpointsDifferentCanonicalName) {
2126   std::string target_name = "example.com";
2127   std::string other_target_name = "other.example.com";
2128   ConnectionEndpointMetadata metadata;
2129   metadata.supported_protocol_alpns = {"h5", "h6", "monster truck rally"};
2130   metadata.ech_config_list = {'h', 'i'};
2131   metadata.target_name = target_name;
2132 
2133   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadata_map{
2134       {4u, metadata}};
2135   HostCache::Entry metadata_entry(OK, metadata_map,
2136                                   HostCache::Entry::SOURCE_DNS);
2137 
2138   // Expect `GetEndpoints()` to always ignore metadatas with no `IPEndPoint`s.
2139   EXPECT_FALSE(metadata_entry.GetEndpoints());
2140 
2141   // Merge in an `IPEndPoint` with different canonical name.
2142   IPEndPoint ip_endpoint(IPAddress(1, 1, 1, 1), 0);
2143   HostCache::Entry with_ip_endpoint(OK, {ip_endpoint}, /*aliases=*/{},
2144                                     HostCache::Entry::SOURCE_DNS);
2145   with_ip_endpoint.set_canonical_names(
2146       std::set<std::string>{other_target_name});
2147   HostCache::Entry result =
2148       HostCache::Entry::MergeEntries(metadata_entry, with_ip_endpoint);
2149 
2150   // Expect `GetEndpoints()` not to return the metadata.
2151   EXPECT_THAT(result.GetEndpoints(),
2152               Optional(ElementsAre(
2153                   ExpectEndpointResult(std::vector<IPEndPoint>{ip_endpoint}))));
2154 
2155   // Expect merge order irrelevant.
2156   EXPECT_EQ(result,
2157             HostCache::Entry::MergeEntries(with_ip_endpoint, metadata_entry));
2158 }
2159 
TEST(HostCacheTest,MergeMetadatasWithIpEndpointsMatchingCanonicalName)2160 TEST(HostCacheTest, MergeMetadatasWithIpEndpointsMatchingCanonicalName) {
2161   std::string target_name = "example.com";
2162   ConnectionEndpointMetadata metadata;
2163   metadata.supported_protocol_alpns = {"h5", "h6", "monster truck rally"};
2164   metadata.ech_config_list = {'h', 'i'};
2165   metadata.target_name = target_name;
2166 
2167   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadata_map{
2168       {4u, metadata}};
2169   HostCache::Entry metadata_entry(OK, metadata_map,
2170                                   HostCache::Entry::SOURCE_DNS);
2171 
2172   // Expect `GetEndpoints()` to always ignore metadatas with no `IPEndPoint`s.
2173   EXPECT_FALSE(metadata_entry.GetEndpoints());
2174 
2175   // Merge in an `IPEndPoint` with different canonical name.
2176   IPEndPoint ip_endpoint(IPAddress(1, 1, 1, 1), 0);
2177   HostCache::Entry with_ip_endpoint(OK, {ip_endpoint}, /*aliases=*/{},
2178                                     HostCache::Entry::SOURCE_DNS);
2179   with_ip_endpoint.set_canonical_names(std::set<std::string>{target_name});
2180   HostCache::Entry result =
2181       HostCache::Entry::MergeEntries(metadata_entry, with_ip_endpoint);
2182 
2183   // Expect `GetEndpoints()` to return the metadata.
2184   EXPECT_THAT(result.GetEndpoints(),
2185               Optional(ElementsAre(
2186                   ExpectEndpointResult(ElementsAre(ip_endpoint), metadata),
2187                   ExpectEndpointResult(ElementsAre(ip_endpoint)))));
2188 
2189   // Expect merge order irrelevant.
2190   EXPECT_EQ(result,
2191             HostCache::Entry::MergeEntries(with_ip_endpoint, metadata_entry));
2192 }
2193 
TEST(HostCacheTest,MergeMultipleMetadatasWithIpEndpoints)2194 TEST(HostCacheTest, MergeMultipleMetadatasWithIpEndpoints) {
2195   std::string target_name = "example.com";
2196   ConnectionEndpointMetadata front_metadata;
2197   front_metadata.supported_protocol_alpns = {"h5", "h6", "monster truck rally"};
2198   front_metadata.ech_config_list = {'h', 'i'};
2199   front_metadata.target_name = target_name;
2200 
2201   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2202       front_metadata_map{{4u, front_metadata}};
2203   HostCache::Entry front(OK, front_metadata_map, HostCache::Entry::SOURCE_DNS);
2204 
2205   ConnectionEndpointMetadata back_metadata;
2206   back_metadata.supported_protocol_alpns = {"h5"};
2207   back_metadata.target_name = target_name;
2208   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2209       back_metadata_map{{2u, back_metadata}};
2210   HostCache::Entry back(OK, back_metadata_map, HostCache::Entry::SOURCE_DNS);
2211 
2212   HostCache::Entry merged_metadatas =
2213       HostCache::Entry::MergeEntries(front, back);
2214   HostCache::Entry reversed_merged_metadatas =
2215       HostCache::Entry::MergeEntries(back, front);
2216 
2217   // Expect `GetEndpoints()` to always ignore metadatas with no `IPEndPoint`s.
2218   EXPECT_FALSE(merged_metadatas.GetEndpoints());
2219   EXPECT_FALSE(reversed_merged_metadatas.GetEndpoints());
2220 
2221   // Merge in an `IPEndPoint`.
2222   IPEndPoint ip_endpoint(IPAddress(1, 1, 1, 1), 0);
2223   HostCache::Entry with_ip_endpoint(OK, {ip_endpoint}, /*aliases=*/{},
2224                                     HostCache::Entry::SOURCE_DNS);
2225   with_ip_endpoint.set_canonical_names(std::set<std::string>{target_name});
2226 
2227   HostCache::Entry result =
2228       HostCache::Entry::MergeEntries(merged_metadatas, with_ip_endpoint);
2229 
2230   // Expect `back_metadata` before `front_metadata` because it has lower
2231   // priority number.
2232   EXPECT_THAT(
2233       result.GetEndpoints(),
2234       Optional(ElementsAre(
2235           ExpectEndpointResult(ElementsAre(ip_endpoint), back_metadata),
2236           ExpectEndpointResult(ElementsAre(ip_endpoint), front_metadata),
2237           ExpectEndpointResult(ElementsAre(ip_endpoint)))));
2238 
2239   // Expect merge order irrelevant.
2240   EXPECT_EQ(result, HostCache::Entry::MergeEntries(reversed_merged_metadatas,
2241                                                    with_ip_endpoint));
2242   EXPECT_EQ(result,
2243             HostCache::Entry::MergeEntries(with_ip_endpoint, merged_metadatas));
2244   EXPECT_EQ(result, HostCache::Entry::MergeEntries(with_ip_endpoint,
2245                                                    reversed_merged_metadatas));
2246 }
2247 
TEST(HostCacheTest,MergeAliases)2248 TEST(HostCacheTest, MergeAliases) {
2249   HostCache::Entry front(OK, /*ip_endpoints=*/{},
2250                          /*aliases=*/{"foo1.test", "foo2.test", "foo3.test"},
2251                          HostCache::Entry::SOURCE_DNS);
2252 
2253   HostCache::Entry back(OK, /*ip_endpoints=*/{},
2254                         /*aliases=*/{"foo2.test", "foo4.test"},
2255                         HostCache::Entry::SOURCE_DNS);
2256 
2257   HostCache::Entry expected(
2258       OK, /*ip_endpoints=*/{},
2259       /*aliases=*/{"foo1.test", "foo2.test", "foo3.test", "foo4.test"},
2260       HostCache::Entry::SOURCE_DNS);
2261 
2262   HostCache::Entry result = HostCache::Entry::MergeEntries(front, back);
2263   EXPECT_EQ(result, expected);
2264 
2265   // Expect order irrelevant for alias merging.
2266   result = HostCache::Entry::MergeEntries(back, front);
2267   EXPECT_EQ(result, expected);
2268 }
2269 
TEST(HostCacheTest,MergeEntries_frontEmpty)2270 TEST(HostCacheTest, MergeEntries_frontEmpty) {
2271   HostCache::Entry front(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2272 
2273   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2274                                0);
2275   const IPEndPoint kEndpointBack(kAddressBack, 0);
2276   HostCache::Entry back(OK, {kEndpointBack}, {"alias1", "alias2", "alias3"},
2277                         HostCache::Entry::SOURCE_DNS, base::Hours(4));
2278   back.set_text_records(std::vector<std::string>{"text2"});
2279   const HostPortPair kHostnameBack("host", 2);
2280   back.set_hostnames(std::vector<HostPortPair>{kHostnameBack});
2281 
2282   HostCache::Entry result =
2283       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2284 
2285   EXPECT_EQ(OK, result.error());
2286   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2287 
2288   ASSERT_TRUE(result.ip_endpoints());
2289   EXPECT_THAT(*result.ip_endpoints(), ElementsAre(kEndpointBack));
2290   EXPECT_THAT(result.text_records(), Optional(ElementsAre("text2")));
2291   EXPECT_THAT(result.hostnames(), Optional(ElementsAre(kHostnameBack)));
2292 
2293   EXPECT_EQ(base::Hours(4), result.ttl());
2294 
2295   ASSERT_TRUE(result.aliases());
2296   EXPECT_THAT(*result.aliases(),
2297               UnorderedElementsAre("alias1", "alias2", "alias3"));
2298 }
2299 
TEST(HostCacheTest,MergeEntries_backEmpty)2300 TEST(HostCacheTest, MergeEntries_backEmpty) {
2301   const IPAddress kAddressFront(1, 2, 3, 4);
2302   const IPEndPoint kEndpointFront(kAddressFront, 0);
2303   HostCache::Entry front(OK, {kEndpointFront}, {"alias1", "alias2", "alias3"},
2304                          HostCache::Entry::SOURCE_DNS, base::Minutes(5));
2305   front.set_text_records(std::vector<std::string>{"text1"});
2306   const HostPortPair kHostnameFront("host", 1);
2307   front.set_hostnames(std::vector<HostPortPair>{kHostnameFront});
2308 
2309   HostCache::Entry back(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2310 
2311   HostCache::Entry result =
2312       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2313 
2314   EXPECT_EQ(OK, result.error());
2315   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2316 
2317   ASSERT_TRUE(result.ip_endpoints());
2318   EXPECT_THAT(*result.ip_endpoints(), ElementsAre(kEndpointFront));
2319   EXPECT_THAT(result.text_records(), Optional(ElementsAre("text1")));
2320   EXPECT_THAT(result.hostnames(), Optional(ElementsAre(kHostnameFront)));
2321 
2322   EXPECT_EQ(base::Minutes(5), result.ttl());
2323 
2324   ASSERT_TRUE(result.aliases());
2325   EXPECT_THAT(*result.aliases(),
2326               UnorderedElementsAre("alias1", "alias2", "alias3"));
2327 }
2328 
TEST(HostCacheTest,MergeEntries_bothEmpty)2329 TEST(HostCacheTest, MergeEntries_bothEmpty) {
2330   HostCache::Entry front(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2331   HostCache::Entry back(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2332 
2333   HostCache::Entry result =
2334       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2335 
2336   EXPECT_EQ(ERR_NAME_NOT_RESOLVED, result.error());
2337   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2338 
2339   EXPECT_FALSE(result.ip_endpoints());
2340   EXPECT_FALSE(result.text_records());
2341   EXPECT_FALSE(result.hostnames());
2342   EXPECT_FALSE(result.has_ttl());
2343 }
2344 
TEST(HostCacheTest,MergeEntries_frontWithAliasesNoAddressesBackWithBoth)2345 TEST(HostCacheTest, MergeEntries_frontWithAliasesNoAddressesBackWithBoth) {
2346   HostCache::Entry front(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2347   std::set<std::string> aliases_front({"alias0", "alias1", "alias2"});
2348   front.set_aliases(aliases_front);
2349 
2350   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2351                                0);
2352   const IPEndPoint kEndpointBack(kAddressBack, 0);
2353   HostCache::Entry back(OK, {kEndpointBack}, {"alias1", "alias2", "alias3"},
2354                         HostCache::Entry::SOURCE_DNS, base::Hours(4));
2355 
2356   HostCache::Entry result =
2357       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2358 
2359   EXPECT_EQ(OK, result.error());
2360   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2361 
2362   ASSERT_TRUE(result.ip_endpoints());
2363   EXPECT_THAT(*result.ip_endpoints(), ElementsAre(kEndpointBack));
2364 
2365   EXPECT_EQ(base::Hours(4), result.ttl());
2366 
2367   ASSERT_TRUE(result.aliases());
2368   EXPECT_THAT(*result.aliases(),
2369               UnorderedElementsAre("alias0", "alias1", "alias2", "alias3"));
2370 }
2371 
TEST(HostCacheTest,MergeEntries_backWithAliasesNoAddressesFrontWithBoth)2372 TEST(HostCacheTest, MergeEntries_backWithAliasesNoAddressesFrontWithBoth) {
2373   HostCache::Entry back(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2374   std::set<std::string> aliases_back({"alias1", "alias2", "alias3"});
2375   back.set_aliases(aliases_back);
2376 
2377   const IPAddress kAddressFront(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2378                                 0);
2379   const IPEndPoint kEndpointFront(kAddressFront, 0);
2380   HostCache::Entry front(OK, {kEndpointFront}, {"alias0", "alias1", "alias2"},
2381                          HostCache::Entry::SOURCE_DNS, base::Hours(4));
2382 
2383   HostCache::Entry result =
2384       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2385 
2386   EXPECT_EQ(OK, result.error());
2387   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2388 
2389   ASSERT_TRUE(result.ip_endpoints());
2390   EXPECT_THAT(*result.ip_endpoints(), ElementsAre(kEndpointFront));
2391 
2392   EXPECT_EQ(base::Hours(4), result.ttl());
2393 
2394   ASSERT_TRUE(result.aliases());
2395   EXPECT_THAT(*result.aliases(),
2396               UnorderedElementsAre("alias0", "alias1", "alias2", "alias3"));
2397 }
2398 
TEST(HostCacheTest,MergeEntries_frontWithAddressesNoAliasesBackWithBoth)2399 TEST(HostCacheTest, MergeEntries_frontWithAddressesNoAliasesBackWithBoth) {
2400   const IPAddress kAddressFront(1, 2, 3, 4);
2401   const IPEndPoint kEndpointFront(kAddressFront, 0);
2402   HostCache::Entry front(OK, {kEndpointFront}, /*aliases=*/{},
2403                          HostCache::Entry::SOURCE_DNS, base::Hours(4));
2404 
2405   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2406                                0);
2407   const IPEndPoint kEndpointBack(kAddressBack, 0);
2408   HostCache::Entry back(OK, {kEndpointBack}, {"alias1", "alias2", "alias3"},
2409                         HostCache::Entry::SOURCE_DNS, base::Hours(4));
2410   HostCache::Entry result =
2411       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2412 
2413   EXPECT_EQ(OK, result.error());
2414   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2415 
2416   ASSERT_TRUE(result.ip_endpoints());
2417   EXPECT_THAT(*result.ip_endpoints(),
2418               ElementsAre(kEndpointFront, kEndpointBack));
2419 
2420   EXPECT_EQ(base::Hours(4), result.ttl());
2421 
2422   ASSERT_TRUE(result.aliases());
2423   EXPECT_THAT(*result.aliases(),
2424               UnorderedElementsAre("alias1", "alias2", "alias3"));
2425 }
2426 
TEST(HostCacheTest,MergeEntries_backWithAddressesNoAliasesFrontWithBoth)2427 TEST(HostCacheTest, MergeEntries_backWithAddressesNoAliasesFrontWithBoth) {
2428   const IPAddress kAddressFront(1, 2, 3, 4);
2429   const IPEndPoint kEndpointFront(kAddressFront, 0);
2430   HostCache::Entry front(OK, {kEndpointFront}, {"alias1", "alias2", "alias3"},
2431                          HostCache::Entry::SOURCE_DNS, base::Hours(4));
2432   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2433                                0);
2434   const IPEndPoint kEndpointBack(kAddressBack, 0);
2435   HostCache::Entry back(OK, {kEndpointBack}, /*aliases=*/{},
2436                         HostCache::Entry::SOURCE_DNS, base::Hours(4));
2437 
2438   HostCache::Entry result =
2439       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2440 
2441   EXPECT_EQ(OK, result.error());
2442   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2443 
2444   ASSERT_TRUE(result.ip_endpoints());
2445   EXPECT_THAT(*result.ip_endpoints(),
2446               ElementsAre(kEndpointFront, kEndpointBack));
2447 
2448   EXPECT_EQ(base::Hours(4), result.ttl());
2449 
2450   ASSERT_TRUE(result.aliases());
2451   EXPECT_THAT(*result.aliases(),
2452               UnorderedElementsAre("alias1", "alias2", "alias3"));
2453 }
2454 
TEST(HostCacheTest,MergeEntries_differentTtl)2455 TEST(HostCacheTest, MergeEntries_differentTtl) {
2456   HostCache::Entry front(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS,
2457                          base::Days(12));
2458   HostCache::Entry back(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS,
2459                         base::Seconds(42));
2460 
2461   HostCache::Entry result =
2462       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2463 
2464   EXPECT_EQ(base::Seconds(42), result.ttl());
2465 }
2466 
TEST(HostCacheTest,MergeEntries_FrontCannonnamePreserved)2467 TEST(HostCacheTest, MergeEntries_FrontCannonnamePreserved) {
2468   HostCache::Entry front(OK, /*ip_endpoints=*/{}, /*aliases=*/{"name1"},
2469                          HostCache::Entry::SOURCE_DNS);
2470 
2471   HostCache::Entry back(OK, /*ip_endpoints=*/{}, /*aliases=*/{"name2"},
2472                         HostCache::Entry::SOURCE_DNS);
2473 
2474   HostCache::Entry result =
2475       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2476 
2477   ASSERT_TRUE(result.aliases());
2478   EXPECT_THAT(*result.aliases(), UnorderedElementsAre("name1", "name2"));
2479 }
2480 
2481 // Test that the back canonname can be used if there is no front cannonname.
TEST(HostCacheTest,MergeEntries_BackCannonnameUsable)2482 TEST(HostCacheTest, MergeEntries_BackCannonnameUsable) {
2483   HostCache::Entry front(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
2484                          HostCache::Entry::SOURCE_DNS);
2485 
2486   HostCache::Entry back(OK, /*ip_endpoints=*/{}, /*aliases=*/{"name2"},
2487                         HostCache::Entry::SOURCE_DNS);
2488 
2489   HostCache::Entry result =
2490       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2491 
2492   ASSERT_TRUE(result.aliases());
2493   EXPECT_THAT(*result.aliases(), UnorderedElementsAre("name2"));
2494 }
2495 
TEST(HostCacheTest,ConvertFromInternalAddressResult)2496 TEST(HostCacheTest, ConvertFromInternalAddressResult) {
2497   const std::vector<IPEndPoint> kEndpoints{
2498       IPEndPoint(IPAddress(2, 2, 2, 2), 46)};
2499   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2500   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2501   constexpr base::TimeDelta kTtl3 = base::Minutes(55);
2502 
2503   std::vector<std::unique_ptr<HostResolverInternalResult>> results;
2504   results.push_back(std::make_unique<HostResolverInternalDataResult>(
2505       "endpoint.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl1,
2506       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2507       kEndpoints, std::vector<std::string>{}, std::vector<HostPortPair>{}));
2508   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2509       "domain1.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl2,
2510       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2511       "domain2.test"));
2512   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2513       "domain2.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl3,
2514       base::Time() + kTtl3, HostResolverInternalResult::Source::kDns,
2515       "endpoint.test"));
2516 
2517   HostCache::Entry converted(std::move(results), base::Time(),
2518                              base::TimeTicks());
2519 
2520   // Expect kTtl2 because it is the min TTL.
2521   HostCache::Entry expected(
2522       OK, kEndpoints,
2523       /*aliases=*/{"domain1.test", "domain2.test", "endpoint.test"},
2524       HostCache::Entry::SOURCE_DNS, kTtl2);
2525   expected.set_canonical_names(std::set<std::string>{"endpoint.test"});
2526 
2527   // Entries converted from HostResolverInternalDataResults do not differentiate
2528   // between empty and no-data for the various data types, so need to set empty
2529   // strings and hostname entries into `expected`.
2530   expected.set_text_records(std::vector<std::string>());
2531   expected.set_hostnames(std::vector<HostPortPair>());
2532 
2533   EXPECT_EQ(converted, expected);
2534 }
2535 
TEST(HostCacheTest,ConvertFromInternalMetadataResult)2536 TEST(HostCacheTest, ConvertFromInternalMetadataResult) {
2537   const std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2538       kMetadatas{{1, ConnectionEndpointMetadata({"h2", "h3"},
2539                                                 /*ech_config_list=*/{},
2540                                                 "target.test")}};
2541   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2542   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2543   constexpr base::TimeDelta kTtl3 = base::Minutes(55);
2544 
2545   std::vector<std::unique_ptr<HostResolverInternalResult>> results;
2546   results.push_back(std::make_unique<HostResolverInternalMetadataResult>(
2547       "endpoint.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl1,
2548       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2549       kMetadatas));
2550   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2551       "domain1.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl2,
2552       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2553       "domain2.test"));
2554   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2555       "domain2.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl3,
2556       base::Time() + kTtl3, HostResolverInternalResult::Source::kDns,
2557       "endpoint.test"));
2558 
2559   HostCache::Entry converted(std::move(results), base::Time(),
2560                              base::TimeTicks());
2561 
2562   // Expect kTtl2 because it is the min TTL.
2563   HostCache::Entry expected(OK, kMetadatas, HostCache::Entry::SOURCE_DNS,
2564                             kTtl2);
2565   expected.set_https_record_compatibility(std::vector<bool>{true});
2566 
2567   EXPECT_EQ(converted, expected);
2568 }
2569 
2570 // Test the case of compatible HTTPS records but no metadata of use to Chrome.
2571 // Represented in internal result type as an empty metadata result. Represented
2572 // in HostCache::Entry as empty metadata with at least one true in
2573 // `https_record_compatibility_`.
TEST(HostCacheTest,ConvertFromCompatibleOnlyInternalMetadataResult)2574 TEST(HostCacheTest, ConvertFromCompatibleOnlyInternalMetadataResult) {
2575   const std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2576       kMetadatas;
2577   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2578   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2579   constexpr base::TimeDelta kTtl3 = base::Minutes(55);
2580 
2581   std::vector<std::unique_ptr<HostResolverInternalResult>> results;
2582   results.push_back(std::make_unique<HostResolverInternalMetadataResult>(
2583       "endpoint.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl1,
2584       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2585       kMetadatas));
2586   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2587       "domain1.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl2,
2588       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2589       "domain2.test"));
2590   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2591       "domain2.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl3,
2592       base::Time() + kTtl3, HostResolverInternalResult::Source::kDns,
2593       "endpoint.test"));
2594 
2595   HostCache::Entry converted(std::move(results), base::Time(),
2596                              base::TimeTicks());
2597 
2598   // Expect kTtl2 because it is the min TTL.
2599   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED, kMetadatas,
2600                             HostCache::Entry::SOURCE_DNS, kTtl2);
2601   expected.set_https_record_compatibility(std::vector<bool>{true});
2602 
2603   EXPECT_EQ(converted, expected);
2604 }
2605 
TEST(HostCacheTest,ConvertFromInternalErrorResult)2606 TEST(HostCacheTest, ConvertFromInternalErrorResult) {
2607   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2608   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2609   constexpr base::TimeDelta kTtl3 = base::Minutes(55);
2610 
2611   std::vector<std::unique_ptr<HostResolverInternalResult>> results;
2612   results.push_back(std::make_unique<HostResolverInternalErrorResult>(
2613       "endpoint.test", DnsQueryType::A, base::TimeTicks() + kTtl1,
2614       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2615       ERR_NAME_NOT_RESOLVED));
2616   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2617       "domain1.test", DnsQueryType::A, base::TimeTicks() + kTtl2,
2618       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2619       "domain2.test"));
2620   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2621       "domain2.test", DnsQueryType::A, base::TimeTicks() + kTtl3,
2622       base::Time() + kTtl3, HostResolverInternalResult::Source::kDns,
2623       "endpoint.test"));
2624 
2625   HostCache::Entry converted(std::move(results), base::Time(),
2626                              base::TimeTicks());
2627 
2628   // Expect kTtl2 because it is the min TTL.
2629   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS,
2630                             kTtl2);
2631 
2632   EXPECT_EQ(converted, expected);
2633 }
2634 
TEST(HostCacheTest,ConvertFromNonCachableInternalErrorResult)2635 TEST(HostCacheTest, ConvertFromNonCachableInternalErrorResult) {
2636   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2637   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2638 
2639   std::vector<std::unique_ptr<HostResolverInternalResult>> results;
2640   results.push_back(std::make_unique<HostResolverInternalErrorResult>(
2641       "endpoint.test", DnsQueryType::AAAA, /*expiration=*/absl::nullopt,
2642       /*timed_expiration=*/absl::nullopt,
2643       HostResolverInternalResult::Source::kDns, ERR_NAME_NOT_RESOLVED));
2644   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2645       "domain1.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl1,
2646       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2647       "domain2.test"));
2648   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2649       "domain2.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl2,
2650       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2651       "endpoint.test"));
2652 
2653   HostCache::Entry converted(std::move(results), base::Time(),
2654                              base::TimeTicks());
2655 
2656   // Expect no TTL because error is non-cachable (has no TTL itself).
2657   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED,
2658                             HostCache::Entry::SOURCE_DNS);
2659 
2660   EXPECT_EQ(converted, expected);
2661 }
2662 
TEST(HostCacheTest,ConvertFromInternalAliasOnlyResult)2663 TEST(HostCacheTest, ConvertFromInternalAliasOnlyResult) {
2664   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2665   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2666 
2667   std::vector<std::unique_ptr<HostResolverInternalResult>> results;
2668   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2669       "domain1.test", DnsQueryType::A, base::TimeTicks() + kTtl1,
2670       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2671       "domain2.test"));
2672   results.push_back(std::make_unique<HostResolverInternalAliasResult>(
2673       "domain2.test", DnsQueryType::A, base::TimeTicks() + kTtl2,
2674       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2675       "endpoint.test"));
2676 
2677   HostCache::Entry converted(std::move(results), base::Time(),
2678                              base::TimeTicks());
2679 
2680   // Expect no TTL because alias-only results are not cacheable.
2681   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED,
2682                             HostCache::Entry::SOURCE_DNS);
2683 
2684   EXPECT_EQ(converted, expected);
2685 }
2686 
TEST(HostCacheTest,ConvertFromEmptyInternalResult)2687 TEST(HostCacheTest, ConvertFromEmptyInternalResult) {
2688   HostCache::Entry converted({}, base::Time(), base::TimeTicks());
2689   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED,
2690                             HostCache::Entry::SOURCE_UNKNOWN);
2691 
2692   EXPECT_EQ(converted, expected);
2693 }
2694 
2695 }  // namespace net
2696