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/sequence.h"
6
7 #include "base/macros.h"
8 #include "base/time/time.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace base {
12 namespace internal {
13
14 namespace {
15
16 class TaskSchedulerSequenceTest : public testing::Test {
17 public:
TaskSchedulerSequenceTest()18 TaskSchedulerSequenceTest()
19 : task_a_owned_(
20 new Task(FROM_HERE,
21 Closure(),
22 TaskTraits().WithPriority(TaskPriority::BACKGROUND),
23 TimeDelta())),
24 task_b_owned_(
25 new Task(FROM_HERE,
26 Closure(),
27 TaskTraits().WithPriority(TaskPriority::USER_VISIBLE),
28 TimeDelta())),
29 task_c_owned_(
30 new Task(FROM_HERE,
31 Closure(),
32 TaskTraits().WithPriority(TaskPriority::USER_BLOCKING),
33 TimeDelta())),
34 task_d_owned_(
35 new Task(FROM_HERE,
36 Closure(),
37 TaskTraits().WithPriority(TaskPriority::USER_BLOCKING),
38 TimeDelta())),
39 task_e_owned_(
40 new Task(FROM_HERE,
41 Closure(),
42 TaskTraits().WithPriority(TaskPriority::BACKGROUND),
43 TimeDelta())),
44 task_a_(task_a_owned_.get()),
45 task_b_(task_b_owned_.get()),
46 task_c_(task_c_owned_.get()),
47 task_d_(task_d_owned_.get()),
48 task_e_(task_e_owned_.get()) {}
49
50 protected:
51 // Tasks to be handed off to a Sequence for testing.
52 std::unique_ptr<Task> task_a_owned_;
53 std::unique_ptr<Task> task_b_owned_;
54 std::unique_ptr<Task> task_c_owned_;
55 std::unique_ptr<Task> task_d_owned_;
56 std::unique_ptr<Task> task_e_owned_;
57
58 // Raw pointers to those same tasks for verification. This is needed because
59 // the scoped_ptrs above no longer point to the tasks once they have been
60 // moved into a Sequence.
61 const Task* task_a_;
62 const Task* task_b_;
63 const Task* task_c_;
64 const Task* task_d_;
65 const Task* task_e_;
66
67 private:
68 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSequenceTest);
69 };
70
71 } // namespace
72
TEST_F(TaskSchedulerSequenceTest,PushPopPeek)73 TEST_F(TaskSchedulerSequenceTest, PushPopPeek) {
74 scoped_refptr<Sequence> sequence(new Sequence);
75
76 // Push task A in the sequence. Its sequenced time should be updated and it
77 // should be in front of the sequence.
78 EXPECT_TRUE(sequence->PushTask(std::move(task_a_owned_)));
79 EXPECT_FALSE(task_a_->sequenced_time.is_null());
80 EXPECT_EQ(task_a_, sequence->PeekTask());
81
82 // Push task B, C and D in the sequence. Their sequenced time should be
83 // updated and task A should always remain in front of the sequence.
84 EXPECT_FALSE(sequence->PushTask(std::move(task_b_owned_)));
85 EXPECT_FALSE(task_b_->sequenced_time.is_null());
86 EXPECT_EQ(task_a_, sequence->PeekTask());
87
88 EXPECT_FALSE(sequence->PushTask(std::move(task_c_owned_)));
89 EXPECT_FALSE(task_c_->sequenced_time.is_null());
90 EXPECT_EQ(task_a_, sequence->PeekTask());
91
92 EXPECT_FALSE(sequence->PushTask(std::move(task_d_owned_)));
93 EXPECT_FALSE(task_d_->sequenced_time.is_null());
94 EXPECT_EQ(task_a_, sequence->PeekTask());
95
96 // Pop task A. Task B should now be in front.
97 EXPECT_FALSE(sequence->PopTask());
98 EXPECT_EQ(task_b_, sequence->PeekTask());
99
100 // Pop task B. Task C should now be in front.
101 EXPECT_FALSE(sequence->PopTask());
102 EXPECT_EQ(task_c_, sequence->PeekTask());
103
104 // Pop task C. Task D should now be in front.
105 EXPECT_FALSE(sequence->PopTask());
106 EXPECT_EQ(task_d_, sequence->PeekTask());
107
108 // Push task E in the sequence. Its sequenced time should be updated and
109 // task D should remain in front.
110 EXPECT_FALSE(sequence->PushTask(std::move(task_e_owned_)));
111 EXPECT_FALSE(task_e_->sequenced_time.is_null());
112 EXPECT_EQ(task_d_, sequence->PeekTask());
113
114 // Pop task D. Task E should now be in front.
115 EXPECT_FALSE(sequence->PopTask());
116 EXPECT_EQ(task_e_, sequence->PeekTask());
117
118 // Pop task E. The sequence should now be empty.
119 EXPECT_TRUE(sequence->PopTask());
120 EXPECT_EQ(nullptr, sequence->PeekTask());
121 }
122
TEST_F(TaskSchedulerSequenceTest,GetSortKey)123 TEST_F(TaskSchedulerSequenceTest, GetSortKey) {
124 scoped_refptr<Sequence> sequence(new Sequence);
125
126 // Push task A in the sequence. The highest priority is from task A
127 // (BACKGROUND). Task A is in front of the sequence.
128 sequence->PushTask(std::move(task_a_owned_));
129 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_a_->sequenced_time),
130 sequence->GetSortKey());
131
132 // Push task B in the sequence. The highest priority is from task B
133 // (USER_VISIBLE). Task A is still in front of the sequence.
134 sequence->PushTask(std::move(task_b_owned_));
135 EXPECT_EQ(
136 SequenceSortKey(TaskPriority::USER_VISIBLE, task_a_->sequenced_time),
137 sequence->GetSortKey());
138
139 // Push task C in the sequence. The highest priority is from task C
140 // (USER_BLOCKING). Task A is still in front of the sequence.
141 sequence->PushTask(std::move(task_c_owned_));
142 EXPECT_EQ(
143 SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time),
144 sequence->GetSortKey());
145
146 // Push task D in the sequence. The highest priority is from tasks C/D
147 // (USER_BLOCKING). Task A is still in front of the sequence.
148 sequence->PushTask(std::move(task_d_owned_));
149 EXPECT_EQ(
150 SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time),
151 sequence->GetSortKey());
152
153 // Pop task A. The highest priority is still USER_BLOCKING. The task in front
154 // of the sequence is now task B.
155 sequence->PopTask();
156 EXPECT_EQ(
157 SequenceSortKey(TaskPriority::USER_BLOCKING, task_b_->sequenced_time),
158 sequence->GetSortKey());
159
160 // Pop task B. The highest priority is still USER_BLOCKING. The task in front
161 // of the sequence is now task C.
162 sequence->PopTask();
163 EXPECT_EQ(
164 SequenceSortKey(TaskPriority::USER_BLOCKING, task_c_->sequenced_time),
165 sequence->GetSortKey());
166
167 // Pop task C. The highest priority is still USER_BLOCKING. The task in front
168 // of the sequence is now task D.
169 sequence->PopTask();
170 EXPECT_EQ(
171 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time),
172 sequence->GetSortKey());
173
174 // Push task E in the sequence. The highest priority is still USER_BLOCKING.
175 // The task in front of the sequence is still task D.
176 sequence->PushTask(std::move(task_e_owned_));
177 EXPECT_EQ(
178 SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time),
179 sequence->GetSortKey());
180
181 // Pop task D. The highest priority is now from task E (BACKGROUND). The
182 // task in front of the sequence is now task E.
183 sequence->PopTask();
184 EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_e_->sequenced_time),
185 sequence->GetSortKey());
186 }
187
188 } // namespace internal
189 } // namespace base
190