From b582fa3bd8223ba1cf5936ffcb10e078d4ff13e1 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Wed, 10 Feb 2016 14:49:00 -0800 Subject: [PATCH] adb: make fdevent_test, socket_test compile on Windows. Switch pthread_* to use the adb_thread_* abstractions to allow the fdevent and socket tests to compile on Win32. Bug: http://b/27105824 Change-Id: I6541bb1398780b999837e701837d7f86a5eee8ca (cherry picked from commit 022d447e9efcff59e22f0ab13764282116f235dd) --- adb/Android.mk | 10 +- adb/fdevent.cpp | 11 ++ adb/fdevent.h | 4 +- adb/fdevent_test.cpp | 63 ++++------- adb/fdevent_test.h | 58 ++++++++++ adb/socket_test.cpp | 263 +++++++++++++++++++------------------------ 6 files changed, 210 insertions(+), 199 deletions(-) create mode 100644 adb/fdevent_test.h diff --git a/adb/Android.mk b/adb/Android.mk index 7835d9f3a..e0997eafd 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -59,6 +59,8 @@ LIBADB_SRC_FILES := \ LIBADB_TEST_SRCS := \ adb_io_test.cpp \ adb_utils_test.cpp \ + fdevent_test.cpp \ + socket_test.cpp \ sysdeps_test.cpp \ transport_test.cpp \ @@ -87,14 +89,6 @@ LIBADB_windows_SRC_FILES := \ sysdeps_win32.cpp \ usb_windows.cpp \ -LIBADB_TEST_linux_SRCS := \ - fdevent_test.cpp \ - socket_test.cpp \ - -LIBADB_TEST_darwin_SRCS := \ - fdevent_test.cpp \ - socket_test.cpp \ - LIBADB_TEST_windows_SRCS := \ sysdeps_win32_test.cpp \ diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp index 461736422..902548ec5 100644 --- a/adb/fdevent.cpp +++ b/adb/fdevent.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -70,6 +71,7 @@ struct PollNode { // That's why we don't need a lock for fdevent. static auto& g_poll_node_map = *new std::unordered_map(); static auto& g_pending_list = *new std::list(); +static std::atomic terminate_loop(false); static bool main_thread_valid; static unsigned long main_thread_id; @@ -364,6 +366,10 @@ void fdevent_loop() #endif // !ADB_HOST while (true) { + if (terminate_loop) { + return; + } + D("--- --- waiting for events"); fdevent_process(); @@ -376,6 +382,10 @@ void fdevent_loop() } } +void fdevent_terminate_loop() { + terminate_loop = true; +} + size_t fdevent_installed_count() { return g_poll_node_map.size(); } @@ -384,4 +394,5 @@ void fdevent_reset() { g_poll_node_map.clear(); g_pending_list.clear(); main_thread_valid = false; + terminate_loop = false; } diff --git a/adb/fdevent.h b/adb/fdevent.h index 657fde5e9..207f9b702 100644 --- a/adb/fdevent.h +++ b/adb/fdevent.h @@ -76,9 +76,9 @@ void fdevent_set_timeout(fdevent *fde, int64_t timeout_ms); */ void fdevent_loop(); -// For debugging only. +// The following functions are used only for tests. +void fdevent_terminate_loop(); size_t fdevent_installed_count(); -// For debugging only. void fdevent_reset(); #endif diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp index 7fe3d37d2..c933ed528 100644 --- a/adb/fdevent_test.cpp +++ b/adb/fdevent_test.cpp @@ -18,15 +18,13 @@ #include -#include -#include - #include #include #include #include #include "adb_io.h" +#include "fdevent_test.h" class FdHandler { public: @@ -48,7 +46,7 @@ class FdHandler { if (events & FDE_READ) { ASSERT_EQ(fd, handler->read_fd_); char c; - ASSERT_EQ(1, read(fd, &c, 1)); + ASSERT_EQ(1, adb_read(fd, &c, 1)); handler->queue_.push(c); fdevent_add(&handler->write_fde_, FDE_WRITE); } @@ -57,7 +55,7 @@ class FdHandler { ASSERT_FALSE(handler->queue_.empty()); char c = handler->queue_.front(); handler->queue_.pop(); - ASSERT_EQ(1, write(fd, &c, 1)); + ASSERT_EQ(1, adb_write(fd, &c, 1)); if (handler->queue_.empty()) { fdevent_del(&handler->write_fde_, FDE_WRITE); } @@ -72,29 +70,19 @@ class FdHandler { std::queue queue_; }; -static void signal_handler(int) { - pthread_exit(nullptr); -} - -class FdeventTest : public ::testing::Test { - protected: - static void SetUpTestCase() { - ASSERT_NE(SIG_ERR, signal(SIGUSR1, signal_handler)); - ASSERT_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN)); - } - - virtual void SetUp() { - fdevent_reset(); - ASSERT_EQ(0u, fdevent_installed_count()); - } -}; - struct ThreadArg { int first_read_fd; int last_write_fd; size_t middle_pipe_count; }; +TEST_F(FdeventTest, fdevent_terminate) { + adb_thread_t thread; + PrepareThread(); + ASSERT_TRUE(adb_thread_create([](void*) { fdevent_loop(); }, nullptr, &thread)); + TerminateThread(thread); +} + static void FdEventThreadFunc(ThreadArg* arg) { std::vector read_fds; std::vector write_fds; @@ -102,7 +90,7 @@ static void FdEventThreadFunc(ThreadArg* arg) { read_fds.push_back(arg->first_read_fd); for (size_t i = 0; i < arg->middle_pipe_count; ++i) { int fds[2]; - ASSERT_EQ(0, pipe(fds)); + ASSERT_EQ(0, adb_socketpair(fds)); read_fds.push_back(fds[0]); write_fds.push_back(fds[1]); } @@ -122,9 +110,9 @@ TEST_F(FdeventTest, smoke) { const std::string MESSAGE = "fdevent_test"; int fd_pair1[2]; int fd_pair2[2]; - ASSERT_EQ(0, pipe(fd_pair1)); - ASSERT_EQ(0, pipe(fd_pair2)); - pthread_t thread; + ASSERT_EQ(0, adb_socketpair(fd_pair1)); + ASSERT_EQ(0, adb_socketpair(fd_pair2)); + adb_thread_t thread; ThreadArg thread_arg; thread_arg.first_read_fd = fd_pair1[0]; thread_arg.last_write_fd = fd_pair2[1]; @@ -132,9 +120,9 @@ TEST_F(FdeventTest, smoke) { int writer = fd_pair1[1]; int reader = fd_pair2[0]; - ASSERT_EQ(0, pthread_create(&thread, nullptr, - reinterpret_cast(FdEventThreadFunc), - &thread_arg)); + PrepareThread(); + ASSERT_TRUE(adb_thread_create(reinterpret_cast(FdEventThreadFunc), &thread_arg, + &thread)); for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) { std::string read_buffer = MESSAGE; @@ -144,10 +132,9 @@ TEST_F(FdeventTest, smoke) { ASSERT_EQ(read_buffer, write_buffer); } - ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); - ASSERT_EQ(0, pthread_join(thread, nullptr)); - ASSERT_EQ(0, close(writer)); - ASSERT_EQ(0, close(reader)); + TerminateThread(thread); + ASSERT_EQ(0, adb_close(writer)); + ASSERT_EQ(0, adb_close(reader)); } struct InvalidFdArg { @@ -161,7 +148,7 @@ static void InvalidFdEventCallback(int fd, unsigned events, void* userdata) { ASSERT_EQ(arg->expected_events, events); fdevent_remove(&arg->fde); if (++*(arg->happened_event_count) == 2) { - pthread_exit(nullptr); + fdevent_terminate_loop(); } } @@ -184,9 +171,7 @@ static void InvalidFdThreadFunc(void*) { } TEST_F(FdeventTest, invalid_fd) { - pthread_t thread; - ASSERT_EQ(0, pthread_create(&thread, nullptr, - reinterpret_cast(InvalidFdThreadFunc), - nullptr)); - ASSERT_EQ(0, pthread_join(thread, nullptr)); + adb_thread_t thread; + ASSERT_TRUE(adb_thread_create(InvalidFdThreadFunc, nullptr, &thread)); + ASSERT_TRUE(adb_thread_join(thread)); } diff --git a/adb/fdevent_test.h b/adb/fdevent_test.h new file mode 100644 index 000000000..c853bceec --- /dev/null +++ b/adb/fdevent_test.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "socket.h" +#include "sysdeps.h" + +class FdeventTest : public ::testing::Test { + protected: + int dummy = -1; + + static void SetUpTestCase() { +#if !defined(_WIN32) + ASSERT_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN)); +#endif + } + + void SetUp() override { + fdevent_reset(); + ASSERT_EQ(0u, fdevent_installed_count()); + } + + // Register a dummy socket used to wake up the fdevent loop to tell it to die. + void PrepareThread() { + int dummy_fds[2]; + if (adb_socketpair(dummy_fds) != 0) { + FAIL() << "failed to create socketpair: " << strerror(errno); + } + + asocket* dummy_socket = create_local_socket(dummy_fds[1]); + if (!dummy_socket) { + FAIL() << "failed to create local socket: " << strerror(errno); + } + dummy_socket->ready(dummy_socket); + dummy = dummy_fds[0]; + } + + void TerminateThread(adb_thread_t thread) { + fdevent_terminate_loop(); + ASSERT_TRUE(WriteFdExactly(dummy, "", 1)); + ASSERT_TRUE(adb_thread_join(thread)); + ASSERT_EQ(0, adb_close(dummy)); + } +}; diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp index 03cab64a5..471ca09e4 100644 --- a/adb/socket_test.cpp +++ b/adb/socket_test.cpp @@ -18,119 +18,89 @@ #include +#include #include #include #include #include -#include -#include #include #include "adb.h" #include "adb_io.h" +#include "fdevent_test.h" #include "socket.h" #include "sysdeps.h" -static void signal_handler(int) { - ASSERT_EQ(1u, fdevent_installed_count()); - pthread_exit(nullptr); -} - -// On host, register a dummy socket, so fdevet_loop() will not abort when previously -// registered local sockets are all closed. On device, fdevent_subproc_setup() installs -// one fdevent which can be considered as dummy socket. -static void InstallDummySocket() { -#if ADB_HOST - int dummy_fds[2]; - ASSERT_EQ(0, pipe(dummy_fds)); - asocket* dummy_socket = create_local_socket(dummy_fds[0]); - ASSERT_TRUE(dummy_socket != nullptr); - dummy_socket->ready(dummy_socket); -#endif -} - struct ThreadArg { int first_read_fd; int last_write_fd; size_t middle_pipe_count; }; -static void FdEventThreadFunc(ThreadArg* arg) { - std::vector read_fds; - std::vector write_fds; +class LocalSocketTest : public FdeventTest {}; - read_fds.push_back(arg->first_read_fd); - for (size_t i = 0; i < arg->middle_pipe_count; ++i) { - int fds[2]; - ASSERT_EQ(0, adb_socketpair(fds)); - read_fds.push_back(fds[0]); - write_fds.push_back(fds[1]); - } - write_fds.push_back(arg->last_write_fd); - - for (size_t i = 0; i < read_fds.size(); ++i) { - asocket* reader = create_local_socket(read_fds[i]); - ASSERT_TRUE(reader != nullptr); - asocket* writer = create_local_socket(write_fds[i]); - ASSERT_TRUE(writer != nullptr); - reader->peer = writer; - writer->peer = reader; - reader->ready(reader); - } - - InstallDummySocket(); +static void FdEventThreadFunc(void*) { fdevent_loop(); } -class LocalSocketTest : public ::testing::Test { - protected: - static void SetUpTestCase() { - ASSERT_NE(SIG_ERR, signal(SIGUSR1, signal_handler)); - ASSERT_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN)); - } - - virtual void SetUp() { - fdevent_reset(); - ASSERT_EQ(0u, fdevent_installed_count()); - } -}; - TEST_F(LocalSocketTest, smoke) { - const size_t PIPE_COUNT = 100; - const size_t MESSAGE_LOOP_COUNT = 100; + // Join two socketpairs with a chain of intermediate socketpairs. + int first[2]; + std::vector> intermediates; + int last[2]; + + constexpr size_t INTERMEDIATE_COUNT = 50; + constexpr size_t MESSAGE_LOOP_COUNT = 100; const std::string MESSAGE = "socket_test"; - int fd_pair1[2]; - int fd_pair2[2]; - ASSERT_EQ(0, adb_socketpair(fd_pair1)); - ASSERT_EQ(0, adb_socketpair(fd_pair2)); - pthread_t thread; - ThreadArg thread_arg; - thread_arg.first_read_fd = fd_pair1[0]; - thread_arg.last_write_fd = fd_pair2[1]; - thread_arg.middle_pipe_count = PIPE_COUNT; - int writer = fd_pair1[1]; - int reader = fd_pair2[0]; - ASSERT_EQ(0, pthread_create(&thread, nullptr, - reinterpret_cast(FdEventThreadFunc), - &thread_arg)); + intermediates.resize(INTERMEDIATE_COUNT); + ASSERT_EQ(0, adb_socketpair(first)) << strerror(errno); + ASSERT_EQ(0, adb_socketpair(last)) << strerror(errno); + asocket* prev_tail = create_local_socket(first[1]); + ASSERT_NE(nullptr, prev_tail); + + auto connect = [](asocket* tail, asocket* head) { + tail->peer = head; + head->peer = tail; + tail->ready(tail); + }; + + for (auto& intermediate : intermediates) { + ASSERT_EQ(0, adb_socketpair(intermediate.data())) << strerror(errno); + + asocket* head = create_local_socket(intermediate[0]); + ASSERT_NE(nullptr, head); + + asocket* tail = create_local_socket(intermediate[1]); + ASSERT_NE(nullptr, tail); + + connect(prev_tail, head); + prev_tail = tail; + } + + asocket* end = create_local_socket(last[0]); + ASSERT_NE(nullptr, end); + connect(prev_tail, end); + + PrepareThread(); + adb_thread_t thread; + ASSERT_TRUE(adb_thread_create(FdEventThreadFunc, nullptr, &thread)); - usleep(1000); for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) { std::string read_buffer = MESSAGE; std::string write_buffer(MESSAGE.size(), 'a'); - ASSERT_TRUE(WriteFdExactly(writer, read_buffer.c_str(), read_buffer.size())); - ASSERT_TRUE(ReadFdExactly(reader, &write_buffer[0], write_buffer.size())); + ASSERT_TRUE(WriteFdExactly(first[0], &read_buffer[0], read_buffer.size())); + ASSERT_TRUE(ReadFdExactly(last[1], &write_buffer[0], write_buffer.size())); ASSERT_EQ(read_buffer, write_buffer); } - ASSERT_EQ(0, adb_close(writer)); - ASSERT_EQ(0, adb_close(reader)); - // Wait until the local sockets are closed. - sleep(1); - ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); - ASSERT_EQ(0, pthread_join(thread, nullptr)); + ASSERT_EQ(0, adb_close(first[0])); + ASSERT_EQ(0, adb_close(last[1])); + + // Wait until the local sockets are closed. + adb_sleep_ms(100); + TerminateThread(thread); } struct CloseWithPacketArg { @@ -160,7 +130,6 @@ static void CloseWithPacketThreadFunc(CloseWithPacketArg* arg) { s->peer = cause_close_s; cause_close_s->ready(cause_close_s); - InstallDummySocket(); fdevent_loop(); } @@ -176,21 +145,19 @@ TEST_F(LocalSocketTest, close_socket_with_packet) { CloseWithPacketArg arg; arg.socket_fd = socket_fd[1]; arg.cause_close_fd = cause_close_fd[1]; - pthread_t thread; - ASSERT_EQ(0, pthread_create(&thread, nullptr, - reinterpret_cast(CloseWithPacketThreadFunc), - &arg)); - // Wait until the fdevent_loop() starts. - sleep(1); - ASSERT_EQ(0, adb_close(cause_close_fd[0])); - sleep(1); - ASSERT_EQ(2u, fdevent_installed_count()); - ASSERT_EQ(0, adb_close(socket_fd[0])); - // Wait until the socket is closed. - sleep(1); - ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); - ASSERT_EQ(0, pthread_join(thread, nullptr)); + PrepareThread(); + adb_thread_t thread; + ASSERT_TRUE(adb_thread_create(reinterpret_cast(CloseWithPacketThreadFunc), + &arg, &thread)); + // Wait until the fdevent_loop() starts. + adb_sleep_ms(100); + ASSERT_EQ(0, adb_close(cause_close_fd[0])); + adb_sleep_ms(100); + EXPECT_EQ(2u, fdevent_installed_count()); + ASSERT_EQ(0, adb_close(socket_fd[0])); + + TerminateThread(thread); } // This test checks if we can read packets from a closing local socket. @@ -203,26 +170,23 @@ TEST_F(LocalSocketTest, read_from_closing_socket) { arg.socket_fd = socket_fd[1]; arg.cause_close_fd = cause_close_fd[1]; - pthread_t thread; - ASSERT_EQ(0, pthread_create(&thread, nullptr, - reinterpret_cast(CloseWithPacketThreadFunc), - &arg)); + PrepareThread(); + adb_thread_t thread; + ASSERT_TRUE(adb_thread_create(reinterpret_cast(CloseWithPacketThreadFunc), + &arg, &thread)); // Wait until the fdevent_loop() starts. - sleep(1); + adb_sleep_ms(100); ASSERT_EQ(0, adb_close(cause_close_fd[0])); - sleep(1); - ASSERT_EQ(2u, fdevent_installed_count()); + adb_sleep_ms(100); + EXPECT_EQ(2u, fdevent_installed_count()); // Verify if we can read successfully. std::vector buf(arg.bytes_written); + ASSERT_NE(0u, arg.bytes_written); ASSERT_EQ(true, ReadFdExactly(socket_fd[0], buf.data(), buf.size())); ASSERT_EQ(0, adb_close(socket_fd[0])); - // Wait until the socket is closed. - sleep(1); - - ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); - ASSERT_EQ(0, pthread_join(thread, nullptr)); + TerminateThread(thread); } // This test checks if we can close local socket in the following situation: @@ -238,20 +202,17 @@ TEST_F(LocalSocketTest, write_error_when_having_packets) { arg.socket_fd = socket_fd[1]; arg.cause_close_fd = cause_close_fd[1]; - pthread_t thread; - ASSERT_EQ(0, pthread_create(&thread, nullptr, - reinterpret_cast(CloseWithPacketThreadFunc), - &arg)); + PrepareThread(); + adb_thread_t thread; + ASSERT_TRUE(adb_thread_create(reinterpret_cast(CloseWithPacketThreadFunc), + &arg, &thread)); + // Wait until the fdevent_loop() starts. - sleep(1); - ASSERT_EQ(3u, fdevent_installed_count()); + adb_sleep_ms(100); + EXPECT_EQ(3u, fdevent_installed_count()); ASSERT_EQ(0, adb_close(socket_fd[0])); - // Wait until the socket is closed. - sleep(1); - - ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); - ASSERT_EQ(0, pthread_join(thread, nullptr)); + TerminateThread(thread); } #if defined(__linux__) @@ -260,50 +221,52 @@ static void ClientThreadFunc() { std::string error; int fd = network_loopback_client(5038, SOCK_STREAM, &error); ASSERT_GE(fd, 0) << error; - sleep(2); + adb_sleep_ms(200); ASSERT_EQ(0, adb_close(fd)); } struct CloseRdHupSocketArg { - int socket_fd; + int socket_fd; }; static void CloseRdHupSocketThreadFunc(CloseRdHupSocketArg* arg) { - asocket* s = create_local_socket(arg->socket_fd); - ASSERT_TRUE(s != nullptr); + asocket* s = create_local_socket(arg->socket_fd); + ASSERT_TRUE(s != nullptr); - InstallDummySocket(); - fdevent_loop(); + fdevent_loop(); } // This test checks if we can close sockets in CLOSE_WAIT state. TEST_F(LocalSocketTest, close_socket_in_CLOSE_WAIT_state) { - std::string error; - int listen_fd = network_inaddr_any_server(5038, SOCK_STREAM, &error); - ASSERT_GE(listen_fd, 0); - pthread_t client_thread; - ASSERT_EQ(0, pthread_create(&client_thread, nullptr, - reinterpret_cast(ClientThreadFunc), nullptr)); + std::string error; + int listen_fd = network_inaddr_any_server(5038, SOCK_STREAM, &error); + ASSERT_GE(listen_fd, 0); - struct sockaddr addr; - socklen_t alen; - alen = sizeof(addr); - int accept_fd = adb_socket_accept(listen_fd, &addr, &alen); - ASSERT_GE(accept_fd, 0); - CloseRdHupSocketArg arg; - arg.socket_fd = accept_fd; - pthread_t thread; - ASSERT_EQ(0, pthread_create(&thread, nullptr, - reinterpret_cast(CloseRdHupSocketThreadFunc), - &arg)); - // Wait until the fdevent_loop() starts. - sleep(1); - ASSERT_EQ(2u, fdevent_installed_count()); - // Wait until the client closes its socket. - ASSERT_EQ(0, pthread_join(client_thread, nullptr)); - sleep(2); - ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); - ASSERT_EQ(0, pthread_join(thread, nullptr)); + adb_thread_t client_thread; + ASSERT_TRUE(adb_thread_create(reinterpret_cast(ClientThreadFunc), nullptr, + &client_thread)); + + struct sockaddr addr; + socklen_t alen; + alen = sizeof(addr); + int accept_fd = adb_socket_accept(listen_fd, &addr, &alen); + ASSERT_GE(accept_fd, 0); + CloseRdHupSocketArg arg; + arg.socket_fd = accept_fd; + + PrepareThread(); + adb_thread_t thread; + ASSERT_TRUE(adb_thread_create(reinterpret_cast(CloseRdHupSocketThreadFunc), + &arg, &thread)); + + // Wait until the fdevent_loop() starts. + adb_sleep_ms(100); + EXPECT_EQ(2u, fdevent_installed_count()); + + // Wait until the client closes its socket. + ASSERT_TRUE(adb_thread_join(client_thread)); + + TerminateThread(thread); } #endif // defined(__linux__)