OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 | |
15 #include "minidump/minidump_thread_writer.h" | |
16 | |
17 #include <dbghelp.h> | |
18 | |
19 #include "gtest/gtest.h" | |
20 #include "minidump/minidump_context_test_util.h" | |
21 #include "minidump/minidump_context_writer.h" | |
22 #include "minidump/minidump_memory_writer.h" | |
23 #include "minidump/minidump_memory_writer_test_util.h" | |
24 #include "minidump/minidump_file_writer.h" | |
25 #include "minidump/minidump_test_util.h" | |
26 #include "util/file/string_file_writer.h" | |
27 | |
28 namespace crashpad { | |
29 namespace test { | |
30 namespace { | |
31 | |
32 // This returns the MINIDUMP_THREAD_LIST stream in |thread_list|. If | |
33 // |memory_list| is non-NULL, a MINIDUMP_MEMORY_LIST stream is also expected in | |
34 // |file_contents|, and that stream will be returned in |memory_list|. | |
35 void GetThreadListStream(const std::string& file_contents, | |
36 const MINIDUMP_THREAD_LIST** thread_list, | |
37 const MINIDUMP_MEMORY_LIST** memory_list) { | |
38 const size_t kDirectoryOffset = sizeof(MINIDUMP_HEADER); | |
39 const uint32_t kExpectedStreams = memory_list ? 2 : 1; | |
40 const size_t kThreadListStreamOffset = | |
41 kDirectoryOffset + kExpectedStreams * sizeof(MINIDUMP_DIRECTORY); | |
42 const size_t kThreadsOffset = | |
43 kThreadListStreamOffset + sizeof(MINIDUMP_THREAD_LIST); | |
44 | |
45 ASSERT_GE(file_contents.size(), kThreadsOffset); | |
46 | |
47 const MINIDUMP_HEADER* header = | |
48 reinterpret_cast<const MINIDUMP_HEADER*>(&file_contents[0]); | |
49 | |
50 VerifyMinidumpHeader(header, kExpectedStreams, 0); | |
51 if (testing::Test::HasFatalFailure()) { | |
52 return; | |
53 } | |
54 | |
55 const MINIDUMP_DIRECTORY* directory = | |
56 reinterpret_cast<const MINIDUMP_DIRECTORY*>( | |
57 &file_contents[kDirectoryOffset]); | |
58 | |
59 ASSERT_EQ(kMinidumpStreamTypeThreadList, directory[0].StreamType); | |
60 ASSERT_GE(directory[0].Location.DataSize, sizeof(MINIDUMP_THREAD_LIST)); | |
61 ASSERT_EQ(kThreadListStreamOffset, directory[0].Location.Rva); | |
62 | |
63 *thread_list = reinterpret_cast<const MINIDUMP_THREAD_LIST*>( | |
64 &file_contents[kThreadListStreamOffset]); | |
65 | |
66 ASSERT_EQ(sizeof(MINIDUMP_THREAD_LIST) + | |
67 (*thread_list)->NumberOfThreads * sizeof(MINIDUMP_THREAD), | |
68 directory[0].Location.DataSize); | |
69 | |
70 if (memory_list) { | |
71 *memory_list = reinterpret_cast<const MINIDUMP_MEMORY_LIST*>( | |
72 &file_contents[directory[1].Location.Rva]); | |
73 } | |
74 } | |
75 | |
76 TEST(MinidumpThreadWriter, EmptyThreadList) { | |
77 MinidumpFileWriter minidump_file_writer; | |
78 MinidumpThreadListWriter thread_list_writer; | |
79 | |
80 minidump_file_writer.AddStream(&thread_list_writer); | |
81 | |
82 StringFileWriter file_writer; | |
83 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); | |
84 | |
85 ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + | |
86 sizeof(MINIDUMP_THREAD_LIST), | |
87 file_writer.string().size()); | |
88 | |
89 const MINIDUMP_THREAD_LIST* thread_list; | |
90 GetThreadListStream(file_writer.string(), &thread_list, NULL); | |
91 if (Test::HasFatalFailure()) { | |
Robert Sesek
2014/10/08 21:49:31
You use testing::Test above but not here.
Mark Mentovai
2014/10/08 22:41:03
Robert Sesek wrote:
| |
92 return; | |
93 } | |
94 | |
95 EXPECT_EQ(0u, thread_list->NumberOfThreads); | |
96 } | |
97 | |
98 // The MINIDUMP_THREADs |expected| and |observed| are compared against each | |
99 // other using gtest assertions. If |stack| is non-NULL, |observed| is expected | |
100 // to contain a populated MINIDUMP_MEMORY_DESCRIPTOR in its Stack field, | |
101 // otherwise, its Stack field is expected to be zeroed out. The memory | |
102 // descriptor will be placed in |stack|. |observed| must contain a populated | |
103 // ThreadContext field. The context will be recovered from |file_contents| and | |
104 // stored in |context_base|. | |
105 void ExpectThread(const MINIDUMP_THREAD* expected, | |
106 const MINIDUMP_THREAD* observed, | |
107 const std::string& file_contents, | |
108 const MINIDUMP_MEMORY_DESCRIPTOR** stack, | |
109 const void** context_base) { | |
110 EXPECT_EQ(expected->ThreadId, observed->ThreadId); | |
111 EXPECT_EQ(expected->SuspendCount, observed->SuspendCount); | |
112 EXPECT_EQ(expected->PriorityClass, observed->PriorityClass); | |
113 EXPECT_EQ(expected->Priority, observed->Priority); | |
114 EXPECT_EQ(expected->Teb, observed->Teb); | |
115 | |
116 EXPECT_EQ(expected->Stack.StartOfMemoryRange, | |
117 observed->Stack.StartOfMemoryRange); | |
118 EXPECT_EQ(expected->Stack.Memory.DataSize, observed->Stack.Memory.DataSize); | |
119 if (stack) { | |
120 ASSERT_NE(0u, observed->Stack.Memory.DataSize); | |
121 ASSERT_NE(0u, observed->Stack.Memory.Rva); | |
122 ASSERT_GE(file_contents.size(), | |
123 observed->Stack.Memory.Rva + observed->Stack.Memory.DataSize); | |
124 *stack = &observed->Stack; | |
125 } else { | |
126 EXPECT_EQ(0u, observed->Stack.StartOfMemoryRange); | |
127 EXPECT_EQ(0u, observed->Stack.Memory.DataSize); | |
128 EXPECT_EQ(0u, observed->Stack.Memory.Rva); | |
129 } | |
130 | |
131 EXPECT_EQ(expected->ThreadContext.DataSize, observed->ThreadContext.DataSize); | |
132 ASSERT_NE(0u, observed->ThreadContext.DataSize); | |
133 ASSERT_NE(0u, observed->ThreadContext.Rva); | |
134 ASSERT_GE(file_contents.size(), | |
135 observed->ThreadContext.Rva + expected->ThreadContext.DataSize); | |
136 *context_base = &file_contents[observed->ThreadContext.Rva]; | |
137 } | |
138 | |
139 TEST(MinidumpThreadWriter, OneThread_x86_NoStack) { | |
140 MinidumpFileWriter minidump_file_writer; | |
141 MinidumpThreadListWriter thread_list_writer; | |
142 | |
143 const uint32_t kThreadID = 0x11111111; | |
144 const uint32_t kSuspendCount = 1; | |
145 const uint32_t kPriorityClass = 0x20; | |
146 const uint32_t kPriority = 10; | |
147 const uint64_t kTEB = 0x55555555; | |
148 const uint32_t kSeed = 123; | |
149 | |
150 MinidumpThreadWriter thread_writer; | |
151 thread_writer.SetThreadID(kThreadID); | |
152 thread_writer.SetSuspendCount(kSuspendCount); | |
153 thread_writer.SetPriorityClass(kPriorityClass); | |
154 thread_writer.SetPriority(kPriority); | |
155 thread_writer.SetTEB(kTEB); | |
156 | |
157 MinidumpContextX86Writer context_x86_writer; | |
158 InitializeMinidumpContextX86(context_x86_writer.context(), kSeed); | |
159 thread_writer.SetContext(&context_x86_writer); | |
160 | |
161 thread_list_writer.AddThread(&thread_writer); | |
162 minidump_file_writer.AddStream(&thread_list_writer); | |
163 | |
164 StringFileWriter file_writer; | |
165 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); | |
166 | |
167 ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + | |
168 sizeof(MINIDUMP_THREAD_LIST) + 1 * sizeof(MINIDUMP_THREAD) + | |
169 1 * sizeof(MinidumpContextX86), | |
170 file_writer.string().size()); | |
171 | |
172 const MINIDUMP_THREAD_LIST* thread_list; | |
173 GetThreadListStream(file_writer.string(), &thread_list, NULL); | |
174 if (Test::HasFatalFailure()) { | |
175 return; | |
176 } | |
177 | |
178 EXPECT_EQ(1u, thread_list->NumberOfThreads); | |
179 | |
180 MINIDUMP_THREAD expected = {}; | |
181 expected.ThreadId = kThreadID; | |
182 expected.SuspendCount = kSuspendCount; | |
183 expected.PriorityClass = kPriorityClass; | |
184 expected.Priority = kPriority; | |
185 expected.Teb = kTEB; | |
186 expected.ThreadContext.DataSize = sizeof(MinidumpContextX86); | |
187 | |
188 const MinidumpContextX86* observed_context; | |
189 ExpectThread(&expected, | |
190 &thread_list->Threads[0], | |
191 file_writer.string(), | |
192 NULL, | |
193 reinterpret_cast<const void**>(&observed_context)); | |
194 if (Test::HasFatalFailure()) { | |
195 return; | |
196 } | |
197 | |
198 ExpectMinidumpContextX86(kSeed, observed_context); | |
199 if (Test::HasFatalFailure()) { | |
200 return; | |
201 } | |
202 } | |
203 | |
204 TEST(MinidumpThreadWriter, OneThread_AMD64_Stack) { | |
205 MinidumpFileWriter minidump_file_writer; | |
206 MinidumpThreadListWriter thread_list_writer; | |
207 | |
208 const uint32_t kThreadID = 0x22222222; | |
209 const uint32_t kSuspendCount = 2; | |
210 const uint32_t kPriorityClass = 0x30; | |
211 const uint32_t kPriority = 20; | |
212 const uint64_t kTEB = 0x5555555555555555; | |
213 const uint64_t kMemoryBase = 0x765432100000; | |
214 const size_t kMemorySize = 32; | |
215 const uint8_t kMemoryValue = 99; | |
216 const uint32_t kSeed = 456; | |
217 | |
218 MinidumpThreadWriter thread_writer; | |
219 thread_writer.SetThreadID(kThreadID); | |
220 thread_writer.SetSuspendCount(kSuspendCount); | |
221 thread_writer.SetPriorityClass(kPriorityClass); | |
222 thread_writer.SetPriority(kPriority); | |
223 thread_writer.SetTEB(kTEB); | |
224 | |
225 TestMinidumpMemoryWriter memory_writer( | |
226 kMemoryBase, kMemorySize, kMemoryValue); | |
227 thread_writer.SetStack(&memory_writer); | |
228 | |
229 MinidumpContextAMD64Writer context_amd64_writer; | |
230 InitializeMinidumpContextAMD64(context_amd64_writer.context(), kSeed); | |
231 thread_writer.SetContext(&context_amd64_writer); | |
232 | |
233 thread_list_writer.AddThread(&thread_writer); | |
234 minidump_file_writer.AddStream(&thread_list_writer); | |
235 | |
236 StringFileWriter file_writer; | |
237 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); | |
238 | |
239 ASSERT_EQ(sizeof(MINIDUMP_HEADER) + sizeof(MINIDUMP_DIRECTORY) + | |
240 sizeof(MINIDUMP_THREAD_LIST) + 1 * sizeof(MINIDUMP_THREAD) + | |
241 1 * sizeof(MinidumpContextAMD64) + kMemorySize, | |
242 file_writer.string().size()); | |
243 | |
244 const MINIDUMP_THREAD_LIST* thread_list; | |
245 GetThreadListStream(file_writer.string(), &thread_list, NULL); | |
246 if (Test::HasFatalFailure()) { | |
247 return; | |
248 } | |
249 | |
250 EXPECT_EQ(1u, thread_list->NumberOfThreads); | |
251 | |
252 MINIDUMP_THREAD expected = {}; | |
253 expected.ThreadId = kThreadID; | |
254 expected.SuspendCount = kSuspendCount; | |
255 expected.PriorityClass = kPriorityClass; | |
256 expected.Priority = kPriority; | |
257 expected.Teb = kTEB; | |
258 expected.Stack.StartOfMemoryRange = kMemoryBase; | |
259 expected.Stack.Memory.DataSize = kMemorySize; | |
260 expected.ThreadContext.DataSize = sizeof(MinidumpContextAMD64); | |
261 | |
262 const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack; | |
263 const MinidumpContextAMD64* observed_context; | |
264 ExpectThread(&expected, | |
265 &thread_list->Threads[0], | |
266 file_writer.string(), | |
267 &observed_stack, | |
268 reinterpret_cast<const void**>(&observed_context)); | |
269 if (Test::HasFatalFailure()) { | |
270 return; | |
271 } | |
272 | |
273 ExpectMinidumpMemoryDescriptorAndContents(&expected.Stack, | |
274 observed_stack, | |
275 file_writer.string(), | |
276 kMemoryValue, | |
277 true); | |
278 if (Test::HasFatalFailure()) { | |
279 return; | |
280 } | |
281 | |
282 ExpectMinidumpContextAMD64(kSeed, observed_context); | |
283 if (Test::HasFatalFailure()) { | |
284 return; | |
285 } | |
286 } | |
287 | |
288 // The two MINIDUMP_MEMORY_DESCRIPTOR arguments are compared for equality using | |
289 // gtest assertions. | |
290 void ExpectMemoryDescriptors(const MINIDUMP_MEMORY_DESCRIPTOR* expected, | |
Robert Sesek
2014/10/08 21:49:31
This may be useful in a more general location.
| |
291 const MINIDUMP_MEMORY_DESCRIPTOR* observed) { | |
292 EXPECT_EQ(expected->StartOfMemoryRange, observed->StartOfMemoryRange); | |
293 EXPECT_EQ(expected->Memory.DataSize, observed->Memory.DataSize); | |
294 EXPECT_EQ(expected->Memory.Rva, observed->Memory.Rva); | |
295 } | |
296 | |
297 TEST(MinidumpThreadWriter, ThreeThreads_x86_MemoryList) { | |
298 MinidumpFileWriter minidump_file_writer; | |
299 MinidumpThreadListWriter thread_list_writer; | |
300 MinidumpMemoryListWriter memory_list_writer; | |
301 thread_list_writer.SetMemoryListWriter(&memory_list_writer); | |
302 | |
303 const uint32_t kThreadID1 = 1111111; | |
304 const uint32_t kSuspendCount1 = 111111; | |
305 const uint32_t kPriorityClass1 = 11111; | |
306 const uint32_t kPriority1 = 1111; | |
307 const uint64_t kTEB1 = 111; | |
308 const uint64_t kMemoryBase1 = 0x1110; | |
309 const size_t kMemorySize1 = 16; | |
310 const uint8_t kMemoryValue1 = 11; | |
311 const uint32_t kSeed1 = 1; | |
312 | |
313 MinidumpThreadWriter thread_writer_1; | |
314 thread_writer_1.SetThreadID(kThreadID1); | |
315 thread_writer_1.SetSuspendCount(kSuspendCount1); | |
316 thread_writer_1.SetPriorityClass(kPriorityClass1); | |
317 thread_writer_1.SetPriority(kPriority1); | |
318 thread_writer_1.SetTEB(kTEB1); | |
319 | |
320 TestMinidumpMemoryWriter memory_writer_1( | |
321 kMemoryBase1, kMemorySize1, kMemoryValue1); | |
322 thread_writer_1.SetStack(&memory_writer_1); | |
323 | |
324 MinidumpContextX86Writer context_x86_writer_1; | |
325 InitializeMinidumpContextX86(context_x86_writer_1.context(), kSeed1); | |
326 thread_writer_1.SetContext(&context_x86_writer_1); | |
327 | |
328 thread_list_writer.AddThread(&thread_writer_1); | |
329 | |
330 const uint32_t kThreadID2 = 2222222; | |
331 const uint32_t kSuspendCount2 = 222222; | |
332 const uint32_t kPriorityClass2 = 22222; | |
333 const uint32_t kPriority2 = 2222; | |
334 const uint64_t kTEB2 = 222; | |
335 const uint64_t kMemoryBase2 = 0x2220; | |
336 const size_t kMemorySize2 = 32; | |
337 const uint8_t kMemoryValue2 = 22; | |
338 const uint32_t kSeed2 = 2; | |
339 | |
340 MinidumpThreadWriter thread_writer_2; | |
341 thread_writer_2.SetThreadID(kThreadID2); | |
342 thread_writer_2.SetSuspendCount(kSuspendCount2); | |
343 thread_writer_2.SetPriorityClass(kPriorityClass2); | |
344 thread_writer_2.SetPriority(kPriority2); | |
345 thread_writer_2.SetTEB(kTEB2); | |
346 | |
347 TestMinidumpMemoryWriter memory_writer_2( | |
348 kMemoryBase2, kMemorySize2, kMemoryValue2); | |
349 thread_writer_2.SetStack(&memory_writer_2); | |
350 | |
351 MinidumpContextX86Writer context_x86_writer_2; | |
352 InitializeMinidumpContextX86(context_x86_writer_2.context(), kSeed2); | |
353 thread_writer_2.SetContext(&context_x86_writer_2); | |
354 | |
355 thread_list_writer.AddThread(&thread_writer_2); | |
356 | |
357 const uint32_t kThreadID3 = 3333333; | |
358 const uint32_t kSuspendCount3 = 333333; | |
359 const uint32_t kPriorityClass3 = 33333; | |
360 const uint32_t kPriority3 = 3333; | |
361 const uint64_t kTEB3 = 333; | |
362 const uint64_t kMemoryBase3 = 0x3330; | |
363 const size_t kMemorySize3 = 48; | |
364 const uint8_t kMemoryValue3 = 33; | |
365 const uint32_t kSeed3 = 3; | |
366 | |
367 MinidumpThreadWriter thread_writer_3; | |
368 thread_writer_3.SetThreadID(kThreadID3); | |
369 thread_writer_3.SetSuspendCount(kSuspendCount3); | |
370 thread_writer_3.SetPriorityClass(kPriorityClass3); | |
371 thread_writer_3.SetPriority(kPriority3); | |
372 thread_writer_3.SetTEB(kTEB3); | |
373 | |
374 TestMinidumpMemoryWriter memory_writer_3( | |
375 kMemoryBase3, kMemorySize3, kMemoryValue3); | |
376 thread_writer_3.SetStack(&memory_writer_3); | |
377 | |
378 MinidumpContextX86Writer context_x86_writer_3; | |
379 InitializeMinidumpContextX86(context_x86_writer_3.context(), kSeed3); | |
380 thread_writer_3.SetContext(&context_x86_writer_3); | |
381 | |
382 thread_list_writer.AddThread(&thread_writer_3); | |
383 | |
384 minidump_file_writer.AddStream(&thread_list_writer); | |
385 minidump_file_writer.AddStream(&memory_list_writer); | |
386 | |
387 StringFileWriter file_writer; | |
388 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer)); | |
389 | |
390 ASSERT_EQ(sizeof(MINIDUMP_HEADER) + 2 * sizeof(MINIDUMP_DIRECTORY) + | |
391 sizeof(MINIDUMP_THREAD_LIST) + 3 * sizeof(MINIDUMP_THREAD) + | |
392 sizeof(MINIDUMP_MEMORY_LIST) + | |
393 3 * sizeof(MINIDUMP_MEMORY_DESCRIPTOR) + | |
394 3 * sizeof(MinidumpContextX86) + kMemorySize1 + kMemorySize2 + | |
395 kMemorySize3 + 12, // 12 for alignment | |
396 file_writer.string().size()); | |
397 | |
398 const MINIDUMP_THREAD_LIST* thread_list; | |
399 const MINIDUMP_MEMORY_LIST* memory_list; | |
400 GetThreadListStream(file_writer.string(), &thread_list, &memory_list); | |
401 if (Test::HasFatalFailure()) { | |
402 return; | |
403 } | |
404 | |
405 EXPECT_EQ(3u, thread_list->NumberOfThreads); | |
406 EXPECT_EQ(3u, memory_list->NumberOfMemoryRanges); | |
407 | |
408 { | |
409 SCOPED_TRACE("thread 0"); | |
Robert Sesek
2014/10/08 21:49:31
This is "thread 0" in the trace but "1" for all th
| |
410 | |
411 MINIDUMP_THREAD expected = {}; | |
412 expected.ThreadId = kThreadID1; | |
413 expected.SuspendCount = kSuspendCount1; | |
414 expected.PriorityClass = kPriorityClass1; | |
415 expected.Priority = kPriority1; | |
416 expected.Teb = kTEB1; | |
417 expected.Stack.StartOfMemoryRange = kMemoryBase1; | |
418 expected.Stack.Memory.DataSize = kMemorySize1; | |
419 expected.ThreadContext.DataSize = sizeof(MinidumpContextX86); | |
420 | |
421 const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack; | |
422 const MinidumpContextX86* observed_context; | |
423 ExpectThread(&expected, | |
424 &thread_list->Threads[0], | |
425 file_writer.string(), | |
426 &observed_stack, | |
427 reinterpret_cast<const void**>(&observed_context)); | |
428 if (Test::HasFatalFailure()) { | |
429 return; | |
430 } | |
431 | |
432 ExpectMinidumpMemoryDescriptorAndContents(&expected.Stack, | |
433 observed_stack, | |
434 file_writer.string(), | |
435 kMemoryValue1, | |
436 false); | |
437 if (Test::HasFatalFailure()) { | |
Robert Sesek
2014/10/08 21:49:31
This could almost become a macro.
| |
438 return; | |
439 } | |
440 | |
441 ExpectMinidumpContextX86(kSeed1, observed_context); | |
442 if (Test::HasFatalFailure()) { | |
443 return; | |
444 } | |
445 | |
446 ExpectMemoryDescriptors(observed_stack, &memory_list->MemoryRanges[0]); | |
447 if (Test::HasFatalFailure()) { | |
448 return; | |
449 } | |
450 } | |
451 | |
452 { | |
453 SCOPED_TRACE("thread 1"); | |
454 | |
455 MINIDUMP_THREAD expected = {}; | |
456 expected.ThreadId = kThreadID2; | |
457 expected.SuspendCount = kSuspendCount2; | |
458 expected.PriorityClass = kPriorityClass2; | |
459 expected.Priority = kPriority2; | |
460 expected.Teb = kTEB2; | |
461 expected.Stack.StartOfMemoryRange = kMemoryBase2; | |
462 expected.Stack.Memory.DataSize = kMemorySize2; | |
463 expected.ThreadContext.DataSize = sizeof(MinidumpContextX86); | |
464 | |
465 const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack; | |
466 const MinidumpContextX86* observed_context; | |
467 ExpectThread(&expected, | |
468 &thread_list->Threads[1], | |
469 file_writer.string(), | |
470 &observed_stack, | |
471 reinterpret_cast<const void**>(&observed_context)); | |
472 if (Test::HasFatalFailure()) { | |
473 return; | |
474 } | |
475 | |
476 ExpectMinidumpMemoryDescriptorAndContents(&expected.Stack, | |
477 observed_stack, | |
478 file_writer.string(), | |
479 kMemoryValue2, | |
480 false); | |
481 if (Test::HasFatalFailure()) { | |
482 return; | |
483 } | |
484 | |
485 ExpectMinidumpContextX86(kSeed2, observed_context); | |
486 if (Test::HasFatalFailure()) { | |
487 return; | |
488 } | |
489 | |
490 ExpectMemoryDescriptors(observed_stack, &memory_list->MemoryRanges[1]); | |
491 if (Test::HasFatalFailure()) { | |
492 return; | |
493 } | |
494 } | |
495 | |
496 { | |
497 SCOPED_TRACE("thread 2"); | |
498 | |
499 MINIDUMP_THREAD expected = {}; | |
500 expected.ThreadId = kThreadID3; | |
501 expected.SuspendCount = kSuspendCount3; | |
502 expected.PriorityClass = kPriorityClass3; | |
503 expected.Priority = kPriority3; | |
504 expected.Teb = kTEB3; | |
505 expected.Stack.StartOfMemoryRange = kMemoryBase3; | |
506 expected.Stack.Memory.DataSize = kMemorySize3; | |
507 expected.ThreadContext.DataSize = sizeof(MinidumpContextX86); | |
508 | |
509 const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack; | |
510 const MinidumpContextX86* observed_context; | |
511 ExpectThread(&expected, | |
512 &thread_list->Threads[2], | |
513 file_writer.string(), | |
514 &observed_stack, | |
515 reinterpret_cast<const void**>(&observed_context)); | |
516 if (Test::HasFatalFailure()) { | |
517 return; | |
518 } | |
519 | |
520 ExpectMinidumpMemoryDescriptorAndContents(&expected.Stack, | |
521 observed_stack, | |
522 file_writer.string(), | |
523 kMemoryValue3, | |
524 true); | |
525 if (Test::HasFatalFailure()) { | |
526 return; | |
527 } | |
528 | |
529 ExpectMinidumpContextX86(kSeed3, observed_context); | |
530 if (Test::HasFatalFailure()) { | |
531 return; | |
532 } | |
533 | |
534 ExpectMemoryDescriptors(observed_stack, &memory_list->MemoryRanges[2]); | |
535 if (Test::HasFatalFailure()) { | |
536 return; | |
537 } | |
538 } | |
539 } | |
540 | |
541 TEST(MinidumpThreadWriterDeathTest, NoContext) { | |
542 MinidumpFileWriter minidump_file_writer; | |
543 MinidumpThreadListWriter thread_list_writer; | |
544 | |
545 MinidumpThreadWriter thread_writer; | |
546 | |
547 thread_list_writer.AddThread(&thread_writer); | |
548 minidump_file_writer.AddStream(&thread_list_writer); | |
549 | |
550 StringFileWriter file_writer; | |
551 ASSERT_DEATH(minidump_file_writer.WriteEverything(&file_writer), "context_"); | |
552 } | |
553 | |
554 } // namespace | |
555 } // namespace test | |
556 } // namespace crashpad | |
OLD | NEW |