| 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 ab466a175110702c1b00839ac37f039ffc809b3f..f641678a9688675d7239bd6a272e5db8cb28c1ce 100644
|
| --- a/content/browser/memory/memory_coordinator_impl_unittest.cc
|
| +++ b/content/browser/memory/memory_coordinator_impl_unittest.cc
|
| @@ -111,6 +111,31 @@ class TestMemoryCoordinatorDelegate : public MemoryCoordinatorDelegate {
|
| DISALLOW_COPY_AND_ASSIGN(TestMemoryCoordinatorDelegate);
|
| };
|
|
|
| +class MockMemoryCoordinatorPolicy : public MemoryCoordinatorImpl::Policy {
|
| + public:
|
| + explicit MockMemoryCoordinatorPolicy(MemoryCoordinatorImpl* coordinator)
|
| + : coordinator_(coordinator) {
|
| + DCHECK(coordinator_);
|
| + }
|
| +
|
| + ~MockMemoryCoordinatorPolicy() override = default;
|
| +
|
| + void OnCriticalCondition() override { coordinator_->DiscardTab(); }
|
| +
|
| + void OnConditionChanged(MemoryCondition prev, MemoryCondition next) override {
|
| + EXPECT_NE(prev, next);
|
| + last_condition_ = next;
|
| + }
|
| +
|
| + MemoryCondition last_condition() const { return last_condition_; }
|
| +
|
| + private:
|
| + MemoryCoordinatorImpl* coordinator_ = nullptr;
|
| + MemoryCondition last_condition_ = MemoryCondition::NORMAL;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(MockMemoryCoordinatorPolicy);
|
| +};
|
| +
|
| // A MemoryCoordinatorImpl that can be directly constructed.
|
| class TestMemoryCoordinatorImpl : public MemoryCoordinatorImpl {
|
| public:
|
| @@ -130,6 +155,7 @@ class TestMemoryCoordinatorImpl : public MemoryCoordinatorImpl {
|
| : MemoryCoordinatorImpl(task_runner,
|
| base::MakeUnique<MockMemoryMonitor>()) {
|
| SetDelegateForTesting(base::MakeUnique<TestMemoryCoordinatorDelegate>());
|
| + SetPolicyForTesting(base::MakeUnique<MockMemoryCoordinatorPolicy>(this));
|
| SetTickClockForTesting(task_runner->GetMockTickClock());
|
| }
|
|
|
| @@ -163,6 +189,10 @@ class TestMemoryCoordinatorImpl : public MemoryCoordinatorImpl {
|
| return static_cast<TestMemoryCoordinatorDelegate*>(delegate());
|
| }
|
|
|
| + MockMemoryCoordinatorPolicy* GetPolicy() {
|
| + return static_cast<MockMemoryCoordinatorPolicy*>(policy());
|
| + }
|
| +
|
| // Wrapper of MemoryCoordinator::SetMemoryState that also calls RunUntilIdle.
|
| bool SetChildMemoryState(
|
| int render_process_id, MemoryState memory_state) {
|
| @@ -285,31 +315,6 @@ TEST_F(MemoryCoordinatorImplTest, SetChildMemoryState) {
|
| EXPECT_EQ(mojom::MemoryState::THROTTLED, cmc->state());
|
| }
|
|
|
| -// TODO(bashi): Move policy specific tests into a separate file.
|
| -TEST_F(MemoryCoordinatorImplTest, OnChildVisibilityChanged) {
|
| - auto* child = coordinator_->CreateChildMemoryCoordinator(1);
|
| -
|
| - coordinator_->memory_condition_ = MemoryCondition::NORMAL;
|
| - coordinator_->policy_->OnChildVisibilityChanged(1, true);
|
| - RunUntilIdle();
|
| - EXPECT_EQ(mojom::MemoryState::NORMAL, child->state());
|
| - coordinator_->policy_->OnChildVisibilityChanged(1, false);
|
| - RunUntilIdle();
|
| -#if defined(OS_ANDROID)
|
| - EXPECT_EQ(mojom::MemoryState::THROTTLED, child->state());
|
| -#else
|
| - EXPECT_EQ(mojom::MemoryState::NORMAL, child->state());
|
| -#endif
|
| -
|
| - coordinator_->memory_condition_ = MemoryCondition::CRITICAL;
|
| - coordinator_->policy_->OnChildVisibilityChanged(1, true);
|
| - RunUntilIdle();
|
| - EXPECT_EQ(mojom::MemoryState::THROTTLED, child->state());
|
| - coordinator_->policy_->OnChildVisibilityChanged(1, false);
|
| - RunUntilIdle();
|
| - EXPECT_EQ(mojom::MemoryState::THROTTLED, child->state());
|
| -}
|
| -
|
| TEST_F(MemoryCoordinatorImplTest, CalculateNextCondition) {
|
| auto* condition_observer = coordinator_->condition_observer_.get();
|
|
|
| @@ -332,69 +337,25 @@ TEST_F(MemoryCoordinatorImplTest, CalculateNextCondition) {
|
| condition_observer->CalculateNextCondition());
|
| }
|
|
|
| -TEST_F(MemoryCoordinatorImplTest, UpdateCondition) {
|
| - auto* condition_observer = coordinator_->condition_observer_.get();
|
| -
|
| - auto* foreground_child = coordinator_->CreateChildMemoryCoordinator(1);
|
| - auto* background_child = coordinator_->CreateChildMemoryCoordinator(2);
|
| - auto iter = coordinator_->children().find(2);
|
| - iter->second.is_visible = false;
|
| +TEST_F(MemoryCoordinatorImplTest, UpdateConditionIfNeeded) {
|
| + auto* policy = coordinator_->GetPolicy();
|
|
|
| - {
|
| - // Transition happens (NORMAL -> CRITICAL).
|
| - // All processes should be in THROTTLED memory state.
|
| - MockMemoryCoordinatorClient client;
|
| - base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
|
| - GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(0);
|
| - condition_observer->UpdateCondition();
|
| - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(40));
|
| - RunUntilIdle();
|
| - EXPECT_TRUE(client.did_state_changed());
|
| - EXPECT_EQ(base::MemoryState::THROTTLED, client.state());
|
| - EXPECT_EQ(mojom::MemoryState::THROTTLED, foreground_child->state());
|
| - EXPECT_EQ(mojom::MemoryState::THROTTLED, background_child->state());
|
| - base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
|
| - }
|
| + // The initial condition is NORMAL.
|
| + EXPECT_EQ(MemoryCondition::NORMAL, coordinator_->GetMemoryCondition());
|
| + coordinator_->UpdateConditionIfNeeded(MemoryCondition::NORMAL);
|
| + RunUntilIdle();
|
| + EXPECT_EQ(MemoryCondition::NORMAL, policy->last_condition());
|
|
|
| - {
|
| - // No transtion (NORMAL -> NORMAL). OnStateChange shouldn't be called.
|
| - MockMemoryCoordinatorClient client;
|
| - base::MemoryCoordinatorClientRegistry::GetInstance()->Register(&client);
|
| - coordinator_->memory_condition_ = MemoryCondition::NORMAL;
|
| - GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(1000);
|
| - condition_observer->UpdateCondition();
|
| - RunUntilIdle();
|
| - EXPECT_FALSE(client.did_state_changed());
|
| - EXPECT_EQ(base::MemoryState::NORMAL, client.state());
|
| - base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(&client);
|
| - }
|
| + // Change to CRITICAL condition.
|
| + coordinator_->UpdateConditionIfNeeded(MemoryCondition::CRITICAL);
|
| + RunUntilIdle();
|
| + EXPECT_EQ(MemoryCondition::CRITICAL, policy->last_condition());
|
|
|
| - {
|
| - // Transition happends but browser state change is delayed
|
| - // (CRITICAL -> NORMAL).
|
| - base::TimeDelta transition_interval =
|
| - coordinator_->minimum_state_transition_period_ +
|
| - base::TimeDelta::FromSeconds(1);
|
| - coordinator_->memory_condition_ = MemoryCondition::NORMAL;
|
| - coordinator_->last_state_change_ = task_runner_->NowTicks();
|
| - GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(0);
|
| - condition_observer->UpdateCondition();
|
| - EXPECT_EQ(base::MemoryState::THROTTLED,
|
| - coordinator_->GetCurrentMemoryState());
|
| -
|
| - // Back to NORMAL condition before |minimum_state_transition_period_| is
|
| - // passed. At this point the browser's state shouldn't be changed.
|
| - GetMockMemoryMonitor()->SetFreeMemoryUntilCriticalMB(1000);
|
| - condition_observer->UpdateCondition();
|
| - task_runner_->FastForwardBy(transition_interval / 2);
|
| - EXPECT_EQ(MemoryCondition::NORMAL, coordinator_->GetMemoryCondition());
|
| - EXPECT_EQ(base::MemoryState::THROTTLED,
|
| - coordinator_->GetCurrentMemoryState());
|
| -
|
| - // |minimum_state_transition_period_| is passed. State should be changed.
|
| - task_runner_->FastForwardBy(transition_interval / 2);
|
| - EXPECT_EQ(base::MemoryState::NORMAL, coordinator_->GetCurrentMemoryState());
|
| - }
|
| + // Make sure that OnConditionChanged() won't get called when the condition is
|
| + // unchanged. CHECK_NE() in MockMemoryCoordinatorPolicy ensures it.
|
| + coordinator_->UpdateConditionIfNeeded(MemoryCondition::CRITICAL);
|
| + RunUntilIdle();
|
| + EXPECT_EQ(MemoryCondition::CRITICAL, policy->last_condition());
|
| }
|
|
|
| // TODO(bashi): Move ForceSetMemoryCondition?
|
| @@ -468,53 +429,6 @@ TEST_F(MemoryCoordinatorImplTest, DiscardTabUnderCritical) {
|
| EXPECT_EQ(2, delegate->discard_tab_count());
|
| }
|
|
|
| -// TODO(bashi): Move policy specific tests into a separate file.
|
| -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_->policy_->OnChildVisibilityChanged(1, true);
|
| - coordinator_->policy_->OnChildVisibilityChanged(2, false);
|
| -
|
| - // Purge memory from all children regardless of their visibility.
|
| - task_runner_->FastForwardBy(interval);
|
| - coordinator_->policy_->OnCriticalCondition();
|
| - RunUntilIdle();
|
| - task_runner_->FastForwardBy(interval);
|
| - coordinator_->policy_->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_->policy_->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_->policy_->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
|
|
|