1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/api/socket/udp_socket.h"
9 #include "base/location.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/test/test_timeouts.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "chrome/test/base/browser_with_test_window_test.h"
15 #include "net/base/io_buffer.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 namespace extensions
{
20 // UDPSocketUnitTest exists solely to make it easier to pass a specific
21 // gtest_filter argument during development.
22 class UDPSocketUnitTest
: public BrowserWithTestWindowTest
{
25 static void OnConnected(int result
) {
29 static void OnCompleted(int bytes_read
,
30 scoped_refptr
<net::IOBuffer
> io_buffer
,
31 const std::string
& address
,
33 // Do nothing; don't care.
36 static const char test_message
[] = "$$TESTMESSAGETESTMESSAGETESTMESSAGETEST$$";
37 static const int test_message_length
= arraysize(test_message
);
39 net::AddressList
CreateAddressList(const char* address_string
, int port
) {
40 net::IPAddressNumber ip
;
41 EXPECT_TRUE(net::ParseIPLiteralToNumber(address_string
, &ip
));
42 return net::AddressList::CreateFromIPAddress(ip
, port
);
45 static void OnSendCompleted(int result
) {
46 EXPECT_EQ(test_message_length
, result
);
49 TEST(UDPSocketUnitTest
, TestUDPSocketRecvFrom
) {
50 base::MessageLoopForIO io_loop
; // For RecvFrom to do its threaded work.
51 UDPSocket
socket("abcdefghijklmnopqrst");
53 // Confirm that we can call two RecvFroms in quick succession without
54 // triggering crbug.com/146606.
55 socket
.Connect(CreateAddressList("127.0.0.1", 40000),
56 base::Bind(&OnConnected
));
57 socket
.RecvFrom(4096, base::Bind(&OnCompleted
));
58 socket
.RecvFrom(4096, base::Bind(&OnCompleted
));
61 TEST(UDPSocketUnitTest
, TestUDPMulticastJoinGroup
) {
62 const char kGroup
[] = "237.132.100.17";
63 UDPSocket
src("abcdefghijklmnopqrst");
64 UDPSocket
dest("abcdefghijklmnopqrst");
66 EXPECT_EQ(0, dest
.Bind("0.0.0.0", 13333));
67 EXPECT_EQ(0, dest
.JoinGroup(kGroup
));
68 std::vector
<std::string
> groups
= dest
.GetJoinedGroups();
69 EXPECT_EQ(static_cast<size_t>(1), groups
.size());
70 EXPECT_EQ(kGroup
, *groups
.begin());
71 EXPECT_NE(0, dest
.LeaveGroup("237.132.100.13"));
72 EXPECT_EQ(0, dest
.LeaveGroup(kGroup
));
73 groups
= dest
.GetJoinedGroups();
74 EXPECT_EQ(static_cast<size_t>(0), groups
.size());
77 TEST(UDPSocketUnitTest
, TestUDPMulticastTimeToLive
) {
78 const char kGroup
[] = "237.132.100.17";
79 UDPSocket
socket("abcdefghijklmnopqrst");
80 EXPECT_NE(0, socket
.SetMulticastTimeToLive(-1)); // Negative TTL shall fail.
81 EXPECT_EQ(0, socket
.SetMulticastTimeToLive(3));
82 socket
.Connect(CreateAddressList(kGroup
, 13333), base::Bind(&OnConnected
));
85 TEST(UDPSocketUnitTest
, TestUDPMulticastLoopbackMode
) {
86 const char kGroup
[] = "237.132.100.17";
87 UDPSocket
socket("abcdefghijklmnopqrst");
88 EXPECT_EQ(0, socket
.SetMulticastLoopbackMode(false));
89 socket
.Connect(CreateAddressList(kGroup
, 13333), base::Bind(&OnConnected
));
92 static void QuitMessageLoop() {
93 base::MessageLoopForIO::current()->QuitNow();
96 // Send a test multicast packet every second.
97 // Once the target socket received the packet, the message loop will exit.
98 static void SendMulticastPacket(UDPSocket
* src
, int result
) {
100 scoped_refptr
<net::IOBuffer
> data
= new net::WrappedIOBuffer(test_message
);
101 src
->Write(data
, test_message_length
, base::Bind(&OnSendCompleted
));
102 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
103 FROM_HERE
, base::Bind(&SendMulticastPacket
, src
, result
),
104 base::TimeDelta::FromSeconds(1));
107 FAIL() << "Failed to connect to multicast address. Error code: " << result
;
111 static void OnMulticastReadCompleted(bool *packet_received
,
113 scoped_refptr
<net::IOBuffer
> io_buffer
) {
114 EXPECT_EQ(test_message_length
, count
);
115 EXPECT_EQ(0, strncmp(io_buffer
->data(), test_message
, test_message_length
));
116 *packet_received
= true;
120 TEST(UDPSocketUnitTest
, TestUDPMulticastRecv
) {
121 const int kPort
= 9999;
122 const char kGroup
[] = "237.132.100.17";
123 bool packet_received
= false;
124 base::MessageLoopForIO io_loop
; // For Read to do its threaded work.
125 UDPSocket
dest("abcdefghijklmnopqrst");
126 UDPSocket
src("abcdefghijklmnopqrst");
129 EXPECT_EQ(0, dest
.Bind("0.0.0.0", kPort
));
130 EXPECT_EQ(0, dest
.JoinGroup(kGroup
));
131 dest
.Read(1024, base::Bind(&OnMulticastReadCompleted
, &packet_received
));
134 EXPECT_EQ(0, src
.SetMulticastTimeToLive(0));
135 src
.Connect(CreateAddressList(kGroup
, kPort
),
136 base::Bind(&SendMulticastPacket
, &src
));
138 // If not received within the test action timeout, quit the message loop.
139 io_loop
.task_runner()->PostDelayedTask(
140 FROM_HERE
, base::Bind(&QuitMessageLoop
), TestTimeouts::action_timeout());
144 EXPECT_TRUE(packet_received
) << "Failed to receive from multicast address";
147 } // namespace extensions