OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/memory/memory_coordinator_impl.h" | 5 #include "content/browser/memory/memory_coordinator_impl.h" |
6 | 6 |
7 #include "base/memory/memory_coordinator_client_registry.h" | 7 #include "base/memory/memory_coordinator_client_registry.h" |
8 #include "base/memory/memory_coordinator_proxy.h" | 8 #include "base/memory/memory_coordinator_proxy.h" |
9 #include "base/memory/memory_pressure_monitor.h" | 9 #include "base/memory/memory_pressure_monitor.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
12 #include "base/test/scoped_feature_list.h" | 12 #include "base/test/scoped_feature_list.h" |
13 #include "base/test/test_mock_time_task_runner.h" | 13 #include "base/test/test_mock_time_task_runner.h" |
14 #include "content/browser/memory/memory_monitor.h" | 14 #include "content/browser/memory/memory_monitor.h" |
15 #include "content/browser/memory/memory_state_updater.h" | 15 #include "content/browser/memory/memory_state_updater.h" |
16 #include "content/public/common/content_features.h" | 16 #include "content/public/common/content_features.h" |
| 17 #include "content/public/test/mock_render_process_host.h" |
| 18 #include "content/public/test/test_browser_context.h" |
17 #include "mojo/public/cpp/bindings/binding.h" | 19 #include "mojo/public/cpp/bindings/binding.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
19 | 21 |
20 namespace content { | 22 namespace content { |
21 | 23 |
22 namespace { | 24 namespace { |
23 | 25 |
24 void RunUntilIdle() { | 26 void RunUntilIdle() { |
25 base::RunLoop loop; | 27 base::RunLoop loop; |
26 loop.RunUntilIdle(); | 28 loop.RunUntilIdle(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 | 78 |
77 // MemoryMonitor implementation | 79 // MemoryMonitor implementation |
78 int GetFreeMemoryUntilCriticalMB() override { return free_memory_; } | 80 int GetFreeMemoryUntilCriticalMB() override { return free_memory_; } |
79 | 81 |
80 private: | 82 private: |
81 int free_memory_ = 0; | 83 int free_memory_ = 0; |
82 | 84 |
83 DISALLOW_COPY_AND_ASSIGN(MockMemoryMonitor); | 85 DISALLOW_COPY_AND_ASSIGN(MockMemoryMonitor); |
84 }; | 86 }; |
85 | 87 |
| 88 class TestMemoryCoordinatorDelegate : public MemoryCoordinatorDelegate { |
| 89 public: |
| 90 TestMemoryCoordinatorDelegate() {} |
| 91 ~TestMemoryCoordinatorDelegate() override {} |
| 92 |
| 93 bool CanSuspendBackgroundedRenderer(int render_process_id) override { |
| 94 return true; |
| 95 } |
| 96 |
| 97 private: |
| 98 DISALLOW_COPY_AND_ASSIGN(TestMemoryCoordinatorDelegate); |
| 99 }; |
| 100 |
86 // A MemoryCoordinatorImpl that can be directly constructed. | 101 // A MemoryCoordinatorImpl that can be directly constructed. |
87 class TestMemoryCoordinatorImpl : public MemoryCoordinatorImpl { | 102 class TestMemoryCoordinatorImpl : public MemoryCoordinatorImpl { |
88 public: | 103 public: |
89 // Mojo machinery for wrapping a mock ChildMemoryCoordinator. | 104 // Mojo machinery for wrapping a mock ChildMemoryCoordinator. |
90 struct Child { | 105 struct Child { |
91 Child(mojom::ChildMemoryCoordinatorPtr* cmc_ptr) : cmc_binding(&cmc) { | 106 Child(mojom::ChildMemoryCoordinatorPtr* cmc_ptr) : cmc_binding(&cmc) { |
92 cmc_binding.Bind(mojo::GetProxy(cmc_ptr)); | 107 cmc_binding.Bind(mojo::GetProxy(cmc_ptr)); |
93 RunUntilIdle(); | 108 RunUntilIdle(); |
94 } | 109 } |
95 | 110 |
96 MockChildMemoryCoordinator cmc; | 111 MockChildMemoryCoordinator cmc; |
97 mojo::Binding<mojom::ChildMemoryCoordinator> cmc_binding; | 112 mojo::Binding<mojom::ChildMemoryCoordinator> cmc_binding; |
98 }; | 113 }; |
99 | 114 |
100 TestMemoryCoordinatorImpl( | 115 TestMemoryCoordinatorImpl( |
101 scoped_refptr<base::TestMockTimeTaskRunner> task_runner) | 116 scoped_refptr<base::TestMockTimeTaskRunner> task_runner) |
102 : MemoryCoordinatorImpl(task_runner, | 117 : MemoryCoordinatorImpl(task_runner, |
103 base::MakeUnique<MockMemoryMonitor>()) {} | 118 base::MakeUnique<MockMemoryMonitor>()) { |
| 119 SetDelegateForTesting(base::MakeUnique<TestMemoryCoordinatorDelegate>()); |
| 120 } |
| 121 |
104 ~TestMemoryCoordinatorImpl() override {} | 122 ~TestMemoryCoordinatorImpl() override {} |
105 | 123 |
106 using MemoryCoordinatorImpl::OnConnectionError; | 124 using MemoryCoordinatorImpl::OnConnectionError; |
107 using MemoryCoordinatorImpl::children; | 125 using MemoryCoordinatorImpl::children; |
108 | 126 |
109 MockChildMemoryCoordinator* CreateChildMemoryCoordinator( | 127 MockChildMemoryCoordinator* CreateChildMemoryCoordinator( |
110 int process_id) { | 128 int process_id) { |
111 mojom::ChildMemoryCoordinatorPtr cmc_ptr; | 129 mojom::ChildMemoryCoordinatorPtr cmc_ptr; |
112 children_.push_back(std::unique_ptr<Child>(new Child(&cmc_ptr))); | 130 children_.push_back(std::unique_ptr<Child>(new Child(&cmc_ptr))); |
113 AddChildForTesting(process_id, std::move(cmc_ptr)); | 131 AddChildForTesting(process_id, std::move(cmc_ptr)); |
| 132 render_process_hosts_[process_id] = |
| 133 base::MakeUnique<MockRenderProcessHost>(&browser_context_); |
114 return &children_.back()->cmc; | 134 return &children_.back()->cmc; |
115 } | 135 } |
116 | 136 |
| 137 RenderProcessHost* GetRenderProcessHost(int render_process_id) override { |
| 138 return GetMockRenderProcessHost(render_process_id); |
| 139 } |
| 140 |
| 141 MockRenderProcessHost* GetMockRenderProcessHost(int render_process_id) { |
| 142 auto iter = render_process_hosts_.find(render_process_id); |
| 143 if (iter == render_process_hosts_.end()) |
| 144 return nullptr; |
| 145 return iter->second.get(); |
| 146 } |
| 147 |
117 // Wrapper of MemoryCoordinator::SetMemoryState that also calls RunUntilIdle. | 148 // Wrapper of MemoryCoordinator::SetMemoryState that also calls RunUntilIdle. |
118 bool SetChildMemoryState( | 149 bool SetChildMemoryState( |
119 int render_process_id, MemoryState memory_state) { | 150 int render_process_id, MemoryState memory_state) { |
120 bool result = MemoryCoordinatorImpl::SetChildMemoryState( | 151 bool result = MemoryCoordinatorImpl::SetChildMemoryState( |
121 render_process_id, memory_state); | 152 render_process_id, memory_state); |
122 RunUntilIdle(); | 153 RunUntilIdle(); |
123 return result; | 154 return result; |
124 } | 155 } |
125 | 156 |
| 157 TestBrowserContext browser_context_; |
126 std::vector<std::unique_ptr<Child>> children_; | 158 std::vector<std::unique_ptr<Child>> children_; |
| 159 std::map<int, std::unique_ptr<MockRenderProcessHost>> render_process_hosts_; |
127 }; | 160 }; |
128 | 161 |
129 } // namespace | 162 } // namespace |
130 | 163 |
131 class MemoryCoordinatorImplTest : public testing::Test { | 164 class MemoryCoordinatorImplTest : public testing::Test { |
132 public: | 165 public: |
133 using MemoryState = base::MemoryState; | 166 using MemoryState = base::MemoryState; |
134 | 167 |
135 void SetUp() override { | 168 void SetUp() override { |
136 scoped_feature_list_.InitAndEnableFeature(features::kMemoryCoordinator); | 169 scoped_feature_list_.InitAndEnableFeature(features::kMemoryCoordinator); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 coordinator_->SetChildMemoryState(2, MemoryState::SUSPENDED)); | 236 coordinator_->SetChildMemoryState(2, MemoryState::SUSPENDED)); |
204 EXPECT_EQ(1, cmc2->on_state_change_calls()); | 237 EXPECT_EQ(1, cmc2->on_state_change_calls()); |
205 // Child processes are considered as visible (foreground) by default, | 238 // Child processes are considered as visible (foreground) by default, |
206 // and visible ones won't be suspended but throttled. | 239 // and visible ones won't be suspended but throttled. |
207 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc2->state()); | 240 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc2->state()); |
208 } | 241 } |
209 | 242 |
210 TEST_F(MemoryCoordinatorImplTest, SetChildMemoryState) { | 243 TEST_F(MemoryCoordinatorImplTest, SetChildMemoryState) { |
211 auto cmc = coordinator_->CreateChildMemoryCoordinator(1); | 244 auto cmc = coordinator_->CreateChildMemoryCoordinator(1); |
212 auto iter = coordinator_->children().find(1); | 245 auto iter = coordinator_->children().find(1); |
| 246 auto* render_process_host = coordinator_->GetMockRenderProcessHost(1); |
213 ASSERT_TRUE(iter != coordinator_->children().end()); | 247 ASSERT_TRUE(iter != coordinator_->children().end()); |
| 248 ASSERT_TRUE(render_process_host); |
214 | 249 |
215 // Foreground | 250 // Foreground |
216 iter->second.is_visible = true; | 251 iter->second.is_visible = true; |
| 252 render_process_host->set_is_process_backgrounded(false); |
217 EXPECT_TRUE(coordinator_->SetChildMemoryState(1, MemoryState::NORMAL)); | 253 EXPECT_TRUE(coordinator_->SetChildMemoryState(1, MemoryState::NORMAL)); |
218 EXPECT_EQ(mojom::MemoryState::NORMAL, cmc->state()); | 254 EXPECT_EQ(mojom::MemoryState::NORMAL, cmc->state()); |
219 EXPECT_TRUE( | 255 EXPECT_TRUE( |
220 coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED)); | 256 coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED)); |
221 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); | 257 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); |
222 EXPECT_TRUE( | 258 EXPECT_TRUE( |
223 coordinator_->SetChildMemoryState(1, MemoryState::SUSPENDED)); | 259 coordinator_->SetChildMemoryState(1, MemoryState::SUSPENDED)); |
224 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); | 260 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); |
225 | 261 |
226 // Background | 262 // Background |
227 iter->second.is_visible = false; | 263 iter->second.is_visible = false; |
| 264 render_process_host->set_is_process_backgrounded(true); |
228 EXPECT_TRUE(coordinator_->SetChildMemoryState(1, MemoryState::NORMAL)); | 265 EXPECT_TRUE(coordinator_->SetChildMemoryState(1, MemoryState::NORMAL)); |
229 #if defined(OS_ANDROID) | 266 #if defined(OS_ANDROID) |
230 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); | 267 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); |
231 #else | 268 #else |
232 EXPECT_EQ(mojom::MemoryState::NORMAL, cmc->state()); | 269 EXPECT_EQ(mojom::MemoryState::NORMAL, cmc->state()); |
233 #endif | 270 #endif |
234 EXPECT_TRUE( | 271 EXPECT_TRUE( |
235 coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED)); | 272 coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED)); |
236 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); | 273 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); |
237 EXPECT_TRUE( | 274 EXPECT_TRUE( |
238 coordinator_->SetChildMemoryState(1, MemoryState::SUSPENDED)); | 275 coordinator_->SetChildMemoryState(1, MemoryState::SUSPENDED)); |
239 EXPECT_EQ(mojom::MemoryState::SUSPENDED, cmc->state()); | 276 EXPECT_EQ(mojom::MemoryState::SUSPENDED, cmc->state()); |
| 277 |
| 278 // Background but there are workers |
| 279 render_process_host->IncrementServiceWorkerRefCount(); |
| 280 EXPECT_TRUE( |
| 281 coordinator_->SetChildMemoryState(1, MemoryState::THROTTLED)); |
| 282 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); |
| 283 EXPECT_FALSE( |
| 284 coordinator_->SetChildMemoryState(1, MemoryState::SUSPENDED)); |
| 285 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state()); |
| 286 render_process_host->DecrementSharedWorkerRefCount(); |
240 } | 287 } |
241 | 288 |
242 TEST_F(MemoryCoordinatorImplTest, CalculateNextState) { | 289 TEST_F(MemoryCoordinatorImplTest, CalculateNextState) { |
243 auto* state_updater = coordinator_->state_updater_.get(); | 290 auto* state_updater = coordinator_->state_updater_.get(); |
244 state_updater->expected_renderer_size_ = 10; | 291 state_updater->expected_renderer_size_ = 10; |
245 state_updater->new_renderers_until_throttled_ = 4; | 292 state_updater->new_renderers_until_throttled_ = 4; |
246 state_updater->new_renderers_until_suspended_ = 2; | 293 state_updater->new_renderers_until_suspended_ = 2; |
247 state_updater->new_renderers_back_to_normal_ = 5; | 294 state_updater->new_renderers_back_to_normal_ = 5; |
248 state_updater->new_renderers_back_to_throttled_ = 3; | 295 state_updater->new_renderers_back_to_throttled_ = 3; |
249 DCHECK(state_updater->ValidateParameters()); | 296 DCHECK(state_updater->ValidateParameters()); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 // Also make sure that the state is updated based on free avaiable memory. | 464 // Also make sure that the state is updated based on free avaiable memory. |
418 // Since the global state has changed in the previous task, we have to wait | 465 // Since the global state has changed in the previous task, we have to wait |
419 // for |minimum_transition|. | 466 // for |minimum_transition|. |
420 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(40); | 467 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(40); |
421 task_runner_->FastForwardBy(minimum_transition); | 468 task_runner_->FastForwardBy(minimum_transition); |
422 task_runner_->RunUntilIdle(); | 469 task_runner_->RunUntilIdle(); |
423 EXPECT_EQ(base::MemoryState::THROTTLED, coordinator_->GetGlobalMemoryState()); | 470 EXPECT_EQ(base::MemoryState::THROTTLED, coordinator_->GetGlobalMemoryState()); |
424 } | 471 } |
425 | 472 |
426 } // namespace content | 473 } // namespace content |
OLD | NEW |