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