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 |