• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/task_scheduler/test_task_factory.h"
6 
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/sequenced_task_runner_handle.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace base {
18 namespace internal {
19 namespace test {
20 
TestTaskFactory(scoped_refptr<TaskRunner> task_runner,ExecutionMode execution_mode)21 TestTaskFactory::TestTaskFactory(scoped_refptr<TaskRunner> task_runner,
22                                  ExecutionMode execution_mode)
23     : cv_(&lock_),
24       task_runner_(std::move(task_runner)),
25       execution_mode_(execution_mode) {
26   // Detach |thread_checker_| from the current thread. It will be attached to
27   // the first thread that calls ThreadCheckerImpl::CalledOnValidThread().
28   thread_checker_.DetachFromThread();
29 }
30 
~TestTaskFactory()31 TestTaskFactory::~TestTaskFactory() {
32   WaitForAllTasksToRun();
33 }
34 
PostTask(PostNestedTask post_nested_task,OnceClosure after_task_closure)35 bool TestTaskFactory::PostTask(PostNestedTask post_nested_task,
36                                OnceClosure after_task_closure) {
37   AutoLock auto_lock(lock_);
38   return task_runner_->PostTask(
39       FROM_HERE, BindOnce(&TestTaskFactory::RunTaskCallback, Unretained(this),
40                           num_posted_tasks_++, post_nested_task,
41                           std::move(after_task_closure)));
42 }
43 
WaitForAllTasksToRun() const44 void TestTaskFactory::WaitForAllTasksToRun() const {
45   AutoLock auto_lock(lock_);
46   while (ran_tasks_.size() < num_posted_tasks_)
47     cv_.Wait();
48 }
49 
RunTaskCallback(size_t task_index,PostNestedTask post_nested_task,OnceClosure after_task_closure)50 void TestTaskFactory::RunTaskCallback(size_t task_index,
51                                       PostNestedTask post_nested_task,
52                                       OnceClosure after_task_closure) {
53   if (post_nested_task == PostNestedTask::YES)
54     PostTask(PostNestedTask::NO, Closure());
55 
56   EXPECT_TRUE(task_runner_->RunsTasksInCurrentSequence());
57 
58   // Verify TaskRunnerHandles are set as expected in the task's scope.
59   switch (execution_mode_) {
60     case ExecutionMode::PARALLEL:
61       EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
62       EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
63       break;
64     case ExecutionMode::SEQUENCED:
65       EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
66       EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
67       EXPECT_EQ(task_runner_, SequencedTaskRunnerHandle::Get());
68       break;
69     case ExecutionMode::SINGLE_THREADED:
70       // SequencedTaskRunnerHandle inherits from ThreadTaskRunnerHandle so
71       // both are expected to be "set" in the SINGLE_THREADED case.
72       EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
73       EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
74       EXPECT_EQ(task_runner_, ThreadTaskRunnerHandle::Get());
75       EXPECT_EQ(task_runner_, SequencedTaskRunnerHandle::Get());
76       break;
77   }
78 
79   {
80     AutoLock auto_lock(lock_);
81 
82     DCHECK_LE(task_index, num_posted_tasks_);
83 
84     if ((execution_mode_ == ExecutionMode::SINGLE_THREADED ||
85          execution_mode_ == ExecutionMode::SEQUENCED) &&
86         task_index != ran_tasks_.size()) {
87       ADD_FAILURE() << "A task didn't run in the expected order.";
88     }
89 
90     if (execution_mode_ == ExecutionMode::SINGLE_THREADED)
91       EXPECT_TRUE(thread_checker_.CalledOnValidThread());
92 
93     if (ran_tasks_.find(task_index) != ran_tasks_.end())
94       ADD_FAILURE() << "A task ran more than once.";
95     ran_tasks_.insert(task_index);
96 
97     cv_.Signal();
98   }
99 
100   if (!after_task_closure.is_null())
101     std::move(after_task_closure).Run();
102 }
103 
104 }  // namespace test
105 }  // namespace internal
106 }  // namespace base
107