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 <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <vector> | 10 #include <vector> |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 | 133 |
134 // Promote the CreateProcessDump to public so it can be used by test fixtures. | 134 // Promote the CreateProcessDump to public so it can be used by test fixtures. |
135 using MemoryDumpManagerDelegate::CreateProcessDump; | 135 using MemoryDumpManagerDelegate::CreateProcessDump; |
136 }; | 136 }; |
137 | 137 |
138 class MockMemoryDumpProvider : public MemoryDumpProvider { | 138 class MockMemoryDumpProvider : public MemoryDumpProvider { |
139 public: | 139 public: |
140 MOCK_METHOD0(Destructor, void()); | 140 MOCK_METHOD0(Destructor, void()); |
141 MOCK_METHOD2(OnMemoryDump, | 141 MOCK_METHOD2(OnMemoryDump, |
142 bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd)); | 142 bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd)); |
| 143 MOCK_METHOD1(PollFastMemoryTotal, void(uint64_t* memory_total)); |
| 144 MOCK_METHOD0(SuspendFastMemoryPolling, void()); |
143 | 145 |
144 MockMemoryDumpProvider() : enable_mock_destructor(false) { | 146 MockMemoryDumpProvider() : enable_mock_destructor(false) { |
145 ON_CALL(*this, OnMemoryDump(_, _)) | 147 ON_CALL(*this, OnMemoryDump(_, _)) |
146 .WillByDefault(Invoke([](const MemoryDumpArgs&, | 148 .WillByDefault(Invoke([](const MemoryDumpArgs&, |
147 ProcessMemoryDump* pmd) -> bool { | 149 ProcessMemoryDump* pmd) -> bool { |
148 // |session_state| should not be null under any circumstances when | 150 // |session_state| should not be null under any circumstances when |
149 // invoking a memory dump. The problem might arise in race conditions | 151 // invoking a memory dump. The problem might arise in race conditions |
150 // like crbug.com/600570 . | 152 // like crbug.com/600570 . |
151 EXPECT_TRUE(pmd->session_state().get() != nullptr); | 153 EXPECT_TRUE(pmd->session_state().get() != nullptr); |
152 return true; | 154 return true; |
153 })); | 155 })); |
| 156 |
| 157 ON_CALL(*this, PollFastMemoryTotal(_)) |
| 158 .WillByDefault( |
| 159 Invoke([](uint64_t* memory_total) -> void { NOTREACHED(); })); |
154 } | 160 } |
155 ~MockMemoryDumpProvider() override { | 161 ~MockMemoryDumpProvider() override { |
156 if (enable_mock_destructor) | 162 if (enable_mock_destructor) |
157 Destructor(); | 163 Destructor(); |
158 } | 164 } |
159 | 165 |
160 bool enable_mock_destructor; | 166 bool enable_mock_destructor; |
161 }; | 167 }; |
162 | 168 |
163 class TestSequencedTaskRunner : public SequencedTaskRunner { | 169 class TestSequencedTaskRunner : public SequencedTaskRunner { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 // Turns a Closure into a MemoryDumpCallback, keeping track of the callback | 231 // Turns a Closure into a MemoryDumpCallback, keeping track of the callback |
226 // result and taking care of posting the closure on the correct task runner. | 232 // result and taking care of posting the closure on the correct task runner. |
227 void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner, | 233 void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner, |
228 Closure closure, | 234 Closure closure, |
229 uint64_t dump_guid, | 235 uint64_t dump_guid, |
230 bool success) { | 236 bool success) { |
231 last_callback_success_ = success; | 237 last_callback_success_ = success; |
232 task_runner->PostTask(FROM_HERE, closure); | 238 task_runner->PostTask(FROM_HERE, closure); |
233 } | 239 } |
234 | 240 |
| 241 void PollFastMemoryTotal(uint64_t* memory_total) { |
| 242 mdm_->PollFastMemoryTotal(memory_total); |
| 243 } |
| 244 |
235 protected: | 245 protected: |
236 void InitializeMemoryDumpManager(bool is_coordinator) { | 246 void InitializeMemoryDumpManager(bool is_coordinator) { |
237 mdm_->set_dumper_registrations_ignored_for_testing(true); | 247 mdm_->set_dumper_registrations_ignored_for_testing(true); |
238 mdm_->Initialize(delegate_.get(), is_coordinator); | 248 mdm_->Initialize(delegate_.get(), is_coordinator); |
239 } | 249 } |
240 | 250 |
241 void RequestGlobalDumpAndWait(MemoryDumpType dump_type, | 251 void RequestGlobalDumpAndWait(MemoryDumpType dump_type, |
242 MemoryDumpLevelOfDetail level_of_detail) { | 252 MemoryDumpLevelOfDetail level_of_detail) { |
243 RunLoop run_loop; | 253 RunLoop run_loop; |
244 MemoryDumpCallback callback = | 254 MemoryDumpCallback callback = |
(...skipping 16 matching lines...) Expand all Loading... |
261 void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); } | 271 void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); } |
262 | 272 |
263 bool IsPeriodicDumpingEnabled() const { | 273 bool IsPeriodicDumpingEnabled() const { |
264 return mdm_->periodic_dump_timer_.IsRunning(); | 274 return mdm_->periodic_dump_timer_.IsRunning(); |
265 } | 275 } |
266 | 276 |
267 int GetMaxConsecutiveFailuresCount() const { | 277 int GetMaxConsecutiveFailuresCount() const { |
268 return MemoryDumpManager::kMaxConsecutiveFailuresCount; | 278 return MemoryDumpManager::kMaxConsecutiveFailuresCount; |
269 } | 279 } |
270 | 280 |
| 281 scoped_refptr<SequencedTaskRunner> GetPollingTaskRunnerUnsafe() { |
| 282 return mdm_->dump_thread_->task_runner(); |
| 283 } |
| 284 |
271 const MemoryDumpProvider::Options kDefaultOptions; | 285 const MemoryDumpProvider::Options kDefaultOptions; |
272 std::unique_ptr<MemoryDumpManager> mdm_; | 286 std::unique_ptr<MemoryDumpManager> mdm_; |
273 std::unique_ptr<MemoryDumpManagerDelegateForTesting> delegate_; | 287 std::unique_ptr<MemoryDumpManagerDelegateForTesting> delegate_; |
274 bool last_callback_success_; | 288 bool last_callback_success_; |
275 | 289 |
276 private: | 290 private: |
277 std::unique_ptr<MessageLoop> message_loop_; | 291 std::unique_ptr<MessageLoop> message_loop_; |
278 | 292 |
279 // We want our singleton torn down after each test. | 293 // We want our singleton torn down after each test. |
280 ShadowingAtExitManager at_exit_manager_; | 294 ShadowingAtExitManager at_exit_manager_; |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); | 743 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); |
730 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); | 744 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); |
731 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, | 745 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, |
732 MemoryDumpLevelOfDetail::DETAILED); | 746 MemoryDumpLevelOfDetail::DETAILED); |
733 ASSERT_EQ(1, on_memory_dump_call_count); | 747 ASSERT_EQ(1, on_memory_dump_call_count); |
734 ASSERT_TRUE(last_callback_success_); | 748 ASSERT_TRUE(last_callback_success_); |
735 | 749 |
736 DisableTracing(); | 750 DisableTracing(); |
737 } | 751 } |
738 | 752 |
| 753 TEST_F(MemoryDumpManagerTest, TestPollingOnDumpThread) { |
| 754 InitializeMemoryDumpManager(false /* is_coordinator */); |
| 755 std::unique_ptr<MockMemoryDumpProvider> mdp1(new MockMemoryDumpProvider()); |
| 756 std::unique_ptr<MockMemoryDumpProvider> mdp2(new MockMemoryDumpProvider()); |
| 757 mdp1->enable_mock_destructor = true; |
| 758 mdp2->enable_mock_destructor = true; |
| 759 |
| 760 EXPECT_CALL(*mdp1, SuspendFastMemoryPolling()).Times(1); |
| 761 EXPECT_CALL(*mdp2, SuspendFastMemoryPolling()).Times(1); |
| 762 EXPECT_CALL(*mdp1, Destructor()); |
| 763 EXPECT_CALL(*mdp2, Destructor()); |
| 764 |
| 765 RunLoop run_loop; |
| 766 scoped_refptr<SingleThreadTaskRunner> test_task_runner = |
| 767 ThreadTaskRunnerHandle::Get(); |
| 768 auto quit_closure = run_loop.QuitClosure(); |
| 769 |
| 770 int call_count = 0; |
| 771 EXPECT_CALL(*mdp1, PollFastMemoryTotal(_)) |
| 772 .Times(4) |
| 773 .WillRepeatedly(Invoke([&call_count, &test_task_runner, |
| 774 quit_closure](uint64_t* total) -> void { |
| 775 ++call_count; |
| 776 if (call_count == 4) |
| 777 test_task_runner->PostTask(FROM_HERE, quit_closure); |
| 778 })); |
| 779 |
| 780 // Depending on the order of PostTask calls the mdp2 might be registered after |
| 781 // all polls or in between polls. |
| 782 EXPECT_CALL(*mdp2, PollFastMemoryTotal(_)) |
| 783 .Times(Between(0, 4)) |
| 784 .WillRepeatedly(Return()); |
| 785 |
| 786 MemoryDumpProvider::Options options; |
| 787 options.is_fast_polling_supported = true; |
| 788 RegisterDumpProvider(mdp1.get(), nullptr, options); |
| 789 EnableTracingWithTraceConfig( |
| 790 TraceConfigMemoryTestUtil::GetTraceConfig_PeakDetectionTrigger(1)); |
| 791 scoped_refptr<SequencedTaskRunner> polling_task_runner = |
| 792 GetPollingTaskRunnerUnsafe().get(); |
| 793 ASSERT_TRUE(polling_task_runner); |
| 794 |
| 795 uint64_t value = 0; |
| 796 for (int i = 0; i < 4; i++) { |
| 797 if (i == 0) |
| 798 RegisterDumpProvider(mdp2.get(), nullptr, options); |
| 799 if (i == 2) |
| 800 mdm_->UnregisterAndDeleteDumpProviderSoon(std::move(mdp2)); |
| 801 polling_task_runner->PostTask( |
| 802 FROM_HERE, Bind(&MemoryDumpManagerTest::PollFastMemoryTotal, |
| 803 Unretained(this), &value)); |
| 804 } |
| 805 |
| 806 run_loop.Run(); |
| 807 DisableTracing(); |
| 808 mdm_->UnregisterAndDeleteDumpProviderSoon(std::move(mdp1)); |
| 809 } |
| 810 |
739 // If a thread (with a dump provider living on it) is torn down during a dump | 811 // If a thread (with a dump provider living on it) is torn down during a dump |
740 // its dump provider should be skipped but the dump itself should succeed. | 812 // its dump provider should be skipped but the dump itself should succeed. |
741 TEST_F(MemoryDumpManagerTest, TearDownThreadWhileDumping) { | 813 TEST_F(MemoryDumpManagerTest, TearDownThreadWhileDumping) { |
742 InitializeMemoryDumpManager(false /* is_coordinator */); | 814 InitializeMemoryDumpManager(false /* is_coordinator */); |
743 std::vector<std::unique_ptr<TestIOThread>> threads; | 815 std::vector<std::unique_ptr<TestIOThread>> threads; |
744 std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps; | 816 std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps; |
745 | 817 |
746 for (int i = 0; i < 2; i++) { | 818 for (int i = 0; i < 2; i++) { |
747 threads.push_back( | 819 threads.push_back( |
748 WrapUnique(new TestIOThread(TestIOThread::kAutoStart))); | 820 WrapUnique(new TestIOThread(TestIOThread::kAutoStart))); |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 MemoryDumpLevelOfDetail::DETAILED); | 1259 MemoryDumpLevelOfDetail::DETAILED); |
1188 EXPECT_FALSE(last_callback_success_); | 1260 EXPECT_FALSE(last_callback_success_); |
1189 | 1261 |
1190 ASSERT_TRUE(IsPeriodicDumpingEnabled()); | 1262 ASSERT_TRUE(IsPeriodicDumpingEnabled()); |
1191 run_loop.Run(); | 1263 run_loop.Run(); |
1192 DisableTracing(); | 1264 DisableTracing(); |
1193 } | 1265 } |
1194 | 1266 |
1195 } // namespace trace_event | 1267 } // namespace trace_event |
1196 } // namespace base | 1268 } // namespace base |
OLD | NEW |