port_server_unittest.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file. 468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <string> 668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/bind.h" 868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/guid.h" 968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/location.h" 1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/message_loop/message_loop.h" 1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/sync_socket.h" 1268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/threading/thread.h" 1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/time/time.h" 1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h" 1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/test/chromedriver/net/port_server.h" 1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "net/base/sys_addrinfo.h" 1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_LINUX) 2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <fcntl.h> 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <sys/socket.h> 2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <sys/un.h> 2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif 2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace { 2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SetOnCall(bool* called) { 2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *called = true; 3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} // namespace 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST(PortReservationTest, Normal) { 3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool called = false; 3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) { 3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) PortReservation r(base::Bind(&SetOnCall, &called), 100); 3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_TRUE(called); 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST(PortReservationTest, Leak) { 4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool called = false; 4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) { 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) PortReservation r(base::Bind(&SetOnCall, &called), 100); 4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) r.Leak(); 4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_FALSE(called); 4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST(PortReservationTest, MultipleLeaks) { 5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool called = false; 5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) { 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) PortReservation r(base::Bind(&SetOnCall, &called), 100); 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) r.Leak(); 5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) r.Leak(); 5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_FALSE(called); 5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(OS_LINUX) 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace { 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void RunServerOnThread(const std::string& path, 6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& response, 6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::WaitableEvent* listen_event, 6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string* request) { 6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int server_sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_GE(server_sock_fd, 0); 7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_GE(fcntl(server_sock_fd, F_SETFL, O_NONBLOCK), 0); 7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::SyncSocket server_sock(server_sock_fd); 7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct sockaddr_un addr; 7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) memset(&addr, 0, sizeof(addr)); 7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) addr.sun_family = AF_UNIX; 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) memcpy(addr.sun_path, &path[0], path.length()); 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(0, 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bind(server_sock_fd, 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) reinterpret_cast<struct sockaddr*>(&addr), 8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) sizeof(sa_family_t) + path.length())); 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(0, listen(server_sock_fd, 1)); 8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) listen_event->Signal(); 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct sockaddr_un cli_addr; 8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) socklen_t clilen = sizeof(cli_addr); 8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::TimeTicks deadline = 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::TimeTicks::Now() + base::TimeDelta::FromSeconds(2); 8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int client_sock_fd = -1; 8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) while (base::TimeTicks::Now() < deadline && client_sock_fd < 0) { 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) client_sock_fd = accept( 9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) server_sock_fd, reinterpret_cast<struct sockaddr*>(&cli_addr), &clilen); 9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_GE(client_sock_fd, 0); 9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::SyncSocket sock(client_sock_fd); 9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) do { 9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) char c = 0; 9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t rv = sock.Receive(&c, 1); 9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!rv) 9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) break; 10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) request->push_back(c); 10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } while (sock.Peek()); 10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) sock.Send(response.c_str(), response.length()); 10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string GenerateRandomPath() { 10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string path = base::GenerateGUID(); 10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!path.empty()) { 10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string pre_path; 10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) pre_path.push_back(0); // Linux abstract namespace. 11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) path = pre_path + path; 11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return path; 11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} // namespace 11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class PortServerTest : public testing::Test { 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public: 11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) PortServerTest() : thread_("server") { 12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) EXPECT_TRUE(thread_.Start()); 12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) void RunServer(const std::string& path, 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& response, 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string* request) { 12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::WaitableEvent listen_event(false, false); 12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) thread_.message_loop()->PostTask( 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FROM_HERE, 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind( 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) &RunServerOnThread, path, response, &listen_event, request)); 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_TRUE(listen_event.TimedWait(base::TimeDelta::FromSeconds(5))); 13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) private: 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Thread thread_; 13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}; 13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(PortServerTest, Reserve) { 13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string path = GenerateRandomPath(); 14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) PortServer server(path); 14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string request; 14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) RunServer(path, "12345\n", &request); 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int port = 0; 14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<PortReservation> reservation; 14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Status status = server.ReservePort(&port, &reservation); 14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(kOk, status.code()) << status.message(); 14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(port, 12345); 15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(PortServerTest, ReserveResetReserve) { 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string path = GenerateRandomPath(); 15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) PortServer server(path); 15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string request; 15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) RunServer(path, "12345\n", &request); 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int port = 0; 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<PortReservation> reservation; 16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Status status = server.ReservePort(&port, &reservation); 16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(kOk, status.code()) << status.message(); 16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(port, 12345); 16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) reservation.reset(); 16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) status = server.ReservePort(&port, &reservation); 16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(kOk, status.code()) << status.message(); 16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(port, 12345); 16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(PortServerTest, ReserveReserve) { 17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string path = GenerateRandomPath(); 17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) PortServer server(path); 17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string request; 17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) RunServer(path, "12345\n", &request); 17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int port = 0; 17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<PortReservation> reservation; 18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Status status = server.ReservePort(&port, &reservation); 18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(kOk, status.code()) << status.message(); 18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(port, 12345); 18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) RunServer(path, "12346\n", &request); 18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) status = server.ReservePort(&port, &reservation); 18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(kOk, status.code()) << status.message(); 18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(port, 12346); 18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif 190