Chromium Code Reviews| 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/test/test_io_thread.h" | 12 #include "base/test/test_io_thread.h" |
| 12 #include "base/thread_task_runner_handle.h" | 13 #include "base/thread_task_runner_handle.h" |
| 13 #include "base/threading/thread.h" | 14 #include "base/threading/thread.h" |
| 14 #include "base/trace_event/memory_dump_provider.h" | 15 #include "base/trace_event/memory_dump_provider.h" |
| 15 #include "base/trace_event/process_memory_dump.h" | 16 #include "base/trace_event/process_memory_dump.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" | 17 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 19 |
| 19 using testing::_; | 20 using testing::_; |
| 21 using testing::AnyNumber; | |
| 20 using testing::AtMost; | 22 using testing::AtMost; |
| 21 using testing::Between; | 23 using testing::Between; |
| 22 using testing::Invoke; | 24 using testing::Invoke; |
| 23 using testing::Return; | 25 using testing::Return; |
| 24 | 26 |
| 25 namespace base { | 27 namespace base { |
| 26 namespace trace_event { | 28 namespace trace_event { |
| 27 namespace { | 29 namespace { |
| 28 MemoryDumpArgs g_high_detail_args = {MemoryDumpArgs::LevelOfDetail::HIGH}; | 30 MemoryDumpArgs g_high_detail_args = {MemoryDumpArgs::LevelOfDetail::HIGH}; |
| 29 MemoryDumpArgs g_low_detail_args = {MemoryDumpArgs::LevelOfDetail::LOW}; | 31 MemoryDumpArgs g_low_detail_args = {MemoryDumpArgs::LevelOfDetail::LOW}; |
| 32 } // namespace | |
| 33 | |
| 34 // GTest matchers for MemoryDumpRequestArgs arguments. | |
|
petrcermak
2015/09/09 11:48:30
I think that matcher the definitions are grouped i
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
right. fixed.
| |
| 35 MATCHER(IsHighDetail, "") { | |
| 36 return arg.level_of_detail == MemoryDumpArgs::LevelOfDetail::HIGH; | |
| 30 } | 37 } |
| 31 | 38 |
| 32 // Testing MemoryDumpManagerDelegate which short-circuits dump requests locally | 39 MATCHER(IsHighDetailArgs, "") { |
| 33 // instead of performing IPC dances. | 40 return arg.dump_args.level_of_detail == MemoryDumpArgs::LevelOfDetail::HIGH; |
|
petrcermak
2015/09/09 11:48:30
Any chance this could reuse the IsHighDetail match
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Nope, couldn't find any way
| |
| 41 } | |
| 42 | |
| 43 // GTest matchers for MemoryDumpArgs arguments. | |
| 44 MATCHER(IsLowDetail, "") { | |
| 45 return arg.level_of_detail == MemoryDumpArgs::LevelOfDetail::LOW; | |
| 46 } | |
| 47 | |
| 48 MATCHER(IsLowDetailArgs, "") { | |
| 49 return arg.dump_args.level_of_detail == MemoryDumpArgs::LevelOfDetail::LOW; | |
| 50 } | |
| 51 | |
| 52 // Testing MemoryDumpManagerDelegate which, by default, short-circuits dump | |
| 53 // requests locally to the MemoryDUmpManager instead of performing IPC dances. | |
|
petrcermak
2015/09/09 11:48:29
nit: s/MemoryDUmpManager/MemoryDumpManager/
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Done.
| |
| 34 class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate { | 54 class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate { |
| 35 public: | 55 public: |
| 36 void RequestGlobalMemoryDump(const MemoryDumpRequestArgs& args, | 56 MemoryDumpManagerDelegateForTesting() { |
| 37 const MemoryDumpCallback& callback) override { | 57 EXPECT_CALL(*this, IsCoordinatorProcess()).WillRepeatedly(Return(false)); |
| 38 CreateProcessDump(args, callback); | 58 ON_CALL(*this, RequestGlobalMemoryDump(_, _)) |
| 59 .WillByDefault(Invoke( | |
| 60 this, &MemoryDumpManagerDelegateForTesting::CreateProcessDump)); | |
| 39 } | 61 } |
| 40 | 62 |
| 41 bool IsCoordinatorProcess() const override { return false; } | 63 MOCK_METHOD2(RequestGlobalMemoryDump, |
| 64 void(const MemoryDumpRequestArgs& args, | |
| 65 const MemoryDumpCallback& callback)); | |
| 66 | |
| 67 MOCK_CONST_METHOD0(IsCoordinatorProcess, bool()); | |
| 68 | |
| 42 uint64 GetTracingProcessId() const override { | 69 uint64 GetTracingProcessId() const override { |
| 70 NOTREACHED(); | |
| 43 return MemoryDumpManager::kInvalidTracingProcessId; | 71 return MemoryDumpManager::kInvalidTracingProcessId; |
| 44 } | 72 } |
| 45 }; | 73 }; |
| 46 | 74 |
| 47 class MemoryDumpManagerDelegateForPeriodicDumpTest | 75 class MockDumpProvider : public MemoryDumpProvider { |
|
petrcermak
2015/09/09 11:48:29
nit: Wouldn't 'MockMemoryDumpProvider' be better?
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Ok. you're just lucky that didn't cause any wrappi
| |
| 48 : public MemoryDumpManagerDelegateForTesting { | |
| 49 public: | 76 public: |
| 50 MOCK_METHOD2(RequestGlobalMemoryDump, | 77 MOCK_METHOD2(OnMemoryDump, |
| 51 void(const MemoryDumpRequestArgs& args, | 78 bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd)); |
| 52 const MemoryDumpCallback& callback)); | |
| 53 | |
| 54 bool IsCoordinatorProcess() const override { return true; } | |
| 55 }; | 79 }; |
| 56 | 80 |
| 57 class MemoryDumpManagerTest : public testing::Test { | 81 class MemoryDumpManagerTest : public testing::Test { |
| 58 public: | 82 public: |
| 59 void SetUp() override { | 83 void SetUp() override { |
| 60 last_callback_success_ = false; | 84 last_callback_success_ = false; |
| 61 message_loop_.reset(new MessageLoop()); | 85 message_loop_.reset(new MessageLoop()); |
| 62 mdm_.reset(new MemoryDumpManager()); | 86 mdm_.reset(new MemoryDumpManager()); |
| 63 MemoryDumpManager::SetInstanceForTesting(mdm_.get()); | 87 MemoryDumpManager::SetInstanceForTesting(mdm_.get()); |
| 64 ASSERT_EQ(mdm_, MemoryDumpManager::GetInstance()); | 88 ASSERT_EQ(mdm_, MemoryDumpManager::GetInstance()); |
| 65 MemoryDumpManager::GetInstance()->Initialize(); | 89 mdm_->Initialize(); |
| 90 delegate_.reset(new MemoryDumpManagerDelegateForTesting); | |
| 91 mdm_->SetDelegate(delegate_.get()); | |
| 66 } | 92 } |
| 67 | 93 |
| 68 void TearDown() override { | 94 void TearDown() override { |
| 69 MemoryDumpManager::SetInstanceForTesting(nullptr); | 95 MemoryDumpManager::SetInstanceForTesting(nullptr); |
| 70 mdm_.reset(); | 96 mdm_.reset(); |
| 97 delegate_.reset(); | |
| 71 message_loop_.reset(); | 98 message_loop_.reset(); |
| 72 TraceLog::DeleteForTesting(); | 99 TraceLog::DeleteForTesting(); |
| 73 } | 100 } |
| 74 | 101 |
| 75 void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner, | 102 void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner, |
| 76 Closure closure, | 103 Closure closure, |
| 77 uint64 dump_guid, | 104 uint64 dump_guid, |
| 78 bool success) { | 105 bool success) { |
| 79 last_callback_success_ = success; | 106 last_callback_success_ = success; |
| 80 task_runner->PostTask(FROM_HERE, closure); | 107 task_runner->PostTask(FROM_HERE, closure); |
| 81 } | 108 } |
| 82 | 109 |
| 83 protected: | 110 protected: |
| 84 void SetDelegate(scoped_ptr<MemoryDumpManagerDelegateForTesting> delegate) { | 111 // This enables tracing using the legacy category filter string. |
| 85 delegate_ = delegate.Pass(); | |
| 86 MemoryDumpManager::GetInstance()->SetDelegate(delegate_.get()); | |
| 87 } | |
| 88 | |
| 89 // This enalbes tracing using the legacy category filter string. | |
| 90 void EnableTracing(const char* category) { | 112 void EnableTracing(const char* category) { |
|
petrcermak
2015/09/09 11:48:29
nit: Wouldn't 'EnableTracingWithCategories' be cle
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Agree. EnableTracingWithLegacyCategories, it is.
| |
| 91 if (!delegate_) { | 113 TraceLog::GetInstance()->SetEnabled(TraceConfig(category, ""), |
| 92 delegate_.reset(new MemoryDumpManagerDelegateForTesting()); | 114 TraceLog::RECORDING_MODE); |
| 93 MemoryDumpManager::GetInstance()->SetDelegate(delegate_.get()); | |
| 94 } | |
| 95 TraceLog::GetInstance()->SetEnabled( | |
| 96 TraceConfig(category, ""), TraceLog::RECORDING_MODE); | |
| 97 } | 115 } |
| 98 | 116 |
| 99 void EnableTracingWithTraceConfig(const char* trace_config) { | 117 void EnableTracingWithTraceConfig(const char* trace_config) { |
| 100 DCHECK(delegate_); | |
|
petrcermak
2015/09/09 11:48:29
Is there a particular reason for removing this?
Primiano Tucci (use gerrit)
2015/09/09 13:28:43
yes. before it was a responsiblity of the TEST_F t
| |
| 101 TraceConfig tc(trace_config); | 118 TraceConfig tc(trace_config); |
|
petrcermak
2015/09/09 11:48:30
nit: I don't think there's any need to actually na
Primiano Tucci (use gerrit)
2015/09/09 13:28:43
Agree. didn't realize. thanks. done
| |
| 102 TraceLog::GetInstance()->SetEnabled(tc, TraceLog::RECORDING_MODE); | 119 TraceLog::GetInstance()->SetEnabled(tc, TraceLog::RECORDING_MODE); |
| 103 } | 120 } |
| 104 | 121 |
| 105 void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); } | 122 void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); } |
| 106 | 123 |
| 124 bool IsPeriodicDumpingEnabled() const { | |
| 125 return mdm_->periodic_dump_timer_.IsRunning(); | |
| 126 } | |
| 127 | |
| 107 scoped_ptr<MemoryDumpManager> mdm_; | 128 scoped_ptr<MemoryDumpManager> mdm_; |
| 129 scoped_ptr<MemoryDumpManagerDelegateForTesting> delegate_; | |
| 108 bool last_callback_success_; | 130 bool last_callback_success_; |
| 109 scoped_ptr<MemoryDumpManagerDelegateForTesting> delegate_; | |
| 110 | 131 |
| 111 private: | 132 private: |
| 112 scoped_ptr<MessageLoop> message_loop_; | 133 scoped_ptr<MessageLoop> message_loop_; |
| 113 | 134 |
| 114 // We want our singleton torn down after each test. | 135 // We want our singleton torn down after each test. |
| 115 ShadowingAtExitManager at_exit_manager_; | 136 ShadowingAtExitManager at_exit_manager_; |
| 116 }; | 137 }; |
| 117 | 138 |
| 118 class MockDumpProvider : public MemoryDumpProvider { | |
| 119 public: | |
| 120 MockDumpProvider() | |
| 121 : dump_provider_to_register_or_unregister(nullptr), | |
| 122 last_session_state_(nullptr), | |
| 123 level_of_detail_(MemoryDumpArgs::LevelOfDetail::HIGH) {} | |
| 124 | 139 |
| 125 // Ctor used by the RespectTaskRunnerAffinity test. | 140 // Basic sanity checks. Registers a memory dump provider and checks that it is |
| 126 explicit MockDumpProvider( | 141 // called, but only when memory-infra is enabled. |
| 127 const scoped_refptr<SingleThreadTaskRunner>& task_runner) | |
| 128 : last_session_state_(nullptr), | |
| 129 task_runner_(task_runner), | |
| 130 level_of_detail_(MemoryDumpArgs::LevelOfDetail::HIGH) {} | |
| 131 | |
| 132 // Ctor used by CheckMemoryDumpArgs test. | |
| 133 explicit MockDumpProvider(const MemoryDumpArgs::LevelOfDetail level_of_detail) | |
| 134 : last_session_state_(nullptr), level_of_detail_(level_of_detail) {} | |
| 135 | |
| 136 virtual ~MockDumpProvider() {} | |
| 137 | |
| 138 MOCK_METHOD2(OnMemoryDump, | |
| 139 bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd)); | |
| 140 | |
| 141 // OnMemoryDump() override for the RespectTaskRunnerAffinity test. | |
| 142 bool OnMemoryDump_CheckTaskRunner(const MemoryDumpArgs& args, | |
| 143 ProcessMemoryDump* pmd) { | |
| 144 EXPECT_TRUE(task_runner_->RunsTasksOnCurrentThread()); | |
| 145 return true; | |
| 146 } | |
| 147 | |
| 148 // OnMemoryDump() override for the SharedSessionState test. | |
| 149 bool OnMemoryDump_CheckSessionState(const MemoryDumpArgs& args, | |
| 150 ProcessMemoryDump* pmd) { | |
| 151 MemoryDumpSessionState* cur_session_state = pmd->session_state().get(); | |
| 152 if (last_session_state_) | |
| 153 EXPECT_EQ(last_session_state_, cur_session_state); | |
| 154 last_session_state_ = cur_session_state; | |
| 155 return true; | |
| 156 } | |
| 157 | |
| 158 // OnMemoryDump() override for the RegisterDumperWhileDumping test. | |
| 159 bool OnMemoryDump_RegisterExtraDumpProvider(const MemoryDumpArgs& args, | |
| 160 ProcessMemoryDump* pmd) { | |
| 161 MemoryDumpManager::GetInstance()->RegisterDumpProvider( | |
| 162 dump_provider_to_register_or_unregister); | |
| 163 return true; | |
| 164 } | |
| 165 | |
| 166 // OnMemoryDump() override for the UnegisterDumperWhileDumping test. | |
| 167 bool OnMemoryDump_UnregisterDumpProvider(const MemoryDumpArgs& args, | |
| 168 ProcessMemoryDump* pmd) { | |
| 169 MemoryDumpManager::GetInstance()->UnregisterDumpProvider( | |
| 170 dump_provider_to_register_or_unregister); | |
| 171 return true; | |
| 172 } | |
| 173 | |
| 174 // OnMemoryDump() override for the CheckMemoryDumpArgs test. | |
| 175 bool OnMemoryDump_CheckMemoryDumpArgs(const MemoryDumpArgs& args, | |
| 176 ProcessMemoryDump* pmd) { | |
| 177 EXPECT_EQ(level_of_detail_, args.level_of_detail); | |
| 178 return true; | |
| 179 } | |
| 180 | |
| 181 // Used by OnMemoryDump_(Un)RegisterExtraDumpProvider. | |
| 182 MemoryDumpProvider* dump_provider_to_register_or_unregister; | |
| 183 | |
| 184 private: | |
| 185 MemoryDumpSessionState* last_session_state_; | |
| 186 scoped_refptr<SingleThreadTaskRunner> task_runner_; | |
| 187 const MemoryDumpArgs::LevelOfDetail level_of_detail_; | |
| 188 }; | |
| 189 | |
| 190 TEST_F(MemoryDumpManagerTest, SingleDumper) { | 142 TEST_F(MemoryDumpManagerTest, SingleDumper) { |
| 191 MockDumpProvider mdp; | 143 MockDumpProvider mdp; |
| 192 mdm_->RegisterDumpProvider(&mdp); | 144 mdm_->RegisterDumpProvider(&mdp); |
| 193 | 145 |
| 194 // Check that the dumper is not called if the memory category is not enabled. | 146 // Check that the dumper is not called if the memory category is not enabled. |
| 195 EnableTracing("foo-and-bar-but-not-memory"); | 147 EnableTracing("foo-and-bar-but-not-memory"); |
| 148 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(0); | |
| 196 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 149 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); |
| 197 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 150 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 198 g_high_detail_args); | 151 g_high_detail_args); |
| 199 DisableTracing(); | 152 DisableTracing(); |
| 200 | 153 |
| 201 // Now repeat enabling the memory category and check that the dumper is | 154 // Now repeat enabling the memory category and check that the dumper is |
| 202 // invoked this time. | 155 // invoked this time. |
| 203 EnableTracing(MemoryDumpManager::kTraceCategory); | 156 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 157 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(3); | |
| 204 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(3).WillRepeatedly(Return(true)); | 158 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(3).WillRepeatedly(Return(true)); |
| 205 for (int i = 0; i < 3; ++i) | 159 for (int i = 0; i < 3; ++i) |
| 206 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 160 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 207 g_high_detail_args); | 161 g_high_detail_args); |
| 208 DisableTracing(); | 162 DisableTracing(); |
| 209 | 163 |
| 210 mdm_->UnregisterDumpProvider(&mdp); | 164 mdm_->UnregisterDumpProvider(&mdp); |
| 211 | 165 |
| 212 // Finally check the unregister logic (no calls to the mdp after unregister). | 166 // Finally check the unregister logic: the delegate will be invoked but not |
| 167 // the dump provider, as it has been unregistered. | |
| 213 EnableTracing(MemoryDumpManager::kTraceCategory); | 168 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 169 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); | |
|
petrcermak
2015/09/09 11:48:30
Add .Times(1)? It might be implicit, but it's used
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Done.
| |
| 214 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 170 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); |
| 215 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 171 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 216 g_high_detail_args); | 172 g_high_detail_args); |
| 217 TraceLog::GetInstance()->SetDisabled(); | 173 TraceLog::GetInstance()->SetDisabled(); |
| 218 } | 174 } |
| 219 | 175 |
| 176 // Checks that requesting dumps with high level of detail actually propagates | |
| 177 // the level of the detail properly to OnMemoryDump() call on dump providers. | |
| 220 TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgs) { | 178 TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgs) { |
| 221 // Check that requesting dumps with high level of detail actually propagates | 179 MockDumpProvider mdp; |
| 222 // to OnMemoryDump() call on dump providers. | |
| 223 MockDumpProvider mdp_high_detail(MemoryDumpArgs::LevelOfDetail::HIGH); | |
| 224 mdm_->RegisterDumpProvider(&mdp_high_detail); | |
| 225 | 180 |
| 181 mdm_->RegisterDumpProvider(&mdp); | |
| 226 EnableTracing(MemoryDumpManager::kTraceCategory); | 182 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 227 EXPECT_CALL(mdp_high_detail, OnMemoryDump(_, _)) | 183 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); |
|
petrcermak
2015/09/09 11:48:29
Add .Times or .WillOnce? (applies to all "EXPECT_C
Primiano Tucci (use gerrit)
2015/09/09 13:28:43
Done everywhere
| |
| 228 .Times(1) | 184 EXPECT_CALL(mdp, OnMemoryDump(IsHighDetail(), _)).WillOnce(Return(true)); |
| 229 .WillRepeatedly( | |
| 230 Invoke(&mdp_high_detail, | |
| 231 &MockDumpProvider::OnMemoryDump_CheckMemoryDumpArgs)); | |
| 232 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 185 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 233 g_high_detail_args); | 186 g_high_detail_args); |
| 234 DisableTracing(); | 187 DisableTracing(); |
| 235 mdm_->UnregisterDumpProvider(&mdp_high_detail); | 188 mdm_->UnregisterDumpProvider(&mdp); |
| 236 | 189 |
| 237 // Check that requesting dumps with low level of detail actually propagates to | 190 // Check that requesting dumps with low level of detail actually propagates to |
| 238 // OnMemoryDump() call on dump providers. | 191 // OnMemoryDump() call on dump providers. |
| 239 MockDumpProvider mdp_low_detail(MemoryDumpArgs::LevelOfDetail::LOW); | 192 mdm_->RegisterDumpProvider(&mdp); |
| 240 mdm_->RegisterDumpProvider(&mdp_low_detail); | |
| 241 | |
| 242 EnableTracing(MemoryDumpManager::kTraceCategory); | 193 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 243 EXPECT_CALL(mdp_low_detail, OnMemoryDump(_, _)) | 194 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); |
| 244 .Times(1) | 195 EXPECT_CALL(mdp, OnMemoryDump(IsLowDetail(), _)).WillOnce(Return(true)); |
| 245 .WillRepeatedly( | |
| 246 Invoke(&mdp_low_detail, | |
| 247 &MockDumpProvider::OnMemoryDump_CheckMemoryDumpArgs)); | |
| 248 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 196 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 249 g_low_detail_args); | 197 g_low_detail_args); |
| 250 DisableTracing(); | 198 DisableTracing(); |
| 251 mdm_->UnregisterDumpProvider(&mdp_low_detail); | 199 mdm_->UnregisterDumpProvider(&mdp); |
| 252 } | 200 } |
| 253 | 201 |
| 202 // Checks that the SharedSessionState object is acqually shared over time. | |
| 254 TEST_F(MemoryDumpManagerTest, SharedSessionState) { | 203 TEST_F(MemoryDumpManagerTest, SharedSessionState) { |
| 255 MockDumpProvider mdp1; | 204 MockDumpProvider mdp1; |
| 256 MockDumpProvider mdp2; | 205 MockDumpProvider mdp2; |
| 257 mdm_->RegisterDumpProvider(&mdp1); | 206 mdm_->RegisterDumpProvider(&mdp1); |
| 258 mdm_->RegisterDumpProvider(&mdp2); | 207 mdm_->RegisterDumpProvider(&mdp2); |
| 259 | 208 |
| 260 EnableTracing(MemoryDumpManager::kTraceCategory); | 209 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 210 const MemoryDumpSessionState* session_state = mdm_->session_state().get(); | |
| 211 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(2); | |
| 261 EXPECT_CALL(mdp1, OnMemoryDump(_, _)) | 212 EXPECT_CALL(mdp1, OnMemoryDump(_, _)) |
| 262 .Times(2) | 213 .Times(2) |
| 263 .WillRepeatedly( | 214 .WillRepeatedly(Invoke([session_state](const MemoryDumpArgs&, |
| 264 Invoke(&mdp1, &MockDumpProvider::OnMemoryDump_CheckSessionState)); | 215 ProcessMemoryDump* pmd) -> bool { |
| 216 EXPECT_EQ(session_state, pmd->session_state().get()); | |
| 217 return true; | |
| 218 })); | |
| 265 EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 219 EXPECT_CALL(mdp2, OnMemoryDump(_, _)) |
| 266 .Times(2) | 220 .Times(2) |
| 267 .WillRepeatedly( | 221 .WillRepeatedly(Invoke([session_state](const MemoryDumpArgs&, |
| 268 Invoke(&mdp2, &MockDumpProvider::OnMemoryDump_CheckSessionState)); | 222 ProcessMemoryDump* pmd) -> bool { |
| 223 EXPECT_EQ(session_state, pmd->session_state().get()); | |
| 224 return true; | |
| 225 })); | |
| 269 | 226 |
| 270 for (int i = 0; i < 2; ++i) | 227 for (int i = 0; i < 2; ++i) |
| 271 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 228 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 272 g_high_detail_args); | 229 g_high_detail_args); |
| 273 | 230 |
| 274 DisableTracing(); | 231 DisableTracing(); |
| 275 } | 232 } |
| 276 | 233 |
| 234 // Checks that the (Un)RegisterDumpProvider logic behaves sanely. | |
| 277 TEST_F(MemoryDumpManagerTest, MultipleDumpers) { | 235 TEST_F(MemoryDumpManagerTest, MultipleDumpers) { |
| 278 MockDumpProvider mdp1; | 236 MockDumpProvider mdp1; |
| 279 MockDumpProvider mdp2; | 237 MockDumpProvider mdp2; |
| 280 | 238 |
| 281 // Enable only mdp1. | 239 // Enable only mdp1. |
| 282 mdm_->RegisterDumpProvider(&mdp1); | 240 mdm_->RegisterDumpProvider(&mdp1); |
| 283 EnableTracing(MemoryDumpManager::kTraceCategory); | 241 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 284 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 242 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); |
| 243 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).WillOnce(Return(true)); | |
| 285 EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(0); | 244 EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(0); |
| 286 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 245 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 287 g_high_detail_args); | 246 g_high_detail_args); |
| 288 DisableTracing(); | 247 DisableTracing(); |
| 289 | 248 |
| 290 // Invert: enable mdp1 and disable mdp2. | 249 // Invert: enable mdp1 and disable mdp2. |
| 291 mdm_->UnregisterDumpProvider(&mdp1); | 250 mdm_->UnregisterDumpProvider(&mdp1); |
| 292 mdm_->RegisterDumpProvider(&mdp2); | 251 mdm_->RegisterDumpProvider(&mdp2); |
| 293 EnableTracing(MemoryDumpManager::kTraceCategory); | 252 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 253 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); | |
| 294 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); | 254 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); |
| 295 EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 255 EXPECT_CALL(mdp2, OnMemoryDump(_, _)).WillOnce(Return(true)); |
| 296 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 256 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 297 g_high_detail_args); | 257 g_high_detail_args); |
| 298 DisableTracing(); | 258 DisableTracing(); |
| 299 | 259 |
| 300 // Enable both mdp1 and mdp2. | 260 // Enable both mdp1 and mdp2. |
| 301 mdm_->RegisterDumpProvider(&mdp1); | 261 mdm_->RegisterDumpProvider(&mdp1); |
| 302 EnableTracing(MemoryDumpManager::kTraceCategory); | 262 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 303 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 263 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); |
| 304 EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 264 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).WillOnce(Return(true)); |
| 265 EXPECT_CALL(mdp2, OnMemoryDump(_, _)).WillOnce(Return(true)); | |
| 305 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 266 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 306 g_high_detail_args); | 267 g_high_detail_args); |
| 307 DisableTracing(); | 268 DisableTracing(); |
| 308 } | 269 } |
| 309 | 270 |
| 310 // Verify that whether OnMemoryDump is called depends only on the current | 271 // Checks that the dump provider invocations depend only on the current |
| 311 // registration state and not on previous registrations and dumps. | 272 // registration state and not on previous registrations and dumps. |
| 312 TEST_F(MemoryDumpManagerTest, RegistrationConsistency) { | 273 TEST_F(MemoryDumpManagerTest, RegistrationConsistency) { |
| 313 MockDumpProvider mdp; | 274 MockDumpProvider mdp; |
| 314 | 275 |
| 315 mdm_->RegisterDumpProvider(&mdp); | 276 mdm_->RegisterDumpProvider(&mdp); |
| 316 | 277 |
| 317 { | 278 { |
| 318 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(1); | 279 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); |
| 280 EXPECT_CALL(mdp, OnMemoryDump(_, _)).WillOnce(Return(true)); | |
| 319 EnableTracing(MemoryDumpManager::kTraceCategory); | 281 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 320 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 282 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 321 g_high_detail_args); | 283 g_high_detail_args); |
| 322 DisableTracing(); | 284 DisableTracing(); |
| 323 } | 285 } |
| 324 | 286 |
| 325 mdm_->UnregisterDumpProvider(&mdp); | 287 mdm_->UnregisterDumpProvider(&mdp); |
| 326 | 288 |
| 327 { | 289 { |
| 290 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); | |
| 328 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 291 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); |
| 329 EnableTracing(MemoryDumpManager::kTraceCategory); | 292 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 330 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 293 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 331 g_high_detail_args); | 294 g_high_detail_args); |
| 332 DisableTracing(); | 295 DisableTracing(); |
| 333 } | 296 } |
| 334 | 297 |
| 335 mdm_->RegisterDumpProvider(&mdp); | 298 mdm_->RegisterDumpProvider(&mdp); |
| 336 mdm_->UnregisterDumpProvider(&mdp); | 299 mdm_->UnregisterDumpProvider(&mdp); |
| 337 | 300 |
| 338 { | 301 { |
| 302 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); | |
| 339 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 303 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); |
| 340 EnableTracing(MemoryDumpManager::kTraceCategory); | 304 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 341 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 305 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 342 g_high_detail_args); | 306 g_high_detail_args); |
| 343 DisableTracing(); | 307 DisableTracing(); |
| 344 } | 308 } |
| 345 | 309 |
| 346 mdm_->RegisterDumpProvider(&mdp); | 310 mdm_->RegisterDumpProvider(&mdp); |
| 347 mdm_->UnregisterDumpProvider(&mdp); | 311 mdm_->UnregisterDumpProvider(&mdp); |
| 348 mdm_->RegisterDumpProvider(&mdp); | 312 mdm_->RegisterDumpProvider(&mdp); |
| 349 | 313 |
| 350 { | 314 { |
| 351 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(1); | 315 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); |
| 316 EXPECT_CALL(mdp, OnMemoryDump(_, _)).WillOnce(Return(true)); | |
| 352 EnableTracing(MemoryDumpManager::kTraceCategory); | 317 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 353 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 318 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 354 g_high_detail_args); | 319 g_high_detail_args); |
| 355 DisableTracing(); | 320 DisableTracing(); |
| 356 } | 321 } |
| 357 } | 322 } |
| 358 | 323 |
| 359 // Checks that the MemoryDumpManager respects the thread affinity when a | 324 // Checks that the MemoryDumpManager respects the thread affinity when a |
| 360 // MemoryDumpProvider specifies a task_runner(). The test starts creating 8 | 325 // MemoryDumpProvider specifies a task_runner(). The test starts creating 8 |
| 361 // threads and registering a MemoryDumpProvider on each of them. At each | 326 // threads and registering a MemoryDumpProvider on each of them. At each |
| 362 // iteration, one thread is removed, to check the live unregistration logic. | 327 // iteration, one thread is removed, to check the live unregistration logic. |
| 363 TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) { | 328 TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) { |
| 364 const uint32 kNumInitialThreads = 8; | 329 const uint32 kNumInitialThreads = 8; |
| 365 | 330 |
| 366 ScopedVector<Thread> threads; | 331 ScopedVector<Thread> threads; |
| 367 ScopedVector<MockDumpProvider> mdps; | 332 ScopedVector<MockDumpProvider> mdps; |
| 368 | 333 |
| 369 // Create the threads and setup the expectations. Given that at each iteration | 334 // Create the threads and setup the expectations. Given that at each iteration |
| 370 // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be | 335 // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be |
| 371 // invoked a number of times equal to its index. | 336 // invoked a number of times equal to its index. |
| 372 for (uint32 i = kNumInitialThreads; i > 0; --i) { | 337 for (uint32 i = kNumInitialThreads; i > 0; --i) { |
| 373 threads.push_back(new Thread("test thread")); | 338 threads.push_back(new Thread("test thread")); |
|
petrcermak
2015/09/09 11:48:30
Wouldn't it be nicer to define the thread and then
Primiano Tucci (use gerrit)
2015/09/09 13:28:43
Done.
| |
| 374 threads.back()->Start(); | 339 threads.back()->Start(); |
| 375 mdps.push_back(new MockDumpProvider(threads.back()->task_runner())); | 340 scoped_refptr<SingleThreadTaskRunner> task_runner = |
| 341 threads.back()->task_runner(); | |
| 342 mdps.push_back(new MockDumpProvider()); | |
| 376 MockDumpProvider* mdp = mdps.back(); | 343 MockDumpProvider* mdp = mdps.back(); |
| 377 mdm_->RegisterDumpProvider(mdp, threads.back()->task_runner()); | 344 mdm_->RegisterDumpProvider(mdp, task_runner); |
| 378 EXPECT_CALL(*mdp, OnMemoryDump(_, _)) | 345 EXPECT_CALL(*mdp, OnMemoryDump(_, _)) |
| 379 .Times(i) | 346 .Times(i) |
| 380 .WillRepeatedly( | 347 .WillRepeatedly(Invoke( |
| 381 Invoke(mdp, &MockDumpProvider::OnMemoryDump_CheckTaskRunner)); | 348 [task_runner](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool { |
| 349 EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread()); | |
| 350 return true; | |
| 351 })); | |
| 382 } | 352 } |
| 383 | 353 |
| 384 EnableTracing(MemoryDumpManager::kTraceCategory); | 354 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 385 | 355 |
| 386 while (!threads.empty()) { | 356 while (!threads.empty()) { |
| 387 last_callback_success_ = false; | 357 last_callback_success_ = false; |
| 388 { | 358 { |
| 389 RunLoop run_loop; | 359 RunLoop run_loop; |
| 390 MemoryDumpCallback callback = | 360 MemoryDumpCallback callback = |
| 391 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 361 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), |
| 392 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 362 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); |
| 363 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)); | |
| 393 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 364 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 394 g_high_detail_args, callback); | 365 g_high_detail_args, callback); |
| 395 // This nested message loop (|run_loop|) will be quit if and only if | 366 // This nested message loop (|run_loop|) will quit if and only if the |
| 396 // the RequestGlobalDump callback is invoked. | 367 // |callback| passed to RequestGlobalDump() is invoked. |
| 397 run_loop.Run(); | 368 run_loop.Run(); |
| 398 } | 369 } |
| 399 EXPECT_TRUE(last_callback_success_); | 370 EXPECT_TRUE(last_callback_success_); |
| 400 | 371 |
| 401 // Unregister a MDP and destroy one thread at each iteration to check the | 372 // Unregister a MDP and destroy one thread at each iteration to check the |
| 402 // live unregistration logic. The unregistration needs to happen on the same | 373 // live unregistration logic. The unregistration needs to happen on the same |
| 403 // thread the MDP belongs to. | 374 // thread the MDP belongs to. |
| 404 { | 375 { |
| 405 RunLoop run_loop; | 376 RunLoop run_loop; |
| 406 Closure unregistration = | 377 Closure unregistration = |
| 407 Bind(&MemoryDumpManager::UnregisterDumpProvider, | 378 Bind(&MemoryDumpManager::UnregisterDumpProvider, |
| 408 Unretained(mdm_.get()), Unretained(mdps.back())); | 379 Unretained(mdm_.get()), Unretained(mdps.back())); |
| 409 threads.back()->task_runner()->PostTaskAndReply(FROM_HERE, unregistration, | 380 threads.back()->task_runner()->PostTaskAndReply(FROM_HERE, unregistration, |
| 410 run_loop.QuitClosure()); | 381 run_loop.QuitClosure()); |
| 411 run_loop.Run(); | 382 run_loop.Run(); |
| 412 } | 383 } |
| 413 mdps.pop_back(); | 384 mdps.pop_back(); |
| 414 threads.back()->Stop(); | 385 threads.back()->Stop(); |
| 415 threads.pop_back(); | 386 threads.pop_back(); |
| 416 } | 387 } |
| 417 | 388 |
| 418 DisableTracing(); | 389 DisableTracing(); |
| 419 } | 390 } |
| 420 | 391 |
| 421 // Enable both dump providers, make sure that mdp gets disabled after 3 failures | 392 // Checks that providers get disabled after 3 failures, but not after just 1. |
| 422 // and not disabled after 1. | |
| 423 TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) { | 393 TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) { |
|
petrcermak
2015/09/09 11:48:29
Just a thought here: What's the expected behavior
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Done.
| |
| 424 MockDumpProvider mdp1; | 394 MockDumpProvider mdp1; |
| 425 MockDumpProvider mdp2; | 395 MockDumpProvider mdp2; |
| 426 | 396 |
| 427 mdm_->RegisterDumpProvider(&mdp1); | 397 mdm_->RegisterDumpProvider(&mdp1); |
| 428 mdm_->RegisterDumpProvider(&mdp2); | 398 mdm_->RegisterDumpProvider(&mdp2); |
| 429 EnableTracing(MemoryDumpManager::kTraceCategory); | 399 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 430 | 400 |
| 401 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)) | |
| 402 .Times(1 + MemoryDumpManager::kMaxConsecutiveFailuresCount); | |
| 403 | |
| 431 EXPECT_CALL(mdp1, OnMemoryDump(_, _)) | 404 EXPECT_CALL(mdp1, OnMemoryDump(_, _)) |
| 432 .Times(MemoryDumpManager::kMaxConsecutiveFailuresCount) | 405 .Times(MemoryDumpManager::kMaxConsecutiveFailuresCount) |
| 433 .WillRepeatedly(Return(false)); | 406 .WillRepeatedly(Return(false)); |
| 434 | 407 |
| 435 EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 408 EXPECT_CALL(mdp2, OnMemoryDump(_, _)) |
| 436 .Times(1 + MemoryDumpManager::kMaxConsecutiveFailuresCount) | 409 .Times(1 + MemoryDumpManager::kMaxConsecutiveFailuresCount) |
| 437 .WillOnce(Return(false)) | 410 .WillOnce(Return(false)) |
| 438 .WillRepeatedly(Return(true)); | 411 .WillRepeatedly(Return(true)); |
| 412 | |
| 439 for (int i = 0; i < 1 + MemoryDumpManager::kMaxConsecutiveFailuresCount; | 413 for (int i = 0; i < 1 + MemoryDumpManager::kMaxConsecutiveFailuresCount; |
| 440 i++) { | 414 i++) { |
| 441 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 415 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 442 g_high_detail_args); | 416 g_high_detail_args); |
| 443 } | 417 } |
| 444 | 418 |
| 445 DisableTracing(); | 419 DisableTracing(); |
| 446 } | 420 } |
| 447 | 421 |
| 448 // Sneakily register an extra memory dump provider while an existing one is | 422 // Sneakily registers an extra memory dump provider while an existing one is |
| 449 // dumping and expect it to take part in the already active tracing session. | 423 // dumping and expect it to take part in the already active tracing session. |
| 450 TEST_F(MemoryDumpManagerTest, RegisterDumperWhileDumping) { | 424 TEST_F(MemoryDumpManagerTest, RegisterDumperWhileDumping) { |
| 451 MockDumpProvider mdp1; | 425 MockDumpProvider mdp1; |
| 452 MockDumpProvider mdp2; | 426 MockDumpProvider mdp2; |
| 453 | 427 |
| 454 mdp1.dump_provider_to_register_or_unregister = &mdp2; | |
| 455 mdm_->RegisterDumpProvider(&mdp1); | 428 mdm_->RegisterDumpProvider(&mdp1); |
| 456 EnableTracing(MemoryDumpManager::kTraceCategory); | 429 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 457 | 430 |
| 431 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(4); | |
| 432 | |
| 458 EXPECT_CALL(mdp1, OnMemoryDump(_, _)) | 433 EXPECT_CALL(mdp1, OnMemoryDump(_, _)) |
| 459 .Times(4) | 434 .Times(4) |
| 460 .WillOnce(Return(true)) | 435 .WillOnce(Return(true)) |
| 461 .WillOnce(Invoke( | 436 .WillOnce( |
| 462 &mdp1, &MockDumpProvider::OnMemoryDump_RegisterExtraDumpProvider)) | 437 Invoke([&mdp2](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool { |
| 438 MemoryDumpManager::GetInstance()->RegisterDumpProvider(&mdp2); | |
| 439 return true; | |
| 440 })) | |
| 463 .WillRepeatedly(Return(true)); | 441 .WillRepeatedly(Return(true)); |
| 464 | 442 |
| 465 // Depending on the insertion order (before or after mdp1), mdp2 might be | 443 // Depending on the insertion order (before or after mdp1), mdp2 might be |
| 466 // called also immediately after it gets registered. | 444 // called also immediately after it gets registered. |
| 467 EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 445 EXPECT_CALL(mdp2, OnMemoryDump(_, _)) |
| 468 .Times(Between(2, 3)) | 446 .Times(Between(2, 3)) |
| 469 .WillRepeatedly(Return(true)); | 447 .WillRepeatedly(Return(true)); |
| 470 | 448 |
| 471 for (int i = 0; i < 4; i++) { | 449 for (int i = 0; i < 4; i++) { |
| 472 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 450 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 473 g_high_detail_args); | 451 g_high_detail_args); |
| 474 } | 452 } |
| 475 | 453 |
| 476 DisableTracing(); | 454 DisableTracing(); |
| 477 } | 455 } |
| 478 | 456 |
| 479 // Like the above, but suddenly unregister the dump provider. | 457 // Like RegisterDumperWhileDumping, but suddenly unregister the dump provider. |
|
petrcermak
2015/09/09 11:48:30
super-nit: Maybe add "instead" to the description:
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Done.
| |
| 480 TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileDumping) { | 458 TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileDumping) { |
| 481 MockDumpProvider mdp1; | 459 MockDumpProvider mdp1; |
| 482 MockDumpProvider mdp2; | 460 MockDumpProvider mdp2; |
| 483 | 461 |
| 484 mdm_->RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get()); | 462 mdm_->RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get()); |
| 485 mdm_->RegisterDumpProvider(&mdp2, ThreadTaskRunnerHandle::Get()); | 463 mdm_->RegisterDumpProvider(&mdp2, ThreadTaskRunnerHandle::Get()); |
| 486 mdp1.dump_provider_to_register_or_unregister = &mdp2; | |
| 487 EnableTracing(MemoryDumpManager::kTraceCategory); | 464 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 488 | 465 |
| 466 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(4); | |
| 467 | |
| 489 EXPECT_CALL(mdp1, OnMemoryDump(_, _)) | 468 EXPECT_CALL(mdp1, OnMemoryDump(_, _)) |
| 490 .Times(4) | 469 .Times(4) |
| 491 .WillOnce(Return(true)) | 470 .WillOnce(Return(true)) |
| 492 .WillOnce( | 471 .WillOnce( |
| 493 Invoke(&mdp1, &MockDumpProvider::OnMemoryDump_UnregisterDumpProvider)) | 472 Invoke([&mdp2](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool { |
| 473 MemoryDumpManager::GetInstance()->UnregisterDumpProvider(&mdp2); | |
| 474 return true; | |
| 475 })) | |
| 494 .WillRepeatedly(Return(true)); | 476 .WillRepeatedly(Return(true)); |
| 495 | 477 |
| 496 // Depending on the insertion order (before or after mdp1), mdp2 might have | 478 // Depending on the insertion order (before or after mdp1), mdp2 might have |
| 497 // been already called when OnMemoryDump_UnregisterDumpProvider happens. | 479 // been already called when UnregisterDumpProvider happens. |
| 498 EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 480 EXPECT_CALL(mdp2, OnMemoryDump(_, _)) |
| 499 .Times(Between(1, 2)) | 481 .Times(Between(1, 2)) |
| 500 .WillRepeatedly(Return(true)); | 482 .WillRepeatedly(Return(true)); |
| 501 | 483 |
| 502 for (int i = 0; i < 4; i++) { | 484 for (int i = 0; i < 4; i++) { |
| 503 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 485 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 504 g_high_detail_args); | 486 g_high_detail_args); |
| 505 } | 487 } |
| 506 | 488 |
| 507 DisableTracing(); | 489 DisableTracing(); |
| 508 } | 490 } |
| 509 | 491 |
| 510 // Verify that the dump does not abort when unregistering a provider while | 492 // Checks that the dump does not abort when unregistering a provider while |
| 511 // dumping from a different thread than the dumping thread. | 493 // dumping from a different thread than the dumping thread. |
| 512 TEST_F(MemoryDumpManagerTest, UnregisterDumperFromThreadWhileDumping) { | 494 TEST_F(MemoryDumpManagerTest, UnregisterDumperFromThreadWhileDumping) { |
| 513 ScopedVector<TestIOThread> threads; | 495 ScopedVector<TestIOThread> threads; |
| 514 ScopedVector<MockDumpProvider> mdps; | 496 ScopedVector<MockDumpProvider> mdps; |
| 515 | 497 |
| 516 for (int i = 0; i < 2; i++) { | 498 for (int i = 0; i < 2; i++) { |
| 517 threads.push_back(new TestIOThread(TestIOThread::kAutoStart)); | 499 threads.push_back(new TestIOThread(TestIOThread::kAutoStart)); |
|
petrcermak
2015/09/09 11:48:29
Same comment as above:
auto thread = new TestIOTh
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Nah this would add extra lines. IMHO this one is l
| |
| 518 mdps.push_back(new MockDumpProvider(threads.back()->task_runner())); | 500 mdps.push_back(new MockDumpProvider()); |
| 519 mdm_->RegisterDumpProvider(mdps.back(), threads.back()->task_runner()); | 501 mdm_->RegisterDumpProvider(mdps.back(), threads.back()->task_runner()); |
| 520 } | 502 } |
| 521 | 503 |
| 522 int on_memory_dump_call_count = 0; | 504 int on_memory_dump_call_count = 0; |
| 523 RunLoop run_loop; | 505 RunLoop run_loop; |
| 524 | 506 |
| 525 // When OnMemoryDump is called on either of the dump providers, it will | 507 // When OnMemoryDump is called on either of the dump providers, it will |
| 526 // unregister the other one. | 508 // unregister the other one. |
| 527 for (MockDumpProvider* mdp : mdps) { | 509 for (MockDumpProvider* mdp : mdps) { |
| 528 int other_idx = (mdps.front() == mdp); | 510 int other_idx = (mdps.front() == mdp); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 555 mdm_->CreateProcessDump(request_args, callback); | 537 mdm_->CreateProcessDump(request_args, callback); |
| 556 | 538 |
| 557 run_loop.Run(); | 539 run_loop.Run(); |
| 558 | 540 |
| 559 ASSERT_EQ(1, on_memory_dump_call_count); | 541 ASSERT_EQ(1, on_memory_dump_call_count); |
| 560 ASSERT_EQ(true, last_callback_success_); | 542 ASSERT_EQ(true, last_callback_success_); |
| 561 | 543 |
| 562 DisableTracing(); | 544 DisableTracing(); |
| 563 } | 545 } |
| 564 | 546 |
| 565 // Ensures that a NACK callback is invoked if RequestGlobalDump is called when | 547 // Checks that a NACK callback is invoked if RequestGlobalDump() is called when |
| 566 // tracing is not enabled. | 548 // tracing is not enabled. |
| 567 TEST_F(MemoryDumpManagerTest, CallbackCalledOnFailure) { | 549 TEST_F(MemoryDumpManagerTest, CallbackCalledOnFailure) { |
| 568 MockDumpProvider mdp1; | 550 MockDumpProvider mdp1; |
| 551 mdm_->RegisterDumpProvider(&mdp1); | |
| 569 | 552 |
| 570 mdm_->RegisterDumpProvider(&mdp1); | 553 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(0); |
| 571 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); | 554 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); |
| 572 | 555 |
| 573 last_callback_success_ = true; | 556 last_callback_success_ = true; |
| 574 { | 557 { |
| 575 RunLoop run_loop; | 558 RunLoop run_loop; |
| 576 MemoryDumpCallback callback = | 559 MemoryDumpCallback callback = |
| 577 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 560 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), |
| 578 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 561 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); |
| 579 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 562 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 580 g_high_detail_args, callback); | 563 g_high_detail_args, callback); |
| 581 run_loop.Run(); | 564 run_loop.Run(); |
| 582 } | 565 } |
| 583 EXPECT_FALSE(last_callback_success_); | 566 EXPECT_FALSE(last_callback_success_); |
| 584 } | 567 } |
| 585 | 568 |
| 586 MATCHER(IsHighDetail, "") { | 569 // This test crystallizes the expectations of the chrome://tracing UI and |
| 587 return arg.dump_args.level_of_detail == MemoryDumpArgs::LevelOfDetail::HIGH; | 570 // chrome telemetry w.r.t. periodic dumps in memory-infra, handling gracefully |
| 588 } | 571 // the transition between the legacy and the new-style (JSON-based) TraceConfig. |
| 572 TEST_F(MemoryDumpManagerTest, TraceConfigExpectations) { | |
| 573 MemoryDumpManagerDelegateForTesting& delegate = *delegate_; | |
| 589 | 574 |
| 590 MATCHER(IsLowDetail, "") { | 575 // Don't trigger the default behavior of the mock delegate in this test, |
| 591 return arg.dump_args.level_of_detail == MemoryDumpArgs::LevelOfDetail::LOW; | 576 // which would short-circuit the dump request to the actual |
| 592 } | 577 // CreateProcessDump(). |
| 578 // We don't want to create any dump in this test, only check whether the dumps | |
| 579 // are requested or not. | |
| 580 ON_CALL(delegate, RequestGlobalMemoryDump(_, _)).WillByDefault(Return()); | |
| 593 | 581 |
| 594 TEST_F(MemoryDumpManagerTest, SchedulePeriodicDumpsFromTraceConfig) { | 582 // Enabling memory-infra in a non-coordinator process should not trigger any |
| 595 const char kMemoryDumpTraceConfigString[] = | 583 // periodic dumps. |
| 596 "{" | 584 EXPECT_CALL(delegate, IsCoordinatorProcess()).WillRepeatedly(Return(false)); |
| 597 "\"included_categories\":[" | 585 EnableTracing(MemoryDumpManager::kTraceCategory); |
| 598 "\"disabled-by-default-memory-infra\"" | 586 EXPECT_FALSE(IsPeriodicDumpingEnabled()); |
| 599 "]," | 587 DisableTracing(); |
| 600 "\"memory_dump_config\":{" | 588 |
| 589 // Enabling memory-infra with the legacy TraceConfig (category filter) in | |
| 590 // a coordinator process should enable periodic dumps. | |
| 591 EXPECT_CALL(delegate, IsCoordinatorProcess()).WillRepeatedly(Return(true)); | |
| 592 EnableTracing(MemoryDumpManager::kTraceCategory); | |
| 593 EXPECT_TRUE(IsPeriodicDumpingEnabled()); | |
| 594 DisableTracing(); | |
| 595 | |
| 596 // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator | |
| 597 // process without specifying any "memory_dump_config" section should enable | |
| 598 // periodic dumps. This is to preserve the behavior chrome://tracing UI, that | |
| 599 // is: ticking memory-infra should dump periodically with the default config. | |
| 600 EXPECT_CALL(delegate, IsCoordinatorProcess()).WillRepeatedly(Return(true)); | |
| 601 const std::string kTraceConfigWithNoMemorDumpConfig = StringPrintf( | |
| 602 "{\"included_categories\":[\"%s\"]}", MemoryDumpManager::kTraceCategory); | |
|
petrcermak
2015/09/09 11:48:30
It might be better to keep the JSON strings as con
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Discussed offline. It is the case right now.
| |
| 603 EnableTracingWithTraceConfig(kTraceConfigWithNoMemorDumpConfig.c_str()); | |
| 604 EXPECT_TRUE(IsPeriodicDumpingEnabled()); | |
| 605 DisableTracing(); | |
| 606 | |
| 607 // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator | |
| 608 // process with an empty "memory_dump_config" should NOT enable periodic | |
| 609 // dumps. This is the way telemetry is supposed to use memory-infra with | |
| 610 // only explicitly triggered dumps. | |
| 611 EXPECT_CALL(delegate, IsCoordinatorProcess()).WillRepeatedly(Return(true)); | |
| 612 const std::string kTraceConfigWithNoTriggers = StringPrintf( | |
| 613 "{\"included_categories\":[\"%s\"], \"memory_dump_config\":{}", | |
| 614 MemoryDumpManager::kTraceCategory); | |
| 615 EnableTracingWithTraceConfig(kTraceConfigWithNoTriggers.c_str()); | |
| 616 EXPECT_FALSE(IsPeriodicDumpingEnabled()); | |
| 617 DisableTracing(); | |
| 618 | |
| 619 // Enabling memory-infra with the new (JSON) TraceConfig in a non-coordinator | |
| 620 // process with a fully defined trigger config should NOT enable any periodic | |
| 621 // dumps. | |
| 622 EXPECT_CALL(delegate, IsCoordinatorProcess()).WillRepeatedly(Return(false)); | |
| 623 const std::string kTraceConfigWithTriggers = StringPrintf( | |
| 624 "{\"included_categories\":[\"%s\"]," | |
| 625 "\"memory_dump_config\":{" | |
| 601 "\"triggers\":[" | 626 "\"triggers\":[" |
| 602 "{" | 627 "{\"mode\":\"light\", \"periodic_interval_ms\":1}," |
| 603 "\"mode\":\"light\"," | 628 "{\"mode\":\"detailed\", \"periodic_interval_ms\":5}" |
| 604 "\"periodic_interval_ms\":1" | |
| 605 "}," | |
| 606 "{" | |
| 607 "\"mode\":\"detailed\"," | |
| 608 "\"periodic_interval_ms\":3" | |
| 609 "}" | |
| 610 "]" | 629 "]" |
| 611 "}" | 630 "}" |
| 612 "}"; | 631 "}", MemoryDumpManager::kTraceCategory); |
| 632 EnableTracingWithTraceConfig(kTraceConfigWithTriggers.c_str()); | |
| 633 EXPECT_FALSE(IsPeriodicDumpingEnabled()); | |
| 634 DisableTracing(); | |
| 635 | |
| 636 // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator | |
| 637 // process with a fully defined trigger config should cause periodic dumps to | |
| 638 // be performed in the right sequence. | |
|
petrcermak
2015/09/09 11:48:30
nit: "correct order" sounds more English to me tha
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Done.
| |
| 639 EXPECT_CALL(delegate, IsCoordinatorProcess()).WillRepeatedly(Return(true)); | |
| 613 | 640 |
| 614 RunLoop run_loop; | 641 RunLoop run_loop; |
| 615 scoped_ptr<MemoryDumpManagerDelegateForPeriodicDumpTest> delegate( | 642 auto quit_closure = run_loop.QuitClosure(); |
| 616 new MemoryDumpManagerDelegateForPeriodicDumpTest()); | |
| 617 | 643 |
| 618 auto quit_closure = run_loop.QuitClosure(); | 644 // The expected sequence with config of light=1ms, heavy=5ms is H,L,L,L,H,... |
| 619 testing::InSequence sequence; | 645 testing::InSequence sequence; |
|
petrcermak
2015/09/09 11:48:29
It might be a good idea to nest lines 645-654 in a
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
I'm going to move these lines in the next CL.
| |
| 620 EXPECT_CALL(*delegate.get(), RequestGlobalMemoryDump(IsHighDetail(), _)) | 646 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsHighDetailArgs(), _)); |
| 621 .Times(1); | 647 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLowDetailArgs(), _)).Times(3); |
| 622 EXPECT_CALL(*delegate.get(), RequestGlobalMemoryDump(IsLowDetail(), _)) | 648 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsHighDetailArgs(), _)); |
| 623 .Times(2); | 649 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLowDetailArgs(), _)).Times(2); |
| 624 EXPECT_CALL(*delegate.get(), RequestGlobalMemoryDump(IsHighDetail(), _)) | 650 EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLowDetailArgs(), _)) |
| 625 .Times(1); | |
| 626 EXPECT_CALL(*delegate.get(), RequestGlobalMemoryDump(IsLowDetail(), _)) | |
| 627 .Times(1) | |
| 628 .WillOnce(Invoke([quit_closure](const MemoryDumpRequestArgs& args, | 651 .WillOnce(Invoke([quit_closure](const MemoryDumpRequestArgs& args, |
| 629 const MemoryDumpCallback& callback) { | 652 const MemoryDumpCallback& callback) { |
| 630 TraceLog::GetInstance()->SetDisabled(); | |
| 631 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure); | 653 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure); |
| 632 })); | 654 })); |
| 633 | 655 |
| 634 SetDelegate(delegate.Pass()); | 656 // Swallow all the final the spurious calls until tracing gets disabled. |
|
petrcermak
2015/09/09 11:48:29
nit: s/the final the/final/ (I don't think you nee
petrcermak
2015/09/09 11:48:30
nit: Don't you mean "can be disabled"?
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
Done.
Primiano Tucci (use gerrit)
2015/09/09 13:28:44
No. I mean that between the time we decide to disa
| |
| 635 EnableTracingWithTraceConfig(kMemoryDumpTraceConfigString); | 657 EXPECT_CALL(delegate, RequestGlobalMemoryDump(_, _)).Times(AnyNumber()); |
| 636 | 658 |
| 659 EnableTracingWithTraceConfig(kTraceConfigWithTriggers.c_str()); | |
| 637 run_loop.Run(); | 660 run_loop.Run(); |
| 661 DisableTracing(); | |
| 638 } | 662 } |
| 639 | 663 |
| 640 } // namespace trace_event | 664 } // namespace trace_event |
| 641 } // namespace base | 665 } // namespace base |
| OLD | NEW |