blob: 86d1547e48e25e5b4242da604da34a08b2468e29 [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"
tzik5fe35262017-04-05 02:27:34 +090010#include "base/bind_helpers.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"
Robert Liao6ce6b3c2017-12-18 10:38:07 +090014#include "testing/gmock/include/gmock/gmock.h"
fdorayf4329522016-03-17 10:57:42 +090015#include "testing/gtest/include/gtest/gtest.h"
16
17namespace base {
18namespace internal {
19
20namespace {
21
Robert Liao6ce6b3c2017-12-18 10:38:07 +090022class MockTask {
fdorayf4329522016-03-17 10:57:42 +090023 public:
Robert Liao6ce6b3c2017-12-18 10:38:07 +090024 MOCK_METHOD0(Run, void());
fdorayf4329522016-03-17 10:57:42 +090025};
26
Robert Liao6ce6b3c2017-12-18 10:38:07 +090027Task CreateTask(MockTask* mock_task) {
28 return Task(FROM_HERE, BindOnce(&MockTask::Run, Unretained(mock_task)),
29 {TaskPriority::BACKGROUND}, TimeDelta());
30}
31
32void ExpectMockTask(MockTask* mock_task, Task* task) {
33 EXPECT_CALL(*mock_task, Run());
34 std::move(task->task).Run();
35 testing::Mock::VerifyAndClear(mock_task);
36}
37
fdorayf4329522016-03-17 10:57:42 +090038} // namespace
39
Robert Liao6ce6b3c2017-12-18 10:38:07 +090040TEST(TaskSchedulerSequenceTest, PushTakeRemove) {
41 testing::StrictMock<MockTask> mock_task_a;
42 testing::StrictMock<MockTask> mock_task_b;
43 testing::StrictMock<MockTask> mock_task_c;
44 testing::StrictMock<MockTask> mock_task_d;
45 testing::StrictMock<MockTask> mock_task_e;
fdorayf4329522016-03-17 10:57:42 +090046
Robert Liao6ce6b3c2017-12-18 10:38:07 +090047 scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
fdorayf4329522016-03-17 10:57:42 +090048
Robert Liao6ce6b3c2017-12-18 10:38:07 +090049 // Push task A in the sequence. PushTask() should return true since it's the
50 // first task->
51 EXPECT_TRUE(sequence->PushTask(CreateTask(&mock_task_a)));
fdorayf4329522016-03-17 10:57:42 +090052
Robert Liao6ce6b3c2017-12-18 10:38:07 +090053 // Push task B, C and D in the sequence. PushTask() should return false since
54 // there is already a task in a sequence.
55 EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_b)));
56 EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_c)));
57 EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_d)));
fdorayf4329522016-03-17 10:57:42 +090058
Robert Liao6ce6b3c2017-12-18 10:38:07 +090059 // Take the task in front of the sequence. It should be task A.
60 Optional<Task> task = sequence->TakeTask();
61 ExpectMockTask(&mock_task_a, &task.value());
62 EXPECT_FALSE(task->sequenced_time.is_null());
fdorayf4329522016-03-17 10:57:42 +090063
fdorayd7a33a62016-10-12 21:21:27 +090064 // Remove the empty slot. Task B should now be in front.
65 EXPECT_FALSE(sequence->Pop());
Robert Liao6ce6b3c2017-12-18 10:38:07 +090066 task = sequence->TakeTask();
67 ExpectMockTask(&mock_task_b, &task.value());
68 EXPECT_FALSE(task->sequenced_time.is_null());
fdorayf4329522016-03-17 10:57:42 +090069
fdorayd7a33a62016-10-12 21:21:27 +090070 // Remove the empty slot. Task C should now be in front.
71 EXPECT_FALSE(sequence->Pop());
Robert Liao6ce6b3c2017-12-18 10:38:07 +090072 task = sequence->TakeTask();
73 ExpectMockTask(&mock_task_c, &task.value());
74 EXPECT_FALSE(task->sequenced_time.is_null());
fdorayf4329522016-03-17 10:57:42 +090075
Robert Liao6ce6b3c2017-12-18 10:38:07 +090076 // Remove the empty slot.
fdorayd7a33a62016-10-12 21:21:27 +090077 EXPECT_FALSE(sequence->Pop());
fdorayd7a33a62016-10-12 21:21:27 +090078
Robert Liao6ce6b3c2017-12-18 10:38:07 +090079 // Push task E in the sequence.
80 EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_e)));
81
82 // Task D should be in front.
83 task = sequence->TakeTask();
84 ExpectMockTask(&mock_task_d, &task.value());
85 EXPECT_FALSE(task->sequenced_time.is_null());
fdorayf4329522016-03-17 10:57:42 +090086
fdorayd7a33a62016-10-12 21:21:27 +090087 // Remove the empty slot. Task E should now be in front.
88 EXPECT_FALSE(sequence->Pop());
Robert Liao6ce6b3c2017-12-18 10:38:07 +090089 task = sequence->TakeTask();
90 ExpectMockTask(&mock_task_e, &task.value());
91 EXPECT_FALSE(task->sequenced_time.is_null());
fdorayf4329522016-03-17 10:57:42 +090092
fdorayd7a33a62016-10-12 21:21:27 +090093 // Remove the empty slot. The sequence should now be empty.
94 EXPECT_TRUE(sequence->Pop());
fdorayf4329522016-03-17 10:57:42 +090095}
96
Robert Liao6ce6b3c2017-12-18 10:38:07 +090097// Verifies the sort key of a sequence that contains one BACKGROUND task.
98TEST(TaskSchedulerSequenceTest, GetSortKeyBackground) {
99 // Create a sequence with a BACKGROUND task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900100 Task background_task(FROM_HERE, DoNothing(), {TaskPriority::BACKGROUND},
101 TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900102 scoped_refptr<Sequence> background_sequence = MakeRefCounted<Sequence>();
103 background_sequence->PushTask(std::move(background_task));
fdorayf4329522016-03-17 10:57:42 +0900104
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900105 // Get the sort key.
106 const SequenceSortKey background_sort_key = background_sequence->GetSortKey();
fdorayf4329522016-03-17 10:57:42 +0900107
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900108 // Take the task from the sequence, so that its sequenced time is available
109 // for the check below.
110 auto take_background_task = background_sequence->TakeTask();
fdorayf4329522016-03-17 10:57:42 +0900111
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900112 // Verify the sort key.
113 EXPECT_EQ(TaskPriority::BACKGROUND, background_sort_key.priority());
114 EXPECT_EQ(take_background_task->sequenced_time,
115 background_sort_key.next_task_sequenced_time());
fdorayf4329522016-03-17 10:57:42 +0900116
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900117 // Pop for correctness.
118 background_sequence->Pop();
119}
fdorayf4329522016-03-17 10:57:42 +0900120
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900121// Same as TaskSchedulerSequenceTest.GetSortKeyBackground, but with a
122// USER_VISIBLE task.
123TEST(TaskSchedulerSequenceTest, GetSortKeyForeground) {
124 // Create a sequence with a USER_VISIBLE task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900125 Task foreground_task(FROM_HERE, DoNothing(), {TaskPriority::USER_VISIBLE},
126 TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900127 scoped_refptr<Sequence> foreground_sequence = MakeRefCounted<Sequence>();
128 foreground_sequence->PushTask(std::move(foreground_task));
fdorayf4329522016-03-17 10:57:42 +0900129
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900130 // Get the sort key.
131 const SequenceSortKey foreground_sort_key = foreground_sequence->GetSortKey();
fdorayf4329522016-03-17 10:57:42 +0900132
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900133 // Take the task from the sequence, so that its sequenced time is available
134 // for the check below.
135 auto take_foreground_task = foreground_sequence->TakeTask();
fdorayf4329522016-03-17 10:57:42 +0900136
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900137 // Verify the sort key.
138 EXPECT_EQ(TaskPriority::USER_VISIBLE, foreground_sort_key.priority());
139 EXPECT_EQ(take_foreground_task->sequenced_time,
140 foreground_sort_key.next_task_sequenced_time());
fdorayf4329522016-03-17 10:57:42 +0900141
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900142 // Pop for correctness.
143 foreground_sequence->Pop();
fdorayf4329522016-03-17 10:57:42 +0900144}
145
fdorayd7a33a62016-10-12 21:21:27 +0900146// Verify that a DCHECK fires if Pop() is called on a sequence whose front slot
147// isn't empty.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900148TEST(TaskSchedulerSequenceTest, PopNonEmptyFrontSlot) {
149 scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
Peter Kasting24efe5e2018-02-24 09:03:01 +0900150 sequence->PushTask(Task(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta()));
fdoray66f5a342016-07-22 06:22:59 +0900151
fdorayd7a33a62016-10-12 21:21:27 +0900152 EXPECT_DCHECK_DEATH({ sequence->Pop(); });
153}
fdoray66f5a342016-07-22 06:22:59 +0900154
fdorayd7a33a62016-10-12 21:21:27 +0900155// Verify that a DCHECK fires if TakeTask() is called on a sequence whose front
156// slot is empty.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900157TEST(TaskSchedulerSequenceTest, TakeEmptyFrontSlot) {
158 scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
Peter Kasting24efe5e2018-02-24 09:03:01 +0900159 sequence->PushTask(Task(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta()));
fdorayd7a33a62016-10-12 21:21:27 +0900160
161 EXPECT_TRUE(sequence->TakeTask());
162 EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
163}
164
165// Verify that a DCHECK fires if TakeTask() is called on an empty sequence.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900166TEST(TaskSchedulerSequenceTest, TakeEmptySequence) {
167 scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
fdorayd7a33a62016-10-12 21:21:27 +0900168 EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
fdoray66f5a342016-07-22 06:22:59 +0900169}
170
fdorayf4329522016-03-17 10:57:42 +0900171} // namespace internal
172} // namespace base