| OLD | NEW | 
|---|
|  | (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                                                           ¶m)) |  | 
| 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(), ¶m)) |  | 
| 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(), ¶m)) |  | 
| 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 |  | 
| OLD | NEW | 
|---|