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

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. 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"
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 // Sets up the memory status to reflect the provided loads.
44 void SetMemoryLoad(int phys_load_pct, int virt_load_pct) {
45 static const DWORDLONG k4GB = 4ull * 1024 * 1024 * 1024;
46
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, int virt_left_mb) {
60 // Figure out an amount of memory that makes sense for the desired
61 // quantities of memory to be left.
62 DWORDLONG total = 64; // Minimum of 64MB.
63 while (total < phys_left_mb || total < virt_left_mb)
64 total *= 2;
65 total *= 1024 * 1024;
Nico 2015/05/05 21:25:12 nit: I'd have total_mb and then do size_t total_b
chrisha 2015/05/06 02:40:24 Done.
66
67 mem_status_.ullTotalPhys = total;
68 mem_status_.ullAvailPhys =
69 static_cast<DWORDLONG>(phys_left_mb) * 1024 * 1024;
70 mem_status_.ullTotalPageFile = total;
71 mem_status_.ullAvailPageFile = total;
72 mem_status_.ullTotalVirtual = total;
73 mem_status_.ullAvailVirtual =
74 static_cast<DWORDLONG>(virt_left_mb) * 1024 * 1024;
75 mem_status_.dwMemoryLoad = static_cast<DWORD>(
76 100 * (mem_status_.ullTotalPhys - mem_status_.ullAvailPhys) /
77 mem_status_.ullTotalPhys);
78 }
79
80 private:
81 virtual bool GetSystemMemoryStatus(_MEMORYSTATUSEX* mem_status) override {
82 // Simply copy the memory status set by the test fixture.
83 *mem_status = mem_status_;
84 return true;
85 }
86
87 _MEMORYSTATUSEX mem_status_;
88
89 DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor);
90 };
91
92 // Tests the fundamental direct calculation of memory pressure.
93 TEST(WinMemoryPressureMonitorTest, CalculateCurrentMemoryPressureLevel) {
94 base::MessageLoopForUI message_loop;
95 TestMemoryPressureMonitor monitor;
96
97 // A bunch of memory load settings and the expected memory pressure.
98 const PressureSettings kLoadSettings[] = {
99 { 10, 10, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE },
100 { 40, 40, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE },
101 { 65, 10, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
102 { 10, 65, 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 { 10, 98, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
107 { 65, 98, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
108 { 98, 98, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
109 };
110
111 for (const PressureSettings& setting : kLoadSettings) {
112 monitor.SetMemoryLoad(setting.phys, setting.virt);
113 EXPECT_EQ(setting.level, monitor.CalculateCurrentPressureLevel());
114 }
115
116 // A bunch of free memory settings and the expected memory pressure.
117 const PressureSettings kFreeSettings[] = {
118 { 500, 500, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE },
119 { 250, 500, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
120 { 500, 250, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
121 { 250, 250, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
122 { 50, 500, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
123 { 50, 250, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
124 { 500, 50, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
125 { 250, 50, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
126 { 50, 50, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
127 };
128
129 for (const PressureSettings& setting : kFreeSettings) {
130 monitor.SetMemoryFree(setting.phys, setting.virt);
131 EXPECT_EQ(setting.level, monitor.CalculateCurrentPressureLevel());
132 }
133 }
Nico 2015/05/05 21:25:12 nice test!
134
135 // This test tests the various transition states from memory pressure, looking
136 // for the correct behavior on event reposting as well as state updates.
137 TEST(WinMemoryPressureMonitorTest, CheckMemoryPressure) {
138 base::MessageLoopForUI message_loop;
139 testing::StrictMock<TestMemoryPressureMonitor> monitor;
140 MemoryPressureListener listener(
141 base::Bind(&TestMemoryPressureMonitor::OnMemoryPressure,
142 base::Unretained(&monitor)));
143
144 // Checking the memory pressure at 0% load should not produce any
145 // events.
146 monitor.SetMemoryLoad(0, 0);
147 monitor.CheckMemoryPressure();
148 message_loop.RunUntilIdle();
149 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
150 monitor.GetCurrentPressureLevel());
151
152 // Setting the memory level to 80% should produce a moderate pressure level.
153 EXPECT_CALL(monitor,
154 OnMemoryPressure(MemoryPressureListener::
155 MEMORY_PRESSURE_LEVEL_MODERATE));
156 monitor.SetMemoryLoad(80, 80);
157 monitor.CheckMemoryPressure();
158 message_loop.RunUntilIdle();
159 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
160 monitor.GetCurrentPressureLevel());
161
162 // Check that the event gets reposted after a while.
Nico 2015/05/05 21:25:12 This relies on the notification firing every 10th
chrisha 2015/05/06 02:40:24 Done.
163 EXPECT_CALL(monitor,
164 OnMemoryPressure(MemoryPressureListener::
165 MEMORY_PRESSURE_LEVEL_MODERATE));
166 for (int i = 0; i < 15; ++i) {
167 monitor.CheckMemoryPressure();
168 message_loop.RunUntilIdle();
169 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
170 monitor.GetCurrentPressureLevel());
171 }
172
173 // Setting the memory usage to 99% should produce critical levels.
174 EXPECT_CALL(monitor,
175 OnMemoryPressure(MemoryPressureListener::
176 MEMORY_PRESSURE_LEVEL_CRITICAL));
177 monitor.SetMemoryLoad(99, 99);
178 monitor.CheckMemoryPressure();
179 message_loop.RunUntilIdle();
180 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
181 monitor.GetCurrentPressureLevel());
182
183 // Calling it again should immediately produce a second call.
184 EXPECT_CALL(monitor,
185 OnMemoryPressure(MemoryPressureListener::
186 MEMORY_PRESSURE_LEVEL_CRITICAL));
187 monitor.CheckMemoryPressure();
188 message_loop.RunUntilIdle();
189 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
190 monitor.GetCurrentPressureLevel());
191
192 // When lowering the pressure again there should be a notification and the
193 // pressure should go back to moderate.
194 EXPECT_CALL(monitor,
195 OnMemoryPressure(MemoryPressureListener::
196 MEMORY_PRESSURE_LEVEL_MODERATE));
197 monitor.SetMemoryLoad(80, 80);
198 monitor.CheckMemoryPressure();
199 message_loop.RunUntilIdle();
200 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
201 monitor.GetCurrentPressureLevel());
202
203 // Check that the event gets reposted after a while.
204 EXPECT_CALL(monitor,
205 OnMemoryPressure(MemoryPressureListener::
206 MEMORY_PRESSURE_LEVEL_MODERATE));
207 for (int i = 0; i < 15; ++i) {
208 monitor.CheckMemoryPressure();
209 message_loop.RunUntilIdle();
210 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
211 monitor.GetCurrentPressureLevel());
212 }
213
214 // Going down to no pressure should not produce an notification.
215 monitor.SetMemoryLoad(0, 0);
216 monitor.CheckMemoryPressure();
217 message_loop.RunUntilIdle();
218 EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
219 monitor.GetCurrentPressureLevel());
220 }
221
222 } // namespace win
223 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698