Index: net/dns/host_resolver_impl_unittest.cc |
=================================================================== |
--- net/dns/host_resolver_impl_unittest.cc (revision 218544) |
+++ net/dns/host_resolver_impl_unittest.cc (working copy) |
@@ -12,6 +12,7 @@ |
#include "base/memory/ref_counted.h" |
#include "base/memory/scoped_vector.h" |
#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
#include "base/strings/string_util.h" |
#include "base/strings/stringprintf.h" |
#include "base/synchronization/condition_variable.h" |
@@ -420,6 +421,20 @@ |
HostResolverImplTest() : proc_(new MockHostResolverProc()) {} |
+ void CreateResolver() { |
+ CreateResolverWithLimitsAndParams(DefaultLimits(), |
+ DefaultParams(proc_.get())); |
+ } |
+ |
+ // This HostResolverImpl will only allow 1 outstanding resolve at a time and |
+ // perform no retries. |
+ void CreateSerialResolver() { |
+ HostResolverImpl::ProcTaskParams params = DefaultParams(proc_.get()); |
+ params.max_retry_attempts = 0u; |
+ PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1); |
+ CreateResolverWithLimitsAndParams(limits, params); |
+ } |
+ |
protected: |
// A Request::Handler which is a proxy to the HostResolverImplTest fixture. |
struct Handler : public Request::Handler { |
@@ -443,26 +458,24 @@ |
HostResolverImplTest* test; |
}; |
- void CreateResolver() { |
- resolver_.reset(new HostResolverImpl(HostCache::CreateDefaultCache(), |
- DefaultLimits(), |
- DefaultParams(proc_.get()), |
- NULL)); |
+ // testing::Test implementation: |
+ virtual void SetUp() OVERRIDE { |
+ CreateResolver(); |
} |
- // This HostResolverImpl will only allow 1 outstanding resolve at a time and |
- // perform no retries. |
- void CreateSerialResolver() { |
- HostResolverImpl::ProcTaskParams params = DefaultParams(proc_.get()); |
- params.max_retry_attempts = 0u; |
- PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1); |
- resolver_.reset(new HostResolverImpl( |
- HostCache::CreateDefaultCache(), |
- limits, |
- params, |
- NULL)); |
+ virtual void TearDown() OVERRIDE { |
+ if (resolver_.get()) |
+ EXPECT_EQ(0u, resolver_->num_running_dispatcher_jobs_for_tests()); |
+ EXPECT_FALSE(proc_->HasBlockedRequests()); |
} |
+ virtual void CreateResolverWithLimitsAndParams( |
+ const PrioritizedDispatcher::Limits& limits, |
+ const HostResolverImpl::ProcTaskParams& params) { |
+ resolver_.reset(new HostResolverImpl(HostCache::CreateDefaultCache(), |
+ limits, params, NULL)); |
+ } |
+ |
// The Request will not be made until a call to |Resolve()|, and the Job will |
// not start until released by |proc_->SignalXXX|. |
Request* CreateRequest(const HostResolver::RequestInfo& info, |
@@ -496,25 +509,15 @@ |
return CreateRequest(hostname, kDefaultPort); |
} |
- virtual void SetUp() OVERRIDE { |
- CreateResolver(); |
- } |
- |
- virtual void TearDown() OVERRIDE { |
- if (resolver_.get()) |
- EXPECT_EQ(0u, resolver_->num_running_jobs_for_tests()); |
- EXPECT_FALSE(proc_->HasBlockedRequests()); |
- } |
- |
void set_handler(Handler* handler) { |
handler_.reset(handler); |
handler_->test = this; |
} |
// Friendship is not inherited, so use proxies to access those. |
- size_t num_running_jobs() const { |
+ size_t num_running_dispatcher_jobs() const { |
DCHECK(resolver_.get()); |
- return resolver_->num_running_jobs_for_tests(); |
+ return resolver_->num_running_dispatcher_jobs_for_tests(); |
} |
void set_fallback_to_proctask(bool fallback_to_proctask) { |
@@ -898,7 +901,7 @@ |
EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[0]->WaitForResult()); |
- EXPECT_EQ(1u, num_running_jobs()); |
+ EXPECT_EQ(1u, num_running_dispatcher_jobs()); |
EXPECT_FALSE(requests_[1]->completed()); |
EXPECT_FALSE(requests_[2]->completed()); |
@@ -1265,36 +1268,63 @@ |
// Specialized fixture for tests of DnsTask. |
class HostResolverImplDnsTest : public HostResolverImplTest { |
+ public: |
+ HostResolverImplDnsTest() : dns_client_(NULL) {} |
+ |
protected: |
+ // testing::Test implementation: |
virtual void SetUp() OVERRIDE { |
- AddDnsRule("nx", dns_protocol::kTypeA, MockDnsClientRule::FAIL); |
- AddDnsRule("nx", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL); |
- AddDnsRule("ok", dns_protocol::kTypeA, MockDnsClientRule::OK); |
- AddDnsRule("ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK); |
- AddDnsRule("4ok", dns_protocol::kTypeA, MockDnsClientRule::OK); |
- AddDnsRule("4ok", dns_protocol::kTypeAAAA, MockDnsClientRule::EMPTY); |
- AddDnsRule("6ok", dns_protocol::kTypeA, MockDnsClientRule::EMPTY); |
- AddDnsRule("6ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK); |
- AddDnsRule("4nx", dns_protocol::kTypeA, MockDnsClientRule::OK); |
- AddDnsRule("4nx", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL); |
+ AddDnsRule("nx", dns_protocol::kTypeA, MockDnsClientRule::FAIL, false); |
+ AddDnsRule("nx", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL, false); |
+ AddDnsRule("ok", dns_protocol::kTypeA, MockDnsClientRule::OK, false); |
+ AddDnsRule("ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK, false); |
+ AddDnsRule("4ok", dns_protocol::kTypeA, MockDnsClientRule::OK, false); |
+ AddDnsRule("4ok", dns_protocol::kTypeAAAA, MockDnsClientRule::EMPTY, false); |
+ AddDnsRule("6ok", dns_protocol::kTypeA, MockDnsClientRule::EMPTY, false); |
+ AddDnsRule("6ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK, false); |
+ AddDnsRule("4nx", dns_protocol::kTypeA, MockDnsClientRule::OK, false); |
+ AddDnsRule("4nx", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL, false); |
+ |
+ AddDnsRule("4slow_ok", dns_protocol::kTypeA, MockDnsClientRule::OK, true); |
+ AddDnsRule("4slow_ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK, |
+ false); |
+ AddDnsRule("6slow_ok", dns_protocol::kTypeA, MockDnsClientRule::OK, false); |
+ AddDnsRule("6slow_ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK, |
+ true); |
+ AddDnsRule("4slow_4ok", dns_protocol::kTypeA, MockDnsClientRule::OK, true); |
+ AddDnsRule("4slow_4ok", dns_protocol::kTypeAAAA, MockDnsClientRule::EMPTY, |
+ false); |
+ AddDnsRule("4slow_4timeout", dns_protocol::kTypeA, |
+ MockDnsClientRule::TIMEOUT, true); |
+ AddDnsRule("4slow_4timeout", dns_protocol::kTypeAAAA, MockDnsClientRule::OK, |
+ false); |
+ AddDnsRule("4slow_6timeout", dns_protocol::kTypeA, |
+ MockDnsClientRule::OK, true); |
+ AddDnsRule("4slow_6timeout", dns_protocol::kTypeAAAA, |
+ MockDnsClientRule::TIMEOUT, false); |
CreateResolver(); |
} |
- void CreateResolver() { |
+ // HostResolverImplTest implementation: |
+ virtual void CreateResolverWithLimitsAndParams( |
+ const PrioritizedDispatcher::Limits& limits, |
+ const HostResolverImpl::ProcTaskParams& params) OVERRIDE { |
resolver_.reset(new HostResolverImpl(HostCache::CreateDefaultCache(), |
- DefaultLimits(), |
- DefaultParams(proc_.get()), |
+ limits, |
+ params, |
NULL)); |
// Disable IPv6 support probing. |
resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_UNSPECIFIED); |
- resolver_->SetDnsClient(CreateMockDnsClient(DnsConfig(), dns_rules_)); |
+ dns_client_ = new MockDnsClient(DnsConfig(), dns_rules_); |
+ resolver_->SetDnsClient(scoped_ptr<DnsClient>(dns_client_)); |
} |
// Adds a rule to |dns_rules_|. Must be followed by |CreateResolver| to apply. |
void AddDnsRule(const std::string& prefix, |
uint16 qtype, |
- MockDnsClientRule::Result result) { |
- dns_rules_.push_back(MockDnsClientRule(prefix, qtype, result)); |
+ MockDnsClientRule::Result result, |
+ bool delay) { |
+ dns_rules_.push_back(MockDnsClientRule(prefix, qtype, result, delay)); |
} |
void ChangeDnsConfig(const DnsConfig& config) { |
@@ -1304,6 +1334,8 @@ |
} |
MockDnsClientRuleList dns_rules_; |
+ // Owned by |resolver_|. |
+ MockDnsClient* dns_client_; |
}; |
// TODO(szym): Test AbortAllInProgressJobs due to DnsConfig change. |
@@ -1371,7 +1403,8 @@ |
// Simulate the case when the preference or policy has disabled the DNS client |
// causing AbortDnsTasks. |
- resolver_->SetDnsClient(CreateMockDnsClient(DnsConfig(), dns_rules_)); |
+ resolver_->SetDnsClient( |
+ scoped_ptr<DnsClient>(new MockDnsClient(DnsConfig(), dns_rules_))); |
ChangeDnsConfig(CreateValidDnsConfig()); |
// First request is resolved by MockDnsClient, others should fail due to |
@@ -1595,7 +1628,8 @@ |
DefaultLimits(), |
DefaultParams(proc.get()), |
NULL)); |
- resolver_->SetDnsClient(CreateMockDnsClient(DnsConfig(), dns_rules_)); |
+ resolver_->SetDnsClient( |
+ scoped_ptr<DnsClient>(new MockDnsClient(DnsConfig(), dns_rules_))); |
resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_IPV4); |
// Get the expected output. |
@@ -1648,4 +1682,186 @@ |
EXPECT_EQ(saw_ipv6, req->HasAddress("::1", 80)); |
} |
+// Cancel a request with a single DNS transaction active. |
+TEST_F(HostResolverImplDnsTest, CancelWithOneTransactionActive) { |
+ resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_IPV4); |
+ ChangeDnsConfig(CreateValidDnsConfig()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80)->Resolve()); |
+ EXPECT_EQ(1u, num_running_dispatcher_jobs()); |
+ requests_[0]->Cancel(); |
+ |
+ // Dispatcher state checked in TearDown. |
+} |
+ |
+// Cancel a request with a single DNS transaction active and another pending. |
+TEST_F(HostResolverImplDnsTest, CancelWithOneTransactionActiveOnePending) { |
+ CreateSerialResolver(); |
+ resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_UNSPECIFIED); |
+ ChangeDnsConfig(CreateValidDnsConfig()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80)->Resolve()); |
+ EXPECT_EQ(1u, num_running_dispatcher_jobs()); |
+ requests_[0]->Cancel(); |
+ |
+ // Dispatcher state checked in TearDown. |
+} |
+ |
+// Cancel a request with two DNS transactions active. |
+TEST_F(HostResolverImplDnsTest, CancelWithTwoTransactionsActive) { |
+ resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_UNSPECIFIED); |
+ ChangeDnsConfig(CreateValidDnsConfig()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80)->Resolve()); |
+ EXPECT_EQ(2u, num_running_dispatcher_jobs()); |
+ requests_[0]->Cancel(); |
+ |
+ // Dispatcher state checked in TearDown. |
+} |
+ |
+// Delete a resolver with some active requests and some queued requests. |
+TEST_F(HostResolverImplDnsTest, DeleteWithActiveTransactions) { |
+ // At most 10 Jobs active at once. |
+ CreateResolverWithLimitsAndParams( |
+ PrioritizedDispatcher::Limits(NUM_PRIORITIES, 10u), |
+ DefaultParams(proc_.get())); |
+ |
+ resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_UNSPECIFIED); |
+ ChangeDnsConfig(CreateValidDnsConfig()); |
+ |
+ // First active job is an IPv4 request. |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80, MEDIUM, |
+ ADDRESS_FAMILY_IPV4)->Resolve()); |
+ |
+ // Add 10 more DNS lookups for different hostnames. First 4 should have two |
+ // active jobs, next one has a single active job, and one pending. Others |
+ // should all be queued. |
+ for (int i = 0; i < 10; ++i) { |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest( |
+ base::StringPrintf("ok%i", i))->Resolve()); |
+ } |
+ EXPECT_EQ(10u, num_running_dispatcher_jobs()); |
+ |
+ resolver_.reset(); |
+} |
+ |
+// Cancel a request with only the IPv6 transaction active. |
+TEST_F(HostResolverImplDnsTest, CancelWithIPv6TransactionActive) { |
+ resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_UNSPECIFIED); |
+ ChangeDnsConfig(CreateValidDnsConfig()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("6slow_ok", 80)->Resolve()); |
+ EXPECT_EQ(2u, num_running_dispatcher_jobs()); |
+ |
+ // The IPv4 request should complete, the IPv6 request is still pending. |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_EQ(1u, num_running_dispatcher_jobs()); |
+ requests_[0]->Cancel(); |
+ |
+ // Dispatcher state checked in TearDown. |
+} |
+ |
+// Cancel a request with only the IPv4 transaction pending. |
+TEST_F(HostResolverImplDnsTest, CancelWithIPv4TransactionPending) { |
+ set_fallback_to_proctask(false); |
+ resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_UNSPECIFIED); |
+ ChangeDnsConfig(CreateValidDnsConfig()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("4slow_ok", 80)->Resolve()); |
+ EXPECT_EQ(2u, num_running_dispatcher_jobs()); |
+ |
+ // The IPv6 request should complete, the IPv4 request is still pending. |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_EQ(1u, num_running_dispatcher_jobs()); |
+ |
+ requests_[0]->Cancel(); |
+} |
+ |
+// Test cases where AAAA completes first. |
+TEST_F(HostResolverImplDnsTest, AAAACompletesFirst) { |
+ set_fallback_to_proctask(false); |
+ resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_UNSPECIFIED); |
+ ChangeDnsConfig(CreateValidDnsConfig()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("4slow_ok", 80)->Resolve()); |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("4slow_4ok", 80)->Resolve()); |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("4slow_4timeout", 80)->Resolve()); |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("4slow_6timeout", 80)->Resolve()); |
+ |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_FALSE(requests_[0]->completed()); |
+ EXPECT_FALSE(requests_[1]->completed()); |
+ EXPECT_FALSE(requests_[2]->completed()); |
+ // The IPv6 of the third request should have failed and resulted in cancelling |
+ // the IPv4 request. |
+ EXPECT_TRUE(requests_[3]->completed()); |
+ EXPECT_EQ(ERR_DNS_TIMED_OUT, requests_[3]->result()); |
+ EXPECT_EQ(3u, num_running_dispatcher_jobs()); |
+ |
+ dns_client_->CompleteDelayedTransactions(); |
+ EXPECT_TRUE(requests_[0]->completed()); |
+ EXPECT_EQ(OK, requests_[0]->result()); |
+ EXPECT_EQ(2u, requests_[0]->NumberOfAddresses()); |
+ EXPECT_TRUE(requests_[0]->HasAddress("127.0.0.1", 80)); |
+ EXPECT_TRUE(requests_[0]->HasAddress("::1", 80)); |
+ |
+ EXPECT_TRUE(requests_[1]->completed()); |
+ EXPECT_EQ(OK, requests_[1]->result()); |
+ EXPECT_EQ(1u, requests_[1]->NumberOfAddresses()); |
+ EXPECT_TRUE(requests_[1]->HasAddress("127.0.0.1", 80)); |
+ |
+ EXPECT_TRUE(requests_[2]->completed()); |
+ EXPECT_EQ(ERR_DNS_TIMED_OUT, requests_[2]->result()); |
+} |
+ |
+// Test the case where only a single transaction slot is available. |
+TEST_F(HostResolverImplDnsTest, SerialResolver) { |
+ CreateSerialResolver(); |
+ set_fallback_to_proctask(false); |
+ resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_UNSPECIFIED); |
+ ChangeDnsConfig(CreateValidDnsConfig()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80)->Resolve()); |
+ EXPECT_EQ(1u, num_running_dispatcher_jobs()); |
+ |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_TRUE(requests_[0]->completed()); |
+ EXPECT_EQ(OK, requests_[0]->result()); |
+ EXPECT_EQ(2u, requests_[0]->NumberOfAddresses()); |
+ EXPECT_TRUE(requests_[0]->HasAddress("127.0.0.1", 80)); |
+ EXPECT_TRUE(requests_[0]->HasAddress("::1", 80)); |
+} |
+ |
+// Test the case where the AAAA query is started when another transaction |
+// completes. |
+TEST_F(HostResolverImplDnsTest, AAAAStartsAfterOtherJobFinishes) { |
+ CreateResolverWithLimitsAndParams( |
+ PrioritizedDispatcher::Limits(NUM_PRIORITIES, 2), |
+ DefaultParams(proc_.get())); |
+ set_fallback_to_proctask(false); |
+ resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_UNSPECIFIED); |
+ ChangeDnsConfig(CreateValidDnsConfig()); |
+ |
+ EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80, MEDIUM, |
+ ADDRESS_FAMILY_IPV4)->Resolve()); |
+ EXPECT_EQ(ERR_IO_PENDING, |
+ CreateRequest("4slow_ok", 80, MEDIUM)->Resolve()); |
+ // An IPv4 request should have been started pending for each job. |
+ EXPECT_EQ(2u, num_running_dispatcher_jobs()); |
+ |
+ // Request 0's IPv4 request should complete, starting Request 1's IPv6 |
+ // request, which should also complete. |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_EQ(1u, num_running_dispatcher_jobs()); |
+ EXPECT_TRUE(requests_[0]->completed()); |
+ EXPECT_FALSE(requests_[1]->completed()); |
+ |
+ dns_client_->CompleteDelayedTransactions(); |
+ EXPECT_TRUE(requests_[1]->completed()); |
+ EXPECT_EQ(OK, requests_[1]->result()); |
+ EXPECT_EQ(2u, requests_[1]->NumberOfAddresses()); |
+ EXPECT_TRUE(requests_[1]->HasAddress("127.0.0.1", 80)); |
+ EXPECT_TRUE(requests_[1]->HasAddress("::1", 80)); |
+} |
+ |
} // namespace net |