///===- ThreadCrashReporterTests.cpp - Thread local signal handling tests -===// // // 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 "support/ThreadCrashReporter.h" #include "support/Threading.h" #include "llvm/Support/Signals.h" #include "gtest/gtest.h" #include #include namespace clang { namespace clangd { namespace { static void infoSignalHandler() { ThreadCrashReporter::runCrashHandlers(); } TEST(ThreadCrashReporterTest, All) { #if defined(_WIN32) // Simulate signals on Windows for unit testing purposes. // The `crash.test` lit test checks the end-to-end integration. auto SignalCurrentThread = []() { infoSignalHandler(); }; #else llvm::sys::SetInfoSignalFunction(&infoSignalHandler); auto SignalCurrentThread = []() { raise(SIGUSR1); }; #endif AsyncTaskRunner Runner; auto SignalAnotherThread = [&]() { Runner.runAsync("signal another thread", SignalCurrentThread); Runner.wait(); }; bool Called; { ThreadCrashReporter ScopedReporter([&Called]() { Called = true; }); // Check handler gets called when a signal gets delivered to the current // thread. Called = false; SignalCurrentThread(); EXPECT_TRUE(Called); // Check handler does not get called when another thread gets signalled. Called = false; SignalAnotherThread(); EXPECT_FALSE(Called); } // Check handler does not get called when the reporter object goes out of // scope. Called = false; SignalCurrentThread(); EXPECT_FALSE(Called); std::string Order = ""; { ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('a'); }); { ThreadCrashReporter ScopedReporter([&Order] { Order.push_back('b'); }); SignalCurrentThread(); } // Check that handlers are called in LIFO order. EXPECT_EQ(Order, "ba"); // Check that current handler is the only one after the nested scope is // over. SignalCurrentThread(); EXPECT_EQ(Order, "baa"); } } } // namespace } // namespace clangd } // namespace clang