diff options
-rw-r--r-- | net/base/host_resolver.h | 8 | ||||
-rw-r--r-- | net/base/host_resolver_impl.cc | 131 | ||||
-rw-r--r-- | net/base/host_resolver_impl.h | 29 | ||||
-rw-r--r-- | net/base/host_resolver_impl_unittest.cc | 309 | ||||
-rw-r--r-- | net/base/net_log_event_type_list.h | 3 | ||||
-rw-r--r-- | net/dns/dns_client.cc | 58 | ||||
-rw-r--r-- | net/dns/dns_client.h | 40 | ||||
-rw-r--r-- | net/dns/dns_test_util.cc | 166 | ||||
-rw-r--r-- | net/dns/dns_test_util.h | 21 | ||||
-rw-r--r-- | net/dns/dns_transaction_unittest.cc | 2 | ||||
-rw-r--r-- | net/net.gyp | 3 |
11 files changed, 662 insertions, 108 deletions
diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h index e375961..a282701 100644 --- a/net/base/host_resolver.h +++ b/net/base/host_resolver.h @@ -132,10 +132,10 @@ class NET_EXPORT HostResolver { RequestHandle* out_req, const BoundNetLog& net_log) = 0; - // Resolves the given hostname (or IP address literal) out of cache - // only. This is guaranteed to complete synchronously. This acts like - // |Resolve()| if the hostname is IP literal or cached value exists. - // Otherwise, ERR_DNS_CACHE_MISS is returned. + // Resolves the given hostname (or IP address literal) out of cache or HOSTS + // file (if enabled) only. This is guaranteed to complete synchronously. + // This acts like |Resolve()| if the hostname is IP literal, or cached value + // or HOSTS entry exists. Otherwise, ERR_DNS_CACHE_MISS is returned. virtual int ResolveFromCache(const RequestInfo& info, AddressList* addresses, const BoundNetLog& net_log) = 0; diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc index ecbbd58..2a51153 100644 --- a/net/base/host_resolver_impl.cc +++ b/net/base/host_resolver_impl.cc @@ -24,7 +24,6 @@ #include "base/message_loop_proxy.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" -#include "base/rand_util.h" #include "base/stl_util.h" #include "base/string_util.h" #include "base/threading/worker_pool.h" @@ -40,12 +39,11 @@ #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/net_util.h" +#include "net/dns/dns_client.h" #include "net/dns/dns_config_service.h" #include "net/dns/dns_protocol.h" #include "net/dns/dns_response.h" -#include "net/dns/dns_session.h" #include "net/dns/dns_transaction.h" -#include "net/socket/client_socket_factory.h" #if defined(OS_WIN) #include "net/base/winsock_init.h" @@ -755,7 +753,7 @@ class HostResolverImpl::ProcTask DNS_HISTOGRAM("DNS.ResolveSpeculativeSuccess", duration); } - // Log DNS lookups based on address_family. This will help us determine + // Log DNS lookups based on |address_family|. This will help us determine // if IPv4 or IPv4/6 lookups are faster or slower. switch(key_.address_family) { case ADDRESS_FAMILY_IPV4: @@ -776,7 +774,7 @@ class HostResolverImpl::ProcTask category = RESOLVE_SPECULATIVE_FAIL; DNS_HISTOGRAM("DNS.ResolveSpeculativeFail", duration); } - // Log DNS lookups based on address_family. This will help us determine + // Log DNS lookups based on |address_family|. This will help us determine // if IPv4 or IPv4/6 lookups are faster or slower. switch(key_.address_family) { case ADDRESS_FAMILY_IPV4: @@ -1205,6 +1203,21 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { base::TimeDelta()); } + // Attempts to serve the job from HOSTS. Returns true if succeeded and + // this Job was destroyed. + bool ServeFromHosts() { + DCHECK_GT(num_active_requests(), 0u); + AddressList addr_list; + if (resolver_->ServeFromHosts(key(), + requests_.front()->info(), + &addr_list)) { + // This will destroy the Job. + CompleteRequests(OK, addr_list, base::TimeDelta()); + return true; + } + return false; + } + private: RequestPriority priority() const { return priority_tracker_.highest_priority(); @@ -1231,7 +1244,7 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED, NULL); // Job::Start must not complete synchronously. - if (resolver_->dns_transaction_factory_.get()) { + if (resolver_->HaveDnsConfig()) { StartDnsTask(); } else { StartProcTask(); @@ -1270,8 +1283,9 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { } void StartDnsTask() { + DCHECK(resolver_->HaveDnsConfig()); dns_task_.reset(new DnsTask( - resolver_->dns_transaction_factory_.get(), + resolver_->dns_client_->GetTransactionFactory(), key_, base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), net_log_)); @@ -1292,6 +1306,10 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { if (net_error != OK) { dns_task_.reset(); + + // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. + // http://crbug.com/117655 + // TODO(szym): Some net errors indicate lack of connectivity. Starting // ProcTask in that case is a waste of time. StartProcTask(); @@ -1344,9 +1362,11 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, net_error); + DCHECK(!requests_.empty()); + // We are the only consumer of |list|, so we can safely change the port // without copy-on-write. This pays off, when job has only one request. - if (net_error == OK && !requests_.empty()) + if (net_error == OK) MutableSetPort(requests_.front()->info().port(), &list); if ((net_error != ERR_ABORTED) && @@ -1424,6 +1444,7 @@ HostResolverImpl::HostResolverImpl( max_queued_jobs_(job_limits.total_jobs * 100u), proc_params_(proc_params), default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), + dns_client_(NULL), dns_config_service_(dns_config_service.Pass()), ipv6_probe_monitoring_(false), additional_resolver_flags_(0), @@ -1452,8 +1473,10 @@ HostResolverImpl::HostResolverImpl( NetworkChangeNotifier::AddDNSObserver(this); #endif - if (dns_config_service_.get()) + if (dns_config_service_.get()) { dns_config_service_->AddObserver(this); + dns_client_ = DnsClient::CreateClient(net_log_); + } } HostResolverImpl::~HostResolverImpl() { @@ -1552,9 +1575,17 @@ int HostResolverImpl::ResolveHelper(const Key& key, int net_error = ERR_UNEXPECTED; if (ResolveAsIP(key, info, &net_error, addresses)) return net_error; - net_error = ERR_DNS_CACHE_MISS; - ServeFromCache(key, info, request_net_log, &net_error, addresses); - return net_error; + if (ServeFromCache(key, info, &net_error, addresses)) { + request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); + return net_error; + } + // TODO(szym): Do not do this if nsswitch.conf instructs not to. + // http://crbug.com/117655 + if (ServeFromHosts(key, info, addresses)) { + request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_HOSTS_HIT, NULL); + return OK; + } + return ERR_DNS_CACHE_MISS; } int HostResolverImpl::ResolveFromCache(const RequestInfo& info, @@ -1637,7 +1668,6 @@ bool HostResolverImpl::ResolveAsIP(const Key& key, bool HostResolverImpl::ServeFromCache(const Key& key, const RequestInfo& info, - const BoundNetLog& request_net_log, int* net_error, AddressList* addresses) { DCHECK(addresses); @@ -1650,13 +1680,43 @@ bool HostResolverImpl::ServeFromCache(const Key& key, if (!cache_entry) return false; - request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); + *net_error = cache_entry->error; if (*net_error == OK) *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); return true; } +bool HostResolverImpl::ServeFromHosts(const Key& key, + const RequestInfo& info, + AddressList* addresses) { + DCHECK(addresses); + if (!HaveDnsConfig()) + return false; + + // If |address_family| is ADDRESS_FAMILY_UNSPECIFIED other implementations + // (glibc and c-ares) return the first matching line. We have more + // flexibility, but lose implicit ordering. + // TODO(szym) http://crbug.com/117850 + const DnsHosts& hosts = dns_client_->GetConfig()->hosts; + DnsHosts::const_iterator it = hosts.find( + DnsHostsKey(key.hostname, + key.address_family == ADDRESS_FAMILY_UNSPECIFIED ? + ADDRESS_FAMILY_IPV4 : key.address_family)); + + if (it == hosts.end()) { + if (key.address_family != ADDRESS_FAMILY_UNSPECIFIED) + return false; + + it = hosts.find(DnsHostsKey(key.hostname, ADDRESS_FAMILY_IPV6)); + if (it == hosts.end()) + return false; + } + + *addresses = AddressList::CreateFromIPAddress(it->second, info.port()); + return true; +} + void HostResolverImpl::CacheResult(const Key& key, int net_error, const AddressList& addr_list, @@ -1734,6 +1794,24 @@ void HostResolverImpl::AbortAllInProgressJobs() { } } +void HostResolverImpl::TryServingAllJobsFromHosts() { + if (!HaveDnsConfig()) + return; + + // TODO(szym): Do not do this if nsswitch.conf instructs not to. + // http://crbug.com/117655 + + // Life check to bail once |this| is deleted. + base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); + + for (JobMap::iterator it = jobs_.begin(); self && it != jobs_.end(); ) { + Job* job = it->second; + ++it; + // This could remove |job| from |jobs_|, but iterator will remain valid. + job->ServeFromHosts(); + } +} + void HostResolverImpl::OnIPAddressChanged() { if (cache_.get()) cache_->clear(); @@ -1769,20 +1847,25 @@ void HostResolverImpl::OnDNSChanged(unsigned detail) { void HostResolverImpl::OnConfigChanged(const DnsConfig& dns_config) { // We want a new factory in place, before we Abort running Jobs, so that the // newly started jobs use the new factory. - bool had_factory = (dns_transaction_factory_.get() != NULL); - if (dns_config.IsValid()) { - dns_transaction_factory_ = DnsTransactionFactory::CreateFactory( - new DnsSession(dns_config, - ClientSocketFactory::GetDefaultFactory(), - base::Bind(&base::RandInt), - net_log_)); - } else { - dns_transaction_factory_.reset(); - } + DCHECK(dns_client_.get()); + + // Life check to bail once |this| is deleted. + base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); + + bool had_factory = (dns_client_->GetConfig() != NULL); + dns_client_->SetConfig(dns_config); + // Don't Abort running Jobs unless they were running on DnsTransaction. // TODO(szym): This will change once http://crbug.com/114827 is fixed. if (had_factory) OnDNSChanged(NetworkChangeNotifier::CHANGE_DNS_SETTINGS); + + if (self && dns_config.IsValid()) + TryServingAllJobsFromHosts(); +} + +bool HostResolverImpl::HaveDnsConfig() const { + return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL); } } // namespace net diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h index dd8c70e..7b0900f 100644 --- a/net/base/host_resolver_impl.h +++ b/net/base/host_resolver_impl.h @@ -23,12 +23,11 @@ #include "net/base/net_log.h" #include "net/base/network_change_notifier.h" #include "net/base/prioritized_dispatcher.h" +#include "net/dns/dns_client.h" #include "net/dns/dns_config_service.h" namespace net { -class DnsTransactionFactory; - // For each hostname that is requested, HostResolver creates a // HostResolverImpl::Job. When this job gets dispatched it creates a ProcTask // which runs the given HostResolverProc on a WorkerPool thread. If requests for @@ -154,6 +153,8 @@ class NET_EXPORT HostResolverImpl } private: + FRIEND_TEST_ALL_PREFIXES(HostResolverImplTest, DnsTask); + FRIEND_TEST_ALL_PREFIXES(HostResolverImplTest, ServeFromHosts); class Job; class ProcTask; class IPv6ProbeJob; @@ -163,10 +164,14 @@ class NET_EXPORT HostResolverImpl typedef std::map<Key, Job*> JobMap; typedef std::vector<Request*> RequestsList; + void set_dns_client_for_tests(scoped_ptr<DnsClient> client) { + dns_client_ = client.Pass(); + } + // Helper used by |Resolve()| and |ResolveFromCache()|. Performs IP - // literal and cache lookup, returns OK if successful, + // literal, cache and HOSTS lookup (if enabled), returns OK if successful, // ERR_NAME_NOT_RESOLVED if either hostname is invalid or IP literal is - // incompatible, ERR_DNS_CACHE_MISS if entry was not found in cache. + // incompatible, ERR_DNS_CACHE_MISS if entry was not found in cache and HOSTS. int ResolveHelper(const Key& key, const RequestInfo& info, AddressList* addresses, @@ -184,10 +189,15 @@ class NET_EXPORT HostResolverImpl // if it is a positive entry. bool ServeFromCache(const Key& key, const RequestInfo& info, - const BoundNetLog& request_net_log, int* net_error, AddressList* addresses); + // If |key| is not found in the HOSTS file or no HOSTS file known, returns + // false, otherwise returns true and fills |addresses|. + bool ServeFromHosts(const Key& key, + const RequestInfo& info, + AddressList* addresses); + // Notifies IPv6ProbeJob not to call back, and discard reference to the job. void DiscardIPv6ProbeJob(); @@ -212,6 +222,9 @@ class NET_EXPORT HostResolverImpl // Might start new jobs. void AbortAllInProgressJobs(); + // Attempts to serve each Job in |jobs_| from the HOSTS file. + void TryServingAllJobsFromHosts(); + // NetworkChangeNotifier::IPAddressObserver: virtual void OnIPAddressChanged() OVERRIDE; @@ -221,6 +234,9 @@ class NET_EXPORT HostResolverImpl // DnsConfigService::Observer: virtual void OnConfigChanged(const DnsConfig& dns_config) OVERRIDE; + // True if have fully configured DNS client. + bool HaveDnsConfig() const; + // Cache of host resolution results. scoped_ptr<HostCache> cache_; @@ -236,11 +252,10 @@ class NET_EXPORT HostResolverImpl // Parameters for ProcTask. ProcTaskParams proc_params_; - scoped_ptr<DnsTransactionFactory> dns_transaction_factory_; - // Address family to use when the request doesn't specify one. AddressFamily default_address_family_; + scoped_ptr<DnsClient> dns_client_; scoped_ptr<DnsConfigService> dns_config_service_; // Indicate if probing is done after each network change event to set address diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc index b99dbf7..7e9606e 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); } @@ -470,6 +518,7 @@ class ResolveRequest { DISALLOW_COPY_AND_ASSIGN(ResolveRequest); }; +// TODO(szym): Make this fixture more useful. http://crbug.com/117830 class HostResolverImplTest : public testing::Test { public: HostResolverImplTest() @@ -491,9 +540,30 @@ class HostResolverImplTest : public testing::Test { CompletionCallback callback_; }; +// Returns the first address in |addr_list| in host:port form or empty string if +// the list is empty. +std::string FirstAddressToString(const AddressList& addr_list) { + const struct addrinfo* ai = addr_list.head(); + if (!ai) + return ""; + return NetAddressToStringWithPort(ai); +} + +// Returns the number of addresses in |addr_list|. +unsigned NumberOfAddresses(const AddressList& addr_list) { + unsigned count = 0; + for (const struct addrinfo* ai = addr_list.head(); + ai != NULL; + ai = ai->ai_next) { + ++count; + } + return count; +} + +} // namespace net + TEST_F(HostResolverImplTest, AsynchronousLookup) { AddressList addrlist; - const int kPortnum = 80; scoped_refptr<RuleBasedHostResolverProc> resolver_proc( new RuleBasedHostResolverProc(NULL)); @@ -502,7 +572,7 @@ TEST_F(HostResolverImplTest, AsynchronousLookup) { scoped_ptr<HostResolver> host_resolver( CreateHostResolverImpl(resolver_proc)); - HostResolver::RequestInfo info(HostPortPair("just.testing", kPortnum)); + HostResolver::RequestInfo info(HostPortPair("just.testing", 80)); CapturingBoundNetLog log(CapturingNetLog::kUnbounded); int err = host_resolver->Resolve(info, &addrlist, callback_, NULL, log.bound()); @@ -526,27 +596,19 @@ TEST_F(HostResolverImplTest, AsynchronousLookup) { EXPECT_TRUE(LogContainsEndEvent( entries, 1, NetLog::TYPE_HOST_RESOLVER_IMPL)); - const struct addrinfo* ainfo = addrlist.head(); - EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); - EXPECT_EQ(sizeof(struct sockaddr_in), static_cast<size_t>(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); + EXPECT_EQ("192.168.1.42:80", FirstAddressToString(addrlist)); + EXPECT_EQ(1u, NumberOfAddresses(addrlist)); } TEST_F(HostResolverImplTest, FailedAsynchronousLookup) { AddressList addrlist; - const int kPortnum = 80; - scoped_refptr<RuleBasedHostResolverProc> resolver_proc( new RuleBasedHostResolverProc(NULL)); resolver_proc->AddSimulatedFailure("just.testing"); scoped_ptr<HostResolver> host_resolver(CreateHostResolverImpl(resolver_proc)); - HostResolver::RequestInfo info(HostPortPair("just.testing", kPortnum)); + HostResolver::RequestInfo info(HostPortPair("just.testing", 80)); CapturingBoundNetLog log(CapturingNetLog::kUnbounded); int err = host_resolver->Resolve(info, &addrlist, callback_, NULL, log.bound()); @@ -590,9 +652,7 @@ TEST_F(HostResolverImplTest, AbortedAsynchronousLookup) { scoped_ptr<DnsConfigService>(NULL), &net_log)); AddressList addrlist; - const int kPortnum = 80; - - HostResolver::RequestInfo info(HostPortPair("just.testing", kPortnum)); + HostResolver::RequestInfo info(HostPortPair("just.testing", 80)); int err = host_resolver->Resolve(info, &addrlist, callback_, NULL, log.bound()); EXPECT_EQ(ERR_IO_PENDING, err); @@ -652,21 +712,14 @@ TEST_F(HostResolverImplTest, NumericIPv4Address) { scoped_ptr<HostResolver> host_resolver( CreateHostResolverImpl(resolver_proc)); AddressList addrlist; - const int kPortnum = 5555; TestCompletionCallback callback; - HostResolver::RequestInfo info(HostPortPair("127.1.2.3", kPortnum)); + HostResolver::RequestInfo info(HostPortPair("127.1.2.3", 5555)); int err = host_resolver->Resolve(info, &addrlist, callback.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, err); - const struct addrinfo* ainfo = addrlist.head(); - EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); - EXPECT_EQ(sizeof(struct sockaddr_in), static_cast<size_t>(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); + EXPECT_EQ("127.1.2.3:5555", FirstAddressToString(addrlist)); + EXPECT_EQ(1u, NumberOfAddresses(addrlist)); } TEST_F(HostResolverImplTest, NumericIPv6Address) { @@ -679,29 +732,14 @@ TEST_F(HostResolverImplTest, NumericIPv6Address) { scoped_ptr<HostResolver> host_resolver( CreateHostResolverImpl(resolver_proc)); AddressList addrlist; - const int kPortnum = 5555; TestCompletionCallback callback; - HostResolver::RequestInfo info(HostPortPair("2001:db8::1", kPortnum)); + HostResolver::RequestInfo info(HostPortPair("2001:db8::1", 5555)); int err = host_resolver->Resolve(info, &addrlist, callback.callback(), NULL, BoundNetLog()); EXPECT_EQ(OK, err); - const struct addrinfo* ainfo = addrlist.head(); - EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); - EXPECT_EQ(sizeof(struct sockaddr_in6), - static_cast<size_t>(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]); - } + EXPECT_EQ("[2001:db8::1]:5555", FirstAddressToString(addrlist)); + EXPECT_EQ(1u, NumberOfAddresses(addrlist)); } TEST_F(HostResolverImplTest, EmptyHost) { @@ -712,9 +750,8 @@ TEST_F(HostResolverImplTest, EmptyHost) { scoped_ptr<HostResolver> host_resolver( CreateHostResolverImpl(resolver_proc)); AddressList addrlist; - const int kPortnum = 5555; TestCompletionCallback callback; - HostResolver::RequestInfo info(HostPortPair("", kPortnum)); + HostResolver::RequestInfo info(HostPortPair("", 5555)); int err = host_resolver->Resolve(info, &addrlist, callback.callback(), NULL, BoundNetLog()); EXPECT_EQ(ERR_NAME_NOT_RESOLVED, err); @@ -728,10 +765,9 @@ TEST_F(HostResolverImplTest, LongHost) { scoped_ptr<HostResolver> host_resolver( CreateHostResolverImpl(resolver_proc)); AddressList addrlist; - const int kPortnum = 5555; std::string hostname(4097, 'a'); TestCompletionCallback callback; - HostResolver::RequestInfo info(HostPortPair(hostname, kPortnum)); + HostResolver::RequestInfo info(HostPortPair(hostname, 5555)); int err = host_resolver->Resolve(info, &addrlist, callback.callback(), NULL, BoundNetLog()); EXPECT_EQ(ERR_NAME_NOT_RESOLVED, err); @@ -870,20 +906,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) {} + CountingDelegate() : num_completions_(0), awaited_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_; }; TEST_F(HostResolverImplTest, CanceledRequestsReleaseJobSlots) { @@ -918,8 +964,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()); } @@ -1594,9 +1639,12 @@ TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv4) { // x = length of hostname // y = ASCII value of hostname[0] // z = value of address family - EXPECT_EQ("192.2.104.1", NetAddressToString(addrlist[0].head())); - EXPECT_EQ("192.2.104.1", NetAddressToString(addrlist[1].head())); - EXPECT_EQ("192.2.104.2", NetAddressToString(addrlist[2].head())); + EXPECT_EQ("192.2.104.1:80", FirstAddressToString(addrlist[0])); + EXPECT_EQ("192.2.104.1:80", FirstAddressToString(addrlist[1])); + EXPECT_EQ("192.2.104.2:80", FirstAddressToString(addrlist[2])); + EXPECT_EQ(1u, NumberOfAddresses(addrlist[0])); + EXPECT_EQ(1u, NumberOfAddresses(addrlist[1])); + EXPECT_EQ(1u, NumberOfAddresses(addrlist[2])); } // This is the exact same test as SetDefaultAddressFamily_IPv4, except the order @@ -1661,14 +1709,16 @@ TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv6) { // x = length of hostname // y = ASCII value of hostname[0] // z = value of address family - EXPECT_EQ("192.2.104.2", NetAddressToString(addrlist[0].head())); - EXPECT_EQ("192.2.104.2", NetAddressToString(addrlist[1].head())); - EXPECT_EQ("192.2.104.1", NetAddressToString(addrlist[2].head())); + EXPECT_EQ("192.2.104.2:80", FirstAddressToString(addrlist[0])); + EXPECT_EQ("192.2.104.2:80", FirstAddressToString(addrlist[1])); + EXPECT_EQ("192.2.104.1:80", FirstAddressToString(addrlist[2])); + EXPECT_EQ(1u, NumberOfAddresses(addrlist[0])); + EXPECT_EQ(1u, NumberOfAddresses(addrlist[1])); + EXPECT_EQ(1u, NumberOfAddresses(addrlist[2])); } TEST_F(HostResolverImplTest, DisallowNonCachedResponses) { AddressList addrlist; - const int kPortnum = 80; scoped_refptr<RuleBasedHostResolverProc> resolver_proc( new RuleBasedHostResolverProc(NULL)); @@ -1678,7 +1728,7 @@ TEST_F(HostResolverImplTest, DisallowNonCachedResponses) { CreateHostResolverImpl(resolver_proc)); // First hit will miss the cache. - HostResolver::RequestInfo info(HostPortPair("just.testing", kPortnum)); + HostResolver::RequestInfo info(HostPortPair("just.testing", 80)); CapturingBoundNetLog log(CapturingNetLog::kUnbounded); int err = host_resolver->ResolveFromCache(info, &addrlist, log.bound()); EXPECT_EQ(ERR_DNS_CACHE_MISS, err); @@ -1695,14 +1745,8 @@ TEST_F(HostResolverImplTest, DisallowNonCachedResponses) { err = host_resolver->ResolveFromCache(info, &addrlist, log.bound()); EXPECT_EQ(OK, err); - const struct addrinfo* ainfo = addrlist.head(); - EXPECT_EQ(static_cast<addrinfo*>(NULL), ainfo->ai_next); - EXPECT_EQ(sizeof(struct sockaddr_in), static_cast<size_t>(ainfo->ai_addrlen)); - - const struct sockaddr* sa = ainfo->ai_addr; - const struct sockaddr_in* sa_in = reinterpret_cast<const sockaddr_in*>(sa); - EXPECT_TRUE(htons(kPortnum) == sa_in->sin_port); - EXPECT_TRUE(htonl(0xc0a8012a) == sa_in->sin_addr.s_addr); + EXPECT_EQ("192.168.1.42:80", FirstAddressToString(addrlist)); + EXPECT_EQ(1u, NumberOfAddresses(addrlist)); } // Test the retry attempts simulating host resolver proc that takes too long. @@ -1750,6 +1794,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. +// 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:80", FirstAddressToString(req2.addrlist())); + 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:80", FirstAddressToString(req5.addrlist())); + EXPECT_EQ(OK, req6.result()); + EXPECT_EQ("192.168.1.102:80", FirstAddressToString(req6.addrlist())); +} + +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); + EXPECT_EQ(OK, req2.result()); + EXPECT_EQ("127.0.0.1:80", FirstAddressToString(req2.addrlist())); + + ResolveRequest req3(host_resolver.get(), "er_ipv6", 80); + EXPECT_EQ(OK, req3.result()); + EXPECT_EQ("[::1]:80", FirstAddressToString(req3.addrlist())); + + ResolveRequest req4(host_resolver.get(), "er_both", 80); + EXPECT_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); + EXPECT_EQ(OK, req5.result()); + EXPECT_EQ("127.0.0.1:80", FirstAddressToString(req5.addrlist())); + EXPECT_EQ(1u, NumberOfAddresses(req5.addrlist())); + + info.set_address_family(ADDRESS_FAMILY_IPV6); + ResolveRequest req6(host_resolver.get(), info); + EXPECT_EQ(OK, req6.result()); + EXPECT_EQ("[::1]:80", FirstAddressToString(req6.addrlist())); + EXPECT_EQ(1u, NumberOfAddresses(req6.addrlist())); +} + } // namespace net diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h index ceb4a72..68c2b4f 100644 --- a/net/base/net_log_event_type_list.h +++ b/net/base/net_log_event_type_list.h @@ -62,6 +62,9 @@ EVENT_TYPE(HOST_RESOLVER_IMPL_REQUEST) // This event is logged when a request is handled by a cache entry. EVENT_TYPE(HOST_RESOLVER_IMPL_CACHE_HIT) +// This event is logged when a request is handled by a HOSTS entry. +EVENT_TYPE(HOST_RESOLVER_IMPL_HOSTS_HIT) + // This event is created when a new HostResolverImpl::Job is about to be created // for a request. EVENT_TYPE(HOST_RESOLVER_IMPL_CREATE_JOB) diff --git a/net/dns/dns_client.cc b/net/dns/dns_client.cc new file mode 100644 index 0000000..5381452 --- /dev/null +++ b/net/dns/dns_client.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2012 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/dns/dns_client.h" + +#include "base/bind.h" +#include "base/rand_util.h" +#include "net/base/net_log.h" +#include "net/dns/dns_config_service.h" +#include "net/dns/dns_session.h" +#include "net/dns/dns_transaction.h" +#include "net/socket/client_socket_factory.h" + +namespace net { + +namespace { + +class DnsClientImpl : public DnsClient { + public: + explicit DnsClientImpl(NetLog* net_log) : net_log_(net_log) {} + + virtual void SetConfig(const DnsConfig& config) OVERRIDE { + factory_.reset(); + session_.release(); + if (config.IsValid()) { + session_ = new DnsSession(config, + ClientSocketFactory::GetDefaultFactory(), + base::Bind(&base::RandInt), + net_log_); + factory_ = DnsTransactionFactory::CreateFactory(session_); + } + } + + virtual const DnsConfig* GetConfig() const OVERRIDE { + return session_.get() ? &session_->config() : NULL; + } + + virtual DnsTransactionFactory* GetTransactionFactory() OVERRIDE { + return session_.get() ? factory_.get() : NULL; + } + + private: + scoped_refptr<DnsSession> session_; + scoped_ptr<DnsTransactionFactory> factory_; + + NetLog* net_log_; +}; + +} // namespace + +// static +scoped_ptr<DnsClient> DnsClient::CreateClient(NetLog* net_log) { + return scoped_ptr<DnsClient>(new DnsClientImpl(net_log)); +} + +} // namespace net + diff --git a/net/dns/dns_client.h b/net/dns/dns_client.h new file mode 100644 index 0000000..c5461ec --- /dev/null +++ b/net/dns/dns_client.h @@ -0,0 +1,40 @@ +// Copyright (c) 2012 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. + +#ifndef NET_DNS_DNS_CLIENT_H_ +#define NET_DNS_DNS_CLIENT_H_ +#pragma once + +#include "base/memory/scoped_ptr.h" +#include "net/base/net_export.h" + +namespace net { + +struct DnsConfig; +class DnsTransactionFactory; +class NetLog; + +// Convenience wrapper allows easy injection of DnsTransaction into +// HostResolverImpl. +class NET_EXPORT DnsClient { + public: + virtual ~DnsClient() {} + + // Creates a new DnsTransactionFactory according to the new |config|. + virtual void SetConfig(const DnsConfig& config) = 0; + + // Returns NULL if the current config is not valid. + virtual const DnsConfig* GetConfig() const = 0; + + // Returns NULL if the current config is not valid. + virtual DnsTransactionFactory* GetTransactionFactory() = 0; + + // Creates default client. + static scoped_ptr<DnsClient> CreateClient(NetLog* net_log); +}; + +} // namespace net + +#endif // NET_DNS_DNS_CLIENT_H_ + diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc new file mode 100644 index 0000000..fa1bed1 --- /dev/null +++ b/net/dns/dns_test_util.cc @@ -0,0 +1,166 @@ +// Copyright (c) 2012 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/dns/dns_test_util.h" + +#include <string> + +#include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "base/message_loop.h" +#include "base/sys_byteorder.h" +#include "net/base/big_endian.h" +#include "net/base/dns_util.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/dns/dns_client.h" +#include "net/dns/dns_config_service.h" +#include "net/dns/dns_protocol.h" +#include "net/dns/dns_query.h" +#include "net/dns/dns_response.h" +#include "net/dns/dns_transaction.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { +namespace { + +// A DnsTransaction which responds with loopback to all queries starting with +// "ok", fails synchronously on all queries starting with "er", and NXDOMAIN to +// all others. +class MockTransaction : public DnsTransaction, + public base::SupportsWeakPtr<MockTransaction> { + public: + MockTransaction(const std::string& hostname, + uint16 qtype, + const DnsTransactionFactory::CallbackType& callback) + : hostname_(hostname), + qtype_(qtype), + callback_(callback), + started_(false) { + } + + virtual const std::string& GetHostname() const OVERRIDE { + return hostname_; + } + + virtual uint16 GetType() const OVERRIDE { + return qtype_; + } + + virtual int Start() OVERRIDE { + EXPECT_FALSE(started_); + started_ = true; + if (hostname_.substr(0, 2) == "er") + return ERR_NAME_NOT_RESOLVED; + // Using WeakPtr to cleanly cancel when transaction is destroyed. + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&MockTransaction::Finish, AsWeakPtr())); + return ERR_IO_PENDING; + } + + private: + void Finish() { + if (hostname_.substr(0, 2) == "ok") { + std::string qname; + DNSDomainFromDot(hostname_, &qname); + DnsQuery query(0, qname, qtype_); + + DnsResponse response; + char* buffer = response.io_buffer()->data(); + int nbytes = query.io_buffer()->size(); + memcpy(buffer, query.io_buffer()->data(), nbytes); + + const uint16 kPointerToQueryName = + static_cast<uint16>(0xc000 | sizeof(net::dns_protocol::Header)); + + const uint32 kTTL = 86400; // One day. + + // Size of RDATA which is a IPv4 or IPv6 address. + size_t rdata_size = qtype_ == net::dns_protocol::kTypeA ? + net::kIPv4AddressSize : net::kIPv6AddressSize; + + // 12 is the sum of sizes of the compressed name reference, TYPE, + // CLASS, TTL and RDLENGTH. + size_t answer_size = 12 + rdata_size; + + // Write answer with loopback IP address. + reinterpret_cast<dns_protocol::Header*>(buffer)->ancount = htons(1); + BigEndianWriter writer(buffer + nbytes, answer_size); + writer.WriteU16(kPointerToQueryName); + writer.WriteU16(qtype_); + writer.WriteU16(net::dns_protocol::kClassIN); + writer.WriteU32(kTTL); + writer.WriteU16(rdata_size); + if (qtype_ == net::dns_protocol::kTypeA) { + char kIPv4Loopback[] = { 0x7f, 0, 0, 1 }; + writer.WriteBytes(kIPv4Loopback, sizeof(kIPv4Loopback)); + } else { + char kIPv6Loopback[] = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1 }; + writer.WriteBytes(kIPv6Loopback, sizeof(kIPv6Loopback)); + } + + EXPECT_TRUE(response.InitParse(nbytes + answer_size, query)); + callback_.Run(this, OK, &response); + } else { + callback_.Run(this, ERR_NAME_NOT_RESOLVED, NULL); + } + } + + const std::string hostname_; + const uint16 qtype_; + DnsTransactionFactory::CallbackType callback_; + bool started_; +}; + + +// A DnsTransactionFactory which creates MockTransaction. +class MockTransactionFactory : public DnsTransactionFactory { + public: + MockTransactionFactory() {} + virtual ~MockTransactionFactory() {} + + virtual scoped_ptr<DnsTransaction> CreateTransaction( + const std::string& hostname, + uint16 qtype, + const DnsTransactionFactory::CallbackType& callback, + const BoundNetLog&) OVERRIDE { + return scoped_ptr<DnsTransaction>( + new MockTransaction(hostname, qtype, callback)); + } +}; + +// MockDnsClient provides MockTransactionFactory. +class MockDnsClient : public DnsClient { + public: + explicit MockDnsClient(const DnsConfig& config) : config_(config) {} + virtual ~MockDnsClient() {} + + virtual void SetConfig(const DnsConfig& config) OVERRIDE { + config_ = config; + } + + virtual const DnsConfig* GetConfig() const OVERRIDE { + return config_.IsValid() ? &config_ : NULL; + } + + virtual DnsTransactionFactory* GetTransactionFactory() OVERRIDE { + return config_.IsValid() ? &factory_ : NULL; + } + + private: + DnsConfig config_; + MockTransactionFactory factory_; +}; + +} // namespace + +// static +scoped_ptr<DnsClient> CreateMockDnsClient(const DnsConfig& config) { + return scoped_ptr<DnsClient>(new MockDnsClient(config)); +} + +} // namespace net + diff --git a/net/dns/dns_test_util.h b/net/dns/dns_test_util.h index 8d8c0a6..e247be0 100644 --- a/net/dns/dns_test_util.h +++ b/net/dns/dns_test_util.h @@ -7,6 +7,8 @@ #pragma once #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "net/dns/dns_config_service.h" #include "net/dns/dns_protocol.h" namespace net { @@ -156,6 +158,25 @@ static const char* const kT3IpAddresses[] = { static const char kT3CanonName[] = "www.l.google.com"; static const int kT3TTL = 0x00000015; +class DnsClient; +// Creates mock DnsClient for testing HostResolverImpl. +scoped_ptr<DnsClient> CreateMockDnsClient(const DnsConfig& config); + +class MockDnsConfigService : public DnsConfigService { + public: + virtual ~MockDnsConfigService() {} + + // Expose the protected methods for tests. + void ChangeConfig(const DnsConfig& config) { + DnsConfigService::OnConfigRead(config); + } + + void ChangeHosts(const DnsHosts& hosts) { + DnsConfigService::OnHostsRead(hosts); + } +}; + + } // namespace net #endif // NET_DNS_DNS_TEST_UTIL_H_ diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc index b865457..063c6ea 100644 --- a/net/dns/dns_transaction_unittest.cc +++ b/net/dns/dns_transaction_unittest.cc @@ -202,7 +202,7 @@ class DnsTransactionTest : public testing::Test { config_.nameservers.clear(); IPAddressNumber dns_ip; { - bool rv = ParseIPLiteralToNumber("192.128.1.0", &dns_ip); + bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip); EXPECT_TRUE(rv); } for (unsigned i = 0; i < num_servers; ++i) { diff --git a/net/net.gyp b/net/net.gyp index a850041..a359eea 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -334,6 +334,8 @@ 'disk_cache/stress_support.h', 'disk_cache/trace.cc', 'disk_cache/trace.h', + 'dns/dns_client.cc', + 'dns/dns_client.h', 'dns/dns_config_service.cc', 'dns/dns_config_service.h', 'dns/dns_config_service_posix.cc', @@ -1527,6 +1529,7 @@ 'disk_cache/disk_cache_test_base.h', 'disk_cache/disk_cache_test_util.cc', 'disk_cache/disk_cache_test_util.h', + 'dns/dns_test_util.cc', 'dns/dns_test_util.h', 'proxy/mock_proxy_resolver.cc', 'proxy/mock_proxy_resolver.h', |