summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-18 08:02:08 +0000
committerericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-18 08:02:08 +0000
commit40f153572764e76066588fd2e358d05b8fa453bb (patch)
tree9c8bf3de47da4fac879d1035addf2a6780f163e4
parenta2c2fb9ff48cd37dbed258dca5b40461c92b71a8 (diff)
downloadchromium_src-40f153572764e76066588fd2e358d05b8fa453bb.zip
chromium_src-40f153572764e76066588fd2e358d05b8fa453bb.tar.gz
chromium_src-40f153572764e76066588fd2e358d05b8fa453bb.tar.bz2
Use manually constructed IPv6 socket addresses for tests, rather than system created ones.
The advantage is that GURL's parsing of IPv6 addresses works on all systems, whereas getaddrinfo(ipv6_literal) only succeeds on IPv6 enabled systems. This allows the tests to run consistently on all systems, including our own WinXP buildbots (which do not support IPv6). BUG=http://crbug.com/16452 TEST=[net_unittests] SOCKS5ClientSocketTest.IPv6Domain, SOCKSClientSocketTest.SOCKS4AIfDomainInIPv6 Review URL: http://codereview.chromium.org/155618 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21053 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--DEPS2
-rw-r--r--net/base/address_list.cc19
-rw-r--r--net/base/address_list.h9
-rw-r--r--net/base/host_resolver_impl_unittest.cc7
-rw-r--r--net/base/mock_host_resolver.cc108
-rw-r--r--net/base/mock_host_resolver.h8
-rw-r--r--net/socket/socks5_client_socket_unittest.cc14
-rw-r--r--net/socket/socks_client_socket_unittest.cc2
8 files changed, 126 insertions, 43 deletions
diff --git a/DEPS b/DEPS
index 49be09e..603b9f0 100644
--- a/DEPS
+++ b/DEPS
@@ -13,7 +13,7 @@ deps = {
"/trunk/deps/support@19914",
"src/googleurl":
- "http://google-url.googlecode.com/svn/trunk@109",
+ "http://google-url.googlecode.com/svn/trunk@110",
"src/sdch/open-vcdiff":
"http://open-vcdiff.googlecode.com/svn/trunk@26",
diff --git a/net/base/address_list.cc b/net/base/address_list.cc
index 9fc8d32..7cfab3f 100644
--- a/net/base/address_list.cc
+++ b/net/base/address_list.cc
@@ -127,6 +127,25 @@ void AddressList::Reset() {
data_ = NULL;
}
+// static
+AddressList AddressList::CreateIPv6Address(unsigned char data[16]) {
+ struct addrinfo* ai = new struct addrinfo;
+ memset(ai, 0, sizeof(struct addrinfo));
+
+ ai->ai_family = AF_INET6;
+ ai->ai_socktype = SOCK_STREAM;
+ ai->ai_addrlen = sizeof(sockaddr_in6);
+
+ struct sockaddr_in6* addr6 = new sockaddr_in6;
+ memset(addr6, 0, sizeof(sockaddr_in6));
+
+ ai->ai_addr = reinterpret_cast<sockaddr*>(addr6);
+ addr6->sin6_family = AF_INET6;
+ memcpy(&addr6->sin6_addr, data, 16);
+
+ return AddressList(new Data(ai, false /*is_system_created*/));
+}
+
AddressList::Data::~Data() {
// Call either freeaddrinfo(head), or FreeMyAddrinfo(head), depending who
// created the data.
diff --git a/net/base/address_list.h b/net/base/address_list.h
index 506350b..165086c 100644
--- a/net/base/address_list.h
+++ b/net/base/address_list.h
@@ -15,6 +15,9 @@ namespace net {
// class is designed to be copied around by value.
class AddressList {
public:
+ // Constructs an empty address list.
+ AddressList() {}
+
// Adopt the given addrinfo list in place of the existing one if any. This
// hands over responsibility for freeing the addrinfo list to the AddressList
// object.
@@ -41,6 +44,9 @@ class AddressList {
// empty state as when first constructed.
void Reset();
+ // Used by unit-tests to manually set the TCP socket address.
+ static AddressList CreateIPv6Address(unsigned char data[16]);
+
// Get access to the head of the addrinfo list.
const struct addrinfo* head() const { return data_->head; }
@@ -54,6 +60,9 @@ class AddressList {
// Indicates which free function to use for |head|.
bool is_system_created;
};
+
+ explicit AddressList(Data* data) : data_(data) {}
+
scoped_refptr<Data> data_;
};
diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc
index 0ff345c..350a25d 100644
--- a/net/base/host_resolver_impl_unittest.cc
+++ b/net/base/host_resolver_impl_unittest.cc
@@ -318,7 +318,12 @@ TEST_F(HostResolverImplTest, NumericIPv6Address) {
}
}
-TEST_F(HostResolverImplTest, EmptyHost) {
+// TODO(eroman): This test is disabled because it is bogus. It used to pass
+// solely because of a bug in the RuleBasedHostMapper -- (empty replacements
+// would map to a failure). However when using the actual host resolver
+// (getaddrinfo), this is not necessarily the case. On windows getaddrinfo("")
+// gives you the address of your machine.
+TEST_F(HostResolverImplTest, DISABLED_EmptyHost) {
scoped_refptr<RuleBasedHostResolverProc> resolver_proc =
new RuleBasedHostResolverProc(NULL);
resolver_proc->AllowDirectLookup("*");
diff --git a/net/base/mock_host_resolver.cc b/net/base/mock_host_resolver.cc
index 508ef38..c83f3c8 100644
--- a/net/base/mock_host_resolver.cc
+++ b/net/base/mock_host_resolver.cc
@@ -7,10 +7,36 @@
#include "base/string_util.h"
#include "base/platform_thread.h"
#include "base/ref_counted.h"
+#include "googleurl/src/url_canon_ip.h"
#include "net/base/net_errors.h"
namespace net {
+namespace {
+// Fills |addrlist| with a socket address for |host| which should be an
+// IPv6 literal. Returns OK on success.
+int ResolveIPV6LiteralUsingGURL(const std::string& host,
+ AddressList* addrlist) {
+ // GURL expects the hostname to be surrounded with brackets.
+ std::string host_brackets = "[" + host + "]";
+ url_parse::Component host_comp(0, host_brackets.size());
+
+ // Try parsing the hostname as an IPv6 literal.
+ unsigned char ipv6_addr[16]; // 128 bits.
+ bool ok = url_canon::IPv6AddressToNumber(host_brackets.data(),
+ host_comp,
+ ipv6_addr);
+ if (!ok) {
+ LOG(WARNING) << "Not an IPv6 literal: " << host;
+ return ERR_UNEXPECTED;
+ }
+
+ *addrlist = AddressList::CreateIPv6Address(ipv6_addr);
+ return OK;
+}
+
+} // namespace
+
MockHostResolverBase::MockHostResolverBase(bool use_caching)
: use_caching_(use_caching) {
Reset(NULL);
@@ -71,27 +97,25 @@ void MockHostResolverBase::Reset(HostResolverProc* interceptor) {
//-----------------------------------------------------------------------------
struct RuleBasedHostResolverProc::Rule {
+ enum ResolverType {
+ kResolverTypeFail,
+ kResolverTypeSystem,
+ kResolverTypeIPV6Literal,
+ };
+
+ ResolverType resolver_type;
std::string host_pattern;
std::string replacement;
int latency_ms; // In milliseconds.
- bool direct; // if true, don't mangle hostname and ignore replacement
- Rule(const std::string& host_pattern, const std::string& replacement)
- : host_pattern(host_pattern),
- replacement(replacement),
- latency_ms(0),
- direct(false) {}
- Rule(const std::string& host_pattern, const std::string& replacement,
- const int latency_ms)
- : host_pattern(host_pattern),
- replacement(replacement),
- latency_ms(latency_ms),
- direct(false) {}
- Rule(const std::string& host_pattern, const std::string& replacement,
- const bool direct)
- : host_pattern(host_pattern),
+
+ Rule(ResolverType resolver_type,
+ const std::string& host_pattern,
+ const std::string& replacement,
+ int latency_ms)
+ : resolver_type(resolver_type),
+ host_pattern(host_pattern),
replacement(replacement),
- latency_ms(0),
- direct(direct) {}
+ latency_ms(latency_ms) {}
};
RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
@@ -103,21 +127,36 @@ RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
const std::string& replacement) {
- rules_.push_back(Rule(host_pattern, replacement));
+ DCHECK(!replacement.empty());
+ Rule rule(Rule::kResolverTypeSystem, host_pattern, replacement, 0);
+ rules_.push_back(rule);
+}
+
+void RuleBasedHostResolverProc::AddIPv6Rule(const std::string& host_pattern,
+ const std::string& ipv6_literal) {
+ Rule rule(Rule::kResolverTypeIPV6Literal, host_pattern, ipv6_literal, 0);
+ rules_.push_back(rule);
}
void RuleBasedHostResolverProc::AddRuleWithLatency(
const std::string& host_pattern,
- const std::string& replacement, int latency_ms) {
- rules_.push_back(Rule(host_pattern, replacement, latency_ms));
+ const std::string& replacement,
+ int latency_ms) {
+ DCHECK(!replacement.empty());
+ Rule rule(Rule::kResolverTypeSystem, host_pattern, replacement, latency_ms);
+ rules_.push_back(rule);
}
-void RuleBasedHostResolverProc::AllowDirectLookup(const std::string& host) {
- rules_.push_back(Rule(host, "", true));
+void RuleBasedHostResolverProc::AllowDirectLookup(
+ const std::string& host_pattern) {
+ Rule rule(Rule::kResolverTypeSystem, host_pattern, "", 0);
+ rules_.push_back(rule);
}
-void RuleBasedHostResolverProc::AddSimulatedFailure(const std::string& host) {
- AddRule(host, "");
+void RuleBasedHostResolverProc::AddSimulatedFailure(
+ const std::string& host_pattern) {
+ Rule rule(Rule::kResolverTypeFail, host_pattern, "", 0);
+ rules_.push_back(rule);
}
int RuleBasedHostResolverProc::Resolve(const std::string& host,
@@ -130,10 +169,23 @@ int RuleBasedHostResolverProc::Resolve(const std::string& host,
// Hmm, this seems unecessary.
r->latency_ms = 1;
}
- const std::string& effective_host = r->direct ? host : r->replacement;
- if (effective_host.empty())
- return ERR_NAME_NOT_RESOLVED;
- return SystemHostResolverProc(effective_host, addrlist);
+
+ // Remap to a new host.
+ const std::string& effective_host =
+ r->replacement.empty() ? host : r->replacement;
+
+ // Apply the resolving function to the remapped hostname.
+ switch (r->resolver_type) {
+ case Rule::kResolverTypeFail:
+ return ERR_NAME_NOT_RESOLVED;
+ case Rule::kResolverTypeSystem:
+ return SystemHostResolverProc(effective_host, addrlist);
+ case Rule::kResolverTypeIPV6Literal:
+ return ResolveIPV6LiteralUsingGURL(effective_host, addrlist);
+ default:
+ NOTREACHED();
+ return ERR_UNEXPECTED;
+ }
}
}
return ResolveUsingPrevious(host, addrlist);
diff --git a/net/base/mock_host_resolver.h b/net/base/mock_host_resolver.h
index 1d29684..413bd36 100644
--- a/net/base/mock_host_resolver.h
+++ b/net/base/mock_host_resolver.h
@@ -98,6 +98,13 @@ class RuleBasedHostResolverProc : public HostResolverProc {
void AddRule(const std::string& host_pattern,
const std::string& replacement);
+ // Same as AddRule(), but the replacement is expected to be an IPV6 literal.
+ // You should use this in place of AddRule(), since the system's host resolver
+ // may not support IPv6 literals on all systems. Whereas this variant
+ // constructs the socket address directly so it will always work.
+ void AddIPv6Rule(const std::string& host_pattern,
+ const std::string& ipv6_literal);
+
void AddRuleWithLatency(const std::string& host_pattern,
const std::string& replacement,
int latency_ms);
@@ -115,6 +122,7 @@ class RuleBasedHostResolverProc : public HostResolverProc {
private:
struct Rule;
typedef std::list<Rule> RuleList;
+
RuleList rules_;
};
diff --git a/net/socket/socks5_client_socket_unittest.cc b/net/socket/socks5_client_socket_unittest.cc
index b225887..33b3fa3 100644
--- a/net/socket/socks5_client_socket_unittest.cc
+++ b/net/socket/socks5_client_socket_unittest.cc
@@ -179,17 +179,7 @@ TEST_F(SOCKS5ClientSocketTest, IPv6Domain) {
const uint8 ipv6_addr[] = { 0x20, 0x01, 0x0d, 0xb8, 0x87, 0x14, 0x3a, 0x90,
0x00, 0x00, 0x00, 0x00, 0x00, 0x000, 0x00, 0x12 };
- host_resolver_->rules()->AddRule(hostname, "2001:db8:8714:3a90::12");
-
- AddressList address_list;
- HostResolver::RequestInfo info(hostname, 80);
- int rv = host_resolver_->Resolve(info, &address_list, NULL, NULL);
- if (rv != OK || !address_list.head()) {
- // This machine does not support IPv6. We skip this test altogether.
- // TODO(arindam): create a MockIPv6HostResolver to manually
- // populate the |address_list| in case of a machine with no IPv6 suppport.
- return;
- }
+ host_resolver_->rules()->AddIPv6Rule(hostname, "2001:db8:8714:3a90::12");
std::string request(kSOCKS5IPv6Request,
arraysize(kSOCKS5IPv6Request));
@@ -205,7 +195,7 @@ TEST_F(SOCKS5ClientSocketTest, IPv6Domain) {
user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80));
- rv = user_sock_->Connect(&callback_);
+ int rv = user_sock_->Connect(&callback_);
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback_.WaitForResult();
EXPECT_EQ(OK, rv);
diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc
index 3d7fa85..32eb725 100644
--- a/net/socket/socks_client_socket_unittest.cc
+++ b/net/socket/socks_client_socket_unittest.cc
@@ -253,7 +253,7 @@ TEST_F(SOCKSClientSocketTest, SOCKS4AFailedDNS) {
TEST_F(SOCKSClientSocketTest, SOCKS4AIfDomainInIPv6) {
const char hostname[] = "an.ipv6.address";
- host_resolver_->rules()->AddRule(hostname, "2001:db8:8714:3a90::12");
+ host_resolver_->rules()->AddIPv6Rule(hostname, "2001:db8:8714:3a90::12");
std::string request(kSOCKS4aInitialRequest,
arraysize(kSOCKS4aInitialRequest));