• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
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 <string_view>
11 #include <utility>
12 #include <vector>
13 
14 #include "base/allocator/buildflags.h"
15 #include "base/at_exit.h"
16 #include "base/base_switches.h"
17 #include "base/command_line.h"
18 #include "base/functional/bind.h"
19 #include "base/functional/callback.h"
20 #include "base/run_loop.h"
21 #include "base/synchronization/waitable_event.h"
22 #include "base/task/sequenced_task_runner.h"
23 #include "base/task/single_thread_task_runner.h"
24 #include "base/task/thread_pool.h"
25 #include "base/test/task_environment.h"
26 #include "base/test/test_io_thread.h"
27 #include "base/threading/platform_thread.h"
28 #include "base/threading/thread.h"
29 #include "base/trace_event/memory_dump_manager_test_utils.h"
30 #include "base/trace_event/memory_dump_provider.h"
31 #include "base/trace_event/memory_dump_request_args.h"
32 #include "base/trace_event/memory_dump_scheduler.h"
33 #include "base/trace_event/memory_infra_background_allowlist.h"
34 #include "base/trace_event/process_memory_dump.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::AtMost;
41 using testing::Between;
42 using testing::Invoke;
43 using testing::Return;
44 
45 namespace base {
46 namespace trace_event {
47 
48 // GTest matchers for MemoryDumpRequestArgs arguments.
49 MATCHER(IsDetailedDump, "") {
50   return arg.level_of_detail == MemoryDumpLevelOfDetail::kDetailed;
51 }
52 
53 MATCHER(IsLightDump, "") {
54   return arg.level_of_detail == MemoryDumpLevelOfDetail::kLight;
55 }
56 
57 MATCHER(IsDeterministicDump, "") {
58   return arg.determinism == MemoryDumpDeterminism::kForceGc;
59 }
60 
61 MATCHER(IsNotDeterministicDump, "") {
62   return arg.determinism == MemoryDumpDeterminism::kNone;
63 }
64 
65 namespace {
66 
67 constexpr char kMDPName[] = "TestDumpProvider";
68 constexpr char kAllowlistedMDPName[] = "AllowlistedTestDumpProvider";
69 constexpr std::string_view kTestMDPAllowlist[] = {kAllowlistedMDPName};
70 
RegisterDumpProvider(MemoryDumpProvider * mdp,scoped_refptr<base::SingleThreadTaskRunner> task_runner,const MemoryDumpProvider::Options & options,const char * name=kMDPName)71 void RegisterDumpProvider(
72     MemoryDumpProvider* mdp,
73     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
74     const MemoryDumpProvider::Options& options,
75     const char* name = kMDPName) {
76   MemoryDumpManager* mdm = MemoryDumpManager::GetInstance();
77   mdm->set_dumper_registrations_ignored_for_testing(false);
78   mdm->RegisterDumpProvider(mdp, name, std::move(task_runner), options);
79   mdm->set_dumper_registrations_ignored_for_testing(true);
80 }
81 
RegisterDumpProvider(MemoryDumpProvider * mdp,scoped_refptr<base::SingleThreadTaskRunner> task_runner)82 void RegisterDumpProvider(
83     MemoryDumpProvider* mdp,
84     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
85   RegisterDumpProvider(mdp, task_runner, MemoryDumpProvider::Options());
86 }
87 
RegisterDumpProviderWithSequencedTaskRunner(MemoryDumpProvider * mdp,scoped_refptr<base::SequencedTaskRunner> task_runner,const MemoryDumpProvider::Options & options)88 void RegisterDumpProviderWithSequencedTaskRunner(
89     MemoryDumpProvider* mdp,
90     scoped_refptr<base::SequencedTaskRunner> task_runner,
91     const MemoryDumpProvider::Options& options) {
92   MemoryDumpManager* mdm = MemoryDumpManager::GetInstance();
93   mdm->set_dumper_registrations_ignored_for_testing(false);
94   mdm->RegisterDumpProviderWithSequencedTaskRunner(mdp, kMDPName, task_runner,
95                                                    options);
96   mdm->set_dumper_registrations_ignored_for_testing(true);
97 }
98 
99 // Posts |task| to |task_runner| and blocks until it is executed.
PostTaskAndWait(const Location & from_here,SequencedTaskRunner * task_runner,base::OnceClosure task)100 void PostTaskAndWait(const Location& from_here,
101                      SequencedTaskRunner* task_runner,
102                      base::OnceClosure task) {
103   base::WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
104                             WaitableEvent::InitialState::NOT_SIGNALED);
105   task_runner->PostTask(from_here, std::move(task));
106   task_runner->PostTask(FROM_HERE, base::BindOnce(&WaitableEvent::Signal,
107                                                   base::Unretained(&event)));
108   // The SequencedTaskRunner guarantees that |event| will only be signaled after
109   // |task| is executed.
110   event.Wait();
111 }
112 
113 class MockMemoryDumpProvider : public MemoryDumpProvider {
114  public:
115   MOCK_METHOD0(Destructor, void());
116   MOCK_METHOD2(OnMemoryDump,
117                bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd));
118 
MockMemoryDumpProvider()119   MockMemoryDumpProvider() : enable_mock_destructor(false) {
120     ON_CALL(*this, OnMemoryDump(_, _))
121         .WillByDefault(
122             Invoke([](const MemoryDumpArgs&, ProcessMemoryDump* pmd) -> bool {
123               return true;
124             }));
125   }
~MockMemoryDumpProvider()126   ~MockMemoryDumpProvider() override {
127     if (enable_mock_destructor)
128       Destructor();
129   }
130 
131   bool enable_mock_destructor;
132 };
133 
134 class TestSequencedTaskRunner : public SequencedTaskRunner {
135  public:
136   TestSequencedTaskRunner() = default;
137 
set_enabled(bool value)138   void set_enabled(bool value) { enabled_ = value; }
no_of_post_tasks() const139   unsigned no_of_post_tasks() const { return num_of_post_tasks_; }
140 
PostNonNestableDelayedTask(const Location & from_here,OnceClosure task,TimeDelta delay)141   bool PostNonNestableDelayedTask(const Location& from_here,
142                                   OnceClosure task,
143                                   TimeDelta delay) override {
144     NOTREACHED();
145   }
146 
PostDelayedTask(const Location & from_here,OnceClosure task,TimeDelta delay)147   bool PostDelayedTask(const Location& from_here,
148                        OnceClosure task,
149                        TimeDelta delay) override {
150     num_of_post_tasks_++;
151     if (enabled_) {
152       return task_runner_->PostDelayedTask(from_here, std::move(task), delay);
153     }
154     return false;
155   }
156 
RunsTasksInCurrentSequence() const157   bool RunsTasksInCurrentSequence() const override {
158     return task_runner_->RunsTasksInCurrentSequence();
159   }
160 
161  private:
162   ~TestSequencedTaskRunner() override = default;
163 
164   const scoped_refptr<SequencedTaskRunner> task_runner_ =
165       ThreadPool::CreateSequencedTaskRunner({});
166   bool enabled_ = true;
167   unsigned num_of_post_tasks_ = 0;
168 };
169 
170 }  // namespace
171 
172 class MemoryDumpManagerTest : public testing::Test {
173  public:
MemoryDumpManagerTest(bool is_coordinator=false)174   MemoryDumpManagerTest(bool is_coordinator = false)
175       : is_coordinator_(is_coordinator) {}
176 
177   MemoryDumpManagerTest(const MemoryDumpManagerTest&) = delete;
178   MemoryDumpManagerTest& operator=(const MemoryDumpManagerTest&) = delete;
179 
SetUp()180   void SetUp() override {
181     // Bring up and initialize MemoryDumpManager while single-threaded (before
182     // instantiating TaskEnvironment) to avoid data races if worker
183     // threads use tracing globals early.
184     mdm_ = MemoryDumpManager::CreateInstanceForTesting();
185     ASSERT_EQ(mdm_.get(), MemoryDumpManager::GetInstance());
186 
187     InitializeMemoryDumpManagerForInProcessTesting(is_coordinator_);
188 
189     task_environment_ = std::make_unique<test::TaskEnvironment>();
190   }
191 
TearDown()192   void TearDown() override {
193     task_environment_.reset();
194 
195     // Tear down the MemoryDumpManager while single-threaded to mirror logic in
196     // SetUp().
197     mdm_.reset();
198     TraceLog::ResetForTesting();
199   }
200 
201  protected:
202   // Blocks the current thread (spinning a nested message loop) until the
203   // memory dump is complete. Returns:
204   // - return value: the |success| from the CreateProcessDump() callback.
RequestProcessDumpAndWait(MemoryDumpType dump_type,MemoryDumpLevelOfDetail level_of_detail,MemoryDumpDeterminism determinism)205   bool RequestProcessDumpAndWait(MemoryDumpType dump_type,
206                                  MemoryDumpLevelOfDetail level_of_detail,
207                                  MemoryDumpDeterminism determinism) {
208     RunLoop run_loop;
209     bool success = false;
210     static uint64_t test_guid = 1;
211     test_guid++;
212     MemoryDumpRequestArgs request_args{test_guid, dump_type, level_of_detail,
213                                        determinism};
214 
215     // The signature of the callback delivered by MemoryDumpManager is:
216     // void ProcessMemoryDumpCallback(
217     //     uint64_t dump_guid,
218     //     bool success,
219     //     std::unique_ptr<ProcessMemoryDump> pmd)
220     // The extra arguments prepended to the |callback| below (the ones with the
221     // "curried_" prefix) are just passed from the BindOnce(). This is just to
222     // get around the limitation of BindOnce() in supporting only capture-less
223     // lambdas.
224     ProcessMemoryDumpCallback callback = BindOnce(
225         [](bool* curried_success, OnceClosure curried_quit_closure,
226            uint64_t curried_expected_guid, bool success, uint64_t dump_guid,
227            std::unique_ptr<ProcessMemoryDump> pmd) {
228           *curried_success = success;
229           EXPECT_EQ(curried_expected_guid, dump_guid);
230           SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
231               FROM_HERE, std::move(curried_quit_closure));
232         },
233         Unretained(&success), run_loop.QuitClosure(), test_guid);
234 
235     mdm_->CreateProcessDump(request_args, std::move(callback));
236     run_loop.Run();
237     return success;
238   }
239 
EnableForTracing()240   void EnableForTracing() {
241     mdm_->SetupForTracing(TraceConfig::MemoryDumpConfig());
242   }
243 
EnableForTracingWithTraceConfig(const std::string & trace_config_string)244   void EnableForTracingWithTraceConfig(const std::string& trace_config_string) {
245     TraceConfig trace_config(trace_config_string);
246     mdm_->SetupForTracing(trace_config.memory_dump_config());
247   }
248 
DisableTracing()249   void DisableTracing() { mdm_->TeardownForTracing(); }
250 
GetMaxConsecutiveFailuresCount() const251   int GetMaxConsecutiveFailuresCount() const {
252     return MemoryDumpManager::kMaxConsecutiveFailuresCount;
253   }
254 
255   const MemoryDumpProvider::Options kDefaultOptions;
256   std::unique_ptr<MemoryDumpManager> mdm_;
257 
258  private:
259   // To tear down the singleton instance after each test.
260   ShadowingAtExitManager at_exit_manager_;
261 
262   std::unique_ptr<test::TaskEnvironment> task_environment_;
263 
264   // Whether the test MemoryDumpManager should be initialized as the
265   // coordinator.
266   const bool is_coordinator_;
267 };
268 
269 class MemoryDumpManagerTestAsCoordinator : public MemoryDumpManagerTest {
270  public:
MemoryDumpManagerTestAsCoordinator()271   MemoryDumpManagerTestAsCoordinator() : MemoryDumpManagerTest(true) {}
272 
273   MemoryDumpManagerTestAsCoordinator(
274       const MemoryDumpManagerTestAsCoordinator&) = delete;
275   MemoryDumpManagerTestAsCoordinator& operator=(
276       const MemoryDumpManagerTestAsCoordinator&) = delete;
277 };
278 
279 // Basic sanity checks. Registers a memory dump provider and checks that it is
280 // called.
TEST_F(MemoryDumpManagerTest,SingleDumper)281 TEST_F(MemoryDumpManagerTest, SingleDumper) {
282   MockMemoryDumpProvider mdp;
283   RegisterDumpProvider(&mdp, SingleThreadTaskRunner::GetCurrentDefault());
284 
285   // Now repeat enabling the memory category and check that the dumper is
286   // invoked this time.
287   EnableForTracing();
288   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(3);
289   for (int i = 0; i < 3; ++i) {
290     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
291                                           MemoryDumpLevelOfDetail::kDetailed,
292                                           MemoryDumpDeterminism::kNone));
293   }
294   DisableTracing();
295 
296   mdm_->UnregisterDumpProvider(&mdp);
297 
298   // Finally check the unregister logic: the global dump handler will be invoked
299   // but not the dump provider, as it has been unregistered.
300   EnableForTracing();
301   EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
302   for (int i = 0; i < 3; ++i) {
303     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
304                                           MemoryDumpLevelOfDetail::kDetailed,
305                                           MemoryDumpDeterminism::kNone));
306   }
307   DisableTracing();
308 }
309 
310 // Checks that requesting dumps with high level of detail actually propagates
311 // the level of the detail properly to OnMemoryDump() call on dump providers.
TEST_F(MemoryDumpManagerTest,CheckMemoryDumpArgs)312 TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgs) {
313   MockMemoryDumpProvider mdp;
314 
315   RegisterDumpProvider(&mdp, SingleThreadTaskRunner::GetCurrentDefault());
316   EnableForTracing();
317   EXPECT_CALL(mdp, OnMemoryDump(IsDetailedDump(), _));
318   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
319                                         MemoryDumpLevelOfDetail::kDetailed,
320                                         MemoryDumpDeterminism::kNone));
321   DisableTracing();
322   mdm_->UnregisterDumpProvider(&mdp);
323 
324   // Check that requesting dumps with low level of detail actually propagates to
325   // OnMemoryDump() call on dump providers.
326   RegisterDumpProvider(&mdp, SingleThreadTaskRunner::GetCurrentDefault());
327   EnableForTracing();
328   EXPECT_CALL(mdp, OnMemoryDump(IsLightDump(), _));
329   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
330                                         MemoryDumpLevelOfDetail::kLight,
331                                         MemoryDumpDeterminism::kNone));
332   DisableTracing();
333   mdm_->UnregisterDumpProvider(&mdp);
334 }
335 
336 // Checks that requesting deterministic dumps actually propagates
337 // the deterministic option properly to OnMemoryDump() call on dump providers.
TEST_F(MemoryDumpManagerTest,CheckMemoryDumpArgsDeterministic)338 TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgsDeterministic) {
339   MockMemoryDumpProvider mdp;
340 
341   RegisterDumpProvider(&mdp, SingleThreadTaskRunner::GetCurrentDefault());
342   EnableForTracing();
343   EXPECT_CALL(mdp, OnMemoryDump(IsDeterministicDump(), _));
344   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
345                                         MemoryDumpLevelOfDetail::kDetailed,
346                                         MemoryDumpDeterminism::kForceGc));
347   DisableTracing();
348   mdm_->UnregisterDumpProvider(&mdp);
349 
350   // Check that requesting dumps with deterministic option set to false
351   // actually propagates to OnMemoryDump() call on dump providers.
352   RegisterDumpProvider(&mdp, SingleThreadTaskRunner::GetCurrentDefault());
353   EnableForTracing();
354   EXPECT_CALL(mdp, OnMemoryDump(IsNotDeterministicDump(), _));
355   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
356                                         MemoryDumpLevelOfDetail::kLight,
357                                         MemoryDumpDeterminism::kNone));
358   DisableTracing();
359   mdm_->UnregisterDumpProvider(&mdp);
360 }
361 
362 // Checks that the (Un)RegisterDumpProvider logic behaves sanely.
TEST_F(MemoryDumpManagerTest,MultipleDumpers)363 TEST_F(MemoryDumpManagerTest, MultipleDumpers) {
364   MockMemoryDumpProvider mdp1;
365   MockMemoryDumpProvider mdp2;
366 
367   // Enable only mdp1.
368   RegisterDumpProvider(&mdp1, SingleThreadTaskRunner::GetCurrentDefault());
369   EnableForTracing();
370   EXPECT_CALL(mdp1, OnMemoryDump(_, _));
371   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(0);
372   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
373                                         MemoryDumpLevelOfDetail::kDetailed,
374                                         MemoryDumpDeterminism::kNone));
375   DisableTracing();
376 
377   // Invert: enable mdp2 and disable mdp1.
378   mdm_->UnregisterDumpProvider(&mdp1);
379   RegisterDumpProvider(&mdp2, nullptr);
380   EnableForTracing();
381   EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0);
382   EXPECT_CALL(mdp2, OnMemoryDump(_, _));
383   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
384                                         MemoryDumpLevelOfDetail::kDetailed,
385                                         MemoryDumpDeterminism::kNone));
386   DisableTracing();
387 
388   // Enable both mdp1 and mdp2.
389   RegisterDumpProvider(&mdp1, nullptr);
390   EnableForTracing();
391   EXPECT_CALL(mdp1, OnMemoryDump(_, _));
392   EXPECT_CALL(mdp2, OnMemoryDump(_, _));
393   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
394                                         MemoryDumpLevelOfDetail::kDetailed,
395                                         MemoryDumpDeterminism::kNone));
396   DisableTracing();
397 }
398 
399 // Checks that the dump provider invocations depend only on the current
400 // registration state and not on previous registrations and dumps.
401 // Flaky on iOS, see crbug.com/706874
402 #if BUILDFLAG(IS_IOS)
403 #define MAYBE_RegistrationConsistency DISABLED_RegistrationConsistency
404 #else
405 #define MAYBE_RegistrationConsistency RegistrationConsistency
406 #endif
TEST_F(MemoryDumpManagerTest,MAYBE_RegistrationConsistency)407 TEST_F(MemoryDumpManagerTest, MAYBE_RegistrationConsistency) {
408   MockMemoryDumpProvider mdp;
409 
410   RegisterDumpProvider(&mdp, SingleThreadTaskRunner::GetCurrentDefault());
411 
412   {
413     EXPECT_CALL(mdp, OnMemoryDump(_, _));
414     EnableForTracing();
415     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
416                                           MemoryDumpLevelOfDetail::kDetailed,
417                                           MemoryDumpDeterminism::kNone));
418     DisableTracing();
419   }
420 
421   mdm_->UnregisterDumpProvider(&mdp);
422 
423   {
424     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
425     EnableForTracing();
426     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
427                                           MemoryDumpLevelOfDetail::kDetailed,
428                                           MemoryDumpDeterminism::kNone));
429     DisableTracing();
430   }
431 
432   RegisterDumpProvider(&mdp, SingleThreadTaskRunner::GetCurrentDefault());
433   mdm_->UnregisterDumpProvider(&mdp);
434 
435   {
436     EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
437     EnableForTracing();
438     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
439                                           MemoryDumpLevelOfDetail::kDetailed,
440                                           MemoryDumpDeterminism::kNone));
441     DisableTracing();
442   }
443 
444   RegisterDumpProvider(&mdp, SingleThreadTaskRunner::GetCurrentDefault());
445   mdm_->UnregisterDumpProvider(&mdp);
446   RegisterDumpProvider(&mdp, SingleThreadTaskRunner::GetCurrentDefault());
447 
448   {
449     EXPECT_CALL(mdp, OnMemoryDump(_, _));
450     EnableForTracing();
451     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
452                                           MemoryDumpLevelOfDetail::kDetailed,
453                                           MemoryDumpDeterminism::kNone));
454     DisableTracing();
455   }
456 }
457 
458 // Checks that the MemoryDumpManager respects the thread affinity when a
459 // MemoryDumpProvider specifies a task_runner(). The test starts creating 8
460 // threads and registering a MemoryDumpProvider on each of them. At each
461 // iteration, one thread is removed, to check the live unregistration logic.
TEST_F(MemoryDumpManagerTest,RespectTaskRunnerAffinity)462 TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) {
463   const uint32_t kNumInitialThreads = 8;
464 
465   std::vector<std::unique_ptr<Thread>> threads;
466   std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps;
467 
468   // Create the threads and setup the expectations. Given that at each iteration
469   // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be
470   // invoked a number of times equal to its index.
471   for (uint32_t i = kNumInitialThreads; i > 0; --i) {
472     threads.push_back(std::make_unique<Thread>("test thread"));
473     auto* thread = threads.back().get();
474     thread->Start();
475     scoped_refptr<SingleThreadTaskRunner> task_runner = thread->task_runner();
476     mdps.push_back(std::make_unique<MockMemoryDumpProvider>());
477     auto* mdp = mdps.back().get();
478     RegisterDumpProvider(mdp, task_runner, kDefaultOptions);
479     EXPECT_CALL(*mdp, OnMemoryDump(_, _))
480         .Times(i)
481         .WillRepeatedly(Invoke(
482             [task_runner](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
483               EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
484               return true;
485             }));
486   }
487   EnableForTracing();
488 
489   while (!threads.empty()) {
490     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
491                                           MemoryDumpLevelOfDetail::kDetailed,
492                                           MemoryDumpDeterminism::kNone));
493 
494     // Unregister a MDP and destroy one thread at each iteration to check the
495     // live unregistration logic. The unregistration needs to happen on the same
496     // thread the MDP belongs to.
497     {
498       RunLoop run_loop;
499       OnceClosure unregistration =
500           BindOnce(&MemoryDumpManager::UnregisterDumpProvider,
501                    Unretained(mdm_.get()), Unretained(mdps.back().get()));
502       threads.back()->task_runner()->PostTaskAndReply(
503           FROM_HERE, std::move(unregistration), run_loop.QuitClosure());
504       run_loop.Run();
505     }
506     mdps.pop_back();
507     threads.back()->Stop();
508     threads.pop_back();
509   }
510 
511   DisableTracing();
512 }
513 
514 // Check that the memory dump calls are always posted on task runner for
515 // SequencedTaskRunner case and that the dump provider gets disabled when
516 // PostTask fails, but the dump still succeeds.
TEST_F(MemoryDumpManagerTest,PostTaskForSequencedTaskRunner)517 TEST_F(MemoryDumpManagerTest, PostTaskForSequencedTaskRunner) {
518   std::vector<MockMemoryDumpProvider> mdps(3);
519   scoped_refptr<TestSequencedTaskRunner> task_runner1(
520       MakeRefCounted<TestSequencedTaskRunner>());
521   scoped_refptr<TestSequencedTaskRunner> task_runner2(
522       MakeRefCounted<TestSequencedTaskRunner>());
523   RegisterDumpProviderWithSequencedTaskRunner(&mdps[0], task_runner1,
524                                               kDefaultOptions);
525   RegisterDumpProviderWithSequencedTaskRunner(&mdps[1], task_runner2,
526                                               kDefaultOptions);
527   RegisterDumpProviderWithSequencedTaskRunner(&mdps[2], task_runner2,
528                                               kDefaultOptions);
529   // |mdps[0]| should be disabled permanently after first dump.
530   EXPECT_CALL(mdps[0], OnMemoryDump(_, _)).Times(0);
531   EXPECT_CALL(mdps[1], OnMemoryDump(_, _)).Times(2);
532   EXPECT_CALL(mdps[2], OnMemoryDump(_, _)).Times(2);
533 
534   EnableForTracing();
535 
536   task_runner1->set_enabled(false);
537   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
538                                         MemoryDumpLevelOfDetail::kDetailed,
539                                         MemoryDumpDeterminism::kNone));
540   EXPECT_EQ(1u, task_runner1->no_of_post_tasks());
541   EXPECT_EQ(1u, task_runner2->no_of_post_tasks());
542 
543   task_runner1->set_enabled(true);
544   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
545                                         MemoryDumpLevelOfDetail::kDetailed,
546                                         MemoryDumpDeterminism::kNone));
547   EXPECT_EQ(2u, task_runner1->no_of_post_tasks());
548   EXPECT_EQ(2u, task_runner2->no_of_post_tasks());
549   DisableTracing();
550 }
551 
552 // Checks that providers get disabled after 3 consecutive failures, but not
553 // otherwise (e.g., if interleaved).
TEST_F(MemoryDumpManagerTest,DisableFailingDumpers)554 TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) {
555   MockMemoryDumpProvider mdp1;
556   MockMemoryDumpProvider mdp2;
557 
558   RegisterDumpProvider(&mdp1, nullptr);
559   RegisterDumpProvider(&mdp2, nullptr);
560   EnableForTracing();
561 
562   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
563       .Times(GetMaxConsecutiveFailuresCount())
564       .WillRepeatedly(Return(false));
565 
566   EXPECT_CALL(mdp2, OnMemoryDump(_, _))
567       .WillOnce(Return(false))
568       .WillOnce(Return(true))
569       .WillOnce(Return(false))
570       .WillOnce(Return(false))
571       .WillOnce(Return(true))
572       .WillOnce(Return(false));
573 
574   const int kNumDumps = 2 * GetMaxConsecutiveFailuresCount();
575   for (int i = 0; i < kNumDumps; i++) {
576     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
577                                           MemoryDumpLevelOfDetail::kDetailed,
578                                           MemoryDumpDeterminism::kNone));
579   }
580 
581   DisableTracing();
582 }
583 
584 // Sneakily registers an extra memory dump provider while an existing one is
585 // dumping and expect it to take part in the already active tracing session.
TEST_F(MemoryDumpManagerTest,RegisterDumperWhileDumping)586 TEST_F(MemoryDumpManagerTest, RegisterDumperWhileDumping) {
587   MockMemoryDumpProvider mdp1;
588   MockMemoryDumpProvider mdp2;
589 
590   RegisterDumpProvider(&mdp1, nullptr);
591   EnableForTracing();
592 
593   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
594       .Times(4)
595       .WillOnce(Return(true))
596       .WillOnce(
597           Invoke([&mdp2](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
598             RegisterDumpProvider(&mdp2, nullptr);
599             return true;
600           }))
601       .WillRepeatedly(Return(true));
602 
603   // Depending on the insertion order (before or after mdp1), mdp2 might be
604   // called also immediately after it gets registered.
605   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(Between(2, 3));
606 
607   for (int i = 0; i < 4; i++) {
608     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
609                                           MemoryDumpLevelOfDetail::kDetailed,
610                                           MemoryDumpDeterminism::kNone));
611   }
612 
613   DisableTracing();
614 }
615 
616 // Like RegisterDumperWhileDumping, but unregister the dump provider instead.
TEST_F(MemoryDumpManagerTest,UnregisterDumperWhileDumping)617 TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileDumping) {
618   MockMemoryDumpProvider mdp1;
619   MockMemoryDumpProvider mdp2;
620 
621   RegisterDumpProvider(&mdp1, SingleThreadTaskRunner::GetCurrentDefault(),
622                        kDefaultOptions);
623   RegisterDumpProvider(&mdp2, SingleThreadTaskRunner::GetCurrentDefault(),
624                        kDefaultOptions);
625   EnableForTracing();
626 
627   EXPECT_CALL(mdp1, OnMemoryDump(_, _))
628       .Times(4)
629       .WillOnce(Return(true))
630       .WillOnce(
631           Invoke([&mdp2](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
632             MemoryDumpManager::GetInstance()->UnregisterDumpProvider(&mdp2);
633             return true;
634           }))
635       .WillRepeatedly(Return(true));
636 
637   // Depending on the insertion order (before or after mdp1), mdp2 might have
638   // been already called when UnregisterDumpProvider happens.
639   EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(Between(1, 2));
640 
641   for (int i = 0; i < 4; i++) {
642     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
643                                           MemoryDumpLevelOfDetail::kDetailed,
644                                           MemoryDumpDeterminism::kNone));
645   }
646 
647   DisableTracing();
648 }
649 
650 // Checks that the dump does not abort when unregistering a provider while
651 // dumping from a different thread than the dumping thread.
TEST_F(MemoryDumpManagerTest,UnregisterDumperFromThreadWhileDumping)652 TEST_F(MemoryDumpManagerTest, UnregisterDumperFromThreadWhileDumping) {
653   std::vector<std::unique_ptr<TestIOThread>> threads;
654   std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps;
655 
656   for (int i = 0; i < 2; i++) {
657     threads.push_back(std::make_unique<TestIOThread>(TestIOThread::kAutoStart));
658     mdps.push_back(std::make_unique<MockMemoryDumpProvider>());
659     RegisterDumpProvider(mdps.back().get(), threads.back()->task_runner(),
660                          kDefaultOptions);
661   }
662 
663   int on_memory_dump_call_count = 0;
664 
665   // When OnMemoryDump is called on either of the dump providers, it will
666   // unregister the other one.
667   for (const std::unique_ptr<MockMemoryDumpProvider>& mdp : mdps) {
668     int other_idx = (mdps.front() == mdp);
669     // TestIOThread's task runner must be obtained from the main thread but can
670     // then be used from other threads.
671     scoped_refptr<SingleThreadTaskRunner> other_runner =
672         threads[other_idx]->task_runner();
673     MockMemoryDumpProvider* other_mdp = mdps[other_idx].get();
674     auto on_dump = [this, other_runner, other_mdp, &on_memory_dump_call_count](
675                        const MemoryDumpArgs& args, ProcessMemoryDump* pmd) {
676       PostTaskAndWait(FROM_HERE, other_runner.get(),
677                       base::BindOnce(&MemoryDumpManager::UnregisterDumpProvider,
678                                      base::Unretained(&*mdm_), other_mdp));
679       on_memory_dump_call_count++;
680       return true;
681     };
682 
683     // OnMemoryDump is called once for the provider that dumps first, and zero
684     // times for the other provider.
685     EXPECT_CALL(*mdp, OnMemoryDump(_, _))
686         .Times(AtMost(1))
687         .WillOnce(Invoke(on_dump));
688   }
689 
690   EnableForTracing();
691   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
692                                         MemoryDumpLevelOfDetail::kDetailed,
693                                         MemoryDumpDeterminism::kNone));
694   ASSERT_EQ(1, on_memory_dump_call_count);
695 
696   DisableTracing();
697 }
698 
699 // If a thread (with a dump provider living on it) is torn down during a dump
700 // its dump provider should be skipped but the dump itself should succeed.
TEST_F(MemoryDumpManagerTest,TearDownThreadWhileDumping)701 TEST_F(MemoryDumpManagerTest, TearDownThreadWhileDumping) {
702   std::vector<std::unique_ptr<TestIOThread>> threads;
703   std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps;
704 
705   for (int i = 0; i < 2; i++) {
706     threads.push_back(std::make_unique<TestIOThread>(TestIOThread::kAutoStart));
707     mdps.push_back(std::make_unique<MockMemoryDumpProvider>());
708     RegisterDumpProvider(mdps.back().get(), threads.back()->task_runner(),
709                          kDefaultOptions);
710   }
711 
712   int on_memory_dump_call_count = 0;
713 
714   // When OnMemoryDump is called on either of the dump providers, it will
715   // tear down the thread of the other one.
716   for (const std::unique_ptr<MockMemoryDumpProvider>& mdp : mdps) {
717     int other_idx = (mdps.front() == mdp);
718     TestIOThread* other_thread = threads[other_idx].get();
719     // TestIOThread isn't thread-safe and must be stopped on the |main_runner|.
720     scoped_refptr<SequencedTaskRunner> main_runner =
721         SequencedTaskRunner::GetCurrentDefault();
722     auto on_dump = [other_thread, main_runner, &on_memory_dump_call_count](
723                        const MemoryDumpArgs& args, ProcessMemoryDump* pmd) {
724       PostTaskAndWait(
725           FROM_HERE, main_runner.get(),
726           base::BindOnce(&TestIOThread::Stop, base::Unretained(other_thread)));
727       on_memory_dump_call_count++;
728       return true;
729     };
730 
731     // OnMemoryDump is called once for the provider that dumps first, and zero
732     // times for the other provider.
733     EXPECT_CALL(*mdp, OnMemoryDump(_, _))
734         .Times(AtMost(1))
735         .WillOnce(Invoke(on_dump));
736   }
737 
738   EnableForTracing();
739   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
740                                         MemoryDumpLevelOfDetail::kDetailed,
741                                         MemoryDumpDeterminism::kNone));
742   ASSERT_EQ(1, on_memory_dump_call_count);
743 
744   DisableTracing();
745 }
746 
747 // Checks that the callback is invoked if CreateProcessDump() is called when
748 // tracing is not enabled.
TEST_F(MemoryDumpManagerTest,TriggerDumpWithoutTracing)749 TEST_F(MemoryDumpManagerTest, TriggerDumpWithoutTracing) {
750   MockMemoryDumpProvider mdp;
751   RegisterDumpProvider(&mdp, nullptr);
752   EXPECT_CALL(mdp, OnMemoryDump(_, _));
753   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
754                                         MemoryDumpLevelOfDetail::kDetailed,
755                                         MemoryDumpDeterminism::kNone));
756 }
757 
TEST_F(MemoryDumpManagerTest,BackgroundAllowlisting)758 TEST_F(MemoryDumpManagerTest, BackgroundAllowlisting) {
759   SetDumpProviderAllowlistForTesting(kTestMDPAllowlist);
760 
761   // Standard provider with default options (create dump for current process).
762   MockMemoryDumpProvider backgroundMdp;
763   RegisterDumpProvider(&backgroundMdp, nullptr, kDefaultOptions,
764                        kAllowlistedMDPName);
765 
766   EnableForTracing();
767 
768   EXPECT_CALL(backgroundMdp, OnMemoryDump(_, _)).Times(1);
769   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kSummaryOnly,
770                                         MemoryDumpLevelOfDetail::kBackground,
771                                         MemoryDumpDeterminism::kNone));
772   DisableTracing();
773 }
774 
775 // Tests the basics of the UnregisterAndDeleteDumpProviderSoon(): the
776 // unregistration should actually delete the providers and not leak them.
TEST_F(MemoryDumpManagerTest,UnregisterAndDeleteDumpProviderSoon)777 TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoon) {
778   static const int kNumProviders = 3;
779   int dtor_count = 0;
780   std::vector<std::unique_ptr<MemoryDumpProvider>> mdps;
781   for (int i = 0; i < kNumProviders; ++i) {
782     std::unique_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider);
783     mdp->enable_mock_destructor = true;
784     EXPECT_CALL(*mdp, Destructor()).WillOnce(Invoke([&dtor_count] {
785       dtor_count++;
786     }));
787     RegisterDumpProvider(mdp.get(), nullptr, kDefaultOptions);
788     mdps.push_back(std::move(mdp));
789   }
790 
791   while (!mdps.empty()) {
792     mdm_->UnregisterAndDeleteDumpProviderSoon(std::move(mdps.back()));
793     mdps.pop_back();
794   }
795 
796   ASSERT_EQ(kNumProviders, dtor_count);
797 }
798 
799 // This test checks against races when unregistering an unbound dump provider
800 // from another thread while dumping. It registers one MDP and, when
801 // OnMemoryDump() is called, it invokes UnregisterAndDeleteDumpProviderSoon()
802 // from another thread. The OnMemoryDump() and the dtor call are expected to
803 // happen on the same thread (the MemoryDumpManager utility thread).
TEST_F(MemoryDumpManagerTest,UnregisterAndDeleteDumpProviderSoonDuringDump)804 TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoonDuringDump) {
805   std::unique_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider);
806   mdp->enable_mock_destructor = true;
807   RegisterDumpProvider(mdp.get(), nullptr, kDefaultOptions);
808 
809   base::PlatformThreadRef thread_ref;
810   auto self_unregister_from_another_thread = [&mdp, &thread_ref](
811       const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
812     thread_ref = PlatformThread::CurrentRef();
813     TestIOThread thread_for_unregistration(TestIOThread::kAutoStart);
814     PostTaskAndWait(
815         FROM_HERE, thread_for_unregistration.task_runner().get(),
816         base::BindOnce(&MemoryDumpManager::UnregisterAndDeleteDumpProviderSoon,
817                        base::Unretained(MemoryDumpManager::GetInstance()),
818                        std::move(mdp)));
819     thread_for_unregistration.Stop();
820     return true;
821   };
822   EXPECT_CALL(*mdp, OnMemoryDump(_, _))
823       .Times(1)
824       .WillOnce(Invoke(self_unregister_from_another_thread));
825   EXPECT_CALL(*mdp, Destructor()).Times(1).WillOnce(Invoke([&thread_ref] {
826     EXPECT_EQ(thread_ref, PlatformThread::CurrentRef());
827   }));
828 
829   EnableForTracing();
830   for (int i = 0; i < 2; ++i) {
831     EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
832                                           MemoryDumpLevelOfDetail::kDetailed,
833                                           MemoryDumpDeterminism::kNone));
834   }
835   DisableTracing();
836 }
837 
838 // Mock MDP class that tests if the number of OnMemoryDump() calls are expected.
839 // It is implemented without gmocks since EXPECT_CALL implementation is slow
840 // when there are 1000s of instances, as required in
841 // NoStackOverflowWithTooManyMDPs test.
842 class SimpleMockMemoryDumpProvider : public MemoryDumpProvider {
843  public:
SimpleMockMemoryDumpProvider(int expected_num_dump_calls)844   SimpleMockMemoryDumpProvider(int expected_num_dump_calls)
845       : expected_num_dump_calls_(expected_num_dump_calls), num_dump_calls_(0) {}
846 
~SimpleMockMemoryDumpProvider()847   ~SimpleMockMemoryDumpProvider() override {
848     EXPECT_EQ(expected_num_dump_calls_, num_dump_calls_);
849   }
850 
OnMemoryDump(const MemoryDumpArgs & args,ProcessMemoryDump * pmd)851   bool OnMemoryDump(const MemoryDumpArgs& args,
852                     ProcessMemoryDump* pmd) override {
853     ++num_dump_calls_;
854     return true;
855   }
856 
857  private:
858   int expected_num_dump_calls_;
859   int num_dump_calls_;
860 };
861 
TEST_F(MemoryDumpManagerTest,NoStackOverflowWithTooManyMDPs)862 TEST_F(MemoryDumpManagerTest, NoStackOverflowWithTooManyMDPs) {
863   SetDumpProviderAllowlistForTesting(kTestMDPAllowlist);
864 
865   int kMDPCount = 1000;
866   std::vector<std::unique_ptr<SimpleMockMemoryDumpProvider>> mdps;
867   for (int i = 0; i < kMDPCount; ++i) {
868     mdps.push_back(std::make_unique<SimpleMockMemoryDumpProvider>(1));
869     RegisterDumpProvider(mdps.back().get(), nullptr);
870   }
871   for (int i = 0; i < kMDPCount; ++i) {
872     mdps.push_back(std::make_unique<SimpleMockMemoryDumpProvider>(3));
873     RegisterDumpProvider(mdps.back().get(), nullptr, kDefaultOptions,
874                          kAllowlistedMDPName);
875   }
876   std::unique_ptr<Thread> stopped_thread(new Thread("test thread"));
877   stopped_thread->Start();
878   for (int i = 0; i < kMDPCount; ++i) {
879     mdps.push_back(std::make_unique<SimpleMockMemoryDumpProvider>(0));
880     RegisterDumpProvider(mdps.back().get(), stopped_thread->task_runner(),
881                          kDefaultOptions, kAllowlistedMDPName);
882   }
883   stopped_thread->Stop();
884 
885   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
886                                         MemoryDumpLevelOfDetail::kDetailed,
887                                         MemoryDumpDeterminism::kNone));
888   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kExplicitlyTriggered,
889                                         MemoryDumpLevelOfDetail::kBackground,
890                                         MemoryDumpDeterminism::kNone));
891   EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::kSummaryOnly,
892                                         MemoryDumpLevelOfDetail::kBackground,
893                                         MemoryDumpDeterminism::kNone));
894 }
895 
896 }  // namespace trace_event
897 }  // namespace base
898