blob: 15155c14d0ff23902fba1d73df2f0ce1f87d4727 [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
16#include "absl/memory/memory.h"
17#include "rtc_base/task_queue.h"
18#include "rtc_base/task_utils/repeating_task.h"
19#include "test/gmock.h"
20#include "test/gtest.h"
Sebastian Jansson0d617cc2019-03-22 15:22:16 +010021
22// NOTE: Since these tests rely on real time behavior, they will be flaky
23// if run on heavily loaded systems.
24namespace webrtc {
25namespace {
26using ::testing::AtLeast;
27using ::testing::Invoke;
28using ::testing::MockFunction;
29using ::testing::NiceMock;
30using ::testing::Return;
31constexpr Timestamp kStartTime = Timestamp::Seconds<1000>();
32
33// Helper closure class to stop repeating task on a task queue. This is
34// equivalent to [handle{move(handle)}] { handle.Stop(); } in c++14.
35class TaskHandleStopper {
36 public:
37 explicit TaskHandleStopper(RepeatingTaskHandle handle)
38 : handle_(std::move(handle)) {}
39 void operator()() { handle_.Stop(); }
40
41 private:
42 RepeatingTaskHandle handle_;
43};
44} // namespace
45
46TEST(SimulatedTimeControllerTest, TaskIsStoppedOnStop) {
47 const TimeDelta kShortInterval = TimeDelta::ms(5);
48 const TimeDelta kLongInterval = TimeDelta::ms(20);
49 const int kShortIntervalCount = 4;
50 const int kMargin = 1;
51 GlobalSimulatedTimeController time_simulation(kStartTime);
52 rtc::TaskQueue task_queue(
53 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
54 "TestQueue", TaskQueueFactory::Priority::NORMAL));
55 std::atomic_int counter(0);
56 auto handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
57 if (++counter >= kShortIntervalCount)
58 return kLongInterval;
59 return kShortInterval;
60 });
61 // Sleep long enough to go through the initial phase.
62 time_simulation.Sleep(kShortInterval * (kShortIntervalCount + kMargin));
63 EXPECT_EQ(counter.load(), kShortIntervalCount);
64
65 task_queue.PostTask(TaskHandleStopper(std::move(handle)));
66 // Sleep long enough that the task would run at least once more if not
67 // stopped.
68 time_simulation.Sleep(kLongInterval * 2);
69 EXPECT_EQ(counter.load(), kShortIntervalCount);
70}
71
72TEST(SimulatedTimeControllerTest, TaskCanStopItself) {
73 std::atomic_int counter(0);
74 GlobalSimulatedTimeController time_simulation(kStartTime);
75 rtc::TaskQueue task_queue(
76 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
77 "TestQueue", TaskQueueFactory::Priority::NORMAL));
78
79 RepeatingTaskHandle handle;
80 task_queue.PostTask([&] {
81 handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
82 ++counter;
83 handle.Stop();
84 return TimeDelta::ms(2);
85 });
86 });
87 time_simulation.Sleep(TimeDelta::ms(10));
88 EXPECT_EQ(counter.load(), 1);
89}
90TEST(SimulatedTimeControllerTest, Example) {
91 class ObjectOnTaskQueue {
92 public:
93 void DoPeriodicTask() {}
94 TimeDelta TimeUntilNextRun() { return TimeDelta::ms(100); }
95 void StartPeriodicTask(RepeatingTaskHandle* handle,
96 rtc::TaskQueue* task_queue) {
97 *handle = RepeatingTaskHandle::Start(task_queue->Get(), [this] {
98 DoPeriodicTask();
99 return TimeUntilNextRun();
100 });
101 }
102 };
103 GlobalSimulatedTimeController time_simulation(kStartTime);
104 rtc::TaskQueue task_queue(
105 time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
106 "TestQueue", TaskQueueFactory::Priority::NORMAL));
107 auto object = absl::make_unique<ObjectOnTaskQueue>();
108 // Create and start the periodic task.
109 RepeatingTaskHandle handle;
110 object->StartPeriodicTask(&handle, &task_queue);
111 // Restart the task
112 task_queue.PostTask(TaskHandleStopper(std::move(handle)));
113 object->StartPeriodicTask(&handle, &task_queue);
114 task_queue.PostTask(TaskHandleStopper(std::move(handle)));
115 struct Destructor {
116 void operator()() { object.reset(); }
117 std::unique_ptr<ObjectOnTaskQueue> object;
118 };
119 task_queue.PostTask(Destructor{std::move(object)});
120}
121} // namespace webrtc