Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: components/cronet/stale_host_resolver_unittest.cc

Issue 1898873006: Cronet: Use stale DNS cache entries experimentally. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@dns_stale2
Patch Set: Make requested changes. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
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 "base/callback_helpers.h"
8 #include "base/logging.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/test/test_timeouts.h"
14 #include "base/values.h"
15 #include "components/cronet/url_request_context_config.h"
16 #include "net/base/net_errors.h"
17 #include "net/cert/cert_verifier.h"
18 #include "net/dns/host_resolver_proc.h"
19 #include "net/http/http_network_session.h"
20 #include "net/proxy/proxy_config.h"
21 #include "net/proxy/proxy_config_service_fixed.h"
22 #include "net/url_request/url_request_context.h"
23 #include "net/url_request/url_request_context_builder.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace cronet {
27
28 namespace {
29
30 const char kHostname[] = "example.com";
31 const char kCacheAddress[] = "1.1.1.1";
32 const char kNetworkAddress[] = "2.2.2.2";
33 const char kUninitializedAddress[] = "3.3.3.3";
34 const int kCacheEntryTTLSec = 300;
35
36 const int kNoStaleDelaySec = 0;
37 const int kLongStaleDelaySec = 3600;
38 const uint16_t kPort = 12345;
39
40 const int kAgeFreshSec = 0;
41 const int kAgeExpiredSec = kCacheEntryTTLSec * 2;
42
43 // How long to wait for resolve calls to return. If the tests are working
44 // correctly, we won't end up waiting this long -- it's just a backup.
45 const int kWaitTimeoutSec = 1;
46
47 net::AddressList MakeAddressList(const char* ip_address_str) {
48 net::IPAddress address;
49 bool rv = address.AssignFromIPLiteral(ip_address_str);
50 DCHECK(rv);
51
52 net::AddressList address_list;
53 address_list.push_back(net::IPEndPoint(address, 0u));
54 return address_list;
55 }
56
57 class MockHostResolverProc : public net::HostResolverProc {
58 public:
59 MockHostResolverProc() : HostResolverProc(nullptr) {}
60
61 ~MockHostResolverProc() override {}
62
63 int Resolve(const std::string& hostname,
64 net::AddressFamily address_family,
65 net::HostResolverFlags host_resolver_flags,
66 net::AddressList* address_list,
67 int* os_error) override {
68 *address_list = MakeAddressList(kNetworkAddress);
69 return net::OK;
70 }
71 };
72
73 class StaleHostResolverTest : public testing::Test {
74 protected:
75 StaleHostResolverTest()
76 : mock_proc_(new MockHostResolverProc()),
77 resolver_(nullptr),
78 resolve_pending_(false),
79 resolve_complete_(false) {}
80
81 ~StaleHostResolverTest() {}
82
83 void SetStaleDelay(int stale_delay_sec) {
84 DCHECK(!resolver_);
85
86 options_.delay = base::TimeDelta::FromSeconds(stale_delay_sec);
87 }
88
89 void SetStaleUsability(int max_expired_time_sec,
90 int max_stale_uses,
91 bool allow_other_network) {
92 DCHECK(!resolver_);
93
94 options_.max_expired_time =
95 base::TimeDelta::FromSeconds(max_expired_time_sec);
96 options_.max_stale_uses = max_stale_uses;
97 options_.allow_other_network = allow_other_network;
98 }
99
100 void CreateResolver() {
101 DCHECK(!resolver_);
102
103 std::unique_ptr<net::HostResolverImpl> inner_resolver(
104 net::HostResolver::CreateDefaultResolverImpl(nullptr));
105
106 net::HostResolverImpl::ProcTaskParams proc_params(mock_proc_.get(), 1u);
107 inner_resolver->set_proc_params_for_test(proc_params);
108
109 stale_resolver_ = base::WrapUnique(
110 new StaleHostResolver(std::move(inner_resolver), options_));
111 resolver_ = stale_resolver_.get();
112 }
113
114 void DestroyResolver() {
115 DCHECK(stale_resolver_);
116
117 stale_resolver_.reset();
118 resolver_ = nullptr;
119 }
120
121 void SetResolver(net::HostResolver* resolver) {
122 DCHECK(!resolver_);
123
124 resolver_ = resolver;
125 }
126
127 void ClearResolver() {
128 DCHECK(resolver_);
129 DCHECK(!stale_resolver_);
130
131 resolver_ = nullptr;
132 }
133
134 // Creates a cache entry for |kHostname| that is |age_sec| seconds old.
135 void CreateCacheEntry(int age_sec) {
136 DCHECK(resolver_);
137 DCHECK(resolver_->GetHostCache());
138
139 base::TimeDelta ttl(base::TimeDelta::FromSeconds(kCacheEntryTTLSec));
140 net::HostCache::Key key(kHostname, net::ADDRESS_FAMILY_IPV4, 0);
141 net::HostCache::Entry entry(net::OK, MakeAddressList(kCacheAddress), ttl);
142 base::TimeDelta age = base::TimeDelta::FromSeconds(age_sec);
143 base::TimeTicks then = base::TimeTicks::Now() - age;
144 resolver_->GetHostCache()->Set(key, entry, then, ttl);
145 }
146
147 void OnNetworkChange() {
148 DCHECK(resolver_);
149 DCHECK(resolver_->GetHostCache());
150
151 resolver_->GetHostCache()->OnNetworkChange();
152 }
153
154 void LookupStale() {
155 DCHECK(resolver_);
156 DCHECK(resolver_->GetHostCache());
157
158 net::HostCache::Key key(kHostname, net::ADDRESS_FAMILY_IPV4, 0);
159 base::TimeTicks now = base::TimeTicks::Now();
160 const net::HostCache::Entry* entry;
161 net::HostCache::EntryStaleness stale;
162 entry = resolver_->GetHostCache()->LookupStale(key, now, &stale);
163 EXPECT_TRUE(entry);
164 EXPECT_TRUE(stale.is_stale());
165 }
166
167 void Resolve() {
168 DCHECK(resolver_);
169 EXPECT_FALSE(resolve_pending_);
170
171 net::HostResolver::RequestInfo info(net::HostPortPair(kHostname, kPort));
172 info.set_address_family(net::ADDRESS_FAMILY_IPV4);
173
174 resolve_pending_ = true;
175 resolve_complete_ = false;
176 resolve_addresses_ = MakeAddressList(kUninitializedAddress);
177 resolve_error_ = net::ERR_UNEXPECTED;
178
179 int rv =
180 resolver_->Resolve(info, net::DEFAULT_PRIORITY, &resolve_addresses_,
181 base::Bind(&StaleHostResolverTest::OnResolveComplete,
182 base::Unretained(this)),
183 &request_, net::BoundNetLog());
184 if (rv != net::ERR_IO_PENDING) {
185 resolve_pending_ = false;
186 resolve_complete_ = true;
187 resolve_error_ = rv;
188 }
189 }
190
191 void WaitForResolve() {
192 if (!resolve_pending_)
193 return;
194
195 base::RunLoop run_loop;
196
197 // Run until resolve completes or timeout.
198 resolve_closure_ = run_loop.QuitWhenIdleClosure();
199 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
200 FROM_HERE, run_loop.QuitWhenIdleClosure(),
201 base::TimeDelta::FromSeconds(kWaitTimeoutSec));
202 run_loop.Run();
203 }
204
205 void WaitForIdle() {
206 base::RunLoop run_loop;
207
208 base::ThreadTaskRunnerHandle::Get()->PostTask(
209 FROM_HERE, run_loop.QuitWhenIdleClosure());
210 run_loop.Run();
211 }
212
213 void Cancel() {
214 DCHECK(resolver_);
215 EXPECT_TRUE(resolve_pending_);
216
217 delete request_.release();
218
219 resolve_pending_ = false;
220 }
221
222 void OnResolveComplete(int error) {
223 EXPECT_TRUE(resolve_pending_);
224
225 request_.reset();
226
227 resolve_error_ = error;
228 resolve_pending_ = false;
229 resolve_complete_ = true;
230
231 if (!resolve_closure_.is_null())
232 base::ResetAndReturn(&resolve_closure_).Run();
233 }
234
235 bool resolve_complete() const { return resolve_complete_; }
236 int resolve_error() const { return resolve_error_; }
237 const net::AddressList& resolve_addresses() const {
238 return resolve_addresses_;
239 }
240
241 private:
242 // Needed for HostResolver to run HostResolverProc callbacks.
243 base::MessageLoopForIO message_loop_for_io_;
244 scoped_refptr<MockHostResolverProc> mock_proc_;
245
246 net::HostResolver* resolver_;
247 StaleHostResolver::StaleOptions options_;
248 std::unique_ptr<StaleHostResolver> stale_resolver_;
249
250 base::TimeTicks now_;
251 std::unique_ptr<net::HostResolver::Request> request_;
252 bool resolve_pending_;
253 bool resolve_complete_;
254 net::AddressList resolve_addresses_;
255 int resolve_error_;
256
257 base::Closure resolve_closure_;
258 };
259
260 // Make sure that test harness can be created and destroyed without crashing.
261 TEST_F(StaleHostResolverTest, Null) {}
262
263 // Make sure that resolver can be created and destroyed without crashing.
264 TEST_F(StaleHostResolverTest, Create) {
265 CreateResolver();
266 }
267
268 TEST_F(StaleHostResolverTest, Network) {
269 CreateResolver();
270
271 Resolve();
272 WaitForResolve();
273
274 EXPECT_TRUE(resolve_complete());
275 EXPECT_EQ(net::OK, resolve_error());
276 EXPECT_EQ(1u, resolve_addresses().size());
277 EXPECT_EQ(kNetworkAddress, resolve_addresses()[0].ToStringWithoutPort());
278 }
279
280 TEST_F(StaleHostResolverTest, FreshCache) {
281 CreateResolver();
282 CreateCacheEntry(kAgeFreshSec);
283
284 Resolve();
285
286 EXPECT_TRUE(resolve_complete());
287 EXPECT_EQ(net::OK, resolve_error());
288 EXPECT_EQ(1u, resolve_addresses().size());
289 EXPECT_EQ(kCacheAddress, resolve_addresses()[0].ToStringWithoutPort());
290
291 WaitForIdle();
292 }
293
294 TEST_F(StaleHostResolverTest, StaleCache) {
295 SetStaleDelay(kNoStaleDelaySec);
296 CreateResolver();
297 CreateCacheEntry(kAgeExpiredSec);
298
299 Resolve();
300 WaitForResolve();
301
302 EXPECT_TRUE(resolve_complete());
303 EXPECT_EQ(net::OK, resolve_error());
304 EXPECT_EQ(1u, resolve_addresses().size());
305 EXPECT_EQ(kCacheAddress, resolve_addresses()[0].ToStringWithoutPort());
306 }
307
308 TEST_F(StaleHostResolverTest, NetworkWithStaleCache) {
309 SetStaleDelay(kLongStaleDelaySec);
310 CreateResolver();
311 CreateCacheEntry(kAgeExpiredSec);
312
313 Resolve();
314 WaitForResolve();
315
316 EXPECT_TRUE(resolve_complete());
317 EXPECT_EQ(net::OK, resolve_error());
318 EXPECT_EQ(1u, resolve_addresses().size());
319 EXPECT_EQ(kNetworkAddress, resolve_addresses()[0].ToStringWithoutPort());
320 }
321
322 TEST_F(StaleHostResolverTest, CancelWithNoCache) {
323 SetStaleDelay(kNoStaleDelaySec);
324 CreateResolver();
325
326 Resolve();
327
328 Cancel();
329
330 EXPECT_FALSE(resolve_complete());
331
332 // Make sure there's no lingering |OnResolveComplete()| callback waiting.
333 WaitForIdle();
334 }
335
336 TEST_F(StaleHostResolverTest, CancelWithStaleCache) {
337 SetStaleDelay(kLongStaleDelaySec);
338 CreateResolver();
339 CreateCacheEntry(kAgeExpiredSec);
340
341 Resolve();
342
343 Cancel();
344
345 EXPECT_FALSE(resolve_complete());
346
347 // Make sure there's no lingering |OnResolveComplete()| callback waiting.
348 WaitForIdle();
349 }
350
351 // CancelWithFreshCache makes no sense; the request would've returned
352 // synchronously.
353
354 TEST_F(StaleHostResolverTest, StaleUsability) {
355 const struct {
356 int max_expired_time_sec;
357 int max_stale_uses;
358 bool allow_other_network;
359
360 int age_sec;
361 int stale_use;
362 int network_changes;
363
364 bool usable;
365 } kUsabilityTestCases[] = {
366 // Fresh data always accepted.
367 {0, 0, true, -1, 1, 0, true},
368 {1, 1, false, -1, 1, 0, true},
369
370 // Unlimited expired time accepts non-zero time.
371 {0, 0, true, 1, 1, 0, true},
372
373 // Limited expired time accepts before but not after limit.
374 {2, 0, true, 1, 1, 0, true},
375 {2, 0, true, 3, 1, 0, false},
376
377 // Unlimited stale uses accepts first and later uses.
378 {2, 0, true, 1, 1, 0, true},
379 {2, 0, true, 1, 9, 0, true},
380
381 // Limited stale uses accepts up to and including limit.
382 {2, 2, true, 1, 1, 0, true},
383 {2, 2, true, 1, 2, 0, true},
384 {2, 2, true, 1, 3, 0, false},
385 {2, 2, true, 1, 9, 0, false},
386
387 // Allowing other networks accepts zero or more network changes.
388 {2, 0, true, 1, 1, 0, true},
389 {2, 0, true, 1, 1, 1, true},
390 {2, 0, true, 1, 1, 9, true},
391
392 // Disallowing other networks only accepts zero network changes.
393 {2, 0, false, 1, 1, 0, true},
394 {2, 0, false, 1, 1, 1, false},
395 {2, 0, false, 1, 1, 9, false},
396 };
397
398 SetStaleDelay(kNoStaleDelaySec);
399
400 for (size_t i = 0; i < arraysize(kUsabilityTestCases); ++i) {
401 const auto& test_case = kUsabilityTestCases[i];
402
403 SetStaleUsability(test_case.max_expired_time_sec, test_case.max_stale_uses,
404 test_case.allow_other_network);
405 CreateResolver();
406 CreateCacheEntry(kCacheEntryTTLSec + test_case.age_sec);
407 for (int j = 0; j < test_case.network_changes; ++j)
408 OnNetworkChange();
409 for (int j = 0; j < test_case.stale_use - 1; ++j)
410 LookupStale();
411
412 Resolve();
413 WaitForResolve();
414 EXPECT_TRUE(resolve_complete()) << i;
415 EXPECT_EQ(net::OK, resolve_error()) << i;
416 EXPECT_EQ(1u, resolve_addresses().size()) << i;
417 {
418 const char* expected = test_case.usable ? kCacheAddress : kNetworkAddress;
419 EXPECT_EQ(expected, resolve_addresses()[0].ToStringWithoutPort()) << i;
420 }
421
422 DestroyResolver();
423 }
424 }
425
426 TEST_F(StaleHostResolverTest, CreatedByContext) {
427 URLRequestContextConfig config(
428 // Enable QUIC.
429 true,
430 // QUIC User Agent ID.
431 "Default QUIC User Agent ID",
432 // Enable SPDY.
433 true,
434 // Enable SDCH.
435 false,
436 // Type of http cache.
437 URLRequestContextConfig::HttpCacheType::DISK,
438 // Max size of http cache in bytes.
439 1024000,
440 // Disable caching for HTTP responses. Other information may be stored in
441 // the cache.
442 false,
443 // Storage path for http cache and cookie storage.
444 "/data/data/org.chromium.net/app_cronet_test/test_storage",
445 // User-Agent request header field.
446 "fake agent",
447 // JSON encoded experimental options.
448 "{\"AsyncDNS\":{\"enable\":false},"
449 "\"StaleDNS\":{\"enable\":true,"
450 "\"delay_ms\":0,"
451 "\"max_expired_time_ms\":0,"
452 "\"max_stale_uses\":0}}",
453 // Data reduction proxy key.
454 "",
455 // Data reduction proxy.
456 "",
457 // Fallback data reduction proxy.
458 "",
459 // Data reduction proxy secure proxy check URL.
460 "",
461 // MockCertVerifier to use for testing purposes.
462 std::unique_ptr<net::CertVerifier>(),
463 // Enable network quality estimator.
464 false,
465 // Enable Public Key Pinning bypass for local trust anchors.
466 true,
467 // Certificate verifier cache data.
468 "");
469
470 net::URLRequestContextBuilder builder;
471 net::NetLog net_log;
472 config.ConfigureURLRequestContextBuilder(&builder, &net_log, nullptr);
473 // Set a ProxyConfigService to avoid DCHECK failure when building.
474 builder.set_proxy_config_service(base::WrapUnique(
475 new net::ProxyConfigServiceFixed(net::ProxyConfig::CreateDirect())));
476 std::unique_ptr<net::URLRequestContext> context(builder.Build());
477
478 // Duplicate StaleCache test case to ensure StaleHostResolver was created:
479
480 // Note: Experimental config above sets 0ms stale delay.
481 SetResolver(context->host_resolver());
482 CreateCacheEntry(kAgeExpiredSec);
483
484 Resolve();
485 EXPECT_FALSE(resolve_complete());
486 WaitForResolve();
487
488 EXPECT_TRUE(resolve_complete());
489 EXPECT_EQ(net::OK, resolve_error());
490 EXPECT_EQ(1u, resolve_addresses().size());
491 EXPECT_EQ(kCacheAddress, resolve_addresses()[0].ToStringWithoutPort());
492 }
493
494 } // namespace
495
496 } // namespace cronet
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698