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

Side by Side Diff: base/win/memory_pressure_monitor_unittest.cc

Issue 1122863005: Create base::win::MemoryPressureMonitor class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed grt@'s comments on patchset 3. Created 5 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 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.
4
5 #include "base/win/memory_pressure_monitor.h"
6
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"
12
13 namespace base {
14 namespace win {
15
16 namespace {
17
18 struct PressureSettings {
19 int phys;
20 int virt;
21 MemoryPressureListener::MemoryPressureLevel level;
22 };
23
24 } // namespace
25
26 // This is outside of the anonymous namespace so that it can be seen as a friend
27 // to the monitor class.
28 class TestMemoryPressureMonitor : public MemoryPressureMonitor {
29 public:
30 using MemoryPressureMonitor::CalculateCurrentPressureLevel;
31 using MemoryPressureMonitor::CheckMemoryPressure;
32
33 static const DWORDLONG k4GB = 4ull * 1024 * 1024 * 1024;
34
35 TestMemoryPressureMonitor() {
36 // Disable any timers which are going on and set a special memory reporting
37 // function.
38 StopObserving();
39 }
40
41 virtual ~TestMemoryPressureMonitor() {}
42
43 MOCK_METHOD1(OnMemoryPressure,
44 void(MemoryPressureListener::MemoryPressureLevel level));
45
46 // Sets up the memory status to reflect the provided loads.
47 void SetMemoryLoad(int phys_load_pct, int virt_load_pct) {
48 mem_status_.dwMemoryLoad = static_cast<DWORD>(phys_load_pct);
49 mem_status_.ullTotalPhys = k4GB;
50 mem_status_.ullAvailPhys = (k4GB * (100 - phys_load_pct)) / 100;
51 mem_status_.ullTotalPageFile = k4GB;
52 mem_status_.ullAvailPageFile = k4GB;
53 mem_status_.ullTotalVirtual = k4GB;
54 mem_status_.ullAvailVirtual = (k4GB * (100 - virt_load_pct)) / 100;
55 }
56
57 // Sets up the memory status to reflect the provided absolute memory left.
58 // This uses quite small total memory quantities so that the absolute memory
59 // limits have a chance to kick in.
60 void SetMemoryFree(int phys_left_mb) {
61 static DWORDLONG kMBBytes = 1024 * 1024;
62
63 // Figure out an amount of memory that makes sense for the desired
64 // quantities of memory to be left.
65 DWORDLONG total_mb = 64; // Minimum of 64MB.
66 while (total_mb < phys_left_mb)
67 total_mb *= 2;
68 DWORDLONG total_bytes = total_mb * kMBBytes;
69
70 mem_status_.ullTotalPhys = total_bytes;
71 mem_status_.ullAvailPhys =
72 static_cast<DWORDLONG>(phys_left_mb) * kMBBytes;
73 mem_status_.ullTotalPageFile = total_bytes;
74 mem_status_.ullAvailPageFile = total_bytes;
75 mem_status_.ullTotalVirtual = k4GB;
76 mem_status_.ullAvailVirtual = k4GB;
77 mem_status_.dwMemoryLoad = static_cast<DWORD>(
78 100 * (mem_status_.ullTotalPhys - mem_status_.ullAvailPhys) /
79 mem_status_.ullTotalPhys);
80 }
81
82 private:
83 bool GetSystemMemoryStatus(MEMORYSTATUSEX* mem_status) override {
84 // Simply copy the memory status set by the test fixture.
85 *mem_status = mem_status_;
86 return true;
87 }
88
89 MEMORYSTATUSEX mem_status_;
90
91 DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor);
92 };
93
94 // Tests the fundamental direct calculation of memory pressure.
95 TEST(WinMemoryPressureMonitorTest, CalculateCurrentMemoryPressureLevel) {
96 base::MessageLoopForUI message_loop;
97 TestMemoryPressureMonitor monitor;
98
99 // A bunch of memory load settings and the expected memory pressure.
100 const PressureSettings kLoadSettings[] = {
101 { 10, 10, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE },
102 { 40, 40, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE },
103 { 65, 10, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
104 { 65, 65, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
105 { 98, 10, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
106 { 98, 65, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
107 { 98, 98, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
108 #if !defined(ARCH_CPU_64_BITS)
109 // This simulates low virtual memory, which is only applicable on
110 // 32-bit systems.
111 { 10, 65, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
112 { 10, 98, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
113 { 65, 98, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
114 #endif // !defined(ARCH_CPU_64_BITS)
115 };
116
117 for (const PressureSettings& setting : kLoadSettings) {
118 monitor.SetMemoryLoad(setting.phys, setting.virt);
119 EXPECT_EQ(setting.level, monitor.CalculateCurrentPressureLevel());
120 }
121
122 // A bunch of free memory settings and the expected memory pressure. The
123 // 'virt' parameter is ignored, thus zeroed.
124 const PressureSettings kFreeSettings[] = {
125 { 500, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE },
126 { 250, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
127 { 250, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
128 { 50, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
129 { 50, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
130 { 50, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
131 };
132
133 for (const PressureSettings& setting : kFreeSettings) {
134 monitor.SetMemoryFree(setting.phys);
135 EXPECT_EQ(setting.level, monitor.CalculateCurrentPressureLevel());
136 }
137 }
138
139 // This test tests the various transition states from memory pressure, looking
140 // for the correct behavior on event reposting as well as state updates.
141 TEST(WinMemoryPressureMonitorTest, CheckMemoryPressure) {
142 base::MessageLoopForUI message_loop;
143 testing::StrictMock<TestMemoryPressureMonitor> monitor;
grt (UTC plus 2) 2015/05/06 16:31:09 to force Google Mock to evaluate all expectation f
chrisha 2015/05/06 16:59:04 Ooh, didn't know about VerifyAndClearExpectations,
144 MemoryPressureListener listener(
145 base::Bind(&TestMemoryPressureMonitor::OnMemoryPressure,
146 base::Unretained(&monitor)));
147
148 // Checking the memory pressure at 0% load should not produce any
149 // events.
150 monitor.SetMemoryLoad(0, 0);
151 monitor.CheckMemoryPressure();
152 message_loop.RunUntilIdle();
153 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
154 monitor.GetCurrentPressureLevel());
155
156 // Setting the memory level to 80% should produce a moderate pressure level.
157 EXPECT_CALL(monitor,
158 OnMemoryPressure(MemoryPressureListener::
159 MEMORY_PRESSURE_LEVEL_MODERATE));
160 monitor.SetMemoryLoad(80, 80);
161 monitor.CheckMemoryPressure();
162 message_loop.RunUntilIdle();
163 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
164 monitor.GetCurrentPressureLevel());
165
166 // Check that the event gets reposted after a while.
167 for (int i = 0; i < monitor.kModeratePressureCooldownCycles; ++i) {
168 if (i + 1 == monitor.kModeratePressureCooldownCycles) {
169 EXPECT_CALL(monitor,
170 OnMemoryPressure(MemoryPressureListener::
171 MEMORY_PRESSURE_LEVEL_MODERATE));
172 }
173 monitor.CheckMemoryPressure();
174 message_loop.RunUntilIdle();
175 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
176 monitor.GetCurrentPressureLevel());
177 }
178
179 // Setting the memory usage to 99% should produce critical levels.
180 EXPECT_CALL(monitor,
181 OnMemoryPressure(MemoryPressureListener::
182 MEMORY_PRESSURE_LEVEL_CRITICAL));
183 monitor.SetMemoryLoad(99, 99);
184 monitor.CheckMemoryPressure();
185 message_loop.RunUntilIdle();
186 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
187 monitor.GetCurrentPressureLevel());
188
189 // Calling it again should immediately produce a second call.
190 EXPECT_CALL(monitor,
191 OnMemoryPressure(MemoryPressureListener::
192 MEMORY_PRESSURE_LEVEL_CRITICAL));
193 monitor.CheckMemoryPressure();
194 message_loop.RunUntilIdle();
195 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
196 monitor.GetCurrentPressureLevel());
197
198 // When lowering the pressure again there should be a notification and the
199 // pressure should go back to moderate.
200 EXPECT_CALL(monitor,
201 OnMemoryPressure(MemoryPressureListener::
202 MEMORY_PRESSURE_LEVEL_MODERATE));
203 monitor.SetMemoryLoad(80, 80);
204 monitor.CheckMemoryPressure();
205 message_loop.RunUntilIdle();
206 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
207 monitor.GetCurrentPressureLevel());
208
209 // Check that the event gets reposted after a while.
210 for (int i = 0; i < monitor.kModeratePressureCooldownCycles; ++i) {
211 if (i + 1 == monitor.kModeratePressureCooldownCycles) {
212 EXPECT_CALL(monitor,
213 OnMemoryPressure(MemoryPressureListener::
214 MEMORY_PRESSURE_LEVEL_MODERATE));
215 }
216 monitor.CheckMemoryPressure();
217 message_loop.RunUntilIdle();
218 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
219 monitor.GetCurrentPressureLevel());
220 }
221
222 // Going down to no pressure should not produce an notification.
223 monitor.SetMemoryLoad(0, 0);
224 monitor.CheckMemoryPressure();
225 message_loop.RunUntilIdle();
226 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
227 monitor.GetCurrentPressureLevel());
228 }
229
230 } // namespace win
231 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698