blob: 5fc944358df6c728952eeb7a1828fe10c943a175 [file] [log] [blame]
Sebastian Jansson0d617cc2019-03-22 15:22:16 +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 "test/time_controller/simulated_time_controller.h"
12
Sebastian Jansson0d617cc2019-03-22 15:22:16 +010013#include <atomic>
14#include <memory>
15
Sebastian Jansson0d617cc2019-03-22 15:22:16 +010016#include "rtc_base/task_queue.h"
17#include "rtc_base/task_utils/repeating_task.h"
18#include "test/gmock.h"
19#include "test/gtest.h"
Sebastian Jansson0d617cc2019-03-22 15:22:16 +010020
21// NOTE: Since these tests rely on real time behavior, they will be flaky
22// if run on heavily loaded systems.
23namespace webrtc {
24namespace {
25using ::testing::AtLeast;
26using ::testing::Invoke;
27using ::testing::MockFunction;
28using ::testing::NiceMock;
29using ::testing::Return;
30constexpr Timestamp kStartTime = Timestamp::Seconds<1000>();
Sebastian Jansson0d617cc2019-03-22 15:22:16 +010031} // namespace
32
33TEST(SimulatedTimeControllerTest, TaskIsStoppedOnStop) {
34 const TimeDelta kShortInterval = TimeDelta::ms(5);
35 const TimeDelta kLongInterval = TimeDelta::ms(20);
36 const int kShortIntervalCount = 4;
37 const int kMargin = 1;
38 GlobalSimulatedTimeController time_simulation(kStartTime);
39 rtc::TaskQueue task_queue(
40 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
41 "TestQueue", TaskQueueFactory::Priority::NORMAL));
42 std::atomic_int counter(0);
43 auto handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
44 if (++counter >= kShortIntervalCount)
45 return kLongInterval;
46 return kShortInterval;
47 });
48 // Sleep long enough to go through the initial phase.
49 time_simulation.Sleep(kShortInterval * (kShortIntervalCount + kMargin));
50 EXPECT_EQ(counter.load(), kShortIntervalCount);
51
Sebastian Jansson86314cf2019-09-17 20:29:59 +020052 task_queue.PostTask(
53 [handle = std::move(handle)]() mutable { handle.Stop(); });
54
Sebastian Jansson0d617cc2019-03-22 15:22:16 +010055 // Sleep long enough that the task would run at least once more if not
56 // stopped.
57 time_simulation.Sleep(kLongInterval * 2);
58 EXPECT_EQ(counter.load(), kShortIntervalCount);
59}
60
61TEST(SimulatedTimeControllerTest, TaskCanStopItself) {
62 std::atomic_int counter(0);
63 GlobalSimulatedTimeController time_simulation(kStartTime);
64 rtc::TaskQueue task_queue(
65 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
66 "TestQueue", TaskQueueFactory::Priority::NORMAL));
67
68 RepeatingTaskHandle handle;
69 task_queue.PostTask([&] {
70 handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
71 ++counter;
72 handle.Stop();
73 return TimeDelta::ms(2);
74 });
75 });
76 time_simulation.Sleep(TimeDelta::ms(10));
77 EXPECT_EQ(counter.load(), 1);
78}
79TEST(SimulatedTimeControllerTest, Example) {
80 class ObjectOnTaskQueue {
81 public:
82 void DoPeriodicTask() {}
83 TimeDelta TimeUntilNextRun() { return TimeDelta::ms(100); }
84 void StartPeriodicTask(RepeatingTaskHandle* handle,
85 rtc::TaskQueue* task_queue) {
86 *handle = RepeatingTaskHandle::Start(task_queue->Get(), [this] {
87 DoPeriodicTask();
88 return TimeUntilNextRun();
89 });
90 }
91 };
92 GlobalSimulatedTimeController time_simulation(kStartTime);
93 rtc::TaskQueue task_queue(
94 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
95 "TestQueue", TaskQueueFactory::Priority::NORMAL));
Mirko Bonadei317a1f02019-09-17 17:06:18 +020096 auto object = std::make_unique<ObjectOnTaskQueue>();
Sebastian Jansson0d617cc2019-03-22 15:22:16 +010097 // Create and start the periodic task.
98 RepeatingTaskHandle handle;
99 object->StartPeriodicTask(&handle, &task_queue);
100 // Restart the task
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200101 task_queue.PostTask(
102 [handle = std::move(handle)]() mutable { handle.Stop(); });
Sebastian Jansson0d617cc2019-03-22 15:22:16 +0100103 object->StartPeriodicTask(&handle, &task_queue);
Sebastian Jansson86314cf2019-09-17 20:29:59 +0200104 task_queue.PostTask(
105 [handle = std::move(handle)]() mutable { handle.Stop(); });
106
Sebastian Jansson0d617cc2019-03-22 15:22:16 +0100107 struct Destructor {
108 void operator()() { object.reset(); }
109 std::unique_ptr<ObjectOnTaskQueue> object;
110 };
111 task_queue.PostTask(Destructor{std::move(object)});
112}
113} // namespace webrtc