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 b99dbf7b064d8ad818ce8bc13d555039eba9ddff..b0d1e2c23f75c28ed27c6530937316c5c16097c4 100644 |
--- a/net/base/host_resolver_impl_unittest.cc |
+++ b/net/base/host_resolver_impl_unittest.cc |
@@ -28,15 +28,18 @@ |
#include "net/base/net_util.h" |
#include "net/base/sys_addrinfo.h" |
#include "net/base/test_completion_callback.h" |
+#include "net/dns/dns_client.h" |
+#include "net/dns/dns_test_util.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace net { |
+namespace { |
using base::TimeDelta; |
using base::TimeTicks; |
-static const size_t kMaxJobs = 10u; |
-static const size_t kMaxRetryAttempts = 4u; |
+const size_t kMaxJobs = 10u; |
+const size_t kMaxRetryAttempts = 4u; |
PrioritizedDispatcher::Limits DefaultLimits() { |
PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, kMaxJobs); |
@@ -58,6 +61,17 @@ HostResolverImpl* CreateHostResolverImpl(HostResolverProc* resolver_proc) { |
NULL); |
} |
+HostResolverImpl* CreateHostResolverImplWithDnsConfig( |
+ HostResolverProc* resolver_proc, |
+ scoped_ptr<DnsConfigService> config_service) { |
+ return new HostResolverImpl( |
+ HostCache::CreateDefaultCache(), |
+ DefaultLimits(), |
+ DefaultParams(resolver_proc), |
+ config_service.Pass(), |
+ NULL); |
+} |
+ |
// This HostResolverImpl will only allow 1 outstanding resolve at a time. |
HostResolverImpl* CreateSerialHostResolverImpl( |
HostResolverProc* resolver_proc) { |
@@ -397,6 +411,7 @@ class ResolveRequest { |
virtual void OnCompleted(ResolveRequest* resolve) = 0; |
}; |
+ // For asynchronous resolutions. |
ResolveRequest(HostResolver* resolver, |
const std::string& hostname, |
int port, |
@@ -412,6 +427,7 @@ class ResolveRequest { |
EXPECT_EQ(ERR_IO_PENDING, err); |
} |
+ // For asynchronous resolutions. |
ResolveRequest(HostResolver* resolver, |
const HostResolver::RequestInfo& info, |
Delegate* delegate) |
@@ -421,10 +437,39 @@ class ResolveRequest { |
info, &addrlist_, |
base::Bind(&ResolveRequest::OnLookupFinished, |
base::Unretained(this)), |
- &req_, BoundNetLog()); |
+ &req_, BoundNetLog()); |
EXPECT_EQ(ERR_IO_PENDING, err); |
} |
+ // For synchronous resolutions. |
+ ResolveRequest(HostResolver* resolver, |
+ const std::string& hostname, |
+ int port) |
+ : info_(HostPortPair(hostname, port)), |
+ resolver_(resolver), |
+ delegate_(NULL) { |
+ // Start the request. |
+ result_ = resolver->Resolve( |
+ info_, &addrlist_, |
+ base::Bind(&ResolveRequest::OnLookupFinished, base::Unretained(this)), |
+ &req_, BoundNetLog()); |
+ EXPECT_NE(ERR_IO_PENDING, result_); |
+ } |
+ |
+ // For synchronous resolutions. |
+ ResolveRequest(HostResolver* resolver, |
+ const HostResolver::RequestInfo& info) |
+ : info_(info), |
+ resolver_(resolver), |
+ delegate_(NULL) { |
+ // Start the request. |
+ result_ = resolver->Resolve( |
+ info_, &addrlist_, |
+ base::Bind(&ResolveRequest::OnLookupFinished, base::Unretained(this)), |
+ &req_, BoundNetLog()); |
+ EXPECT_NE(ERR_IO_PENDING, result_); |
+ } |
+ |
void Cancel() { |
resolver_->CancelRequest(req_); |
} |
@@ -451,6 +496,9 @@ class ResolveRequest { |
private: |
void OnLookupFinished(int result) { |
+ EXPECT_TRUE(delegate_ != NULL); |
+ if (delegate_ == NULL) |
+ return; |
result_ = result; |
delegate_->OnCompleted(this); |
} |
@@ -870,20 +918,30 @@ TEST_F(HostResolverImplTest, CancelMultipleRequests) { |
MessageLoop::current()->Run(); |
} |
-// Helper class used by HostResolverImplTest.CanceledRequestsReleaseJobSlots. |
+// Delegate which allows to wait for specific number of requests to complete. |
+// Used by HostResolverImplTest.CanceledRequestsReleaseJobSlots and .DnsTask. |
class CountingDelegate : public ResolveRequest::Delegate { |
public: |
CountingDelegate() : num_completions_(0) {} |
virtual void OnCompleted(ResolveRequest* resolve) OVERRIDE { |
++num_completions_; |
- MessageLoop::current()->Quit(); |
+ if (num_completions_ == awaited_num_completions_) |
+ MessageLoop::current()->Quit(); |
} |
unsigned num_completions() const { return num_completions_; } |
+ void WaitForCompletions(unsigned completions) { |
+ ASSERT_LT(num_completions_, completions); |
+ awaited_num_completions_ = completions; |
+ MessageLoop::current()->Run(); |
+ EXPECT_EQ(completions, num_completions_); |
+ } |
+ |
private: |
unsigned num_completions_; |
+ unsigned awaited_num_completions_; |
mmenke
2012/03/13 20:31:08
You need to initialize this to 0 in the constructo
szym
2012/03/13 21:17:19
Good catch. Thanks.
|
}; |
TEST_F(HostResolverImplTest, CanceledRequestsReleaseJobSlots) { |
@@ -918,8 +976,7 @@ TEST_F(HostResolverImplTest, CanceledRequestsReleaseJobSlots) { |
resolver_proc->SignalAll(); |
- while (delegate.num_completions() < 2) |
- MessageLoop::current()->Run(); |
+ delegate.WaitForCompletions(2); |
EXPECT_EQ(0u, host_resolver->num_running_jobs_for_tests()); |
} |
@@ -1750,6 +1807,127 @@ TEST_F(HostResolverImplTest, MultipleAttempts) { |
EXPECT_EQ(resolver_proc->resolved_attempt_number(), kAttemptNumberToResolve); |
} |
+DnsConfig CreateValidDnsConfig() { |
+ IPAddressNumber dns_ip; |
+ bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip); |
+ EXPECT_TRUE(rv); |
+ |
+ DnsConfig config; |
+ config.nameservers.push_back(IPEndPoint(dns_ip, |
+ dns_protocol::kDefaultPort)); |
+ EXPECT_TRUE(config.IsValid()); |
+ return config; |
+} |
+ |
+// TODO(szym): Test AbortAllInProgressJobs due to DnsConfig change. |
+ |
// TODO(cbentzel): Test a mix of requests with different HostResolverFlags. |
+} // namespace |
+ |
+// Test successful and fallback resolutions in HostResolverImpl::DnsTask. |
+TEST_F(HostResolverImplTest, DnsTask) { |
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc( |
+ new RuleBasedHostResolverProc(NULL)); |
+ scoped_ptr<HostResolverImpl> host_resolver(CreateHostResolverImpl( |
+ resolver_proc)); |
+ |
+ resolver_proc->AddRule("er_succeed", "192.168.1.101"); |
+ resolver_proc->AddRule("nx_succeed", "192.168.1.102"); |
+ resolver_proc->AddSimulatedFailure("ok_fail"); |
+ resolver_proc->AddSimulatedFailure("er_fail"); |
+ resolver_proc->AddSimulatedFailure("nx_fail"); |
+ |
+ CountingDelegate delegate; |
+ |
+ // Initially there is no config, so client should not be invoked. |
+ ResolveRequest req1(host_resolver.get(), "ok_fail", 80, &delegate); |
+ |
+ delegate.WaitForCompletions(1); |
+ EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req1.result()); |
+ |
+ host_resolver->set_dns_client_for_tests( |
+ CreateMockDnsClient(CreateValidDnsConfig())); |
+ |
+ ResolveRequest req2(host_resolver.get(), "ok_fail", 80, &delegate); |
+ ResolveRequest req3(host_resolver.get(), "er_fail", 80, &delegate); |
+ ResolveRequest req4(host_resolver.get(), "nx_fail", 80, &delegate); |
+ ResolveRequest req5(host_resolver.get(), "er_succeed", 80, &delegate); |
+ ResolveRequest req6(host_resolver.get(), "nx_succeed", 80, &delegate); |
+ |
+ delegate.WaitForCompletions(6); |
+ EXPECT_EQ(OK, req2.result()); |
+ // Resolved by MockDnsClient. |
+ EXPECT_EQ("127.0.0.1", NetAddressToString(req2.addrlist().head())); |
+ EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req3.result()); |
+ EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req4.result()); |
+ EXPECT_EQ(OK, req5.result()); |
+ EXPECT_EQ("192.168.1.101", NetAddressToString(req5.addrlist().head())); |
+ EXPECT_EQ(OK, req6.result()); |
+ EXPECT_EQ("192.168.1.102", NetAddressToString(req6.addrlist().head())); |
+} |
+ |
+TEST_F(HostResolverImplTest, ServeFromHosts) { |
+ scoped_refptr<RuleBasedHostResolverProc> resolver_proc( |
+ new RuleBasedHostResolverProc(NULL)); |
+ MockDnsConfigService* config_service = new MockDnsConfigService(); |
+ scoped_ptr<HostResolverImpl> host_resolver( |
+ CreateHostResolverImplWithDnsConfig( |
+ resolver_proc, |
+ scoped_ptr<DnsConfigService>(config_service))); |
+ |
+ resolver_proc->AddSimulatedFailure("*"); |
+ |
+ DnsConfig config = CreateValidDnsConfig(); |
+ host_resolver->set_dns_client_for_tests(CreateMockDnsClient(config)); |
+ |
+ CountingDelegate delegate; |
+ |
+ ResolveRequest req1(host_resolver.get(), "er_ipv4", 80, &delegate); |
+ delegate.WaitForCompletions(1); |
+ EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req1.result()); |
+ |
+ IPAddressNumber local_ipv4, local_ipv6; |
+ ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &local_ipv4)); |
+ ASSERT_TRUE(ParseIPLiteralToNumber("::1", &local_ipv6)); |
+ |
+ DnsHosts hosts; |
+ hosts[DnsHostsKey("er_ipv4", ADDRESS_FAMILY_IPV4)] = local_ipv4; |
+ hosts[DnsHostsKey("er_ipv6", ADDRESS_FAMILY_IPV6)] = local_ipv6; |
+ hosts[DnsHostsKey("er_both", ADDRESS_FAMILY_IPV4)] = local_ipv4; |
+ hosts[DnsHostsKey("er_both", ADDRESS_FAMILY_IPV6)] = local_ipv6; |
+ |
+ config_service->ChangeConfig(config); |
+ config_service->ChangeHosts(hosts); |
+ |
+ ResolveRequest req2(host_resolver.get(), "er_ipv4", 80); |
+ ASSERT_EQ(OK, req2.result()); |
mmenke
2012/03/13 20:31:08
There are still a couple more cases like this in t
szym
2012/03/13 21:17:19
Rather than using ASSERT_EQ to avoid a crash, I ad
mmenke
2012/03/13 21:23:39
Sounds like a better idea to me.
|
+ EXPECT_EQ("127.0.0.1", NetAddressToString(req2.addrlist().head())); |
+ |
+ ResolveRequest req3(host_resolver.get(), "er_ipv6", 80); |
+ ASSERT_EQ(OK, req3.result()); |
+ EXPECT_EQ("::1", NetAddressToString(req3.addrlist().head())); |
+ |
+ ResolveRequest req4(host_resolver.get(), "er_both", 80); |
+ ASSERT_EQ(OK, req4.result()); |
+ // Either result is satisfactory. http://crbug.com/117850 |
+ const addrinfo* addr = req4.addrlist().head(); |
+ if (addr->ai_addrlen == sizeof(struct sockaddr_in)) |
+ EXPECT_EQ("127.0.0.1", NetAddressToString(addr)); |
+ else |
+ EXPECT_EQ("::1", NetAddressToString(addr)); |
+ |
+ // Requests with specified AddressFamily. |
+ HostResolver::RequestInfo info(HostPortPair("er_both", 80)); |
+ info.set_address_family(ADDRESS_FAMILY_IPV4); |
+ ResolveRequest req5(host_resolver.get(), info); |
+ ASSERT_EQ(OK, req5.result()); |
+ EXPECT_EQ("127.0.0.1", NetAddressToString(req5.addrlist().head())); |
+ |
+ info.set_address_family(ADDRESS_FAMILY_IPV6); |
+ ResolveRequest req6(host_resolver.get(), info); |
+ ASSERT_EQ(OK, req6.result()); |
+ EXPECT_EQ("::1", NetAddressToString(req6.addrlist().head())); |
+} |
+ |
} // namespace net |