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