| Index: content/browser/memory/memory_coordinator_impl_unittest.cc
|
| diff --git a/content/browser/memory/memory_coordinator_impl_unittest.cc b/content/browser/memory/memory_coordinator_impl_unittest.cc
|
| index a2d1be92e067b210b1720ad1bd8084e9ebdc2bd6..c734077f9676443987e76594a3b31b61aa89da55 100644
|
| --- a/content/browser/memory/memory_coordinator_impl_unittest.cc
|
| +++ b/content/browser/memory/memory_coordinator_impl_unittest.cc
|
| @@ -66,12 +66,16 @@ class MockMemoryCoordinatorClient : public base::MemoryCoordinatorClient {
|
| state_ = state;
|
| }
|
|
|
| + void OnPurgeMemory() override { ++purge_memory_calls_; }
|
| +
|
| bool did_state_changed() const { return did_state_changed_; }
|
| base::MemoryState state() const { return state_; }
|
| + int purge_memory_calls() const { return purge_memory_calls_; }
|
|
|
| private:
|
| bool did_state_changed_ = false;
|
| base::MemoryState state_ = base::MemoryState::NORMAL;
|
| + int purge_memory_calls_ = 0;
|
| };
|
|
|
| class MockMemoryMonitor : public MemoryMonitor {
|
| @@ -566,6 +570,106 @@ TEST_F(MemoryCoordinatorImplTest, DiscardTabUnderCritical) {
|
| EXPECT_EQ(2, delegate->discard_tab_count());
|
| }
|
|
|
| +TEST_F(MemoryCoordinatorImplTest, OnWarningCondition) {
|
| + MockMemoryCoordinatorClient client;
|
| + base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
|
| + auto* child1 = coordinator_->CreateChildMemoryCoordinator(1);
|
| + auto* child2 = coordinator_->CreateChildMemoryCoordinator(2);
|
| + base::TimeDelta interval = base::TimeDelta::FromSeconds(31);
|
| +
|
| + // child1: Foreground, child2: Background
|
| + coordinator_->OnChildVisibilityChanged(1, true);
|
| + coordinator_->OnChildVisibilityChanged(2, false);
|
| +
|
| + // Note: we never ask foreground processes (including the browser process) to
|
| + // purge memory on WARNING condition.
|
| +
|
| + // Don't ask the background child to purge until the child remains
|
| + // backgrounded for a certain period of time.
|
| + coordinator_->OnWarningCondition();
|
| + RunUntilIdle();
|
| + EXPECT_EQ(0, client.purge_memory_calls());
|
| + EXPECT_EQ(0, child1->purge_memory_calls());
|
| + EXPECT_EQ(0, child2->purge_memory_calls());
|
| +
|
| + // After a certain period of time is passed, request the child to purge
|
| + // memory.
|
| + task_runner_->FastForwardBy(interval);
|
| + coordinator_->OnWarningCondition();
|
| + task_runner_->RunUntilIdle();
|
| + RunUntilIdle();
|
| + EXPECT_EQ(0, client.purge_memory_calls());
|
| + EXPECT_EQ(0, child1->purge_memory_calls());
|
| + EXPECT_EQ(1, child2->purge_memory_calls());
|
| +
|
| + // Don't purge memory more than once when the child stays backgrounded.
|
| + task_runner_->FastForwardBy(interval);
|
| + coordinator_->OnWarningCondition();
|
| + RunUntilIdle();
|
| + EXPECT_EQ(0, client.purge_memory_calls());
|
| + EXPECT_EQ(0, child1->purge_memory_calls());
|
| + EXPECT_EQ(1, child2->purge_memory_calls());
|
| +
|
| + // The background child goes to foreground, goes to background, then a
|
| + // certain period of time is passed. Another purging request should be sent.
|
| + coordinator_->OnChildVisibilityChanged(2, true);
|
| + coordinator_->OnChildVisibilityChanged(2, false);
|
| + task_runner_->FastForwardBy(interval);
|
| + coordinator_->OnWarningCondition();
|
| + RunUntilIdle();
|
| + EXPECT_EQ(0, client.purge_memory_calls());
|
| + EXPECT_EQ(0, child1->purge_memory_calls());
|
| + EXPECT_EQ(2, child2->purge_memory_calls());
|
| +
|
| + base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
|
| +}
|
| +
|
| +TEST_F(MemoryCoordinatorImplTest, OnCriticalCondition) {
|
| + MockMemoryCoordinatorClient client;
|
| + base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
|
| + auto* child1 = coordinator_->CreateChildMemoryCoordinator(1);
|
| + auto* child2 = coordinator_->CreateChildMemoryCoordinator(2);
|
| + auto* delegate = coordinator_->GetDelegate();
|
| + base::TimeDelta interval = base::TimeDelta::FromSeconds(31);
|
| +
|
| + // child1: Foreground, child2: Background
|
| + coordinator_->OnChildVisibilityChanged(1, true);
|
| + coordinator_->OnChildVisibilityChanged(2, false);
|
| +
|
| + // Purge memory from all children regardless of their visibility.
|
| + task_runner_->FastForwardBy(interval);
|
| + coordinator_->OnCriticalCondition();
|
| + RunUntilIdle();
|
| + task_runner_->FastForwardBy(interval);
|
| + coordinator_->OnCriticalCondition();
|
| + RunUntilIdle();
|
| + EXPECT_EQ(2, delegate->discard_tab_count());
|
| + EXPECT_EQ(0, client.purge_memory_calls());
|
| + EXPECT_EQ(1, child1->purge_memory_calls());
|
| + EXPECT_EQ(1, child2->purge_memory_calls());
|
| +
|
| + // Purge memory from browser process only after we asked all children to
|
| + // purge memory.
|
| + task_runner_->FastForwardBy(interval);
|
| + coordinator_->OnCriticalCondition();
|
| + RunUntilIdle();
|
| + EXPECT_EQ(3, delegate->discard_tab_count());
|
| + EXPECT_EQ(1, client.purge_memory_calls());
|
| + EXPECT_EQ(1, child1->purge_memory_calls());
|
| + EXPECT_EQ(1, child2->purge_memory_calls());
|
| +
|
| + // Don't request purging for a certain period of time if we already requested.
|
| + task_runner_->FastForwardBy(interval);
|
| + coordinator_->OnCriticalCondition();
|
| + RunUntilIdle();
|
| + EXPECT_EQ(4, delegate->discard_tab_count());
|
| + EXPECT_EQ(1, client.purge_memory_calls());
|
| + EXPECT_EQ(1, child1->purge_memory_calls());
|
| + EXPECT_EQ(1, child2->purge_memory_calls());
|
| +
|
| + base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
|
| +}
|
| +
|
| #if defined(OS_ANDROID)
|
| // TODO(jcivelli): Broken on Android. http://crbug.com/678665
|
| #define MAYBE_GetStateForProcess DISABLED_GetStateForProcess
|
|
|