Index: minidump/minidump_thread_writer_test.cc |
diff --git a/minidump/minidump_thread_writer_test.cc b/minidump/minidump_thread_writer_test.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4b7dad99895340e0647ac9f1bdd18fb8d9ecf48d |
--- /dev/null |
+++ b/minidump/minidump_thread_writer_test.cc |
@@ -0,0 +1,490 @@ |
+// Copyright 2014 The Crashpad Authors. All rights reserved. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
+ |
+#include "minidump/minidump_thread_writer.h" |
+ |
+#include <dbghelp.h> |
+ |
+#include "gtest/gtest.h" |
+#include "minidump/minidump_context_test_util.h" |
+#include "minidump/minidump_context_writer.h" |
+#include "minidump/minidump_memory_writer.h" |
+#include "minidump/minidump_memory_writer_test_util.h" |
+#include "minidump/minidump_file_writer.h" |
+#include "minidump/minidump_test_util.h" |
+#include "util/file/string_file_writer.h" |
+ |
+namespace crashpad { |
+namespace test { |
+namespace { |
+ |
+// This returns the MINIDUMP_THREAD_LIST stream in |thread_list|. If |
+// |memory_list| is non-NULL, a MINIDUMP_MEMORY_LIST stream is also expected in |
+// |file_contents|, and that stream will be returned in |memory_list|. |
+void GetThreadListStream(const std::string& file_contents, |
+ const MINIDUMP_THREAD_LIST** thread_list, |
+ const MINIDUMP_MEMORY_LIST** memory_list) { |
+ const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); |
+ const uint32_t kExpectedStreams = memory_list ? 2 : 1; |
+ const size_t kThreadListStreamOffset = |
+ kDirectoryOffset + kExpectedStreams * sizeof(MINIDUMP_DIRECTORY); |
+ const size_t kThreadsOffset = |
+ kThreadListStreamOffset + sizeof(MINIDUMP_THREAD_LIST); |
+ |
+ ASSERT_GE(file_contents.size(), kThreadsOffset); |
+ |
+ const MINIDUMP_HEADER* header = |
+ reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]); |
+ |
+ ASSERT_NO_FATAL_FAILURE(VerifyMinidumpHeader(header, kExpectedStreams, 0)); |
+ |
+ const MINIDUMP_DIRECTORY* directory = |
+ reinterpret_cast<const MINIDUMP_DIRECTORY*>( |
+ &file_contents[kDirectoryOffset]); |
+ |
+ ASSERT_EQ(kMinidumpStreamTypeThreadList, directory[0].StreamType); |
+ ASSERT_GE(directory[0].Location.DataSize, sizeof(MINIDUMP_THREAD_LIST)); |
+ ASSERT_EQ(kThreadListStreamOffset, directory[0].Location.Rva); |
+ |
+ *thread_list = reinterpret_cast<const MINIDUMP_THREAD_LIST*>( |
+ &file_contents[kThreadListStreamOffset]); |
+ |
+ ASSERT_EQ(sizeof(MINIDUMP_THREAD_LIST) + |
+ (*thread_list)->NumberOfThreads * sizeof(MINIDUMP_THREAD), |
+ directory[0].Location.DataSize); |
+ |
+ if (memory_list) { |
+ *memory_list = reinterpret_cast<const MINIDUMP_MEMORY_LIST*>( |
+ &file_contents[directory[1].Location.Rva]); |
+ } |
+} |
+ |
+TEST(MinidumpThreadWriter, EmptyThreadList) { |
+ MinidumpFileWriter minidump_file_writer; |
+ MinidumpThreadListWriter thread_list_writer; |
+ |
+ minidump_file_writer.AddStream(&thread_list_writer); |
+ |
+ StringFileWriter file_writer; |
+ ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); |
+ |
+ ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + |
+ sizeof(MINIDUMP_THREAD_LIST), |
+ file_writer.string().size()); |
+ |
+ const MINIDUMP_THREAD_LIST* thread_list; |
+ ASSERT_NO_FATAL_FAILURE( |
+ GetThreadListStream(file_writer.string(), &thread_list, NULL)); |
+ |
+ EXPECT_EQ(0u, thread_list->NumberOfThreads); |
+} |
+ |
+// The MINIDUMP_THREADs |expected| and |observed| are compared against each |
+// other using gtest assertions. If |stack| is non-NULL, |observed| is expected |
+// to contain a populated MINIDUMP_MEMORY_DESCRIPTOR in its Stack field, |
+// otherwise, its Stack field is expected to be zeroed out. The memory |
+// descriptor will be placed in |stack|. |observed| must contain a populated |
+// ThreadContext field. The context will be recovered from |file_contents| and |
+// stored in |context_base|. |
+void ExpectThread(const MINIDUMP_THREAD* expected, |
+ const MINIDUMP_THREAD* observed, |
+ const std::string& file_contents, |
+ const MINIDUMP_MEMORY_DESCRIPTOR** stack, |
+ const void** context_base) { |
+ EXPECT_EQ(expected->ThreadId, observed->ThreadId); |
+ EXPECT_EQ(expected->SuspendCount, observed->SuspendCount); |
+ EXPECT_EQ(expected->PriorityClass, observed->PriorityClass); |
+ EXPECT_EQ(expected->Priority, observed->Priority); |
+ EXPECT_EQ(expected->Teb, observed->Teb); |
+ |
+ EXPECT_EQ(expected->Stack.StartOfMemoryRange, |
+ observed->Stack.StartOfMemoryRange); |
+ EXPECT_EQ(expected->Stack.Memory.DataSize, observed->Stack.Memory.DataSize); |
+ if (stack) { |
+ ASSERT_NE(0u, observed->Stack.Memory.DataSize); |
+ ASSERT_NE(0u, observed->Stack.Memory.Rva); |
+ ASSERT_GE(file_contents.size(), |
+ observed->Stack.Memory.Rva + observed->Stack.Memory.DataSize); |
+ *stack = &observed->Stack; |
+ } else { |
+ EXPECT_EQ(0u, observed->Stack.StartOfMemoryRange); |
+ EXPECT_EQ(0u, observed->Stack.Memory.DataSize); |
+ EXPECT_EQ(0u, observed->Stack.Memory.Rva); |
+ } |
+ |
+ EXPECT_EQ(expected->ThreadContext.DataSize, observed->ThreadContext.DataSize); |
+ ASSERT_NE(0u, observed->ThreadContext.DataSize); |
+ ASSERT_NE(0u, observed->ThreadContext.Rva); |
+ ASSERT_GE(file_contents.size(), |
+ observed->ThreadContext.Rva + expected->ThreadContext.DataSize); |
+ *context_base = &file_contents[observed->ThreadContext.Rva]; |
+} |
+ |
+TEST(MinidumpThreadWriter, OneThread_x86_NoStack) { |
+ MinidumpFileWriter minidump_file_writer; |
+ MinidumpThreadListWriter thread_list_writer; |
+ |
+ const uint32_t kThreadID = 0x11111111; |
+ const uint32_t kSuspendCount = 1; |
+ const uint32_t kPriorityClass = 0x20; |
+ const uint32_t kPriority = 10; |
+ const uint64_t kTEB = 0x55555555; |
+ const uint32_t kSeed = 123; |
+ |
+ MinidumpThreadWriter thread_writer; |
+ thread_writer.SetThreadID(kThreadID); |
+ thread_writer.SetSuspendCount(kSuspendCount); |
+ thread_writer.SetPriorityClass(kPriorityClass); |
+ thread_writer.SetPriority(kPriority); |
+ thread_writer.SetTEB(kTEB); |
+ |
+ MinidumpContextX86Writer context_x86_writer; |
+ InitializeMinidumpContextX86(context_x86_writer.context(), kSeed); |
+ thread_writer.SetContext(&context_x86_writer); |
+ |
+ thread_list_writer.AddThread(&thread_writer); |
+ minidump_file_writer.AddStream(&thread_list_writer); |
+ |
+ StringFileWriter file_writer; |
+ ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); |
+ |
+ ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + |
+ sizeof(MINIDUMP_THREAD_LIST) + 1 * sizeof(MINIDUMP_THREAD) + |
+ 1 * sizeof(MinidumpContextX86), |
+ file_writer.string().size()); |
+ |
+ const MINIDUMP_THREAD_LIST* thread_list; |
+ ASSERT_NO_FATAL_FAILURE( |
+ GetThreadListStream(file_writer.string(), &thread_list, NULL)); |
+ |
+ EXPECT_EQ(1u, thread_list->NumberOfThreads); |
+ |
+ MINIDUMP_THREAD expected = {}; |
+ expected.ThreadId = kThreadID; |
+ expected.SuspendCount = kSuspendCount; |
+ expected.PriorityClass = kPriorityClass; |
+ expected.Priority = kPriority; |
+ expected.Teb = kTEB; |
+ expected.ThreadContext.DataSize = sizeof(MinidumpContextX86); |
+ |
+ const MinidumpContextX86* observed_context; |
+ ASSERT_NO_FATAL_FAILURE( |
+ ExpectThread(&expected, |
+ &thread_list->Threads[0], |
+ file_writer.string(), |
+ NULL, |
+ reinterpret_cast<const void**>(&observed_context))); |
+ |
+ ASSERT_NO_FATAL_FAILURE(ExpectMinidumpContextX86(kSeed, observed_context)); |
+} |
+ |
+TEST(MinidumpThreadWriter, OneThread_AMD64_Stack) { |
+ MinidumpFileWriter minidump_file_writer; |
+ MinidumpThreadListWriter thread_list_writer; |
+ |
+ const uint32_t kThreadID = 0x22222222; |
+ const uint32_t kSuspendCount = 2; |
+ const uint32_t kPriorityClass = 0x30; |
+ const uint32_t kPriority = 20; |
+ const uint64_t kTEB = 0x5555555555555555; |
+ const uint64_t kMemoryBase = 0x765432100000; |
+ const size_t kMemorySize = 32; |
+ const uint8_t kMemoryValue = 99; |
+ const uint32_t kSeed = 456; |
+ |
+ MinidumpThreadWriter thread_writer; |
+ thread_writer.SetThreadID(kThreadID); |
+ thread_writer.SetSuspendCount(kSuspendCount); |
+ thread_writer.SetPriorityClass(kPriorityClass); |
+ thread_writer.SetPriority(kPriority); |
+ thread_writer.SetTEB(kTEB); |
+ |
+ TestMinidumpMemoryWriter memory_writer( |
+ kMemoryBase, kMemorySize, kMemoryValue); |
+ thread_writer.SetStack(&memory_writer); |
+ |
+ MinidumpContextAMD64Writer context_amd64_writer; |
+ InitializeMinidumpContextAMD64(context_amd64_writer.context(), kSeed); |
+ thread_writer.SetContext(&context_amd64_writer); |
+ |
+ thread_list_writer.AddThread(&thread_writer); |
+ minidump_file_writer.AddStream(&thread_list_writer); |
+ |
+ StringFileWriter file_writer; |
+ ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); |
+ |
+ ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + |
+ sizeof(MINIDUMP_THREAD_LIST) + 1 * sizeof(MINIDUMP_THREAD) + |
+ 1 * sizeof(MinidumpContextAMD64) + kMemorySize, |
+ file_writer.string().size()); |
+ |
+ const MINIDUMP_THREAD_LIST* thread_list; |
+ ASSERT_NO_FATAL_FAILURE( |
+ GetThreadListStream(file_writer.string(), &thread_list, NULL)); |
+ |
+ EXPECT_EQ(1u, thread_list->NumberOfThreads); |
+ |
+ MINIDUMP_THREAD expected = {}; |
+ expected.ThreadId = kThreadID; |
+ expected.SuspendCount = kSuspendCount; |
+ expected.PriorityClass = kPriorityClass; |
+ expected.Priority = kPriority; |
+ expected.Teb = kTEB; |
+ expected.Stack.StartOfMemoryRange = kMemoryBase; |
+ expected.Stack.Memory.DataSize = kMemorySize; |
+ expected.ThreadContext.DataSize = sizeof(MinidumpContextAMD64); |
+ |
+ const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack; |
+ const MinidumpContextAMD64* observed_context; |
+ ASSERT_NO_FATAL_FAILURE( |
+ ExpectThread(&expected, |
+ &thread_list->Threads[0], |
+ file_writer.string(), |
+ &observed_stack, |
+ reinterpret_cast<const void**>(&observed_context))); |
+ |
+ ASSERT_NO_FATAL_FAILURE( |
+ ExpectMinidumpMemoryDescriptorAndContents(&expected.Stack, |
+ observed_stack, |
+ file_writer.string(), |
+ kMemoryValue, |
+ true)); |
+ ASSERT_NO_FATAL_FAILURE(ExpectMinidumpContextAMD64(kSeed, observed_context)); |
+} |
+ |
+TEST(MinidumpThreadWriter, ThreeThreads_x86_MemoryList) { |
+ MinidumpFileWriter minidump_file_writer; |
+ MinidumpThreadListWriter thread_list_writer; |
+ MinidumpMemoryListWriter memory_list_writer; |
+ thread_list_writer.SetMemoryListWriter(&memory_list_writer); |
+ |
+ const uint32_t kThreadID0 = 1111111; |
+ const uint32_t kSuspendCount0 = 111111; |
+ const uint32_t kPriorityClass0 = 11111; |
+ const uint32_t kPriority0 = 1111; |
+ const uint64_t kTEB0 = 111; |
+ const uint64_t kMemoryBase0 = 0x1110; |
+ const size_t kMemorySize0 = 16; |
+ const uint8_t kMemoryValue0 = 11; |
+ const uint32_t kSeed0 = 1; |
+ |
+ MinidumpThreadWriter thread_writer_0; |
+ thread_writer_0.SetThreadID(kThreadID0); |
+ thread_writer_0.SetSuspendCount(kSuspendCount0); |
+ thread_writer_0.SetPriorityClass(kPriorityClass0); |
+ thread_writer_0.SetPriority(kPriority0); |
+ thread_writer_0.SetTEB(kTEB0); |
+ |
+ TestMinidumpMemoryWriter memory_writer_0( |
+ kMemoryBase0, kMemorySize0, kMemoryValue0); |
+ thread_writer_0.SetStack(&memory_writer_0); |
+ |
+ MinidumpContextX86Writer context_x86_writer_0; |
+ InitializeMinidumpContextX86(context_x86_writer_0.context(), kSeed0); |
+ thread_writer_0.SetContext(&context_x86_writer_0); |
+ |
+ thread_list_writer.AddThread(&thread_writer_0); |
+ |
+ const uint32_t kThreadID1 = 2222222; |
+ const uint32_t kSuspendCount1 = 222222; |
+ const uint32_t kPriorityClass1 = 22222; |
+ const uint32_t kPriority1 = 2222; |
+ const uint64_t kTEB1 = 222; |
+ const uint64_t kMemoryBase1 = 0x2220; |
+ const size_t kMemorySize1 = 32; |
+ const uint8_t kMemoryValue1 = 22; |
+ const uint32_t kSeed1 = 2; |
+ |
+ MinidumpThreadWriter thread_writer_1; |
+ thread_writer_1.SetThreadID(kThreadID1); |
+ thread_writer_1.SetSuspendCount(kSuspendCount1); |
+ thread_writer_1.SetPriorityClass(kPriorityClass1); |
+ thread_writer_1.SetPriority(kPriority1); |
+ thread_writer_1.SetTEB(kTEB1); |
+ |
+ TestMinidumpMemoryWriter memory_writer_1( |
+ kMemoryBase1, kMemorySize1, kMemoryValue1); |
+ thread_writer_1.SetStack(&memory_writer_1); |
+ |
+ MinidumpContextX86Writer context_x86_writer_1; |
+ InitializeMinidumpContextX86(context_x86_writer_1.context(), kSeed1); |
+ thread_writer_1.SetContext(&context_x86_writer_1); |
+ |
+ thread_list_writer.AddThread(&thread_writer_1); |
+ |
+ const uint32_t kThreadID2 = 3333333; |
+ const uint32_t kSuspendCount2 = 333333; |
+ const uint32_t kPriorityClass2 = 33333; |
+ const uint32_t kPriority2 = 3333; |
+ const uint64_t kTEB2 = 333; |
+ const uint64_t kMemoryBase2 = 0x3330; |
+ const size_t kMemorySize2 = 48; |
+ const uint8_t kMemoryValue2 = 33; |
+ const uint32_t kSeed2 = 3; |
+ |
+ MinidumpThreadWriter thread_writer_2; |
+ thread_writer_2.SetThreadID(kThreadID2); |
+ thread_writer_2.SetSuspendCount(kSuspendCount2); |
+ thread_writer_2.SetPriorityClass(kPriorityClass2); |
+ thread_writer_2.SetPriority(kPriority2); |
+ thread_writer_2.SetTEB(kTEB2); |
+ |
+ TestMinidumpMemoryWriter memory_writer_2( |
+ kMemoryBase2, kMemorySize2, kMemoryValue2); |
+ thread_writer_2.SetStack(&memory_writer_2); |
+ |
+ MinidumpContextX86Writer context_x86_writer_2; |
+ InitializeMinidumpContextX86(context_x86_writer_2.context(), kSeed2); |
+ thread_writer_2.SetContext(&context_x86_writer_2); |
+ |
+ thread_list_writer.AddThread(&thread_writer_2); |
+ |
+ minidump_file_writer.AddStream(&thread_list_writer); |
+ minidump_file_writer.AddStream(&memory_list_writer); |
+ |
+ StringFileWriter file_writer; |
+ ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); |
+ |
+ ASSERT_EQ(sizeof(MINIDUMP_HEADER) + 2 * sizeof(MINIDUMP_DIRECTORY) + |
+ sizeof(MINIDUMP_THREAD_LIST) + 3 * sizeof(MINIDUMP_THREAD) + |
+ sizeof(MINIDUMP_MEMORY_LIST) + |
+ 3 * sizeof(MINIDUMP_MEMORY_DESCRIPTOR) + |
+ 3 * sizeof(MinidumpContextX86) + kMemorySize0 + kMemorySize1 + |
+ kMemorySize2 + 12, // 12 for alignment |
+ file_writer.string().size()); |
+ |
+ const MINIDUMP_THREAD_LIST* thread_list; |
+ const MINIDUMP_MEMORY_LIST* memory_list; |
+ ASSERT_NO_FATAL_FAILURE( |
+ GetThreadListStream(file_writer.string(), &thread_list, &memory_list)); |
+ |
+ EXPECT_EQ(3u, thread_list->NumberOfThreads); |
+ EXPECT_EQ(3u, memory_list->NumberOfMemoryRanges); |
+ |
+ { |
+ SCOPED_TRACE("thread 0"); |
+ |
+ MINIDUMP_THREAD expected = {}; |
+ expected.ThreadId = kThreadID0; |
+ expected.SuspendCount = kSuspendCount0; |
+ expected.PriorityClass = kPriorityClass0; |
+ expected.Priority = kPriority0; |
+ expected.Teb = kTEB0; |
+ expected.Stack.StartOfMemoryRange = kMemoryBase0; |
+ expected.Stack.Memory.DataSize = kMemorySize0; |
+ expected.ThreadContext.DataSize = sizeof(MinidumpContextX86); |
+ |
+ const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack; |
+ const MinidumpContextX86* observed_context; |
+ ASSERT_NO_FATAL_FAILURE( |
+ ExpectThread(&expected, |
+ &thread_list->Threads[0], |
+ file_writer.string(), |
+ &observed_stack, |
+ reinterpret_cast<const void**>(&observed_context))); |
+ |
+ ASSERT_NO_FATAL_FAILURE( |
+ ExpectMinidumpMemoryDescriptorAndContents(&expected.Stack, |
+ observed_stack, |
+ file_writer.string(), |
+ kMemoryValue0, |
+ false)); |
+ ASSERT_NO_FATAL_FAILURE(ExpectMinidumpContextX86(kSeed0, observed_context)); |
+ ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptor( |
+ observed_stack, &memory_list->MemoryRanges[0])); |
+ } |
+ |
+ { |
+ SCOPED_TRACE("thread 1"); |
+ |
+ MINIDUMP_THREAD expected = {}; |
+ expected.ThreadId = kThreadID1; |
+ expected.SuspendCount = kSuspendCount1; |
+ expected.PriorityClass = kPriorityClass1; |
+ expected.Priority = kPriority1; |
+ expected.Teb = kTEB1; |
+ expected.Stack.StartOfMemoryRange = kMemoryBase1; |
+ expected.Stack.Memory.DataSize = kMemorySize1; |
+ expected.ThreadContext.DataSize = sizeof(MinidumpContextX86); |
+ |
+ const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack; |
+ const MinidumpContextX86* observed_context; |
+ ASSERT_NO_FATAL_FAILURE( |
+ ExpectThread(&expected, |
+ &thread_list->Threads[1], |
+ file_writer.string(), |
+ &observed_stack, |
+ reinterpret_cast<const void**>(&observed_context))); |
+ |
+ ASSERT_NO_FATAL_FAILURE( |
+ ExpectMinidumpMemoryDescriptorAndContents(&expected.Stack, |
+ observed_stack, |
+ file_writer.string(), |
+ kMemoryValue1, |
+ false)); |
+ ASSERT_NO_FATAL_FAILURE(ExpectMinidumpContextX86(kSeed1, observed_context)); |
+ ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptor( |
+ observed_stack, &memory_list->MemoryRanges[1])); |
+ } |
+ |
+ { |
+ SCOPED_TRACE("thread 2"); |
+ |
+ MINIDUMP_THREAD expected = {}; |
+ expected.ThreadId = kThreadID2; |
+ expected.SuspendCount = kSuspendCount2; |
+ expected.PriorityClass = kPriorityClass2; |
+ expected.Priority = kPriority2; |
+ expected.Teb = kTEB2; |
+ expected.Stack.StartOfMemoryRange = kMemoryBase2; |
+ expected.Stack.Memory.DataSize = kMemorySize2; |
+ expected.ThreadContext.DataSize = sizeof(MinidumpContextX86); |
+ |
+ const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack; |
+ const MinidumpContextX86* observed_context; |
+ ASSERT_NO_FATAL_FAILURE( |
+ ExpectThread(&expected, |
+ &thread_list->Threads[2], |
+ file_writer.string(), |
+ &observed_stack, |
+ reinterpret_cast<const void**>(&observed_context))); |
+ |
+ ASSERT_NO_FATAL_FAILURE( |
+ ExpectMinidumpMemoryDescriptorAndContents(&expected.Stack, |
+ observed_stack, |
+ file_writer.string(), |
+ kMemoryValue2, |
+ true)); |
+ ASSERT_NO_FATAL_FAILURE(ExpectMinidumpContextX86(kSeed2, observed_context)); |
+ ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptor( |
+ observed_stack, &memory_list->MemoryRanges[2])); |
+ } |
+} |
+ |
+TEST(MinidumpThreadWriterDeathTest, NoContext) { |
+ MinidumpFileWriter minidump_file_writer; |
+ MinidumpThreadListWriter thread_list_writer; |
+ |
+ MinidumpThreadWriter thread_writer; |
+ |
+ thread_list_writer.AddThread(&thread_writer); |
+ minidump_file_writer.AddStream(&thread_list_writer); |
+ |
+ StringFileWriter file_writer; |
+ ASSERT_DEATH(minidump_file_writer.WriteEverything(&file_writer), "context_"); |
+} |
+ |
+} // namespace |
+} // namespace test |
+} // namespace crashpad |