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

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

Powered by Google App Engine
This is Rietveld 408576698