// Copyright 2017 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #if defined(_MSC_VER) #include // for timeval #endif #include "absl/base/config.h" // For feature testing and determining which headers can be included. #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L #include #endif #include #include #include // NOLINT(build/c++11) #ifdef __cpp_lib_three_way_comparison #include #endif // __cpp_lib_three_way_comparison #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/str_format.h" #include "absl/time/time.h" namespace { constexpr int64_t kint64max = std::numeric_limits::max(); constexpr int64_t kint64min = std::numeric_limits::min(); // Approximates the given number of years. This is only used to make some test // code more readable. absl::Duration ApproxYears(int64_t n) { return absl::Hours(n) * 365 * 24; } // A gMock matcher to match timespec values. Use this matcher like: // timespec ts1, ts2; // EXPECT_THAT(ts1, TimespecMatcher(ts2)); MATCHER_P(TimespecMatcher, ts, "") { if (ts.tv_sec == arg.tv_sec && ts.tv_nsec == arg.tv_nsec) return true; *result_listener << "expected: {" << ts.tv_sec << ", " << ts.tv_nsec << "} "; *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_nsec << "}"; return false; } // A gMock matcher to match timeval values. Use this matcher like: // timeval tv1, tv2; // EXPECT_THAT(tv1, TimevalMatcher(tv2)); MATCHER_P(TimevalMatcher, tv, "") { if (tv.tv_sec == arg.tv_sec && tv.tv_usec == arg.tv_usec) return true; *result_listener << "expected: {" << tv.tv_sec << ", " << tv.tv_usec << "} "; *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_usec << "}"; return false; } TEST(Duration, ConstExpr) { constexpr absl::Duration d0 = absl::ZeroDuration(); static_assert(d0 == absl::ZeroDuration(), "ZeroDuration()"); constexpr absl::Duration d1 = absl::Seconds(1); static_assert(d1 == absl::Seconds(1), "Seconds(1)"); static_assert(d1 != absl::ZeroDuration(), "Seconds(1)"); constexpr absl::Duration d2 = absl::InfiniteDuration(); static_assert(d2 == absl::InfiniteDuration(), "InfiniteDuration()"); static_assert(d2 != absl::ZeroDuration(), "InfiniteDuration()"); } TEST(Duration, ValueSemantics) { // If this compiles, the test passes. constexpr absl::Duration a; // Default construction constexpr absl::Duration b = a; // Copy construction constexpr absl::Duration c(b); // Copy construction (again) absl::Duration d; d = c; // Assignment } TEST(Duration, Factories) { constexpr absl::Duration zero = absl::ZeroDuration(); constexpr absl::Duration nano = absl::Nanoseconds(1); constexpr absl::Duration micro = absl::Microseconds(1); constexpr absl::Duration milli = absl::Milliseconds(1); constexpr absl::Duration sec = absl::Seconds(1); constexpr absl::Duration min = absl::Minutes(1); constexpr absl::Duration hour = absl::Hours(1); EXPECT_EQ(zero, absl::Duration()); EXPECT_EQ(zero, absl::Seconds(0)); EXPECT_EQ(nano, absl::Nanoseconds(1)); EXPECT_EQ(micro, absl::Nanoseconds(1000)); EXPECT_EQ(milli, absl::Microseconds(1000)); EXPECT_EQ(sec, absl::Milliseconds(1000)); EXPECT_EQ(min, absl::Seconds(60)); EXPECT_EQ(hour, absl::Minutes(60)); // Tests factory limits const absl::Duration inf = absl::InfiniteDuration(); EXPECT_GT(inf, absl::Seconds(kint64max)); EXPECT_LT(-inf, absl::Seconds(kint64min)); EXPECT_LT(-inf, absl::Seconds(-kint64max)); EXPECT_EQ(inf, absl::Minutes(kint64max)); EXPECT_EQ(-inf, absl::Minutes(kint64min)); EXPECT_EQ(-inf, absl::Minutes(-kint64max)); EXPECT_GT(inf, absl::Minutes(kint64max / 60)); EXPECT_LT(-inf, absl::Minutes(kint64min / 60)); EXPECT_LT(-inf, absl::Minutes(-kint64max / 60)); EXPECT_EQ(inf, absl::Hours(kint64max)); EXPECT_EQ(-inf, absl::Hours(kint64min)); EXPECT_EQ(-inf, absl::Hours(-kint64max)); EXPECT_GT(inf, absl::Hours(kint64max / 3600)); EXPECT_LT(-inf, absl::Hours(kint64min / 3600)); EXPECT_LT(-inf, absl::Hours(-kint64max / 3600)); } TEST(Duration, ToConversion) { #define TEST_DURATION_CONVERSION(UNIT) \ do { \ const absl::Duration d = absl::UNIT(1.5); \ constexpr absl::Duration z = absl::ZeroDuration(); \ constexpr absl::Duration inf = absl::InfiniteDuration(); \ constexpr double dbl_inf = std::numeric_limits::infinity(); \ EXPECT_EQ(kint64min, absl::ToInt64##UNIT(-inf)); \ EXPECT_EQ(-1, absl::ToInt64##UNIT(-d)); \ EXPECT_EQ(0, absl::ToInt64##UNIT(z)); \ EXPECT_EQ(1, absl::ToInt64##UNIT(d)); \ EXPECT_EQ(kint64max, absl::ToInt64##UNIT(inf)); \ EXPECT_EQ(-dbl_inf, absl::ToDouble##UNIT(-inf)); \ EXPECT_EQ(-1.5, absl::ToDouble##UNIT(-d)); \ EXPECT_EQ(0, absl::ToDouble##UNIT(z)); \ EXPECT_EQ(1.5, absl::ToDouble##UNIT(d)); \ EXPECT_EQ(dbl_inf, absl::ToDouble##UNIT(inf)); \ } while (0) TEST_DURATION_CONVERSION(Nanoseconds); TEST_DURATION_CONVERSION(Microseconds); TEST_DURATION_CONVERSION(Milliseconds); TEST_DURATION_CONVERSION(Seconds); TEST_DURATION_CONVERSION(Minutes); TEST_DURATION_CONVERSION(Hours); #undef TEST_DURATION_CONVERSION } template void TestToConversion() { constexpr absl::Duration nano = absl::Nanoseconds(N); EXPECT_EQ(N, absl::ToInt64Nanoseconds(nano)); EXPECT_EQ(0, absl::ToInt64Microseconds(nano)); EXPECT_EQ(0, absl::ToInt64Milliseconds(nano)); EXPECT_EQ(0, absl::ToInt64Seconds(nano)); EXPECT_EQ(0, absl::ToInt64Minutes(nano)); EXPECT_EQ(0, absl::ToInt64Hours(nano)); const absl::Duration micro = absl::Microseconds(N); EXPECT_EQ(N * 1000, absl::ToInt64Nanoseconds(micro)); EXPECT_EQ(N, absl::ToInt64Microseconds(micro)); EXPECT_EQ(0, absl::ToInt64Milliseconds(micro)); EXPECT_EQ(0, absl::ToInt64Seconds(micro)); EXPECT_EQ(0, absl::ToInt64Minutes(micro)); EXPECT_EQ(0, absl::ToInt64Hours(micro)); const absl::Duration milli = absl::Milliseconds(N); EXPECT_EQ(N * 1000 * 1000, absl::ToInt64Nanoseconds(milli)); EXPECT_EQ(N * 1000, absl::ToInt64Microseconds(milli)); EXPECT_EQ(N, absl::ToInt64Milliseconds(milli)); EXPECT_EQ(0, absl::ToInt64Seconds(milli)); EXPECT_EQ(0, absl::ToInt64Minutes(milli)); EXPECT_EQ(0, absl::ToInt64Hours(milli)); const absl::Duration sec = absl::Seconds(N); EXPECT_EQ(N * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(sec)); EXPECT_EQ(N * 1000 * 1000, absl::ToInt64Microseconds(sec)); EXPECT_EQ(N * 1000, absl::ToInt64Milliseconds(sec)); EXPECT_EQ(N, absl::ToInt64Seconds(sec)); EXPECT_EQ(0, absl::ToInt64Minutes(sec)); EXPECT_EQ(0, absl::ToInt64Hours(sec)); const absl::Duration min = absl::Minutes(N); EXPECT_EQ(N * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(min)); EXPECT_EQ(N * 60 * 1000 * 1000, absl::ToInt64Microseconds(min)); EXPECT_EQ(N * 60 * 1000, absl::ToInt64Milliseconds(min)); EXPECT_EQ(N * 60, absl::ToInt64Seconds(min)); EXPECT_EQ(N, absl::ToInt64Minutes(min)); EXPECT_EQ(0, absl::ToInt64Hours(min)); const absl::Duration hour = absl::Hours(N); EXPECT_EQ(N * 60 * 60 * 1000 * 1000 * 1000, absl::ToInt64Nanoseconds(hour)); EXPECT_EQ(N * 60 * 60 * 1000 * 1000, absl::ToInt64Microseconds(hour)); EXPECT_EQ(N * 60 * 60 * 1000, absl::ToInt64Milliseconds(hour)); EXPECT_EQ(N * 60 * 60, absl::ToInt64Seconds(hour)); EXPECT_EQ(N * 60, absl::ToInt64Minutes(hour)); EXPECT_EQ(N, absl::ToInt64Hours(hour)); } TEST(Duration, ToConversionDeprecated) { TestToConversion<43>(); TestToConversion<1>(); TestToConversion<0>(); TestToConversion<-1>(); TestToConversion<-43>(); } template void TestFromChronoBasicEquality() { using std::chrono::nanoseconds; using std::chrono::microseconds; using std::chrono::milliseconds; using std::chrono::seconds; using std::chrono::minutes; using std::chrono::hours; static_assert(absl::Nanoseconds(N) == absl::FromChrono(nanoseconds(N)), ""); static_assert(absl::Microseconds(N) == absl::FromChrono(microseconds(N)), ""); static_assert(absl::Milliseconds(N) == absl::FromChrono(milliseconds(N)), ""); static_assert(absl::Seconds(N) == absl::FromChrono(seconds(N)), ""); static_assert(absl::Minutes(N) == absl::FromChrono(minutes(N)), ""); static_assert(absl::Hours(N) == absl::FromChrono(hours(N)), ""); } TEST(Duration, FromChrono) { TestFromChronoBasicEquality<-123>(); TestFromChronoBasicEquality<-1>(); TestFromChronoBasicEquality<0>(); TestFromChronoBasicEquality<1>(); TestFromChronoBasicEquality<123>(); // Minutes (might, depending on the platform) saturate at +inf. const auto chrono_minutes_max = std::chrono::minutes::max(); const auto minutes_max = absl::FromChrono(chrono_minutes_max); const int64_t minutes_max_count = chrono_minutes_max.count(); if (minutes_max_count > kint64max / 60) { EXPECT_EQ(absl::InfiniteDuration(), minutes_max); } else { EXPECT_EQ(absl::Minutes(minutes_max_count), minutes_max); } // Minutes (might, depending on the platform) saturate at -inf. const auto chrono_minutes_min = std::chrono::minutes::min(); const auto minutes_min = absl::FromChrono(chrono_minutes_min); const int64_t minutes_min_count = chrono_minutes_min.count(); if (minutes_min_count < kint64min / 60) { EXPECT_EQ(-absl::InfiniteDuration(), minutes_min); } else { EXPECT_EQ(absl::Minutes(minutes_min_count), minutes_min); } // Hours (might, depending on the platform) saturate at +inf. const auto chrono_hours_max = std::chrono::hours::max(); const auto hours_max = absl::FromChrono(chrono_hours_max); const int64_t hours_max_count = chrono_hours_max.count(); if (hours_max_count > kint64max / 3600) { EXPECT_EQ(absl::InfiniteDuration(), hours_max); } else { EXPECT_EQ(absl::Hours(hours_max_count), hours_max); } // Hours (might, depending on the platform) saturate at -inf. const auto chrono_hours_min = std::chrono::hours::min(); const auto hours_min = absl::FromChrono(chrono_hours_min); const int64_t hours_min_count = chrono_hours_min.count(); if (hours_min_count < kint64min / 3600) { EXPECT_EQ(-absl::InfiniteDuration(), hours_min); } else { EXPECT_EQ(absl::Hours(hours_min_count), hours_min); } } template void TestToChrono() { using std::chrono::nanoseconds; using std::chrono::microseconds; using std::chrono::milliseconds; using std::chrono::seconds; using std::chrono::minutes; using std::chrono::hours; EXPECT_EQ(nanoseconds(N), absl::ToChronoNanoseconds(absl::Nanoseconds(N))); EXPECT_EQ(microseconds(N), absl::ToChronoMicroseconds(absl::Microseconds(N))); EXPECT_EQ(milliseconds(N), absl::ToChronoMilliseconds(absl::Milliseconds(N))); EXPECT_EQ(seconds(N), absl::ToChronoSeconds(absl::Seconds(N))); constexpr auto absl_minutes = absl::Minutes(N); auto chrono_minutes = minutes(N); if (absl_minutes == -absl::InfiniteDuration()) { chrono_minutes = minutes::min(); } else if (absl_minutes == absl::InfiniteDuration()) { chrono_minutes = minutes::max(); } EXPECT_EQ(chrono_minutes, absl::ToChronoMinutes(absl_minutes)); constexpr auto absl_hours = absl::Hours(N); auto chrono_hours = hours(N); if (absl_hours == -absl::InfiniteDuration()) { chrono_hours = hours::min(); } else if (absl_hours == absl::InfiniteDuration()) { chrono_hours = hours::max(); } EXPECT_EQ(chrono_hours, absl::ToChronoHours(absl_hours)); } TEST(Duration, ToChrono) { using std::chrono::nanoseconds; using std::chrono::microseconds; using std::chrono::milliseconds; using std::chrono::seconds; using std::chrono::minutes; using std::chrono::hours; TestToChrono(); TestToChrono<-1>(); TestToChrono<0>(); TestToChrono<1>(); TestToChrono(); // Verify truncation toward zero. const auto tick = absl::Nanoseconds(1) / 4; EXPECT_EQ(nanoseconds(0), absl::ToChronoNanoseconds(tick)); EXPECT_EQ(nanoseconds(0), absl::ToChronoNanoseconds(-tick)); EXPECT_EQ(microseconds(0), absl::ToChronoMicroseconds(tick)); EXPECT_EQ(microseconds(0), absl::ToChronoMicroseconds(-tick)); EXPECT_EQ(milliseconds(0), absl::ToChronoMilliseconds(tick)); EXPECT_EQ(milliseconds(0), absl::ToChronoMilliseconds(-tick)); EXPECT_EQ(seconds(0), absl::ToChronoSeconds(tick)); EXPECT_EQ(seconds(0), absl::ToChronoSeconds(-tick)); EXPECT_EQ(minutes(0), absl::ToChronoMinutes(tick)); EXPECT_EQ(minutes(0), absl::ToChronoMinutes(-tick)); EXPECT_EQ(hours(0), absl::ToChronoHours(tick)); EXPECT_EQ(hours(0), absl::ToChronoHours(-tick)); // Verifies +/- infinity saturation at max/min. constexpr auto inf = absl::InfiniteDuration(); EXPECT_EQ(nanoseconds::min(), absl::ToChronoNanoseconds(-inf)); EXPECT_EQ(nanoseconds::max(), absl::ToChronoNanoseconds(inf)); EXPECT_EQ(microseconds::min(), absl::ToChronoMicroseconds(-inf)); EXPECT_EQ(microseconds::max(), absl::ToChronoMicroseconds(inf)); EXPECT_EQ(milliseconds::min(), absl::ToChronoMilliseconds(-inf)); EXPECT_EQ(milliseconds::max(), absl::ToChronoMilliseconds(inf)); EXPECT_EQ(seconds::min(), absl::ToChronoSeconds(-inf)); EXPECT_EQ(seconds::max(), absl::ToChronoSeconds(inf)); EXPECT_EQ(minutes::min(), absl::ToChronoMinutes(-inf)); EXPECT_EQ(minutes::max(), absl::ToChronoMinutes(inf)); EXPECT_EQ(hours::min(), absl::ToChronoHours(-inf)); EXPECT_EQ(hours::max(), absl::ToChronoHours(inf)); } TEST(Duration, FactoryOverloads) { enum E { kOne = 1 }; #define TEST_FACTORY_OVERLOADS(NAME) \ EXPECT_EQ(1, NAME(kOne) / NAME(kOne)); \ EXPECT_EQ(1, NAME(static_cast(1)) / NAME(1)); \ EXPECT_EQ(1, NAME(static_cast(1)) / NAME(1)); \ EXPECT_EQ(1, NAME(static_cast(1)) / NAME(1)); \ EXPECT_EQ(1, NAME(static_cast(1)) / NAME(1)); \ EXPECT_EQ(1, NAME(static_cast(1)) / NAME(1)); \ EXPECT_EQ(1, NAME(static_cast(1)) / NAME(1)); \ EXPECT_EQ(1, NAME(static_cast(1)) / NAME(1)); \ EXPECT_EQ(1, NAME(static_cast(1)) / NAME(1)); \ EXPECT_EQ(NAME(1) / 2, NAME(static_cast(0.5))); \ EXPECT_EQ(NAME(1) / 2, NAME(static_cast(0.5))); \ EXPECT_EQ(1.5, absl::FDivDuration(NAME(static_cast(1.5)), NAME(1))); \ EXPECT_EQ(1.5, absl::FDivDuration(NAME(static_cast(1.5)), NAME(1))); TEST_FACTORY_OVERLOADS(absl::Nanoseconds); TEST_FACTORY_OVERLOADS(absl::Microseconds); TEST_FACTORY_OVERLOADS(absl::Milliseconds); TEST_FACTORY_OVERLOADS(absl::Seconds); TEST_FACTORY_OVERLOADS(absl::Minutes); TEST_FACTORY_OVERLOADS(absl::Hours); #undef TEST_FACTORY_OVERLOADS EXPECT_EQ(absl::Milliseconds(1500), absl::Seconds(1.5)); EXPECT_LT(absl::Nanoseconds(1), absl::Nanoseconds(1.5)); EXPECT_GT(absl::Nanoseconds(2), absl::Nanoseconds(1.5)); const double dbl_inf = std::numeric_limits::infinity(); EXPECT_EQ(absl::InfiniteDuration(), absl::Nanoseconds(dbl_inf)); EXPECT_EQ(absl::InfiniteDuration(), absl::Microseconds(dbl_inf)); EXPECT_EQ(absl::InfiniteDuration(), absl::Milliseconds(dbl_inf)); EXPECT_EQ(absl::InfiniteDuration(), absl::Seconds(dbl_inf)); EXPECT_EQ(absl::InfiniteDuration(), absl::Minutes(dbl_inf)); EXPECT_EQ(absl::InfiniteDuration(), absl::Hours(dbl_inf)); EXPECT_EQ(-absl::InfiniteDuration(), absl::Nanoseconds(-dbl_inf)); EXPECT_EQ(-absl::InfiniteDuration(), absl::Microseconds(-dbl_inf)); EXPECT_EQ(-absl::InfiniteDuration(), absl::Milliseconds(-dbl_inf)); EXPECT_EQ(-absl::InfiniteDuration(), absl::Seconds(-dbl_inf)); EXPECT_EQ(-absl::InfiniteDuration(), absl::Minutes(-dbl_inf)); EXPECT_EQ(-absl::InfiniteDuration(), absl::Hours(-dbl_inf)); } TEST(Duration, InfinityExamples) { // These examples are used in the documentation in time.h. They are // written so that they can be copy-n-pasted easily. constexpr absl::Duration inf = absl::InfiniteDuration(); constexpr absl::Duration d = absl::Seconds(1); // Any finite duration EXPECT_TRUE(inf == inf + inf); EXPECT_TRUE(inf == inf + d); EXPECT_TRUE(inf == inf - inf); EXPECT_TRUE(-inf == d - inf); EXPECT_TRUE(inf == d * 1e100); EXPECT_TRUE(0 == d / inf); // NOLINT(readability/check) // Division by zero returns infinity, or kint64min/MAX where necessary. EXPECT_TRUE(inf == d / 0); EXPECT_TRUE(kint64max == d / absl::ZeroDuration()); } TEST(Duration, InfinityComparison) { const absl::Duration inf = absl::InfiniteDuration(); const absl::Duration any_dur = absl::Seconds(1); // Equality EXPECT_EQ(inf, inf); EXPECT_EQ(-inf, -inf); EXPECT_NE(inf, -inf); EXPECT_NE(any_dur, inf); EXPECT_NE(any_dur, -inf); // Relational EXPECT_GT(inf, any_dur); EXPECT_LT(-inf, any_dur); EXPECT_LT(-inf, inf); EXPECT_GT(inf, -inf); #ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON EXPECT_EQ(inf <=> inf, std::strong_ordering::equal); EXPECT_EQ(-inf <=> -inf, std::strong_ordering::equal); EXPECT_EQ(-inf <=> inf, std::strong_ordering::less); EXPECT_EQ(inf <=> -inf, std::strong_ordering::greater); EXPECT_EQ(any_dur <=> inf, std::strong_ordering::less); EXPECT_EQ(any_dur <=> -inf, std::strong_ordering::greater); #endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON } TEST(Duration, InfinityAddition) { const absl::Duration sec_max = absl::Seconds(kint64max); const absl::Duration sec_min = absl::Seconds(kint64min); const absl::Duration any_dur = absl::Seconds(1); const absl::Duration inf = absl::InfiniteDuration(); // Addition EXPECT_EQ(inf, inf + inf); EXPECT_EQ(inf, inf + -inf); EXPECT_EQ(-inf, -inf + inf); EXPECT_EQ(-inf, -inf + -inf); EXPECT_EQ(inf, inf + any_dur); EXPECT_EQ(inf, any_dur + inf); EXPECT_EQ(-inf, -inf + any_dur); EXPECT_EQ(-inf, any_dur + -inf); // Interesting case absl::Duration almost_inf = sec_max + absl::Nanoseconds(999999999); EXPECT_GT(inf, almost_inf); almost_inf += -absl::Nanoseconds(999999999); EXPECT_GT(inf, almost_inf); // Addition overflow/underflow EXPECT_EQ(inf, sec_max + absl::Seconds(1)); EXPECT_EQ(inf, sec_max + sec_max); EXPECT_EQ(-inf, sec_min + -absl::Seconds(1)); EXPECT_EQ(-inf, sec_min + -sec_max); // For reference: IEEE 754 behavior const double dbl_inf = std::numeric_limits::infinity(); EXPECT_TRUE(std::isinf(dbl_inf + dbl_inf)); EXPECT_TRUE(std::isnan(dbl_inf + -dbl_inf)); // We return inf EXPECT_TRUE(std::isnan(-dbl_inf + dbl_inf)); // We return inf EXPECT_TRUE(std::isinf(-dbl_inf + -dbl_inf)); } TEST(Duration, InfinitySubtraction) { const absl::Duration sec_max = absl::Seconds(kint64max); const absl::Duration sec_min = absl::Seconds(kint64min); const absl::Duration any_dur = absl::Seconds(1); const absl::Duration inf = absl::InfiniteDuration(); // Subtraction EXPECT_EQ(inf, inf - inf); EXPECT_EQ(inf, inf - -inf); EXPECT_EQ(-inf, -inf - inf); EXPECT_EQ(-inf, -inf - -inf); EXPECT_EQ(inf, inf - any_dur); EXPECT_EQ(-inf, any_dur - inf); EXPECT_EQ(-inf, -inf - any_dur); EXPECT_EQ(inf, any_dur - -inf); // Subtraction overflow/underflow EXPECT_EQ(inf, sec_max - -absl::Seconds(1)); EXPECT_EQ(inf, sec_max - -sec_max); EXPECT_EQ(-inf, sec_min - absl::Seconds(1)); EXPECT_EQ(-inf, sec_min - sec_max); // Interesting case absl::Duration almost_neg_inf = sec_min; EXPECT_LT(-inf, almost_neg_inf); #ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less); EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater); #endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON almost_neg_inf -= -absl::Nanoseconds(1); EXPECT_LT(-inf, almost_neg_inf); #ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less); EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater); #endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON // For reference: IEEE 754 behavior const double dbl_inf = std::numeric_limits::infinity(); EXPECT_TRUE(std::isnan(dbl_inf - dbl_inf)); // We return inf EXPECT_TRUE(std::isinf(dbl_inf - -dbl_inf)); EXPECT_TRUE(std::isinf(-dbl_inf - dbl_inf)); EXPECT_TRUE(std::isnan(-dbl_inf - -dbl_inf)); // We return inf } TEST(Duration, InfinityMultiplication) { const absl::Duration sec_max = absl::Seconds(kint64max); const absl::Duration sec_min = absl::Seconds(kint64min); const absl::Duration inf = absl::InfiniteDuration(); #define TEST_INF_MUL_WITH_TYPE(T) \ EXPECT_EQ(inf, inf * static_cast(2)); \ EXPECT_EQ(-inf, inf * static_cast(-2)); \ EXPECT_EQ(-inf, -inf * static_cast(2)); \ EXPECT_EQ(inf, -inf * static_cast(-2)); \ EXPECT_EQ(inf, inf * static_cast(0)); \ EXPECT_EQ(-inf, -inf * static_cast(0)); \ EXPECT_EQ(inf, sec_max * static_cast(2)); \ EXPECT_EQ(inf, sec_min * static_cast(-2)); \ EXPECT_EQ(inf, (sec_max / static_cast(2)) * static_cast(3)); \ EXPECT_EQ(-inf, sec_max * static_cast(-2)); \ EXPECT_EQ(-inf, sec_min * static_cast(2)); \ EXPECT_EQ(-inf, (sec_min / static_cast(2)) * static_cast(3)); TEST_INF_MUL_WITH_TYPE(int64_t); // NOLINT(readability/function) TEST_INF_MUL_WITH_TYPE(double); // NOLINT(readability/function) #undef TEST_INF_MUL_WITH_TYPE const double dbl_inf = std::numeric_limits::infinity(); EXPECT_EQ(inf, inf * dbl_inf); EXPECT_EQ(-inf, -inf * dbl_inf); EXPECT_EQ(-inf, inf * -dbl_inf); EXPECT_EQ(inf, -inf * -dbl_inf); const absl::Duration any_dur = absl::Seconds(1); EXPECT_EQ(inf, any_dur * dbl_inf); EXPECT_EQ(-inf, -any_dur * dbl_inf); EXPECT_EQ(-inf, any_dur * -dbl_inf); EXPECT_EQ(inf, -any_dur * -dbl_inf); // Fixed-point multiplication will produce a finite value, whereas floating // point fuzziness will overflow to inf. EXPECT_NE(absl::InfiniteDuration(), absl::Seconds(1) * kint64max); EXPECT_EQ(inf, absl::Seconds(1) * static_cast(kint64max)); EXPECT_NE(-absl::InfiniteDuration(), absl::Seconds(1) * kint64min); EXPECT_EQ(-inf, absl::Seconds(1) * static_cast(kint64min)); // Note that sec_max * or / by 1.0 overflows to inf due to the 53-bit // limitations of double. EXPECT_NE(inf, sec_max); EXPECT_NE(inf, sec_max / 1); EXPECT_EQ(inf, sec_max / 1.0); EXPECT_NE(inf, sec_max * 1); EXPECT_EQ(inf, sec_max * 1.0); } TEST(Duration, InfinityDivision) { const absl::Duration sec_max = absl::Seconds(kint64max); const absl::Duration sec_min = absl::Seconds(kint64min); const absl::Duration inf = absl::InfiniteDuration(); // Division of Duration by a double #define TEST_INF_DIV_WITH_TYPE(T) \ EXPECT_EQ(inf, inf / static_cast(2)); \ EXPECT_EQ(-inf, inf / static_cast(-2)); \ EXPECT_EQ(-inf, -inf / static_cast(2)); \ EXPECT_EQ(inf, -inf / static_cast(-2)); TEST_INF_DIV_WITH_TYPE(int64_t); // NOLINT(readability/function) TEST_INF_DIV_WITH_TYPE(double); // NOLINT(readability/function) #undef TEST_INF_DIV_WITH_TYPE // Division of Duration by a double overflow/underflow EXPECT_EQ(inf, sec_max / 0.5); EXPECT_EQ(inf, sec_min / -0.5); EXPECT_EQ(inf, ((sec_max / 0.5) + absl::Seconds(1)) / 0.5); EXPECT_EQ(-inf, sec_max / -0.5); EXPECT_EQ(-inf, sec_min / 0.5); EXPECT_EQ(-inf, ((sec_min / 0.5) - absl::Seconds(1)) / 0.5); const double dbl_inf = std::numeric_limits::infinity(); EXPECT_EQ(inf, inf / dbl_inf); EXPECT_EQ(-inf, inf / -dbl_inf); EXPECT_EQ(-inf, -inf / dbl_inf); EXPECT_EQ(inf, -inf / -dbl_inf); const absl::Duration any_dur = absl::Seconds(1); EXPECT_EQ(absl::ZeroDuration(), any_dur / dbl_inf); EXPECT_EQ(absl::ZeroDuration(), any_dur / -dbl_inf); EXPECT_EQ(absl::ZeroDuration(), -any_dur / dbl_inf); EXPECT_EQ(absl::ZeroDuration(), -any_dur / -dbl_inf); } TEST(Duration, InfinityModulus) { const absl::Duration sec_max = absl::Seconds(kint64max); const absl::Duration any_dur = absl::Seconds(1); const absl::Duration inf = absl::InfiniteDuration(); EXPECT_EQ(inf, inf % inf); EXPECT_EQ(inf, inf % -inf); EXPECT_EQ(-inf, -inf % -inf); EXPECT_EQ(-inf, -inf % inf); EXPECT_EQ(any_dur, any_dur % inf); EXPECT_EQ(any_dur, any_dur % -inf); EXPECT_EQ(-any_dur, -any_dur % inf); EXPECT_EQ(-any_dur, -any_dur % -inf); EXPECT_EQ(inf, inf % -any_dur); EXPECT_EQ(inf, inf % any_dur); EXPECT_EQ(-inf, -inf % -any_dur); EXPECT_EQ(-inf, -inf % any_dur); // Remainder isn't affected by overflow. EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Seconds(1)); EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Milliseconds(1)); EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Microseconds(1)); EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Nanoseconds(1)); EXPECT_EQ(absl::ZeroDuration(), sec_max % absl::Nanoseconds(1) / 4); } TEST(Duration, InfinityIDiv) { const absl::Duration sec_max = absl::Seconds(kint64max); const absl::Duration any_dur = absl::Seconds(1); const absl::Duration inf = absl::InfiniteDuration(); const double dbl_inf = std::numeric_limits::infinity(); // IDivDuration (int64_t return value + a remainer) absl::Duration rem = absl::ZeroDuration(); EXPECT_EQ(kint64max, absl::IDivDuration(inf, inf, &rem)); EXPECT_EQ(inf, rem); rem = absl::ZeroDuration(); EXPECT_EQ(kint64max, absl::IDivDuration(-inf, -inf, &rem)); EXPECT_EQ(-inf, rem); rem = absl::ZeroDuration(); EXPECT_EQ(kint64max, absl::IDivDuration(inf, any_dur, &rem)); EXPECT_EQ(inf, rem); rem = absl::ZeroDuration(); EXPECT_EQ(0, absl::IDivDuration(any_dur, inf, &rem)); EXPECT_EQ(any_dur, rem); rem = absl::ZeroDuration(); EXPECT_EQ(kint64max, absl::IDivDuration(-inf, -any_dur, &rem)); EXPECT_EQ(-inf, rem); rem = absl::ZeroDuration(); EXPECT_EQ(0, absl::IDivDuration(-any_dur, -inf, &rem)); EXPECT_EQ(-any_dur, rem); rem = absl::ZeroDuration(); EXPECT_EQ(kint64min, absl::IDivDuration(-inf, inf, &rem)); EXPECT_EQ(-inf, rem); rem = absl::ZeroDuration(); EXPECT_EQ(kint64min, absl::IDivDuration(inf, -inf, &rem)); EXPECT_EQ(inf, rem); rem = absl::ZeroDuration(); EXPECT_EQ(kint64min, absl::IDivDuration(-inf, any_dur, &rem)); EXPECT_EQ(-inf, rem); rem = absl::ZeroDuration(); EXPECT_EQ(0, absl::IDivDuration(-any_dur, inf, &rem)); EXPECT_EQ(-any_dur, rem); rem = absl::ZeroDuration(); EXPECT_EQ(kint64min, absl::IDivDuration(inf, -any_dur, &rem)); EXPECT_EQ(inf, rem); rem = absl::ZeroDuration(); EXPECT_EQ(0, absl::IDivDuration(any_dur, -inf, &rem)); EXPECT_EQ(any_dur, rem); // IDivDuration overflow/underflow rem = any_dur; EXPECT_EQ(kint64max, absl::IDivDuration(sec_max, absl::Nanoseconds(1) / 4, &rem)); EXPECT_EQ(sec_max - absl::Nanoseconds(kint64max) / 4, rem); rem = any_dur; EXPECT_EQ(kint64max, absl::IDivDuration(sec_max, absl::Milliseconds(1), &rem)); EXPECT_EQ(sec_max - absl::Milliseconds(kint64max), rem); rem = any_dur; EXPECT_EQ(kint64max, absl::IDivDuration(-sec_max, -absl::Milliseconds(1), &rem)); EXPECT_EQ(-sec_max + absl::Milliseconds(kint64max), rem); rem = any_dur; EXPECT_EQ(kint64min, absl::IDivDuration(-sec_max, absl::Milliseconds(1), &rem)); EXPECT_EQ(-sec_max - absl::Milliseconds(kint64min), rem); rem = any_dur; EXPECT_EQ(kint64min, absl::IDivDuration(sec_max, -absl::Milliseconds(1), &rem)); EXPECT_EQ(sec_max + absl::Milliseconds(kint64min), rem); // // operator/(Duration, Duration) is a wrapper for IDivDuration(). // // IEEE 754 says inf / inf should be nan, but int64_t doesn't have // nan so we'll return kint64max/kint64min instead. EXPECT_TRUE(std::isnan(dbl_inf / dbl_inf)); EXPECT_EQ(kint64max, inf / inf); EXPECT_EQ(kint64max, -inf / -inf); EXPECT_EQ(kint64min, -inf / inf); EXPECT_EQ(kint64min, inf / -inf); EXPECT_TRUE(std::isinf(dbl_inf / 2.0)); EXPECT_EQ(kint64max, inf / any_dur); EXPECT_EQ(kint64max, -inf / -any_dur); EXPECT_EQ(kint64min, -inf / any_dur); EXPECT_EQ(kint64min, inf / -any_dur); EXPECT_EQ(0.0, 2.0 / dbl_inf); EXPECT_EQ(0, any_dur / inf); EXPECT_EQ(0, any_dur / -inf); EXPECT_EQ(0, -any_dur / inf); EXPECT_EQ(0, -any_dur / -inf); EXPECT_EQ(0, absl::ZeroDuration() / inf); // Division of Duration by a Duration overflow/underflow EXPECT_EQ(kint64max, sec_max / absl::Milliseconds(1)); EXPECT_EQ(kint64max, -sec_max / -absl::Milliseconds(1)); EXPECT_EQ(kint64min, -sec_max / absl::Milliseconds(1)); EXPECT_EQ(kint64min, sec_max / -absl::Milliseconds(1)); } TEST(Duration, InfinityFDiv) { const absl::Duration any_dur = absl::Seconds(1); const absl::Duration inf = absl::InfiniteDuration(); const double dbl_inf = std::numeric_limits::infinity(); EXPECT_EQ(dbl_inf, absl::FDivDuration(inf, inf)); EXPECT_EQ(dbl_inf, absl::FDivDuration(-inf, -inf)); EXPECT_EQ(dbl_inf, absl::FDivDuration(inf, any_dur)); EXPECT_EQ(0.0, absl::FDivDuration(any_dur, inf)); EXPECT_EQ(dbl_inf, absl::FDivDuration(-inf, -any_dur)); EXPECT_EQ(0.0, absl::FDivDuration(-any_dur, -inf)); EXPECT_EQ(-dbl_inf, absl::FDivDuration(-inf, inf)); EXPECT_EQ(-dbl_inf, absl::FDivDuration(inf, -inf)); EXPECT_EQ(-dbl_inf, absl::FDivDuration(-inf, any_dur)); EXPECT_EQ(0.0, absl::FDivDuration(-any_dur, inf)); EXPECT_EQ(-dbl_inf, absl::FDivDuration(inf, -any_dur)); EXPECT_EQ(0.0, absl::FDivDuration(any_dur, -inf)); } TEST(Duration, DivisionByZero) { const absl::Duration zero = absl::ZeroDuration(); const absl::Duration inf = absl::InfiniteDuration(); const absl::Duration any_dur = absl::Seconds(1); const double dbl_inf = std::numeric_limits::infinity(); const double dbl_denorm = std::numeric_limits::denorm_min(); // Operator/(Duration, double) EXPECT_EQ(inf, zero / 0.0); EXPECT_EQ(-inf, zero / -0.0); EXPECT_EQ(inf, any_dur / 0.0); EXPECT_EQ(-inf, any_dur / -0.0); EXPECT_EQ(-inf, -any_dur / 0.0); EXPECT_EQ(inf, -any_dur / -0.0); // Tests dividing by a number very close to, but not quite zero. EXPECT_EQ(zero, zero / dbl_denorm); EXPECT_EQ(zero, zero / -dbl_denorm); EXPECT_EQ(inf, any_dur / dbl_denorm); EXPECT_EQ(-inf, any_dur / -dbl_denorm); EXPECT_EQ(-inf, -any_dur / dbl_denorm); EXPECT_EQ(inf, -any_dur / -dbl_denorm); // IDiv absl::Duration rem = zero; EXPECT_EQ(kint64max, absl::IDivDuration(zero, zero, &rem)); EXPECT_EQ(inf, rem); rem = zero; EXPECT_EQ(kint64max, absl::IDivDuration(any_dur, zero, &rem)); EXPECT_EQ(inf, rem); rem = zero; EXPECT_EQ(kint64min, absl::IDivDuration(-any_dur, zero, &rem)); EXPECT_EQ(-inf, rem); // Operator/(Duration, Duration) EXPECT_EQ(kint64max, zero / zero); EXPECT_EQ(kint64max, any_dur / zero); EXPECT_EQ(kint64min, -any_dur / zero); // FDiv EXPECT_EQ(dbl_inf, absl::FDivDuration(zero, zero)); EXPECT_EQ(dbl_inf, absl::FDivDuration(any_dur, zero)); EXPECT_EQ(-dbl_inf, absl::FDivDuration(-any_dur, zero)); } TEST(Duration, NaN) { // Note that IEEE 754 does not define the behavior of a nan's sign when it is // copied, so the code below allows for either + or - InfiniteDuration. #define TEST_NAN_HANDLING(NAME, NAN) \ do { \ const auto inf = absl::InfiniteDuration(); \ auto x = NAME(NAN); \ EXPECT_TRUE(x == inf || x == -inf); \ auto y = NAME(42); \ y *= NAN; \ EXPECT_TRUE(y == inf || y == -inf); \ auto z = NAME(42); \ z /= NAN; \ EXPECT_TRUE(z == inf || z == -inf); \ } while (0) const double nan = std::numeric_limits::quiet_NaN(); TEST_NAN_HANDLING(absl::Nanoseconds, nan); TEST_NAN_HANDLING(absl::Microseconds, nan); TEST_NAN_HANDLING(absl::Milliseconds, nan); TEST_NAN_HANDLING(absl::Seconds, nan); TEST_NAN_HANDLING(absl::Minutes, nan); TEST_NAN_HANDLING(absl::Hours, nan); TEST_NAN_HANDLING(absl::Nanoseconds, -nan); TEST_NAN_HANDLING(absl::Microseconds, -nan); TEST_NAN_HANDLING(absl::Milliseconds, -nan); TEST_NAN_HANDLING(absl::Seconds, -nan); TEST_NAN_HANDLING(absl::Minutes, -nan); TEST_NAN_HANDLING(absl::Hours, -nan); #undef TEST_NAN_HANDLING } TEST(Duration, Range) { const absl::Duration range = ApproxYears(100 * 1e9); const absl::Duration range_future = range; const absl::Duration range_past = -range; EXPECT_LT(range_future, absl::InfiniteDuration()); EXPECT_GT(range_past, -absl::InfiniteDuration()); const absl::Duration full_range = range_future - range_past; EXPECT_GT(full_range, absl::ZeroDuration()); EXPECT_LT(full_range, absl::InfiniteDuration()); const absl::Duration neg_full_range = range_past - range_future; EXPECT_LT(neg_full_range, absl::ZeroDuration()); EXPECT_GT(neg_full_range, -absl::InfiniteDuration()); EXPECT_LT(neg_full_range, full_range); EXPECT_EQ(neg_full_range, -full_range); #ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON EXPECT_EQ(range_future <=> absl::InfiniteDuration(), std::strong_ordering::less); EXPECT_EQ(range_past <=> -absl::InfiniteDuration(), std::strong_ordering::greater); EXPECT_EQ(full_range <=> absl::ZeroDuration(), // std::strong_ordering::greater); EXPECT_EQ(full_range <=> -absl::InfiniteDuration(), std::strong_ordering::greater); EXPECT_EQ(neg_full_range <=> -absl::InfiniteDuration(), std::strong_ordering::greater); EXPECT_EQ(neg_full_range <=> full_range, std::strong_ordering::less); EXPECT_EQ(neg_full_range <=> -full_range, std::strong_ordering::equal); #endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON } TEST(Duration, RelationalOperators) { #define TEST_REL_OPS(UNIT) \ static_assert(UNIT(2) == UNIT(2), ""); \ static_assert(UNIT(1) != UNIT(2), ""); \ static_assert(UNIT(1) < UNIT(2), ""); \ static_assert(UNIT(3) > UNIT(2), ""); \ static_assert(UNIT(1) <= UNIT(2), ""); \ static_assert(UNIT(2) <= UNIT(2), ""); \ static_assert(UNIT(3) >= UNIT(2), ""); \ static_assert(UNIT(2) >= UNIT(2), ""); TEST_REL_OPS(absl::Nanoseconds); TEST_REL_OPS(absl::Microseconds); TEST_REL_OPS(absl::Milliseconds); TEST_REL_OPS(absl::Seconds); TEST_REL_OPS(absl::Minutes); TEST_REL_OPS(absl::Hours); #undef TEST_REL_OPS } #ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON TEST(Duration, SpaceshipOperators) { #define TEST_REL_OPS(UNIT) \ static_assert(UNIT(2) <=> UNIT(2) == std::strong_ordering::equal, ""); \ static_assert(UNIT(1) <=> UNIT(2) == std::strong_ordering::less, ""); \ static_assert(UNIT(3) <=> UNIT(2) == std::strong_ordering::greater, ""); TEST_REL_OPS(absl::Nanoseconds); TEST_REL_OPS(absl::Microseconds); TEST_REL_OPS(absl::Milliseconds); TEST_REL_OPS(absl::Seconds); TEST_REL_OPS(absl::Minutes); TEST_REL_OPS(absl::Hours); #undef TEST_REL_OPS } #endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON TEST(Duration, Addition) { #define TEST_ADD_OPS(UNIT) \ do { \ EXPECT_EQ(UNIT(2), UNIT(1) + UNIT(1)); \ EXPECT_EQ(UNIT(1), UNIT(2) - UNIT(1)); \ EXPECT_EQ(UNIT(0), UNIT(2) - UNIT(2)); \ EXPECT_EQ(UNIT(-1), UNIT(1) - UNIT(2)); \ EXPECT_EQ(UNIT(-2), UNIT(0) - UNIT(2)); \ EXPECT_EQ(UNIT(-2), UNIT(1) - UNIT(3)); \ absl::Duration a = UNIT(1); \ a += UNIT(1); \ EXPECT_EQ(UNIT(2), a); \ a -= UNIT(1); \ EXPECT_EQ(UNIT(1), a); \ } while (0) TEST_ADD_OPS(absl::Nanoseconds); TEST_ADD_OPS(absl::Microseconds); TEST_ADD_OPS(absl::Milliseconds); TEST_ADD_OPS(absl::Seconds); TEST_ADD_OPS(absl::Minutes); TEST_ADD_OPS(absl::Hours); #undef TEST_ADD_OPS EXPECT_EQ(absl::Seconds(2), absl::Seconds(3) - 2 * absl::Milliseconds(500)); EXPECT_EQ(absl::Seconds(2) + absl::Milliseconds(500), absl::Seconds(3) - absl::Milliseconds(500)); EXPECT_EQ(absl::Seconds(1) + absl::Milliseconds(998), absl::Milliseconds(999) + absl::Milliseconds(999)); EXPECT_EQ(absl::Milliseconds(-1), absl::Milliseconds(998) - absl::Milliseconds(999)); // Tests fractions of a nanoseconds. These are implementation details only. EXPECT_GT(absl::Nanoseconds(1), absl::Nanoseconds(1) / 2); EXPECT_EQ(absl::Nanoseconds(1), absl::Nanoseconds(1) / 2 + absl::Nanoseconds(1) / 2); EXPECT_GT(absl::Nanoseconds(1) / 4, absl::Nanoseconds(0)); EXPECT_EQ(absl::Nanoseconds(1) / 8, absl::Nanoseconds(0)); // Tests subtraction that will cause wrap around of the rep_lo_ bits. absl::Duration d_7_5 = absl::Seconds(7) + absl::Milliseconds(500); absl::Duration d_3_7 = absl::Seconds(3) + absl::Milliseconds(700); absl::Duration ans_3_8 = absl::Seconds(3) + absl::Milliseconds(800); EXPECT_EQ(ans_3_8, d_7_5 - d_3_7); // Subtracting min_duration absl::Duration min_dur = absl::Seconds(kint64min); EXPECT_EQ(absl::Seconds(0), min_dur - min_dur); EXPECT_EQ(absl::Seconds(kint64max), absl::Seconds(-1) - min_dur); } TEST(Duration, Negation) { // By storing negations of various values in constexpr variables we // verify that the initializers are constant expressions. constexpr absl::Duration negated_zero_duration = -absl::ZeroDuration(); EXPECT_EQ(negated_zero_duration, absl::ZeroDuration()); constexpr absl::Duration negated_infinite_duration = -absl::InfiniteDuration(); EXPECT_NE(negated_infinite_duration, absl::InfiniteDuration()); EXPECT_EQ(-negated_infinite_duration, absl::InfiniteDuration()); // The public APIs to check if a duration is infinite depend on using // -InfiniteDuration(), but we're trying to test operator- here, so we // need to use the lower-level internal query IsInfiniteDuration. EXPECT_TRUE( absl::time_internal::IsInfiniteDuration(negated_infinite_duration)); // The largest Duration is kint64max seconds and kTicksPerSecond - 1 ticks. // Using the absl::time_internal::MakeDuration API is the cleanest way to // construct that Duration. constexpr absl::Duration max_duration = absl::time_internal::MakeDuration( kint64max, absl::time_internal::kTicksPerSecond - 1); constexpr absl::Duration negated_max_duration = -max_duration; // The largest negatable value is one tick above the minimum representable; // it's the negation of max_duration. constexpr absl::Duration nearly_min_duration = absl::time_internal::MakeDuration(kint64min, int64_t{1}); constexpr absl::Duration negated_nearly_min_duration = -nearly_min_duration; EXPECT_EQ(negated_max_duration, nearly_min_duration); EXPECT_EQ(negated_nearly_min_duration, max_duration); EXPECT_EQ(-(-max_duration), max_duration); constexpr absl::Duration min_duration = absl::time_internal::MakeDuration(kint64min); constexpr absl::Duration negated_min_duration = -min_duration; EXPECT_EQ(negated_min_duration, absl::InfiniteDuration()); } TEST(Duration, AbsoluteValue) { EXPECT_EQ(absl::ZeroDuration(), AbsDuration(absl::ZeroDuration())); EXPECT_EQ(absl::Seconds(1), AbsDuration(absl::Seconds(1))); EXPECT_EQ(absl::Seconds(1), AbsDuration(absl::Seconds(-1))); EXPECT_EQ(absl::InfiniteDuration(), AbsDuration(absl::InfiniteDuration())); EXPECT_EQ(absl::InfiniteDuration(), AbsDuration(-absl::InfiniteDuration())); absl::Duration max_dur = absl::Seconds(kint64max) + (absl::Seconds(1) - absl::Nanoseconds(1) / 4); EXPECT_EQ(max_dur, AbsDuration(max_dur)); absl::Duration min_dur = absl::Seconds(kint64min); EXPECT_EQ(absl::InfiniteDuration(), AbsDuration(min_dur)); EXPECT_EQ(max_dur, AbsDuration(min_dur + absl::Nanoseconds(1) / 4)); } TEST(Duration, Multiplication) { #define TEST_MUL_OPS(UNIT) \ do { \ EXPECT_EQ(UNIT(5), UNIT(2) * 2.5); \ EXPECT_EQ(UNIT(2), UNIT(5) / 2.5); \ EXPECT_EQ(UNIT(-5), UNIT(-2) * 2.5); \ EXPECT_EQ(UNIT(-5), -UNIT(2) * 2.5); \ EXPECT_EQ(UNIT(-5), UNIT(2) * -2.5); \ EXPECT_EQ(UNIT(-2), UNIT(-5) / 2.5); \ EXPECT_EQ(UNIT(-2), -UNIT(5) / 2.5); \ EXPECT_EQ(UNIT(-2), UNIT(5) / -2.5); \ EXPECT_EQ(UNIT(2), UNIT(11) % UNIT(3)); \ absl::Duration a = UNIT(2); \ a *= 2.5; \ EXPECT_EQ(UNIT(5), a); \ a /= 2.5; \ EXPECT_EQ(UNIT(2), a); \ a %= UNIT(1); \ EXPECT_EQ(UNIT(0), a); \ absl::Duration big = UNIT(1000000000); \ big *= 3; \ big /= 3; \ EXPECT_EQ(UNIT(1000000000), big); \ EXPECT_EQ(-UNIT(2), -UNIT(2)); \ EXPECT_EQ(-UNIT(2), UNIT(2) * -1); \ EXPECT_EQ(-UNIT(2), -1 * UNIT(2)); \ EXPECT_EQ(-UNIT(-2), UNIT(2)); \ EXPECT_EQ(2, UNIT(2) / UNIT(1)); \ absl::Duration rem; \ EXPECT_EQ(2, absl::IDivDuration(UNIT(2), UNIT(1), &rem)); \ EXPECT_EQ(2.0, absl::FDivDuration(UNIT(2), UNIT(1))); \ } while (0) TEST_MUL_OPS(absl::Nanoseconds); TEST_MUL_OPS(absl::Microseconds); TEST_MUL_OPS(absl::Milliseconds); TEST_MUL_OPS(absl::Seconds); TEST_MUL_OPS(absl::Minutes); TEST_MUL_OPS(absl::Hours); #undef TEST_MUL_OPS // Ensures that multiplication and division by 1 with a maxed-out durations // doesn't lose precision. absl::Duration max_dur = absl::Seconds(kint64max) + (absl::Seconds(1) - absl::Nanoseconds(1) / 4); absl::Duration min_dur = absl::Seconds(kint64min); EXPECT_EQ(max_dur, max_dur * 1); EXPECT_EQ(max_dur, max_dur / 1); EXPECT_EQ(min_dur, min_dur * 1); EXPECT_EQ(min_dur, min_dur / 1); // Tests division on a Duration with a large number of significant digits. // Tests when the digits span hi and lo as well as only in hi. absl::Duration sigfigs = absl::Seconds(2000000000) + absl::Nanoseconds(3); EXPECT_EQ(absl::Seconds(666666666) + absl::Nanoseconds(666666667) + absl::Nanoseconds(1) / 2, sigfigs / 3); sigfigs = absl::Seconds(int64_t{7000000000}); EXPECT_EQ(absl::Seconds(2333333333) + absl::Nanoseconds(333333333) + absl::Nanoseconds(1) / 4, sigfigs / 3); EXPECT_EQ(absl::Seconds(7) + absl::Milliseconds(500), absl::Seconds(3) * 2.5); EXPECT_EQ(absl::Seconds(8) * -1 + absl::Milliseconds(300), (absl::Seconds(2) + absl::Milliseconds(200)) * -3.5); EXPECT_EQ(-absl::Seconds(8) + absl::Milliseconds(300), (absl::Seconds(2) + absl::Milliseconds(200)) * -3.5); EXPECT_EQ(absl::Seconds(1) + absl::Milliseconds(875), (absl::Seconds(7) + absl::Milliseconds(500)) / 4); EXPECT_EQ(absl::Seconds(30), (absl::Seconds(7) + absl::Milliseconds(500)) / 0.25); EXPECT_EQ(absl::Seconds(3), (absl::Seconds(7) + absl::Milliseconds(500)) / 2.5); // Tests division remainder. EXPECT_EQ(absl::Nanoseconds(0), absl::Nanoseconds(7) % absl::Nanoseconds(1)); EXPECT_EQ(absl::Nanoseconds(0), absl::Nanoseconds(0) % absl::Nanoseconds(10)); EXPECT_EQ(absl::Nanoseconds(2), absl::Nanoseconds(7) % absl::Nanoseconds(5)); EXPECT_EQ(absl::Nanoseconds(2), absl::Nanoseconds(2) % absl::Nanoseconds(5)); EXPECT_EQ(absl::Nanoseconds(1), absl::Nanoseconds(10) % absl::Nanoseconds(3)); EXPECT_EQ(absl::Nanoseconds(1), absl::Nanoseconds(10) % absl::Nanoseconds(-3)); EXPECT_EQ(absl::Nanoseconds(-1), absl::Nanoseconds(-10) % absl::Nanoseconds(3)); EXPECT_EQ(absl::Nanoseconds(-1), absl::Nanoseconds(-10) % absl::Nanoseconds(-3)); EXPECT_EQ(absl::Milliseconds(100), absl::Seconds(1) % absl::Milliseconds(300)); EXPECT_EQ( absl::Milliseconds(300), (absl::Seconds(3) + absl::Milliseconds(800)) % absl::Milliseconds(500)); EXPECT_EQ(absl::Nanoseconds(1), absl::Nanoseconds(1) % absl::Seconds(1)); EXPECT_EQ(absl::Nanoseconds(-1), absl::Nanoseconds(-1) % absl::Seconds(1)); EXPECT_EQ(0, absl::Nanoseconds(-1) / absl::Seconds(1)); // Actual -1e-9 // Tests identity a = (a/b)*b + a%b #define TEST_MOD_IDENTITY(a, b) \ EXPECT_EQ((a), ((a) / (b))*(b) + ((a)%(b))) TEST_MOD_IDENTITY(absl::Seconds(0), absl::Seconds(2)); TEST_MOD_IDENTITY(absl::Seconds(1), absl::Seconds(1)); TEST_MOD_IDENTITY(absl::Seconds(1), absl::Seconds(2)); TEST_MOD_IDENTITY(absl::Seconds(2), absl::Seconds(1)); TEST_MOD_IDENTITY(absl::Seconds(-2), absl::Seconds(1)); TEST_MOD_IDENTITY(absl::Seconds(2), absl::Seconds(-1)); TEST_MOD_IDENTITY(absl::Seconds(-2), absl::Seconds(-1)); TEST_MOD_IDENTITY(absl::Nanoseconds(0), absl::Nanoseconds(2)); TEST_MOD_IDENTITY(absl::Nanoseconds(1), absl::Nanoseconds(1)); TEST_MOD_IDENTITY(absl::Nanoseconds(1), absl::Nanoseconds(2)); TEST_MOD_IDENTITY(absl::Nanoseconds(2), absl::Nanoseconds(1)); TEST_MOD_IDENTITY(absl::Nanoseconds(-2), absl::Nanoseconds(1)); TEST_MOD_IDENTITY(absl::Nanoseconds(2), absl::Nanoseconds(-1)); TEST_MOD_IDENTITY(absl::Nanoseconds(-2), absl::Nanoseconds(-1)); // Mixed seconds + subseconds absl::Duration mixed_a = absl::Seconds(1) + absl::Nanoseconds(2); absl::Duration mixed_b = absl::Seconds(1) + absl::Nanoseconds(3); TEST_MOD_IDENTITY(absl::Seconds(0), mixed_a); TEST_MOD_IDENTITY(mixed_a, mixed_a); TEST_MOD_IDENTITY(mixed_a, mixed_b); TEST_MOD_IDENTITY(mixed_b, mixed_a); TEST_MOD_IDENTITY(-mixed_a, mixed_b); TEST_MOD_IDENTITY(mixed_a, -mixed_b); TEST_MOD_IDENTITY(-mixed_a, -mixed_b); #undef TEST_MOD_IDENTITY } TEST(Duration, Truncation) { const absl::Duration d = absl::Nanoseconds(1234567890); const absl::Duration inf = absl::InfiniteDuration(); for (int unit_sign : {1, -1}) { // sign shouldn't matter EXPECT_EQ(absl::Nanoseconds(1234567890), Trunc(d, unit_sign * absl::Nanoseconds(1))); EXPECT_EQ(absl::Microseconds(1234567), Trunc(d, unit_sign * absl::Microseconds(1))); EXPECT_EQ(absl::Milliseconds(1234), Trunc(d, unit_sign * absl::Milliseconds(1))); EXPECT_EQ(absl::Seconds(1), Trunc(d, unit_sign * absl::Seconds(1))); EXPECT_EQ(inf, Trunc(inf, unit_sign * absl::Seconds(1))); EXPECT_EQ(absl::Nanoseconds(-1234567890), Trunc(-d, unit_sign * absl::Nanoseconds(1))); EXPECT_EQ(absl::Microseconds(-1234567), Trunc(-d, unit_sign * absl::Microseconds(1))); EXPECT_EQ(absl::Milliseconds(-1234), Trunc(-d, unit_sign * absl::Milliseconds(1))); EXPECT_EQ(absl::Seconds(-1), Trunc(-d, unit_sign * absl::Seconds(1))); EXPECT_EQ(-inf, Trunc(-inf, unit_sign * absl::Seconds(1))); } } TEST(Duration, Flooring) { const absl::Duration d = absl::Nanoseconds(1234567890); const absl::Duration inf = absl::InfiniteDuration(); for (int unit_sign : {1, -1}) { // sign shouldn't matter EXPECT_EQ(absl::Nanoseconds(1234567890), absl::Floor(d, unit_sign * absl::Nanoseconds(1))); EXPECT_EQ(absl::Microseconds(1234567), absl::Floor(d, unit_sign * absl::Microseconds(1))); EXPECT_EQ(absl::Milliseconds(1234), absl::Floor(d, unit_sign * absl::Milliseconds(1))); EXPECT_EQ(absl::Seconds(1), absl::Floor(d, unit_sign * absl::Seconds(1))); EXPECT_EQ(inf, absl::Floor(inf, unit_sign * absl::Seconds(1))); EXPECT_EQ(absl::Nanoseconds(-1234567890), absl::Floor(-d, unit_sign * absl::Nanoseconds(1))); EXPECT_EQ(absl::Microseconds(-1234568), absl::Floor(-d, unit_sign * absl::Microseconds(1))); EXPECT_EQ(absl::Milliseconds(-1235), absl::Floor(-d, unit_sign * absl::Milliseconds(1))); EXPECT_EQ(absl::Seconds(-2), absl::Floor(-d, unit_sign * absl::Seconds(1))); EXPECT_EQ(-inf, absl::Floor(-inf, unit_sign * absl::Seconds(1))); } } TEST(Duration, Ceiling) { const absl::Duration d = absl::Nanoseconds(1234567890); const absl::Duration inf = absl::InfiniteDuration(); for (int unit_sign : {1, -1}) { // // sign shouldn't matter EXPECT_EQ(absl::Nanoseconds(1234567890), absl::Ceil(d, unit_sign * absl::Nanoseconds(1))); EXPECT_EQ(absl::Microseconds(1234568), absl::Ceil(d, unit_sign * absl::Microseconds(1))); EXPECT_EQ(absl::Milliseconds(1235), absl::Ceil(d, unit_sign * absl::Milliseconds(1))); EXPECT_EQ(absl::Seconds(2), absl::Ceil(d, unit_sign * absl::Seconds(1))); EXPECT_EQ(inf, absl::Ceil(inf, unit_sign * absl::Seconds(1))); EXPECT_EQ(absl::Nanoseconds(-1234567890), absl::Ceil(-d, unit_sign * absl::Nanoseconds(1))); EXPECT_EQ(absl::Microseconds(-1234567), absl::Ceil(-d, unit_sign * absl::Microseconds(1))); EXPECT_EQ(absl::Milliseconds(-1234), absl::Ceil(-d, unit_sign * absl::Milliseconds(1))); EXPECT_EQ(absl::Seconds(-1), absl::Ceil(-d, unit_sign * absl::Seconds(1))); EXPECT_EQ(-inf, absl::Ceil(-inf, unit_sign * absl::Seconds(1))); } } TEST(Duration, RoundTripUnits) { const int kRange = 100000; #define ROUND_TRIP_UNIT(U, LOW, HIGH) \ do { \ for (int64_t i = LOW; i < HIGH; ++i) { \ absl::Duration d = absl::U(i); \ if (d == absl::InfiniteDuration()) \ EXPECT_EQ(kint64max, d / absl::U(1)); \ else if (d == -absl::InfiniteDuration()) \ EXPECT_EQ(kint64min, d / absl::U(1)); \ else \ EXPECT_EQ(i, absl::U(i) / absl::U(1)); \ } \ } while (0) ROUND_TRIP_UNIT(Nanoseconds, kint64min, kint64min + kRange); ROUND_TRIP_UNIT(Nanoseconds, -kRange, kRange); ROUND_TRIP_UNIT(Nanoseconds, kint64max - kRange, kint64max); ROUND_TRIP_UNIT(Microseconds, kint64min, kint64min + kRange); ROUND_TRIP_UNIT(Microseconds, -kRange, kRange); ROUND_TRIP_UNIT(Microseconds, kint64max - kRange, kint64max); ROUND_TRIP_UNIT(Milliseconds, kint64min, kint64min + kRange); ROUND_TRIP_UNIT(Milliseconds, -kRange, kRange); ROUND_TRIP_UNIT(Milliseconds, kint64max - kRange, kint64max); ROUND_TRIP_UNIT(Seconds, kint64min, kint64min + kRange); ROUND_TRIP_UNIT(Seconds, -kRange, kRange); ROUND_TRIP_UNIT(Seconds, kint64max - kRange, kint64max); ROUND_TRIP_UNIT(Minutes, kint64min / 60, kint64min / 60 + kRange); ROUND_TRIP_UNIT(Minutes, -kRange, kRange); ROUND_TRIP_UNIT(Minutes, kint64max / 60 - kRange, kint64max / 60); ROUND_TRIP_UNIT(Hours, kint64min / 3600, kint64min / 3600 + kRange); ROUND_TRIP_UNIT(Hours, -kRange, kRange); ROUND_TRIP_UNIT(Hours, kint64max / 3600 - kRange, kint64max / 3600); #undef ROUND_TRIP_UNIT } TEST(Duration, TruncConversions) { // Tests ToTimespec()/DurationFromTimespec() const struct { absl::Duration d; timespec ts; } to_ts[] = { {absl::Seconds(1) + absl::Nanoseconds(1), {1, 1}}, {absl::Seconds(1) + absl::Nanoseconds(1) / 2, {1, 0}}, {absl::Seconds(1) + absl::Nanoseconds(0), {1, 0}}, {absl::Seconds(0) + absl::Nanoseconds(0), {0, 0}}, {absl::Seconds(0) - absl::Nanoseconds(1) / 2, {0, 0}}, {absl::Seconds(0) - absl::Nanoseconds(1), {-1, 999999999}}, {absl::Seconds(-1) + absl::Nanoseconds(1), {-1, 1}}, {absl::Seconds(-1) + absl::Nanoseconds(1) / 2, {-1, 1}}, {absl::Seconds(-1) + absl::Nanoseconds(0), {-1, 0}}, {absl::Seconds(-1) - absl::Nanoseconds(1) / 2, {-1, 0}}, }; for (const auto& test : to_ts) { EXPECT_THAT(absl::ToTimespec(test.d), TimespecMatcher(test.ts)); } const struct { timespec ts; absl::Duration d; } from_ts[] = { {{1, 1}, absl::Seconds(1) + absl::Nanoseconds(1)}, {{1, 0}, absl::Seconds(1) + absl::Nanoseconds(0)}, {{0, 0}, absl::Seconds(0) + absl::Nanoseconds(0)}, {{0, -1}, absl::Seconds(0) - absl::Nanoseconds(1)}, {{-1, 999999999}, absl::Seconds(0) - absl::Nanoseconds(1)}, {{-1, 1}, absl::Seconds(-1) + absl::Nanoseconds(1)}, {{-1, 0}, absl::Seconds(-1) + absl::Nanoseconds(0)}, {{-1, -1}, absl::Seconds(-1) - absl::Nanoseconds(1)}, {{-2, 999999999}, absl::Seconds(-1) - absl::Nanoseconds(1)}, }; for (const auto& test : from_ts) { EXPECT_EQ(test.d, absl::DurationFromTimespec(test.ts)); } // Tests ToTimeval()/DurationFromTimeval() (same as timespec above) const struct { absl::Duration d; timeval tv; } to_tv[] = { {absl::Seconds(1) + absl::Microseconds(1), {1, 1}}, {absl::Seconds(1) + absl::Microseconds(1) / 2, {1, 0}}, {absl::Seconds(1) + absl::Microseconds(0), {1, 0}}, {absl::Seconds(0) + absl::Microseconds(0), {0, 0}}, {absl::Seconds(0) - absl::Microseconds(1) / 2, {0, 0}}, {absl::Seconds(0) - absl::Microseconds(1), {-1, 999999}}, {absl::Seconds(-1) + absl::Microseconds(1), {-1, 1}}, {absl::Seconds(-1) + absl::Microseconds(1) / 2, {-1, 1}}, {absl::Seconds(-1) + absl::Microseconds(0), {-1, 0}}, {absl::Seconds(-1) - absl::Microseconds(1) / 2, {-1, 0}}, }; for (const auto& test : to_tv) { EXPECT_THAT(absl::ToTimeval(test.d), TimevalMatcher(test.tv)); } const struct { timeval tv; absl::Duration d; } from_tv[] = { {{1, 1}, absl::Seconds(1) + absl::Microseconds(1)}, {{1, 0}, absl::Seconds(1) + absl::Microseconds(0)}, {{0, 0}, absl::Seconds(0) + absl::Microseconds(0)}, {{0, -1}, absl::Seconds(0) - absl::Microseconds(1)}, {{-1, 999999}, absl::Seconds(0) - absl::Microseconds(1)}, {{-1, 1}, absl::Seconds(-1) + absl::Microseconds(1)}, {{-1, 0}, absl::Seconds(-1) + absl::Microseconds(0)}, {{-1, -1}, absl::Seconds(-1) - absl::Microseconds(1)}, {{-2, 999999}, absl::Seconds(-1) - absl::Microseconds(1)}, }; for (const auto& test : from_tv) { EXPECT_EQ(test.d, absl::DurationFromTimeval(test.tv)); } } TEST(Duration, SmallConversions) { // Special tests for conversions of small durations. EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(0)); // TODO(bww): Is the next one OK? EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(0.125e-9, 0))); EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.125e-9)); EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.250e-9)); EXPECT_EQ(absl::Nanoseconds(1) / 2, absl::Seconds(0.375e-9)); EXPECT_EQ(absl::Nanoseconds(1) / 2, absl::Seconds(0.500e-9)); EXPECT_EQ(absl::Nanoseconds(3) / 4, absl::Seconds(0.625e-9)); EXPECT_EQ(absl::Nanoseconds(3) / 4, absl::Seconds(0.750e-9)); EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(0.875e-9)); EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(1.000e-9)); EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(-0.125e-9, 0))); EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.125e-9)); EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.250e-9)); EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.375e-9)); EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.500e-9)); EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.625e-9)); EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.750e-9)); EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-0.875e-9)); EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-1.000e-9)); timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0; EXPECT_THAT(ToTimespec(absl::Nanoseconds(0)), TimespecMatcher(ts)); // TODO(bww): Are the next three OK? EXPECT_THAT(ToTimespec(absl::Nanoseconds(1) / 4), TimespecMatcher(ts)); EXPECT_THAT(ToTimespec(absl::Nanoseconds(2) / 4), TimespecMatcher(ts)); EXPECT_THAT(ToTimespec(absl::Nanoseconds(3) / 4), TimespecMatcher(ts)); ts.tv_nsec = 1; EXPECT_THAT(ToTimespec(absl::Nanoseconds(4) / 4), TimespecMatcher(ts)); EXPECT_THAT(ToTimespec(absl::Nanoseconds(5) / 4), TimespecMatcher(ts)); EXPECT_THAT(ToTimespec(absl::Nanoseconds(6) / 4), TimespecMatcher(ts)); EXPECT_THAT(ToTimespec(absl::Nanoseconds(7) / 4), TimespecMatcher(ts)); ts.tv_nsec = 2; EXPECT_THAT(ToTimespec(absl::Nanoseconds(8) / 4), TimespecMatcher(ts)); timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; EXPECT_THAT(ToTimeval(absl::Nanoseconds(0)), TimevalMatcher(tv)); // TODO(bww): Is the next one OK? EXPECT_THAT(ToTimeval(absl::Nanoseconds(999)), TimevalMatcher(tv)); tv.tv_usec = 1; EXPECT_THAT(ToTimeval(absl::Nanoseconds(1000)), TimevalMatcher(tv)); EXPECT_THAT(ToTimeval(absl::Nanoseconds(1999)), TimevalMatcher(tv)); tv.tv_usec = 2; EXPECT_THAT(ToTimeval(absl::Nanoseconds(2000)), TimevalMatcher(tv)); } void VerifyApproxSameAsMul(double time_as_seconds, int* const misses) { auto direct_seconds = absl::Seconds(time_as_seconds); auto mul_by_one_second = time_as_seconds * absl::Seconds(1); // These are expected to differ by up to one tick due to fused multiply/add // contraction. if (absl::AbsDuration(direct_seconds - mul_by_one_second) > absl::time_internal::MakeDuration(0, 1u)) { if (*misses > 10) return; ASSERT_LE(++(*misses), 10) << "Too many errors, not reporting more."; EXPECT_EQ(direct_seconds, mul_by_one_second) << "given double time_as_seconds = " << std::setprecision(17) << time_as_seconds; } } // For a variety of interesting durations, we find the exact point // where one double converts to that duration, and the very next double // converts to the next duration. For both of those points, verify that // Seconds(point) returns a duration near point * Seconds(1.0). (They may // not be exactly equal due to fused multiply/add contraction.) TEST(Duration, ToDoubleSecondsCheckEdgeCases) { #if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0 // We're using an x87-compatible FPU, and intermediate operations can be // performed with 80-bit floats. This means the edge cases are different than // what we expect here, so just skip this test. GTEST_SKIP() << "Skipping the test because we detected x87 floating-point semantics"; #endif constexpr uint32_t kTicksPerSecond = absl::time_internal::kTicksPerSecond; constexpr auto duration_tick = absl::time_internal::MakeDuration(0, 1u); int misses = 0; for (int64_t seconds = 0; seconds < 99; ++seconds) { uint32_t tick_vals[] = {0, +999, +999999, +999999999, kTicksPerSecond - 1, 0, 1000, 1000000, 1000000000, kTicksPerSecond, 1, 1001, 1000001, 1000000001, kTicksPerSecond + 1, 2, 1002, 1000002, 1000000002, kTicksPerSecond + 2, 3, 1003, 1000003, 1000000003, kTicksPerSecond + 3, 4, 1004, 1000004, 1000000004, kTicksPerSecond + 4, 5, 6, 7, 8, 9}; for (uint32_t ticks : tick_vals) { absl::Duration s_plus_t = absl::Seconds(seconds) + ticks * duration_tick; for (absl::Duration d : {s_plus_t, -s_plus_t}) { absl::Duration after_d = d + duration_tick; EXPECT_NE(d, after_d); EXPECT_EQ(after_d - d, duration_tick); double low_edge = ToDoubleSeconds(d); EXPECT_EQ(d, absl::Seconds(low_edge)); double high_edge = ToDoubleSeconds(after_d); EXPECT_EQ(after_d, absl::Seconds(high_edge)); for (;;) { double midpoint = low_edge + (high_edge - low_edge) / 2; if (midpoint == low_edge || midpoint == high_edge) break; absl::Duration mid_duration = absl::Seconds(midpoint); if (mid_duration == d) { low_edge = midpoint; } else { EXPECT_EQ(mid_duration, after_d); high_edge = midpoint; } } // Now low_edge is the highest double that converts to Duration d, // and high_edge is the lowest double that converts to Duration after_d. VerifyApproxSameAsMul(low_edge, &misses); VerifyApproxSameAsMul(high_edge, &misses); } } } } TEST(Duration, ToDoubleSecondsCheckRandom) { std::random_device rd; std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()}); std::mt19937_64 gen(seed); // We want doubles distributed from 1/8ns up to 2^63, where // as many values are tested from 1ns to 2ns as from 1sec to 2sec, // so even distribute along a log-scale of those values, and // exponentiate before using them. (9.223377e+18 is just slightly // out of bounds for absl::Duration.) std::uniform_real_distribution uniform(std::log(0.125e-9), std::log(9.223377e+18)); int misses = 0; for (int i = 0; i < 1000000; ++i) { double d = std::exp(uniform(gen)); VerifyApproxSameAsMul(d, &misses); VerifyApproxSameAsMul(-d, &misses); } } TEST(Duration, ConversionSaturation) { absl::Duration d; const auto max_timeval_sec = std::numeric_limits::max(); const auto min_timeval_sec = std::numeric_limits::min(); timeval tv; tv.tv_sec = max_timeval_sec; tv.tv_usec = 999998; d = absl::DurationFromTimeval(tv); tv = ToTimeval(d); EXPECT_EQ(max_timeval_sec, tv.tv_sec); EXPECT_EQ(999998, tv.tv_usec); d += absl::Microseconds(1); tv = ToTimeval(d); EXPECT_EQ(max_timeval_sec, tv.tv_sec); EXPECT_EQ(999999, tv.tv_usec); d += absl::Microseconds(1); // no effect tv = ToTimeval(d); EXPECT_EQ(max_timeval_sec, tv.tv_sec); EXPECT_EQ(999999, tv.tv_usec); tv.tv_sec = min_timeval_sec; tv.tv_usec = 1; d = absl::DurationFromTimeval(tv); tv = ToTimeval(d); EXPECT_EQ(min_timeval_sec, tv.tv_sec); EXPECT_EQ(1, tv.tv_usec); d -= absl::Microseconds(1); tv = ToTimeval(d); EXPECT_EQ(min_timeval_sec, tv.tv_sec); EXPECT_EQ(0, tv.tv_usec); d -= absl::Microseconds(1); // no effect tv = ToTimeval(d); EXPECT_EQ(min_timeval_sec, tv.tv_sec); EXPECT_EQ(0, tv.tv_usec); const auto max_timespec_sec = std::numeric_limits::max(); const auto min_timespec_sec = std::numeric_limits::min(); timespec ts; ts.tv_sec = max_timespec_sec; ts.tv_nsec = 999999998; d = absl::DurationFromTimespec(ts); ts = absl::ToTimespec(d); EXPECT_EQ(max_timespec_sec, ts.tv_sec); EXPECT_EQ(999999998, ts.tv_nsec); d += absl::Nanoseconds(1); ts = absl::ToTimespec(d); EXPECT_EQ(max_timespec_sec, ts.tv_sec); EXPECT_EQ(999999999, ts.tv_nsec); d += absl::Nanoseconds(1); // no effect ts = absl::ToTimespec(d); EXPECT_EQ(max_timespec_sec, ts.tv_sec); EXPECT_EQ(999999999, ts.tv_nsec); ts.tv_sec = min_timespec_sec; ts.tv_nsec = 1; d = absl::DurationFromTimespec(ts); ts = absl::ToTimespec(d); EXPECT_EQ(min_timespec_sec, ts.tv_sec); EXPECT_EQ(1, ts.tv_nsec); d -= absl::Nanoseconds(1); ts = absl::ToTimespec(d); EXPECT_EQ(min_timespec_sec, ts.tv_sec); EXPECT_EQ(0, ts.tv_nsec); d -= absl::Nanoseconds(1); // no effect ts = absl::ToTimespec(d); EXPECT_EQ(min_timespec_sec, ts.tv_sec); EXPECT_EQ(0, ts.tv_nsec); } TEST(Duration, FormatDuration) { // Example from Go's docs. EXPECT_EQ("72h3m0.5s", absl::FormatDuration(absl::Hours(72) + absl::Minutes(3) + absl::Milliseconds(500))); // Go's largest time: 2540400h10m10.000000000s EXPECT_EQ("2540400h10m10s", absl::FormatDuration(absl::Hours(2540400) + absl::Minutes(10) + absl::Seconds(10))); EXPECT_EQ("0", absl::FormatDuration(absl::ZeroDuration())); EXPECT_EQ("0", absl::FormatDuration(absl::Seconds(0))); EXPECT_EQ("0", absl::FormatDuration(absl::Nanoseconds(0))); EXPECT_EQ("1ns", absl::FormatDuration(absl::Nanoseconds(1))); EXPECT_EQ("1us", absl::FormatDuration(absl::Microseconds(1))); EXPECT_EQ("1ms", absl::FormatDuration(absl::Milliseconds(1))); EXPECT_EQ("1s", absl::FormatDuration(absl::Seconds(1))); EXPECT_EQ("1m", absl::FormatDuration(absl::Minutes(1))); EXPECT_EQ("1h", absl::FormatDuration(absl::Hours(1))); EXPECT_EQ("1h1m", absl::FormatDuration(absl::Hours(1) + absl::Minutes(1))); EXPECT_EQ("1h1s", absl::FormatDuration(absl::Hours(1) + absl::Seconds(1))); EXPECT_EQ("1m1s", absl::FormatDuration(absl::Minutes(1) + absl::Seconds(1))); EXPECT_EQ("1h0.25s", absl::FormatDuration(absl::Hours(1) + absl::Milliseconds(250))); EXPECT_EQ("1m0.25s", absl::FormatDuration(absl::Minutes(1) + absl::Milliseconds(250))); EXPECT_EQ("1h1m0.25s", absl::FormatDuration(absl::Hours(1) + absl::Minutes(1) + absl::Milliseconds(250))); EXPECT_EQ("1h0.0005s", absl::FormatDuration(absl::Hours(1) + absl::Microseconds(500))); EXPECT_EQ("1h0.0000005s", absl::FormatDuration(absl::Hours(1) + absl::Nanoseconds(500))); // Subsecond special case. EXPECT_EQ("1.5ns", absl::FormatDuration(absl::Nanoseconds(1) + absl::Nanoseconds(1) / 2)); EXPECT_EQ("1.25ns", absl::FormatDuration(absl::Nanoseconds(1) + absl::Nanoseconds(1) / 4)); EXPECT_EQ("1ns", absl::FormatDuration(absl::Nanoseconds(1) + absl::Nanoseconds(1) / 9)); EXPECT_EQ("1.2us", absl::FormatDuration(absl::Microseconds(1) + absl::Nanoseconds(200))); EXPECT_EQ("1.2ms", absl::FormatDuration(absl::Milliseconds(1) + absl::Microseconds(200))); EXPECT_EQ("1.0002ms", absl::FormatDuration(absl::Milliseconds(1) + absl::Nanoseconds(200))); EXPECT_EQ("1.00001ms", absl::FormatDuration(absl::Milliseconds(1) + absl::Nanoseconds(10))); EXPECT_EQ("1.000001ms", absl::FormatDuration(absl::Milliseconds(1) + absl::Nanoseconds(1))); // Negative durations. EXPECT_EQ("-1ns", absl::FormatDuration(absl::Nanoseconds(-1))); EXPECT_EQ("-1us", absl::FormatDuration(absl::Microseconds(-1))); EXPECT_EQ("-1ms", absl::FormatDuration(absl::Milliseconds(-1))); EXPECT_EQ("-1s", absl::FormatDuration(absl::Seconds(-1))); EXPECT_EQ("-1m", absl::FormatDuration(absl::Minutes(-1))); EXPECT_EQ("-1h", absl::FormatDuration(absl::Hours(-1))); EXPECT_EQ("-1h1m", absl::FormatDuration(-(absl::Hours(1) + absl::Minutes(1)))); EXPECT_EQ("-1h1s", absl::FormatDuration(-(absl::Hours(1) + absl::Seconds(1)))); EXPECT_EQ("-1m1s", absl::FormatDuration(-(absl::Minutes(1) + absl::Seconds(1)))); EXPECT_EQ("-1ns", absl::FormatDuration(absl::Nanoseconds(-1))); EXPECT_EQ("-1.2us", absl::FormatDuration( -(absl::Microseconds(1) + absl::Nanoseconds(200)))); EXPECT_EQ("-1.2ms", absl::FormatDuration( -(absl::Milliseconds(1) + absl::Microseconds(200)))); EXPECT_EQ("-1.0002ms", absl::FormatDuration(-(absl::Milliseconds(1) + absl::Nanoseconds(200)))); EXPECT_EQ("-1.00001ms", absl::FormatDuration(-(absl::Milliseconds(1) + absl::Nanoseconds(10)))); EXPECT_EQ("-1.000001ms", absl::FormatDuration(-(absl::Milliseconds(1) + absl::Nanoseconds(1)))); // // Interesting corner cases. // const absl::Duration qns = absl::Nanoseconds(1) / 4; const absl::Duration max_dur = absl::Seconds(kint64max) + (absl::Seconds(1) - qns); const absl::Duration min_dur = absl::Seconds(kint64min); EXPECT_EQ("0.25ns", absl::FormatDuration(qns)); EXPECT_EQ("-0.25ns", absl::FormatDuration(-qns)); EXPECT_EQ("2562047788015215h30m7.99999999975s", absl::FormatDuration(max_dur)); EXPECT_EQ("-2562047788015215h30m8s", absl::FormatDuration(min_dur)); // Tests printing full precision from units that print using FDivDuration EXPECT_EQ("55.00000000025s", absl::FormatDuration(absl::Seconds(55) + qns)); EXPECT_EQ("55.00000025ms", absl::FormatDuration(absl::Milliseconds(55) + qns)); EXPECT_EQ("55.00025us", absl::FormatDuration(absl::Microseconds(55) + qns)); EXPECT_EQ("55.25ns", absl::FormatDuration(absl::Nanoseconds(55) + qns)); // Formatting infinity EXPECT_EQ("inf", absl::FormatDuration(absl::InfiniteDuration())); EXPECT_EQ("-inf", absl::FormatDuration(-absl::InfiniteDuration())); // Formatting approximately +/- 100 billion years const absl::Duration huge_range = ApproxYears(100000000000); EXPECT_EQ("876000000000000h", absl::FormatDuration(huge_range)); EXPECT_EQ("-876000000000000h", absl::FormatDuration(-huge_range)); EXPECT_EQ("876000000000000h0.999999999s", absl::FormatDuration(huge_range + (absl::Seconds(1) - absl::Nanoseconds(1)))); EXPECT_EQ("876000000000000h0.9999999995s", absl::FormatDuration( huge_range + (absl::Seconds(1) - absl::Nanoseconds(1) / 2))); EXPECT_EQ("876000000000000h0.99999999975s", absl::FormatDuration( huge_range + (absl::Seconds(1) - absl::Nanoseconds(1) / 4))); EXPECT_EQ("-876000000000000h0.999999999s", absl::FormatDuration(-huge_range - (absl::Seconds(1) - absl::Nanoseconds(1)))); EXPECT_EQ("-876000000000000h0.9999999995s", absl::FormatDuration( -huge_range - (absl::Seconds(1) - absl::Nanoseconds(1) / 2))); EXPECT_EQ("-876000000000000h0.99999999975s", absl::FormatDuration( -huge_range - (absl::Seconds(1) - absl::Nanoseconds(1) / 4))); } TEST(Duration, ParseDuration) { absl::Duration d; // No specified unit. Should only work for zero and infinity. EXPECT_TRUE(absl::ParseDuration("0", &d)); EXPECT_EQ(absl::ZeroDuration(), d); EXPECT_TRUE(absl::ParseDuration("+0", &d)); EXPECT_EQ(absl::ZeroDuration(), d); EXPECT_TRUE(absl::ParseDuration("-0", &d)); EXPECT_EQ(absl::ZeroDuration(), d); EXPECT_TRUE(absl::ParseDuration("inf", &d)); EXPECT_EQ(absl::InfiniteDuration(), d); EXPECT_TRUE(absl::ParseDuration("+inf", &d)); EXPECT_EQ(absl::InfiniteDuration(), d); EXPECT_TRUE(absl::ParseDuration("-inf", &d)); EXPECT_EQ(-absl::InfiniteDuration(), d); EXPECT_FALSE(absl::ParseDuration("infBlah", &d)); // Illegal input forms. EXPECT_FALSE(absl::ParseDuration("", &d)); EXPECT_FALSE(absl::ParseDuration("0.0", &d)); EXPECT_FALSE(absl::ParseDuration(".0", &d)); EXPECT_FALSE(absl::ParseDuration(".", &d)); EXPECT_FALSE(absl::ParseDuration("01", &d)); EXPECT_FALSE(absl::ParseDuration("1", &d)); EXPECT_FALSE(absl::ParseDuration("-1", &d)); EXPECT_FALSE(absl::ParseDuration("2", &d)); EXPECT_FALSE(absl::ParseDuration("2 s", &d)); EXPECT_FALSE(absl::ParseDuration(".s", &d)); EXPECT_FALSE(absl::ParseDuration("-.s", &d)); EXPECT_FALSE(absl::ParseDuration("s", &d)); EXPECT_FALSE(absl::ParseDuration(" 2s", &d)); EXPECT_FALSE(absl::ParseDuration("2s ", &d)); EXPECT_FALSE(absl::ParseDuration(" 2s ", &d)); EXPECT_FALSE(absl::ParseDuration("2mt", &d)); EXPECT_FALSE(absl::ParseDuration("1e3s", &d)); // One unit type. EXPECT_TRUE(absl::ParseDuration("1ns", &d)); EXPECT_EQ(absl::Nanoseconds(1), d); EXPECT_TRUE(absl::ParseDuration("1us", &d)); EXPECT_EQ(absl::Microseconds(1), d); EXPECT_TRUE(absl::ParseDuration("1ms", &d)); EXPECT_EQ(absl::Milliseconds(1), d); EXPECT_TRUE(absl::ParseDuration("1s", &d)); EXPECT_EQ(absl::Seconds(1), d); EXPECT_TRUE(absl::ParseDuration("2m", &d)); EXPECT_EQ(absl::Minutes(2), d); EXPECT_TRUE(absl::ParseDuration("2h", &d)); EXPECT_EQ(absl::Hours(2), d); // Huge counts of a unit. EXPECT_TRUE(absl::ParseDuration("9223372036854775807us", &d)); EXPECT_EQ(absl::Microseconds(9223372036854775807), d); EXPECT_TRUE(absl::ParseDuration("-9223372036854775807us", &d)); EXPECT_EQ(absl::Microseconds(-9223372036854775807), d); // Multiple units. EXPECT_TRUE(absl::ParseDuration("2h3m4s", &d)); EXPECT_EQ(absl::Hours(2) + absl::Minutes(3) + absl::Seconds(4), d); EXPECT_TRUE(absl::ParseDuration("3m4s5us", &d)); EXPECT_EQ(absl::Minutes(3) + absl::Seconds(4) + absl::Microseconds(5), d); EXPECT_TRUE(absl::ParseDuration("2h3m4s5ms6us7ns", &d)); EXPECT_EQ(absl::Hours(2) + absl::Minutes(3) + absl::Seconds(4) + absl::Milliseconds(5) + absl::Microseconds(6) + absl::Nanoseconds(7), d); // Multiple units out of order. EXPECT_TRUE(absl::ParseDuration("2us3m4s5h", &d)); EXPECT_EQ(absl::Hours(5) + absl::Minutes(3) + absl::Seconds(4) + absl::Microseconds(2), d); // Fractional values of units. EXPECT_TRUE(absl::ParseDuration("1.5ns", &d)); EXPECT_EQ(1.5 * absl::Nanoseconds(1), d); EXPECT_TRUE(absl::ParseDuration("1.5us", &d)); EXPECT_EQ(1.5 * absl::Microseconds(1), d); EXPECT_TRUE(absl::ParseDuration("1.5ms", &d)); EXPECT_EQ(1.5 * absl::Milliseconds(1), d); EXPECT_TRUE(absl::ParseDuration("1.5s", &d)); EXPECT_EQ(1.5 * absl::Seconds(1), d); EXPECT_TRUE(absl::ParseDuration("1.5m", &d)); EXPECT_EQ(1.5 * absl::Minutes(1), d); EXPECT_TRUE(absl::ParseDuration("1.5h", &d)); EXPECT_EQ(1.5 * absl::Hours(1), d); // Huge fractional counts of a unit. EXPECT_TRUE(absl::ParseDuration("0.4294967295s", &d)); EXPECT_EQ(absl::Nanoseconds(429496729) + absl::Nanoseconds(1) / 2, d); EXPECT_TRUE(absl::ParseDuration("0.429496729501234567890123456789s", &d)); EXPECT_EQ(absl::Nanoseconds(429496729) + absl::Nanoseconds(1) / 2, d); // Negative durations. EXPECT_TRUE(absl::ParseDuration("-1s", &d)); EXPECT_EQ(absl::Seconds(-1), d); EXPECT_TRUE(absl::ParseDuration("-1m", &d)); EXPECT_EQ(absl::Minutes(-1), d); EXPECT_TRUE(absl::ParseDuration("-1h", &d)); EXPECT_EQ(absl::Hours(-1), d); EXPECT_TRUE(absl::ParseDuration("-1h2s", &d)); EXPECT_EQ(-(absl::Hours(1) + absl::Seconds(2)), d); EXPECT_FALSE(absl::ParseDuration("1h-2s", &d)); EXPECT_FALSE(absl::ParseDuration("-1h-2s", &d)); EXPECT_FALSE(absl::ParseDuration("-1h -2s", &d)); } TEST(Duration, FormatParseRoundTrip) { #define TEST_PARSE_ROUNDTRIP(d) \ do { \ std::string s = absl::FormatDuration(d); \ absl::Duration dur; \ EXPECT_TRUE(absl::ParseDuration(s, &dur)); \ EXPECT_EQ(d, dur); \ } while (0) TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(1)); TEST_PARSE_ROUNDTRIP(absl::Microseconds(1)); TEST_PARSE_ROUNDTRIP(absl::Milliseconds(1)); TEST_PARSE_ROUNDTRIP(absl::Seconds(1)); TEST_PARSE_ROUNDTRIP(absl::Minutes(1)); TEST_PARSE_ROUNDTRIP(absl::Hours(1)); TEST_PARSE_ROUNDTRIP(absl::Hours(1) + absl::Nanoseconds(2)); TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(-1)); TEST_PARSE_ROUNDTRIP(absl::Microseconds(-1)); TEST_PARSE_ROUNDTRIP(absl::Milliseconds(-1)); TEST_PARSE_ROUNDTRIP(absl::Seconds(-1)); TEST_PARSE_ROUNDTRIP(absl::Minutes(-1)); TEST_PARSE_ROUNDTRIP(absl::Hours(-1)); TEST_PARSE_ROUNDTRIP(absl::Hours(-1) + absl::Nanoseconds(2)); TEST_PARSE_ROUNDTRIP(absl::Hours(1) + absl::Nanoseconds(-2)); TEST_PARSE_ROUNDTRIP(absl::Hours(-1) + absl::Nanoseconds(-2)); TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(1) + absl::Nanoseconds(1) / 4); // 1.25ns const absl::Duration huge_range = ApproxYears(100000000000); TEST_PARSE_ROUNDTRIP(huge_range); TEST_PARSE_ROUNDTRIP(huge_range + (absl::Seconds(1) - absl::Nanoseconds(1))); #undef TEST_PARSE_ROUNDTRIP } TEST(Duration, AbslStringify) { // FormatDuration is already well tested, so just use one test case here to // verify that StrFormat("%v", d) works as expected. absl::Duration d = absl::Seconds(1); EXPECT_EQ(absl::StrFormat("%v", d), absl::FormatDuration(d)); } TEST(Duration, NoPadding) { // Should match the size of a struct with uint32_t alignment and no padding. using NoPadding = std::array; EXPECT_EQ(sizeof(NoPadding), sizeof(absl::Duration)); EXPECT_EQ(alignof(NoPadding), alignof(absl::Duration)); } } // namespace