| Index: net/socket/tcp_socket_unittest.cc
|
| diff --git a/net/socket/tcp_socket_unittest.cc b/net/socket/tcp_socket_unittest.cc
|
| index 15f935516739d3716d9d146fbb0bdbf8cd9ca0ea..5a34d40064fef768daebdec109933e5fc7faf072 100644
|
| --- a/net/socket/tcp_socket_unittest.cc
|
| +++ b/net/socket/tcp_socket_unittest.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "net/socket/tcp_socket.h"
|
|
|
| +#include <stddef.h>
|
| #include <string.h>
|
|
|
| #include <string>
|
| @@ -11,12 +12,15 @@
|
|
|
| #include "base/memory/ref_counted.h"
|
| #include "base/memory/scoped_ptr.h"
|
| +#include "base/test/simple_test_tick_clock.h"
|
| +#include "base/time/time.h"
|
| #include "net/base/address_list.h"
|
| #include "net/base/io_buffer.h"
|
| #include "net/base/ip_endpoint.h"
|
| #include "net/base/ip_endpoint.h"
|
| #include "net/base/net_errors.h"
|
| #include "net/base/sockaddr_storage.h"
|
| +#include "net/base/socket_performance_watcher.h"
|
| #include "net/base/test_completion_callback.h"
|
| #include "net/socket/tcp_client_socket.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| @@ -25,12 +29,42 @@
|
| namespace net {
|
|
|
| namespace {
|
| +
|
| +class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
|
| + public:
|
| + explicit TestSocketPerformanceWatcher(bool should_notify_updated_rtt)
|
| + : should_notify_updated_rtt_(should_notify_updated_rtt),
|
| + connection_changed_count_(0u),
|
| + rtt_notification_count_(0u) {}
|
| + ~TestSocketPerformanceWatcher() override {}
|
| +
|
| + bool ShouldNotifyUpdatedRTT() const override {
|
| + return should_notify_updated_rtt_;
|
| + }
|
| +
|
| + void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) override {
|
| + rtt_notification_count_++;
|
| + }
|
| +
|
| + void OnConnectionChanged() override { connection_changed_count_++; }
|
| +
|
| + size_t rtt_notification_count() const { return rtt_notification_count_; }
|
| +
|
| + size_t connection_changed_count() const { return connection_changed_count_; }
|
| +
|
| + private:
|
| + const bool should_notify_updated_rtt_;
|
| + size_t connection_changed_count_;
|
| + size_t rtt_notification_count_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TestSocketPerformanceWatcher);
|
| +};
|
| +
|
| const int kListenBacklog = 5;
|
|
|
| class TCPSocketTest : public PlatformTest {
|
| protected:
|
| - TCPSocketTest() : socket_(NULL, NetLog::Source()) {
|
| - }
|
| + TCPSocketTest() : socket_(NULL, NULL, NetLog::Source()) {}
|
|
|
| void SetUpListenIPv4() {
|
| ASSERT_EQ(OK, socket_.Open(ADDRESS_FAMILY_IPV4));
|
| @@ -62,8 +96,8 @@ class TCPSocketTest : public PlatformTest {
|
| accept_callback.callback()));
|
|
|
| TestCompletionCallback connect_callback;
|
| - TCPClientSocket connecting_socket(local_address_list(),
|
| - NULL, NetLog::Source());
|
| + TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
|
| + NetLog::Source());
|
| connecting_socket.Connect(connect_callback.callback());
|
|
|
| EXPECT_EQ(OK, connect_callback.WaitForResult());
|
| @@ -75,6 +109,87 @@ class TCPSocketTest : public PlatformTest {
|
| EXPECT_EQ(accepted_address.address(), local_address_.address());
|
| }
|
|
|
| +#if defined(TCP_INFO) || defined(OS_LINUX)
|
| + // Tests that notifications to Socket Performance Watcher (SPW) are delivered
|
| + // correctly. |advance_ticks| is the duration by which the clock is advanced
|
| + // before a message is read. |should_notify_updated_rtt| is true if the SPW
|
| + // is interested in receiving RTT notifications. |num_messages| is the number
|
| + // of messages that are written/read by the sockets.
|
| + // |expect_connection_changed_count| is the expected number of connection
|
| + // change notifications received by the SPW. |expect_rtt_notification_count|
|
| + // is the expected number of RTT notifications received by the SPW.
|
| + // This test works by writing |num_messages| to the socket. A different
|
| + // socket (with a SPW attached to it) reads the messages.
|
| + void TestSPWNotifications(const base::TimeDelta& advance_ticks,
|
| + bool should_notify_updated_rtt,
|
| + size_t num_messages,
|
| + size_t expect_connection_changed_count,
|
| + size_t expect_rtt_notification_count) {
|
| + ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
|
| +
|
| + scoped_ptr<base::SimpleTestTickClock> tick_clock(
|
| + new base::SimpleTestTickClock());
|
| + base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get();
|
| + tick_clock_ptr->SetNowTicks(base::TimeTicks::Now());
|
| +
|
| + TestCompletionCallback connect_callback;
|
| +
|
| + scoped_ptr<TestSocketPerformanceWatcher> watcher(
|
| + new TestSocketPerformanceWatcher(should_notify_updated_rtt));
|
| + TestSocketPerformanceWatcher* watcher_ptr = watcher.get();
|
| +
|
| + TCPSocket connecting_socket(std::move(watcher), NULL, NetLog::Source());
|
| + connecting_socket.SetTickClockForTesting(std::move(tick_clock));
|
| +
|
| + int result = connecting_socket.Open(ADDRESS_FAMILY_IPV4);
|
| + ASSERT_EQ(OK, result);
|
| + connecting_socket.Connect(local_address_, connect_callback.callback());
|
| +
|
| + TestCompletionCallback accept_callback;
|
| + scoped_ptr<TCPSocket> accepted_socket;
|
| + IPEndPoint accepted_address;
|
| + result = socket_.Accept(&accepted_socket, &accepted_address,
|
| + accept_callback.callback());
|
| + ASSERT_EQ(OK, accept_callback.GetResult(result));
|
| +
|
| + ASSERT_TRUE(accepted_socket.get());
|
| +
|
| + // Both sockets should be on the loopback network interface.
|
| + EXPECT_EQ(accepted_address.address(), local_address_.address());
|
| +
|
| + ASSERT_EQ(OK, connect_callback.WaitForResult());
|
| +
|
| + for (size_t i = 0; i < num_messages; ++i) {
|
| + tick_clock_ptr->Advance(advance_ticks);
|
| +
|
| + // Use a 1 byte message so that the watcher is notified at most once per
|
| + // message.
|
| + const std::string message("t");
|
| +
|
| + scoped_refptr<IOBufferWithSize> write_buffer(
|
| + new IOBufferWithSize(message.size()));
|
| + memmove(write_buffer->data(), message.data(), message.size());
|
| +
|
| + TestCompletionCallback write_callback;
|
| + int write_result = accepted_socket->Write(
|
| + write_buffer.get(), write_buffer->size(), write_callback.callback());
|
| +
|
| + scoped_refptr<IOBufferWithSize> read_buffer(
|
| + new IOBufferWithSize(message.size()));
|
| + TestCompletionCallback read_callback;
|
| + int read_result = connecting_socket.Read(
|
| + read_buffer.get(), read_buffer->size(), read_callback.callback());
|
| +
|
| + ASSERT_EQ(1, write_callback.GetResult(write_result));
|
| + ASSERT_EQ(1, read_callback.GetResult(read_result));
|
| + }
|
| + EXPECT_EQ(expect_connection_changed_count,
|
| + watcher_ptr->connection_changed_count());
|
| + EXPECT_EQ(expect_rtt_notification_count,
|
| + watcher_ptr->rtt_notification_count());
|
| + }
|
| +#endif // defined(TCP_INFO) || defined(OS_LINUX)
|
| +
|
| AddressList local_address_list() const {
|
| return AddressList(local_address_);
|
| }
|
| @@ -90,8 +205,8 @@ TEST_F(TCPSocketTest, Accept) {
|
| TestCompletionCallback connect_callback;
|
| // TODO(yzshen): Switch to use TCPSocket when it supports client socket
|
| // operations.
|
| - TCPClientSocket connecting_socket(local_address_list(),
|
| - NULL, NetLog::Source());
|
| + TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
|
| + NetLog::Source());
|
| connecting_socket.Connect(connect_callback.callback());
|
|
|
| TestCompletionCallback accept_callback;
|
| @@ -149,13 +264,13 @@ TEST_F(TCPSocketTest, Accept2Connections) {
|
| accept_callback.callback()));
|
|
|
| TestCompletionCallback connect_callback;
|
| - TCPClientSocket connecting_socket(local_address_list(),
|
| - NULL, NetLog::Source());
|
| + TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
|
| + NetLog::Source());
|
| connecting_socket.Connect(connect_callback.callback());
|
|
|
| TestCompletionCallback connect_callback2;
|
| - TCPClientSocket connecting_socket2(local_address_list(),
|
| - NULL, NetLog::Source());
|
| + TCPClientSocket connecting_socket2(local_address_list(), NULL, NULL,
|
| + NetLog::Source());
|
| connecting_socket2.Connect(connect_callback2.callback());
|
|
|
| EXPECT_EQ(OK, accept_callback.WaitForResult());
|
| @@ -189,8 +304,8 @@ TEST_F(TCPSocketTest, AcceptIPv6) {
|
| return;
|
|
|
| TestCompletionCallback connect_callback;
|
| - TCPClientSocket connecting_socket(local_address_list(),
|
| - NULL, NetLog::Source());
|
| + TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
|
| + NetLog::Source());
|
| connecting_socket.Connect(connect_callback.callback());
|
|
|
| TestCompletionCallback accept_callback;
|
| @@ -214,7 +329,7 @@ TEST_F(TCPSocketTest, ReadWrite) {
|
| ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
|
|
|
| TestCompletionCallback connect_callback;
|
| - TCPSocket connecting_socket(NULL, NetLog::Source());
|
| + TCPSocket connecting_socket(NULL, NULL, NetLog::Source());
|
| int result = connecting_socket.Open(ADDRESS_FAMILY_IPV4);
|
| ASSERT_EQ(OK, result);
|
| connecting_socket.Connect(local_address_, connect_callback.callback());
|
| @@ -270,5 +385,30 @@ TEST_F(TCPSocketTest, ReadWrite) {
|
| ASSERT_EQ(message, received_message);
|
| }
|
|
|
| +// These tests require kernel support for tcp_info struct, and so they are
|
| +// enabled only on certain platforms.
|
| +#if defined(TCP_INFO) || defined(OS_LINUX)
|
| +// If SocketPerformanceWatcher::ShouldNotifyUpdatedRTT always returns false,
|
| +// then the wtatcher should not receive any notifications.
|
| +TEST_F(TCPSocketTest, SPWNotInterested) {
|
| + TestSPWNotifications(base::TimeDelta::FromSeconds(0), false, 2u, 0u, 0u);
|
| +}
|
| +
|
| +// One notification should be received when the socket connects. No additional
|
| +// notifications should be received when the message is read because the clock
|
| +// is not advanced.
|
| +TEST_F(TCPSocketTest, SPWNoAdvance) {
|
| + TestSPWNotifications(base::TimeDelta::FromSeconds(0), true, 2u, 0u, 1u);
|
| +}
|
| +
|
| +// One notification should be received when the socket connects. One
|
| +// additional notification should be received for each message read since this
|
| +// test advances clock by 2 seconds (which is longer than the minimum interval
|
| +// between consecutive notifications) before every read.
|
| +TEST_F(TCPSocketTest, SPWAdvance) {
|
| + TestSPWNotifications(base::TimeDelta::FromSeconds(2), true, 2u, 0u, 3u);
|
| +}
|
| +#endif // defined(TCP_INFO) || defined(OS_LINUX)
|
| +
|
| } // namespace
|
| } // namespace net
|
|
|