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

Unified Diff: content/browser/memory/memory_coordinator_impl_unittest.cc

Issue 2763933002: memory coordinator: Purge memory under memory pressure (Closed)
Patch Set: Use int64_t Created 3 years, 9 months 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 side-by-side diff with in-line comments
Download patch
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..761351cbefaa34387e4451a61b3437ca6f5a9844 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 {
@@ -101,7 +105,13 @@ class TestMemoryCoordinatorDelegate : public MemoryCoordinatorDelegate {
return true;
}
- void DiscardTab() override { ++discard_tab_count_; }
+ bool DiscardTab() override {
+ const int kMaxDiscardTabCount = 2;
+ if (discard_tab_count_ >= kMaxDiscardTabCount)
+ return false;
+ ++discard_tab_count_;
+ return true;
+ }
int discard_tab_count() const { return discard_tab_count_; }
@@ -566,6 +576,127 @@ 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 =
+ coordinator_->background_child_purge_candidate_period_ +
+ base::TimeDelta::FromSeconds(1);
+
+ // 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 =
+ coordinator_->background_child_purge_candidate_period_ +
+ base::TimeDelta::FromSeconds(1);
+
+ // child1: Foreground, child2: Background
+ coordinator_->OnChildVisibilityChanged(1, true);
+ coordinator_->OnChildVisibilityChanged(2, false);
+
+ // Our mocked |delegate| allows discarding tab twice. While tab discarding
+ // succeeds we don't purge memory.
+ coordinator_->OnCriticalCondition();
+ task_runner_->RunUntilIdle();
+ RunUntilIdle();
+ EXPECT_EQ(1, delegate->discard_tab_count());
+ EXPECT_EQ(0, client.purge_memory_calls());
+ EXPECT_EQ(0, child1->purge_memory_calls());
+ EXPECT_EQ(0, child2->purge_memory_calls());
+ task_runner_->FastForwardBy(interval);
+ coordinator_->OnCriticalCondition();
+ RunUntilIdle();
+ EXPECT_EQ(2, delegate->discard_tab_count());
+ EXPECT_EQ(0, client.purge_memory_calls());
+ EXPECT_EQ(0, child1->purge_memory_calls());
+ EXPECT_EQ(0, child2->purge_memory_calls());
+
+ // 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(2, 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(2, 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

Powered by Google App Engine
This is Rietveld 408576698