1 // Copyright (c) 2013 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.
9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/sync_socket.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "base/time/time.h"
15 #include "chrome/test/chromedriver/chrome/status.h"
16 #include "chrome/test/chromedriver/net/port_server.h"
17 #include "net/base/sys_addrinfo.h"
18 #include "testing/gtest/include/gtest/gtest.h"
22 #include <sys/socket.h>
28 void SetOnCall(bool* called
) {
34 TEST(PortReservationTest
, Normal
) {
37 PortReservation
r(base::Bind(&SetOnCall
, &called
), 100);
42 TEST(PortReservationTest
, Leak
) {
45 PortReservation
r(base::Bind(&SetOnCall
, &called
), 100);
51 TEST(PortReservationTest
, MultipleLeaks
) {
54 PortReservation
r(base::Bind(&SetOnCall
, &called
), 100);
64 void RunServerOnThread(const std::string
& path
,
65 const std::string
& response
,
66 base::WaitableEvent
* listen_event
,
67 std::string
* request
) {
68 int server_sock_fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
69 ASSERT_GE(server_sock_fd
, 0);
70 ASSERT_GE(fcntl(server_sock_fd
, F_SETFL
, O_NONBLOCK
), 0);
71 base::SyncSocket
server_sock(server_sock_fd
);
73 struct sockaddr_un addr
;
74 memset(&addr
, 0, sizeof(addr
));
75 addr
.sun_family
= AF_UNIX
;
76 memcpy(addr
.sun_path
, &path
[0], path
.length());
79 reinterpret_cast<struct sockaddr
*>(&addr
),
80 sizeof(sa_family_t
) + path
.length()));
81 ASSERT_EQ(0, listen(server_sock_fd
, 1));
82 listen_event
->Signal();
84 struct sockaddr_un cli_addr
;
85 socklen_t clilen
= sizeof(cli_addr
);
86 base::TimeTicks deadline
=
87 base::TimeTicks::Now() + base::TimeDelta::FromSeconds(2);
88 int client_sock_fd
= -1;
89 while (base::TimeTicks::Now() < deadline
&& client_sock_fd
< 0) {
90 client_sock_fd
= accept(
91 server_sock_fd
, reinterpret_cast<struct sockaddr
*>(&cli_addr
), &clilen
);
93 ASSERT_GE(client_sock_fd
, 0);
94 base::SyncSocket
sock(client_sock_fd
);
97 size_t rv
= sock
.Receive(&c
, 1);
100 request
->push_back(c
);
101 } while (sock
.Peek());
102 sock
.Send(response
.c_str(), response
.length());
105 std::string
GenerateRandomPath() {
106 std::string path
= base::GenerateGUID();
108 std::string pre_path
;
109 pre_path
.push_back(0); // Linux abstract namespace.
110 path
= pre_path
+ path
;
117 class PortServerTest
: public testing::Test
{
119 PortServerTest() : thread_("server") {
120 EXPECT_TRUE(thread_
.Start());
123 void RunServer(const std::string
& path
,
124 const std::string
& response
,
125 std::string
* request
) {
126 base::WaitableEvent
listen_event(false, false);
127 thread_
.task_runner()->PostTask(
129 base::Bind(&RunServerOnThread
, path
, response
, &listen_event
, request
));
130 ASSERT_TRUE(listen_event
.TimedWait(base::TimeDelta::FromSeconds(5)));
134 base::Thread thread_
;
137 TEST_F(PortServerTest
, Reserve
) {
138 std::string path
= GenerateRandomPath();
139 PortServer
server(path
);
142 RunServer(path
, "12345\n", &request
);
145 scoped_ptr
<PortReservation
> reservation
;
146 Status status
= server
.ReservePort(&port
, &reservation
);
147 ASSERT_EQ(kOk
, status
.code()) << status
.message();
148 ASSERT_EQ(12345u, port
);
151 TEST_F(PortServerTest
, ReserveResetReserve
) {
152 std::string path
= GenerateRandomPath();
153 PortServer
server(path
);
156 RunServer(path
, "12345\n", &request
);
159 scoped_ptr
<PortReservation
> reservation
;
160 Status status
= server
.ReservePort(&port
, &reservation
);
161 ASSERT_EQ(kOk
, status
.code()) << status
.message();
162 ASSERT_EQ(12345u, port
);
165 status
= server
.ReservePort(&port
, &reservation
);
166 ASSERT_EQ(kOk
, status
.code()) << status
.message();
167 ASSERT_EQ(12345u, port
);
170 TEST_F(PortServerTest
, ReserveReserve
) {
171 std::string path
= GenerateRandomPath();
172 PortServer
server(path
);
175 RunServer(path
, "12345\n", &request
);
178 scoped_ptr
<PortReservation
> reservation
;
179 Status status
= server
.ReservePort(&port
, &reservation
);
180 ASSERT_EQ(kOk
, status
.code()) << status
.message();
181 ASSERT_EQ(12345u, port
);
183 RunServer(path
, "12346\n", &request
);
184 status
= server
.ReservePort(&port
, &reservation
);
185 ASSERT_EQ(kOk
, status
.code()) << status
.message();
186 ASSERT_EQ(12346u, port
);
190 TEST(PortManagerTest
, ReservePort
) {
191 PortManager
mgr(15000, 16000);
193 scoped_ptr
<PortReservation
> reservation
;
194 Status status
= mgr
.ReservePort(&port
, &reservation
);
195 ASSERT_EQ(kOk
, status
.code()) << status
.message();
197 ASSERT_GE(port
, 15000);
198 ASSERT_LE(port
, 16000);
199 ASSERT_TRUE(reservation
);
202 TEST(PortManagerTest
, ReservePortFromPool
) {
203 PortManager
mgr(15000, 16000);
204 uint16 first_port
= 0, port
= 1;
205 for (int i
= 0; i
< 10; i
++) {
206 scoped_ptr
<PortReservation
> reservation
;
207 Status status
= mgr
.ReservePortFromPool(&port
, &reservation
);
208 ASSERT_EQ(kOk
, status
.code()) << status
.message();
209 ASSERT_TRUE(reservation
);
210 ASSERT_GE(port
, 15000);
211 ASSERT_LE(port
, 16000);
214 ASSERT_EQ(port
, first_port
);