| // 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_SCHEDULER_TEST_TASK_FACTORY_H_ | 
 | #define BASE_TASK_SCHEDULER_TEST_TASK_FACTORY_H_ | 
 |  | 
 | #include <stddef.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_runner.h" | 
 | #include "base/task_scheduler/task_traits.h" | 
 | #include "base/task_scheduler/test_utils.h" | 
 | #include "base/threading/thread_checker_impl.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_SCHEDULER_TEST_TASK_FACTORY_H_ |