blob: ca334461bad83a3c0ea0661903e64b554be086ae [file] [log] [blame]
Sebastian Janssonecb68972019-01-18 10:30:54 +01001/*
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 19:08:33 +020011#include "rtc_base/task_utils/repeating_task.h"
12
Sebastian Janssonecb68972019-01-18 10:30:54 +010013#include <atomic>
Sebastian Janssonecb68972019-01-18 10:30:54 +010014#include <memory>
Sebastian Janssonecb68972019-01-18 10:30:54 +010015
Evan Shrubsolef0f47432021-11-15 17:24:45 +010016#include "api/task_queue/queued_task.h"
17#include "api/task_queue/task_queue_base.h"
Artem Titovc374d112022-06-16 21:27:45 +020018#include "api/task_queue/to_queued_task.h"
Evan Shrubsolef0f47432021-11-15 17:24:45 +010019#include "api/units/timestamp.h"
Sebastian Janssonecb68972019-01-18 10:30:54 +010020#include "rtc_base/event.h"
Danil Chapovalov07122bc2019-03-26 14:37:01 +010021#include "rtc_base/task_queue_for_test.h"
Evan Shrubsolef0f47432021-11-15 17:24:45 +010022#include "system_wrappers/include/clock.h"
Sebastian Janssonecb68972019-01-18 10:30:54 +010023#include "test/gmock.h"
24#include "test/gtest.h"
25
26// NOTE: Since these tests rely on real time behavior, they will be flaky
27// if run on heavily loaded systems.
28namespace webrtc {
29namespace {
30using ::testing::AtLeast;
31using ::testing::Invoke;
32using ::testing::MockFunction;
33using ::testing::NiceMock;
34using ::testing::Return;
35
Danil Chapovalov0c626af2020-02-10 11:16:00 +010036constexpr TimeDelta kTimeout = TimeDelta::Millis(1000);
Sebastian Janssonecb68972019-01-18 10:30:54 +010037
Sebastian Janssonecb68972019-01-18 10:30:54 +010038class MockClosure {
39 public:
Danil Chapovalov42748d82020-05-14 20:42:41 +020040 MOCK_METHOD(TimeDelta, Call, ());
41 MOCK_METHOD(void, Delete, ());
Sebastian Janssonecb68972019-01-18 10:30:54 +010042};
43
Tommi532cac52020-05-18 14:53:42 +020044class MockTaskQueue : public TaskQueueBase {
45 public:
46 MockTaskQueue() : task_queue_setter_(this) {}
47
48 MOCK_METHOD(void, Delete, (), (override));
49 MOCK_METHOD(void, PostTask, (std::unique_ptr<QueuedTask> task), (override));
50 MOCK_METHOD(void,
51 PostDelayedTask,
52 (std::unique_ptr<QueuedTask> task, uint32_t milliseconds),
53 (override));
54
55 private:
56 CurrentTaskQueueSetter task_queue_setter_;
57};
58
Evan Shrubsolef0f47432021-11-15 17:24:45 +010059class FakeTaskQueue : public TaskQueueBase {
60 public:
61 explicit FakeTaskQueue(SimulatedClock* clock)
62 : task_queue_setter_(this), clock_(clock) {}
63
64 void Delete() override {}
65
66 void PostTask(std::unique_ptr<QueuedTask> task) override {
Henrik Boström27e8a092022-01-24 17:12:35 +010067 last_task_ = std::move(task);
68 last_precision_ = absl::nullopt;
69 last_delay_ = 0;
Evan Shrubsolef0f47432021-11-15 17:24:45 +010070 }
71
72 void PostDelayedTask(std::unique_ptr<QueuedTask> task,
73 uint32_t milliseconds) override {
74 last_task_ = std::move(task);
Henrik Boström27e8a092022-01-24 17:12:35 +010075 last_precision_ = TaskQueueBase::DelayPrecision::kLow;
76 last_delay_ = milliseconds;
77 }
78
79 void PostDelayedHighPrecisionTask(std::unique_ptr<QueuedTask> task,
80 uint32_t milliseconds) override {
81 last_task_ = std::move(task);
82 last_precision_ = TaskQueueBase::DelayPrecision::kHigh;
Evan Shrubsolef0f47432021-11-15 17:24:45 +010083 last_delay_ = milliseconds;
84 }
85
86 bool AdvanceTimeAndRunLastTask() {
87 EXPECT_TRUE(last_task_);
88 EXPECT_TRUE(last_delay_);
89 clock_->AdvanceTimeMilliseconds(last_delay_.value_or(0));
90 last_delay_.reset();
91 auto task = std::move(last_task_);
92 bool delete_task = task->Run();
93 if (!delete_task) {
94 // If the task should not be deleted then just release it.
95 task.release();
96 }
97 return delete_task;
98 }
99
100 bool IsTaskQueued() { return !!last_task_; }
101
102 uint32_t last_delay() const {
103 EXPECT_TRUE(last_delay_.has_value());
104 return last_delay_.value_or(-1);
105 }
106
Henrik Boström27e8a092022-01-24 17:12:35 +0100107 absl::optional<TaskQueueBase::DelayPrecision> last_precision() const {
108 return last_precision_;
109 }
110
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100111 private:
112 CurrentTaskQueueSetter task_queue_setter_;
113 SimulatedClock* clock_;
114 std::unique_ptr<QueuedTask> last_task_;
115 absl::optional<uint32_t> last_delay_;
Henrik Boström27e8a092022-01-24 17:12:35 +0100116 absl::optional<TaskQueueBase::DelayPrecision> last_precision_;
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100117};
118
Tomas Gunnarsson87e7b3d2022-01-17 09:58:45 +0100119// NOTE: Since this utility class holds a raw pointer to a variable that likely
120// lives on the stack, it's important that any repeating tasks that use this
121// class be explicitly stopped when the test criteria have been met. If the
122// task is not stopped, an instance of this class can be deleted when the
123// pointed-to MockClosure has been deleted and we end up trying to call a
124// virtual method on a deleted object in the dtor.
Sebastian Janssonecb68972019-01-18 10:30:54 +0100125class MoveOnlyClosure {
126 public:
127 explicit MoveOnlyClosure(MockClosure* mock) : mock_(mock) {}
128 MoveOnlyClosure(const MoveOnlyClosure&) = delete;
129 MoveOnlyClosure(MoveOnlyClosure&& other) : mock_(other.mock_) {
130 other.mock_ = nullptr;
131 }
132 ~MoveOnlyClosure() {
133 if (mock_)
134 mock_->Delete();
135 }
136 TimeDelta operator()() { return mock_->Call(); }
137
138 private:
139 MockClosure* mock_;
140};
141} // namespace
142
143TEST(RepeatingTaskTest, TaskIsStoppedOnStop) {
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100144 const TimeDelta kShortInterval = TimeDelta::Millis(50);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100145
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100146 SimulatedClock clock(Timestamp::Zero());
147 FakeTaskQueue task_queue(&clock);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100148 std::atomic_int counter(0);
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100149 auto handle = RepeatingTaskHandle::Start(&task_queue, [&] {
150 counter++;
Sebastian Janssonecb68972019-01-18 10:30:54 +0100151 return kShortInterval;
152 });
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100153 EXPECT_EQ(task_queue.last_delay(), 0u);
154 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
155 EXPECT_EQ(counter.load(), 1);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100156
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100157 // The handle reposted at the short interval.
158 EXPECT_EQ(task_queue.last_delay(), kShortInterval.ms());
159
160 // Stop the handle. This prevernts the counter from incrementing.
161 handle.Stop();
162 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
163 EXPECT_EQ(counter.load(), 1);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100164}
165
166TEST(RepeatingTaskTest, CompensatesForLongRunTime) {
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100167 const TimeDelta kRepeatInterval = TimeDelta::Millis(2);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100168 // Sleeping inside the task for longer than the repeat interval once, should
169 // be compensated for by repeating the task faster to catch up.
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100170 const TimeDelta kSleepDuration = TimeDelta::Millis(20);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100171
172 std::atomic_int counter(0);
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100173 SimulatedClock clock(Timestamp::Zero());
174 FakeTaskQueue task_queue(&clock);
175 RepeatingTaskHandle::Start(
176 &task_queue,
177 [&] {
178 ++counter;
179 // Task takes longer than the repeat duration.
180 clock.AdvanceTime(kSleepDuration);
181 return kRepeatInterval;
182 },
Henrik Boström27e8a092022-01-24 17:12:35 +0100183 TaskQueueBase::DelayPrecision::kLow, &clock);
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100184
185 EXPECT_EQ(task_queue.last_delay(), 0u);
186 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
187
188 // Task is posted right away since it took longer to run then the repeat
189 // interval.
190 EXPECT_EQ(task_queue.last_delay(), 0u);
191 EXPECT_EQ(counter.load(), 1);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100192}
193
194TEST(RepeatingTaskTest, CompensatesForShortRunTime) {
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100195 SimulatedClock clock(Timestamp::Millis(0));
196 FakeTaskQueue task_queue(&clock);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100197 std::atomic_int counter(0);
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100198 RepeatingTaskHandle::Start(
199 &task_queue,
200 [&] {
201 // Simulate the task taking 100ms, which should be compensated for.
202 counter++;
203 clock.AdvanceTime(TimeDelta::Millis(100));
204 return TimeDelta::Millis(300);
205 },
Henrik Boström27e8a092022-01-24 17:12:35 +0100206 TaskQueueBase::DelayPrecision::kLow, &clock);
Sebastian Janssona497d122019-02-04 16:39:28 +0100207
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100208 // Expect instant post task.
209 EXPECT_EQ(task_queue.last_delay(), 0u);
210 // Task should be retained by the handler since it is not cancelled.
211 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
212 // New delay should be 200ms since repeat delay was 300ms but task took 100ms.
213 EXPECT_EQ(task_queue.last_delay(), 200u);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100214}
215
216TEST(RepeatingTaskTest, CancelDelayedTaskBeforeItRuns) {
217 rtc::Event done;
218 MockClosure mock;
219 EXPECT_CALL(mock, Call).Times(0);
220 EXPECT_CALL(mock, Delete).WillOnce(Invoke([&done] { done.Set(); }));
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100221 TaskQueueForTest task_queue("queue");
Sebastian Janssonecb68972019-01-18 10:30:54 +0100222 auto handle = RepeatingTaskHandle::DelayedStart(
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100223 task_queue.Get(), TimeDelta::Millis(100), MoveOnlyClosure(&mock));
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200224 task_queue.PostTask(
225 [handle = std::move(handle)]() mutable { handle.Stop(); });
Sebastian Janssonecb68972019-01-18 10:30:54 +0100226 EXPECT_TRUE(done.Wait(kTimeout.ms()));
227}
228
229TEST(RepeatingTaskTest, CancelTaskAfterItRuns) {
230 rtc::Event done;
231 MockClosure mock;
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100232 EXPECT_CALL(mock, Call).WillOnce(Return(TimeDelta::Millis(100)));
Sebastian Janssonecb68972019-01-18 10:30:54 +0100233 EXPECT_CALL(mock, Delete).WillOnce(Invoke([&done] { done.Set(); }));
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100234 TaskQueueForTest task_queue("queue");
Danil Chapovalov4423c362019-03-06 18:41:39 +0100235 auto handle =
236 RepeatingTaskHandle::Start(task_queue.Get(), MoveOnlyClosure(&mock));
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200237 task_queue.PostTask(
238 [handle = std::move(handle)]() mutable { handle.Stop(); });
Sebastian Janssonecb68972019-01-18 10:30:54 +0100239 EXPECT_TRUE(done.Wait(kTimeout.ms()));
240}
241
242TEST(RepeatingTaskTest, TaskCanStopItself) {
243 std::atomic_int counter(0);
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100244 SimulatedClock clock(Timestamp::Zero());
245 FakeTaskQueue task_queue(&clock);
246 RepeatingTaskHandle handle = RepeatingTaskHandle::Start(&task_queue, [&] {
247 ++counter;
248 handle.Stop();
249 return TimeDelta::Millis(2);
Sebastian Janssonecb68972019-01-18 10:30:54 +0100250 });
Evan Shrubsolef0f47432021-11-15 17:24:45 +0100251 EXPECT_EQ(task_queue.last_delay(), 0u);
252 // Task cancelled itself so wants to be released.
253 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
Sebastian Janssonecb68972019-01-18 10:30:54 +0100254 EXPECT_EQ(counter.load(), 1);
255}
256
Niels Möller902b5542022-01-17 15:20:24 +0100257TEST(RepeatingTaskTest, TaskCanStopItselfByReturningInfinity) {
258 std::atomic_int counter(0);
259 SimulatedClock clock(Timestamp::Zero());
260 FakeTaskQueue task_queue(&clock);
261 RepeatingTaskHandle handle = RepeatingTaskHandle::Start(&task_queue, [&] {
262 ++counter;
263 return TimeDelta::PlusInfinity();
264 });
265 EXPECT_EQ(task_queue.last_delay(), 0u);
266 // Task cancelled itself so wants to be released.
267 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
268 EXPECT_EQ(counter.load(), 1);
269}
270
Sebastian Janssonecb68972019-01-18 10:30:54 +0100271TEST(RepeatingTaskTest, ZeroReturnValueRepostsTheTask) {
272 NiceMock<MockClosure> closure;
273 rtc::Event done;
274 EXPECT_CALL(closure, Call())
275 .WillOnce(Return(TimeDelta::Zero()))
Tomas Gunnarsson87e7b3d2022-01-17 09:58:45 +0100276 .WillOnce(Invoke([&] {
Sebastian Janssonecb68972019-01-18 10:30:54 +0100277 done.Set();
Niels Möller902b5542022-01-17 15:20:24 +0100278 return TimeDelta::PlusInfinity();
Sebastian Janssonecb68972019-01-18 10:30:54 +0100279 }));
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100280 TaskQueueForTest task_queue("queue");
Niels Möller902b5542022-01-17 15:20:24 +0100281 RepeatingTaskHandle::Start(task_queue.Get(), MoveOnlyClosure(&closure));
Sebastian Janssonecb68972019-01-18 10:30:54 +0100282 EXPECT_TRUE(done.Wait(kTimeout.ms()));
283}
284
285TEST(RepeatingTaskTest, StartPeriodicTask) {
286 MockFunction<TimeDelta()> closure;
287 rtc::Event done;
288 EXPECT_CALL(closure, Call())
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100289 .WillOnce(Return(TimeDelta::Millis(20)))
290 .WillOnce(Return(TimeDelta::Millis(20)))
Tomas Gunnarsson87e7b3d2022-01-17 09:58:45 +0100291 .WillOnce(Invoke([&] {
Sebastian Janssonecb68972019-01-18 10:30:54 +0100292 done.Set();
Niels Möller902b5542022-01-17 15:20:24 +0100293 return TimeDelta::PlusInfinity();
Sebastian Janssonecb68972019-01-18 10:30:54 +0100294 }));
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100295 TaskQueueForTest task_queue("queue");
Danil Chapovalov4423c362019-03-06 18:41:39 +0100296 RepeatingTaskHandle::Start(task_queue.Get(), closure.AsStdFunction());
Sebastian Janssonecb68972019-01-18 10:30:54 +0100297 EXPECT_TRUE(done.Wait(kTimeout.ms()));
298}
299
300TEST(RepeatingTaskTest, Example) {
301 class ObjectOnTaskQueue {
302 public:
303 void DoPeriodicTask() {}
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100304 TimeDelta TimeUntilNextRun() { return TimeDelta::Millis(100); }
Sebastian Janssonecb68972019-01-18 10:30:54 +0100305 void StartPeriodicTask(RepeatingTaskHandle* handle,
Danil Chapovalov4423c362019-03-06 18:41:39 +0100306 TaskQueueBase* task_queue) {
Sebastian Janssonecb68972019-01-18 10:30:54 +0100307 *handle = RepeatingTaskHandle::Start(task_queue, [this] {
308 DoPeriodicTask();
309 return TimeUntilNextRun();
310 });
311 }
312 };
Danil Chapovalov07122bc2019-03-26 14:37:01 +0100313 TaskQueueForTest task_queue("queue");
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200314 auto object = std::make_unique<ObjectOnTaskQueue>();
Sebastian Janssonecb68972019-01-18 10:30:54 +0100315 // Create and start the periodic task.
316 RepeatingTaskHandle handle;
Danil Chapovalov4423c362019-03-06 18:41:39 +0100317 object->StartPeriodicTask(&handle, task_queue.Get());
Sebastian Janssonecb68972019-01-18 10:30:54 +0100318 // Restart the task
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200319 task_queue.PostTask(
320 [handle = std::move(handle)]() mutable { handle.Stop(); });
Danil Chapovalov4423c362019-03-06 18:41:39 +0100321 object->StartPeriodicTask(&handle, task_queue.Get());
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200322 task_queue.PostTask(
323 [handle = std::move(handle)]() mutable { handle.Stop(); });
Sebastian Janssonecb68972019-01-18 10:30:54 +0100324 struct Destructor {
325 void operator()() { object.reset(); }
326 std::unique_ptr<ObjectOnTaskQueue> object;
327 };
328 task_queue.PostTask(Destructor{std::move(object)});
329 // Do not wait for the destructor closure in order to create a race between
330 // task queue destruction and running the desctructor closure.
331}
332
Tommi532cac52020-05-18 14:53:42 +0200333TEST(RepeatingTaskTest, ClockIntegration) {
334 std::unique_ptr<QueuedTask> delayed_task;
335 uint32_t expected_ms = 0;
336 SimulatedClock clock(Timestamp::Millis(0));
337
338 NiceMock<MockTaskQueue> task_queue;
339 ON_CALL(task_queue, PostDelayedTask)
340 .WillByDefault(
341 Invoke([&delayed_task, &expected_ms](std::unique_ptr<QueuedTask> task,
342 uint32_t milliseconds) {
343 EXPECT_EQ(milliseconds, expected_ms);
344 delayed_task = std::move(task);
345 }));
346
347 expected_ms = 100;
348 RepeatingTaskHandle handle = RepeatingTaskHandle::DelayedStart(
349 &task_queue, TimeDelta::Millis(100),
350 [&clock]() {
351 EXPECT_EQ(Timestamp::Millis(100), clock.CurrentTime());
352 // Simulate work happening for 10ms.
353 clock.AdvanceTimeMilliseconds(10);
354 return TimeDelta::Millis(100);
355 },
Henrik Boström27e8a092022-01-24 17:12:35 +0100356 TaskQueueBase::DelayPrecision::kLow, &clock);
Tommi532cac52020-05-18 14:53:42 +0200357
358 clock.AdvanceTimeMilliseconds(100);
359 QueuedTask* task_to_run = delayed_task.release();
360 expected_ms = 90;
361 EXPECT_FALSE(task_to_run->Run());
362 EXPECT_NE(nullptr, delayed_task.get());
363 handle.Stop();
364}
365
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200366TEST(RepeatingTaskTest, CanBeStoppedAfterTaskQueueDeletedTheRepeatingTask) {
367 std::unique_ptr<QueuedTask> repeating_task;
368
369 MockTaskQueue task_queue;
370 EXPECT_CALL(task_queue, PostDelayedTask)
371 .WillOnce([&](std::unique_ptr<QueuedTask> task, uint32_t milliseconds) {
372 repeating_task = std::move(task);
373 });
374
375 RepeatingTaskHandle handle =
376 RepeatingTaskHandle::DelayedStart(&task_queue, TimeDelta::Millis(100),
377 [] { return TimeDelta::Millis(100); });
378
379 // shutdown task queue: delete all pending tasks and run 'regular' task.
380 repeating_task = nullptr;
381 handle.Stop();
382}
383
Henrik Boström27e8a092022-01-24 17:12:35 +0100384TEST(RepeatingTaskTest, DefaultPrecisionIsLow) {
385 SimulatedClock clock(Timestamp::Zero());
386 FakeTaskQueue task_queue(&clock);
387 // Closure that repeats twice.
388 MockFunction<TimeDelta()> closure;
389 EXPECT_CALL(closure, Call())
390 .WillOnce(Return(TimeDelta::Millis(1)))
391 .WillOnce(Return(TimeDelta::PlusInfinity()));
392 RepeatingTaskHandle::Start(&task_queue, closure.AsStdFunction());
393 // Initial task is a PostTask().
394 EXPECT_FALSE(task_queue.last_precision().has_value());
395 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
396 // Repeated task is a delayed task with the default precision: low.
397 EXPECT_TRUE(task_queue.last_precision().has_value());
398 EXPECT_EQ(task_queue.last_precision().value(),
399 TaskQueueBase::DelayPrecision::kLow);
400 // No more tasks.
401 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
402}
403
404TEST(RepeatingTaskTest, CanSpecifyToPostTasksWithLowPrecision) {
405 SimulatedClock clock(Timestamp::Zero());
406 FakeTaskQueue task_queue(&clock);
407 // Closure that repeats twice.
408 MockFunction<TimeDelta()> closure;
409 EXPECT_CALL(closure, Call())
410 .WillOnce(Return(TimeDelta::Millis(1)))
411 .WillOnce(Return(TimeDelta::PlusInfinity()));
412 RepeatingTaskHandle::Start(&task_queue, closure.AsStdFunction(),
413 TaskQueueBase::DelayPrecision::kLow);
414 // Initial task is a PostTask().
415 EXPECT_FALSE(task_queue.last_precision().has_value());
416 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
417 // Repeated task is a delayed task with the specified precision.
418 EXPECT_TRUE(task_queue.last_precision().has_value());
419 EXPECT_EQ(task_queue.last_precision().value(),
420 TaskQueueBase::DelayPrecision::kLow);
421 // No more tasks.
422 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
423}
424
425TEST(RepeatingTaskTest, CanSpecifyToPostTasksWithHighPrecision) {
426 SimulatedClock clock(Timestamp::Zero());
427 FakeTaskQueue task_queue(&clock);
428 // Closure that repeats twice.
429 MockFunction<TimeDelta()> closure;
430 EXPECT_CALL(closure, Call())
431 .WillOnce(Return(TimeDelta::Millis(1)))
432 .WillOnce(Return(TimeDelta::PlusInfinity()));
433 RepeatingTaskHandle::Start(&task_queue, closure.AsStdFunction(),
434 TaskQueueBase::DelayPrecision::kHigh);
435 // Initial task is a PostTask().
436 EXPECT_FALSE(task_queue.last_precision().has_value());
437 EXPECT_FALSE(task_queue.AdvanceTimeAndRunLastTask());
438 // Repeated task is a delayed task with the specified precision.
439 EXPECT_TRUE(task_queue.last_precision().has_value());
440 EXPECT_EQ(task_queue.last_precision().value(),
441 TaskQueueBase::DelayPrecision::kHigh);
442 // No more tasks.
443 EXPECT_TRUE(task_queue.AdvanceTimeAndRunLastTask());
444}
445
Sebastian Janssonecb68972019-01-18 10:30:54 +0100446} // namespace webrtc