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