• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/dns/stale_host_resolver.h"
11 
12 #include <memory>
13 #include <optional>
14 #include <string>
15 #include <utility>
16 
17 #include "base/check.h"
18 #include "base/functional/bind.h"
19 #include "base/memory/raw_ptr.h"
20 #include "base/memory/ref_counted.h"
21 #include "base/run_loop.h"
22 #include "base/task/single_thread_task_runner.h"
23 #include "base/test/simple_test_tick_clock.h"
24 #include "base/test/task_environment.h"
25 #include "base/test/test_timeouts.h"
26 #include "base/time/time.h"
27 #include "base/values.h"
28 #include "build/build_config.h"
29 #include "net/base/address_family.h"
30 #include "net/base/host_port_pair.h"
31 #include "net/base/ip_endpoint.h"
32 #include "net/base/mock_network_change_notifier.h"
33 #include "net/base/net_errors.h"
34 #include "net/base/network_anonymization_key.h"
35 #include "net/base/network_change_notifier.h"
36 #include "net/cert/cert_verifier.h"
37 #include "net/dns/context_host_resolver.h"
38 #include "net/dns/dns_config.h"
39 #include "net/dns/dns_hosts.h"
40 #include "net/dns/dns_test_util.h"
41 #include "net/dns/host_cache.h"
42 #include "net/dns/host_resolver_manager.h"
43 #include "net/dns/host_resolver_proc.h"
44 #include "net/dns/host_resolver_system_task.h"
45 #include "net/dns/public/dns_protocol.h"
46 #include "net/dns/public/dns_query_type.h"
47 #include "net/dns/public/host_resolver_source.h"
48 #include "net/http/http_network_session.h"
49 #include "net/log/net_log_with_source.h"
50 #include "net/proxy_resolution/proxy_config.h"
51 #include "net/proxy_resolution/proxy_config_service_fixed.h"
52 #include "net/url_request/url_request_context.h"
53 #include "net/url_request/url_request_context_builder.h"
54 #include "testing/gtest/include/gtest/gtest.h"
55 
56 namespace net {
57 
58 namespace {
59 
60 const char kHostname[] = "example.com";
61 const char kCacheAddress[] = "1.1.1.1";
62 const char kNetworkAddress[] = "2.2.2.2";
63 const char kHostsAddress[] = "4.4.4.4";
64 const int kCacheEntryTTLSec = 300;
65 
66 const int kNoStaleDelaySec = 0;
67 const int kLongStaleDelaySec = 3600;
68 const uint16_t kPort = 12345;
69 
70 const int kAgeFreshSec = 0;
71 const int kAgeExpiredSec = kCacheEntryTTLSec * 2;
72 
73 // How long to wait for resolve calls to return. If the tests are working
74 // correctly, we won't end up waiting this long -- it's just a backup.
75 const int kWaitTimeoutSec = 1;
76 
MakeEndpoints(const char * ip_address_str)77 std::vector<IPEndPoint> MakeEndpoints(const char* ip_address_str) {
78   IPAddress address;
79   bool rv = address.AssignFromIPLiteral(ip_address_str);
80   DCHECK(rv);
81   return std::vector<IPEndPoint>({{address, 0}});
82 }
83 
MakeAddressList(const char * ip_address_str)84 AddressList MakeAddressList(const char* ip_address_str) {
85   return AddressList(MakeEndpoints(ip_address_str));
86 }
87 
CreateMockDnsClientForHosts()88 std::unique_ptr<DnsClient> CreateMockDnsClientForHosts() {
89   DnsConfig config;
90   config.nameservers.push_back(IPEndPoint());
91   ParseHosts("4.4.4.4 example.com", &config.hosts);
92 
93   return std::make_unique<MockDnsClient>(config, MockDnsClientRuleList());
94 }
95 
96 // Create a DnsClient where address requests for |kHostname| will hang
97 // until unblocked via CompleteDelayedTransactions() and then fail.
CreateHangingMockDnsClient()98 std::unique_ptr<MockDnsClient> CreateHangingMockDnsClient() {
99   DnsConfig config;
100   config.nameservers.push_back(IPEndPoint());
101 
102   MockDnsClientRuleList rules;
103   rules.emplace_back(
104       kHostname, dns_protocol::kTypeA, false /* secure */,
105       MockDnsClientRule::Result(MockDnsClientRule::ResultType::kFail),
106       true /* delay */);
107   rules.emplace_back(
108       kHostname, dns_protocol::kTypeAAAA, false /* secure */,
109       MockDnsClientRule::Result(MockDnsClientRule::ResultType::kFail),
110       true /* delay */);
111 
112   return std::make_unique<MockDnsClient>(config, std::move(rules));
113 }
114 
115 class MockHostResolverProc : public HostResolverProc {
116  public:
117   // |result| is the net error code to return from resolution attempts.
MockHostResolverProc(int result)118   explicit MockHostResolverProc(int result)
119       : HostResolverProc(nullptr), result_(result) {}
120 
Resolve(const std::string & hostname,AddressFamily address_family,HostResolverFlags host_resolver_flags,AddressList * address_list,int * os_error)121   int Resolve(const std::string& hostname,
122               AddressFamily address_family,
123               HostResolverFlags host_resolver_flags,
124               AddressList* address_list,
125               int* os_error) override {
126     *address_list = MakeAddressList(kNetworkAddress);
127     return result_;
128   }
129 
130  protected:
131   ~MockHostResolverProc() override = default;
132 
133  private:
134   // Result code to return from Resolve().
135   const int result_;
136 };
137 
138 class StaleHostResolverTest : public testing::Test {
139  protected:
StaleHostResolverTest()140   StaleHostResolverTest()
141       : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
142         mock_network_change_notifier_(
143             net::NetworkChangeNotifier::CreateMockIfNeeded()),
144         mock_proc_(new MockHostResolverProc(OK)),
145         resolver_(nullptr) {
146     // Make value clock not empty.
147     tick_clock_.Advance(base::Microseconds(1));
148   }
149 
~StaleHostResolverTest()150   ~StaleHostResolverTest() override {}
151 
SetStaleDelay(int stale_delay_sec)152   void SetStaleDelay(int stale_delay_sec) {
153     DCHECK(!resolver_);
154 
155     options_.delay = base::Seconds(stale_delay_sec);
156   }
157 
SetUseStaleOnNameNotResolved()158   void SetUseStaleOnNameNotResolved() {
159     DCHECK(!resolver_);
160 
161     options_.use_stale_on_name_not_resolved = true;
162   }
163 
SetStaleUsability(int max_expired_time_sec,int max_stale_uses,bool allow_other_network)164   void SetStaleUsability(int max_expired_time_sec,
165                          int max_stale_uses,
166                          bool allow_other_network) {
167     DCHECK(!resolver_);
168 
169     options_.max_expired_time = base::Seconds(max_expired_time_sec);
170     options_.max_stale_uses = max_stale_uses;
171     options_.allow_other_network = allow_other_network;
172   }
173 
SetNetResult(int result)174   void SetNetResult(int result) {
175     DCHECK(!resolver_);
176 
177     mock_proc_ = new MockHostResolverProc(result);
178   }
179 
CreateMockInnerResolverWithDnsClient(std::unique_ptr<DnsClient> dns_client,URLRequestContext * context=nullptr)180   std::unique_ptr<ContextHostResolver> CreateMockInnerResolverWithDnsClient(
181       std::unique_ptr<DnsClient> dns_client,
182       URLRequestContext* context = nullptr) {
183     std::unique_ptr<ContextHostResolver> inner_resolver(
184         HostResolver::CreateStandaloneContextResolver(nullptr));
185     if (context) {
186       inner_resolver->SetRequestContext(context);
187     }
188 
189     HostResolverSystemTask::Params system_params(mock_proc_, 1u);
190     inner_resolver->SetHostResolverSystemParamsForTest(system_params);
191     if (dns_client) {
192       inner_resolver->GetManagerForTesting()->SetDnsClientForTesting(
193           std::move(dns_client));
194       inner_resolver->GetManagerForTesting()->SetInsecureDnsClientEnabled(
195           /*enabled=*/true,
196           /*additional_dns_types_enabled=*/true);
197     } else {
198       inner_resolver->GetManagerForTesting()->SetInsecureDnsClientEnabled(
199           /*enabled=*/false,
200           /*additional_dns_types_enabled=*/false);
201     }
202     return inner_resolver;
203   }
204 
CreateResolverWithDnsClient(std::unique_ptr<DnsClient> dns_client)205   void CreateResolverWithDnsClient(std::unique_ptr<DnsClient> dns_client) {
206     DCHECK(!resolver_);
207 
208     stale_resolver_ = std::make_unique<StaleHostResolver>(
209         CreateMockInnerResolverWithDnsClient(std::move(dns_client)), options_);
210     stale_resolver_->SetTickClockForTesting(&tick_clock_);
211     resolver_ = stale_resolver_.get();
212   }
213 
SetResolver(StaleHostResolver * stale_resolver,net::URLRequestContext * context=nullptr)214   void SetResolver(StaleHostResolver* stale_resolver,
215                    net::URLRequestContext* context = nullptr) {
216     DCHECK(!resolver_);
217     stale_resolver->inner_resolver_ =
218         CreateMockInnerResolverWithDnsClient(nullptr /* dns_client */, context);
219     resolver_ = stale_resolver;
220   }
221 
CreateResolver()222   void CreateResolver() { CreateResolverWithDnsClient(nullptr); }
223 
DestroyResolver()224   void DestroyResolver() {
225     DCHECK(stale_resolver_);
226 
227     resolver_ = nullptr;
228     stale_resolver_.reset();
229   }
230 
DropResolver()231   void DropResolver() { resolver_ = nullptr; }
232 
233   // Creates a cache entry for |kHostname| that is |age_sec| seconds old.
CreateCacheEntry(int age_sec,int error)234   void CreateCacheEntry(int age_sec, int error) {
235     DCHECK(resolver_);
236     DCHECK(resolver_->GetHostCache());
237 
238     base::TimeDelta ttl(base::Seconds(kCacheEntryTTLSec));
239     HostCache::Key key(kHostname, DnsQueryType::UNSPECIFIED, 0,
240                        HostResolverSource::ANY, NetworkAnonymizationKey());
241     HostCache::Entry entry(
242         error,
243         error == OK ? MakeEndpoints(kCacheAddress) : std::vector<IPEndPoint>(),
244         /*aliases=*/{}, HostCache::Entry::SOURCE_UNKNOWN, ttl);
245     base::TimeDelta age = base::Seconds(age_sec);
246     base::TimeTicks then = tick_clock_.NowTicks() - age;
247     resolver_->GetHostCache()->Set(key, entry, then, ttl);
248   }
249 
OnNetworkChange()250   void OnNetworkChange() {
251     // Real network changes on Android will send both notifications.
252     NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
253     NetworkChangeNotifier::NotifyObserversOfDNSChangeForTests();
254     base::RunLoop().RunUntilIdle();  // Wait for notification.
255   }
256 
LookupStale()257   void LookupStale() {
258     DCHECK(resolver_);
259     DCHECK(resolver_->GetHostCache());
260 
261     HostCache::Key key(kHostname, DnsQueryType::UNSPECIFIED, 0,
262                        HostResolverSource::ANY, NetworkAnonymizationKey());
263     base::TimeTicks now = tick_clock_.NowTicks();
264     HostCache::EntryStaleness stale;
265     EXPECT_TRUE(resolver_->GetHostCache()->LookupStale(key, now, &stale));
266     EXPECT_TRUE(stale.is_stale());
267   }
268 
Resolve(const std::optional<StaleHostResolver::ResolveHostParameters> & optional_parameters)269   void Resolve(const std::optional<StaleHostResolver::ResolveHostParameters>&
270                    optional_parameters) {
271     DCHECK(resolver_);
272     EXPECT_FALSE(resolve_pending_);
273 
274     request_ = resolver_->CreateRequest(
275         HostPortPair(kHostname, kPort), NetworkAnonymizationKey(),
276         NetLogWithSource(), optional_parameters);
277     resolve_pending_ = true;
278     resolve_complete_ = false;
279     resolve_error_ = ERR_UNEXPECTED;
280 
281     int rv = request_->Start(base::BindOnce(
282         &StaleHostResolverTest::OnResolveComplete, base::Unretained(this)));
283     if (rv != ERR_IO_PENDING) {
284       resolve_pending_ = false;
285       resolve_complete_ = true;
286       resolve_error_ = rv;
287     }
288   }
289 
WaitForResolve()290   void WaitForResolve() {
291     if (!resolve_pending_) {
292       return;
293     }
294 
295     base::RunLoop run_loop;
296 
297     // Run until resolve completes or timeout.
298     resolve_closure_ = run_loop.QuitWhenIdleClosure();
299     base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
300         FROM_HERE, resolve_closure_, base::Seconds(kWaitTimeoutSec));
301     run_loop.Run();
302   }
303 
WaitForIdle()304   void WaitForIdle() {
305     base::RunLoop run_loop;
306 
307     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
308         FROM_HERE, run_loop.QuitWhenIdleClosure());
309     run_loop.Run();
310   }
311 
WaitForNetworkResolveComplete()312   void WaitForNetworkResolveComplete() {
313     // The stale host resolver cache is initially setup with |kCacheAddress|,
314     // so getting that address means that network resolve is still pending.
315     // The network resolve is guaranteed to return |kNetworkAddress| at some
316     // point because inner resolver is using MockHostResolverProc that always
317     // returns |kNetworkAddress|.
318     while (resolve_error() != OK ||
319            resolve_addresses()[0].ToStringWithoutPort() != kNetworkAddress) {
320       Resolve(std::nullopt);
321       WaitForResolve();
322     }
323   }
324 
Cancel()325   void Cancel() {
326     DCHECK(resolver_);
327     EXPECT_TRUE(resolve_pending_);
328 
329     request_ = nullptr;
330 
331     resolve_pending_ = false;
332   }
333 
OnResolveComplete(int error)334   void OnResolveComplete(int error) {
335     EXPECT_TRUE(resolve_pending_);
336 
337     resolve_error_ = error;
338     resolve_pending_ = false;
339     resolve_complete_ = true;
340 
341     if (!resolve_closure_.is_null()) {
342       std::move(resolve_closure_).Run();
343     }
344   }
345 
AdvanceTickClock(base::TimeDelta delta)346   void AdvanceTickClock(base::TimeDelta delta) { tick_clock_.Advance(delta); }
347 
resolve_complete() const348   bool resolve_complete() const { return resolve_complete_; }
resolve_error() const349   int resolve_error() const { return resolve_error_; }
resolve_addresses() const350   const AddressList& resolve_addresses() const {
351     DCHECK(resolve_complete_);
352     return *request_->GetAddressResults();
353   }
354 
355  private:
356   // Needed for HostResolver to run HostResolverProc callbacks.
357   base::test::TaskEnvironment task_environment_;
358   base::SimpleTestTickClock tick_clock_;
359   std::unique_ptr<net::NetworkChangeNotifier> mock_network_change_notifier_;
360 
361   scoped_refptr<MockHostResolverProc> mock_proc_;
362 
363   StaleHostResolver::StaleOptions options_;
364 
365   // Must outlive `resolver_`.
366   std::unique_ptr<StaleHostResolver> stale_resolver_;
367 
368   raw_ptr<HostResolver> resolver_;
369 
370   base::TimeTicks now_;
371   std::unique_ptr<HostResolver::ResolveHostRequest> request_;
372   bool resolve_pending_{false};
373   bool resolve_complete_{false};
374   int resolve_error_;
375 
376   base::RepeatingClosure resolve_closure_;
377 };
378 
379 // Make sure that test harness can be created and destroyed without crashing.
TEST_F(StaleHostResolverTest,Null)380 TEST_F(StaleHostResolverTest, Null) {}
381 
382 // Make sure that resolver can be created and destroyed without crashing.
TEST_F(StaleHostResolverTest,Create)383 TEST_F(StaleHostResolverTest, Create) {
384   CreateResolver();
385 }
386 
TEST_F(StaleHostResolverTest,Network)387 TEST_F(StaleHostResolverTest, Network) {
388   CreateResolver();
389 
390   Resolve(std::nullopt);
391   WaitForResolve();
392 
393   EXPECT_TRUE(resolve_complete());
394   EXPECT_EQ(OK, resolve_error());
395   EXPECT_EQ(1u, resolve_addresses().size());
396   EXPECT_EQ(kNetworkAddress, resolve_addresses()[0].ToStringWithoutPort());
397 }
398 
TEST_F(StaleHostResolverTest,Hosts)399 TEST_F(StaleHostResolverTest, Hosts) {
400   CreateResolverWithDnsClient(CreateMockDnsClientForHosts());
401 
402   Resolve(std::nullopt);
403   WaitForResolve();
404 
405   EXPECT_TRUE(resolve_complete());
406   EXPECT_EQ(OK, resolve_error());
407   EXPECT_EQ(1u, resolve_addresses().size());
408   EXPECT_EQ(kHostsAddress, resolve_addresses()[0].ToStringWithoutPort());
409 }
410 
TEST_F(StaleHostResolverTest,FreshCache)411 TEST_F(StaleHostResolverTest, FreshCache) {
412   CreateResolver();
413   CreateCacheEntry(kAgeFreshSec, OK);
414 
415   Resolve(std::nullopt);
416 
417   EXPECT_TRUE(resolve_complete());
418   EXPECT_EQ(OK, resolve_error());
419   EXPECT_EQ(1u, resolve_addresses().size());
420   EXPECT_EQ(kCacheAddress, resolve_addresses()[0].ToStringWithoutPort());
421 
422   WaitForIdle();
423 }
424 
425 // Flaky on Linux ASan, crbug.com/838524.
426 #if defined(ADDRESS_SANITIZER)
427 #define MAYBE_StaleCache DISABLED_StaleCache
428 #else
429 #define MAYBE_StaleCache StaleCache
430 #endif
TEST_F(StaleHostResolverTest,MAYBE_StaleCache)431 TEST_F(StaleHostResolverTest, MAYBE_StaleCache) {
432   SetStaleDelay(kNoStaleDelaySec);
433   CreateResolver();
434   CreateCacheEntry(kAgeExpiredSec, OK);
435 
436   Resolve(std::nullopt);
437   WaitForResolve();
438 
439   EXPECT_TRUE(resolve_complete());
440   EXPECT_EQ(OK, resolve_error());
441   EXPECT_EQ(1u, resolve_addresses().size());
442   EXPECT_EQ(kCacheAddress, resolve_addresses()[0].ToStringWithoutPort());
443 }
444 
445 // If the resolver is destroyed before a stale cache entry is returned, the
446 // resolve should not complete.
TEST_F(StaleHostResolverTest,StaleCache_DestroyedResolver)447 TEST_F(StaleHostResolverTest, StaleCache_DestroyedResolver) {
448   SetStaleDelay(kNoStaleDelaySec);
449   CreateResolverWithDnsClient(CreateHangingMockDnsClient());
450   CreateCacheEntry(kAgeExpiredSec, OK);
451 
452   Resolve(std::nullopt);
453   DestroyResolver();
454   WaitForResolve();
455 
456   EXPECT_FALSE(resolve_complete());
457 }
458 
459 // Ensure that |use_stale_on_name_not_resolved| causes stale results to be
460 // returned when ERR_NAME_NOT_RESOLVED is returned from network resolution.
TEST_F(StaleHostResolverTest,StaleCacheNameNotResolvedEnabled)461 TEST_F(StaleHostResolverTest, StaleCacheNameNotResolvedEnabled) {
462   SetStaleDelay(kLongStaleDelaySec);
463   SetUseStaleOnNameNotResolved();
464   SetNetResult(ERR_NAME_NOT_RESOLVED);
465   CreateResolver();
466   CreateCacheEntry(kAgeExpiredSec, OK);
467 
468   Resolve(std::nullopt);
469   WaitForResolve();
470 
471   EXPECT_TRUE(resolve_complete());
472   EXPECT_EQ(OK, resolve_error());
473   EXPECT_EQ(1u, resolve_addresses().size());
474   EXPECT_EQ(kCacheAddress, resolve_addresses()[0].ToStringWithoutPort());
475 }
476 
477 // Ensure that without |use_stale_on_name_not_resolved| network resolution
478 // failing causes StaleHostResolver jobs to fail with the same error code.
TEST_F(StaleHostResolverTest,StaleCacheNameNotResolvedDisabled)479 TEST_F(StaleHostResolverTest, StaleCacheNameNotResolvedDisabled) {
480   SetStaleDelay(kLongStaleDelaySec);
481   SetNetResult(ERR_NAME_NOT_RESOLVED);
482   CreateResolver();
483   CreateCacheEntry(kAgeExpiredSec, OK);
484 
485   Resolve(std::nullopt);
486   WaitForResolve();
487 
488   EXPECT_TRUE(resolve_complete());
489   EXPECT_EQ(ERR_NAME_NOT_RESOLVED, resolve_error());
490 }
491 
TEST_F(StaleHostResolverTest,NetworkWithStaleCache)492 TEST_F(StaleHostResolverTest, NetworkWithStaleCache) {
493   SetStaleDelay(kLongStaleDelaySec);
494   CreateResolver();
495   CreateCacheEntry(kAgeExpiredSec, OK);
496 
497   Resolve(std::nullopt);
498   WaitForResolve();
499 
500   EXPECT_TRUE(resolve_complete());
501   EXPECT_EQ(OK, resolve_error());
502   EXPECT_EQ(1u, resolve_addresses().size());
503   EXPECT_EQ(kNetworkAddress, resolve_addresses()[0].ToStringWithoutPort());
504 }
505 
TEST_F(StaleHostResolverTest,CancelWithNoCache)506 TEST_F(StaleHostResolverTest, CancelWithNoCache) {
507   SetStaleDelay(kNoStaleDelaySec);
508   CreateResolver();
509 
510   Resolve(std::nullopt);
511 
512   Cancel();
513 
514   EXPECT_FALSE(resolve_complete());
515 
516   // Make sure there's no lingering |OnResolveComplete()| callback waiting.
517   WaitForIdle();
518 }
519 
TEST_F(StaleHostResolverTest,CancelWithStaleCache)520 TEST_F(StaleHostResolverTest, CancelWithStaleCache) {
521   SetStaleDelay(kLongStaleDelaySec);
522   CreateResolver();
523   CreateCacheEntry(kAgeExpiredSec, OK);
524 
525   Resolve(std::nullopt);
526 
527   Cancel();
528 
529   EXPECT_FALSE(resolve_complete());
530 
531   // Make sure there's no lingering |OnResolveComplete()| callback waiting.
532   WaitForIdle();
533 }
534 
TEST_F(StaleHostResolverTest,ReturnStaleCacheSync)535 TEST_F(StaleHostResolverTest, ReturnStaleCacheSync) {
536   SetStaleDelay(kLongStaleDelaySec);
537   CreateResolver();
538   CreateCacheEntry(kAgeExpiredSec, OK);
539 
540   StaleHostResolver::ResolveHostParameters parameters;
541   parameters.cache_usage =
542       StaleHostResolver::ResolveHostParameters::CacheUsage::STALE_ALLOWED;
543 
544   Resolve(parameters);
545 
546   EXPECT_TRUE(resolve_complete());
547   EXPECT_EQ(OK, resolve_error());
548   EXPECT_EQ(1u, resolve_addresses().size());
549   EXPECT_EQ(kCacheAddress, resolve_addresses()[0].ToStringWithoutPort());
550 
551   WaitForIdle();
552 }
553 
554 // CancelWithFreshCache makes no sense; the request would've returned
555 // synchronously.
556 
557 // Disallow other networks cases fail under Fuchsia (crbug.com/816143).
558 // Flaky on Win buildbots. See crbug.com/836106
559 #if BUILDFLAG(IS_WIN)
560 #define MAYBE_StaleUsability DISABLED_StaleUsability
561 #else
562 #define MAYBE_StaleUsability StaleUsability
563 #endif
TEST_F(StaleHostResolverTest,MAYBE_StaleUsability)564 TEST_F(StaleHostResolverTest, MAYBE_StaleUsability) {
565   const struct {
566     int max_expired_time_sec;
567     int max_stale_uses;
568     bool allow_other_network;
569 
570     int age_sec;
571     int stale_use;
572     int network_changes;
573     int error;
574 
575     bool usable;
576   } kUsabilityTestCases[] = {
577       // Fresh data always accepted.
578       {0, 0, true, -1, 1, 0, OK, true},
579       {1, 1, false, -1, 1, 0, OK, true},
580 
581       // Unlimited expired time accepts non-zero time.
582       {0, 0, true, 1, 1, 0, OK, true},
583 
584       // Limited expired time accepts before but not after limit.
585       {2, 0, true, 1, 1, 0, OK, true},
586       {2, 0, true, 3, 1, 0, OK, false},
587 
588       // Unlimited stale uses accepts first and later uses.
589       {2, 0, true, 1, 1, 0, OK, true},
590       {2, 0, true, 1, 9, 0, OK, true},
591 
592       // Limited stale uses accepts up to and including limit.
593       {2, 2, true, 1, 1, 0, OK, true},
594       {2, 2, true, 1, 2, 0, OK, true},
595       {2, 2, true, 1, 3, 0, OK, false},
596       {2, 2, true, 1, 9, 0, OK, false},
597 
598       // Allowing other networks accepts zero or more network changes.
599       {2, 0, true, 1, 1, 0, OK, true},
600       {2, 0, true, 1, 1, 1, OK, true},
601       {2, 0, true, 1, 1, 9, OK, true},
602 
603       // Disallowing other networks only accepts zero network changes.
604       {2, 0, false, 1, 1, 0, OK, true},
605       {2, 0, false, 1, 1, 1, OK, false},
606       {2, 0, false, 1, 1, 9, OK, false},
607 
608       // Errors are only accepted if fresh.
609       {0, 0, true, -1, 1, 0, ERR_NAME_NOT_RESOLVED, true},
610       {1, 1, false, -1, 1, 0, ERR_NAME_NOT_RESOLVED, true},
611       {0, 0, true, 1, 1, 0, ERR_NAME_NOT_RESOLVED, false},
612       {2, 0, true, 1, 1, 0, ERR_NAME_NOT_RESOLVED, false},
613       {2, 0, true, 1, 1, 0, ERR_NAME_NOT_RESOLVED, false},
614       {2, 2, true, 1, 2, 0, ERR_NAME_NOT_RESOLVED, false},
615       {2, 0, true, 1, 1, 1, ERR_NAME_NOT_RESOLVED, false},
616       {2, 0, false, 1, 1, 0, ERR_NAME_NOT_RESOLVED, false},
617   };
618 
619   SetStaleDelay(kNoStaleDelaySec);
620 
621   for (size_t i = 0; i < std::size(kUsabilityTestCases); ++i) {
622     const auto& test_case = kUsabilityTestCases[i];
623 
624     SetStaleUsability(test_case.max_expired_time_sec, test_case.max_stale_uses,
625                       test_case.allow_other_network);
626     CreateResolver();
627     CreateCacheEntry(kCacheEntryTTLSec + test_case.age_sec, test_case.error);
628 
629     AdvanceTickClock(base::Milliseconds(1));
630     for (int j = 0; j < test_case.network_changes; ++j) {
631       OnNetworkChange();
632     }
633 
634     AdvanceTickClock(base::Milliseconds(1));
635     for (int j = 0; j < test_case.stale_use - 1; ++j) {
636       LookupStale();
637     }
638 
639     AdvanceTickClock(base::Milliseconds(1));
640     Resolve(std::nullopt);
641     WaitForResolve();
642     EXPECT_TRUE(resolve_complete()) << i;
643 
644     if (test_case.error == OK) {
645       EXPECT_EQ(test_case.error, resolve_error()) << i;
646       EXPECT_EQ(1u, resolve_addresses().size()) << i;
647       {
648         const char* expected =
649             test_case.usable ? kCacheAddress : kNetworkAddress;
650         EXPECT_EQ(expected, resolve_addresses()[0].ToStringWithoutPort()) << i;
651       }
652     } else {
653       if (test_case.usable) {
654         EXPECT_EQ(test_case.error, resolve_error()) << i;
655       } else {
656         EXPECT_EQ(OK, resolve_error()) << i;
657         EXPECT_EQ(1u, resolve_addresses().size()) << i;
658         EXPECT_EQ(kNetworkAddress, resolve_addresses()[0].ToStringWithoutPort())
659             << i;
660       }
661     }
662     // Make sure that all tasks complete so jobs are freed properly.
663     AdvanceTickClock(base::Seconds(kLongStaleDelaySec));
664     WaitForNetworkResolveComplete();
665     base::RunLoop run_loop;
666     run_loop.RunUntilIdle();
667 
668     DestroyResolver();
669   }
670 }
671 
672 }  // namespace
673 
674 }  // namespace net
675