| Index: net/base/host_resolver_impl_unittest.cc
|
| diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc
|
| index 88211ea06e3921feedccf42edce859650f50de62..ebc7fcbf8973d5a302ae60a8e93169131580807f 100644
|
| --- a/net/base/host_resolver_impl_unittest.cc
|
| +++ b/net/base/host_resolver_impl_unittest.cc
|
| @@ -15,6 +15,7 @@
|
| #include "base/stringprintf.h"
|
| #include "base/synchronization/condition_variable.h"
|
| #include "base/synchronization/lock.h"
|
| +#include "base/test/test_timeouts.h"
|
| #include "base/time.h"
|
| #include "net/base/address_list.h"
|
| #include "net/base/completion_callback.h"
|
| @@ -90,6 +91,45 @@ HostResolver::RequestInfo CreateResolverRequestForAddressFamily(
|
| return info;
|
| }
|
|
|
| +// Using WaitingHostResolverProc you can simulate very long lookups.
|
| +class WaitingHostResolverProc : public HostResolverProc {
|
| + public:
|
| + explicit WaitingHostResolverProc(HostResolverProc* previous)
|
| + : HostResolverProc(previous),
|
| + is_waiting_(false, false),
|
| + is_signaled_(false, false) {}
|
| +
|
| + // Waits until a call to |Resolve| is blocked. It is recommended to always
|
| + // |Wait| before |Signal|, and required if issuing a series of two or more
|
| + // calls to |Signal|, because |WaitableEvent| does not count the number of
|
| + // signals.
|
| + void Wait() {
|
| + is_waiting_.Wait();
|
| + }
|
| +
|
| + // Signals a waiting call to |Resolve|.
|
| + void Signal() {
|
| + is_signaled_.Signal();
|
| + }
|
| +
|
| + // HostResolverProc methods:
|
| + virtual int Resolve(const std::string& host,
|
| + AddressFamily address_family,
|
| + HostResolverFlags host_resolver_flags,
|
| + AddressList* addrlist,
|
| + int* os_error) OVERRIDE {
|
| + is_waiting_.Signal();
|
| + is_signaled_.Wait();
|
| + return ResolveUsingPrevious(host, address_family, host_resolver_flags,
|
| + addrlist, os_error);
|
| + }
|
| +
|
| + private:
|
| + virtual ~WaitingHostResolverProc() {}
|
| + base::WaitableEvent is_waiting_;
|
| + base::WaitableEvent is_signaled_;
|
| +};
|
| +
|
| // A variant of WaitingHostResolverProc that pushes each host mapped into a
|
| // list.
|
| // (and uses a manual-reset event rather than auto-reset).
|
| @@ -143,6 +183,72 @@ class CapturingHostResolverProc : public HostResolverProc {
|
| base::WaitableEvent event_;
|
| };
|
|
|
| +// A variant of WaitingHostResolverProc which waits for a specific number of
|
| +// requests.
|
| +class CountingHostResolverProc : public HostResolverProc {
|
| + public:
|
| + explicit CountingHostResolverProc(HostResolverProc* previous)
|
| + : HostResolverProc(previous),
|
| + num_requests_waiting_(0),
|
| + num_slots_available_(0),
|
| + requests_waiting_(&lock_),
|
| + slots_available_(&lock_) {}
|
| +
|
| + // Waits until |count| calls to |Resolve| are blocked. Returns false when
|
| + // timed out.
|
| + bool WaitFor(unsigned count) {
|
| + base::AutoLock lock(lock_);
|
| + base::Time start_time = base::Time::Now();
|
| + while (num_requests_waiting_ < count) {
|
| + requests_waiting_.TimedWait(TestTimeouts::action_timeout());
|
| + if (base::Time::Now() > start_time + TestTimeouts::action_timeout())
|
| + return false;
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + // Signals |count| waiting calls to |Resolve|. First come first served.
|
| + void SignalMultiple(unsigned count) {
|
| + base::AutoLock lock(lock_);
|
| + num_slots_available_ += count;
|
| + slots_available_.Broadcast();
|
| + }
|
| +
|
| + // Signals all waiting calls to |Resolve|. Beware of races.
|
| + void SignalAll() {
|
| + base::AutoLock lock(lock_);
|
| + num_slots_available_ += num_requests_waiting_;
|
| + slots_available_.Broadcast();
|
| + }
|
| +
|
| + // HostResolverProc methods:
|
| + virtual int Resolve(const std::string& host,
|
| + AddressFamily address_family,
|
| + HostResolverFlags host_resolver_flags,
|
| + AddressList* addrlist,
|
| + int* os_error) OVERRIDE {
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + ++num_requests_waiting_;
|
| + requests_waiting_.Broadcast();
|
| + while (!num_slots_available_)
|
| + slots_available_.Wait();
|
| + --num_slots_available_;
|
| + --num_requests_waiting_;
|
| + }
|
| + return ResolveUsingPrevious(host, address_family, host_resolver_flags,
|
| + addrlist, os_error);
|
| + }
|
| +
|
| + private:
|
| + virtual ~CountingHostResolverProc() {}
|
| + unsigned num_requests_waiting_;
|
| + unsigned num_slots_available_;
|
| + base::Lock lock_;
|
| + base::ConditionVariable requests_waiting_;
|
| + base::ConditionVariable slots_available_;
|
| +};
|
| +
|
| // This resolver function creates an IPv4 address, whose numeral value
|
| // describes a hash of the requested hostname, and the value of the requested
|
| // address_family.
|
| @@ -467,52 +573,6 @@ TEST_F(HostResolverImplTest, FailedAsynchronousLookup) {
|
| EXPECT_EQ(ERR_DNS_CACHE_MISS, err);
|
| }
|
|
|
| -// Using WaitingHostResolverProc you can simulate very long lookups.
|
| -class WaitingHostResolverProc : public HostResolverProc {
|
| - public:
|
| - explicit WaitingHostResolverProc(HostResolverProc* previous)
|
| - : HostResolverProc(previous),
|
| - is_waiting_(false, false),
|
| - is_signaled_(false, false) {}
|
| -
|
| - // If |manual_reset| is true, once Signalled, it will let all Resolve calls
|
| - // proceed.
|
| - WaitingHostResolverProc(HostResolverProc* previous, bool manual_reset)
|
| - : HostResolverProc(previous),
|
| - is_waiting_(false, false),
|
| - is_signaled_(manual_reset, false) {}
|
| -
|
| - // Waits until a call to |Resolve| is blocked. It is recommended to always
|
| - // |Wait| before |Signal|, and required if issuing a series of two or more
|
| - // calls to |Signal|, because |WaitableEvent| does not count the number of
|
| - // signals.
|
| - void Wait() {
|
| - is_waiting_.Wait();
|
| - }
|
| -
|
| - // Signals a waiting call to |Resolve|.
|
| - void Signal() {
|
| - is_signaled_.Signal();
|
| - }
|
| -
|
| - // HostResolverProc methods:
|
| - virtual int Resolve(const std::string& host,
|
| - AddressFamily address_family,
|
| - HostResolverFlags host_resolver_flags,
|
| - AddressList* addrlist,
|
| - int* os_error) OVERRIDE {
|
| - is_waiting_.Signal();
|
| - is_signaled_.Wait();
|
| - return ResolveUsingPrevious(host, address_family, host_resolver_flags,
|
| - addrlist, os_error);
|
| - }
|
| -
|
| - private:
|
| - virtual ~WaitingHostResolverProc() {}
|
| - base::WaitableEvent is_waiting_;
|
| - base::WaitableEvent is_signaled_;
|
| -};
|
| -
|
| TEST_F(HostResolverImplTest, AbortedAsynchronousLookup) {
|
| scoped_refptr<WaitingHostResolverProc> resolver_proc(
|
| new WaitingHostResolverProc(NULL));
|
| @@ -559,8 +619,8 @@ TEST_F(HostResolverImplTest, AbortedAsynchronousLookup) {
|
| NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
|
| NetLog::PHASE_BEGIN);
|
| pos = ExpectLogContainsSomewhereAfter(net_log_entries, pos + 1,
|
| - NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK,
|
| - NetLog::PHASE_BEGIN);
|
| + NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK,
|
| + NetLog::PHASE_BEGIN);
|
|
|
| // The Request needs to be cancelled. (The Job is "aborted".)
|
| // Don't care about order in which Request, Job and ProcTask end.
|
| @@ -808,6 +868,60 @@ TEST_F(HostResolverImplTest, CancelMultipleRequests) {
|
| MessageLoop::current()->Run();
|
| }
|
|
|
| +// Helper class used by HostResolverImplTest.CanceledRequestsReleaseJobSlots.
|
| +class CountingDelegate : public ResolveRequest::Delegate {
|
| + public:
|
| + CountingDelegate() : num_completions_(0) {}
|
| +
|
| + virtual void OnCompleted(ResolveRequest* resolve) OVERRIDE {
|
| + ++num_completions_;
|
| + MessageLoop::current()->Quit();
|
| + }
|
| +
|
| + unsigned num_completions() const { return num_completions_; }
|
| +
|
| + private:
|
| + unsigned num_completions_;
|
| +};
|
| +
|
| +TEST_F(HostResolverImplTest, CanceledRequestsReleaseJobSlots) {
|
| + scoped_refptr<CountingHostResolverProc> resolver_proc(
|
| + new CountingHostResolverProc(NULL));
|
| +
|
| + scoped_ptr<HostResolver> host_resolver(
|
| + CreateHostResolverImpl(resolver_proc));
|
| +
|
| + CountingDelegate delegate;
|
| + std::vector<ResolveRequest*> requests;
|
| +
|
| + // Fill up the dispatcher and queue.
|
| + for (unsigned i = 0; i < kMaxJobs + 1; ++i) {
|
| + std::string hostname = "a_";
|
| + hostname[1] = 'a' + i;
|
| + requests.push_back(new ResolveRequest(host_resolver.get(), hostname, 80,
|
| + &delegate));
|
| + requests.push_back(new ResolveRequest(host_resolver.get(), hostname, 81,
|
| + &delegate));
|
| + }
|
| +
|
| + EXPECT_TRUE(resolver_proc->WaitFor(kMaxJobs));
|
| +
|
| + // Cancel all but last two.
|
| + for (unsigned i = 0; i < requests.size() - 2; ++i) {
|
| + requests[i]->Cancel();
|
| + }
|
| +
|
| + EXPECT_TRUE(resolver_proc->WaitFor(kMaxJobs + 1));
|
| + EXPECT_EQ(0u, delegate.num_completions());
|
| +
|
| + resolver_proc->SignalAll();
|
| +
|
| + while (delegate.num_completions() < 2)
|
| + MessageLoop::current()->Run();
|
| +
|
| + MessageLoop::current()->AssertIdle();
|
| +}
|
| +
|
| // Helper class used by HostResolverImplTest.CancelWithinCallback.
|
| class CancelWithinCallbackVerifier : public ResolveRequest::Delegate {
|
| public:
|
| @@ -1185,9 +1299,8 @@ class StartWithinAbortedCallbackVerifier : public ResolveRequest::Delegate {
|
| // Tests that a new Request made from the callback of a previously aborted one
|
| // will not be aborted.
|
| TEST_F(HostResolverImplTest, AbortOnlyExistingRequestsOnIPAddressChange) {
|
| - // Setting |manual_reset| to true so that Signal unblocks all calls.
|
| - scoped_refptr<WaitingHostResolverProc> resolver_proc(
|
| - new WaitingHostResolverProc(CreateCatchAllHostResolverProc(), true));
|
| + scoped_refptr<CountingHostResolverProc> resolver_proc(
|
| + new CountingHostResolverProc(CreateCatchAllHostResolverProc()));
|
| scoped_ptr<HostResolver> host_resolver(CreateHostResolverImpl(resolver_proc));
|
|
|
| StartWithinAbortedCallbackVerifier verifier1("zzz");
|
| @@ -1198,8 +1311,8 @@ TEST_F(HostResolverImplTest, AbortOnlyExistingRequestsOnIPAddressChange) {
|
| ResolveRequest req2(host_resolver.get(), "eee", 80, &verifier2);
|
| ResolveRequest req3(host_resolver.get(), "ccc", 90, &verifier3);
|
| // The jobs start immediately.
|
| - // Wait until at least one is blocked.
|
| - resolver_proc->Wait();
|
| + // Wait until all are blocked;
|
| + resolver_proc->WaitFor(3u);
|
| // Trigger an IP address change.
|
| NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
|
| // This should abort all running jobs.
|
| @@ -1208,7 +1321,7 @@ TEST_F(HostResolverImplTest, AbortOnlyExistingRequestsOnIPAddressChange) {
|
| EXPECT_EQ(ERR_ABORTED, req2.result());
|
| EXPECT_EQ(ERR_ABORTED, req3.result());
|
| // Unblock all calls to proc.
|
| - resolver_proc->Signal();
|
| + resolver_proc->SignalMultiple(6u);
|
| // Run until the re-started requests finish.
|
| EXPECT_EQ(OK, verifier1.WaitUntilDone());
|
| EXPECT_EQ(OK, verifier2.WaitUntilDone());
|
|
|