OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/trace_event/memory_dump_manager.h" | 5 #include "base/trace_event/memory_dump_manager.h" |
6 | 6 |
7 #include "base/bind_helpers.h" | 7 #include "base/bind_helpers.h" |
8 #include "base/memory/scoped_vector.h" | 8 #include "base/memory/scoped_vector.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 private: | 74 private: |
75 scoped_ptr<MessageLoop> message_loop_; | 75 scoped_ptr<MessageLoop> message_loop_; |
76 MemoryDumpManagerDelegateForTesting delegate_; | 76 MemoryDumpManagerDelegateForTesting delegate_; |
77 | 77 |
78 // We want our singleton torn down after each test. | 78 // We want our singleton torn down after each test. |
79 ShadowingAtExitManager at_exit_manager_; | 79 ShadowingAtExitManager at_exit_manager_; |
80 }; | 80 }; |
81 | 81 |
82 class MockDumpProvider : public MemoryDumpProvider { | 82 class MockDumpProvider : public MemoryDumpProvider { |
83 public: | 83 public: |
84 MockDumpProvider() {} | 84 MockDumpProvider() : last_session_state_(nullptr) {} |
85 | 85 |
| 86 // Ctor used by the RespectTaskRunnerAffinity test. |
86 explicit MockDumpProvider( | 87 explicit MockDumpProvider( |
87 const scoped_refptr<SingleThreadTaskRunner>& task_runner) | 88 const scoped_refptr<SingleThreadTaskRunner>& task_runner) |
88 : MemoryDumpProvider(task_runner) {} | 89 : last_session_state_(nullptr), task_runner_(task_runner) {} |
89 | 90 |
90 // Ctor for the SharedSessionState test. | 91 virtual ~MockDumpProvider() {} |
91 explicit MockDumpProvider(const std::string& id) { | |
92 DeclareAllocatorAttribute("allocator" + id, "attr" + id, "type" + id); | |
93 } | |
94 | 92 |
95 MOCK_METHOD1(DumpInto, bool(ProcessMemoryDump* pmd)); | 93 MOCK_METHOD1(OnMemoryDump, bool(ProcessMemoryDump* pmd)); |
96 | 94 |
97 // DumpInto() override for the ActiveDumpProviderConsistency test. | 95 // OnMemoryDump() override for the RespectTaskRunnerAffinity test. |
98 bool DumpIntoAndCheckDumpProviderCurrentlyActive(ProcessMemoryDump* pmd) { | 96 bool OnMemoryDump_CheckTaskRunner(ProcessMemoryDump* pmd) { |
99 EXPECT_EQ( | 97 EXPECT_TRUE(task_runner_->RunsTasksOnCurrentThread()); |
100 this, | |
101 MemoryDumpManager::GetInstance()->dump_provider_currently_active()); | |
102 return true; | 98 return true; |
103 } | 99 } |
104 | 100 |
105 // DumpInto() override for the RespectTaskRunnerAffinity test. | 101 // OnMemoryDump() override for the SharedSessionState test. |
106 bool DumpIntoAndCheckTaskRunner(ProcessMemoryDump* pmd) { | 102 bool OnMemoryDump_CheckSessionState(ProcessMemoryDump* pmd) { |
107 EXPECT_TRUE(task_runner()->RunsTasksOnCurrentThread()); | 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; |
108 return true; | 107 return true; |
109 } | 108 } |
110 | 109 |
111 // DumpInto() override for the SharedSessionState test. | 110 private: |
112 bool DumpIntoAndCheckSessionState(ProcessMemoryDump* pmd) { | 111 MemoryDumpSessionState* last_session_state_; |
113 EXPECT_TRUE(pmd->session_state()); | 112 scoped_refptr<SingleThreadTaskRunner> task_runner_; |
114 const auto& attrs_type_info = | |
115 pmd->session_state()->allocators_attributes_type_info; | |
116 EXPECT_TRUE(attrs_type_info.Exists("allocator1", "attr1")); | |
117 EXPECT_TRUE(attrs_type_info.Exists("allocator2", "attr2")); | |
118 return true; | |
119 } | |
120 | |
121 const char* GetFriendlyName() const override { return "MockDumpProvider"; } | |
122 }; | 113 }; |
123 | 114 |
124 TEST_F(MemoryDumpManagerTest, SingleDumper) { | 115 TEST_F(MemoryDumpManagerTest, SingleDumper) { |
125 MockDumpProvider mdp; | 116 MockDumpProvider mdp; |
126 mdm_->RegisterDumpProvider(&mdp); | 117 mdm_->RegisterDumpProvider(&mdp); |
127 | 118 |
128 // Check that the dumper is not called if the memory category is not enabled. | 119 // Check that the dumper is not called if the memory category is not enabled. |
129 EnableTracing("foo-and-bar-but-not-memory"); | 120 EnableTracing("foo-and-bar-but-not-memory"); |
130 EXPECT_CALL(mdp, DumpInto(_)).Times(0); | 121 EXPECT_CALL(mdp, OnMemoryDump(_)).Times(0); |
131 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | 122 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); |
132 DisableTracing(); | 123 DisableTracing(); |
133 | 124 |
134 // Now repeat enabling the memory category and check that the dumper is | 125 // Now repeat enabling the memory category and check that the dumper is |
135 // invoked this time. | 126 // invoked this time. |
136 EnableTracing(kTraceCategory); | 127 EnableTracing(kTraceCategory); |
137 EXPECT_CALL(mdp, DumpInto(_)).Times(3).WillRepeatedly(Return(true)); | 128 EXPECT_CALL(mdp, OnMemoryDump(_)).Times(3).WillRepeatedly(Return(true)); |
138 for (int i = 0; i < 3; ++i) | 129 for (int i = 0; i < 3; ++i) |
139 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | 130 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); |
140 DisableTracing(); | 131 DisableTracing(); |
141 | 132 |
142 mdm_->UnregisterDumpProvider(&mdp); | 133 mdm_->UnregisterDumpProvider(&mdp); |
143 | 134 |
144 // Finally check the unregister logic (no calls to the mdp after unregister). | 135 // Finally check the unregister logic (no calls to the mdp after unregister). |
145 EnableTracing(kTraceCategory); | 136 EnableTracing(kTraceCategory); |
146 EXPECT_CALL(mdp, DumpInto(_)).Times(0); | 137 EXPECT_CALL(mdp, OnMemoryDump(_)).Times(0); |
147 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | 138 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); |
148 TraceLog::GetInstance()->SetDisabled(); | 139 TraceLog::GetInstance()->SetDisabled(); |
149 } | 140 } |
150 | 141 |
151 TEST_F(MemoryDumpManagerTest, SharedSessionState) { | 142 TEST_F(MemoryDumpManagerTest, SharedSessionState) { |
152 MockDumpProvider mdp1("1"); // Will declare an allocator property "attr1". | 143 MockDumpProvider mdp1; |
153 MockDumpProvider mdp2("2"); // Will declare an allocator property "attr2". | 144 MockDumpProvider mdp2; |
154 mdm_->RegisterDumpProvider(&mdp1); | 145 mdm_->RegisterDumpProvider(&mdp1); |
155 mdm_->RegisterDumpProvider(&mdp2); | 146 mdm_->RegisterDumpProvider(&mdp2); |
156 | 147 |
157 EnableTracing(kTraceCategory); | 148 EnableTracing(kTraceCategory); |
158 EXPECT_CALL(mdp1, DumpInto(_)).Times(2).WillRepeatedly( | 149 EXPECT_CALL(mdp1, OnMemoryDump(_)) |
159 Invoke(&mdp1, &MockDumpProvider::DumpIntoAndCheckSessionState)); | 150 .Times(2) |
160 EXPECT_CALL(mdp2, DumpInto(_)).Times(2).WillRepeatedly( | 151 .WillRepeatedly( |
161 Invoke(&mdp2, &MockDumpProvider::DumpIntoAndCheckSessionState)); | 152 Invoke(&mdp1, &MockDumpProvider::OnMemoryDump_CheckSessionState)); |
| 153 EXPECT_CALL(mdp2, OnMemoryDump(_)) |
| 154 .Times(2) |
| 155 .WillRepeatedly( |
| 156 Invoke(&mdp2, &MockDumpProvider::OnMemoryDump_CheckSessionState)); |
162 | 157 |
163 for (int i = 0; i < 2; ++i) | 158 for (int i = 0; i < 2; ++i) |
164 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | 159 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); |
165 | 160 |
166 DisableTracing(); | 161 DisableTracing(); |
167 } | 162 } |
168 | 163 |
169 TEST_F(MemoryDumpManagerTest, MultipleDumpers) { | 164 TEST_F(MemoryDumpManagerTest, MultipleDumpers) { |
170 MockDumpProvider mdp1; | 165 MockDumpProvider mdp1; |
171 MockDumpProvider mdp2; | 166 MockDumpProvider mdp2; |
172 | 167 |
173 // Enable only mdp1. | 168 // Enable only mdp1. |
174 mdm_->RegisterDumpProvider(&mdp1); | 169 mdm_->RegisterDumpProvider(&mdp1); |
175 EnableTracing(kTraceCategory); | 170 EnableTracing(kTraceCategory); |
176 EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(true)); | 171 EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true)); |
177 EXPECT_CALL(mdp2, DumpInto(_)).Times(0); | 172 EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(0); |
178 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | 173 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); |
179 DisableTracing(); | 174 DisableTracing(); |
180 | 175 |
181 // Invert: enable mdp1 and disable mdp2. | 176 // Invert: enable mdp1 and disable mdp2. |
182 mdm_->UnregisterDumpProvider(&mdp1); | 177 mdm_->UnregisterDumpProvider(&mdp1); |
183 mdm_->RegisterDumpProvider(&mdp2); | 178 mdm_->RegisterDumpProvider(&mdp2); |
184 EnableTracing(kTraceCategory); | 179 EnableTracing(kTraceCategory); |
185 EXPECT_CALL(mdp1, DumpInto(_)).Times(0); | 180 EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(0); |
186 EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true)); | 181 EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true)); |
187 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | 182 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); |
188 DisableTracing(); | 183 DisableTracing(); |
189 | 184 |
190 // Enable both mdp1 and mdp2. | 185 // Enable both mdp1 and mdp2. |
191 mdm_->RegisterDumpProvider(&mdp1); | 186 mdm_->RegisterDumpProvider(&mdp1); |
192 EnableTracing(kTraceCategory); | 187 EnableTracing(kTraceCategory); |
193 EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(true)); | 188 EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true)); |
194 EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true)); | 189 EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true)); |
195 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | 190 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); |
196 DisableTracing(); | 191 DisableTracing(); |
197 } | 192 } |
198 | 193 |
199 // Checks that the MemoryDumpManager respects the thread affinity when a | 194 // Checks that the MemoryDumpManager respects the thread affinity when a |
200 // MemoryDumpProvider specifies a task_runner(). The test starts creating 8 | 195 // MemoryDumpProvider specifies a task_runner(). The test starts creating 8 |
201 // threads and registering a MemoryDumpProvider on each of them. At each | 196 // threads and registering a MemoryDumpProvider on each of them. At each |
202 // iteration, one thread is removed, to check the live unregistration logic. | 197 // iteration, one thread is removed, to check the live unregistration logic. |
203 TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) { | 198 TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) { |
204 const uint32 kNumInitialThreads = 8; | 199 const uint32 kNumInitialThreads = 8; |
205 | 200 |
206 ScopedVector<Thread> threads; | 201 ScopedVector<Thread> threads; |
207 ScopedVector<MockDumpProvider> mdps; | 202 ScopedVector<MockDumpProvider> mdps; |
208 | 203 |
209 // Create the threads and setup the expectations. Given that at each iteration | 204 // Create the threads and setup the expectations. Given that at each iteration |
210 // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be | 205 // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be |
211 // invoked a number of times equal to its index. | 206 // invoked a number of times equal to its index. |
212 for (uint32 i = kNumInitialThreads; i > 0; --i) { | 207 for (uint32 i = kNumInitialThreads; i > 0; --i) { |
213 threads.push_back(new Thread("test thread")); | 208 threads.push_back(new Thread("test thread")); |
214 threads.back()->Start(); | 209 threads.back()->Start(); |
215 mdps.push_back(new MockDumpProvider(threads.back()->task_runner())); | 210 mdps.push_back(new MockDumpProvider(threads.back()->task_runner())); |
216 MockDumpProvider* mdp = mdps.back(); | 211 MockDumpProvider* mdp = mdps.back(); |
217 mdm_->RegisterDumpProvider(mdp); | 212 mdm_->RegisterDumpProvider(mdp, threads.back()->task_runner()); |
218 EXPECT_CALL(*mdp, DumpInto(_)) | 213 EXPECT_CALL(*mdp, OnMemoryDump(_)) |
219 .Times(i) | 214 .Times(i) |
220 .WillRepeatedly( | 215 .WillRepeatedly( |
221 Invoke(mdp, &MockDumpProvider::DumpIntoAndCheckTaskRunner)); | 216 Invoke(mdp, &MockDumpProvider::OnMemoryDump_CheckTaskRunner)); |
222 } | 217 } |
223 | 218 |
224 EnableTracing(kTraceCategory); | 219 EnableTracing(kTraceCategory); |
225 | 220 |
226 while (!threads.empty()) { | 221 while (!threads.empty()) { |
227 { | 222 { |
228 RunLoop run_loop; | 223 RunLoop run_loop; |
229 MemoryDumpCallback callback = | 224 MemoryDumpCallback callback = |
230 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 225 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), |
231 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 226 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); |
(...skipping 27 matching lines...) Expand all Loading... |
259 // invoked the 2nd time. | 254 // invoked the 2nd time. |
260 // FIXME(primiano): remove once crbug.com/461788 gets fixed. | 255 // FIXME(primiano): remove once crbug.com/461788 gets fixed. |
261 TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) { | 256 TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) { |
262 MockDumpProvider mdp1; | 257 MockDumpProvider mdp1; |
263 MockDumpProvider mdp2; | 258 MockDumpProvider mdp2; |
264 | 259 |
265 mdm_->RegisterDumpProvider(&mdp1); | 260 mdm_->RegisterDumpProvider(&mdp1); |
266 mdm_->RegisterDumpProvider(&mdp2); | 261 mdm_->RegisterDumpProvider(&mdp2); |
267 EnableTracing(kTraceCategory); | 262 EnableTracing(kTraceCategory); |
268 | 263 |
269 EXPECT_CALL(mdp1, DumpInto(_)).Times(1).WillRepeatedly(Return(false)); | 264 EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(false)); |
270 EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(true)); | 265 EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(true)); |
271 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | 266 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); |
272 | 267 |
273 EXPECT_CALL(mdp1, DumpInto(_)).Times(0); | 268 EXPECT_CALL(mdp1, OnMemoryDump(_)).Times(0); |
274 EXPECT_CALL(mdp2, DumpInto(_)).Times(1).WillRepeatedly(Return(false)); | 269 EXPECT_CALL(mdp2, OnMemoryDump(_)).Times(1).WillRepeatedly(Return(false)); |
275 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | 270 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); |
276 | 271 |
277 DisableTracing(); | 272 DisableTracing(); |
278 } | 273 } |
279 | 274 |
280 // TODO(primiano): remove once crbug.com/466121 gets fixed. | |
281 // Ascertains that calls to MDM::dump_provider_currently_active() actually | |
282 // returns the MemoryDumpProvider currently active during the DumpInto() call. | |
283 TEST_F(MemoryDumpManagerTest, ActiveDumpProviderConsistency) { | |
284 MockDumpProvider mdp1; | |
285 MockDumpProvider mdp2; | |
286 | |
287 mdm_->RegisterDumpProvider(&mdp1); | |
288 mdm_->RegisterDumpProvider(&mdp2); | |
289 EnableTracing(kTraceCategory); | |
290 EXPECT_CALL(mdp1, DumpInto(_)) | |
291 .Times(2) | |
292 .WillRepeatedly(Invoke( | |
293 &mdp1, | |
294 &MockDumpProvider::DumpIntoAndCheckDumpProviderCurrentlyActive)); | |
295 EXPECT_CALL(mdp2, DumpInto(_)) | |
296 .Times(2) | |
297 .WillRepeatedly(Invoke( | |
298 &mdp2, | |
299 &MockDumpProvider::DumpIntoAndCheckDumpProviderCurrentlyActive)); | |
300 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | |
301 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED); | |
302 DisableTracing(); | |
303 } | |
304 | |
305 } // namespace trace_event | 275 } // namespace trace_event |
306 } // namespace base | 276 } // namespace base |
OLD | NEW |