blob: ba020cb31c085aa3c3edd77045631b9acf27b884 [file] [log] [blame]
fdorayf4329522016-03-17 10:57:42 +09001// 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/sequence.h"
6
fdoray66f5a342016-07-22 06:22:59 +09007#include <utility>
8
9#include "base/bind.h"
fdorayf4329522016-03-17 10:57:42 +090010#include "base/macros.h"
fdoray66f5a342016-07-22 06:22:59 +090011#include "base/memory/ptr_util.h"
fdorayd7a33a62016-10-12 21:21:27 +090012#include "base/test/gtest_util.h"
fdorayf4329522016-03-17 10:57:42 +090013#include "base/time/time.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
16namespace base {
17namespace internal {
18
19namespace {
20
fdoray66f5a342016-07-22 06:22:59 +090021
fdorayf4329522016-03-17 10:57:42 +090022class TaskSchedulerSequenceTest : public testing::Test {
23 public:
24 TaskSchedulerSequenceTest()
25 : task_a_owned_(
26 new Task(FROM_HERE,
27 Closure(),
fdoray97e43582016-04-19 02:46:30 +090028 TaskTraits().WithPriority(TaskPriority::BACKGROUND),
fdoray01ddcba2016-04-26 12:19:16 +090029 TimeDelta())),
fdorayf4329522016-03-17 10:57:42 +090030 task_b_owned_(
31 new Task(FROM_HERE,
32 Closure(),
fdoray97e43582016-04-19 02:46:30 +090033 TaskTraits().WithPriority(TaskPriority::USER_VISIBLE),
fdoray01ddcba2016-04-26 12:19:16 +090034 TimeDelta())),
fdorayf4329522016-03-17 10:57:42 +090035 task_c_owned_(
36 new Task(FROM_HERE,
37 Closure(),
fdoray97e43582016-04-19 02:46:30 +090038 TaskTraits().WithPriority(TaskPriority::USER_BLOCKING),
fdoray01ddcba2016-04-26 12:19:16 +090039 TimeDelta())),
fdorayf4329522016-03-17 10:57:42 +090040 task_d_owned_(
41 new Task(FROM_HERE,
42 Closure(),
fdoray97e43582016-04-19 02:46:30 +090043 TaskTraits().WithPriority(TaskPriority::USER_BLOCKING),
fdoray01ddcba2016-04-26 12:19:16 +090044 TimeDelta())),
fdorayf4329522016-03-17 10:57:42 +090045 task_e_owned_(
46 new Task(FROM_HERE,
47 Closure(),
fdoray97e43582016-04-19 02:46:30 +090048 TaskTraits().WithPriority(TaskPriority::BACKGROUND),
fdoray01ddcba2016-04-26 12:19:16 +090049 TimeDelta())),
fdorayf4329522016-03-17 10:57:42 +090050 task_a_(task_a_owned_.get()),
51 task_b_(task_b_owned_.get()),
52 task_c_(task_c_owned_.get()),
53 task_d_(task_d_owned_.get()),
54 task_e_(task_e_owned_.get()) {}
55
56 protected:
57 // Tasks to be handed off to a Sequence for testing.
dchengcc8e4d82016-04-05 06:25:51 +090058 std::unique_ptr<Task> task_a_owned_;
59 std::unique_ptr<Task> task_b_owned_;
60 std::unique_ptr<Task> task_c_owned_;
61 std::unique_ptr<Task> task_d_owned_;
62 std::unique_ptr<Task> task_e_owned_;
fdorayf4329522016-03-17 10:57:42 +090063
64 // Raw pointers to those same tasks for verification. This is needed because
65 // the scoped_ptrs above no longer point to the tasks once they have been
66 // moved into a Sequence.
67 const Task* task_a_;
68 const Task* task_b_;
69 const Task* task_c_;
70 const Task* task_d_;
71 const Task* task_e_;
72
73 private:
74 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSequenceTest);
75};
76
fdorayf4329522016-03-17 10:57:42 +090077} // namespace
78
fdorayd7a33a62016-10-12 21:21:27 +090079TEST_F(TaskSchedulerSequenceTest, PushTakeRemove) {
fdorayf4329522016-03-17 10:57:42 +090080 scoped_refptr<Sequence> sequence(new Sequence);
81
82 // Push task A in the sequence. Its sequenced time should be updated and it
83 // should be in front of the sequence.
84 EXPECT_TRUE(sequence->PushTask(std::move(task_a_owned_)));
85 EXPECT_FALSE(task_a_->sequenced_time.is_null());
fdorayd7a33a62016-10-12 21:21:27 +090086 EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
fdorayf4329522016-03-17 10:57:42 +090087
88 // Push task B, C and D in the sequence. Their sequenced time should be
89 // updated and task A should always remain in front of the sequence.
90 EXPECT_FALSE(sequence->PushTask(std::move(task_b_owned_)));
91 EXPECT_FALSE(task_b_->sequenced_time.is_null());
fdorayd7a33a62016-10-12 21:21:27 +090092 EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
fdorayf4329522016-03-17 10:57:42 +090093
94 EXPECT_FALSE(sequence->PushTask(std::move(task_c_owned_)));
95 EXPECT_FALSE(task_c_->sequenced_time.is_null());
fdorayd7a33a62016-10-12 21:21:27 +090096 EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
fdorayf4329522016-03-17 10:57:42 +090097
98 EXPECT_FALSE(sequence->PushTask(std::move(task_d_owned_)));
99 EXPECT_FALSE(task_d_->sequenced_time.is_null());
fdorayd7a33a62016-10-12 21:21:27 +0900100 EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority());
fdorayf4329522016-03-17 10:57:42 +0900101
fdorayd7a33a62016-10-12 21:21:27 +0900102 // Get the task in front of the sequence. It should be task A.
103 EXPECT_EQ(task_a_, sequence->TakeTask().get());
fdorayf4329522016-03-17 10:57:42 +0900104
fdorayd7a33a62016-10-12 21:21:27 +0900105 // Remove the empty slot. Task B should now be in front.
106 EXPECT_FALSE(sequence->Pop());
107 EXPECT_EQ(task_b_, sequence->TakeTask().get());
fdorayf4329522016-03-17 10:57:42 +0900108
fdorayd7a33a62016-10-12 21:21:27 +0900109 // Remove the empty slot. Task C should now be in front.
110 EXPECT_FALSE(sequence->Pop());
111 EXPECT_EQ(task_c_, sequence->TakeTask().get());
fdorayf4329522016-03-17 10:57:42 +0900112
fdorayd7a33a62016-10-12 21:21:27 +0900113 // Remove the empty slot. Task D should now be 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.
fdorayf4329522016-03-17 10:57:42 +0900118 EXPECT_FALSE(sequence->PushTask(std::move(task_e_owned_)));
119 EXPECT_FALSE(task_e_->sequenced_time.is_null());
fdorayf4329522016-03-17 10:57:42 +0900120
fdorayd7a33a62016-10-12 21:21:27 +0900121 // Remove the empty slot. Task E should now be in front.
122 EXPECT_FALSE(sequence->Pop());
123 EXPECT_EQ(task_e_, sequence->TakeTask().get());
fdorayf4329522016-03-17 10:57:42 +0900124
fdorayd7a33a62016-10-12 21:21:27 +0900125 // Remove the empty slot. The sequence should now be empty.
126 EXPECT_TRUE(sequence->Pop());
fdorayf4329522016-03-17 10:57:42 +0900127}
128
129TEST_F(TaskSchedulerSequenceTest, GetSortKey) {
130 scoped_refptr<Sequence> sequence(new Sequence);
131
132 // Push task A in the sequence. The highest priority is from task A
133 // (BACKGROUND). Task A is in front of the sequence.
134 sequence->PushTask(std::move(task_a_owned_));
gab558d9d92016-04-29 04:44:45 +0900135 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_a_->sequenced_time),
136 sequence->GetSortKey());
fdorayf4329522016-03-17 10:57:42 +0900137
138 // Push task B in the sequence. The highest priority is from task B
139 // (USER_VISIBLE). Task A is still in front of the sequence.
140 sequence->PushTask(std::move(task_b_owned_));
gab558d9d92016-04-29 04:44:45 +0900141 EXPECT_EQ(
142 SequenceSortKey(TaskPriority::USER_VISIBLE, task_a_->sequenced_time),
143 sequence->GetSortKey());
fdorayf4329522016-03-17 10:57:42 +0900144
145 // Push task C in the sequence. The highest priority is from task C
146 // (USER_BLOCKING). Task A is still in front of the sequence.
147 sequence->PushTask(std::move(task_c_owned_));
gab558d9d92016-04-29 04:44:45 +0900148 EXPECT_EQ(
149 SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time),
150 sequence->GetSortKey());
fdorayf4329522016-03-17 10:57:42 +0900151
152 // Push task D in the sequence. The highest priority is from tasks C/D
153 // (USER_BLOCKING). Task A is still in front of the sequence.
154 sequence->PushTask(std::move(task_d_owned_));
gab558d9d92016-04-29 04:44:45 +0900155 EXPECT_EQ(
156 SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time),
157 sequence->GetSortKey());
fdorayf4329522016-03-17 10:57:42 +0900158
159 // Pop task A. The highest priority is still USER_BLOCKING. The task in front
160 // of the sequence is now task B.
fdorayd7a33a62016-10-12 21:21:27 +0900161 sequence->TakeTask();
162 sequence->Pop();
gab558d9d92016-04-29 04:44:45 +0900163 EXPECT_EQ(
164 SequenceSortKey(TaskPriority::USER_BLOCKING, task_b_->sequenced_time),
165 sequence->GetSortKey());
fdorayf4329522016-03-17 10:57:42 +0900166
167 // Pop task B. The highest priority is still USER_BLOCKING. The task in front
168 // of the sequence is now task C.
fdorayd7a33a62016-10-12 21:21:27 +0900169 sequence->TakeTask();
170 sequence->Pop();
gab558d9d92016-04-29 04:44:45 +0900171 EXPECT_EQ(
172 SequenceSortKey(TaskPriority::USER_BLOCKING, task_c_->sequenced_time),
173 sequence->GetSortKey());
fdorayf4329522016-03-17 10:57:42 +0900174
175 // Pop task C. The highest priority is still USER_BLOCKING. The task in front
176 // of the sequence is now task D.
fdorayd7a33a62016-10-12 21:21:27 +0900177 sequence->TakeTask();
178 sequence->Pop();
gab558d9d92016-04-29 04:44:45 +0900179 EXPECT_EQ(
180 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time),
181 sequence->GetSortKey());
fdorayf4329522016-03-17 10:57:42 +0900182
183 // Push task E in the sequence. The highest priority is still USER_BLOCKING.
184 // The task in front of the sequence is still task D.
185 sequence->PushTask(std::move(task_e_owned_));
gab558d9d92016-04-29 04:44:45 +0900186 EXPECT_EQ(
187 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time),
188 sequence->GetSortKey());
fdorayf4329522016-03-17 10:57:42 +0900189
190 // Pop task D. The highest priority is now from task E (BACKGROUND). The
191 // task in front of the sequence is now task E.
fdorayd7a33a62016-10-12 21:21:27 +0900192 sequence->TakeTask();
193 sequence->Pop();
gab558d9d92016-04-29 04:44:45 +0900194 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_e_->sequenced_time),
195 sequence->GetSortKey());
fdorayf4329522016-03-17 10:57:42 +0900196}
197
fdorayd7a33a62016-10-12 21:21:27 +0900198// Verify that a DCHECK fires if Pop() is called on a sequence whose front slot
199// isn't empty.
200TEST_F(TaskSchedulerSequenceTest, PopNonEmptyFrontSlot) {
fdoray66f5a342016-07-22 06:22:59 +0900201 scoped_refptr<Sequence> sequence(new Sequence);
fdorayd7a33a62016-10-12 21:21:27 +0900202 sequence->PushTask(
203 MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), TimeDelta()));
fdoray66f5a342016-07-22 06:22:59 +0900204
fdorayd7a33a62016-10-12 21:21:27 +0900205 EXPECT_DCHECK_DEATH({ sequence->Pop(); });
206}
fdoray66f5a342016-07-22 06:22:59 +0900207
fdorayd7a33a62016-10-12 21:21:27 +0900208// Verify that a DCHECK fires if TakeTask() is called on a sequence whose front
209// slot is empty.
210TEST_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.
220TEST_F(TaskSchedulerSequenceTest, TakeEmptySequence) {
221 scoped_refptr<Sequence> sequence(new Sequence);
222 EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
fdoray66f5a342016-07-22 06:22:59 +0900223}
224
fdorayf4329522016-03-17 10:57:42 +0900225} // namespace internal
226} // namespace base