OLD | NEW |
---|---|
(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/scheduler_worker_thread.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include <vector> | |
10 | |
11 #include "base/bind.h" | |
12 #include "base/bind_helpers.h" | |
13 #include "base/macros.h" | |
14 #include "base/memory/scoped_ptr.h" | |
15 #include "base/synchronization/condition_variable.h" | |
16 #include "base/task_scheduler/scheduler_lock.h" | |
17 #include "base/task_scheduler/sequence.h" | |
18 #include "base/task_scheduler/task.h" | |
19 #include "base/task_scheduler/task_tracker.h" | |
20 #include "testing/gtest/include/gtest/gtest.h" | |
21 | |
22 namespace base { | |
23 namespace internal { | |
24 namespace { | |
25 | |
26 const size_t kNumSequencesPerTest = 150; | |
27 | |
28 class TaskSchedulerWorkerThreadTest : public testing::Test { | |
29 protected: | |
30 TaskSchedulerWorkerThreadTest() | |
31 : num_main_entry_callback_cv_(lock_.CreateConditionVariable()), | |
32 num_get_work_callback_cv_(lock_.CreateConditionVariable()), | |
33 run_sequences_cv_(lock_.CreateConditionVariable()) {} | |
34 | |
35 void SetUp() override { | |
36 worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread( | |
37 ThreadPriority::NORMAL, | |
38 Bind(&TaskSchedulerWorkerThreadTest::MainEntryCallback, | |
39 Unretained(this)), | |
40 Bind(&TaskSchedulerWorkerThreadTest::GetWorkCallback, Unretained(this)), | |
41 Bind(&TaskSchedulerWorkerThreadTest::RanTaskFromSequenceCallback, | |
42 Unretained(this)), | |
43 &task_tracker_); | |
44 ASSERT_TRUE(worker_thread_); | |
45 WaitForNumMainEntryCallback(1); | |
46 } | |
47 | |
48 void TearDown() override { | |
49 worker_thread_->JoinForTesting(); | |
50 | |
51 AutoSchedulerLock auto_lock(lock_); | |
52 EXPECT_EQ(1U, num_main_entry_callback_); | |
53 } | |
gab
2016/04/05 23:35:20
Would be nice to test that the tests observed ever
fdoray
2016/04/07 13:56:47
Added "EXPECT_LE(num_run_tasks_, created_sequences
| |
54 | |
55 // Wait until MainEntryCallback() has been called |num_main_entry_callback| | |
56 // times. | |
57 void WaitForNumMainEntryCallback(size_t num_main_entry_callback) { | |
58 AutoSchedulerLock auto_lock(lock_); | |
59 while (num_main_entry_callback_ < num_main_entry_callback) | |
60 num_main_entry_callback_cv_->Wait(); | |
61 } | |
62 | |
63 // Wait until GetWorkCallback() has been called |num_get_work_callback| times. | |
64 void WaitForNumGetWorkCallback(size_t num_get_work_callback) { | |
65 AutoSchedulerLock auto_lock(lock_); | |
66 while (num_get_work_callback_ < num_get_work_callback) | |
67 num_get_work_callback_cv_->Wait(); | |
68 } | |
69 | |
70 // Wait until there is no more Sequences to create and | |
71 // RanTaskFromSequenceCallback() has been invoked once for each Sequence | |
72 // returned by GetWorkCallback(). | |
73 void WaitForAllSequencesToRun() { | |
74 AutoSchedulerLock auto_lock(lock_); | |
75 | |
76 while (num_sequences_to_create_ > 0 || | |
77 run_sequences_.size() < created_sequences_.size()) { | |
78 run_sequences_cv_->Wait(); | |
79 } | |
80 | |
81 // Verify that RanTaskFromSequenceCallback() has been invoked with the | |
82 // same Sequences that were returned by GetWorkCallback(). | |
83 EXPECT_EQ(created_sequences_, run_sequences_); | |
84 | |
85 // Verify that RunTaskCallback() has been invoked once for each Sequence | |
86 // returned by GetWorkCallback(). | |
87 EXPECT_EQ(created_sequences_.size(), num_run_tasks_); | |
88 } | |
89 | |
90 void SetNumSequencesToCreate(size_t num_sequences_to_create) { | |
91 AutoSchedulerLock auto_lock(lock_); | |
92 EXPECT_EQ(0U, num_sequences_to_create_); | |
93 num_sequences_to_create_ = num_sequences_to_create; | |
94 } | |
95 | |
96 size_t NumGetWorkCallback() const { | |
97 AutoSchedulerLock auto_lock(lock_); | |
98 return num_get_work_callback_; | |
99 } | |
100 | |
101 scoped_ptr<SchedulerWorkerThread> worker_thread_; | |
102 | |
103 private: | |
104 void MainEntryCallback() { | |
105 AutoSchedulerLock auto_lock(lock_); | |
106 ++num_main_entry_callback_; | |
107 num_main_entry_callback_cv_->Signal(); | |
108 } | |
109 | |
110 // Returns a Sequence that contains 1 Task if |num_sequences_to_create_| is | |
111 // greater than 0. | |
112 scoped_refptr<Sequence> GetWorkCallback( | |
113 SchedulerWorkerThread* worker_thread) { | |
114 EXPECT_EQ(worker_thread_.get(), worker_thread); | |
115 | |
116 { | |
117 AutoSchedulerLock auto_lock(lock_); | |
118 | |
119 // Increment the number of times that this callback has been invoked. | |
120 ++num_get_work_callback_; | |
121 num_get_work_callback_cv_->Signal(); | |
122 | |
123 // Check if a Sequence should be returned. | |
124 if (num_sequences_to_create_ == 0) | |
125 return nullptr; | |
126 --num_sequences_to_create_; | |
127 } | |
128 | |
129 // Create a Sequence that contains 1 Task. | |
130 scoped_refptr<Sequence> sequence(new Sequence); | |
131 task_tracker_.PostTask( | |
132 Bind(IgnoreResult(&Sequence::PushTask), Unretained(sequence.get())), | |
133 make_scoped_ptr(new Task( | |
134 FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback, | |
135 Unretained(this)), | |
136 TaskTraits()))); | |
137 | |
138 { | |
139 // Add the Sequence to the vector of created Sequences. | |
140 AutoSchedulerLock auto_lock(lock_); | |
141 created_sequences_.push_back(sequence); | |
142 } | |
143 | |
144 return sequence; | |
145 } | |
146 | |
147 void RanTaskFromSequenceCallback(const SchedulerWorkerThread* worker_thread, | |
148 scoped_refptr<Sequence> sequence) { | |
149 EXPECT_EQ(worker_thread_.get(), worker_thread); | |
150 | |
151 AutoSchedulerLock auto_lock(lock_); | |
152 run_sequences_.push_back(std::move(sequence)); | |
153 run_sequences_cv_->Signal(); | |
154 } | |
155 | |
156 void RunTaskCallback() { | |
157 AutoSchedulerLock auto_lock(lock_); | |
158 ++num_run_tasks_; | |
159 } | |
160 | |
161 TaskTracker task_tracker_; | |
162 | |
163 // Synchronizes access to all members below. | |
164 mutable SchedulerLock lock_; | |
165 | |
166 // Number of times that MainEntryCallback() has been called. | |
167 size_t num_main_entry_callback_ = 0; | |
168 | |
169 // Condition variable signaled when |num_main_entry_callback_| is incremented. | |
170 scoped_ptr<ConditionVariable> num_main_entry_callback_cv_; | |
171 | |
172 // Number of Sequences that should be created by GetWorkCallback(). When this | |
173 // is 0, GetWorkCallback() returns nullptr. | |
174 size_t num_sequences_to_create_ = 0; | |
175 | |
176 // Number of times that GetWorkCallback() has been called. | |
177 size_t num_get_work_callback_ = 0; | |
178 | |
179 // Condition variable signaled when |num_get_work_callback_| is incremented. | |
180 scoped_ptr<ConditionVariable> num_get_work_callback_cv_; | |
181 | |
182 // Sequences created by GetWorkCallback(). | |
183 std::vector<scoped_refptr<Sequence>> created_sequences_; | |
184 | |
185 // Sequences passed to RanTaskFromSequenceCallback(). | |
186 std::vector<scoped_refptr<Sequence>> run_sequences_; | |
187 | |
188 // Condition variable signaled when a Sequence is added to |run_sequences_|. | |
189 scoped_ptr<ConditionVariable> run_sequences_cv_; | |
190 | |
191 // Number of times that RunTaskCallback() has been called. | |
192 size_t num_run_tasks_ = 0; | |
193 | |
194 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadTest); | |
195 }; | |
196 | |
197 // Verify that when GetWorkCallback() continuously returns Sequences, all Tasks | |
198 // in these Sequences run successfully. The SchedulerWorkerThread is woken up | |
199 // once. | |
200 TEST_F(TaskSchedulerWorkerThreadTest, ContinousWork) { | |
gab
2016/04/05 23:35:20
Continuous Work
^
fdoray
2016/04/07 13:56:47
Done.
| |
201 // Set GetWorkCallback() to return |kNumSequencesPerTest| Sequences before | |
202 // starting to return nullptr. | |
203 SetNumSequencesToCreate(kNumSequencesPerTest); | |
204 | |
205 // Wake up |worker_thread_| and wait until it has run all the Tasks returned | |
206 // by GetWorkCallback(). | |
207 worker_thread_->WakeUp(); | |
208 WaitForAllSequencesToRun(); | |
209 | |
210 // Expect |kNumSequencesPerTest| calls to GetWorkCallback() in which it | |
211 // returned a Sequence and 1 call in which it returned nullptr. | |
212 const size_t expected_num_get_work_callback = kNumSequencesPerTest + 1; | |
gab
2016/04/05 23:35:20
kExpectedNumGetWorkCallback
fdoray
2016/04/07 13:56:47
Done.
| |
213 WaitForNumGetWorkCallback(expected_num_get_work_callback); | |
gab
2016/04/05 23:35:20
If all sequences ran we shouldn't need to wait her
fdoray
2016/04/07 13:56:47
Yes, we need to wait for the call to GetWork() tha
| |
214 EXPECT_EQ(expected_num_get_work_callback, NumGetWorkCallback()); | |
gab
2016/04/05 23:35:20
if we don't need to wait above maybe make |num_get
fdoray
2016/04/07 13:56:47
We do need to wait above.
| |
215 } | |
gab
2016/04/05 23:35:20
Test num wakeups? Since it's stated in test descri
fdoray
2016/04/07 13:56:47
I updated the test description. The test calls Wak
| |
216 | |
217 // Verify that when GetWorkCallback() alternates between returning a Sequence | |
218 // and returning nullptr, all Tasks in the returned Sequences run successfully. | |
219 // The SchedulerWorkerThread is woken up once for each Sequence. | |
220 TEST_F(TaskSchedulerWorkerThreadTest, IntermittentWork) { | |
221 for (size_t i = 0; i < kNumSequencesPerTest; ++i) { | |
222 // Set GetWorkCallback() to return 1 Sequence before starting to return | |
223 // nullptr. | |
224 SetNumSequencesToCreate(1); | |
225 | |
226 // Wake up |worker_thread_| and wait until it has run all the Tasks returned | |
227 // by GetWorkCallback(). | |
228 worker_thread_->WakeUp(); | |
229 WaitForAllSequencesToRun(); | |
230 | |
231 // Expect |i| calls to GetWorkCallback() in which it returned a Sequence and | |
232 // |i| calls in which it returned nullptr. | |
233 const size_t expected_num_get_work_callback = 2 * (i + 1); | |
234 WaitForNumGetWorkCallback(expected_num_get_work_callback); | |
235 EXPECT_EQ(expected_num_get_work_callback, NumGetWorkCallback()); | |
236 } | |
237 } | |
gab
2016/04/05 23:35:20
Test num wakeups?
fdoray
2016/04/07 13:56:47
ditto
| |
238 | |
239 } // namespace | |
240 } // namespace internal | |
241 } // namespace base | |
OLD | NEW |