diff options
author | darin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-24 06:31:34 +0000 |
---|---|---|
committer | darin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-24 06:31:34 +0000 |
commit | 025517044b4be3ab45efc2f383e5a7b830aa7281 (patch) | |
tree | b43566625f0702e8fa44590a7a82b3c41b56b5cc /net | |
parent | 8943d1c09b155984790847a849e816ffe695a91a (diff) | |
download | chromium_src-025517044b4be3ab45efc2f383e5a7b830aa7281.zip chromium_src-025517044b4be3ab45efc2f383e5a7b830aa7281.tar.gz chromium_src-025517044b4be3ab45efc2f383e5a7b830aa7281.tar.bz2 |
Add support for mock DNS queries. This allows us to eliminate
flaky DNS queries from the unit tests.
Note: some unit tests still connect to www.google.com. My plan
is to resolve those in a subsequent CL.
R=wtc
BUG=2635
Review URL: http://codereview.chromium.org/4022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2545 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/host_resolver.cc | 24 | ||||
-rw-r--r-- | net/base/host_resolver.h | 24 | ||||
-rw-r--r-- | net/base/host_resolver_unittest.h | 86 | ||||
-rw-r--r-- | net/base/run_all_unittests.cc | 6 | ||||
-rw-r--r-- | net/base/tcp_client_socket_unittest.cc | 9 | ||||
-rw-r--r-- | net/http/http_network_layer_unittest.cc | 9 |
6 files changed, 155 insertions, 3 deletions
diff --git a/net/base/host_resolver.cc b/net/base/host_resolver.cc index ab706b3..d3b054f 100644 --- a/net/base/host_resolver.cc +++ b/net/base/host_resolver.cc @@ -26,8 +26,15 @@ namespace net { //----------------------------------------------------------------------------- -static int ResolveAddrInfo(const std::string& host, const std::string& port, - struct addrinfo** results) { +static HostMapper* host_mapper; + +HostMapper* SetHostMapper(HostMapper* value) { + std::swap(host_mapper, value); + return value; +} + +static int HostResolverProc( + const std::string& host, const std::string& port, struct addrinfo** out) { struct addrinfo hints = {0}; hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; @@ -35,10 +42,21 @@ static int ResolveAddrInfo(const std::string& host, const std::string& port, // Restrict result set to only this socket type to avoid duplicates. hints.ai_socktype = SOCK_STREAM; - int err = getaddrinfo(host.c_str(), port.c_str(), &hints, results); + int err = getaddrinfo(host.c_str(), port.c_str(), &hints, out); return err ? ERR_NAME_NOT_RESOLVED : OK; } +static int ResolveAddrInfo( + const std::string& host, const std::string& port, struct addrinfo** out) { + int rv; + if (host_mapper) { + rv = HostResolverProc(host_mapper->Map(host), port, out); + } else { + rv = HostResolverProc(host, port, out); + } + return rv; +} + //----------------------------------------------------------------------------- class HostResolver::Request : diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h index 5364d17..1f649f8 100644 --- a/net/base/host_resolver.h +++ b/net/base/host_resolver.h @@ -55,6 +55,30 @@ class HostResolver { DISALLOW_COPY_AND_ASSIGN(HostResolver); }; +// A helper class used in unit tests to alter hostname mappings. See +// SetHostMapper for details. +class HostMapper { + public: + virtual ~HostMapper() {} + virtual std::string Map(const std::string& host) = 0; +}; + +#ifdef UNIT_TEST +// This function is designed to allow unit tests to override the behavior of +// HostResolver. For example, a HostMapper instance can force all hostnames +// to map to a fixed IP address such as 127.0.0.1. +// +// The previously set HostMapper (or NULL if there was none) is returned. +// +// NOTE: This function is not thread-safe, so take care to only call this +// function while there are no outstanding HostResolver instances. +// +// NOTE: In most cases, you should use ScopedHostMapper instead, which is +// defined in host_resolver_unittest.h +// +HostMapper* SetHostMapper(HostMapper* host_mapper); +#endif + } // namespace net #endif // NET_BASE_HOST_RESOLVER_H_ diff --git a/net/base/host_resolver_unittest.h b/net/base/host_resolver_unittest.h new file mode 100644 index 0000000..c7ecea81 --- /dev/null +++ b/net/base/host_resolver_unittest.h @@ -0,0 +1,86 @@ +// 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. + +// This file defines ScopedHostMapper, which is a helper class for writing +// tests that use HostResolver either directly or indirectly. +// +// In most cases, it is important that unit tests avoid making actual DNS +// queries since the resulting tests can be flaky, especially if the network is +// unreliable for some reason. To simplify writing tests that avoid making +// actual DNS queries, the following helper class may be used: +// +// ScopedHostMapper scoped_host_mapper; +// scoped_host_mapper.AddRule("foo.com", "1.2.3.4"); +// scoped_host_mapper.AddRule("bar.com", "2.3.4.5"); +// ... +// +// The above rules define a static mapping from hostnames to IP address +// literals. The first parameter to AddRule specifies a host pattern to match +// against, and the second parameter indicates what value should be used to +// replace the given hostname. So, the following is also supported: +// +// scoped_host_mapper.AddRule("*.com", "127.0.0.1"); +// +// If there are multiple ScopedHostMappers on the stack, then the last one +// allocated will be used. However, if it does not provide a matching rule, +// then it will delegate to the previously allocated ScopedHostMapper. +// Finally, if no HostMapper matches a given hostname, then the hostname will +// be unmodified. + +#ifndef NET_BASE_HOST_RESOLVER_UNITTEST_H_ +#define NET_BASE_HOST_RESOLVER_UNITTEST_H_ + +#ifdef UNIT_TEST + +#include <list> + +#include "base/string_util.h" +#include "net/base/host_resolver.h" +#include "net/base/net_errors.h" + +namespace net { + +// This class sets the HostResolverProc for a particular scope. +class ScopedHostMapper : public HostMapper { + public: + ScopedHostMapper() { + previous_host_mapper_ = SetHostMapper(this); + } + + ~ScopedHostMapper() { + SetHostMapper(previous_host_mapper_); + } + + // Any hostname matching the given pattern will be replaced with the given + // replacement value. Usually, replacement should be an IP address literal. + void AddRule(const char* host_pattern, const char* replacement) { + rules_.push_back(Rule(host_pattern, replacement)); + } + + private: + std::string Map(const std::string& host) { + RuleList::const_iterator r; + for (r = rules_.begin(); r != rules_.end(); ++r) { + if (MatchPattern(host, r->host_pattern)) + return r->replacement; + } + return previous_host_mapper_ ? previous_host_mapper_->Map(host) : host; + } + + struct Rule { + std::string host_pattern; + std::string replacement; + Rule(const char* h, const char* r) : host_pattern(h), replacement(r) {} + }; + typedef std::list<Rule> RuleList; + + HostMapper* previous_host_mapper_; + RuleList rules_; +}; + +} // namespace net + +#endif // UNIT_TEST + +#endif // NET_BASE_HOST_RESOLVER_UNITTEST_H_ diff --git a/net/base/run_all_unittests.cc b/net/base/run_all_unittests.cc index f5c1419b..de79e68 100644 --- a/net/base/run_all_unittests.cc +++ b/net/base/run_all_unittests.cc @@ -29,10 +29,15 @@ #include "base/message_loop.h" #include "base/test_suite.h" +#include "net/base/host_resolver_unittest.h" class NetTestSuite : public TestSuite { public: NetTestSuite(int argc, char** argv) : TestSuite(argc, argv) { + // In case any attempts are made to resolve host names, force them all to + // be mapped to localhost. This prevents DNS queries from being sent in + // the process of running these unit tests. + host_mapper_.AddRule("*", "127.0.0.1"); } virtual void Initialize() { @@ -51,6 +56,7 @@ class NetTestSuite : public TestSuite { private: scoped_ptr<MessageLoop> message_loop_; + net::ScopedHostMapper host_mapper_; }; int main(int argc, char** argv) { diff --git a/net/base/tcp_client_socket_unittest.cc b/net/base/tcp_client_socket_unittest.cc index 062a9b9..34c0940 100644 --- a/net/base/tcp_client_socket_unittest.cc +++ b/net/base/tcp_client_socket_unittest.cc @@ -5,12 +5,21 @@ #include "base/platform_test.h" #include "net/base/address_list.h" #include "net/base/host_resolver.h" +#include "net/base/host_resolver_unittest.h" #include "net/base/net_errors.h" #include "net/base/tcp_client_socket.h" #include "net/base/test_completion_callback.h" #include "testing/gtest/include/gtest/gtest.h" class TCPClientSocketTest : public PlatformTest { + public: + TCPClientSocketTest() { + // TODO(darin): kill this exception once we have a way to test out the + // TCPClientSocket class using loopback connections. + host_mapper_.AddRule("www.google.com", "www.google.com"); + } + private: + net::ScopedHostMapper host_mapper_; }; diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc index ab59edc..316c91d 100644 --- a/net/http/http_network_layer_unittest.cc +++ b/net/http/http_network_layer_unittest.cc @@ -2,6 +2,7 @@ // 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_unittest.h" #include "net/http/http_network_layer.h" #include "net/http/http_transaction_unittest.h" #include "testing/gtest/include/gtest/gtest.h" @@ -9,6 +10,14 @@ namespace { class HttpNetworkLayerTest : public testing::Test { + public: + HttpNetworkLayerTest() { + // TODO(darin): kill this exception once we have a way to test out the + // HttpNetworkLayer class using loopback connections. + host_mapper_.AddRule("www.google.com", "www.google.com"); + } + private: + net::ScopedHostMapper host_mapper_; }; } // namespace |