fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 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 | |
fdoray | 66f5a34 | 2016-07-22 06:22:59 +0900 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
| 9 | #include "base/bind.h" |
tzik | 5fe3526 | 2017-04-05 02:27:34 +0900 | [diff] [blame] | 10 | #include "base/bind_helpers.h" |
fdoray | 66f5a34 | 2016-07-22 06:22:59 +0900 | [diff] [blame] | 11 | #include "base/memory/ptr_util.h" |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 12 | #include "base/test/gtest_util.h" |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 13 | #include "base/time/time.h" |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 14 | #include "testing/gmock/include/gmock/gmock.h" |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 15 | #include "testing/gtest/include/gtest/gtest.h" |
| 16 | |
| 17 | namespace base { |
| 18 | namespace internal { |
| 19 | |
| 20 | namespace { |
| 21 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 22 | class MockTask { |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 23 | public: |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 24 | MOCK_METHOD0(Run, void()); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 25 | }; |
| 26 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 27 | Task CreateTask(MockTask* mock_task) { |
| 28 | return Task(FROM_HERE, BindOnce(&MockTask::Run, Unretained(mock_task)), |
| 29 | {TaskPriority::BACKGROUND}, TimeDelta()); |
| 30 | } |
| 31 | |
| 32 | void 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 | |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 38 | } // namespace |
| 39 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 40 | TEST(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; |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 46 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 47 | scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 48 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 49 | // 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))); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 52 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 53 | // 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))); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 58 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 59 | // 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()); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 63 | |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 64 | // Remove the empty slot. Task B should now be in front. |
| 65 | EXPECT_FALSE(sequence->Pop()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 66 | task = sequence->TakeTask(); |
| 67 | ExpectMockTask(&mock_task_b, &task.value()); |
| 68 | EXPECT_FALSE(task->sequenced_time.is_null()); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 69 | |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 70 | // Remove the empty slot. Task C should now be in front. |
| 71 | EXPECT_FALSE(sequence->Pop()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 72 | task = sequence->TakeTask(); |
| 73 | ExpectMockTask(&mock_task_c, &task.value()); |
| 74 | EXPECT_FALSE(task->sequenced_time.is_null()); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 75 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 76 | // Remove the empty slot. |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 77 | EXPECT_FALSE(sequence->Pop()); |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 78 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 79 | // 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()); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 86 | |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 87 | // Remove the empty slot. Task E should now be in front. |
| 88 | EXPECT_FALSE(sequence->Pop()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 89 | task = sequence->TakeTask(); |
| 90 | ExpectMockTask(&mock_task_e, &task.value()); |
| 91 | EXPECT_FALSE(task->sequenced_time.is_null()); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 92 | |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 93 | // Remove the empty slot. The sequence should now be empty. |
| 94 | EXPECT_TRUE(sequence->Pop()); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 95 | } |
| 96 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 97 | // Verifies the sort key of a sequence that contains one BACKGROUND task. |
| 98 | TEST(TaskSchedulerSequenceTest, GetSortKeyBackground) { |
| 99 | // Create a sequence with a BACKGROUND task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 100 | Task background_task(FROM_HERE, DoNothing(), {TaskPriority::BACKGROUND}, |
| 101 | TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 102 | scoped_refptr<Sequence> background_sequence = MakeRefCounted<Sequence>(); |
| 103 | background_sequence->PushTask(std::move(background_task)); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 104 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 105 | // Get the sort key. |
| 106 | const SequenceSortKey background_sort_key = background_sequence->GetSortKey(); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 107 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 108 | // 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(); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 111 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 112 | // 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()); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 116 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 117 | // Pop for correctness. |
| 118 | background_sequence->Pop(); |
| 119 | } |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 120 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 121 | // Same as TaskSchedulerSequenceTest.GetSortKeyBackground, but with a |
| 122 | // USER_VISIBLE task. |
| 123 | TEST(TaskSchedulerSequenceTest, GetSortKeyForeground) { |
| 124 | // Create a sequence with a USER_VISIBLE task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 125 | Task foreground_task(FROM_HERE, DoNothing(), {TaskPriority::USER_VISIBLE}, |
| 126 | TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 127 | scoped_refptr<Sequence> foreground_sequence = MakeRefCounted<Sequence>(); |
| 128 | foreground_sequence->PushTask(std::move(foreground_task)); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 129 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 130 | // Get the sort key. |
| 131 | const SequenceSortKey foreground_sort_key = foreground_sequence->GetSortKey(); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 132 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 133 | // 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(); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 136 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 137 | // 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()); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 141 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 142 | // Pop for correctness. |
| 143 | foreground_sequence->Pop(); |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 144 | } |
| 145 | |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 146 | // Verify that a DCHECK fires if Pop() is called on a sequence whose front slot |
| 147 | // isn't empty. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 148 | TEST(TaskSchedulerSequenceTest, PopNonEmptyFrontSlot) { |
| 149 | scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 150 | sequence->PushTask(Task(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta())); |
fdoray | 66f5a34 | 2016-07-22 06:22:59 +0900 | [diff] [blame] | 151 | |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 152 | EXPECT_DCHECK_DEATH({ sequence->Pop(); }); |
| 153 | } |
fdoray | 66f5a34 | 2016-07-22 06:22:59 +0900 | [diff] [blame] | 154 | |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 155 | // Verify that a DCHECK fires if TakeTask() is called on a sequence whose front |
| 156 | // slot is empty. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 157 | TEST(TaskSchedulerSequenceTest, TakeEmptyFrontSlot) { |
| 158 | scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 159 | sequence->PushTask(Task(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta())); |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 160 | |
| 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 Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 166 | TEST(TaskSchedulerSequenceTest, TakeEmptySequence) { |
| 167 | scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 168 | EXPECT_DCHECK_DEATH({ sequence->TakeTask(); }); |
fdoray | 66f5a34 | 2016-07-22 06:22:59 +0900 | [diff] [blame] | 169 | } |
| 170 | |
fdoray | f432952 | 2016-03-17 10:57:42 +0900 | [diff] [blame] | 171 | } // namespace internal |
| 172 | } // namespace base |