• 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               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(), 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(), IsEmpty());
198 }
199 
TEST(HostCacheTest,GetMissingEndpoints)200 TEST(HostCacheTest, GetMissingEndpoints) {
201   HostCache::Entry entry(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
202   EXPECT_THAT(entry.GetEndpoints(), IsEmpty());
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 empty.
220   EXPECT_THAT(merged_entry.GetEndpoints(), IsEmpty());
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(result1.GetEndpoints(),
1015               ElementsAre(ExpectEndpointResult(ElementsAre(endpoint1))));
1016   EXPECT_THAT(result1.pinning(), Optional(true));
1017 
1018   // Insert |entry2|, and verify that it when it is retrieved, it
1019   // has the new IP, and the "pinned" flag copied from |entry1|.
1020   cache.Set(key, entry2, now, base::Seconds(10));
1021   const auto* pair2 = cache.Lookup(key, now);
1022   ASSERT_TRUE(pair2);
1023   const HostCache::Entry& result2 = pair2->second;
1024   EXPECT_THAT(result2.GetEndpoints(),
1025               ElementsAre(ExpectEndpointResult(ElementsAre(endpoint2))));
1026   EXPECT_THAT(result2.pinning(), Optional(true));
1027 }
1028 
1029 // An obsolete cache pin is not preserved if the record is replaced.
TEST(HostCacheTest,DontPreserveObsoletePin)1030 TEST(HostCacheTest, DontPreserveObsoletePin) {
1031   HostCache cache(2);
1032 
1033   base::TimeTicks now;
1034 
1035   // Make entry1 and entry2, identical except for IP and "pinned" flag.
1036   IPEndPoint endpoint1(IPAddress(192, 0, 2, 1), 0);
1037   IPEndPoint endpoint2(IPAddress(192, 0, 2, 2), 0);
1038   HostCache::Entry entry1 = HostCache::Entry(OK, {endpoint1}, /*aliases=*/{},
1039                                              HostCache::Entry::SOURCE_UNKNOWN);
1040   HostCache::Entry entry2 = HostCache::Entry(OK, {endpoint2}, /*aliases=*/{},
1041                                              HostCache::Entry::SOURCE_UNKNOWN);
1042   entry1.set_pinning(true);
1043 
1044   HostCache::Key key = Key("foobar.com");
1045 
1046   // Insert entry1, and verify that it can be retrieved with the
1047   // correct IP and |pinning()| == true.
1048   cache.Set(key, entry1, now, base::Seconds(10));
1049   const auto* pair1 = cache.Lookup(key, now);
1050   ASSERT_TRUE(pair1);
1051   const HostCache::Entry& result1 = pair1->second;
1052   EXPECT_THAT(result1.GetEndpoints(),
1053               ElementsAre(ExpectEndpointResult(ElementsAre(endpoint1))));
1054   EXPECT_THAT(result1.pinning(), Optional(true));
1055 
1056   // Make entry1 obsolete.
1057   cache.Invalidate();
1058 
1059   // Insert |entry2|, and verify that it when it is retrieved, it
1060   // has the new IP, and the "pinned" flag is not copied from |entry1|.
1061   cache.Set(key, entry2, now, base::Seconds(10));
1062   const auto* pair2 = cache.Lookup(key, now);
1063   ASSERT_TRUE(pair2);
1064   const HostCache::Entry& result2 = pair2->second;
1065   EXPECT_THAT(result2.GetEndpoints(),
1066               ElementsAre(ExpectEndpointResult(ElementsAre(endpoint2))));
1067   EXPECT_THAT(result2.pinning(), Optional(false));
1068 }
1069 
1070 // An active pin is removed if the record is replaced by a Set() call
1071 // with the pin flag set to false.
TEST(HostCacheTest,Unpin)1072 TEST(HostCacheTest, Unpin) {
1073   HostCache cache(2);
1074 
1075   base::TimeTicks now;
1076 
1077   // Make entry1 and entry2, identical except for IP and pinned flag.
1078   IPEndPoint endpoint1(IPAddress(192, 0, 2, 1), 0);
1079   IPEndPoint endpoint2(IPAddress(192, 0, 2, 2), 0);
1080   HostCache::Entry entry1 = HostCache::Entry(OK, {endpoint1}, /*aliases=*/{},
1081                                              HostCache::Entry::SOURCE_UNKNOWN);
1082   HostCache::Entry entry2 = HostCache::Entry(OK, {endpoint2}, /*aliases=*/{},
1083                                              HostCache::Entry::SOURCE_UNKNOWN);
1084   entry1.set_pinning(true);
1085   entry2.set_pinning(false);
1086 
1087   HostCache::Key key = Key("foobar.com");
1088 
1089   // Insert entry1, and verify that it can be retrieved with the
1090   // correct IP and |pinning()| == true.
1091   cache.Set(key, entry1, now, base::Seconds(10));
1092   const auto* pair1 = cache.Lookup(key, now);
1093   ASSERT_TRUE(pair1);
1094   const HostCache::Entry& result1 = pair1->second;
1095   EXPECT_THAT(result1.GetEndpoints(),
1096               ElementsAre(ExpectEndpointResult(ElementsAre(endpoint1))));
1097   EXPECT_THAT(result1.pinning(), Optional(true));
1098 
1099   // Insert |entry2|, and verify that it when it is retrieved, it
1100   // has the new IP, and the "pinned" flag is now false.
1101   cache.Set(key, entry2, now, base::Seconds(10));
1102   const auto* pair2 = cache.Lookup(key, now);
1103   ASSERT_TRUE(pair2);
1104   const HostCache::Entry& result2 = pair2->second;
1105   EXPECT_THAT(result2.GetEndpoints(),
1106               ElementsAre(ExpectEndpointResult(ElementsAre(endpoint2))));
1107   EXPECT_THAT(result2.pinning(), Optional(false));
1108 }
1109 
1110 // Tests the less than and equal operators for HostCache::Key work.
TEST(HostCacheTest,KeyComparators)1111 TEST(HostCacheTest, KeyComparators) {
1112   struct CacheTestParameters {
1113     CacheTestParameters(const HostCache::Key key1,
1114                         const HostCache::Key key2,
1115                         int expected_comparison)
1116         : key1(key1), key2(key2), expected_comparison(expected_comparison) {}
1117 
1118     // Inputs.
1119     HostCache::Key key1;
1120     HostCache::Key key2;
1121 
1122     // Expectation.
1123     //   -1 means key1 is less than key2
1124     //    0 means key1 equals key2
1125     //    1 means key1 is greater than key2
1126     int expected_comparison;
1127   };
1128   std::vector<CacheTestParameters> tests = {
1129       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1130                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1131                       NetworkAnonymizationKey()),
1132        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1133                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1134                       NetworkAnonymizationKey()),
1135        0},
1136       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1137                       DnsQueryType::A, 0, HostResolverSource::ANY,
1138                       NetworkAnonymizationKey()),
1139        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1140                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1141                       NetworkAnonymizationKey()),
1142        1},
1143       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1144                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1145                       NetworkAnonymizationKey()),
1146        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1147                       DnsQueryType::A, 0, HostResolverSource::ANY,
1148                       NetworkAnonymizationKey()),
1149        -1},
1150       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1151                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1152                       NetworkAnonymizationKey()),
1153        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
1154                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1155                       NetworkAnonymizationKey()),
1156        -1},
1157       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1158                       DnsQueryType::A, 0, HostResolverSource::ANY,
1159                       NetworkAnonymizationKey()),
1160        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
1161                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1162                       NetworkAnonymizationKey()),
1163        1},
1164       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1165                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1166                       NetworkAnonymizationKey()),
1167        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
1168                       DnsQueryType::A, 0, HostResolverSource::ANY,
1169                       NetworkAnonymizationKey()),
1170        -1},
1171       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1172                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1173                       NetworkAnonymizationKey()),
1174        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1175                       DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
1176                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1177        -1},
1178       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1179                       DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
1180                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1181        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1182                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1183                       NetworkAnonymizationKey()),
1184        1},
1185       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1186                       DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
1187                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1188        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
1189                       DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
1190                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1191        -1},
1192       // 9: Different host scheme.
1193       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1194                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1195                       NetworkAnonymizationKey()),
1196        HostCache::Key(url::SchemeHostPort(url::kHttpScheme, "host1", 443),
1197                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1198                       NetworkAnonymizationKey()),
1199        1},
1200       // 10: Different host port.
1201       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1202                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1203                       NetworkAnonymizationKey()),
1204        HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 1544),
1205                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1206                       NetworkAnonymizationKey()),
1207        -1},
1208       // 11: Same host name without scheme/port.
1209       {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
1210                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1211        HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
1212                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1213        0},
1214       // 12: Different host name without scheme/port.
1215       {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
1216                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1217        HostCache::Key("host2", DnsQueryType::UNSPECIFIED, 0,
1218                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1219        -1},
1220       // 13: Only one with scheme/port.
1221       {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1222                       DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1223                       NetworkAnonymizationKey()),
1224        HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
1225                       HostResolverSource::ANY, NetworkAnonymizationKey()),
1226        -1},
1227   };
1228   HostCache::Key insecure_key =
1229       HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1230                      DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1231                      NetworkAnonymizationKey());
1232   HostCache::Key secure_key =
1233       HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
1234                      DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
1235                      NetworkAnonymizationKey());
1236   secure_key.secure = true;
1237   tests.emplace_back(insecure_key, secure_key, -1);
1238 
1239   for (size_t i = 0; i < std::size(tests); ++i) {
1240     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
1241 
1242     const HostCache::Key& key1 = tests[i].key1;
1243     const HostCache::Key& key2 = tests[i].key2;
1244 
1245     switch (tests[i].expected_comparison) {
1246       case -1:
1247         EXPECT_TRUE(key1 < key2);
1248         EXPECT_FALSE(key2 < key1);
1249         break;
1250       case 0:
1251         EXPECT_FALSE(key1 < key2);
1252         EXPECT_FALSE(key2 < key1);
1253         break;
1254       case 1:
1255         EXPECT_FALSE(key1 < key2);
1256         EXPECT_TRUE(key2 < key1);
1257         break;
1258       default:
1259         FAIL() << "Invalid expectation. Can be only -1, 0, 1";
1260     }
1261   }
1262 }
1263 
TEST(HostCacheTest,SerializeAndDeserializeWithExpirations)1264 TEST(HostCacheTest, SerializeAndDeserializeWithExpirations) {
1265   const base::TimeDelta kTTL = base::Seconds(10);
1266 
1267   HostCache cache(kMaxCacheEntries);
1268 
1269   // Start at t=0.
1270   base::TimeTicks now;
1271 
1272   HostCache::Key expire_by_time_key = Key("expire.by.time.test");
1273   HostCache::Key expire_by_changes_key = Key("expire.by.changes.test");
1274 
1275   IPEndPoint endpoint(IPAddress(1, 2, 3, 4), 0);
1276   HostCache::Entry entry = HostCache::Entry(OK, {endpoint}, /*aliases=*/{},
1277                                             HostCache::Entry::SOURCE_UNKNOWN);
1278 
1279   EXPECT_EQ(0u, cache.size());
1280 
1281   // Add an entry for `expire_by_time_key` at t=0.
1282   EXPECT_FALSE(cache.Lookup(expire_by_time_key, now));
1283   cache.Set(expire_by_time_key, entry, now, kTTL);
1284   EXPECT_THAT(cache.Lookup(expire_by_time_key, now),
1285               Pointee(Pair(expire_by_time_key, EntryContentsEqual(entry))));
1286 
1287   EXPECT_EQ(1u, cache.size());
1288 
1289   // Advance to t=5.
1290   now += base::Seconds(5);
1291 
1292   // Add entry for `expire_by_changes_key` at t=5.
1293   EXPECT_FALSE(cache.Lookup(expire_by_changes_key, now));
1294   cache.Set(expire_by_changes_key, entry, now, kTTL);
1295   EXPECT_TRUE(cache.Lookup(expire_by_changes_key, now));
1296   EXPECT_EQ(2u, cache.size());
1297 
1298   EXPECT_EQ(0u, cache.last_restore_size());
1299 
1300   // Advance to t=12, and serialize/deserialize the cache.
1301   now += base::Seconds(7);
1302 
1303   base::Value::List serialized_cache;
1304   cache.GetList(serialized_cache, false /* include_staleness */,
1305                 HostCache::SerializationType::kRestorable);
1306   HostCache restored_cache(kMaxCacheEntries);
1307 
1308   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1309 
1310   HostCache::EntryStaleness stale;
1311 
1312   // The `expire_by_time_key` entry is stale due to both network changes and
1313   // expiration time.
1314   EXPECT_FALSE(restored_cache.Lookup(expire_by_time_key, now));
1315   EXPECT_THAT(restored_cache.LookupStale(expire_by_time_key, now, &stale),
1316               Pointee(Pair(expire_by_time_key, EntryContentsEqual(entry))));
1317   EXPECT_EQ(1, stale.network_changes);
1318   // Time to TimeTicks conversion is fuzzy, so just check that expected and
1319   // actual expiration times are close.
1320   EXPECT_GT(base::Milliseconds(100),
1321             (base::Seconds(2) - stale.expired_by).magnitude());
1322 
1323   // The `expire_by_changes_key` entry is stale only due to network changes.
1324   EXPECT_FALSE(restored_cache.Lookup(expire_by_changes_key, now));
1325   EXPECT_THAT(restored_cache.LookupStale(expire_by_changes_key, now, &stale),
1326               Pointee(Pair(expire_by_changes_key, EntryContentsEqual(entry))));
1327   EXPECT_EQ(1, stale.network_changes);
1328   EXPECT_GT(base::Milliseconds(100),
1329             (base::Seconds(-3) - stale.expired_by).magnitude());
1330 
1331   EXPECT_EQ(2u, restored_cache.last_restore_size());
1332 }
1333 
1334 // Test that any changes between serialization and restore are preferred over
1335 // old restored entries.
TEST(HostCacheTest,SerializeAndDeserializeWithChanges)1336 TEST(HostCacheTest, SerializeAndDeserializeWithChanges) {
1337   const base::TimeDelta kTTL = base::Seconds(10);
1338 
1339   HostCache cache(kMaxCacheEntries);
1340 
1341   // Start at t=0.
1342   base::TimeTicks now;
1343 
1344   HostCache::Key to_serialize_key1 = Key("to.serialize1.test");
1345   HostCache::Key to_serialize_key2 = Key("to.serialize2.test");
1346   HostCache::Key other_key = Key("other.test");
1347 
1348   IPEndPoint endpoint(IPAddress(1, 1, 1, 1), 0);
1349   HostCache::Entry serialized_entry = HostCache::Entry(
1350       OK, {endpoint}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1351 
1352   IPEndPoint replacement_endpoint(IPAddress(2, 2, 2, 2), 0);
1353   HostCache::Entry replacement_entry =
1354       HostCache::Entry(OK, {replacement_endpoint}, /*aliases=*/{},
1355                        HostCache::Entry::SOURCE_UNKNOWN);
1356 
1357   IPEndPoint other_endpoint(IPAddress(3, 3, 3, 3), 0);
1358   HostCache::Entry other_entry = HostCache::Entry(
1359       OK, {other_endpoint}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1360 
1361   EXPECT_EQ(0u, cache.size());
1362 
1363   // Add `to_serialize_key1` and `to_serialize_key2`
1364   EXPECT_FALSE(cache.Lookup(to_serialize_key1, now));
1365   cache.Set(to_serialize_key1, serialized_entry, now, kTTL);
1366   EXPECT_THAT(
1367       cache.Lookup(to_serialize_key1, now),
1368       Pointee(Pair(to_serialize_key1, EntryContentsEqual(serialized_entry))));
1369   EXPECT_FALSE(cache.Lookup(to_serialize_key2, now));
1370   cache.Set(to_serialize_key2, serialized_entry, now, kTTL);
1371   EXPECT_THAT(
1372       cache.Lookup(to_serialize_key2, now),
1373       Pointee(Pair(to_serialize_key2, EntryContentsEqual(serialized_entry))));
1374   EXPECT_EQ(2u, cache.size());
1375 
1376   // Serialize the cache.
1377   base::Value::List serialized_cache;
1378   cache.GetList(serialized_cache, false /* include_staleness */,
1379                 HostCache::SerializationType::kRestorable);
1380   HostCache restored_cache(kMaxCacheEntries);
1381 
1382   // Add entries for `to_serialize_key1` and `other_key` to the new cache
1383   // before restoring the serialized one. The `to_serialize_key1` result is
1384   // different from the original.
1385   EXPECT_FALSE(restored_cache.Lookup(to_serialize_key1, now));
1386   restored_cache.Set(to_serialize_key1, replacement_entry, now, kTTL);
1387   EXPECT_THAT(
1388       restored_cache.Lookup(to_serialize_key1, now),
1389       Pointee(Pair(to_serialize_key1, EntryContentsEqual(replacement_entry))));
1390   EXPECT_EQ(1u, restored_cache.size());
1391 
1392   EXPECT_FALSE(restored_cache.Lookup(other_key, now));
1393   restored_cache.Set(other_key, other_entry, now, kTTL);
1394   EXPECT_THAT(restored_cache.Lookup(other_key, now),
1395               Pointee(Pair(other_key, EntryContentsEqual(other_entry))));
1396   EXPECT_EQ(2u, restored_cache.size());
1397 
1398   EXPECT_EQ(0u, restored_cache.last_restore_size());
1399 
1400   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1401   EXPECT_EQ(1u, restored_cache.last_restore_size());
1402 
1403   HostCache::EntryStaleness stale;
1404 
1405   // Expect `to_serialize_key1` has the replacement entry.
1406   EXPECT_THAT(
1407       restored_cache.Lookup(to_serialize_key1, now),
1408       Pointee(Pair(to_serialize_key1, EntryContentsEqual(replacement_entry))));
1409 
1410   // Expect `to_serialize_key2` has the original entry.
1411   EXPECT_THAT(
1412       restored_cache.LookupStale(to_serialize_key2, now, &stale),
1413       Pointee(Pair(to_serialize_key2, EntryContentsEqual(serialized_entry))));
1414 
1415   // Expect no change for `other_key`.
1416   EXPECT_THAT(restored_cache.Lookup(other_key, now),
1417               Pointee(Pair(other_key, EntryContentsEqual(other_entry))));
1418 }
1419 
TEST(HostCacheTest,SerializeAndDeserializeAddresses)1420 TEST(HostCacheTest, SerializeAndDeserializeAddresses) {
1421   const base::TimeDelta kTTL = base::Seconds(10);
1422 
1423   HostCache cache(kMaxCacheEntries);
1424 
1425   // Start at t=0.
1426   base::TimeTicks now;
1427 
1428   HostCache::Key key1 = Key("foobar.com");
1429   key1.secure = true;
1430   HostCache::Key key2 = Key("foobar2.com");
1431   HostCache::Key key3 = Key("foobar3.com");
1432   HostCache::Key key4 = Key("foobar4.com");
1433 
1434   IPAddress address_ipv4(1, 2, 3, 4);
1435   IPAddress address_ipv6(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1436   IPEndPoint endpoint_ipv4(address_ipv4, 0);
1437   IPEndPoint endpoint_ipv6(address_ipv6, 0);
1438 
1439   HostCache::Entry entry1 = HostCache::Entry(
1440       OK, {endpoint_ipv4}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1441   HostCache::Entry entry2 =
1442       HostCache::Entry(OK, {endpoint_ipv6, endpoint_ipv4}, /*aliases=*/{},
1443                        HostCache::Entry::SOURCE_UNKNOWN);
1444   HostCache::Entry entry3 = HostCache::Entry(
1445       OK, {endpoint_ipv6}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1446   HostCache::Entry entry4 = HostCache::Entry(
1447       OK, {endpoint_ipv4}, /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1448 
1449   EXPECT_EQ(0u, cache.size());
1450 
1451   // Add an entry for "foobar.com" at t=0.
1452   EXPECT_FALSE(cache.Lookup(key1, now));
1453   cache.Set(key1, entry1, now, kTTL);
1454   EXPECT_TRUE(cache.Lookup(key1, now));
1455   EXPECT_TRUE(cache.Lookup(key1, now)->second.error() == entry1.error());
1456 
1457   EXPECT_EQ(1u, cache.size());
1458 
1459   // Advance to t=5.
1460   now += base::Seconds(5);
1461 
1462   // Add entries for "foobar2.com" and "foobar3.com" at t=5.
1463   EXPECT_FALSE(cache.Lookup(key2, now));
1464   cache.Set(key2, entry2, now, kTTL);
1465   EXPECT_TRUE(cache.Lookup(key2, now));
1466   EXPECT_EQ(2u, cache.size());
1467 
1468   EXPECT_FALSE(cache.Lookup(key3, now));
1469   cache.Set(key3, entry3, now, kTTL);
1470   EXPECT_TRUE(cache.Lookup(key3, now));
1471   EXPECT_EQ(3u, cache.size());
1472 
1473   EXPECT_EQ(0u, cache.last_restore_size());
1474 
1475   // Advance to t=12, ansd serialize the cache.
1476   now += base::Seconds(7);
1477 
1478   base::Value::List serialized_cache;
1479   cache.GetList(serialized_cache, false /* include_staleness */,
1480                 HostCache::SerializationType::kRestorable);
1481   HostCache restored_cache(kMaxCacheEntries);
1482 
1483   // Add entries for "foobar3.com" and "foobar4.com" to the cache before
1484   // restoring it. The "foobar3.com" result is different from the original.
1485   EXPECT_FALSE(restored_cache.Lookup(key3, now));
1486   restored_cache.Set(key3, entry1, now, kTTL);
1487   EXPECT_TRUE(restored_cache.Lookup(key3, now));
1488   EXPECT_EQ(1u, restored_cache.size());
1489 
1490   EXPECT_FALSE(restored_cache.Lookup(key4, now));
1491   restored_cache.Set(key4, entry4, now, kTTL);
1492   EXPECT_TRUE(restored_cache.Lookup(key4, now));
1493   EXPECT_EQ(2u, restored_cache.size());
1494 
1495   EXPECT_EQ(0u, restored_cache.last_restore_size());
1496 
1497   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1498 
1499   HostCache::EntryStaleness stale;
1500 
1501   // The "foobar.com" entry is stale due to both network changes and expiration
1502   // time.
1503   EXPECT_FALSE(restored_cache.Lookup(key1, now));
1504   const std::pair<const HostCache::Key, HostCache::Entry>* result1 =
1505       restored_cache.LookupStale(key1, now, &stale);
1506   EXPECT_TRUE(result1);
1507   EXPECT_TRUE(result1->first.secure);
1508   EXPECT_THAT(result1->second.text_records(), IsEmpty());
1509   EXPECT_THAT(result1->second.hostnames(), IsEmpty());
1510   EXPECT_EQ(1u, result1->second.ip_endpoints().size());
1511   EXPECT_EQ(endpoint_ipv4, result1->second.ip_endpoints().front());
1512   EXPECT_EQ(1, stale.network_changes);
1513   // Time to TimeTicks conversion is fuzzy, so just check that expected and
1514   // actual expiration times are close.
1515   EXPECT_GT(base::Milliseconds(100),
1516             (base::Seconds(2) - stale.expired_by).magnitude());
1517 
1518   // The "foobar2.com" entry is stale only due to network changes.
1519   EXPECT_FALSE(restored_cache.Lookup(key2, now));
1520   const std::pair<const HostCache::Key, HostCache::Entry>* result2 =
1521       restored_cache.LookupStale(key2, now, &stale);
1522   EXPECT_TRUE(result2);
1523   EXPECT_FALSE(result2->first.secure);
1524   EXPECT_EQ(2u, result2->second.ip_endpoints().size());
1525   EXPECT_EQ(endpoint_ipv6, result2->second.ip_endpoints().front());
1526   EXPECT_EQ(endpoint_ipv4, result2->second.ip_endpoints().back());
1527   EXPECT_EQ(1, stale.network_changes);
1528   EXPECT_GT(base::Milliseconds(100),
1529             (base::Seconds(-3) - stale.expired_by).magnitude());
1530 
1531   // The "foobar3.com" entry is the new one, not the restored one.
1532   const std::pair<const HostCache::Key, HostCache::Entry>* result3 =
1533       restored_cache.Lookup(key3, now);
1534   EXPECT_TRUE(result3);
1535   EXPECT_EQ(1u, result3->second.ip_endpoints().size());
1536   EXPECT_EQ(endpoint_ipv4, result3->second.ip_endpoints().front());
1537 
1538   // The "foobar4.com" entry is still present and usable.
1539   const std::pair<const HostCache::Key, HostCache::Entry>* result4 =
1540       restored_cache.Lookup(key4, now);
1541   EXPECT_TRUE(result4);
1542   EXPECT_EQ(1u, result4->second.ip_endpoints().size());
1543   EXPECT_EQ(endpoint_ipv4, result4->second.ip_endpoints().front());
1544 
1545   EXPECT_EQ(2u, restored_cache.last_restore_size());
1546 }
1547 
TEST(HostCacheTest,SerializeAndDeserializeEntryWithoutScheme)1548 TEST(HostCacheTest, SerializeAndDeserializeEntryWithoutScheme) {
1549   const base::TimeDelta kTTL = base::Seconds(10);
1550 
1551   HostCache::Key key("host.test", DnsQueryType::UNSPECIFIED, 0,
1552                      HostResolverSource::ANY, NetworkAnonymizationKey());
1553   HostCache::Entry entry =
1554       HostCache::Entry(OK, /*ip_endpoints=*/{},
1555                        /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1556 
1557   base::TimeTicks now;
1558   HostCache cache(kMaxCacheEntries);
1559 
1560   cache.Set(key, entry, now, kTTL);
1561   ASSERT_TRUE(cache.Lookup(key, now));
1562   ASSERT_EQ(cache.size(), 1u);
1563 
1564   base::Value::List serialized_cache;
1565   cache.GetList(serialized_cache, /*include_staleness=*/false,
1566                 HostCache::SerializationType::kRestorable);
1567   HostCache restored_cache(kMaxCacheEntries);
1568   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1569   EXPECT_EQ(restored_cache.size(), 1u);
1570 
1571   HostCache::EntryStaleness staleness;
1572   EXPECT_THAT(restored_cache.LookupStale(key, now, &staleness),
1573               Pointee(Pair(key, EntryContentsEqual(entry))));
1574 }
1575 
TEST(HostCacheTest,SerializeAndDeserializeWithNetworkAnonymizationKey)1576 TEST(HostCacheTest, SerializeAndDeserializeWithNetworkAnonymizationKey) {
1577   const url::SchemeHostPort kHost =
1578       url::SchemeHostPort(url::kHttpsScheme, "hostname.test", 443);
1579   const base::TimeDelta kTTL = base::Seconds(10);
1580   const SchemefulSite kSite(GURL("https://site.test/"));
1581   const auto kNetworkAnonymizationKey =
1582       NetworkAnonymizationKey::CreateSameSite(kSite);
1583   const SchemefulSite kOpaqueSite;
1584   const auto kOpaqueNetworkAnonymizationKey =
1585       NetworkAnonymizationKey::CreateSameSite(kOpaqueSite);
1586 
1587   HostCache::Key key1(kHost, DnsQueryType::UNSPECIFIED, 0,
1588                       HostResolverSource::ANY, kNetworkAnonymizationKey);
1589   HostCache::Key key2(kHost, DnsQueryType::UNSPECIFIED, 0,
1590                       HostResolverSource::ANY, kOpaqueNetworkAnonymizationKey);
1591 
1592   IPEndPoint endpoint(IPAddress(1, 2, 3, 4), 0);
1593   HostCache::Entry entry = HostCache::Entry(OK, {endpoint}, /*aliases=*/{},
1594                                             HostCache::Entry::SOURCE_UNKNOWN);
1595 
1596   base::TimeTicks now;
1597   HostCache cache(kMaxCacheEntries);
1598 
1599   cache.Set(key1, entry, now, kTTL);
1600   cache.Set(key2, entry, now, kTTL);
1601 
1602   EXPECT_TRUE(cache.Lookup(key1, now));
1603   EXPECT_EQ(kNetworkAnonymizationKey,
1604             cache.Lookup(key1, now)->first.network_anonymization_key);
1605   EXPECT_TRUE(cache.Lookup(key2, now));
1606   EXPECT_EQ(kOpaqueNetworkAnonymizationKey,
1607             cache.Lookup(key2, now)->first.network_anonymization_key);
1608   EXPECT_EQ(2u, cache.size());
1609 
1610   base::Value::List serialized_cache;
1611   cache.GetList(serialized_cache, false /* include_staleness */,
1612                 HostCache::SerializationType::kRestorable);
1613   HostCache restored_cache(kMaxCacheEntries);
1614   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1615   EXPECT_EQ(1u, restored_cache.size());
1616 
1617   HostCache::EntryStaleness stale;
1618   EXPECT_THAT(restored_cache.LookupStale(key1, now, &stale),
1619               Pointee(Pair(key1, EntryContentsEqual(entry))));
1620   EXPECT_FALSE(restored_cache.Lookup(key2, now));
1621 }
1622 
TEST(HostCacheTest,SerializeForDebugging)1623 TEST(HostCacheTest, SerializeForDebugging) {
1624   const url::SchemeHostPort kHost(url::kHttpsScheme, "hostname.test", 443);
1625   const base::TimeDelta kTTL = base::Seconds(10);
1626   const NetworkAnonymizationKey kNetworkAnonymizationKey =
1627       NetworkAnonymizationKey::CreateTransient();
1628 
1629   HostCache::Key key(kHost, DnsQueryType::UNSPECIFIED, 0,
1630                      HostResolverSource::ANY, kNetworkAnonymizationKey);
1631 
1632   IPEndPoint endpoint(IPAddress(1, 2, 3, 4), 0);
1633   HostCache::Entry entry = HostCache::Entry(OK, {endpoint}, /*aliases=*/{},
1634                                             HostCache::Entry::SOURCE_UNKNOWN);
1635 
1636   base::TimeTicks now;
1637   HostCache cache(kMaxCacheEntries);
1638 
1639   cache.Set(key, entry, now, kTTL);
1640 
1641   EXPECT_TRUE(cache.Lookup(key, now));
1642   EXPECT_EQ(kNetworkAnonymizationKey,
1643             cache.Lookup(key, now)->first.network_anonymization_key);
1644   EXPECT_EQ(1u, cache.size());
1645 
1646   base::Value::List serialized_cache;
1647   cache.GetList(serialized_cache, false /* include_staleness */,
1648                 HostCache::SerializationType::kDebug);
1649   HostCache restored_cache(kMaxCacheEntries);
1650   EXPECT_FALSE(restored_cache.RestoreFromListValue(serialized_cache));
1651 
1652   ASSERT_EQ(1u, serialized_cache.size());
1653   ASSERT_TRUE(serialized_cache[0].is_dict());
1654   const std::string* nik_string =
1655       serialized_cache[0].GetDict().FindString("network_anonymization_key");
1656   ASSERT_TRUE(nik_string);
1657   ASSERT_EQ(kNetworkAnonymizationKey.ToDebugString(), *nik_string);
1658 }
1659 
TEST(HostCacheTest,SerializeAndDeserialize_Text)1660 TEST(HostCacheTest, SerializeAndDeserialize_Text) {
1661   base::TimeTicks now;
1662 
1663   base::TimeDelta ttl = base::Seconds(99);
1664   std::vector<std::string> text_records({"foo", "bar"});
1665   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1666                      DnsQueryType::A, 0, HostResolverSource::DNS,
1667                      NetworkAnonymizationKey());
1668   key.secure = true;
1669   HostCache::Entry entry(OK, text_records, HostCache::Entry::SOURCE_DNS, ttl);
1670   EXPECT_THAT(entry.text_records(), Not(IsEmpty()));
1671 
1672   HostCache cache(kMaxCacheEntries);
1673   cache.Set(key, entry, now, ttl);
1674   EXPECT_EQ(1u, cache.size());
1675 
1676   base::Value::List serialized_cache;
1677   cache.GetList(serialized_cache, false /* include_staleness */,
1678                 HostCache::SerializationType::kRestorable);
1679   HostCache restored_cache(kMaxCacheEntries);
1680   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1681 
1682   ASSERT_EQ(1u, serialized_cache.size());
1683   ASSERT_EQ(1u, restored_cache.size());
1684   HostCache::EntryStaleness stale;
1685   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1686       restored_cache.LookupStale(key, now, &stale);
1687   EXPECT_THAT(result, Pointee(Pair(key, EntryContentsEqual(entry))));
1688   EXPECT_THAT(result->second.text_records(), text_records);
1689 }
1690 
TEST(HostCacheTest,SerializeAndDeserialize_Hostname)1691 TEST(HostCacheTest, SerializeAndDeserialize_Hostname) {
1692   base::TimeTicks now;
1693 
1694   base::TimeDelta ttl = base::Seconds(99);
1695   std::vector<HostPortPair> hostnames(
1696       {HostPortPair("example.com", 95), HostPortPair("chromium.org", 122)});
1697   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1698                      DnsQueryType::A, 0, HostResolverSource::DNS,
1699                      NetworkAnonymizationKey());
1700   HostCache::Entry entry(OK, hostnames, HostCache::Entry::SOURCE_DNS, ttl);
1701   EXPECT_THAT(entry.hostnames(), Not(IsEmpty()));
1702 
1703   HostCache cache(kMaxCacheEntries);
1704   cache.Set(key, entry, now, ttl);
1705   EXPECT_EQ(1u, cache.size());
1706 
1707   base::Value::List serialized_cache;
1708   cache.GetList(serialized_cache, false /* include_staleness */,
1709                 HostCache::SerializationType::kRestorable);
1710   HostCache restored_cache(kMaxCacheEntries);
1711   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1712 
1713   ASSERT_EQ(1u, restored_cache.size());
1714   HostCache::EntryStaleness stale;
1715   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1716       restored_cache.LookupStale(key, now, &stale);
1717   EXPECT_THAT(result, Pointee(Pair(key, EntryContentsEqual(entry))));
1718   EXPECT_THAT(result->second.hostnames(), hostnames);
1719 }
1720 
TEST(HostCacheTest,SerializeAndDeserializeEndpointResult)1721 TEST(HostCacheTest, SerializeAndDeserializeEndpointResult) {
1722   base::TimeTicks now;
1723 
1724   base::TimeDelta ttl = base::Seconds(99);
1725   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1726                      DnsQueryType::A, 0, HostResolverSource::DNS,
1727                      NetworkAnonymizationKey());
1728   IPEndPoint ipv6_endpoint(
1729       IPAddress(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4), 110);
1730   IPEndPoint ipv4_endpoint1(IPAddress(1, 1, 1, 1), 80);
1731   IPEndPoint ipv4_endpoint2(IPAddress(2, 2, 2, 2), 90);
1732   IPEndPoint other_ipv4_endpoint(IPAddress(3, 3, 3, 3), 100);
1733   std::string ipv6_alias = "ipv6_alias.test";
1734   std::string ipv4_alias = "ipv4_alias.test";
1735   std::string other_alias = "other_alias.test";
1736   std::vector<IPEndPoint> ip_endpoints = {ipv6_endpoint, ipv4_endpoint1,
1737                                           ipv4_endpoint2, other_ipv4_endpoint};
1738   std::set<std::string> aliases = {ipv6_alias, ipv4_alias, other_alias};
1739   HostCache::Entry entry(OK, ip_endpoints, aliases,
1740                          HostCache::Entry::SOURCE_DNS, ttl);
1741 
1742   std::set<std::string> canonical_names = {ipv6_alias, ipv4_alias};
1743   entry.set_canonical_names(canonical_names);
1744 
1745   EXPECT_THAT(entry.GetEndpoints(), Not(IsEmpty()));
1746 
1747   ConnectionEndpointMetadata metadata1;
1748   metadata1.supported_protocol_alpns = {"h3", "h2"};
1749   metadata1.ech_config_list = {'f', 'o', 'o'};
1750   metadata1.target_name = ipv6_alias;
1751   ConnectionEndpointMetadata metadata2;
1752   metadata2.supported_protocol_alpns = {"h2", "h4"};
1753   metadata2.target_name = ipv4_alias;
1754   HostCache::Entry metadata_entry(
1755       OK,
1756       std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>{
1757           {1u, metadata1}, {2u, metadata2}},
1758       HostCache::Entry::SOURCE_DNS);
1759 
1760   auto merged_entry = HostCache::Entry::MergeEntries(entry, metadata_entry);
1761 
1762   EXPECT_THAT(merged_entry.GetEndpoints(),
1763               ElementsAre(ExpectEndpointResult(ip_endpoints)));
1764   EXPECT_THAT(
1765       merged_entry.GetMetadatas(),
1766       testing::ElementsAre(
1767           ExpectConnectionEndpointMetadata(testing::ElementsAre("h3", "h2"),
1768                                            testing::ElementsAre('f', 'o', 'o'),
1769                                            ipv6_alias),
1770           ExpectConnectionEndpointMetadata(testing::ElementsAre("h2", "h4"),
1771                                            IsEmpty(), ipv4_alias)));
1772   EXPECT_THAT(merged_entry.canonical_names(),
1773               UnorderedElementsAre(ipv4_alias, ipv6_alias));
1774 
1775   HostCache cache(kMaxCacheEntries);
1776   cache.Set(key, merged_entry, now, ttl);
1777   EXPECT_EQ(1u, cache.size());
1778 
1779   base::Value::List serialized_cache;
1780   cache.GetList(serialized_cache, false /* include_staleness */,
1781                 HostCache::SerializationType::kRestorable);
1782   HostCache restored_cache(kMaxCacheEntries);
1783   EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
1784 
1785   // Check `serialized_cache` can be encoded as JSON. This ensures it has no
1786   // binary values.
1787   std::string json;
1788   EXPECT_TRUE(base::JSONWriter::Write(serialized_cache, &json));
1789 
1790   ASSERT_EQ(1u, restored_cache.size());
1791   HostCache::EntryStaleness stale;
1792   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1793       restored_cache.LookupStale(key, now, &stale);
1794 
1795   ASSERT_TRUE(result);
1796   EXPECT_THAT(result, Pointee(Pair(key, EntryContentsEqual(merged_entry))));
1797   EXPECT_THAT(result->second.GetEndpoints(),
1798               ElementsAre(ExpectEndpointResult(ip_endpoints)));
1799   EXPECT_THAT(
1800       result->second.GetMetadatas(),
1801       testing::ElementsAre(
1802           ExpectConnectionEndpointMetadata(testing::ElementsAre("h3", "h2"),
1803                                            testing::ElementsAre('f', 'o', 'o'),
1804                                            ipv6_alias),
1805           ExpectConnectionEndpointMetadata(testing::ElementsAre("h2", "h4"),
1806                                            IsEmpty(), ipv4_alias)));
1807   EXPECT_THAT(result->second.canonical_names(),
1808               UnorderedElementsAre(ipv4_alias, ipv6_alias));
1809 
1810   EXPECT_EQ(result->second.aliases(), aliases);
1811 }
1812 
TEST(HostCacheTest,DeserializeNoEndpointNoAliase)1813 TEST(HostCacheTest, DeserializeNoEndpointNoAliase) {
1814   base::TimeDelta ttl = base::Seconds(99);
1815   std::string expiration_time_str = base::NumberToString(
1816       (base::Time::Now() + ttl).since_origin().InMicroseconds());
1817 
1818   auto dict = base::JSONReader::Read(base::StringPrintf(
1819       R"(
1820  [ {
1821    "dns_query_type": 1,
1822    "expiration": "%s",
1823    "flags": 0,
1824    "host_resolver_source": 2,
1825    "hostname": "example.com",
1826    "network_anonymization_key": [  ],
1827    "port": 443,
1828    "scheme": "https",
1829    "secure": false
1830 } ]
1831 )",
1832       expiration_time_str.c_str()));
1833   ASSERT_TRUE(dict);
1834 
1835   HostCache restored_cache(kMaxCacheEntries);
1836   ASSERT_TRUE(dict->is_list());
1837   EXPECT_TRUE(restored_cache.RestoreFromListValue(dict->GetList()));
1838 
1839   ASSERT_EQ(1u, restored_cache.size());
1840 
1841   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1842                      DnsQueryType::A, 0, HostResolverSource::DNS,
1843                      NetworkAnonymizationKey());
1844 
1845   HostCache::EntryStaleness stale;
1846   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1847       restored_cache.LookupStale(key, base::TimeTicks::Now(), &stale);
1848 
1849   ASSERT_TRUE(result);
1850   EXPECT_THAT(result->second.aliases(), ElementsAre());
1851   EXPECT_THAT(result->second.ip_endpoints(), ElementsAre());
1852 }
1853 
TEST(HostCacheTest,DeserializeLegacyAddresses)1854 TEST(HostCacheTest, DeserializeLegacyAddresses) {
1855   base::TimeDelta ttl = base::Seconds(99);
1856   std::string expiration_time_str = base::NumberToString(
1857       (base::Time::Now() + ttl).since_origin().InMicroseconds());
1858 
1859   auto dict = base::JSONReader::Read(base::StringPrintf(
1860       R"(
1861  [ {
1862    "addresses": [ "2000::", "1.2.3.4" ],
1863    "dns_query_type": 1,
1864    "expiration": "%s",
1865    "flags": 0,
1866    "host_resolver_source": 2,
1867    "hostname": "example.com",
1868    "network_anonymization_key": [  ],
1869    "port": 443,
1870    "scheme": "https",
1871    "secure": false
1872 } ]
1873 )",
1874       expiration_time_str.c_str()));
1875   ASSERT_TRUE(dict);
1876 
1877   HostCache restored_cache(kMaxCacheEntries);
1878   ASSERT_TRUE(dict->is_list());
1879   EXPECT_TRUE(restored_cache.RestoreFromListValue(dict->GetList()));
1880 
1881   ASSERT_EQ(1u, restored_cache.size());
1882 
1883   HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
1884                      DnsQueryType::A, 0, HostResolverSource::DNS,
1885                      NetworkAnonymizationKey());
1886 
1887   HostCache::EntryStaleness stale;
1888   const std::pair<const HostCache::Key, HostCache::Entry>* result =
1889       restored_cache.LookupStale(key, base::TimeTicks::Now(), &stale);
1890 
1891   ASSERT_TRUE(result);
1892   EXPECT_THAT(result->second.ip_endpoints(),
1893               ElementsAreArray(MakeEndpoints({"2000::", "1.2.3.4"})));
1894   EXPECT_THAT(result->second.aliases(), ElementsAre());
1895 }
1896 
TEST(HostCacheTest,DeserializeInvalidQueryTypeIntegrity)1897 TEST(HostCacheTest, DeserializeInvalidQueryTypeIntegrity) {
1898   base::TimeDelta ttl = base::Seconds(99);
1899   std::string expiration_time_str = base::NumberToString(
1900       (base::Time::Now() + ttl).since_origin().InMicroseconds());
1901 
1902   // RestoreFromListValue doesn't support dns_query_type=6 (INTEGRITY).
1903   auto dict = base::JSONReader::Read(base::StringPrintf(
1904       R"(
1905  [ {
1906    "addresses": [ "2000::", "1.2.3.4" ],
1907    "dns_query_type": 6,
1908    "expiration": "%s",
1909    "flags": 0,
1910    "host_resolver_source": 2,
1911    "hostname": "example.com",
1912    "network_anonymization_key": [  ],
1913    "port": 443,
1914    "scheme": "https",
1915    "secure": false
1916 } ]
1917 )",
1918       expiration_time_str.c_str()));
1919   ASSERT_TRUE(dict);
1920 
1921   HostCache restored_cache(kMaxCacheEntries);
1922   ASSERT_TRUE(dict->is_list());
1923   EXPECT_FALSE(restored_cache.RestoreFromListValue(dict->GetList()));
1924 
1925   ASSERT_EQ(0u, restored_cache.size());
1926 }
1927 
TEST(HostCacheTest,DeserializeInvalidQueryTypeHttpsExperimental)1928 TEST(HostCacheTest, DeserializeInvalidQueryTypeHttpsExperimental) {
1929   base::TimeDelta ttl = base::Seconds(99);
1930   std::string expiration_time_str = base::NumberToString(
1931       (base::Time::Now() + ttl).since_origin().InMicroseconds());
1932 
1933   // RestoreFromListValue doesn't support dns_query_type=8 (HTTPS_EXPERIMENTAL).
1934   auto dict = base::JSONReader::Read(base::StringPrintf(
1935       R"(
1936  [ {
1937    "addresses": [ "2000::", "1.2.3.4" ],
1938    "dns_query_type": 8,
1939    "expiration": "%s",
1940    "flags": 0,
1941    "host_resolver_source": 2,
1942    "hostname": "example.com",
1943    "network_anonymization_key": [  ],
1944    "port": 443,
1945    "scheme": "https",
1946    "secure": false
1947 } ]
1948 )",
1949       expiration_time_str.c_str()));
1950   ASSERT_TRUE(dict);
1951 
1952   HostCache restored_cache(kMaxCacheEntries);
1953   ASSERT_TRUE(dict->is_list());
1954   EXPECT_FALSE(restored_cache.RestoreFromListValue(dict->GetList()));
1955 
1956   ASSERT_EQ(0u, restored_cache.size());
1957 }
1958 
TEST(HostCacheTest,PersistenceDelegate)1959 TEST(HostCacheTest, PersistenceDelegate) {
1960   const base::TimeDelta kTTL = base::Seconds(10);
1961   HostCache cache(kMaxCacheEntries);
1962   MockPersistenceDelegate delegate;
1963   cache.set_persistence_delegate(&delegate);
1964 
1965   HostCache::Key key1 = Key("foobar.com");
1966   HostCache::Key key2 = Key("foobar2.com");
1967 
1968   HostCache::Entry ok_entry =
1969       HostCache::Entry(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
1970                        HostCache::Entry::SOURCE_UNKNOWN);
1971   std::vector<IPEndPoint> other_endpoints = {
1972       IPEndPoint(IPAddress(1, 1, 1, 1), 300)};
1973   HostCache::Entry other_entry(OK, std::move(other_endpoints), /*aliases=*/{},
1974                                HostCache::Entry::SOURCE_UNKNOWN);
1975   HostCache::Entry error_entry =
1976       HostCache::Entry(ERR_NAME_NOT_RESOLVED, /*ip_endpoints=*/{},
1977                        /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN);
1978 
1979   // Start at t=0.
1980   base::TimeTicks now;
1981   EXPECT_EQ(0u, cache.size());
1982 
1983   // Add two entries at t=0.
1984   EXPECT_FALSE(cache.Lookup(key1, now));
1985   cache.Set(key1, ok_entry, now, kTTL);
1986   EXPECT_TRUE(cache.Lookup(key1, now));
1987   EXPECT_EQ(1u, cache.size());
1988   EXPECT_EQ(1, delegate.num_changes());
1989 
1990   EXPECT_FALSE(cache.Lookup(key2, now));
1991   cache.Set(key2, error_entry, now, kTTL);
1992   EXPECT_TRUE(cache.Lookup(key2, now));
1993   EXPECT_EQ(2u, cache.size());
1994   EXPECT_EQ(2, delegate.num_changes());
1995 
1996   // Advance to t=5.
1997   now += base::Seconds(5);
1998 
1999   // Changes that shouldn't trigger a write:
2000   // Add an entry for "foobar.com" with different expiration time.
2001   EXPECT_TRUE(cache.Lookup(key1, now));
2002   cache.Set(key1, ok_entry, now, kTTL);
2003   EXPECT_TRUE(cache.Lookup(key1, now));
2004   EXPECT_EQ(2u, cache.size());
2005   EXPECT_EQ(2, delegate.num_changes());
2006 
2007   // Add an entry for "foobar.com" with different TTL.
2008   EXPECT_TRUE(cache.Lookup(key1, now));
2009   cache.Set(key1, ok_entry, now, kTTL - base::Seconds(5));
2010   EXPECT_TRUE(cache.Lookup(key1, now));
2011   EXPECT_EQ(2u, cache.size());
2012   EXPECT_EQ(2, delegate.num_changes());
2013 
2014   // Changes that should trigger a write:
2015   // Add an entry for "foobar.com" with different address list.
2016   EXPECT_TRUE(cache.Lookup(key1, now));
2017   cache.Set(key1, other_entry, now, kTTL);
2018   EXPECT_TRUE(cache.Lookup(key1, now));
2019   EXPECT_EQ(2u, cache.size());
2020   EXPECT_EQ(3, delegate.num_changes());
2021 
2022   // Add an entry for "foobar2.com" with different error.
2023   EXPECT_TRUE(cache.Lookup(key1, now));
2024   cache.Set(key2, ok_entry, now, kTTL);
2025   EXPECT_TRUE(cache.Lookup(key1, now));
2026   EXPECT_EQ(2u, cache.size());
2027   EXPECT_EQ(4, delegate.num_changes());
2028 }
2029 
TEST(HostCacheTest,MergeEndpointsWithAliases)2030 TEST(HostCacheTest, MergeEndpointsWithAliases) {
2031   const IPAddress kAddressFront(1, 2, 3, 4);
2032   const IPEndPoint kEndpointFront(kAddressFront, 0);
2033   HostCache::Entry front(OK, {kEndpointFront}, {"alias1", "alias2", "alias3"},
2034                          HostCache::Entry::SOURCE_DNS);
2035   front.set_text_records(std::vector<std::string>{"text1"});
2036   const HostPortPair kHostnameFront("host", 1);
2037   front.set_hostnames(std::vector<HostPortPair>{kHostnameFront});
2038 
2039   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2040                                0);
2041   const IPEndPoint kEndpointBack(kAddressBack, 0);
2042   HostCache::Entry back(OK, {kEndpointBack}, {"alias2", "alias4", "alias5"},
2043                         HostCache::Entry::SOURCE_DNS);
2044   back.set_text_records(std::vector<std::string>{"text2"});
2045   const HostPortPair kHostnameBack("host", 2);
2046   back.set_hostnames(std::vector<HostPortPair>{kHostnameBack});
2047 
2048   HostCache::Entry result =
2049       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2050 
2051   EXPECT_EQ(OK, result.error());
2052   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2053 
2054   EXPECT_THAT(result.ip_endpoints(),
2055               ElementsAre(kEndpointFront, kEndpointBack));
2056   EXPECT_THAT(result.text_records(), ElementsAre("text1", "text2"));
2057 
2058   EXPECT_THAT(result.hostnames(), ElementsAre(kHostnameFront, kHostnameBack));
2059 
2060   EXPECT_THAT(
2061       result.aliases(),
2062       UnorderedElementsAre("alias1", "alias2", "alias3", "alias4", "alias5"));
2063 }
2064 
TEST(HostCacheTest,MergeEndpointsKeepEndpointsOrder)2065 TEST(HostCacheTest, MergeEndpointsKeepEndpointsOrder) {
2066   std::vector<IPEndPoint> front_addresses =
2067       MakeEndpoints({"::1", "0.0.0.2", "0.0.0.4"});
2068   std::vector<IPEndPoint> back_addresses =
2069       MakeEndpoints({"0.0.0.2", "0.0.0.2", "::3", "::3", "0.0.0.4"});
2070 
2071   HostCache::Entry front(OK, front_addresses, /*aliases=*/{"front"},
2072                          HostCache::Entry::SOURCE_DNS);
2073   HostCache::Entry back(OK, back_addresses, /*aliases=*/{"back"},
2074                         HostCache::Entry::SOURCE_DNS);
2075 
2076   HostCache::Entry result =
2077       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2078 
2079   EXPECT_THAT(
2080       result.ip_endpoints(),
2081       ElementsAreArray(MakeEndpoints({"::1", "0.0.0.2", "0.0.0.4", "0.0.0.2",
2082                                       "0.0.0.2", "::3", "::3", "0.0.0.4"})));
2083   EXPECT_THAT(result.aliases(), UnorderedElementsAre("front", "back"));
2084 }
2085 
TEST(HostCacheTest,MergeMetadatas)2086 TEST(HostCacheTest, MergeMetadatas) {
2087   ConnectionEndpointMetadata front_metadata;
2088   front_metadata.supported_protocol_alpns = {"h5", "h6", "monster truck rally"};
2089   front_metadata.ech_config_list = {'h', 'i'};
2090   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2091       front_metadata_map{{4u, front_metadata}};
2092   HostCache::Entry front(OK, front_metadata_map, HostCache::Entry::SOURCE_DNS);
2093 
2094   ConnectionEndpointMetadata back_metadata;
2095   back_metadata.supported_protocol_alpns = {"h5"};
2096   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2097       back_metadata_map{{2u, back_metadata}};
2098   HostCache::Entry back(OK, back_metadata_map, HostCache::Entry::SOURCE_DNS);
2099 
2100   HostCache::Entry result = HostCache::Entry::MergeEntries(front, back);
2101 
2102   // Expect `GetEndpoints()` to ignore metadatas if no `IPEndPoint`s.
2103   EXPECT_THAT(result.GetEndpoints(), IsEmpty());
2104 
2105   // Expect order irrelevant for endpoint metadata merging.
2106   result = HostCache::Entry::MergeEntries(back, front);
2107   EXPECT_THAT(result.GetEndpoints(), IsEmpty());
2108 }
2109 
TEST(HostCacheTest,MergeMetadatasWithIpEndpointsDifferentCanonicalName)2110 TEST(HostCacheTest, MergeMetadatasWithIpEndpointsDifferentCanonicalName) {
2111   std::string target_name = "example.com";
2112   std::string other_target_name = "other.example.com";
2113   ConnectionEndpointMetadata metadata;
2114   metadata.supported_protocol_alpns = {"h5", "h6", "monster truck rally"};
2115   metadata.ech_config_list = {'h', 'i'};
2116   metadata.target_name = target_name;
2117 
2118   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadata_map{
2119       {4u, metadata}};
2120   HostCache::Entry metadata_entry(OK, metadata_map,
2121                                   HostCache::Entry::SOURCE_DNS);
2122 
2123   // Expect `GetEndpoints()` to always ignore metadatas with no `IPEndPoint`s.
2124   EXPECT_THAT(metadata_entry.GetEndpoints(), IsEmpty());
2125 
2126   // Merge in an `IPEndPoint` with different canonical name.
2127   IPEndPoint ip_endpoint(IPAddress(1, 1, 1, 1), 0);
2128   HostCache::Entry with_ip_endpoint(OK, {ip_endpoint}, /*aliases=*/{},
2129                                     HostCache::Entry::SOURCE_DNS);
2130   with_ip_endpoint.set_canonical_names(
2131       std::set<std::string>{other_target_name});
2132   HostCache::Entry result =
2133       HostCache::Entry::MergeEntries(metadata_entry, with_ip_endpoint);
2134 
2135   // Expect `GetEndpoints()` not to return the metadata.
2136   EXPECT_THAT(
2137       result.GetEndpoints(),
2138       ElementsAre(ExpectEndpointResult(std::vector<IPEndPoint>{ip_endpoint})));
2139 
2140   // Expect merge order irrelevant.
2141   EXPECT_EQ(result,
2142             HostCache::Entry::MergeEntries(with_ip_endpoint, metadata_entry));
2143 }
2144 
TEST(HostCacheTest,MergeMetadatasWithIpEndpointsMatchingCanonicalName)2145 TEST(HostCacheTest, MergeMetadatasWithIpEndpointsMatchingCanonicalName) {
2146   std::string target_name = "example.com";
2147   ConnectionEndpointMetadata metadata;
2148   metadata.supported_protocol_alpns = {"h5", "h6", "monster truck rally"};
2149   metadata.ech_config_list = {'h', 'i'};
2150   metadata.target_name = target_name;
2151 
2152   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadata_map{
2153       {4u, metadata}};
2154   HostCache::Entry metadata_entry(OK, metadata_map,
2155                                   HostCache::Entry::SOURCE_DNS);
2156 
2157   // Expect `GetEndpoints()` to always ignore metadatas with no `IPEndPoint`s.
2158   EXPECT_THAT(metadata_entry.GetEndpoints(), IsEmpty());
2159 
2160   // Merge in an `IPEndPoint` with different canonical name.
2161   IPEndPoint ip_endpoint(IPAddress(1, 1, 1, 1), 0);
2162   HostCache::Entry with_ip_endpoint(OK, {ip_endpoint}, /*aliases=*/{},
2163                                     HostCache::Entry::SOURCE_DNS);
2164   with_ip_endpoint.set_canonical_names(std::set<std::string>{target_name});
2165   HostCache::Entry result =
2166       HostCache::Entry::MergeEntries(metadata_entry, with_ip_endpoint);
2167 
2168   // Expect `GetEndpoints()` to return the metadata.
2169   EXPECT_THAT(
2170       result.GetEndpoints(),
2171       ElementsAre(ExpectEndpointResult(ElementsAre(ip_endpoint), metadata),
2172                   ExpectEndpointResult(ElementsAre(ip_endpoint))));
2173 
2174   // Expect merge order irrelevant.
2175   EXPECT_EQ(result,
2176             HostCache::Entry::MergeEntries(with_ip_endpoint, metadata_entry));
2177 }
2178 
TEST(HostCacheTest,MergeMultipleMetadatasWithIpEndpoints)2179 TEST(HostCacheTest, MergeMultipleMetadatasWithIpEndpoints) {
2180   std::string target_name = "example.com";
2181   ConnectionEndpointMetadata front_metadata;
2182   front_metadata.supported_protocol_alpns = {"h5", "h6", "monster truck rally"};
2183   front_metadata.ech_config_list = {'h', 'i'};
2184   front_metadata.target_name = target_name;
2185 
2186   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2187       front_metadata_map{{4u, front_metadata}};
2188   HostCache::Entry front(OK, front_metadata_map, HostCache::Entry::SOURCE_DNS);
2189 
2190   ConnectionEndpointMetadata back_metadata;
2191   back_metadata.supported_protocol_alpns = {"h5"};
2192   back_metadata.target_name = target_name;
2193   std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2194       back_metadata_map{{2u, back_metadata}};
2195   HostCache::Entry back(OK, back_metadata_map, HostCache::Entry::SOURCE_DNS);
2196 
2197   HostCache::Entry merged_metadatas =
2198       HostCache::Entry::MergeEntries(front, back);
2199   HostCache::Entry reversed_merged_metadatas =
2200       HostCache::Entry::MergeEntries(back, front);
2201 
2202   // Expect `GetEndpoints()` to always ignore metadatas with no `IPEndPoint`s.
2203   EXPECT_THAT(merged_metadatas.GetEndpoints(), IsEmpty());
2204   EXPECT_THAT(reversed_merged_metadatas.GetEndpoints(), IsEmpty());
2205 
2206   // Merge in an `IPEndPoint`.
2207   IPEndPoint ip_endpoint(IPAddress(1, 1, 1, 1), 0);
2208   HostCache::Entry with_ip_endpoint(OK, {ip_endpoint}, /*aliases=*/{},
2209                                     HostCache::Entry::SOURCE_DNS);
2210   with_ip_endpoint.set_canonical_names(std::set<std::string>{target_name});
2211 
2212   HostCache::Entry result =
2213       HostCache::Entry::MergeEntries(merged_metadatas, with_ip_endpoint);
2214 
2215   // Expect `back_metadata` before `front_metadata` because it has lower
2216   // priority number.
2217   EXPECT_THAT(
2218       result.GetEndpoints(),
2219       ElementsAre(
2220           ExpectEndpointResult(ElementsAre(ip_endpoint), back_metadata),
2221           ExpectEndpointResult(ElementsAre(ip_endpoint), front_metadata),
2222           ExpectEndpointResult(ElementsAre(ip_endpoint))));
2223 
2224   // Expect merge order irrelevant.
2225   EXPECT_EQ(result, HostCache::Entry::MergeEntries(reversed_merged_metadatas,
2226                                                    with_ip_endpoint));
2227   EXPECT_EQ(result,
2228             HostCache::Entry::MergeEntries(with_ip_endpoint, merged_metadatas));
2229   EXPECT_EQ(result, HostCache::Entry::MergeEntries(with_ip_endpoint,
2230                                                    reversed_merged_metadatas));
2231 }
2232 
TEST(HostCacheTest,MergeAliases)2233 TEST(HostCacheTest, MergeAliases) {
2234   HostCache::Entry front(OK, /*ip_endpoints=*/{},
2235                          /*aliases=*/{"foo1.test", "foo2.test", "foo3.test"},
2236                          HostCache::Entry::SOURCE_DNS);
2237 
2238   HostCache::Entry back(OK, /*ip_endpoints=*/{},
2239                         /*aliases=*/{"foo2.test", "foo4.test"},
2240                         HostCache::Entry::SOURCE_DNS);
2241 
2242   HostCache::Entry expected(
2243       OK, /*ip_endpoints=*/{},
2244       /*aliases=*/{"foo1.test", "foo2.test", "foo3.test", "foo4.test"},
2245       HostCache::Entry::SOURCE_DNS);
2246 
2247   HostCache::Entry result = HostCache::Entry::MergeEntries(front, back);
2248   EXPECT_EQ(result, expected);
2249 
2250   // Expect order irrelevant for alias merging.
2251   result = HostCache::Entry::MergeEntries(back, front);
2252   EXPECT_EQ(result, expected);
2253 }
2254 
TEST(HostCacheTest,MergeEntries_frontEmpty)2255 TEST(HostCacheTest, MergeEntries_frontEmpty) {
2256   HostCache::Entry front(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2257 
2258   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2259                                0);
2260   const IPEndPoint kEndpointBack(kAddressBack, 0);
2261   HostCache::Entry back(OK, {kEndpointBack}, {"alias1", "alias2", "alias3"},
2262                         HostCache::Entry::SOURCE_DNS, base::Hours(4));
2263   back.set_text_records(std::vector<std::string>{"text2"});
2264   const HostPortPair kHostnameBack("host", 2);
2265   back.set_hostnames(std::vector<HostPortPair>{kHostnameBack});
2266 
2267   HostCache::Entry result =
2268       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2269 
2270   EXPECT_EQ(OK, result.error());
2271   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2272 
2273   EXPECT_THAT(result.ip_endpoints(), ElementsAre(kEndpointBack));
2274   EXPECT_THAT(result.text_records(), ElementsAre("text2"));
2275   EXPECT_THAT(result.hostnames(), ElementsAre(kHostnameBack));
2276 
2277   EXPECT_EQ(base::Hours(4), result.ttl());
2278 
2279   EXPECT_THAT(result.aliases(),
2280               UnorderedElementsAre("alias1", "alias2", "alias3"));
2281 }
2282 
TEST(HostCacheTest,MergeEntries_backEmpty)2283 TEST(HostCacheTest, MergeEntries_backEmpty) {
2284   const IPAddress kAddressFront(1, 2, 3, 4);
2285   const IPEndPoint kEndpointFront(kAddressFront, 0);
2286   HostCache::Entry front(OK, {kEndpointFront}, {"alias1", "alias2", "alias3"},
2287                          HostCache::Entry::SOURCE_DNS, base::Minutes(5));
2288   front.set_text_records(std::vector<std::string>{"text1"});
2289   const HostPortPair kHostnameFront("host", 1);
2290   front.set_hostnames(std::vector<HostPortPair>{kHostnameFront});
2291 
2292   HostCache::Entry back(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2293 
2294   HostCache::Entry result =
2295       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2296 
2297   EXPECT_EQ(OK, result.error());
2298   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2299 
2300   EXPECT_THAT(result.ip_endpoints(), ElementsAre(kEndpointFront));
2301   EXPECT_THAT(result.text_records(), ElementsAre("text1"));
2302   EXPECT_THAT(result.hostnames(), ElementsAre(kHostnameFront));
2303 
2304   EXPECT_EQ(base::Minutes(5), result.ttl());
2305 
2306   EXPECT_THAT(result.aliases(),
2307               UnorderedElementsAre("alias1", "alias2", "alias3"));
2308 }
2309 
TEST(HostCacheTest,MergeEntries_bothEmpty)2310 TEST(HostCacheTest, MergeEntries_bothEmpty) {
2311   HostCache::Entry front(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2312   HostCache::Entry back(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2313 
2314   HostCache::Entry result =
2315       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2316 
2317   EXPECT_EQ(ERR_NAME_NOT_RESOLVED, result.error());
2318   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2319 
2320   EXPECT_THAT(result.ip_endpoints(), IsEmpty());
2321   EXPECT_THAT(result.text_records(), IsEmpty());
2322   EXPECT_THAT(result.hostnames(), IsEmpty());
2323   EXPECT_FALSE(result.has_ttl());
2324 }
2325 
TEST(HostCacheTest,MergeEntries_frontWithAliasesNoAddressesBackWithBoth)2326 TEST(HostCacheTest, MergeEntries_frontWithAliasesNoAddressesBackWithBoth) {
2327   HostCache::Entry front(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2328   std::set<std::string> aliases_front({"alias0", "alias1", "alias2"});
2329   front.set_aliases(aliases_front);
2330 
2331   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2332                                0);
2333   const IPEndPoint kEndpointBack(kAddressBack, 0);
2334   HostCache::Entry back(OK, {kEndpointBack}, {"alias1", "alias2", "alias3"},
2335                         HostCache::Entry::SOURCE_DNS, base::Hours(4));
2336 
2337   HostCache::Entry result =
2338       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2339 
2340   EXPECT_EQ(OK, result.error());
2341   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2342 
2343   EXPECT_THAT(result.ip_endpoints(), ElementsAre(kEndpointBack));
2344 
2345   EXPECT_EQ(base::Hours(4), result.ttl());
2346 
2347   EXPECT_THAT(result.aliases(),
2348               UnorderedElementsAre("alias0", "alias1", "alias2", "alias3"));
2349 }
2350 
TEST(HostCacheTest,MergeEntries_backWithAliasesNoAddressesFrontWithBoth)2351 TEST(HostCacheTest, MergeEntries_backWithAliasesNoAddressesFrontWithBoth) {
2352   HostCache::Entry back(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS);
2353   std::set<std::string> aliases_back({"alias1", "alias2", "alias3"});
2354   back.set_aliases(aliases_back);
2355 
2356   const IPAddress kAddressFront(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2357                                 0);
2358   const IPEndPoint kEndpointFront(kAddressFront, 0);
2359   HostCache::Entry front(OK, {kEndpointFront}, {"alias0", "alias1", "alias2"},
2360                          HostCache::Entry::SOURCE_DNS, base::Hours(4));
2361 
2362   HostCache::Entry result =
2363       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2364 
2365   EXPECT_EQ(OK, result.error());
2366   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2367 
2368   EXPECT_THAT(result.ip_endpoints(), ElementsAre(kEndpointFront));
2369 
2370   EXPECT_EQ(base::Hours(4), result.ttl());
2371 
2372   EXPECT_THAT(result.aliases(),
2373               UnorderedElementsAre("alias0", "alias1", "alias2", "alias3"));
2374 }
2375 
TEST(HostCacheTest,MergeEntries_frontWithAddressesNoAliasesBackWithBoth)2376 TEST(HostCacheTest, MergeEntries_frontWithAddressesNoAliasesBackWithBoth) {
2377   const IPAddress kAddressFront(1, 2, 3, 4);
2378   const IPEndPoint kEndpointFront(kAddressFront, 0);
2379   HostCache::Entry front(OK, {kEndpointFront}, /*aliases=*/{},
2380                          HostCache::Entry::SOURCE_DNS, base::Hours(4));
2381 
2382   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2383                                0);
2384   const IPEndPoint kEndpointBack(kAddressBack, 0);
2385   HostCache::Entry back(OK, {kEndpointBack}, {"alias1", "alias2", "alias3"},
2386                         HostCache::Entry::SOURCE_DNS, base::Hours(4));
2387   HostCache::Entry result =
2388       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2389 
2390   EXPECT_EQ(OK, result.error());
2391   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2392 
2393   EXPECT_THAT(result.ip_endpoints(),
2394               ElementsAre(kEndpointFront, kEndpointBack));
2395 
2396   EXPECT_EQ(base::Hours(4), result.ttl());
2397 
2398   EXPECT_THAT(result.aliases(),
2399               UnorderedElementsAre("alias1", "alias2", "alias3"));
2400 }
2401 
TEST(HostCacheTest,MergeEntries_backWithAddressesNoAliasesFrontWithBoth)2402 TEST(HostCacheTest, MergeEntries_backWithAddressesNoAliasesFrontWithBoth) {
2403   const IPAddress kAddressFront(1, 2, 3, 4);
2404   const IPEndPoint kEndpointFront(kAddressFront, 0);
2405   HostCache::Entry front(OK, {kEndpointFront}, {"alias1", "alias2", "alias3"},
2406                          HostCache::Entry::SOURCE_DNS, base::Hours(4));
2407   const IPAddress kAddressBack(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2408                                0);
2409   const IPEndPoint kEndpointBack(kAddressBack, 0);
2410   HostCache::Entry back(OK, {kEndpointBack}, /*aliases=*/{},
2411                         HostCache::Entry::SOURCE_DNS, base::Hours(4));
2412 
2413   HostCache::Entry result =
2414       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2415 
2416   EXPECT_EQ(OK, result.error());
2417   EXPECT_EQ(HostCache::Entry::SOURCE_DNS, result.source());
2418 
2419   EXPECT_THAT(result.ip_endpoints(),
2420               ElementsAre(kEndpointFront, kEndpointBack));
2421 
2422   EXPECT_EQ(base::Hours(4), result.ttl());
2423 
2424   EXPECT_THAT(result.aliases(),
2425               UnorderedElementsAre("alias1", "alias2", "alias3"));
2426 }
2427 
TEST(HostCacheTest,MergeEntries_differentTtl)2428 TEST(HostCacheTest, MergeEntries_differentTtl) {
2429   HostCache::Entry front(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS,
2430                          base::Days(12));
2431   HostCache::Entry back(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS,
2432                         base::Seconds(42));
2433 
2434   HostCache::Entry result =
2435       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2436 
2437   EXPECT_EQ(base::Seconds(42), result.ttl());
2438 }
2439 
TEST(HostCacheTest,MergeEntries_FrontCannonnamePreserved)2440 TEST(HostCacheTest, MergeEntries_FrontCannonnamePreserved) {
2441   HostCache::Entry front(OK, /*ip_endpoints=*/{}, /*aliases=*/{"name1"},
2442                          HostCache::Entry::SOURCE_DNS);
2443 
2444   HostCache::Entry back(OK, /*ip_endpoints=*/{}, /*aliases=*/{"name2"},
2445                         HostCache::Entry::SOURCE_DNS);
2446 
2447   HostCache::Entry result =
2448       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2449 
2450   EXPECT_THAT(result.aliases(), UnorderedElementsAre("name1", "name2"));
2451 }
2452 
2453 // Test that the back canonname can be used if there is no front cannonname.
TEST(HostCacheTest,MergeEntries_BackCannonnameUsable)2454 TEST(HostCacheTest, MergeEntries_BackCannonnameUsable) {
2455   HostCache::Entry front(OK, /*ip_endpoints=*/{}, /*aliases=*/{},
2456                          HostCache::Entry::SOURCE_DNS);
2457 
2458   HostCache::Entry back(OK, /*ip_endpoints=*/{}, /*aliases=*/{"name2"},
2459                         HostCache::Entry::SOURCE_DNS);
2460 
2461   HostCache::Entry result =
2462       HostCache::Entry::MergeEntries(std::move(front), std::move(back));
2463 
2464   EXPECT_THAT(result.aliases(), UnorderedElementsAre("name2"));
2465 }
2466 
TEST(HostCacheTest,ConvertFromInternalAddressResult)2467 TEST(HostCacheTest, ConvertFromInternalAddressResult) {
2468   const std::vector<IPEndPoint> kEndpoints{
2469       IPEndPoint(IPAddress(2, 2, 2, 2), 46)};
2470   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2471   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2472   constexpr base::TimeDelta kTtl3 = base::Minutes(55);
2473 
2474   std::set<std::unique_ptr<HostResolverInternalResult>> results;
2475   results.insert(std::make_unique<HostResolverInternalDataResult>(
2476       "endpoint.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl1,
2477       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2478       kEndpoints, std::vector<std::string>{}, std::vector<HostPortPair>{}));
2479   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2480       "domain1.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl2,
2481       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2482       "domain2.test"));
2483   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2484       "domain2.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl3,
2485       base::Time() + kTtl3, HostResolverInternalResult::Source::kDns,
2486       "endpoint.test"));
2487 
2488   HostCache::Entry converted(std::move(results), base::Time(),
2489                              base::TimeTicks());
2490 
2491   // Expect kTtl2 because it is the min TTL.
2492   HostCache::Entry expected(
2493       OK, kEndpoints,
2494       /*aliases=*/{"domain1.test", "domain2.test", "endpoint.test"},
2495       HostCache::Entry::SOURCE_DNS, kTtl2);
2496   expected.set_canonical_names(std::set<std::string>{"endpoint.test"});
2497 
2498   // Entries converted from HostResolverInternalDataResults do not differentiate
2499   // between empty and no-data for the various data types, so need to set empty
2500   // strings and hostname entries into `expected`.
2501   expected.set_text_records(std::vector<std::string>());
2502   expected.set_hostnames(std::vector<HostPortPair>());
2503 
2504   EXPECT_EQ(converted, expected);
2505 }
2506 
TEST(HostCacheTest,ConvertFromInternalMetadataResult)2507 TEST(HostCacheTest, ConvertFromInternalMetadataResult) {
2508   const std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2509       kMetadatas{{1, ConnectionEndpointMetadata({"h2", "h3"},
2510                                                 /*ech_config_list=*/{},
2511                                                 "target.test")}};
2512   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2513   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2514   constexpr base::TimeDelta kTtl3 = base::Minutes(55);
2515 
2516   std::set<std::unique_ptr<HostResolverInternalResult>> results;
2517   results.insert(std::make_unique<HostResolverInternalMetadataResult>(
2518       "endpoint.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl1,
2519       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2520       kMetadatas));
2521   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2522       "domain1.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl2,
2523       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2524       "domain2.test"));
2525   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2526       "domain2.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl3,
2527       base::Time() + kTtl3, HostResolverInternalResult::Source::kDns,
2528       "endpoint.test"));
2529 
2530   HostCache::Entry converted(std::move(results), base::Time(),
2531                              base::TimeTicks());
2532 
2533   // Expect kTtl2 because it is the min TTL.
2534   HostCache::Entry expected(OK, kMetadatas, HostCache::Entry::SOURCE_DNS,
2535                             kTtl2);
2536   expected.set_https_record_compatibility(std::vector<bool>{true});
2537 
2538   EXPECT_EQ(converted, expected);
2539 }
2540 
2541 // Test the case of compatible HTTPS records but no metadata of use to Chrome.
2542 // Represented in internal result type as an empty metadata result. Represented
2543 // in HostCache::Entry as empty metadata with at least one true in
2544 // `https_record_compatibility_`.
TEST(HostCacheTest,ConvertFromCompatibleOnlyInternalMetadataResult)2545 TEST(HostCacheTest, ConvertFromCompatibleOnlyInternalMetadataResult) {
2546   const std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
2547       kMetadatas;
2548   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2549   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2550   constexpr base::TimeDelta kTtl3 = base::Minutes(55);
2551 
2552   std::set<std::unique_ptr<HostResolverInternalResult>> results;
2553   results.insert(std::make_unique<HostResolverInternalMetadataResult>(
2554       "endpoint.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl1,
2555       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2556       kMetadatas));
2557   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2558       "domain1.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl2,
2559       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2560       "domain2.test"));
2561   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2562       "domain2.test", DnsQueryType::HTTPS, base::TimeTicks() + kTtl3,
2563       base::Time() + kTtl3, HostResolverInternalResult::Source::kDns,
2564       "endpoint.test"));
2565 
2566   HostCache::Entry converted(std::move(results), base::Time(),
2567                              base::TimeTicks());
2568 
2569   // Expect kTtl2 because it is the min TTL.
2570   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED, kMetadatas,
2571                             HostCache::Entry::SOURCE_DNS, kTtl2);
2572   expected.set_https_record_compatibility(std::vector<bool>{true});
2573 
2574   EXPECT_EQ(converted, expected);
2575 }
2576 
TEST(HostCacheTest,ConvertFromInternalErrorResult)2577 TEST(HostCacheTest, ConvertFromInternalErrorResult) {
2578   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2579   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2580   constexpr base::TimeDelta kTtl3 = base::Minutes(55);
2581 
2582   std::set<std::unique_ptr<HostResolverInternalResult>> results;
2583   results.insert(std::make_unique<HostResolverInternalErrorResult>(
2584       "endpoint.test", DnsQueryType::A, base::TimeTicks() + kTtl1,
2585       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2586       ERR_NAME_NOT_RESOLVED));
2587   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2588       "domain1.test", DnsQueryType::A, base::TimeTicks() + kTtl2,
2589       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2590       "domain2.test"));
2591   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2592       "domain2.test", DnsQueryType::A, base::TimeTicks() + kTtl3,
2593       base::Time() + kTtl3, HostResolverInternalResult::Source::kDns,
2594       "endpoint.test"));
2595 
2596   HostCache::Entry converted(std::move(results), base::Time(),
2597                              base::TimeTicks());
2598 
2599   // Expect kTtl2 because it is the min TTL.
2600   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_DNS,
2601                             kTtl2);
2602 
2603   EXPECT_EQ(converted, expected);
2604 }
2605 
TEST(HostCacheTest,ConvertFromNonCachableInternalErrorResult)2606 TEST(HostCacheTest, ConvertFromNonCachableInternalErrorResult) {
2607   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2608   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2609 
2610   std::set<std::unique_ptr<HostResolverInternalResult>> results;
2611   results.insert(std::make_unique<HostResolverInternalErrorResult>(
2612       "endpoint.test", DnsQueryType::AAAA, /*expiration=*/absl::nullopt,
2613       /*timed_expiration=*/absl::nullopt,
2614       HostResolverInternalResult::Source::kDns, ERR_NAME_NOT_RESOLVED));
2615   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2616       "domain1.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl1,
2617       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2618       "domain2.test"));
2619   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2620       "domain2.test", DnsQueryType::AAAA, base::TimeTicks() + kTtl2,
2621       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2622       "endpoint.test"));
2623 
2624   HostCache::Entry converted(std::move(results), base::Time(),
2625                              base::TimeTicks());
2626 
2627   // Expect no TTL because error is non-cachable (has no TTL itself).
2628   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED,
2629                             HostCache::Entry::SOURCE_DNS);
2630 
2631   EXPECT_EQ(converted, expected);
2632 }
2633 
TEST(HostCacheTest,ConvertFromInternalAliasOnlyResult)2634 TEST(HostCacheTest, ConvertFromInternalAliasOnlyResult) {
2635   constexpr base::TimeDelta kTtl1 = base::Minutes(45);
2636   constexpr base::TimeDelta kTtl2 = base::Minutes(40);
2637 
2638   std::set<std::unique_ptr<HostResolverInternalResult>> results;
2639   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2640       "domain1.test", DnsQueryType::A, base::TimeTicks() + kTtl1,
2641       base::Time() + kTtl1, HostResolverInternalResult::Source::kDns,
2642       "domain2.test"));
2643   results.insert(std::make_unique<HostResolverInternalAliasResult>(
2644       "domain2.test", DnsQueryType::A, base::TimeTicks() + kTtl2,
2645       base::Time() + kTtl2, HostResolverInternalResult::Source::kDns,
2646       "endpoint.test"));
2647 
2648   HostCache::Entry converted(std::move(results), base::Time(),
2649                              base::TimeTicks());
2650 
2651   // Expect no TTL because alias-only results are not cacheable.
2652   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED,
2653                             HostCache::Entry::SOURCE_DNS);
2654 
2655   EXPECT_EQ(converted, expected);
2656 }
2657 
TEST(HostCacheTest,ConvertFromEmptyInternalResult)2658 TEST(HostCacheTest, ConvertFromEmptyInternalResult) {
2659   HostCache::Entry converted({}, base::Time(), base::TimeTicks());
2660   HostCache::Entry expected(ERR_NAME_NOT_RESOLVED,
2661                             HostCache::Entry::SOURCE_UNKNOWN);
2662 
2663   EXPECT_EQ(converted, expected);
2664 }
2665 
2666 }  // namespace net
2667