blob: 684009fea5dd64fc5d217f88e21b1c298eb8cda4 [file] [log] [blame]
Bjorn A Mellemc4f86542019-11-21 18:37:181/*
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
11#include "test/time_controller/external_time_controller.h"
12
13#include <atomic>
14#include <memory>
15#include <utility>
16
17#include "rtc_base/event.h"
18#include "rtc_base/task_queue.h"
19#include "rtc_base/task_utils/repeating_task.h"
20#include "test/gmock.h"
21#include "test/gtest.h"
22
23// NOTE: Since these tests rely on real time behavior, they will be flaky
24// if run on heavily loaded systems.
25namespace webrtc {
26namespace {
27using ::testing::AtLeast;
28using ::testing::Invoke;
29using ::testing::MockFunction;
30using ::testing::NiceMock;
31using ::testing::Return;
Danil Chapovalov0c626af2020-02-10 10:16:0032constexpr Timestamp kStartTime = Timestamp::Seconds(1000);
Bjorn A Mellemc4f86542019-11-21 18:37:1833
34class FakeAlarm : public ControlledAlarmClock {
35 public:
36 explicit FakeAlarm(Timestamp start_time);
37
38 Clock* GetClock() override;
39 bool ScheduleAlarmAt(Timestamp deadline) override;
40 void SetCallback(std::function<void()> callback) override;
41 void Sleep(TimeDelta duration) override;
42
43 private:
44 SimulatedClock clock_;
45 Timestamp deadline_;
46 std::function<void()> callback_;
47};
48
49FakeAlarm::FakeAlarm(Timestamp start_time)
50 : clock_(start_time),
51 deadline_(Timestamp::PlusInfinity()),
52 callback_([] {}) {}
53
54Clock* FakeAlarm::GetClock() {
55 return &clock_;
56}
57
58bool FakeAlarm::ScheduleAlarmAt(Timestamp deadline) {
59 if (deadline < deadline_) {
60 deadline_ = deadline;
61 return true;
62 }
63 return false;
64}
65
66void FakeAlarm::SetCallback(std::function<void()> callback) {
67 callback_ = callback;
68}
69
70void FakeAlarm::Sleep(TimeDelta duration) {
71 Timestamp end_time = clock_.CurrentTime() + duration;
72
73 while (deadline_ <= end_time) {
74 clock_.AdvanceTime(deadline_ - clock_.CurrentTime());
75 deadline_ = Timestamp::PlusInfinity();
76 callback_();
77 }
78
79 clock_.AdvanceTime(end_time - clock_.CurrentTime());
80}
81
82} // namespace
83
84TEST(ExternalTimeControllerTest, TaskIsStoppedOnStop) {
Danil Chapovalov0c626af2020-02-10 10:16:0085 const TimeDelta kShortInterval = TimeDelta::Millis(5);
86 const TimeDelta kLongInterval = TimeDelta::Millis(20);
Bjorn A Mellemc4f86542019-11-21 18:37:1887 const int kShortIntervalCount = 4;
88 const int kMargin = 1;
89 FakeAlarm alarm(kStartTime);
90 ExternalTimeController time_simulation(&alarm);
91 rtc::TaskQueue task_queue(
92 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
93 "TestQueue", TaskQueueFactory::Priority::NORMAL));
94 std::atomic_int counter(0);
95 auto handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
96 if (++counter >= kShortIntervalCount)
97 return kLongInterval;
98 return kShortInterval;
99 });
100 // Sleep long enough to go through the initial phase.
Markus Handell486cc552019-12-03 13:37:28101 time_simulation.AdvanceTime(kShortInterval * (kShortIntervalCount + kMargin));
Bjorn A Mellemc4f86542019-11-21 18:37:18102 EXPECT_EQ(counter.load(), kShortIntervalCount);
103
104 task_queue.PostTask(
105 [handle = std::move(handle)]() mutable { handle.Stop(); });
106
107 // Sleep long enough that the task would run at least once more if not
108 // stopped.
Markus Handell486cc552019-12-03 13:37:28109 time_simulation.AdvanceTime(kLongInterval * 2);
Bjorn A Mellemc4f86542019-11-21 18:37:18110 EXPECT_EQ(counter.load(), kShortIntervalCount);
111}
112
113TEST(ExternalTimeControllerTest, TaskCanStopItself) {
114 std::atomic_int counter(0);
115 FakeAlarm alarm(kStartTime);
116 ExternalTimeController time_simulation(&alarm);
117 rtc::TaskQueue task_queue(
118 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
119 "TestQueue", TaskQueueFactory::Priority::NORMAL));
120
121 RepeatingTaskHandle handle;
122 task_queue.PostTask([&] {
123 handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
124 ++counter;
125 handle.Stop();
Danil Chapovalov0c626af2020-02-10 10:16:00126 return TimeDelta::Millis(2);
Bjorn A Mellemc4f86542019-11-21 18:37:18127 });
128 });
Danil Chapovalov0c626af2020-02-10 10:16:00129 time_simulation.AdvanceTime(TimeDelta::Millis(10));
Bjorn A Mellemc4f86542019-11-21 18:37:18130 EXPECT_EQ(counter.load(), 1);
131}
132
133TEST(ExternalTimeControllerTest, YieldForTask) {
134 FakeAlarm alarm(kStartTime);
135 ExternalTimeController time_simulation(&alarm);
136
137 rtc::TaskQueue task_queue(
138 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
139 "TestQueue", TaskQueueFactory::Priority::NORMAL));
140
Sebastian Jansson340af972019-12-04 09:07:48141 rtc::Event event;
142 task_queue.PostTask([&] { event.Set(); });
143 EXPECT_TRUE(event.Wait(200));
Bjorn A Mellemc4f86542019-11-21 18:37:18144}
145
146TEST(ExternalTimeControllerTest, TasksYieldToEachOther) {
147 FakeAlarm alarm(kStartTime);
148 ExternalTimeController time_simulation(&alarm);
149
150 rtc::TaskQueue task_queue(
151 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
152 "TestQueue", TaskQueueFactory::Priority::NORMAL));
153 rtc::TaskQueue other_queue(
154 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
155 "OtherQueue", TaskQueueFactory::Priority::NORMAL));
156
157 task_queue.PostTask([&] {
158 rtc::Event event;
159 other_queue.PostTask([&] { event.Set(); });
160 EXPECT_TRUE(event.Wait(200));
161 });
162
Danil Chapovalov0c626af2020-02-10 10:16:00163 time_simulation.AdvanceTime(TimeDelta::Millis(300));
Bjorn A Mellemc4f86542019-11-21 18:37:18164}
165
166TEST(ExternalTimeControllerTest, CurrentTaskQueue) {
167 FakeAlarm alarm(kStartTime);
168 ExternalTimeController time_simulation(&alarm);
169
170 rtc::TaskQueue task_queue(
171 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
172 "TestQueue", TaskQueueFactory::Priority::NORMAL));
173
174 task_queue.PostTask([&] { EXPECT_TRUE(task_queue.IsCurrent()); });
175
Danil Chapovalov0c626af2020-02-10 10:16:00176 time_simulation.AdvanceTime(TimeDelta::Millis(10));
Bjorn A Mellemc4f86542019-11-21 18:37:18177}
178
179} // namespace webrtc