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

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

Issue 2399213005: TaskScheduler: Change Sequence::PeekTask to Sequence::TakeTask. (Closed)
Patch Set: self-review 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
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(),
87 sequence->GetFrontTaskTraits().priority());
110 88
111 // Push task B, C and D in the sequence. Their sequenced time should be 89 // 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. 90 // updated and task A should always remain in front of the sequence.
113 EXPECT_FALSE(sequence->PushTask(std::move(task_b_owned_))); 91 EXPECT_FALSE(sequence->PushTask(std::move(task_b_owned_)));
114 EXPECT_FALSE(task_b_->sequenced_time.is_null()); 92 EXPECT_FALSE(task_b_->sequenced_time.is_null());
115 EXPECT_EQ(task_a_, sequence->PeekTask()); 93 EXPECT_EQ(task_a_->traits.priority(),
94 sequence->GetFrontTaskTraits().priority());
116 95
117 EXPECT_FALSE(sequence->PushTask(std::move(task_c_owned_))); 96 EXPECT_FALSE(sequence->PushTask(std::move(task_c_owned_)));
118 EXPECT_FALSE(task_c_->sequenced_time.is_null()); 97 EXPECT_FALSE(task_c_->sequenced_time.is_null());
119 EXPECT_EQ(task_a_, sequence->PeekTask()); 98 EXPECT_EQ(task_a_->traits.priority(),
99 sequence->GetFrontTaskTraits().priority());
120 100
121 EXPECT_FALSE(sequence->PushTask(std::move(task_d_owned_))); 101 EXPECT_FALSE(sequence->PushTask(std::move(task_d_owned_)));
122 EXPECT_FALSE(task_d_->sequenced_time.is_null()); 102 EXPECT_FALSE(task_d_->sequenced_time.is_null());
123 EXPECT_EQ(task_a_, sequence->PeekTask()); 103 EXPECT_EQ(task_a_->traits.priority(),
104 sequence->GetFrontTaskTraits().priority());
124 105
125 // Pop task A. Task B should now be in front. 106 // Take ownership of the task in front of the sequence. It should be task A.
126 EXPECT_FALSE(sequence->PopTask()); 107 EXPECT_EQ(task_a_, sequence->TakeTask().get());
127 EXPECT_EQ(task_b_, sequence->PeekTask());
128 108
129 // Pop task B. Task C should now be in front. 109 // Expect to find an empty slot in front of the sequence.
130 EXPECT_FALSE(sequence->PopTask()); 110 EXPECT_FALSE(sequence->TakeTask());
131 EXPECT_EQ(task_c_, sequence->PeekTask());
132 111
133 // Pop task C. Task D should now be in front. 112 // Remove the empty slot. Task B should now be in front.
134 EXPECT_FALSE(sequence->PopTask()); 113 EXPECT_FALSE(sequence->RemoveFrontSlot());
135 EXPECT_EQ(task_d_, sequence->PeekTask()); 114 EXPECT_EQ(task_b_, sequence->TakeTask().get());
115 EXPECT_FALSE(sequence->TakeTask());
116
117 // Remove the empty slot. Task C should now be in front.
118 EXPECT_FALSE(sequence->RemoveFrontSlot());
119 EXPECT_EQ(task_c_, sequence->TakeTask().get());
120 EXPECT_FALSE(sequence->TakeTask());
121
122 // Remove the empty slot. Task D should now be in front.
123 EXPECT_FALSE(sequence->RemoveFrontSlot());
124 EXPECT_EQ(task_d_, sequence->TakeTask().get());
125 EXPECT_FALSE(sequence->TakeTask());
136 126
137 // Push task E in the sequence. Its sequenced time should be updated and 127 // Push task E in the sequence. Its sequenced time should be updated and
138 // task D should remain in front. 128 // there should still be an empty slot in front of the sequence.
139 EXPECT_FALSE(sequence->PushTask(std::move(task_e_owned_))); 129 EXPECT_FALSE(sequence->PushTask(std::move(task_e_owned_)));
140 EXPECT_FALSE(task_e_->sequenced_time.is_null()); 130 EXPECT_FALSE(task_e_->sequenced_time.is_null());
141 EXPECT_EQ(task_d_, sequence->PeekTask()); 131 EXPECT_FALSE(sequence->TakeTask());
142 132
143 // Pop task D. Task E should now be in front. 133 // Remove the empty slot. Task E should now be in front.
144 EXPECT_FALSE(sequence->PopTask()); 134 EXPECT_FALSE(sequence->RemoveFrontSlot());
145 EXPECT_EQ(task_e_, sequence->PeekTask()); 135 EXPECT_EQ(task_e_, sequence->TakeTask().get());
136 EXPECT_FALSE(sequence->TakeTask());
146 137
147 // Pop task E. The sequence should now be empty. 138 // Remove the empty slot. The sequence should now be empty.
148 EXPECT_TRUE(sequence->PopTask()); 139 EXPECT_TRUE(sequence->RemoveFrontSlot());
149 EXPECT_EQ(nullptr, sequence->PeekTask()); 140 EXPECT_FALSE(sequence->TakeTask());
150 } 141 }
151 142
152 TEST_F(TaskSchedulerSequenceTest, GetSortKey) { 143 TEST_F(TaskSchedulerSequenceTest, GetSortKey) {
153 scoped_refptr<Sequence> sequence(new Sequence); 144 scoped_refptr<Sequence> sequence(new Sequence);
154 145
155 // Push task A in the sequence. The highest priority is from task A 146 // Push task A in the sequence. The highest priority is from task A
156 // (BACKGROUND). Task A is in front of the sequence. 147 // (BACKGROUND). Task A is in front of the sequence.
157 sequence->PushTask(std::move(task_a_owned_)); 148 sequence->PushTask(std::move(task_a_owned_));
158 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_a_->sequenced_time), 149 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_a_->sequenced_time),
159 sequence->GetSortKey()); 150 sequence->GetSortKey());
(...skipping 14 matching lines...) Expand all
174 165
175 // Push task D in the sequence. The highest priority is from tasks C/D 166 // 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. 167 // (USER_BLOCKING). Task A is still in front of the sequence.
177 sequence->PushTask(std::move(task_d_owned_)); 168 sequence->PushTask(std::move(task_d_owned_));
178 EXPECT_EQ( 169 EXPECT_EQ(
179 SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time), 170 SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time),
180 sequence->GetSortKey()); 171 sequence->GetSortKey());
181 172
182 // Pop task A. The highest priority is still USER_BLOCKING. The task in front 173 // Pop task A. The highest priority is still USER_BLOCKING. The task in front
183 // of the sequence is now task B. 174 // of the sequence is now task B.
184 sequence->PopTask(); 175 sequence->TakeTask();
176 sequence->RemoveFrontSlot();
185 EXPECT_EQ( 177 EXPECT_EQ(
186 SequenceSortKey(TaskPriority::USER_BLOCKING, task_b_->sequenced_time), 178 SequenceSortKey(TaskPriority::USER_BLOCKING, task_b_->sequenced_time),
187 sequence->GetSortKey()); 179 sequence->GetSortKey());
188 180
189 // Pop task B. The highest priority is still USER_BLOCKING. The task in front 181 // Pop task B. The highest priority is still USER_BLOCKING. The task in front
190 // of the sequence is now task C. 182 // of the sequence is now task C.
191 sequence->PopTask(); 183 sequence->TakeTask();
184 sequence->RemoveFrontSlot();
192 EXPECT_EQ( 185 EXPECT_EQ(
193 SequenceSortKey(TaskPriority::USER_BLOCKING, task_c_->sequenced_time), 186 SequenceSortKey(TaskPriority::USER_BLOCKING, task_c_->sequenced_time),
194 sequence->GetSortKey()); 187 sequence->GetSortKey());
195 188
196 // Pop task C. The highest priority is still USER_BLOCKING. The task in front 189 // Pop task C. The highest priority is still USER_BLOCKING. The task in front
197 // of the sequence is now task D. 190 // of the sequence is now task D.
198 sequence->PopTask(); 191 sequence->TakeTask();
192 sequence->RemoveFrontSlot();
199 EXPECT_EQ( 193 EXPECT_EQ(
200 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time), 194 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time),
201 sequence->GetSortKey()); 195 sequence->GetSortKey());
202 196
203 // Push task E in the sequence. The highest priority is still USER_BLOCKING. 197 // 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. 198 // The task in front of the sequence is still task D.
205 sequence->PushTask(std::move(task_e_owned_)); 199 sequence->PushTask(std::move(task_e_owned_));
206 EXPECT_EQ( 200 EXPECT_EQ(
207 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time), 201 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time),
208 sequence->GetSortKey()); 202 sequence->GetSortKey());
209 203
210 // Pop task D. The highest priority is now from task E (BACKGROUND). The 204 // Pop task D. The highest priority is now from task E (BACKGROUND). The
211 // task in front of the sequence is now task E. 205 // task in front of the sequence is now task E.
212 sequence->PopTask(); 206 sequence->TakeTask();
207 sequence->RemoveFrontSlot();
213 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_e_->sequenced_time), 208 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_e_->sequenced_time),
214 sequence->GetSortKey()); 209 sequence->GetSortKey());
215 } 210 }
216 211
217 TEST_F(TaskSchedulerSequenceTest, CanPushTaskInTaskDestructor) { 212 // Verify that a DCHECK fires if RemoveFrontSlot() is called on a sequence whose
213 // front slot isn't empty.
214 TEST_F(TaskSchedulerSequenceTest, RemoveNonEmptyFrontSlot) {
218 scoped_refptr<Sequence> sequence(new Sequence); 215 scoped_refptr<Sequence> sequence(new Sequence);
219 sequence->PushTask(MakeUnique<Task>( 216 sequence->PushTask(
220 FROM_HERE, Bind(&DoNothing, PushTaskInDestructor(sequence)), TaskTraits(), 217 MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), TimeDelta()));
221 TimeDelta()));
222 218
223 // PushTask() is invoked on |sequence| when the popped Task is destroyed. If 219 EXPECT_DCHECK_DEATH({ sequence->RemoveFrontSlot(); });
224 // PopTask() destroys the Task outside the scope of its lock as expected, no
225 // deadlock will occur when PushTask() tries to acquire the Sequence's lock.
226 sequence->PopTask();
227
228 // Verify that |sequence| contains exactly one Task.
229 EXPECT_TRUE(sequence->PeekTask());
230 EXPECT_TRUE(sequence->PopTask());
231 } 220 }
232 221
233 } // namespace internal 222 } // namespace internal
234 } // namespace base 223 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698