blob: 97f4c8bf38d81cb2cb016c858b1e23277d1108d2 [file] [log] [blame]
// Copyright 2019 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/heap/cancelable_task_scheduler.h"
#include <atomic>
#include "base/memory/scoped_refptr.h"
#include "base/task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
#include "third_party/blink/renderer/platform/scheduler/test/fake_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
class ParallelTaskRunner : public base::TaskRunner {
public:
bool PostDelayedTask(const base::Location& location,
base::OnceClosure task,
base::TimeDelta) override {
worker_pool::PostTask(location, WTF::CrossThreadBindOnce(std::move(task)));
return true;
}
void RunUntilIdle() {}
};
template <class Runner>
class CancelableTaskSchedulerTest : public TestSupportingGC {
public:
using Task = CancelableTaskScheduler::Task;
void ScheduleTask(Task callback) {
scheduler_.ScheduleTask(std::move(callback));
}
void RunTaskRunner() { task_runner_->RunUntilIdle(); }
size_t CancelAndWait() { return scheduler_.CancelAndWait(); }
size_t NumberOfRegisteredTasks() const {
return scheduler_.NumberOfTasksForTesting();
}
private:
scoped_refptr<Runner> task_runner_ = base::MakeRefCounted<Runner>();
CancelableTaskScheduler scheduler_{task_runner_};
};
using RunnerTypes =
::testing::Types<scheduler::FakeTaskRunner, ParallelTaskRunner>;
TYPED_TEST_SUITE(CancelableTaskSchedulerTest, RunnerTypes);
TYPED_TEST(CancelableTaskSchedulerTest, EmptyCancelTasks) {
const size_t cancelled = this->CancelAndWait();
EXPECT_EQ(0u, cancelled);
EXPECT_EQ(0u, this->NumberOfRegisteredTasks());
}
TYPED_TEST(CancelableTaskSchedulerTest, RunAndCancelTasks) {
static constexpr size_t kNumberOfTasks = 10u;
const auto callback = [](std::atomic<int>* i) { ++(*i); };
std::atomic<int> var{0};
for (size_t i = 0; i < kNumberOfTasks; ++i) {
this->ScheduleTask(
WTF::CrossThreadBindOnce(callback, WTF::CrossThreadUnretained(&var)));
EXPECT_GE(i + 1, this->NumberOfRegisteredTasks());
}
this->RunTaskRunner();
// Tasks will remove themselves after running
EXPECT_LE(0u, this->NumberOfRegisteredTasks());
const size_t cancelled = this->CancelAndWait();
EXPECT_EQ(0u, this->NumberOfRegisteredTasks());
EXPECT_EQ(kNumberOfTasks, var + cancelled);
}
TEST(CancelableTaskSchedulerTest, RemoveTasksFromQueue) {
auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>();
CancelableTaskScheduler scheduler{task_runner};
int var = 0;
scheduler.ScheduleTask(WTF::CrossThreadBindOnce(
[](int* var) { ++(*var); }, WTF::CrossThreadUnretained(&var)));
auto tasks = task_runner->TakePendingTasksForTesting();
// Clearing the task queue should destroy all cancelable closures, which in
// turn will notify CancelableTaskScheduler to remove corresponding tasks.
tasks.clear();
EXPECT_EQ(0, var);
}
} // namespace blink