xref: /aosp_15_r20/external/webrtc/test/time_controller/simulated_time_controller_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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/simulated_time_controller.h"
12 
13 #include <atomic>
14 #include <memory>
15 
16 #include "rtc_base/event.h"
17 #include "rtc_base/task_queue.h"
18 #include "rtc_base/task_queue_for_test.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.
25 namespace webrtc {
26 namespace {
27 using ::testing::AtLeast;
28 using ::testing::Invoke;
29 using ::testing::MockFunction;
30 using ::testing::NiceMock;
31 using ::testing::Return;
32 constexpr Timestamp kStartTime = Timestamp::Seconds(1000);
33 }  // namespace
34 
TEST(SimulatedTimeControllerTest,TaskIsStoppedOnStop)35 TEST(SimulatedTimeControllerTest, TaskIsStoppedOnStop) {
36   const TimeDelta kShortInterval = TimeDelta::Millis(5);
37   const TimeDelta kLongInterval = TimeDelta::Millis(20);
38   const int kShortIntervalCount = 4;
39   const int kMargin = 1;
40   GlobalSimulatedTimeController time_simulation(kStartTime);
41   rtc::TaskQueue task_queue(
42       time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
43           "TestQueue", TaskQueueFactory::Priority::NORMAL));
44   std::atomic_int counter(0);
45   auto handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
46     if (++counter >= kShortIntervalCount)
47       return kLongInterval;
48     return kShortInterval;
49   });
50   // Sleep long enough to go through the initial phase.
51   time_simulation.AdvanceTime(kShortInterval * (kShortIntervalCount + kMargin));
52   EXPECT_EQ(counter.load(), kShortIntervalCount);
53 
54   task_queue.PostTask(
55       [handle = std::move(handle)]() mutable { handle.Stop(); });
56 
57   // Sleep long enough that the task would run at least once more if not
58   // stopped.
59   time_simulation.AdvanceTime(kLongInterval * 2);
60   EXPECT_EQ(counter.load(), kShortIntervalCount);
61 }
62 
TEST(SimulatedTimeControllerTest,TaskCanStopItself)63 TEST(SimulatedTimeControllerTest, TaskCanStopItself) {
64   std::atomic_int counter(0);
65   GlobalSimulatedTimeController time_simulation(kStartTime);
66   rtc::TaskQueue task_queue(
67       time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
68           "TestQueue", TaskQueueFactory::Priority::NORMAL));
69 
70   RepeatingTaskHandle handle;
71   task_queue.PostTask([&] {
72     handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
73       ++counter;
74       handle.Stop();
75       return TimeDelta::Millis(2);
76     });
77   });
78   time_simulation.AdvanceTime(TimeDelta::Millis(10));
79   EXPECT_EQ(counter.load(), 1);
80 }
81 
TEST(SimulatedTimeControllerTest,Example)82 TEST(SimulatedTimeControllerTest, Example) {
83   class ObjectOnTaskQueue {
84    public:
85     void DoPeriodicTask() {}
86     TimeDelta TimeUntilNextRun() { return TimeDelta::Millis(100); }
87     void StartPeriodicTask(RepeatingTaskHandle* handle,
88                            rtc::TaskQueue* task_queue) {
89       *handle = RepeatingTaskHandle::Start(task_queue->Get(), [this] {
90         DoPeriodicTask();
91         return TimeUntilNextRun();
92       });
93     }
94   };
95   GlobalSimulatedTimeController time_simulation(kStartTime);
96   rtc::TaskQueue task_queue(
97       time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
98           "TestQueue", TaskQueueFactory::Priority::NORMAL));
99   auto object = std::make_unique<ObjectOnTaskQueue>();
100   // Create and start the periodic task.
101   RepeatingTaskHandle handle;
102   object->StartPeriodicTask(&handle, &task_queue);
103   // Restart the task
104   task_queue.PostTask(
105       [handle = std::move(handle)]() mutable { handle.Stop(); });
106   object->StartPeriodicTask(&handle, &task_queue);
107   task_queue.PostTask(
108       [handle = std::move(handle)]() mutable { handle.Stop(); });
109 
110   task_queue.PostTask([object = std::move(object)] {});
111 }
112 
TEST(SimulatedTimeControllerTest,DelayTaskRunOnTime)113 TEST(SimulatedTimeControllerTest, DelayTaskRunOnTime) {
114   GlobalSimulatedTimeController time_simulation(kStartTime);
115   std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
116       time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
117           "TestQueue", TaskQueueFactory::Priority::NORMAL);
118 
119   bool delay_task_executed = false;
120   task_queue->PostDelayedTask([&] { delay_task_executed = true; },
121                               TimeDelta::Millis(10));
122 
123   time_simulation.AdvanceTime(TimeDelta::Millis(10));
124   EXPECT_TRUE(delay_task_executed);
125 }
126 
TEST(SimulatedTimeControllerTest,ThreadYeildsOnSynchronousCall)127 TEST(SimulatedTimeControllerTest, ThreadYeildsOnSynchronousCall) {
128   GlobalSimulatedTimeController sim(kStartTime);
129   auto main_thread = sim.GetMainThread();
130   auto t2 = sim.CreateThread("thread", nullptr);
131   bool task_has_run = false;
132   // Posting a task to the main thread, this should not run until AdvanceTime is
133   // called.
134   main_thread->PostTask([&] { task_has_run = true; });
135   SendTask(t2.get(), [] {
136     rtc::Event yield_event;
137     // Wait() triggers YieldExecution() which will runs message processing on
138     // all threads that are not in the yielded set.
139 
140     yield_event.Wait(TimeDelta::Zero());
141   });
142   // Since we are doing an invoke from the main thread, we don't expect the main
143   // thread message loop to be processed.
144   EXPECT_FALSE(task_has_run);
145   sim.AdvanceTime(TimeDelta::Seconds(1));
146   ASSERT_TRUE(task_has_run);
147 }
148 
149 }  // namespace webrtc
150