OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "base/trace_event/memory_dump_manager.h" | 5 #include "base/trace_event/memory_dump_manager.h" |
6 | 6 |
7 #include "base/bind_helpers.h" | 7 #include "base/bind_helpers.h" |
8 #include "base/memory/scoped_vector.h" | 8 #include "base/memory/scoped_vector.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
12 #include "base/test/test_io_thread.h" | 12 #include "base/test/test_io_thread.h" |
13 #include "base/thread_task_runner_handle.h" | 13 #include "base/thread_task_runner_handle.h" |
14 #include "base/threading/thread.h" | 14 #include "base/threading/thread.h" |
15 #include "base/trace_event/memory_dump_provider.h" | 15 #include "base/trace_event/memory_dump_provider.h" |
16 #include "base/trace_event/process_memory_dump.h" | 16 #include "base/trace_event/process_memory_dump.h" |
| 17 #include "base/trace_event/trace_config_memory_test_util.h" |
17 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
19 | 20 |
20 using testing::_; | 21 using testing::_; |
21 using testing::AnyNumber; | 22 using testing::AnyNumber; |
22 using testing::AtMost; | 23 using testing::AtMost; |
23 using testing::Between; | 24 using testing::Between; |
24 using testing::Invoke; | 25 using testing::Invoke; |
25 using testing::Return; | 26 using testing::Return; |
26 | 27 |
27 namespace base { | 28 namespace base { |
28 namespace trace_event { | 29 namespace trace_event { |
29 namespace { | 30 namespace { |
30 MemoryDumpArgs g_high_detail_args = {MemoryDumpArgs::LevelOfDetail::HIGH}; | 31 MemoryDumpArgs g_high_detail_args = {MemoryDumpArgs::LevelOfDetail::HIGH}; |
31 MemoryDumpArgs g_low_detail_args = {MemoryDumpArgs::LevelOfDetail::LOW}; | 32 MemoryDumpArgs g_low_detail_args = {MemoryDumpArgs::LevelOfDetail::LOW}; |
32 const char kTraceConfigWithTriggersFmt[] = | |
33 "{\"included_categories\":[\"%s\"],\"memory_dump_config\":{\"triggers\":[" | |
34 "{\"mode\":\"light\", \"periodic_interval_ms\":1}," | |
35 "{\"mode\":\"detailed\", \"periodic_interval_ms\":5}]}}"; | |
36 } // namespace | 33 } // namespace |
37 | 34 |
38 // GTest matchers for MemoryDumpRequestArgs arguments. | 35 // GTest matchers for MemoryDumpRequestArgs arguments. |
39 MATCHER(IsHighDetail, "") { | 36 MATCHER(IsHighDetail, "") { |
40 return arg.level_of_detail == MemoryDumpArgs::LevelOfDetail::HIGH; | 37 return arg.level_of_detail == MemoryDumpArgs::LevelOfDetail::HIGH; |
41 } | 38 } |
42 | 39 |
43 MATCHER(IsLowDetail, "") { | 40 MATCHER(IsLowDetail, "") { |
44 return arg.level_of_detail == MemoryDumpArgs::LevelOfDetail::LOW; | 41 return arg.level_of_detail == MemoryDumpArgs::LevelOfDetail::LOW; |
45 } | 42 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 protected: | 106 protected: |
110 void InitializeMemoryDumpManager(bool is_coordinator) { | 107 void InitializeMemoryDumpManager(bool is_coordinator) { |
111 mdm_->Initialize(delegate_.get(), is_coordinator); | 108 mdm_->Initialize(delegate_.get(), is_coordinator); |
112 } | 109 } |
113 | 110 |
114 void EnableTracingWithLegacyCategories(const char* category) { | 111 void EnableTracingWithLegacyCategories(const char* category) { |
115 TraceLog::GetInstance()->SetEnabled(TraceConfig(category, ""), | 112 TraceLog::GetInstance()->SetEnabled(TraceConfig(category, ""), |
116 TraceLog::RECORDING_MODE); | 113 TraceLog::RECORDING_MODE); |
117 } | 114 } |
118 | 115 |
119 void EnableTracingWithTraceConfig(const char* trace_config) { | 116 void EnableTracingWithTraceConfig(const std::string& trace_config) { |
120 TraceLog::GetInstance()->SetEnabled(TraceConfig(trace_config), | 117 TraceLog::GetInstance()->SetEnabled(TraceConfig(trace_config), |
121 TraceLog::RECORDING_MODE); | 118 TraceLog::RECORDING_MODE); |
122 } | 119 } |
123 | 120 |
124 void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); } | 121 void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); } |
125 | 122 |
126 bool IsPeriodicDumpingEnabled() const { | 123 bool IsPeriodicDumpingEnabled() const { |
127 return mdm_->periodic_dump_timer_.IsRunning(); | 124 return mdm_->periodic_dump_timer_.IsRunning(); |
128 } | 125 } |
129 | 126 |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 MemoryDumpCallback callback = | 576 MemoryDumpCallback callback = |
580 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 577 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), |
581 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 578 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); |
582 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 579 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
583 g_high_detail_args, callback); | 580 g_high_detail_args, callback); |
584 run_loop.Run(); | 581 run_loop.Run(); |
585 } | 582 } |
586 EXPECT_FALSE(last_callback_success_); | 583 EXPECT_FALSE(last_callback_success_); |
587 } | 584 } |
588 | 585 |
| 586 // Checks that is the MemoryDumpManager is initialized after tracing already |
| 587 // began, it will still late-join the party (real use case: startup tracing). |
| 588 TEST_F(MemoryDumpManagerTest, InitializedAfterStartOfTracing) { |
| 589 MockMemoryDumpProvider mdp; |
| 590 mdm_->RegisterDumpProvider(&mdp); |
| 591 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); |
| 592 |
| 593 // First check that a RequestGlobalDump() issued before the MemoryDumpManager |
| 594 // initialization gets NACK-ed cleanly. |
| 595 { |
| 596 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); |
| 597 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(0); |
| 598 RunLoop run_loop; |
| 599 MemoryDumpCallback callback = |
| 600 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), |
| 601 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); |
| 602 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 603 g_high_detail_args, callback); |
| 604 run_loop.Run(); |
| 605 EXPECT_FALSE(last_callback_success_); |
| 606 } |
| 607 |
| 608 // Now late-initialize the MemoryDumpManager and check that the |
| 609 // RequestGlobalDump completes successfully. |
| 610 { |
| 611 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(1); |
| 612 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); |
| 613 InitializeMemoryDumpManager(false /* is_coordinator */); |
| 614 RunLoop run_loop; |
| 615 MemoryDumpCallback callback = |
| 616 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), |
| 617 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); |
| 618 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 619 g_high_detail_args, callback); |
| 620 run_loop.Run(); |
| 621 EXPECT_TRUE(last_callback_success_); |
| 622 } |
| 623 DisableTracing(); |
| 624 } |
| 625 |
589 // This test (and the MemoryDumpManagerTestCoordinator below) crystallizes the | 626 // This test (and the MemoryDumpManagerTestCoordinator below) crystallizes the |
590 // expectations of the chrome://tracing UI and chrome telemetry w.r.t. periodic | 627 // expectations of the chrome://tracing UI and chrome telemetry w.r.t. periodic |
591 // dumps in memory-infra, handling gracefully the transition between the legacy | 628 // dumps in memory-infra, handling gracefully the transition between the legacy |
592 // and the new-style (JSON-based) TraceConfig. | 629 // and the new-style (JSON-based) TraceConfig. |
593 TEST_F(MemoryDumpManagerTest, TraceConfigExpectations) { | 630 TEST_F(MemoryDumpManagerTest, TraceConfigExpectations) { |
594 InitializeMemoryDumpManager(false /* is_coordinator */); | 631 InitializeMemoryDumpManager(false /* is_coordinator */); |
595 MemoryDumpManagerDelegateForTesting& delegate = *delegate_; | 632 MemoryDumpManagerDelegateForTesting& delegate = *delegate_; |
596 | 633 |
597 // Don't trigger the default behavior of the mock delegate in this test, | 634 // Don't trigger the default behavior of the mock delegate in this test, |
598 // which would short-circuit the dump request to the actual | 635 // which would short-circuit the dump request to the actual |
599 // CreateProcessDump(). | 636 // CreateProcessDump(). |
600 // We don't want to create any dump in this test, only check whether the dumps | 637 // We don't want to create any dump in this test, only check whether the dumps |
601 // are requested or not. | 638 // are requested or not. |
602 ON_CALL(delegate, RequestGlobalMemoryDump(_, _)).WillByDefault(Return()); | 639 ON_CALL(delegate, RequestGlobalMemoryDump(_, _)).WillByDefault(Return()); |
603 | 640 |
604 // Enabling memory-infra in a non-coordinator process should not trigger any | 641 // Enabling memory-infra in a non-coordinator process should not trigger any |
605 // periodic dumps. | 642 // periodic dumps. |
606 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); | 643 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); |
607 EXPECT_FALSE(IsPeriodicDumpingEnabled()); | 644 EXPECT_FALSE(IsPeriodicDumpingEnabled()); |
608 DisableTracing(); | 645 DisableTracing(); |
609 | 646 |
610 // Enabling memory-infra with the new (JSON) TraceConfig in a non-coordinator | 647 // Enabling memory-infra with the new (JSON) TraceConfig in a non-coordinator |
611 // process with a fully defined trigger config should NOT enable any periodic | 648 // process with a fully defined trigger config should NOT enable any periodic |
612 // dumps. | 649 // dumps. |
613 const std::string kTraceConfigWithTriggers = StringPrintf( | 650 EnableTracingWithTraceConfig( |
614 kTraceConfigWithTriggersFmt, MemoryDumpManager::kTraceCategory); | 651 TraceConfigMemoryTestUtil::GetTraceConfig_PeriodicTriggers(1, 5)); |
615 EnableTracingWithTraceConfig(kTraceConfigWithTriggers.c_str()); | |
616 EXPECT_FALSE(IsPeriodicDumpingEnabled()); | 652 EXPECT_FALSE(IsPeriodicDumpingEnabled()); |
617 DisableTracing(); | 653 DisableTracing(); |
618 } | 654 } |
619 | 655 |
620 TEST_F(MemoryDumpManagerTest, TraceConfigExpectationsWhenIsCoordinator) { | 656 TEST_F(MemoryDumpManagerTest, TraceConfigExpectationsWhenIsCoordinator) { |
621 InitializeMemoryDumpManager(true /* is_coordinator */); | 657 InitializeMemoryDumpManager(true /* is_coordinator */); |
622 MemoryDumpManagerDelegateForTesting& delegate = *delegate_; | 658 MemoryDumpManagerDelegateForTesting& delegate = *delegate_; |
623 ON_CALL(delegate, RequestGlobalMemoryDump(_, _)).WillByDefault(Return()); | 659 ON_CALL(delegate, RequestGlobalMemoryDump(_, _)).WillByDefault(Return()); |
624 | 660 |
625 // Enabling memory-infra with the legacy TraceConfig (category filter) in | 661 // Enabling memory-infra with the legacy TraceConfig (category filter) in |
626 // a coordinator process should enable periodic dumps. | 662 // a coordinator process should enable periodic dumps. |
627 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); | 663 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); |
628 EXPECT_TRUE(IsPeriodicDumpingEnabled()); | 664 EXPECT_TRUE(IsPeriodicDumpingEnabled()); |
629 DisableTracing(); | 665 DisableTracing(); |
630 | 666 |
631 // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator | 667 // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator |
632 // process without specifying any "memory_dump_config" section should enable | 668 // process without specifying any "memory_dump_config" section should enable |
633 // periodic dumps. This is to preserve the behavior chrome://tracing UI, that | 669 // periodic dumps. This is to preserve the behavior chrome://tracing UI, that |
634 // is: ticking memory-infra should dump periodically with the default config. | 670 // is: ticking memory-infra should dump periodically with the default config. |
635 const std::string kTraceConfigWithNoMemorDumpConfig = StringPrintf( | 671 EnableTracingWithTraceConfig( |
636 "{\"included_categories\":[\"%s\"]}", MemoryDumpManager::kTraceCategory); | 672 TraceConfigMemoryTestUtil::GetTraceConfig_NoTriggers()); |
637 EnableTracingWithTraceConfig(kTraceConfigWithNoMemorDumpConfig.c_str()); | |
638 EXPECT_TRUE(IsPeriodicDumpingEnabled()); | 673 EXPECT_TRUE(IsPeriodicDumpingEnabled()); |
639 DisableTracing(); | 674 DisableTracing(); |
640 | 675 |
641 // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator | 676 // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator |
642 // process with an empty "memory_dump_config" should NOT enable periodic | 677 // process with an empty "memory_dump_config" should NOT enable periodic |
643 // dumps. This is the way telemetry is supposed to use memory-infra with | 678 // dumps. This is the way telemetry is supposed to use memory-infra with |
644 // only explicitly triggered dumps. | 679 // only explicitly triggered dumps. |
645 const std::string kTraceConfigWithNoTriggers = StringPrintf( | 680 EnableTracingWithTraceConfig( |
646 "{\"included_categories\":[\"%s\"], \"memory_dump_config\":{}", | 681 TraceConfigMemoryTestUtil::GetTraceConfig_EmptyTriggers()); |
647 MemoryDumpManager::kTraceCategory); | |
648 EnableTracingWithTraceConfig(kTraceConfigWithNoTriggers.c_str()); | |
649 EXPECT_FALSE(IsPeriodicDumpingEnabled()); | 682 EXPECT_FALSE(IsPeriodicDumpingEnabled()); |
650 DisableTracing(); | 683 DisableTracing(); |
651 | 684 |
652 // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator | 685 // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator |
653 // process with a fully defined trigger config should cause periodic dumps to | 686 // process with a fully defined trigger config should cause periodic dumps to |
654 // be performed in the correct order. | 687 // be performed in the correct order. |
655 RunLoop run_loop; | 688 RunLoop run_loop; |
656 auto quit_closure = run_loop.QuitClosure(); | 689 auto quit_closure = run_loop.QuitClosure(); |
657 | 690 |
658 // The expected sequence with config of light=1ms, heavy=5ms is H,L,L,L,H,... | 691 const int kHeavyDumpRate = 5; |
| 692 const int kLightDumpPeriodMs = 1; |
| 693 const int kHeavyDumpPeriodMs = kHeavyDumpRate * kLightDumpPeriodMs; |
| 694 // The expected sequence with light=1ms, heavy=5ms is H,L,L,L,L,H,... |
659 testing::InSequence sequence; | 695 testing::InSequence sequence; |
660 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsHighDetailArgs(), _)); | 696 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsHighDetailArgs(), _)); |
661 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLowDetailArgs(), _)).Times(3); | 697 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLowDetailArgs(), _)) |
| 698 .Times(kHeavyDumpRate - 1); |
662 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsHighDetailArgs(), _)); | 699 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsHighDetailArgs(), _)); |
663 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLowDetailArgs(), _)).Times(2); | 700 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLowDetailArgs(), _)) |
| 701 .Times(kHeavyDumpRate - 2); |
664 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLowDetailArgs(), _)) | 702 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLowDetailArgs(), _)) |
665 .WillOnce(Invoke([quit_closure](const MemoryDumpRequestArgs& args, | 703 .WillOnce(Invoke([quit_closure](const MemoryDumpRequestArgs& args, |
666 const MemoryDumpCallback& callback) { | 704 const MemoryDumpCallback& callback) { |
667 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure); | 705 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure); |
668 })); | 706 })); |
669 | 707 |
670 // Swallow all the final spurious calls until tracing gets disabled. | 708 // Swallow all the final spurious calls until tracing gets disabled. |
671 EXPECT_CALL(delegate, RequestGlobalMemoryDump(_, _)).Times(AnyNumber()); | 709 EXPECT_CALL(delegate, RequestGlobalMemoryDump(_, _)).Times(AnyNumber()); |
672 | 710 |
673 const std::string kTraceConfigWithTriggers = StringPrintf( | 711 EnableTracingWithTraceConfig( |
674 kTraceConfigWithTriggersFmt, MemoryDumpManager::kTraceCategory); | 712 TraceConfigMemoryTestUtil::GetTraceConfig_PeriodicTriggers( |
675 EnableTracingWithTraceConfig(kTraceConfigWithTriggers.c_str()); | 713 kLightDumpPeriodMs, kHeavyDumpPeriodMs)); |
676 run_loop.Run(); | 714 run_loop.Run(); |
677 DisableTracing(); | 715 DisableTracing(); |
678 } | 716 } |
679 | 717 |
680 } // namespace trace_event | 718 } // namespace trace_event |
681 } // namespace base | 719 } // namespace base |
OLD | NEW |