You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
4.4 KiB
107 lines
4.4 KiB
// Copyright 2019 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "cast/streaming/ntp_time.h"
|
|
|
|
#include <chrono>
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "util/chrono_helpers.h"
|
|
|
|
namespace openscreen {
|
|
namespace cast {
|
|
|
|
TEST(NtpTimestampTest, SplitsIntoParts) {
|
|
// 1 Jan 1900.
|
|
NtpTimestamp timestamp = UINT64_C(0x0000000000000000);
|
|
EXPECT_EQ(NtpSeconds::zero(), NtpSecondsPart(timestamp));
|
|
EXPECT_EQ(NtpFraction::zero(), NtpFractionPart(timestamp));
|
|
|
|
// 1 Jan 1900 plus 10 ms.
|
|
timestamp = UINT64_C(0x00000000028f5c29);
|
|
EXPECT_EQ(NtpSeconds::zero(), NtpSecondsPart(timestamp));
|
|
EXPECT_EQ(milliseconds(10), to_milliseconds(NtpFractionPart(timestamp)));
|
|
|
|
// 1 Jan 1970 minus 2^-32 seconds.
|
|
timestamp = UINT64_C(0x83aa7e80ffffffff);
|
|
EXPECT_EQ(NtpSeconds(INT64_C(2208988800)), NtpSecondsPart(timestamp));
|
|
EXPECT_EQ(NtpFraction(0xffffffff), NtpFractionPart(timestamp));
|
|
|
|
// 2019-03-23 17:25:50.500.
|
|
timestamp = UINT64_C(0xe0414d0e80000000);
|
|
EXPECT_EQ(NtpSeconds(INT64_C(3762375950)), NtpSecondsPart(timestamp));
|
|
EXPECT_EQ(milliseconds(500), to_milliseconds(NtpFractionPart(timestamp)));
|
|
}
|
|
|
|
TEST(NtpTimestampTest, AssemblesFromParts) {
|
|
// 1 Jan 1900.
|
|
NtpTimestamp timestamp =
|
|
AssembleNtpTimestamp(NtpSeconds::zero(), NtpFraction::zero());
|
|
EXPECT_EQ(UINT64_C(0x0000000000000000), timestamp);
|
|
|
|
// 1 Jan 1900 plus 10 ms. Note that the duration_cast<NtpFraction>(10ms)
|
|
// truncates rather than rounds the 10ms value, so the resulting timestamp is
|
|
// one fractional tick less than the one found in the SplitsIntoParts test.
|
|
// The ~0.4 nanosecond error in the conversion is totally insignificant to a
|
|
// live system.
|
|
timestamp = AssembleNtpTimestamp(
|
|
NtpSeconds::zero(),
|
|
std::chrono::duration_cast<NtpFraction>(milliseconds(10)));
|
|
EXPECT_EQ(UINT64_C(0x00000000028f5c28), timestamp);
|
|
|
|
// 1 Jan 1970 minus 2^-32 seconds.
|
|
timestamp = AssembleNtpTimestamp(NtpSeconds(INT64_C(2208988799)),
|
|
NtpFraction(0xffffffff));
|
|
EXPECT_EQ(UINT64_C(0x83aa7e7fffffffff), timestamp);
|
|
|
|
// 2019-03-23 17:25:50.500.
|
|
timestamp = AssembleNtpTimestamp(
|
|
NtpSeconds(INT64_C(3762375950)),
|
|
std::chrono::duration_cast<NtpFraction>(milliseconds(500)));
|
|
EXPECT_EQ(UINT64_C(0xe0414d0e80000000), timestamp);
|
|
}
|
|
|
|
TEST(NtpTimeConverterTest, ConvertsToNtpTimeAndBack) {
|
|
// There is an undetermined amount of delay between the sampling of the two
|
|
// clocks, but that is accounted for in the design (see class comments).
|
|
// Normally, sampling real clocks in unit tests is a recipe for flakiness
|
|
// down-the-road. However, if there is flakiness in this test, then some of
|
|
// our core assumptions (or the design) about the time math are wrong and
|
|
// should be looked into!
|
|
const Clock::time_point steady_clock_start = Clock::now();
|
|
const seconds wall_clock_start = GetWallTimeSinceUnixEpoch();
|
|
SCOPED_TRACE(::testing::Message()
|
|
<< "steady_clock_start.time_since_epoch().count() is "
|
|
<< steady_clock_start.time_since_epoch().count()
|
|
<< ", wall_clock_start.count() is " << wall_clock_start.count());
|
|
|
|
const NtpTimeConverter converter(steady_clock_start, wall_clock_start);
|
|
|
|
// Convert time points between the start time and 5 seconds later, in 10 ms
|
|
// increments. Allow the converted-back time point to be at most 1 clock tick
|
|
// off from the original value, but all converted values should always be
|
|
// monotonically increasing.
|
|
const Clock::time_point end_point = steady_clock_start + milliseconds(5000);
|
|
NtpTimestamp last_ntp_timestamp = 0;
|
|
Clock::time_point last_converted_back_time_point = Clock::time_point::min();
|
|
for (Clock::time_point t = steady_clock_start; t < end_point;
|
|
t += milliseconds(10)) {
|
|
const NtpTimestamp ntp_timestamp = converter.ToNtpTimestamp(t);
|
|
ASSERT_GT(ntp_timestamp, last_ntp_timestamp);
|
|
last_ntp_timestamp = ntp_timestamp;
|
|
|
|
const Clock::time_point converted_back_time_point =
|
|
converter.ToLocalTime(ntp_timestamp);
|
|
ASSERT_GT(converted_back_time_point, last_converted_back_time_point);
|
|
last_converted_back_time_point = converted_back_time_point;
|
|
|
|
ASSERT_NEAR(t.time_since_epoch().count(),
|
|
converted_back_time_point.time_since_epoch().count(),
|
|
1 /* tick */);
|
|
}
|
|
}
|
|
|
|
} // namespace cast
|
|
} // namespace openscreen
|