| 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/test/test_io_thread.h" | 11 #include "base/test/test_io_thread.h" | 
| 12 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" | 
| 13 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" | 
| 14 #include "base/trace_event/memory_dump_provider.h" | 14 #include "base/trace_event/memory_dump_provider.h" | 
| 15 #include "base/trace_event/process_memory_dump.h" | 15 #include "base/trace_event/process_memory_dump.h" | 
| 16 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" | 
| 17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" | 
| 18 | 18 | 
| 19 using testing::_; | 19 using testing::_; | 
| 20 using testing::AtMost; | 20 using testing::AtMost; | 
| 21 using testing::Between; | 21 using testing::Between; | 
| 22 using testing::Invoke; | 22 using testing::Invoke; | 
| 23 using testing::Return; | 23 using testing::Return; | 
| 24 | 24 | 
| 25 namespace base { | 25 namespace base { | 
| 26 namespace trace_event { | 26 namespace trace_event { | 
| 27 namespace { | 27 namespace { | 
| 28 MemoryDumpArgs high_detail_args = {MemoryDumpArgs::LevelOfDetail::HIGH}; | 28 MemoryDumpArgs g_high_detail_args = {MemoryDumpArgs::LevelOfDetail::HIGH}; | 
| 29 MemoryDumpArgs low_detail_args = {MemoryDumpArgs::LevelOfDetail::LOW}; | 29 MemoryDumpArgs g_low_detail_args = {MemoryDumpArgs::LevelOfDetail::LOW}; | 
| 30 } | 30 } | 
| 31 | 31 | 
| 32 // Testing MemoryDumpManagerDelegate which short-circuits dump requests locally | 32 // Testing MemoryDumpManagerDelegate which short-circuits dump requests locally | 
| 33 // instead of performing IPC dances. | 33 // instead of performing IPC dances. | 
| 34 class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate { | 34 class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate { | 
| 35  public: | 35  public: | 
| 36   void RequestGlobalMemoryDump(const MemoryDumpRequestArgs& args, | 36   void RequestGlobalMemoryDump(const MemoryDumpRequestArgs& args, | 
| 37                                const MemoryDumpCallback& callback) override { | 37                                const MemoryDumpCallback& callback) override { | 
| 38     CreateProcessDump(args, callback); | 38     CreateProcessDump(args, callback); | 
| 39   } | 39   } | 
| 40 | 40 | 
| 41   bool IsCoordinatorProcess() const override { return false; } | 41   bool IsCoordinatorProcess() const override { return false; } | 
| 42   uint64 GetTracingProcessId() const override { | 42   uint64 GetTracingProcessId() const override { | 
| 43     return MemoryDumpManager::kInvalidTracingProcessId; | 43     return MemoryDumpManager::kInvalidTracingProcessId; | 
| 44   } | 44   } | 
| 45 }; | 45 }; | 
| 46 | 46 | 
|  | 47 class MemoryDumpManagerDelegateForPeriodicDumpTest | 
|  | 48     : public MemoryDumpManagerDelegateForTesting { | 
|  | 49  public: | 
|  | 50   MOCK_METHOD2(RequestGlobalMemoryDump, | 
|  | 51                void(const MemoryDumpRequestArgs& args, | 
|  | 52                     const MemoryDumpCallback& callback)); | 
|  | 53 | 
|  | 54   bool IsCoordinatorProcess() const override { return true; } | 
|  | 55 }; | 
|  | 56 | 
| 47 class MemoryDumpManagerTest : public testing::Test { | 57 class MemoryDumpManagerTest : public testing::Test { | 
| 48  public: | 58  public: | 
| 49   void SetUp() override { | 59   void SetUp() override { | 
| 50     last_callback_success_ = false; | 60     last_callback_success_ = false; | 
| 51     message_loop_.reset(new MessageLoop()); | 61     message_loop_.reset(new MessageLoop()); | 
| 52     mdm_.reset(new MemoryDumpManager()); | 62     mdm_.reset(new MemoryDumpManager()); | 
| 53     MemoryDumpManager::SetInstanceForTesting(mdm_.get()); | 63     MemoryDumpManager::SetInstanceForTesting(mdm_.get()); | 
| 54     ASSERT_EQ(mdm_, MemoryDumpManager::GetInstance()); | 64     ASSERT_EQ(mdm_, MemoryDumpManager::GetInstance()); | 
| 55     MemoryDumpManager::GetInstance()->Initialize(); | 65     MemoryDumpManager::GetInstance()->Initialize(); | 
| 56     MemoryDumpManager::GetInstance()->SetDelegate(&delegate_); |  | 
| 57   } | 66   } | 
| 58 | 67 | 
| 59   void TearDown() override { | 68   void TearDown() override { | 
| 60     MemoryDumpManager::SetInstanceForTesting(nullptr); | 69     MemoryDumpManager::SetInstanceForTesting(nullptr); | 
| 61     mdm_.reset(); | 70     mdm_.reset(); | 
| 62     message_loop_.reset(); | 71     message_loop_.reset(); | 
| 63     TraceLog::DeleteForTesting(); | 72     TraceLog::DeleteForTesting(); | 
| 64   } | 73   } | 
| 65 | 74 | 
| 66   void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner, | 75   void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner, | 
| 67                            Closure closure, | 76                            Closure closure, | 
| 68                            uint64 dump_guid, | 77                            uint64 dump_guid, | 
| 69                            bool success) { | 78                            bool success) { | 
| 70     last_callback_success_ = success; | 79     last_callback_success_ = success; | 
| 71     task_runner->PostTask(FROM_HERE, closure); | 80     task_runner->PostTask(FROM_HERE, closure); | 
| 72   } | 81   } | 
| 73 | 82 | 
| 74  protected: | 83  protected: | 
|  | 84   void SetDelegate(scoped_ptr<MemoryDumpManagerDelegateForTesting> delegate) { | 
|  | 85     delegate_ = delegate.Pass(); | 
|  | 86     MemoryDumpManager::GetInstance()->SetDelegate(delegate_.get()); | 
|  | 87   } | 
|  | 88 | 
|  | 89   // This enalbes tracing using the legacy category filter string. | 
| 75   void EnableTracing(const char* category) { | 90   void EnableTracing(const char* category) { | 
|  | 91     if (!delegate_) { | 
|  | 92       delegate_.reset(new MemoryDumpManagerDelegateForTesting()); | 
|  | 93       MemoryDumpManager::GetInstance()->SetDelegate(delegate_.get()); | 
|  | 94     } | 
| 76     TraceLog::GetInstance()->SetEnabled( | 95     TraceLog::GetInstance()->SetEnabled( | 
| 77         TraceConfig(category, ""), TraceLog::RECORDING_MODE); | 96         TraceConfig(category, ""), TraceLog::RECORDING_MODE); | 
| 78   } | 97   } | 
| 79 | 98 | 
|  | 99   void EnableTracingWithTraceConfig(const char* trace_config) { | 
|  | 100     DCHECK(delegate_); | 
|  | 101     TraceConfig tc(trace_config); | 
|  | 102     TraceLog::GetInstance()->SetEnabled(tc, TraceLog::RECORDING_MODE); | 
|  | 103   } | 
|  | 104 | 
| 80   void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); } | 105   void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); } | 
| 81 | 106 | 
| 82   scoped_ptr<MemoryDumpManager> mdm_; | 107   scoped_ptr<MemoryDumpManager> mdm_; | 
| 83   bool last_callback_success_; | 108   bool last_callback_success_; | 
|  | 109   scoped_ptr<MemoryDumpManagerDelegateForTesting> delegate_; | 
| 84 | 110 | 
| 85  private: | 111  private: | 
| 86   scoped_ptr<MessageLoop> message_loop_; | 112   scoped_ptr<MessageLoop> message_loop_; | 
| 87   MemoryDumpManagerDelegateForTesting delegate_; |  | 
| 88 | 113 | 
| 89   // We want our singleton torn down after each test. | 114   // We want our singleton torn down after each test. | 
| 90   ShadowingAtExitManager at_exit_manager_; | 115   ShadowingAtExitManager at_exit_manager_; | 
| 91 }; | 116 }; | 
| 92 | 117 | 
| 93 class MockDumpProvider : public MemoryDumpProvider { | 118 class MockDumpProvider : public MemoryDumpProvider { | 
| 94  public: | 119  public: | 
| 95   MockDumpProvider() | 120   MockDumpProvider() | 
| 96       : dump_provider_to_register_or_unregister(nullptr), | 121       : dump_provider_to_register_or_unregister(nullptr), | 
| 97         last_session_state_(nullptr), | 122         last_session_state_(nullptr), | 
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 163 }; | 188 }; | 
| 164 | 189 | 
| 165 TEST_F(MemoryDumpManagerTest, SingleDumper) { | 190 TEST_F(MemoryDumpManagerTest, SingleDumper) { | 
| 166   MockDumpProvider mdp; | 191   MockDumpProvider mdp; | 
| 167   mdm_->RegisterDumpProvider(&mdp); | 192   mdm_->RegisterDumpProvider(&mdp); | 
| 168 | 193 | 
| 169   // Check that the dumper is not called if the memory category is not enabled. | 194   // Check that the dumper is not called if the memory category is not enabled. | 
| 170   EnableTracing("foo-and-bar-but-not-memory"); | 195   EnableTracing("foo-and-bar-but-not-memory"); | 
| 171   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 196   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 
| 172   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 197   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 173                           high_detail_args); | 198                           g_high_detail_args); | 
| 174   DisableTracing(); | 199   DisableTracing(); | 
| 175 | 200 | 
| 176   // Now repeat enabling the memory category and check that the dumper is | 201   // Now repeat enabling the memory category and check that the dumper is | 
| 177   // invoked this time. | 202   // invoked this time. | 
| 178   EnableTracing(MemoryDumpManager::kTraceCategory); | 203   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 179   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(3).WillRepeatedly(Return(true)); | 204   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(3).WillRepeatedly(Return(true)); | 
| 180   for (int i = 0; i < 3; ++i) | 205   for (int i = 0; i < 3; ++i) | 
| 181     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 206     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 182                             high_detail_args); | 207                             g_high_detail_args); | 
| 183   DisableTracing(); | 208   DisableTracing(); | 
| 184 | 209 | 
| 185   mdm_->UnregisterDumpProvider(&mdp); | 210   mdm_->UnregisterDumpProvider(&mdp); | 
| 186 | 211 | 
| 187   // Finally check the unregister logic (no calls to the mdp after unregister). | 212   // Finally check the unregister logic (no calls to the mdp after unregister). | 
| 188   EnableTracing(MemoryDumpManager::kTraceCategory); | 213   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 189   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 214   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 
| 190   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 215   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 191                           high_detail_args); | 216                           g_high_detail_args); | 
| 192   TraceLog::GetInstance()->SetDisabled(); | 217   TraceLog::GetInstance()->SetDisabled(); | 
| 193 } | 218 } | 
| 194 | 219 | 
| 195 TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgs) { | 220 TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgs) { | 
| 196   // Check that requesting dumps with high level of detail actually propagates | 221   // Check that requesting dumps with high level of detail actually propagates | 
| 197   // to OnMemoryDump() call on dump providers. | 222   // to OnMemoryDump() call on dump providers. | 
| 198   MockDumpProvider mdp_high_detail(MemoryDumpArgs::LevelOfDetail::HIGH); | 223   MockDumpProvider mdp_high_detail(MemoryDumpArgs::LevelOfDetail::HIGH); | 
| 199   mdm_->RegisterDumpProvider(&mdp_high_detail); | 224   mdm_->RegisterDumpProvider(&mdp_high_detail); | 
| 200 | 225 | 
| 201   EnableTracing(MemoryDumpManager::kTraceCategory); | 226   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 202   EXPECT_CALL(mdp_high_detail, OnMemoryDump(_, _)) | 227   EXPECT_CALL(mdp_high_detail, OnMemoryDump(_, _)) | 
| 203       .Times(1) | 228       .Times(1) | 
| 204       .WillRepeatedly( | 229       .WillRepeatedly( | 
| 205           Invoke(&mdp_high_detail, | 230           Invoke(&mdp_high_detail, | 
| 206                  &MockDumpProvider::OnMemoryDump_CheckMemoryDumpArgs)); | 231                  &MockDumpProvider::OnMemoryDump_CheckMemoryDumpArgs)); | 
| 207   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 232   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 208                           high_detail_args); | 233                           g_high_detail_args); | 
| 209   DisableTracing(); | 234   DisableTracing(); | 
| 210   mdm_->UnregisterDumpProvider(&mdp_high_detail); | 235   mdm_->UnregisterDumpProvider(&mdp_high_detail); | 
| 211 | 236 | 
| 212   // Check that requesting dumps with low level of detail actually propagates to | 237   // Check that requesting dumps with low level of detail actually propagates to | 
| 213   // OnMemoryDump() call on dump providers. | 238   // OnMemoryDump() call on dump providers. | 
| 214   MockDumpProvider mdp_low_detail(MemoryDumpArgs::LevelOfDetail::LOW); | 239   MockDumpProvider mdp_low_detail(MemoryDumpArgs::LevelOfDetail::LOW); | 
| 215   mdm_->RegisterDumpProvider(&mdp_low_detail); | 240   mdm_->RegisterDumpProvider(&mdp_low_detail); | 
| 216 | 241 | 
| 217   EnableTracing(MemoryDumpManager::kTraceCategory); | 242   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 218   EXPECT_CALL(mdp_low_detail, OnMemoryDump(_, _)) | 243   EXPECT_CALL(mdp_low_detail, OnMemoryDump(_, _)) | 
| 219       .Times(1) | 244       .Times(1) | 
| 220       .WillRepeatedly( | 245       .WillRepeatedly( | 
| 221           Invoke(&mdp_low_detail, | 246           Invoke(&mdp_low_detail, | 
| 222                  &MockDumpProvider::OnMemoryDump_CheckMemoryDumpArgs)); | 247                  &MockDumpProvider::OnMemoryDump_CheckMemoryDumpArgs)); | 
| 223   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 248   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 224                           low_detail_args); | 249                           g_low_detail_args); | 
| 225   DisableTracing(); | 250   DisableTracing(); | 
| 226   mdm_->UnregisterDumpProvider(&mdp_low_detail); | 251   mdm_->UnregisterDumpProvider(&mdp_low_detail); | 
| 227 } | 252 } | 
| 228 | 253 | 
| 229 TEST_F(MemoryDumpManagerTest, SharedSessionState) { | 254 TEST_F(MemoryDumpManagerTest, SharedSessionState) { | 
| 230   MockDumpProvider mdp1; | 255   MockDumpProvider mdp1; | 
| 231   MockDumpProvider mdp2; | 256   MockDumpProvider mdp2; | 
| 232   mdm_->RegisterDumpProvider(&mdp1); | 257   mdm_->RegisterDumpProvider(&mdp1); | 
| 233   mdm_->RegisterDumpProvider(&mdp2); | 258   mdm_->RegisterDumpProvider(&mdp2); | 
| 234 | 259 | 
| 235   EnableTracing(MemoryDumpManager::kTraceCategory); | 260   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 236   EXPECT_CALL(mdp1, OnMemoryDump(_, _)) | 261   EXPECT_CALL(mdp1, OnMemoryDump(_, _)) | 
| 237       .Times(2) | 262       .Times(2) | 
| 238       .WillRepeatedly( | 263       .WillRepeatedly( | 
| 239           Invoke(&mdp1, &MockDumpProvider::OnMemoryDump_CheckSessionState)); | 264           Invoke(&mdp1, &MockDumpProvider::OnMemoryDump_CheckSessionState)); | 
| 240   EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 265   EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 
| 241       .Times(2) | 266       .Times(2) | 
| 242       .WillRepeatedly( | 267       .WillRepeatedly( | 
| 243           Invoke(&mdp2, &MockDumpProvider::OnMemoryDump_CheckSessionState)); | 268           Invoke(&mdp2, &MockDumpProvider::OnMemoryDump_CheckSessionState)); | 
| 244 | 269 | 
| 245   for (int i = 0; i < 2; ++i) | 270   for (int i = 0; i < 2; ++i) | 
| 246     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 271     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 247                             high_detail_args); | 272                             g_high_detail_args); | 
| 248 | 273 | 
| 249   DisableTracing(); | 274   DisableTracing(); | 
| 250 } | 275 } | 
| 251 | 276 | 
| 252 TEST_F(MemoryDumpManagerTest, MultipleDumpers) { | 277 TEST_F(MemoryDumpManagerTest, MultipleDumpers) { | 
| 253   MockDumpProvider mdp1; | 278   MockDumpProvider mdp1; | 
| 254   MockDumpProvider mdp2; | 279   MockDumpProvider mdp2; | 
| 255 | 280 | 
| 256   // Enable only mdp1. | 281   // Enable only mdp1. | 
| 257   mdm_->RegisterDumpProvider(&mdp1); | 282   mdm_->RegisterDumpProvider(&mdp1); | 
| 258   EnableTracing(MemoryDumpManager::kTraceCategory); | 283   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 259   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 284   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 
| 260   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(0); | 285   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(0); | 
| 261   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 286   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 262                           high_detail_args); | 287                           g_high_detail_args); | 
| 263   DisableTracing(); | 288   DisableTracing(); | 
| 264 | 289 | 
| 265   // Invert: enable mdp1 and disable mdp2. | 290   // Invert: enable mdp1 and disable mdp2. | 
| 266   mdm_->UnregisterDumpProvider(&mdp1); | 291   mdm_->UnregisterDumpProvider(&mdp1); | 
| 267   mdm_->RegisterDumpProvider(&mdp2); | 292   mdm_->RegisterDumpProvider(&mdp2); | 
| 268   EnableTracing(MemoryDumpManager::kTraceCategory); | 293   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 269   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); | 294   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); | 
| 270   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 295   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 
| 271   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 296   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 272                           high_detail_args); | 297                           g_high_detail_args); | 
| 273   DisableTracing(); | 298   DisableTracing(); | 
| 274 | 299 | 
| 275   // Enable both mdp1 and mdp2. | 300   // Enable both mdp1 and mdp2. | 
| 276   mdm_->RegisterDumpProvider(&mdp1); | 301   mdm_->RegisterDumpProvider(&mdp1); | 
| 277   EnableTracing(MemoryDumpManager::kTraceCategory); | 302   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 278   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 303   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 
| 279   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 304   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true)); | 
| 280   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 305   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 281                           high_detail_args); | 306                           g_high_detail_args); | 
| 282   DisableTracing(); | 307   DisableTracing(); | 
| 283 } | 308 } | 
| 284 | 309 | 
| 285 // Verify that whether OnMemoryDump is called depends only on the current | 310 // Verify that whether OnMemoryDump is called depends only on the current | 
| 286 // registration state and not on previous registrations and dumps. | 311 // registration state and not on previous registrations and dumps. | 
| 287 TEST_F(MemoryDumpManagerTest, RegistrationConsistency) { | 312 TEST_F(MemoryDumpManagerTest, RegistrationConsistency) { | 
| 288   MockDumpProvider mdp; | 313   MockDumpProvider mdp; | 
| 289 | 314 | 
| 290   mdm_->RegisterDumpProvider(&mdp); | 315   mdm_->RegisterDumpProvider(&mdp); | 
| 291 | 316 | 
| 292   { | 317   { | 
| 293     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(1); | 318     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(1); | 
| 294     EnableTracing(MemoryDumpManager::kTraceCategory); | 319     EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 295     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 320     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 296                             high_detail_args); | 321                             g_high_detail_args); | 
| 297     DisableTracing(); | 322     DisableTracing(); | 
| 298   } | 323   } | 
| 299 | 324 | 
| 300   mdm_->UnregisterDumpProvider(&mdp); | 325   mdm_->UnregisterDumpProvider(&mdp); | 
| 301 | 326 | 
| 302   { | 327   { | 
| 303     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 328     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 
| 304     EnableTracing(MemoryDumpManager::kTraceCategory); | 329     EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 305     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 330     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 306                             high_detail_args); | 331                             g_high_detail_args); | 
| 307     DisableTracing(); | 332     DisableTracing(); | 
| 308   } | 333   } | 
| 309 | 334 | 
| 310   mdm_->RegisterDumpProvider(&mdp); | 335   mdm_->RegisterDumpProvider(&mdp); | 
| 311   mdm_->UnregisterDumpProvider(&mdp); | 336   mdm_->UnregisterDumpProvider(&mdp); | 
| 312 | 337 | 
| 313   { | 338   { | 
| 314     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 339     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 
| 315     EnableTracing(MemoryDumpManager::kTraceCategory); | 340     EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 316     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 341     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 317                             high_detail_args); | 342                             g_high_detail_args); | 
| 318     DisableTracing(); | 343     DisableTracing(); | 
| 319   } | 344   } | 
| 320 | 345 | 
| 321   mdm_->RegisterDumpProvider(&mdp); | 346   mdm_->RegisterDumpProvider(&mdp); | 
| 322   mdm_->UnregisterDumpProvider(&mdp); | 347   mdm_->UnregisterDumpProvider(&mdp); | 
| 323   mdm_->RegisterDumpProvider(&mdp); | 348   mdm_->RegisterDumpProvider(&mdp); | 
| 324 | 349 | 
| 325   { | 350   { | 
| 326     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(1); | 351     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(1); | 
| 327     EnableTracing(MemoryDumpManager::kTraceCategory); | 352     EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 328     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 353     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 329                             high_detail_args); | 354                             g_high_detail_args); | 
| 330     DisableTracing(); | 355     DisableTracing(); | 
| 331   } | 356   } | 
| 332 } | 357 } | 
| 333 | 358 | 
| 334 // Checks that the MemoryDumpManager respects the thread affinity when a | 359 // Checks that the MemoryDumpManager respects the thread affinity when a | 
| 335 // MemoryDumpProvider specifies a task_runner(). The test starts creating 8 | 360 // MemoryDumpProvider specifies a task_runner(). The test starts creating 8 | 
| 336 // threads and registering a MemoryDumpProvider on each of them. At each | 361 // threads and registering a MemoryDumpProvider on each of them. At each | 
| 337 // iteration, one thread is removed, to check the live unregistration logic. | 362 // iteration, one thread is removed, to check the live unregistration logic. | 
| 338 TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) { | 363 TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) { | 
| 339   const uint32 kNumInitialThreads = 8; | 364   const uint32 kNumInitialThreads = 8; | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 359   EnableTracing(MemoryDumpManager::kTraceCategory); | 384   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 360 | 385 | 
| 361   while (!threads.empty()) { | 386   while (!threads.empty()) { | 
| 362     last_callback_success_ = false; | 387     last_callback_success_ = false; | 
| 363     { | 388     { | 
| 364       RunLoop run_loop; | 389       RunLoop run_loop; | 
| 365       MemoryDumpCallback callback = | 390       MemoryDumpCallback callback = | 
| 366           Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 391           Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 
| 367                MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 392                MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 
| 368       mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 393       mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 369                               high_detail_args, callback); | 394                               g_high_detail_args, callback); | 
| 370       // This nested message loop (|run_loop|) will be quit if and only if | 395       // This nested message loop (|run_loop|) will be quit if and only if | 
| 371       // the RequestGlobalDump callback is invoked. | 396       // the RequestGlobalDump callback is invoked. | 
| 372       run_loop.Run(); | 397       run_loop.Run(); | 
| 373     } | 398     } | 
| 374     EXPECT_TRUE(last_callback_success_); | 399     EXPECT_TRUE(last_callback_success_); | 
| 375 | 400 | 
| 376     // Unregister a MDP and destroy one thread at each iteration to check the | 401     // Unregister a MDP and destroy one thread at each iteration to check the | 
| 377     // live unregistration logic. The unregistration needs to happen on the same | 402     // live unregistration logic. The unregistration needs to happen on the same | 
| 378     // thread the MDP belongs to. | 403     // thread the MDP belongs to. | 
| 379     { | 404     { | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 407       .Times(MemoryDumpManager::kMaxConsecutiveFailuresCount) | 432       .Times(MemoryDumpManager::kMaxConsecutiveFailuresCount) | 
| 408       .WillRepeatedly(Return(false)); | 433       .WillRepeatedly(Return(false)); | 
| 409 | 434 | 
| 410   EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 435   EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 
| 411       .Times(1 + MemoryDumpManager::kMaxConsecutiveFailuresCount) | 436       .Times(1 + MemoryDumpManager::kMaxConsecutiveFailuresCount) | 
| 412       .WillOnce(Return(false)) | 437       .WillOnce(Return(false)) | 
| 413       .WillRepeatedly(Return(true)); | 438       .WillRepeatedly(Return(true)); | 
| 414   for (int i = 0; i < 1 + MemoryDumpManager::kMaxConsecutiveFailuresCount; | 439   for (int i = 0; i < 1 + MemoryDumpManager::kMaxConsecutiveFailuresCount; | 
| 415        i++) { | 440        i++) { | 
| 416     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 441     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 417                             high_detail_args); | 442                             g_high_detail_args); | 
| 418   } | 443   } | 
| 419 | 444 | 
| 420   DisableTracing(); | 445   DisableTracing(); | 
| 421 } | 446 } | 
| 422 | 447 | 
| 423 // Sneakily register an extra memory dump provider while an existing one is | 448 // Sneakily register an extra memory dump provider while an existing one is | 
| 424 // dumping and expect it to take part in the already active tracing session. | 449 // dumping and expect it to take part in the already active tracing session. | 
| 425 TEST_F(MemoryDumpManagerTest, RegisterDumperWhileDumping) { | 450 TEST_F(MemoryDumpManagerTest, RegisterDumperWhileDumping) { | 
| 426   MockDumpProvider mdp1; | 451   MockDumpProvider mdp1; | 
| 427   MockDumpProvider mdp2; | 452   MockDumpProvider mdp2; | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 438       .WillRepeatedly(Return(true)); | 463       .WillRepeatedly(Return(true)); | 
| 439 | 464 | 
| 440   // Depending on the insertion order (before or after mdp1), mdp2 might be | 465   // Depending on the insertion order (before or after mdp1), mdp2 might be | 
| 441   // called also immediately after it gets registered. | 466   // called also immediately after it gets registered. | 
| 442   EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 467   EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 
| 443       .Times(Between(2, 3)) | 468       .Times(Between(2, 3)) | 
| 444       .WillRepeatedly(Return(true)); | 469       .WillRepeatedly(Return(true)); | 
| 445 | 470 | 
| 446   for (int i = 0; i < 4; i++) { | 471   for (int i = 0; i < 4; i++) { | 
| 447     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 472     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 448                             high_detail_args); | 473                             g_high_detail_args); | 
| 449   } | 474   } | 
| 450 | 475 | 
| 451   DisableTracing(); | 476   DisableTracing(); | 
| 452 } | 477 } | 
| 453 | 478 | 
| 454 // Like the above, but suddenly unregister the dump provider. | 479 // Like the above, but suddenly unregister the dump provider. | 
| 455 TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileDumping) { | 480 TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileDumping) { | 
| 456   MockDumpProvider mdp1; | 481   MockDumpProvider mdp1; | 
| 457   MockDumpProvider mdp2; | 482   MockDumpProvider mdp2; | 
| 458 | 483 | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 469       .WillRepeatedly(Return(true)); | 494       .WillRepeatedly(Return(true)); | 
| 470 | 495 | 
| 471   // Depending on the insertion order (before or after mdp1), mdp2 might have | 496   // Depending on the insertion order (before or after mdp1), mdp2 might have | 
| 472   // been already called when OnMemoryDump_UnregisterDumpProvider happens. | 497   // been already called when OnMemoryDump_UnregisterDumpProvider happens. | 
| 473   EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 498   EXPECT_CALL(mdp2, OnMemoryDump(_, _)) | 
| 474       .Times(Between(1, 2)) | 499       .Times(Between(1, 2)) | 
| 475       .WillRepeatedly(Return(true)); | 500       .WillRepeatedly(Return(true)); | 
| 476 | 501 | 
| 477   for (int i = 0; i < 4; i++) { | 502   for (int i = 0; i < 4; i++) { | 
| 478     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 503     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 479                             high_detail_args); | 504                             g_high_detail_args); | 
| 480   } | 505   } | 
| 481 | 506 | 
| 482   DisableTracing(); | 507   DisableTracing(); | 
| 483 } | 508 } | 
| 484 | 509 | 
| 485 // Verify that the dump does not abort when unregistering a provider while | 510 // Verify that the dump does not abort when unregistering a provider while | 
| 486 // dumping from a different thread than the dumping thread. | 511 // dumping from a different thread than the dumping thread. | 
| 487 TEST_F(MemoryDumpManagerTest, UnregisterDumperFromThreadWhileDumping) { | 512 TEST_F(MemoryDumpManagerTest, UnregisterDumperFromThreadWhileDumping) { | 
| 488   ScopedVector<TestIOThread> threads; | 513   ScopedVector<TestIOThread> threads; | 
| 489   ScopedVector<MockDumpProvider> mdps; | 514   ScopedVector<MockDumpProvider> mdps; | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 519         .WillOnce(Invoke(on_dump)); | 544         .WillOnce(Invoke(on_dump)); | 
| 520   } | 545   } | 
| 521 | 546 | 
| 522   last_callback_success_ = false; | 547   last_callback_success_ = false; | 
| 523   MemoryDumpCallback callback = | 548   MemoryDumpCallback callback = | 
| 524       Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 549       Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 
| 525            MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 550            MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 
| 526 | 551 | 
| 527   EnableTracing(MemoryDumpManager::kTraceCategory); | 552   EnableTracing(MemoryDumpManager::kTraceCategory); | 
| 528   MemoryDumpRequestArgs request_args = {0, MemoryDumpType::EXPLICITLY_TRIGGERED, | 553   MemoryDumpRequestArgs request_args = {0, MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 529                                         high_detail_args}; | 554                                         g_high_detail_args}; | 
| 530   mdm_->CreateProcessDump(request_args, callback); | 555   mdm_->CreateProcessDump(request_args, callback); | 
| 531 | 556 | 
| 532   run_loop.Run(); | 557   run_loop.Run(); | 
| 533 | 558 | 
| 534   ASSERT_EQ(1, on_memory_dump_call_count); | 559   ASSERT_EQ(1, on_memory_dump_call_count); | 
| 535   ASSERT_EQ(true, last_callback_success_); | 560   ASSERT_EQ(true, last_callback_success_); | 
| 536 | 561 | 
| 537   DisableTracing(); | 562   DisableTracing(); | 
| 538 } | 563 } | 
| 539 | 564 | 
| 540 // Ensures that a NACK callback is invoked if RequestGlobalDump is called when | 565 // Ensures that a NACK callback is invoked if RequestGlobalDump is called when | 
| 541 // tracing is not enabled. | 566 // tracing is not enabled. | 
| 542 TEST_F(MemoryDumpManagerTest, CallbackCalledOnFailure) { | 567 TEST_F(MemoryDumpManagerTest, CallbackCalledOnFailure) { | 
| 543   MockDumpProvider mdp1; | 568   MockDumpProvider mdp1; | 
| 544 | 569 | 
| 545   mdm_->RegisterDumpProvider(&mdp1); | 570   mdm_->RegisterDumpProvider(&mdp1); | 
| 546   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); | 571   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); | 
| 547 | 572 | 
| 548   last_callback_success_ = true; | 573   last_callback_success_ = true; | 
| 549   { | 574   { | 
| 550     RunLoop run_loop; | 575     RunLoop run_loop; | 
| 551     MemoryDumpCallback callback = | 576     MemoryDumpCallback callback = | 
| 552         Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 577         Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 
| 553              MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 578              MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 
| 554     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 579     mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 
| 555                             high_detail_args, callback); | 580                             g_high_detail_args, callback); | 
| 556     run_loop.Run(); | 581     run_loop.Run(); | 
| 557   } | 582   } | 
| 558   EXPECT_FALSE(last_callback_success_); | 583   EXPECT_FALSE(last_callback_success_); | 
| 559 } | 584 } | 
| 560 | 585 | 
|  | 586 MATCHER(IsHighDetail, "") { | 
|  | 587   return arg.dump_args.level_of_detail == MemoryDumpArgs::LevelOfDetail::HIGH; | 
|  | 588 } | 
|  | 589 | 
|  | 590 MATCHER(IsLowDetail, "") { | 
|  | 591   return arg.dump_args.level_of_detail == MemoryDumpArgs::LevelOfDetail::LOW; | 
|  | 592 } | 
|  | 593 | 
|  | 594 TEST_F(MemoryDumpManagerTest, SchedulePeriodicDumpsFromTraceConfig) { | 
|  | 595   const char kMemoryDumpTraceConfigString[] = | 
|  | 596     "{" | 
|  | 597       "\"included_categories\":[" | 
|  | 598         "\"disabled-by-default-memory-infra\"" | 
|  | 599       "]," | 
|  | 600       "\"memory_dump_config\":{" | 
|  | 601         "\"triggers\":[" | 
|  | 602           "{" | 
|  | 603             "\"mode\":\"light\"," | 
|  | 604             "\"periodic_interval_ms\":1" | 
|  | 605           "}," | 
|  | 606           "{" | 
|  | 607             "\"mode\":\"detailed\"," | 
|  | 608             "\"periodic_interval_ms\":3" | 
|  | 609           "}" | 
|  | 610         "]" | 
|  | 611       "}" | 
|  | 612     "}"; | 
|  | 613 | 
|  | 614   RunLoop run_loop; | 
|  | 615   scoped_ptr<MemoryDumpManagerDelegateForPeriodicDumpTest> delegate( | 
|  | 616       new MemoryDumpManagerDelegateForPeriodicDumpTest()); | 
|  | 617 | 
|  | 618   auto quit_closure = run_loop.QuitClosure(); | 
|  | 619   testing::InSequence sequence; | 
|  | 620   EXPECT_CALL(*delegate.get(), RequestGlobalMemoryDump(IsHighDetail(), _)) | 
|  | 621       .Times(1); | 
|  | 622   EXPECT_CALL(*delegate.get(), RequestGlobalMemoryDump(IsLowDetail(), _)) | 
|  | 623       .Times(2); | 
|  | 624   EXPECT_CALL(*delegate.get(), RequestGlobalMemoryDump(IsHighDetail(), _)) | 
|  | 625       .Times(1); | 
|  | 626   EXPECT_CALL(*delegate.get(), RequestGlobalMemoryDump(IsLowDetail(), _)) | 
|  | 627       .Times(1) | 
|  | 628       .WillOnce(Invoke([quit_closure](const MemoryDumpRequestArgs& args, | 
|  | 629                                       const MemoryDumpCallback& callback) { | 
|  | 630         TraceLog::GetInstance()->SetDisabled(); | 
|  | 631         ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure); | 
|  | 632       })); | 
|  | 633 | 
|  | 634   SetDelegate(delegate.Pass()); | 
|  | 635   EnableTracingWithTraceConfig(kMemoryDumpTraceConfigString); | 
|  | 636 | 
|  | 637   run_loop.Run(); | 
|  | 638 } | 
|  | 639 | 
| 561 }  // namespace trace_event | 640 }  // namespace trace_event | 
| 562 }  // namespace base | 641 }  // namespace base | 
| OLD | NEW | 
|---|