1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TASK_THREAD_POOL_TEST_TASK_FACTORY_H_ 6 #define BASE_TASK_THREAD_POOL_TEST_TASK_FACTORY_H_ 7 8 #include <stddef.h> 9 10 #include <unordered_set> 11 12 #include "base/functional/callback_forward.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/synchronization/condition_variable.h" 15 #include "base/synchronization/lock.h" 16 #include "base/task/task_runner.h" 17 #include "base/task/task_traits.h" 18 #include "base/task/thread_pool/test_utils.h" 19 #include "base/threading/thread_checker_impl.h" 20 21 namespace base { 22 namespace internal { 23 namespace test { 24 25 // A TestTaskFactory posts tasks to a TaskRunner and verifies that they run as 26 // expected. Generates a test failure when: 27 // - The RunsTasksInCurrentSequence() method of the SequencedTaskRunner 28 // (kSequenced or kSingleThread modes) returns false on a thread on which a 29 // Task is run. 30 // - The task runner CurrentDefaultHandles set in the context of the task don't 31 // match what's expected for the tested TaskSourceExecutionMode. 32 // - The TaskSourceExecutionMode of the TaskRunner is kSequenced or 33 // kSingleThread and Tasks don't run in posting order. 34 // - The TaskSourceExecutionMode of the TaskRunner is kSingleThread and Tasks 35 // don't run on the same thread. 36 // - A Task runs more than once. 37 class TestTaskFactory { 38 public: 39 enum class PostNestedTask { 40 YES, 41 NO, 42 }; 43 44 // Constructs a TestTaskFactory that posts tasks to |task_runner|. 45 // |execution_mode| is the TaskSourceExecutionMode of |task_runner|. 46 TestTaskFactory(scoped_refptr<TaskRunner> task_runner, 47 TaskSourceExecutionMode execution_mode); 48 49 TestTaskFactory(const TestTaskFactory&) = delete; 50 TestTaskFactory& operator=(const TestTaskFactory&) = delete; 51 ~TestTaskFactory(); 52 53 // Posts a task. The posted task will: 54 // - Post a new task if |post_nested_task| is YES. The nested task won't run 55 // |after_task_closure|. 56 // - Verify conditions in which the task runs (see potential failures above). 57 // - Run |after_task_closure| if it is not null. 58 bool PostTask(PostNestedTask post_nested_task, 59 OnceClosure after_task_closure); 60 61 // Waits for all tasks posted by PostTask() to start running. It is not 62 // guaranteed that the tasks have completed their execution when this returns. 63 void WaitForAllTasksToRun() const; 64 task_runner()65 const TaskRunner* task_runner() const { return task_runner_.get(); } 66 67 private: 68 void RunTaskCallback(size_t task_index, 69 PostNestedTask post_nested_task, 70 OnceClosure after_task_closure); 71 72 // Synchronizes access to all members. 73 mutable Lock lock_; 74 75 // Condition variable signaled when a task runs. 76 mutable ConditionVariable cv_; 77 78 // Task runner through which this factory posts tasks. 79 const scoped_refptr<TaskRunner> task_runner_; 80 81 // Execution mode of |task_runner_|. 82 const TaskSourceExecutionMode execution_mode_; 83 84 // Number of tasks posted by PostTask(). 85 size_t num_posted_tasks_ = 0; 86 87 // Indexes of tasks that ran. 88 std::unordered_set<size_t> ran_tasks_; 89 90 // Used to verify that all tasks run on the same thread when |execution_mode_| 91 // is SINGLE_THREADED. 92 ThreadCheckerImpl thread_checker_; 93 }; 94 95 } // namespace test 96 } // namespace internal 97 } // namespace base 98 99 #endif // BASE_TASK_THREAD_POOL_TEST_TASK_FACTORY_H_ 100