| // 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. |
| |
| #ifndef BASE_TASK_TASK_SCHEDULER_TEST_TASK_FACTORY_H_ |
| #define BASE_TASK_TASK_SCHEDULER_TEST_TASK_FACTORY_H_ |
| |
| #include <unordered_set> |
| |
| #include "base/callback_forward.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/synchronization/condition_variable.h" |
| #include "base/synchronization/lock.h" |
| #include "base/task/task_scheduler/test_utils.h" |
| #include "base/task/task_traits.h" |
| #include "base/task_runner.h" |
| #include "base/threading/thread_checker_impl.h" |
| #include "starboard/types.h" |
| |
| namespace base { |
| namespace internal { |
| namespace test { |
| |
| // A TestTaskFactory posts tasks to a TaskRunner and verifies that they run as |
| // expected. Generates a test failure when: |
| // - The RunsTasksInCurrentSequence() method of the TaskRunner returns false on |
| // a thread on which a Task is run. |
| // - The TaskRunnerHandles set in the context of the task don't match what's |
| // expected for the tested ExecutionMode. |
| // - The ExecutionMode of the TaskRunner is SEQUENCED or SINGLE_THREADED and |
| // Tasks don't run in posting order. |
| // - The ExecutionMode of the TaskRunner is SINGLE_THREADED and Tasks don't run |
| // on the same thread. |
| // - A Task runs more than once. |
| class TestTaskFactory { |
| public: |
| enum class PostNestedTask { |
| YES, |
| NO, |
| }; |
| |
| // Constructs a TestTaskFactory that posts tasks to |task_runner|. |
| // |execution_mode| is the ExecutionMode of |task_runner|. |
| TestTaskFactory(scoped_refptr<TaskRunner> task_runner, |
| ExecutionMode execution_mode); |
| |
| ~TestTaskFactory(); |
| |
| // Posts a task. The posted task will: |
| // - Post a new task if |post_nested_task| is YES. The nested task won't run |
| // |after_task_closure|. |
| // - Verify conditions in which the task runs (see potential failures above). |
| // - Run |after_task_closure| if it is not null. |
| bool PostTask(PostNestedTask post_nested_task, |
| OnceClosure after_task_closure); |
| |
| // Waits for all tasks posted by PostTask() to start running. It is not |
| // guaranteed that the tasks have completed their execution when this returns. |
| void WaitForAllTasksToRun() const; |
| |
| const TaskRunner* task_runner() const { return task_runner_.get(); } |
| |
| private: |
| void RunTaskCallback(size_t task_index, |
| PostNestedTask post_nested_task, |
| OnceClosure after_task_closure); |
| |
| // Synchronizes access to all members. |
| mutable Lock lock_; |
| |
| // Condition variable signaled when a task runs. |
| mutable ConditionVariable cv_; |
| |
| // Task runner through which this factory posts tasks. |
| const scoped_refptr<TaskRunner> task_runner_; |
| |
| // Execution mode of |task_runner_|. |
| const ExecutionMode execution_mode_; |
| |
| // Number of tasks posted by PostTask(). |
| size_t num_posted_tasks_ = 0; |
| |
| // Indexes of tasks that ran. |
| std::unordered_set<size_t> ran_tasks_; |
| |
| // Used to verify that all tasks run on the same thread when |execution_mode_| |
| // is SINGLE_THREADED. |
| ThreadCheckerImpl thread_checker_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestTaskFactory); |
| }; |
| |
| } // namespace test |
| } // namespace internal |
| } // namespace base |
| |
| #endif // BASE_TASK_TASK_SCHEDULER_TEST_TASK_FACTORY_H_ |