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