blob: 37b4c198e9635fa574fba3bb583ccb9200aed1a8 [file] [log] [blame]
// 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 "services/network/p2p/socket_tcp_server.h"
#include <stdint.h>
#include <list>
#include <utility>
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "net/base/completion_once_callback.h"
#include "services/network/p2p/socket_tcp.h"
#include "services/network/p2p/socket_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_(nullptr) {}
~FakeServerSocket() override {}
bool listening() { return listening_; }
void AddIncoming(net::StreamSocket* socket) {
if (!accept_callback_.is_null()) {
DCHECK(incoming_sockets_.empty());
accept_socket_->reset(socket);
accept_socket_ = nullptr;
std::move(accept_callback_).Run(net::OK);
} else {
incoming_sockets_.push_back(socket);
}
}
int Listen(const net::IPEndPoint& address, int backlog) override {
local_address_ = address;
listening_ = true;
return net::OK;
}
int GetLocalAddress(net::IPEndPoint* address) const override {
*address = local_address_;
return net::OK;
}
int Accept(std::unique_ptr<net::StreamSocket>* socket,
net::CompletionOnceCallback 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_ = std::move(callback);
return net::ERR_IO_PENDING;
}
}
private:
bool listening_;
net::IPEndPoint local_address_;
std::unique_ptr<net::StreamSocket>* accept_socket_;
net::CompletionOnceCallback accept_callback_;
std::list<net::StreamSocket*> incoming_sockets_;
};
} // namespace
namespace network {
class P2PSocketTcpServerTest : public testing::Test {
protected:
void SetUp() override {
mojom::P2PSocketClientPtr socket_client;
auto socket_client_request = mojo::MakeRequest(&socket_client);
mojom::P2PSocketPtr socket;
auto socket_request = mojo::MakeRequest(&socket);
fake_client_.reset(new FakeSocketClient(std::move(socket),
std::move(socket_client_request)));
socket_ = new FakeServerSocket();
p2p_socket_ = std::make_unique<P2PSocketTcpServer>(
&socket_delegate_, std::move(socket_client), std::move(socket_request),
P2P_SOCKET_TCP_CLIENT);
p2p_socket_->socket_.reset(socket_);
EXPECT_CALL(*fake_client_.get(), SocketCreated(_, _)).Times(1);
P2PHostAndIPEndPoint dest;
dest.ip_address = ParseAddress(kTestIpAddress1, kTestPort1);
p2p_socket_->Init(ParseAddress(kTestLocalIpAddress, 0), 0, 0, dest);
EXPECT_TRUE(socket_->listening());
base::RunLoop().RunUntilIdle();
}
// Needed by the child classes because only this class is a friend
// of P2PSocketTcp.
net::StreamSocket* GetSocketFromTcpSocket(P2PSocketTcpBase* host) {
return host->socket_.get();
}
base::test::ScopedTaskEnvironment scoped_task_environment_;
FakeServerSocket* socket_; // Owned by |p2p_socket_|.
std::unique_ptr<FakeSocketClient> fake_client_;
FakeP2PSocketDelegate socket_delegate_;
std::unique_ptr<P2PSocketTcpServer> p2p_socket_;
};
// Accept incoming connection.
TEST_F(P2PSocketTcpServerTest, Accept) {
FakeSocket* incoming = new FakeSocket(nullptr);
incoming->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1));
net::IPEndPoint addr = ParseAddress(kTestIpAddress1, kTestPort1);
incoming->SetPeerAddress(addr);
network::mojom::P2PSocketPtr socket;
network::mojom::P2PSocketClientRequest client_request;
socket_->AddIncoming(incoming);
std::unique_ptr<P2PSocket> accepted_socket =
socket_delegate_.pop_accepted_socket();
ASSERT_TRUE(accepted_socket);
EXPECT_EQ(incoming, GetSocketFromTcpSocket(reinterpret_cast<P2PSocketTcp*>(
accepted_socket.get())));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(fake_client_->num_accepted(), 1U);
// Verify that the socket is destroyed when the client drops it.
socket_delegate_.ExpectDestruction(std::move(accepted_socket));
fake_client_->CloseAccepted();
base::RunLoop().RunUntilIdle();
}
// Accept 2 simultaneous connections.
TEST_F(P2PSocketTcpServerTest, Accept2) {
FakeSocket* incoming1 = new FakeSocket(nullptr);
incoming1->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1));
net::IPEndPoint addr1 = ParseAddress(kTestIpAddress1, kTestPort1);
incoming1->SetPeerAddress(addr1);
FakeSocket* incoming2 = new FakeSocket(nullptr);
incoming2->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1));
net::IPEndPoint addr2 = ParseAddress(kTestIpAddress2, kTestPort2);
incoming2->SetPeerAddress(addr2);
socket_->AddIncoming(incoming1);
socket_->AddIncoming(incoming2);
std::unique_ptr<P2PSocket> accepted_socket_1 =
socket_delegate_.pop_accepted_socket();
ASSERT_TRUE(accepted_socket_1.get() != nullptr);
EXPECT_EQ(incoming1, GetSocketFromTcpSocket(reinterpret_cast<P2PSocketTcp*>(
accepted_socket_1.get())));
std::unique_ptr<P2PSocket> accepted_socket_2 =
socket_delegate_.pop_accepted_socket();
ASSERT_TRUE(accepted_socket_2.get() != nullptr);
EXPECT_EQ(incoming2, GetSocketFromTcpSocket(reinterpret_cast<P2PSocketTcp*>(
accepted_socket_2.get())));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(fake_client_->num_accepted(), 2U);
}
} // namespace network