Index: util/mach/exception_ports_test.cc |
diff --git a/util/mach/exception_ports_test.cc b/util/mach/exception_ports_test.cc |
index 43fb025757a32c706dc1abca830147d17938bb40..8948eae791668123ced9510c5a824d1f09d91a26 100644 |
--- a/util/mach/exception_ports_test.cc |
+++ b/util/mach/exception_ports_test.cc |
@@ -107,6 +107,12 @@ void TestGetExceptionPorts(const ExceptionPorts& exception_ports, |
class TestExceptionPorts : public MachMultiprocess, |
public UniversalMachExcServer::Interface { |
public: |
+ // Which entities to set exception ports for. |
+ enum SetOn { |
+ kSetOnTaskOnly = 0, |
+ kSetOnTaskAndThreads, |
+ }; |
+ |
// Where to call ExceptionPorts::SetExceptionPort() from. |
enum SetType { |
// Call it from the child process on itself. |
@@ -116,12 +122,6 @@ class TestExceptionPorts : public MachMultiprocess, |
kSetOutOfProcess, |
}; |
- // Which entities to set exception ports for. |
- enum SetOn { |
- kSetOnTaskOnly = 0, |
- kSetOnTaskAndThreads, |
- }; |
- |
// Which thread in the child process is expected to crash. |
enum WhoCrashes { |
kNobodyCrashes = 0, |
@@ -129,16 +129,16 @@ class TestExceptionPorts : public MachMultiprocess, |
kOtherThreadCrashes, |
}; |
- TestExceptionPorts(SetType set_type, SetOn set_on, WhoCrashes who_crashes) |
+ TestExceptionPorts(SetOn set_on, SetType set_type, WhoCrashes who_crashes) |
: MachMultiprocess(), |
UniversalMachExcServer::Interface(), |
- set_type_(set_type), |
set_on_(set_on), |
+ set_type_(set_type), |
who_crashes_(who_crashes), |
handled_(false) {} |
- SetType set_type() const { return set_type_; } |
SetOn set_on() const { return set_on_; } |
+ SetType set_type() const { return set_type_; } |
WhoCrashes who_crashes() const { return who_crashes_; } |
// UniversalMachExcServer::Interface: |
@@ -191,10 +191,8 @@ class TestExceptionPorts : public MachMultiprocess, |
int signal; |
ExcCrashRecoverOriginalException(code[0], nullptr, &signal); |
- // The child crashed with a division by zero, which shows up as SIGFPE. |
- // This was chosen because it’s unlikely to be generated by testing or |
- // assertion failures. |
- EXPECT_EQ(SIGFPE, signal); |
+ // The child crashed with __builtin_trap(), which shows up as SIGILL. |
+ EXPECT_EQ(SIGILL, signal); |
SetExpectedChildTermination(kTerminationSignal, signal); |
} |
@@ -326,10 +324,9 @@ class TestExceptionPorts : public MachMultiprocess, |
return nullptr; |
} |
- // Crashes by performing a division by zero. The assignment is present to |
- // avoid optimizing zero_ out entirely by making it appear that its value |
- // might change. |
- static void Crash() { zero_ = 1 / zero_; } |
+ static void Crash() { |
+ __builtin_trap(); |
+ } |
// The parent object. |
TestExceptionPorts* test_exception_ports_; // weak |
@@ -345,11 +342,6 @@ class TestExceptionPorts : public MachMultiprocess, |
// child can test its exception ports and possibly crash, as appropriate. |
Semaphore crash_semaphore_; |
- // Always zero. Crash() divides by this in order to trigger a crash. This is |
- // structured as a static volatile int to ward off aggressive compiler |
- // optimizations. |
- static volatile int zero_; |
- |
DISALLOW_COPY_AND_ASSIGN(Child); |
}; |
@@ -447,13 +439,14 @@ class TestExceptionPorts : public MachMultiprocess, |
if (who_crashes_ != kNobodyCrashes) { |
UniversalMachExcServer universal_mach_exc_server(this); |
+ const mach_msg_timeout_t kTimeoutMs = 50; |
kern_return_t kr = |
MachMessageServer::Run(&universal_mach_exc_server, |
local_port, |
MACH_MSG_OPTION_NONE, |
MachMessageServer::kOneShot, |
MachMessageServer::kReceiveLargeError, |
- kMachMessageTimeoutWaitIndefinitely); |
+ kTimeoutMs); |
EXPECT_EQ(KERN_SUCCESS, kr) |
<< MachErrorMessage(kr, "MachMessageServer::Run"); |
@@ -471,8 +464,8 @@ class TestExceptionPorts : public MachMultiprocess, |
child.Run(); |
} |
- SetType set_type_; |
SetOn set_on_; |
+ SetType set_type_; |
WhoCrashes who_crashes_; |
// true if an exception message was handled. |
@@ -481,66 +474,103 @@ class TestExceptionPorts : public MachMultiprocess, |
DISALLOW_COPY_AND_ASSIGN(TestExceptionPorts); |
}; |
-volatile int TestExceptionPorts::Child::zero_ = 0; |
+TEST(ExceptionPorts, TaskExceptionPorts_SetInProcess_NoCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskOnly, |
+ TestExceptionPorts::kSetInProcess, |
+ TestExceptionPorts::kNobodyCrashes); |
+ test_exception_ports.Run(); |
+} |
-TEST(ExceptionPorts, TaskAndThreadExceptionPorts) { |
- struct Testcase { |
- TestExceptionPorts::SetType set_type; |
- TestExceptionPorts::SetOn set_on; |
- TestExceptionPorts::WhoCrashes who_crashes; |
- }; |
- const Testcase kTestcases[] = { |
- {TestExceptionPorts::kSetInProcess, |
- TestExceptionPorts::kSetOnTaskOnly, |
- TestExceptionPorts::kNobodyCrashes}, |
- {TestExceptionPorts::kSetInProcess, |
- TestExceptionPorts::kSetOnTaskOnly, |
- TestExceptionPorts::kMainThreadCrashes}, |
- {TestExceptionPorts::kSetInProcess, |
- TestExceptionPorts::kSetOnTaskOnly, |
- TestExceptionPorts::kOtherThreadCrashes}, |
- {TestExceptionPorts::kSetInProcess, |
- TestExceptionPorts::kSetOnTaskAndThreads, |
- TestExceptionPorts::kNobodyCrashes}, |
- {TestExceptionPorts::kSetInProcess, |
- TestExceptionPorts::kSetOnTaskAndThreads, |
- TestExceptionPorts::kMainThreadCrashes}, |
- {TestExceptionPorts::kSetInProcess, |
- TestExceptionPorts::kSetOnTaskAndThreads, |
- TestExceptionPorts::kOtherThreadCrashes}, |
- {TestExceptionPorts::kSetOutOfProcess, |
- TestExceptionPorts::kSetOnTaskOnly, |
- TestExceptionPorts::kNobodyCrashes}, |
- {TestExceptionPorts::kSetOutOfProcess, |
- TestExceptionPorts::kSetOnTaskOnly, |
- TestExceptionPorts::kMainThreadCrashes}, |
- {TestExceptionPorts::kSetOutOfProcess, |
- TestExceptionPorts::kSetOnTaskOnly, |
- TestExceptionPorts::kOtherThreadCrashes}, |
- {TestExceptionPorts::kSetOutOfProcess, |
- TestExceptionPorts::kSetOnTaskAndThreads, |
- TestExceptionPorts::kNobodyCrashes}, |
- {TestExceptionPorts::kSetOutOfProcess, |
- TestExceptionPorts::kSetOnTaskAndThreads, |
- TestExceptionPorts::kMainThreadCrashes}, |
- {TestExceptionPorts::kSetOutOfProcess, |
- TestExceptionPorts::kSetOnTaskAndThreads, |
- TestExceptionPorts::kOtherThreadCrashes}, |
- }; |
+TEST(ExceptionPorts, TaskExceptionPorts_SetInProcess_MainThreadCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskOnly, |
+ TestExceptionPorts::kSetInProcess, |
+ TestExceptionPorts::kMainThreadCrashes); |
+ test_exception_ports.Run(); |
+} |
- for (size_t index = 0; index < arraysize(kTestcases); ++index) { |
- const Testcase& testcase = kTestcases[index]; |
- SCOPED_TRACE( |
- base::StringPrintf("index %zu, set_type %d, set_on %d, who_crashes %d", |
- index, |
- testcase.set_type, |
- testcase.set_on, |
- testcase.who_crashes)); |
- |
- TestExceptionPorts test_exception_ports( |
- testcase.set_type, testcase.set_on, testcase.who_crashes); |
- test_exception_ports.Run(); |
- } |
+TEST(ExceptionPorts, TaskExceptionPorts_SetInProcess_OtherThreadCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskOnly, |
+ TestExceptionPorts::kSetInProcess, |
+ TestExceptionPorts::kOtherThreadCrashes); |
+ test_exception_ports.Run(); |
+} |
+ |
+TEST(ExceptionPorts, TaskAndThreadExceptionPorts_SetInProcess_NoCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskAndThreads, |
+ TestExceptionPorts::kSetInProcess, |
+ TestExceptionPorts::kNobodyCrashes); |
+ test_exception_ports.Run(); |
+} |
+ |
+TEST(ExceptionPorts, TaskAndThreadExceptionPorts_SetInProcess_MainThreadCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskAndThreads, |
+ TestExceptionPorts::kSetInProcess, |
+ TestExceptionPorts::kMainThreadCrashes); |
+ test_exception_ports.Run(); |
+} |
+ |
+TEST(ExceptionPorts, |
+ TaskAndThreadExceptionPorts_SetInProcess_OtherThreadCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskAndThreads, |
+ TestExceptionPorts::kSetInProcess, |
+ TestExceptionPorts::kOtherThreadCrashes); |
+ test_exception_ports.Run(); |
+} |
+ |
+TEST(ExceptionPorts, TaskExceptionPorts_SetOutOfProcess_NoCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskOnly, |
+ TestExceptionPorts::kSetOutOfProcess, |
+ TestExceptionPorts::kNobodyCrashes); |
+ test_exception_ports.Run(); |
+} |
+ |
+TEST(ExceptionPorts, TaskExceptionPorts_SetOutOfProcess_MainThreadCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskOnly, |
+ TestExceptionPorts::kSetOutOfProcess, |
+ TestExceptionPorts::kMainThreadCrashes); |
+ test_exception_ports.Run(); |
+} |
+ |
+TEST(ExceptionPorts, TaskExceptionPorts_SetOutOfProcess_OtherThreadCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskOnly, |
+ TestExceptionPorts::kSetOutOfProcess, |
+ TestExceptionPorts::kOtherThreadCrashes); |
+ test_exception_ports.Run(); |
+} |
+ |
+TEST(ExceptionPorts, TaskAndThreadExceptionPorts_SetOutOfProcess_NoCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskAndThreads, |
+ TestExceptionPorts::kSetOutOfProcess, |
+ TestExceptionPorts::kNobodyCrashes); |
+ test_exception_ports.Run(); |
+} |
+ |
+TEST(ExceptionPorts, |
+ TaskAndThreadExceptionPorts_SetOutOfProcess_MainThreadCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskAndThreads, |
+ TestExceptionPorts::kSetOutOfProcess, |
+ TestExceptionPorts::kMainThreadCrashes); |
+ test_exception_ports.Run(); |
+} |
+ |
+TEST(ExceptionPorts, |
+ TaskAndThreadExceptionPorts_SetOutOfProcess_OtherThreadCrash) { |
+ TestExceptionPorts test_exception_ports( |
+ TestExceptionPorts::kSetOnTaskAndThreads, |
+ TestExceptionPorts::kSetOutOfProcess, |
+ TestExceptionPorts::kOtherThreadCrashes); |
+ test_exception_ports.Run(); |
} |
TEST(ExceptionPorts, HostExceptionPorts) { |