| Index: util/mach/exc_server_variants_test.cc
|
| diff --git a/util/mach/exc_server_variants_test.cc b/util/mach/exc_server_variants_test.cc
|
| index 8ca041eb3891ffbc322cf7ea06bfbf7349da2e6b..36439f48d91a94f76d91d5d963ab0ac5dbd14c3e 100644
|
| --- a/util/mach/exc_server_variants_test.cc
|
| +++ b/util/mach/exc_server_variants_test.cc
|
| @@ -15,6 +15,7 @@
|
| #include "util/mach/exc_server_variants.h"
|
|
|
| #include <mach/mach.h>
|
| +#include <signal.h>
|
| #include <string.h>
|
|
|
| #include "base/basictypes.h"
|
| @@ -904,15 +905,13 @@ class TestExcServerVariants : public UniversalMachExcServer,
|
| EXPECT_EQ(EXC_CRASH, exception);
|
| EXPECT_EQ(2u, code_count);
|
|
|
| - // The code_count check above would ideally use ASSERT_EQ so that the next
|
| - // conditional would not be necessary, but ASSERT_* requires a function
|
| - // returning type void, and the interface dictates otherwise here.
|
| - if (code_count >= 1) {
|
| - // The signal that terminated the process is stored in code[0] along with
|
| - // some other data. See 10.9.4 xnu-2422.110.17/bsd/kern/kern_exit.c
|
| - // proc_prepareexit().
|
| - int sig = (code[0] >> 24) & 0xff;
|
| - SetExpectedChildTermination(kTerminationSignal, sig);
|
| + // The exception and code_count checks above would ideally use ASSERT_EQ so
|
| + // that the next conditional would not be necessary, but ASSERT_* requires a
|
| + // function returning type void, and the interface dictates otherwise here.
|
| + if (exception == EXC_CRASH && code_count >= 1) {
|
| + int signal;
|
| + ExcCrashRecoverOriginalException(code[0], NULL, &signal);
|
| + SetExpectedChildTermination(kTerminationSignal, signal);
|
| }
|
|
|
| const bool has_state = ExceptionBehaviorHasState(behavior);
|
| @@ -1075,6 +1074,61 @@ TEST(ExcServerVariants, ThreadStates) {
|
| }
|
| }
|
|
|
| +TEST(ExcServerVariants, ExcCrashRecoverOriginalException) {
|
| + struct TestData {
|
| + mach_exception_data_type_t code_0;
|
| + exception_type_t exception;
|
| + mach_exception_data_type_t original_code_0;
|
| + int signal;
|
| + };
|
| + const TestData kTestData[] = {
|
| + {0xb100001, EXC_BAD_ACCESS, KERN_INVALID_ADDRESS, SIGSEGV},
|
| + {0xb100002, EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE, SIGSEGV},
|
| + {0xa100002, EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE, SIGBUS},
|
| + {0x4200001, EXC_BAD_INSTRUCTION, 1, SIGILL},
|
| + {0x8300001, EXC_ARITHMETIC, 1, SIGFPE},
|
| + {0x5600002, EXC_BREAKPOINT, 2, SIGTRAP},
|
| + {0x6000000, 0, 0, SIGABRT},
|
| + {0, 0, 0, 0},
|
| + };
|
| +
|
| + for (size_t index = 0; index < arraysize(kTestData); ++index) {
|
| + const TestData& test_data = kTestData[index];
|
| + SCOPED_TRACE(base::StringPrintf("index %zu, code_0 0x%llx",
|
| + index,
|
| + test_data.code_0));
|
| +
|
| + mach_exception_data_type_t original_code_0;
|
| + int signal;
|
| + exception_type_t exception =
|
| + ExcCrashRecoverOriginalException(test_data.code_0,
|
| + &original_code_0,
|
| + &signal);
|
| +
|
| + EXPECT_EQ(test_data.exception, exception);
|
| + EXPECT_EQ(test_data.original_code_0, original_code_0);
|
| + EXPECT_EQ(test_data.signal, signal);
|
| + }
|
| +
|
| + // Now make sure that ExcCrashRecoverOriginalException() properly ignores
|
| + // optional arguments.
|
| + COMPILE_ASSERT(arraysize(kTestData) >= 1, must_have_something_to_test);
|
| + const TestData& test_data = kTestData[0];
|
| + EXPECT_EQ(test_data.exception,
|
| + ExcCrashRecoverOriginalException(test_data.code_0, NULL, NULL));
|
| +
|
| + mach_exception_data_type_t original_code_0;
|
| + EXPECT_EQ(test_data.exception,
|
| + ExcCrashRecoverOriginalException(
|
| + test_data.code_0, &original_code_0, NULL));
|
| + EXPECT_EQ(test_data.original_code_0, original_code_0);
|
| +
|
| + int signal;
|
| + EXPECT_EQ(test_data.exception,
|
| + ExcCrashRecoverOriginalException(test_data.code_0, NULL, &signal));
|
| + EXPECT_EQ(test_data.signal, signal);
|
| +}
|
| +
|
| TEST(ExcServerVariants, ExcServerSuccessfulReturnValue) {
|
| struct TestData {
|
| exception_behavior_t behavior;
|
|
|