• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2014 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 "system_wrappers/include/ntp_time.h"
12 
13 #include <random>
14 
15 #include "system_wrappers/include/clock.h"
16 #include "test/gtest.h"
17 
18 namespace webrtc {
19 namespace {
20 
21 constexpr uint32_t kNtpSec = 0x12345678;
22 constexpr uint32_t kNtpFrac = 0x23456789;
23 
24 constexpr int64_t kOneSecQ32x32 = uint64_t{1} << 32;
25 constexpr int64_t kOneMsQ32x32 = 4294967;
26 
TEST(NtpTimeTest,NoValueMeansInvalid)27 TEST(NtpTimeTest, NoValueMeansInvalid) {
28   NtpTime ntp;
29   EXPECT_FALSE(ntp.Valid());
30 }
31 
TEST(NtpTimeTest,CanResetValue)32 TEST(NtpTimeTest, CanResetValue) {
33   NtpTime ntp(kNtpSec, kNtpFrac);
34   EXPECT_TRUE(ntp.Valid());
35   ntp.Reset();
36   EXPECT_FALSE(ntp.Valid());
37 }
38 
TEST(NtpTimeTest,CanGetWhatIsSet)39 TEST(NtpTimeTest, CanGetWhatIsSet) {
40   NtpTime ntp;
41   ntp.Set(kNtpSec, kNtpFrac);
42   EXPECT_EQ(kNtpSec, ntp.seconds());
43   EXPECT_EQ(kNtpFrac, ntp.fractions());
44 }
45 
TEST(NtpTimeTest,SetIsSameAs2ParameterConstructor)46 TEST(NtpTimeTest, SetIsSameAs2ParameterConstructor) {
47   NtpTime ntp1(kNtpSec, kNtpFrac);
48   NtpTime ntp2;
49   EXPECT_NE(ntp1, ntp2);
50 
51   ntp2.Set(kNtpSec, kNtpFrac);
52   EXPECT_EQ(ntp1, ntp2);
53 }
54 
TEST(NtpTimeTest,ToMsMeansToNtpMilliseconds)55 TEST(NtpTimeTest, ToMsMeansToNtpMilliseconds) {
56   SimulatedClock clock(0x123456789abc);
57 
58   NtpTime ntp = clock.CurrentNtpTime();
59   EXPECT_EQ(ntp.ToMs(), Clock::NtpToMs(ntp.seconds(), ntp.fractions()));
60   EXPECT_EQ(ntp.ToMs(), clock.CurrentNtpInMilliseconds());
61 }
62 
TEST(NtpTimeTest,CanExplicitlyConvertToAndFromUint64)63 TEST(NtpTimeTest, CanExplicitlyConvertToAndFromUint64) {
64   uint64_t untyped_time = 0x123456789;
65   NtpTime time(untyped_time);
66   EXPECT_EQ(untyped_time, static_cast<uint64_t>(time));
67   EXPECT_EQ(NtpTime(0x12345678, 0x90abcdef), NtpTime(0x1234567890abcdef));
68 }
69 
TEST(NtpTimeTest,VerifyInt64MsToQ32x32NearZero)70 TEST(NtpTimeTest, VerifyInt64MsToQ32x32NearZero) {
71   // Zero
72   EXPECT_EQ(Int64MsToQ32x32(0), 0);
73 
74   // Zero + 1 millisecond
75   EXPECT_EQ(Int64MsToQ32x32(1), kOneMsQ32x32);
76 
77   // Zero - 1 millisecond
78   EXPECT_EQ(Int64MsToQ32x32(-1), -kOneMsQ32x32);
79 
80   // Zero + 1 second
81   EXPECT_EQ(Int64MsToQ32x32(1000), kOneSecQ32x32);
82 
83   // Zero - 1 second
84   EXPECT_EQ(Int64MsToQ32x32(-1000), -kOneSecQ32x32);
85 }
86 
TEST(NtpTimeTest,VerifyInt64MsToUQ32x32NearZero)87 TEST(NtpTimeTest, VerifyInt64MsToUQ32x32NearZero) {
88   // Zero
89   EXPECT_EQ(Int64MsToUQ32x32(0), uint64_t{0});
90 
91   // Zero + 1 millisecond
92   EXPECT_EQ(Int64MsToUQ32x32(1), uint64_t{kOneMsQ32x32});
93 
94   // Zero - 1 millisecond
95   EXPECT_EQ(Int64MsToUQ32x32(-1), uint64_t{0});  // Clamped
96 
97   // Zero + 1 second
98   EXPECT_EQ(Int64MsToUQ32x32(1000), uint64_t{kOneSecQ32x32});
99 
100   // Zero - 1 second
101   EXPECT_EQ(Int64MsToUQ32x32(-1000), uint64_t{0});  // Clamped
102 }
103 
TEST(NtpTimeTest,VerifyQ32x32ToInt64MsNearZero)104 TEST(NtpTimeTest, VerifyQ32x32ToInt64MsNearZero) {
105   // Zero
106   EXPECT_EQ(Q32x32ToInt64Ms(0), 0);
107 
108   // Zero + 1 millisecond
109   EXPECT_EQ(Q32x32ToInt64Ms(kOneMsQ32x32), 1);
110 
111   // Zero - 1 millisecond
112   EXPECT_EQ(Q32x32ToInt64Ms(-kOneMsQ32x32), -1);
113 
114   // Zero + 1 second
115   EXPECT_EQ(Q32x32ToInt64Ms(kOneSecQ32x32), 1000);
116 
117   // Zero - 1 second
118   EXPECT_EQ(Q32x32ToInt64Ms(-kOneSecQ32x32), -1000);
119 }
120 
TEST(NtpTimeTest,VerifyUQ32x32ToInt64MsNearZero)121 TEST(NtpTimeTest, VerifyUQ32x32ToInt64MsNearZero) {
122   // Zero
123   EXPECT_EQ(UQ32x32ToInt64Ms(0), 0);
124 
125   // Zero + 1 millisecond
126   EXPECT_EQ(UQ32x32ToInt64Ms(kOneMsQ32x32), 1);
127 
128   // Zero + 1 second
129   EXPECT_EQ(UQ32x32ToInt64Ms(kOneSecQ32x32), 1000);
130 }
131 
TEST(NtpTimeTest,VerifyInt64MsToQ32x32NearMax)132 TEST(NtpTimeTest, VerifyInt64MsToQ32x32NearMax) {
133   constexpr int64_t kMaxQ32x32 = std::numeric_limits<int64_t>::max();
134   constexpr int64_t kBoundaryMs = (kMaxQ32x32 >> 32) * 1000 + 999;
135 
136   // Max
137   const int64_t boundary_q32x32 = Int64MsToQ32x32(kBoundaryMs);
138   EXPECT_LE(boundary_q32x32, kMaxQ32x32);
139   EXPECT_GT(boundary_q32x32, kMaxQ32x32 - kOneMsQ32x32);
140 
141   // Max + 1 millisecond
142   EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs + 1), kMaxQ32x32);  // Clamped
143 
144   // Max - 1 millisecond
145   EXPECT_LE(Int64MsToQ32x32(kBoundaryMs - 1), kMaxQ32x32 - kOneMsQ32x32);
146 
147   // Max + 1 second
148   EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs + 1000), kMaxQ32x32);  // Clamped
149 
150   // Max - 1 second
151   EXPECT_LE(Int64MsToQ32x32(kBoundaryMs - 1000), kMaxQ32x32 - kOneSecQ32x32);
152 }
153 
TEST(NtpTimeTest,VerifyInt64MsToUQ32x32NearMax)154 TEST(NtpTimeTest, VerifyInt64MsToUQ32x32NearMax) {
155   constexpr uint64_t kMaxUQ32x32 = std::numeric_limits<uint64_t>::max();
156   constexpr int64_t kBoundaryMs = (kMaxUQ32x32 >> 32) * 1000 + 999;
157 
158   // Max
159   const uint64_t boundary_uq32x32 = Int64MsToUQ32x32(kBoundaryMs);
160   EXPECT_LE(boundary_uq32x32, kMaxUQ32x32);
161   EXPECT_GT(boundary_uq32x32, kMaxUQ32x32 - kOneMsQ32x32);
162 
163   // Max + 1 millisecond
164   EXPECT_EQ(Int64MsToUQ32x32(kBoundaryMs + 1), kMaxUQ32x32);  // Clamped
165 
166   // Max - 1 millisecond
167   EXPECT_LE(Int64MsToUQ32x32(kBoundaryMs - 1), kMaxUQ32x32 - kOneMsQ32x32);
168 
169   // Max + 1 second
170   EXPECT_EQ(Int64MsToUQ32x32(kBoundaryMs + 1000), kMaxUQ32x32);  // Clamped
171 
172   // Max - 1 second
173   EXPECT_LE(Int64MsToUQ32x32(kBoundaryMs - 1000), kMaxUQ32x32 - kOneSecQ32x32);
174 }
175 
TEST(NtpTimeTest,VerifyQ32x32ToInt64MsNearMax)176 TEST(NtpTimeTest, VerifyQ32x32ToInt64MsNearMax) {
177   constexpr int64_t kMaxQ32x32 = std::numeric_limits<int64_t>::max();
178   constexpr int64_t kBoundaryMs = (kMaxQ32x32 >> 32) * 1000 + 1000;
179 
180   // Max
181   EXPECT_EQ(Q32x32ToInt64Ms(kMaxQ32x32), kBoundaryMs);
182 
183   // Max - 1 millisecond
184   EXPECT_EQ(Q32x32ToInt64Ms(kMaxQ32x32 - kOneMsQ32x32), kBoundaryMs - 1);
185 
186   // Max - 1 second
187   EXPECT_EQ(Q32x32ToInt64Ms(kMaxQ32x32 - kOneSecQ32x32), kBoundaryMs - 1000);
188 }
189 
TEST(NtpTimeTest,VerifyUQ32x32ToInt64MsNearMax)190 TEST(NtpTimeTest, VerifyUQ32x32ToInt64MsNearMax) {
191   constexpr uint64_t kMaxUQ32x32 = std::numeric_limits<uint64_t>::max();
192   constexpr int64_t kBoundaryMs = (kMaxUQ32x32 >> 32) * 1000 + 1000;
193 
194   // Max
195   EXPECT_EQ(UQ32x32ToInt64Ms(kMaxUQ32x32), kBoundaryMs);
196 
197   // Max - 1 millisecond
198   EXPECT_EQ(UQ32x32ToInt64Ms(kMaxUQ32x32 - kOneMsQ32x32), kBoundaryMs - 1);
199 
200   // Max - 1 second
201   EXPECT_EQ(UQ32x32ToInt64Ms(kMaxUQ32x32 - kOneSecQ32x32), kBoundaryMs - 1000);
202 }
203 
TEST(NtpTimeTest,VerifyInt64MsToQ32x32NearMin)204 TEST(NtpTimeTest, VerifyInt64MsToQ32x32NearMin) {
205   constexpr int64_t kBoundaryQ32x32 = 0x8000000000000000;
206   constexpr int64_t kBoundaryMs = -int64_t{0x80000000} * 1000;
207 
208   // Min
209   EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs), kBoundaryQ32x32);
210 
211   // Min + 1 millisecond
212   EXPECT_EQ(Q32x32ToInt64Ms(Int64MsToQ32x32(kBoundaryMs + 1)), kBoundaryMs + 1);
213 
214   // Min - 1 millisecond
215   EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs - 1), kBoundaryQ32x32);  // Clamped
216 
217   // Min + 1 second
218   EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs + 1000),
219             kBoundaryQ32x32 + kOneSecQ32x32);
220 
221   // Min - 1 second
222   EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs - 1000), kBoundaryQ32x32);  // Clamped
223 }
224 
TEST(NtpTimeTest,VerifyQ32x32ToInt64MsNearMin)225 TEST(NtpTimeTest, VerifyQ32x32ToInt64MsNearMin) {
226   constexpr int64_t kBoundaryQ32x32 = 0x8000000000000000;
227   constexpr int64_t kBoundaryMs = -int64_t{0x80000000} * 1000;
228 
229   // Min
230   EXPECT_EQ(Q32x32ToInt64Ms(kBoundaryQ32x32), kBoundaryMs);
231 
232   // Min + 1 millisecond
233   EXPECT_EQ(Q32x32ToInt64Ms(kBoundaryQ32x32 + kOneMsQ32x32), kBoundaryMs + 1);
234 
235   // Min + 1 second
236   EXPECT_EQ(Q32x32ToInt64Ms(kBoundaryQ32x32 + kOneSecQ32x32),
237             kBoundaryMs + 1000);
238 }
239 
TEST(NtpTimeTest,VerifyInt64MsToQ32x32RoundTrip)240 TEST(NtpTimeTest, VerifyInt64MsToQ32x32RoundTrip) {
241   constexpr int kIterations = 50000;
242 
243   std::mt19937 generator(123456789);
244   std::uniform_int_distribution<int64_t> distribution(
245       Q32x32ToInt64Ms(std::numeric_limits<int64_t>::min()),
246       Q32x32ToInt64Ms(std::numeric_limits<int64_t>::max()));
247 
248   for (int iteration = 0; iteration < kIterations; ++iteration) {
249     int64_t input_ms = distribution(generator);
250     int64_t transit_q32x32 = Int64MsToQ32x32(input_ms);
251     int64_t output_ms = Q32x32ToInt64Ms(transit_q32x32);
252 
253     ASSERT_EQ(input_ms, output_ms)
254         << "iteration = " << iteration << ", input_ms = " << input_ms
255         << ", transit_q32x32 = " << transit_q32x32
256         << ", output_ms = " << output_ms;
257   }
258 }
259 
TEST(NtpTimeTest,VerifyInt64MsToUQ32x32RoundTrip)260 TEST(NtpTimeTest, VerifyInt64MsToUQ32x32RoundTrip) {
261   constexpr int kIterations = 50000;
262 
263   std::mt19937 generator(123456789);
264   std::uniform_int_distribution<uint64_t> distribution(
265       UQ32x32ToInt64Ms(std::numeric_limits<uint64_t>::min()),
266       UQ32x32ToInt64Ms(std::numeric_limits<uint64_t>::max()));
267 
268   for (int iteration = 0; iteration < kIterations; ++iteration) {
269     uint64_t input_ms = distribution(generator);
270     uint64_t transit_uq32x32 = Int64MsToUQ32x32(input_ms);
271     uint64_t output_ms = UQ32x32ToInt64Ms(transit_uq32x32);
272 
273     ASSERT_EQ(input_ms, output_ms)
274         << "iteration = " << iteration << ", input_ms = " << input_ms
275         << ", transit_uq32x32 = " << transit_uq32x32
276         << ", output_ms = " << output_ms;
277   }
278 }
279 
280 }  // namespace
281 }  // namespace webrtc
282