1//===-- UnixSignalsTest.cpp -----------------------------------------------===//
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#include <string>
9
10#include "gtest/gtest.h"
11
12#include "lldb/Target/UnixSignals.h"
13#include "llvm/Support/FormatVariadic.h"
14
15using namespace lldb;
16using namespace lldb_private;
17
18class TestSignals : public UnixSignals {
19public:
20 TestSignals() {
21 m_signals.clear();
22 AddSignal(signo: 2, name: "SIG2", default_suppress: false, default_stop: true, default_notify: true, description: "DESC2");
23 AddSignal(signo: 4, name: "SIG4", default_suppress: true, default_stop: false, default_notify: true, description: "DESC4");
24 AddSignal(signo: 8, name: "SIG8", default_suppress: true, default_stop: true, default_notify: true, description: "DESC8");
25 AddSignal(signo: 16, name: "SIG16", default_suppress: true, default_stop: false, default_notify: false, description: "DESC16");
26 AddSignalCode(signo: 16, code: 1, description: "a specific type of SIG16");
27 AddSignalCode(signo: 16, code: 2, description: "SIG16 with a fault address",
28 print_option: SignalCodePrintOption::Address);
29 AddSignalCode(signo: 16, code: 3, description: "bounds violation", print_option: SignalCodePrintOption::Bounds);
30 }
31};
32
33void ExpectEqArrays(llvm::ArrayRef<int32_t> expected,
34 llvm::ArrayRef<int32_t> observed, const char *file,
35 int line) {
36 std::string location = llvm::formatv(Fmt: "{0}:{1}", Vals&: file, Vals&: line);
37 ASSERT_EQ(expected.size(), observed.size()) << location;
38
39 for (size_t i = 0; i < observed.size(); ++i) {
40 ASSERT_EQ(expected[i], observed[i])
41 << "array index: " << i << "location:" << location;
42 }
43}
44
45#define EXPECT_EQ_ARRAYS(expected, observed) \
46 ExpectEqArrays((expected), (observed), __FILE__, __LINE__);
47
48TEST(UnixSignalsTest, Iteration) {
49 TestSignals signals;
50
51 EXPECT_EQ(4, signals.GetNumSignals());
52 EXPECT_EQ(2, signals.GetFirstSignalNumber());
53 EXPECT_EQ(4, signals.GetNextSignalNumber(2));
54 EXPECT_EQ(8, signals.GetNextSignalNumber(4));
55 EXPECT_EQ(16, signals.GetNextSignalNumber(8));
56 EXPECT_EQ(LLDB_INVALID_SIGNAL_NUMBER, signals.GetNextSignalNumber(16));
57}
58
59TEST(UnixSignalsTest, Reset) {
60 TestSignals signals;
61 bool stop_val = signals.GetShouldStop(signo: 2);
62 bool notify_val = signals.GetShouldNotify(signo: 2);
63 bool suppress_val = signals.GetShouldSuppress(signo: 2);
64
65 // Change two, then reset one and make sure only that one was reset:
66 EXPECT_EQ(true, signals.SetShouldNotify(2, !notify_val));
67 EXPECT_EQ(true, signals.SetShouldSuppress(2, !suppress_val));
68 EXPECT_EQ(true, signals.ResetSignal(2, false, true, false));
69 EXPECT_EQ(stop_val, signals.GetShouldStop(2));
70 EXPECT_EQ(notify_val, signals.GetShouldStop(2));
71 EXPECT_EQ(!suppress_val, signals.GetShouldNotify(2));
72
73 // Make sure reset with no arguments resets them all:
74 EXPECT_EQ(true, signals.SetShouldSuppress(2, !suppress_val));
75 EXPECT_EQ(true, signals.SetShouldNotify(2, !notify_val));
76 EXPECT_EQ(true, signals.ResetSignal(2));
77 EXPECT_EQ(stop_val, signals.GetShouldStop(2));
78 EXPECT_EQ(notify_val, signals.GetShouldNotify(2));
79 EXPECT_EQ(suppress_val, signals.GetShouldSuppress(2));
80}
81
82TEST(UnixSignalsTest, GetInfo) {
83 TestSignals signals;
84
85 bool should_suppress = false, should_stop = false, should_notify = false;
86 int32_t signo = 4;
87 bool success =
88 signals.GetSignalInfo(signo, should_suppress, should_stop, should_notify);
89 ASSERT_TRUE(success);
90 EXPECT_EQ(true, should_suppress);
91 EXPECT_EQ(false, should_stop);
92 EXPECT_EQ(true, should_notify);
93
94 EXPECT_EQ(true, signals.GetShouldSuppress(signo));
95 EXPECT_EQ(false, signals.GetShouldStop(signo));
96 EXPECT_EQ(true, signals.GetShouldNotify(signo));
97}
98
99TEST(UnixSignalsTest, GetAsStringRef) {
100 TestSignals signals;
101
102 ASSERT_EQ(llvm::StringRef(), signals.GetSignalAsStringRef(100));
103 ASSERT_EQ("SIG16", signals.GetSignalAsStringRef(16));
104}
105
106TEST(UnixSignalsTest, GetAsString) {
107 TestSignals signals;
108
109 ASSERT_EQ("", signals.GetSignalDescription(100, std::nullopt));
110 ASSERT_EQ("SIG16", signals.GetSignalDescription(16, std::nullopt));
111 ASSERT_EQ("", signals.GetSignalDescription(100, 100));
112 ASSERT_EQ("SIG16", signals.GetSignalDescription(16, 100));
113 ASSERT_EQ("SIG16: a specific type of SIG16",
114 signals.GetSignalDescription(16, 1));
115
116 // Unknown code, won't use the address.
117 ASSERT_EQ("SIG16", signals.GetSignalDescription(16, 100, 0xCAFEF00D));
118 // Known code, that shouldn't print fault address.
119 ASSERT_EQ("SIG16: a specific type of SIG16",
120 signals.GetSignalDescription(16, 1, 0xCAFEF00D));
121 // Known code that should.
122 ASSERT_EQ("SIG16: SIG16 with a fault address (fault address: 0xcafef00d)",
123 signals.GetSignalDescription(16, 2, 0xCAFEF00D));
124 // No address given just print the code description.
125 ASSERT_EQ("SIG16: SIG16 with a fault address",
126 signals.GetSignalDescription(16, 2));
127
128 const char *expected = "SIG16: bounds violation";
129 // Must pass all needed info to get full output.
130 ASSERT_EQ(expected, signals.GetSignalDescription(16, 3));
131 ASSERT_EQ(expected, signals.GetSignalDescription(16, 3, 0xcafef00d));
132 ASSERT_EQ(expected, signals.GetSignalDescription(16, 3, 0xcafef00d, 0x1234));
133
134 ASSERT_EQ("SIG16: upper bound violation (fault address: 0x5679, lower bound: "
135 "0x1234, upper bound: 0x5678)",
136 signals.GetSignalDescription(16, 3, 0x5679, 0x1234, 0x5678));
137 ASSERT_EQ("SIG16: lower bound violation (fault address: 0x1233, lower bound: "
138 "0x1234, upper bound: 0x5678)",
139 signals.GetSignalDescription(16, 3, 0x1233, 0x1234, 0x5678));
140}
141
142TEST(UnixSignalsTest, VersionChange) {
143 TestSignals signals;
144
145 int32_t signo = 8;
146 uint64_t ver = signals.GetVersion();
147 EXPECT_GT(ver, 0ull);
148 EXPECT_EQ(true, signals.GetShouldSuppress(signo));
149 EXPECT_EQ(true, signals.GetShouldStop(signo));
150 EXPECT_EQ(true, signals.GetShouldNotify(signo));
151
152 EXPECT_EQ(signals.GetVersion(), ver);
153
154 signals.SetShouldSuppress(signo, value: false);
155 EXPECT_LT(ver, signals.GetVersion());
156 ver = signals.GetVersion();
157
158 signals.SetShouldStop(signo, value: true);
159 EXPECT_LT(ver, signals.GetVersion());
160 ver = signals.GetVersion();
161
162 signals.SetShouldNotify(signo, value: false);
163 EXPECT_LT(ver, signals.GetVersion());
164 ver = signals.GetVersion();
165
166 EXPECT_EQ(false, signals.GetShouldSuppress(signo));
167 EXPECT_EQ(true, signals.GetShouldStop(signo));
168 EXPECT_EQ(false, signals.GetShouldNotify(signo));
169
170 EXPECT_EQ(ver, signals.GetVersion());
171}
172
173TEST(UnixSignalsTest, GetFilteredSignals) {
174 TestSignals signals;
175
176 auto all_signals =
177 signals.GetFilteredSignals(should_suppress: std::nullopt, should_stop: std::nullopt, should_notify: std::nullopt);
178 std::vector<int32_t> expected = {2, 4, 8, 16};
179 EXPECT_EQ_ARRAYS(expected, all_signals);
180
181 auto supressed = signals.GetFilteredSignals(should_suppress: true, should_stop: std::nullopt, should_notify: std::nullopt);
182 expected = {4, 8, 16};
183 EXPECT_EQ_ARRAYS(expected, supressed);
184
185 auto not_supressed =
186 signals.GetFilteredSignals(should_suppress: false, should_stop: std::nullopt, should_notify: std::nullopt);
187 expected = {2};
188 EXPECT_EQ_ARRAYS(expected, not_supressed);
189
190 auto stopped = signals.GetFilteredSignals(should_suppress: std::nullopt, should_stop: true, should_notify: std::nullopt);
191 expected = {2, 8};
192 EXPECT_EQ_ARRAYS(expected, stopped);
193
194 auto not_stopped =
195 signals.GetFilteredSignals(should_suppress: std::nullopt, should_stop: false, should_notify: std::nullopt);
196 expected = {4, 16};
197 EXPECT_EQ_ARRAYS(expected, not_stopped);
198
199 auto notified = signals.GetFilteredSignals(should_suppress: std::nullopt, should_stop: std::nullopt, should_notify: true);
200 expected = {2, 4, 8};
201 EXPECT_EQ_ARRAYS(expected, notified);
202
203 auto not_notified =
204 signals.GetFilteredSignals(should_suppress: std::nullopt, should_stop: std::nullopt, should_notify: false);
205 expected = {16};
206 EXPECT_EQ_ARRAYS(expected, not_notified);
207
208 auto signal4 = signals.GetFilteredSignals(should_suppress: true, should_stop: false, should_notify: true);
209 expected = {4};
210 EXPECT_EQ_ARRAYS(expected, signal4);
211}
212

source code of lldb/unittests/Signals/UnixSignalsTest.cpp