| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/memory/memory_pressure_monitor_chromeos.h" |
| |
| #include "base/macros.h" |
| #include "base/memory/memory_pressure_listener.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| #include "base/sys_info.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace base { |
| namespace chromeos { |
| |
| namespace { |
| |
| // True if the memory notifier got called. |
| // Do not read/modify value directly. |
| bool on_memory_pressure_called = false; |
| |
| // If the memory notifier got called, this is the memory pressure reported. |
| MemoryPressureListener::MemoryPressureLevel on_memory_pressure_level = |
| MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; |
| |
| // Processes OnMemoryPressure calls. |
| void OnMemoryPressure(MemoryPressureListener::MemoryPressureLevel level) { |
| on_memory_pressure_called = true; |
| on_memory_pressure_level = level; |
| } |
| |
| // Resets the indicator for memory pressure. |
| void ResetOnMemoryPressureCalled() { |
| on_memory_pressure_called = false; |
| } |
| |
| // Returns true when OnMemoryPressure was called (and resets it). |
| bool WasOnMemoryPressureCalled() { |
| bool b = on_memory_pressure_called; |
| ResetOnMemoryPressureCalled(); |
| return b; |
| } |
| |
| } // namespace |
| |
| class TestMemoryPressureMonitor : public MemoryPressureMonitor { |
| public: |
| TestMemoryPressureMonitor() |
| : MemoryPressureMonitor(THRESHOLD_DEFAULT), |
| memory_in_percent_override_(0) { |
| // Disable any timers which are going on and set a special memory reporting |
| // function. |
| StopObserving(); |
| } |
| ~TestMemoryPressureMonitor() override = default; |
| |
| void SetMemoryInPercentOverride(int percent) { |
| memory_in_percent_override_ = percent; |
| } |
| |
| void CheckMemoryPressureForTest() { |
| CheckMemoryPressure(); |
| } |
| |
| private: |
| int GetUsedMemoryInPercent() override { |
| return memory_in_percent_override_; |
| } |
| |
| int memory_in_percent_override_; |
| DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor); |
| }; |
| |
| // This test tests the various transition states from memory pressure, looking |
| // for the correct behavior on event reposting as well as state updates. |
| TEST(ChromeOSMemoryPressureMonitorTest, CheckMemoryPressure) { |
| // crbug.com/844102: |
| if (base::SysInfo::IsRunningOnChromeOS()) |
| return; |
| |
| base::MessageLoopForUI message_loop; |
| std::unique_ptr<TestMemoryPressureMonitor> monitor( |
| new TestMemoryPressureMonitor); |
| std::unique_ptr<MemoryPressureListener> listener( |
| new MemoryPressureListener(base::Bind(&OnMemoryPressure))); |
| // Checking the memory pressure while 0% are used should not produce any |
| // events. |
| monitor->SetMemoryInPercentOverride(0); |
| ResetOnMemoryPressureCalled(); |
| |
| monitor->CheckMemoryPressureForTest(); |
| RunLoop().RunUntilIdle(); |
| EXPECT_FALSE(WasOnMemoryPressureCalled()); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, |
| monitor->GetCurrentPressureLevel()); |
| |
| // Setting the memory level to 80% should produce a moderate pressure level. |
| monitor->SetMemoryInPercentOverride(80); |
| monitor->CheckMemoryPressureForTest(); |
| RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(WasOnMemoryPressureCalled()); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, |
| monitor->GetCurrentPressureLevel()); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, |
| on_memory_pressure_level); |
| |
| // We need to check that the event gets reposted after a while. |
| int i = 0; |
| for (; i < 100; i++) { |
| monitor->CheckMemoryPressureForTest(); |
| RunLoop().RunUntilIdle(); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, |
| monitor->GetCurrentPressureLevel()); |
| if (WasOnMemoryPressureCalled()) { |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, |
| on_memory_pressure_level); |
| break; |
| } |
| } |
| // Should be more than 5 and less than 100. |
| EXPECT_LE(5, i); |
| EXPECT_GE(99, i); |
| |
| // Setting the memory usage to 99% should produce critical levels. |
| monitor->SetMemoryInPercentOverride(99); |
| monitor->CheckMemoryPressureForTest(); |
| RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(WasOnMemoryPressureCalled()); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, |
| on_memory_pressure_level); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, |
| monitor->GetCurrentPressureLevel()); |
| |
| // Calling it again should immediately produce a second call. |
| monitor->CheckMemoryPressureForTest(); |
| RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(WasOnMemoryPressureCalled()); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, |
| on_memory_pressure_level); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, |
| monitor->GetCurrentPressureLevel()); |
| |
| // When lowering the pressure again we should not get an event, but the |
| // pressure should go back to moderate. |
| monitor->SetMemoryInPercentOverride(80); |
| monitor->CheckMemoryPressureForTest(); |
| RunLoop().RunUntilIdle(); |
| EXPECT_FALSE(WasOnMemoryPressureCalled()); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, |
| monitor->GetCurrentPressureLevel()); |
| |
| // We should need exactly the same amount of calls as before, before the next |
| // call comes in. |
| int j = 0; |
| for (; j < 100; j++) { |
| monitor->CheckMemoryPressureForTest(); |
| RunLoop().RunUntilIdle(); |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, |
| monitor->GetCurrentPressureLevel()); |
| if (WasOnMemoryPressureCalled()) { |
| EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, |
| on_memory_pressure_level); |
| break; |
| } |
| } |
| // We should have needed exactly the same amount of checks as before. |
| EXPECT_EQ(j, i); |
| } |
| |
| } // namespace chromeos |
| } // namespace base |