xref: /llvm-project/lldb/unittests/Signals/UnixSignalsTest.cpp (revision 0236cb689550ed2dac406443c652efb723cb2602)
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 
15 using namespace lldb;
16 using namespace lldb_private;
17 
18 class TestSignals : public UnixSignals {
19 public:
20   TestSignals() {
21     m_signals.clear();
22     AddSignal(2, "SIG2", false, true, true, "DESC2");
23     AddSignal(4, "SIG4", true, false, true, "DESC4");
24     AddSignal(8, "SIG8", true, true, true, "DESC8");
25     AddSignal(16, "SIG16", true, false, false, "DESC16");
26     AddSignalCode(16, 1, "a specific type of SIG16");
27     AddSignalCode(16, 2, "SIG16 with a fault address",
28                   SignalCodePrintOption::Address);
29     AddSignalCode(16, 3, "bounds violation", SignalCodePrintOption::Bounds);
30   }
31 };
32 
33 void ExpectEqArrays(llvm::ArrayRef<int32_t> expected,
34                     llvm::ArrayRef<int32_t> observed, const char *file,
35                     int line) {
36   std::string location = llvm::formatv("{0}:{1}", file, 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 
48 TEST(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 
59 TEST(UnixSignalsTest, Reset) {
60   TestSignals signals;
61   bool stop_val     = signals.GetShouldStop(2);
62   bool notify_val   = signals.GetShouldNotify(2);
63   bool suppress_val = signals.GetShouldSuppress(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 
82 TEST(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 
99 TEST(UnixSignalsTest, GetAsStringRef) {
100   TestSignals signals;
101 
102   ASSERT_EQ(llvm::StringRef(), signals.GetSignalAsStringRef(100));
103   ASSERT_EQ("SIG16", signals.GetSignalAsStringRef(16));
104 }
105 
106 TEST(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 
142 TEST(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, false);
155   EXPECT_LT(ver, signals.GetVersion());
156   ver = signals.GetVersion();
157 
158   signals.SetShouldStop(signo, true);
159   EXPECT_LT(ver, signals.GetVersion());
160   ver = signals.GetVersion();
161 
162   signals.SetShouldNotify(signo, 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 
173 TEST(UnixSignalsTest, GetFilteredSignals) {
174   TestSignals signals;
175 
176   auto all_signals =
177       signals.GetFilteredSignals(std::nullopt, std::nullopt, 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(true, std::nullopt, std::nullopt);
182   expected = {4, 8, 16};
183   EXPECT_EQ_ARRAYS(expected, supressed);
184 
185   auto not_supressed =
186       signals.GetFilteredSignals(false, std::nullopt, std::nullopt);
187   expected = {2};
188   EXPECT_EQ_ARRAYS(expected, not_supressed);
189 
190   auto stopped = signals.GetFilteredSignals(std::nullopt, true, std::nullopt);
191   expected = {2, 8};
192   EXPECT_EQ_ARRAYS(expected, stopped);
193 
194   auto not_stopped =
195       signals.GetFilteredSignals(std::nullopt, false, std::nullopt);
196   expected = {4, 16};
197   EXPECT_EQ_ARRAYS(expected, not_stopped);
198 
199   auto notified = signals.GetFilteredSignals(std::nullopt, std::nullopt, true);
200   expected = {2, 4, 8};
201   EXPECT_EQ_ARRAYS(expected, notified);
202 
203   auto not_notified =
204       signals.GetFilteredSignals(std::nullopt, std::nullopt, false);
205   expected = {16};
206   EXPECT_EQ_ARRAYS(expected, not_notified);
207 
208   auto signal4 = signals.GetFilteredSignals(true, false, true);
209   expected = {4};
210   EXPECT_EQ_ARRAYS(expected, signal4);
211 }
212