blob: de6cfdbd2be107c2d17df4bea7b919df63de6901 [file] [log] [blame]
Sebastian Janssonecb68972019-01-18 09:30:541/*
2 * Copyright 2019 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Jonas Olssona4d87372019-07-05 17:08:3311#include "rtc_base/task_utils/repeating_task.h"
12
Sebastian Janssonecb68972019-01-18 09:30:5413#include <atomic>
Sebastian Janssonecb68972019-01-18 09:30:5414#include <memory>
Sebastian Janssonecb68972019-01-18 09:30:5415
Danil Chapovalovdde7fe42022-07-05 19:26:0616#include "absl/functional/any_invocable.h"
Danil Chapovalov91ebd5f2024-02-26 17:09:3817#include "absl/types/optional.h"
Evan Shrubsolef0f47432021-11-15 16:24:4518#include "api/task_queue/task_queue_base.h"
Markus Handella1ceae22023-03-01 09:13:2819#include "api/task_queue/test/mock_task_queue_base.h"
Danil Chapovalovdde7fe42022-07-05 19:26:0620#include "api/units/time_delta.h"
Evan Shrubsolef0f47432021-11-15 16:24:4521#include "api/units/timestamp.h"
Sebastian Janssonecb68972019-01-18 09:30:5422#include "rtc_base/event.h"
Danil Chapovalov07122bc2019-03-26 13:37:0123#include "rtc_base/task_queue_for_test.h"
Evan Shrubsolef0f47432021-11-15 16:24:4524#include "system_wrappers/include/clock.h"
Sebastian Janssonecb68972019-01-18 09:30:5425#include "test/gmock.h"
26#include "test/gtest.h"
27
28// NOTE: Since these tests rely on real time behavior, they will be flaky
29// if run on heavily loaded systems.
30namespace webrtc {
31namespace {
32using ::testing::AtLeast;
33using ::testing::Invoke;
34using ::testing::MockFunction;
35using ::testing::NiceMock;
36using ::testing::Return;
Markus Handella1ceae22023-03-01 09:13:2837using ::testing::WithArg;
Sebastian Janssonecb68972019-01-18 09:30:5438
Danil Chapovalov0c626af2020-02-10 10:16:0039constexpr TimeDelta kTimeout = TimeDelta::Millis(1000);
Sebastian Janssonecb68972019-01-18 09:30:5440
Sebastian Janssonecb68972019-01-18 09:30:5441class MockClosure {
42 public:
Danil Chapovalov42748d82020-05-14 18:42:4143 MOCK_METHOD(TimeDelta, Call, ());
44 MOCK_METHOD(void, Delete, ());
Sebastian Janssonecb68972019-01-18 09:30:5445};
46
Markus Handella1ceae22023-03-01 09:13:2847class MockTaskQueue : public MockTaskQueueBase {
Tommi532cac52020-05-18 12:53:4248 public:
49 MockTaskQueue() : task_queue_setter_(this) {}
50
Tommi532cac52020-05-18 12:53:4251 private:
52 CurrentTaskQueueSetter task_queue_setter_;
53};
54
Evan Shrubsolef0f47432021-11-15 16:24:4555class FakeTaskQueue : public TaskQueueBase {
56 public:
57 explicit FakeTaskQueue(SimulatedClock* clock)
58 : task_queue_setter_(this), clock_(clock) {}
59
60 void Delete() override {}
61
Markus Handella1ceae22023-03-01 09:13:2862 void PostTaskImpl(absl::AnyInvocable<void() &&> task,
63 const PostTaskTraits& /*traits*/,
64 const Location& /*location*/) override {
Henrik Boström27e8a092022-01-24 16:12:3565 last_task_ = std::move(task);
66 last_precision_ = absl::nullopt;
Danil Chapovalovdde7fe42022-07-05 19:26:0667 last_delay_ = TimeDelta::Zero();
Evan Shrubsolef0f47432021-11-15 16:24:4568 }
69
Markus Handella1ceae22023-03-01 09:13:2870 void PostDelayedTaskImpl(absl::AnyInvocable<void() &&> task,
71 TimeDelta delay,
72 const PostDelayedTaskTraits& traits,
73 const Location& /*location*/) override {
Evan Shrubsolef0f47432021-11-15 16:24:4574 last_task_ = std::move(task);
Markus Handella1ceae22023-03-01 09:13:2875 last_precision_ = traits.high_precision
76 ? TaskQueueBase::DelayPrecision::kHigh
77 : TaskQueueBase::DelayPrecision::kLow;
Danil Chapovalovdde7fe42022-07-05 19:26:0678 last_delay_ = delay;
Evan Shrubsolef0f47432021-11-15 16:24:4579 }
80
81 bool AdvanceTimeAndRunLastTask() {
82 EXPECT_TRUE(last_task_);
Danil Chapovalovdde7fe42022-07-05 19:26:0683 EXPECT_TRUE(last_delay_.IsFinite());
84 clock_->AdvanceTime(last_delay_);
85 last_delay_ = TimeDelta::MinusInfinity();
Evan Shrubsolef0f47432021-11-15 16:24:4586 auto task = std::move(last_task_);
Danil Chapovalovdde7fe42022-07-05 19:26:0687 std::move(task)();
88 return last_task_ == nullptr;
Evan Shrubsolef0f47432021-11-15 16:24:4589 }
90
91 bool IsTaskQueued() { return !!last_task_; }
92
Danil Chapovalovdde7fe42022-07-05 19:26:0693 TimeDelta last_delay() const {
94 EXPECT_TRUE(last_delay_.IsFinite());
95 return last_delay_;
Evan Shrubsolef0f47432021-11-15 16:24:4596 }
97
Henrik Boström27e8a092022-01-24 16:12:3598 absl::optional<TaskQueueBase::DelayPrecision> last_precision() const {
99 return last_precision_;
100 }
101
Evan Shrubsolef0f47432021-11-15 16:24:45102 private:
103 CurrentTaskQueueSetter task_queue_setter_;
104 SimulatedClock* clock_;
Danil Chapovalovdde7fe42022-07-05 19:26:06105 absl::AnyInvocable<void() &&> last_task_;
106 TimeDelta last_delay_ = TimeDelta::MinusInfinity();
Henrik Boström27e8a092022-01-24 16:12:35107 absl::optional<TaskQueueBase::DelayPrecision> last_precision_;
Evan Shrubsolef0f47432021-11-15 16:24:45108};
109
Tomas Gunnarsson87e7b3dd2022-01-17 08:58:45110// NOTE: Since this utility class holds a raw pointer to a variable that likely
111// lives on the stack, it's important that any repeating tasks that use this
112// class be explicitly stopped when the test criteria have been met. If the
113// task is not stopped, an instance of this class can be deleted when the
114// pointed-to MockClosure has been deleted and we end up trying to call a
115// virtual method on a deleted object in the dtor.
Sebastian Janssonecb68972019-01-18 09:30:54116class MoveOnlyClosure {
117 public:
118 explicit MoveOnlyClosure(MockClosure* mock) : mock_(mock) {}
119 MoveOnlyClosure(const MoveOnlyClosure&) = delete;
120 MoveOnlyClosure(MoveOnlyClosure&& other) : mock_(other.mock_) {
121 other.mock_ = nullptr;
122 }
123 ~MoveOnlyClosure() {
124 if (mock_)
125 mock_->Delete();
126 }
127 TimeDelta operator()() { return mock_->Call(); }
128
129 private:
130 MockClosure* mock_;
131};
132} // namespace
133
134TEST(RepeatingTaskTest, TaskIsStoppedOnStop) {
Danil Chapovalov0c626af2020-02-10 10:16:00135 const TimeDelta kShortInterval = TimeDelta::Millis(50);
Sebastian Janssonecb68972019-01-18 09:30:54136
Evan Shrubsolef0f47432021-11-15 16:24:45137 SimulatedClock clock(Timestamp::Zero());
138 FakeTaskQueue task_queue(&clock);
Sebastian Janssonecb68972019-01-18 09:30:54139 std::atomic_int counter(0);
Danil Chapovalovdde7fe42022-07-05 19:26:06140 auto handle = RepeatingTaskHandle::Start(
141 &task_queue,
142 [&] {
143 counter++;
144 return kShortInterval;
145 },
146 TaskQueueBase::DelayPrecision::kLow, &clock);
147 EXPECT_EQ(task_queue.last_delay(), TimeDelta::Zero());
Evan Shrubsolef0f47432021-11-15 16:24:45148 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
149 EXPECT_EQ(counter.load(), 1);
Sebastian Janssonecb68972019-01-18 09:30:54150
Evan Shrubsolef0f47432021-11-15 16:24:45151 // The handle reposted at the short interval.
Danil Chapovalovdde7fe42022-07-05 19:26:06152 EXPECT_EQ(task_queue.last_delay(), kShortInterval);
Evan Shrubsolef0f47432021-11-15 16:24:45153
154 // Stop the handle. This prevernts the counter from incrementing.
155 handle.Stop();
156 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
157 EXPECT_EQ(counter.load(), 1);
Sebastian Janssonecb68972019-01-18 09:30:54158}
159
160TEST(RepeatingTaskTest, CompensatesForLongRunTime) {
Danil Chapovalov0c626af2020-02-10 10:16:00161 const TimeDelta kRepeatInterval = TimeDelta::Millis(2);
Sebastian Janssonecb68972019-01-18 09:30:54162 // Sleeping inside the task for longer than the repeat interval once, should
163 // be compensated for by repeating the task faster to catch up.
Danil Chapovalov0c626af2020-02-10 10:16:00164 const TimeDelta kSleepDuration = TimeDelta::Millis(20);
Sebastian Janssonecb68972019-01-18 09:30:54165
166 std::atomic_int counter(0);
Evan Shrubsolef0f47432021-11-15 16:24:45167 SimulatedClock clock(Timestamp::Zero());
168 FakeTaskQueue task_queue(&clock);
169 RepeatingTaskHandle::Start(
170 &task_queue,
171 [&] {
172 ++counter;
173 // Task takes longer than the repeat duration.
174 clock.AdvanceTime(kSleepDuration);
175 return kRepeatInterval;
176 },
Henrik Boström27e8a092022-01-24 16:12:35177 TaskQueueBase::DelayPrecision::kLow, &clock);
Evan Shrubsolef0f47432021-11-15 16:24:45178
Danil Chapovalovdde7fe42022-07-05 19:26:06179 EXPECT_EQ(task_queue.last_delay(), TimeDelta::Zero());
Evan Shrubsolef0f47432021-11-15 16:24:45180 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
181
182 // Task is posted right away since it took longer to run then the repeat
183 // interval.
Danil Chapovalovdde7fe42022-07-05 19:26:06184 EXPECT_EQ(task_queue.last_delay(), TimeDelta::Zero());
Evan Shrubsolef0f47432021-11-15 16:24:45185 EXPECT_EQ(counter.load(), 1);
Sebastian Janssonecb68972019-01-18 09:30:54186}
187
188TEST(RepeatingTaskTest, CompensatesForShortRunTime) {
Philipp Hanckea204ad22022-07-08 16:43:25189 SimulatedClock clock(Timestamp::Zero());
Evan Shrubsolef0f47432021-11-15 16:24:45190 FakeTaskQueue task_queue(&clock);
Sebastian Janssonecb68972019-01-18 09:30:54191 std::atomic_int counter(0);
Evan Shrubsolef0f47432021-11-15 16:24:45192 RepeatingTaskHandle::Start(
193 &task_queue,
194 [&] {
195 // Simulate the task taking 100ms, which should be compensated for.
196 counter++;
197 clock.AdvanceTime(TimeDelta::Millis(100));
198 return TimeDelta::Millis(300);
199 },
Henrik Boström27e8a092022-01-24 16:12:35200 TaskQueueBase::DelayPrecision::kLow, &clock);
Sebastian Janssona497d122019-02-04 15:39:28201
Evan Shrubsolef0f47432021-11-15 16:24:45202 // Expect instant post task.
Danil Chapovalovdde7fe42022-07-05 19:26:06203 EXPECT_EQ(task_queue.last_delay(), TimeDelta::Zero());
Evan Shrubsolef0f47432021-11-15 16:24:45204 // Task should be retained by the handler since it is not cancelled.
205 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
206 // New delay should be 200ms since repeat delay was 300ms but task took 100ms.
Danil Chapovalovdde7fe42022-07-05 19:26:06207 EXPECT_EQ(task_queue.last_delay(), TimeDelta::Millis(200));
Sebastian Janssonecb68972019-01-18 09:30:54208}
209
210TEST(RepeatingTaskTest, CancelDelayedTaskBeforeItRuns) {
211 rtc::Event done;
212 MockClosure mock;
213 EXPECT_CALL(mock, Call).Times(0);
214 EXPECT_CALL(mock, Delete).WillOnce(Invoke([&done] { done.Set(); }));
Danil Chapovalov07122bc2019-03-26 13:37:01215 TaskQueueForTest task_queue("queue");
Sebastian Janssonecb68972019-01-18 09:30:54216 auto handle = RepeatingTaskHandle::DelayedStart(
Danil Chapovalov0c626af2020-02-10 10:16:00217 task_queue.Get(), TimeDelta::Millis(100), MoveOnlyClosure(&mock));
Sebastian Jansson86314cf2019-09-17 18:29:59218 task_queue.PostTask(
219 [handle = std::move(handle)]() mutable { handle.Stop(); });
Markus Handell2cfc1af2022-08-19 08:16:48220 EXPECT_TRUE(done.Wait(kTimeout));
Sebastian Janssonecb68972019-01-18 09:30:54221}
222
223TEST(RepeatingTaskTest, CancelTaskAfterItRuns) {
224 rtc::Event done;
225 MockClosure mock;
Danil Chapovalov0c626af2020-02-10 10:16:00226 EXPECT_CALL(mock, Call).WillOnce(Return(TimeDelta::Millis(100)));
Sebastian Janssonecb68972019-01-18 09:30:54227 EXPECT_CALL(mock, Delete).WillOnce(Invoke([&done] { done.Set(); }));
Danil Chapovalov07122bc2019-03-26 13:37:01228 TaskQueueForTest task_queue("queue");
Danil Chapovalov4423c362019-03-06 17:41:39229 auto handle =
230 RepeatingTaskHandle::Start(task_queue.Get(), MoveOnlyClosure(&mock));
Sebastian Jansson86314cf2019-09-17 18:29:59231 task_queue.PostTask(
232 [handle = std::move(handle)]() mutable { handle.Stop(); });
Markus Handell2cfc1af2022-08-19 08:16:48233 EXPECT_TRUE(done.Wait(kTimeout));
Sebastian Janssonecb68972019-01-18 09:30:54234}
235
236TEST(RepeatingTaskTest, TaskCanStopItself) {
237 std::atomic_int counter(0);
Evan Shrubsolef0f47432021-11-15 16:24:45238 SimulatedClock clock(Timestamp::Zero());
239 FakeTaskQueue task_queue(&clock);
240 RepeatingTaskHandle handle = RepeatingTaskHandle::Start(&task_queue, [&] {
241 ++counter;
242 handle.Stop();
243 return TimeDelta::Millis(2);
Sebastian Janssonecb68972019-01-18 09:30:54244 });
Danil Chapovalovdde7fe42022-07-05 19:26:06245 EXPECT_EQ(task_queue.last_delay(), TimeDelta::Zero());
Evan Shrubsolef0f47432021-11-15 16:24:45246 // Task cancelled itself so wants to be released.
247 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
Sebastian Janssonecb68972019-01-18 09:30:54248 EXPECT_EQ(counter.load(), 1);
249}
250
Niels Möller902b5542022-01-17 14:20:24251TEST(RepeatingTaskTest, TaskCanStopItselfByReturningInfinity) {
252 std::atomic_int counter(0);
253 SimulatedClock clock(Timestamp::Zero());
254 FakeTaskQueue task_queue(&clock);
255 RepeatingTaskHandle handle = RepeatingTaskHandle::Start(&task_queue, [&] {
256 ++counter;
257 return TimeDelta::PlusInfinity();
258 });
Danil Chapovalovdde7fe42022-07-05 19:26:06259 EXPECT_EQ(task_queue.last_delay(), TimeDelta::Zero());
Niels Möller902b5542022-01-17 14:20:24260 // Task cancelled itself so wants to be released.
261 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
262 EXPECT_EQ(counter.load(), 1);
263}
264
Sebastian Janssonecb68972019-01-18 09:30:54265TEST(RepeatingTaskTest, ZeroReturnValueRepostsTheTask) {
266 NiceMock<MockClosure> closure;
267 rtc::Event done;
268 EXPECT_CALL(closure, Call())
269 .WillOnce(Return(TimeDelta::Zero()))
Tomas Gunnarsson87e7b3dd2022-01-17 08:58:45270 .WillOnce(Invoke([&] {
Sebastian Janssonecb68972019-01-18 09:30:54271 done.Set();
Niels Möller902b5542022-01-17 14:20:24272 return TimeDelta::PlusInfinity();
Sebastian Janssonecb68972019-01-18 09:30:54273 }));
Danil Chapovalov07122bc2019-03-26 13:37:01274 TaskQueueForTest task_queue("queue");
Niels Möller902b5542022-01-17 14:20:24275 RepeatingTaskHandle::Start(task_queue.Get(), MoveOnlyClosure(&closure));
Markus Handell2cfc1af2022-08-19 08:16:48276 EXPECT_TRUE(done.Wait(kTimeout));
Sebastian Janssonecb68972019-01-18 09:30:54277}
278
279TEST(RepeatingTaskTest, StartPeriodicTask) {
280 MockFunction<TimeDelta()> closure;
281 rtc::Event done;
282 EXPECT_CALL(closure, Call())
Danil Chapovalov0c626af2020-02-10 10:16:00283 .WillOnce(Return(TimeDelta::Millis(20)))
284 .WillOnce(Return(TimeDelta::Millis(20)))
Tomas Gunnarsson87e7b3dd2022-01-17 08:58:45285 .WillOnce(Invoke([&] {
Sebastian Janssonecb68972019-01-18 09:30:54286 done.Set();
Niels Möller902b5542022-01-17 14:20:24287 return TimeDelta::PlusInfinity();
Sebastian Janssonecb68972019-01-18 09:30:54288 }));
Danil Chapovalov07122bc2019-03-26 13:37:01289 TaskQueueForTest task_queue("queue");
Danil Chapovalov4423c362019-03-06 17:41:39290 RepeatingTaskHandle::Start(task_queue.Get(), closure.AsStdFunction());
Markus Handell2cfc1af2022-08-19 08:16:48291 EXPECT_TRUE(done.Wait(kTimeout));
Sebastian Janssonecb68972019-01-18 09:30:54292}
293
294TEST(RepeatingTaskTest, Example) {
295 class ObjectOnTaskQueue {
296 public:
297 void DoPeriodicTask() {}
Danil Chapovalov0c626af2020-02-10 10:16:00298 TimeDelta TimeUntilNextRun() { return TimeDelta::Millis(100); }
Sebastian Janssonecb68972019-01-18 09:30:54299 void StartPeriodicTask(RepeatingTaskHandle* handle,
Danil Chapovalov4423c362019-03-06 17:41:39300 TaskQueueBase* task_queue) {
Sebastian Janssonecb68972019-01-18 09:30:54301 *handle = RepeatingTaskHandle::Start(task_queue, [this] {
302 DoPeriodicTask();
303 return TimeUntilNextRun();
304 });
305 }
306 };
Danil Chapovalov07122bc2019-03-26 13:37:01307 TaskQueueForTest task_queue("queue");
Mirko Bonadei317a1f02019-09-17 15:06:18308 auto object = std::make_unique<ObjectOnTaskQueue>();
Sebastian Janssonecb68972019-01-18 09:30:54309 // Create and start the periodic task.
310 RepeatingTaskHandle handle;
Danil Chapovalov4423c362019-03-06 17:41:39311 object->StartPeriodicTask(&handle, task_queue.Get());
Sebastian Janssonecb68972019-01-18 09:30:54312 // Restart the task
Sebastian Jansson86314cf2019-09-17 18:29:59313 task_queue.PostTask(
314 [handle = std::move(handle)]() mutable { handle.Stop(); });
Danil Chapovalov4423c362019-03-06 17:41:39315 object->StartPeriodicTask(&handle, task_queue.Get());
Sebastian Jansson86314cf2019-09-17 18:29:59316 task_queue.PostTask(
317 [handle = std::move(handle)]() mutable { handle.Stop(); });
Sebastian Janssonecb68972019-01-18 09:30:54318 struct Destructor {
319 void operator()() { object.reset(); }
320 std::unique_ptr<ObjectOnTaskQueue> object;
321 };
322 task_queue.PostTask(Destructor{std::move(object)});
323 // Do not wait for the destructor closure in order to create a race between
324 // task queue destruction and running the desctructor closure.
325}
326
Tommi532cac52020-05-18 12:53:42327TEST(RepeatingTaskTest, ClockIntegration) {
Danil Chapovalovdde7fe42022-07-05 19:26:06328 absl::AnyInvocable<void() &&> delayed_task;
329 TimeDelta expected_delay = TimeDelta::Zero();
Philipp Hanckea204ad22022-07-08 16:43:25330 SimulatedClock clock(Timestamp::Zero());
Tommi532cac52020-05-18 12:53:42331
332 NiceMock<MockTaskQueue> task_queue;
Markus Handella1ceae22023-03-01 09:13:28333 ON_CALL(task_queue, PostDelayedTaskImpl)
334 .WillByDefault([&](absl::AnyInvocable<void() &&> task, TimeDelta delay,
335 const MockTaskQueue::PostDelayedTaskTraits&,
336 const Location&) {
Danil Chapovalovdde7fe42022-07-05 19:26:06337 EXPECT_EQ(delay, expected_delay);
338 delayed_task = std::move(task);
339 });
Tommi532cac52020-05-18 12:53:42340
Danil Chapovalovdde7fe42022-07-05 19:26:06341 expected_delay = TimeDelta::Millis(100);
Tommi532cac52020-05-18 12:53:42342 RepeatingTaskHandle handle = RepeatingTaskHandle::DelayedStart(
343 &task_queue, TimeDelta::Millis(100),
344 [&clock]() {
345 EXPECT_EQ(Timestamp::Millis(100), clock.CurrentTime());
346 // Simulate work happening for 10ms.
347 clock.AdvanceTimeMilliseconds(10);
348 return TimeDelta::Millis(100);
349 },
Henrik Boström27e8a092022-01-24 16:12:35350 TaskQueueBase::DelayPrecision::kLow, &clock);
Tommi532cac52020-05-18 12:53:42351
352 clock.AdvanceTimeMilliseconds(100);
Danil Chapovalovdde7fe42022-07-05 19:26:06353 absl::AnyInvocable<void()&&> task_to_run = std::move(delayed_task);
354 expected_delay = TimeDelta::Millis(90);
355 std::move(task_to_run)();
356 EXPECT_NE(delayed_task, nullptr);
Tommi532cac52020-05-18 12:53:42357 handle.Stop();
358}
359
Danil Chapovalov0f9a8e332021-06-11 16:39:17360TEST(RepeatingTaskTest, CanBeStoppedAfterTaskQueueDeletedTheRepeatingTask) {
Danil Chapovalovdde7fe42022-07-05 19:26:06361 absl::AnyInvocable<void() &&> repeating_task;
Danil Chapovalov0f9a8e332021-06-11 16:39:17362
363 MockTaskQueue task_queue;
Markus Handella1ceae22023-03-01 09:13:28364 EXPECT_CALL(task_queue, PostDelayedTaskImpl)
365 .WillOnce(WithArg<0>([&](absl::AnyInvocable<void() &&> task) {
Danil Chapovalov0f9a8e332021-06-11 16:39:17366 repeating_task = std::move(task);
Markus Handella1ceae22023-03-01 09:13:28367 }));
Danil Chapovalov0f9a8e332021-06-11 16:39:17368
369 RepeatingTaskHandle handle =
370 RepeatingTaskHandle::DelayedStart(&task_queue, TimeDelta::Millis(100),
371 [] { return TimeDelta::Millis(100); });
372
373 // shutdown task queue: delete all pending tasks and run 'regular' task.
374 repeating_task = nullptr;
375 handle.Stop();
376}
377
Henrik Boström27e8a092022-01-24 16:12:35378TEST(RepeatingTaskTest, DefaultPrecisionIsLow) {
379 SimulatedClock clock(Timestamp::Zero());
380 FakeTaskQueue task_queue(&clock);
381 // Closure that repeats twice.
382 MockFunction<TimeDelta()> closure;
383 EXPECT_CALL(closure, Call())
384 .WillOnce(Return(TimeDelta::Millis(1)))
385 .WillOnce(Return(TimeDelta::PlusInfinity()));
386 RepeatingTaskHandle::Start(&task_queue, closure.AsStdFunction());
387 // Initial task is a PostTask().
388 EXPECT_FALSE(task_queue.last_precision().has_value());
389 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
390 // Repeated task is a delayed task with the default precision: low.
391 EXPECT_TRUE(task_queue.last_precision().has_value());
392 EXPECT_EQ(task_queue.last_precision().value(),
393 TaskQueueBase::DelayPrecision::kLow);
394 // No more tasks.
395 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
396}
397
398TEST(RepeatingTaskTest, CanSpecifyToPostTasksWithLowPrecision) {
399 SimulatedClock clock(Timestamp::Zero());
400 FakeTaskQueue task_queue(&clock);
401 // Closure that repeats twice.
402 MockFunction<TimeDelta()> closure;
403 EXPECT_CALL(closure, Call())
404 .WillOnce(Return(TimeDelta::Millis(1)))
405 .WillOnce(Return(TimeDelta::PlusInfinity()));
406 RepeatingTaskHandle::Start(&task_queue, closure.AsStdFunction(),
407 TaskQueueBase::DelayPrecision::kLow);
408 // Initial task is a PostTask().
409 EXPECT_FALSE(task_queue.last_precision().has_value());
410 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
411 // Repeated task is a delayed task with the specified precision.
412 EXPECT_TRUE(task_queue.last_precision().has_value());
413 EXPECT_EQ(task_queue.last_precision().value(),
414 TaskQueueBase::DelayPrecision::kLow);
415 // No more tasks.
416 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
417}
418
419TEST(RepeatingTaskTest, CanSpecifyToPostTasksWithHighPrecision) {
420 SimulatedClock clock(Timestamp::Zero());
421 FakeTaskQueue task_queue(&clock);
422 // Closure that repeats twice.
423 MockFunction<TimeDelta()> closure;
424 EXPECT_CALL(closure, Call())
425 .WillOnce(Return(TimeDelta::Millis(1)))
426 .WillOnce(Return(TimeDelta::PlusInfinity()));
427 RepeatingTaskHandle::Start(&task_queue, closure.AsStdFunction(),
428 TaskQueueBase::DelayPrecision::kHigh);
429 // Initial task is a PostTask().
430 EXPECT_FALSE(task_queue.last_precision().has_value());
431 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
432 // Repeated task is a delayed task with the specified precision.
433 EXPECT_TRUE(task_queue.last_precision().has_value());
434 EXPECT_EQ(task_queue.last_precision().value(),
435 TaskQueueBase::DelayPrecision::kHigh);
436 // No more tasks.
437 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
438}
439
Sebastian Janssonecb68972019-01-18 09:30:54440} // namespace webrtc