| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/browser_watcher/postmortem_report_collector.h" | 5 #include "components/browser_watcher/postmortem_report_collector.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <set> | 10 #include <set> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <utility> | 12 #include <utility> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/debug/activity_analyzer.h" |
| 15 #include "base/debug/activity_tracker.h" | 16 #include "base/debug/activity_tracker.h" |
| 16 #include "base/files/file.h" | 17 #include "base/files/file.h" |
| 17 #include "base/files/file_path.h" | 18 #include "base/files/file_path.h" |
| 18 #include "base/files/file_util.h" | 19 #include "base/files/file_util.h" |
| 19 #include "base/files/memory_mapped_file.h" | 20 #include "base/files/memory_mapped_file.h" |
| 20 #include "base/files/scoped_file.h" | 21 #include "base/files/scoped_file.h" |
| 21 #include "base/files/scoped_temp_dir.h" | 22 #include "base/files/scoped_temp_dir.h" |
| 22 #include "base/memory/ptr_util.h" | 23 #include "base/memory/ptr_util.h" |
| 23 #include "base/metrics/persistent_memory_allocator.h" | 24 #include "base/metrics/persistent_memory_allocator.h" |
| 24 #include "base/process/process_handle.h" | 25 #include "base/process/process_handle.h" |
| 26 #include "base/stl_util.h" |
| 25 #include "base/threading/platform_thread.h" | 27 #include "base/threading/platform_thread.h" |
| 26 #include "testing/gmock/include/gmock/gmock.h" | 28 #include "testing/gmock/include/gmock/gmock.h" |
| 27 #include "testing/gtest/include/gtest/gtest.h" | 29 #include "testing/gtest/include/gtest/gtest.h" |
| 28 #include "third_party/crashpad/crashpad/client/crash_report_database.h" | 30 #include "third_party/crashpad/crashpad/client/crash_report_database.h" |
| 29 | 31 |
| 30 namespace browser_watcher { | 32 namespace browser_watcher { |
| 31 | 33 |
| 32 using base::debug::ActivityData; | 34 using base::debug::ActivityData; |
| 35 using base::debug::ActivityTrackerMemoryAllocator; |
| 36 using base::debug::ActivityUserData; |
| 33 using base::debug::GlobalActivityTracker; | 37 using base::debug::GlobalActivityTracker; |
| 34 using base::debug::ThreadActivityTracker; | 38 using base::debug::ThreadActivityTracker; |
| 35 using base::File; | 39 using base::File; |
| 36 using base::FilePersistentMemoryAllocator; | 40 using base::FilePersistentMemoryAllocator; |
| 37 using base::MemoryMappedFile; | 41 using base::MemoryMappedFile; |
| 38 using base::PersistentMemoryAllocator; | 42 using base::PersistentMemoryAllocator; |
| 39 using base::WrapUnique; | 43 using base::WrapUnique; |
| 40 using crashpad::CrashReportDatabase; | 44 using crashpad::CrashReportDatabase; |
| 41 using crashpad::Settings; | 45 using crashpad::Settings; |
| 42 using crashpad::UUID; | 46 using crashpad::UUID; |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 }; | 420 }; |
| 417 | 421 |
| 418 TEST_F(PostmortemReportCollectorCollectionTest, CollectSuccess) { | 422 TEST_F(PostmortemReportCollectorCollectionTest, CollectSuccess) { |
| 419 // Create some activity data. | 423 // Create some activity data. |
| 420 tracker_->PushActivity(reinterpret_cast<void*>(kTaskOrigin), | 424 tracker_->PushActivity(reinterpret_cast<void*>(kTaskOrigin), |
| 421 base::debug::Activity::ACT_TASK_RUN, | 425 base::debug::Activity::ACT_TASK_RUN, |
| 422 ActivityData::ForTask(kTaskSequenceNum)); | 426 ActivityData::ForTask(kTaskSequenceNum)); |
| 423 tracker_->PushActivity( | 427 tracker_->PushActivity( |
| 424 nullptr, base::debug::Activity::ACT_LOCK_ACQUIRE, | 428 nullptr, base::debug::Activity::ACT_LOCK_ACQUIRE, |
| 425 ActivityData::ForLock(reinterpret_cast<void*>(kLockAddress))); | 429 ActivityData::ForLock(reinterpret_cast<void*>(kLockAddress))); |
| 426 tracker_->PushActivity( | 430 ThreadActivityTracker::ActivityId activity_id = tracker_->PushActivity( |
| 427 nullptr, base::debug::Activity::ACT_EVENT_WAIT, | 431 nullptr, base::debug::Activity::ACT_EVENT_WAIT, |
| 428 ActivityData::ForEvent(reinterpret_cast<void*>(kEventAddress))); | 432 ActivityData::ForEvent(reinterpret_cast<void*>(kEventAddress))); |
| 429 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_THREAD_JOIN, | 433 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_THREAD_JOIN, |
| 430 ActivityData::ForThread(kThreadId)); | 434 ActivityData::ForThread(kThreadId)); |
| 431 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_PROCESS_WAIT, | 435 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_PROCESS_WAIT, |
| 432 ActivityData::ForProcess(kProcessId)); | 436 ActivityData::ForProcess(kProcessId)); |
| 433 // Note: this exceeds the activity stack's capacity. | 437 // Note: this exceeds the activity stack's capacity. |
| 434 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_THREAD_JOIN, | 438 tracker_->PushActivity(nullptr, base::debug::Activity::ACT_THREAD_JOIN, |
| 435 ActivityData::ForThread(kAnotherThreadId)); | 439 ActivityData::ForThread(kAnotherThreadId)); |
| 436 | 440 |
| 441 // Add some user data. |
| 442 ActivityTrackerMemoryAllocator user_data_allocator( |
| 443 allocator_.get(), GlobalActivityTracker::kTypeIdUserDataRecord, |
| 444 GlobalActivityTracker::kTypeIdUserDataRecordFree, 1024U, 10U, false); |
| 445 std::unique_ptr<ActivityUserData> user_data = |
| 446 tracker_->GetUserData(activity_id, &user_data_allocator); |
| 447 user_data->SetInt("some_int", 42); |
| 448 |
| 437 // Validate collection returns the expected report. | 449 // Validate collection returns the expected report. |
| 438 PostmortemReportCollector collector(kProductName, kVersionNumber, | 450 PostmortemReportCollector collector(kProductName, kVersionNumber, |
| 439 kChannelName); | 451 kChannelName); |
| 440 std::unique_ptr<StabilityReport> report; | 452 std::unique_ptr<StabilityReport> report; |
| 441 ASSERT_EQ(PostmortemReportCollector::SUCCESS, | 453 ASSERT_EQ(PostmortemReportCollector::SUCCESS, |
| 442 collector.Collect(debug_file_path(), &report)); | 454 collector.Collect(debug_file_path(), &report)); |
| 443 ASSERT_NE(nullptr, report); | 455 ASSERT_NE(nullptr, report); |
| 444 | 456 |
| 445 // Validate the report. | 457 // Validate the report. |
| 446 ASSERT_EQ(1, report->process_states_size()); | 458 ASSERT_EQ(1, report->process_states_size()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 457 thread_state.thread_id()); | 469 thread_state.thread_id()); |
| 458 #endif | 470 #endif |
| 459 | 471 |
| 460 EXPECT_EQ(6, thread_state.activity_count()); | 472 EXPECT_EQ(6, thread_state.activity_count()); |
| 461 ASSERT_EQ(5, thread_state.activities_size()); | 473 ASSERT_EQ(5, thread_state.activities_size()); |
| 462 { | 474 { |
| 463 const Activity& activity = thread_state.activities(0); | 475 const Activity& activity = thread_state.activities(0); |
| 464 EXPECT_EQ(Activity::ACT_TASK_RUN, activity.type()); | 476 EXPECT_EQ(Activity::ACT_TASK_RUN, activity.type()); |
| 465 EXPECT_EQ(kTaskOrigin, activity.origin_address()); | 477 EXPECT_EQ(kTaskOrigin, activity.origin_address()); |
| 466 EXPECT_EQ(kTaskSequenceNum, activity.task_sequence_id()); | 478 EXPECT_EQ(kTaskSequenceNum, activity.task_sequence_id()); |
| 479 EXPECT_EQ(0U, activity.user_data().size()); |
| 467 } | 480 } |
| 468 { | 481 { |
| 469 const Activity& activity = thread_state.activities(1); | 482 const Activity& activity = thread_state.activities(1); |
| 470 EXPECT_EQ(Activity::ACT_LOCK_ACQUIRE, activity.type()); | 483 EXPECT_EQ(Activity::ACT_LOCK_ACQUIRE, activity.type()); |
| 471 EXPECT_EQ(kLockAddress, activity.lock_address()); | 484 EXPECT_EQ(kLockAddress, activity.lock_address()); |
| 485 EXPECT_EQ(0U, activity.user_data().size()); |
| 472 } | 486 } |
| 473 { | 487 { |
| 474 const Activity& activity = thread_state.activities(2); | 488 const Activity& activity = thread_state.activities(2); |
| 475 EXPECT_EQ(Activity::ACT_EVENT_WAIT, activity.type()); | 489 EXPECT_EQ(Activity::ACT_EVENT_WAIT, activity.type()); |
| 476 EXPECT_EQ(kEventAddress, activity.event_address()); | 490 EXPECT_EQ(kEventAddress, activity.event_address()); |
| 491 ASSERT_EQ(1U, activity.user_data().size()); |
| 492 ASSERT_TRUE(base::ContainsKey(activity.user_data(), "some_int")); |
| 493 EXPECT_EQ(TypedValue::kSignedValue, |
| 494 activity.user_data().at("some_int").value_case()); |
| 495 EXPECT_EQ(42, activity.user_data().at("some_int").signed_value()); |
| 477 } | 496 } |
| 478 { | 497 { |
| 479 const Activity& activity = thread_state.activities(3); | 498 const Activity& activity = thread_state.activities(3); |
| 480 EXPECT_EQ(Activity::ACT_THREAD_JOIN, activity.type()); | 499 EXPECT_EQ(Activity::ACT_THREAD_JOIN, activity.type()); |
| 481 EXPECT_EQ(kThreadId, activity.thread_id()); | 500 EXPECT_EQ(kThreadId, activity.thread_id()); |
| 501 EXPECT_EQ(0U, activity.user_data().size()); |
| 482 } | 502 } |
| 483 { | 503 { |
| 484 const Activity& activity = thread_state.activities(4); | 504 const Activity& activity = thread_state.activities(4); |
| 485 EXPECT_EQ(Activity::ACT_PROCESS_WAIT, activity.type()); | 505 EXPECT_EQ(Activity::ACT_PROCESS_WAIT, activity.type()); |
| 486 EXPECT_EQ(kProcessId, activity.process_id()); | 506 EXPECT_EQ(kProcessId, activity.process_id()); |
| 507 EXPECT_EQ(0U, activity.user_data().size()); |
| 487 } | 508 } |
| 488 } | 509 } |
| 489 | 510 |
| 490 class PostmortemReportCollectorCollectionFromGlobalTrackerTest | 511 class PostmortemReportCollectorCollectionFromGlobalTrackerTest |
| 491 : public testing::Test { | 512 : public testing::Test { |
| 492 public: | 513 public: |
| 493 const int kMemorySize = 1 << 20; // 1MiB | 514 const int kMemorySize = 1 << 20; // 1MiB |
| 494 | 515 |
| 495 PostmortemReportCollectorCollectionFromGlobalTrackerTest() {} | 516 PostmortemReportCollectorCollectionFromGlobalTrackerTest() {} |
| 496 ~PostmortemReportCollectorCollectionFromGlobalTrackerTest() override { | 517 ~PostmortemReportCollectorCollectionFromGlobalTrackerTest() override { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 531 ASSERT_EQ(PostmortemReportCollector::SUCCESS, | 552 ASSERT_EQ(PostmortemReportCollector::SUCCESS, |
| 532 collector.Collect(debug_file_path(), &report)); | 553 collector.Collect(debug_file_path(), &report)); |
| 533 ASSERT_NE(nullptr, report); | 554 ASSERT_NE(nullptr, report); |
| 534 | 555 |
| 535 // Validate the report's log content. | 556 // Validate the report's log content. |
| 536 ASSERT_EQ(2, report->log_messages_size()); | 557 ASSERT_EQ(2, report->log_messages_size()); |
| 537 ASSERT_EQ("hello world", report->log_messages(0)); | 558 ASSERT_EQ("hello world", report->log_messages(0)); |
| 538 ASSERT_EQ("foo bar", report->log_messages(1)); | 559 ASSERT_EQ("foo bar", report->log_messages(1)); |
| 539 } | 560 } |
| 540 | 561 |
| 562 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest, |
| 563 GlobalUserDataCollection) { |
| 564 const char string1[] = "foo"; |
| 565 const char string2[] = "bar"; |
| 566 |
| 567 // Record some global user data. |
| 568 GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL, |
| 569 "", 3); |
| 570 ActivityUserData& global_data = GlobalActivityTracker::Get()->user_data(); |
| 571 global_data.Set("raw", "foo", 3); |
| 572 global_data.SetString("string", "bar"); |
| 573 global_data.SetChar("char", '9'); |
| 574 global_data.SetInt("int", -9999); |
| 575 global_data.SetUint("uint", 9999); |
| 576 global_data.SetBool("bool", true); |
| 577 global_data.SetReference("ref", string1, strlen(string1)); |
| 578 global_data.SetStringReference("sref", string2); |
| 579 |
| 580 // Collect the stability report. |
| 581 PostmortemReportCollector collector(kProductName, kVersionNumber, |
| 582 kChannelName); |
| 583 std::unique_ptr<StabilityReport> report; |
| 584 ASSERT_EQ(PostmortemReportCollector::SUCCESS, |
| 585 collector.Collect(debug_file_path(), &report)); |
| 586 ASSERT_NE(nullptr, report); |
| 587 |
| 588 // Validate the report's log content. |
| 589 const auto& collected_data = report->global_data(); |
| 590 ASSERT_EQ(8U, collected_data.size()); |
| 591 |
| 592 ASSERT_TRUE(base::ContainsKey(collected_data, "raw")); |
| 593 EXPECT_EQ(TypedValue::kBytesValue, collected_data.at("raw").value_case()); |
| 594 EXPECT_EQ("foo", collected_data.at("raw").bytes_value()); |
| 595 |
| 596 ASSERT_TRUE(base::ContainsKey(collected_data, "string")); |
| 597 EXPECT_EQ(TypedValue::kStringValue, collected_data.at("string").value_case()); |
| 598 EXPECT_EQ("bar", collected_data.at("string").string_value()); |
| 599 |
| 600 ASSERT_TRUE(base::ContainsKey(collected_data, "char")); |
| 601 EXPECT_EQ(TypedValue::kCharValue, collected_data.at("char").value_case()); |
| 602 EXPECT_EQ("9", collected_data.at("char").char_value()); |
| 603 |
| 604 ASSERT_TRUE(base::ContainsKey(collected_data, "int")); |
| 605 EXPECT_EQ(TypedValue::kSignedValue, collected_data.at("int").value_case()); |
| 606 EXPECT_EQ(-9999, collected_data.at("int").signed_value()); |
| 607 |
| 608 ASSERT_TRUE(base::ContainsKey(collected_data, "uint")); |
| 609 EXPECT_EQ(TypedValue::kUnsignedValue, collected_data.at("uint").value_case()); |
| 610 EXPECT_EQ(9999U, collected_data.at("uint").unsigned_value()); |
| 611 |
| 612 ASSERT_TRUE(base::ContainsKey(collected_data, "bool")); |
| 613 EXPECT_EQ(TypedValue::kBoolValue, collected_data.at("bool").value_case()); |
| 614 EXPECT_TRUE(collected_data.at("bool").bool_value()); |
| 615 |
| 616 ASSERT_TRUE(base::ContainsKey(collected_data, "ref")); |
| 617 EXPECT_EQ(TypedValue::kBytesReference, collected_data.at("ref").value_case()); |
| 618 const TypedValue::Reference& ref = collected_data.at("ref").bytes_reference(); |
| 619 EXPECT_EQ(reinterpret_cast<uintptr_t>(string1), ref.address()); |
| 620 EXPECT_EQ(strlen(string1), static_cast<uint64_t>(ref.size())); |
| 621 |
| 622 ASSERT_TRUE(base::ContainsKey(collected_data, "sref")); |
| 623 EXPECT_EQ(TypedValue::kStringReference, |
| 624 collected_data.at("sref").value_case()); |
| 625 const TypedValue::Reference& sref = |
| 626 collected_data.at("sref").string_reference(); |
| 627 EXPECT_EQ(reinterpret_cast<uintptr_t>(string2), sref.address()); |
| 628 EXPECT_EQ(strlen(string2), static_cast<uint64_t>(sref.size())); |
| 629 } |
| 630 |
| 541 } // namespace browser_watcher | 631 } // namespace browser_watcher |
| OLD | NEW |