Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Unified Diff: net/socket/transport_client_socket_pool_unittest.cc

Issue 7029049: Merge 84251, 85083, 85188, 85375. (Closed) Base URL: svn://svn.chromium.org/chrome/branches/742/src/
Patch Set: Upload before checkin Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/transport_client_socket_pool.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/transport_client_socket_pool_unittest.cc
===================================================================
--- net/socket/transport_client_socket_pool_unittest.cc (revision 85841)
+++ net/socket/transport_client_socket_pool_unittest.cc (working copy)
@@ -6,10 +6,14 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/logging.h"
#include "base/message_loop.h"
#include "base/threading/platform_thread.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/base/sys_addrinfo.h"
#include "net/base/test_completion_callback.h"
#include "net/socket/client_socket.h"
#include "net/socket/client_socket_factory.h"
@@ -29,9 +33,23 @@
const int kMaxSocketsPerGroup = 6;
const net::RequestPriority kDefaultPriority = LOW;
+void SetIPv4Address(IPEndPoint* address) {
+ IPAddressNumber number;
+ CHECK(ParseIPLiteralToNumber("1.1.1.1", &number));
+ *address = IPEndPoint(number, 80);
+}
+
+void SetIPv6Address(IPEndPoint* address) {
+ IPAddressNumber number;
+ CHECK(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number));
+ *address = IPEndPoint(number, 80);
+}
+
class MockClientSocket : public ClientSocket {
public:
- MockClientSocket() : connected_(false) {}
+ MockClientSocket(const AddressList& addrlist)
+ : connected_(false),
+ addrlist_(addrlist) {}
// ClientSocket methods:
virtual int Connect(CompletionCallback* callback) {
@@ -51,7 +69,13 @@
return ERR_UNEXPECTED;
}
virtual int GetLocalAddress(IPEndPoint* address) const {
- return ERR_UNEXPECTED;
+ if (!connected_)
+ return ERR_SOCKET_NOT_CONNECTED;
+ if (addrlist_.head()->ai_family == AF_INET)
+ SetIPv4Address(address);
+ else
+ SetIPv6Address(address);
+ return OK;
}
virtual const BoundNetLog& NetLog() const {
return net_log_;
@@ -76,12 +100,13 @@
private:
bool connected_;
+ const AddressList addrlist_;
BoundNetLog net_log_;
};
class MockFailingClientSocket : public ClientSocket {
public:
- MockFailingClientSocket() {}
+ MockFailingClientSocket(const AddressList& addrlist) : addrlist_(addrlist) {}
// ClientSocket methods:
virtual int Connect(CompletionCallback* callback) {
@@ -125,6 +150,7 @@
virtual bool SetSendBufferSize(int32 size) { return true; }
private:
+ const AddressList addrlist_;
BoundNetLog net_log_;
};
@@ -134,12 +160,17 @@
// or fail.
// |should_stall| indicates that this socket should never connect.
// |delay_ms| is the delay, in milliseconds, before simulating a connect.
- MockPendingClientSocket(bool should_connect, bool should_stall, int delay_ms)
+ MockPendingClientSocket(
+ const AddressList& addrlist,
+ bool should_connect,
+ bool should_stall,
+ int delay_ms)
: method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
should_connect_(should_connect),
should_stall_(should_stall),
delay_ms_(delay_ms),
- is_connected_(false) {}
+ is_connected_(false),
+ addrlist_(addrlist) {}
// ClientSocket methods:
virtual int Connect(CompletionCallback* callback) {
@@ -162,7 +193,13 @@
return ERR_UNEXPECTED;
}
virtual int GetLocalAddress(IPEndPoint* address) const {
- return ERR_UNEXPECTED;
+ if (!is_connected_)
+ return ERR_SOCKET_NOT_CONNECTED;
+ if (addrlist_.head()->ai_family == AF_INET)
+ SetIPv4Address(address);
+ else
+ SetIPv6Address(address);
+ return OK;
}
virtual const BoundNetLog& NetLog() const {
return net_log_;
@@ -205,6 +242,7 @@
bool should_stall_;
int delay_ms_;
bool is_connected_;
+ const AddressList addrlist_;
BoundNetLog net_log_;
};
@@ -224,7 +262,8 @@
MockClientSocketFactory()
: allocation_count_(0), client_socket_type_(MOCK_CLIENT_SOCKET),
client_socket_types_(NULL), client_socket_index_(0),
- client_socket_index_max_(0) {}
+ client_socket_index_max_(0),
+ delay_ms_(ClientSocketPool::kMaxConnectRetryIntervalMs) {}
virtual ClientSocket* CreateTransportClientSocket(
const AddressList& addresses,
@@ -240,21 +279,20 @@
switch (type) {
case MOCK_CLIENT_SOCKET:
- return new MockClientSocket();
+ return new MockClientSocket(addresses);
case MOCK_FAILING_CLIENT_SOCKET:
- return new MockFailingClientSocket();
+ return new MockFailingClientSocket(addresses);
case MOCK_PENDING_CLIENT_SOCKET:
- return new MockPendingClientSocket(true, false, 0);
+ return new MockPendingClientSocket(addresses, true, false, 0);
case MOCK_PENDING_FAILING_CLIENT_SOCKET:
- return new MockPendingClientSocket(false, false, 0);
+ return new MockPendingClientSocket(addresses, false, false, 0);
case MOCK_DELAYED_CLIENT_SOCKET:
- return new MockPendingClientSocket(true, false,
- ClientSocketPool::kMaxConnectRetryIntervalMs);
+ return new MockPendingClientSocket(addresses, true, false, delay_ms_);
case MOCK_STALLED_CLIENT_SOCKET:
- return new MockPendingClientSocket(true, true, 0);
+ return new MockPendingClientSocket(addresses, true, true, 0);
default:
NOTREACHED();
- return new MockClientSocket();
+ return new MockClientSocket(addresses);
}
}
@@ -289,12 +327,15 @@
client_socket_index_max_ = num_types;
}
+ void set_delay_ms(int delay_ms) { delay_ms_ = delay_ms; }
+
private:
int allocation_count_;
ClientSocketType client_socket_type_;
ClientSocketType* client_socket_types_;
int client_socket_index_;
int client_socket_index_max_;
+ int delay_ms_;
};
class TransportClientSocketPoolTest : public testing::Test {
@@ -355,6 +396,89 @@
ClientSocketPoolTest test_base_;
};
+TEST(TransportConnectJobTest, MakeAddrListStartWithIPv4) {
+ IPAddressNumber ip_number;
+ ASSERT_TRUE(ParseIPLiteralToNumber("192.168.1.1", &ip_number));
+ AddressList addrlist_v4_1(ip_number, 80, false);
+ ASSERT_TRUE(ParseIPLiteralToNumber("192.168.1.2", &ip_number));
+ AddressList addrlist_v4_2(ip_number, 80, false);
+ ASSERT_TRUE(ParseIPLiteralToNumber("2001:4860:b006::64", &ip_number));
+ AddressList addrlist_v6_1(ip_number, 80, false);
+ ASSERT_TRUE(ParseIPLiteralToNumber("2001:4860:b006::66", &ip_number));
+ AddressList addrlist_v6_2(ip_number, 80, false);
+
+ AddressList addrlist;
+ const struct addrinfo* ai;
+
+ // Test 1: IPv4 only. Expect no change.
+ addrlist.Copy(addrlist_v4_1.head(), true);
+ addrlist.Append(addrlist_v4_2.head());
+ TransportConnectJob::MakeAddrListStartWithIPv4(&addrlist);
+ ai = addrlist.head();
+ EXPECT_EQ(AF_INET, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET, ai->ai_family);
+ EXPECT_TRUE(ai->ai_next == NULL);
+
+ // Test 2: IPv6 only. Expect no change.
+ addrlist.Copy(addrlist_v6_1.head(), true);
+ addrlist.Append(addrlist_v6_2.head());
+ TransportConnectJob::MakeAddrListStartWithIPv4(&addrlist);
+ ai = addrlist.head();
+ EXPECT_EQ(AF_INET6, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET6, ai->ai_family);
+ EXPECT_TRUE(ai->ai_next == NULL);
+
+ // Test 3: IPv4 then IPv6. Expect no change.
+ addrlist.Copy(addrlist_v4_1.head(), true);
+ addrlist.Append(addrlist_v4_2.head());
+ addrlist.Append(addrlist_v6_1.head());
+ addrlist.Append(addrlist_v6_2.head());
+ TransportConnectJob::MakeAddrListStartWithIPv4(&addrlist);
+ ai = addrlist.head();
+ EXPECT_EQ(AF_INET, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET6, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET6, ai->ai_family);
+ EXPECT_TRUE(ai->ai_next == NULL);
+
+ // Test 4: IPv6, IPv4, IPv6, IPv4. Expect first IPv6 moved to the end.
+ addrlist.Copy(addrlist_v6_1.head(), true);
+ addrlist.Append(addrlist_v4_1.head());
+ addrlist.Append(addrlist_v6_2.head());
+ addrlist.Append(addrlist_v4_2.head());
+ TransportConnectJob::MakeAddrListStartWithIPv4(&addrlist);
+ ai = addrlist.head();
+ EXPECT_EQ(AF_INET, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET6, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET6, ai->ai_family);
+ EXPECT_TRUE(ai->ai_next == NULL);
+
+ // Test 5: IPv6, IPv6, IPv4, IPv4. Expect first two IPv6's moved to the end.
+ addrlist.Copy(addrlist_v6_1.head(), true);
+ addrlist.Append(addrlist_v6_2.head());
+ addrlist.Append(addrlist_v4_1.head());
+ addrlist.Append(addrlist_v4_2.head());
+ TransportConnectJob::MakeAddrListStartWithIPv4(&addrlist);
+ ai = addrlist.head();
+ EXPECT_EQ(AF_INET, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET6, ai->ai_family);
+ ai = ai->ai_next;
+ EXPECT_EQ(AF_INET6, ai->ai_family);
+ EXPECT_TRUE(ai->ai_next == NULL);
+}
+
TEST_F(TransportClientSocketPoolTest, Basic) {
TestCompletionCallback callback;
ClientSocketHandle handle;
@@ -787,7 +911,7 @@
// Wait for the backup socket timer to fire.
base::PlatformThread::Sleep(
- ClientSocketPool::kMaxConnectRetryIntervalMs * 2);
+ ClientSocketPool::kMaxConnectRetryIntervalMs + 50);
// Let the appropriate socket connect.
MessageLoop::current()->RunAllPending();
@@ -935,6 +1059,157 @@
host_resolver_->set_synchronous_mode(false);
}
+// Test the case of the IPv6 address stalling, and falling back to the IPv4
+// socket which finishes first.
+TEST_F(TransportClientSocketPoolTest, IPv6FallbackSocketIPv4FinishesFirst) {
+ // Create a pool without backup jobs.
+ ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
+ TransportClientSocketPool pool(kMaxSockets,
+ kMaxSocketsPerGroup,
+ histograms_.get(),
+ host_resolver_.get(),
+ &client_socket_factory_,
+ NULL);
+
+ MockClientSocketFactory::ClientSocketType case_types[] = {
+ // This is the IPv6 socket.
+ MockClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET,
+ // This is the IPv4 socket.
+ MockClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET
+ };
+
+ client_socket_factory_.set_client_socket_types(case_types, 2);
+
+ // Resolve an AddressList with a IPv6 address first and then a IPv4 address.
+ host_resolver_->rules()->AddIPLiteralRule(
+ "*", "2:abcd::3:4:ff,2.2.2.2", "");
+
+ TestCompletionCallback callback;
+ ClientSocketHandle handle;
+ int rv = handle.Init("a", low_params_, LOW, &callback, &pool, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+ EXPECT_TRUE(handle.is_initialized());
+ EXPECT_TRUE(handle.socket());
+ IPEndPoint endpoint;
+ handle.socket()->GetLocalAddress(&endpoint);
+ EXPECT_EQ(kIPv4AddressSize, endpoint.address().size());
+ EXPECT_EQ(2, client_socket_factory_.allocation_count());
+}
+
+// Test the case of the IPv6 address being slow, thus falling back to trying to
+// connect to the IPv4 address, but having the connect to the IPv6 address
+// finish first.
+TEST_F(TransportClientSocketPoolTest, IPv6FallbackSocketIPv6FinishesFirst) {
+ // Create a pool without backup jobs.
+ ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
+ TransportClientSocketPool pool(kMaxSockets,
+ kMaxSocketsPerGroup,
+ histograms_.get(),
+ host_resolver_.get(),
+ &client_socket_factory_,
+ NULL);
+
+ MockClientSocketFactory::ClientSocketType case_types[] = {
+ // This is the IPv6 socket.
+ MockClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET,
+ // This is the IPv4 socket.
+ MockClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET
+ };
+
+ client_socket_factory_.set_client_socket_types(case_types, 2);
+ client_socket_factory_.set_delay_ms(
+ TransportConnectJob::kIPv6FallbackTimerInMs + 50);
+
+ // Resolve an AddressList with a IPv6 address first and then a IPv4 address.
+ host_resolver_->rules()->AddIPLiteralRule(
+ "*", "2:abcd::3:4:ff,2.2.2.2", "");
+
+ TestCompletionCallback callback;
+ ClientSocketHandle handle;
+ int rv = handle.Init("a", low_params_, LOW, &callback, &pool, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+ EXPECT_TRUE(handle.is_initialized());
+ EXPECT_TRUE(handle.socket());
+ IPEndPoint endpoint;
+ handle.socket()->GetLocalAddress(&endpoint);
+ EXPECT_EQ(kIPv6AddressSize, endpoint.address().size());
+ EXPECT_EQ(2, client_socket_factory_.allocation_count());
+}
+
+TEST_F(TransportClientSocketPoolTest, IPv6NoIPv4AddressesToFallbackTo) {
+ // Create a pool without backup jobs.
+ ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
+ TransportClientSocketPool pool(kMaxSockets,
+ kMaxSocketsPerGroup,
+ histograms_.get(),
+ host_resolver_.get(),
+ &client_socket_factory_,
+ NULL);
+
+ client_socket_factory_.set_client_socket_type(
+ MockClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET);
+
+ // Resolve an AddressList with only IPv6 addresses.
+ host_resolver_->rules()->AddIPLiteralRule(
+ "*", "2:abcd::3:4:ff,3:abcd::3:4:ff", "");
+
+ TestCompletionCallback callback;
+ ClientSocketHandle handle;
+ int rv = handle.Init("a", low_params_, LOW, &callback, &pool, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+ EXPECT_TRUE(handle.is_initialized());
+ EXPECT_TRUE(handle.socket());
+ IPEndPoint endpoint;
+ handle.socket()->GetLocalAddress(&endpoint);
+ EXPECT_EQ(kIPv6AddressSize, endpoint.address().size());
+ EXPECT_EQ(1, client_socket_factory_.allocation_count());
+}
+
+TEST_F(TransportClientSocketPoolTest, IPv4HasNoFallback) {
+ // Create a pool without backup jobs.
+ ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
+ TransportClientSocketPool pool(kMaxSockets,
+ kMaxSocketsPerGroup,
+ histograms_.get(),
+ host_resolver_.get(),
+ &client_socket_factory_,
+ NULL);
+
+ client_socket_factory_.set_client_socket_type(
+ MockClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET);
+
+ // Resolve an AddressList with only IPv4 addresses.
+ host_resolver_->rules()->AddIPLiteralRule(
+ "*", "1.1.1.1", "");
+
+ TestCompletionCallback callback;
+ ClientSocketHandle handle;
+ int rv = handle.Init("a", low_params_, LOW, &callback, &pool, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(handle.is_initialized());
+ EXPECT_FALSE(handle.socket());
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+ EXPECT_TRUE(handle.is_initialized());
+ EXPECT_TRUE(handle.socket());
+ IPEndPoint endpoint;
+ handle.socket()->GetLocalAddress(&endpoint);
+ EXPECT_EQ(kIPv4AddressSize, endpoint.address().size());
+ EXPECT_EQ(1, client_socket_factory_.allocation_count());
+}
+
} // namespace
} // namespace net
« no previous file with comments | « net/socket/transport_client_socket_pool.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698