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 "webrtc/base/common.h"
12#include "webrtc/base/gunit.h"
13#include "webrtc/base/helpers.h"
14#include "webrtc/base/thread.h"
15#include "webrtc/base/timeutils.h"
16
17namespace rtc {
18
19TEST(TimeTest, TimeInMs) {
20  uint32_t ts_earlier = Time();
21  Thread::SleepMs(100);
22  uint32_t ts_now = Time();
23  // Allow for the thread to wakeup ~20ms early.
24  EXPECT_GE(ts_now, ts_earlier + 80);
25  // Make sure the Time is not returning in smaller unit like microseconds.
26  EXPECT_LT(ts_now, ts_earlier + 1000);
27}
28
29TEST(TimeTest, Comparison) {
30  // Obtain two different times, in known order
31  TimeStamp ts_earlier = Time();
32  Thread::SleepMs(100);
33  TimeStamp ts_now = Time();
34  EXPECT_NE(ts_earlier, ts_now);
35
36  // Common comparisons
37  EXPECT_TRUE( TimeIsLaterOrEqual(ts_earlier, ts_now));
38  EXPECT_TRUE( TimeIsLater(       ts_earlier, ts_now));
39  EXPECT_FALSE(TimeIsLaterOrEqual(ts_now,     ts_earlier));
40  EXPECT_FALSE(TimeIsLater(       ts_now,     ts_earlier));
41
42  // Edge cases
43  EXPECT_TRUE( TimeIsLaterOrEqual(ts_earlier, ts_earlier));
44  EXPECT_FALSE(TimeIsLater(       ts_earlier, ts_earlier));
45
46  // Obtain a third time
47  TimeStamp ts_later = TimeAfter(100);
48  EXPECT_NE(ts_now, ts_later);
49  EXPECT_TRUE( TimeIsLater(ts_now,     ts_later));
50  EXPECT_TRUE( TimeIsLater(ts_earlier, ts_later));
51
52  // Common comparisons
53  EXPECT_TRUE( TimeIsBetween(ts_earlier, ts_now,     ts_later));
54  EXPECT_FALSE(TimeIsBetween(ts_earlier, ts_later,   ts_now));
55  EXPECT_FALSE(TimeIsBetween(ts_now,     ts_earlier, ts_later));
56  EXPECT_TRUE( TimeIsBetween(ts_now,     ts_later,   ts_earlier));
57  EXPECT_TRUE( TimeIsBetween(ts_later,   ts_earlier, ts_now));
58  EXPECT_FALSE(TimeIsBetween(ts_later,   ts_now,     ts_earlier));
59
60  // Edge cases
61  EXPECT_TRUE( TimeIsBetween(ts_earlier, ts_earlier, ts_earlier));
62  EXPECT_TRUE( TimeIsBetween(ts_earlier, ts_earlier, ts_later));
63  EXPECT_TRUE( TimeIsBetween(ts_earlier, ts_later,   ts_later));
64
65  // Earlier of two times
66  EXPECT_EQ(ts_earlier, TimeMin(ts_earlier, ts_earlier));
67  EXPECT_EQ(ts_earlier, TimeMin(ts_earlier, ts_now));
68  EXPECT_EQ(ts_earlier, TimeMin(ts_earlier, ts_later));
69  EXPECT_EQ(ts_earlier, TimeMin(ts_now,     ts_earlier));
70  EXPECT_EQ(ts_earlier, TimeMin(ts_later,   ts_earlier));
71
72  // Later of two times
73  EXPECT_EQ(ts_earlier, TimeMax(ts_earlier, ts_earlier));
74  EXPECT_EQ(ts_now,     TimeMax(ts_earlier, ts_now));
75  EXPECT_EQ(ts_later,   TimeMax(ts_earlier, ts_later));
76  EXPECT_EQ(ts_now,     TimeMax(ts_now,     ts_earlier));
77  EXPECT_EQ(ts_later,   TimeMax(ts_later,   ts_earlier));
78}
79
80TEST(TimeTest, Intervals) {
81  TimeStamp ts_earlier = Time();
82  TimeStamp ts_later = TimeAfter(500);
83
84  // We can't depend on ts_later and ts_earlier to be exactly 500 apart
85  // since time elapses between the calls to Time() and TimeAfter(500)
86  EXPECT_LE(500,  TimeDiff(ts_later, ts_earlier));
87  EXPECT_GE(-500, TimeDiff(ts_earlier, ts_later));
88
89  // Time has elapsed since ts_earlier
90  EXPECT_GE(TimeSince(ts_earlier), 0);
91
92  // ts_earlier is earlier than now, so TimeUntil ts_earlier is -ve
93  EXPECT_LE(TimeUntil(ts_earlier), 0);
94
95  // ts_later likely hasn't happened yet, so TimeSince could be -ve
96  // but within 500
97  EXPECT_GE(TimeSince(ts_later), -500);
98
99  // TimeUntil ts_later is at most 500
100  EXPECT_LE(TimeUntil(ts_later), 500);
101}
102
103TEST(TimeTest, BoundaryComparison) {
104  // Obtain two different times, in known order
105  TimeStamp ts_earlier = static_cast<TimeStamp>(-50);
106  TimeStamp ts_later = ts_earlier + 100;
107  EXPECT_NE(ts_earlier, ts_later);
108
109  // Common comparisons
110  EXPECT_TRUE( TimeIsLaterOrEqual(ts_earlier, ts_later));
111  EXPECT_TRUE( TimeIsLater(       ts_earlier, ts_later));
112  EXPECT_FALSE(TimeIsLaterOrEqual(ts_later,   ts_earlier));
113  EXPECT_FALSE(TimeIsLater(       ts_later,   ts_earlier));
114
115  // Earlier of two times
116  EXPECT_EQ(ts_earlier, TimeMin(ts_earlier, ts_earlier));
117  EXPECT_EQ(ts_earlier, TimeMin(ts_earlier, ts_later));
118  EXPECT_EQ(ts_earlier, TimeMin(ts_later,   ts_earlier));
119
120  // Later of two times
121  EXPECT_EQ(ts_earlier, TimeMax(ts_earlier, ts_earlier));
122  EXPECT_EQ(ts_later,   TimeMax(ts_earlier, ts_later));
123  EXPECT_EQ(ts_later,   TimeMax(ts_later,   ts_earlier));
124
125  // Interval
126  EXPECT_EQ(100,  TimeDiff(ts_later, ts_earlier));
127  EXPECT_EQ(-100, TimeDiff(ts_earlier, ts_later));
128}
129
130TEST(TimeTest, DISABLED_CurrentTmTime) {
131  struct tm tm;
132  int microseconds;
133
134  time_t before = ::time(NULL);
135  CurrentTmTime(&tm, &microseconds);
136  time_t after = ::time(NULL);
137
138  // Assert that 'tm' represents a time between 'before' and 'after'.
139  // mktime() uses local time, so we have to compensate for that.
140  time_t local_delta = before - ::mktime(::gmtime(&before));  // NOLINT
141  time_t t = ::mktime(&tm) + local_delta;
142
143  EXPECT_TRUE(before <= t && t <= after);
144  EXPECT_TRUE(0 <= microseconds && microseconds < 1000000);
145}
146
147class TimestampWrapAroundHandlerTest : public testing::Test {
148 public:
149  TimestampWrapAroundHandlerTest() {}
150
151 protected:
152  TimestampWrapAroundHandler wraparound_handler_;
153};
154
155TEST_F(TimestampWrapAroundHandlerTest, Unwrap) {
156  uint32_t ts = 0xfffffff2;
157  int64_t unwrapped_ts = ts;
158  EXPECT_EQ(ts, wraparound_handler_.Unwrap(ts));
159  ts = 2;
160  unwrapped_ts += 0x10;
161  EXPECT_EQ(unwrapped_ts, wraparound_handler_.Unwrap(ts));
162  ts = 0xfffffff2;
163  unwrapped_ts += 0xfffffff0;
164  EXPECT_EQ(unwrapped_ts, wraparound_handler_.Unwrap(ts));
165  ts = 0;
166  unwrapped_ts += 0xe;
167  EXPECT_EQ(unwrapped_ts, wraparound_handler_.Unwrap(ts));
168}
169
170class TmToSeconds : public testing::Test {
171 public:
172  TmToSeconds() {
173    // Set use of the test RNG to get deterministic expiration timestamp.
174    rtc::SetRandomTestMode(true);
175  }
176  ~TmToSeconds() {
177    // Put it back for the next test.
178    rtc::SetRandomTestMode(false);
179  }
180
181  void TestTmToSeconds(int times) {
182    static char mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
183    for (int i = 0; i < times; i++) {
184
185      // First generate something correct and check that TmToSeconds is happy.
186      int year = rtc::CreateRandomId() % 400 + 1970;
187
188      bool leap_year = false;
189      if (year % 4 == 0)
190        leap_year = true;
191      if (year % 100 == 0)
192        leap_year = false;
193      if (year % 400 == 0)
194        leap_year = true;
195
196      std::tm tm;
197      tm.tm_year = year - 1900;  // std::tm is year 1900 based.
198      tm.tm_mon = rtc::CreateRandomId() % 12;
199      tm.tm_mday = rtc::CreateRandomId() % mdays[tm.tm_mon] + 1;
200      tm.tm_hour = rtc::CreateRandomId() % 24;
201      tm.tm_min = rtc::CreateRandomId() % 60;
202      tm.tm_sec = rtc::CreateRandomId() % 60;
203      int64_t t = rtc::TmToSeconds(tm);
204      EXPECT_TRUE(t >= 0);
205
206      // Now damage a random field and check that TmToSeconds is unhappy.
207      switch (rtc::CreateRandomId() % 11) {
208        case 0:
209          tm.tm_year = 1969 - 1900;
210          break;
211        case 1:
212          tm.tm_mon = -1;
213          break;
214        case 2:
215          tm.tm_mon = 12;
216          break;
217        case 3:
218          tm.tm_mday = 0;
219          break;
220        case 4:
221          tm.tm_mday = mdays[tm.tm_mon] + (leap_year && tm.tm_mon == 1) + 1;
222          break;
223        case 5:
224          tm.tm_hour = -1;
225          break;
226        case 6:
227          tm.tm_hour = 24;
228          break;
229        case 7:
230          tm.tm_min = -1;
231          break;
232        case 8:
233          tm.tm_min = 60;
234          break;
235        case 9:
236          tm.tm_sec = -1;
237          break;
238        case 10:
239          tm.tm_sec = 60;
240          break;
241      }
242      EXPECT_EQ(rtc::TmToSeconds(tm), -1);
243    }
244    // Check consistency with the system gmtime_r.  With time_t, we can only
245    // portably test dates until 2038, which is achieved by the % 0x80000000.
246    for (int i = 0; i < times; i++) {
247      time_t t = rtc::CreateRandomId() % 0x80000000;
248#if defined(WEBRTC_WIN)
249      std::tm* tm = std::gmtime(&t);
250      EXPECT_TRUE(tm);
251      EXPECT_TRUE(rtc::TmToSeconds(*tm) == t);
252#else
253      std::tm tm;
254      EXPECT_TRUE(gmtime_r(&t, &tm));
255      EXPECT_TRUE(rtc::TmToSeconds(tm) == t);
256#endif
257    }
258  }
259};
260
261TEST_F(TmToSeconds, TestTmToSeconds) {
262  TestTmToSeconds(100000);
263}
264
265}  // namespace rtc
266