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