Revert of Revert of Roll src/third_party/skia 8bcc7a0:724ae28 (patchset #1 id:1 of...
[chromium-blink-merge.git] / base / trace_event / memory_dump_manager_unittest.cc
blobd90b7c6073563ba4d1bdab0250b2f78e9381f861
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.
5 #include "base/trace_event/memory_dump_manager.h"
7 #include "base/bind_helpers.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/threading/thread.h"
12 #include "base/trace_event/memory_dump_provider.h"
13 #include "base/trace_event/process_memory_dump.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 using testing::_;
18 using testing::Invoke;
19 using testing::Return;
21 namespace base {
22 namespace trace_event {
24 // Testing MemoryDumpManagerDelegate which short-circuits dump requests locally
25 // instead of performing IPC dances.
26 class MemoryDumpManagerDelegateForTesting : public MemoryDumpManagerDelegate {
27 public:
28 void RequestGlobalMemoryDump(
29 const base::trace_event::MemoryDumpRequestArgs& args,
30 const MemoryDumpCallback& callback) override {
31 CreateProcessDump(args, callback);
34 bool IsCoordinatorProcess() const override { return false; }
37 class MemoryDumpManagerTest : public testing::Test {
38 public:
39 void SetUp() override {
40 message_loop_.reset(new MessageLoop());
41 mdm_.reset(new MemoryDumpManager());
42 MemoryDumpManager::SetInstanceForTesting(mdm_.get());
43 ASSERT_EQ(mdm_, MemoryDumpManager::GetInstance());
44 MemoryDumpManager::GetInstance()->Initialize();
45 MemoryDumpManager::GetInstance()->SetDelegate(&delegate_);
48 void TearDown() override {
49 MemoryDumpManager::SetInstanceForTesting(nullptr);
50 mdm_.reset();
51 message_loop_.reset();
52 TraceLog::DeleteForTesting();
55 void DumpCallbackAdapter(scoped_refptr<SingleThreadTaskRunner> task_runner,
56 Closure closure,
57 uint64 dump_guid,
58 bool success) {
59 task_runner->PostTask(FROM_HERE, closure);
62 protected:
63 const char* kTraceCategory = MemoryDumpManager::kTraceCategoryForTesting;
65 void EnableTracing(const char* category) {
66 TraceLog::GetInstance()->SetEnabled(
67 TraceConfig(category, ""), TraceLog::RECORDING_MODE);
70 void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); }
72 scoped_ptr<MemoryDumpManager> mdm_;
74 private:
75 scoped_ptr<MessageLoop> message_loop_;
76 MemoryDumpManagerDelegateForTesting delegate_;
78 // We want our singleton torn down after each test.
79 ShadowingAtExitManager at_exit_manager_;
82 class MockDumpProvider : public MemoryDumpProvider {
83 public:
84 MockDumpProvider() : last_session_state_(nullptr) {}
86 // Ctor used by the RespectTaskRunnerAffinity test.
87 explicit MockDumpProvider(
88 const scoped_refptr<SingleThreadTaskRunner>& task_runner)
89 : last_session_state_(nullptr), task_runner_(task_runner) {}
91 virtual ~MockDumpProvider() {}
93 MOCK_METHOD1(OnMemoryDump, bool(ProcessMemoryDump* pmd));
95 // OnMemoryDump() override for the RespectTaskRunnerAffinity test.
96 bool OnMemoryDump_CheckTaskRunner(ProcessMemoryDump* pmd) {
97 EXPECT_TRUE(task_runner_->RunsTasksOnCurrentThread());
98 return true;
101 // OnMemoryDump() override for the SharedSessionState test.
102 bool OnMemoryDump_CheckSessionState(ProcessMemoryDump* pmd) {
103 MemoryDumpSessionState* cur_session_state = pmd->session_state().get();
104 if (last_session_state_)
105 EXPECT_EQ(last_session_state_, cur_session_state);
106 last_session_state_ = cur_session_state;
107 return true;
110 private:
111 MemoryDumpSessionState* last_session_state_;
112 scoped_refptr<SingleThreadTaskRunner> task_runner_;
115 TEST_F(MemoryDumpManagerTest, SingleDumper) {
116 MockDumpProvider mdp;
117 mdm_->RegisterDumpProvider(&mdp);
119 // Check that the dumper is not called if the memory category is not enabled.
120 EnableTracing("foo-and-bar-but-not-memory");
121 EXPECT_CALL(mdp, OnMemoryDump(_)).Times(0);
122 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
123 DisableTracing();
125 // Now repeat enabling the memory category and check that the dumper is
126 // invoked this time.
127 EnableTracing(kTraceCategory);
128 EXPECT_CALL(mdp, OnMemoryDump(_)).Times(3).WillRepeatedly(Return(true));
129 for (int i = 0; i < 3; ++i)
130 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
131 DisableTracing();
133 mdm_->UnregisterDumpProvider(&mdp);
135 // Finally check the unregister logic (no calls to the mdp after unregister).
136 EnableTracing(kTraceCategory);
137 EXPECT_CALL(mdp, OnMemoryDump(_)).Times(0);
138 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
139 TraceLog::GetInstance()->SetDisabled();
142 TEST_F(MemoryDumpManagerTest, SharedSessionState) {
143 MockDumpProvider mdp1;
144 MockDumpProvider mdp2;
145 mdm_->RegisterDumpProvider(&mdp1);
146 mdm_->RegisterDumpProvider(&mdp2);
148 EnableTracing(kTraceCategory);
149 EXPECT_CALL(mdp1, OnMemoryDump(_))
150 .Times(2)
151 .WillRepeatedly(
152 Invoke(&mdp1, &MockDumpProvider::OnMemoryDump_CheckSessionState));
153 EXPECT_CALL(mdp2, OnMemoryDump(_))
154 .Times(2)
155 .WillRepeatedly(
156 Invoke(&mdp2, &MockDumpProvider::OnMemoryDump_CheckSessionState));
158 for (int i = 0; i < 2; ++i)
159 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
161 DisableTracing();
164 TEST_F(MemoryDumpManagerTest, MultipleDumpers) {
165 MockDumpProvider mdp1;
166 MockDumpProvider mdp2;
168 // Enable only mdp1.
169 mdm_->RegisterDumpProvider(&mdp1);
170 EnableTracing(kTraceCategory);
171 EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true));
172 EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(0);
173 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
174 DisableTracing();
176 // Invert: enable mdp1 and disable mdp2.
177 mdm_->UnregisterDumpProvider(&mdp1);
178 mdm_->RegisterDumpProvider(&mdp2);
179 EnableTracing(kTraceCategory);
180 EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(0);
181 EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true));
182 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
183 DisableTracing();
185 // Enable both mdp1 and mdp2.
186 mdm_->RegisterDumpProvider(&mdp1);
187 EnableTracing(kTraceCategory);
188 EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true));
189 EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true));
190 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
191 DisableTracing();
194 // Checks that the MemoryDumpManager respects the thread affinity when a
195 // MemoryDumpProvider specifies a task_runner(). The test starts creating 8
196 // threads and registering a MemoryDumpProvider on each of them. At each
197 // iteration, one thread is removed, to check the live unregistration logic.
198 TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) {
199 const uint32 kNumInitialThreads = 8;
201 ScopedVector<Thread> threads;
202 ScopedVector<MockDumpProvider> mdps;
204 // Create the threads and setup the expectations. Given that at each iteration
205 // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be
206 // invoked a number of times equal to its index.
207 for (uint32 i = kNumInitialThreads; i > 0; --i) {
208 threads.push_back(new Thread("test thread"));
209 threads.back()->Start();
210 mdps.push_back(new MockDumpProvider(threads.back()->task_runner()));
211 MockDumpProvider* mdp = mdps.back();
212 mdm_->RegisterDumpProvider(mdp, threads.back()->task_runner());
213 EXPECT_CALL(*mdp, OnMemoryDump(_))
214 .Times(i)
215 .WillRepeatedly(
216 Invoke(mdp, &MockDumpProvider::OnMemoryDump_CheckTaskRunner));
219 EnableTracing(kTraceCategory);
221 while (!threads.empty()) {
223 RunLoop run_loop;
224 MemoryDumpCallback callback =
225 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this),
226 MessageLoop::current()->task_runner(), run_loop.QuitClosure());
227 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, callback);
228 // This nested message loop (|run_loop|) will be quit if and only if
229 // the RequestGlobalDump callback is invoked.
230 run_loop.Run();
233 // Unregister a MDP and destroy one thread at each iteration to check the
234 // live unregistration logic. The unregistration needs to happen on the same
235 // thread the MDP belongs to.
237 RunLoop run_loop;
238 Closure unregistration =
239 Bind(&MemoryDumpManager::UnregisterDumpProvider,
240 Unretained(mdm_.get()), Unretained(mdps.back()));
241 threads.back()->task_runner()->PostTaskAndReply(FROM_HERE, unregistration,
242 run_loop.QuitClosure());
243 run_loop.Run();
245 mdps.pop_back();
246 threads.back()->Stop();
247 threads.pop_back();
250 DisableTracing();
253 // Enable both dump providers, make sure that mdp gets disabled after 3 failures
254 // and not disabled after 1.
255 TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) {
256 MockDumpProvider mdp1;
257 MockDumpProvider mdp2;
259 mdm_->RegisterDumpProvider(&mdp1);
260 mdm_->RegisterDumpProvider(&mdp2);
261 EnableTracing(kTraceCategory);
263 EXPECT_CALL(mdp1, OnMemoryDump(_))
264 .Times(MemoryDumpManager::kMaxConsecutiveFailuresCount)
265 .WillRepeatedly(Return(false));
266 EXPECT_CALL(mdp2, OnMemoryDump(_))
267 .Times(1 + MemoryDumpManager::kMaxConsecutiveFailuresCount)
268 .WillOnce(Return(false))
269 .WillRepeatedly(Return(true));
270 for (int i = 0; i < 1 + MemoryDumpManager::kMaxConsecutiveFailuresCount;
271 i++) {
272 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED);
275 DisableTracing();
278 } // namespace trace_event
279 } // namespace base