blob: 146cb81232970b82f841488f8df395194554fb7b [file] [log] [blame]
// Copyright 2016 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 "third_party/blink/renderer/platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
#include <memory>
#include "base/test/simple_test_tick_clock.h"
#include "components/viz/test/ordered_simple_task_runner.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
#include "third_party/blink/renderer/platform/scheduler/base/test_task_time_observer.h"
#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_helper.h"
#include "third_party/blink/renderer/platform/scheduler/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/scheduler/test/test_task_queue.h"
namespace blink {
namespace scheduler {
// Namespace to avoid symbol collisions in jumbo builds.
namespace auto_advancing_virtual_time_domain_unittest {
class AutoAdvancingVirtualTimeDomainTest : public testing::Test {
public:
AutoAdvancingVirtualTimeDomainTest() = default;
~AutoAdvancingVirtualTimeDomainTest() override = default;
void SetUp() override {
clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
mock_task_runner_ =
base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
scheduler_helper_.reset(new WorkerSchedulerHelper(
TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_),
nullptr));
scheduler_helper_->AddTaskTimeObserver(&test_task_time_observer_);
task_queue_ = scheduler_helper_->DefaultWorkerTaskQueue();
initial_time_ = base::Time::FromJsTime(100000.0);
initial_time_ticks_ = clock_.NowTicks();
auto_advancing_time_domain_.reset(new AutoAdvancingVirtualTimeDomain(
initial_time_, initial_time_ticks_, scheduler_helper_.get(),
AutoAdvancingVirtualTimeDomain::BaseTimeOverridePolicy::OVERRIDE));
scheduler_helper_->RegisterTimeDomain(auto_advancing_time_domain_.get());
task_queue_->SetTimeDomain(auto_advancing_time_domain_.get());
}
void TearDown() override {
task_queue_->ShutdownTaskQueue();
scheduler_helper_->UnregisterTimeDomain(auto_advancing_time_domain_.get());
}
base::Time initial_time_;
base::TimeTicks initial_time_ticks_;
base::SimpleTestTickClock clock_;
scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
std::unique_ptr<WorkerSchedulerHelper> scheduler_helper_;
scoped_refptr<TaskQueue> task_queue_;
std::unique_ptr<AutoAdvancingVirtualTimeDomain> auto_advancing_time_domain_;
TestTaskTimeObserver test_task_time_observer_;
};
namespace {
void NopTask(bool* task_run) {
*task_run = true;
}
class MockObserver : public AutoAdvancingVirtualTimeDomain::Observer {
public:
MOCK_METHOD0(OnVirtualTimeAdvanced, void());
};
} // namesapce
TEST_F(AutoAdvancingVirtualTimeDomainTest, VirtualTimeAdvances) {
MockObserver mock_observer;
auto_advancing_time_domain_->SetObserver(&mock_observer);
base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
bool task_run = false;
task_queue_->PostDelayedTask(FROM_HERE, base::BindOnce(NopTask, &task_run),
delay);
EXPECT_CALL(mock_observer, OnVirtualTimeAdvanced());
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(initial_time_ticks_, clock_.NowTicks());
EXPECT_EQ(initial_time_ticks_ + delay,
auto_advancing_time_domain_->CreateLazyNow().Now());
EXPECT_TRUE(task_run);
auto_advancing_time_domain_->SetObserver(nullptr);
}
TEST_F(AutoAdvancingVirtualTimeDomainTest, VirtualTimeDoesNotAdvance) {
MockObserver mock_observer;
auto_advancing_time_domain_->SetObserver(&mock_observer);
base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
bool task_run = false;
task_queue_->PostDelayedTask(FROM_HERE, base::BindOnce(NopTask, &task_run),
delay);
auto_advancing_time_domain_->SetCanAdvanceVirtualTime(false);
EXPECT_CALL(mock_observer, OnVirtualTimeAdvanced()).Times(0);
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(initial_time_ticks_, clock_.NowTicks());
EXPECT_EQ(initial_time_ticks_,
auto_advancing_time_domain_->CreateLazyNow().Now());
EXPECT_FALSE(task_run);
auto_advancing_time_domain_->SetObserver(nullptr);
}
namespace {
void RepostingTask(scoped_refptr<TaskQueue> task_queue,
int max_count,
int* count) {
if (++(*count) >= max_count)
return;
task_queue->PostTask(
FROM_HERE, base::BindOnce(&RepostingTask, task_queue, max_count, count));
}
void DelayedTask(int* count_in, int* count_out) {
*count_out = *count_in;
}
} // namespace
TEST_F(AutoAdvancingVirtualTimeDomainTest,
MaxVirtualTimeTaskStarvationCountOneHundred) {
auto_advancing_time_domain_->SetCanAdvanceVirtualTime(true);
auto_advancing_time_domain_->SetMaxVirtualTimeTaskStarvationCount(100);
int count = 0;
int delayed_task_run_at_count = 0;
RepostingTask(task_queue_, 1000, &count);
task_queue_->PostDelayedTask(
FROM_HERE,
base::BindOnce(DelayedTask, &count, &delayed_task_run_at_count),
base::TimeDelta::FromMilliseconds(10));
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(1000, count);
EXPECT_EQ(102, delayed_task_run_at_count);
}
TEST_F(AutoAdvancingVirtualTimeDomainTest,
MaxVirtualTimeTaskStarvationCountZero) {
auto_advancing_time_domain_->SetCanAdvanceVirtualTime(true);
auto_advancing_time_domain_->SetMaxVirtualTimeTaskStarvationCount(0);
int count = 0;
int delayed_task_run_at_count = 0;
RepostingTask(task_queue_, 1000, &count);
task_queue_->PostDelayedTask(
FROM_HERE,
base::BindOnce(DelayedTask, &count, &delayed_task_run_at_count),
base::TimeDelta::FromMilliseconds(10));
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(1000, count);
// If the initial count had been higher, the delayed task could have been
// arbitrarily delayed.
EXPECT_EQ(1000, delayed_task_run_at_count);
}
TEST_F(AutoAdvancingVirtualTimeDomainTest, TaskStarvationCountIncrements) {
auto_advancing_time_domain_->SetMaxVirtualTimeTaskStarvationCount(100);
EXPECT_EQ(0, auto_advancing_time_domain_->task_starvation_count());
base::PendingTask fake_task(FROM_HERE, base::OnceClosure());
auto_advancing_time_domain_->DidProcessTask(fake_task);
EXPECT_EQ(1, auto_advancing_time_domain_->task_starvation_count());
}
TEST_F(AutoAdvancingVirtualTimeDomainTest, TaskStarvationCountNotIncrements) {
auto_advancing_time_domain_->SetMaxVirtualTimeTaskStarvationCount(0);
EXPECT_EQ(0, auto_advancing_time_domain_->task_starvation_count());
base::PendingTask fake_task(FROM_HERE, base::OnceClosure());
auto_advancing_time_domain_->DidProcessTask(fake_task);
EXPECT_EQ(0, auto_advancing_time_domain_->task_starvation_count());
}
TEST_F(AutoAdvancingVirtualTimeDomainTest, TaskStarvationCountResets) {
auto_advancing_time_domain_->SetMaxVirtualTimeTaskStarvationCount(100);
base::PendingTask fake_task(FROM_HERE, base::OnceClosure());
auto_advancing_time_domain_->DidProcessTask(fake_task);
EXPECT_EQ(1, auto_advancing_time_domain_->task_starvation_count());
auto_advancing_time_domain_->SetMaxVirtualTimeTaskStarvationCount(0);
EXPECT_EQ(0, auto_advancing_time_domain_->task_starvation_count());
}
TEST_F(AutoAdvancingVirtualTimeDomainTest, BaseTimeOverriden) {
base::Time initial_time = base::Time::FromJsTime(100000.0);
EXPECT_EQ(base::Time::Now(), initial_time);
// Make time advance.
base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
bool task_run = false;
task_queue_->PostDelayedTask(FROM_HERE, base::BindOnce(NopTask, &task_run),
delay);
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(base::Time::Now(), initial_time + delay);
}
TEST_F(AutoAdvancingVirtualTimeDomainTest, BaseTimeTicksOverriden) {
base::TimeTicks initial_time = clock_.NowTicks();
EXPECT_EQ(base::TimeTicks::Now(), initial_time);
// Make time advance.
base::TimeDelta delay = base::TimeDelta::FromMilliseconds(20);
bool task_run = false;
task_queue_->PostDelayedTask(FROM_HERE, base::BindOnce(NopTask, &task_run),
delay);
mock_task_runner_->RunUntilIdle();
EXPECT_EQ(base::TimeTicks::Now(), initial_time + delay);
}
TEST_F(AutoAdvancingVirtualTimeDomainTest,
DelayTillNextTaskHandlesPastRunTime) {
base::TimeTicks initial_time = clock_.NowTicks();
// Post a task for t+10ms.
bool task_run = false;
task_queue_->PostDelayedTask(FROM_HERE, base::BindOnce(NopTask, &task_run),
base::TimeDelta::FromMilliseconds(10));
// Advance virtual time past task time to t+100ms.
auto_advancing_time_domain_->MaybeAdvanceVirtualTime(
initial_time + base::TimeDelta::FromMilliseconds(100));
// Task at t+10ms should be run immediately.
EXPECT_EQ(base::TimeDelta(),
auto_advancing_time_domain_->DelayTillNextTask(nullptr));
}
} // namespace auto_advancing_virtual_time_domain_unittest
} // namespace scheduler
} // namespace blink