Chromium Code Reviews| 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/mach/symbolic_constants_mach.h" | |
| 16 | |
| 17 #include <mach/mach.h> | |
| 18 #include <string.h> | |
| 19 | |
| 20 #include "base/basictypes.h" | |
| 21 #include "base/strings/string_piece.h" | |
| 22 #include "base/strings/stringprintf.h" | |
| 23 #include "gtest/gtest.h" | |
| 24 #include "util/mach/mach_extensions.h" | |
| 25 | |
| 26 namespace { | |
| 27 | |
| 28 using namespace crashpad; | |
| 29 | |
| 30 // If expect is NULL, the conversion is expected to fail. If expect is empty, | |
|
Robert Sesek
2014/09/15 23:00:16
Use |expect| so that it's clear you're talking abo
| |
| 31 // the conversion is expected to succeed, but the precise returned string value | |
| 32 // is unknown. Otherwise, the conversion is expected to succeed, and expect | |
| 33 // contains the precise expected string value to be returned. If expect contains | |
| 34 // the substring "0x1", the conversion is expected only to succeed when | |
| 35 // kUnknownIsNumeric is set. | |
| 36 // | |
| 37 // Only set kUseFullName or kUseShortName when calling this. Other options are | |
| 38 // exercised directly by this function. | |
| 39 template <typename Traits> | |
| 40 void TestSomethingToStringOnce(typename Traits::ValueType value, | |
| 41 const char* expect, | |
| 42 SymbolicConstantToStringOptions options) { | |
| 43 std::string actual = | |
| 44 Traits::SomethingToString(value, options | kUnknownIsEmpty | kUseOr); | |
| 45 std::string actual_numeric = | |
| 46 Traits::SomethingToString(value, options | kUnknownIsNumeric | kUseOr); | |
| 47 if (expect) { | |
| 48 if (expect[0] == '\0') { | |
| 49 EXPECT_FALSE(actual.empty()) << Traits::kValueName << " " << value; | |
| 50 } else if (strstr(expect, "0x1")) { | |
| 51 EXPECT_TRUE(actual.empty()) << Traits::kValueName << " " << value | |
| 52 << ", actual " << actual; | |
| 53 actual.assign(expect); | |
| 54 } else { | |
| 55 EXPECT_EQ(expect, actual) << Traits::kValueName << " " << value; | |
| 56 } | |
| 57 EXPECT_EQ(actual, actual_numeric) << Traits::kValueName << " " << value; | |
| 58 } else { | |
| 59 EXPECT_TRUE(actual.empty()) << Traits::kValueName << " " << value | |
| 60 << ", actual " << actual; | |
| 61 EXPECT_FALSE(actual_numeric.empty()) << Traits::kValueName << " " << value | |
| 62 << ", actual_numeric " | |
| 63 << actual_numeric; | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 template <typename Traits> | |
| 68 void TestSomethingToString(typename Traits::ValueType value, | |
| 69 const char* expect_full, | |
| 70 const char* expect_short) { | |
| 71 { | |
| 72 SCOPED_TRACE("full_name"); | |
| 73 TestSomethingToStringOnce<Traits>(value, expect_full, kUseFullName); | |
| 74 } | |
| 75 | |
| 76 { | |
| 77 SCOPED_TRACE("short_name"); | |
| 78 TestSomethingToStringOnce<Traits>(value, expect_short, kUseShortName); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 template <typename Traits> | |
| 83 void TestStringToSomething(const base::StringPiece& string, | |
| 84 StringToSymbolicConstantOptions options, | |
| 85 bool expect_result, | |
| 86 typename Traits::ValueType expect_value) { | |
| 87 typename Traits::ValueType actual_value; | |
| 88 bool actual_result = | |
| 89 Traits::StringToSomething(string, options, &actual_value); | |
| 90 if (expect_result) { | |
| 91 EXPECT_TRUE(actual_result) << "string " << string << ", options " << options | |
| 92 << ", " << Traits::kValueName << " " | |
| 93 << expect_value; | |
| 94 if (actual_result) { | |
| 95 EXPECT_EQ(expect_value, actual_value) << "string " << string | |
| 96 << ", options " << options; | |
| 97 } | |
| 98 } else { | |
| 99 EXPECT_FALSE(actual_result) << "string " << string << ", options " | |
| 100 << options << ", " << Traits::kValueName << " " | |
| 101 << actual_value; | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 const struct { | |
| 106 exception_type_t exception; | |
| 107 const char* full_name; | |
| 108 const char* short_name; | |
| 109 } kExceptionTestData[] = { | |
| 110 {EXC_BAD_ACCESS, "EXC_BAD_ACCESS", "BAD_ACCESS"}, | |
| 111 {EXC_BAD_INSTRUCTION, "EXC_BAD_INSTRUCTION", "BAD_INSTRUCTION"}, | |
| 112 {EXC_ARITHMETIC, "EXC_ARITHMETIC", "ARITHMETIC"}, | |
| 113 {EXC_EMULATION, "EXC_EMULATION", "EMULATION"}, | |
| 114 {EXC_SOFTWARE, "EXC_SOFTWARE", "SOFTWARE"}, | |
| 115 {EXC_MACH_SYSCALL, "EXC_MACH_SYSCALL", "MACH_SYSCALL"}, | |
| 116 {EXC_RPC_ALERT, "EXC_RPC_ALERT", "RPC_ALERT"}, | |
| 117 {EXC_CRASH, "EXC_CRASH", "CRASH"}, | |
| 118 {EXC_RESOURCE, "EXC_RESOURCE", "RESOURCE"}, | |
| 119 {EXC_GUARD, "EXC_GUARD", "GUARD"}, | |
| 120 }; | |
| 121 | |
| 122 struct ConvertExceptionTraits { | |
| 123 typedef exception_type_t ValueType; | |
| 124 static std::string SomethingToString( | |
| 125 ValueType value, | |
| 126 SymbolicConstantToStringOptions options) { | |
| 127 return ExceptionToString(value, options); | |
| 128 } | |
| 129 static bool StringToSomething(const base::StringPiece& string, | |
| 130 StringToSymbolicConstantOptions options, | |
| 131 ValueType* value) { | |
| 132 return StringToException(string, options, value); | |
| 133 } | |
| 134 static const char kValueName[]; | |
| 135 }; | |
| 136 const char ConvertExceptionTraits::kValueName[] = "exception"; | |
| 137 | |
| 138 void TestExceptionToString(exception_type_t value, | |
| 139 const char* expect_full, | |
| 140 const char* expect_short) { | |
| 141 return TestSomethingToString<ConvertExceptionTraits>( | |
| 142 value, expect_full, expect_short); | |
| 143 } | |
| 144 | |
| 145 TEST(SymbolicConstantsMach, ExceptionToString) { | |
| 146 for (size_t index = 0; index < arraysize(kExceptionTestData); ++index) { | |
| 147 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 148 TestExceptionToString(kExceptionTestData[index].exception, | |
| 149 kExceptionTestData[index].full_name, | |
| 150 kExceptionTestData[index].short_name); | |
| 151 } | |
| 152 | |
| 153 for (exception_type_t exception = 0; exception < EXC_TYPES_COUNT + 8; | |
| 154 ++exception) { | |
| 155 SCOPED_TRACE(base::StringPrintf("exception %d", exception)); | |
| 156 if (exception > 0 && exception < EXC_TYPES_COUNT) { | |
| 157 TestExceptionToString(exception, "", ""); | |
| 158 } else { | |
| 159 TestExceptionToString(exception, NULL, NULL); | |
| 160 } | |
| 161 } | |
| 162 } | |
| 163 | |
| 164 void TestStringToException(const base::StringPiece& string, | |
| 165 StringToSymbolicConstantOptions options, | |
| 166 bool expect_result, | |
| 167 exception_type_t expect_value) { | |
| 168 return TestStringToSomething<ConvertExceptionTraits>( | |
| 169 string, options, expect_result, expect_value); | |
| 170 } | |
| 171 | |
| 172 TEST(SymbolicConstantsMach, StringToException) { | |
| 173 const StringToSymbolicConstantOptions kOptions[] = { | |
| 174 0, | |
| 175 kAllowFullName, | |
| 176 kAllowShortName, | |
| 177 kAllowFullName | kAllowShortName, | |
| 178 kAllowNumber, | |
| 179 kAllowFullName | kAllowNumber, | |
| 180 kAllowShortName | kAllowNumber, | |
| 181 kAllowFullName | kAllowShortName | kAllowNumber, | |
| 182 }; | |
| 183 | |
| 184 for (size_t option_index = 0; option_index < arraysize(kOptions); | |
| 185 ++option_index) { | |
| 186 SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); | |
| 187 StringToSymbolicConstantOptions options = kOptions[option_index]; | |
| 188 for (size_t index = 0; index < arraysize(kExceptionTestData); ++index) { | |
| 189 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 190 exception_type_t exception = kExceptionTestData[index].exception; | |
| 191 { | |
| 192 SCOPED_TRACE("full_name"); | |
| 193 TestStringToException(kExceptionTestData[index].full_name, | |
| 194 options, | |
| 195 options & kAllowFullName, | |
| 196 exception); | |
| 197 } | |
| 198 { | |
| 199 SCOPED_TRACE("short_name"); | |
| 200 TestStringToException(kExceptionTestData[index].short_name, | |
| 201 options, | |
| 202 options & kAllowShortName, | |
| 203 exception); | |
| 204 } | |
| 205 { | |
| 206 SCOPED_TRACE("number"); | |
| 207 std::string number_string = base::StringPrintf("%d", exception); | |
| 208 TestStringToException( | |
| 209 number_string, options, options & kAllowNumber, exception); | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 const char* const kNegativeTestData[] = { | |
| 214 "EXC_CRASH ", | |
| 215 " EXC_BAD_INSTRUCTION", | |
| 216 "CRASH ", | |
| 217 " BAD_INSTRUCTION", | |
| 218 "EXC_EXC_BAD_ACCESS", | |
| 219 "EXC_SOFTWARES", | |
| 220 "SOFTWARES", | |
| 221 "EXC_JUNK", | |
| 222 "random", | |
| 223 "", | |
| 224 }; | |
| 225 | |
| 226 for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { | |
| 227 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 228 TestStringToException(kNegativeTestData[index], options, false, 0); | |
| 229 } | |
| 230 | |
| 231 const struct { | |
| 232 const char* string; | |
| 233 size_t length; | |
| 234 } kNULTestData[] = { | |
| 235 #define NUL_TEST_DATA(string) { string, arraysize(string) - 1 } | |
| 236 NUL_TEST_DATA("\0EXC_ARITHMETIC"), | |
| 237 NUL_TEST_DATA("EXC_\0ARITHMETIC"), | |
| 238 NUL_TEST_DATA("EXC_ARITH\0METIC"), | |
| 239 NUL_TEST_DATA("EXC_ARITHMETIC\0"), | |
| 240 NUL_TEST_DATA("\0ARITHMETIC"), | |
| 241 NUL_TEST_DATA("ARITH\0METIC"), | |
| 242 NUL_TEST_DATA("ARITHMETIC\0"), | |
| 243 NUL_TEST_DATA("\0003"), | |
| 244 NUL_TEST_DATA("3\0"), | |
| 245 NUL_TEST_DATA("1\0002"), | |
| 246 #undef NUL_TEST_DATA | |
| 247 }; | |
| 248 | |
| 249 for (size_t index = 0; index < arraysize(kNULTestData); ++index) { | |
| 250 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 251 base::StringPiece string(kNULTestData[index].string, | |
| 252 kNULTestData[index].length); | |
| 253 TestStringToException(string, options, false, 0); | |
| 254 } | |
| 255 } | |
| 256 | |
| 257 // Ensure that a NUL is not required at the end of the string. | |
| 258 { | |
| 259 SCOPED_TRACE("trailing_NUL_full"); | |
| 260 TestStringToException(base::StringPiece("EXC_BREAKPOINTED", 14), | |
| 261 kAllowFullName, | |
| 262 true, | |
| 263 EXC_BREAKPOINT); | |
| 264 } | |
| 265 { | |
| 266 SCOPED_TRACE("trailing_NUL_short"); | |
| 267 TestStringToException(base::StringPiece("BREAKPOINTED", 10), | |
| 268 kAllowShortName, | |
| 269 true, | |
| 270 EXC_BREAKPOINT); | |
| 271 } | |
| 272 } | |
| 273 | |
| 274 const struct { | |
| 275 exception_mask_t exception_mask; | |
| 276 const char* full_name; | |
| 277 const char* short_name; | |
| 278 } kExceptionMaskTestData[] = { | |
| 279 {EXC_MASK_BAD_ACCESS, "EXC_MASK_BAD_ACCESS", "BAD_ACCESS"}, | |
| 280 {EXC_MASK_BAD_INSTRUCTION, "EXC_MASK_BAD_INSTRUCTION", "BAD_INSTRUCTION"}, | |
| 281 {EXC_MASK_ARITHMETIC, "EXC_MASK_ARITHMETIC", "ARITHMETIC"}, | |
| 282 {EXC_MASK_EMULATION, "EXC_MASK_EMULATION", "EMULATION"}, | |
| 283 {EXC_MASK_SOFTWARE, "EXC_MASK_SOFTWARE", "SOFTWARE"}, | |
| 284 {EXC_MASK_MACH_SYSCALL, "EXC_MASK_MACH_SYSCALL", "MACH_SYSCALL"}, | |
| 285 {EXC_MASK_RPC_ALERT, "EXC_MASK_RPC_ALERT", "RPC_ALERT"}, | |
| 286 {EXC_MASK_CRASH, "EXC_MASK_CRASH", "CRASH"}, | |
| 287 {EXC_MASK_RESOURCE, "EXC_MASK_RESOURCE", "RESOURCE"}, | |
| 288 {EXC_MASK_GUARD, "EXC_MASK_GUARD", "GUARD"}, | |
|
Robert Sesek
2014/09/15 23:00:16
Will this compile on 10.6?
Mark Mentovai
2014/09/16 13:42:17
rsesek wrote:
| |
| 289 {0x1, "0x1", "0x1"}, | |
| 290 {EXC_MASK_CRASH | 0x1, "EXC_MASK_CRASH|0x1", "CRASH|0x1"}, | |
| 291 {EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | | |
| 292 EXC_MASK_EMULATION | | |
| 293 EXC_MASK_SOFTWARE | | |
| 294 EXC_MASK_BREAKPOINT | | |
| 295 EXC_MASK_SYSCALL | | |
| 296 EXC_MASK_MACH_SYSCALL | | |
| 297 EXC_MASK_RPC_ALERT, | |
| 298 "EXC_MASK_BAD_ACCESS|EXC_MASK_BAD_INSTRUCTION|EXC_MASK_ARITHMETIC|" | |
| 299 "EXC_MASK_EMULATION|EXC_MASK_SOFTWARE|EXC_MASK_BREAKPOINT|" | |
| 300 "EXC_MASK_SYSCALL|EXC_MASK_MACH_SYSCALL|EXC_MASK_RPC_ALERT", | |
| 301 "BAD_ACCESS|BAD_INSTRUCTION|ARITHMETIC|EMULATION|SOFTWARE|BREAKPOINT|" | |
| 302 "SYSCALL|MACH_SYSCALL|RPC_ALERT"}, | |
| 303 {EXC_MASK_RESOURCE | EXC_MASK_GUARD, | |
| 304 "EXC_MASK_RESOURCE|EXC_MASK_GUARD", | |
| 305 "RESOURCE|GUARD"}, | |
| 306 }; | |
| 307 | |
| 308 struct ConvertExceptionMaskTraits { | |
| 309 typedef exception_mask_t ValueType; | |
| 310 static std::string SomethingToString( | |
| 311 ValueType value, | |
| 312 SymbolicConstantToStringOptions options) { | |
| 313 return ExceptionMaskToString(value, options); | |
| 314 } | |
| 315 static bool StringToSomething(const base::StringPiece& string, | |
| 316 StringToSymbolicConstantOptions options, | |
| 317 ValueType* value) { | |
| 318 return StringToExceptionMask(string, options, value); | |
| 319 } | |
| 320 static const char kValueName[]; | |
| 321 }; | |
| 322 const char ConvertExceptionMaskTraits::kValueName[] = "exception_mask"; | |
| 323 | |
| 324 void TestExceptionMaskToString(exception_mask_t value, | |
| 325 const char* expect_full, | |
| 326 const char* expect_short) { | |
| 327 return TestSomethingToString<ConvertExceptionMaskTraits>( | |
| 328 value, expect_full, expect_short); | |
| 329 } | |
| 330 | |
| 331 TEST(SymbolicConstantsMach, ExceptionMaskToString) { | |
| 332 for (size_t index = 0; index < arraysize(kExceptionMaskTestData); ++index) { | |
| 333 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 334 TestExceptionMaskToString(kExceptionMaskTestData[index].exception_mask, | |
| 335 kExceptionMaskTestData[index].full_name, | |
| 336 kExceptionMaskTestData[index].short_name); | |
| 337 } | |
| 338 | |
| 339 // Test kUseOr handling. | |
| 340 EXPECT_TRUE(ExceptionMaskToString(EXC_MASK_CRASH | EXC_MASK_GUARD, | |
| 341 kUseFullName).empty()); | |
| 342 EXPECT_TRUE(ExceptionMaskToString(EXC_MASK_CRASH | EXC_MASK_GUARD, | |
| 343 kUseShortName).empty()); | |
| 344 EXPECT_EQ("0x1400", | |
| 345 ExceptionMaskToString(EXC_MASK_CRASH | EXC_MASK_GUARD, | |
| 346 kUseFullName | kUnknownIsNumeric)); | |
| 347 EXPECT_EQ("0x1400", | |
| 348 ExceptionMaskToString(EXC_MASK_CRASH | EXC_MASK_GUARD, | |
| 349 kUseShortName | kUnknownIsNumeric)); | |
| 350 EXPECT_EQ("EXC_MASK_CRASH|EXC_MASK_GUARD", | |
| 351 ExceptionMaskToString(EXC_MASK_CRASH | EXC_MASK_GUARD, | |
| 352 kUseFullName | kUseOr)); | |
| 353 EXPECT_EQ("CRASH|GUARD", | |
| 354 ExceptionMaskToString(EXC_MASK_CRASH | EXC_MASK_GUARD, | |
| 355 kUseShortName | kUseOr)); | |
| 356 } | |
| 357 | |
| 358 void TestStringToExceptionMask(const base::StringPiece& string, | |
| 359 StringToSymbolicConstantOptions options, | |
| 360 bool expect_result, | |
| 361 exception_mask_t expect_value) { | |
| 362 return TestStringToSomething<ConvertExceptionMaskTraits>( | |
| 363 string, options, expect_result, expect_value); | |
| 364 } | |
| 365 | |
| 366 TEST(SymbolicConstantsMach, StringToExceptionMask) { | |
| 367 const StringToSymbolicConstantOptions kOptions[] = { | |
| 368 0, | |
| 369 kAllowFullName, | |
| 370 kAllowShortName, | |
| 371 kAllowFullName | kAllowShortName, | |
| 372 kAllowNumber, | |
| 373 kAllowFullName | kAllowNumber, | |
| 374 kAllowShortName | kAllowNumber, | |
| 375 kAllowFullName | kAllowShortName | kAllowNumber, | |
| 376 kAllowOr, | |
| 377 kAllowFullName | kAllowOr, | |
| 378 kAllowShortName | kAllowOr, | |
| 379 kAllowFullName | kAllowShortName | kAllowOr, | |
| 380 kAllowNumber | kAllowOr, | |
| 381 kAllowFullName | kAllowNumber | kAllowOr, | |
| 382 kAllowShortName | kAllowNumber | kAllowOr, | |
| 383 kAllowFullName | kAllowShortName | kAllowNumber | kAllowOr, | |
| 384 }; | |
| 385 | |
| 386 for (size_t option_index = 0; option_index < arraysize(kOptions); | |
| 387 ++option_index) { | |
| 388 SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); | |
| 389 StringToSymbolicConstantOptions options = kOptions[option_index]; | |
| 390 for (size_t index = 0; index < arraysize(kExceptionMaskTestData); ++index) { | |
| 391 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 392 exception_mask_t exception_mask = | |
| 393 kExceptionMaskTestData[index].exception_mask; | |
| 394 { | |
| 395 SCOPED_TRACE("full_name"); | |
| 396 base::StringPiece full_name(kExceptionMaskTestData[index].full_name); | |
| 397 bool has_number = full_name.find("0x", 0) != base::StringPiece::npos; | |
| 398 bool has_or = full_name.find('|', 0) != base::StringPiece::npos; | |
| 399 bool allowed_characteristics = | |
| 400 (has_number ? (options & kAllowNumber) : true) && | |
| 401 (has_or ? (options & kAllowOr) : true); | |
| 402 bool is_number = full_name.compare("0x1") == 0; | |
| 403 bool expect_valid = | |
| 404 ((options & kAllowFullName) && allowed_characteristics) || | |
| 405 ((options & kAllowNumber) && is_number); | |
| 406 TestStringToExceptionMask( | |
| 407 full_name, options, expect_valid, exception_mask); | |
| 408 } | |
| 409 { | |
| 410 SCOPED_TRACE("short_name"); | |
| 411 base::StringPiece short_name(kExceptionMaskTestData[index].short_name); | |
| 412 bool has_number = short_name.find("0x", 0) != base::StringPiece::npos; | |
| 413 bool has_or = short_name.find('|', 0) != base::StringPiece::npos; | |
| 414 bool allowed_characteristics = | |
| 415 (has_number ? (options & kAllowNumber) : true) && | |
| 416 (has_or ? (options & kAllowOr) : true); | |
| 417 bool is_number = short_name.compare("0x1") == 0; | |
| 418 bool expect_valid = | |
| 419 ((options & kAllowShortName) && allowed_characteristics) || | |
| 420 ((options & kAllowNumber) && is_number); | |
| 421 TestStringToExceptionMask( | |
| 422 short_name, options, expect_valid, exception_mask); | |
| 423 } | |
| 424 } | |
| 425 | |
| 426 const char* const kNegativeTestData[] = { | |
| 427 "EXC_MASK_CRASH ", | |
| 428 " EXC_MASK_BAD_INSTRUCTION", | |
| 429 "EXC_MASK_EXC_MASK_BAD_ACCESS", | |
| 430 "EXC_MASK_SOFTWARES", | |
| 431 "EXC_MASK_JUNK", | |
| 432 "EXC_GUARD", | |
| 433 "EXC_ARITHMETIC|EXC_FAKE", | |
| 434 "ARITHMETIC|FAKE", | |
| 435 "FAKE|ARITHMETIC", | |
| 436 "EXC_FAKE|EXC_ARITHMETIC", | |
| 437 "random", | |
| 438 "", | |
| 439 }; | |
| 440 | |
| 441 for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { | |
| 442 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 443 TestStringToExceptionMask(kNegativeTestData[index], options, false, 0); | |
| 444 } | |
| 445 | |
| 446 const struct { | |
| 447 const char* string; | |
| 448 size_t length; | |
| 449 } kNULTestData[] = { | |
| 450 #define NUL_TEST_DATA(string) { string, arraysize(string) - 1 } | |
|
Robert Sesek
2014/09/15 23:00:16
Promote this to a file-level #define ?
| |
| 451 NUL_TEST_DATA("\0EXC_MASK_ARITHMETIC"), | |
| 452 NUL_TEST_DATA("EXC_\0MASK_ARITHMETIC"), | |
| 453 NUL_TEST_DATA("EXC_MASK_\0ARITHMETIC"), | |
| 454 NUL_TEST_DATA("EXC_MASK_ARITH\0METIC"), | |
| 455 NUL_TEST_DATA("EXC_MASK_ARITHMETIC\0"), | |
| 456 NUL_TEST_DATA("\0ARITHMETIC"), | |
| 457 NUL_TEST_DATA("ARITH\0METIC"), | |
| 458 NUL_TEST_DATA("ARITHMETIC\0"), | |
| 459 NUL_TEST_DATA("\0003"), | |
| 460 NUL_TEST_DATA("3\0"), | |
| 461 NUL_TEST_DATA("1\0002"), | |
| 462 NUL_TEST_DATA("EXC_MASK_ARITHMETIC\0|EXC_MASK_EMULATION"), | |
| 463 NUL_TEST_DATA("EXC_MASK_ARITHMETIC|\0EXC_MASK_EMULATION"), | |
| 464 NUL_TEST_DATA("ARITHMETIC\0|EMULATION"), | |
| 465 NUL_TEST_DATA("ARITHMETIC|\0EMULATION"), | |
| 466 #undef NUL_TEST_DATA | |
| 467 }; | |
| 468 | |
| 469 for (size_t index = 0; index < arraysize(kNULTestData); ++index) { | |
| 470 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 471 base::StringPiece string(kNULTestData[index].string, | |
| 472 kNULTestData[index].length); | |
| 473 TestStringToExceptionMask(string, options, false, 0); | |
| 474 } | |
| 475 } | |
| 476 | |
| 477 const struct { | |
| 478 const char* string; | |
| 479 StringToSymbolicConstantOptions options; | |
| 480 exception_mask_t mask; | |
| 481 } kNonCanonicalTestData[] = { | |
| 482 {"EXC_MASK_ALL", kAllowFullName, ExcMaskAll()}, | |
| 483 {"ALL", kAllowShortName, ExcMaskAll()}, | |
| 484 {"EXC_MASK_ALL|EXC_MASK_CRASH", | |
| 485 kAllowFullName | kAllowOr, | |
| 486 ExcMaskAll() | EXC_MASK_CRASH}, | |
| 487 {"ALL|CRASH", | |
| 488 kAllowShortName | kAllowOr, | |
| 489 ExcMaskAll() | EXC_MASK_CRASH}, | |
| 490 {"EXC_MASK_BAD_INSTRUCTION|EXC_MASK_BAD_ACCESS", | |
| 491 kAllowFullName | kAllowOr, | |
| 492 EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION}, | |
| 493 {"EMULATION|ARITHMETIC", | |
| 494 kAllowShortName | kAllowOr, | |
| 495 EXC_MASK_ARITHMETIC | EXC_MASK_EMULATION}, | |
| 496 {"EXC_MASK_SOFTWARE|BREAKPOINT", | |
| 497 kAllowFullName | kAllowShortName | kAllowOr, | |
| 498 EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT}, | |
| 499 {"SYSCALL|0x100", | |
| 500 kAllowShortName | kAllowNumber | kAllowOr, | |
| 501 EXC_MASK_SYSCALL | 0x100}, | |
| 502 }; | |
| 503 | |
| 504 for (size_t index = 0; index < arraysize(kNonCanonicalTestData); ++index) { | |
| 505 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 506 TestStringToExceptionMask(kNonCanonicalTestData[index].string, | |
| 507 kNonCanonicalTestData[index].options, | |
| 508 true, | |
| 509 kNonCanonicalTestData[index].mask); | |
| 510 } | |
| 511 | |
| 512 // Ensure that a NUL is not required at the end of the string. | |
| 513 { | |
| 514 SCOPED_TRACE("trailing_NUL_full"); | |
| 515 TestStringToExceptionMask(base::StringPiece("EXC_MASK_BREAKPOINTED", 19), | |
| 516 kAllowFullName, | |
| 517 true, | |
| 518 EXC_MASK_BREAKPOINT); | |
| 519 } | |
| 520 { | |
| 521 SCOPED_TRACE("trailing_NUL_short"); | |
| 522 TestStringToExceptionMask(base::StringPiece("BREAKPOINTED", 10), | |
| 523 kAllowShortName, | |
| 524 true, | |
| 525 EXC_MASK_BREAKPOINT); | |
| 526 } | |
| 527 } | |
| 528 | |
| 529 const struct { | |
| 530 exception_behavior_t behavior; | |
| 531 const char* full_name; | |
| 532 const char* short_name; | |
| 533 } kExceptionBehaviorTestData[] = { | |
| 534 {EXCEPTION_DEFAULT, "EXCEPTION_DEFAULT", "DEFAULT"}, | |
| 535 {EXCEPTION_STATE, "EXCEPTION_STATE", "STATE"}, | |
| 536 {EXCEPTION_STATE_IDENTITY, "EXCEPTION_STATE_IDENTITY", "STATE_IDENTITY"}, | |
| 537 {static_cast<exception_behavior_t>(EXCEPTION_DEFAULT | | |
| 538 MACH_EXCEPTION_CODES), | |
| 539 "EXCEPTION_DEFAULT|MACH_EXCEPTION_CODES", | |
| 540 "DEFAULT|MACH"}, | |
| 541 {static_cast<exception_behavior_t>(EXCEPTION_STATE | | |
| 542 MACH_EXCEPTION_CODES), | |
| 543 "EXCEPTION_STATE|MACH_EXCEPTION_CODES", | |
| 544 "STATE|MACH"}, | |
| 545 {static_cast<exception_behavior_t>(EXCEPTION_STATE_IDENTITY | | |
| 546 MACH_EXCEPTION_CODES), | |
| 547 "EXCEPTION_STATE_IDENTITY|MACH_EXCEPTION_CODES", | |
| 548 "STATE_IDENTITY|MACH"}, | |
| 549 }; | |
| 550 | |
| 551 struct ConvertExceptionBehaviorTraits { | |
| 552 typedef exception_behavior_t ValueType; | |
| 553 static std::string SomethingToString( | |
| 554 ValueType value, | |
| 555 SymbolicConstantToStringOptions options) { | |
| 556 return ExceptionBehaviorToString(value, options); | |
| 557 } | |
| 558 static bool StringToSomething(const base::StringPiece& string, | |
| 559 StringToSymbolicConstantOptions options, | |
| 560 ValueType* value) { | |
| 561 return StringToExceptionBehavior(string, options, value); | |
| 562 } | |
| 563 static const char kValueName[]; | |
| 564 }; | |
| 565 const char ConvertExceptionBehaviorTraits::kValueName[] = "behavior"; | |
| 566 | |
| 567 void TestExceptionBehaviorToString(exception_behavior_t value, | |
| 568 const char* expect_full, | |
| 569 const char* expect_short) { | |
| 570 return TestSomethingToString<ConvertExceptionBehaviorTraits>( | |
| 571 value, expect_full, expect_short); | |
| 572 } | |
| 573 | |
| 574 TEST(SymbolicConstantsMach, ExceptionBehaviorToString) { | |
| 575 for (size_t index = 0; index < arraysize(kExceptionBehaviorTestData); | |
| 576 ++index) { | |
| 577 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 578 TestExceptionBehaviorToString(kExceptionBehaviorTestData[index].behavior, | |
| 579 kExceptionBehaviorTestData[index].full_name, | |
| 580 kExceptionBehaviorTestData[index].short_name); | |
| 581 } | |
| 582 | |
| 583 for (exception_behavior_t behavior = 0; behavior < 8; ++behavior) { | |
| 584 SCOPED_TRACE(base::StringPrintf("behavior %d", behavior)); | |
| 585 exception_behavior_t behavior_mach = behavior | MACH_EXCEPTION_CODES; | |
| 586 if (behavior > 0 && behavior <= EXCEPTION_STATE_IDENTITY) { | |
| 587 TestExceptionBehaviorToString(behavior, "", ""); | |
| 588 TestExceptionBehaviorToString(behavior_mach, "", ""); | |
| 589 } else { | |
| 590 TestExceptionBehaviorToString(behavior, NULL, NULL); | |
| 591 TestExceptionBehaviorToString(behavior_mach, NULL, NULL); | |
| 592 } | |
| 593 } | |
| 594 } | |
| 595 | |
| 596 void TestStringToExceptionBehavior(const base::StringPiece& string, | |
| 597 StringToSymbolicConstantOptions options, | |
| 598 bool expect_result, | |
| 599 exception_behavior_t expect_value) { | |
| 600 return TestStringToSomething<ConvertExceptionBehaviorTraits>( | |
| 601 string, options, expect_result, expect_value); | |
| 602 } | |
| 603 | |
| 604 TEST(SymbolicConstantsMach, StringToExceptionBehavior) { | |
| 605 const StringToSymbolicConstantOptions kOptions[] = { | |
|
Robert Sesek
2014/09/15 23:00:16
Share this table across tests where they're the sa
| |
| 606 0, | |
| 607 kAllowFullName, | |
| 608 kAllowShortName, | |
| 609 kAllowFullName | kAllowShortName, | |
| 610 kAllowNumber, | |
| 611 kAllowFullName | kAllowNumber, | |
| 612 kAllowShortName | kAllowNumber, | |
| 613 kAllowFullName | kAllowShortName | kAllowNumber, | |
| 614 }; | |
| 615 | |
| 616 for (size_t option_index = 0; option_index < arraysize(kOptions); | |
| 617 ++option_index) { | |
| 618 SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); | |
| 619 StringToSymbolicConstantOptions options = kOptions[option_index]; | |
| 620 for (size_t index = 0; index < arraysize(kExceptionBehaviorTestData); | |
| 621 ++index) { | |
| 622 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 623 exception_behavior_t behavior = | |
| 624 kExceptionBehaviorTestData[index].behavior; | |
| 625 { | |
| 626 SCOPED_TRACE("full_name"); | |
| 627 TestStringToExceptionBehavior( | |
| 628 kExceptionBehaviorTestData[index].full_name, | |
| 629 options, | |
| 630 options & kAllowFullName, | |
| 631 behavior); | |
| 632 } | |
| 633 { | |
| 634 SCOPED_TRACE("short_name"); | |
| 635 TestStringToExceptionBehavior( | |
| 636 kExceptionBehaviorTestData[index].short_name, | |
| 637 options, | |
| 638 options & kAllowShortName, | |
| 639 behavior); | |
| 640 } | |
| 641 { | |
| 642 SCOPED_TRACE("number"); | |
| 643 std::string number_string = base::StringPrintf("0x%x", behavior); | |
| 644 TestStringToExceptionBehavior( | |
| 645 number_string, options, options & kAllowNumber, behavior); | |
| 646 } | |
| 647 } | |
| 648 | |
| 649 const char* const kNegativeTestData[] = { | |
| 650 "EXCEPTION_DEFAULT ", | |
| 651 " EXCEPTION_STATE", | |
| 652 "EXCEPTION_EXCEPTION_STATE_IDENTITY", | |
| 653 "EXCEPTION_DEFAULTS", | |
| 654 "EXCEPTION_JUNK", | |
| 655 "random", | |
| 656 "MACH_EXCEPTION_CODES", | |
| 657 "MACH", | |
| 658 "MACH_EXCEPTION_CODES|MACH_EXCEPTION_CODES", | |
| 659 "MACH_EXCEPTION_CODES|EXCEPTION_NONEXISTENT", | |
| 660 "MACH|junk", | |
| 661 "EXCEPTION_DEFAULT|EXCEPTION_STATE", | |
| 662 "1|2", | |
| 663 "", | |
| 664 }; | |
| 665 | |
| 666 for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { | |
| 667 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 668 TestStringToExceptionBehavior( | |
| 669 kNegativeTestData[index], options, false, 0); | |
| 670 } | |
| 671 | |
| 672 const struct { | |
| 673 const char* string; | |
| 674 size_t length; | |
| 675 } kNULTestData[] = { | |
| 676 #define NUL_TEST_DATA(string) { string, arraysize(string) - 1 } | |
| 677 NUL_TEST_DATA("\0EXCEPTION_STATE_IDENTITY"), | |
| 678 NUL_TEST_DATA("EXCEPTION_\0STATE_IDENTITY"), | |
| 679 NUL_TEST_DATA("EXCEPTION_STATE\0_IDENTITY"), | |
| 680 NUL_TEST_DATA("EXCEPTION_STATE_IDENTITY\0"), | |
| 681 NUL_TEST_DATA("\0STATE_IDENTITY"), | |
| 682 NUL_TEST_DATA("STATE\0_IDENTITY"), | |
| 683 NUL_TEST_DATA("STATE_IDENTITY\0"), | |
| 684 NUL_TEST_DATA("\0003"), | |
| 685 NUL_TEST_DATA("3\0"), | |
| 686 NUL_TEST_DATA("0x8000000\0001"), | |
| 687 NUL_TEST_DATA("EXCEPTION_STATE_IDENTITY\0|MACH_EXCEPTION_CODES"), | |
| 688 NUL_TEST_DATA("EXCEPTION_STATE_IDENTITY|\0MACH_EXCEPTION_CODES"), | |
| 689 NUL_TEST_DATA("STATE_IDENTITY\0|MACH"), | |
| 690 NUL_TEST_DATA("STATE_IDENTITY|\0MACH"), | |
| 691 #undef NUL_TEST_DATA | |
| 692 }; | |
| 693 | |
| 694 for (size_t index = 0; index < arraysize(kNULTestData); ++index) { | |
| 695 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 696 base::StringPiece string(kNULTestData[index].string, | |
| 697 kNULTestData[index].length); | |
| 698 TestStringToExceptionBehavior(string, options, false, 0); | |
| 699 } | |
| 700 } | |
| 701 | |
| 702 const struct { | |
| 703 const char* string; | |
| 704 StringToSymbolicConstantOptions options; | |
| 705 exception_behavior_t behavior; | |
| 706 } kNonCanonicalTestData[] = { | |
| 707 {"MACH_EXCEPTION_CODES|EXCEPTION_STATE_IDENTITY", | |
| 708 kAllowFullName, | |
| 709 static_cast<exception_behavior_t>(EXCEPTION_STATE_IDENTITY | | |
| 710 MACH_EXCEPTION_CODES)}, | |
| 711 {"MACH|STATE_IDENTITY", | |
| 712 kAllowShortName, | |
| 713 static_cast<exception_behavior_t>(EXCEPTION_STATE_IDENTITY | | |
| 714 MACH_EXCEPTION_CODES)}, | |
| 715 {"MACH_EXCEPTION_CODES|STATE", | |
| 716 kAllowFullName | kAllowShortName, | |
| 717 static_cast<exception_behavior_t>(EXCEPTION_STATE | | |
| 718 MACH_EXCEPTION_CODES)}, | |
| 719 {"MACH|EXCEPTION_STATE", | |
| 720 kAllowFullName | kAllowShortName, | |
| 721 static_cast<exception_behavior_t>(EXCEPTION_STATE | | |
| 722 MACH_EXCEPTION_CODES)}, | |
| 723 {"3|MACH_EXCEPTION_CODES", | |
| 724 kAllowFullName | kAllowNumber, | |
| 725 static_cast<exception_behavior_t>(MACH_EXCEPTION_CODES | 3)}, | |
| 726 {"MACH|0x2", | |
| 727 kAllowShortName | kAllowNumber, | |
| 728 static_cast<exception_behavior_t>(MACH_EXCEPTION_CODES | 0x2)}, | |
| 729 }; | |
| 730 | |
| 731 for (size_t index = 0; index < arraysize(kNonCanonicalTestData); ++index) { | |
| 732 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 733 TestStringToExceptionBehavior(kNonCanonicalTestData[index].string, | |
| 734 kNonCanonicalTestData[index].options, | |
| 735 true, | |
| 736 kNonCanonicalTestData[index].behavior); | |
| 737 } | |
| 738 | |
| 739 // Ensure that a NUL is not required at the end of the string. | |
| 740 { | |
| 741 SCOPED_TRACE("trailing_NUL_full"); | |
| 742 TestStringToExceptionBehavior(base::StringPiece("EXCEPTION_DEFAULTS", 17), | |
| 743 kAllowFullName, | |
| 744 true, | |
| 745 EXCEPTION_DEFAULT); | |
| 746 } | |
| 747 { | |
| 748 SCOPED_TRACE("trailing_NUL_short"); | |
| 749 TestStringToExceptionBehavior(base::StringPiece("DEFAULTS", 7), | |
| 750 kAllowShortName, | |
| 751 true, | |
| 752 EXCEPTION_DEFAULT); | |
| 753 } | |
| 754 { | |
| 755 SCOPED_TRACE("trailing_NUL_full_mach"); | |
| 756 base::StringPiece string("EXCEPTION_DEFAULT|MACH_EXCEPTION_CODESS", 38); | |
| 757 TestStringToExceptionBehavior(string, | |
| 758 kAllowFullName | kAllowOr, | |
| 759 true, | |
| 760 EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES); | |
| 761 } | |
| 762 { | |
| 763 SCOPED_TRACE("trailing_NUL_short_mach"); | |
| 764 TestStringToExceptionBehavior(base::StringPiece("DEFAULT|MACH_", 12), | |
| 765 kAllowShortName | kAllowOr, | |
| 766 true, | |
| 767 EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES); | |
| 768 } | |
| 769 } | |
| 770 | |
| 771 const struct { | |
| 772 thread_state_flavor_t flavor; | |
| 773 const char* full_name; | |
| 774 const char* short_name; | |
| 775 } kThreadStateFlavorTestData[] = { | |
| 776 {THREAD_STATE_NONE, "THREAD_STATE_NONE", "NONE"}, | |
| 777 {THREAD_STATE_FLAVOR_LIST, "THREAD_STATE_FLAVOR_LIST", "FLAVOR_LIST"}, | |
| 778 {THREAD_STATE_FLAVOR_LIST_NEW, | |
| 779 "THREAD_STATE_FLAVOR_LIST_NEW", | |
| 780 "FLAVOR_LIST_NEW"}, | |
| 781 {THREAD_STATE_FLAVOR_LIST_10_9, | |
| 782 "THREAD_STATE_FLAVOR_LIST_10_9", | |
| 783 "FLAVOR_LIST_10_9"}, | |
| 784 #if defined(__i386__) || defined(__x86_64__) | |
| 785 {x86_THREAD_STATE32, "x86_THREAD_STATE32", "THREAD32"}, | |
| 786 {x86_FLOAT_STATE32, "x86_FLOAT_STATE32", "FLOAT32"}, | |
| 787 {x86_EXCEPTION_STATE32, "x86_EXCEPTION_STATE32", "EXCEPTION32"}, | |
| 788 {x86_THREAD_STATE64, "x86_THREAD_STATE64", "THREAD64"}, | |
| 789 {x86_FLOAT_STATE64, "x86_FLOAT_STATE64", "FLOAT64"}, | |
| 790 {x86_EXCEPTION_STATE64, "x86_EXCEPTION_STATE64", "EXCEPTION64"}, | |
| 791 {x86_THREAD_STATE, "x86_THREAD_STATE", "THREAD"}, | |
| 792 {x86_FLOAT_STATE, "x86_FLOAT_STATE", "FLOAT"}, | |
| 793 {x86_EXCEPTION_STATE, "x86_EXCEPTION_STATE", "EXCEPTION"}, | |
| 794 {x86_DEBUG_STATE32, "x86_DEBUG_STATE32", "DEBUG32"}, | |
| 795 {x86_DEBUG_STATE64, "x86_DEBUG_STATE64", "DEBUG64"}, | |
| 796 {x86_DEBUG_STATE, "x86_DEBUG_STATE", "DEBUG"}, | |
| 797 {14, "x86_SAVED_STATE32", "SAVED32"}, | |
| 798 {15, "x86_SAVED_STATE64", "SAVED64"}, | |
| 799 {x86_AVX_STATE32, "x86_AVX_STATE32", "AVX32"}, | |
| 800 {x86_AVX_STATE64, "x86_AVX_STATE64", "AVX64"}, | |
| 801 {x86_AVX_STATE, "x86_AVX_STATE", "AVX"}, | |
| 802 #elif defined(__ppc__) || defined(__ppc64__) | |
| 803 {PPC_THREAD_STATE, "PPC_THREAD_STATE", "THREAD"}, | |
| 804 {PPC_FLOAT_STATE, "PPC_FLOAT_STATE", "FLOAT"}, | |
| 805 {PPC_EXCEPTION_STATE, "PPC_EXCEPTION_STATE", "EXCEPTION"}, | |
| 806 {PPC_VECTOR_STATE, "PPC_VECTOR_STATE", "VECTOR"}, | |
| 807 {PPC_THREAD_STATE64, "PPC_THREAD_STATE64", "THREAD64"}, | |
| 808 {PPC_EXCEPTION_STATE64, "PPC_EXCEPTION_STATE64", "EXCEPTION64"}, | |
| 809 #elif defined(__arm__) || defined(__arm64__) | |
| 810 {ARM_THREAD_STATE, "ARM_THREAD_STATE", "THREAD"}, | |
| 811 {ARM_VFP_STATE, "ARM_VFP_STATE", "VFP"}, | |
| 812 {ARM_EXCEPTION_STATE, "ARM_EXCEPTION_STATE", "EXCEPTION"}, | |
| 813 {ARM_DEBUG_STATE, "ARM_DEBUG_STATE", "DEBUG"}, | |
| 814 {ARM_THREAD_STATE64, "ARM_THREAD_STATE64", "THREAD64"}, | |
| 815 {ARM_EXCEPTION_STATE64, "ARM_EXCEPTION_STATE64", "EXCEPTION64"}, | |
| 816 {ARM_THREAD_STATE32, "ARM_THREAD_STATE32", "THREAD32"}, | |
| 817 {ARM_DEBUG_STATE32, "ARM_DEBUG_STATE32", "DEBUG32"}, | |
| 818 {ARM_DEBUG_STATE64, "ARM_DEBUG_STATE64", "DEBUG64"}, | |
| 819 {ARM_NEON_STATE, "ARM_NEON_STATE", "NEON"}, | |
| 820 {ARM_NEON_STATE64, "ARM_NEON_STATE64", "NEON64"}, | |
| 821 #endif | |
| 822 }; | |
| 823 | |
| 824 struct ConvertThreadStateFlavorTraits { | |
| 825 typedef thread_state_flavor_t ValueType; | |
| 826 static std::string SomethingToString( | |
| 827 ValueType value, | |
| 828 SymbolicConstantToStringOptions options) { | |
| 829 return ThreadStateFlavorToString(value, options); | |
| 830 } | |
| 831 static bool StringToSomething(const base::StringPiece& string, | |
| 832 StringToSymbolicConstantOptions options, | |
| 833 ValueType* value) { | |
| 834 return StringToThreadStateFlavor(string, options, value); | |
| 835 } | |
| 836 static const char kValueName[]; | |
| 837 }; | |
| 838 const char ConvertThreadStateFlavorTraits::kValueName[] = "flavor"; | |
| 839 | |
| 840 void TestThreadStateFlavorToString(exception_type_t value, | |
| 841 const char* expect_full, | |
| 842 const char* expect_short) { | |
| 843 return TestSomethingToString<ConvertThreadStateFlavorTraits>( | |
| 844 value, expect_full, expect_short); | |
| 845 } | |
| 846 | |
| 847 TEST(SymbolicConstantsMach, ThreadStateFlavorToString) { | |
| 848 for (size_t index = 0; index < arraysize(kThreadStateFlavorTestData); | |
| 849 ++index) { | |
| 850 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 851 TestThreadStateFlavorToString(kThreadStateFlavorTestData[index].flavor, | |
| 852 kThreadStateFlavorTestData[index].full_name, | |
| 853 kThreadStateFlavorTestData[index].short_name); | |
| 854 } | |
| 855 | |
| 856 for (thread_state_flavor_t flavor = 0; flavor < 136; ++flavor) { | |
| 857 SCOPED_TRACE(base::StringPrintf("flavor %d", flavor)); | |
| 858 if ( | |
| 859 #if defined(__i386__) || defined(__x86_64__) | |
| 860 flavor <= 18 | |
| 861 #elif defined(__ppc__) || defined(__ppc64__) | |
| 862 flavor <= 7 | |
| 863 #elif defined(__arm__) || defined(__arm64__) | |
| 864 (flavor <= 7 || flavor == 9 || (flavor >= 14 && flavor <= 17)) | |
|
Robert Sesek
2014/09/15 23:00:16
Why use magic numbers here?
Mark Mentovai
2014/09/16 13:42:16
rsesek wrote:
| |
| 865 #endif | |
| 866 || | |
| 867 flavor == THREAD_STATE_FLAVOR_LIST_NEW || | |
| 868 flavor == THREAD_STATE_FLAVOR_LIST_10_9) { | |
| 869 TestThreadStateFlavorToString(flavor, "", ""); | |
| 870 } else { | |
| 871 TestThreadStateFlavorToString(flavor, NULL, NULL); | |
| 872 } | |
| 873 } | |
| 874 } | |
| 875 | |
| 876 void TestStringToThreadStateFlavor(const base::StringPiece& string, | |
| 877 StringToSymbolicConstantOptions options, | |
| 878 bool expect_result, | |
| 879 thread_state_flavor_t expect_value) { | |
| 880 return TestStringToSomething<ConvertThreadStateFlavorTraits>( | |
| 881 string, options, expect_result, expect_value); | |
| 882 } | |
| 883 | |
| 884 TEST(SymbolicConstantsMach, StringToThreadStateFlavor) { | |
| 885 const StringToSymbolicConstantOptions kOptions[] = { | |
| 886 0, | |
| 887 kAllowFullName, | |
| 888 kAllowShortName, | |
| 889 kAllowFullName | kAllowShortName, | |
| 890 kAllowNumber, | |
| 891 kAllowFullName | kAllowNumber, | |
| 892 kAllowShortName | kAllowNumber, | |
| 893 kAllowFullName | kAllowShortName | kAllowNumber, | |
| 894 }; | |
| 895 | |
| 896 for (size_t option_index = 0; option_index < arraysize(kOptions); | |
| 897 ++option_index) { | |
| 898 SCOPED_TRACE(base::StringPrintf("option_index %zu", option_index)); | |
| 899 StringToSymbolicConstantOptions options = kOptions[option_index]; | |
| 900 for (size_t index = 0; index < arraysize(kThreadStateFlavorTestData); | |
| 901 ++index) { | |
| 902 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 903 thread_state_flavor_t flavor = kThreadStateFlavorTestData[index].flavor; | |
| 904 { | |
| 905 SCOPED_TRACE("full_name"); | |
| 906 TestStringToThreadStateFlavor( | |
| 907 kThreadStateFlavorTestData[index].full_name, | |
| 908 options, | |
| 909 options & kAllowFullName, | |
| 910 flavor); | |
| 911 } | |
| 912 { | |
| 913 SCOPED_TRACE("short_name"); | |
| 914 TestStringToThreadStateFlavor( | |
| 915 kThreadStateFlavorTestData[index].short_name, | |
| 916 options, | |
| 917 options & kAllowShortName, | |
| 918 flavor); | |
| 919 } | |
| 920 { | |
| 921 SCOPED_TRACE("number"); | |
| 922 std::string number_string = base::StringPrintf("%d", flavor); | |
| 923 TestStringToThreadStateFlavor( | |
| 924 number_string, options, options & kAllowNumber, flavor); | |
| 925 } | |
| 926 } | |
| 927 | |
| 928 const char* const kNegativeTestData[] = { | |
| 929 "THREAD_STATE_NONE ", | |
| 930 " THREAD_STATE_NONE", | |
| 931 "NONE ", | |
| 932 " NONE", | |
| 933 "THREAD_STATE_THREAD_STATE_NONE", | |
| 934 "THREAD_STATE_NONE_AT_ALL", | |
| 935 "NONE_AT_ALL", | |
| 936 "THREAD_STATE_JUNK", | |
| 937 "JUNK", | |
| 938 "random", | |
| 939 " THREAD64", | |
| 940 "THREAD64 ", | |
| 941 "THREAD642", | |
| 942 "", | |
| 943 #if defined(__i386__) || defined(__x86_64__) | |
| 944 " x86_THREAD_STATE64", | |
| 945 "x86_THREAD_STATE64 ", | |
| 946 "x86_THREAD_STATE642", | |
| 947 "x86_JUNK", | |
| 948 "x86_JUNK_STATE32", | |
| 949 "PPC_THREAD_STATE", | |
| 950 "ARM_THREAD_STATE", | |
| 951 #elif defined(__ppc__) || defined(__ppc64__) | |
| 952 " PPC_THREAD_STATE64", | |
| 953 "PPC_THREAD_STATE64 ", | |
| 954 "PPC_THREAD_STATE642", | |
| 955 "PPC_JUNK", | |
| 956 "PPC_JUNK_STATE32", | |
| 957 "x86_THREAD_STATE", | |
| 958 "ARM_THREAD_STATE", | |
| 959 #elif defined(__arm__) || defined(__arm64__) | |
| 960 " ARM_THREAD_STATE64", | |
| 961 "ARM_THREAD_STATE64 ", | |
| 962 "ARM_THREAD_STATE642", | |
| 963 "ARM_JUNK", | |
| 964 "ARM_JUNK_STATE32", | |
| 965 "x86_THREAD_STATE", | |
| 966 "PPC_THREAD_STATE", | |
| 967 #endif | |
| 968 }; | |
| 969 | |
| 970 for (size_t index = 0; index < arraysize(kNegativeTestData); ++index) { | |
| 971 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 972 TestStringToThreadStateFlavor( | |
| 973 kNegativeTestData[index], options, false, 0); | |
| 974 } | |
| 975 | |
| 976 const struct { | |
| 977 const char* string; | |
| 978 size_t length; | |
| 979 } kNULTestData[] = { | |
| 980 #define NUL_TEST_DATA(string) { string, arraysize(string) - 1 } | |
| 981 NUL_TEST_DATA("\0THREAD_STATE_NONE"), | |
| 982 NUL_TEST_DATA("THREAD_\0STATE_NONE"), | |
| 983 NUL_TEST_DATA("THREAD_STATE_\0NONE"), | |
| 984 NUL_TEST_DATA("THREAD_STATE_NO\0NE"), | |
| 985 NUL_TEST_DATA("THREAD_STATE_NONE\0"), | |
| 986 NUL_TEST_DATA("\0NONE"), | |
| 987 NUL_TEST_DATA("NO\0NE"), | |
| 988 NUL_TEST_DATA("NONE\0"), | |
| 989 NUL_TEST_DATA("\0THREAD_STATE_FLAVOR_LIST_NEW"), | |
| 990 NUL_TEST_DATA("THREAD_STATE_\0FLAVOR_LIST_NEW"), | |
| 991 NUL_TEST_DATA("THREAD_STATE_FLAVOR_LIST\0_NEW"), | |
| 992 NUL_TEST_DATA("THREAD_STATE_FLAVOR_LIST_NEW\0"), | |
| 993 NUL_TEST_DATA("\0FLAVOR_LIST_NEW"), | |
| 994 NUL_TEST_DATA("FLAVOR_LIST\0_NEW"), | |
| 995 NUL_TEST_DATA("FLAVOR_LIST_NEW\0"), | |
| 996 NUL_TEST_DATA("\0THREAD"), | |
| 997 NUL_TEST_DATA("THR\0EAD"), | |
| 998 NUL_TEST_DATA("THREAD\0"), | |
| 999 NUL_TEST_DATA("\0THREAD64"), | |
| 1000 NUL_TEST_DATA("THR\0EAD64"), | |
| 1001 NUL_TEST_DATA("THREAD\064"), | |
| 1002 NUL_TEST_DATA("THREAD64\0"), | |
| 1003 NUL_TEST_DATA("\0002"), | |
| 1004 NUL_TEST_DATA("2\0"), | |
| 1005 NUL_TEST_DATA("1\0002"), | |
| 1006 #if defined(__i386__) || defined(__x86_64__) | |
| 1007 NUL_TEST_DATA("\0x86_THREAD_STATE64"), | |
| 1008 NUL_TEST_DATA("x86\0_THREAD_STATE64"), | |
| 1009 NUL_TEST_DATA("x86_\0THREAD_STATE64"), | |
| 1010 NUL_TEST_DATA("x86_THR\0EAD_STATE64"), | |
| 1011 NUL_TEST_DATA("x86_THREAD\0_STATE64"), | |
| 1012 NUL_TEST_DATA("x86_THREAD_\0STATE64"), | |
| 1013 NUL_TEST_DATA("x86_THREAD_STA\0TE64"), | |
| 1014 NUL_TEST_DATA("x86_THREAD_STATE\00064"), | |
| 1015 NUL_TEST_DATA("x86_THREAD_STATE64\0"), | |
| 1016 #elif defined(__ppc__) || defined(__ppc64__) | |
| 1017 NUL_TEST_DATA("\0PPC_THREAD_STATE64"), | |
| 1018 NUL_TEST_DATA("PPC\0_THREAD_STATE64"), | |
| 1019 NUL_TEST_DATA("PPC_\0THREAD_STATE64"), | |
| 1020 NUL_TEST_DATA("PPC_THR\0EAD_STATE64"), | |
| 1021 NUL_TEST_DATA("PPC_THREAD\0_STATE64"), | |
| 1022 NUL_TEST_DATA("PPC_THREAD_\0STATE64"), | |
| 1023 NUL_TEST_DATA("PPC_THREAD_STA\0TE64"), | |
| 1024 NUL_TEST_DATA("PPC_THREAD_STATE\00064"), | |
| 1025 #elif defined(__arm__) || defined(__arm64__) | |
| 1026 NUL_TEST_DATA("\0ARM_THREAD_STATE64"), | |
| 1027 NUL_TEST_DATA("ARM\0_THREAD_STATE64"), | |
| 1028 NUL_TEST_DATA("ARM_\0THREAD_STATE64"), | |
| 1029 NUL_TEST_DATA("ARM_THR\0EAD_STATE64"), | |
| 1030 NUL_TEST_DATA("ARM_THREAD\0_STATE64"), | |
| 1031 NUL_TEST_DATA("ARM_THREAD_\0STATE64"), | |
| 1032 NUL_TEST_DATA("ARM_THREAD_STA\0TE64"), | |
| 1033 NUL_TEST_DATA("ARM_THREAD_STATE\00064"), | |
| 1034 #endif | |
| 1035 #undef NUL_TEST_DATA | |
| 1036 }; | |
| 1037 | |
| 1038 for (size_t index = 0; index < arraysize(kNULTestData); ++index) { | |
| 1039 SCOPED_TRACE(base::StringPrintf("index %zu", index)); | |
| 1040 base::StringPiece string(kNULTestData[index].string, | |
| 1041 kNULTestData[index].length); | |
| 1042 TestStringToThreadStateFlavor(string, options, false, 0); | |
| 1043 } | |
| 1044 } | |
| 1045 | |
| 1046 // Ensure that a NUL is not required at the end of the string. | |
| 1047 { | |
| 1048 SCOPED_TRACE("trailing_NUL_full"); | |
| 1049 TestStringToThreadStateFlavor(base::StringPiece("THREAD_STATE_NONER", 17), | |
| 1050 kAllowFullName, | |
| 1051 true, | |
| 1052 THREAD_STATE_NONE); | |
| 1053 } | |
| 1054 { | |
| 1055 SCOPED_TRACE("trailing_NUL_short"); | |
| 1056 TestStringToThreadStateFlavor(base::StringPiece("NONER", 4), | |
| 1057 kAllowShortName, | |
| 1058 true, | |
| 1059 THREAD_STATE_NONE); | |
| 1060 } | |
| 1061 { | |
| 1062 SCOPED_TRACE("trailing_NUL_full_new"); | |
| 1063 base::StringPiece string("THREAD_STATE_FLAVOR_LIST_NEWS", 28); | |
| 1064 TestStringToThreadStateFlavor( | |
| 1065 string, kAllowFullName, true, THREAD_STATE_FLAVOR_LIST_NEW); | |
| 1066 } | |
| 1067 { | |
| 1068 SCOPED_TRACE("trailing_NUL_short_new"); | |
| 1069 TestStringToThreadStateFlavor(base::StringPiece("FLAVOR_LIST_NEWS", 15), | |
| 1070 kAllowShortName, | |
| 1071 true, | |
| 1072 THREAD_STATE_FLAVOR_LIST_NEW); | |
| 1073 } | |
| 1074 } | |
| 1075 | |
| 1076 } // namespace | |
| OLD | NEW |