Index: net/base/host_resolver_unittest.cc |
=================================================================== |
--- net/base/host_resolver_unittest.cc (revision 20760) |
+++ net/base/host_resolver_unittest.cc (working copy) |
@@ -1,899 +0,0 @@ |
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "net/base/host_resolver.h" |
- |
-#if defined(OS_WIN) |
-#include <ws2tcpip.h> |
-#include <wspiapi.h> |
-#elif defined(OS_POSIX) |
-#include <netdb.h> |
-#endif |
- |
-#include <string> |
- |
-#include "base/compiler_specific.h" |
-#include "base/message_loop.h" |
-#include "base/ref_counted.h" |
-#include "net/base/address_list.h" |
-#include "net/base/completion_callback.h" |
-#include "net/base/host_resolver_unittest.h" |
-#include "net/base/net_errors.h" |
-#include "net/base/test_completion_callback.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-using net::RuleBasedHostMapper; |
-using net::ScopedHostMapper; |
-using net::WaitingHostMapper; |
- |
-// TODO(eroman): |
-// - Test mixing async with sync (in particular how does sync update the |
-// cache while an async is already pending). |
- |
-namespace { |
- |
-// A variant of WaitingHostMapper that pushes each host mapped into a list. |
-// (and uses a manual-reset event rather than auto-reset). |
-class CapturingHostMapper : public net::HostMapper { |
- public: |
- CapturingHostMapper() : event_(true, false) { |
- } |
- |
- void Signal() { |
- event_.Signal(); |
- } |
- |
- virtual std::string Map(const std::string& host) { |
- event_.Wait(); |
- { |
- AutoLock l(lock_); |
- capture_list_.push_back(host); |
- } |
- return MapUsingPrevious(host); |
- } |
- |
- std::vector<std::string> GetCaptureList() const { |
- std::vector<std::string> copy; |
- { |
- AutoLock l(lock_); |
- copy = capture_list_; |
- } |
- return copy; |
- } |
- |
- private: |
- std::vector<std::string> capture_list_; |
- mutable Lock lock_; |
- base::WaitableEvent event_; |
-}; |
- |
-// Helper that represents a single Resolve() result, used to inspect all the |
-// resolve results by forwarding them to Delegate. |
-class ResolveRequest { |
- public: |
- // Delegate interface, for notification when the ResolveRequest completes. |
- class Delegate { |
- public: |
- virtual ~Delegate() {} |
- virtual void OnCompleted(ResolveRequest* resolve) = 0; |
- }; |
- |
- ResolveRequest(net::HostResolver* resolver, |
- const std::string& hostname, |
- int port, |
- Delegate* delegate) |
- : info_(hostname, port), resolver_(resolver), delegate_(delegate), |
- ALLOW_THIS_IN_INITIALIZER_LIST( |
- callback_(this, &ResolveRequest::OnLookupFinished)) { |
- // Start the request. |
- int err = resolver->Resolve(info_, &addrlist_, &callback_, &req_); |
- EXPECT_EQ(net::ERR_IO_PENDING, err); |
- } |
- |
- ResolveRequest(net::HostResolver* resolver, |
- const net::HostResolver::RequestInfo& info, |
- Delegate* delegate) |
- : info_(info), resolver_(resolver), delegate_(delegate), |
- ALLOW_THIS_IN_INITIALIZER_LIST( |
- callback_(this, &ResolveRequest::OnLookupFinished)) { |
- // Start the request. |
- int err = resolver->Resolve(info, &addrlist_, &callback_, &req_); |
- EXPECT_EQ(net::ERR_IO_PENDING, err); |
- } |
- |
- void Cancel() { |
- resolver_->CancelRequest(req_); |
- } |
- |
- const std::string& hostname() const { |
- return info_.hostname(); |
- } |
- |
- int port() const { |
- return info_.port(); |
- } |
- |
- int result() const { |
- return result_; |
- } |
- |
- const net::AddressList& addrlist() const { |
- return addrlist_; |
- } |
- |
- net::HostResolver* resolver() const { |
- return resolver_; |
- } |
- |
- private: |
- void OnLookupFinished(int result) { |
- result_ = result; |
- delegate_->OnCompleted(this); |
- } |
- |
- // The request details. |
- net::HostResolver::RequestInfo info_; |
- net::HostResolver::Request* req_; |
- |
- // The result of the resolve. |
- int result_; |
- net::AddressList addrlist_; |
- |
- // We don't use a scoped_refptr, to simplify deleting shared resolver in |
- // DeleteWithinCallback test. |
- net::HostResolver* resolver_; |
- |
- Delegate* delegate_; |
- net::CompletionCallbackImpl<ResolveRequest> callback_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ResolveRequest); |
-}; |
- |
-class HostResolverTest : public testing::Test { |
- public: |
- HostResolverTest() |
- : callback_called_(false), |
- ALLOW_THIS_IN_INITIALIZER_LIST( |
- callback_(this, &HostResolverTest::OnLookupFinished)) { |
- } |
- |
- protected: |
- bool callback_called_; |
- int callback_result_; |
- net::CompletionCallbackImpl<HostResolverTest> callback_; |
- |
- private: |
- void OnLookupFinished(int result) { |
- callback_called_ = true; |
- callback_result_ = result; |
- MessageLoop::current()->Quit(); |
- } |
-}; |
- |
-TEST_F(HostResolverTest, SynchronousLookup) { |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- net::AddressList adrlist; |
- const int kPortnum = 80; |
- |
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
- mapper->AddRule("just.testing", "192.168.1.42"); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- net::HostResolver::RequestInfo info("just.testing", kPortnum); |
- int err = host_resolver->Resolve(info, &adrlist, NULL, NULL); |
- EXPECT_EQ(net::OK, err); |
- |
- const struct addrinfo* ainfo = adrlist.head(); |
- EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); |
- EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); |
- |
- const struct sockaddr* sa = ainfo->ai_addr; |
- const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; |
- EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); |
- EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr); |
-} |
- |
-TEST_F(HostResolverTest, AsynchronousLookup) { |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- net::AddressList adrlist; |
- const int kPortnum = 80; |
- |
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
- mapper->AddRule("just.testing", "192.168.1.42"); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- net::HostResolver::RequestInfo info("just.testing", kPortnum); |
- int err = host_resolver->Resolve(info, &adrlist, &callback_, NULL); |
- EXPECT_EQ(net::ERR_IO_PENDING, err); |
- |
- MessageLoop::current()->Run(); |
- |
- ASSERT_TRUE(callback_called_); |
- ASSERT_EQ(net::OK, callback_result_); |
- |
- const struct addrinfo* ainfo = adrlist.head(); |
- EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); |
- EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); |
- |
- const struct sockaddr* sa = ainfo->ai_addr; |
- const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; |
- EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); |
- EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr); |
-} |
- |
-TEST_F(HostResolverTest, CanceledAsynchronousLookup) { |
- scoped_refptr<WaitingHostMapper> mapper = new WaitingHostMapper(); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- { |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- net::AddressList adrlist; |
- const int kPortnum = 80; |
- |
- net::HostResolver::RequestInfo info("just.testing", kPortnum); |
- int err = host_resolver->Resolve(info, &adrlist, &callback_, NULL); |
- EXPECT_EQ(net::ERR_IO_PENDING, err); |
- |
- // Make sure we will exit the queue even when callback is not called. |
- MessageLoop::current()->PostDelayedTask(FROM_HERE, |
- new MessageLoop::QuitTask(), |
- 1000); |
- MessageLoop::current()->Run(); |
- } |
- |
- mapper->Signal(); |
- |
- EXPECT_FALSE(callback_called_); |
-} |
- |
-TEST_F(HostResolverTest, NumericIPv4Address) { |
- // Stevens says dotted quads with AI_UNSPEC resolve to a single sockaddr_in. |
- |
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
- mapper->AllowDirectLookup("*"); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- net::AddressList adrlist; |
- const int kPortnum = 5555; |
- net::HostResolver::RequestInfo info("127.1.2.3", kPortnum); |
- int err = host_resolver->Resolve(info, &adrlist, NULL, NULL); |
- EXPECT_EQ(net::OK, err); |
- |
- const struct addrinfo* ainfo = adrlist.head(); |
- EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); |
- EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); |
- |
- const struct sockaddr* sa = ainfo->ai_addr; |
- const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; |
- EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); |
- EXPECT_TRUE(htonl(0x7f010203) == sa_in->sin_addr.s_addr); |
-} |
- |
-TEST_F(HostResolverTest, NumericIPv6Address) { |
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
- mapper->AllowDirectLookup("*"); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- // Resolve a plain IPv6 address. Don't worry about [brackets], because |
- // the caller should have removed them. |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- net::AddressList adrlist; |
- const int kPortnum = 5555; |
- net::HostResolver::RequestInfo info("2001:db8::1", kPortnum); |
- int err = host_resolver->Resolve(info, &adrlist, NULL, NULL); |
- // On computers without IPv6 support, getaddrinfo cannot convert IPv6 |
- // address literals to addresses (getaddrinfo returns EAI_NONAME). So this |
- // test has to allow host_resolver->Resolve to fail. |
- if (err == net::ERR_NAME_NOT_RESOLVED) |
- return; |
- EXPECT_EQ(net::OK, err); |
- |
- const struct addrinfo* ainfo = adrlist.head(); |
- EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); |
- EXPECT_EQ(sizeof(struct sockaddr_in6), ainfo->ai_addrlen); |
- |
- const struct sockaddr* sa = ainfo->ai_addr; |
- const struct sockaddr_in6* sa_in6 = (const struct sockaddr_in6*) sa; |
- EXPECT_TRUE(htons(kPortnum) == sa_in6->sin6_port); |
- |
- const uint8 expect_addr[] = { |
- 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, |
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 |
- }; |
- for (int i = 0; i < 16; i++) { |
- EXPECT_EQ(expect_addr[i], sa_in6->sin6_addr.s6_addr[i]); |
- } |
-} |
- |
-TEST_F(HostResolverTest, EmptyHost) { |
- scoped_refptr<RuleBasedHostMapper> mapper = new RuleBasedHostMapper(); |
- mapper->AllowDirectLookup("*"); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- net::AddressList adrlist; |
- const int kPortnum = 5555; |
- net::HostResolver::RequestInfo info("", kPortnum); |
- int err = host_resolver->Resolve(info, &adrlist, NULL, NULL); |
- EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, err); |
-} |
- |
-// Helper class used by HostResolverTest.DeDupeRequests. It receives request |
-// completion notifications for all the resolves, so it can tally up and |
-// determine when we are done. |
-class DeDupeRequestsVerifier : public ResolveRequest::Delegate { |
- public: |
- explicit DeDupeRequestsVerifier(CapturingHostMapper* mapper) |
- : count_a_(0), count_b_(0), mapper_(mapper) {} |
- |
- // The test does 5 resolves (which can complete in any order). |
- virtual void OnCompleted(ResolveRequest* resolve) { |
- // Tally up how many requests we have seen. |
- if (resolve->hostname() == "a") { |
- count_a_++; |
- } else if (resolve->hostname() == "b") { |
- count_b_++; |
- } else { |
- FAIL() << "Unexpected hostname: " << resolve->hostname(); |
- } |
- |
- // Check that the port was set correctly. |
- EXPECT_EQ(resolve->port(), resolve->addrlist().GetPort()); |
- |
- // Check whether all the requests have finished yet. |
- int total_completions = count_a_ + count_b_; |
- if (total_completions == 5) { |
- EXPECT_EQ(2, count_a_); |
- EXPECT_EQ(3, count_b_); |
- |
- // The mapper should have been called only twice -- once with "a", once |
- // with "b". |
- std::vector<std::string> capture_list = mapper_->GetCaptureList(); |
- EXPECT_EQ(2U, capture_list.size()); |
- |
- // End this test, we are done. |
- MessageLoop::current()->Quit(); |
- } |
- } |
- |
- private: |
- int count_a_; |
- int count_b_; |
- CapturingHostMapper* mapper_; |
- |
- DISALLOW_COPY_AND_ASSIGN(DeDupeRequestsVerifier); |
-}; |
- |
-TEST_F(HostResolverTest, DeDupeRequests) { |
- // Use a capturing mapper, since the verifier needs to know what calls |
- // reached Map(). Also, the capturing mapper is initially blocked. |
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- |
- // The class will receive callbacks for when each resolve completes. It |
- // checks that the right things happened. |
- DeDupeRequestsVerifier verifier(mapper.get()); |
- |
- // Start 5 requests, duplicating hosts "a" and "b". Since the mapper is |
- // blocked, these should all pile up until we signal it. |
- |
- ResolveRequest req1(host_resolver, "a", 80, &verifier); |
- ResolveRequest req2(host_resolver, "b", 80, &verifier); |
- ResolveRequest req3(host_resolver, "b", 81, &verifier); |
- ResolveRequest req4(host_resolver, "a", 82, &verifier); |
- ResolveRequest req5(host_resolver, "b", 83, &verifier); |
- |
- // Ready, Set, GO!!! |
- mapper->Signal(); |
- |
- // |verifier| will send quit message once all the requests have finished. |
- MessageLoop::current()->Run(); |
-} |
- |
-// Helper class used by HostResolverTest.CancelMultipleRequests. |
-class CancelMultipleRequestsVerifier : public ResolveRequest::Delegate { |
- public: |
- CancelMultipleRequestsVerifier() {} |
- |
- // The cancels kill all but one request. |
- virtual void OnCompleted(ResolveRequest* resolve) { |
- EXPECT_EQ("a", resolve->hostname()); |
- EXPECT_EQ(82, resolve->port()); |
- |
- // Check that the port was set correctly. |
- EXPECT_EQ(resolve->port(), resolve->addrlist().GetPort()); |
- |
- // End this test, we are done. |
- MessageLoop::current()->Quit(); |
- } |
- |
- private: |
- DISALLOW_COPY_AND_ASSIGN(CancelMultipleRequestsVerifier); |
-}; |
- |
-TEST_F(HostResolverTest, CancelMultipleRequests) { |
- // Use a capturing mapper, since the verifier needs to know what calls |
- // reached Map(). Also, the capturing mapper is initially blocked. |
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- |
- // The class will receive callbacks for when each resolve completes. It |
- // checks that the right things happened. |
- CancelMultipleRequestsVerifier verifier; |
- |
- // Start 5 requests, duplicating hosts "a" and "b". Since the mapper is |
- // blocked, these should all pile up until we signal it. |
- |
- ResolveRequest req1(host_resolver, "a", 80, &verifier); |
- ResolveRequest req2(host_resolver, "b", 80, &verifier); |
- ResolveRequest req3(host_resolver, "b", 81, &verifier); |
- ResolveRequest req4(host_resolver, "a", 82, &verifier); |
- ResolveRequest req5(host_resolver, "b", 83, &verifier); |
- |
- // Cancel everything except request 4. |
- req1.Cancel(); |
- req2.Cancel(); |
- req3.Cancel(); |
- req5.Cancel(); |
- |
- // Ready, Set, GO!!! |
- mapper->Signal(); |
- |
- // |verifier| will send quit message once all the requests have finished. |
- MessageLoop::current()->Run(); |
-} |
- |
-// Helper class used by HostResolverTest.CancelWithinCallback. |
-class CancelWithinCallbackVerifier : public ResolveRequest::Delegate { |
- public: |
- CancelWithinCallbackVerifier() |
- : req_to_cancel1_(NULL), req_to_cancel2_(NULL), num_completions_(0) { |
- } |
- |
- virtual void OnCompleted(ResolveRequest* resolve) { |
- num_completions_++; |
- |
- // Port 80 is the first request that the callback will be invoked for. |
- // While we are executing within that callback, cancel the other requests |
- // in the job and start another request. |
- if (80 == resolve->port()) { |
- EXPECT_EQ("a", resolve->hostname()); |
- |
- req_to_cancel1_->Cancel(); |
- req_to_cancel2_->Cancel(); |
- |
- // Start a request (so we can make sure the canceled requests don't |
- // complete before "finalrequest" finishes. |
- final_request_.reset(new ResolveRequest( |
- resolve->resolver(), "finalrequest", 70, this)); |
- |
- } else if (83 == resolve->port()) { |
- EXPECT_EQ("a", resolve->hostname()); |
- } else if (resolve->hostname() == "finalrequest") { |
- EXPECT_EQ(70, resolve->addrlist().GetPort()); |
- |
- // End this test, we are done. |
- MessageLoop::current()->Quit(); |
- } else { |
- FAIL() << "Unexpected completion: " << resolve->hostname() << ", " |
- << resolve->port(); |
- } |
- } |
- |
- void SetRequestsToCancel(ResolveRequest* req_to_cancel1, |
- ResolveRequest* req_to_cancel2) { |
- req_to_cancel1_ = req_to_cancel1; |
- req_to_cancel2_ = req_to_cancel2; |
- } |
- |
- private: |
- scoped_ptr<ResolveRequest> final_request_; |
- ResolveRequest* req_to_cancel1_; |
- ResolveRequest* req_to_cancel2_; |
- int num_completions_; |
- DISALLOW_COPY_AND_ASSIGN(CancelWithinCallbackVerifier); |
-}; |
- |
-TEST_F(HostResolverTest, CancelWithinCallback) { |
- // Use a capturing mapper, since the verifier needs to know what calls |
- // reached Map(). Also, the capturing mapper is initially blocked. |
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- |
- // The class will receive callbacks for when each resolve completes. It |
- // checks that the right things happened. |
- CancelWithinCallbackVerifier verifier; |
- |
- // Start 4 requests, duplicating hosts "a". Since the mapper is |
- // blocked, these should all pile up until we signal it. |
- |
- ResolveRequest req1(host_resolver, "a", 80, &verifier); |
- ResolveRequest req2(host_resolver, "a", 81, &verifier); |
- ResolveRequest req3(host_resolver, "a", 82, &verifier); |
- ResolveRequest req4(host_resolver, "a", 83, &verifier); |
- |
- // Once "a:80" completes, it will cancel "a:81" and "a:82". |
- verifier.SetRequestsToCancel(&req2, &req3); |
- |
- // Ready, Set, GO!!! |
- mapper->Signal(); |
- |
- // |verifier| will send quit message once all the requests have finished. |
- MessageLoop::current()->Run(); |
-} |
- |
-// Helper class used by HostResolverTest.DeleteWithinCallback. |
-class DeleteWithinCallbackVerifier : public ResolveRequest::Delegate { |
- public: |
- // |host_resolver| is the resolver that the the resolve requests were started |
- // with. |
- DeleteWithinCallbackVerifier(net::HostResolver* host_resolver) |
- : host_resolver_(host_resolver) {} |
- |
- virtual void OnCompleted(ResolveRequest* resolve) { |
- EXPECT_EQ("a", resolve->hostname()); |
- EXPECT_EQ(80, resolve->port()); |
- |
- // Release the last reference to the host resolver that started the |
- // requests. |
- host_resolver_ = NULL; |
- |
- // Quit after returning from OnCompleted (to give it a chance at |
- // incorrectly running the cancelled tasks). |
- MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
- } |
- |
- private: |
- scoped_refptr<net::HostResolver> host_resolver_; |
- DISALLOW_COPY_AND_ASSIGN(DeleteWithinCallbackVerifier); |
-}; |
- |
-TEST_F(HostResolverTest, DeleteWithinCallback) { |
- // Use a capturing mapper, since the verifier needs to know what calls |
- // reached Map(). Also, the capturing mapper is initially blocked. |
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- // The class will receive callbacks for when each resolve completes. It |
- // checks that the right things happened. Note that the verifier holds the |
- // only reference to |host_resolver|, so it can delete it within callback. |
- net::HostResolver* host_resolver = new net::HostResolver; |
- DeleteWithinCallbackVerifier verifier(host_resolver); |
- |
- // Start 4 requests, duplicating hosts "a". Since the mapper is |
- // blocked, these should all pile up until we signal it. |
- |
- ResolveRequest req1(host_resolver, "a", 80, &verifier); |
- ResolveRequest req2(host_resolver, "a", 81, &verifier); |
- ResolveRequest req3(host_resolver, "a", 82, &verifier); |
- ResolveRequest req4(host_resolver, "a", 83, &verifier); |
- |
- // Ready, Set, GO!!! |
- mapper->Signal(); |
- |
- // |verifier| will send quit message once all the requests have finished. |
- MessageLoop::current()->Run(); |
-} |
- |
-// Helper class used by HostResolverTest.StartWithinCallback. |
-class StartWithinCallbackVerifier : public ResolveRequest::Delegate { |
- public: |
- StartWithinCallbackVerifier() : num_requests_(0) {} |
- |
- virtual void OnCompleted(ResolveRequest* resolve) { |
- EXPECT_EQ("a", resolve->hostname()); |
- |
- if (80 == resolve->port()) { |
- // On completing the first request, start another request for "a". |
- // Since caching is disabled, this will result in another async request. |
- final_request_.reset(new ResolveRequest( |
- resolve->resolver(), "a", 70, this)); |
- } |
- if (++num_requests_ == 5) { |
- // Test is done. |
- MessageLoop::current()->Quit(); |
- } |
- } |
- |
- private: |
- int num_requests_; |
- scoped_ptr<ResolveRequest> final_request_; |
- DISALLOW_COPY_AND_ASSIGN(StartWithinCallbackVerifier); |
-}; |
- |
-TEST_F(HostResolverTest, StartWithinCallback) { |
- // Use a capturing mapper, since the verifier needs to know what calls |
- // reached Map(). Also, the capturing mapper is initially blocked. |
- scoped_refptr<CapturingHostMapper> mapper = new CapturingHostMapper(); |
- ScopedHostMapper scoped_mapper(mapper.get()); |
- |
- // Turn off caching for this host resolver. |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver(0, 0)); |
- |
- // The class will receive callbacks for when each resolve completes. It |
- // checks that the right things happened. |
- StartWithinCallbackVerifier verifier; |
- |
- // Start 4 requests, duplicating hosts "a". Since the mapper is |
- // blocked, these should all pile up until we signal it. |
- |
- ResolveRequest req1(host_resolver, "a", 80, &verifier); |
- ResolveRequest req2(host_resolver, "a", 81, &verifier); |
- ResolveRequest req3(host_resolver, "a", 82, &verifier); |
- ResolveRequest req4(host_resolver, "a", 83, &verifier); |
- |
- // Ready, Set, GO!!! |
- mapper->Signal(); |
- |
- // |verifier| will send quit message once all the requests have finished. |
- MessageLoop::current()->Run(); |
-} |
- |
-// Helper class used by HostResolverTest.BypassCache. |
-class BypassCacheVerifier : public ResolveRequest::Delegate { |
- public: |
- BypassCacheVerifier() {} |
- |
- virtual void OnCompleted(ResolveRequest* resolve) { |
- EXPECT_EQ("a", resolve->hostname()); |
- net::HostResolver* resolver = resolve->resolver(); |
- |
- if (80 == resolve->port()) { |
- // On completing the first request, start another request for "a". |
- // Since caching is enabled, this should complete synchronously. |
- |
- // Note that |junk_callback| shouldn't be used since we are going to |
- // complete synchronously. We can't specify NULL though since that would |
- // mean synchronous mode so we give it a value of 1. |
- net::CompletionCallback* junk_callback = |
- reinterpret_cast<net::CompletionCallback*> (1); |
- net::AddressList addrlist; |
- |
- net::HostResolver::RequestInfo info("a", 70); |
- int error = resolver->Resolve(info, &addrlist, junk_callback, NULL); |
- EXPECT_EQ(net::OK, error); |
- |
- // Ok good. Now make sure that if we ask to bypass the cache, it can no |
- // longer service the request synchronously. |
- info = net::HostResolver::RequestInfo("a", 71); |
- info.set_allow_cached_response(false); |
- final_request_.reset(new ResolveRequest(resolver, info, this)); |
- } else if (71 == resolve->port()) { |
- // Test is done. |
- MessageLoop::current()->Quit(); |
- } else { |
- FAIL() << "Unexpected port number"; |
- } |
- } |
- |
- private: |
- scoped_ptr<ResolveRequest> final_request_; |
- DISALLOW_COPY_AND_ASSIGN(BypassCacheVerifier); |
-}; |
- |
-TEST_F(HostResolverTest, BypassCache) { |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- |
- // The class will receive callbacks for when each resolve completes. It |
- // checks that the right things happened. |
- BypassCacheVerifier verifier; |
- |
- // Start a request. |
- ResolveRequest req1(host_resolver, "a", 80, &verifier); |
- |
- // |verifier| will send quit message once all the requests have finished. |
- MessageLoop::current()->Run(); |
-} |
- |
-bool operator==(const net::HostResolver::RequestInfo& a, |
- const net::HostResolver::RequestInfo& b) { |
- return a.hostname() == b.hostname() && |
- a.port() == b.port() && |
- a.allow_cached_response() == b.allow_cached_response() && |
- a.is_speculative() == b.is_speculative() && |
- a.referrer() == b.referrer(); |
-} |
- |
-// Observer that just makes note of how it was called. The test code can then |
-// inspect to make sure it was called with the right parameters. |
-class CapturingObserver : public net::HostResolver::Observer { |
- public: |
- // DnsResolutionObserver methods: |
- virtual void OnStartResolution(int id, |
- const net::HostResolver::RequestInfo& info) { |
- start_log.push_back(StartOrCancelEntry(id, info)); |
- } |
- |
- virtual void OnFinishResolutionWithStatus( |
- int id, |
- bool was_resolved, |
- const net::HostResolver::RequestInfo& info) { |
- finish_log.push_back(FinishEntry(id, was_resolved, info)); |
- } |
- |
- virtual void OnCancelResolution(int id, |
- const net::HostResolver::RequestInfo& info) { |
- cancel_log.push_back(StartOrCancelEntry(id, info)); |
- } |
- |
- // Tuple (id, info). |
- struct StartOrCancelEntry { |
- StartOrCancelEntry(int id, const net::HostResolver::RequestInfo& info) |
- : id(id), info(info) {} |
- |
- bool operator==(const StartOrCancelEntry& other) const { |
- return id == other.id && info == other.info; |
- } |
- |
- int id; |
- net::HostResolver::RequestInfo info; |
- }; |
- |
- // Tuple (id, was_resolved, info). |
- struct FinishEntry { |
- FinishEntry(int id, bool was_resolved, |
- const net::HostResolver::RequestInfo& info) |
- : id(id), was_resolved(was_resolved), info(info) {} |
- |
- bool operator==(const FinishEntry& other) const { |
- return id == other.id && |
- was_resolved == other.was_resolved && |
- info == other.info; |
- } |
- |
- int id; |
- bool was_resolved; |
- net::HostResolver::RequestInfo info; |
- }; |
- |
- std::vector<StartOrCancelEntry> start_log; |
- std::vector<FinishEntry> finish_log; |
- std::vector<StartOrCancelEntry> cancel_log; |
-}; |
- |
-// Test that registering, unregistering, and notifying of observers works. |
-// Does not test the cancellation notification since all resolves are |
-// synchronous. |
-TEST_F(HostResolverTest, Observers) { |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- |
- CapturingObserver observer; |
- |
- host_resolver->AddObserver(&observer); |
- |
- net::AddressList addrlist; |
- |
- // Resolve "host1". |
- net::HostResolver::RequestInfo info1("host1", 70); |
- int rv = host_resolver->Resolve(info1, &addrlist, NULL, NULL); |
- EXPECT_EQ(net::OK, rv); |
- |
- EXPECT_EQ(1U, observer.start_log.size()); |
- EXPECT_EQ(1U, observer.finish_log.size()); |
- EXPECT_EQ(0U, observer.cancel_log.size()); |
- EXPECT_TRUE(observer.start_log[0] == |
- CapturingObserver::StartOrCancelEntry(0, info1)); |
- EXPECT_TRUE(observer.finish_log[0] == |
- CapturingObserver::FinishEntry(0, true, info1)); |
- |
- // Resolve "host1" again -- this time it will be served from cache, but it |
- // should still notify of completion. |
- TestCompletionCallback callback; |
- rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL); |
- ASSERT_EQ(net::OK, rv); // Should complete synchronously. |
- |
- EXPECT_EQ(2U, observer.start_log.size()); |
- EXPECT_EQ(2U, observer.finish_log.size()); |
- EXPECT_EQ(0U, observer.cancel_log.size()); |
- EXPECT_TRUE(observer.start_log[1] == |
- CapturingObserver::StartOrCancelEntry(1, info1)); |
- EXPECT_TRUE(observer.finish_log[1] == |
- CapturingObserver::FinishEntry(1, true, info1)); |
- |
- // Resolve "host2", setting referrer to "http://foobar.com" |
- net::HostResolver::RequestInfo info2("host2", 70); |
- info2.set_referrer(GURL("http://foobar.com")); |
- rv = host_resolver->Resolve(info2, &addrlist, NULL, NULL); |
- EXPECT_EQ(net::OK, rv); |
- |
- EXPECT_EQ(3U, observer.start_log.size()); |
- EXPECT_EQ(3U, observer.finish_log.size()); |
- EXPECT_EQ(0U, observer.cancel_log.size()); |
- EXPECT_TRUE(observer.start_log[2] == |
- CapturingObserver::StartOrCancelEntry(2, info2)); |
- EXPECT_TRUE(observer.finish_log[2] == |
- CapturingObserver::FinishEntry(2, true, info2)); |
- |
- // Unregister the observer. |
- host_resolver->RemoveObserver(&observer); |
- |
- // Resolve "host3" |
- net::HostResolver::RequestInfo info3("host3", 70); |
- host_resolver->Resolve(info3, &addrlist, NULL, NULL); |
- |
- // No effect this time, since observer was removed. |
- EXPECT_EQ(3U, observer.start_log.size()); |
- EXPECT_EQ(3U, observer.finish_log.size()); |
- EXPECT_EQ(0U, observer.cancel_log.size()); |
-} |
- |
-// Tests that observers are sent OnCancelResolution() whenever a request is |
-// cancelled. There are two ways to cancel a request: |
-// (1) Delete the HostResolver while job is outstanding. |
-// (2) Call HostResolver::CancelRequest() while a request is outstanding. |
-TEST_F(HostResolverTest, CancellationObserver) { |
- CapturingObserver observer; |
- { |
- // Create a host resolver and attach an observer. |
- scoped_refptr<net::HostResolver> host_resolver(new net::HostResolver); |
- host_resolver->AddObserver(&observer); |
- |
- TestCompletionCallback callback; |
- |
- EXPECT_EQ(0U, observer.start_log.size()); |
- EXPECT_EQ(0U, observer.finish_log.size()); |
- EXPECT_EQ(0U, observer.cancel_log.size()); |
- |
- // Start an async resolve for (host1:70). |
- net::HostResolver::RequestInfo info1("host1", 70); |
- net::HostResolver::Request* req = NULL; |
- net::AddressList addrlist; |
- int rv = host_resolver->Resolve(info1, &addrlist, &callback, &req); |
- EXPECT_EQ(net::ERR_IO_PENDING, rv); |
- EXPECT_TRUE(NULL != req); |
- |
- EXPECT_EQ(1U, observer.start_log.size()); |
- EXPECT_EQ(0U, observer.finish_log.size()); |
- EXPECT_EQ(0U, observer.cancel_log.size()); |
- |
- EXPECT_TRUE(observer.start_log[0] == |
- CapturingObserver::StartOrCancelEntry(0, info1)); |
- |
- // Cancel the request (host mapper is blocked so it cant be finished yet). |
- host_resolver->CancelRequest(req); |
- |
- EXPECT_EQ(1U, observer.start_log.size()); |
- EXPECT_EQ(0U, observer.finish_log.size()); |
- EXPECT_EQ(1U, observer.cancel_log.size()); |
- |
- EXPECT_TRUE(observer.cancel_log[0] == |
- CapturingObserver::StartOrCancelEntry(0, info1)); |
- |
- // Start an async request for (host2:60) |
- net::HostResolver::RequestInfo info2("host2", 60); |
- rv = host_resolver->Resolve(info2, &addrlist, &callback, NULL); |
- EXPECT_EQ(net::ERR_IO_PENDING, rv); |
- EXPECT_TRUE(NULL != req); |
- |
- EXPECT_EQ(2U, observer.start_log.size()); |
- EXPECT_EQ(0U, observer.finish_log.size()); |
- EXPECT_EQ(1U, observer.cancel_log.size()); |
- |
- EXPECT_TRUE(observer.start_log[1] == |
- CapturingObserver::StartOrCancelEntry(1, info2)); |
- |
- // Upon exiting this scope, HostResolver is destroyed, so all requests are |
- // implicitly cancelled. |
- } |
- |
- // Check that destroying the HostResolver sent a notification for |
- // cancellation of host2:60 request. |
- |
- EXPECT_EQ(2U, observer.start_log.size()); |
- EXPECT_EQ(0U, observer.finish_log.size()); |
- EXPECT_EQ(2U, observer.cancel_log.size()); |
- |
- net::HostResolver::RequestInfo info("host2", 60); |
- EXPECT_TRUE(observer.cancel_log[1] == |
- CapturingObserver::StartOrCancelEntry(1, info)); |
-} |
- |
-} // namespace |