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

Side by Side Diff: components/memory_pressure/memory_pressure_monitor_unittest.cc

Issue 2874553004: Remove memory_pressure component. (Closed)
Patch Set: Created 3 years, 7 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 2016 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 "components/memory_pressure/memory_pressure_monitor.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/task_runner.h"
12 #include "base/test/simple_test_tick_clock.h"
13 #include "base/tracked_objects.h"
14 #include "components/memory_pressure/memory_pressure_stats_collector.h"
15 #include "components/memory_pressure/test_memory_pressure_calculator.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace memory_pressure {
20
21 namespace {
22
23 using MemoryPressureLevel = MemoryPressureMonitor::MemoryPressureLevel;
24 const MemoryPressureLevel MEMORY_PRESSURE_LEVEL_NONE =
25 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
26 const MemoryPressureLevel MEMORY_PRESSURE_LEVEL_MODERATE =
27 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
28 const MemoryPressureLevel MEMORY_PRESSURE_LEVEL_CRITICAL =
29 MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
30
31 using testing::_;
32
33 } // namespace
34
35 // A mock task runner. This isn't directly a TaskRunner as the reference
36 // counting confuses gmock.
37 class LenientMockTaskRunner {
38 public:
39 MOCK_METHOD2(PostDelayedTask,
40 bool(const tracked_objects::Location&, base::TimeDelta));
41 };
42 using MockTaskRunner = testing::StrictMock<LenientMockTaskRunner>;
43
44 // A TaskRunner implementation that wraps a MockTaskRunner.
45 class TaskRunnerProxy : public base::TaskRunner {
46 public:
47 // The provided |mock| must outlive this object.
48 explicit TaskRunnerProxy(MockTaskRunner* mock) : mock_(mock) {}
49 bool RunsTasksInCurrentSequence() const override { return true; }
50 bool PostDelayedTask(const tracked_objects::Location& location,
51 base::OnceClosure closure,
52 base::TimeDelta delta) override {
53 return mock_->PostDelayedTask(location, delta);
54 }
55
56 private:
57 MockTaskRunner* mock_;
58 ~TaskRunnerProxy() override {}
59 };
60
61 class TestMemoryPressureMonitor : public MemoryPressureMonitor {
62 public:
63 // Expose the callback that is used for scheduled checks.
64 using MemoryPressureMonitor::CheckPressureAndUpdateStats;
65
66 #if !defined(MEMORY_PRESSURE_IS_POLLING)
67 using MemoryPressureMonitor::OnMemoryPressureChanged;
68 #endif
69
70 #if defined(MEMORY_PRESSURE_IS_POLLING)
71 TestMemoryPressureMonitor(scoped_refptr<base::TaskRunner> task_runner,
72 base::TickClock* tick_clock,
73 MemoryPressureStatsCollector* stats_collector,
74 MemoryPressureCalculator* calculator,
75 DispatchCallback dispatch_callback)
76 : MemoryPressureMonitor(task_runner,
77 tick_clock,
78 stats_collector,
79 calculator,
80 dispatch_callback) {}
81 #else // MEMORY_PRESSURE_IS_POLLING
82 TestMemoryPressureMonitor(scoped_refptr<base::TaskRunner> task_runner,
83 base::TickClock* tick_clock,
84 MemoryPressureStatsCollector* stats_collector,
85 DispatchCallback dispatch_callback,
86 MemoryPressureLevel initial_level)
87 : MemoryPressureMonitor(task_runner,
88 tick_clock,
89 stats_collector,
90 dispatch_callback,
91 initial_level) {}
92 #endif // !MEMORY_PRESSURE_IS_POLLING
93
94 // A handful of accessors for unittesting.
95 MemoryPressureLevel current_memory_pressure_level() const {
96 return current_memory_pressure_level_;
97 }
98 const std::map<int, base::TimeTicks>& scheduled_checks() const {
99 return scheduled_checks_;
100 }
101 int serial_number() const { return serial_number_; }
102 };
103
104 // A mock dispatch class.
105 class LenientMockDispatch {
106 public:
107 MOCK_METHOD1(Dispatch, void(MemoryPressureLevel));
108 };
109 using MockDispatch = testing::StrictMock<LenientMockDispatch>;
110
111 class MemoryPressureMonitorTest : public testing::Test {
112 public:
113 MemoryPressureMonitorTest()
114 : task_runner_proxy_(new TaskRunnerProxy(&mock_task_runner_)),
115 stats_collector_(&tick_clock_) {}
116
117 #if defined(MEMORY_PRESSURE_IS_POLLING)
118 // Creates a monitor in the given initial pressure level and validates its
119 // state.
120 void CreateMonitor(MemoryPressureLevel initial_level) {
121 calculator_.SetLevel(initial_level);
122 Tick(1); // Advance the clock so it doesn't return zero.
123
124 // Determine the delay with which we expect the task to be posted.
125 int delay = MemoryPressureMonitor::kDefaultPollingIntervalMs;
126 if (initial_level == MEMORY_PRESSURE_LEVEL_MODERATE)
127 delay = MemoryPressureMonitor::kNotificationIntervalPressureModerateMs;
128 else if (initial_level == MEMORY_PRESSURE_LEVEL_CRITICAL)
129 delay = MemoryPressureMonitor::kNotificationIntervalPressureCriticalMs;
130
131 // The monitor will make one call to the task runner during construction.
132 ExpectTaskPosted(delay);
133 monitor_.reset(new TestMemoryPressureMonitor(
134 task_runner_proxy_, &tick_clock_, &stats_collector_, &calculator_,
135 base::Bind(&MockDispatch::Dispatch,
136 base::Unretained(&mock_dispatch_))));
137 VerifyAndClearExpectations();
138 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
139
140 // The monitor should have made one call immediately to the calculator_.
141 EXPECT_EQ(1, calculator_.calls());
142 ExpectPressure(initial_level);
143 calculator_.ResetCalls();
144 }
145 #else // MEMORY_PRESSURE_IS_POLLING
146 void CreateMonitor(MemoryPressureLevel initial_level) {
147 Tick(1); // Advance the clock so it doesn't return zero.
148
149 // The monitor will make one call to the task runner during construction.
150 ExpectTaskPosted(MemoryPressureMonitor::kDefaultPollingIntervalMs);
151 monitor_.reset(new TestMemoryPressureMonitor(
152 task_runner_proxy_, &tick_clock_, &stats_collector_,
153 base::Bind(&MockDispatch::Dispatch, base::Unretained(&mock_dispatch_)),
154 initial_level));
155 VerifyAndClearExpectations();
156 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
157
158 // The monitor should have made one call immediately to the calculator_.
159 ExpectPressure(initial_level);
160 }
161 #endif // !MEMORY_PRESSURE_IS_POLLING
162
163 // Advances the tick clock by the given number of milliseconds.
164 void Tick(int ms) {
165 tick_clock_.Advance(base::TimeDelta::FromMilliseconds(ms));
166 }
167
168 // Sets expectations for tasks scheduled via |mock_task_runner_|.
169 void ExpectTaskPosted(int delay_ms) {
170 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms);
171 EXPECT_CALL(mock_task_runner_, PostDelayedTask(_, delay))
172 .WillOnce(testing::Return(true));
173 }
174
175 // Sets up expectations for calls to |mock_dispatch_|.
176 void ExpectDispatch(MemoryPressureLevel level) {
177 EXPECT_CALL(mock_dispatch_, Dispatch(level));
178 }
179 void ExpectDispatchModerate() {
180 EXPECT_CALL(mock_dispatch_, Dispatch(MEMORY_PRESSURE_LEVEL_MODERATE));
181 }
182 void ExpectDispatchCritical() {
183 EXPECT_CALL(mock_dispatch_, Dispatch(MEMORY_PRESSURE_LEVEL_CRITICAL));
184 }
185
186 // Verifies and clears expectations for both |mock_task_runner_| and
187 // |mock_dispatch_|.
188 void VerifyAndClearExpectations() {
189 testing::Mock::VerifyAndClearExpectations(&mock_task_runner_);
190 testing::Mock::VerifyAndClearExpectations(&mock_dispatch_);
191 }
192
193 // Checks expectations on |monitor_->current_memory_pressure_level()|.
194 void ExpectPressure(MemoryPressureLevel level) {
195 EXPECT_EQ(level, monitor_->current_memory_pressure_level());
196 }
197 void ExpectNone() {
198 EXPECT_EQ(MEMORY_PRESSURE_LEVEL_NONE,
199 monitor_->current_memory_pressure_level());
200 }
201 void ExpectModerate() {
202 EXPECT_EQ(MEMORY_PRESSURE_LEVEL_MODERATE,
203 monitor_->current_memory_pressure_level());
204 }
205 void ExpectCritical() {
206 EXPECT_EQ(MEMORY_PRESSURE_LEVEL_CRITICAL,
207 monitor_->current_memory_pressure_level());
208 }
209
210 MockTaskRunner mock_task_runner_;
211 scoped_refptr<TaskRunnerProxy> task_runner_proxy_;
212 base::SimpleTestTickClock tick_clock_;
213 MemoryPressureStatsCollector stats_collector_;
214
215 #if defined(MEMORY_PRESSURE_IS_POLLING)
216 TestMemoryPressureCalculator calculator_;
217 #endif
218
219 MockDispatch mock_dispatch_;
220 std::unique_ptr<TestMemoryPressureMonitor> monitor_;
221 };
222
223 TEST_F(MemoryPressureMonitorTest, NormalScheduling) {
224 CreateMonitor(MEMORY_PRESSURE_LEVEL_NONE);
225
226 Tick(MemoryPressureMonitor::kDefaultPollingIntervalMs);
227 ExpectTaskPosted(MemoryPressureMonitor::kDefaultPollingIntervalMs);
228 monitor_->CheckPressureAndUpdateStats(monitor_->serial_number());
229 VerifyAndClearExpectations();
230
231 Tick(MemoryPressureMonitor::kDefaultPollingIntervalMs);
232 ExpectTaskPosted(MemoryPressureMonitor::kDefaultPollingIntervalMs);
233 monitor_->CheckPressureAndUpdateStats(monitor_->serial_number());
234 VerifyAndClearExpectations();
235 }
236
237 #if defined(MEMORY_PRESSURE_IS_POLLING)
238
239 TEST_F(MemoryPressureMonitorTest, CalculatorNotAlwaysInvoked) {
240 CreateMonitor(MEMORY_PRESSURE_LEVEL_NONE);
241
242 // Callback into the monitor too soon and expect nothing to happen.
243 Tick(1);
244 EXPECT_EQ(MEMORY_PRESSURE_LEVEL_NONE, monitor_->GetCurrentPressureLevel());
245 VerifyAndClearExpectations();
246 EXPECT_EQ(0, calculator_.calls());
247 ExpectNone();
248 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
249
250 // Pass sufficient time that the rate limiter will allow another calculation.
251 // Don't expect another scheduled call because there's already one pending.
252 Tick(MemoryPressureMonitor::kMinimumTimeBetweenSamplesMs);
253 EXPECT_EQ(MEMORY_PRESSURE_LEVEL_NONE, monitor_->GetCurrentPressureLevel());
254 VerifyAndClearExpectations();
255 EXPECT_EQ(1, calculator_.calls());
256 ExpectNone();
257 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
258 }
259
260 TEST_F(MemoryPressureMonitorTest, NoPressureScheduling) {
261 CreateMonitor(MEMORY_PRESSURE_LEVEL_NONE);
262
263 // Step forward by a polling interval. This should cause another scheduled
264 // check to be posted.
265 Tick(MemoryPressureMonitor::kDefaultPollingIntervalMs);
266 ExpectTaskPosted(MemoryPressureMonitor::kDefaultPollingIntervalMs);
267 monitor_->CheckPressureAndUpdateStats(monitor_->serial_number());
268 VerifyAndClearExpectations();
269 ExpectNone();
270 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
271 }
272
273 TEST_F(MemoryPressureMonitorTest, NoPressureToModerateViaScheduling) {
274 CreateMonitor(MEMORY_PRESSURE_LEVEL_NONE);
275
276 // Step forward by a polling interval. This should cause another scheduled
277 // check to be posted.
278 calculator_.SetModerate();
279 Tick(MemoryPressureMonitor::kDefaultPollingIntervalMs);
280 ExpectTaskPosted(
281 MemoryPressureMonitor::kNotificationIntervalPressureModerateMs);
282 ExpectDispatchModerate();
283 monitor_->CheckPressureAndUpdateStats(monitor_->serial_number());
284 VerifyAndClearExpectations();
285 ExpectModerate();
286 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
287 }
288
289 TEST_F(MemoryPressureMonitorTest, NoPressureToCriticalViaScheduling) {
290 CreateMonitor(MEMORY_PRESSURE_LEVEL_NONE);
291
292 // Step forward by a polling interval. This should cause another scheduled
293 // check to be posted.
294 calculator_.SetCritical();
295 Tick(MemoryPressureMonitor::kDefaultPollingIntervalMs);
296 ExpectTaskPosted(
297 MemoryPressureMonitor::kNotificationIntervalPressureCriticalMs);
298 ExpectDispatchCritical();
299 monitor_->CheckPressureAndUpdateStats(monitor_->serial_number());
300 VerifyAndClearExpectations();
301 ExpectCritical();
302 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
303 }
304
305 TEST_F(MemoryPressureMonitorTest, ModeratePressureToCriticalViaScheduling) {
306 CreateMonitor(MEMORY_PRESSURE_LEVEL_MODERATE);
307
308 // Step forward by a polling interval. This should cause another scheduled
309 // check to be posted.
310 calculator_.SetCritical();
311 Tick(MemoryPressureMonitor::kNotificationIntervalPressureModerateMs);
312 ExpectTaskPosted(
313 MemoryPressureMonitor::kNotificationIntervalPressureCriticalMs);
314 ExpectDispatchCritical();
315 monitor_->CheckPressureAndUpdateStats(monitor_->serial_number());
316 VerifyAndClearExpectations();
317 ExpectCritical();
318 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
319 }
320
321 TEST_F(MemoryPressureMonitorTest, UnscheduledStateChange) {
322 CreateMonitor(MEMORY_PRESSURE_LEVEL_NONE);
323
324 // Callback into the monitor directly. This will change the memory pressure
325 // and cause a new call to be scheduled as the higher memory pressure has a
326 // higher renotification frequency.
327 // NOTE: This test relies implicitly on the following facts:
328 // kMinimumTimeBetweenSamplesMs < kDefaultPollingIntervalMs / 2
329 // kNotificationIntervalPressureCriticalMs < kDefaultPollingIntervalMs / 2
330 calculator_.SetCritical();
331 Tick(MemoryPressureMonitor::kDefaultPollingIntervalMs / 2);
332 ExpectTaskPosted(
333 MemoryPressureMonitor::kNotificationIntervalPressureCriticalMs);
334 ExpectDispatchCritical();
335 EXPECT_EQ(MEMORY_PRESSURE_LEVEL_CRITICAL,
336 monitor_->GetCurrentPressureLevel());
337 VerifyAndClearExpectations();
338 EXPECT_EQ(1, calculator_.calls());
339 ExpectCritical();
340 EXPECT_EQ(2u, monitor_->scheduled_checks().size());
341 }
342
343 #else // MEMORY_PRESSURE_IS_POLLING
344
345 TEST_F(MemoryPressureMonitorTest, PressureChangeNop) {
346 CreateMonitor(MEMORY_PRESSURE_LEVEL_NONE);
347
348 // The pressure hasn't changed so this should be a nop.
349 Tick(1);
350 monitor_->OnMemoryPressureChanged(MEMORY_PRESSURE_LEVEL_NONE);
351 VerifyAndClearExpectations();
352 ExpectNone();
353 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
354 }
355
356 TEST_F(MemoryPressureMonitorTest, PressureChangeNoNewScheduledTask) {
357 CreateMonitor(MEMORY_PRESSURE_LEVEL_NONE);
358
359 // The pressure is increasing and the renotification frequency has changed.
360 // However, a pending event is already scheduled soon enough so no new one
361 // should be scheduled.
362 Tick(MemoryPressureMonitor::kDefaultPollingIntervalMs -
363 MemoryPressureMonitor::kNotificationIntervalPressureModerateMs / 2);
364 ExpectDispatchModerate();
365 monitor_->OnMemoryPressureChanged(MEMORY_PRESSURE_LEVEL_MODERATE);
366 VerifyAndClearExpectations();
367 ExpectModerate();
368 EXPECT_EQ(1u, monitor_->scheduled_checks().size());
369 }
370
371 TEST_F(MemoryPressureMonitorTest, PressureChangeNewScheduledTask) {
372 CreateMonitor(MEMORY_PRESSURE_LEVEL_NONE);
373
374 // The pressure is increasing and the renotification frequency has changed.
375 // The already scheduled event is too far in the future so a new event should
376 // be scheduled.
377 Tick(1);
378 ExpectTaskPosted(
379 MemoryPressureMonitor::kNotificationIntervalPressureCriticalMs);
380 ExpectDispatchCritical();
381 monitor_->OnMemoryPressureChanged(MEMORY_PRESSURE_LEVEL_CRITICAL);
382 VerifyAndClearExpectations();
383 ExpectCritical();
384 EXPECT_EQ(2u, monitor_->scheduled_checks().size());
385 }
386
387 #endif // !MEMORY_PRESSURE_IS_POLLING
388
389 } // namespace memory_pressure
OLDNEW
« no previous file with comments | « components/memory_pressure/memory_pressure_monitor.cc ('k') | components/memory_pressure/memory_pressure_stats_collector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698