1 // Copyright (c) 2006-2008 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 "net/base/host_resolver_impl.h" 6 7 #include <string> 8 9 #include "base/compiler_specific.h" 10 #include "base/message_loop.h" 11 #include "base/ref_counted.h" 12 #include "net/base/address_list.h" 13 #include "net/base/completion_callback.h" 14 #include "net/base/load_log_unittest.h" 15 #include "net/base/mock_host_resolver.h" 16 #include "net/base/mock_network_change_notifier.h" 17 #include "net/base/net_errors.h" 18 #include "net/base/sys_addrinfo.h" 19 #include "net/base/test_completion_callback.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 // TODO(eroman): 23 // - Test mixing async with sync (in particular how does sync update the 24 // cache while an async is already pending). 25 26 namespace net { 27 28 namespace { 29 30 HostCache* CreateDefaultCache() { 31 return new HostCache( 32 100, // max cache entries. 33 base::TimeDelta::FromMinutes(1), 34 base::TimeDelta::FromSeconds(0)); 35 } 36 37 static const size_t kMaxJobs = 10u; 38 39 HostResolverImpl* CreateHostResolverImpl(HostResolverProc* resolver_proc) { 40 return new HostResolverImpl( 41 resolver_proc, 42 CreateDefaultCache(), 43 NULL, // network_change_notifier 44 kMaxJobs); 45 } 46 47 // Helper to create a HostResolver::RequestInfo. 48 HostResolver::RequestInfo CreateResolverRequest( 49 const std::string& hostname, 50 RequestPriority priority) { 51 HostResolver::RequestInfo info(hostname, 80); 52 info.set_priority(priority); 53 return info; 54 } 55 56 // A variant of WaitingHostResolverProc that pushes each host mapped into a 57 // list. 58 // (and uses a manual-reset event rather than auto-reset). 59 class CapturingHostResolverProc : public HostResolverProc { 60 public: 61 explicit CapturingHostResolverProc(HostResolverProc* previous) 62 : HostResolverProc(previous), event_(true, false) { 63 } 64 65 void Signal() { 66 event_.Signal(); 67 } 68 69 virtual int Resolve(const std::string& host, 70 AddressFamily address_family, 71 AddressList* addrlist) { 72 event_.Wait(); 73 { 74 AutoLock l(lock_); 75 capture_list_.push_back(host); 76 } 77 return ResolveUsingPrevious(host, address_family, addrlist); 78 } 79 80 std::vector<std::string> GetCaptureList() const { 81 std::vector<std::string> copy; 82 { 83 AutoLock l(lock_); 84 copy = capture_list_; 85 } 86 return copy; 87 } 88 89 private: 90 ~CapturingHostResolverProc() {} 91 92 std::vector<std::string> capture_list_; 93 mutable Lock lock_; 94 base::WaitableEvent event_; 95 }; 96 97 // Helper that represents a single Resolve() result, used to inspect all the 98 // resolve results by forwarding them to Delegate. 99 class ResolveRequest { 100 public: 101 // Delegate interface, for notification when the ResolveRequest completes. 102 class Delegate { 103 public: 104 virtual ~Delegate() {} 105 virtual void OnCompleted(ResolveRequest* resolve) = 0; 106 }; 107 108 ResolveRequest(HostResolver* resolver, 109 const std::string& hostname, 110 int port, 111 Delegate* delegate) 112 : info_(hostname, port), resolver_(resolver), delegate_(delegate), 113 ALLOW_THIS_IN_INITIALIZER_LIST( 114 callback_(this, &ResolveRequest::OnLookupFinished)) { 115 // Start the request. 116 int err = resolver->Resolve(info_, &addrlist_, &callback_, &req_, NULL); 117 EXPECT_EQ(ERR_IO_PENDING, err); 118 } 119 120 ResolveRequest(HostResolver* resolver, 121 const HostResolver::RequestInfo& info, 122 Delegate* delegate) 123 : info_(info), resolver_(resolver), delegate_(delegate), 124 ALLOW_THIS_IN_INITIALIZER_LIST( 125 callback_(this, &ResolveRequest::OnLookupFinished)) { 126 // Start the request. 127 int err = resolver->Resolve(info, &addrlist_, &callback_, &req_, NULL); 128 EXPECT_EQ(ERR_IO_PENDING, err); 129 } 130 131 void Cancel() { 132 resolver_->CancelRequest(req_); 133 } 134 135 const std::string& hostname() const { 136 return info_.hostname(); 137 } 138 139 int port() const { 140 return info_.port(); 141 } 142 143 int result() const { 144 return result_; 145 } 146 147 const AddressList& addrlist() const { 148 return addrlist_; 149 } 150 151 HostResolver* resolver() const { 152 return resolver_; 153 } 154 155 private: 156 void OnLookupFinished(int result) { 157 result_ = result; 158 delegate_->OnCompleted(this); 159 } 160 161 // The request details. 162 HostResolver::RequestInfo info_; 163 HostResolver::RequestHandle req_; 164 165 // The result of the resolve. 166 int result_; 167 AddressList addrlist_; 168 169 // We don't use a scoped_refptr, to simplify deleting shared resolver in 170 // DeleteWithinCallback test. 171 HostResolver* resolver_; 172 173 Delegate* delegate_; 174 CompletionCallbackImpl<ResolveRequest> callback_; 175 176 DISALLOW_COPY_AND_ASSIGN(ResolveRequest); 177 }; 178 179 class HostResolverImplTest : public testing::Test { 180 public: 181 HostResolverImplTest() 182 : callback_called_(false), 183 ALLOW_THIS_IN_INITIALIZER_LIST( 184 callback_(this, &HostResolverImplTest::OnLookupFinished)) { 185 } 186 187 protected: 188 bool callback_called_; 189 int callback_result_; 190 CompletionCallbackImpl<HostResolverImplTest> callback_; 191 192 private: 193 void OnLookupFinished(int result) { 194 callback_called_ = true; 195 callback_result_ = result; 196 MessageLoop::current()->Quit(); 197 } 198 }; 199 200 TEST_F(HostResolverImplTest, SynchronousLookup) { 201 AddressList adrlist; 202 const int kPortnum = 80; 203 204 scoped_refptr<RuleBasedHostResolverProc> resolver_proc = 205 new RuleBasedHostResolverProc(NULL); 206 resolver_proc->AddRule("just.testing", "192.168.1.42"); 207 208 scoped_refptr<HostResolver> host_resolver( 209 CreateHostResolverImpl(resolver_proc)); 210 211 HostResolver::RequestInfo info("just.testing", kPortnum); 212 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); 213 int err = host_resolver->Resolve(info, &adrlist, NULL, NULL, log); 214 EXPECT_EQ(OK, err); 215 216 EXPECT_EQ(2u, log->entries().size()); 217 EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_HOST_RESOLVER_IMPL)); 218 EXPECT_TRUE(LogContainsEndEvent(*log, 1, LoadLog::TYPE_HOST_RESOLVER_IMPL)); 219 220 const struct addrinfo* ainfo = adrlist.head(); 221 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); 222 EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); 223 224 const struct sockaddr* sa = ainfo->ai_addr; 225 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; 226 EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); 227 EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr); 228 } 229 230 TEST_F(HostResolverImplTest, AsynchronousLookup) { 231 AddressList adrlist; 232 const int kPortnum = 80; 233 234 scoped_refptr<RuleBasedHostResolverProc> resolver_proc = 235 new RuleBasedHostResolverProc(NULL); 236 resolver_proc->AddRule("just.testing", "192.168.1.42"); 237 238 scoped_refptr<HostResolver> host_resolver( 239 CreateHostResolverImpl(resolver_proc)); 240 241 HostResolver::RequestInfo info("just.testing", kPortnum); 242 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); 243 int err = host_resolver->Resolve(info, &adrlist, &callback_, NULL, log); 244 EXPECT_EQ(ERR_IO_PENDING, err); 245 246 EXPECT_EQ(1u, log->entries().size()); 247 EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_HOST_RESOLVER_IMPL)); 248 249 MessageLoop::current()->Run(); 250 251 ASSERT_TRUE(callback_called_); 252 ASSERT_EQ(OK, callback_result_); 253 254 EXPECT_EQ(2u, log->entries().size()); 255 EXPECT_TRUE(LogContainsEndEvent(*log, 1, LoadLog::TYPE_HOST_RESOLVER_IMPL)); 256 257 const struct addrinfo* ainfo = adrlist.head(); 258 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); 259 EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); 260 261 const struct sockaddr* sa = ainfo->ai_addr; 262 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; 263 EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); 264 EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr); 265 } 266 267 TEST_F(HostResolverImplTest, CanceledAsynchronousLookup) { 268 scoped_refptr<WaitingHostResolverProc> resolver_proc = 269 new WaitingHostResolverProc(NULL); 270 271 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); 272 { 273 scoped_refptr<HostResolver> host_resolver( 274 CreateHostResolverImpl(resolver_proc)); 275 AddressList adrlist; 276 const int kPortnum = 80; 277 278 HostResolver::RequestInfo info("just.testing", kPortnum); 279 int err = host_resolver->Resolve(info, &adrlist, &callback_, NULL, log); 280 EXPECT_EQ(ERR_IO_PENDING, err); 281 282 // Make sure we will exit the queue even when callback is not called. 283 MessageLoop::current()->PostDelayedTask(FROM_HERE, 284 new MessageLoop::QuitTask(), 285 1000); 286 MessageLoop::current()->Run(); 287 } 288 289 resolver_proc->Signal(); 290 291 EXPECT_EQ(3u, log->entries().size()); 292 EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_HOST_RESOLVER_IMPL)); 293 EXPECT_TRUE(LogContainsEvent( 294 *log, 1, LoadLog::TYPE_CANCELLED, LoadLog::PHASE_NONE)); 295 EXPECT_TRUE(LogContainsEndEvent(*log, 2, LoadLog::TYPE_HOST_RESOLVER_IMPL)); 296 297 EXPECT_FALSE(callback_called_); 298 } 299 300 TEST_F(HostResolverImplTest, NumericIPv4Address) { 301 // Stevens says dotted quads with AI_UNSPEC resolve to a single sockaddr_in. 302 303 scoped_refptr<RuleBasedHostResolverProc> resolver_proc = 304 new RuleBasedHostResolverProc(NULL); 305 resolver_proc->AllowDirectLookup("*"); 306 307 scoped_refptr<HostResolver> host_resolver( 308 CreateHostResolverImpl(resolver_proc)); 309 AddressList adrlist; 310 const int kPortnum = 5555; 311 HostResolver::RequestInfo info("127.1.2.3", kPortnum); 312 int err = host_resolver->Resolve(info, &adrlist, NULL, NULL, NULL); 313 EXPECT_EQ(OK, err); 314 315 const struct addrinfo* ainfo = adrlist.head(); 316 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); 317 EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); 318 319 const struct sockaddr* sa = ainfo->ai_addr; 320 const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; 321 EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); 322 EXPECT_TRUE(htonl(0x7f010203) == sa_in->sin_addr.s_addr); 323 } 324 325 TEST_F(HostResolverImplTest, NumericIPv6Address) { 326 scoped_refptr<RuleBasedHostResolverProc> resolver_proc = 327 new RuleBasedHostResolverProc(NULL); 328 resolver_proc->AllowDirectLookup("*"); 329 330 // Resolve a plain IPv6 address. Don't worry about [brackets], because 331 // the caller should have removed them. 332 scoped_refptr<HostResolver> host_resolver( 333 CreateHostResolverImpl(resolver_proc)); 334 AddressList adrlist; 335 const int kPortnum = 5555; 336 HostResolver::RequestInfo info("2001:db8::1", kPortnum); 337 int err = host_resolver->Resolve(info, &adrlist, NULL, NULL, NULL); 338 // On computers without IPv6 support, getaddrinfo cannot convert IPv6 339 // address literals to addresses (getaddrinfo returns EAI_NONAME). So this 340 // test has to allow host_resolver->Resolve to fail. 341 if (err == ERR_NAME_NOT_RESOLVED) 342 return; 343 EXPECT_EQ(OK, err); 344 345 const struct addrinfo* ainfo = adrlist.head(); 346 EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); 347 EXPECT_EQ(sizeof(struct sockaddr_in6), ainfo->ai_addrlen); 348 349 const struct sockaddr* sa = ainfo->ai_addr; 350 const struct sockaddr_in6* sa_in6 = (const struct sockaddr_in6*) sa; 351 EXPECT_TRUE(htons(kPortnum) == sa_in6->sin6_port); 352 353 const uint8 expect_addr[] = { 354 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 356 }; 357 for (int i = 0; i < 16; i++) { 358 EXPECT_EQ(expect_addr[i], sa_in6->sin6_addr.s6_addr[i]); 359 } 360 } 361 362 TEST_F(HostResolverImplTest, EmptyHost) { 363 scoped_refptr<RuleBasedHostResolverProc> resolver_proc = 364 new RuleBasedHostResolverProc(NULL); 365 resolver_proc->AllowDirectLookup("*"); 366 367 scoped_refptr<HostResolver> host_resolver( 368 CreateHostResolverImpl(resolver_proc)); 369 AddressList adrlist; 370 const int kPortnum = 5555; 371 HostResolver::RequestInfo info("", kPortnum); 372 int err = host_resolver->Resolve(info, &adrlist, NULL, NULL, NULL); 373 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, err); 374 } 375 376 // Helper class used by HostResolverImplTest.DeDupeRequests. It receives request 377 // completion notifications for all the resolves, so it can tally up and 378 // determine when we are done. 379 class DeDupeRequestsVerifier : public ResolveRequest::Delegate { 380 public: 381 explicit DeDupeRequestsVerifier(CapturingHostResolverProc* resolver_proc) 382 : count_a_(0), count_b_(0), resolver_proc_(resolver_proc) {} 383 384 // The test does 5 resolves (which can complete in any order). 385 virtual void OnCompleted(ResolveRequest* resolve) { 386 // Tally up how many requests we have seen. 387 if (resolve->hostname() == "a") { 388 count_a_++; 389 } else if (resolve->hostname() == "b") { 390 count_b_++; 391 } else { 392 FAIL() << "Unexpected hostname: " << resolve->hostname(); 393 } 394 395 // Check that the port was set correctly. 396 EXPECT_EQ(resolve->port(), resolve->addrlist().GetPort()); 397 398 // Check whether all the requests have finished yet. 399 int total_completions = count_a_ + count_b_; 400 if (total_completions == 5) { 401 EXPECT_EQ(2, count_a_); 402 EXPECT_EQ(3, count_b_); 403 404 // The resolver_proc should have been called only twice -- once with "a", 405 // once with "b". 406 std::vector<std::string> capture_list = resolver_proc_->GetCaptureList(); 407 EXPECT_EQ(2U, capture_list.size()); 408 409 // End this test, we are done. 410 MessageLoop::current()->Quit(); 411 } 412 } 413 414 private: 415 int count_a_; 416 int count_b_; 417 CapturingHostResolverProc* resolver_proc_; 418 419 DISALLOW_COPY_AND_ASSIGN(DeDupeRequestsVerifier); 420 }; 421 422 TEST_F(HostResolverImplTest, DeDupeRequests) { 423 // Use a capturing resolver_proc, since the verifier needs to know what calls 424 // reached Resolve(). Also, the capturing resolver_proc is initially blocked. 425 scoped_refptr<CapturingHostResolverProc> resolver_proc = 426 new CapturingHostResolverProc(NULL); 427 428 scoped_refptr<HostResolver> host_resolver( 429 CreateHostResolverImpl(resolver_proc)); 430 431 // The class will receive callbacks for when each resolve completes. It 432 // checks that the right things happened. 433 DeDupeRequestsVerifier verifier(resolver_proc.get()); 434 435 // Start 5 requests, duplicating hosts "a" and "b". Since the resolver_proc is 436 // blocked, these should all pile up until we signal it. 437 438 ResolveRequest req1(host_resolver, "a", 80, &verifier); 439 ResolveRequest req2(host_resolver, "b", 80, &verifier); 440 ResolveRequest req3(host_resolver, "b", 81, &verifier); 441 ResolveRequest req4(host_resolver, "a", 82, &verifier); 442 ResolveRequest req5(host_resolver, "b", 83, &verifier); 443 444 // Ready, Set, GO!!! 445 resolver_proc->Signal(); 446 447 // |verifier| will send quit message once all the requests have finished. 448 MessageLoop::current()->Run(); 449 } 450 451 // Helper class used by HostResolverImplTest.CancelMultipleRequests. 452 class CancelMultipleRequestsVerifier : public ResolveRequest::Delegate { 453 public: 454 CancelMultipleRequestsVerifier() {} 455 456 // The cancels kill all but one request. 457 virtual void OnCompleted(ResolveRequest* resolve) { 458 EXPECT_EQ("a", resolve->hostname()); 459 EXPECT_EQ(82, resolve->port()); 460 461 // Check that the port was set correctly. 462 EXPECT_EQ(resolve->port(), resolve->addrlist().GetPort()); 463 464 // End this test, we are done. 465 MessageLoop::current()->Quit(); 466 } 467 468 private: 469 DISALLOW_COPY_AND_ASSIGN(CancelMultipleRequestsVerifier); 470 }; 471 472 TEST_F(HostResolverImplTest, CancelMultipleRequests) { 473 // Use a capturing resolver_proc, since the verifier needs to know what calls 474 // reached Resolver(). Also, the capturing resolver_proc is initially 475 // blocked. 476 scoped_refptr<CapturingHostResolverProc> resolver_proc = 477 new CapturingHostResolverProc(NULL); 478 479 scoped_refptr<HostResolver> host_resolver( 480 CreateHostResolverImpl(resolver_proc)); 481 482 // The class will receive callbacks for when each resolve completes. It 483 // checks that the right things happened. 484 CancelMultipleRequestsVerifier verifier; 485 486 // Start 5 requests, duplicating hosts "a" and "b". Since the resolver_proc is 487 // blocked, these should all pile up until we signal it. 488 489 ResolveRequest req1(host_resolver, "a", 80, &verifier); 490 ResolveRequest req2(host_resolver, "b", 80, &verifier); 491 ResolveRequest req3(host_resolver, "b", 81, &verifier); 492 ResolveRequest req4(host_resolver, "a", 82, &verifier); 493 ResolveRequest req5(host_resolver, "b", 83, &verifier); 494 495 // Cancel everything except request 4. 496 req1.Cancel(); 497 req2.Cancel(); 498 req3.Cancel(); 499 req5.Cancel(); 500 501 // Ready, Set, GO!!! 502 resolver_proc->Signal(); 503 504 // |verifier| will send quit message once all the requests have finished. 505 MessageLoop::current()->Run(); 506 } 507 508 // Helper class used by HostResolverImplTest.CancelWithinCallback. 509 class CancelWithinCallbackVerifier : public ResolveRequest::Delegate { 510 public: 511 CancelWithinCallbackVerifier() 512 : req_to_cancel1_(NULL), req_to_cancel2_(NULL), num_completions_(0) { 513 } 514 515 virtual void OnCompleted(ResolveRequest* resolve) { 516 num_completions_++; 517 518 // Port 80 is the first request that the callback will be invoked for. 519 // While we are executing within that callback, cancel the other requests 520 // in the job and start another request. 521 if (80 == resolve->port()) { 522 EXPECT_EQ("a", resolve->hostname()); 523 524 req_to_cancel1_->Cancel(); 525 req_to_cancel2_->Cancel(); 526 527 // Start a request (so we can make sure the canceled requests don't 528 // complete before "finalrequest" finishes. 529 final_request_.reset(new ResolveRequest( 530 resolve->resolver(), "finalrequest", 70, this)); 531 532 } else if (83 == resolve->port()) { 533 EXPECT_EQ("a", resolve->hostname()); 534 } else if (resolve->hostname() == "finalrequest") { 535 EXPECT_EQ(70, resolve->addrlist().GetPort()); 536 537 // End this test, we are done. 538 MessageLoop::current()->Quit(); 539 } else { 540 FAIL() << "Unexpected completion: " << resolve->hostname() << ", " 541 << resolve->port(); 542 } 543 } 544 545 void SetRequestsToCancel(ResolveRequest* req_to_cancel1, 546 ResolveRequest* req_to_cancel2) { 547 req_to_cancel1_ = req_to_cancel1; 548 req_to_cancel2_ = req_to_cancel2; 549 } 550 551 private: 552 scoped_ptr<ResolveRequest> final_request_; 553 ResolveRequest* req_to_cancel1_; 554 ResolveRequest* req_to_cancel2_; 555 int num_completions_; 556 DISALLOW_COPY_AND_ASSIGN(CancelWithinCallbackVerifier); 557 }; 558 559 TEST_F(HostResolverImplTest, CancelWithinCallback) { 560 // Use a capturing resolver_proc, since the verifier needs to know what calls 561 // reached Resolver(). Also, the capturing resolver_proc is initially 562 // blocked. 563 scoped_refptr<CapturingHostResolverProc> resolver_proc = 564 new CapturingHostResolverProc(NULL); 565 566 scoped_refptr<HostResolver> host_resolver( 567 CreateHostResolverImpl(resolver_proc)); 568 569 // The class will receive callbacks for when each resolve completes. It 570 // checks that the right things happened. 571 CancelWithinCallbackVerifier verifier; 572 573 // Start 4 requests, duplicating hosts "a". Since the resolver_proc is 574 // blocked, these should all pile up until we signal it. 575 576 ResolveRequest req1(host_resolver, "a", 80, &verifier); 577 ResolveRequest req2(host_resolver, "a", 81, &verifier); 578 ResolveRequest req3(host_resolver, "a", 82, &verifier); 579 ResolveRequest req4(host_resolver, "a", 83, &verifier); 580 581 // Once "a:80" completes, it will cancel "a:81" and "a:82". 582 verifier.SetRequestsToCancel(&req2, &req3); 583 584 // Ready, Set, GO!!! 585 resolver_proc->Signal(); 586 587 // |verifier| will send quit message once all the requests have finished. 588 MessageLoop::current()->Run(); 589 } 590 591 // Helper class used by HostResolverImplTest.DeleteWithinCallback. 592 class DeleteWithinCallbackVerifier : public ResolveRequest::Delegate { 593 public: 594 // |host_resolver| is the resolver that the the resolve requests were started 595 // with. 596 DeleteWithinCallbackVerifier(HostResolver* host_resolver) 597 : host_resolver_(host_resolver) {} 598 599 virtual void OnCompleted(ResolveRequest* resolve) { 600 EXPECT_EQ("a", resolve->hostname()); 601 EXPECT_EQ(80, resolve->port()); 602 603 // Release the last reference to the host resolver that started the 604 // requests. 605 host_resolver_ = NULL; 606 607 // Quit after returning from OnCompleted (to give it a chance at 608 // incorrectly running the cancelled tasks). 609 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); 610 } 611 612 private: 613 scoped_refptr<HostResolver> host_resolver_; 614 DISALLOW_COPY_AND_ASSIGN(DeleteWithinCallbackVerifier); 615 }; 616 617 TEST_F(HostResolverImplTest, DeleteWithinCallback) { 618 // Use a capturing resolver_proc, since the verifier needs to know what calls 619 // reached Resolver(). Also, the capturing resolver_proc is initially 620 // blocked. 621 scoped_refptr<CapturingHostResolverProc> resolver_proc = 622 new CapturingHostResolverProc(NULL); 623 624 // The class will receive callbacks for when each resolve completes. It 625 // checks that the right things happened. Note that the verifier holds the 626 // only reference to |host_resolver|, so it can delete it within callback. 627 HostResolver* host_resolver = 628 CreateHostResolverImpl(resolver_proc); 629 DeleteWithinCallbackVerifier verifier(host_resolver); 630 631 // Start 4 requests, duplicating hosts "a". Since the resolver_proc is 632 // blocked, these should all pile up until we signal it. 633 634 ResolveRequest req1(host_resolver, "a", 80, &verifier); 635 ResolveRequest req2(host_resolver, "a", 81, &verifier); 636 ResolveRequest req3(host_resolver, "a", 82, &verifier); 637 ResolveRequest req4(host_resolver, "a", 83, &verifier); 638 639 // Ready, Set, GO!!! 640 resolver_proc->Signal(); 641 642 // |verifier| will send quit message once all the requests have finished. 643 MessageLoop::current()->Run(); 644 } 645 646 // Helper class used by HostResolverImplTest.StartWithinCallback. 647 class StartWithinCallbackVerifier : public ResolveRequest::Delegate { 648 public: 649 StartWithinCallbackVerifier() : num_requests_(0) {} 650 651 virtual void OnCompleted(ResolveRequest* resolve) { 652 EXPECT_EQ("a", resolve->hostname()); 653 654 if (80 == resolve->port()) { 655 // On completing the first request, start another request for "a". 656 // Since caching is disabled, this will result in another async request. 657 final_request_.reset(new ResolveRequest( 658 resolve->resolver(), "a", 70, this)); 659 } 660 if (++num_requests_ == 5) { 661 // Test is done. 662 MessageLoop::current()->Quit(); 663 } 664 } 665 666 private: 667 int num_requests_; 668 scoped_ptr<ResolveRequest> final_request_; 669 DISALLOW_COPY_AND_ASSIGN(StartWithinCallbackVerifier); 670 }; 671 672 TEST_F(HostResolverImplTest, StartWithinCallback) { 673 // Use a capturing resolver_proc, since the verifier needs to know what calls 674 // reached Resolver(). Also, the capturing resolver_proc is initially 675 // blocked. 676 scoped_refptr<CapturingHostResolverProc> resolver_proc = 677 new CapturingHostResolverProc(NULL); 678 679 // Turn off caching for this host resolver. 680 scoped_refptr<HostResolver> host_resolver( 681 new HostResolverImpl(resolver_proc, NULL, NULL, kMaxJobs)); 682 683 // The class will receive callbacks for when each resolve completes. It 684 // checks that the right things happened. 685 StartWithinCallbackVerifier verifier; 686 687 // Start 4 requests, duplicating hosts "a". Since the resolver_proc is 688 // blocked, these should all pile up until we signal it. 689 690 ResolveRequest req1(host_resolver, "a", 80, &verifier); 691 ResolveRequest req2(host_resolver, "a", 81, &verifier); 692 ResolveRequest req3(host_resolver, "a", 82, &verifier); 693 ResolveRequest req4(host_resolver, "a", 83, &verifier); 694 695 // Ready, Set, GO!!! 696 resolver_proc->Signal(); 697 698 // |verifier| will send quit message once all the requests have finished. 699 MessageLoop::current()->Run(); 700 } 701 702 // Helper class used by HostResolverImplTest.BypassCache. 703 class BypassCacheVerifier : public ResolveRequest::Delegate { 704 public: 705 BypassCacheVerifier() {} 706 707 virtual void OnCompleted(ResolveRequest* resolve) { 708 EXPECT_EQ("a", resolve->hostname()); 709 HostResolver* resolver = resolve->resolver(); 710 711 if (80 == resolve->port()) { 712 // On completing the first request, start another request for "a". 713 // Since caching is enabled, this should complete synchronously. 714 715 // Note that |junk_callback| shouldn't be used since we are going to 716 // complete synchronously. We can't specify NULL though since that would 717 // mean synchronous mode so we give it a value of 1. 718 CompletionCallback* junk_callback = 719 reinterpret_cast<CompletionCallback*> (1); 720 AddressList addrlist; 721 722 HostResolver::RequestInfo info("a", 70); 723 int error = resolver->Resolve(info, &addrlist, junk_callback, NULL, NULL); 724 EXPECT_EQ(OK, error); 725 726 // Ok good. Now make sure that if we ask to bypass the cache, it can no 727 // longer service the request synchronously. 728 info = HostResolver::RequestInfo("a", 71); 729 info.set_allow_cached_response(false); 730 final_request_.reset(new ResolveRequest(resolver, info, this)); 731 } else if (71 == resolve->port()) { 732 // Test is done. 733 MessageLoop::current()->Quit(); 734 } else { 735 FAIL() << "Unexpected port number"; 736 } 737 } 738 739 private: 740 scoped_ptr<ResolveRequest> final_request_; 741 DISALLOW_COPY_AND_ASSIGN(BypassCacheVerifier); 742 }; 743 744 TEST_F(HostResolverImplTest, BypassCache) { 745 scoped_refptr<HostResolver> host_resolver( 746 CreateHostResolverImpl(NULL)); 747 748 // The class will receive callbacks for when each resolve completes. It 749 // checks that the right things happened. 750 BypassCacheVerifier verifier; 751 752 // Start a request. 753 ResolveRequest req1(host_resolver, "a", 80, &verifier); 754 755 // |verifier| will send quit message once all the requests have finished. 756 MessageLoop::current()->Run(); 757 } 758 759 bool operator==(const HostResolver::RequestInfo& a, 760 const HostResolver::RequestInfo& b) { 761 return a.hostname() == b.hostname() && 762 a.port() == b.port() && 763 a.allow_cached_response() == b.allow_cached_response() && 764 a.priority() == b.priority() && 765 a.is_speculative() == b.is_speculative() && 766 a.referrer() == b.referrer(); 767 } 768 769 // Observer that just makes note of how it was called. The test code can then 770 // inspect to make sure it was called with the right parameters. 771 class CapturingObserver : public HostResolver::Observer { 772 public: 773 // DnsResolutionObserver methods: 774 virtual void OnStartResolution(int id, 775 const HostResolver::RequestInfo& info) { 776 start_log.push_back(StartOrCancelEntry(id, info)); 777 } 778 779 virtual void OnFinishResolutionWithStatus( 780 int id, 781 bool was_resolved, 782 const HostResolver::RequestInfo& info) { 783 finish_log.push_back(FinishEntry(id, was_resolved, info)); 784 } 785 786 virtual void OnCancelResolution(int id, 787 const HostResolver::RequestInfo& info) { 788 cancel_log.push_back(StartOrCancelEntry(id, info)); 789 } 790 791 // Tuple (id, info). 792 struct StartOrCancelEntry { 793 StartOrCancelEntry(int id, const HostResolver::RequestInfo& info) 794 : id(id), info(info) {} 795 796 bool operator==(const StartOrCancelEntry& other) const { 797 return id == other.id && info == other.info; 798 } 799 800 int id; 801 HostResolver::RequestInfo info; 802 }; 803 804 // Tuple (id, was_resolved, info). 805 struct FinishEntry { 806 FinishEntry(int id, bool was_resolved, 807 const HostResolver::RequestInfo& info) 808 : id(id), was_resolved(was_resolved), info(info) {} 809 810 bool operator==(const FinishEntry& other) const { 811 return id == other.id && 812 was_resolved == other.was_resolved && 813 info == other.info; 814 } 815 816 int id; 817 bool was_resolved; 818 HostResolver::RequestInfo info; 819 }; 820 821 std::vector<StartOrCancelEntry> start_log; 822 std::vector<FinishEntry> finish_log; 823 std::vector<StartOrCancelEntry> cancel_log; 824 }; 825 826 // Test that registering, unregistering, and notifying of observers works. 827 // Does not test the cancellation notification since all resolves are 828 // synchronous. 829 TEST_F(HostResolverImplTest, Observers) { 830 scoped_refptr<HostResolver> host_resolver( 831 CreateHostResolverImpl(NULL)); 832 833 CapturingObserver observer; 834 835 host_resolver->AddObserver(&observer); 836 837 AddressList addrlist; 838 839 // Resolve "host1". 840 HostResolver::RequestInfo info1("host1", 70); 841 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); 842 int rv = host_resolver->Resolve(info1, &addrlist, NULL, NULL, log); 843 EXPECT_EQ(OK, rv); 844 845 EXPECT_EQ(6u, log->entries().size()); 846 EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_HOST_RESOLVER_IMPL)); 847 EXPECT_TRUE(LogContainsBeginEvent( 848 *log, 1, LoadLog::TYPE_HOST_RESOLVER_IMPL_OBSERVER_ONSTART)); 849 EXPECT_TRUE(LogContainsEndEvent( 850 *log, 2, LoadLog::TYPE_HOST_RESOLVER_IMPL_OBSERVER_ONSTART)); 851 EXPECT_TRUE(LogContainsBeginEvent( 852 *log, 3, LoadLog::TYPE_HOST_RESOLVER_IMPL_OBSERVER_ONFINISH)); 853 EXPECT_TRUE(LogContainsEndEvent( 854 *log, 4, LoadLog::TYPE_HOST_RESOLVER_IMPL_OBSERVER_ONFINISH)); 855 EXPECT_TRUE(LogContainsEndEvent( 856 *log, 5, LoadLog::TYPE_HOST_RESOLVER_IMPL)); 857 858 EXPECT_EQ(1U, observer.start_log.size()); 859 EXPECT_EQ(1U, observer.finish_log.size()); 860 EXPECT_EQ(0U, observer.cancel_log.size()); 861 EXPECT_TRUE(observer.start_log[0] == 862 CapturingObserver::StartOrCancelEntry(0, info1)); 863 EXPECT_TRUE(observer.finish_log[0] == 864 CapturingObserver::FinishEntry(0, true, info1)); 865 866 // Resolve "host1" again -- this time it will be served from cache, but it 867 // should still notify of completion. 868 TestCompletionCallback callback; 869 rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL, NULL); 870 ASSERT_EQ(OK, rv); // Should complete synchronously. 871 872 EXPECT_EQ(2U, observer.start_log.size()); 873 EXPECT_EQ(2U, observer.finish_log.size()); 874 EXPECT_EQ(0U, observer.cancel_log.size()); 875 EXPECT_TRUE(observer.start_log[1] == 876 CapturingObserver::StartOrCancelEntry(1, info1)); 877 EXPECT_TRUE(observer.finish_log[1] == 878 CapturingObserver::FinishEntry(1, true, info1)); 879 880 // Resolve "host2", setting referrer to "http://foobar.com" 881 HostResolver::RequestInfo info2("host2", 70); 882 info2.set_referrer(GURL("http://foobar.com")); 883 rv = host_resolver->Resolve(info2, &addrlist, NULL, NULL, NULL); 884 EXPECT_EQ(OK, rv); 885 886 EXPECT_EQ(3U, observer.start_log.size()); 887 EXPECT_EQ(3U, observer.finish_log.size()); 888 EXPECT_EQ(0U, observer.cancel_log.size()); 889 EXPECT_TRUE(observer.start_log[2] == 890 CapturingObserver::StartOrCancelEntry(2, info2)); 891 EXPECT_TRUE(observer.finish_log[2] == 892 CapturingObserver::FinishEntry(2, true, info2)); 893 894 // Unregister the observer. 895 host_resolver->RemoveObserver(&observer); 896 897 // Resolve "host3" 898 HostResolver::RequestInfo info3("host3", 70); 899 host_resolver->Resolve(info3, &addrlist, NULL, NULL, NULL); 900 901 // No effect this time, since observer was removed. 902 EXPECT_EQ(3U, observer.start_log.size()); 903 EXPECT_EQ(3U, observer.finish_log.size()); 904 EXPECT_EQ(0U, observer.cancel_log.size()); 905 } 906 907 // Tests that observers are sent OnCancelResolution() whenever a request is 908 // cancelled. There are two ways to cancel a request: 909 // (1) Delete the HostResolver while job is outstanding. 910 // (2) Call HostResolver::CancelRequest() while a request is outstanding. 911 TEST_F(HostResolverImplTest, CancellationObserver) { 912 CapturingObserver observer; 913 { 914 // Create a host resolver and attach an observer. 915 scoped_refptr<HostResolver> host_resolver( 916 CreateHostResolverImpl(NULL)); 917 host_resolver->AddObserver(&observer); 918 919 TestCompletionCallback callback; 920 921 EXPECT_EQ(0U, observer.start_log.size()); 922 EXPECT_EQ(0U, observer.finish_log.size()); 923 EXPECT_EQ(0U, observer.cancel_log.size()); 924 925 // Start an async resolve for (host1:70). 926 HostResolver::RequestInfo info1("host1", 70); 927 HostResolver::RequestHandle req = NULL; 928 AddressList addrlist; 929 int rv = host_resolver->Resolve(info1, &addrlist, &callback, &req, NULL); 930 EXPECT_EQ(ERR_IO_PENDING, rv); 931 EXPECT_TRUE(NULL != req); 932 933 EXPECT_EQ(1U, observer.start_log.size()); 934 EXPECT_EQ(0U, observer.finish_log.size()); 935 EXPECT_EQ(0U, observer.cancel_log.size()); 936 937 EXPECT_TRUE(observer.start_log[0] == 938 CapturingObserver::StartOrCancelEntry(0, info1)); 939 940 // Cancel the request. 941 host_resolver->CancelRequest(req); 942 943 EXPECT_EQ(1U, observer.start_log.size()); 944 EXPECT_EQ(0U, observer.finish_log.size()); 945 EXPECT_EQ(1U, observer.cancel_log.size()); 946 947 EXPECT_TRUE(observer.cancel_log[0] == 948 CapturingObserver::StartOrCancelEntry(0, info1)); 949 950 // Start an async request for (host2:60) 951 HostResolver::RequestInfo info2("host2", 60); 952 rv = host_resolver->Resolve(info2, &addrlist, &callback, NULL, NULL); 953 EXPECT_EQ(ERR_IO_PENDING, rv); 954 EXPECT_TRUE(NULL != req); 955 956 EXPECT_EQ(2U, observer.start_log.size()); 957 EXPECT_EQ(0U, observer.finish_log.size()); 958 EXPECT_EQ(1U, observer.cancel_log.size()); 959 960 EXPECT_TRUE(observer.start_log[1] == 961 CapturingObserver::StartOrCancelEntry(1, info2)); 962 963 // Upon exiting this scope, HostResolver is destroyed, so all requests are 964 // implicitly cancelled. 965 } 966 967 // Check that destroying the HostResolver sent a notification for 968 // cancellation of host2:60 request. 969 970 EXPECT_EQ(2U, observer.start_log.size()); 971 EXPECT_EQ(0U, observer.finish_log.size()); 972 EXPECT_EQ(2U, observer.cancel_log.size()); 973 974 HostResolver::RequestInfo info("host2", 60); 975 EXPECT_TRUE(observer.cancel_log[1] == 976 CapturingObserver::StartOrCancelEntry(1, info)); 977 } 978 979 // Test that IP address changes flush the cache. 980 TEST_F(HostResolverImplTest, FlushCacheOnIPAddressChange) { 981 MockNetworkChangeNotifier mock_network_change_notifier; 982 scoped_refptr<HostResolver> host_resolver( 983 new HostResolverImpl(NULL, CreateDefaultCache(), 984 &mock_network_change_notifier, 985 kMaxJobs)); 986 987 AddressList addrlist; 988 989 // Resolve "host1". 990 HostResolver::RequestInfo info1("host1", 70); 991 TestCompletionCallback callback; 992 int rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL, NULL); 993 EXPECT_EQ(ERR_IO_PENDING, rv); 994 EXPECT_EQ(OK, callback.WaitForResult()); 995 996 // Resolve "host1" again -- this time it will be served from cache, but it 997 // should still notify of completion. 998 rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL, NULL); 999 ASSERT_EQ(OK, rv); // Should complete synchronously. 1000 1001 // Flush cache by triggering an IP address change. 1002 mock_network_change_notifier.NotifyIPAddressChange(); 1003 1004 // Resolve "host1" again -- this time it won't be served from cache, so it 1005 // will complete asynchronously. 1006 rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL, NULL); 1007 ASSERT_EQ(ERR_IO_PENDING, rv); // Should complete asynchronously. 1008 EXPECT_EQ(OK, callback.WaitForResult()); 1009 } 1010 1011 // Tests that when the maximum threads is set to 1, requests are dequeued 1012 // in order of priority. 1013 TEST_F(HostResolverImplTest, HigherPriorityRequestsStartedFirst) { 1014 scoped_refptr<CapturingHostResolverProc> resolver_proc = 1015 new CapturingHostResolverProc(NULL); 1016 1017 // This HostResolverImpl will only allow 1 outstanding resolve at a time. 1018 size_t kMaxJobs = 1u; 1019 scoped_refptr<HostResolver> host_resolver( 1020 new HostResolverImpl(resolver_proc, CreateDefaultCache(), 1021 NULL, kMaxJobs)); 1022 1023 CapturingObserver observer; 1024 host_resolver->AddObserver(&observer); 1025 1026 // Note that at this point the CapturingHostResolverProc is blocked, so any 1027 // requests we make will not complete. 1028 1029 HostResolver::RequestInfo req[] = { 1030 CreateResolverRequest("req0", LOW), 1031 CreateResolverRequest("req1", MEDIUM), 1032 CreateResolverRequest("req2", MEDIUM), 1033 CreateResolverRequest("req3", LOW), 1034 CreateResolverRequest("req4", HIGHEST), 1035 CreateResolverRequest("req5", LOW), 1036 CreateResolverRequest("req6", LOW), 1037 CreateResolverRequest("req5", HIGHEST), 1038 }; 1039 1040 TestCompletionCallback callback[arraysize(req)]; 1041 AddressList addrlist[arraysize(req)]; 1042 1043 // Start all of the requests. 1044 for (size_t i = 0; i < arraysize(req); ++i) { 1045 int rv = host_resolver->Resolve(req[i], &addrlist[i], 1046 &callback[i], NULL, NULL); 1047 EXPECT_EQ(ERR_IO_PENDING, rv); 1048 } 1049 1050 // Unblock the resolver thread so the requests can run. 1051 resolver_proc->Signal(); 1052 1053 // Wait for all the requests to complete succesfully. 1054 for (size_t i = 0; i < arraysize(req); ++i) { 1055 EXPECT_EQ(OK, callback[i].WaitForResult()) << "i=" << i; 1056 } 1057 1058 host_resolver->RemoveObserver(&observer); 1059 1060 // Since we have restricted to a single concurrent thread in the jobpool, 1061 // the requests should complete in order of priority (with the exception 1062 // of the first request, which gets started right away, since there is 1063 // nothing outstanding). 1064 std::vector<std::string> capture_list = resolver_proc->GetCaptureList(); 1065 ASSERT_EQ(7u, capture_list.size()); 1066 1067 EXPECT_EQ("req0", capture_list[0]); 1068 EXPECT_EQ("req4", capture_list[1]); 1069 EXPECT_EQ("req5", capture_list[2]); 1070 EXPECT_EQ("req1", capture_list[3]); 1071 EXPECT_EQ("req2", capture_list[4]); 1072 EXPECT_EQ("req3", capture_list[5]); 1073 EXPECT_EQ("req6", capture_list[6]); 1074 1075 // Also check using the observer's trace. 1076 EXPECT_EQ(8U, observer.start_log.size()); 1077 EXPECT_EQ(8U, observer.finish_log.size()); 1078 EXPECT_EQ(0U, observer.cancel_log.size()); 1079 1080 EXPECT_EQ("req0", observer.finish_log[0].info.hostname()); 1081 EXPECT_EQ("req4", observer.finish_log[1].info.hostname()); 1082 1083 // There were two requests for "req5". The highest priority 1084 // one should have been dispatched earlier. 1085 EXPECT_EQ("req5", observer.finish_log[2].info.hostname()); 1086 EXPECT_EQ("req5", observer.finish_log[3].info.hostname()); 1087 EXPECT_EQ(HIGHEST, observer.finish_log[2].info.priority()); 1088 EXPECT_EQ(LOW, observer.finish_log[3].info.priority()); 1089 1090 EXPECT_EQ("req1", observer.finish_log[4].info.hostname()); 1091 EXPECT_EQ("req2", observer.finish_log[5].info.hostname()); 1092 EXPECT_EQ("req3", observer.finish_log[6].info.hostname()); 1093 EXPECT_EQ("req6", observer.finish_log[7].info.hostname()); 1094 } 1095 1096 // Try cancelling a request which has not been attached to a job yet. 1097 TEST_F(HostResolverImplTest, CancelPendingRequest) { 1098 scoped_refptr<CapturingHostResolverProc> resolver_proc = 1099 new CapturingHostResolverProc(NULL); 1100 1101 // This HostResolverImpl will only allow 1 outstanding resolve at a time. 1102 const size_t kMaxJobs = 1u; 1103 scoped_refptr<HostResolver> host_resolver( 1104 new HostResolverImpl(resolver_proc, CreateDefaultCache(), 1105 NULL, kMaxJobs)); 1106 1107 // Note that at this point the CapturingHostResolverProc is blocked, so any 1108 // requests we make will not complete. 1109 1110 HostResolver::RequestInfo req[] = { 1111 CreateResolverRequest("req0", LOWEST), 1112 CreateResolverRequest("req1", HIGHEST), // Will cancel. 1113 CreateResolverRequest("req2", MEDIUM), 1114 CreateResolverRequest("req3", LOW), 1115 CreateResolverRequest("req4", HIGHEST), // Will cancel. 1116 CreateResolverRequest("req5", LOWEST), // Will cancel. 1117 CreateResolverRequest("req6", MEDIUM), 1118 }; 1119 1120 TestCompletionCallback callback[arraysize(req)]; 1121 AddressList addrlist[arraysize(req)]; 1122 HostResolver::RequestHandle handle[arraysize(req)]; 1123 1124 // Start all of the requests. 1125 for (size_t i = 0; i < arraysize(req); ++i) { 1126 int rv = host_resolver->Resolve(req[i], &addrlist[i], 1127 &callback[i], &handle[i], NULL); 1128 EXPECT_EQ(ERR_IO_PENDING, rv); 1129 } 1130 1131 // Cancel some requests 1132 host_resolver->CancelRequest(handle[1]); 1133 host_resolver->CancelRequest(handle[4]); 1134 host_resolver->CancelRequest(handle[5]); 1135 handle[1] = handle[4] = handle[5] = NULL; 1136 1137 // Unblock the resolver thread so the requests can run. 1138 resolver_proc->Signal(); 1139 1140 // Wait for all the requests to complete succesfully. 1141 for (size_t i = 0; i < arraysize(req); ++i) { 1142 if (!handle[i]) 1143 continue; // Don't wait for the requests we cancelled. 1144 EXPECT_EQ(OK, callback[i].WaitForResult()); 1145 } 1146 1147 // Verify that they called out the the resolver proc (which runs on the 1148 // resolver thread) in the expected order. 1149 std::vector<std::string> capture_list = resolver_proc->GetCaptureList(); 1150 ASSERT_EQ(4u, capture_list.size()); 1151 1152 EXPECT_EQ("req0", capture_list[0]); 1153 EXPECT_EQ("req2", capture_list[1]); 1154 EXPECT_EQ("req6", capture_list[2]); 1155 EXPECT_EQ("req3", capture_list[3]); 1156 } 1157 1158 // Test that when too many requests are enqueued, old ones start to be aborted. 1159 TEST_F(HostResolverImplTest, QueueOverflow) { 1160 scoped_refptr<CapturingHostResolverProc> resolver_proc = 1161 new CapturingHostResolverProc(NULL); 1162 1163 // This HostResolverImpl will only allow 1 outstanding resolve at a time. 1164 const size_t kMaxOutstandingJobs = 1u; 1165 scoped_refptr<HostResolverImpl> host_resolver( 1166 new HostResolverImpl(resolver_proc, CreateDefaultCache(), 1167 NULL, kMaxOutstandingJobs)); 1168 1169 // Only allow up to 3 requests to be enqueued at a time. 1170 const size_t kMaxPendingRequests = 3u; 1171 host_resolver->SetPoolConstraints(HostResolverImpl::POOL_NORMAL, 1172 kMaxOutstandingJobs, 1173 kMaxPendingRequests); 1174 1175 // Note that at this point the CapturingHostResolverProc is blocked, so any 1176 // requests we make will not complete. 1177 1178 HostResolver::RequestInfo req[] = { 1179 CreateResolverRequest("req0", LOWEST), 1180 CreateResolverRequest("req1", HIGHEST), 1181 CreateResolverRequest("req2", MEDIUM), 1182 CreateResolverRequest("req3", MEDIUM), 1183 1184 // At this point, there are 3 enqueued requests. 1185 // Insertion of subsequent requests will cause evictions 1186 // based on priority. 1187 1188 CreateResolverRequest("req4", LOW), // Evicts itself! 1189 CreateResolverRequest("req5", MEDIUM), // Evicts req3 1190 CreateResolverRequest("req6", HIGHEST), // Evicts req5. 1191 CreateResolverRequest("req7", MEDIUM), // Evicts req2. 1192 }; 1193 1194 TestCompletionCallback callback[arraysize(req)]; 1195 AddressList addrlist[arraysize(req)]; 1196 HostResolver::RequestHandle handle[arraysize(req)]; 1197 1198 // Start all of the requests. 1199 for (size_t i = 0; i < arraysize(req); ++i) { 1200 int rv = host_resolver->Resolve(req[i], &addrlist[i], 1201 &callback[i], &handle[i], NULL); 1202 if (i == 4u) 1203 EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, rv); 1204 else 1205 EXPECT_EQ(ERR_IO_PENDING, rv) << i; 1206 } 1207 1208 // Unblock the resolver thread so the requests can run. 1209 resolver_proc->Signal(); 1210 1211 // Requests 3, 5, 2 will have been evicted due to queue overflow. 1212 size_t reqs_expected_to_fail[] = { 2, 3, 5 }; 1213 for (size_t i = 0; i < arraysize(reqs_expected_to_fail); ++i) { 1214 EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, 1215 callback[reqs_expected_to_fail[i]].WaitForResult()); 1216 } 1217 1218 // The rest should succeed. 1219 size_t reqs_expected_to_succeed[] = { 0, 1, 6, 7 }; 1220 for (size_t i = 0; i < arraysize(reqs_expected_to_succeed); ++i) { 1221 EXPECT_EQ(OK, callback[reqs_expected_to_succeed[i]].WaitForResult()); 1222 } 1223 1224 // Verify that they called out the the resolver proc (which runs on the 1225 // resolver thread) in the expected order. 1226 std::vector<std::string> capture_list = resolver_proc->GetCaptureList(); 1227 ASSERT_EQ(4u, capture_list.size()); 1228 1229 EXPECT_EQ("req0", capture_list[0]); 1230 EXPECT_EQ("req1", capture_list[1]); 1231 EXPECT_EQ("req6", capture_list[2]); 1232 EXPECT_EQ("req7", capture_list[3]); 1233 } 1234 1235 } // namespace 1236 1237 } // namespace net 1238