1 //===-- MainLoopTest.cpp ----------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Host/MainLoop.h" 11 #include "lldb/Host/common/TCPSocket.h" 12 #include "gtest/gtest.h" 13 #include <future> 14 15 using namespace lldb_private; 16 17 namespace { 18 class MainLoopTest : public testing::Test { 19 public: 20 static void SetUpTestCase() { 21 #ifdef _MSC_VER 22 WSADATA data; 23 ASSERT_EQ(0, WSAStartup(MAKEWORD(2, 2), &data)); 24 #endif 25 } 26 27 static void TearDownTestCase() { 28 #ifdef _MSC_VER 29 ASSERT_EQ(0, WSACleanup()); 30 #endif 31 } 32 33 void SetUp() override { 34 bool child_processes_inherit = false; 35 Status error; 36 std::unique_ptr<TCPSocket> listen_socket_up( 37 new TCPSocket(true, child_processes_inherit)); 38 ASSERT_TRUE(error.Success()); 39 error = listen_socket_up->Listen("localhost:0", 5); 40 ASSERT_TRUE(error.Success()); 41 42 Socket *accept_socket; 43 std::future<Status> accept_error = std::async(std::launch::async, [&] { 44 return listen_socket_up->Accept(accept_socket); 45 }); 46 47 std::unique_ptr<TCPSocket> connect_socket_up( 48 new TCPSocket(true, child_processes_inherit)); 49 error = connect_socket_up->Connect( 50 llvm::formatv("localhost:{0}", listen_socket_up->GetLocalPortNumber()) 51 .str()); 52 ASSERT_TRUE(error.Success()); 53 ASSERT_TRUE(accept_error.get().Success()); 54 55 callback_count = 0; 56 socketpair[0] = std::move(connect_socket_up); 57 socketpair[1].reset(accept_socket); 58 } 59 60 void TearDown() override { 61 socketpair[0].reset(); 62 socketpair[1].reset(); 63 } 64 65 protected: 66 MainLoop::Callback make_callback() { 67 return [&](MainLoopBase &loop) { 68 ++callback_count; 69 loop.RequestTermination(); 70 }; 71 } 72 std::shared_ptr<Socket> socketpair[2]; 73 unsigned callback_count; 74 }; 75 } // namespace 76 77 TEST_F(MainLoopTest, ReadObject) { 78 char X = 'X'; 79 size_t len = sizeof(X); 80 ASSERT_TRUE(socketpair[0]->Write(&X, len).Success()); 81 82 MainLoop loop; 83 84 Status error; 85 auto handle = loop.RegisterReadObject(socketpair[1], make_callback(), error); 86 ASSERT_TRUE(error.Success()); 87 ASSERT_TRUE(handle); 88 ASSERT_TRUE(loop.Run().Success()); 89 ASSERT_EQ(1u, callback_count); 90 } 91 92 TEST_F(MainLoopTest, TerminatesImmediately) { 93 char X = 'X'; 94 size_t len = sizeof(X); 95 ASSERT_TRUE(socketpair[0]->Write(&X, len).Success()); 96 ASSERT_TRUE(socketpair[1]->Write(&X, len).Success()); 97 98 MainLoop loop; 99 Status error; 100 auto handle0 = loop.RegisterReadObject(socketpair[0], make_callback(), error); 101 ASSERT_TRUE(error.Success()); 102 auto handle1 = loop.RegisterReadObject(socketpair[1], make_callback(), error); 103 ASSERT_TRUE(error.Success()); 104 105 ASSERT_TRUE(loop.Run().Success()); 106 ASSERT_EQ(1u, callback_count); 107 } 108 109 #ifdef LLVM_ON_UNIX 110 TEST_F(MainLoopTest, Signal) { 111 MainLoop loop; 112 Status error; 113 114 auto handle = loop.RegisterSignal(SIGUSR1, make_callback(), error); 115 ASSERT_TRUE(error.Success()); 116 kill(getpid(), SIGUSR1); 117 ASSERT_TRUE(loop.Run().Success()); 118 ASSERT_EQ(1u, callback_count); 119 } 120 #endif 121