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

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

Issue 1864333002: TaskScheduler: Delegate instead of callbacks for SchedulerWorkerThread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR robliao #5 Created 4 years, 8 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/task_scheduler/scheduler_worker_thread.h" 5 #include "base/task_scheduler/scheduler_worker_thread.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/synchronization/condition_variable.h" 16 #include "base/synchronization/condition_variable.h"
17 #include "base/task_scheduler/scheduler_lock.h" 17 #include "base/task_scheduler/scheduler_lock.h"
18 #include "base/task_scheduler/scheduler_worker_thread_delegate.h"
18 #include "base/task_scheduler/sequence.h" 19 #include "base/task_scheduler/sequence.h"
19 #include "base/task_scheduler/task.h" 20 #include "base/task_scheduler/task.h"
20 #include "base/task_scheduler/task_tracker.h" 21 #include "base/task_scheduler/task_tracker.h"
21 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
22 23
23 namespace base { 24 namespace base {
24 namespace internal { 25 namespace internal {
25 namespace { 26 namespace {
26 27
27 const size_t kNumSequencesPerTest = 150; 28 const size_t kNumSequencesPerTest = 150;
28 29
29 class TaskSchedulerWorkerThreadTest : public testing::Test { 30 class TaskSchedulerWorkerThreadTest : public testing::Test,
31 public SchedulerWorkerThreadDelegate {
30 protected: 32 protected:
31 TaskSchedulerWorkerThreadTest() 33 TaskSchedulerWorkerThreadTest()
32 : num_main_entry_callback_cv_(lock_.CreateConditionVariable()), 34 : num_main_entry_cv_(lock_.CreateConditionVariable()),
33 num_get_work_callback_cv_(lock_.CreateConditionVariable()), 35 num_get_work_cv_(lock_.CreateConditionVariable()),
34 run_sequences_cv_(lock_.CreateConditionVariable()) {} 36 run_sequences_cv_(lock_.CreateConditionVariable()) {}
35 37
36 void SetUp() override { 38 void SetUp() override {
37 worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread( 39 worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread(
38 ThreadPriority::NORMAL, 40 ThreadPriority::NORMAL, this, &task_tracker_);
39 Bind(&TaskSchedulerWorkerThreadTest::MainEntryCallback,
40 Unretained(this)),
41 Bind(&TaskSchedulerWorkerThreadTest::GetWorkCallback, Unretained(this)),
42 Bind(&TaskSchedulerWorkerThreadTest::RanTaskFromSequenceCallback,
43 Unretained(this)),
44 &task_tracker_);
45 ASSERT_TRUE(worker_thread_); 41 ASSERT_TRUE(worker_thread_);
46 WaitForNumMainEntryCallback(1); 42 WaitForMainEntry();
47 } 43 }
48 44
49 void TearDown() override { 45 void TearDown() override {
46 {
47 AutoSchedulerLock auto_lock(lock_);
48 EXPECT_EQ(0U, num_main_exit_);
49 }
50
50 worker_thread_->JoinForTesting(); 51 worker_thread_->JoinForTesting();
51 52
52 AutoSchedulerLock auto_lock(lock_); 53 AutoSchedulerLock auto_lock(lock_);
53 EXPECT_EQ(1U, num_main_entry_callback_); 54 EXPECT_EQ(1U, num_main_entry_);
gab 2016/04/07 16:42:08 Move to test before Join?
fdoray 2016/04/07 17:59:33 I no longer need this in TearDown(). SetUp() verif
55 EXPECT_EQ(1U, num_main_exit_);
54 } 56 }
55 57
56 // Wait until MainEntryCallback() has been called |num_main_entry_callback| 58 // Wait until OnMainEntry() has been called once.
57 // times. 59 void WaitForMainEntry() {
58 void WaitForNumMainEntryCallback(size_t num_main_entry_callback) {
59 AutoSchedulerLock auto_lock(lock_); 60 AutoSchedulerLock auto_lock(lock_);
60 while (num_main_entry_callback_ < num_main_entry_callback) 61 while (num_main_entry_ < 1)
gab 2016/04/07 16:42:08 Make |num_main_entry_| a bool (and thus probably a
fdoray 2016/04/07 17:59:33 Done.
61 num_main_entry_callback_cv_->Wait(); 62 num_main_entry_cv_->Wait();
62 } 63 }
63 64
64 // Wait until GetWorkCallback() has been called |num_get_work_callback| times. 65 // Wait until GetWork() has been called |num_get_work| times.
65 void WaitForNumGetWorkCallback(size_t num_get_work_callback) { 66 void WaitForNumGetWork(size_t num_get_work) {
66 AutoSchedulerLock auto_lock(lock_); 67 AutoSchedulerLock auto_lock(lock_);
67 while (num_get_work_callback_ < num_get_work_callback) 68 while (num_get_work_ < num_get_work)
68 num_get_work_callback_cv_->Wait(); 69 num_get_work_cv_->Wait();
69 } 70 }
70 71
71 // Wait until there is no more Sequences to create and 72 // Wait until there are no more Sequences to create and RanTaskFromSequence()
72 // RanTaskFromSequenceCallback() has been invoked once for each Sequence 73 // has been invoked once for each Sequence returned by GetWork().
73 // returned by GetWorkCallback().
74 void WaitForAllSequencesToRun() { 74 void WaitForAllSequencesToRun() {
75 AutoSchedulerLock auto_lock(lock_); 75 AutoSchedulerLock auto_lock(lock_);
76 76
77 while (num_sequences_to_create_ > 0 || 77 while (num_sequences_to_create_ > 0 ||
78 run_sequences_.size() < created_sequences_.size()) { 78 run_sequences_.size() < created_sequences_.size()) {
79 run_sequences_cv_->Wait(); 79 run_sequences_cv_->Wait();
80 } 80 }
81 81
82 // Verify that RanTaskFromSequenceCallback() has been invoked with the 82 // Verify that RanTaskFromSequence() has been invoked with the same
83 // same Sequences that were returned by GetWorkCallback(). 83 // Sequences that were returned by GetWork().
84 EXPECT_EQ(created_sequences_, run_sequences_); 84 EXPECT_EQ(created_sequences_, run_sequences_);
85 85
86 // Verify that RunTaskCallback() has been invoked once for each Sequence 86 // Verify that RunTaskCallback() has been invoked once for each Sequence
87 // returned by GetWorkCallback(). 87 // returned by GetWork().
88 EXPECT_EQ(created_sequences_.size(), num_run_tasks_); 88 EXPECT_EQ(created_sequences_.size(), num_run_tasks_);
89 } 89 }
90 90
91 void SetNumSequencesToCreate(size_t num_sequences_to_create) { 91 void SetNumSequencesToCreate(size_t num_sequences_to_create) {
92 AutoSchedulerLock auto_lock(lock_); 92 AutoSchedulerLock auto_lock(lock_);
93 EXPECT_EQ(0U, num_sequences_to_create_); 93 EXPECT_EQ(0U, num_sequences_to_create_);
94 num_sequences_to_create_ = num_sequences_to_create; 94 num_sequences_to_create_ = num_sequences_to_create;
95 } 95 }
96 96
97 size_t NumGetWorkCallback() const { 97 size_t NumGetWork() const {
98 AutoSchedulerLock auto_lock(lock_); 98 AutoSchedulerLock auto_lock(lock_);
99 return num_get_work_callback_; 99 return num_get_work_;
100 } 100 }
101 101
102 std::unique_ptr<SchedulerWorkerThread> worker_thread_; 102 std::unique_ptr<SchedulerWorkerThread> worker_thread_;
103 103
104 private: 104 private:
105 void MainEntryCallback() { 105 // SchedulerWorkerThreadDelegate:
106 void OnMainEntry() override {
106 AutoSchedulerLock auto_lock(lock_); 107 AutoSchedulerLock auto_lock(lock_);
107 ++num_main_entry_callback_; 108 ++num_main_entry_;
108 num_main_entry_callback_cv_->Signal(); 109 num_main_entry_cv_->Signal();
109 } 110 }
110 111
111 // Returns a Sequence that contains 1 Task if |num_sequences_to_create_| is 112 void OnMainExit() override {
112 // greater than 0. 113 AutoSchedulerLock auto_lock(lock_);
113 scoped_refptr<Sequence> GetWorkCallback( 114 ++num_main_exit_;
114 SchedulerWorkerThread* worker_thread) { 115 }
115 EXPECT_EQ(worker_thread_.get(), worker_thread);
116 116
117 scoped_refptr<Sequence> GetWork() override {
117 { 118 {
118 AutoSchedulerLock auto_lock(lock_); 119 AutoSchedulerLock auto_lock(lock_);
119 120
120 // Increment the number of times that this callback has been invoked. 121 // Increment the number of times that this method has been called.
121 ++num_get_work_callback_; 122 ++num_get_work_;
122 num_get_work_callback_cv_->Signal(); 123 num_get_work_cv_->Signal();
123 124
124 // Check if a Sequence should be returned. 125 // Check if a Sequence should be returned.
125 if (num_sequences_to_create_ == 0) 126 if (num_sequences_to_create_ == 0)
126 return nullptr; 127 return nullptr;
127 --num_sequences_to_create_; 128 --num_sequences_to_create_;
128 } 129 }
129 130
130 // Create a Sequence that contains 1 Task. 131 // Create a Sequence that contains 1 Task.
131 scoped_refptr<Sequence> sequence(new Sequence); 132 scoped_refptr<Sequence> sequence(new Sequence);
132 task_tracker_.PostTask( 133 task_tracker_.PostTask(
133 Bind(IgnoreResult(&Sequence::PushTask), Unretained(sequence.get())), 134 Bind(IgnoreResult(&Sequence::PushTask), Unretained(sequence.get())),
134 WrapUnique(new Task( 135 WrapUnique(new Task(
135 FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback, 136 FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback,
136 Unretained(this)), 137 Unretained(this)),
137 TaskTraits()))); 138 TaskTraits())));
138 139
139 { 140 {
140 // Add the Sequence to the vector of created Sequences. 141 // Add the Sequence to the vector of created Sequences.
141 AutoSchedulerLock auto_lock(lock_); 142 AutoSchedulerLock auto_lock(lock_);
142 created_sequences_.push_back(sequence); 143 created_sequences_.push_back(sequence);
143 } 144 }
144 145
145 return sequence; 146 return sequence;
146 } 147 }
147 148
148 void RanTaskFromSequenceCallback(const SchedulerWorkerThread* worker_thread, 149 // Called after the SchedulerWorkerThread has tried to run a Task from
149 scoped_refptr<Sequence> sequence) { 150 // |sequence| (a TaskTracker might have prevented the Task from running).
gab 2016/04/07 16:42:08 No need to re-state comment from override.
fdoray 2016/04/07 17:59:33 Done.
150 EXPECT_EQ(worker_thread_.get(), worker_thread); 151 void RanTaskFromSequence(scoped_refptr<Sequence> sequence) override {
151
152 AutoSchedulerLock auto_lock(lock_); 152 AutoSchedulerLock auto_lock(lock_);
153 run_sequences_.push_back(std::move(sequence)); 153 run_sequences_.push_back(std::move(sequence));
154 run_sequences_cv_->Signal(); 154 run_sequences_cv_->Signal();
155 } 155 }
156 156
157 void RunTaskCallback() { 157 void RunTaskCallback() {
158 AutoSchedulerLock auto_lock(lock_); 158 AutoSchedulerLock auto_lock(lock_);
159 ++num_run_tasks_; 159 ++num_run_tasks_;
160 } 160 }
161 161
162 TaskTracker task_tracker_; 162 TaskTracker task_tracker_;
163 163
164 // Synchronizes access to all members below. 164 // Synchronizes access to all members below.
165 mutable SchedulerLock lock_; 165 mutable SchedulerLock lock_;
166 166
167 // Number of times that MainEntryCallback() has been called. 167 // Number of times that OnMainEntry() has been called.
168 size_t num_main_entry_callback_ = 0; 168 size_t num_main_entry_ = 0;
169 169
170 // Condition variable signaled when |num_main_entry_callback_| is incremented. 170 // Condition variable signaled when |num_main_entry_| is incremented.
171 std::unique_ptr<ConditionVariable> num_main_entry_callback_cv_; 171 std::unique_ptr<ConditionVariable> num_main_entry_cv_;
172 172
173 // Number of Sequences that should be created by GetWorkCallback(). When this 173 // Number of times that OnMainExit() has been called.
174 // is 0, GetWorkCallback() returns nullptr. 174 size_t num_main_exit_ = 0;
175
176 // Number of Sequences that should be created by GetWork(). When this
177 // is 0, GetWork() returns nullptr.
175 size_t num_sequences_to_create_ = 0; 178 size_t num_sequences_to_create_ = 0;
176 179
177 // Number of times that GetWorkCallback() has been called. 180 // Number of times that GetWork() has been called.
178 size_t num_get_work_callback_ = 0; 181 size_t num_get_work_ = 0;
179 182
180 // Condition variable signaled when |num_get_work_callback_| is incremented. 183 // Condition variable signaled when |num_get_work_| is incremented.
181 std::unique_ptr<ConditionVariable> num_get_work_callback_cv_; 184 std::unique_ptr<ConditionVariable> num_get_work_cv_;
182 185
183 // Sequences created by GetWorkCallback(). 186 // Sequences created by GetWork().
184 std::vector<scoped_refptr<Sequence>> created_sequences_; 187 std::vector<scoped_refptr<Sequence>> created_sequences_;
185 188
186 // Sequences passed to RanTaskFromSequenceCallback(). 189 // Sequences passed to RanTaskFromSequence().
187 std::vector<scoped_refptr<Sequence>> run_sequences_; 190 std::vector<scoped_refptr<Sequence>> run_sequences_;
188 191
189 // Condition variable signaled when a Sequence is added to |run_sequences_|. 192 // Condition variable signaled when a Sequence is added to |run_sequences_|.
190 std::unique_ptr<ConditionVariable> run_sequences_cv_; 193 std::unique_ptr<ConditionVariable> run_sequences_cv_;
191 194
192 // Number of times that RunTaskCallback() has been called. 195 // Number of times that RunTaskCallback() has been called.
193 size_t num_run_tasks_ = 0; 196 size_t num_run_tasks_ = 0;
194 197
195 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadTest); 198 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadTest);
196 }; 199 };
197 200
198 // Verify that when GetWorkCallback() continuously returns Sequences, all Tasks 201 // Verify that when GetWork() continuously returns Sequences, all Tasks in these
199 // in these Sequences run successfully. The SchedulerWorkerThread is woken up 202 // Sequences run successfully. The SchedulerWorkerThread is woken up once.
200 // once.
201 TEST_F(TaskSchedulerWorkerThreadTest, ContinousWork) { 203 TEST_F(TaskSchedulerWorkerThreadTest, ContinousWork) {
202 // Set GetWorkCallback() to return |kNumSequencesPerTest| Sequences before 204 // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to
203 // starting to return nullptr. 205 // return nullptr.
204 SetNumSequencesToCreate(kNumSequencesPerTest); 206 SetNumSequencesToCreate(kNumSequencesPerTest);
205 207
206 // Wake up |worker_thread_| and wait until it has run all the Tasks returned 208 // Wake up |worker_thread_| and wait until it has run all the Tasks returned
207 // by GetWorkCallback(). 209 // by GetWork().
208 worker_thread_->WakeUp(); 210 worker_thread_->WakeUp();
209 WaitForAllSequencesToRun(); 211 WaitForAllSequencesToRun();
210 212
211 // Expect |kNumSequencesPerTest| calls to GetWorkCallback() in which it 213 // Expect |kNumSequencesPerTest| calls to GetWork() in which it returned a
212 // returned a Sequence and 1 call in which it returned nullptr. 214 // Sequence and 1 call in which it returned nullptr.
213 const size_t expected_num_get_work_callback = kNumSequencesPerTest + 1; 215 const size_t expected_num_get_work = kNumSequencesPerTest + 1;
214 WaitForNumGetWorkCallback(expected_num_get_work_callback); 216 WaitForNumGetWork(expected_num_get_work);
215 EXPECT_EQ(expected_num_get_work_callback, NumGetWorkCallback()); 217 EXPECT_EQ(expected_num_get_work, NumGetWork());
216 } 218 }
217 219
218 // Verify that when GetWorkCallback() alternates between returning a Sequence 220 // Verify that when GetWork() alternates between returning a Sequence and
219 // and returning nullptr, all Tasks in the returned Sequences run successfully. 221 // returning nullptr, all Tasks in the returned Sequences run successfully. The
220 // The SchedulerWorkerThread is woken up once for each Sequence. 222 // SchedulerWorkerThread is woken up once for each Sequence.
221 TEST_F(TaskSchedulerWorkerThreadTest, IntermittentWork) { 223 TEST_F(TaskSchedulerWorkerThreadTest, IntermittentWork) {
222 for (size_t i = 0; i < kNumSequencesPerTest; ++i) { 224 for (size_t i = 0; i < kNumSequencesPerTest; ++i) {
223 // Set GetWorkCallback() to return 1 Sequence before starting to return 225 // Set GetWork() to return 1 Sequence before starting to return
224 // nullptr. 226 // nullptr.
225 SetNumSequencesToCreate(1); 227 SetNumSequencesToCreate(1);
226 228
227 // Wake up |worker_thread_| and wait until it has run all the Tasks returned 229 // Wake up |worker_thread_| and wait until it has run all the Tasks returned
gab 2016/04/07 16:42:08 s/all the Tasks/the Task/ ?
fdoray 2016/04/07 17:59:33 Done.
228 // by GetWorkCallback(). 230 // by GetWork().
229 worker_thread_->WakeUp(); 231 worker_thread_->WakeUp();
230 WaitForAllSequencesToRun(); 232 WaitForAllSequencesToRun();
231 233
232 // Expect |i| calls to GetWorkCallback() in which it returned a Sequence and 234 // Expect |i| calls to GetWork() in which it returned a Sequence and
233 // |i| calls in which it returned nullptr. 235 // |i| calls in which it returned nullptr.
234 const size_t expected_num_get_work_callback = 2 * (i + 1); 236 const size_t expected_num_get_work = 2 * (i + 1);
235 WaitForNumGetWorkCallback(expected_num_get_work_callback); 237 WaitForNumGetWork(expected_num_get_work);
236 EXPECT_EQ(expected_num_get_work_callback, NumGetWorkCallback()); 238 EXPECT_EQ(expected_num_get_work, NumGetWork());
237 } 239 }
238 } 240 }
239 241
240 } // namespace 242 } // namespace
241 } // namespace internal 243 } // namespace internal
242 } // namespace base 244 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698