xref: /aosp_15_r20/external/openscreen/cast/streaming/ntp_time_unittest.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "cast/streaming/ntp_time.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <chrono>
8*3f982cf4SFabien Sanglard 
9*3f982cf4SFabien Sanglard #include "gtest/gtest.h"
10*3f982cf4SFabien Sanglard #include "util/chrono_helpers.h"
11*3f982cf4SFabien Sanglard 
12*3f982cf4SFabien Sanglard namespace openscreen {
13*3f982cf4SFabien Sanglard namespace cast {
14*3f982cf4SFabien Sanglard 
TEST(NtpTimestampTest,SplitsIntoParts)15*3f982cf4SFabien Sanglard TEST(NtpTimestampTest, SplitsIntoParts) {
16*3f982cf4SFabien Sanglard   // 1 Jan 1900.
17*3f982cf4SFabien Sanglard   NtpTimestamp timestamp = UINT64_C(0x0000000000000000);
18*3f982cf4SFabien Sanglard   EXPECT_EQ(NtpSeconds::zero(), NtpSecondsPart(timestamp));
19*3f982cf4SFabien Sanglard   EXPECT_EQ(NtpFraction::zero(), NtpFractionPart(timestamp));
20*3f982cf4SFabien Sanglard 
21*3f982cf4SFabien Sanglard   // 1 Jan 1900 plus 10 ms.
22*3f982cf4SFabien Sanglard   timestamp = UINT64_C(0x00000000028f5c29);
23*3f982cf4SFabien Sanglard   EXPECT_EQ(NtpSeconds::zero(), NtpSecondsPart(timestamp));
24*3f982cf4SFabien Sanglard   EXPECT_EQ(milliseconds(10), to_milliseconds(NtpFractionPart(timestamp)));
25*3f982cf4SFabien Sanglard 
26*3f982cf4SFabien Sanglard   // 1 Jan 1970 minus 2^-32 seconds.
27*3f982cf4SFabien Sanglard   timestamp = UINT64_C(0x83aa7e80ffffffff);
28*3f982cf4SFabien Sanglard   EXPECT_EQ(NtpSeconds(INT64_C(2208988800)), NtpSecondsPart(timestamp));
29*3f982cf4SFabien Sanglard   EXPECT_EQ(NtpFraction(0xffffffff), NtpFractionPart(timestamp));
30*3f982cf4SFabien Sanglard 
31*3f982cf4SFabien Sanglard   // 2019-03-23 17:25:50.500.
32*3f982cf4SFabien Sanglard   timestamp = UINT64_C(0xe0414d0e80000000);
33*3f982cf4SFabien Sanglard   EXPECT_EQ(NtpSeconds(INT64_C(3762375950)), NtpSecondsPart(timestamp));
34*3f982cf4SFabien Sanglard   EXPECT_EQ(milliseconds(500), to_milliseconds(NtpFractionPart(timestamp)));
35*3f982cf4SFabien Sanglard }
36*3f982cf4SFabien Sanglard 
TEST(NtpTimestampTest,AssemblesFromParts)37*3f982cf4SFabien Sanglard TEST(NtpTimestampTest, AssemblesFromParts) {
38*3f982cf4SFabien Sanglard   // 1 Jan 1900.
39*3f982cf4SFabien Sanglard   NtpTimestamp timestamp =
40*3f982cf4SFabien Sanglard       AssembleNtpTimestamp(NtpSeconds::zero(), NtpFraction::zero());
41*3f982cf4SFabien Sanglard   EXPECT_EQ(UINT64_C(0x0000000000000000), timestamp);
42*3f982cf4SFabien Sanglard 
43*3f982cf4SFabien Sanglard   // 1 Jan 1900 plus 10 ms. Note that the duration_cast<NtpFraction>(10ms)
44*3f982cf4SFabien Sanglard   // truncates rather than rounds the 10ms value, so the resulting timestamp is
45*3f982cf4SFabien Sanglard   // one fractional tick less than the one found in the SplitsIntoParts test.
46*3f982cf4SFabien Sanglard   // The ~0.4 nanosecond error in the conversion is totally insignificant to a
47*3f982cf4SFabien Sanglard   // live system.
48*3f982cf4SFabien Sanglard   timestamp = AssembleNtpTimestamp(
49*3f982cf4SFabien Sanglard       NtpSeconds::zero(),
50*3f982cf4SFabien Sanglard       std::chrono::duration_cast<NtpFraction>(milliseconds(10)));
51*3f982cf4SFabien Sanglard   EXPECT_EQ(UINT64_C(0x00000000028f5c28), timestamp);
52*3f982cf4SFabien Sanglard 
53*3f982cf4SFabien Sanglard   // 1 Jan 1970 minus 2^-32 seconds.
54*3f982cf4SFabien Sanglard   timestamp = AssembleNtpTimestamp(NtpSeconds(INT64_C(2208988799)),
55*3f982cf4SFabien Sanglard                                    NtpFraction(0xffffffff));
56*3f982cf4SFabien Sanglard   EXPECT_EQ(UINT64_C(0x83aa7e7fffffffff), timestamp);
57*3f982cf4SFabien Sanglard 
58*3f982cf4SFabien Sanglard   // 2019-03-23 17:25:50.500.
59*3f982cf4SFabien Sanglard   timestamp = AssembleNtpTimestamp(
60*3f982cf4SFabien Sanglard       NtpSeconds(INT64_C(3762375950)),
61*3f982cf4SFabien Sanglard       std::chrono::duration_cast<NtpFraction>(milliseconds(500)));
62*3f982cf4SFabien Sanglard   EXPECT_EQ(UINT64_C(0xe0414d0e80000000), timestamp);
63*3f982cf4SFabien Sanglard }
64*3f982cf4SFabien Sanglard 
TEST(NtpTimeConverterTest,ConvertsToNtpTimeAndBack)65*3f982cf4SFabien Sanglard TEST(NtpTimeConverterTest, ConvertsToNtpTimeAndBack) {
66*3f982cf4SFabien Sanglard   // There is an undetermined amount of delay between the sampling of the two
67*3f982cf4SFabien Sanglard   // clocks, but that is accounted for in the design (see class comments).
68*3f982cf4SFabien Sanglard   // Normally, sampling real clocks in unit tests is a recipe for flakiness
69*3f982cf4SFabien Sanglard   // down-the-road. However, if there is flakiness in this test, then some of
70*3f982cf4SFabien Sanglard   // our core assumptions (or the design) about the time math are wrong and
71*3f982cf4SFabien Sanglard   // should be looked into!
72*3f982cf4SFabien Sanglard   const Clock::time_point steady_clock_start = Clock::now();
73*3f982cf4SFabien Sanglard   const seconds wall_clock_start = GetWallTimeSinceUnixEpoch();
74*3f982cf4SFabien Sanglard   SCOPED_TRACE(::testing::Message()
75*3f982cf4SFabien Sanglard                << "steady_clock_start.time_since_epoch().count() is "
76*3f982cf4SFabien Sanglard                << steady_clock_start.time_since_epoch().count()
77*3f982cf4SFabien Sanglard                << ", wall_clock_start.count() is " << wall_clock_start.count());
78*3f982cf4SFabien Sanglard 
79*3f982cf4SFabien Sanglard   const NtpTimeConverter converter(steady_clock_start, wall_clock_start);
80*3f982cf4SFabien Sanglard 
81*3f982cf4SFabien Sanglard   // Convert time points between the start time and 5 seconds later, in 10 ms
82*3f982cf4SFabien Sanglard   // increments. Allow the converted-back time point to be at most 1 clock tick
83*3f982cf4SFabien Sanglard   // off from the original value, but all converted values should always be
84*3f982cf4SFabien Sanglard   // monotonically increasing.
85*3f982cf4SFabien Sanglard   const Clock::time_point end_point = steady_clock_start + milliseconds(5000);
86*3f982cf4SFabien Sanglard   NtpTimestamp last_ntp_timestamp = 0;
87*3f982cf4SFabien Sanglard   Clock::time_point last_converted_back_time_point = Clock::time_point::min();
88*3f982cf4SFabien Sanglard   for (Clock::time_point t = steady_clock_start; t < end_point;
89*3f982cf4SFabien Sanglard        t += milliseconds(10)) {
90*3f982cf4SFabien Sanglard     const NtpTimestamp ntp_timestamp = converter.ToNtpTimestamp(t);
91*3f982cf4SFabien Sanglard     ASSERT_GT(ntp_timestamp, last_ntp_timestamp);
92*3f982cf4SFabien Sanglard     last_ntp_timestamp = ntp_timestamp;
93*3f982cf4SFabien Sanglard 
94*3f982cf4SFabien Sanglard     const Clock::time_point converted_back_time_point =
95*3f982cf4SFabien Sanglard         converter.ToLocalTime(ntp_timestamp);
96*3f982cf4SFabien Sanglard     ASSERT_GT(converted_back_time_point, last_converted_back_time_point);
97*3f982cf4SFabien Sanglard     last_converted_back_time_point = converted_back_time_point;
98*3f982cf4SFabien Sanglard 
99*3f982cf4SFabien Sanglard     ASSERT_NEAR(t.time_since_epoch().count(),
100*3f982cf4SFabien Sanglard                 converted_back_time_point.time_since_epoch().count(),
101*3f982cf4SFabien Sanglard                 1 /* tick */);
102*3f982cf4SFabien Sanglard   }
103*3f982cf4SFabien Sanglard }
104*3f982cf4SFabien Sanglard 
105*3f982cf4SFabien Sanglard }  // namespace cast
106*3f982cf4SFabien Sanglard }  // namespace openscreen
107