Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: minidump/minidump_thread_writer_test.cc

Issue 693933002: Add MinidumpThreadListWriter::InitializeFromSnapshot() (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@minidump_init_from_snapshot_context_new
Patch Set: Address review feedback Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « minidump/minidump_thread_writer.cc ('k') | snapshot/cpu_context_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Crashpad Authors. All rights reserved. 1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with 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 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "minidump/minidump_thread_writer.h" 15 #include "minidump/minidump_thread_writer.h"
16 16
17 #include <dbghelp.h> 17 #include <dbghelp.h>
18 #include <sys/types.h> 18 #include <sys/types.h>
19 19
20 #include "base/strings/stringprintf.h"
20 #include "gtest/gtest.h" 21 #include "gtest/gtest.h"
21 #include "minidump/minidump_context_writer.h" 22 #include "minidump/minidump_context_writer.h"
22 #include "minidump/minidump_memory_writer.h" 23 #include "minidump/minidump_memory_writer.h"
23 #include "minidump/minidump_file_writer.h" 24 #include "minidump/minidump_file_writer.h"
25 #include "minidump/minidump_thread_id_map.h"
24 #include "minidump/test/minidump_context_test_util.h" 26 #include "minidump/test/minidump_context_test_util.h"
25 #include "minidump/test/minidump_memory_writer_test_util.h" 27 #include "minidump/test/minidump_memory_writer_test_util.h"
26 #include "minidump/test/minidump_file_writer_test_util.h" 28 #include "minidump/test/minidump_file_writer_test_util.h"
27 #include "minidump/test/minidump_writable_test_util.h" 29 #include "minidump/test/minidump_writable_test_util.h"
30 #include "snapshot/test/test_cpu_context.h"
31 #include "snapshot/test/test_memory_snapshot.h"
32 #include "snapshot/test/test_thread_snapshot.h"
28 #include "util/file/string_file_writer.h" 33 #include "util/file/string_file_writer.h"
29 34
30 namespace crashpad { 35 namespace crashpad {
31 namespace test { 36 namespace test {
32 namespace { 37 namespace {
33 38
34 // This returns the MINIDUMP_THREAD_LIST stream in |thread_list|. If 39 // This returns the MINIDUMP_THREAD_LIST stream in |thread_list|. If
35 // |memory_list| is not nullptr, a MINIDUMP_MEMORY_LIST stream is also expected 40 // |memory_list| is not nullptr, a MINIDUMP_MEMORY_LIST stream is also expected
36 // in |file_contents|, and that stream will be returned in |memory_list|. 41 // in |file_contents|, and that stream will be returned in |memory_list|.
37 void GetThreadListStream(const std::string& file_contents, 42 void GetThreadListStream(const std::string& file_contents,
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 file_writer.string(), 473 file_writer.string(),
469 kMemoryValue2, 474 kMemoryValue2,
470 true)); 475 true));
471 ASSERT_NO_FATAL_FAILURE( 476 ASSERT_NO_FATAL_FAILURE(
472 ExpectMinidumpContextX86(kSeed2, observed_context, false)); 477 ExpectMinidumpContextX86(kSeed2, observed_context, false));
473 ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptor( 478 ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptor(
474 observed_stack, &memory_list->MemoryRanges[2])); 479 observed_stack, &memory_list->MemoryRanges[2]));
475 } 480 }
476 } 481 }
477 482
483 struct InitializeFromSnapshotX86Traits {
484 typedef MinidumpContextX86 MinidumpContextType;
485 static void InitializeCPUContext(CPUContext* context, uint32_t seed) {
486 return InitializeCPUContextX86(context, seed);
487 }
488 static void ExpectMinidumpContext(
489 uint32_t expect_seed, const MinidumpContextX86* observed, bool snapshot) {
490 return ExpectMinidumpContextX86(expect_seed, observed, snapshot);
491 }
492 };
493
494 struct InitializeFromSnapshotAMD64Traits {
495 typedef MinidumpContextAMD64 MinidumpContextType;
496 static void InitializeCPUContext(CPUContext* context, uint32_t seed) {
497 return InitializeCPUContextX86_64(context, seed);
498 }
499 static void ExpectMinidumpContext(uint32_t expect_seed,
500 const MinidumpContextAMD64* observed,
501 bool snapshot) {
502 return ExpectMinidumpContextAMD64(expect_seed, observed, snapshot);
503 }
504 };
505
506 struct InitializeFromSnapshotNoContextTraits {
507 typedef MinidumpContextX86 MinidumpContextType;
508 static void InitializeCPUContext(CPUContext* context, uint32_t seed) {
509 context->architecture = kCPUArchitectureUnknown;
510 }
511 static void ExpectMinidumpContext(uint32_t expect_seed,
512 const MinidumpContextX86* observed,
513 bool snapshot) {
514 FAIL();
515 }
516 };
517
518 template <typename Traits>
519 void RunInitializeFromSnapshotTest(bool thread_id_collision) {
520 typedef typename Traits::MinidumpContextType MinidumpContextType;
521 MINIDUMP_THREAD expect_threads[3] = {};
522 uint64_t thread_ids[arraysize(expect_threads)] = {};
523 uint8_t memory_values[arraysize(expect_threads)] = {};
524 uint32_t context_seeds[arraysize(expect_threads)] = {};
525
526 expect_threads[0].ThreadId = 1;
527 expect_threads[0].SuspendCount = 2;
528 expect_threads[0].Priority = 3;
529 expect_threads[0].Teb = 0x0123456789abcdef;
530 expect_threads[0].Stack.StartOfMemoryRange = 0x1000;
531 expect_threads[0].Stack.Memory.DataSize = 0x100;
532 expect_threads[0].ThreadContext.DataSize = sizeof(MinidumpContextType);
533 memory_values[0] = 'A';
534 context_seeds[0] = 0x80000000;
535
536 // The thread at index 1 has no stack.
537 expect_threads[1].ThreadId = 11;
538 expect_threads[1].SuspendCount = 12;
539 expect_threads[1].Priority = 13;
540 expect_threads[1].Teb = 0xfedcba9876543210;
541 expect_threads[1].ThreadContext.DataSize = sizeof(MinidumpContextType);
542 context_seeds[1] = 0x40000001;
543
544 expect_threads[2].ThreadId = 21;
545 expect_threads[2].SuspendCount = 22;
546 expect_threads[2].Priority = 23;
547 expect_threads[2].Teb = 0x1111111111111111;
548 expect_threads[2].Stack.StartOfMemoryRange = 0x3000;
549 expect_threads[2].Stack.Memory.DataSize = 0x300;
550 expect_threads[2].ThreadContext.DataSize = sizeof(MinidumpContextType);
551 memory_values[2] = 'd';
552 context_seeds[2] = 0x20000002;
553
554 if (thread_id_collision) {
555 thread_ids[0] = 0x0123456700000001;
556 thread_ids[1] = 0x89abcdef00000001;
557 thread_ids[2] = 4;
558 expect_threads[0].ThreadId = 0;
559 expect_threads[1].ThreadId = 1;
560 expect_threads[2].ThreadId = 2;
561 } else {
562 thread_ids[0] = 1;
563 thread_ids[1] = 11;
564 thread_ids[2] = 22;
565 expect_threads[0].ThreadId = thread_ids[0];
566 expect_threads[1].ThreadId = thread_ids[1];
567 expect_threads[2].ThreadId = thread_ids[2];
568 }
569
570 PointerVector<TestThreadSnapshot> thread_snapshots_owner;
571 std::vector<const ThreadSnapshot*> thread_snapshots;
572 for (size_t index = 0; index < arraysize(expect_threads); ++index) {
573 TestThreadSnapshot* thread_snapshot = new TestThreadSnapshot();
574 thread_snapshots_owner.push_back(thread_snapshot);
575
576 thread_snapshot->SetThreadID(thread_ids[index]);
577 thread_snapshot->SetSuspendCount(expect_threads[index].SuspendCount);
578 thread_snapshot->SetPriority(expect_threads[index].Priority);
579 thread_snapshot->SetThreadSpecificDataAddress(expect_threads[index].Teb);
580
581 if (expect_threads[index].Stack.Memory.DataSize) {
582 auto memory_snapshot = make_scoped_ptr(new TestMemorySnapshot());
583 memory_snapshot->SetAddress(
584 expect_threads[index].Stack.StartOfMemoryRange);
585 memory_snapshot->SetSize(expect_threads[index].Stack.Memory.DataSize);
586 memory_snapshot->SetValue(memory_values[index]);
587 thread_snapshot->SetStack(memory_snapshot.Pass());
588 }
589
590 Traits::InitializeCPUContext(thread_snapshot->MutableContext(),
591 context_seeds[index]);
592
593 thread_snapshots.push_back(thread_snapshot);
594 }
595
596 auto thread_list_writer = make_scoped_ptr(new MinidumpThreadListWriter());
597 auto memory_list_writer = make_scoped_ptr(new MinidumpMemoryListWriter());
598 thread_list_writer->SetMemoryListWriter(memory_list_writer.get());
599 MinidumpThreadIDMap thread_id_map;
600 thread_list_writer->InitializeFromSnapshot(thread_snapshots, &thread_id_map);
601
602 MinidumpFileWriter minidump_file_writer;
603 minidump_file_writer.AddStream(thread_list_writer.Pass());
604 minidump_file_writer.AddStream(memory_list_writer.Pass());
605
606 StringFileWriter file_writer;
607 ASSERT_TRUE(minidump_file_writer.WriteEverything(&file_writer));
608
609 const MINIDUMP_THREAD_LIST* thread_list;
610 const MINIDUMP_MEMORY_LIST* memory_list;
611 ASSERT_NO_FATAL_FAILURE(
612 GetThreadListStream(file_writer.string(), &thread_list, &memory_list));
613
614 ASSERT_EQ(3u, thread_list->NumberOfThreads);
615 ASSERT_EQ(2u, memory_list->NumberOfMemoryRanges);
616
617 size_t memory_index = 0;
618 for (size_t index = 0; index < thread_list->NumberOfThreads; ++index) {
619 SCOPED_TRACE(base::StringPrintf("index %zu", index));
620
621 const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack;
622 const MINIDUMP_MEMORY_DESCRIPTOR** observed_stack_p =
623 expect_threads[index].Stack.Memory.DataSize ? &observed_stack : nullptr;
624 const MinidumpContextType* observed_context;
625 ASSERT_NO_FATAL_FAILURE(
626 ExpectThread(&expect_threads[index],
627 &thread_list->Threads[index],
628 file_writer.string(),
629 observed_stack_p,
630 reinterpret_cast<const void**>(&observed_context)));
631
632 ASSERT_NO_FATAL_FAILURE(Traits::ExpectMinidumpContext(
633 context_seeds[index], observed_context, true));
634
635 if (observed_stack_p) {
636 ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptorAndContents(
637 &expect_threads[index].Stack,
638 observed_stack,
639 file_writer.string(),
640 memory_values[index],
641 index == thread_list->NumberOfThreads - 1));
642
643 ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptor(
644 observed_stack, &memory_list->MemoryRanges[memory_index]));
645
646 ++memory_index;
647 }
648 }
649 }
650
651 TEST(MinidumpThreadWriter, InitializeFromSnapshot_x86) {
652 RunInitializeFromSnapshotTest<InitializeFromSnapshotX86Traits>(false);
653 }
654
655 TEST(MinidumpThreadWriter, InitializeFromSnapshot_AMD64) {
656 RunInitializeFromSnapshotTest<InitializeFromSnapshotAMD64Traits>(false);
657 }
658
659 TEST(MinidumpThreadWriter, InitializeFromSnapshot_ThreadIDCollision) {
660 RunInitializeFromSnapshotTest<InitializeFromSnapshotX86Traits>(true);
661 }
662
478 TEST(MinidumpThreadWriterDeathTest, NoContext) { 663 TEST(MinidumpThreadWriterDeathTest, NoContext) {
479 MinidumpFileWriter minidump_file_writer; 664 MinidumpFileWriter minidump_file_writer;
480 auto thread_list_writer = make_scoped_ptr(new MinidumpThreadListWriter()); 665 auto thread_list_writer = make_scoped_ptr(new MinidumpThreadListWriter());
481 666
482 auto thread_writer = make_scoped_ptr(new MinidumpThreadWriter()); 667 auto thread_writer = make_scoped_ptr(new MinidumpThreadWriter());
483 668
484 thread_list_writer->AddThread(thread_writer.Pass()); 669 thread_list_writer->AddThread(thread_writer.Pass());
485 minidump_file_writer.AddStream(thread_list_writer.Pass()); 670 minidump_file_writer.AddStream(thread_list_writer.Pass());
486 671
487 StringFileWriter file_writer; 672 StringFileWriter file_writer;
488 ASSERT_DEATH(minidump_file_writer.WriteEverything(&file_writer), "context_"); 673 ASSERT_DEATH(minidump_file_writer.WriteEverything(&file_writer), "context_");
489 } 674 }
490 675
676 TEST(MinidumpThreadWriterDeathTest, InitializeFromSnapshot_NoContext) {
677 ASSERT_DEATH(
678 RunInitializeFromSnapshotTest<InitializeFromSnapshotNoContextTraits>(
679 false), "context_");
680 }
681
491 } // namespace 682 } // namespace
492 } // namespace test 683 } // namespace test
493 } // namespace crashpad 684 } // namespace crashpad
OLDNEW
« no previous file with comments | « minidump/minidump_thread_writer.cc ('k') | snapshot/cpu_context_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698