1///===- ThreadCrashReporterTests.cpp - Thread local signal handling tests -===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "support/ThreadCrashReporter.h"
10#include "support/Threading.h"
11#include "llvm/Support/Signals.h"
12#include "gtest/gtest.h"
13#include <csignal>
14#include <string>
15
16namespace clang {
17namespace clangd {
18
19namespace {
20
21static void infoSignalHandler() { ThreadCrashReporter::runCrashHandlers(); }
22
23TEST(ThreadCrashReporterTest, All) {
24#if defined(_WIN32)
25 // Simulate signals on Windows for unit testing purposes.
26 // The `crash.test` lit test checks the end-to-end integration.
27 auto SignalCurrentThread = []() { infoSignalHandler(); };
28#else
29 llvm::sys::SetInfoSignalFunction(&infoSignalHandler);
30 auto SignalCurrentThread = []() { raise(SIGUSR1); };
31#endif
32
33 AsyncTaskRunner Runner;
34 auto SignalAnotherThread = [&]() {
35 Runner.runAsync(Name: "signal another thread", Action: SignalCurrentThread);
36 Runner.wait();
37 };
38
39 bool Called;
40 {
41 ThreadCrashReporter ScopedReporter([&Called]() { Called = true; });
42 // Check handler gets called when a signal gets delivered to the current
43 // thread.
44 Called = false;
45 SignalCurrentThread();
46 EXPECT_TRUE(Called);
47
48 // Check handler does not get called when another thread gets signalled.
49 Called = false;
50 SignalAnotherThread();
51 EXPECT_FALSE(Called);
52 }
53 // Check handler does not get called when the reporter object goes out of
54 // scope.
55 Called = false;
56 SignalCurrentThread();
57 EXPECT_FALSE(Called);
58
59 std::string Order = "";
60 {
61 ThreadCrashReporter ScopedReporter([&Order] { Order.push_back(c: 'a'); });
62 {
63 ThreadCrashReporter ScopedReporter([&Order] { Order.push_back(c: 'b'); });
64 SignalCurrentThread();
65 }
66 // Check that handlers are called in LIFO order.
67 EXPECT_EQ(Order, "ba");
68
69 // Check that current handler is the only one after the nested scope is
70 // over.
71 SignalCurrentThread();
72 EXPECT_EQ(Order, "baa");
73 }
74}
75
76} // namespace
77} // namespace clangd
78} // namespace clang
79

source code of clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp