1*635a8641SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/sequence.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <utility>
8*635a8641SAndroid Build Coastguard Worker
9*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/bind_helpers.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/test/gtest_util.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/time/time.h"
14*635a8641SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
15*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
16*635a8641SAndroid Build Coastguard Worker
17*635a8641SAndroid Build Coastguard Worker namespace base {
18*635a8641SAndroid Build Coastguard Worker namespace internal {
19*635a8641SAndroid Build Coastguard Worker
20*635a8641SAndroid Build Coastguard Worker namespace {
21*635a8641SAndroid Build Coastguard Worker
22*635a8641SAndroid Build Coastguard Worker class MockTask {
23*635a8641SAndroid Build Coastguard Worker public:
24*635a8641SAndroid Build Coastguard Worker MOCK_METHOD0(Run, void());
25*635a8641SAndroid Build Coastguard Worker };
26*635a8641SAndroid Build Coastguard Worker
CreateTask(MockTask * mock_task)27*635a8641SAndroid Build Coastguard Worker Task CreateTask(MockTask* mock_task) {
28*635a8641SAndroid Build Coastguard Worker return Task(FROM_HERE, BindOnce(&MockTask::Run, Unretained(mock_task)),
29*635a8641SAndroid Build Coastguard Worker {TaskPriority::BACKGROUND}, TimeDelta());
30*635a8641SAndroid Build Coastguard Worker }
31*635a8641SAndroid Build Coastguard Worker
ExpectMockTask(MockTask * mock_task,Task * task)32*635a8641SAndroid Build Coastguard Worker void ExpectMockTask(MockTask* mock_task, Task* task) {
33*635a8641SAndroid Build Coastguard Worker EXPECT_CALL(*mock_task, Run());
34*635a8641SAndroid Build Coastguard Worker std::move(task->task).Run();
35*635a8641SAndroid Build Coastguard Worker testing::Mock::VerifyAndClear(mock_task);
36*635a8641SAndroid Build Coastguard Worker }
37*635a8641SAndroid Build Coastguard Worker
38*635a8641SAndroid Build Coastguard Worker } // namespace
39*635a8641SAndroid Build Coastguard Worker
TEST(TaskSchedulerSequenceTest,PushTakeRemove)40*635a8641SAndroid Build Coastguard Worker TEST(TaskSchedulerSequenceTest, PushTakeRemove) {
41*635a8641SAndroid Build Coastguard Worker testing::StrictMock<MockTask> mock_task_a;
42*635a8641SAndroid Build Coastguard Worker testing::StrictMock<MockTask> mock_task_b;
43*635a8641SAndroid Build Coastguard Worker testing::StrictMock<MockTask> mock_task_c;
44*635a8641SAndroid Build Coastguard Worker testing::StrictMock<MockTask> mock_task_d;
45*635a8641SAndroid Build Coastguard Worker testing::StrictMock<MockTask> mock_task_e;
46*635a8641SAndroid Build Coastguard Worker
47*635a8641SAndroid Build Coastguard Worker scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
48*635a8641SAndroid Build Coastguard Worker
49*635a8641SAndroid Build Coastguard Worker // Push task A in the sequence. PushTask() should return true since it's the
50*635a8641SAndroid Build Coastguard Worker // first task->
51*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(sequence->PushTask(CreateTask(&mock_task_a)));
52*635a8641SAndroid Build Coastguard Worker
53*635a8641SAndroid Build Coastguard Worker // Push task B, C and D in the sequence. PushTask() should return false since
54*635a8641SAndroid Build Coastguard Worker // there is already a task in a sequence.
55*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_b)));
56*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_c)));
57*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_d)));
58*635a8641SAndroid Build Coastguard Worker
59*635a8641SAndroid Build Coastguard Worker // Take the task in front of the sequence. It should be task A.
60*635a8641SAndroid Build Coastguard Worker Optional<Task> task = sequence->TakeTask();
61*635a8641SAndroid Build Coastguard Worker ExpectMockTask(&mock_task_a, &task.value());
62*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(task->sequenced_time.is_null());
63*635a8641SAndroid Build Coastguard Worker
64*635a8641SAndroid Build Coastguard Worker // Remove the empty slot. Task B should now be in front.
65*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(sequence->Pop());
66*635a8641SAndroid Build Coastguard Worker task = sequence->TakeTask();
67*635a8641SAndroid Build Coastguard Worker ExpectMockTask(&mock_task_b, &task.value());
68*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(task->sequenced_time.is_null());
69*635a8641SAndroid Build Coastguard Worker
70*635a8641SAndroid Build Coastguard Worker // Remove the empty slot. Task C should now be in front.
71*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(sequence->Pop());
72*635a8641SAndroid Build Coastguard Worker task = sequence->TakeTask();
73*635a8641SAndroid Build Coastguard Worker ExpectMockTask(&mock_task_c, &task.value());
74*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(task->sequenced_time.is_null());
75*635a8641SAndroid Build Coastguard Worker
76*635a8641SAndroid Build Coastguard Worker // Remove the empty slot.
77*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(sequence->Pop());
78*635a8641SAndroid Build Coastguard Worker
79*635a8641SAndroid Build Coastguard Worker // Push task E in the sequence.
80*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_e)));
81*635a8641SAndroid Build Coastguard Worker
82*635a8641SAndroid Build Coastguard Worker // Task D should be in front.
83*635a8641SAndroid Build Coastguard Worker task = sequence->TakeTask();
84*635a8641SAndroid Build Coastguard Worker ExpectMockTask(&mock_task_d, &task.value());
85*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(task->sequenced_time.is_null());
86*635a8641SAndroid Build Coastguard Worker
87*635a8641SAndroid Build Coastguard Worker // Remove the empty slot. Task E should now be in front.
88*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(sequence->Pop());
89*635a8641SAndroid Build Coastguard Worker task = sequence->TakeTask();
90*635a8641SAndroid Build Coastguard Worker ExpectMockTask(&mock_task_e, &task.value());
91*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(task->sequenced_time.is_null());
92*635a8641SAndroid Build Coastguard Worker
93*635a8641SAndroid Build Coastguard Worker // Remove the empty slot. The sequence should now be empty.
94*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(sequence->Pop());
95*635a8641SAndroid Build Coastguard Worker }
96*635a8641SAndroid Build Coastguard Worker
97*635a8641SAndroid Build Coastguard Worker // Verifies the sort key of a sequence that contains one BACKGROUND task.
TEST(TaskSchedulerSequenceTest,GetSortKeyBackground)98*635a8641SAndroid Build Coastguard Worker TEST(TaskSchedulerSequenceTest, GetSortKeyBackground) {
99*635a8641SAndroid Build Coastguard Worker // Create a sequence with a BACKGROUND task.
100*635a8641SAndroid Build Coastguard Worker Task background_task(FROM_HERE, DoNothing(), {TaskPriority::BACKGROUND},
101*635a8641SAndroid Build Coastguard Worker TimeDelta());
102*635a8641SAndroid Build Coastguard Worker scoped_refptr<Sequence> background_sequence = MakeRefCounted<Sequence>();
103*635a8641SAndroid Build Coastguard Worker background_sequence->PushTask(std::move(background_task));
104*635a8641SAndroid Build Coastguard Worker
105*635a8641SAndroid Build Coastguard Worker // Get the sort key.
106*635a8641SAndroid Build Coastguard Worker const SequenceSortKey background_sort_key = background_sequence->GetSortKey();
107*635a8641SAndroid Build Coastguard Worker
108*635a8641SAndroid Build Coastguard Worker // Take the task from the sequence, so that its sequenced time is available
109*635a8641SAndroid Build Coastguard Worker // for the check below.
110*635a8641SAndroid Build Coastguard Worker auto take_background_task = background_sequence->TakeTask();
111*635a8641SAndroid Build Coastguard Worker
112*635a8641SAndroid Build Coastguard Worker // Verify the sort key.
113*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(TaskPriority::BACKGROUND, background_sort_key.priority());
114*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(take_background_task->sequenced_time,
115*635a8641SAndroid Build Coastguard Worker background_sort_key.next_task_sequenced_time());
116*635a8641SAndroid Build Coastguard Worker
117*635a8641SAndroid Build Coastguard Worker // Pop for correctness.
118*635a8641SAndroid Build Coastguard Worker background_sequence->Pop();
119*635a8641SAndroid Build Coastguard Worker }
120*635a8641SAndroid Build Coastguard Worker
121*635a8641SAndroid Build Coastguard Worker // Same as TaskSchedulerSequenceTest.GetSortKeyBackground, but with a
122*635a8641SAndroid Build Coastguard Worker // USER_VISIBLE task.
TEST(TaskSchedulerSequenceTest,GetSortKeyForeground)123*635a8641SAndroid Build Coastguard Worker TEST(TaskSchedulerSequenceTest, GetSortKeyForeground) {
124*635a8641SAndroid Build Coastguard Worker // Create a sequence with a USER_VISIBLE task.
125*635a8641SAndroid Build Coastguard Worker Task foreground_task(FROM_HERE, DoNothing(), {TaskPriority::USER_VISIBLE},
126*635a8641SAndroid Build Coastguard Worker TimeDelta());
127*635a8641SAndroid Build Coastguard Worker scoped_refptr<Sequence> foreground_sequence = MakeRefCounted<Sequence>();
128*635a8641SAndroid Build Coastguard Worker foreground_sequence->PushTask(std::move(foreground_task));
129*635a8641SAndroid Build Coastguard Worker
130*635a8641SAndroid Build Coastguard Worker // Get the sort key.
131*635a8641SAndroid Build Coastguard Worker const SequenceSortKey foreground_sort_key = foreground_sequence->GetSortKey();
132*635a8641SAndroid Build Coastguard Worker
133*635a8641SAndroid Build Coastguard Worker // Take the task from the sequence, so that its sequenced time is available
134*635a8641SAndroid Build Coastguard Worker // for the check below.
135*635a8641SAndroid Build Coastguard Worker auto take_foreground_task = foreground_sequence->TakeTask();
136*635a8641SAndroid Build Coastguard Worker
137*635a8641SAndroid Build Coastguard Worker // Verify the sort key.
138*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(TaskPriority::USER_VISIBLE, foreground_sort_key.priority());
139*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(take_foreground_task->sequenced_time,
140*635a8641SAndroid Build Coastguard Worker foreground_sort_key.next_task_sequenced_time());
141*635a8641SAndroid Build Coastguard Worker
142*635a8641SAndroid Build Coastguard Worker // Pop for correctness.
143*635a8641SAndroid Build Coastguard Worker foreground_sequence->Pop();
144*635a8641SAndroid Build Coastguard Worker }
145*635a8641SAndroid Build Coastguard Worker
146*635a8641SAndroid Build Coastguard Worker // Verify that a DCHECK fires if Pop() is called on a sequence whose front slot
147*635a8641SAndroid Build Coastguard Worker // isn't empty.
TEST(TaskSchedulerSequenceTest,PopNonEmptyFrontSlot)148*635a8641SAndroid Build Coastguard Worker TEST(TaskSchedulerSequenceTest, PopNonEmptyFrontSlot) {
149*635a8641SAndroid Build Coastguard Worker scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
150*635a8641SAndroid Build Coastguard Worker sequence->PushTask(Task(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta()));
151*635a8641SAndroid Build Coastguard Worker
152*635a8641SAndroid Build Coastguard Worker EXPECT_DCHECK_DEATH({ sequence->Pop(); });
153*635a8641SAndroid Build Coastguard Worker }
154*635a8641SAndroid Build Coastguard Worker
155*635a8641SAndroid Build Coastguard Worker // Verify that a DCHECK fires if TakeTask() is called on a sequence whose front
156*635a8641SAndroid Build Coastguard Worker // slot is empty.
TEST(TaskSchedulerSequenceTest,TakeEmptyFrontSlot)157*635a8641SAndroid Build Coastguard Worker TEST(TaskSchedulerSequenceTest, TakeEmptyFrontSlot) {
158*635a8641SAndroid Build Coastguard Worker scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
159*635a8641SAndroid Build Coastguard Worker sequence->PushTask(Task(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta()));
160*635a8641SAndroid Build Coastguard Worker
161*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(sequence->TakeTask());
162*635a8641SAndroid Build Coastguard Worker EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
163*635a8641SAndroid Build Coastguard Worker }
164*635a8641SAndroid Build Coastguard Worker
165*635a8641SAndroid Build Coastguard Worker // Verify that a DCHECK fires if TakeTask() is called on an empty sequence.
TEST(TaskSchedulerSequenceTest,TakeEmptySequence)166*635a8641SAndroid Build Coastguard Worker TEST(TaskSchedulerSequenceTest, TakeEmptySequence) {
167*635a8641SAndroid Build Coastguard Worker scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
168*635a8641SAndroid Build Coastguard Worker EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
169*635a8641SAndroid Build Coastguard Worker }
170*635a8641SAndroid Build Coastguard Worker
171*635a8641SAndroid Build Coastguard Worker } // namespace internal
172*635a8641SAndroid Build Coastguard Worker } // namespace base
173