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

Side by Side Diff: content/browser/memory/memory_pressure_controller_browsertest.cc

Issue 1641813002: Provide renderers with memory pressure signals. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@contentapi
Patch Set: Addressed creis' comments. Created 4 years, 10 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/bind.h"
6 #include "base/memory/memory_pressure_listener.h"
7 #include "content/browser/memory/memory_message_filter.h"
8 #include "content/browser/memory/memory_pressure_controller.h"
9 #include "content/common/memory_messages.h"
10 #include "content/public/test/content_browser_test.h"
11 #include "content/public/test/content_browser_test_utils.h"
12 #include "content/public/test/test_utils.h"
13 #include "ipc/ipc_message.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15
16 namespace content {
17
18 MATCHER_P(IsSetSuppressedMessage, suppressed, "") {
19 // Ensure that the message is deleted upon return.
20 scoped_ptr<IPC::Message> message(arg);
21 if (message == nullptr)
22 return false;
23 MemoryMsg_SetPressureNotificationsSuppressed::Param param;
24 if (!MemoryMsg_SetPressureNotificationsSuppressed::Read(message.get(),
25 &param))
26 return false;
27 return suppressed == base::get<0>(param);
28 }
29
30 MATCHER_P(IsSimulateMessage, level, "") {
31 // Ensure that the message is deleted upon return.
32 scoped_ptr<IPC::Message> message(arg);
33 if (message == nullptr)
34 return false;
35 MemoryMsg_SimulatePressureNotification::Param param;
36 if (!MemoryMsg_SimulatePressureNotification::Read(message.get(), &param))
37 return false;
38 return level == base::get<0>(param);
39 }
40
41 MATCHER_P(IsPressureMessage, level, "") {
42 // Ensure that the message is deleted upon return.
43 scoped_ptr<IPC::Message> message(arg);
44 if (message == nullptr)
45 return false;
46 MemoryMsg_PressureNotification::Param param;
47 if (!MemoryMsg_PressureNotification::Read(message.get(), &param))
48 return false;
49 return level == base::get<0>(param);
50 }
51
52 class MemoryMessageFilterForTesting : public MemoryMessageFilter {
53 public:
54 // Use this object itself as a fake RenderProcessHost pointer. The address is
55 // only used for looking up the message filter in the controller and is never
56 // actually dereferenced, so this is safe.
57 MemoryMessageFilterForTesting()
58 : MemoryMessageFilter(reinterpret_cast<RenderProcessHost*>(this)) {}
59
60 MOCK_METHOD1(Send, bool(IPC::Message* message));
61
62 void Add() {
63 // The filter must be added on the IO thread.
64 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
65 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
66 base::Bind(&MemoryMessageFilterForTesting::Add,
67 base::Unretained(this)));
68 RunAllPendingInMessageLoop(BrowserThread::IO);
69 return;
70 }
71 OnChannelConnected(0);
72 OnFilterAdded(nullptr);
73 }
74
75 void Remove() {
76 // The filter must be removed on the IO thread.
77 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
78 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
79 base::Bind(&MemoryMessageFilterForTesting::Remove,
80 base::Unretained(this)));
81 RunAllPendingInMessageLoop(BrowserThread::IO);
82 return;
83 }
84 OnChannelClosing();
85 OnFilterRemoved();
86 }
87
88 protected:
89 ~MemoryMessageFilterForTesting() override {}
90 };
91
92 class MemoryPressureControllerBrowserTest : public ContentBrowserTest {
93 public:
94 MOCK_METHOD1(OnMemoryPressure,
95 void(base::MemoryPressureListener::MemoryPressureLevel level));
96
97 protected:
98 void SetPressureNotificationsSuppressedInAllProcessesAndWait(
99 bool suppressed) {
100 MemoryPressureController::GetInstance()
101 ->SetPressureNotificationsSuppressedInAllProcesses(suppressed);
102 RunAllPendingInMessageLoop(BrowserThread::IO);
103 }
104
105 void SimulatePressureNotificationInAllProcessesAndWait(
106 base::MemoryPressureListener::MemoryPressureLevel level) {
107 MemoryPressureController::GetInstance()
108 ->SimulatePressureNotificationInAllProcesses(level);
109 RunAllPendingInMessageLoop(BrowserThread::IO);
110 }
111
112 void SendPressureNotificationAndWait(
113 const void* fake_process_host,
114 base::MemoryPressureListener::MemoryPressureLevel level) {
115 MemoryPressureController::GetInstance()->SendPressureNotification(
116 reinterpret_cast<const RenderProcessHost*>(fake_process_host), level);
117 RunAllPendingInMessageLoop(BrowserThread::IO);
118 }
119 };
120
121 const auto MEMORY_PRESSURE_LEVEL_MODERATE =
122 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
123 const auto MEMORY_PRESSURE_LEVEL_CRITICAL =
124 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
125
126 IN_PROC_BROWSER_TEST_F(MemoryPressureControllerBrowserTest,
127 SetPressureNotificationsSuppressedInAllProcesses) {
128 scoped_refptr<MemoryMessageFilterForTesting> filter1(
129 new MemoryMessageFilterForTesting);
130 scoped_refptr<MemoryMessageFilterForTesting> filter2(
131 new MemoryMessageFilterForTesting);
132
133 NavigateToURL(shell(), GetTestUrl("", "title.html"));
134
135 // Add the first filter. No messages should be sent because notifications are
136 // not suppressed.
137 EXPECT_CALL(*filter1, Send(testing::_)).Times(0);
138 EXPECT_CALL(*filter2, Send(testing::_)).Times(0);
139 filter1->Add();
140 EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed());
141 testing::Mock::VerifyAndClearExpectations(this);
142
143 // Enable suppressing memory pressure notifications in all processes. The
144 // first filter should send a message.
145 EXPECT_CALL(*filter1, Send(IsSetSuppressedMessage(true))).Times(1);
146 EXPECT_CALL(*filter2, Send(testing::_)).Times(0);
147 SetPressureNotificationsSuppressedInAllProcessesAndWait(true);
148 EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed());
149 testing::Mock::VerifyAndClearExpectations(this);
150
151 // Add the second filter. It should send a message because notifications are
152 // suppressed.
153 EXPECT_CALL(*filter1, Send(testing::_)).Times(0);
154 EXPECT_CALL(*filter2, Send(IsSetSuppressedMessage(true))).Times(1);
155 filter2->Add();
156 testing::Mock::VerifyAndClearExpectations(this);
157
158 // Send a memory pressure event to the first child process. No messages should
159 // be sent as the notifications are suppressed.
160 EXPECT_CALL(*filter1, Send(testing::_)).Times(0);
161 EXPECT_CALL(*filter2, Send(testing::_)).Times(0);
162 SendPressureNotificationAndWait(filter1.get(),
163 MEMORY_PRESSURE_LEVEL_MODERATE);
164 testing::Mock::VerifyAndClearExpectations(this);
165
166 // Disable suppressing memory pressure notifications in all processes. Both
167 // filters should send a message.
168 EXPECT_CALL(*filter1, Send(IsSetSuppressedMessage(false))).Times(1);
169 EXPECT_CALL(*filter2, Send(IsSetSuppressedMessage(false))).Times(1);
170 SetPressureNotificationsSuppressedInAllProcessesAndWait(false);
171 EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed());
172 testing::Mock::VerifyAndClearExpectations(this);
173
174 // Send a memory pressure event to the first child process. A message should
175 // be received as messages are not being suppressed.
176 EXPECT_CALL(*filter1, Send(IsPressureMessage(MEMORY_PRESSURE_LEVEL_MODERATE)))
177 .Times(1);
178 EXPECT_CALL(*filter2, Send(testing::_)).Times(0);
179 SendPressureNotificationAndWait(filter1.get(),
180 MEMORY_PRESSURE_LEVEL_MODERATE);
181 testing::Mock::VerifyAndClearExpectations(this);
182
183 // Send a memory pressure event to a non-existing child process. No message
184 // should be sent.
185 EXPECT_CALL(*filter1, Send(testing::_)).Times(0);
186 EXPECT_CALL(*filter2, Send(testing::_)).Times(0);
187 SendPressureNotificationAndWait(reinterpret_cast<const void*>(0xF005BA11),
188 MEMORY_PRESSURE_LEVEL_MODERATE);
189 testing::Mock::VerifyAndClearExpectations(this);
190
191 // Remove the first filter. No messages should be sent.
192 EXPECT_CALL(*filter1, Send(testing::_)).Times(0);
193 EXPECT_CALL(*filter2, Send(testing::_)).Times(0);
194 filter1->Remove();
195 testing::Mock::VerifyAndClearExpectations(this);
196
197 // Enable suppressing memory pressure notifications in all processes. The
198 // second filter should send a message.
199 EXPECT_CALL(*filter1, Send(testing::_)).Times(0);
200 EXPECT_CALL(*filter2, Send(IsSetSuppressedMessage(true))).Times(1);
201 SetPressureNotificationsSuppressedInAllProcessesAndWait(true);
202 EXPECT_TRUE(base::MemoryPressureListener::AreNotificationsSuppressed());
203 testing::Mock::VerifyAndClearExpectations(this);
204
205 // Remove the second filter and disable suppressing memory pressure
206 // notifications in all processes. No messages should be sent.
207 EXPECT_CALL(*filter1, Send(testing::_)).Times(0);
208 EXPECT_CALL(*filter2, Send(testing::_)).Times(0);
209 filter2->Remove();
210 SetPressureNotificationsSuppressedInAllProcessesAndWait(false);
211 EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed());
212 testing::Mock::VerifyAndClearExpectations(this);
213 }
214
215 IN_PROC_BROWSER_TEST_F(MemoryPressureControllerBrowserTest,
216 SimulatePressureNotificationInAllProcesses) {
217 scoped_refptr<MemoryMessageFilterForTesting> filter(
218 new MemoryMessageFilterForTesting);
219 scoped_ptr<base::MemoryPressureListener> listener(
220 new base::MemoryPressureListener(
221 base::Bind(&MemoryPressureControllerBrowserTest::OnMemoryPressure,
222 base::Unretained(this))));
223
224 NavigateToURL(shell(), GetTestUrl("", "title.html"));
225
226 filter->Add();
227
228 // Send a memory pressure event to the first child process. It should send a
229 // pressure notification message.
230 EXPECT_CALL(*filter, Send(IsPressureMessage(MEMORY_PRESSURE_LEVEL_MODERATE)))
231 .Times(1);
232 SendPressureNotificationAndWait(filter.get(), MEMORY_PRESSURE_LEVEL_MODERATE);
233 testing::Mock::VerifyAndClearExpectations(this);
234
235 EXPECT_CALL(*filter, Send(IsSimulateMessage(MEMORY_PRESSURE_LEVEL_CRITICAL)))
236 .Times(1);
237 EXPECT_CALL(*this, OnMemoryPressure(MEMORY_PRESSURE_LEVEL_CRITICAL)).Times(1);
238 SimulatePressureNotificationInAllProcessesAndWait(
239 MEMORY_PRESSURE_LEVEL_CRITICAL);
240 RunAllPendingInMessageLoop(); // Wait for the listener to run.
241 testing::Mock::VerifyAndClearExpectations(this);
242
243 // Enable suppressing memory pressure notifications in all processes. This
244 // should have no impact on simulating memory pressure notifications.
245 EXPECT_CALL(*filter, Send(IsSetSuppressedMessage(true))).Times(1);
246 SetPressureNotificationsSuppressedInAllProcessesAndWait(true);
247 testing::Mock::VerifyAndClearExpectations(this);
248
249 EXPECT_CALL(*filter, Send(IsSimulateMessage(MEMORY_PRESSURE_LEVEL_MODERATE)))
250 .Times(1);
251 EXPECT_CALL(*this, OnMemoryPressure(MEMORY_PRESSURE_LEVEL_MODERATE)).Times(1);
252 SimulatePressureNotificationInAllProcessesAndWait(
253 MEMORY_PRESSURE_LEVEL_MODERATE);
254 RunAllPendingInMessageLoop(); // Wait for the listener to run.
255 testing::Mock::VerifyAndClearExpectations(this);
256
257 // Disable suppressing memory pressure notifications in all processes. This
258 // should have no impact on simulating memory pressure notifications.
259 EXPECT_CALL(*filter, Send(IsSetSuppressedMessage(false))).Times(1);
260 SetPressureNotificationsSuppressedInAllProcessesAndWait(false);
261 testing::Mock::VerifyAndClearExpectations(this);
262
263 EXPECT_CALL(*filter, Send(IsSimulateMessage(MEMORY_PRESSURE_LEVEL_MODERATE)))
264 .Times(1);
265 EXPECT_CALL(*this, OnMemoryPressure(MEMORY_PRESSURE_LEVEL_MODERATE)).Times(1);
266 SimulatePressureNotificationInAllProcessesAndWait(
267 MEMORY_PRESSURE_LEVEL_MODERATE);
268 RunAllPendingInMessageLoop(); // Wait for the listener to run.
269 testing::Mock::VerifyAndClearExpectations(this);
270
271 filter->Remove();
272 }
273
274 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/memory/memory_pressure_controller.cc ('k') | content/browser/memory/memory_pressure_controller_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698