Commit b7aa302b authored by Farah Charab's avatar Farah Charab Committed by Commit Bot

SQM Fuzzer: Follow-up patch for cl 1165145.

Follow up patch for comment on line 215 in sequence_manager_processor.h
for https://chromium-review.googlesource.com/c/chromium/src/+/1165145/4.

We move some interfaces from SequenceManagerFuzzerProcessor to
ThreadData to hide member variables of ThreadData.

Change-Id: I4793fe7d7514a4730d1bfc08deba8b92b68667a1
Reviewed-on: https://chromium-review.googlesource.com/1176087
Commit-Queue: Farah Charab <farahcharab@chromium.org>
Reviewed-by: default avatarSami Kyöstilä <skyostil@chromium.org>
Reviewed-by: default avatarAlex Clarke <alexclarke@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584489}
parent a54cd17b
......@@ -242,15 +242,15 @@ source_set("scheduler_fuzzer_tests") {
if (is_linux) {
sources += [
"base/sequence_manager_fuzzer_processor.cc",
"base/sequence_manager_fuzzer_processor.h",
"base/sequence_manager_fuzzer_processor_unittest.cc",
"base/simple_thread_impl.cc",
"base/simple_thread_impl.h",
"base/thread_data.cc",
"base/thread_data.h",
"base/thread_pool_manager.cc",
"base/thread_pool_manager.h",
"test/fuzzer/sequence_manager_fuzzer_processor.cc",
"test/fuzzer/sequence_manager_fuzzer_processor.h",
"test/fuzzer/sequence_manager_fuzzer_processor_unittest.cc",
"test/fuzzer/simple_thread_impl.cc",
"test/fuzzer/simple_thread_impl.h",
"test/fuzzer/thread_manager.cc",
"test/fuzzer/thread_manager.h",
"test/fuzzer/thread_pool_manager.cc",
"test/fuzzer/thread_pool_manager.h",
]
deps += [
......@@ -264,15 +264,15 @@ source_set("scheduler_fuzzer_tests") {
fuzzer_test("sequence_manager_fuzzer") {
sources = [
"base/sequence_manager_fuzzer.cc",
"base/sequence_manager_fuzzer_processor.cc",
"base/sequence_manager_fuzzer_processor.h",
"base/simple_thread_impl.cc",
"base/simple_thread_impl.h",
"base/thread_data.cc",
"base/thread_data.h",
"base/thread_pool_manager.cc",
"base/thread_pool_manager.h",
"test/fuzzer/sequence_manager_fuzzer.cc",
"test/fuzzer/sequence_manager_fuzzer_processor.cc",
"test/fuzzer/sequence_manager_fuzzer_processor.h",
"test/fuzzer/simple_thread_impl.cc",
"test/fuzzer/simple_thread_impl.h",
"test/fuzzer/thread_manager.cc",
"test/fuzzer/thread_manager.h",
"test/fuzzer/thread_pool_manager.cc",
"test/fuzzer/thread_pool_manager.h",
]
deps = [
......@@ -285,6 +285,6 @@ fuzzer_test("sequence_manager_fuzzer") {
proto_library("sequence_manager_test_description_proto") {
sources = [
"base/proto/sequence_manager_test_description.proto",
"test/fuzzer/proto/sequence_manager_test_description.proto",
]
}
......@@ -6,10 +6,3 @@ include_rules = [
"+third_party/blink/renderer/platform/platform_export.h",
"+base",
]
specific_include_rules = {
"sequence_manager_fuzzer_processor_unittest.cc": [
"+third_party/protobuf/src/google/protobuf/text_format.h",
"+third_party/protobuf/src/google/protobuf/util/message_differencer.h",
],
}
#include "third_party/blink/renderer/platform/scheduler/base/simple_thread_impl.h"
namespace base {
namespace sequence_manager {
SimpleThreadImpl::SimpleThreadImpl(ThreadCallback callback,
TimeTicks initial_time)
: SimpleThread("TestThread"),
callback_(std::move(callback)),
initial_time_(initial_time) {}
void SimpleThreadImpl::Run() {
std::unique_ptr<ThreadData> thread_data =
std::make_unique<ThreadData>(initial_time_);
thread_data_ = thread_data.get();
std::move(callback_).Run(thread_data_);
thread_can_shutdown_.Wait();
}
SimpleThreadImpl::~SimpleThreadImpl() {
thread_can_shutdown_.Signal();
Join();
}
ThreadData* SimpleThreadImpl::thread_data() const {
return thread_data_;
}
} // namespace sequence_manager
} // namespace base
#include "third_party/blink/renderer/platform/scheduler/base/thread_data.h"
#include "base/task/sequence_manager/test/test_task_queue.h"
#include "base/threading/thread_task_runner_handle.h"
namespace base {
namespace sequence_manager {
ThreadData::ThreadData(TimeTicks initial_time) {
test_task_runner_ = WrapRefCounted(
new TestMockTimeTaskRunner(TestMockTimeTaskRunner::Type::kBoundToThread));
DCHECK(!(initial_time - TimeTicks()).is_zero())
<< "A zero clock is not allowed as empty TimeTicks have a special value "
"(i.e. base::TimeTicks::is_null())";
test_task_runner_->AdvanceMockTickClock(initial_time - TimeTicks());
manager_ =
SequenceManagerForTest::Create(nullptr, ThreadTaskRunnerHandle::Get(),
test_task_runner_->GetMockTickClock());
TaskQueue::Spec spec = TaskQueue::Spec("default_task_queue");
task_queues_.emplace_back(manager_->CreateTaskQueue<TestTaskQueue>(spec));
}
ThreadData::~ThreadData() = default;
} // namespace sequence_manager
} // namespace base
......@@ -152,7 +152,7 @@ message SequenceManagerTestDescription {
repeated Action initial_thread_actions = 1;
}
message InitialThread {
message CreateInitialThreadAction {
// NEXT ID = 3
optional uint64 action_id = 1;
......@@ -160,5 +160,5 @@ message SequenceManagerTestDescription {
required CreateThreadAction create_thread = 2;
}
repeated InitialThread main_thread_actions = 1;
repeated CreateInitialThreadAction main_thread_actions = 1;
}
......@@ -2,8 +2,8 @@
#include <iostream>
#include "testing/libfuzzer/proto/lpm_interface.h"
#include "third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.pb.h"
#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/proto/sequence_manager_test_description.pb.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h"
// Tests some APIs in base::sequence_manager::SequenceManager (ones defined in
// SequenceManagerTesrDescription proto) for crashes, hangs, memory leaks,
......
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_manager.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h"
namespace base {
namespace sequence_manager {
void SequenceManagerFuzzerProcessor::ParseAndRun(
const SequenceManagerTestDescription& description) {
SequenceManagerFuzzerProcessor processor;
processor.RunTest(description);
}
SequenceManagerFuzzerProcessor::SequenceManagerFuzzerProcessor()
: SequenceManagerFuzzerProcessor(false) {}
SequenceManagerFuzzerProcessor::SequenceManagerFuzzerProcessor(
bool log_for_testing)
: log_for_testing_(log_for_testing),
initial_time_(TimeTicks() + TimeDelta::FromMilliseconds(1)),
thread_pool_manager_(std::make_unique<ThreadPoolManager>(this)),
main_thread_manager_(
std::make_unique<ThreadManager>(initial_time_, this)) {}
SequenceManagerFuzzerProcessor::~SequenceManagerFuzzerProcessor() = default;
void SequenceManagerFuzzerProcessor::RunTest(
const SequenceManagerTestDescription& description) {
for (const auto& initial_action : description.main_thread_actions()) {
main_thread_manager_->ExecuteCreateThreadAction(
initial_action.action_id(), initial_action.create_thread());
}
thread_pool_manager_->StartInitialThreads();
thread_pool_manager_->WaitForAllThreads();
if (log_for_testing_) {
ordered_actions_.emplace_back(main_thread_manager_->ordered_actions());
ordered_tasks_.emplace_back(main_thread_manager_->ordered_tasks());
for (auto&& thread : (thread_pool_manager_->threads())) {
DCHECK(thread->thread_manager());
ordered_actions_.emplace_back(
thread->thread_manager()->ordered_actions());
ordered_tasks_.emplace_back(thread->thread_manager()->ordered_tasks());
}
}
}
void SequenceManagerFuzzerProcessor::LogTaskForTesting(
std::vector<TaskForTest>* ordered_tasks,
uint64_t task_id,
TimeTicks start_time,
TimeTicks end_time) {
if (!log_for_testing_)
return;
uint64_t start_time_ms = (start_time - initial_time_).InMilliseconds();
uint64_t end_time_ms = (end_time - initial_time_).InMilliseconds();
ordered_tasks->emplace_back(task_id, start_time_ms, end_time_ms);
}
void SequenceManagerFuzzerProcessor::LogActionForTesting(
std::vector<ActionForTest>* ordered_actions,
uint64_t action_id,
ActionForTest::ActionType type,
TimeTicks start_time) {
if (!log_for_testing_)
return;
ordered_actions->emplace_back(action_id, type,
(start_time - initial_time_).InMilliseconds());
}
const std::vector<std::vector<SequenceManagerFuzzerProcessor::TaskForTest>>&
SequenceManagerFuzzerProcessor::ordered_tasks() const {
return ordered_tasks_;
}
const std::vector<std::vector<SequenceManagerFuzzerProcessor::ActionForTest>>&
SequenceManagerFuzzerProcessor::ordered_actions() const {
return ordered_actions_;
}
SequenceManagerFuzzerProcessor::TaskForTest::TaskForTest(uint64_t id,
uint64_t start_time_ms,
uint64_t end_time_ms)
: task_id(id), start_time_ms(start_time_ms), end_time_ms(end_time_ms) {}
bool SequenceManagerFuzzerProcessor::TaskForTest::operator==(
const TaskForTest& rhs) const {
return task_id == rhs.task_id && start_time_ms == rhs.start_time_ms &&
end_time_ms == rhs.end_time_ms;
}
SequenceManagerFuzzerProcessor::ActionForTest::ActionForTest(
uint64_t id,
ActionType type,
uint64_t start_time_ms)
: action_id(id), action_type(type), start_time_ms(start_time_ms) {}
bool SequenceManagerFuzzerProcessor::ActionForTest::operator==(
const ActionForTest& rhs) const {
return action_id == rhs.action_id && action_type == rhs.action_type &&
start_time_ms == rhs.start_time_ms;
}
ThreadPoolManager* SequenceManagerFuzzerProcessor::thread_pool_manager() const {
return thread_pool_manager_.get();
}
} // namespace sequence_manager
} // namespace base
......@@ -2,28 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_SEQUENCE_MANAGER_FUZZER_PROCESSOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_SEQUENCE_MANAGER_FUZZER_PROCESSOR_H_
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_FUZZER_SEQUENCE_MANAGER_FUZZER_PROCESSOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_FUZZER_SEQUENCE_MANAGER_FUZZER_PROCESSOR_H_
#include <memory>
#include <vector>
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.pb.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/proto/sequence_manager_test_description.pb.h"
namespace base {
namespace sequence_manager {
class ThreadData;
class ThreadManager;
class ThreadPoolManager;
// Provides functionality to parse the fuzzer's test description and run the
// relevant APIs.
//
// Warning: For unit testing purposes, the thread data of the threads managed by
// the |thread_pool_manager_| should live for the scope of the main thread
// Warning: For unit testing purposes, the thread manager of the threads managed
// by the |thread_pool_manager_| should live for the scope of the main thread
// entry function i.e RunTest.
class PLATFORM_EXPORT SequenceManagerFuzzerProcessor {
public:
......@@ -31,6 +30,8 @@ class PLATFORM_EXPORT SequenceManagerFuzzerProcessor {
// run the relevant APIs.
static void ParseAndRun(const SequenceManagerTestDescription& description);
ThreadPoolManager* thread_pool_manager() const;
protected:
struct TaskForTest {
TaskForTest(uint64_t id, uint64_t start_time_ms, uint64_t end_time_ms);
......@@ -64,19 +65,6 @@ class PLATFORM_EXPORT SequenceManagerFuzzerProcessor {
uint64_t start_time_ms;
};
class Task {
public:
Task(ThreadData* thread_data, SequenceManagerFuzzerProcessor* processor);
~Task() = default;
void Execute(const SequenceManagerTestDescription::Task& task);
bool is_running;
SequenceManagerFuzzerProcessor* processor_;
ThreadData* thread_data_;
base::WeakPtrFactory<Task> weak_ptr_factory_;
};
SequenceManagerFuzzerProcessor();
explicit SequenceManagerFuzzerProcessor(bool log_for_testing);
......@@ -85,11 +73,6 @@ class PLATFORM_EXPORT SequenceManagerFuzzerProcessor {
void RunTest(const SequenceManagerTestDescription& description);
void ExecuteThread(
ThreadData* thread_data,
const google::protobuf::RepeatedPtrField<
SequenceManagerTestDescription::Action>& initial_thread_actions);
// Returns an ordered list of tasks executed on each thread. Note that the
// ordering of the threads isn't deterministic since it follows the order in
// which the threads were constructed. Furthermore, given that
......@@ -104,78 +87,32 @@ class PLATFORM_EXPORT SequenceManagerFuzzerProcessor {
const std::vector<std::vector<ActionForTest>>& ordered_actions() const;
private:
friend class ThreadData;
friend class ThreadPoolManager;
void RunAction(ThreadData* thread_data,
const SequenceManagerTestDescription::Action& action);
void ExecuteCreateThreadAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::CreateThreadAction& action);
void ExecuteCreateTaskQueueAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::CreateTaskQueueAction& action);
void ExecutePostDelayedTaskAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::PostDelayedTaskAction& action);
void ExecuteSetQueuePriorityAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::SetQueuePriorityAction& action);
void ExecuteSetQueueEnabledAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::SetQueueEnabledAction& action);
void ExecuteCreateQueueVoterAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::CreateQueueVoterAction& action);
void ExecuteShutdownTaskQueueAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::ShutdownTaskQueueAction& action);
void ExecuteCancelTaskAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::CancelTaskAction& action);
void ExecuteInsertFenceAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::InsertFenceAction& action);
void ExecuteRemoveFenceAction(
ThreadData* thread_data,
uint64_t action_id,
const SequenceManagerTestDescription::RemoveFenceAction& action);
void ExecuteTask(ThreadData* thread_data,
const SequenceManagerTestDescription::Task& task);
void DeleteTask(Task* task);
void LogTaskForTesting(ThreadData* thread_data,
friend class ThreadManager;
// Logs the task defined by the parameters passed to |ordered_tasks| if
// |log_for_testing_| is enabled.
void LogTaskForTesting(std::vector<TaskForTest>* ordered_tasks,
uint64_t task_id,
TimeTicks start_time,
TimeTicks end_time);
void LogActionForTesting(ThreadData* thread_data,
// Logs the action defined by the parameters passed to |ordered_actions| if
// |log_for_testing_| is enabled.
void LogActionForTesting(std::vector<ActionForTest>* ordered_actions,
uint64_t action_id,
ActionForTest::ActionType type,
TimeTicks start_time);
const bool log_for_testing_;
TimeTicks initial_time_;
const TimeTicks initial_time_;
std::unique_ptr<ThreadPoolManager> thread_pool_manager_;
const std::unique_ptr<ThreadPoolManager> thread_pool_manager_;
// The clock of the main thread data task runner is initialized to
// The clock of the main thread manager task runner is initialized to
// |initial_time_| and never advanced, since it can only execute actions at
// the start of the program.
std::unique_ptr<ThreadData> main_thread_data_;
const std::unique_ptr<ThreadManager> main_thread_manager_;
// For Testing. Each entry contains the ordered list of tasks for one of the
// created threads. The first entry is reserved for the main thread (which is
......
......@@ -2,7 +2,7 @@
// 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/base/sequence_manager_fuzzer_processor.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h"
#include <memory>
......@@ -10,7 +10,7 @@
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.pb.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/proto/sequence_manager_test_description.pb.h"
#include "third_party/protobuf/src/google/protobuf/text_format.h"
#include "third_party/protobuf/src/google/protobuf/util/message_differencer.h"
......@@ -149,7 +149,7 @@ TEST(SequenceManagerFuzzerProcessorTest, CreateQueueVoter) {
EXPECT_THAT(executed_actions, ContainerEq(expected_actions));
}
TEST(SequenceManagerFuzzerProcessorTest, PostDelayedTaskWithDuration) {
TEST(SequenceManagerFuzzerProcessorTest, PostDelayedTaskWDuration) {
std::vector<TaskForTest> executed_tasks;
std::vector<ActionForTest> executed_actions;
......@@ -278,12 +278,12 @@ TEST(SequenceManagerFuzzerProcessorTest, SetQueueEnabled) {
EXPECT_THAT(executed_actions, ContainerEq(expected_actions));
// All the tasks posted to the task queue with id 1 do not get executed since
// All the tasks posted to the task queue w id 1 do not get executed since
// this task queue is disabled.
EXPECT_THAT(executed_tasks, IsEmpty());
}
TEST(SequenceManagerFuzzerProcessorTest, SetQueueEnabledWithDelays) {
TEST(SequenceManagerFuzzerProcessorTest, SetQueueEnabledWDelays) {
std::vector<TaskForTest> executed_tasks;
// Describes a test that posts two tasks to disable and enable a queue after
......@@ -522,7 +522,7 @@ TEST(SequenceManagerFuzzerProcessorTest, ShutdownTaskQueue) {
std::vector<TaskForTest> expected_tasks;
// Note that the task with id 4 isn't posted to the queue that was shutdown,
// Note that the task w id 4 isn't posted to the queue that was shutdown,
// since that was posted to the first available queue (Check
// sequence_manager_test_description.proto for more details).
expected_tasks.emplace_back(4, 0, 0);
......@@ -755,7 +755,7 @@ TEST(SequenceManagerFuzzerProcessorTest,
std::vector<TaskForTest> expected_tasks;
// Task with id 2 is expected to run first and block the other task until it
// Task w id 2 is expected to run first and block the other task until it
// done.
expected_tasks.emplace_back(2, 0, 40);
expected_tasks.emplace_back(1, 40, 60);
......@@ -770,7 +770,7 @@ TEST(SequenceManagerFuzzerProcessorTest,
}
TEST(SequenceManagerFuzzerProcessorTest,
TaskDurationBlocksOtherNonNestableTaskWhenPostedFromTheWithinTask) {
TaskDurationBlocksOtherNonNestableTaskWhenPostedFromTheWinTask) {
std::vector<TaskForTest> executed_tasks;
// Posts an instant task of duration 40 ms that posts another non-nested
......@@ -796,9 +796,9 @@ TEST(SequenceManagerFuzzerProcessorTest,
std::vector<TaskForTest> expected_tasks;
// Task with task id 1 is expected to run for 40 ms, and block the other
// posted task from running until its done. Note that the task with id 2 is
// blocked since it is non-nested, so it is not supposed to run from within
// Task w task id 1 is expected to run for 40 ms, and block the other
// posted task from running until its done. Note that the task w id 2 is
// blocked since it is non-nested, so it is not supposed to run from win
// the posting task.
expected_tasks.emplace_back(1, 0, 40);
expected_tasks.emplace_back(2, 40, 40);
......@@ -865,9 +865,9 @@ TEST(SequenceManagerFuzzerProcessorTest, PostNonEmptyTask) {
std::vector<TaskForTest> expected_tasks;
// Task with task id 1 is expected to run first, and block all other pending
// Task w task id 1 is expected to run first, and block all other pending
// tasks until its done. The remaining tasks will be executed in
// non-decreasing order of the delay parameter with ties broken by
// non-decreasing order of the delay parameter w ties broken by
// the post order.
expected_tasks.emplace_back(1, 5, 45);
expected_tasks.emplace_back(3, 45, 45);
......@@ -950,8 +950,8 @@ TEST(SequenceManagerFuzzerProcessorTest, OrderOfSimpleUnnestedExecutedActions) {
std::vector<TaskForTest> expected_tasks;
// Tasks are expected to run in order of non-decreasing delay with ties broken
// by order of posting. Note that the task with id 3 will block the task with
// Tasks are expected to run in order of non-decreasing delay w ties broken
// by order of posting. Note that the task w id 3 will block the task with
// id 2 from running at its scheduled time.
expected_tasks.emplace_back(1, 10, 10);
expected_tasks.emplace_back(3, 15, 25);
......@@ -1052,7 +1052,7 @@ TEST(SequenceManagerFuzzerProcessorTest, InsertAndRemoveFence) {
expected_tasks.emplace_back(1, 20, 20);
expected_tasks.emplace_back(2, 30, 30);
// Task with id 3 will not execute until the fence is removed from the task
// Task w id 3 will not execute until the fence is removed from the task
// queue it was posted to.
expected_tasks.emplace_back(3, 30, 30);
......@@ -1091,7 +1091,7 @@ TEST(SequenceManagerFuzzerProcessorTest, ThrottleTaskQueue) {
EXPECT_THAT(executed_actions, ContainerEq(expected_actions));
// Task queue with id 1 is throttled, so posted tasks will not get executed.
// Task queue w id 1 is throttled, so posted tasks will not get executed.
EXPECT_THAT(executed_tasks, IsEmpty());
}
......@@ -1151,7 +1151,7 @@ TEST(SequenceManagerFuzzerProcessorTest, MultipleThreadsButNotInteracting) {
}
})";
// Threads initialized with same list of actions.
// Threads initialized w same list of actions.
std::vector<std::string> threads{thread_actions, thread_actions,
thread_actions, thread_actions,
thread_actions};
......@@ -1168,8 +1168,8 @@ TEST(SequenceManagerFuzzerProcessorTest, MultipleThreadsButNotInteracting) {
for (int i = 1; i <= 5; i++) {
// Created thread tasks: tasks are expected to run in order of
// non-decreasing delay with ties broken by order of posting. Note that the
// task with id 3 will block the task with id 2 from running at its
// non-decreasing delay w ties broken by order of posting. Note that the
// task w id 3 will block the task with id 2 from running at its
// scheduled time.
expected_tasks[i].emplace_back(1, 10, 10);
expected_tasks[i].emplace_back(3, 15, 25);
......
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_manager.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h"
namespace base {
namespace sequence_manager {
SimpleThreadImpl::SimpleThreadImpl(ThreadPoolManager* thread_pool_manager,
TimeTicks initial_time,
ThreadCallback callback)
: SimpleThread("TestThread"),
thread_pool_manager_(thread_pool_manager),
initial_time_(initial_time),
callback_(std::move(callback)) {
DCHECK(thread_pool_manager_);
}
void SimpleThreadImpl::Run() {
std::unique_ptr<ThreadManager> thread_manager =
std::make_unique<ThreadManager>(initial_time_,
thread_pool_manager_->processor());
thread_manager_ = thread_manager.get();
std::move(callback_).Run(thread_manager_);
thread_can_shutdown_.Wait();
}
SimpleThreadImpl::~SimpleThreadImpl() {
thread_can_shutdown_.Signal();
Join();
}
ThreadManager* SimpleThreadImpl::thread_manager() const {
return thread_manager_;
}
} // namespace sequence_manager
} // namespace base
......@@ -2,48 +2,55 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_SIMPLE_THREAD_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_SIMPLE_THREAD_IMPL_H_
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_FUZZER_SIMPLE_THREAD_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_FUZZER_SIMPLE_THREAD_IMPL_H_
#include "base/callback.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/simple_thread.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/base/thread_data.h"
namespace base {
namespace sequence_manager {
class ThreadPoolManager;
class ThreadManager;
// Used by the ThreadPoolManager to create threads that do not have an
// associated message loop, since we want to use base::TestMockTimeTaskRunner to
// control the task execution and the clock of the thread.
class PLATFORM_EXPORT SimpleThreadImpl : public SimpleThread {
public:
using ThreadCallback = base::OnceCallback<void(ThreadData*)>;
using ThreadCallback = base::OnceCallback<void(ThreadManager*)>;
SimpleThreadImpl(ThreadCallback callback, TimeTicks initial_time);
SimpleThreadImpl(ThreadPoolManager* thread_pool_manager,
TimeTicks initial_time,
ThreadCallback callback);
~SimpleThreadImpl() override;
ThreadData* thread_data() const;
ThreadManager* thread_manager() const;
private:
// This doesn't terminate until |this| object is destructed.
void Run() override;
ThreadCallback callback_;
// Owner of this class.
ThreadPoolManager* thread_pool_manager_;
// Time in which the thread is created.
TimeTicks initial_time_;
// The object pointed to by |thread_data_| is created and destructed from the
// Run function. This is necessary since it has to be constructed from the
// The object pointed to by |thread_manager_| is created and destructed from
// the Run function. This is necessary since it has to be constructed from the
// thread it should be bound to and destructed from the same thread.
ThreadData* thread_data_;
ThreadManager* thread_manager_;
// Used by the Run function to only terminate when |this| is destructed, and
// this is used so that |thread_data_| will live as long as |this|.
WaitableEvent thread_can_shutdown_;
ThreadCallback callback_;
};
} // namespace sequence_manager
......
......@@ -2,26 +2,64 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_THREAD_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_THREAD_DATA_H_
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_FUZZER_THREAD_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_FUZZER_THREAD_MANAGER_H_
#include <memory>
#include <vector>
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
#include "base/task/sequence_manager/test/test_task_queue.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/proto/sequence_manager_test_description.pb.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h"
namespace base {
namespace sequence_manager {
class PLATFORM_EXPORT ThreadData {
// Used by the SequenceManagerFuzzerProcessor to execute actions on a thread.
class PLATFORM_EXPORT ThreadManager {
public:
// |initial_time| is the time in which |this| was instantiated.
ThreadManager(TimeTicks initial_time,
SequenceManagerFuzzerProcessor* processor);
~ThreadManager();
// Returns the time of the underlying task runner.
TimeTicks NowTicks();
// Returns the delay of the oldest pending task on the thread |this| is bound
// to.
TimeDelta NextPendingTaskDelay();
// Advances the clock of the underlying task runner by |delta|.
void AdvanceMockTickClock(TimeDelta delta);
// Used to create a thread and register it with the thread pool manager owned
// by |processor_|.
void ExecuteCreateThreadAction(
uint64_t action_id,
const SequenceManagerTestDescription::CreateThreadAction& action);
// Used by the thread pool manager owned by |processor_| to execute the
// thread.
void ExecuteThread(
const google::protobuf::RepeatedPtrField<
SequenceManagerTestDescription::Action>& initial_thread_actions);
const std::vector<SequenceManagerFuzzerProcessor::TaskForTest>&
ordered_tasks() const;
const std::vector<SequenceManagerFuzzerProcessor::ActionForTest>&
ordered_actions() const;
protected:
struct TaskQueueWithVoters {
explicit TaskQueueWithVoters(scoped_refptr<TestTaskQueue> task_queue)
: queue(std::move(task_queue)){};
......@@ -30,10 +68,58 @@ class PLATFORM_EXPORT ThreadData {
std::vector<std::unique_ptr<TaskQueue::QueueEnabledVoter>> voters;
};
// |initial_time| is the time in which |this| was instantiated.
explicit ThreadData(TimeTicks initial_time);
class Task {
public:
explicit Task(ThreadManager* thread_manager);
~Task() = default;
void Execute(const SequenceManagerTestDescription::Task& task);
~ThreadData();
bool is_running;
// Should outlive |this|.
ThreadManager* thread_manager_;
base::WeakPtrFactory<Task> weak_ptr_factory_;
};
void RunAction(const SequenceManagerTestDescription::Action& action);
void ExecuteCreateTaskQueueAction(
uint64_t action_id,
const SequenceManagerTestDescription::CreateTaskQueueAction& action);
void ExecutePostDelayedTaskAction(
uint64_t action_id,
const SequenceManagerTestDescription::PostDelayedTaskAction& action);
void ExecuteSetQueuePriorityAction(
uint64_t action_id,
const SequenceManagerTestDescription::SetQueuePriorityAction& action);
void ExecuteSetQueueEnabledAction(
uint64_t action_id,
const SequenceManagerTestDescription::SetQueueEnabledAction& action);
void ExecuteCreateQueueVoterAction(
uint64_t action_id,
const SequenceManagerTestDescription::CreateQueueVoterAction& action);
void ExecuteShutdownTaskQueueAction(
uint64_t action_id,
const SequenceManagerTestDescription::ShutdownTaskQueueAction& action);
void ExecuteCancelTaskAction(
uint64_t action_id,
const SequenceManagerTestDescription::CancelTaskAction& action);
void ExecuteInsertFenceAction(
uint64_t action_id,
const SequenceManagerTestDescription::InsertFenceAction& action);
void ExecuteRemoveFenceAction(
uint64_t action_id,
const SequenceManagerTestDescription::RemoveFenceAction& action);
private:
using ActionForTest = SequenceManagerFuzzerProcessor::ActionForTest;
using TaskForTest = SequenceManagerFuzzerProcessor::TaskForTest;
void ExecuteTask(const SequenceManagerTestDescription::Task& task);
// Used to delete |task| from |pending_tasks_|.
void DeleteTask(Task* task);
// Bound to the thread in which this object was instantiated. Used to
// control the clock of the sequence manager.
......@@ -48,8 +134,7 @@ class PLATFORM_EXPORT ThreadData {
// Used to be able to cancel pending tasks from the sequence manager. For
// testing purposes, this should follow the order in which the tasks were
// posted to the thread in which |this| was instantiated.
std::vector<std::unique_ptr<SequenceManagerFuzzerProcessor::Task>>
pending_tasks_;
std::vector<std::unique_ptr<Task>> pending_tasks_;
// For Testing. Used to log tasks in their order of execution on the
// thread in which |this| was instantiated.
......@@ -59,6 +144,10 @@ class PLATFORM_EXPORT ThreadData {
// thread in which |this| was instantiated.
std::vector<SequenceManagerFuzzerProcessor::ActionForTest> ordered_actions_;
// Outlives this class. |processor_| owns a thread pool manager that creates
// threads.
SequenceManagerFuzzerProcessor* const processor_;
THREAD_CHECKER(thread_checker_);
};
......
#include "third_party/blink/renderer/platform/scheduler/base/thread_pool_manager.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h"
#include <algorithm>
#include "base/bind.h"
#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h"
#include "third_party/blink/renderer/platform/scheduler/base/simple_thread_impl.h"
#include "third_party/blink/renderer/platform/scheduler/base/thread_data.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_manager.h"
namespace base {
namespace sequence_manager {
......@@ -37,9 +37,9 @@ void ThreadPoolManager::CreateThread(
{
AutoLock lock(lock_);
threads_.push_back(std::make_unique<SimpleThreadImpl>(
this, time,
BindOnce(&ThreadPoolManager::StartThread, Unretained(this),
initial_thread_actions),
time));
initial_thread_actions)));
thread = threads_.back().get();
}
thread->Start();
......@@ -48,30 +48,26 @@ void ThreadPoolManager::CreateThread(
void ThreadPoolManager::StartThread(
const google::protobuf::RepeatedPtrField<
SequenceManagerTestDescription::Action>& initial_thread_actions,
ThreadData* thread_data) {
ThreadManager* thread_manager) {
{
AutoLock lock(lock_);
while (!initial_threads_created_)
ready_to_execute_threads_.Wait();
}
processor_->ExecuteThread(thread_data, initial_thread_actions);
thread_manager->ExecuteThread(initial_thread_actions);
}
void ThreadPoolManager::AdvanceClockSynchronouslyByPendingTaskDelay(
ThreadData* thread_data) {
DCHECK_CALLED_ON_VALID_THREAD(thread_data->thread_checker_);
ThreadManager* thread_manager) {
ThreadReadyToComputeTime();
{
AutoLock lock(lock_);
while (threads_waiting_to_compute_time_ != threads_.size())
ready_to_compute_time_.Wait();
next_time_ = std::min(
next_time_,
thread_data->test_task_runner_->GetMockTickClock()->NowTicks() +
std::max(TimeDelta::FromMilliseconds(0),
thread_data->test_task_runner_->NextPendingTaskDelay()));
next_time_ =
std::min(next_time_, thread_manager->NowTicks() +
thread_manager->NextPendingTaskDelay());
threads_waiting_to_advance_time_++;
if (threads_waiting_to_advance_time_ == threads_.size()) {
threads_waiting_to_compute_time_ = 0;
......@@ -79,11 +75,12 @@ void ThreadPoolManager::AdvanceClockSynchronouslyByPendingTaskDelay(
}
}
AdvanceThreadClock(thread_data);
AdvanceThreadClock(thread_manager);
}
void ThreadPoolManager::AdvanceClockSynchronouslyToTime(ThreadData* thread_data,
TimeTicks time) {
void ThreadPoolManager::AdvanceClockSynchronouslyToTime(
ThreadManager* thread_manager,
TimeTicks time) {
ThreadReadyToComputeTime();
{
AutoLock lock(lock_);
......@@ -96,7 +93,7 @@ void ThreadPoolManager::AdvanceClockSynchronouslyToTime(ThreadData* thread_data,
ready_to_advance_time_.Broadcast();
}
}
AdvanceThreadClock(thread_data);
AdvanceThreadClock(thread_manager);
}
void ThreadPoolManager::ThreadReadyToComputeTime() {
......@@ -110,13 +107,11 @@ void ThreadPoolManager::ThreadReadyToComputeTime() {
}
}
void ThreadPoolManager::AdvanceThreadClock(ThreadData* thread_data) {
void ThreadPoolManager::AdvanceThreadClock(ThreadManager* thread_manager) {
AutoLock lock(lock_);
while (threads_waiting_to_advance_time_ != threads_.size())
ready_to_advance_time_.Wait();
thread_data->test_task_runner_->AdvanceMockTickClock(
next_time_ -
thread_data->test_task_runner_->GetMockTickClock()->NowTicks());
thread_manager->AdvanceMockTickClock(next_time_ - thread_manager->NowTicks());
threads_ready_for_next_round_++;
if (threads_ready_for_next_round_ == threads_.size()) {
threads_waiting_to_advance_time_ = 0;
......@@ -153,9 +148,13 @@ void ThreadPoolManager::ThreadDone() {
}
const std::vector<std::unique_ptr<SimpleThreadImpl>>&
ThreadPoolManager::threads() {
ThreadPoolManager::threads() const {
return threads_;
}
SequenceManagerFuzzerProcessor* ThreadPoolManager::processor() const {
return processor_;
}
} // namespace sequence_manager
} // namespace base
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_THREAD_POOL_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_THREAD_POOL_MANAGER_H_
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_FUZZER_THREAD_POOL_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_FUZZER_THREAD_POOL_MANAGER_H_
#include <memory>
#include <vector>
......@@ -12,14 +12,14 @@
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.pb.h"
#include "third_party/blink/renderer/platform/scheduler/test/fuzzer/proto/sequence_manager_test_description.pb.h"
namespace base {
namespace sequence_manager {
class SequenceManagerFuzzerProcessor;
class SimpleThreadImpl;
class ThreadData;
class ThreadManager;
// Used by the SequenceManagerFuzzerProcessor to manage threads and synchronize
// their clocks.
......@@ -28,23 +28,24 @@ class PLATFORM_EXPORT ThreadPoolManager {
explicit ThreadPoolManager(SequenceManagerFuzzerProcessor* processor);
~ThreadPoolManager();
// |time| is the virtual time in which the thread is created. The virtual time
// is controlled by |this| and synchronized for all the threads it owns.
// |initial_time| is the time in which the thread is created.
void CreateThread(
const google::protobuf::RepeatedPtrField<
SequenceManagerTestDescription::Action>& initial_thread_actions,
TimeTicks time);
TimeTicks initial_time);
// Advances the mock tick clock of all the threads synchronously.
// Note that this doesn't guarantee advancing the thread's clock to |time|.
// The clock is advanced to the minimum desired time of all the owned threads.
void AdvanceClockSynchronouslyToTime(ThreadData* thread_data, TimeTicks time);
void AdvanceClockSynchronouslyToTime(ThreadManager* thread_manager,
TimeTicks time);
// Advances the mock tick clock of all the threads synchronously.
// Note that this doesn't guarantee advancing the thread's clock by the next
// pending task delay. The clock is advanced to the minimum desired time of
// all the owned threads.
void AdvanceClockSynchronouslyByPendingTaskDelay(ThreadData* thread_data);
void AdvanceClockSynchronouslyByPendingTaskDelay(
ThreadManager* thread_manager);
// Used by a thread to notify the thread manager that it is done executing the
// thread actions passed to ThreadPoolManager::CreateThread.
......@@ -57,13 +58,15 @@ class PLATFORM_EXPORT ThreadPoolManager {
// the threads are not terminated until |this| gets destructed.
void WaitForAllThreads();
const std::vector<std::unique_ptr<SimpleThreadImpl>>& threads();
const std::vector<std::unique_ptr<SimpleThreadImpl>>& threads() const;
SequenceManagerFuzzerProcessor* processor() const;
private:
void StartThread(
const google::protobuf::RepeatedPtrField<
SequenceManagerTestDescription::Action>& initial_thread_actions,
ThreadData* thread_data);
ThreadManager* thread_manager);
// Helper function used by AdvanceClockSynchronouslyToTime and
// AdvanceClockSynchronouslyByPendingTaskDelay to notify the manager when all
......@@ -72,9 +75,9 @@ class PLATFORM_EXPORT ThreadPoolManager {
// Helper function used by AdvanceClockSynchronouslyToTime and
// AdvanceClockSynchronouslyByPendingTaskDelay to advance the thread's clock
// to |next_time_|. Note that this function waits until all owned threads have
// to |next_time_|. Note that this function waits until all threads have
// voted on the value of |next_time_|.
void AdvanceThreadClock(ThreadData* thread_data);
void AdvanceThreadClock(ThreadManager* thread_manager);
// Owner of this class.
SequenceManagerFuzzerProcessor* const processor_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment