OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 #include "util/posix/symbolic_constants_posix.h" |
| 16 |
| 17 #include <sys/signal.h> |
| 18 |
| 19 #include "base/basictypes.h" |
| 20 #include "base/strings/string_piece.h" |
| 21 #include "base/strings/stringprintf.h" |
| 22 #include "gtest/gtest.h" |
| 23 |
| 24 namespace { |
| 25 |
| 26 using namespace crashpad; |
| 27 |
| 28 const struct { |
| 29 int signal; |
| 30 const char* full_name; |
| 31 const char* short_name; |
| 32 } kSignalTestData[] = { |
| 33 {SIGABRT, "SIGABRT", "ABRT"}, |
| 34 {SIGALRM, "SIGALRM", "ALRM"}, |
| 35 {SIGBUS, "SIGBUS", "BUS"}, |
| 36 {SIGCHLD, "SIGCHLD", "CHLD"}, |
| 37 {SIGCONT, "SIGCONT", "CONT"}, |
| 38 {SIGFPE, "SIGFPE", "FPE"}, |
| 39 {SIGHUP, "SIGHUP", "HUP"}, |
| 40 {SIGILL, "SIGILL", "ILL"}, |
| 41 {SIGINT, "SIGINT", "INT"}, |
| 42 {SIGIO, "SIGIO", "IO"}, |
| 43 {SIGKILL, "SIGKILL", "KILL"}, |
| 44 {SIGPIPE, "SIGPIPE", "PIPE"}, |
| 45 {SIGPROF, "SIGPROF", "PROF"}, |
| 46 {SIGQUIT, "SIGQUIT", "QUIT"}, |
| 47 {SIGSEGV, "SIGSEGV", "SEGV"}, |
| 48 {SIGSTOP, "SIGSTOP", "STOP"}, |
| 49 {SIGSYS, "SIGSYS", "SYS"}, |
| 50 {SIGTERM, "SIGTERM", "TERM"}, |
| 51 {SIGTRAP, "SIGTRAP", "TRAP"}, |
| 52 {SIGTSTP, "SIGTSTP", "TSTP"}, |
| 53 {SIGTTIN, "SIGTTIN", "TTIN"}, |
| 54 {SIGTTOU, "SIGTTOU", "TTOU"}, |
| 55 {SIGURG, "SIGURG", "URG"}, |
| 56 {SIGUSR1, "SIGUSR1", "USR1"}, |
| 57 {SIGUSR2, "SIGUSR2", "USR2"}, |
| 58 {SIGVTALRM, "SIGVTALRM", "VTALRM"}, |
| 59 {SIGWINCH, "SIGWINCH", "WINCH"}, |
| 60 {SIGXCPU, "SIGXCPU", "XCPU"}, |
| 61 #if defined(OS_MACOSX) |
| 62 {SIGEMT, "SIGEMT", "EMT"}, |
| 63 {SIGINFO, "SIGINFO", "INFO"}, |
| 64 #elif defined(OS_LINUX) |
| 65 {SIGPWR, "SIGPWR", "PWR"}, |
| 66 {SIGSTKFLT, "SIGSTKFLT", "STKFLT"}, |
| 67 #endif |
| 68 }; |
| 69 |
| 70 // If expect is NULL, the conversion is expected to fail. If expect is empty, |
| 71 // the conversion is expected to succeed, but the precise returned string value |
| 72 // is unknown. Otherwise, the conversion is expected to succeed, and expect |
| 73 // contains the precise expected string value to be returned. |
| 74 // |
| 75 // Only set kUseFullName or kUseShortName when calling this. Other options are |
| 76 // exercised directly by this function. |
| 77 void TestSignalToStringOnce(int value, |
| 78 const char* expect, |
| 79 SymbolicConstantToStringOptions options) { |
| 80 std::string actual = SignalToString(value, options | kUnknownIsEmpty); |
| 81 std::string actual_numeric = |
| 82 SignalToString(value, options | kUnknownIsNumeric); |
| 83 if (expect) { |
| 84 if (expect[0] == '\0') { |
| 85 EXPECT_FALSE(actual.empty()) << "signal " << value; |
| 86 } else { |
| 87 EXPECT_EQ(expect, actual) << "signal " << value; |
| 88 } |
| 89 EXPECT_EQ(actual, actual_numeric) << "signal " << value; |
| 90 } else { |
| 91 EXPECT_TRUE(actual.empty()) << "signal " << value << ", actual " << actual; |
| 92 EXPECT_FALSE(actual_numeric.empty()) |
| 93 << "signal " << value << ", actual_numeric " << actual_numeric; |
| 94 } |
| 95 } |
| 96 |
| 97 void TestSignalToString(int value, |
| 98 const char* expect_full, |
| 99 const char* expect_short) { |
| 100 { |
| 101 SCOPED_TRACE("full_name"); |
| 102 TestSignalToStringOnce(value, expect_full, kUseFullName); |
| 103 } |
| 104 |
| 105 { |
| 106 SCOPED_TRACE("short_name"); |
| 107 TestSignalToStringOnce(value, expect_short, kUseShortName); |
| 108 } |
| 109 } |
| 110 |
| 111 TEST(SymbolicConstantsPOSIX, SignalToString) { |
| 112 for (size_t index = 0; index < arraysize(kSignalTestData); ++index) { |
| 113 SCOPED_TRACE(base::StringPrintf("index %zu", index)); |
| 114 TestSignalToString(kSignalTestData[index].signal, |
| 115 kSignalTestData[index].full_name, |
| 116 kSignalTestData[index].short_name); |
| 117 } |
| 118 |
| 119 #if defined(OS_LINUX) |
| 120 // NSIG is 64 to account for real-time signals. |
| 121 const int kSignalCount = 32; |
| 122 #else |
| 123 const int kSignalCount = NSIG; |
| 124 #endif |
| 125 |
| 126 for (int signal = 0; signal < kSignalCount + 8; ++signal) { |
| 127 SCOPED_TRACE(base::StringPrintf("signal %d", signal)); |
| 128 if (signal > 0 && signal < kSignalCount) { |
| 129 TestSignalToString(signal, "", ""); |
| 130 } else { |
| 131 TestSignalToString(signal, NULL, NULL); |
| 132 } |
| 133 } |
| 134 } |
| 135 |
| 136 void TestStringToSignal(const base::StringPiece& string, |
| 137 StringToSymbolicConstantOptions options, |
| 138 bool expect_result, |
| 139 int expect_value) { |
| 140 int actual_value; |
| 141 bool actual_result = StringToSignal(string, options, &actual_value); |
| 142 if (expect_result) { |
| 143 EXPECT_TRUE(actual_result) << "string " << string << ", options " << options |
| 144 << ", signal " << expect_value; |
| 145 if (actual_result) { |
| 146 EXPECT_EQ(expect_value, actual_value) << "string " << string |
| 147 << ", options " << options; |
| 148 } |
| 149 } else { |
| 150 EXPECT_FALSE(actual_result) << "string " << string << ", options " |
| 151 << options << ", signal " << actual_value; |
| 152 } |
| 153 } |
| 154 |
| 155 TEST(SymbolicConstantsPOSIX, StringToSignal) { |
| 156 const StringToSymbolicConstantOptions kOptions[] = { |
| 157 0, |
| 158 kAllowFullName, |
| 159 kAllowShortName, |
| 160 kAllowFullName | kAllowShortName, |
| 161 kAllowNumber, |
| 162 kAllowFullName | kAllowNumber, |
| 163 kAllowShortName | kAllowNumber, |
| 164 kAllowFullName | kAllowShortName | kAllowNumber, |
| 165 }; |
| 166 |
| 167 for (size_t option_index = 0; option_index < arraysize(kOptions); |
| 168 ++option_index) { |
| 169 SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); |
| 170 StringToSymbolicConstantOptions options = kOptions[option_index]; |
| 171 for (size_t index = 0; index < arraysize(kSignalTestData); ++index) { |
| 172 SCOPED_TRACE(base::StringPrintf("index %zu", index)); |
| 173 int signal = kSignalTestData[index].signal; |
| 174 { |
| 175 SCOPED_TRACE("full_name"); |
| 176 TestStringToSignal(kSignalTestData[index].full_name, |
| 177 options, |
| 178 options & kAllowFullName, |
| 179 signal); |
| 180 } |
| 181 { |
| 182 SCOPED_TRACE("short_name"); |
| 183 TestStringToSignal(kSignalTestData[index].short_name, |
| 184 options, |
| 185 options & kAllowShortName, |
| 186 signal); |
| 187 } |
| 188 { |
| 189 SCOPED_TRACE("number"); |
| 190 std::string number_string = base::StringPrintf("%d", signal); |
| 191 TestStringToSignal( |
| 192 number_string, options, options & kAllowNumber, signal); |
| 193 } |
| 194 } |
| 195 |
| 196 const char* const kNegativeTestData[] = { |
| 197 "SIGHUP ", |
| 198 " SIGINT", |
| 199 "QUIT ", |
| 200 " ILL", |
| 201 "SIGSIGTRAP", |
| 202 "SIGABRTRON", |
| 203 "FPES", |
| 204 "SIGGARBAGE", |
| 205 "random", |
| 206 "", |
| 207 }; |
| 208 |
| 209 for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { |
| 210 SCOPED_TRACE(base::StringPrintf("index %zu", index)); |
| 211 TestStringToSignal(kNegativeTestData[index], options, false, 0); |
| 212 } |
| 213 |
| 214 const struct { |
| 215 const char* string; |
| 216 size_t length; |
| 217 } kNULTestData[] = { |
| 218 #define NUL_TEST_DATA(string) { string, arraysize(string) - 1 } |
| 219 NUL_TEST_DATA("\0SIGBUS"), |
| 220 NUL_TEST_DATA("SIG\0BUS"), |
| 221 NUL_TEST_DATA("SIGB\0US"), |
| 222 NUL_TEST_DATA("SIGBUS\0"), |
| 223 NUL_TEST_DATA("\0BUS"), |
| 224 NUL_TEST_DATA("BUS\0"), |
| 225 NUL_TEST_DATA("B\0US"), |
| 226 NUL_TEST_DATA("\0002"), |
| 227 NUL_TEST_DATA("2\0"), |
| 228 NUL_TEST_DATA("1\0002"), |
| 229 #undef NUL_TEST_DATA |
| 230 }; |
| 231 |
| 232 for (size_t index = 0; index < arraysize(kNULTestData); ++index) { |
| 233 SCOPED_TRACE(base::StringPrintf("index %zu", index)); |
| 234 base::StringPiece string(kNULTestData[index].string, |
| 235 kNULTestData[index].length); |
| 236 TestStringToSignal(string, options, false, 0); |
| 237 } |
| 238 } |
| 239 |
| 240 // Ensure that a NUL is not required at the end of the string. |
| 241 { |
| 242 SCOPED_TRACE("trailing_NUL_full"); |
| 243 TestStringToSignal( |
| 244 base::StringPiece("SIGBUST", 6), kAllowFullName, true, SIGBUS); |
| 245 } |
| 246 { |
| 247 SCOPED_TRACE("trailing_NUL_short"); |
| 248 TestStringToSignal( |
| 249 base::StringPiece("BUST", 3), kAllowShortName, true, SIGBUS); |
| 250 } |
| 251 } |
| 252 |
| 253 } // namespace |
OLD | NEW |