| OLD | NEW |
| (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 |
| OLD | NEW |