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/message_loop/message_loop.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_
.message_loop()->PostTask(
130 &RunServerOnThread
, path
, response
, &listen_event
, request
));
131 ASSERT_TRUE(listen_event
.TimedWait(base::TimeDelta::FromSeconds(5)));
135 base::Thread thread_
;
138 TEST_F(PortServerTest
, Reserve
) {
139 std::string path
= GenerateRandomPath();
140 PortServer
server(path
);
143 RunServer(path
, "12345\n", &request
);
146 scoped_ptr
<PortReservation
> reservation
;
147 Status status
= server
.ReservePort(&port
, &reservation
);
148 ASSERT_EQ(kOk
, status
.code()) << status
.message();
149 ASSERT_EQ(port
, 12345);
152 TEST_F(PortServerTest
, ReserveResetReserve
) {
153 std::string path
= GenerateRandomPath();
154 PortServer
server(path
);
157 RunServer(path
, "12345\n", &request
);
160 scoped_ptr
<PortReservation
> reservation
;
161 Status status
= server
.ReservePort(&port
, &reservation
);
162 ASSERT_EQ(kOk
, status
.code()) << status
.message();
163 ASSERT_EQ(port
, 12345);
166 status
= server
.ReservePort(&port
, &reservation
);
167 ASSERT_EQ(kOk
, status
.code()) << status
.message();
168 ASSERT_EQ(port
, 12345);
171 TEST_F(PortServerTest
, ReserveReserve
) {
172 std::string path
= GenerateRandomPath();
173 PortServer
server(path
);
176 RunServer(path
, "12345\n", &request
);
179 scoped_ptr
<PortReservation
> reservation
;
180 Status status
= server
.ReservePort(&port
, &reservation
);
181 ASSERT_EQ(kOk
, status
.code()) << status
.message();
182 ASSERT_EQ(port
, 12345);
184 RunServer(path
, "12346\n", &request
);
185 status
= server
.ReservePort(&port
, &reservation
);
186 ASSERT_EQ(kOk
, status
.code()) << status
.message();
187 ASSERT_EQ(port
, 12346);
191 TEST(PortManagerTest
, ReservePort
) {
192 PortManager
mgr(15000, 16000);
194 scoped_ptr
<PortReservation
> reservation
;
195 Status status
= mgr
.ReservePort(&port
, &reservation
);
196 ASSERT_EQ(kOk
, status
.code()) << status
.message();
198 ASSERT_GE(port
, 15000);
199 ASSERT_LE(port
, 16000);
200 ASSERT_TRUE(reservation
);
203 TEST(PortManagerTest
, ReservePortFromPool
) {
204 PortManager
mgr(15000, 16000);
205 int first_port
= 0, port
= 1;
206 for (int i
= 0; i
< 10; i
++) {
207 scoped_ptr
<PortReservation
> reservation
;
208 Status status
= mgr
.ReservePortFromPool(&port
, &reservation
);
209 ASSERT_EQ(kOk
, status
.code()) << status
.message();
210 ASSERT_TRUE(reservation
);
211 ASSERT_GE(port
, 15000);
212 ASSERT_LE(port
, 16000);
215 ASSERT_EQ(port
, first_port
);