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

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

Issue 2399213005: TaskScheduler: Change Sequence::PeekTask to Sequence::TakeTask. (Closed)
Patch Set: CR robliao #5 Created 4 years, 2 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
« no previous file with comments | « base/task_scheduler/sequence.cc ('k') | base/task_scheduler/task_scheduler_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/sequence.h" 5 #include "base/task_scheduler/sequence.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/macros.h" 10 #include "base/macros.h"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/test/gtest_util.h"
12 #include "base/time/time.h" 13 #include "base/time/time.h"
13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
14 15
15 namespace base { 16 namespace base {
16 namespace internal { 17 namespace internal {
17 18
18 namespace { 19 namespace {
19 20
20 // A class that pushes a Task to a Sequence in its destructor.
21 class PushTaskInDestructor {
22 public:
23 explicit PushTaskInDestructor(scoped_refptr<Sequence> sequence)
24 : sequence_(std::move(sequence)) {}
25 PushTaskInDestructor(PushTaskInDestructor&&) = default;
26 PushTaskInDestructor& operator=(PushTaskInDestructor&&) = default;
27
28 ~PushTaskInDestructor() {
29 // |sequence_| may be nullptr in a temporary instance of this class.
30 if (sequence_) {
31 EXPECT_FALSE(sequence_->PeekTask());
32 sequence_->PushTask(WrapUnique(
33 new Task(FROM_HERE, Closure(), TaskTraits(), TimeDelta())));
34 }
35 }
36
37 private:
38 scoped_refptr<Sequence> sequence_;
39
40 DISALLOW_COPY_AND_ASSIGN(PushTaskInDestructor);
41 };
42
43 void DoNothing(const PushTaskInDestructor&) {}
44 21
45 class TaskSchedulerSequenceTest : public testing::Test { 22 class TaskSchedulerSequenceTest : public testing::Test {
46 public: 23 public:
47 TaskSchedulerSequenceTest() 24 TaskSchedulerSequenceTest()
48 : task_a_owned_( 25 : task_a_owned_(
49 new Task(FROM_HERE, 26 new Task(FROM_HERE,
50 Closure(), 27 Closure(),
51 TaskTraits().WithPriority(TaskPriority::BACKGROUND), 28 TaskTraits().WithPriority(TaskPriority::BACKGROUND),
52 TimeDelta())), 29 TimeDelta())),
53 task_b_owned_( 30 task_b_owned_(
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 const Task* task_c_; 69 const Task* task_c_;
93 const Task* task_d_; 70 const Task* task_d_;
94 const Task* task_e_; 71 const Task* task_e_;
95 72
96 private: 73 private:
97 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSequenceTest); 74 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSequenceTest);
98 }; 75 };
99 76
100 } // namespace 77 } // namespace
101 78
102 TEST_F(TaskSchedulerSequenceTest, PushPopPeek) { 79 TEST_F(TaskSchedulerSequenceTest, PushTakeRemove) {
103 scoped_refptr<Sequence> sequence(new Sequence); 80 scoped_refptr<Sequence> sequence(new Sequence);
104 81
105 // Push task A in the sequence. Its sequenced time should be updated and it 82 // Push task A in the sequence. Its sequenced time should be updated and it
106 // should be in front of the sequence. 83 // should be in front of the sequence.
107 EXPECT_TRUE(sequence->PushTask(std::move(task_a_owned_))); 84 EXPECT_TRUE(sequence->PushTask(std::move(task_a_owned_)));
108 EXPECT_FALSE(task_a_->sequenced_time.is_null()); 85 EXPECT_FALSE(task_a_->sequenced_time.is_null());
109 EXPECT_EQ(task_a_, sequence->PeekTask()); 86 EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
110 87
111 // Push task B, C and D in the sequence. Their sequenced time should be 88 // Push task B, C and D in the sequence. Their sequenced time should be
112 // updated and task A should always remain in front of the sequence. 89 // updated and task A should always remain in front of the sequence.
113 EXPECT_FALSE(sequence->PushTask(std::move(task_b_owned_))); 90 EXPECT_FALSE(sequence->PushTask(std::move(task_b_owned_)));
114 EXPECT_FALSE(task_b_->sequenced_time.is_null()); 91 EXPECT_FALSE(task_b_->sequenced_time.is_null());
115 EXPECT_EQ(task_a_, sequence->PeekTask()); 92 EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
116 93
117 EXPECT_FALSE(sequence->PushTask(std::move(task_c_owned_))); 94 EXPECT_FALSE(sequence->PushTask(std::move(task_c_owned_)));
118 EXPECT_FALSE(task_c_->sequenced_time.is_null()); 95 EXPECT_FALSE(task_c_->sequenced_time.is_null());
119 EXPECT_EQ(task_a_, sequence->PeekTask()); 96 EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
120 97
121 EXPECT_FALSE(sequence->PushTask(std::move(task_d_owned_))); 98 EXPECT_FALSE(sequence->PushTask(std::move(task_d_owned_)));
122 EXPECT_FALSE(task_d_->sequenced_time.is_null()); 99 EXPECT_FALSE(task_d_->sequenced_time.is_null());
123 EXPECT_EQ(task_a_, sequence->PeekTask()); 100 EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
124 101
125 // Pop task A. Task B should now be in front. 102 // Get the task in front of the sequence. It should be task A.
126 EXPECT_FALSE(sequence->PopTask()); 103 EXPECT_EQ(task_a_, sequence->TakeTask().get());
127 EXPECT_EQ(task_b_, sequence->PeekTask());
128 104
129 // Pop task B. Task C should now be in front. 105 // Remove the empty slot. Task B should now be in front.
130 EXPECT_FALSE(sequence->PopTask()); 106 EXPECT_FALSE(sequence->Pop());
131 EXPECT_EQ(task_c_, sequence->PeekTask()); 107 EXPECT_EQ(task_b_, sequence->TakeTask().get());
132 108
133 // Pop task C. Task D should now be in front. 109 // Remove the empty slot. Task C should now be in front.
134 EXPECT_FALSE(sequence->PopTask()); 110 EXPECT_FALSE(sequence->Pop());
135 EXPECT_EQ(task_d_, sequence->PeekTask()); 111 EXPECT_EQ(task_c_, sequence->TakeTask().get());
136 112
137 // Push task E in the sequence. Its sequenced time should be updated and 113 // Remove the empty slot. Task D should now be in front.
138 // task D should remain in front. 114 EXPECT_FALSE(sequence->Pop());
115 EXPECT_EQ(task_d_, sequence->TakeTask().get());
116
117 // Push task E in the sequence. Its sequenced time should be updated.
139 EXPECT_FALSE(sequence->PushTask(std::move(task_e_owned_))); 118 EXPECT_FALSE(sequence->PushTask(std::move(task_e_owned_)));
140 EXPECT_FALSE(task_e_->sequenced_time.is_null()); 119 EXPECT_FALSE(task_e_->sequenced_time.is_null());
141 EXPECT_EQ(task_d_, sequence->PeekTask());
142 120
143 // Pop task D. Task E should now be in front. 121 // Remove the empty slot. Task E should now be in front.
144 EXPECT_FALSE(sequence->PopTask()); 122 EXPECT_FALSE(sequence->Pop());
145 EXPECT_EQ(task_e_, sequence->PeekTask()); 123 EXPECT_EQ(task_e_, sequence->TakeTask().get());
146 124
147 // Pop task E. The sequence should now be empty. 125 // Remove the empty slot. The sequence should now be empty.
148 EXPECT_TRUE(sequence->PopTask()); 126 EXPECT_TRUE(sequence->Pop());
149 EXPECT_EQ(nullptr, sequence->PeekTask());
150 } 127 }
151 128
152 TEST_F(TaskSchedulerSequenceTest, GetSortKey) { 129 TEST_F(TaskSchedulerSequenceTest, GetSortKey) {
153 scoped_refptr<Sequence> sequence(new Sequence); 130 scoped_refptr<Sequence> sequence(new Sequence);
154 131
155 // Push task A in the sequence. The highest priority is from task A 132 // Push task A in the sequence. The highest priority is from task A
156 // (BACKGROUND). Task A is in front of the sequence. 133 // (BACKGROUND). Task A is in front of the sequence.
157 sequence->PushTask(std::move(task_a_owned_)); 134 sequence->PushTask(std::move(task_a_owned_));
158 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_a_->sequenced_time), 135 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_a_->sequenced_time),
159 sequence->GetSortKey()); 136 sequence->GetSortKey());
(...skipping 14 matching lines...) Expand all
174 151
175 // Push task D in the sequence. The highest priority is from tasks C/D 152 // Push task D in the sequence. The highest priority is from tasks C/D
176 // (USER_BLOCKING). Task A is still in front of the sequence. 153 // (USER_BLOCKING). Task A is still in front of the sequence.
177 sequence->PushTask(std::move(task_d_owned_)); 154 sequence->PushTask(std::move(task_d_owned_));
178 EXPECT_EQ( 155 EXPECT_EQ(
179 SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time), 156 SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time),
180 sequence->GetSortKey()); 157 sequence->GetSortKey());
181 158
182 // Pop task A. The highest priority is still USER_BLOCKING. The task in front 159 // Pop task A. The highest priority is still USER_BLOCKING. The task in front
183 // of the sequence is now task B. 160 // of the sequence is now task B.
184 sequence->PopTask(); 161 sequence->TakeTask();
162 sequence->Pop();
185 EXPECT_EQ( 163 EXPECT_EQ(
186 SequenceSortKey(TaskPriority::USER_BLOCKING, task_b_->sequenced_time), 164 SequenceSortKey(TaskPriority::USER_BLOCKING, task_b_->sequenced_time),
187 sequence->GetSortKey()); 165 sequence->GetSortKey());
188 166
189 // Pop task B. The highest priority is still USER_BLOCKING. The task in front 167 // Pop task B. The highest priority is still USER_BLOCKING. The task in front
190 // of the sequence is now task C. 168 // of the sequence is now task C.
191 sequence->PopTask(); 169 sequence->TakeTask();
170 sequence->Pop();
192 EXPECT_EQ( 171 EXPECT_EQ(
193 SequenceSortKey(TaskPriority::USER_BLOCKING, task_c_->sequenced_time), 172 SequenceSortKey(TaskPriority::USER_BLOCKING, task_c_->sequenced_time),
194 sequence->GetSortKey()); 173 sequence->GetSortKey());
195 174
196 // Pop task C. The highest priority is still USER_BLOCKING. The task in front 175 // Pop task C. The highest priority is still USER_BLOCKING. The task in front
197 // of the sequence is now task D. 176 // of the sequence is now task D.
198 sequence->PopTask(); 177 sequence->TakeTask();
178 sequence->Pop();
199 EXPECT_EQ( 179 EXPECT_EQ(
200 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time), 180 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time),
201 sequence->GetSortKey()); 181 sequence->GetSortKey());
202 182
203 // Push task E in the sequence. The highest priority is still USER_BLOCKING. 183 // Push task E in the sequence. The highest priority is still USER_BLOCKING.
204 // The task in front of the sequence is still task D. 184 // The task in front of the sequence is still task D.
205 sequence->PushTask(std::move(task_e_owned_)); 185 sequence->PushTask(std::move(task_e_owned_));
206 EXPECT_EQ( 186 EXPECT_EQ(
207 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time), 187 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time),
208 sequence->GetSortKey()); 188 sequence->GetSortKey());
209 189
210 // Pop task D. The highest priority is now from task E (BACKGROUND). The 190 // Pop task D. The highest priority is now from task E (BACKGROUND). The
211 // task in front of the sequence is now task E. 191 // task in front of the sequence is now task E.
212 sequence->PopTask(); 192 sequence->TakeTask();
193 sequence->Pop();
213 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_e_->sequenced_time), 194 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_e_->sequenced_time),
214 sequence->GetSortKey()); 195 sequence->GetSortKey());
215 } 196 }
216 197
217 TEST_F(TaskSchedulerSequenceTest, CanPushTaskInTaskDestructor) { 198 // Verify that a DCHECK fires if Pop() is called on a sequence whose front slot
199 // isn't empty.
200 TEST_F(TaskSchedulerSequenceTest, PopNonEmptyFrontSlot) {
218 scoped_refptr<Sequence> sequence(new Sequence); 201 scoped_refptr<Sequence> sequence(new Sequence);
219 sequence->PushTask(MakeUnique<Task>( 202 sequence->PushTask(
220 FROM_HERE, Bind(&DoNothing, PushTaskInDestructor(sequence)), TaskTraits(), 203 MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), TimeDelta()));
221 TimeDelta()));
222 204
223 // PushTask() is invoked on |sequence| when the popped Task is destroyed. If 205 EXPECT_DCHECK_DEATH({ sequence->Pop(); });
224 // PopTask() destroys the Task outside the scope of its lock as expected, no 206 }
225 // deadlock will occur when PushTask() tries to acquire the Sequence's lock.
226 sequence->PopTask();
227 207
228 // Verify that |sequence| contains exactly one Task. 208 // Verify that a DCHECK fires if TakeTask() is called on a sequence whose front
229 EXPECT_TRUE(sequence->PeekTask()); 209 // slot is empty.
230 EXPECT_TRUE(sequence->PopTask()); 210 TEST_F(TaskSchedulerSequenceTest, TakeEmptyFrontSlot) {
211 scoped_refptr<Sequence> sequence(new Sequence);
212 sequence->PushTask(
213 MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), TimeDelta()));
214
215 EXPECT_TRUE(sequence->TakeTask());
216 EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
217 }
218
219 // Verify that a DCHECK fires if TakeTask() is called on an empty sequence.
220 TEST_F(TaskSchedulerSequenceTest, TakeEmptySequence) {
221 scoped_refptr<Sequence> sequence(new Sequence);
222 EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
231 } 223 }
232 224
233 } // namespace internal 225 } // namespace internal
234 } // namespace base 226 } // namespace base
OLDNEW
« no previous file with comments | « base/task_scheduler/sequence.cc ('k') | base/task_scheduler/task_scheduler_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698