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"
18 struct PressureSettings
{
20 MemoryPressureListener::MemoryPressureLevel level
;
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
{
29 using MemoryPressureMonitor::CalculateCurrentPressureLevel
;
30 using MemoryPressureMonitor::CheckMemoryPressure
;
32 static const DWORDLONG kMBBytes
= 1024 * 1024;
34 explicit TestMemoryPressureMonitor(bool large_memory
)
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.
46 TestMemoryPressureMonitor(int system_memory_mb
,
47 int moderate_threshold_mb
,
48 int critical_threshold_mb
)
49 : MemoryPressureMonitor(moderate_threshold_mb
, critical_threshold_mb
),
51 // Set the amount of system memory.
52 mem_status_
.ullTotalPhys
= static_cast<DWORDLONG
>(
53 system_memory_mb
* kMBBytes
);
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
66 int GenerateTotalMemoryMb(bool large_memory
) {
68 while (total_mb
< MemoryPressureMonitor::kLargeMemoryThresholdMb
)
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;
93 SetMemoryFree(moderate_threshold_mb() + 1);
97 SetMemoryFree(moderate_threshold_mb() - 1);
101 SetMemoryFree(critical_threshold_mb() - 1);
105 bool GetSystemMemoryStatus(MEMORYSTATUSEX
* mem_status
) override
{
106 // Simply copy the memory status set by the test fixture.
107 *mem_status
= mem_status_
;
111 MEMORYSTATUSEX mem_status_
;
113 DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor
);
116 class WinMemoryPressureMonitorTest
: public testing::Test
{
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
) {
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
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.
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
) {
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.
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.
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.
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
) {
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.
290 monitor
.CheckMemoryPressure();
291 message_loop_
.RunUntilIdle();
292 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE
,
293 monitor
.GetCurrentPressureLevel());
294 testing::Mock::VerifyAndClearExpectations(&monitor
);