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