This source file includes following definitions.
- RecvFromSocket
- SendToSocket
- SendToSocket
- ReadSocket
- WriteSocket
- CreateUDPAddress
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- GetNext
- TEST_F
- TEST_F
- PrivilegedRand
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "net/udp/udp_client_socket.h"
#include "net/udp/udp_server_socket.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/net_log_unittest.h"
#include "net/base/net_util.h"
#include "net/base/test_completion_callback.h"
#include "net/test/net_test_suite.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
namespace net {
namespace {
class UDPSocketTest : public PlatformTest {
public:
UDPSocketTest()
: buffer_(new IOBufferWithSize(kMaxRead)) {
}
std::string RecvFromSocket(UDPServerSocket* socket) {
TestCompletionCallback callback;
int rv = socket->RecvFrom(
buffer_.get(), kMaxRead, &recv_from_address_, callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
if (rv < 0)
return std::string();
return std::string(buffer_->data(), rv);
}
int SendToSocket(UDPServerSocket* socket, std::string msg) {
return SendToSocket(socket, msg, recv_from_address_);
}
int SendToSocket(UDPServerSocket* socket,
std::string msg,
const IPEndPoint& address) {
TestCompletionCallback callback;
int length = msg.length();
scoped_refptr<StringIOBuffer> io_buffer(new StringIOBuffer(msg));
scoped_refptr<DrainableIOBuffer> buffer(
new DrainableIOBuffer(io_buffer.get(), length));
int bytes_sent = 0;
while (buffer->BytesRemaining()) {
int rv = socket->SendTo(
buffer.get(), buffer->BytesRemaining(), address, callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
if (rv <= 0)
return bytes_sent > 0 ? bytes_sent : rv;
bytes_sent += rv;
buffer->DidConsume(rv);
}
return bytes_sent;
}
std::string ReadSocket(UDPClientSocket* socket) {
TestCompletionCallback callback;
int rv = socket->Read(buffer_.get(), kMaxRead, callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
if (rv < 0)
return std::string();
return std::string(buffer_->data(), rv);
}
int WriteSocket(UDPClientSocket* socket, std::string msg) {
TestCompletionCallback callback;
int length = msg.length();
scoped_refptr<StringIOBuffer> io_buffer(new StringIOBuffer(msg));
scoped_refptr<DrainableIOBuffer> buffer(
new DrainableIOBuffer(io_buffer.get(), length));
int bytes_sent = 0;
while (buffer->BytesRemaining()) {
int rv = socket->Write(
buffer.get(), buffer->BytesRemaining(), callback.callback());
if (rv == ERR_IO_PENDING)
rv = callback.WaitForResult();
if (rv <= 0)
return bytes_sent > 0 ? bytes_sent : rv;
bytes_sent += rv;
buffer->DidConsume(rv);
}
return bytes_sent;
}
protected:
static const int kMaxRead = 1024;
scoped_refptr<IOBufferWithSize> buffer_;
IPEndPoint recv_from_address_;
};
void CreateUDPAddress(std::string ip_str, int port, IPEndPoint* address) {
IPAddressNumber ip_number;
bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
if (!rv)
return;
*address = IPEndPoint(ip_number, port);
}
TEST_F(UDPSocketTest, Connect) {
const int kPort = 9999;
std::string simple_message("hello world!");
IPEndPoint bind_address;
CreateUDPAddress("127.0.0.1", kPort, &bind_address);
CapturingNetLog server_log;
scoped_ptr<UDPServerSocket> server(
new UDPServerSocket(&server_log, NetLog::Source()));
server->AllowAddressReuse();
int rv = server->Listen(bind_address);
ASSERT_EQ(OK, rv);
IPEndPoint server_address;
CreateUDPAddress("127.0.0.1", kPort, &server_address);
CapturingNetLog client_log;
scoped_ptr<UDPClientSocket> client(
new UDPClientSocket(DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
&client_log,
NetLog::Source()));
rv = client->Connect(server_address);
EXPECT_EQ(OK, rv);
rv = WriteSocket(client.get(), simple_message);
EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv));
std::string str = RecvFromSocket(server.get());
DCHECK(simple_message == str);
rv = SendToSocket(server.get(), simple_message);
EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv));
str = ReadSocket(client.get());
DCHECK(simple_message == str);
server.reset();
client.reset();
CapturingNetLog::CapturedEntryList server_entries;
server_log.GetEntries(&server_entries);
EXPECT_EQ(4u, server_entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
server_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
EXPECT_TRUE(LogContainsEvent(
server_entries, 1, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEvent(
server_entries, 2, NetLog::TYPE_UDP_BYTES_SENT, NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEndEvent(
server_entries, 3, NetLog::TYPE_SOCKET_ALIVE));
CapturingNetLog::CapturedEntryList client_entries;
client_log.GetEntries(&client_entries);
EXPECT_EQ(6u, client_entries.size());
EXPECT_TRUE(LogContainsBeginEvent(
client_entries, 0, NetLog::TYPE_SOCKET_ALIVE));
EXPECT_TRUE(LogContainsBeginEvent(
client_entries, 1, NetLog::TYPE_UDP_CONNECT));
EXPECT_TRUE(LogContainsEndEvent(
client_entries, 2, NetLog::TYPE_UDP_CONNECT));
EXPECT_TRUE(LogContainsEvent(
client_entries, 3, NetLog::TYPE_UDP_BYTES_SENT, NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEvent(
client_entries, 4, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE));
EXPECT_TRUE(LogContainsEndEvent(
client_entries, 5, NetLog::TYPE_SOCKET_ALIVE));
}
#if defined(OS_MACOSX)
TEST_F(UDPSocketTest, DISABLED_Broadcast) {
#elif defined(OS_ANDROID)
TEST_F(UDPSocketTest, DISABLED_Broadcast) {
#else
TEST_F(UDPSocketTest, Broadcast) {
#endif
const int kPort = 9999;
std::string first_message("first message"), second_message("second message");
IPEndPoint broadcast_address;
CreateUDPAddress("255.255.255.255", kPort, &broadcast_address);
IPEndPoint listen_address;
CreateUDPAddress("0.0.0.0", kPort, &listen_address);
CapturingNetLog server1_log, server2_log;
scoped_ptr<UDPServerSocket> server1(
new UDPServerSocket(&server1_log, NetLog::Source()));
scoped_ptr<UDPServerSocket> server2(
new UDPServerSocket(&server2_log, NetLog::Source()));
server1->AllowAddressReuse();
server1->AllowBroadcast();
server2->AllowAddressReuse();
server2->AllowBroadcast();
int rv = server1->Listen(listen_address);
EXPECT_EQ(OK, rv);
rv = server2->Listen(listen_address);
EXPECT_EQ(OK, rv);
rv = SendToSocket(server1.get(), first_message, broadcast_address);
ASSERT_EQ(static_cast<int>(first_message.size()), rv);
std::string str = RecvFromSocket(server1.get());
ASSERT_EQ(first_message, str);
str = RecvFromSocket(server2.get());
ASSERT_EQ(first_message, str);
rv = SendToSocket(server2.get(), second_message, broadcast_address);
ASSERT_EQ(static_cast<int>(second_message.size()), rv);
str = RecvFromSocket(server1.get());
ASSERT_EQ(second_message, str);
str = RecvFromSocket(server2.get());
ASSERT_EQ(second_message, str);
}
static const int kBindRetries = 10;
class TestPrng {
public:
explicit TestPrng(const std::deque<int>& numbers) : numbers_(numbers) {}
int GetNext(int , int ) {
DCHECK(!numbers_.empty());
int rv = numbers_.front();
numbers_.pop_front();
return rv;
}
private:
std::deque<int> numbers_;
DISALLOW_COPY_AND_ASSIGN(TestPrng);
};
#if defined(OS_ANDROID)
TEST_F(UDPSocketTest, DISABLED_ConnectRandomBind) {
#else
TEST_F(UDPSocketTest, ConnectRandomBind) {
#endif
std::vector<UDPClientSocket*> sockets;
IPEndPoint peer_address;
CreateUDPAddress("192.168.1.13", 53, &peer_address);
std::deque<int> used_ports;
for (int i = 0; i < kBindRetries; ++i) {
UDPClientSocket* socket =
new UDPClientSocket(DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
NULL,
NetLog::Source());
sockets.push_back(socket);
EXPECT_EQ(OK, socket->Connect(peer_address));
IPEndPoint client_address;
EXPECT_EQ(OK, socket->GetLocalAddress(&client_address));
used_ports.push_back(client_address.port());
}
delete sockets.back();
sockets.pop_back();
TestPrng test_prng(used_ports);
RandIntCallback rand_int_cb =
base::Bind(&TestPrng::GetNext, base::Unretained(&test_prng));
scoped_ptr<UDPClientSocket> test_socket(
new UDPClientSocket(DatagramSocket::RANDOM_BIND,
rand_int_cb,
NULL,
NetLog::Source()));
EXPECT_EQ(OK, test_socket->Connect(peer_address));
IPEndPoint client_address;
EXPECT_EQ(OK, test_socket->GetLocalAddress(&client_address));
EXPECT_EQ(used_ports.back(), client_address.port());
STLDeleteElements(&sockets);
}
int PrivilegedRand(int min, int max) {
return 4;
}
TEST_F(UDPSocketTest, ConnectFail) {
IPEndPoint peer_address;
CreateUDPAddress("0.0.0.0", 53, &peer_address);
scoped_ptr<UDPSocket> socket(
new UDPSocket(DatagramSocket::RANDOM_BIND,
base::Bind(&PrivilegedRand),
NULL,
NetLog::Source()));
int rv = socket->Connect(peer_address);
EXPECT_NE(OK, rv);
EXPECT_FALSE(socket->is_connected());
}
TEST_F(UDPSocketTest, VerifyConnectBindsAddr) {
const int kPort1 = 9999;
const int kPort2 = 10000;
std::string simple_message("hello world!");
std::string foreign_message("BAD MESSAGE TO GET!!");
IPEndPoint bind_address;
CreateUDPAddress("127.0.0.1", kPort1, &bind_address);
UDPServerSocket server1(NULL, NetLog::Source());
server1.AllowAddressReuse();
int rv = server1.Listen(bind_address);
ASSERT_EQ(OK, rv);
CreateUDPAddress("127.0.0.1", kPort2, &bind_address);
UDPServerSocket server2(NULL, NetLog::Source());
server2.AllowAddressReuse();
rv = server2.Listen(bind_address);
ASSERT_EQ(OK, rv);
IPEndPoint server_address;
CreateUDPAddress("127.0.0.1", kPort1, &server_address);
UDPClientSocket client(DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
NULL,
NetLog::Source());
rv = client.Connect(server_address);
EXPECT_EQ(OK, rv);
rv = WriteSocket(&client, simple_message);
EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv));
std::string str = RecvFromSocket(&server1);
DCHECK(simple_message == str);
IPEndPoint client_address;
rv = client.GetLocalAddress(&client_address);
EXPECT_EQ(OK, rv);
rv = SendToSocket(&server2, foreign_message,
client_address);
EXPECT_EQ(foreign_message.length(), static_cast<size_t>(rv));
rv = SendToSocket(&server1, simple_message,
client_address);
EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv));
str = ReadSocket(&client);
DCHECK(simple_message == str);
}
TEST_F(UDPSocketTest, ClientGetLocalPeerAddresses) {
struct TestData {
std::string remote_address;
std::string local_address;
bool may_fail;
} tests[] = {
{ "127.0.00.1", "127.0.0.1", false },
{ "::1", "::1", true },
#if !defined(OS_ANDROID)
{ "192.168.1.1", "127.0.0.1", false },
{ "2001:db8:0::42", "::1", true },
#endif
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); i++) {
SCOPED_TRACE(std::string("Connecting from ") + tests[i].local_address +
std::string(" to ") + tests[i].remote_address);
IPAddressNumber ip_number;
ParseIPLiteralToNumber(tests[i].remote_address, &ip_number);
IPEndPoint remote_address(ip_number, 80);
ParseIPLiteralToNumber(tests[i].local_address, &ip_number);
IPEndPoint local_address(ip_number, 80);
UDPClientSocket client(DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
NULL,
NetLog::Source());
int rv = client.Connect(remote_address);
if (tests[i].may_fail && rv == ERR_ADDRESS_UNREACHABLE) {
continue;
}
EXPECT_LE(ERR_IO_PENDING, rv);
IPEndPoint fetched_local_address;
rv = client.GetLocalAddress(&fetched_local_address);
EXPECT_EQ(OK, rv);
IPEndPoint fetched_remote_address;
rv = client.GetPeerAddress(&fetched_remote_address);
EXPECT_EQ(OK, rv);
EXPECT_EQ(remote_address, fetched_remote_address);
}
}
TEST_F(UDPSocketTest, ServerGetLocalAddress) {
IPEndPoint bind_address;
CreateUDPAddress("127.0.0.1", 0, &bind_address);
UDPServerSocket server(NULL, NetLog::Source());
int rv = server.Listen(bind_address);
EXPECT_EQ(OK, rv);
IPEndPoint local_address;
rv = server.GetLocalAddress(&local_address);
EXPECT_EQ(rv, 0);
EXPECT_GT(local_address.port(), 0);
EXPECT_EQ(local_address.address(), bind_address.address());
}
TEST_F(UDPSocketTest, ServerGetPeerAddress) {
IPEndPoint bind_address;
CreateUDPAddress("127.0.0.1", 0, &bind_address);
UDPServerSocket server(NULL, NetLog::Source());
int rv = server.Listen(bind_address);
EXPECT_EQ(OK, rv);
IPEndPoint peer_address;
rv = server.GetPeerAddress(&peer_address);
EXPECT_EQ(rv, ERR_SOCKET_NOT_CONNECTED);
}
TEST_F(UDPSocketTest, CloseWithPendingRead) {
IPEndPoint bind_address;
CreateUDPAddress("127.0.0.1", 0, &bind_address);
UDPServerSocket server(NULL, NetLog::Source());
int rv = server.Listen(bind_address);
EXPECT_EQ(OK, rv);
TestCompletionCallback callback;
IPEndPoint from;
rv = server.RecvFrom(buffer_.get(), kMaxRead, &from, callback.callback());
EXPECT_EQ(rv, ERR_IO_PENDING);
server.Close();
EXPECT_FALSE(callback.have_result());
}
#if defined(OS_ANDROID)
#define MAYBE_JoinMulticastGroup DISABLED_JoinMulticastGroup
#else
#define MAYBE_JoinMulticastGroup JoinMulticastGroup
#endif
TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) {
const int kPort = 9999;
const char* const kGroup = "237.132.100.17";
IPEndPoint bind_address;
CreateUDPAddress("0.0.0.0", kPort, &bind_address);
IPAddressNumber group_ip;
EXPECT_TRUE(ParseIPLiteralToNumber(kGroup, &group_ip));
UDPSocket socket(DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
NULL,
NetLog::Source());
EXPECT_EQ(OK, socket.Bind(bind_address));
EXPECT_EQ(OK, socket.JoinGroup(group_ip));
EXPECT_NE(OK, socket.JoinGroup(group_ip));
EXPECT_EQ(OK, socket.LeaveGroup(group_ip));
EXPECT_NE(OK, socket.LeaveGroup(group_ip));
socket.Close();
}
TEST_F(UDPSocketTest, MulticastOptions) {
const int kPort = 9999;
IPEndPoint bind_address;
CreateUDPAddress("0.0.0.0", kPort, &bind_address);
UDPSocket socket(DatagramSocket::DEFAULT_BIND,
RandIntCallback(),
NULL,
NetLog::Source());
EXPECT_EQ(OK, socket.SetMulticastLoopbackMode(false));
EXPECT_EQ(OK, socket.SetMulticastLoopbackMode(true));
EXPECT_EQ(OK, socket.SetMulticastTimeToLive(0));
EXPECT_EQ(OK, socket.SetMulticastTimeToLive(3));
EXPECT_NE(OK, socket.SetMulticastTimeToLive(-1));
EXPECT_EQ(OK, socket.SetMulticastInterface(0));
EXPECT_EQ(OK, socket.Bind(bind_address));
EXPECT_NE(OK, socket.SetMulticastLoopbackMode(false));
EXPECT_NE(OK, socket.SetMulticastTimeToLive(0));
EXPECT_NE(OK, socket.SetMulticastInterface(0));
socket.Close();
}
}
}