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