mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00

This helper method does not belong to the Clock class. Also, it's simple enough that it's not needed. Bug: webrtc:11327 Change-Id: I95a33f08fd568b293b591171ecaf5e7aef8d413c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/214123 Reviewed-by: Henrik Andreassson <henrika@webrtc.org> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Minyue Li <minyue@webrtc.org> Commit-Queue: Paul Hallak <phallak@google.com> Cr-Commit-Position: refs/heads/master@{#33652}
280 lines
8.2 KiB
C++
280 lines
8.2 KiB
C++
/*
|
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "system_wrappers/include/ntp_time.h"
|
|
|
|
#include <random>
|
|
|
|
#include "system_wrappers/include/clock.h"
|
|
#include "test/gtest.h"
|
|
|
|
namespace webrtc {
|
|
namespace {
|
|
|
|
constexpr uint32_t kNtpSec = 0x12345678;
|
|
constexpr uint32_t kNtpFrac = 0x23456789;
|
|
|
|
constexpr int64_t kOneSecQ32x32 = uint64_t{1} << 32;
|
|
constexpr int64_t kOneMsQ32x32 = 4294967;
|
|
|
|
TEST(NtpTimeTest, NoValueMeansInvalid) {
|
|
NtpTime ntp;
|
|
EXPECT_FALSE(ntp.Valid());
|
|
}
|
|
|
|
TEST(NtpTimeTest, CanResetValue) {
|
|
NtpTime ntp(kNtpSec, kNtpFrac);
|
|
EXPECT_TRUE(ntp.Valid());
|
|
ntp.Reset();
|
|
EXPECT_FALSE(ntp.Valid());
|
|
}
|
|
|
|
TEST(NtpTimeTest, CanGetWhatIsSet) {
|
|
NtpTime ntp;
|
|
ntp.Set(kNtpSec, kNtpFrac);
|
|
EXPECT_EQ(kNtpSec, ntp.seconds());
|
|
EXPECT_EQ(kNtpFrac, ntp.fractions());
|
|
}
|
|
|
|
TEST(NtpTimeTest, SetIsSameAs2ParameterConstructor) {
|
|
NtpTime ntp1(kNtpSec, kNtpFrac);
|
|
NtpTime ntp2;
|
|
EXPECT_NE(ntp1, ntp2);
|
|
|
|
ntp2.Set(kNtpSec, kNtpFrac);
|
|
EXPECT_EQ(ntp1, ntp2);
|
|
}
|
|
|
|
TEST(NtpTimeTest, ToMsMeansToNtpMilliseconds) {
|
|
SimulatedClock clock(0x123456789abc);
|
|
|
|
NtpTime ntp = clock.CurrentNtpTime();
|
|
EXPECT_EQ(ntp.ToMs(), clock.CurrentNtpInMilliseconds());
|
|
}
|
|
|
|
TEST(NtpTimeTest, CanExplicitlyConvertToAndFromUint64) {
|
|
uint64_t untyped_time = 0x123456789;
|
|
NtpTime time(untyped_time);
|
|
EXPECT_EQ(untyped_time, static_cast<uint64_t>(time));
|
|
EXPECT_EQ(NtpTime(0x12345678, 0x90abcdef), NtpTime(0x1234567890abcdef));
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyInt64MsToQ32x32NearZero) {
|
|
// Zero
|
|
EXPECT_EQ(Int64MsToQ32x32(0), 0);
|
|
|
|
// Zero + 1 millisecond
|
|
EXPECT_EQ(Int64MsToQ32x32(1), kOneMsQ32x32);
|
|
|
|
// Zero - 1 millisecond
|
|
EXPECT_EQ(Int64MsToQ32x32(-1), -kOneMsQ32x32);
|
|
|
|
// Zero + 1 second
|
|
EXPECT_EQ(Int64MsToQ32x32(1000), kOneSecQ32x32);
|
|
|
|
// Zero - 1 second
|
|
EXPECT_EQ(Int64MsToQ32x32(-1000), -kOneSecQ32x32);
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyInt64MsToUQ32x32NearZero) {
|
|
// Zero
|
|
EXPECT_EQ(Int64MsToUQ32x32(0), uint64_t{0});
|
|
|
|
// Zero + 1 millisecond
|
|
EXPECT_EQ(Int64MsToUQ32x32(1), uint64_t{kOneMsQ32x32});
|
|
|
|
// Zero - 1 millisecond
|
|
EXPECT_EQ(Int64MsToUQ32x32(-1), uint64_t{0}); // Clamped
|
|
|
|
// Zero + 1 second
|
|
EXPECT_EQ(Int64MsToUQ32x32(1000), uint64_t{kOneSecQ32x32});
|
|
|
|
// Zero - 1 second
|
|
EXPECT_EQ(Int64MsToUQ32x32(-1000), uint64_t{0}); // Clamped
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyQ32x32ToInt64MsNearZero) {
|
|
// Zero
|
|
EXPECT_EQ(Q32x32ToInt64Ms(0), 0);
|
|
|
|
// Zero + 1 millisecond
|
|
EXPECT_EQ(Q32x32ToInt64Ms(kOneMsQ32x32), 1);
|
|
|
|
// Zero - 1 millisecond
|
|
EXPECT_EQ(Q32x32ToInt64Ms(-kOneMsQ32x32), -1);
|
|
|
|
// Zero + 1 second
|
|
EXPECT_EQ(Q32x32ToInt64Ms(kOneSecQ32x32), 1000);
|
|
|
|
// Zero - 1 second
|
|
EXPECT_EQ(Q32x32ToInt64Ms(-kOneSecQ32x32), -1000);
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyUQ32x32ToInt64MsNearZero) {
|
|
// Zero
|
|
EXPECT_EQ(UQ32x32ToInt64Ms(0), 0);
|
|
|
|
// Zero + 1 millisecond
|
|
EXPECT_EQ(UQ32x32ToInt64Ms(kOneMsQ32x32), 1);
|
|
|
|
// Zero + 1 second
|
|
EXPECT_EQ(UQ32x32ToInt64Ms(kOneSecQ32x32), 1000);
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyInt64MsToQ32x32NearMax) {
|
|
constexpr int64_t kMaxQ32x32 = std::numeric_limits<int64_t>::max();
|
|
constexpr int64_t kBoundaryMs = (kMaxQ32x32 >> 32) * 1000 + 999;
|
|
|
|
// Max
|
|
const int64_t boundary_q32x32 = Int64MsToQ32x32(kBoundaryMs);
|
|
EXPECT_LE(boundary_q32x32, kMaxQ32x32);
|
|
EXPECT_GT(boundary_q32x32, kMaxQ32x32 - kOneMsQ32x32);
|
|
|
|
// Max + 1 millisecond
|
|
EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs + 1), kMaxQ32x32); // Clamped
|
|
|
|
// Max - 1 millisecond
|
|
EXPECT_LE(Int64MsToQ32x32(kBoundaryMs - 1), kMaxQ32x32 - kOneMsQ32x32);
|
|
|
|
// Max + 1 second
|
|
EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs + 1000), kMaxQ32x32); // Clamped
|
|
|
|
// Max - 1 second
|
|
EXPECT_LE(Int64MsToQ32x32(kBoundaryMs - 1000), kMaxQ32x32 - kOneSecQ32x32);
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyInt64MsToUQ32x32NearMax) {
|
|
constexpr uint64_t kMaxUQ32x32 = std::numeric_limits<uint64_t>::max();
|
|
constexpr int64_t kBoundaryMs = (kMaxUQ32x32 >> 32) * 1000 + 999;
|
|
|
|
// Max
|
|
const uint64_t boundary_uq32x32 = Int64MsToUQ32x32(kBoundaryMs);
|
|
EXPECT_LE(boundary_uq32x32, kMaxUQ32x32);
|
|
EXPECT_GT(boundary_uq32x32, kMaxUQ32x32 - kOneMsQ32x32);
|
|
|
|
// Max + 1 millisecond
|
|
EXPECT_EQ(Int64MsToUQ32x32(kBoundaryMs + 1), kMaxUQ32x32); // Clamped
|
|
|
|
// Max - 1 millisecond
|
|
EXPECT_LE(Int64MsToUQ32x32(kBoundaryMs - 1), kMaxUQ32x32 - kOneMsQ32x32);
|
|
|
|
// Max + 1 second
|
|
EXPECT_EQ(Int64MsToUQ32x32(kBoundaryMs + 1000), kMaxUQ32x32); // Clamped
|
|
|
|
// Max - 1 second
|
|
EXPECT_LE(Int64MsToUQ32x32(kBoundaryMs - 1000), kMaxUQ32x32 - kOneSecQ32x32);
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyQ32x32ToInt64MsNearMax) {
|
|
constexpr int64_t kMaxQ32x32 = std::numeric_limits<int64_t>::max();
|
|
constexpr int64_t kBoundaryMs = (kMaxQ32x32 >> 32) * 1000 + 1000;
|
|
|
|
// Max
|
|
EXPECT_EQ(Q32x32ToInt64Ms(kMaxQ32x32), kBoundaryMs);
|
|
|
|
// Max - 1 millisecond
|
|
EXPECT_EQ(Q32x32ToInt64Ms(kMaxQ32x32 - kOneMsQ32x32), kBoundaryMs - 1);
|
|
|
|
// Max - 1 second
|
|
EXPECT_EQ(Q32x32ToInt64Ms(kMaxQ32x32 - kOneSecQ32x32), kBoundaryMs - 1000);
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyUQ32x32ToInt64MsNearMax) {
|
|
constexpr uint64_t kMaxUQ32x32 = std::numeric_limits<uint64_t>::max();
|
|
constexpr int64_t kBoundaryMs = (kMaxUQ32x32 >> 32) * 1000 + 1000;
|
|
|
|
// Max
|
|
EXPECT_EQ(UQ32x32ToInt64Ms(kMaxUQ32x32), kBoundaryMs);
|
|
|
|
// Max - 1 millisecond
|
|
EXPECT_EQ(UQ32x32ToInt64Ms(kMaxUQ32x32 - kOneMsQ32x32), kBoundaryMs - 1);
|
|
|
|
// Max - 1 second
|
|
EXPECT_EQ(UQ32x32ToInt64Ms(kMaxUQ32x32 - kOneSecQ32x32), kBoundaryMs - 1000);
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyInt64MsToQ32x32NearMin) {
|
|
constexpr int64_t kBoundaryQ32x32 = 0x8000000000000000;
|
|
constexpr int64_t kBoundaryMs = -int64_t{0x80000000} * 1000;
|
|
|
|
// Min
|
|
EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs), kBoundaryQ32x32);
|
|
|
|
// Min + 1 millisecond
|
|
EXPECT_EQ(Q32x32ToInt64Ms(Int64MsToQ32x32(kBoundaryMs + 1)), kBoundaryMs + 1);
|
|
|
|
// Min - 1 millisecond
|
|
EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs - 1), kBoundaryQ32x32); // Clamped
|
|
|
|
// Min + 1 second
|
|
EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs + 1000),
|
|
kBoundaryQ32x32 + kOneSecQ32x32);
|
|
|
|
// Min - 1 second
|
|
EXPECT_EQ(Int64MsToQ32x32(kBoundaryMs - 1000), kBoundaryQ32x32); // Clamped
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyQ32x32ToInt64MsNearMin) {
|
|
constexpr int64_t kBoundaryQ32x32 = 0x8000000000000000;
|
|
constexpr int64_t kBoundaryMs = -int64_t{0x80000000} * 1000;
|
|
|
|
// Min
|
|
EXPECT_EQ(Q32x32ToInt64Ms(kBoundaryQ32x32), kBoundaryMs);
|
|
|
|
// Min + 1 millisecond
|
|
EXPECT_EQ(Q32x32ToInt64Ms(kBoundaryQ32x32 + kOneMsQ32x32), kBoundaryMs + 1);
|
|
|
|
// Min + 1 second
|
|
EXPECT_EQ(Q32x32ToInt64Ms(kBoundaryQ32x32 + kOneSecQ32x32),
|
|
kBoundaryMs + 1000);
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyInt64MsToQ32x32RoundTrip) {
|
|
constexpr int kIterations = 50000;
|
|
|
|
std::mt19937 generator(123456789);
|
|
std::uniform_int_distribution<int64_t> distribution(
|
|
Q32x32ToInt64Ms(std::numeric_limits<int64_t>::min()),
|
|
Q32x32ToInt64Ms(std::numeric_limits<int64_t>::max()));
|
|
|
|
for (int iteration = 0; iteration < kIterations; ++iteration) {
|
|
int64_t input_ms = distribution(generator);
|
|
int64_t transit_q32x32 = Int64MsToQ32x32(input_ms);
|
|
int64_t output_ms = Q32x32ToInt64Ms(transit_q32x32);
|
|
|
|
ASSERT_EQ(input_ms, output_ms)
|
|
<< "iteration = " << iteration << ", input_ms = " << input_ms
|
|
<< ", transit_q32x32 = " << transit_q32x32
|
|
<< ", output_ms = " << output_ms;
|
|
}
|
|
}
|
|
|
|
TEST(NtpTimeTest, VerifyInt64MsToUQ32x32RoundTrip) {
|
|
constexpr int kIterations = 50000;
|
|
|
|
std::mt19937 generator(123456789);
|
|
std::uniform_int_distribution<uint64_t> distribution(
|
|
UQ32x32ToInt64Ms(std::numeric_limits<uint64_t>::min()),
|
|
UQ32x32ToInt64Ms(std::numeric_limits<uint64_t>::max()));
|
|
|
|
for (int iteration = 0; iteration < kIterations; ++iteration) {
|
|
uint64_t input_ms = distribution(generator);
|
|
uint64_t transit_uq32x32 = Int64MsToUQ32x32(input_ms);
|
|
uint64_t output_ms = UQ32x32ToInt64Ms(transit_uq32x32);
|
|
|
|
ASSERT_EQ(input_ms, output_ms)
|
|
<< "iteration = " << iteration << ", input_ms = " << input_ms
|
|
<< ", transit_uq32x32 = " << transit_uq32x32
|
|
<< ", output_ms = " << output_ms;
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace webrtc
|