Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: base/task_scheduler/worker_thread_unittest.cc

Issue 1704113002: TaskScheduler [6] SchedulerWorkerThread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@s_4_shutdown
Patch Set: CR from robliao Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/worker_thread.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback_forward.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/synchronization/condition_variable.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/task_scheduler/priority_queue.h"
15 #include "base/task_scheduler/scheduler_lock.h"
16 #include "base/task_scheduler/task_tracker.h"
17 #include "base/task_scheduler/utils.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace base {
21 namespace internal {
22
23 class TaskSchedulerWorkerThreadTest : public testing::Test {
24 protected:
25 TaskSchedulerWorkerThreadTest()
26 : shared_priority_queue_(Bind(&DoNothing)),
27 run_task_cv_(lock_.CreateConditionVariable()),
28 becomes_idle_callback_cv_(lock_.CreateConditionVariable()),
29 num_becomes_idle_callback_invocations_(0),
30 last_posted_task_index_(0),
31 last_run_task_index_(0),
32 ran_task_that_should_not_run_(false),
33 ran_tasks_in_wrong_order_(true) {
34 worker_thread_ = WorkerThread::CreateWorkerThread(
35 ThreadPriority::NORMAL,
36 &shared_priority_queue_,
37 Bind(&TaskSchedulerWorkerThreadTest::ReinsertSequenceCallback,
38 Unretained(this)),
39 Bind(&TaskSchedulerWorkerThreadTest::BecomesIdleCallback,
40 Unretained(this)),
41 &task_tracker_);
42 }
43
44 Closure GetTaskThatShouldRunClosure() {
45 ++last_posted_task_index_;
46 return Bind(&TaskSchedulerWorkerThreadTest::RunTaskThatShouldRun,
47 Unretained(this), last_posted_task_index_);
48 }
49
50 Closure GetTaskThatShouldNotRunClosure() {
51 return Bind(&TaskSchedulerWorkerThreadTest::RunTaskThatShouldNotRun,
52 Unretained(this));
53 }
54
55 void WaitUntilLastPostedTaskHasRun() {
gab 2016/03/21 19:11:55 s/HasRun/Ran/ (here and below)
fdoray 2016/03/24 19:21:11 Done.
56 AutoSchedulerLock auto_lock(lock_);
57 while (last_posted_task_index_ != last_run_task_index_)
58 run_task_cv_->Wait();
59 }
60
61 void ExpectLastPostedTaskHasRun() {
62 AutoSchedulerLock auto_lock(lock_);
63 EXPECT_EQ(last_posted_task_index_, last_run_task_index_);
64 }
65
66 void WaitUntilNumBecomesIdleCallbackInvocations(
67 size_t expected_num_becomes_idle_callback_invocations) {
68 AutoSchedulerLock auto_lock(lock_);
69 while (num_becomes_idle_callback_invocations_ !=
70 expected_num_becomes_idle_callback_invocations) {
71 EXPECT_LT(num_becomes_idle_callback_invocations_,
72 expected_num_becomes_idle_callback_invocations);
73 becomes_idle_callback_cv_->Wait();
74 }
75 }
76
77 bool ran_task_that_should_not_run() const {
78 return ran_task_that_should_not_run_;
79 }
80
81 protected:
82 PriorityQueue shared_priority_queue_;
83 TaskTracker task_tracker_;
84 scoped_ptr<WorkerThread> worker_thread_;
85
86 private:
87 void ReinsertSequenceCallback(scoped_refptr<Sequence> sequence,
88 const WorkerThread* worker_thread) {
89 const SequenceSortKey sort_key = sequence->GetSortKey();
90 shared_priority_queue_.BeginTransaction()->Push(make_scoped_ptr(
91 new PriorityQueue::SequenceAndSortKey(std::move(sequence), sort_key)));
92 }
93
94 void BecomesIdleCallback(WorkerThread* worker_thread) {
95 AutoSchedulerLock auto_lock(lock_);
96 ++num_becomes_idle_callback_invocations_;
97 becomes_idle_callback_cv_->Signal();
98 }
99
100 void RunTaskThatShouldRun(size_t index) {
101 AutoSchedulerLock auto_lock(lock_);
102
103 if (index != last_run_task_index_ + 1)
104 ran_tasks_in_wrong_order_ = true;
gab 2016/03/21 19:11:55 ADD_FAILURE here too instead of maintaining extra
fdoray 2016/03/24 19:21:10 Done.
105
106 last_run_task_index_ = index;
107 run_task_cv_->Signal();
108 }
109
110 void RunTaskThatShouldNotRun() { ran_task_that_should_not_run_ = true; }
gab 2016/03/21 19:11:55 Instead of having extra state here and checking fo
fdoray 2016/03/24 19:21:11 Done.
111
112 // Lock protecting |run_task_cv_|.
gab 2016/03/21 19:11:55 Hmm, it does more than that it seems?
fdoray 2016/03/24 19:21:11 Done.
113 SchedulerLock lock_;
114
115 // Condition variable signaled each time a task completes its execution.
116 scoped_ptr<ConditionVariable> run_task_cv_;
117
118 // Condition variable signaled when BecomesIdleCallback() is invoked.
119 scoped_ptr<ConditionVariable> becomes_idle_callback_cv_;
120
121 // Number of times that BecomesIdleCallback() has been called.
122 size_t num_becomes_idle_callback_invocations_;
123
124 // Index of the last posted task.
125 size_t last_posted_task_index_;
126
127 // Index of the last run task.
128 size_t last_run_task_index_;
129
130 // True if a task that shouldn't run has run.
131 bool ran_task_that_should_not_run_;
132
133 // True if tasks were run in the wrong order.
134 bool ran_tasks_in_wrong_order_;
135
136 };
137
138 TEST_F(TaskSchedulerWorkerThreadTest, PostOneSingleThreadedTask) {
139 ASSERT_NE(nullptr, worker_thread_.get());
gab 2016/03/21 19:11:55 ASSERT_TRUE(worker_thread_);
fdoray 2016/03/24 19:21:11 Done.
140 WaitUntilNumBecomesIdleCallbackInvocations(1);
gab 2016/03/21 19:11:55 Move these two lines to constructor instead of at
fdoray 2016/03/24 19:21:11 Done.
141
142 worker_thread_->CreateTaskRunnerWithTraits(TaskTraits())
143 ->PostTask(FROM_HERE, GetTaskThatShouldRunClosure());
144
145 WaitUntilNumBecomesIdleCallbackInvocations(2);
gab 2016/03/21 19:11:55 Since WaitUntilNumBecomesIdleCallbackInvocations(1
fdoray 2016/03/24 19:21:10 With WaitForNextBecomesIdleCallbackInvocation(), i
146 ExpectLastPostedTaskHasRun();
147 worker_thread_->JoinForTesting();
gab 2016/03/21 19:11:55 Since the thread is created by the fixture I think
gab 2016/03/21 19:11:55 In fact I think TearDown() should do both: Expect
fdoray 2016/03/24 19:21:11 Done.
fdoray 2016/03/24 19:21:11 ExpectLastPostedTaskHasRun() is not done in the de
148 }
149
150 TEST_F(TaskSchedulerWorkerThreadTest,
151 PostMultipleSingleThreadedTasksNoWaitBetweenPosts) {
152 ASSERT_NE(nullptr, worker_thread_.get());
153 WaitUntilNumBecomesIdleCallbackInvocations(1);
154
155 auto task_runner = worker_thread_->CreateTaskRunnerWithTraits(TaskTraits());
156
157 for (size_t i = 0; i < 100; ++i)
158 task_runner->PostTask(FROM_HERE, GetTaskThatShouldRunClosure());
159
160 WaitUntilLastPostedTaskHasRun();
161 worker_thread_->JoinForTesting();
162 }
163
164 TEST_F(TaskSchedulerWorkerThreadTest,
165 PostMultipleSingleThreadedTasksWaitBetweenPosts) {
166 ASSERT_NE(nullptr, worker_thread_.get());
167 WaitUntilNumBecomesIdleCallbackInvocations(1);
168
169 auto task_runner = worker_thread_->CreateTaskRunnerWithTraits(TaskTraits());
170
171 for (size_t i = 0; i < 100; ++i) {
172 task_runner->PostTask(FROM_HERE, GetTaskThatShouldRunClosure());
173 WaitUntilLastPostedTaskHasRun();
174 WaitUntilNumBecomesIdleCallbackInvocations(2 + i);
175 }
176
177 worker_thread_->JoinForTesting();
178 }
179
180 TEST_F(TaskSchedulerWorkerThreadTest,
181 PostMultipleTasksTwoSingleThreadedTaskRunners) {
182 ASSERT_NE(nullptr, worker_thread_.get());
183 WaitUntilNumBecomesIdleCallbackInvocations(1);
184
185 auto task_runner_a = worker_thread_->CreateTaskRunnerWithTraits(TaskTraits());
186 auto task_runner_b = worker_thread_->CreateTaskRunnerWithTraits(TaskTraits());
187
188 for (size_t i = 0; i < 100; ++i) {
189 task_runner_a->PostTask(FROM_HERE, GetTaskThatShouldRunClosure());
190 task_runner_b->PostTask(FROM_HERE, GetTaskThatShouldRunClosure());
191 }
192
193 WaitUntilLastPostedTaskHasRun();
194 worker_thread_->JoinForTesting();
195 }
196
197 TEST_F(TaskSchedulerWorkerThreadTest, PostOneTaskInSharedPriorityQueue) {
198 ASSERT_NE(nullptr, worker_thread_.get());
199 WaitUntilNumBecomesIdleCallbackInvocations(1);
200
201 PostTaskHelper(make_scoped_ptr(new Task(
202 FROM_HERE, GetTaskThatShouldRunClosure(), TaskTraits())),
203 new Sequence, &shared_priority_queue_, &task_tracker_);
gab 2016/03/21 19:11:55 make_scoped_refptr(new Sequence) here and below (
fdoray 2016/03/24 19:21:11 Done.
204 EXPECT_TRUE(worker_thread_->WakeUp());
205
206 WaitUntilNumBecomesIdleCallbackInvocations(2);
207 ExpectLastPostedTaskHasRun();
208 worker_thread_->JoinForTesting();
209 }
210
211 TEST_F(TaskSchedulerWorkerThreadTest, PostSharedAndSingleThreadedTasks) {
212 ASSERT_NE(nullptr, worker_thread_.get());
213 WaitUntilNumBecomesIdleCallbackInvocations(1);
214
215 // Post a task in the shared priority queue.
216 PostTaskHelper(make_scoped_ptr(new Task(
217 FROM_HERE, GetTaskThatShouldRunClosure(), TaskTraits())),
218 new Sequence, &shared_priority_queue_, &task_tracker_);
219
220 // Post a task in the single-threaded priority queue. The TaskRunner will wake
221 // up the WorkerThread.
222 worker_thread_->CreateTaskRunnerWithTraits(TaskTraits())
223 ->PostTask(FROM_HERE, GetTaskThatShouldRunClosure());
224
225 WaitUntilNumBecomesIdleCallbackInvocations(2);
226 ExpectLastPostedTaskHasRun();
227 worker_thread_->JoinForTesting();
228 }
229
230 TEST_F(TaskSchedulerWorkerThreadTest, WakeUpIdleThread) {
231 ASSERT_NE(nullptr, worker_thread_.get());
232 WaitUntilNumBecomesIdleCallbackInvocations(1);
233
234 EXPECT_TRUE(worker_thread_->WakeUp());
235 WaitUntilNumBecomesIdleCallbackInvocations(2);
236
237 worker_thread_->JoinForTesting();
238 }
239
240 TEST_F(TaskSchedulerWorkerThreadTest, WakeUpBusyThread) {
241 ASSERT_NE(nullptr, worker_thread_.get());
242 WaitUntilNumBecomesIdleCallbackInvocations(1);
243
244 // Post a task.
245 WaitableEvent event(false, false);
246 worker_thread_->CreateTaskRunnerWithTraits(TaskTraits())
247 ->PostTask(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)));
248
249 // Because the thread is busy, WakeUp() should return false.
250 EXPECT_FALSE(worker_thread_->WakeUp());
251
252 event.Signal();
253 WaitUntilNumBecomesIdleCallbackInvocations(2);
254 worker_thread_->JoinForTesting();
255 }
gab 2016/03/21 19:11:55 A good chunk of ThreadMain is about handling race
fdoray 2016/03/24 19:21:11 Done.
256
257 } // namespace internal
258 } // namespace base
OLDNEW
« base/task_scheduler/worker_thread.cc ('K') | « base/task_scheduler/worker_thread.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698