aboutsummaryrefslogtreecommitdiff
path: root/src/client/mac/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/mac/tests')
-rw-r--r--src/client/mac/tests/exception_handler_test.cc62
1 files changed, 61 insertions, 1 deletions
diff --git a/src/client/mac/tests/exception_handler_test.cc b/src/client/mac/tests/exception_handler_test.cc
index 4bdd1856..004bc8e7 100644
--- a/src/client/mac/tests/exception_handler_test.cc
+++ b/src/client/mac/tests/exception_handler_test.cc
@@ -29,6 +29,7 @@
// exception_handler_test.cc: Unit tests for google_breakpad::ExceptionHandler
+#include <pthread.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -241,7 +242,7 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemory) {
// of the block of memory, because the minidump should contain 128
// bytes on either side of the instruction pointer.
memcpy(memory + kOffset, instructions, sizeof(instructions));
-
+
// Now execute the instructions, which should crash.
typedef void (*void_function)(void);
void_function memory_function =
@@ -594,4 +595,63 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) {
ASSERT_EQ((unsigned int)1, memory_list->region_count());
}
+static void *Junk(void *) {
+ sleep(1000000);
+ return NULL;
+}
+
+// Test that the memory list gets written correctly when multiple
+// threads are running.
+TEST_F(ExceptionHandlerTest, MemoryListMultipleThreads) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path, NULL, MDCallback, &fds[1], true, NULL);
+
+ // Run an extra thread so >2 memory regions will be written.
+ pthread_t junk_thread;
+ if (pthread_create(&junk_thread, NULL, Junk, NULL) == 0)
+ pthread_detach(junk_thread);
+
+ // Just crash.
+ Crasher();
+
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump, and verify that the memory list can be read.
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(memory_list);
+ // Verify that there are three memory regions:
+ // one per thread, and one for the instruction pointer memory.
+ ASSERT_EQ((unsigned int)3, memory_list->region_count());
+}
+
}