1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <gtest/gtest.h> 18 19 #include <condition_variable> 20 #include <mutex> 21 #include <thread> 22 23 #include "adb_io.h" 24 #include "adb_unique_fd.h" 25 #include "socket.h" 26 #include "sysdeps.h" 27 #include "sysdeps/chrono.h" 28 29 static void WaitForFdeventLoop() { 30 // Sleep for a bit to make sure that network events have propagated. 31 std::this_thread::sleep_for(100ms); 32 33 // fdevent_run_on_main_thread has a guaranteed ordering, and is guaranteed to happen after 34 // socket events, so as soon as our function is called, we know that we've processed all 35 // previous events. 36 std::mutex mutex; 37 std::condition_variable cv; 38 std::unique_lock<std::mutex> lock(mutex); 39 fdevent_run_on_main_thread([&]() { 40 mutex.lock(); 41 mutex.unlock(); 42 cv.notify_one(); 43 }); 44 cv.wait(lock); 45 } 46 47 class FdeventTest : public ::testing::Test { 48 protected: 49 unique_fd dummy; 50 51 ~FdeventTest() { 52 if (thread_.joinable()) { 53 TerminateThread(); 54 } 55 } 56 57 static void SetUpTestCase() { 58 #if !defined(_WIN32) 59 ASSERT_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN)); 60 #endif 61 } 62 63 void SetUp() override { 64 fdevent_reset(); 65 ASSERT_EQ(0u, fdevent_installed_count()); 66 } 67 68 // Register a placeholder socket used to wake up the fdevent loop to tell it to die. 69 void PrepareThread() { 70 int dummy_fds[2]; 71 if (adb_socketpair(dummy_fds) != 0) { 72 FAIL() << "failed to create socketpair: " << strerror(errno); 73 } 74 75 asocket* dummy_socket = create_local_socket(unique_fd(dummy_fds[1])); 76 if (!dummy_socket) { 77 FAIL() << "failed to create local socket: " << strerror(errno); 78 } 79 dummy_socket->ready(dummy_socket); 80 dummy.reset(dummy_fds[0]); 81 82 thread_ = std::thread([]() { fdevent_loop(); }); 83 WaitForFdeventLoop(); 84 } 85 86 size_t GetAdditionalLocalSocketCount() { 87 // placeholder socket installed in PrepareThread() 88 return 1; 89 } 90 91 void TerminateThread() { 92 fdevent_terminate_loop(); 93 ASSERT_TRUE(WriteFdExactly(dummy, "", 1)); 94 thread_.join(); 95 dummy.reset(); 96 } 97 98 std::thread thread_; 99 }; 100