diff options
author | 2020-08-03 14:33:06 +0000 | |
---|---|---|
committer | 2020-08-03 14:33:06 +0000 | |
commit | 061da546b983eb767bad15e67af1174fb0bcf31c (patch) | |
tree | 83c78b820819d70aa40c36d90447978b300078c5 /gnu/llvm/lldb/unittests/Host/MainLoopTest.cpp | |
parent | Import LLVM 10.0.0 release including clang, lld and lldb. (diff) | |
download | wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.tar.xz wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.zip |
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom
tested by plenty
Diffstat (limited to 'gnu/llvm/lldb/unittests/Host/MainLoopTest.cpp')
-rw-r--r-- | gnu/llvm/lldb/unittests/Host/MainLoopTest.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/unittests/Host/MainLoopTest.cpp b/gnu/llvm/lldb/unittests/Host/MainLoopTest.cpp new file mode 100644 index 00000000000..da509b940a1 --- /dev/null +++ b/gnu/llvm/lldb/unittests/Host/MainLoopTest.cpp @@ -0,0 +1,155 @@ +//===-- MainLoopTest.cpp ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/MainLoop.h" +#include "TestingSupport/SubsystemRAII.h" +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/PseudoTerminal.h" +#include "lldb/Host/common/TCPSocket.h" +#include "llvm/Testing/Support/Error.h" +#include "gtest/gtest.h" +#include <future> + +using namespace lldb_private; + +namespace { +class MainLoopTest : public testing::Test { +public: + SubsystemRAII<Socket> subsystems; + + void SetUp() override { + bool child_processes_inherit = false; + Status error; + std::unique_ptr<TCPSocket> listen_socket_up( + new TCPSocket(true, child_processes_inherit)); + ASSERT_TRUE(error.Success()); + error = listen_socket_up->Listen("localhost:0", 5); + ASSERT_TRUE(error.Success()); + + Socket *accept_socket; + std::future<Status> accept_error = std::async(std::launch::async, [&] { + return listen_socket_up->Accept(accept_socket); + }); + + std::unique_ptr<TCPSocket> connect_socket_up( + new TCPSocket(true, child_processes_inherit)); + error = connect_socket_up->Connect( + llvm::formatv("localhost:{0}", listen_socket_up->GetLocalPortNumber()) + .str()); + ASSERT_TRUE(error.Success()); + ASSERT_TRUE(accept_error.get().Success()); + + callback_count = 0; + socketpair[0] = std::move(connect_socket_up); + socketpair[1].reset(accept_socket); + } + + void TearDown() override { + socketpair[0].reset(); + socketpair[1].reset(); + } + +protected: + MainLoop::Callback make_callback() { + return [&](MainLoopBase &loop) { + ++callback_count; + loop.RequestTermination(); + }; + } + std::shared_ptr<Socket> socketpair[2]; + unsigned callback_count; +}; +} // namespace + +TEST_F(MainLoopTest, ReadObject) { + char X = 'X'; + size_t len = sizeof(X); + ASSERT_TRUE(socketpair[0]->Write(&X, len).Success()); + + MainLoop loop; + + Status error; + auto handle = loop.RegisterReadObject(socketpair[1], make_callback(), error); + ASSERT_TRUE(error.Success()); + ASSERT_TRUE(handle); + ASSERT_TRUE(loop.Run().Success()); + ASSERT_EQ(1u, callback_count); +} + +TEST_F(MainLoopTest, TerminatesImmediately) { + char X = 'X'; + size_t len = sizeof(X); + ASSERT_TRUE(socketpair[0]->Write(&X, len).Success()); + ASSERT_TRUE(socketpair[1]->Write(&X, len).Success()); + + MainLoop loop; + Status error; + auto handle0 = loop.RegisterReadObject(socketpair[0], make_callback(), error); + ASSERT_TRUE(error.Success()); + auto handle1 = loop.RegisterReadObject(socketpair[1], make_callback(), error); + ASSERT_TRUE(error.Success()); + + ASSERT_TRUE(loop.Run().Success()); + ASSERT_EQ(1u, callback_count); +} + +#ifdef LLVM_ON_UNIX +TEST_F(MainLoopTest, DetectsEOF) { + + PseudoTerminal term; + ASSERT_TRUE(term.OpenFirstAvailableMaster(O_RDWR, nullptr, 0)); + ASSERT_TRUE(term.OpenSlave(O_RDWR | O_NOCTTY, nullptr, 0)); + auto conn = std::make_unique<ConnectionFileDescriptor>( + term.ReleaseMasterFileDescriptor(), true); + + Status error; + MainLoop loop; + auto handle = + loop.RegisterReadObject(conn->GetReadObject(), make_callback(), error); + ASSERT_TRUE(error.Success()); + term.CloseSlaveFileDescriptor(); + + ASSERT_TRUE(loop.Run().Success()); + ASSERT_EQ(1u, callback_count); +} + +TEST_F(MainLoopTest, Signal) { + MainLoop loop; + Status error; + + auto handle = loop.RegisterSignal(SIGUSR1, make_callback(), error); + ASSERT_TRUE(error.Success()); + kill(getpid(), SIGUSR1); + ASSERT_TRUE(loop.Run().Success()); + ASSERT_EQ(1u, callback_count); +} + +// Test that a signal which is not monitored by the MainLoop does not +// cause a premature exit. +TEST_F(MainLoopTest, UnmonitoredSignal) { + MainLoop loop; + Status error; + struct sigaction sa; + sa.sa_sigaction = [](int, siginfo_t *, void *) { }; + sa.sa_flags = SA_SIGINFO; // important: no SA_RESTART + sigemptyset(&sa.sa_mask); + ASSERT_EQ(0, sigaction(SIGUSR2, &sa, nullptr)); + + auto handle = loop.RegisterSignal(SIGUSR1, make_callback(), error); + ASSERT_TRUE(error.Success()); + std::thread killer([]() { + sleep(1); + kill(getpid(), SIGUSR2); + sleep(1); + kill(getpid(), SIGUSR1); + }); + ASSERT_TRUE(loop.Run().Success()); + killer.join(); + ASSERT_EQ(1u, callback_count); +} +#endif |