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

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

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

Powered by Google App Engine
This is Rietveld 408576698