Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Side by Side Diff: base/trace_event/memory_peak_detector_unittest.cc

Issue 2786373002: memory-infra: Add peak-detector skeleton. (Closed)
Patch Set: . Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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_peak_detector.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/run_loop.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/test/test_timeouts.h"
14 #include "base/threading/platform_thread.h"
15 #include "base/threading/thread.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "base/trace_event/memory_dump_provider.h"
18 #include "base/trace_event/memory_dump_provider_info.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace base {
22 namespace trace_event {
23
24 namespace {
25 class MockMemoryDumpProvider : public MemoryDumpProvider {
26 public:
27 MockMemoryDumpProvider(WaitableEvent* evt) : evt_(evt) {}
28 bool OnMemoryDump(const MemoryDumpArgs&, ProcessMemoryDump*) override {
29 NOTREACHED();
30 return true;
31 }
32
33 void PollFastMemoryTotal(uint64_t* memory_total) override { evt_->Signal(); }
34
35 WaitableEvent* const evt_;
36 };
37 } // namespace
38
39 class MemoryPeakDetectorTest : public testing::Test {
40 public:
41 MemoryPeakDetectorTest() : testing::Test() {}
42
43 void RestartThreadAndReinitializePeakDetector() {
44 if (bg_thread_)
45 bg_thread_->Stop();
46 bg_thread_.reset(new Thread("Peak Detector Test Thread"));
47 bg_thread_->Start();
48 peak_detector_->Initialize(
49 Bind(&MemoryPeakDetectorTest::MockGetDumpProviders, Unretained(this)),
50 bg_thread_->task_runner(),
51 Bind(&MemoryPeakDetectorTest::OnPeakDetectedCallback,
52 Unretained(this)));
53 }
54
55 void SetUp() override {
56 peak_detector_ = MemoryPeakDetector::GetInstance();
57 get_mdp_call_count = 0;
58 RestartThreadAndReinitializePeakDetector();
59 }
60
61 void TearDown() override {
62 dump_providers.clear();
63 peak_detector_->TearDownForTesting();
64 bg_thread_->Stop();
65 bg_thread_.reset();
66 }
67
68 // Calls MemoryPeakDetector::state_for_testing() on the bg thread and returns
69 // the result on the current thread.
70 MemoryPeakDetector::State GetPeakDetectorState() {
71 MemoryPeakDetector::State res = MemoryPeakDetector::NOT_INITIALIZED;
72 auto get_fn = [](MemoryPeakDetector* peak_detector, WaitableEvent* evt,
73 MemoryPeakDetector::State* res) {
74 *res = peak_detector->state_for_testing();
75 evt->Signal();
76 };
77
78 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
79 WaitableEvent::InitialState::NOT_SIGNALED);
80 bg_thread_->task_runner()->PostTask(
81 FROM_HERE, Bind(get_fn, Unretained(peak_detector_), Unretained(&evt),
82 Unretained(&res)));
83 evt.Wait();
84 return res;
85 }
86
87 // Calls MemoryPeakDetector::poll_tasks_count_for_testing() on the bg thread
88 // and returns the result on the current thread.
89 uint32_t GetNumPollingTasksRan() {
90 uint32_t res = 0;
91 auto get_fn = [](MemoryPeakDetector* peak_detector, WaitableEvent* evt,
92 uint32_t* res) {
93 *res = peak_detector->poll_tasks_count_for_testing();
94 evt->Signal();
95 };
96
97 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
98 WaitableEvent::InitialState::NOT_SIGNALED);
99 bg_thread_->task_runner()->PostTask(
100 FROM_HERE, Bind(get_fn, Unretained(peak_detector_), Unretained(&evt),
101 Unretained(&res)));
102 evt.Wait();
103 return res;
104 }
105
106 void MockGetDumpProviders(MemoryPeakDetector::DumpProvidersList* mdps) {
107 get_mdp_call_count++;
108 *mdps = dump_providers;
109 }
110
111 void OnPeakDetectedCallback() {
112 // TODO(primiano): use in upcoming CLs.
113 }
114
115 scoped_refptr<MemoryDumpProviderInfo> CreateMockDumpProvider(
116 WaitableEvent* evt) {
117 std::unique_ptr<MemoryDumpProvider> mdp(new MockMemoryDumpProvider(evt));
118 MemoryDumpProvider::Options opt;
119 opt.is_fast_polling_supported = true;
120 scoped_refptr<MemoryDumpProviderInfo> mdp_info(
121 new MemoryDumpProviderInfo(mdp.get(), "Mock MDP", nullptr, opt, false));
122
123 // The |mdp| instance will be destroyed together with the |mdp_info|.
124 mdp_info->owned_dump_provider = std::move(mdp);
125 return mdp_info;
126 }
127
128 protected:
129 MemoryPeakDetector::DumpProvidersList dump_providers;
130 uint32_t get_mdp_call_count;
131 MemoryPeakDetector* peak_detector_;
132 std::unique_ptr<Thread> bg_thread_;
133 };
134
135 TEST_F(MemoryPeakDetectorTest, GetDumpProvidersFunctionCalled) {
136 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
137 peak_detector_->Start();
138 bg_thread_->FlushForTesting();
139 EXPECT_EQ(1u, get_mdp_call_count);
140 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
141
142 peak_detector_->Stop();
143 bg_thread_->FlushForTesting();
144 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
145 EXPECT_EQ(0u, GetNumPollingTasksRan());
146 }
147
148 TEST_F(MemoryPeakDetectorTest, DoubleStop) {
149 peak_detector_->Start();
150 bg_thread_->FlushForTesting();
151
152 peak_detector_->Stop();
153 bg_thread_->FlushForTesting();
154
155 peak_detector_->Stop();
156 bg_thread_->FlushForTesting();
157
158 EXPECT_EQ(1u, get_mdp_call_count);
159 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
160 EXPECT_EQ(0u, GetNumPollingTasksRan());
161 }
162
163 TEST_F(MemoryPeakDetectorTest, OneDumpProviderRegisteredBeforeStart) {
164 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
165 WaitableEvent::InitialState::NOT_SIGNALED);
166 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider(&evt);
167 dump_providers.push_back(mdp);
168
169 peak_detector_->Start();
170 bg_thread_->FlushForTesting();
171 evt.Wait(); // Signaled when PollFastMemoryTotal() is called on the MockMDP.
172 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
173
174 peak_detector_->Stop();
175 bg_thread_->FlushForTesting();
176
177 EXPECT_EQ(1u, get_mdp_call_count);
178 EXPECT_GT(GetNumPollingTasksRan(), 0u);
179 }
180
181 TEST_F(MemoryPeakDetectorTest, ReInitializeAndRebindToNewThread) {
182 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
183 WaitableEvent::InitialState::NOT_SIGNALED);
184 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider(&evt);
185 dump_providers.push_back(mdp);
186
187 for (int i = 0; i < 5; ++i) {
188 evt.Reset();
189 peak_detector_->Start();
190 bg_thread_->FlushForTesting();
191 evt.Wait(); // Wait for a PollFastMemoryTotal() call.
192 peak_detector_->Stop();
193
194 // Reinitialize and re-bind to a new task runner.
195 RestartThreadAndReinitializePeakDetector();
196 }
197 }
198
199 TEST_F(MemoryPeakDetectorTest, OneDumpProviderRegisteredOutOfBand) {
200 peak_detector_->Start();
201 bg_thread_->FlushForTesting();
202 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
203 EXPECT_EQ(1u, get_mdp_call_count);
204
205 // Check that no poll tasks are posted before any dump provider is registered.
206 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
207 EXPECT_EQ(0u, GetNumPollingTasksRan());
208
209 // Registed the MDP After Start() has been issued and expect that the
210 // PeakDetector transitions ENABLED -> RUNNING on the next
211 // NotifyMemoryDumpProvidersChanged() call.
212 WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
213 WaitableEvent::InitialState::NOT_SIGNALED);
214 scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider(&evt);
215 dump_providers.push_back(mdp);
216 peak_detector_->NotifyMemoryDumpProvidersChanged();
217
218 evt.Wait(); // Signaled when PollFastMemoryTotal() is called on the MockMDP.
219 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
220 EXPECT_EQ(2u, get_mdp_call_count);
221
222 // Now simulate the unregisration and expect that the PeakDetector transitions
223 // back to ENABLED.
224 dump_providers.clear();
225 peak_detector_->NotifyMemoryDumpProvidersChanged();
226 bg_thread_->FlushForTesting();
227 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
228 EXPECT_EQ(3u, get_mdp_call_count);
229 uint32_t num_poll_tasks = GetNumPollingTasksRan();
230 EXPECT_GT(num_poll_tasks, 0u);
231
232 // At this point, no more polling tasks should be posted.
233 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
234 peak_detector_->Stop();
235 bg_thread_->FlushForTesting();
236 EXPECT_EQ(num_poll_tasks, GetNumPollingTasksRan());
237 }
238
239 TEST_F(MemoryPeakDetectorTest, RegisterAndUnregisterTwoDumpProviders) {
240 WaitableEvent evt1(WaitableEvent::ResetPolicy::MANUAL,
241 WaitableEvent::InitialState::NOT_SIGNALED);
242 WaitableEvent evt2(WaitableEvent::ResetPolicy::MANUAL,
243 WaitableEvent::InitialState::NOT_SIGNALED);
244 scoped_refptr<MemoryDumpProviderInfo> mdp1 = CreateMockDumpProvider(&evt1);
245 scoped_refptr<MemoryDumpProviderInfo> mdp2 = CreateMockDumpProvider(&evt2);
246
247 // Register only one MDP and start the detector.
248 dump_providers.push_back(mdp1);
249 peak_detector_->Start();
250 bg_thread_->FlushForTesting();
251 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
252
253 // Wait for one poll task and then register also the other one.
254 evt1.Wait();
255 dump_providers.push_back(mdp2);
256 peak_detector_->NotifyMemoryDumpProvidersChanged();
257 evt2.Wait();
258 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
259
260 // Now unregister the first MDP and check that everything is still running.
261 dump_providers.erase(dump_providers.begin());
262 peak_detector_->NotifyMemoryDumpProvidersChanged();
263 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
264
265 // Now unregister both and check that the detector goes to idle.
266 dump_providers.clear();
267 peak_detector_->NotifyMemoryDumpProvidersChanged();
268 bg_thread_->FlushForTesting();
269 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
270
271 // Now re-register both and check that the detector re-activates posting
272 // new polling tasks.
273 uint32_t num_poll_tasks = GetNumPollingTasksRan();
274 evt1.Reset();
275 evt2.Reset();
276 dump_providers.push_back(mdp1);
277 dump_providers.push_back(mdp2);
278 peak_detector_->NotifyMemoryDumpProvidersChanged();
279 bg_thread_->FlushForTesting();
280 evt1.Wait();
281 evt2.Wait();
282 EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
283 EXPECT_GT(GetNumPollingTasksRan(), num_poll_tasks);
284
285 // Stop everything, tear down the MDPs, restart the detector and check that
286 // it detector doesn't accidentally try to re-access them.
287 peak_detector_->Stop();
288 bg_thread_->FlushForTesting();
289 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
290 dump_providers.clear();
291 mdp1 = nullptr;
292 mdp2 = nullptr;
293
294 num_poll_tasks = GetNumPollingTasksRan();
295 peak_detector_->Start();
296 bg_thread_->FlushForTesting();
297 EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
298 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
299 peak_detector_->Stop();
300 bg_thread_->FlushForTesting();
301 EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
302 EXPECT_EQ(num_poll_tasks, GetNumPollingTasksRan());
303
304 EXPECT_EQ(6u, get_mdp_call_count);
305 }
306
307 } // namespace trace_event
308 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698