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

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

Issue 2579233002: Merge MemoryCoordinator and MemoryCoordinatorImpl into one class (Closed)
Patch Set: addressed comments Created 4 years 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
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_proxy.h" 8 #include "base/memory/memory_coordinator_proxy.h"
9 #include "base/memory/memory_pressure_monitor.h"
10 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h" 11 #include "base/run_loop.h"
9 #include "base/test/scoped_feature_list.h" 12 #include "base/test/scoped_feature_list.h"
10 #include "base/test/test_mock_time_task_runner.h" 13 #include "base/test/test_mock_time_task_runner.h"
11 #include "content/browser/memory/memory_monitor.h" 14 #include "content/browser/memory/memory_monitor.h"
12 #include "content/browser/memory/memory_state_updater.h" 15 #include "content/browser/memory/memory_state_updater.h"
13 #include "content/public/common/content_features.h" 16 #include "content/public/common/content_features.h"
17 #include "mojo/public/cpp/bindings/binding.h"
14 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
15 19
16 namespace content { 20 namespace content {
17 21
18 namespace { 22 namespace {
19 23
24 void RunUntilIdle() {
25 base::RunLoop loop;
26 loop.RunUntilIdle();
27 }
28
29 // A mock ChildMemoryCoordinator, for testing interaction between MC and CMC.
30 class MockChildMemoryCoordinator : public mojom::ChildMemoryCoordinator {
31 public:
32 MockChildMemoryCoordinator()
33 : state_(mojom::MemoryState::NORMAL),
34 on_state_change_calls_(0) {}
35
36 ~MockChildMemoryCoordinator() override {}
37
38 void OnStateChange(mojom::MemoryState state) override {
39 state_ = state;
40 ++on_state_change_calls_;
41 }
42
43 mojom::MemoryState state() const { return state_; }
44 int on_state_change_calls() const { return on_state_change_calls_; }
45
46 private:
47 mojom::MemoryState state_;
48 int on_state_change_calls_;
49 };
50
51 // A mock MemoryCoordinatorClient, for testing interaction between MC and
52 // clients.
20 class MockMemoryCoordinatorClient : public base::MemoryCoordinatorClient { 53 class MockMemoryCoordinatorClient : public base::MemoryCoordinatorClient {
21 public: 54 public:
22 void OnMemoryStateChange(base::MemoryState state) override { 55 void OnMemoryStateChange(base::MemoryState state) override {
23 is_called_ = true; 56 is_called_ = true;
24 state_ = state; 57 state_ = state;
25 } 58 }
26 59
27 bool is_called() { return is_called_; } 60 bool is_called() { return is_called_; }
28 base::MemoryState state() { return state_; } 61 base::MemoryState state() { return state_; }
29 62
30 private: 63 private:
31 bool is_called_ = false; 64 bool is_called_ = false;
32 base::MemoryState state_ = base::MemoryState::NORMAL; 65 base::MemoryState state_ = base::MemoryState::NORMAL;
33 }; 66 };
34 67
35 } // namespace
36
37 class MockMemoryMonitor : public MemoryMonitor { 68 class MockMemoryMonitor : public MemoryMonitor {
38 public: 69 public:
39 MockMemoryMonitor() {} 70 MockMemoryMonitor() {}
40 ~MockMemoryMonitor() override {} 71 ~MockMemoryMonitor() override {}
41 72
42 void SetFreeMemoryUntilCriticalMB(int free_memory) { 73 void SetFreeMemoryUntilCriticalMB(int free_memory) {
43 free_memory_ = free_memory; 74 free_memory_ = free_memory;
44 } 75 }
45 76
46 // MemoryMonitor implementation 77 // MemoryMonitor implementation
47 int GetFreeMemoryUntilCriticalMB() override { return free_memory_; } 78 int GetFreeMemoryUntilCriticalMB() override { return free_memory_; }
48 79
49 private: 80 private:
50 int free_memory_ = 0; 81 int free_memory_ = 0;
51 82
52 DISALLOW_COPY_AND_ASSIGN(MockMemoryMonitor); 83 DISALLOW_COPY_AND_ASSIGN(MockMemoryMonitor);
53 }; 84 };
54 85
86 // A MemoryCoordinatorImpl that can be directly constructed.
87 class TestMemoryCoordinatorImpl : public MemoryCoordinatorImpl {
88 public:
89 // Mojo machinery for wrapping a mock ChildMemoryCoordinator.
90 struct Child {
91 Child(mojom::ChildMemoryCoordinatorPtr* cmc_ptr) : cmc_binding(&cmc) {
92 cmc_binding.Bind(mojo::GetProxy(cmc_ptr));
93 RunUntilIdle();
94 }
95
96 MockChildMemoryCoordinator cmc;
97 mojo::Binding<mojom::ChildMemoryCoordinator> cmc_binding;
98 };
99
100 TestMemoryCoordinatorImpl(
101 scoped_refptr<base::TestMockTimeTaskRunner> task_runner)
102 : MemoryCoordinatorImpl(task_runner,
103 base::MakeUnique<MockMemoryMonitor>()) {}
104 ~TestMemoryCoordinatorImpl() override {}
105
106 using MemoryCoordinatorImpl::OnConnectionError;
107 using MemoryCoordinatorImpl::children;
108
109 MockChildMemoryCoordinator* CreateChildMemoryCoordinator(
110 int process_id) {
111 mojom::ChildMemoryCoordinatorPtr cmc_ptr;
112 children_.push_back(std::unique_ptr<Child>(new Child(&cmc_ptr)));
113 AddChildForTesting(process_id, std::move(cmc_ptr));
114 return &children_.back()->cmc;
115 }
116
117 // Wrapper of MemoryCoordinator::SetMemoryState that also calls RunUntilIdle.
118 bool SetChildMemoryState(
119 int render_process_id, mojom::MemoryState memory_state) {
120 bool result = MemoryCoordinatorImpl::SetChildMemoryState(
121 render_process_id, memory_state);
122 RunUntilIdle();
123 return result;
124 }
125
126 std::vector<std::unique_ptr<Child>> children_;
127 };
128
129 } // namespace
130
55 class MemoryCoordinatorImplTest : public testing::Test { 131 class MemoryCoordinatorImplTest : public testing::Test {
56 public: 132 public:
57 void SetUp() override { 133 void SetUp() override {
58 scoped_feature_list_.InitAndEnableFeature(features::kMemoryCoordinator); 134 scoped_feature_list_.InitAndEnableFeature(features::kMemoryCoordinator);
59 135
60 task_runner_ = new base::TestMockTimeTaskRunner(); 136 task_runner_ = new base::TestMockTimeTaskRunner();
61 coordinator_.reset(new MemoryCoordinatorImpl( 137 coordinator_.reset(new TestMemoryCoordinatorImpl(task_runner_));
62 task_runner_, base::WrapUnique(new MockMemoryMonitor)));
63 138
64 base::MemoryCoordinatorProxy::GetInstance()-> 139 base::MemoryCoordinatorProxy::GetInstance()->
65 SetGetCurrentMemoryStateCallback(base::Bind( 140 SetGetCurrentMemoryStateCallback(base::Bind(
66 &MemoryCoordinator::GetCurrentMemoryState, 141 &MemoryCoordinatorImpl::GetCurrentMemoryState,
67 base::Unretained(coordinator_.get()))); 142 base::Unretained(coordinator_.get())));
68 base::MemoryCoordinatorProxy::GetInstance()-> 143 base::MemoryCoordinatorProxy::GetInstance()->
69 SetSetCurrentMemoryStateForTestingCallback(base::Bind( 144 SetSetCurrentMemoryStateForTestingCallback(base::Bind(
70 &MemoryCoordinator::SetCurrentMemoryStateForTesting, 145 &MemoryCoordinatorImpl::SetCurrentMemoryStateForTesting,
71 base::Unretained(coordinator_.get()))); 146 base::Unretained(coordinator_.get())));
72 } 147 }
73 148
74 MockMemoryMonitor* GetMockMemoryMonitor() { 149 MockMemoryMonitor* GetMockMemoryMonitor() {
75 return static_cast<MockMemoryMonitor*>(coordinator_->memory_monitor()); 150 return static_cast<MockMemoryMonitor*>(coordinator_->memory_monitor());
76 } 151 }
77 152
78 protected: 153 protected:
79 std::unique_ptr<MemoryCoordinatorImpl> coordinator_; 154 std::unique_ptr<TestMemoryCoordinatorImpl> coordinator_;
80 scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; 155 scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
81 base::MessageLoop message_loop_; 156 base::MessageLoop message_loop_;
82 base::test::ScopedFeatureList scoped_feature_list_; 157 base::test::ScopedFeatureList scoped_feature_list_;
83 }; 158 };
84 159
160 TEST_F(MemoryCoordinatorImplTest, ChildRemovedOnConnectionError) {
161 coordinator_->CreateChildMemoryCoordinator(1);
162 ASSERT_EQ(1u, coordinator_->children().size());
163 coordinator_->OnConnectionError(1);
164 EXPECT_EQ(0u, coordinator_->children().size());
165 }
166
167 TEST_F(MemoryCoordinatorImplTest, SetMemoryStateFailsInvalidState) {
168 auto cmc1 = coordinator_->CreateChildMemoryCoordinator(1);
169
170 EXPECT_FALSE(
171 coordinator_->SetChildMemoryState(1, mojom::MemoryState::UNKNOWN));
172 EXPECT_EQ(0, cmc1->on_state_change_calls());
173 }
174
175 TEST_F(MemoryCoordinatorImplTest, SetMemoryStateFailsInvalidRenderer) {
176 auto cmc1 = coordinator_->CreateChildMemoryCoordinator(1);
177
178 EXPECT_FALSE(
179 coordinator_->SetChildMemoryState(2, mojom::MemoryState::THROTTLED));
180 EXPECT_EQ(0, cmc1->on_state_change_calls());
181 }
182
183 TEST_F(MemoryCoordinatorImplTest, SetMemoryStateNotDeliveredNop) {
184 auto cmc1 = coordinator_->CreateChildMemoryCoordinator(1);
185
186 EXPECT_FALSE(
187 coordinator_->SetChildMemoryState(2, mojom::MemoryState::NORMAL));
188 EXPECT_EQ(0, cmc1->on_state_change_calls());
189 }
190
191 TEST_F(MemoryCoordinatorImplTest, SetMemoryStateDelivered) {
192 auto cmc1 = coordinator_->CreateChildMemoryCoordinator(1);
193 auto cmc2 = coordinator_->CreateChildMemoryCoordinator(2);
194
195 EXPECT_TRUE(
196 coordinator_->SetChildMemoryState(1, mojom::MemoryState::THROTTLED));
197 EXPECT_EQ(1, cmc1->on_state_change_calls());
198 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc1->state());
199
200 EXPECT_TRUE(
201 coordinator_->SetChildMemoryState(2, mojom::MemoryState::SUSPENDED));
202 EXPECT_EQ(1, cmc2->on_state_change_calls());
203 // Child processes are considered as visible (foreground) by default,
204 // and visible ones won't be suspended but throttled.
205 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc2->state());
206 }
207
208 TEST_F(MemoryCoordinatorImplTest, SetChildMemoryState) {
209 auto cmc = coordinator_->CreateChildMemoryCoordinator(1);
210 auto iter = coordinator_->children().find(1);
211 ASSERT_TRUE(iter != coordinator_->children().end());
212
213 // Foreground
214 iter->second.is_visible = true;
215 EXPECT_TRUE(coordinator_->SetChildMemoryState(1, mojom::MemoryState::NORMAL));
216 EXPECT_EQ(mojom::MemoryState::NORMAL, cmc->state());
217 EXPECT_TRUE(
218 coordinator_->SetChildMemoryState(1, mojom::MemoryState::THROTTLED));
219 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state());
220 EXPECT_TRUE(
221 coordinator_->SetChildMemoryState(1, mojom::MemoryState::SUSPENDED));
222 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state());
223
224 // Background
225 iter->second.is_visible = false;
226 EXPECT_TRUE(coordinator_->SetChildMemoryState(1, mojom::MemoryState::NORMAL));
227 #if defined(OS_ANDROID)
228 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state());
229 #else
230 EXPECT_EQ(mojom::MemoryState::NORMAL, cmc->state());
231 #endif
232 EXPECT_TRUE(
233 coordinator_->SetChildMemoryState(1, mojom::MemoryState::THROTTLED));
234 EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state());
235 EXPECT_TRUE(
236 coordinator_->SetChildMemoryState(1, mojom::MemoryState::SUSPENDED));
237 EXPECT_EQ(mojom::MemoryState::SUSPENDED, cmc->state());
238 }
239
85 TEST_F(MemoryCoordinatorImplTest, CalculateNextState) { 240 TEST_F(MemoryCoordinatorImplTest, CalculateNextState) {
86 auto* state_updater = coordinator_->state_updater_.get(); 241 auto* state_updater = coordinator_->state_updater_.get();
87 state_updater->expected_renderer_size_ = 10; 242 state_updater->expected_renderer_size_ = 10;
88 state_updater->new_renderers_until_throttled_ = 4; 243 state_updater->new_renderers_until_throttled_ = 4;
89 state_updater->new_renderers_until_suspended_ = 2; 244 state_updater->new_renderers_until_suspended_ = 2;
90 state_updater->new_renderers_back_to_normal_ = 5; 245 state_updater->new_renderers_back_to_normal_ = 5;
91 state_updater->new_renderers_back_to_throttled_ = 3; 246 state_updater->new_renderers_back_to_throttled_ = 3;
92 DCHECK(state_updater->ValidateParameters()); 247 DCHECK(state_updater->ValidateParameters());
93 248
94 // The default state is NORMAL. 249 // The default state is NORMAL.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 state_updater->new_renderers_back_to_throttled_ = 3; 308 state_updater->new_renderers_back_to_throttled_ = 3;
154 DCHECK(state_updater->ValidateParameters()); 309 DCHECK(state_updater->ValidateParameters());
155 310
156 { 311 {
157 // Transition happens (NORMAL -> THROTTLED). 312 // Transition happens (NORMAL -> THROTTLED).
158 MockMemoryCoordinatorClient client; 313 MockMemoryCoordinatorClient client;
159 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client); 314 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
160 coordinator_->current_state_ = base::MemoryState::NORMAL; 315 coordinator_->current_state_ = base::MemoryState::NORMAL;
161 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(40); 316 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(40);
162 state_updater->UpdateState(); 317 state_updater->UpdateState();
163 base::RunLoop loop; 318 RunUntilIdle();
164 loop.RunUntilIdle();
165 EXPECT_TRUE(client.is_called()); 319 EXPECT_TRUE(client.is_called());
166 EXPECT_EQ(base::MemoryState::THROTTLED, client.state()); 320 EXPECT_EQ(base::MemoryState::THROTTLED, client.state());
167 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client); 321 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
168 } 322 }
169 323
170 { 324 {
171 // No transtion (NORMAL -> NORMAL). OnStateChange shouldn't be called. 325 // No transtion (NORMAL -> NORMAL). OnStateChange shouldn't be called.
172 MockMemoryCoordinatorClient client; 326 MockMemoryCoordinatorClient client;
173 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client); 327 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
174 coordinator_->current_state_ = base::MemoryState::NORMAL; 328 coordinator_->current_state_ = base::MemoryState::NORMAL;
175 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50); 329 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(50);
176 state_updater->UpdateState(); 330 state_updater->UpdateState();
177 base::RunLoop loop; 331 RunUntilIdle();
178 loop.RunUntilIdle();
179 EXPECT_FALSE(client.is_called()); 332 EXPECT_FALSE(client.is_called());
180 EXPECT_EQ(base::MemoryState::NORMAL, client.state()); 333 EXPECT_EQ(base::MemoryState::NORMAL, client.state());
181 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client); 334 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
182 } 335 }
183 } 336 }
184 337
185 TEST_F(MemoryCoordinatorImplTest, SetMemoryStateForTesting) { 338 TEST_F(MemoryCoordinatorImplTest, SetMemoryStateForTesting) {
186 auto* state_updater = coordinator_->state_updater_.get(); 339 auto* state_updater = coordinator_->state_updater_.get();
187 state_updater->expected_renderer_size_ = 10; 340 state_updater->expected_renderer_size_ = 10;
188 state_updater->new_renderers_until_throttled_ = 4; 341 state_updater->new_renderers_until_throttled_ = 4;
(...skipping 19 matching lines...) Expand all
208 EXPECT_EQ(base::MemoryState::THROTTLED, 361 EXPECT_EQ(base::MemoryState::THROTTLED,
209 base::MemoryCoordinatorProxy::GetInstance()-> 362 base::MemoryCoordinatorProxy::GetInstance()->
210 GetCurrentMemoryState()); 363 GetCurrentMemoryState());
211 364
212 base::MemoryCoordinatorProxy::GetInstance()->SetCurrentMemoryStateForTesting( 365 base::MemoryCoordinatorProxy::GetInstance()->SetCurrentMemoryStateForTesting(
213 base::MemoryState::THROTTLED); 366 base::MemoryState::THROTTLED);
214 EXPECT_EQ(base::MemoryState::THROTTLED, 367 EXPECT_EQ(base::MemoryState::THROTTLED,
215 coordinator_->GetCurrentMemoryState()); 368 coordinator_->GetCurrentMemoryState());
216 EXPECT_EQ(base::MemoryState::THROTTLED, 369 EXPECT_EQ(base::MemoryState::THROTTLED,
217 base::MemoryCoordinatorProxy::GetInstance()-> 370 base::MemoryCoordinatorProxy::GetInstance()->
218 GetCurrentMemoryState()); 371 GetCurrentMemoryState());
219 base::RunLoop loop; 372 RunUntilIdle();
220 loop.RunUntilIdle();
221 EXPECT_TRUE(client.is_called()); 373 EXPECT_TRUE(client.is_called());
222 EXPECT_EQ(base::MemoryState::THROTTLED, client.state()); 374 EXPECT_EQ(base::MemoryState::THROTTLED, client.state());
223 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client); 375 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
224 } 376 }
225 377
226 TEST_F(MemoryCoordinatorImplTest, ForceSetGlobalState) { 378 TEST_F(MemoryCoordinatorImplTest, ForceSetGlobalState) {
227 auto* state_updater = coordinator_->state_updater_.get(); 379 auto* state_updater = coordinator_->state_updater_.get();
228 state_updater->expected_renderer_size_ = 10; 380 state_updater->expected_renderer_size_ = 10;
229 state_updater->new_renderers_until_throttled_ = 4; 381 state_updater->new_renderers_until_throttled_ = 4;
230 state_updater->new_renderers_until_suspended_ = 2; 382 state_updater->new_renderers_until_suspended_ = 2;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 // Also make sure that the state is updated based on free avaiable memory. 415 // Also make sure that the state is updated based on free avaiable memory.
264 // Since the global state has changed in the previous task, we have to wait 416 // Since the global state has changed in the previous task, we have to wait
265 // for |minimum_transition|. 417 // for |minimum_transition|.
266 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(40); 418 GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(40);
267 task_runner_->FastForwardBy(minimum_transition); 419 task_runner_->FastForwardBy(minimum_transition);
268 task_runner_->RunUntilIdle(); 420 task_runner_->RunUntilIdle();
269 EXPECT_EQ(base::MemoryState::THROTTLED, coordinator_->GetGlobalMemoryState()); 421 EXPECT_EQ(base::MemoryState::THROTTLED, coordinator_->GetGlobalMemoryState());
270 } 422 }
271 423
272 } // namespace content 424 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/memory/memory_coordinator_impl_browsertest.cc ('k') | content/browser/memory/memory_coordinator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698