Home | History | Annotate | Download | only in trace_event
      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
      3 // found in the LICENSE file.
      4 
      5 #include "base/trace_event/memory_dump_manager.h"
      6 
      7 #include <stdint.h>
      8 
      9 #include <memory>
     10 #include <utility>
     11 #include <vector>
     12 
     13 #include "base/bind_helpers.h"
     14 #include "base/callback.h"
     15 #include "base/memory/ptr_util.h"
     16 #include "base/memory/ref_counted_memory.h"
     17 #include "base/message_loop/message_loop.h"
     18 #include "base/run_loop.h"
     19 #include "base/strings/stringprintf.h"
     20 #include "base/synchronization/waitable_event.h"
     21 #include "base/test/sequenced_worker_pool_owner.h"
     22 #include "base/test/test_io_thread.h"
     23 #include "base/test/trace_event_analyzer.h"
     24 #include "base/threading/platform_thread.h"
     25 #include "base/threading/sequenced_task_runner_handle.h"
     26 #include "base/threading/sequenced_worker_pool.h"
     27 #include "base/threading/thread.h"
     28 #include "base/threading/thread_task_runner_handle.h"
     29 #include "base/trace_event/memory_dump_provider.h"
     30 #include "base/trace_event/memory_dump_scheduler.h"
     31 #include "base/trace_event/memory_infra_background_whitelist.h"
     32 #include "base/trace_event/process_memory_dump.h"
     33 #include "base/trace_event/trace_buffer.h"
     34 #include "base/trace_event/trace_config_memory_test_util.h"
     35 #include "build/build_config.h"
     36 #include "testing/gmock/include/gmock/gmock.h"
     37 #include "testing/gtest/include/gtest/gtest.h"
     38 
     39 using testing::_;
     40 using testing::AnyNumber;
     41 using testing::AtMost;
     42 using testing::Between;
     43 using testing::Invoke;
     44 using testing::Return;
     45 
     46 namespace base {
     47 namespace trace_event {
     48 
     49 // GTest matchers for MemoryDumpRequestArgs arguments.
     50 MATCHER(IsDetailedDump, "") {
     51   return arg.level_of_detail == MemoryDumpLevelOfDetail::DETAILED;
     52 }
     53 
     54 MATCHER(IsLightDump, "") {
     55   return arg.level_of_detail == MemoryDumpLevelOfDetail::LIGHT;
     56 }
     57 
     58 MATCHER(IsBackgroundDump, "") {
     59   return arg.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND;
     60 }
     61 
     62 namespace {
     63 
     64 const char* kMDPName = "TestDumpProvider";
     65 const char* kWhitelistedMDPName = "WhitelistedTestDumpProvider";
     66 const char* const kTestMDPWhitelist[] = {kWhitelistedMDPName, nullptr};
     67 
     68 void RegisterDumpProvider(
     69     MemoryDumpProvider* mdp,
     70     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     71     const MemoryDumpProvider::Options& options,
     72     const char* name = kMDPName) {
     73   MemoryDumpManager* mdm = MemoryDumpManager::GetInstance();
     74   mdm->set_dumper_registrations_ignored_for_testing(false);
     75   mdm->RegisterDumpProvider(mdp, name, std::move(task_runner), options);
     76   mdm->set_dumper_registrations_ignored_for_testing(true);
     77 }
     78 
     79 void RegisterDumpProvider(
     80     MemoryDumpProvider* mdp,
     81     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
     82   RegisterDumpProvider(mdp, task_runner, MemoryDumpProvider::Options());
     83 }
     84 
     85 void RegisterDumpProviderWithSequencedTaskRunner(
     86     MemoryDumpProvider* mdp,
     87     scoped_refptr<base::SequencedTaskRunner> task_runner,
     88     const MemoryDumpProvider::Options& options) {
     89   MemoryDumpManager* mdm = MemoryDumpManager::GetInstance();
     90   mdm->set_dumper_registrations_ignored_for_testing(false);
     91   mdm->RegisterDumpProviderWithSequencedTaskRunner(mdp, kMDPName, task_runner,
     92                                                    options);
     93   mdm->set_dumper_registrations_ignored_for_testing(true);
     94 }
     95 
     96 void OnTraceDataCollected(Closure quit_closure,
     97                           trace_event::TraceResultBuffer* buffer,
     98                           const scoped_refptr<RefCountedString>& json,
     99                           bool has_more_events) {
    100   buffer->AddFragment(json->data());
    101   if (!has_more_events)
    102     quit_closure.Run();
    103 }
    104 
    105 // Posts |task| to |task_runner| and blocks until it is executed.
    106 void PostTaskAndWait(const tracked_objects::Location& from_here,
    107                      SequencedTaskRunner* task_runner,
    108                      base::OnceClosure task) {
    109   base::WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
    110                             WaitableEvent::InitialState::NOT_SIGNALED);
    111   task_runner->PostTask(from_here, std::move(task));
    112   task_runner->PostTask(
    113       FROM_HERE, base::Bind(&WaitableEvent::Signal, base::Unretained(&event)));
    114   // The SequencedTaskRunner guarantees that |event| will only be signaled after
    115   // |task| is executed.
    116   event.Wait();
    117 }
    118 
    119 // Testing MemoryDumpManagerDelegate which, by default, short-circuits dump
    120 // requests locally to the MemoryDumpManager instead of performing IPC dances.
    121 class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate {
    122  public:
    123   MemoryDumpManagerDelegateForTesting(bool is_coordinator)
    124       : is_coordinator_(is_coordinator) {
    125     ON_CALL(*this, RequestGlobalMemoryDump(_, _))
    126         .WillByDefault(Invoke(
    127             this, &MemoryDumpManagerDelegateForTesting::CreateProcessDump));
    128   }
    129 
    130   MOCK_METHOD2(RequestGlobalMemoryDump,
    131                void(const MemoryDumpRequestArgs& args,
    132                     const MemoryDumpCallback& callback));
    133 
    134   bool IsCoordinator() const override { return is_coordinator_; }
    135 
    136   // Promote the CreateProcessDump to public so it can be used by test fixtures.
    137   using MemoryDumpManagerDelegate::CreateProcessDump;
    138 
    139  private:
    140   bool is_coordinator_;
    141 };
    142 
    143 class MockMemoryDumpProvider : public MemoryDumpProvider {
    144  public:
    145   MOCK_METHOD0(Destructor, void());
    146   MOCK_METHOD2(OnMemoryDump,
    147                bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd));
    148   MOCK_METHOD1(PollFastMemoryTotal, void(uint64_t* memory_total));
    149   MOCK_METHOD0(SuspendFastMemoryPolling, void());
    150 
    151   MockMemoryDumpProvider() : enable_mock_destructor(false) {
    152     ON_CALL(*this, OnMemoryDump(_, _))
    153         .WillByDefault(Invoke([](const MemoryDumpArgs&,
    154                                  ProcessMemoryDump* pmd) -> bool {
    155           // |session_state| should not be null under any circumstances when
    156           // invoking a memory dump. The problem might arise in race conditions
    157           // like crbug.com/600570 .
    158           EXPECT_TRUE(pmd->session_state().get() != nullptr);
    159           return true;
    160         }));
    161 
    162     ON_CALL(*this, PollFastMemoryTotal(_))
    163         .WillByDefault(
    164             Invoke([](uint64_t* memory_total) -> void { NOTREACHED(); }));
    165   }
    166   ~MockMemoryDumpProvider() override {
    167     if (enable_mock_destructor)
    168       Destructor();
    169   }
    170 
    171   bool enable_mock_destructor;
    172 };
    173 
    174 class TestSequencedTaskRunner : public SequencedTaskRunner {
    175  public:
    176   TestSequencedTaskRunner()
    177       : worker_pool_(2 /* max_threads */, "Test Task Runner"),
    178         enabled_(true),
    179         num_of_post_tasks_(0) {}
    180 
    181   void set_enabled(bool value) { enabled_ = value; }
    182   unsigned no_of_post_tasks() const { return num_of_post_tasks_; }
    183 
    184   bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
    185                                   OnceClosure task,
    186                                   TimeDelta delay) override {
    187     NOTREACHED();
    188     return false;
    189   }
    190 
    191   bool PostDelayedTask(const tracked_objects::Location& from_here,
    192                        OnceClosure task,
    193                        TimeDelta delay) override {
    194     num_of_post_tasks_++;
    195     if (enabled_) {
    196       return worker_pool_.pool()->PostSequencedWorkerTask(token_, from_here,
    197                                                           std::move(task));
    198     }
    199     return false;
    200   }
    201 
    202   bool RunsTasksOnCurrentThread() const override {
    203     return worker_pool_.pool()->RunsTasksOnCurrentThread();
    204   }
    205 
    206  private:
    207   ~TestSequencedTaskRunner() override {}
    208 
    209   SequencedWorkerPoolOwner worker_pool_;
    210   const SequencedWorkerPool::SequenceToken token_;
    211   bool enabled_;
    212   unsigned num_of_post_tasks_;
    213 };
    214 
    215 }  // namespace
    216 
    217 class MemoryDumpManagerTest : public testing::Test {
    218  public:
    219   MemoryDumpManagerTest() : testing::Test(), kDefaultOptions() {}
    220 
    221   void SetUp() override {
    222     last_callback_success_ = false;
    223     message_loop_.reset(new MessageLoop());
    224     mdm_.reset(new MemoryDumpManager());
    225     MemoryDumpManager::SetInstanceForTesting(mdm_.get());
    226     ASSERT_EQ(mdm_.get(), MemoryDumpManager::GetInstance());
    227   }
    228 
    229   void TearDown() override {
    230     MemoryDumpManager::SetInstanceForTesting(nullptr);
    231     delegate_ = nullptr;
    232     mdm_.reset();
    233     message_loop_.reset();
    234     TraceLog::DeleteForTesting();
    235   }
    236 
    237   // Turns a Closure into a MemoryDumpCallback, keeping track of the callback
    238   // result and taking care of posting the closure on the correct task runner.
    239   void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner,
    240                            Closure closure,
    241                            uint64_t dump_guid,
    242                            bool success) {
    243     last_callback_success_ = success;
    244     task_runner->PostTask(FROM_HERE, closure);
    245   }
    246 
    247   void PollFastMemoryTotal(uint64_t* memory_total) {
    248     mdm_->PollFastMemoryTotal(memory_total);
    249   }
    250 
    251  protected:
    252   void InitializeMemoryDumpManager(bool is_coordinator) {
    253     mdm_->set_dumper_registrations_ignored_for_testing(true);
    254     delegate_ = new MemoryDumpManagerDelegateForTesting(is_coordinator);
    255     mdm_->Initialize(base::WrapUnique(delegate_));
    256   }
    257 
    258   void RequestGlobalDumpAndWait(MemoryDumpType dump_type,
    259                                 MemoryDumpLevelOfDetail level_of_detail) {
    260     RunLoop run_loop;
    261     MemoryDumpCallback callback =
    262         Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this),
    263              ThreadTaskRunnerHandle::Get(), run_loop.QuitClosure());
    264     mdm_->RequestGlobalDump(dump_type, level_of_detail, callback);
    265     run_loop.Run();
    266   }
    267 
    268   void EnableTracingWithLegacyCategories(const char* category) {
    269     TraceLog::GetInstance()->SetEnabled(TraceConfig(category, ""),
    270                                         TraceLog::RECORDING_MODE);
    271   }
    272 
    273   void EnableTracingWithTraceConfig(const std::string& trace_config) {
    274     TraceLog::GetInstance()->SetEnabled(TraceConfig(trace_config),
    275                                         TraceLog::RECORDING_MODE);
    276   }
    277 
    278   void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); }
    279 
    280   bool IsPeriodicDumpingEnabled() const {
    281     return MemoryDumpScheduler::GetInstance()
    282         ->IsPeriodicTimerRunningForTesting();
    283   }
    284 
    285   int GetMaxConsecutiveFailuresCount() const {
    286     return MemoryDumpManager::kMaxConsecutiveFailuresCount;
    287   }
    288 
    289   const MemoryDumpProvider::Options kDefaultOptions;
    290   std::unique_ptr<MemoryDumpManager> mdm_;
    291   MemoryDumpManagerDelegateForTesting* delegate_;
    292   bool last_callback_success_;
    293 
    294  private:
    295   std::unique_ptr<MessageLoop> message_loop_;
    296 
    297   // We want our singleton torn down after each test.
    298   ShadowingAtExitManager at_exit_manager_;
    299 };
    300 
    301 // Basic sanity checks. Registers a memory dump provider and checks that it is
    302 // called, but only when memory-infra is enabled.
    303 TEST_F(MemoryDumpManagerTest, SingleDumper) {
    304   InitializeMemoryDumpManager(false /* is_coordinator */);
    305   MockMemoryDumpProvider mdp;
    306   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
    307 
    308   // Check that the dumper is not called if the memory category is not enabled.
    309   EnableTracingWithLegacyCategories("foobar-but-not-memory");
    310   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(0);
    311   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
    312   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    313                            MemoryDumpLevelOfDetail::DETAILED);
    314   DisableTracing();
    315 
    316   // Now repeat enabling the memory category and check that the dumper is
    317   // invoked this time.
    318   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    319   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(3);
    320   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(3).WillRepeatedly(Return(true));
    321   for (int i = 0; i < 3; ++i)
    322     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    323                              MemoryDumpLevelOfDetail::DETAILED);
    324   DisableTracing();
    325 
    326   mdm_->UnregisterDumpProvider(&mdp);
    327 
    328   // Finally check the unregister logic: the delegate will be invoked but not
    329   // the dump provider, as it has been unregistered.
    330   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    331   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(3);
    332   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
    333 
    334   for (int i = 0; i < 3; ++i) {
    335     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    336                              MemoryDumpLevelOfDetail::DETAILED);
    337   }
    338   DisableTracing();
    339 }
    340 
    341 // Checks that requesting dumps with high level of detail actually propagates
    342 // the level of the detail properly to OnMemoryDump() call on dump providers.
    343 TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgs) {
    344   InitializeMemoryDumpManager(false /* is_coordinator */);
    345   MockMemoryDumpProvider mdp;
    346 
    347   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
    348   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    349   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    350   EXPECT_CALL(mdp, OnMemoryDump(IsDetailedDump(), _)).WillOnce(Return(true));
    351   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    352                            MemoryDumpLevelOfDetail::DETAILED);
    353   DisableTracing();
    354   mdm_->UnregisterDumpProvider(&mdp);
    355 
    356   // Check that requesting dumps with low level of detail actually propagates to
    357   // OnMemoryDump() call on dump providers.
    358   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
    359   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    360   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    361   EXPECT_CALL(mdp, OnMemoryDump(IsLightDump(), _)).WillOnce(Return(true));
    362   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    363                            MemoryDumpLevelOfDetail::LIGHT);
    364   DisableTracing();
    365   mdm_->UnregisterDumpProvider(&mdp);
    366 }
    367 
    368 // Checks that the SharedSessionState object is acqually shared over time.
    369 TEST_F(MemoryDumpManagerTest, SharedSessionState) {
    370   InitializeMemoryDumpManager(false /* is_coordinator */);
    371   MockMemoryDumpProvider mdp1;
    372   MockMemoryDumpProvider mdp2;
    373   RegisterDumpProvider(&mdp1, nullptr);
    374   RegisterDumpProvider(&mdp2, nullptr);
    375 
    376   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    377   const MemoryDumpSessionState* session_state =
    378       mdm_->session_state_for_testing().get();
    379   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(2);
    380   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
    381       .Times(2)
    382       .WillRepeatedly(Invoke([session_state](const MemoryDumpArgs&,
    383                                              ProcessMemoryDump* pmd) -> bool {
    384         EXPECT_EQ(session_state, pmd->session_state().get());
    385         return true;
    386       }));
    387   EXPECT_CALL(mdp2, OnMemoryDump(_, _))
    388       .Times(2)
    389       .WillRepeatedly(Invoke([session_state](const MemoryDumpArgs&,
    390                                              ProcessMemoryDump* pmd) -> bool {
    391         EXPECT_EQ(session_state, pmd->session_state().get());
    392         return true;
    393       }));
    394 
    395   for (int i = 0; i < 2; ++i) {
    396     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    397                              MemoryDumpLevelOfDetail::DETAILED);
    398   }
    399 
    400   DisableTracing();
    401 }
    402 
    403 // Checks that the (Un)RegisterDumpProvider logic behaves sanely.
    404 TEST_F(MemoryDumpManagerTest, MultipleDumpers) {
    405   InitializeMemoryDumpManager(false /* is_coordinator */);
    406   MockMemoryDumpProvider mdp1;
    407   MockMemoryDumpProvider mdp2;
    408 
    409   // Enable only mdp1.
    410   RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get());
    411   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    412   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    413   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).WillOnce(Return(true));
    414   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(0);
    415   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    416                            MemoryDumpLevelOfDetail::DETAILED);
    417   DisableTracing();
    418 
    419   // Invert: enable mdp1 and disable mdp2.
    420   mdm_->UnregisterDumpProvider(&mdp1);
    421   RegisterDumpProvider(&mdp2, nullptr);
    422   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    423   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    424   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0);
    425   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).WillOnce(Return(true));
    426   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    427                            MemoryDumpLevelOfDetail::DETAILED);
    428   DisableTracing();
    429 
    430   // Enable both mdp1 and mdp2.
    431   RegisterDumpProvider(&mdp1, nullptr);
    432   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    433   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    434   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).WillOnce(Return(true));
    435   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).WillOnce(Return(true));
    436   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    437                            MemoryDumpLevelOfDetail::DETAILED);
    438   DisableTracing();
    439 }
    440 
    441 // Checks that the dump provider invocations depend only on the current
    442 // registration state and not on previous registrations and dumps.
    443 // Flaky on iOS, see crbug.com/706874
    444 #if defined(OS_IOS)
    445 #define MAYBE_RegistrationConsistency DISABLED_RegistrationConsistency
    446 #else
    447 #define MAYBE_RegistrationConsistency RegistrationConsistency
    448 #endif
    449 TEST_F(MemoryDumpManagerTest, MAYBE_RegistrationConsistency) {
    450   InitializeMemoryDumpManager(false /* is_coordinator */);
    451   MockMemoryDumpProvider mdp;
    452 
    453   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
    454 
    455   {
    456     EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    457     EXPECT_CALL(mdp, OnMemoryDump(_, _)).WillOnce(Return(true));
    458     EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    459     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    460                              MemoryDumpLevelOfDetail::DETAILED);
    461     DisableTracing();
    462   }
    463 
    464   mdm_->UnregisterDumpProvider(&mdp);
    465 
    466   {
    467     EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    468     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
    469     EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    470     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    471                              MemoryDumpLevelOfDetail::DETAILED);
    472     DisableTracing();
    473   }
    474 
    475   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
    476   mdm_->UnregisterDumpProvider(&mdp);
    477 
    478   {
    479     EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    480     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
    481     EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    482     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    483                              MemoryDumpLevelOfDetail::DETAILED);
    484     DisableTracing();
    485   }
    486 
    487   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
    488   mdm_->UnregisterDumpProvider(&mdp);
    489   RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
    490 
    491   {
    492     EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    493     EXPECT_CALL(mdp, OnMemoryDump(_, _)).WillOnce(Return(true));
    494     EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    495     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    496                              MemoryDumpLevelOfDetail::DETAILED);
    497     DisableTracing();
    498   }
    499 }
    500 
    501 // Checks that the MemoryDumpManager respects the thread affinity when a
    502 // MemoryDumpProvider specifies a task_runner(). The test starts creating 8
    503 // threads and registering a MemoryDumpProvider on each of them. At each
    504 // iteration, one thread is removed, to check the live unregistration logic.
    505 TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) {
    506   InitializeMemoryDumpManager(false /* is_coordinator */);
    507   const uint32_t kNumInitialThreads = 8;
    508 
    509   std::vector<std::unique_ptr<Thread>> threads;
    510   std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps;
    511 
    512   // Create the threads and setup the expectations. Given that at each iteration
    513   // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be
    514   // invoked a number of times equal to its index.
    515   for (uint32_t i = kNumInitialThreads; i > 0; --i) {
    516     threads.push_back(WrapUnique(new Thread("test thread")));
    517     auto* thread = threads.back().get();
    518     thread->Start();
    519     scoped_refptr<SingleThreadTaskRunner> task_runner = thread->task_runner();
    520     mdps.push_back(WrapUnique(new MockMemoryDumpProvider()));
    521     auto* mdp = mdps.back().get();
    522     RegisterDumpProvider(mdp, task_runner, kDefaultOptions);
    523     EXPECT_CALL(*mdp, OnMemoryDump(_, _))
    524         .Times(i)
    525         .WillRepeatedly(Invoke(
    526             [task_runner](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
    527               EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread());
    528               return true;
    529             }));
    530   }
    531   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    532 
    533   while (!threads.empty()) {
    534     last_callback_success_ = false;
    535     EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    536     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    537                              MemoryDumpLevelOfDetail::DETAILED);
    538     EXPECT_TRUE(last_callback_success_);
    539 
    540     // Unregister a MDP and destroy one thread at each iteration to check the
    541     // live unregistration logic. The unregistration needs to happen on the same
    542     // thread the MDP belongs to.
    543     {
    544       RunLoop run_loop;
    545       Closure unregistration =
    546           Bind(&MemoryDumpManager::UnregisterDumpProvider,
    547                Unretained(mdm_.get()), Unretained(mdps.back().get()));
    548       threads.back()->task_runner()->PostTaskAndReply(FROM_HERE, unregistration,
    549                                                       run_loop.QuitClosure());
    550       run_loop.Run();
    551     }
    552     mdps.pop_back();
    553     threads.back()->Stop();
    554     threads.pop_back();
    555   }
    556 
    557   DisableTracing();
    558 }
    559 
    560 // Check that the memory dump calls are always posted on task runner for
    561 // SequencedTaskRunner case and that the dump provider gets disabled when
    562 // PostTask fails, but the dump still succeeds.
    563 TEST_F(MemoryDumpManagerTest, PostTaskForSequencedTaskRunner) {
    564   InitializeMemoryDumpManager(false /* is_coordinator */);
    565   std::vector<MockMemoryDumpProvider> mdps(3);
    566   scoped_refptr<TestSequencedTaskRunner> task_runner1(
    567       make_scoped_refptr(new TestSequencedTaskRunner()));
    568   scoped_refptr<TestSequencedTaskRunner> task_runner2(
    569       make_scoped_refptr(new TestSequencedTaskRunner()));
    570   RegisterDumpProviderWithSequencedTaskRunner(&mdps[0], task_runner1,
    571                                               kDefaultOptions);
    572   RegisterDumpProviderWithSequencedTaskRunner(&mdps[1], task_runner2,
    573                                               kDefaultOptions);
    574   RegisterDumpProviderWithSequencedTaskRunner(&mdps[2], task_runner2,
    575                                               kDefaultOptions);
    576   // |mdps[0]| should be disabled permanently after first dump.
    577   EXPECT_CALL(mdps[0], OnMemoryDump(_, _)).Times(0);
    578   EXPECT_CALL(mdps[1], OnMemoryDump(_, _)).Times(2);
    579   EXPECT_CALL(mdps[2], OnMemoryDump(_, _)).Times(2);
    580   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(2);
    581 
    582   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    583 
    584   task_runner1->set_enabled(false);
    585   last_callback_success_ = false;
    586   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    587                            MemoryDumpLevelOfDetail::DETAILED);
    588   // Tasks should be individually posted even if |mdps[1]| and |mdps[2]| belong
    589   // to same task runner.
    590   EXPECT_EQ(1u, task_runner1->no_of_post_tasks());
    591   EXPECT_EQ(2u, task_runner2->no_of_post_tasks());
    592   EXPECT_TRUE(last_callback_success_);
    593 
    594   task_runner1->set_enabled(true);
    595   last_callback_success_ = false;
    596   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    597                            MemoryDumpLevelOfDetail::DETAILED);
    598   EXPECT_EQ(2u, task_runner1->no_of_post_tasks());
    599   EXPECT_EQ(4u, task_runner2->no_of_post_tasks());
    600   EXPECT_TRUE(last_callback_success_);
    601   DisableTracing();
    602 }
    603 
    604 // Checks that providers get disabled after 3 consecutive failures, but not
    605 // otherwise (e.g., if interleaved).
    606 TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) {
    607   InitializeMemoryDumpManager(false /* is_coordinator */);
    608   MockMemoryDumpProvider mdp1;
    609   MockMemoryDumpProvider mdp2;
    610 
    611   RegisterDumpProvider(&mdp1, nullptr);
    612   RegisterDumpProvider(&mdp2, nullptr);
    613   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    614 
    615   const int kNumDumps = 2 * GetMaxConsecutiveFailuresCount();
    616   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(kNumDumps);
    617 
    618   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
    619       .Times(GetMaxConsecutiveFailuresCount())
    620       .WillRepeatedly(Return(false));
    621 
    622   EXPECT_CALL(mdp2, OnMemoryDump(_, _))
    623       .WillOnce(Return(false))
    624       .WillOnce(Return(true))
    625       .WillOnce(Return(false))
    626       .WillOnce(Return(false))
    627       .WillOnce(Return(true))
    628       .WillOnce(Return(false));
    629 
    630   for (int i = 0; i < kNumDumps; i++) {
    631     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    632                              MemoryDumpLevelOfDetail::DETAILED);
    633   }
    634 
    635   DisableTracing();
    636 }
    637 
    638 // Sneakily registers an extra memory dump provider while an existing one is
    639 // dumping and expect it to take part in the already active tracing session.
    640 TEST_F(MemoryDumpManagerTest, RegisterDumperWhileDumping) {
    641   InitializeMemoryDumpManager(false /* is_coordinator */);
    642   MockMemoryDumpProvider mdp1;
    643   MockMemoryDumpProvider mdp2;
    644 
    645   RegisterDumpProvider(&mdp1, nullptr);
    646   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    647 
    648   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(4);
    649 
    650   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
    651       .Times(4)
    652       .WillOnce(Return(true))
    653       .WillOnce(
    654           Invoke([&mdp2](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
    655             RegisterDumpProvider(&mdp2, nullptr);
    656             return true;
    657           }))
    658       .WillRepeatedly(Return(true));
    659 
    660   // Depending on the insertion order (before or after mdp1), mdp2 might be
    661   // called also immediately after it gets registered.
    662   EXPECT_CALL(mdp2, OnMemoryDump(_, _))
    663       .Times(Between(2, 3))
    664       .WillRepeatedly(Return(true));
    665 
    666   for (int i = 0; i < 4; i++) {
    667     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    668                              MemoryDumpLevelOfDetail::DETAILED);
    669   }
    670 
    671   DisableTracing();
    672 }
    673 
    674 // Like RegisterDumperWhileDumping, but unregister the dump provider instead.
    675 TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileDumping) {
    676   InitializeMemoryDumpManager(false /* is_coordinator */);
    677   MockMemoryDumpProvider mdp1;
    678   MockMemoryDumpProvider mdp2;
    679 
    680   RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get(), kDefaultOptions);
    681   RegisterDumpProvider(&mdp2, ThreadTaskRunnerHandle::Get(), kDefaultOptions);
    682   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    683 
    684   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(4);
    685 
    686   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
    687       .Times(4)
    688       .WillOnce(Return(true))
    689       .WillOnce(
    690           Invoke([&mdp2](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
    691             MemoryDumpManager::GetInstance()->UnregisterDumpProvider(&mdp2);
    692             return true;
    693           }))
    694       .WillRepeatedly(Return(true));
    695 
    696   // Depending on the insertion order (before or after mdp1), mdp2 might have
    697   // been already called when UnregisterDumpProvider happens.
    698   EXPECT_CALL(mdp2, OnMemoryDump(_, _))
    699       .Times(Between(1, 2))
    700       .WillRepeatedly(Return(true));
    701 
    702   for (int i = 0; i < 4; i++) {
    703     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    704                              MemoryDumpLevelOfDetail::DETAILED);
    705   }
    706 
    707   DisableTracing();
    708 }
    709 
    710 // Checks that the dump does not abort when unregistering a provider while
    711 // dumping from a different thread than the dumping thread.
    712 TEST_F(MemoryDumpManagerTest, UnregisterDumperFromThreadWhileDumping) {
    713   InitializeMemoryDumpManager(false /* is_coordinator */);
    714   std::vector<std::unique_ptr<TestIOThread>> threads;
    715   std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps;
    716 
    717   for (int i = 0; i < 2; i++) {
    718     threads.push_back(
    719         WrapUnique(new TestIOThread(TestIOThread::kAutoStart)));
    720     mdps.push_back(WrapUnique(new MockMemoryDumpProvider()));
    721     RegisterDumpProvider(mdps.back().get(), threads.back()->task_runner(),
    722                          kDefaultOptions);
    723   }
    724 
    725   int on_memory_dump_call_count = 0;
    726 
    727   // When OnMemoryDump is called on either of the dump providers, it will
    728   // unregister the other one.
    729   for (const std::unique_ptr<MockMemoryDumpProvider>& mdp : mdps) {
    730     int other_idx = (mdps.front() == mdp);
    731     // TestIOThread's task runner must be obtained from the main thread but can
    732     // then be used from other threads.
    733     scoped_refptr<SingleThreadTaskRunner> other_runner =
    734         threads[other_idx]->task_runner();
    735     MockMemoryDumpProvider* other_mdp = mdps[other_idx].get();
    736     auto on_dump = [this, other_runner, other_mdp, &on_memory_dump_call_count](
    737         const MemoryDumpArgs& args, ProcessMemoryDump* pmd) {
    738       PostTaskAndWait(FROM_HERE, other_runner.get(),
    739                       base::Bind(&MemoryDumpManager::UnregisterDumpProvider,
    740                                  base::Unretained(&*mdm_), other_mdp));
    741       on_memory_dump_call_count++;
    742       return true;
    743     };
    744 
    745     // OnMemoryDump is called once for the provider that dumps first, and zero
    746     // times for the other provider.
    747     EXPECT_CALL(*mdp, OnMemoryDump(_, _))
    748         .Times(AtMost(1))
    749         .WillOnce(Invoke(on_dump));
    750   }
    751 
    752   last_callback_success_ = false;
    753   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    754   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    755   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    756                            MemoryDumpLevelOfDetail::DETAILED);
    757   ASSERT_EQ(1, on_memory_dump_call_count);
    758   ASSERT_TRUE(last_callback_success_);
    759 
    760   DisableTracing();
    761 }
    762 
    763 TEST_F(MemoryDumpManagerTest, TestPollingOnDumpThread) {
    764   InitializeMemoryDumpManager(false /* is_coordinator */);
    765   std::unique_ptr<MockMemoryDumpProvider> mdp1(new MockMemoryDumpProvider());
    766   std::unique_ptr<MockMemoryDumpProvider> mdp2(new MockMemoryDumpProvider());
    767   mdp1->enable_mock_destructor = true;
    768   mdp2->enable_mock_destructor = true;
    769 
    770   EXPECT_CALL(*mdp1, SuspendFastMemoryPolling()).Times(1);
    771   EXPECT_CALL(*mdp2, SuspendFastMemoryPolling()).Times(1);
    772   EXPECT_CALL(*mdp1, Destructor());
    773   EXPECT_CALL(*mdp2, Destructor());
    774 
    775   MemoryDumpProvider::Options options;
    776   options.is_fast_polling_supported = true;
    777   RegisterDumpProvider(mdp1.get(), nullptr, options);
    778 
    779   RunLoop run_loop;
    780   scoped_refptr<SingleThreadTaskRunner> test_task_runner =
    781       ThreadTaskRunnerHandle::Get();
    782   auto quit_closure = run_loop.QuitClosure();
    783 
    784   const int kPollsToQuit = 10;
    785   int call_count = 0;
    786   MemoryDumpManager* mdm = mdm_.get();
    787   const auto poll_function1 = [&call_count, &test_task_runner, quit_closure,
    788                                &mdp2, mdm, &options, kPollsToQuit,
    789                                this](uint64_t* total) -> void {
    790     ++call_count;
    791     if (call_count == 1)
    792       RegisterDumpProvider(mdp2.get(), nullptr, options, kMDPName);
    793     else if (call_count == 4)
    794       mdm->UnregisterAndDeleteDumpProviderSoon(std::move(mdp2));
    795     else if (call_count == kPollsToQuit)
    796       test_task_runner->PostTask(FROM_HERE, quit_closure);
    797 
    798     // Record increase of 1 GiB of memory at each call.
    799     *total = static_cast<uint64_t>(call_count) * 1024 * 1024 * 1024;
    800   };
    801   EXPECT_CALL(*mdp1, PollFastMemoryTotal(_))
    802       .Times(testing::AtLeast(kPollsToQuit))
    803       .WillRepeatedly(Invoke(poll_function1));
    804 
    805   // Depending on the order of PostTask calls the mdp2 might be registered after
    806   // all polls or in between polls.
    807   EXPECT_CALL(*mdp2, PollFastMemoryTotal(_))
    808       .Times(Between(0, kPollsToQuit - 1))
    809       .WillRepeatedly(Return());
    810 
    811   MemoryDumpScheduler::SetPollingIntervalForTesting(1);
    812   EnableTracingWithTraceConfig(
    813       TraceConfigMemoryTestUtil::GetTraceConfig_PeakDetectionTrigger(3));
    814 
    815   int last_poll_to_request_dump = -2;
    816   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _))
    817       .Times(testing::AtLeast(2))
    818       .WillRepeatedly(Invoke([&last_poll_to_request_dump, &call_count](
    819                                  const MemoryDumpRequestArgs& args,
    820                                  const MemoryDumpCallback& callback) -> void {
    821         // Minimum number of polls between dumps must be 3 (polling interval is
    822         // 1ms).
    823         EXPECT_GE(call_count - last_poll_to_request_dump, 3);
    824         last_poll_to_request_dump = call_count;
    825       }));
    826 
    827   run_loop.Run();
    828   DisableTracing();
    829   mdm_->UnregisterAndDeleteDumpProviderSoon(std::move(mdp1));
    830 }
    831 
    832 // If a thread (with a dump provider living on it) is torn down during a dump
    833 // its dump provider should be skipped but the dump itself should succeed.
    834 TEST_F(MemoryDumpManagerTest, TearDownThreadWhileDumping) {
    835   InitializeMemoryDumpManager(false /* is_coordinator */);
    836   std::vector<std::unique_ptr<TestIOThread>> threads;
    837   std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps;
    838 
    839   for (int i = 0; i < 2; i++) {
    840     threads.push_back(
    841         WrapUnique(new TestIOThread(TestIOThread::kAutoStart)));
    842     mdps.push_back(WrapUnique(new MockMemoryDumpProvider()));
    843     RegisterDumpProvider(mdps.back().get(), threads.back()->task_runner(),
    844                          kDefaultOptions);
    845   }
    846 
    847   int on_memory_dump_call_count = 0;
    848 
    849   // When OnMemoryDump is called on either of the dump providers, it will
    850   // tear down the thread of the other one.
    851   for (const std::unique_ptr<MockMemoryDumpProvider>& mdp : mdps) {
    852     int other_idx = (mdps.front() == mdp);
    853     TestIOThread* other_thread = threads[other_idx].get();
    854     // TestIOThread isn't thread-safe and must be stopped on the |main_runner|.
    855     scoped_refptr<SequencedTaskRunner> main_runner =
    856         SequencedTaskRunnerHandle::Get();
    857     auto on_dump = [other_thread, main_runner, &on_memory_dump_call_count](
    858         const MemoryDumpArgs& args, ProcessMemoryDump* pmd) {
    859       PostTaskAndWait(
    860           FROM_HERE, main_runner.get(),
    861           base::Bind(&TestIOThread::Stop, base::Unretained(other_thread)));
    862       on_memory_dump_call_count++;
    863       return true;
    864     };
    865 
    866     // OnMemoryDump is called once for the provider that dumps first, and zero
    867     // times for the other provider.
    868     EXPECT_CALL(*mdp, OnMemoryDump(_, _))
    869         .Times(AtMost(1))
    870         .WillOnce(Invoke(on_dump));
    871   }
    872 
    873   last_callback_success_ = false;
    874   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    875   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    876   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    877                            MemoryDumpLevelOfDetail::DETAILED);
    878   ASSERT_EQ(1, on_memory_dump_call_count);
    879   ASSERT_TRUE(last_callback_success_);
    880 
    881   DisableTracing();
    882 }
    883 
    884 // Checks that a NACK callback is invoked if RequestGlobalDump() is called when
    885 // tracing is not enabled.
    886 TEST_F(MemoryDumpManagerTest, CallbackCalledOnFailure) {
    887   InitializeMemoryDumpManager(false /* is_coordinator */);
    888   MockMemoryDumpProvider mdp1;
    889   RegisterDumpProvider(&mdp1, nullptr);
    890 
    891   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(0);
    892   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0);
    893 
    894   last_callback_success_ = true;
    895   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    896                            MemoryDumpLevelOfDetail::DETAILED);
    897   EXPECT_FALSE(last_callback_success_);
    898 }
    899 
    900 // Checks that is the MemoryDumpManager is initialized after tracing already
    901 // began, it will still late-join the party (real use case: startup tracing).
    902 TEST_F(MemoryDumpManagerTest, InitializedAfterStartOfTracing) {
    903   MockMemoryDumpProvider mdp;
    904   RegisterDumpProvider(&mdp, nullptr);
    905   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    906 
    907   // First check that a RequestGlobalDump() issued before the MemoryDumpManager
    908   // initialization gets NACK-ed cleanly.
    909   {
    910     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
    911     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    912                              MemoryDumpLevelOfDetail::DETAILED);
    913     EXPECT_FALSE(last_callback_success_);
    914   }
    915 
    916   // Now late-initialize the MemoryDumpManager and check that the
    917   // RequestGlobalDump completes successfully.
    918   {
    919     InitializeMemoryDumpManager(false /* is_coordinator */);
    920     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(1);
    921     EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
    922     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
    923                              MemoryDumpLevelOfDetail::DETAILED);
    924     EXPECT_TRUE(last_callback_success_);
    925   }
    926   DisableTracing();
    927 }
    928 
    929 // This test (and the MemoryDumpManagerTestCoordinator below) crystallizes the
    930 // expectations of the chrome://tracing UI and chrome telemetry w.r.t. periodic
    931 // dumps in memory-infra, handling gracefully the transition between the legacy
    932 // and the new-style (JSON-based) TraceConfig.
    933 TEST_F(MemoryDumpManagerTest, TraceConfigExpectations) {
    934   InitializeMemoryDumpManager(false /* is_coordinator */);
    935   MemoryDumpManagerDelegateForTesting& delegate = *delegate_;
    936 
    937   // Don't trigger the default behavior of the mock delegate in this test,
    938   // which would short-circuit the dump request to the actual
    939   // CreateProcessDump().
    940   // We don't want to create any dump in this test, only check whether the dumps
    941   // are requested or not.
    942   ON_CALL(delegate, RequestGlobalMemoryDump(_, _)).WillByDefault(Return());
    943 
    944   // Enabling memory-infra in a non-coordinator process should not trigger any
    945   // periodic dumps.
    946   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    947   EXPECT_FALSE(IsPeriodicDumpingEnabled());
    948   DisableTracing();
    949 
    950   // Enabling memory-infra with the new (JSON) TraceConfig in a non-coordinator
    951   // process with a fully defined trigger config should NOT enable any periodic
    952   // dumps.
    953   EnableTracingWithTraceConfig(
    954       TraceConfigMemoryTestUtil::GetTraceConfig_PeriodicTriggers(1, 5));
    955   EXPECT_FALSE(IsPeriodicDumpingEnabled());
    956   DisableTracing();
    957 }
    958 
    959 TEST_F(MemoryDumpManagerTest, TraceConfigExpectationsWhenIsCoordinator) {
    960   InitializeMemoryDumpManager(true /* is_coordinator */);
    961   MemoryDumpManagerDelegateForTesting& delegate = *delegate_;
    962   ON_CALL(delegate, RequestGlobalMemoryDump(_, _)).WillByDefault(Return());
    963 
    964   // Enabling memory-infra with the legacy TraceConfig (category filter) in
    965   // a coordinator process should enable periodic dumps.
    966   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
    967   EXPECT_TRUE(IsPeriodicDumpingEnabled());
    968   DisableTracing();
    969 
    970   // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator
    971   // process without specifying any "memory_dump_config" section should enable
    972   // periodic dumps. This is to preserve the behavior chrome://tracing UI, that
    973   // is: ticking memory-infra should dump periodically with the default config.
    974   EnableTracingWithTraceConfig(
    975       TraceConfigMemoryTestUtil::GetTraceConfig_NoTriggers());
    976   EXPECT_TRUE(IsPeriodicDumpingEnabled());
    977   DisableTracing();
    978 
    979   // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator
    980   // process with an empty "memory_dump_config" should NOT enable periodic
    981   // dumps. This is the way telemetry is supposed to use memory-infra with
    982   // only explicitly triggered dumps.
    983   EnableTracingWithTraceConfig(
    984       TraceConfigMemoryTestUtil::GetTraceConfig_EmptyTriggers());
    985   EXPECT_FALSE(IsPeriodicDumpingEnabled());
    986   DisableTracing();
    987 
    988   // Enabling memory-infra with the new (JSON) TraceConfig in a coordinator
    989   // process with a fully defined trigger config should cause periodic dumps to
    990   // be performed in the correct order.
    991   RunLoop run_loop;
    992   auto quit_closure = run_loop.QuitClosure();
    993 
    994   const int kHeavyDumpRate = 5;
    995   const int kLightDumpPeriodMs = 1;
    996   const int kHeavyDumpPeriodMs = kHeavyDumpRate * kLightDumpPeriodMs;
    997   // The expected sequence with light=1ms, heavy=5ms is H,L,L,L,L,H,...
    998   testing::InSequence sequence;
    999   EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsDetailedDump(), _));
   1000   EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLightDump(), _))
   1001       .Times(kHeavyDumpRate - 1);
   1002   EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsDetailedDump(), _));
   1003   EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLightDump(), _))
   1004       .Times(kHeavyDumpRate - 2);
   1005   EXPECT_CALL(delegate, RequestGlobalMemoryDump(IsLightDump(), _))
   1006       .WillOnce(Invoke([quit_closure](const MemoryDumpRequestArgs& args,
   1007                                       const MemoryDumpCallback& callback) {
   1008         ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure);
   1009       }));
   1010 
   1011   // Swallow all the final spurious calls until tracing gets disabled.
   1012   EXPECT_CALL(delegate, RequestGlobalMemoryDump(_, _)).Times(AnyNumber());
   1013 
   1014   EnableTracingWithTraceConfig(
   1015       TraceConfigMemoryTestUtil::GetTraceConfig_PeriodicTriggers(
   1016           kLightDumpPeriodMs, kHeavyDumpPeriodMs));
   1017   run_loop.Run();
   1018   DisableTracing();
   1019 }
   1020 
   1021 // Tests against race conditions that might arise when disabling tracing in the
   1022 // middle of a global memory dump.
   1023 // Flaky on iOS, see crbug.com/706961
   1024 #if defined(OS_IOS)
   1025 #define MAYBE_DisableTracingWhileDumping DISABLED_DisableTracingWhileDumping
   1026 #else
   1027 #define MAYBE_DisableTracingWhileDumping DisableTracingWhileDumping
   1028 #endif
   1029 TEST_F(MemoryDumpManagerTest, MAYBE_DisableTracingWhileDumping) {
   1030   base::WaitableEvent tracing_disabled_event(
   1031       WaitableEvent::ResetPolicy::AUTOMATIC,
   1032       WaitableEvent::InitialState::NOT_SIGNALED);
   1033   InitializeMemoryDumpManager(false /* is_coordinator */);
   1034 
   1035   // Register a bound dump provider.
   1036   std::unique_ptr<Thread> mdp_thread(new Thread("test thread"));
   1037   mdp_thread->Start();
   1038   MockMemoryDumpProvider mdp_with_affinity;
   1039   RegisterDumpProvider(&mdp_with_affinity, mdp_thread->task_runner(),
   1040                        kDefaultOptions);
   1041 
   1042   // Register also an unbound dump provider. Unbound dump providers are always
   1043   // invoked after bound ones.
   1044   MockMemoryDumpProvider unbound_mdp;
   1045   RegisterDumpProvider(&unbound_mdp, nullptr, kDefaultOptions);
   1046 
   1047   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
   1048   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
   1049   EXPECT_CALL(mdp_with_affinity, OnMemoryDump(_, _))
   1050       .Times(1)
   1051       .WillOnce(
   1052           Invoke([&tracing_disabled_event](const MemoryDumpArgs&,
   1053                                            ProcessMemoryDump* pmd) -> bool {
   1054             tracing_disabled_event.Wait();
   1055 
   1056             // At this point tracing has been disabled and the
   1057             // MemoryDumpManager.dump_thread_ has been shut down.
   1058             return true;
   1059           }));
   1060 
   1061   // |unbound_mdp| should never be invoked because the thread for unbound dump
   1062   // providers has been shutdown in the meanwhile.
   1063   EXPECT_CALL(unbound_mdp, OnMemoryDump(_, _)).Times(0);
   1064 
   1065   last_callback_success_ = true;
   1066   RunLoop run_loop;
   1067   MemoryDumpCallback callback =
   1068       Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this),
   1069            ThreadTaskRunnerHandle::Get(), run_loop.QuitClosure());
   1070   mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED,
   1071                           MemoryDumpLevelOfDetail::DETAILED, callback);
   1072   DisableTracing();
   1073   tracing_disabled_event.Signal();
   1074   run_loop.Run();
   1075 
   1076   EXPECT_FALSE(last_callback_success_);
   1077 }
   1078 
   1079 // Tests against race conditions that can happen if tracing is disabled before
   1080 // the CreateProcessDump() call. Real-world regression: crbug.com/580295 .
   1081 TEST_F(MemoryDumpManagerTest, DisableTracingRightBeforeStartOfDump) {
   1082   base::WaitableEvent tracing_disabled_event(
   1083       WaitableEvent::ResetPolicy::AUTOMATIC,
   1084       WaitableEvent::InitialState::NOT_SIGNALED);
   1085   InitializeMemoryDumpManager(false /* is_coordinator */);
   1086 
   1087   std::unique_ptr<Thread> mdp_thread(new Thread("test thread"));
   1088   mdp_thread->Start();
   1089 
   1090   // Create both same-thread MDP and another MDP with dedicated thread
   1091   MockMemoryDumpProvider mdp1;
   1092   RegisterDumpProvider(&mdp1, nullptr);
   1093   MockMemoryDumpProvider mdp2;
   1094   RegisterDumpProvider(&mdp2, mdp_thread->task_runner(), kDefaultOptions);
   1095   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
   1096 
   1097   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _))
   1098       .WillOnce(Invoke([this](const MemoryDumpRequestArgs& args,
   1099                               const MemoryDumpCallback& callback) {
   1100         DisableTracing();
   1101         delegate_->CreateProcessDump(args, callback);
   1102       }));
   1103 
   1104   // If tracing is disabled for current session CreateProcessDump() should NOT
   1105   // request dumps from providers. Real-world regression: crbug.com/600570 .
   1106   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0);
   1107   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(0);
   1108 
   1109   last_callback_success_ = true;
   1110   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
   1111                            MemoryDumpLevelOfDetail::DETAILED);
   1112   EXPECT_FALSE(last_callback_success_);
   1113 }
   1114 
   1115 TEST_F(MemoryDumpManagerTest, DumpOnBehalfOfOtherProcess) {
   1116   using trace_analyzer::Query;
   1117 
   1118   InitializeMemoryDumpManager(false /* is_coordinator */);
   1119 
   1120   // Standard provider with default options (create dump for current process).
   1121   MemoryDumpProvider::Options options;
   1122   MockMemoryDumpProvider mdp1;
   1123   RegisterDumpProvider(&mdp1, nullptr, options);
   1124 
   1125   // Provider with out-of-process dumping.
   1126   MockMemoryDumpProvider mdp2;
   1127   options.target_pid = 123;
   1128   RegisterDumpProvider(&mdp2, nullptr, options);
   1129 
   1130   // Another provider with out-of-process dumping.
   1131   MockMemoryDumpProvider mdp3;
   1132   options.target_pid = 456;
   1133   RegisterDumpProvider(&mdp3, nullptr, options);
   1134 
   1135   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
   1136   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
   1137   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true));
   1138   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true));
   1139   EXPECT_CALL(mdp3, OnMemoryDump(_, _)).Times(1).WillRepeatedly(Return(true));
   1140   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
   1141                            MemoryDumpLevelOfDetail::DETAILED);
   1142   DisableTracing();
   1143 
   1144   // Flush the trace into JSON.
   1145   trace_event::TraceResultBuffer buffer;
   1146   TraceResultBuffer::SimpleOutput trace_output;
   1147   buffer.SetOutputCallback(trace_output.GetCallback());
   1148   RunLoop run_loop;
   1149   buffer.Start();
   1150   trace_event::TraceLog::GetInstance()->Flush(
   1151       Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
   1152   run_loop.Run();
   1153   buffer.Finish();
   1154 
   1155   // Analyze the JSON.
   1156   std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer = WrapUnique(
   1157       trace_analyzer::TraceAnalyzer::Create(trace_output.json_output));
   1158   trace_analyzer::TraceEventVector events;
   1159   analyzer->FindEvents(Query::EventPhaseIs(TRACE_EVENT_PHASE_MEMORY_DUMP),
   1160                        &events);
   1161 
   1162   ASSERT_EQ(3u, events.size());
   1163   ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(123)));
   1164   ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(456)));
   1165   ASSERT_EQ(1u, trace_analyzer::CountMatches(
   1166                     events, Query::EventPidIs(GetCurrentProcId())));
   1167   ASSERT_EQ(events[0]->id, events[1]->id);
   1168   ASSERT_EQ(events[0]->id, events[2]->id);
   1169 }
   1170 
   1171 // Tests the basics of the UnregisterAndDeleteDumpProviderSoon(): the
   1172 // unregistration should actually delete the providers and not leak them.
   1173 TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoon) {
   1174   InitializeMemoryDumpManager(false /* is_coordinator */);
   1175   static const int kNumProviders = 3;
   1176   int dtor_count = 0;
   1177   std::vector<std::unique_ptr<MemoryDumpProvider>> mdps;
   1178   for (int i = 0; i < kNumProviders; ++i) {
   1179     std::unique_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider);
   1180     mdp->enable_mock_destructor = true;
   1181     EXPECT_CALL(*mdp, Destructor())
   1182         .WillOnce(Invoke([&dtor_count]() { dtor_count++; }));
   1183     RegisterDumpProvider(mdp.get(), nullptr, kDefaultOptions);
   1184     mdps.push_back(std::move(mdp));
   1185   }
   1186 
   1187   while (!mdps.empty()) {
   1188     mdm_->UnregisterAndDeleteDumpProviderSoon(std::move(mdps.back()));
   1189     mdps.pop_back();
   1190   }
   1191 
   1192   ASSERT_EQ(kNumProviders, dtor_count);
   1193 }
   1194 
   1195 // This test checks against races when unregistering an unbound dump provider
   1196 // from another thread while dumping. It registers one MDP and, when
   1197 // OnMemoryDump() is called, it invokes UnregisterAndDeleteDumpProviderSoon()
   1198 // from another thread. The OnMemoryDump() and the dtor call are expected to
   1199 // happen on the same thread (the MemoryDumpManager utility thread).
   1200 TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoonDuringDump) {
   1201   InitializeMemoryDumpManager(false /* is_coordinator */);
   1202   std::unique_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider);
   1203   mdp->enable_mock_destructor = true;
   1204   RegisterDumpProvider(mdp.get(), nullptr, kDefaultOptions);
   1205 
   1206   base::PlatformThreadRef thread_ref;
   1207   auto self_unregister_from_another_thread = [&mdp, &thread_ref](
   1208       const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
   1209     thread_ref = PlatformThread::CurrentRef();
   1210     TestIOThread thread_for_unregistration(TestIOThread::kAutoStart);
   1211     PostTaskAndWait(
   1212         FROM_HERE, thread_for_unregistration.task_runner().get(),
   1213         base::Bind(
   1214             &MemoryDumpManager::UnregisterAndDeleteDumpProviderSoon,
   1215             base::Unretained(MemoryDumpManager::GetInstance()),
   1216             base::Passed(std::unique_ptr<MemoryDumpProvider>(std::move(mdp)))));
   1217     thread_for_unregistration.Stop();
   1218     return true;
   1219   };
   1220   EXPECT_CALL(*mdp, OnMemoryDump(_, _))
   1221       .Times(1)
   1222       .WillOnce(Invoke(self_unregister_from_another_thread));
   1223   EXPECT_CALL(*mdp, Destructor())
   1224       .Times(1)
   1225       .WillOnce(Invoke([&thread_ref]() {
   1226         EXPECT_EQ(thread_ref, PlatformThread::CurrentRef());
   1227       }));
   1228 
   1229   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
   1230   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(2);
   1231   for (int i = 0; i < 2; ++i) {
   1232     RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
   1233                              MemoryDumpLevelOfDetail::DETAILED);
   1234   }
   1235   DisableTracing();
   1236 }
   1237 
   1238 TEST_F(MemoryDumpManagerTest, TestWhitelistingMDP) {
   1239   InitializeMemoryDumpManager(false /* is_coordinator */);
   1240   SetDumpProviderWhitelistForTesting(kTestMDPWhitelist);
   1241   std::unique_ptr<MockMemoryDumpProvider> mdp1(new MockMemoryDumpProvider);
   1242   RegisterDumpProvider(mdp1.get(), nullptr);
   1243   std::unique_ptr<MockMemoryDumpProvider> mdp2(new MockMemoryDumpProvider);
   1244   RegisterDumpProvider(mdp2.get(), nullptr, kDefaultOptions,
   1245                        kWhitelistedMDPName);
   1246 
   1247   EXPECT_CALL(*mdp1, OnMemoryDump(_, _)).Times(0);
   1248   EXPECT_CALL(*mdp2, OnMemoryDump(_, _)).Times(1).WillOnce(Return(true));
   1249   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1);
   1250 
   1251   EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory);
   1252   EXPECT_FALSE(IsPeriodicDumpingEnabled());
   1253   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
   1254                            MemoryDumpLevelOfDetail::BACKGROUND);
   1255   DisableTracing();
   1256 }
   1257 
   1258 TEST_F(MemoryDumpManagerTest, TestBackgroundTracingSetup) {
   1259   InitializeMemoryDumpManager(true /* is_coordinator */);
   1260 
   1261   RunLoop run_loop;
   1262   auto quit_closure = run_loop.QuitClosure();
   1263 
   1264   testing::InSequence sequence;
   1265   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(IsBackgroundDump(), _))
   1266       .Times(5);
   1267   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(IsBackgroundDump(), _))
   1268       .WillOnce(Invoke([quit_closure](const MemoryDumpRequestArgs& args,
   1269                                       const MemoryDumpCallback& callback) {
   1270         ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure);
   1271       }));
   1272   EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(AnyNumber());
   1273 
   1274   EnableTracingWithTraceConfig(
   1275       TraceConfigMemoryTestUtil::GetTraceConfig_BackgroundTrigger(
   1276           1 /* period_ms */));
   1277 
   1278   // Only background mode dumps should be allowed with the trace config.
   1279   last_callback_success_ = false;
   1280   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
   1281                            MemoryDumpLevelOfDetail::LIGHT);
   1282   EXPECT_FALSE(last_callback_success_);
   1283   last_callback_success_ = false;
   1284   RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
   1285                            MemoryDumpLevelOfDetail::DETAILED);
   1286   EXPECT_FALSE(last_callback_success_);
   1287 
   1288   ASSERT_TRUE(IsPeriodicDumpingEnabled());
   1289   run_loop.Run();
   1290   DisableTracing();
   1291 }
   1292 
   1293 TEST_F(MemoryDumpManagerTest, TestBlacklistedUnsafeUnregistration) {
   1294   InitializeMemoryDumpManager(false /* is_coordinator */);
   1295   MockMemoryDumpProvider mdp1;
   1296   RegisterDumpProvider(&mdp1, nullptr, kDefaultOptions,
   1297                        "BlacklistTestDumpProvider");
   1298   // Not calling UnregisterAndDeleteDumpProviderSoon() should not crash.
   1299   mdm_->UnregisterDumpProvider(&mdp1);
   1300 
   1301   Thread thread("test thread");
   1302   thread.Start();
   1303   RegisterDumpProvider(&mdp1, thread.task_runner(), kDefaultOptions,
   1304                        "BlacklistTestDumpProvider");
   1305   // Unregistering on wrong thread should not crash.
   1306   mdm_->UnregisterDumpProvider(&mdp1);
   1307   thread.Stop();
   1308 }
   1309 
   1310 }  // namespace trace_event
   1311 }  // namespace base
   1312