diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-23 02:06:54 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-23 02:06:54 +0000 |
commit | c7a132fad4caf6b7389e5ccbb7c4ca5ed0bb1a54 (patch) | |
tree | add1bf99e82fc25c6177b84ce928ce0fb363a336 /content | |
parent | bdecc3ed22954279b41659121aa69ec29589a46d (diff) | |
download | chromium_src-c7a132fad4caf6b7389e5ccbb7c4ca5ed0bb1a54.zip chromium_src-c7a132fad4caf6b7389e5ccbb7c4ca5ed0bb1a54.tar.gz chromium_src-c7a132fad4caf6b7389e5ccbb7c4ca5ed0bb1a54.tar.bz2 |
Unittests for P2P TCP Sockets Host.
BUG=None
TEST=Unittests
Review URL: http://codereview.chromium.org/6883054
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82771 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
7 files changed, 593 insertions, 85 deletions
diff --git a/content/browser/renderer_host/p2p/socket_host.h b/content/browser/renderer_host/p2p/socket_host.h index 76699d5..b78a7f9 100644 --- a/content/browser/renderer_host/p2p/socket_host.h +++ b/content/browser/renderer_host/p2p/socket_host.h @@ -31,6 +31,8 @@ class P2PSocketHost { const net::IPEndPoint& remote_address, int id) = 0; protected: + friend class P2PSocketHostTcpTest; + enum StunMessageType { STUN_BINDING_REQUEST = 0x0001, STUN_BINDING_RESPONSE = 0x0101, diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.h b/content/browser/renderer_host/p2p/socket_host_tcp.h index 917e622..01a9861 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp.h +++ b/content/browser/renderer_host/p2p/socket_host_tcp.h @@ -38,6 +38,9 @@ class P2PSocketHostTcp : public P2PSocketHost { const net::IPEndPoint& remote_address, int id) OVERRIDE; private: + friend class P2PSocketHostTcpTest; + friend class P2PSocketHostTcpServerTest; + void OnError(); void DoRead(); diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_server.h b/content/browser/renderer_host/p2p/socket_host_tcp_server.h index d0b7268..7bafa76 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp_server.h +++ b/content/browser/renderer_host/p2p/socket_host_tcp_server.h @@ -21,7 +21,7 @@ class ClientSocket; class P2PSocketHostTcpServer : public P2PSocketHost { public: P2PSocketHostTcpServer(IPC::Message::Sender* message_sender, - int routing_id, int id); + int routing_id, int id); virtual ~P2PSocketHostTcpServer(); // P2PSocketHost overrides. @@ -33,6 +33,8 @@ class P2PSocketHostTcpServer : public P2PSocketHost { const net::IPEndPoint& remote_address, int id) OVERRIDE; private: + friend class P2PSocketHostTcpServerTest; + typedef std::map<net::IPEndPoint, net::ClientSocket*> AcceptedSocketsMap; void OnError(); @@ -43,7 +45,7 @@ class P2PSocketHostTcpServer : public P2PSocketHost { // Callback for Accept(). void OnAccepted(int result); - scoped_ptr<net::TCPServerSocket> socket_; + scoped_ptr<net::ServerSocket> socket_; net::IPEndPoint local_address_; scoped_ptr<net::ClientSocket> accept_socket_; diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc b/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc new file mode 100644 index 0000000..e8eb51a --- /dev/null +++ b/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc @@ -0,0 +1,161 @@ +// Copyright (c) 2011 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 "content/browser/renderer_host/p2p/socket_host_tcp_server.h" + +#include "content/browser/renderer_host/p2p/socket_host_tcp.h" +#include "content/browser/renderer_host/p2p/socket_host_test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::DeleteArg; +using ::testing::DoAll; +using ::testing::Return; + +namespace { + +class FakeServerSocket : public net::ServerSocket { + public: + FakeServerSocket() + : listening_(false), + accept_socket_(NULL), + accept_callback_(NULL) { + } + + ~FakeServerSocket() { } + + bool listening() { return listening_; } + + void AddIncoming(net::ClientSocket* socket) { + if (accept_callback_) { + DCHECK(incoming_sockets_.empty()); + accept_socket_->reset(socket); + accept_socket_ = NULL; + net::CompletionCallback* cb = accept_callback_; + accept_callback_ = NULL; + cb->Run(net::OK); + } else { + incoming_sockets_.push_back(socket); + } + } + + // net::ServerSocket implementation. + virtual int Listen(const net::IPEndPoint& address, int backlog) OVERRIDE { + local_address_ = address; + listening_ = true; + return net::OK; + } + + virtual int GetLocalAddress(net::IPEndPoint* address) const OVERRIDE { + *address = local_address_; + return net::OK; + } + + virtual int Accept(scoped_ptr<net::ClientSocket>* socket, + net::CompletionCallback* callback) OVERRIDE { + DCHECK(socket); + if (!incoming_sockets_.empty()) { + socket->reset(incoming_sockets_.front()); + incoming_sockets_.pop_front(); + return net::OK; + } else { + accept_socket_ = socket; + accept_callback_ = callback; + return net::ERR_IO_PENDING; + } + } + + private: + bool listening_; + + net::IPEndPoint local_address_; + + scoped_ptr<net::ClientSocket>* accept_socket_; + net::CompletionCallback* accept_callback_; + + std::list<net::ClientSocket*> incoming_sockets_; +}; + +} // namespace + +class P2PSocketHostTcpServerTest : public testing::Test { + protected: + virtual void SetUp() OVERRIDE { + socket_ = new FakeServerSocket(); + socket_host_.reset(new P2PSocketHostTcpServer(&sender_, 0, 0)); + socket_host_->socket_.reset(socket_); + + EXPECT_CALL(sender_, Send( + MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID)))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + + socket_host_->Init(ParseAddress(kTestLocalIpAddress, 0), + ParseAddress(kTestIpAddress1, kTestPort1)); + EXPECT_TRUE(socket_->listening()); + } + + // Needed by the chilt classes because only this class is a friend + // of P2PSocketHostTcp. + net::ClientSocket* GetSocketFormTcpSocketHost(P2PSocketHostTcp* host) { + return host->socket_.get(); + } + + MockIPCSender sender_; + FakeServerSocket* socket_; // Owned by |socket_host_|. + scoped_ptr<P2PSocketHostTcpServer> socket_host_; +}; + +// Accept incoming connection. +TEST_F(P2PSocketHostTcpServerTest, Accept) { + FakeSocket* incoming = new FakeSocket(NULL); + incoming->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1)); + net::IPEndPoint addr = ParseAddress(kTestIpAddress1, kTestPort1); + incoming->SetPeerAddress(addr); + + EXPECT_CALL(sender_, Send(MatchIncomingSocketMessage(addr))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + socket_->AddIncoming(incoming); + + const int kAcceptedSocketId = 1; + + scoped_ptr<P2PSocketHost> new_host( + socket_host_->AcceptIncomingTcpConnection(addr, kAcceptedSocketId)); + ASSERT_TRUE(new_host.get() != NULL); + EXPECT_EQ(incoming, GetSocketFormTcpSocketHost( + reinterpret_cast<P2PSocketHostTcp*>(new_host.get()))); +} + +// Accept 2 simultaneous connections. +TEST_F(P2PSocketHostTcpServerTest, Accept2) { + FakeSocket* incoming1 = new FakeSocket(NULL); + incoming1->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1)); + net::IPEndPoint addr1 = ParseAddress(kTestIpAddress1, kTestPort1); + incoming1->SetPeerAddress(addr1); + FakeSocket* incoming2 = new FakeSocket(NULL); + incoming2->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1)); + net::IPEndPoint addr2 = ParseAddress(kTestIpAddress2, kTestPort2); + incoming2->SetPeerAddress(addr2); + + EXPECT_CALL(sender_, Send(MatchIncomingSocketMessage(addr1))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + EXPECT_CALL(sender_, Send(MatchIncomingSocketMessage(addr2))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + socket_->AddIncoming(incoming1); + socket_->AddIncoming(incoming2); + + const int kAcceptedSocketId1 = 1; + const int kAcceptedSocketId2 = 2; + + scoped_ptr<P2PSocketHost> new_host1( + socket_host_->AcceptIncomingTcpConnection(addr1, kAcceptedSocketId1)); + ASSERT_TRUE(new_host1.get() != NULL); + EXPECT_EQ(incoming1, GetSocketFormTcpSocketHost( + reinterpret_cast<P2PSocketHostTcp*>(new_host1.get()))); + scoped_ptr<P2PSocketHost> new_host2( + socket_host_->AcceptIncomingTcpConnection(addr2, kAcceptedSocketId2)); + ASSERT_TRUE(new_host2.get() != NULL); + EXPECT_EQ(incoming2, GetSocketFormTcpSocketHost( + reinterpret_cast<P2PSocketHostTcp*>(new_host2.get()))); +} diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc new file mode 100644 index 0000000..af118f1 --- /dev/null +++ b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc @@ -0,0 +1,167 @@ +// Copyright (c) 2011 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 "content/browser/renderer_host/p2p/socket_host_tcp.h" + +#include <deque> + +#include "content/browser/renderer_host/p2p/socket_host_test_utils.h" +#include "net/base/sys_byteorder.h" +#include "net/socket/client_socket.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::DeleteArg; +using ::testing::DoAll; +using ::testing::Return; + +class P2PSocketHostTcpTest : public testing::Test { + protected: + virtual void SetUp() OVERRIDE { + EXPECT_CALL(sender_, Send( + MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID)))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + + socket_host_.reset(new P2PSocketHostTcp(&sender_, 0, 0)); + socket_ = new FakeSocket(&sent_data_); + socket_->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1)); + socket_host_->socket_.reset(socket_); + + dest_ = ParseAddress(kTestIpAddress1, kTestPort1); + + local_address_ = ParseAddress(kTestLocalIpAddress, kTestPort1); + + socket_host_->remote_address_ = dest_; + socket_host_->state_ = P2PSocketHost::STATE_CONNECTING; + socket_host_->OnConnected(net::OK); + } + + std::string IntToSize(int size) { + std::string result; + uint16 size16 = htons(size); + result.resize(sizeof(size16)); + memcpy(&result[0], &size16, sizeof(size16)); + return result; + } + + std::string sent_data_; + FakeSocket* socket_; // Owned by |socket_host_|. + scoped_ptr<P2PSocketHostTcp> socket_host_; + MockIPCSender sender_; + + net::IPEndPoint local_address_; + + net::IPEndPoint dest_; + net::IPEndPoint dest2_; +}; + +// Verify that we can send STUN message and that they are formatted +// properly. +TEST_F(P2PSocketHostTcpTest, SendStunNoAuth) { + std::vector<char> packet1; + CreateStunRequest(&packet1); + socket_host_->Send(dest_, packet1); + + std::vector<char> packet2; + CreateStunResponse(&packet2); + socket_host_->Send(dest_, packet2); + + std::vector<char> packet3; + CreateStunError(&packet3); + socket_host_->Send(dest_, packet3); + + std::string expected_data; + expected_data.append(IntToSize(packet1.size())); + expected_data.append(packet1.begin(), packet1.end()); + expected_data.append(IntToSize(packet2.size())); + expected_data.append(packet2.begin(), packet2.end()); + expected_data.append(IntToSize(packet3.size())); + expected_data.append(packet3.begin(), packet3.end()); + + EXPECT_EQ(expected_data, sent_data_); +} + +// Verify that we can receive STUN messages from the socket, and that +// the messages are parsed properly. +TEST_F(P2PSocketHostTcpTest, ReceiveStun) { + std::vector<char> packet1; + CreateStunRequest(&packet1); + socket_host_->Send(dest_, packet1); + + std::vector<char> packet2; + CreateStunResponse(&packet2); + socket_host_->Send(dest_, packet2); + + std::vector<char> packet3; + CreateStunError(&packet3); + socket_host_->Send(dest_, packet3); + + std::string received_data; + received_data.append(IntToSize(packet1.size())); + received_data.append(packet1.begin(), packet1.end()); + received_data.append(IntToSize(packet2.size())); + received_data.append(packet2.begin(), packet2.end()); + received_data.append(IntToSize(packet3.size())); + received_data.append(packet3.begin(), packet3.end()); + + EXPECT_CALL(sender_, Send(MatchPacketMessage(packet1))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + EXPECT_CALL(sender_, Send(MatchPacketMessage(packet2))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + EXPECT_CALL(sender_, Send(MatchPacketMessage(packet3))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + + size_t pos = 0; + size_t step_sizes[] = {3, 2, 1}; + size_t step = 0; + while (pos < received_data.size()) { + size_t step_size = std::min(step_sizes[step], received_data.size() - pos); + socket_->AppendInputData(&received_data[pos], step_size); + pos += step_size; + if (++step >= arraysize(step_sizes)) + step = 0; + } +} + +// Verify that we can't send data before we've received STUN response +// from the other side. +TEST_F(P2PSocketHostTcpTest, SendDataNoAuth) { + EXPECT_CALL(sender_, Send( + MatchMessage(static_cast<uint32>(P2PMsg_OnError::ID)))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + + std::vector<char> packet; + CreateRandomPacket(&packet); + socket_host_->Send(dest_, packet); + + EXPECT_EQ(0U, sent_data_.size()); +} + +// Verify that we can send data after we've received STUN response +// from the other side. +TEST_F(P2PSocketHostTcpTest, SendAfterStunRequest) { + // Receive packet from |dest_|. + std::vector<char> request_packet; + CreateStunRequest(&request_packet); + + std::string received_data; + received_data.append(IntToSize(request_packet.size())); + received_data.append(request_packet.begin(), request_packet.end()); + + EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); + socket_->AppendInputData(&received_data[0], received_data.size()); + + // Now we should be able to send any data to |dest_|. + std::vector<char> packet; + CreateRandomPacket(&packet); + socket_host_->Send(dest_, packet); + + std::string expected_data; + expected_data.append(IntToSize(packet.size())); + expected_data.append(packet.begin(), packet.end()); + + EXPECT_EQ(expected_data, sent_data_); +} diff --git a/content/browser/renderer_host/p2p/socket_host_test_utils.h b/content/browser/renderer_host/p2p/socket_host_test_utils.h new file mode 100644 index 0000000..1db590c --- /dev/null +++ b/content/browser/renderer_host/p2p/socket_host_test_utils.h @@ -0,0 +1,240 @@ +// Copyright (c) 2011 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 CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TEST_UTILS_H_ +#define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TEST_UTILS_H_ + +#include <vector> + +#include "content/common/p2p_messages.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_message_utils.h" +#include "net/base/address_list.h" +#include "net/base/completion_callback.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/base/sys_byteorder.h" +#include "net/socket/client_socket.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const char kTestLocalIpAddress[] = "123.44.22.4"; +const char kTestIpAddress1[] = "123.44.22.31"; +const int kTestPort1 = 234; +const char kTestIpAddress2[] = "133.11.22.33"; +const int kTestPort2 = 543; + +const int kStunHeaderSize = 20; +const uint16 kStunBindingRequest = 0x0001; +const uint16 kStunBindingResponse = 0x0102; +const uint16 kStunBindingError = 0x0111; +const uint32 kStunMagicCookie = 0x2112A442; + +class MockIPCSender : public IPC::Message::Sender { + public: + MOCK_METHOD1(Send, bool(IPC::Message* msg)); +}; + +class FakeSocket : public net::ClientSocket { + public: + FakeSocket(std::string* written_data) + : read_pending_(false), + written_data_(written_data), + input_pos_(0) { + } + virtual ~FakeSocket() { } + + void AppendInputData(const char* data, int data_size) { + input_data_.insert(input_data_.end(), data, data + data_size); + // Complete pending read if any. + if (read_pending_) { + read_pending_ = false; + int result = std::min(read_buffer_size_, + static_cast<int>(input_data_.size() - input_pos_)); + CHECK(result > 0); + memcpy(read_buffer_->data(), &input_data_[0] + input_pos_, result); + input_pos_ += result; + read_buffer_ = NULL; + net::CompletionCallback* cb = read_callback_; + read_callback_ = NULL; + cb->Run(result); + } + } + int input_pos() const { return input_pos_; } + bool read_pending() const { return read_pending_; } + + void SetPeerAddress(const net::IPEndPoint& peer_address) { + peer_address_ = peer_address; + } + + void SetLocalAddress(const net::IPEndPoint& local_address) { + local_address_ = local_address; + } + + // net::Socket interface. + virtual int Read(net::IOBuffer* buf, int buf_len, + net::CompletionCallback* callback) OVERRIDE { + DCHECK(buf); + if (input_pos_ < static_cast<int>(input_data_.size())){ + int result = std::min(buf_len, + static_cast<int>(input_data_.size()) - input_pos_); + memcpy(buf->data(), &(*input_data_.begin()) + input_pos_, result); + input_pos_ += result; + return result; + } else { + read_pending_ = true; + read_buffer_ = buf; + read_buffer_size_ = buf_len; + read_callback_ = callback; + return net::ERR_IO_PENDING; + } + } + + virtual int Write(net::IOBuffer* buf, int buf_len, + net::CompletionCallback* callback) OVERRIDE { + DCHECK(buf); + if (written_data_) { + written_data_->insert(written_data_->end(), + buf->data(), buf->data() + buf_len); + } + return buf_len; + } + + + virtual bool SetReceiveBufferSize(int32 size) OVERRIDE { + NOTIMPLEMENTED(); + return false; + } + virtual bool SetSendBufferSize(int32 size) OVERRIDE { + NOTIMPLEMENTED(); + return false; + } + + virtual int Connect(net::CompletionCallback* callback) OVERRIDE { + return 0; + } + + virtual void Disconnect() OVERRIDE { + NOTREACHED(); + } + + virtual bool IsConnected() const OVERRIDE { + return true; + } + + virtual bool IsConnectedAndIdle() const OVERRIDE { + return false; + } + + virtual int GetPeerAddress(net::AddressList* address) const OVERRIDE { + *address = net::AddressList(peer_address_.address(), + peer_address_.port(), false); + return net::OK; + } + + virtual int GetLocalAddress(net::IPEndPoint* address) const OVERRIDE { + *address = local_address_; + return net::OK; + } + + virtual const net::BoundNetLog& NetLog() const OVERRIDE { + NOTREACHED(); + return net_log_; + } + + virtual void SetSubresourceSpeculation() OVERRIDE { + NOTREACHED(); + } + + virtual void SetOmniboxSpeculation() OVERRIDE { + NOTREACHED(); + } + + virtual bool WasEverUsed() const OVERRIDE { + return true; + } + + virtual bool UsingTCPFastOpen() const OVERRIDE { + return false; + } + + private: + bool read_pending_; + scoped_refptr<net::IOBuffer> read_buffer_; + int read_buffer_size_; + net::CompletionCallback* read_callback_; + + std::string* written_data_; + std::string input_data_; + int input_pos_; + + net::IPEndPoint peer_address_; + net::IPEndPoint local_address_; + + net::BoundNetLog net_log_; +}; + +void CreateRandomPacket(std::vector<char>* packet) { + size_t size = kStunHeaderSize + rand() % 1000; + packet->resize(size); + for (size_t i = 0; i < size; i++) { + (*packet)[i] = rand() % 256; + } + // Always set the first bit to ensure that generated packet is not + // valid STUN packet. + (*packet)[0] = (*packet)[0] | 0x80; +} + +void CreateStunPacket(std::vector<char>* packet, uint16 type) { + CreateRandomPacket(packet); + *reinterpret_cast<uint16*>(&*packet->begin()) = htons(type); + *reinterpret_cast<uint16*>(&*packet->begin() + 2) = + htons(packet->size() - kStunHeaderSize); + *reinterpret_cast<uint32*>(&*packet->begin() + 4) = htonl(kStunMagicCookie); +} + +void CreateStunRequest(std::vector<char>* packet) { + CreateStunPacket(packet, kStunBindingRequest); +} + +void CreateStunResponse(std::vector<char>* packet) { + CreateStunPacket(packet, kStunBindingResponse); +} + +void CreateStunError(std::vector<char>* packet) { + CreateStunPacket(packet, kStunBindingError); +} + +net::IPEndPoint ParseAddress(const std::string ip_str, int port) { + net::IPAddressNumber ip; + EXPECT_TRUE(net::ParseIPLiteralToNumber(ip_str, &ip)); + return net::IPEndPoint(ip, port); +} + +MATCHER_P(MatchMessage, type, "") { + return arg->type() == type; +} + +MATCHER_P(MatchPacketMessage, packet_content, "") { + if (arg->type() != P2PMsg_OnDataReceived::ID) + return false; + P2PMsg_OnDataReceived::Param params; + IPC::MessageWithTuple<P2PMsg_OnDataReceived::Param>::Read(arg, ¶ms); + return params.c == packet_content; +} + +MATCHER_P(MatchIncomingSocketMessage, address, "") { + if (arg->type() != P2PMsg_OnIncomingTcpConnection::ID) + return false; + P2PMsg_OnIncomingTcpConnection::Param params; + IPC::MessageWithTuple<P2PMsg_OnIncomingTcpConnection::Param>::Read( + arg, ¶ms); + return params.b == address; +} + +} // namespace + +#endif // CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_TEST_UTILS_H_ diff --git a/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc b/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc index 076faae..cd517b8 100644 --- a/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc +++ b/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc @@ -2,22 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <winsock2.h> // for htonl -#else -#include <arpa/inet.h> -#endif +#include "content/browser/renderer_host/p2p/socket_host_udp.h" #include <deque> #include <vector> -#include "content/browser/renderer_host/p2p/socket_host_udp.h" -#include "content/common/p2p_messages.h" +#include "content/browser/renderer_host/p2p/socket_host_test_utils.h" #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" +#include "net/base/sys_byteorder.h" #include "net/udp/datagram_server_socket.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,18 +23,6 @@ using ::testing::Return; namespace { -const char kTestLocalIpAddress[] = "123.44.22.4"; -const char kTestIpAddress1[] = "123.44.22.31"; -const int kTestPort1 = 234; -const char kTestIpAddress2[] = "133.11.22.33"; -const int kTestPort2 = 543; - -const int kStunHeaderSize = 20; -const uint16 kStunBindingRequest = 0x0001; -const uint16 kStunBindingResponse = 0x0102; -const uint16 kStunBindingError = 0x0111; -const uint32 kStunMagicCookie = 0x2112A442; - class FakeDatagramServerSocket : public net::DatagramServerSocket { public: typedef std::pair<net::IPEndPoint, std::vector<char> > UDPPacket; @@ -124,20 +106,11 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket { net::CompletionCallback* recv_callback_; }; -class MockIPCSender : public IPC::Message::Sender { - public: - MOCK_METHOD1(Send, bool(IPC::Message* msg)); -}; - -MATCHER_P(MatchMessage, type, "") { - return arg->type() == type; -} - } // namespace class P2PSocketHostUdpTest : public testing::Test { protected: - void SetUp() OVERRIDE { + virtual void SetUp() OVERRIDE { EXPECT_CALL(sender_, Send( MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID)))) .WillOnce(DoAll(DeleteArg<0>(), Return(true))); @@ -146,48 +119,11 @@ class P2PSocketHostUdpTest : public testing::Test { socket_ = new FakeDatagramServerSocket(&sent_packets_); socket_host_->socket_.reset(socket_); - net::IPAddressNumber local_ip; - ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestLocalIpAddress, &local_ip)); - local_address_ = net::IPEndPoint(local_ip, kTestPort1); + local_address_ = ParseAddress(kTestLocalIpAddress, kTestPort1); socket_host_->Init(local_address_, net::IPEndPoint()); - net::IPAddressNumber ip1; - ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestIpAddress1, &ip1)); - dest1_ = net::IPEndPoint(ip1, kTestPort1); - net::IPAddressNumber ip2; - ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestIpAddress2, &ip2)); - dest2_ = net::IPEndPoint(ip2, kTestPort2); - } - - void CreateRandomPacket(std::vector<char>* packet) { - size_t size = kStunHeaderSize + rand() % 1000; - packet->resize(size); - for (size_t i = 0; i < size; i++) { - (*packet)[i] = rand() % 256; - } - // Always set the first bit to ensure that generated packet is not - // valid STUN packet. - (*packet)[0] = (*packet)[0] | 0x80; - } - - void CreateStunPacket(std::vector<char>* packet, uint16 type) { - CreateRandomPacket(packet); - *reinterpret_cast<uint16*>(&*packet->begin()) = htons(type); - *reinterpret_cast<uint16*>(&*packet->begin() + 2) = - htons(packet->size() - kStunHeaderSize); - *reinterpret_cast<uint32*>(&*packet->begin() + 4) = htonl(kStunMagicCookie); - } - - void CreateStunRequest(std::vector<char>* packet) { - CreateStunPacket(packet, kStunBindingRequest); - } - - void CreateStunResponse(std::vector<char>* packet) { - CreateStunPacket(packet, kStunBindingResponse); - } - - void CreateStunError(std::vector<char>* packet) { - CreateStunPacket(packet, kStunBindingError); + dest1_ = ParseAddress(kTestIpAddress1, kTestPort1); + dest2_ = ParseAddress(kTestIpAddress2, kTestPort2); } std::deque<FakeDatagramServerSocket::UDPPacket> sent_packets_; @@ -239,13 +175,12 @@ TEST_F(P2PSocketHostUdpTest, SendDataNoAuth) { // Verify that we can send data after we've received STUN request // from the other side. TEST_F(P2PSocketHostUdpTest, SendAfterStunRequest) { - EXPECT_CALL(sender_, Send( - MatchMessage(static_cast<uint32>(P2PMsg_OnDataReceived::ID)))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - // Receive packet from |dest1_|. std::vector<char> request_packet; CreateStunRequest(&request_packet); + + EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); socket_->ReceivePacket(dest1_, request_packet); // Now we should be able to send any data to |dest1_|. @@ -260,13 +195,12 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunRequest) { // Verify that we can send data after we've received STUN response // from the other side. TEST_F(P2PSocketHostUdpTest, SendAfterStunResponse) { - EXPECT_CALL(sender_, Send( - MatchMessage(static_cast<uint32>(P2PMsg_OnDataReceived::ID)))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - // Receive packet from |dest1_|. std::vector<char> request_packet; CreateStunRequest(&request_packet); + + EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); socket_->ReceivePacket(dest1_, request_packet); // Now we should be able to send any data to |dest1_|. @@ -281,13 +215,12 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunResponse) { // Verify messages still cannot be sent to an unathorized host after // successful binding with different host. TEST_F(P2PSocketHostUdpTest, SendAfterStunResponseDifferentHost) { - EXPECT_CALL(sender_, Send( - MatchMessage(static_cast<uint32>(P2PMsg_OnDataReceived::ID)))) - .WillOnce(DoAll(DeleteArg<0>(), Return(true))); - // Receive packet from |dest1_|. std::vector<char> request_packet; CreateStunRequest(&request_packet); + + EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet))) + .WillOnce(DoAll(DeleteArg<0>(), Return(true))); socket_->ReceivePacket(dest1_, request_packet); // Should fail when trying to send the same packet to |dest2_|. |