/// 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 "athena/resource_manager/memory_pressure_notifier.h" #include "athena/resource_manager/public/resource_manager_delegate.h" #include "athena/test/base/athena_test_base.h" namespace athena { namespace test { namespace { // Our OS delegate abstraction class to override the memory fill level. class TestResourceManagerDelegate : public ResourceManagerDelegate { public: TestResourceManagerDelegate() : memory_fill_level_percent_(0) {} ~TestResourceManagerDelegate() override {} virtual int GetUsedMemoryInPercent() override { timer_called_++; return memory_fill_level_percent_; } virtual int MemoryPressureIntervalInMS() override { return 5; } void set_memory_fill_level_percent(int memory_fill_level_percent) { memory_fill_level_percent_ = memory_fill_level_percent; } // Returns the number of timer calls to the GetMemoryInPercent() calls. int timer_called() { return timer_called_; } private: // The to be returned memory fill level value in percent. int memory_fill_level_percent_; // How often was the timer calling the GetUsedMemoryInPercent() function. int timer_called_; DISALLOW_COPY_AND_ASSIGN(TestResourceManagerDelegate); }; // Our memory pressure observer class. class TestMemoryPressureObserver : public MemoryPressureObserver { public: TestMemoryPressureObserver(ResourceManagerDelegate* delegate) : delegate_(delegate), number_of_calls_(0), pressure_(ResourceManager::MEMORY_PRESSURE_UNKNOWN) {} ~TestMemoryPressureObserver() override {} // The observer. virtual void OnMemoryPressure( ResourceManager::MemoryPressure pressure) override { number_of_calls_++; pressure_ = pressure; } virtual ResourceManagerDelegate* GetDelegate() override { return delegate_.get(); } int number_of_calls() { return number_of_calls_; } ResourceManager::MemoryPressure pressure() { return pressure_; } private: scoped_ptr delegate_; // Number of calls received. int number_of_calls_; // Last posted memory pressure. ResourceManager::MemoryPressure pressure_; DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureObserver); }; } // namespace // Our testing base. class MemoryPressureTest : public AthenaTestBase { public: MemoryPressureTest() : test_resource_manager_delegate_(nullptr) {} ~MemoryPressureTest() override {} // AthenaTestBase: virtual void SetUp() override { AthenaTestBase::SetUp(); // Create and install our TestAppContentDelegate with instrumentation. test_resource_manager_delegate_ = new TestResourceManagerDelegate(); test_memory_pressure_observer_.reset(new TestMemoryPressureObserver( test_resource_manager_delegate_)); memory_pressure_notifier_.reset( new MemoryPressureNotifier(test_memory_pressure_observer_.get())); } virtual void TearDown() override { memory_pressure_notifier_.reset(); RunAllPendingInMessageLoop(); test_memory_pressure_observer_.reset(); AthenaTestBase::TearDown(); } protected: TestResourceManagerDelegate* test_resource_manager_delegate() { return test_resource_manager_delegate_; } TestMemoryPressureObserver* test_memory_pressure_observer() { return test_memory_pressure_observer_.get(); } // Waits until a timer interrupt occurs. Returns false if no timer is // registered. bool WaitForTimer() { int first_counter = test_resource_manager_delegate()->timer_called(); // Wait up to 500ms for any poll on our memory status function from the // MemoryPressureNotifier. for (int i = 0; i < 500; ++i) { if (test_resource_manager_delegate()->timer_called() != first_counter) return true; usleep(1); RunAllPendingInMessageLoop(); } return false; } private: // Not owned: the resource manager delegate. TestResourceManagerDelegate* test_resource_manager_delegate_; scoped_ptr test_memory_pressure_observer_; scoped_ptr memory_pressure_notifier_; DISALLOW_COPY_AND_ASSIGN(MemoryPressureTest); }; // Only creates and destroys it to see that the system gets properly shut down. TEST_F(MemoryPressureTest, SimpleTest) { } // Test that we get only a single call while the memory pressure is low. TEST_F(MemoryPressureTest, OneEventOnLowPressure) { ASSERT_TRUE(WaitForTimer()); // No call should have happened at this time to the EXPECT_FALSE(test_memory_pressure_observer()->number_of_calls()); // Set to something below 50% and check that we still get no call. test_resource_manager_delegate()->set_memory_fill_level_percent(49); ASSERT_TRUE(WaitForTimer()); EXPECT_EQ(1, test_memory_pressure_observer()->number_of_calls()); EXPECT_EQ(ResourceManager::MEMORY_PRESSURE_LOW, test_memory_pressure_observer()->pressure()); ASSERT_TRUE(WaitForTimer()); EXPECT_EQ(1, test_memory_pressure_observer()->number_of_calls()); EXPECT_EQ(ResourceManager::MEMORY_PRESSURE_LOW, test_memory_pressure_observer()->pressure()); } // Test that we get a |MEMORY_PRESSURE_UNKNOWN| if it cannot be determined. TEST_F(MemoryPressureTest, TestNoCallsOnMemoryPressureUnknown) { test_resource_manager_delegate()->set_memory_fill_level_percent(0); ASSERT_TRUE(WaitForTimer()); // We shouldn't have gotten a single call. EXPECT_FALSE(test_memory_pressure_observer()->number_of_calls()); // And the memory pressure should be unknown. EXPECT_EQ(ResourceManager::MEMORY_PRESSURE_UNKNOWN, test_memory_pressure_observer()->pressure()); } // Test that we get a change to MODERATE if the memory pressure is at 60%. TEST_F(MemoryPressureTest, TestModeratePressure) { test_resource_manager_delegate()->set_memory_fill_level_percent(60); ASSERT_TRUE(WaitForTimer()); // At least one call should have happened. int calls = test_memory_pressure_observer()->number_of_calls(); EXPECT_TRUE(calls); EXPECT_EQ(ResourceManager::MEMORY_PRESSURE_MODERATE, test_memory_pressure_observer()->pressure()); // Even if the value does not change, we should get more calls. ASSERT_TRUE(WaitForTimer()); EXPECT_LT(calls, test_memory_pressure_observer()->number_of_calls()); EXPECT_EQ(ResourceManager::MEMORY_PRESSURE_MODERATE, test_memory_pressure_observer()->pressure()); } // Test that increasing and decreasing the memory pressure does the right thing. TEST_F(MemoryPressureTest, TestPressureUpAndDown) { test_resource_manager_delegate()->set_memory_fill_level_percent(60); ASSERT_TRUE(WaitForTimer()); // At least one call should have happened. int calls1 = test_memory_pressure_observer()->number_of_calls(); EXPECT_TRUE(calls1); EXPECT_EQ(ResourceManager::MEMORY_PRESSURE_MODERATE, test_memory_pressure_observer()->pressure()); // Check to the next level. test_resource_manager_delegate()->set_memory_fill_level_percent(80); ASSERT_TRUE(WaitForTimer()); int calls2 = test_memory_pressure_observer()->number_of_calls(); EXPECT_LT(calls1, calls2); EXPECT_EQ(ResourceManager::MEMORY_PRESSURE_HIGH, test_memory_pressure_observer()->pressure()); // Check to no pressure again. test_resource_manager_delegate()->set_memory_fill_level_percent(20); ASSERT_TRUE(WaitForTimer()); int calls3 = test_memory_pressure_observer()->number_of_calls(); EXPECT_LT(calls2, calls3); EXPECT_EQ(ResourceManager::MEMORY_PRESSURE_LOW, test_memory_pressure_observer()->pressure()); // Even if the value does not change, we should not get any more calls. ASSERT_TRUE(WaitForTimer()); EXPECT_EQ(calls3, test_memory_pressure_observer()->number_of_calls()); EXPECT_EQ(ResourceManager::MEMORY_PRESSURE_LOW, test_memory_pressure_observer()->pressure()); } } // namespace test } // namespace athena