xref: /aosp_15_r20/external/webrtc/rtc_base/time_utils_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2004 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 "rtc_base/time_utils.h"
12 
13 #include <memory>
14 
15 #include "api/units/time_delta.h"
16 #include "rtc_base/event.h"
17 #include "rtc_base/fake_clock.h"
18 #include "rtc_base/helpers.h"
19 #include "rtc_base/thread.h"
20 #include "test/gtest.h"
21 
22 namespace rtc {
23 using ::webrtc::TimeDelta;
24 
TEST(TimeTest,TimeInMs)25 TEST(TimeTest, TimeInMs) {
26   int64_t ts_earlier = TimeMillis();
27   Thread::SleepMs(100);
28   int64_t ts_now = TimeMillis();
29   // Allow for the thread to wakeup ~20ms early.
30   EXPECT_GE(ts_now, ts_earlier + 80);
31   // Make sure the Time is not returning in smaller unit like microseconds.
32   EXPECT_LT(ts_now, ts_earlier + 1000);
33 }
34 
TEST(TimeTest,Intervals)35 TEST(TimeTest, Intervals) {
36   int64_t ts_earlier = TimeMillis();
37   int64_t ts_later = TimeAfter(500);
38 
39   // We can't depend on ts_later and ts_earlier to be exactly 500 apart
40   // since time elapses between the calls to TimeMillis() and TimeAfter(500)
41   EXPECT_LE(500, TimeDiff(ts_later, ts_earlier));
42   EXPECT_GE(-500, TimeDiff(ts_earlier, ts_later));
43 
44   // Time has elapsed since ts_earlier
45   EXPECT_GE(TimeSince(ts_earlier), 0);
46 
47   // ts_earlier is earlier than now, so TimeUntil ts_earlier is -ve
48   EXPECT_LE(TimeUntil(ts_earlier), 0);
49 
50   // ts_later likely hasn't happened yet, so TimeSince could be -ve
51   // but within 500
52   EXPECT_GE(TimeSince(ts_later), -500);
53 
54   // TimeUntil ts_later is at most 500
55   EXPECT_LE(TimeUntil(ts_later), 500);
56 }
57 
TEST(TimeTest,TestTimeDiff64)58 TEST(TimeTest, TestTimeDiff64) {
59   int64_t ts_diff = 100;
60   int64_t ts_earlier = rtc::TimeMillis();
61   int64_t ts_later = ts_earlier + ts_diff;
62   EXPECT_EQ(ts_diff, rtc::TimeDiff(ts_later, ts_earlier));
63   EXPECT_EQ(-ts_diff, rtc::TimeDiff(ts_earlier, ts_later));
64 }
65 
66 class TimestampWrapAroundHandlerTest : public ::testing::Test {
67  public:
TimestampWrapAroundHandlerTest()68   TimestampWrapAroundHandlerTest() {}
69 
70  protected:
71   TimestampWrapAroundHandler wraparound_handler_;
72 };
73 
TEST_F(TimestampWrapAroundHandlerTest,Unwrap)74 TEST_F(TimestampWrapAroundHandlerTest, Unwrap) {
75   // Start value.
76   int64_t ts = 2;
77   EXPECT_EQ(ts,
78             wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
79 
80   // Wrap backwards.
81   ts = -2;
82   EXPECT_EQ(ts,
83             wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
84 
85   // Forward to 2 again.
86   ts = 2;
87   EXPECT_EQ(ts,
88             wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
89 
90   // Max positive skip ahead, until max value (0xffffffff).
91   for (uint32_t i = 0; i <= 0xf; ++i) {
92     ts = (i << 28) + 0x0fffffff;
93     EXPECT_EQ(
94         ts, wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
95   }
96 
97   // Wrap around.
98   ts += 2;
99   EXPECT_EQ(ts,
100             wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
101 
102   // Max wrap backward...
103   ts -= 0x0fffffff;
104   EXPECT_EQ(ts,
105             wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
106 
107   // ...and back again.
108   ts += 0x0fffffff;
109   EXPECT_EQ(ts,
110             wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
111 }
112 
TEST_F(TimestampWrapAroundHandlerTest,NoNegativeStart)113 TEST_F(TimestampWrapAroundHandlerTest, NoNegativeStart) {
114   int64_t ts = 0xfffffff0;
115   EXPECT_EQ(ts,
116             wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
117 }
118 
119 class TmToSeconds : public ::testing::Test {
120  public:
TmToSeconds()121   TmToSeconds() {
122     // Set use of the test RNG to get deterministic expiration timestamp.
123     rtc::SetRandomTestMode(true);
124   }
~TmToSeconds()125   ~TmToSeconds() override {
126     // Put it back for the next test.
127     rtc::SetRandomTestMode(false);
128   }
129 
TestTmToSeconds(int times)130   void TestTmToSeconds(int times) {
131     static char mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
132     for (int i = 0; i < times; i++) {
133       // First generate something correct and check that TmToSeconds is happy.
134       int year = rtc::CreateRandomId() % 400 + 1970;
135 
136       bool leap_year = false;
137       if (year % 4 == 0)
138         leap_year = true;
139       if (year % 100 == 0)
140         leap_year = false;
141       if (year % 400 == 0)
142         leap_year = true;
143 
144       std::tm tm;
145       tm.tm_year = year - 1900;  // std::tm is year 1900 based.
146       tm.tm_mon = rtc::CreateRandomId() % 12;
147       tm.tm_mday = rtc::CreateRandomId() % mdays[tm.tm_mon] + 1;
148       tm.tm_hour = rtc::CreateRandomId() % 24;
149       tm.tm_min = rtc::CreateRandomId() % 60;
150       tm.tm_sec = rtc::CreateRandomId() % 60;
151       int64_t t = rtc::TmToSeconds(tm);
152       EXPECT_TRUE(t >= 0);
153 
154       // Now damage a random field and check that TmToSeconds is unhappy.
155       switch (rtc::CreateRandomId() % 11) {
156         case 0:
157           tm.tm_year = 1969 - 1900;
158           break;
159         case 1:
160           tm.tm_mon = -1;
161           break;
162         case 2:
163           tm.tm_mon = 12;
164           break;
165         case 3:
166           tm.tm_mday = 0;
167           break;
168         case 4:
169           tm.tm_mday = mdays[tm.tm_mon] + (leap_year && tm.tm_mon == 1) + 1;
170           break;
171         case 5:
172           tm.tm_hour = -1;
173           break;
174         case 6:
175           tm.tm_hour = 24;
176           break;
177         case 7:
178           tm.tm_min = -1;
179           break;
180         case 8:
181           tm.tm_min = 60;
182           break;
183         case 9:
184           tm.tm_sec = -1;
185           break;
186         case 10:
187           tm.tm_sec = 60;
188           break;
189       }
190       EXPECT_EQ(rtc::TmToSeconds(tm), -1);
191     }
192     // Check consistency with the system gmtime_r.  With time_t, we can only
193     // portably test dates until 2038, which is achieved by the % 0x80000000.
194     for (int i = 0; i < times; i++) {
195       time_t t = rtc::CreateRandomId() % 0x80000000;
196 #if defined(WEBRTC_WIN)
197       std::tm* tm = std::gmtime(&t);
198       EXPECT_TRUE(tm);
199       EXPECT_TRUE(rtc::TmToSeconds(*tm) == t);
200 #else
201       std::tm tm;
202       EXPECT_TRUE(gmtime_r(&t, &tm));
203       EXPECT_TRUE(rtc::TmToSeconds(tm) == t);
204 #endif
205     }
206   }
207 };
208 
TEST_F(TmToSeconds,TestTmToSeconds)209 TEST_F(TmToSeconds, TestTmToSeconds) {
210   TestTmToSeconds(100000);
211 }
212 
213 // Test that all the time functions exposed by TimeUtils get time from the
214 // fake clock when it's set.
TEST(FakeClock,TimeFunctionsUseFakeClock)215 TEST(FakeClock, TimeFunctionsUseFakeClock) {
216   FakeClock clock;
217   SetClockForTesting(&clock);
218 
219   clock.SetTime(webrtc::Timestamp::Micros(987654));
220   EXPECT_EQ(987u, Time32());
221   EXPECT_EQ(987, TimeMillis());
222   EXPECT_EQ(987654, TimeMicros());
223   EXPECT_EQ(987654000, TimeNanos());
224   EXPECT_EQ(1000u, TimeAfter(13));
225 
226   SetClockForTesting(nullptr);
227   // After it's unset, we should get a normal time.
228   EXPECT_NE(987, TimeMillis());
229 }
230 
TEST(FakeClock,InitialTime)231 TEST(FakeClock, InitialTime) {
232   FakeClock clock;
233   EXPECT_EQ(0, clock.TimeNanos());
234 }
235 
TEST(FakeClock,SetTime)236 TEST(FakeClock, SetTime) {
237   FakeClock clock;
238   clock.SetTime(webrtc::Timestamp::Micros(123));
239   EXPECT_EQ(123000, clock.TimeNanos());
240   clock.SetTime(webrtc::Timestamp::Micros(456));
241   EXPECT_EQ(456000, clock.TimeNanos());
242 }
243 
TEST(FakeClock,AdvanceTime)244 TEST(FakeClock, AdvanceTime) {
245   FakeClock clock;
246   clock.AdvanceTime(webrtc::TimeDelta::Micros(1u));
247   EXPECT_EQ(1000, clock.TimeNanos());
248   clock.AdvanceTime(webrtc::TimeDelta::Micros(2222u));
249   EXPECT_EQ(2223000, clock.TimeNanos());
250   clock.AdvanceTime(webrtc::TimeDelta::Millis(3333u));
251   EXPECT_EQ(3335223000, clock.TimeNanos());
252   clock.AdvanceTime(webrtc::TimeDelta::Seconds(4444u));
253   EXPECT_EQ(4447335223000, clock.TimeNanos());
254 }
255 
256 // When the clock is advanced, threads that are waiting in a socket select
257 // should wake up and look at the new time. This allows tests using the
258 // fake clock to run much faster, if the test is bound by time constraints
259 // (such as a test for a STUN ping timeout).
TEST(FakeClock,SettingTimeWakesThreads)260 TEST(FakeClock, SettingTimeWakesThreads) {
261   int64_t real_start_time_ms = TimeMillis();
262 
263   ThreadProcessingFakeClock clock;
264   SetClockForTesting(&clock);
265 
266   std::unique_ptr<Thread> worker(Thread::CreateWithSocketServer());
267   worker->Start();
268 
269   // Post an event that won't be executed for 10 seconds.
270   Event message_handler_dispatched;
271   worker->PostDelayedTask(
272       [&message_handler_dispatched] { message_handler_dispatched.Set(); },
273       TimeDelta::Seconds(60));
274 
275   // Wait for a bit for the worker thread to be started and enter its socket
276   // select(). Otherwise this test would be trivial since the worker thread
277   // would process the event as soon as it was started.
278   Thread::Current()->SleepMs(1000);
279 
280   // Advance the fake clock, expecting the worker thread to wake up
281   // and dispatch the message instantly.
282   clock.AdvanceTime(webrtc::TimeDelta::Seconds(60u));
283   EXPECT_TRUE(message_handler_dispatched.Wait(webrtc::TimeDelta::Zero()));
284   worker->Stop();
285 
286   SetClockForTesting(nullptr);
287 
288   // The message should have been dispatched long before the 60 seconds fully
289   // elapsed (just a sanity check).
290   int64_t real_end_time_ms = TimeMillis();
291   EXPECT_LT(real_end_time_ms - real_start_time_ms, 10000);
292 }
293 
294 }  // namespace rtc
295