Index: chrome/browser/memory/tab_manager_unittest.cc |
diff --git a/chrome/browser/memory/tab_manager_unittest.cc b/chrome/browser/memory/tab_manager_unittest.cc |
index a3621c1664b72299ee49daa1673b18d42ca76f31..6cf646f66495148a0ec8e04602a15fa2008ece96 100644 |
--- a/chrome/browser/memory/tab_manager_unittest.cc |
+++ b/chrome/browser/memory/tab_manager_unittest.cc |
@@ -31,7 +31,6 @@ |
#include "content/public/browser/web_contents.h" |
#include "content/public/test/mock_render_process_host.h" |
#include "content/public/test/web_contents_tester.h" |
-#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "url/gurl.h" |
@@ -86,95 +85,6 @@ class MockTabStripModelObserver : public TabStripModelObserver { |
DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver); |
}; |
-// A mock task runner. This isn't directly a TaskRunner as the reference |
-// counting confuses gmock. |
-class LenientMockTaskRunner { |
- public: |
- LenientMockTaskRunner() {} |
- MOCK_METHOD2(PostDelayedTask, |
- bool(const tracked_objects::Location&, base::TimeDelta)); |
- |
- private: |
- DISALLOW_COPY_AND_ASSIGN(LenientMockTaskRunner); |
-}; |
-using MockTaskRunner = testing::StrictMock<LenientMockTaskRunner>; |
- |
-// Represents a pending task. |
-using Task = std::pair<base::TimeTicks, base::OnceClosure>; |
- |
-// Comparator used for sorting Task objects. Can't use std::pair's default |
-// comparison operators because Closure's are comparable. |
-struct TaskComparator { |
- bool operator()(const Task& t1, const Task& t2) const { |
- // Reverse the sort order so this can be used with a min-heap. |
- return t1.first > t2.first; |
- } |
-}; |
- |
-// A TaskRunner implementation that delegates to a MockTaskRunner for asserting |
-// on task insertion order, and which stores tasks for actual later execution. |
-class TaskRunnerProxy : public base::TaskRunner { |
- public: |
- TaskRunnerProxy(MockTaskRunner* mock, |
- base::SimpleTestTickClock* clock) |
- : mock_(mock), clock_(clock) {} |
- bool RunsTasksInCurrentSequence() const override { return true; } |
- bool PostDelayedTask(const tracked_objects::Location& location, |
- base::OnceClosure closure, |
- base::TimeDelta delta) override { |
- mock_->PostDelayedTask(location, delta); |
- base::TimeTicks when = clock_->NowTicks() + delta; |
- tasks_.push_back(Task(when, std::move(closure))); |
- // Use 'greater' comparator to make this a min heap. |
- std::push_heap(tasks_.begin(), tasks_.end(), TaskComparator()); |
- return true; |
- } |
- |
- // Runs tasks up to the current time. Returns the number of tasks executed. |
- size_t RunTasks() { |
- base::TimeTicks now = clock_->NowTicks(); |
- size_t count = 0; |
- while (!tasks_.empty() && tasks_.front().first <= now) { |
- std::move(tasks_.front().second).Run(); |
- std::pop_heap(tasks_.begin(), tasks_.end(), TaskComparator()); |
- tasks_.pop_back(); |
- ++count; |
- } |
- return count; |
- } |
- |
- // Advances the clock and runs the next task in the queue. Can run more than |
- // one task if multiple tasks have the same scheduled time. |
- size_t RunNextTask() { |
- // Get the time of the next task that can possibly run. |
- base::TimeTicks when = tasks_.front().first; |
- |
- // Advance the clock to exactly that time. |
- base::TimeTicks now = clock_->NowTicks(); |
- if (now < when) { |
- base::TimeDelta delta = when - now; |
- clock_->Advance(delta); |
- } |
- |
- // Run whatever tasks are now eligible to run. |
- return RunTasks(); |
- } |
- |
- size_t size() const { return tasks_.size(); } |
- |
- private: |
- ~TaskRunnerProxy() override {} |
- |
- MockTaskRunner* mock_; |
- base::SimpleTestTickClock* clock_; |
- |
- // A min-heap of outstanding tasks. |
- using Task = std::pair<base::TimeTicks, base::OnceClosure>; |
- std::vector<Task> tasks_; |
- |
- DISALLOW_COPY_AND_ASSIGN(TaskRunnerProxy); |
-}; |
- |
enum TestIndicies { |
kSelected, |
kAutoDiscardable, |
@@ -188,19 +98,15 @@ enum TestIndicies { |
kOldButPinned, |
kInternalPage, |
}; |
+ |
} // namespace |
-class LenientTabManagerTest : public ChromeRenderViewHostTestHarness { |
+class TabManagerTest : public ChromeRenderViewHostTestHarness { |
public: |
WebContents* CreateWebContents() { |
return WebContents::Create(WebContents::CreateParams(profile())); |
} |
- |
- MOCK_METHOD2(NotifyRendererProcess, |
- void(const content::RenderProcessHost*, |
- base::MemoryPressureListener::MemoryPressureLevel)); |
}; |
-using TabManagerTest = testing::StrictMock<LenientTabManagerTest>; |
// TODO(georgesak): Add tests for protection to tabs with form input and |
// playing audio; |
@@ -508,168 +414,6 @@ TEST_F(TabManagerTest, CanOnlyDiscardOnce) { |
} |
#endif // defined(OS_WIN) || defined(OS_MACOSX) |
-namespace { |
- |
-using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; |
- |
-// Function that always indicates the absence of memory pressure. |
-MemoryPressureLevel ReturnNoPressure() { |
- return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; |
-} |
- |
-// Function that simply parrots back an externally specified memory pressure |
-// level. |
-MemoryPressureLevel ReturnSpecifiedPressure( |
- const MemoryPressureLevel* level) { |
- return *level; |
-} |
- |
-} // namespace |
- |
-// ChildProcessNotification is disabled on Chrome OS. crbug.com/588172. |
-#if defined(OS_CHROMEOS) |
-#define MAYBE_ChildProcessNotifications DISABLED_ChildProcessNotifications |
-#else |
-#define MAYBE_ChildProcessNotifications ChildProcessNotifications |
-#endif |
- |
-// Ensure that memory pressure notifications are forwarded to child processes. |
-TEST_F(TabManagerTest, MAYBE_ChildProcessNotifications) { |
- TabManager tm; |
- |
- // Set up the tab strip. |
- TabStripDummyDelegate delegate; |
- TabStripModel tabstrip(&delegate, profile()); |
- |
- // Create test clock, task runner. |
- base::SimpleTestTickClock test_clock; |
- MockTaskRunner mock_task_runner; |
- scoped_refptr<TaskRunnerProxy> task_runner( |
- new TaskRunnerProxy(&mock_task_runner, &test_clock)); |
- |
- // Configure the TabManager for testing. |
- tabstrip.AddObserver(&tm); |
- tm.test_tab_strip_models_.push_back( |
- TabManager::TestTabStripModel(&tabstrip, false /* !is_app */)); |
- tm.test_tick_clock_ = &test_clock; |
- tm.task_runner_ = task_runner; |
- tm.notify_renderer_process_ = base::Bind( |
- &TabManagerTest::NotifyRendererProcess, base::Unretained(this)); |
- |
- // Create two dummy tabs. |
- auto* tab0 = CreateWebContents(); |
- auto* tab1 = CreateWebContents(); |
- auto* tab2 = CreateWebContents(); |
- tabstrip.AppendWebContents(tab0, true); // Foreground tab. |
- tabstrip.AppendWebContents(tab1, false); // Background tab. |
- tabstrip.AppendWebContents(tab2, false); // Background tab. |
- const content::RenderProcessHost* renderer1 = tab1->GetRenderProcessHost(); |
- const content::RenderProcessHost* renderer2 = tab2->GetRenderProcessHost(); |
- |
- // Make sure that tab2 has a lower priority than tab1 by its access time. |
- test_clock.Advance(base::TimeDelta::FromMilliseconds(1)); |
- tab2->SetLastActiveTime(test_clock.NowTicks()); |
- test_clock.Advance(base::TimeDelta::FromMilliseconds(1)); |
- tab1->SetLastActiveTime(test_clock.NowTicks()); |
- |
- // Expect that the tab manager has not yet encountered memory pressure. |
- EXPECT_FALSE(tm.under_memory_pressure_); |
- EXPECT_EQ(0u, tm.notified_renderers_.size()); |
- |
- // Simulate a memory pressure situation that will immediately end. This should |
- // cause no notifications or scheduled tasks. |
- auto level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; |
- tm.get_current_pressure_level_ = base::Bind(&ReturnNoPressure); |
- tm.OnMemoryPressure(level); |
- testing::Mock::VerifyAndClearExpectations(&mock_task_runner); |
- EXPECT_FALSE(tm.under_memory_pressure_); |
- EXPECT_EQ(0u, task_runner->size()); |
- EXPECT_EQ(0u, tm.notified_renderers_.size()); |
- |
- // START OF MEMORY PRESSURE |
- |
- // Simulate a memory pressure situation that persists. This should cause a |
- // task to be scheduled, and a background renderer to be notified. |
- tm.get_current_pressure_level_ = base::Bind( |
- &ReturnSpecifiedPressure, base::Unretained(&level)); |
- EXPECT_CALL(mock_task_runner, PostDelayedTask( |
- testing::_, |
- base::TimeDelta::FromSeconds(tm.kRendererNotificationDelayInSeconds))); |
- EXPECT_CALL(*this, NotifyRendererProcess(renderer2, level)); |
- tm.OnMemoryPressure(level); |
- testing::Mock::VerifyAndClearExpectations(&mock_task_runner); |
- testing::Mock::VerifyAndClearExpectations(this); |
- EXPECT_TRUE(tm.under_memory_pressure_); |
- EXPECT_EQ(1u, task_runner->size()); |
- EXPECT_EQ(1u, tm.notified_renderers_.size()); |
- EXPECT_EQ(1u, tm.notified_renderers_.count(renderer2)); |
- |
- // REPEATED MEMORY PRESSURE SIGNAL |
- |
- // Simulate another memory pressure event. This should not cause any |
- // additional tasks to be scheduled, nor any further renderer notifications. |
- tm.OnMemoryPressure(level); |
- testing::Mock::VerifyAndClearExpectations(&mock_task_runner); |
- testing::Mock::VerifyAndClearExpectations(this); |
- EXPECT_TRUE(tm.under_memory_pressure_); |
- EXPECT_EQ(1u, task_runner->size()); |
- EXPECT_EQ(1u, tm.notified_renderers_.size()); |
- |
- // FIRST SCHEDULED NOTIFICATION |
- |
- // Run the scheduled task. This should cause another notification, but this |
- // time to the foreground tab. It should also cause another scheduled event. |
- EXPECT_CALL(mock_task_runner, PostDelayedTask( |
- testing::_, |
- base::TimeDelta::FromSeconds(tm.kRendererNotificationDelayInSeconds))); |
- EXPECT_CALL(*this, NotifyRendererProcess(renderer1, level)); |
- EXPECT_EQ(1u, task_runner->RunNextTask()); |
- testing::Mock::VerifyAndClearExpectations(&mock_task_runner); |
- testing::Mock::VerifyAndClearExpectations(this); |
- EXPECT_TRUE(tm.under_memory_pressure_); |
- EXPECT_EQ(1u, task_runner->size()); |
- EXPECT_EQ(2u, tm.notified_renderers_.size()); |
- EXPECT_EQ(1u, tm.notified_renderers_.count(renderer1)); |
- |
- // SECOND SCHEDULED NOTIFICATION |
- |
- // Run the scheduled task. This should cause another notification, to the |
- // background tab. It should also cause another scheduled event. |
- EXPECT_CALL(mock_task_runner, PostDelayedTask( |
- testing::_, |
- base::TimeDelta::FromSeconds(tm.kRendererNotificationDelayInSeconds))); |
- EXPECT_CALL(*this, NotifyRendererProcess(renderer2, level)); |
- EXPECT_EQ(1u, task_runner->RunNextTask()); |
- testing::Mock::VerifyAndClearExpectations(&mock_task_runner); |
- testing::Mock::VerifyAndClearExpectations(this); |
- EXPECT_TRUE(tm.under_memory_pressure_); |
- EXPECT_EQ(1u, task_runner->size()); |
- EXPECT_EQ(1u, tm.notified_renderers_.size()); |
- |
- // Expect that the background tab has been notified. The list of notified |
- // renderers maintained by the TabManager should also have been reset because |
- // the notification logic restarts after all renderers are notified. |
- EXPECT_EQ(1u, tm.notified_renderers_.count(renderer2)); |
- |
- // END OF MEMORY PRESSURE |
- |
- // End the memory pressure condition and run the scheduled event. This should |
- // clean up the various state data. It should not schedule another event nor |
- // fire any notifications. |
- level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; |
- EXPECT_EQ(1u, task_runner->RunNextTask()); |
- testing::Mock::VerifyAndClearExpectations(&mock_task_runner); |
- testing::Mock::VerifyAndClearExpectations(this); |
- EXPECT_FALSE(tm.under_memory_pressure_); |
- EXPECT_EQ(0u, task_runner->size()); |
- EXPECT_EQ(0u, tm.notified_renderers_.size()); |
- |
- |
- // Clean up the tabstrip. |
- tabstrip.CloseAllTabs(); |
- ASSERT_TRUE(tabstrip.empty()); |
-} |
- |
TEST_F(TabManagerTest, DefaultTimeToPurgeInCorrectRange) { |
TabManager tab_manager; |
base::TimeDelta time_to_purge = |