minidump_unittest.cc revision 9244496c6f875ef1f7166d65f218d57ae92cabaa
1// Copyright (c) 2010, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30// Unit test for Minidump.  Uses a pre-generated minidump and
31// verifies that certain streams are correct.
32
33#include <iostream>
34#include <fstream>
35#include <sstream>
36#include <stdlib.h>
37#include <string>
38#include <vector>
39#include "breakpad_googletest_includes.h"
40#include "google_breakpad/common/minidump_format.h"
41#include "google_breakpad/processor/minidump.h"
42#include "processor/logging.h"
43#include "processor/synth_minidump.h"
44
45namespace {
46
47using google_breakpad::Minidump;
48using google_breakpad::MinidumpContext;
49using google_breakpad::MinidumpMemoryList;
50using google_breakpad::MinidumpMemoryRegion;
51using google_breakpad::MinidumpModule;
52using google_breakpad::MinidumpModuleList;
53using google_breakpad::MinidumpSystemInfo;
54using google_breakpad::MinidumpThread;
55using google_breakpad::MinidumpThreadList;
56using google_breakpad::SynthMinidump::Context;
57using google_breakpad::SynthMinidump::Dump;
58using google_breakpad::SynthMinidump::Memory;
59using google_breakpad::SynthMinidump::Module;
60using google_breakpad::SynthMinidump::Stream;
61using google_breakpad::SynthMinidump::String;
62using google_breakpad::SynthMinidump::SystemInfo;
63using google_breakpad::SynthMinidump::Thread;
64using google_breakpad::TestAssembler::kBigEndian;
65using google_breakpad::TestAssembler::kLittleEndian;
66using std::ifstream;
67using std::istringstream;
68using std::string;
69using std::vector;
70using ::testing::Return;
71
72class MinidumpTest : public ::testing::Test {
73public:
74  void SetUp() {
75    minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") +
76      "/src/processor/testdata/minidump2.dmp";
77  }
78  string minidump_file_;
79};
80
81TEST_F(MinidumpTest, TestMinidumpFromFile) {
82  Minidump minidump(minidump_file_);
83  ASSERT_EQ(minidump.path(), minidump_file_);
84  ASSERT_TRUE(minidump.Read());
85  const MDRawHeader* header = minidump.header();
86  ASSERT_NE(header, (MDRawHeader*)NULL);
87  ASSERT_EQ(header->signature, u_int32_t(MD_HEADER_SIGNATURE));
88  //TODO: add more checks here
89}
90
91TEST_F(MinidumpTest, TestMinidumpFromStream) {
92  // read minidump contents into memory, construct a stringstream around them
93  ifstream file_stream(minidump_file_.c_str(), std::ios::in);
94  ASSERT_TRUE(file_stream.good());
95  vector<char> bytes;
96  file_stream.seekg(0, std::ios_base::end);
97  ASSERT_TRUE(file_stream.good());
98  bytes.resize(file_stream.tellg());
99  file_stream.seekg(0, std::ios_base::beg);
100  ASSERT_TRUE(file_stream.good());
101  file_stream.read(&bytes[0], bytes.size());
102  ASSERT_TRUE(file_stream.good());
103  string str(&bytes[0], bytes.size());
104  istringstream stream(str);
105  ASSERT_TRUE(stream.good());
106
107  // now read minidump from stringstream
108  Minidump minidump(stream);
109  ASSERT_EQ(minidump.path(), "");
110  ASSERT_TRUE(minidump.Read());
111  const MDRawHeader* header = minidump.header();
112  ASSERT_NE(header, (MDRawHeader*)NULL);
113  ASSERT_EQ(header->signature, u_int32_t(MD_HEADER_SIGNATURE));
114  //TODO: add more checks here
115}
116
117TEST(Dump, ReadBackEmpty) {
118  Dump dump(0);
119  dump.Finish();
120  string contents;
121  ASSERT_TRUE(dump.GetContents(&contents));
122  istringstream stream(contents);
123  Minidump minidump(stream);
124  ASSERT_TRUE(minidump.Read());
125  ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
126}
127
128TEST(Dump, ReadBackEmptyBigEndian) {
129  Dump big_minidump(0, kBigEndian);
130  big_minidump.Finish();
131  string contents;
132  ASSERT_TRUE(big_minidump.GetContents(&contents));
133  istringstream stream(contents);
134  Minidump minidump(stream);
135  ASSERT_TRUE(minidump.Read());
136  ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
137}
138
139TEST(Dump, OneStream) {
140  Dump dump(0, kBigEndian);
141  Stream stream(dump, 0xfbb7fa2bU);
142  stream.Append("stream contents");
143  dump.Add(&stream);
144  dump.Finish();
145
146  string contents;
147  ASSERT_TRUE(dump.GetContents(&contents));
148  istringstream minidump_stream(contents);
149  Minidump minidump(minidump_stream);
150  ASSERT_TRUE(minidump.Read());
151  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
152
153  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
154  ASSERT_TRUE(dir != NULL);
155  EXPECT_EQ(0xfbb7fa2bU, dir->stream_type);
156
157  u_int32_t stream_length;
158  ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length));
159  ASSERT_EQ(15U, stream_length);
160  char stream_contents[15];
161  ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents)));
162  EXPECT_EQ(string("stream contents"),
163            string(stream_contents, sizeof(stream_contents)));
164
165  EXPECT_FALSE(minidump.GetThreadList());
166  EXPECT_FALSE(minidump.GetModuleList());
167  EXPECT_FALSE(minidump.GetMemoryList());
168  EXPECT_FALSE(minidump.GetException());
169  EXPECT_FALSE(minidump.GetAssertion());
170  EXPECT_FALSE(minidump.GetSystemInfo());
171  EXPECT_FALSE(minidump.GetMiscInfo());
172  EXPECT_FALSE(minidump.GetBreakpadInfo());
173}
174
175TEST(Dump, OneMemory) {
176  Dump dump(0, kBigEndian);
177  Memory memory(dump, 0x309d68010bd21b2cULL);
178  memory.Append("memory contents");
179  dump.Add(&memory);
180  dump.Finish();
181
182  string contents;
183  ASSERT_TRUE(dump.GetContents(&contents));
184  istringstream minidump_stream(contents);
185  Minidump minidump(minidump_stream);
186  ASSERT_TRUE(minidump.Read());
187  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
188
189  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
190  ASSERT_TRUE(dir != NULL);
191  EXPECT_EQ((u_int32_t) MD_MEMORY_LIST_STREAM, dir->stream_type);
192
193  MinidumpMemoryList *memory_list = minidump.GetMemoryList();
194  ASSERT_TRUE(memory_list != NULL);
195  ASSERT_EQ(1U, memory_list->region_count());
196
197  MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0);
198  ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase());
199  ASSERT_EQ(15U, region1->GetSize());
200  const u_int8_t *region1_bytes = region1->GetMemory();
201  ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0);
202}
203
204// One thread --- and its requisite entourage.
205TEST(Dump, OneThread) {
206  Dump dump(0, kLittleEndian);
207  Memory stack(dump, 0x2326a0fa);
208  stack.Append("stack for thread");
209
210  MDRawContextX86 raw_context;
211  raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
212  raw_context.edi = 0x3ecba80d;
213  raw_context.esi = 0x382583b9;
214  raw_context.ebx = 0x7fccc03f;
215  raw_context.edx = 0xf62f8ec2;
216  raw_context.ecx = 0x46a6a6a8;
217  raw_context.eax = 0x6a5025e2;
218  raw_context.ebp = 0xd9fabb4a;
219  raw_context.eip = 0x6913f540;
220  raw_context.cs = 0xbffe6eda;
221  raw_context.eflags = 0xb2ce1e2d;
222  raw_context.esp = 0x659caaa4;
223  raw_context.ss = 0x2e951ef7;
224  Context context(dump, raw_context);
225
226  Thread thread(dump, 0xa898f11b, stack, context,
227                0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
228
229  dump.Add(&stack);
230  dump.Add(&context);
231  dump.Add(&thread);
232  dump.Finish();
233
234  string contents;
235  ASSERT_TRUE(dump.GetContents(&contents));
236
237  istringstream minidump_stream(contents);
238  Minidump minidump(minidump_stream);
239  ASSERT_TRUE(minidump.Read());
240  ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
241
242  MinidumpMemoryList *md_memory_list = minidump.GetMemoryList();
243  ASSERT_TRUE(md_memory_list != NULL);
244  ASSERT_EQ(1U, md_memory_list->region_count());
245
246  MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0);
247  ASSERT_EQ(0x2326a0faU, md_region->GetBase());
248  ASSERT_EQ(16U, md_region->GetSize());
249  const u_int8_t *region_bytes = md_region->GetMemory();
250  ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0);
251
252  MinidumpThreadList *thread_list = minidump.GetThreadList();
253  ASSERT_TRUE(thread_list != NULL);
254  ASSERT_EQ(1U, thread_list->thread_count());
255
256  MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0);
257  ASSERT_TRUE(md_thread != NULL);
258  u_int32_t thread_id;
259  ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
260  ASSERT_EQ(0xa898f11bU, thread_id);
261  MinidumpMemoryRegion *md_stack = md_thread->GetMemory();
262  ASSERT_TRUE(md_stack != NULL);
263  ASSERT_EQ(0x2326a0faU, md_stack->GetBase());
264  ASSERT_EQ(16U, md_stack->GetSize());
265  const u_int8_t *md_stack_bytes = md_stack->GetMemory();
266  ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0);
267
268  MinidumpContext *md_context = md_thread->GetContext();
269  ASSERT_TRUE(md_context != NULL);
270  ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
271  const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
272  ASSERT_TRUE(md_raw_context != NULL);
273  ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
274            (md_raw_context->context_flags
275             & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
276  EXPECT_EQ(0x3ecba80dU, raw_context.edi);
277  EXPECT_EQ(0x382583b9U, raw_context.esi);
278  EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
279  EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
280  EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
281  EXPECT_EQ(0x6a5025e2U, raw_context.eax);
282  EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
283  EXPECT_EQ(0x6913f540U, raw_context.eip);
284  EXPECT_EQ(0xbffe6edaU, raw_context.cs);
285  EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
286  EXPECT_EQ(0x659caaa4U, raw_context.esp);
287  EXPECT_EQ(0x2e951ef7U, raw_context.ss);
288}
289
290TEST(Dump, OneModule) {
291  static const MDVSFixedFileInfo fixed_file_info = {
292    0xb2fba33a,                           // signature
293    0x33d7a728,                           // struct_version
294    0x31afcb20,                           // file_version_hi
295    0xe51cdab1,                           // file_version_lo
296    0xd1ea6907,                           // product_version_hi
297    0x03032857,                           // product_version_lo
298    0x11bf71d7,                           // file_flags_mask
299    0x5fb8cdbf,                           // file_flags
300    0xe45d0d5d,                           // file_os
301    0x107d9562,                           // file_type
302    0x5a8844d4,                           // file_subtype
303    0xa8d30b20,                           // file_date_hi
304    0x651c3e4e                            // file_date_lo
305  };
306
307  Dump dump(0, kBigEndian);
308  String module_name(dump, "single module");
309  Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
310                module_name,
311                0xb1054d2a,
312                0x34571371,
313                fixed_file_info, // from synth_minidump_unittest_data.h
314                NULL, NULL);
315
316  dump.Add(&module);
317  dump.Add(&module_name);
318  dump.Finish();
319
320  string contents;
321  ASSERT_TRUE(dump.GetContents(&contents));
322  istringstream minidump_stream(contents);
323  Minidump minidump(minidump_stream);
324  ASSERT_TRUE(minidump.Read());
325  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
326
327  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
328  ASSERT_TRUE(dir != NULL);
329  EXPECT_EQ((u_int32_t) MD_MODULE_LIST_STREAM, dir->stream_type);
330
331  MinidumpModuleList *md_module_list = minidump.GetModuleList();
332  ASSERT_TRUE(md_module_list != NULL);
333  ASSERT_EQ(1U, md_module_list->module_count());
334
335  const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
336  ASSERT_TRUE(md_module != NULL);
337  ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address());
338  ASSERT_EQ(0xada542bd, md_module->size());
339  ASSERT_EQ("single module", md_module->code_file());
340
341  const MDRawModule *md_raw_module = md_module->module();
342  ASSERT_TRUE(md_raw_module != NULL);
343  ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp);
344  ASSERT_EQ(0x34571371U, md_raw_module->checksum);
345  ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info,
346                     sizeof(fixed_file_info)) == 0);
347}
348
349TEST(Dump, OneSystemInfo) {
350  Dump dump(0, kLittleEndian);
351  String csd_version(dump, "Petulant Pierogi");
352  SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
353
354  dump.Add(&system_info);
355  dump.Add(&csd_version);
356  dump.Finish();
357
358  string contents;
359  ASSERT_TRUE(dump.GetContents(&contents));
360  istringstream minidump_stream(contents);
361  Minidump minidump(minidump_stream);
362  ASSERT_TRUE(minidump.Read());
363  ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
364
365  const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
366  ASSERT_TRUE(dir != NULL);
367  EXPECT_EQ((u_int32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type);
368
369  MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo();
370  ASSERT_TRUE(md_system_info != NULL);
371  ASSERT_EQ("windows", md_system_info->GetOS());
372  ASSERT_EQ("x86", md_system_info->GetCPU());
373  ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion());
374  ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor());
375}
376
377TEST(Dump, BigDump) {
378  Dump dump(0, kLittleEndian);
379
380  // A SystemInfo stream.
381  String csd_version(dump, "Munificent Macaque");
382  SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
383  dump.Add(&csd_version);
384  dump.Add(&system_info);
385
386  // Five threads!
387  Memory stack0(dump, 0x70b9ebfc);
388  stack0.Append("stack for thread zero");
389  MDRawContextX86 raw_context0;
390  raw_context0.context_flags = MD_CONTEXT_X86_INTEGER;
391  raw_context0.eip = 0xaf0709e4;
392  Context context0(dump, raw_context0);
393  Thread thread0(dump, 0xbbef4432, stack0, context0,
394                 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL);
395  dump.Add(&stack0);
396  dump.Add(&context0);
397  dump.Add(&thread0);
398
399  Memory stack1(dump, 0xf988cc45);
400  stack1.Append("stack for thread one");
401  MDRawContextX86 raw_context1;
402  raw_context1.context_flags = MD_CONTEXT_X86_INTEGER;
403  raw_context1.eip = 0xe4f56f81;
404  Context context1(dump, raw_context1);
405  Thread thread1(dump, 0x657c3f58, stack1, context1,
406                 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL);
407  dump.Add(&stack1);
408  dump.Add(&context1);
409  dump.Add(&thread1);
410
411  Memory stack2(dump, 0xc8a92e7c);
412  stack2.Append("stack for thread two");
413  MDRawContextX86 raw_context2;
414  raw_context2.context_flags = MD_CONTEXT_X86_INTEGER;
415  raw_context2.eip = 0xb336a438;
416  Context context2(dump, raw_context2);
417  Thread thread2(dump, 0xdf4b8a71, stack2, context2,
418                 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL);
419  dump.Add(&stack2);
420  dump.Add(&context2);
421  dump.Add(&thread2);
422
423  Memory stack3(dump, 0x36d08e08);
424  stack3.Append("stack for thread three");
425  MDRawContextX86 raw_context3;
426  raw_context3.context_flags = MD_CONTEXT_X86_INTEGER;
427  raw_context3.eip = 0xdf99a60c;
428  Context context3(dump, raw_context3);
429  Thread thread3(dump, 0x86e6c341, stack3, context3,
430                 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL);
431  dump.Add(&stack3);
432  dump.Add(&context3);
433  dump.Add(&thread3);
434
435  Memory stack4(dump, 0x1e0ab4fa);
436  stack4.Append("stack for thread four");
437  MDRawContextX86 raw_context4;
438  raw_context4.context_flags = MD_CONTEXT_X86_INTEGER;
439  raw_context4.eip = 0xaa646267;
440  Context context4(dump, raw_context4);
441  Thread thread4(dump, 0x261a28d4, stack4, context4,
442                 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL);
443  dump.Add(&stack4);
444  dump.Add(&context4);
445  dump.Add(&thread4);
446
447  // Three modules!
448  String module1_name(dump, "module one");
449  Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name);
450  dump.Add(&module1_name);
451  dump.Add(&module1);
452
453  String module2_name(dump, "module two");
454  Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name);
455  dump.Add(&module2_name);
456  dump.Add(&module2);
457
458  String module3_name(dump, "module three");
459  Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name);
460  dump.Add(&module3_name);
461  dump.Add(&module3);
462
463  // Add one more memory region, on top of the five stacks.
464  Memory memory5(dump, 0x61979e828040e564ULL);
465  memory5.Append("contents of memory 5");
466  dump.Add(&memory5);
467
468  dump.Finish();
469
470  string contents;
471  ASSERT_TRUE(dump.GetContents(&contents));
472  istringstream minidump_stream(contents);
473  Minidump minidump(minidump_stream);
474  ASSERT_TRUE(minidump.Read());
475  ASSERT_EQ(4U, minidump.GetDirectoryEntryCount());
476
477  // Check the threads.
478  MinidumpThreadList *thread_list = minidump.GetThreadList();
479  ASSERT_TRUE(thread_list != NULL);
480  ASSERT_EQ(5U, thread_list->thread_count());
481  u_int32_t thread_id;
482  ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id));
483  ASSERT_EQ(0xbbef4432U, thread_id);
484  ASSERT_EQ(0x70b9ebfcU,
485            thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase());
486  ASSERT_EQ(0xaf0709e4U,
487            thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86()
488            ->eip);
489
490  ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id));
491  ASSERT_EQ(0x657c3f58U, thread_id);
492  ASSERT_EQ(0xf988cc45U,
493            thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase());
494  ASSERT_EQ(0xe4f56f81U,
495            thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86()
496            ->eip);
497
498  ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id));
499  ASSERT_EQ(0xdf4b8a71U, thread_id);
500  ASSERT_EQ(0xc8a92e7cU,
501            thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase());
502  ASSERT_EQ(0xb336a438U,
503            thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86()
504            ->eip);
505
506  ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id));
507  ASSERT_EQ(0x86e6c341U, thread_id);
508  ASSERT_EQ(0x36d08e08U,
509            thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase());
510  ASSERT_EQ(0xdf99a60cU,
511            thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86()
512            ->eip);
513
514  ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id));
515  ASSERT_EQ(0x261a28d4U, thread_id);
516  ASSERT_EQ(0x1e0ab4faU,
517            thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase());
518  ASSERT_EQ(0xaa646267U,
519            thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86()
520            ->eip);
521
522  // Check the modules.
523  MinidumpModuleList *md_module_list = minidump.GetModuleList();
524  ASSERT_TRUE(md_module_list != NULL);
525  ASSERT_EQ(3U, md_module_list->module_count());
526  EXPECT_EQ(0xeb77da57b5d4cbdaULL,
527            md_module_list->GetModuleAtIndex(0)->base_address());
528  EXPECT_EQ(0x8675884adfe5ac90ULL,
529            md_module_list->GetModuleAtIndex(1)->base_address());
530  EXPECT_EQ(0x95fc1544da321b6cULL,
531            md_module_list->GetModuleAtIndex(2)->base_address());
532}
533
534}  // namespace
535