// Copyright 2025 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. #include "wv_timestamp.h" #include #include #include #include "wv_duration.h" namespace wvutil { namespace test { namespace { constexpr uint64_t kRawValidEpochSeconds = 1733526346; constexpr Seconds kValidEpochSeconds = Seconds(kRawValidEpochSeconds); constexpr uint64_t kRawOutOfRangeEpochSeconds = 253402300800; // Year 10000 constexpr Seconds kOutOfRangeEpochSeconds = Seconds(kRawOutOfRangeEpochSeconds); constexpr uint64_t kOneS = 1; constexpr uint64_t kOneMinuteS = kOneS * 60; constexpr uint64_t kOneHourS = kOneMinuteS * 60; constexpr uint64_t kOneDayS = kOneHourS * 24; } // namespace TEST(WvTimestampUtilTest, DefaultConstructor) { const Timestamp ts; EXPECT_FALSE(ts.IsSet()); EXPECT_EQ(ts.epoch_milliseconds(), Milliseconds::zero()); EXPECT_EQ(ts.epoch_seconds(), Seconds::zero()); } TEST(WvTimestampUtilTest, MinMax) { const Timestamp max = Timestamp::Max(); EXPECT_TRUE(max.IsSet()); const Timestamp min = Timestamp::Min(); EXPECT_TRUE(min.IsSet()); EXPECT_LE(min, max); EXPECT_GE(max, min); } TEST(WvTimestampUtilTest, FromUnixSeconds) { const Milliseconds epoch_milliseconds = std::chrono::duration_cast(kValidEpochSeconds); const Timestamp ts = Timestamp::FromUnixSeconds(kValidEpochSeconds); EXPECT_TRUE(ts.IsSet()); EXPECT_EQ(ts.epoch_seconds(), kValidEpochSeconds); EXPECT_EQ(ts.epoch_milliseconds(), epoch_milliseconds); EXPECT_EQ(ts.milliseconds(), 0u); EXPECT_EQ(ts, Timestamp::FromUnixSeconds(kRawValidEpochSeconds)); } TEST(WvTimestampUtilTest, FromUnixSeconds_WithMs) { constexpr uint32_t raw_milliseconds = 123; const Milliseconds epoch_milliseconds = kValidEpochSeconds + Milliseconds(raw_milliseconds); const Timestamp ts = Timestamp::FromUnixSeconds(kValidEpochSeconds, raw_milliseconds); EXPECT_TRUE(ts.IsSet()); EXPECT_EQ(ts.epoch_seconds(), kValidEpochSeconds); EXPECT_EQ(ts.epoch_milliseconds(), epoch_milliseconds); EXPECT_EQ(ts.milliseconds(), raw_milliseconds); EXPECT_EQ( ts, Timestamp::FromUnixSeconds(kRawValidEpochSeconds, raw_milliseconds)); } TEST(WvTimestampUtilTest, FromUnixSeconds_SecondsOutOfRange) { EXPECT_FALSE(Timestamp::FromUnixSeconds(kRawOutOfRangeEpochSeconds).IsSet()); EXPECT_FALSE(Timestamp::FromUnixSeconds(kOutOfRangeEpochSeconds).IsSet()); constexpr Seconds negative_epoch_seconds = Seconds(-1); EXPECT_FALSE(Timestamp::FromUnixSeconds(negative_epoch_seconds).IsSet()); } TEST(WvTimestampUtilTest, FromUnixSeconds_MsOutOfRange) { EXPECT_FALSE(Timestamp::FromUnixSeconds(kValidEpochSeconds, 1000).IsSet()); EXPECT_FALSE(Timestamp::FromUnixSeconds(kRawValidEpochSeconds, 1000).IsSet()); } TEST(WvTimestampUtilTest, FromUnixMilliseconds) { constexpr uint32_t raw_milliseconds = 123; constexpr uint64_t raw_total_milliseconds = (kRawValidEpochSeconds * 1000) + raw_milliseconds; constexpr Milliseconds epoch_milliseconds = Milliseconds(raw_total_milliseconds); constexpr Timestamp ts = Timestamp::FromUnixMilliseconds(epoch_milliseconds); EXPECT_TRUE(ts.IsSet()); EXPECT_EQ(ts.epoch_seconds(), kValidEpochSeconds); EXPECT_EQ(ts.epoch_milliseconds(), epoch_milliseconds); EXPECT_EQ(ts.milliseconds(), raw_milliseconds); EXPECT_EQ(ts, Timestamp::FromUnixMilliseconds(raw_total_milliseconds)); } TEST(WvTimestampUtilTest, FromUnixMilliseconds_OutOfRange) { constexpr uint64_t raw_total_milliseconds = kRawOutOfRangeEpochSeconds * 1000; constexpr Milliseconds epoch_milliseconds = Milliseconds(raw_total_milliseconds); EXPECT_FALSE(Timestamp::FromUnixMilliseconds(raw_total_milliseconds).IsSet()); EXPECT_FALSE(Timestamp::FromUnixMilliseconds(epoch_milliseconds).IsSet()); } TEST(WvTimestampUtilTest, Clear) { Timestamp ts = Timestamp::FromUnixSeconds(kValidEpochSeconds); EXPECT_TRUE(ts.IsSet()); ts.Clear(); EXPECT_FALSE(ts.IsSet()); } TEST(WvTimestampUtilTest, Comparison) { constexpr Timestamp ts_a = Timestamp::Min(); constexpr Timestamp ts_b = Timestamp::FromUnixSeconds(kRawValidEpochSeconds - kOneDayS); constexpr Timestamp ts_c = Timestamp::FromUnixSeconds(kValidEpochSeconds); constexpr Timestamp ts_d = Timestamp::FromUnixSeconds(kValidEpochSeconds, 123); constexpr Timestamp ts_e = Timestamp::Max(); // Equality EXPECT_EQ(ts_a, ts_a); EXPECT_EQ(ts_b, ts_b); EXPECT_EQ(ts_c, ts_c); EXPECT_EQ(ts_d, ts_d); EXPECT_EQ(ts_e, ts_e); // Inequality. EXPECT_NE(ts_a, ts_b); EXPECT_NE(ts_a, ts_c); EXPECT_NE(ts_a, ts_d); EXPECT_NE(ts_a, ts_e); EXPECT_NE(ts_b, ts_c); EXPECT_NE(ts_b, ts_d); EXPECT_NE(ts_b, ts_e); EXPECT_NE(ts_c, ts_d); EXPECT_NE(ts_c, ts_e); EXPECT_NE(ts_d, ts_e); // Less than EXPECT_LT(ts_a, ts_b); EXPECT_LT(ts_a, ts_c); EXPECT_LT(ts_a, ts_d); EXPECT_LT(ts_a, ts_e); EXPECT_LT(ts_b, ts_c); EXPECT_LT(ts_b, ts_d); EXPECT_LT(ts_b, ts_e); EXPECT_LT(ts_c, ts_d); EXPECT_LT(ts_c, ts_e); EXPECT_LT(ts_d, ts_e); // Less than or equal. EXPECT_LE(ts_a, ts_a); EXPECT_LE(ts_a, ts_b); EXPECT_LE(ts_a, ts_c); EXPECT_LE(ts_a, ts_d); EXPECT_LE(ts_a, ts_e); EXPECT_LE(ts_b, ts_b); EXPECT_LE(ts_b, ts_c); EXPECT_LE(ts_b, ts_d); EXPECT_LE(ts_b, ts_e); EXPECT_LE(ts_c, ts_c); EXPECT_LE(ts_c, ts_d); EXPECT_LE(ts_c, ts_e); EXPECT_LE(ts_d, ts_d); EXPECT_LE(ts_d, ts_e); EXPECT_LE(ts_e, ts_e); // Greater than EXPECT_GT(ts_b, ts_a); EXPECT_GT(ts_c, ts_a); EXPECT_GT(ts_d, ts_a); EXPECT_GT(ts_e, ts_a); EXPECT_GT(ts_c, ts_b); EXPECT_GT(ts_d, ts_b); EXPECT_GT(ts_e, ts_b); EXPECT_GT(ts_d, ts_c); EXPECT_GT(ts_e, ts_c); EXPECT_GT(ts_e, ts_d); // Greater than or equal. EXPECT_GE(ts_a, ts_a); EXPECT_GE(ts_b, ts_a); EXPECT_GE(ts_c, ts_a); EXPECT_GE(ts_d, ts_a); EXPECT_GE(ts_e, ts_a); EXPECT_GE(ts_b, ts_b); EXPECT_GE(ts_c, ts_b); EXPECT_GE(ts_d, ts_b); EXPECT_GE(ts_e, ts_b); EXPECT_GE(ts_c, ts_c); EXPECT_GE(ts_d, ts_c); EXPECT_GE(ts_e, ts_c); EXPECT_GE(ts_d, ts_d); EXPECT_GE(ts_e, ts_d); EXPECT_GE(ts_e, ts_e); } TEST(WvTimestampUtilTest, Addition_WithDuration) { constexpr Timestamp start = Timestamp::FromUnixSeconds(kValidEpochSeconds); constexpr Duration one_day = Duration::FromSeconds(kOneDayS); constexpr Timestamp tomorrow = start + one_day; constexpr decltype(tomorrow.epoch_seconds().count()) expected_second_count = kRawValidEpochSeconds + kOneDayS; EXPECT_EQ(tomorrow.epoch_seconds().count(), expected_second_count); } TEST(WvTimestampUtilTest, Addition_WithDuration_Unset) { constexpr Timestamp unset; constexpr Duration one_day = Duration::FromSeconds(kOneDayS); constexpr Timestamp result = unset + one_day; EXPECT_FALSE(result.IsSet()); } TEST(WvTimestampUtilTest, Addition_WithDuration_Overflow) { Timestamp start = Timestamp::Max(); constexpr Duration one_day = Duration::FromSeconds(kOneDayS); Timestamp result = start + one_day; EXPECT_FALSE(result.IsSet()); start = Timestamp::Min(); constexpr Duration very_long_duration = Duration::FromSeconds(kOneDayS * 365 * 10000); result = start + very_long_duration; EXPECT_FALSE(result.IsSet()); } TEST(WvTimestampUtilTest, Subtraction_WithDuration) { constexpr Timestamp start = Timestamp::FromUnixSeconds(kValidEpochSeconds); constexpr Duration one_day = Duration::FromSeconds(kOneDayS); constexpr Timestamp yesterday = start - one_day; constexpr decltype(yesterday.epoch_seconds().count()) expected_second_count = kRawValidEpochSeconds - kOneDayS; EXPECT_EQ(yesterday.epoch_seconds().count(), expected_second_count); } TEST(WvTimestampUtilTest, Subtraction_WithDuration_Unset) { constexpr Timestamp unset; constexpr Duration one_day = Duration::FromSeconds(kOneDayS); constexpr Timestamp result = unset - one_day; EXPECT_FALSE(result.IsSet()); } TEST(WvTimestampUtilTest, Subtraction_WithDuration_Underflow) { Timestamp start = Timestamp::Min(); constexpr Duration one_day = Duration::FromSeconds(kOneDayS); Timestamp result = start - one_day; EXPECT_FALSE(result.IsSet()); start = Timestamp::Max(); constexpr Duration very_long_duration = Duration::FromSeconds(kOneDayS * 365 * 10000); result = start - very_long_duration; EXPECT_FALSE(result.IsSet()); } TEST(WvTimestampUtilTest, Difference) { // 4 days, 3 hours, 2 minutes and 1 second. constexpr int64_t kDifferenceS = 1 + 2 * kOneMinuteS + 3 * kOneHourS + 4 * kOneDayS; constexpr Timestamp ts_a = Timestamp::FromUnixSeconds(kValidEpochSeconds); constexpr Timestamp ts_b = Timestamp::FromUnixSeconds(kRawValidEpochSeconds + kDifferenceS); constexpr Duration diff_ab = ts_b - ts_a; EXPECT_EQ(diff_ab.total_seconds().count(), kDifferenceS); constexpr Duration diff_ba = ts_a - ts_b; EXPECT_EQ(diff_ba.total_seconds().count(), -kDifferenceS); } TEST(WvTimestampUtilTest, Difference_Unset) { constexpr Duration unset_duration; constexpr Timestamp ts = Timestamp::FromUnixSeconds(kValidEpochSeconds); constexpr Timestamp unset; EXPECT_EQ(ts - unset, unset_duration); EXPECT_EQ(unset - ts, unset_duration); EXPECT_EQ(unset - unset, unset_duration); } } // namespace test } // namespace wvutil