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