blob: a2b39d1f992d1a0f8ad2cdc1ce743c1bfebef34d [file] [log] [blame]
/// 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<ResourceManagerDelegate> 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<TestMemoryPressureObserver> test_memory_pressure_observer_;
scoped_ptr<MemoryPressureNotifier> 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