blob: f3dccd30d91620f6e9fcbb1e1258ba969540921f [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/android/pre_freeze_background_memory_trimmer.h"
#include "base/task/thread_pool.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base::android {
namespace {
static int s_counter = 0;
void ResetGlobalCounter() {
s_counter = 0;
}
void IncGlobalCounter() {
s_counter++;
}
void PostDelayedIncGlobal() {
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
base::BindRepeating(&IncGlobalCounter), base::Seconds(10));
}
} // namespace
class PreFreezeBackgroundMemoryTrimmerTest : public testing::Test {
public:
PreFreezeBackgroundMemoryTrimmerTest() {
fl_.InitAndEnableFeature(kOnPreFreezeMemoryTrim);
}
void SetUp() override {
PreFreezeBackgroundMemoryTrimmer::SetIsRespectingModernTrimForTesting(true);
ResetGlobalCounter();
}
protected:
size_t pending_task_count() {
return PreFreezeBackgroundMemoryTrimmer::Instance()
.GetNumberOfPendingBackgroundTasksForTesting();
}
test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
private:
test::ScopedFeatureList fl_;
};
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, PostTaskPreFreezeDisabled) {
PreFreezeBackgroundMemoryTrimmer::SetIsRespectingModernTrimForTesting(false);
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
base::BindRepeating(&IncGlobalCounter), base::Seconds(30));
ASSERT_EQ(pending_task_count(), 0u);
task_environment_.FastForwardBy(base::Seconds(30));
ASSERT_EQ(pending_task_count(), 0u);
EXPECT_EQ(s_counter, 1);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, PostDelayedTaskSimple) {
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
base::BindRepeating(&IncGlobalCounter), base::Seconds(30));
ASSERT_EQ(pending_task_count(), 1u);
task_environment_.FastForwardBy(base::Seconds(30));
ASSERT_EQ(pending_task_count(), 0u);
EXPECT_EQ(s_counter, 1);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, PostDelayedTaskMultiple) {
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
base::BindRepeating(&IncGlobalCounter), base::Seconds(40));
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
base::BindRepeating(&IncGlobalCounter), base::Seconds(30));
ASSERT_EQ(pending_task_count(), 2u);
task_environment_.FastForwardBy(base::Seconds(30));
ASSERT_EQ(pending_task_count(), 1u);
EXPECT_EQ(s_counter, 1);
task_environment_.FastForwardBy(base::Seconds(10));
ASSERT_EQ(pending_task_count(), 0u);
EXPECT_EQ(s_counter, 2);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, PostDelayedTaskPreFreeze) {
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
base::BindRepeating(&IncGlobalCounter), base::Seconds(60));
ASSERT_EQ(pending_task_count(), 1u);
task_environment_.FastForwardBy(base::Seconds(30));
PreFreezeBackgroundMemoryTrimmer::OnPreFreezeForTesting();
ASSERT_EQ(pending_task_count(), 0u);
EXPECT_EQ(s_counter, 1);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, PostDelayedTaskMultiThreaded) {
base::WaitableEvent event1(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
base::WaitableEvent event2(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
auto task_runner =
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
ASSERT_FALSE(task_runner->RunsTasksInCurrentSequence());
task_runner->PostTask(
FROM_HERE,
base::BindOnce(
[](scoped_refptr<base::SequencedTaskRunner> task_runner,
base::WaitableEvent* event1, base::WaitableEvent* event2) {
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
task_runner, FROM_HERE,
base::BindOnce(
[](base::WaitableEvent* event) {
IncGlobalCounter();
event->Signal();
},
base::Unretained(event2)),
base::Seconds(30));
event1->Signal();
},
task_runner, base::Unretained(&event1), base::Unretained(&event2)));
task_environment_.FastForwardBy(base::Seconds(1));
event1.Wait();
ASSERT_EQ(pending_task_count(), 1u);
PreFreezeBackgroundMemoryTrimmer::OnPreFreezeForTesting();
event2.Wait();
ASSERT_EQ(pending_task_count(), 0u);
EXPECT_EQ(s_counter, 1);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest,
PostDelayedTaskBeforeAndAfterPreFreeze) {
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
base::BindRepeating(&IncGlobalCounter), base::Seconds(60));
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
base::BindRepeating(&IncGlobalCounter), base::Seconds(30));
ASSERT_EQ(pending_task_count(), 2u);
task_environment_.FastForwardBy(base::Seconds(30));
ASSERT_EQ(pending_task_count(), 1u);
EXPECT_EQ(s_counter, 1);
PreFreezeBackgroundMemoryTrimmer::OnPreFreezeForTesting();
ASSERT_EQ(pending_task_count(), 0u);
EXPECT_EQ(s_counter, 2);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, AddDuringPreFreeze) {
PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
SingleThreadTaskRunner::GetCurrentDefault(), FROM_HERE,
base::BindRepeating(&PostDelayedIncGlobal), base::Seconds(10));
ASSERT_EQ(pending_task_count(), 1u);
PreFreezeBackgroundMemoryTrimmer::OnPreFreezeForTesting();
ASSERT_EQ(pending_task_count(), 0u);
EXPECT_EQ(s_counter, 1);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, TimerNeverStarted) {
OneShotDelayedBackgroundTimer timer;
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
task_environment_.FastForwardBy(base::Seconds(30));
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
EXPECT_EQ(s_counter, 0);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, TimerFastForward) {
OneShotDelayedBackgroundTimer timer;
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, base::Seconds(30), base::BindOnce(&IncGlobalCounter));
ASSERT_EQ(pending_task_count(), 1u);
ASSERT_TRUE(timer.IsRunning());
task_environment_.FastForwardBy(base::Seconds(30));
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
EXPECT_EQ(s_counter, 1);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, TimerOnPreFreeze) {
OneShotDelayedBackgroundTimer timer;
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, base::Seconds(30), base::BindOnce(&IncGlobalCounter));
ASSERT_EQ(pending_task_count(), 1u);
ASSERT_TRUE(timer.IsRunning());
PreFreezeBackgroundMemoryTrimmer::OnPreFreezeForTesting();
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
EXPECT_EQ(s_counter, 1);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, TimerStopSingle) {
OneShotDelayedBackgroundTimer timer;
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, base::Seconds(30), base::BindOnce(&IncGlobalCounter));
ASSERT_EQ(pending_task_count(), 1u);
ASSERT_TRUE(timer.IsRunning());
timer.Stop();
PreFreezeBackgroundMemoryTrimmer::OnPreFreezeForTesting();
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
EXPECT_EQ(s_counter, 0);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, TimerStopMultiple) {
OneShotDelayedBackgroundTimer timer;
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, base::Seconds(30), base::BindOnce(&IncGlobalCounter));
ASSERT_EQ(pending_task_count(), 1u);
ASSERT_TRUE(timer.IsRunning());
timer.Stop();
timer.Stop();
PreFreezeBackgroundMemoryTrimmer::OnPreFreezeForTesting();
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
EXPECT_EQ(s_counter, 0);
}
TEST_F(PreFreezeBackgroundMemoryTrimmerTest, TimerDestroyed) {
// Add scope here to destroy timer.
{
OneShotDelayedBackgroundTimer timer;
ASSERT_EQ(pending_task_count(), 0u);
ASSERT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, base::Seconds(30),
base::BindOnce(&IncGlobalCounter));
ASSERT_EQ(pending_task_count(), 1u);
ASSERT_TRUE(timer.IsRunning());
}
ASSERT_EQ(pending_task_count(), 0u);
PreFreezeBackgroundMemoryTrimmer::OnPreFreezeForTesting();
ASSERT_EQ(pending_task_count(), 0u);
EXPECT_EQ(s_counter, 0);
}
} // namespace base::android