Ensure low-memory renderers retry failed loads correctly.
[chromium-blink-merge.git] / base / memory / memory_pressure_monitor_win_unittest.cc
blobd9a9575aeccb8004a6708b7e218e59274fd19320
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/memory/memory_pressure_monitor_win.h"
7 #include "base/basictypes.h"
8 #include "base/memory/memory_pressure_listener.h"
9 #include "base/message_loop/message_loop.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 namespace base {
14 namespace win {
16 namespace {
18 struct PressureSettings {
19 int phys_left_mb;
20 MemoryPressureListener::MemoryPressureLevel level;
23 } // namespace
25 // This is outside of the anonymous namespace so that it can be seen as a friend
26 // to the monitor class.
27 class TestMemoryPressureMonitor : public MemoryPressureMonitor {
28 public:
29 using MemoryPressureMonitor::CalculateCurrentPressureLevel;
30 using MemoryPressureMonitor::CheckMemoryPressure;
32 static const DWORDLONG kMBBytes = 1024 * 1024;
34 explicit TestMemoryPressureMonitor(bool large_memory)
35 : mem_status_() {
36 // Generate a plausible amount of memory.
37 mem_status_.ullTotalPhys =
38 static_cast<DWORDLONG>(GenerateTotalMemoryMb(large_memory)) * kMBBytes;
40 // Rerun InferThresholds using the test fixture's GetSystemMemoryStatus.
41 InferThresholds();
42 // Stop the timer.
43 StopObserving();
46 TestMemoryPressureMonitor(int system_memory_mb,
47 int moderate_threshold_mb,
48 int critical_threshold_mb)
49 : MemoryPressureMonitor(moderate_threshold_mb, critical_threshold_mb),
50 mem_status_() {
51 // Set the amount of system memory.
52 mem_status_.ullTotalPhys = static_cast<DWORDLONG>(
53 system_memory_mb * kMBBytes);
55 // Stop the timer.
56 StopObserving();
59 virtual ~TestMemoryPressureMonitor() {}
61 MOCK_METHOD1(OnMemoryPressure,
62 void(MemoryPressureListener::MemoryPressureLevel level));
64 // Generates an amount of total memory that is consistent with the requested
65 // memory model.
66 int GenerateTotalMemoryMb(bool large_memory) {
67 int total_mb = 64;
68 while (total_mb < MemoryPressureMonitor::kLargeMemoryThresholdMb)
69 total_mb *= 2;
70 if (large_memory)
71 return total_mb * 2;
72 return total_mb / 2;
75 // Sets up the memory status to reflect the provided absolute memory left.
76 void SetMemoryFree(int phys_left_mb) {
77 // ullTotalPhys is set in the constructor and not modified.
79 // Set the amount of available memory.
80 mem_status_.ullAvailPhys =
81 static_cast<DWORDLONG>(phys_left_mb) * kMBBytes;
82 DCHECK_LT(mem_status_.ullAvailPhys, mem_status_.ullTotalPhys);
84 // These fields are unused.
85 mem_status_.dwMemoryLoad = 0;
86 mem_status_.ullTotalPageFile = 0;
87 mem_status_.ullAvailPageFile = 0;
88 mem_status_.ullTotalVirtual = 0;
89 mem_status_.ullAvailVirtual = 0;
92 void SetNone() {
93 SetMemoryFree(moderate_threshold_mb() + 1);
96 void SetModerate() {
97 SetMemoryFree(moderate_threshold_mb() - 1);
100 void SetCritical() {
101 SetMemoryFree(critical_threshold_mb() - 1);
104 private:
105 bool GetSystemMemoryStatus(MEMORYSTATUSEX* mem_status) override {
106 // Simply copy the memory status set by the test fixture.
107 *mem_status = mem_status_;
108 return true;
111 MEMORYSTATUSEX mem_status_;
113 DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor);
116 class WinMemoryPressureMonitorTest : public testing::Test {
117 protected:
118 void CalculateCurrentMemoryPressureLevelTest(
119 TestMemoryPressureMonitor* monitor) {
121 int mod = monitor->moderate_threshold_mb();
122 monitor->SetMemoryFree(mod + 1);
123 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
124 monitor->CalculateCurrentPressureLevel());
126 monitor->SetMemoryFree(mod);
127 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
128 monitor->CalculateCurrentPressureLevel());
130 monitor->SetMemoryFree(mod - 1);
131 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
132 monitor->CalculateCurrentPressureLevel());
134 int crit = monitor->critical_threshold_mb();
135 monitor->SetMemoryFree(crit + 1);
136 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
137 monitor->CalculateCurrentPressureLevel());
139 monitor->SetMemoryFree(crit);
140 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
141 monitor->CalculateCurrentPressureLevel());
143 monitor->SetMemoryFree(crit - 1);
144 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
145 monitor->CalculateCurrentPressureLevel());
148 base::MessageLoopForUI message_loop_;
151 // Tests the fundamental direct calculation of memory pressure with automatic
152 // small-memory thresholds.
153 TEST_F(WinMemoryPressureMonitorTest, CalculateCurrentMemoryPressureLevelSmall) {
154 static const int kModerateMb =
155 MemoryPressureMonitor::kSmallMemoryDefaultModerateThresholdMb;
156 static const int kCriticalMb =
157 MemoryPressureMonitor::kSmallMemoryDefaultCriticalThresholdMb;
159 TestMemoryPressureMonitor monitor(false); // Small-memory model.
161 EXPECT_EQ(kModerateMb, monitor.moderate_threshold_mb());
162 EXPECT_EQ(kCriticalMb, monitor.critical_threshold_mb());
164 ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&monitor));
167 // Tests the fundamental direct calculation of memory pressure with automatic
168 // large-memory thresholds.
169 TEST_F(WinMemoryPressureMonitorTest, CalculateCurrentMemoryPressureLevelLarge) {
170 static const int kModerateMb =
171 MemoryPressureMonitor::kLargeMemoryDefaultModerateThresholdMb;
172 static const int kCriticalMb =
173 MemoryPressureMonitor::kLargeMemoryDefaultCriticalThresholdMb;
175 TestMemoryPressureMonitor monitor(true); // Large-memory model.
177 EXPECT_EQ(kModerateMb, monitor.moderate_threshold_mb());
178 EXPECT_EQ(kCriticalMb, monitor.critical_threshold_mb());
180 ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&monitor));
183 // Tests the fundamental direct calculation of memory pressure with manually
184 // specified threshold levels.
185 TEST_F(WinMemoryPressureMonitorTest,
186 CalculateCurrentMemoryPressureLevelCustom) {
187 static const int kSystemMb = 512;
188 static const int kModerateMb = 256;
189 static const int kCriticalMb = 128;
191 TestMemoryPressureMonitor monitor(kSystemMb, kModerateMb, kCriticalMb);
193 EXPECT_EQ(kModerateMb, monitor.moderate_threshold_mb());
194 EXPECT_EQ(kCriticalMb, monitor.critical_threshold_mb());
196 ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&monitor));
199 // This test tests the various transition states from memory pressure, looking
200 // for the correct behavior on event reposting as well as state updates.
201 TEST_F(WinMemoryPressureMonitorTest, CheckMemoryPressure) {
202 // Large-memory.
203 testing::StrictMock<TestMemoryPressureMonitor> monitor(true);
204 MemoryPressureListener listener(
205 base::Bind(&TestMemoryPressureMonitor::OnMemoryPressure,
206 base::Unretained(&monitor)));
208 // Checking the memory pressure at 0% load should not produce any
209 // events.
210 monitor.SetNone();
211 monitor.CheckMemoryPressure();
212 message_loop_.RunUntilIdle();
213 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
214 monitor.GetCurrentPressureLevel());
216 // Setting the memory level to 80% should produce a moderate pressure level.
217 EXPECT_CALL(monitor,
218 OnMemoryPressure(MemoryPressureListener::
219 MEMORY_PRESSURE_LEVEL_MODERATE));
220 monitor.SetModerate();
221 monitor.CheckMemoryPressure();
222 message_loop_.RunUntilIdle();
223 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
224 monitor.GetCurrentPressureLevel());
225 testing::Mock::VerifyAndClearExpectations(&monitor);
227 // Check that the event gets reposted after a while.
228 for (int i = 0; i < monitor.kModeratePressureCooldownCycles; ++i) {
229 if (i + 1 == monitor.kModeratePressureCooldownCycles) {
230 EXPECT_CALL(monitor,
231 OnMemoryPressure(MemoryPressureListener::
232 MEMORY_PRESSURE_LEVEL_MODERATE));
234 monitor.CheckMemoryPressure();
235 message_loop_.RunUntilIdle();
236 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
237 monitor.GetCurrentPressureLevel());
238 testing::Mock::VerifyAndClearExpectations(&monitor);
241 // Setting the memory usage to 99% should produce critical levels.
242 EXPECT_CALL(monitor,
243 OnMemoryPressure(MemoryPressureListener::
244 MEMORY_PRESSURE_LEVEL_CRITICAL));
245 monitor.SetCritical();
246 monitor.CheckMemoryPressure();
247 message_loop_.RunUntilIdle();
248 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
249 monitor.GetCurrentPressureLevel());
250 testing::Mock::VerifyAndClearExpectations(&monitor);
252 // Calling it again should immediately produce a second call.
253 EXPECT_CALL(monitor,
254 OnMemoryPressure(MemoryPressureListener::
255 MEMORY_PRESSURE_LEVEL_CRITICAL));
256 monitor.CheckMemoryPressure();
257 message_loop_.RunUntilIdle();
258 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
259 monitor.GetCurrentPressureLevel());
260 testing::Mock::VerifyAndClearExpectations(&monitor);
262 // When lowering the pressure again there should be a notification and the
263 // pressure should go back to moderate.
264 EXPECT_CALL(monitor,
265 OnMemoryPressure(MemoryPressureListener::
266 MEMORY_PRESSURE_LEVEL_MODERATE));
267 monitor.SetModerate();
268 monitor.CheckMemoryPressure();
269 message_loop_.RunUntilIdle();
270 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
271 monitor.GetCurrentPressureLevel());
272 testing::Mock::VerifyAndClearExpectations(&monitor);
274 // Check that the event gets reposted after a while.
275 for (int i = 0; i < monitor.kModeratePressureCooldownCycles; ++i) {
276 if (i + 1 == monitor.kModeratePressureCooldownCycles) {
277 EXPECT_CALL(monitor,
278 OnMemoryPressure(MemoryPressureListener::
279 MEMORY_PRESSURE_LEVEL_MODERATE));
281 monitor.CheckMemoryPressure();
282 message_loop_.RunUntilIdle();
283 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
284 monitor.GetCurrentPressureLevel());
285 testing::Mock::VerifyAndClearExpectations(&monitor);
288 // Going down to no pressure should not produce an notification.
289 monitor.SetNone();
290 monitor.CheckMemoryPressure();
291 message_loop_.RunUntilIdle();
292 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
293 monitor.GetCurrentPressureLevel());
294 testing::Mock::VerifyAndClearExpectations(&monitor);
297 } // namespace win
298 } // namespace base