xref: /aosp_15_r20/external/cronet/base/task/sequence_manager/task_queue_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2019 The Chromium Authors
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/sequence_manager/task_queue.h"
6 
7 #include "base/message_loop/message_pump.h"
8 #include "base/message_loop/message_pump_type.h"
9 #include "base/task/sequence_manager/sequence_manager.h"
10 #include "base/task/sequence_manager/test/sequence_manager_for_test.h"
11 #include "base/task/single_thread_task_runner.h"
12 #include "base/task/task_features.h"
13 #include "base/test/bind.h"
14 #include "base/test/scoped_feature_list.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace base {
18 namespace sequence_manager {
19 namespace internal {
20 // To avoid symbol collisions in jumbo builds.
21 namespace task_queue_unittest {
22 namespace {
23 
TEST(TaskQueueTest,TaskQueueVoters)24 TEST(TaskQueueTest, TaskQueueVoters) {
25   auto sequence_manager = CreateSequenceManagerOnCurrentThreadWithPump(
26       MessagePump::Create(MessagePumpType::DEFAULT));
27 
28   auto queue =
29       sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST_TQ));
30 
31   // The task queue should be initially enabled.
32   EXPECT_TRUE(queue->IsQueueEnabled());
33 
34   std::unique_ptr<TaskQueue::QueueEnabledVoter> voter1 =
35       queue->CreateQueueEnabledVoter();
36   std::unique_ptr<TaskQueue::QueueEnabledVoter> voter2 =
37       queue->CreateQueueEnabledVoter();
38   std::unique_ptr<TaskQueue::QueueEnabledVoter> voter3 =
39       queue->CreateQueueEnabledVoter();
40   std::unique_ptr<TaskQueue::QueueEnabledVoter> voter4 =
41       queue->CreateQueueEnabledVoter();
42 
43   // Voters should initially vote for the queue to be enabled.
44   EXPECT_TRUE(queue->IsQueueEnabled());
45 
46   // If any voter wants to disable, the queue is disabled.
47   voter1->SetVoteToEnable(false);
48   EXPECT_FALSE(queue->IsQueueEnabled());
49 
50   // If the voter is deleted then the queue should be re-enabled.
51   voter1.reset();
52   EXPECT_TRUE(queue->IsQueueEnabled());
53 
54   // If any of the remaining voters wants to disable, the queue should be
55   // disabled.
56   voter2->SetVoteToEnable(false);
57   EXPECT_FALSE(queue->IsQueueEnabled());
58 
59   // If another queue votes to disable, nothing happens because it's already
60   // disabled.
61   voter3->SetVoteToEnable(false);
62   EXPECT_FALSE(queue->IsQueueEnabled());
63 
64   // There are two votes to disable, so one of them voting to enable does
65   // nothing.
66   voter2->SetVoteToEnable(true);
67   EXPECT_FALSE(queue->IsQueueEnabled());
68 
69   // IF all queues vote to enable then the queue is enabled.
70   voter3->SetVoteToEnable(true);
71   EXPECT_TRUE(queue->IsQueueEnabled());
72 }
73 
TEST(TaskQueueTest,ShutdownQueueBeforeEnabledVoterDeleted)74 TEST(TaskQueueTest, ShutdownQueueBeforeEnabledVoterDeleted) {
75   auto sequence_manager = CreateSequenceManagerOnCurrentThreadWithPump(
76       MessagePump::Create(MessagePumpType::DEFAULT));
77   auto queue =
78       sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST_TQ));
79 
80   std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
81       queue->CreateQueueEnabledVoter();
82 
83   voter->SetVoteToEnable(true);  // NOP
84   queue.reset();
85 
86   // This should complete without DCHECKing.
87   voter.reset();
88 }
89 
TEST(TaskQueueTest,ShutdownQueueBeforeDisabledVoterDeleted)90 TEST(TaskQueueTest, ShutdownQueueBeforeDisabledVoterDeleted) {
91   auto sequence_manager = CreateSequenceManagerOnCurrentThreadWithPump(
92       MessagePump::Create(MessagePumpType::DEFAULT));
93   auto queue =
94       sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST_TQ));
95 
96   std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
97       queue->CreateQueueEnabledVoter();
98 
99   voter->SetVoteToEnable(false);
100   queue.reset();
101 
102   // This should complete without DCHECKing.
103   voter.reset();
104 }
105 
TEST(TaskQueueTest,CanceledTaskRemoved)106 TEST(TaskQueueTest, CanceledTaskRemoved) {
107   auto sequence_manager = CreateSequenceManagerOnCurrentThreadWithPump(
108       MessagePump::Create(MessagePumpType::DEFAULT));
109   auto queue =
110       sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST_TQ));
111 
112   // Get the default task runner.
113   auto task_runner = queue->task_runner();
114   EXPECT_EQ(queue->GetNumberOfPendingTasks(), 0u);
115 
116   bool task_ran = false;
117   DelayedTaskHandle delayed_task_handle =
118       task_runner->PostCancelableDelayedTask(
119           subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
120           BindLambdaForTesting([&task_ran]() { task_ran = true; }),
121           Seconds(20));
122   EXPECT_EQ(queue->GetNumberOfPendingTasks(), 1u);
123 
124   // The task is only removed from the queue if the feature is enabled.
125   delayed_task_handle.CancelTask();
126   EXPECT_EQ(queue->GetNumberOfPendingTasks(), 0u);
127 
128   // In any case, the task never actually ran.
129   EXPECT_FALSE(task_ran);
130 }
131 
132 // Tests that a task posted through `PostCancelableDelayedTask()` is not
133 // considered canceled once it has reached the |delayed_work_queue| and is
134 // therefore not removed.
135 //
136 // This is a regression test for a bug in `Task::IsCanceled()` (see
137 // https://crbug.com/1288882). Note that this function is only called on tasks
138 // inside the |delayed_work_queue|, and not for tasks in the
139 // |delayed_incoming_queue|. This is because a task posted through
140 // `PostCancelableDelayedTask()` is always valid while it is in the
141 // |delayed_incoming_queue|, since canceling it would remove it from the queue.
TEST(TaskQueueTest,ValidCancelableTaskIsNotCanceled)142 TEST(TaskQueueTest, ValidCancelableTaskIsNotCanceled) {
143   auto sequence_manager = CreateSequenceManagerOnCurrentThreadWithPump(
144       MessagePump::Create(MessagePumpType::DEFAULT));
145   auto queue =
146       sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST_TQ));
147 
148   // Get the default task runner.
149   auto task_runner = queue->task_runner();
150   EXPECT_EQ(queue->GetNumberOfPendingTasks(), 0u);
151 
152   // RunLoop requires the SingleThreadTaskRunner::CurrentDefaultHandle to be
153   // set.
154   SingleThreadTaskRunner::CurrentDefaultHandle
155       single_thread_task_runner_current_default_handle(task_runner);
156   RunLoop run_loop;
157 
158   // To reach the |delayed_work_queue|, the task must be posted with a non-
159   // zero delay, which is then moved to the |delayed_work_queue| when it is
160   // ripe. To achieve this, run the RunLoop for exactly the same delay of the
161   // cancelable task. Since real time waiting happens, chose a very small delay.
162   constexpr TimeDelta kTestDelay = Microseconds(1);
163   task_runner->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), kTestDelay);
164 
165   DelayedTaskHandle delayed_task_handle =
166       task_runner->PostCancelableDelayedTask(
167           subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE, DoNothing(),
168           kTestDelay);
169   run_loop.Run();
170 
171   // Now only the cancelable delayed task remains and it is ripe.
172   EXPECT_EQ(queue->GetNumberOfPendingTasks(), 1u);
173 
174   // ReclaimMemory doesn't remove the task because it is valid (not canceled).
175   sequence_manager->ReclaimMemory();
176   EXPECT_EQ(queue->GetNumberOfPendingTasks(), 1u);
177 
178   // Clean-up.
179   delayed_task_handle.CancelTask();
180 }
181 
182 }  // namespace
183 }  // namespace task_queue_unittest
184 }  // namespace internal
185 }  // namespace sequence_manager
186 }  // namespace base
187