diff options
author | misterg <misterg@google.com> | 2017-09-19T20·54-0400 |
---|---|---|
committer | misterg <misterg@google.com> | 2017-09-19T20·54-0400 |
commit | c2e754829628d1e9b7a16b3389cfdace76950fdf (patch) | |
tree | 5a7f056f44e27c30e10025113b644f0b3b5801fc /absl/time/duration_test.cc |
Initial Commit
Diffstat (limited to 'absl/time/duration_test.cc')
-rw-r--r-- | absl/time/duration_test.cc | 1530 |
1 files changed, 1530 insertions, 0 deletions
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc new file mode 100644 index 000000000000..eed96e3e18f4 --- /dev/null +++ b/absl/time/duration_test.cc @@ -0,0 +1,1530 @@ +// 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 +// +// http://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. + +#include <cmath> +#include <cstdint> +#include <ctime> +#include <limits> +#include <string> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/time/time.h" + +namespace { + +constexpr int64_t kint64max = std::numeric_limits<int64_t>::max(); +constexpr int64_t kint64min = std::numeric_limits<int64_t>::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, 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); \ + const absl::Duration z = absl::ZeroDuration(); \ + const absl::Duration inf = absl::InfiniteDuration(); \ + const double dbl_inf = std::numeric_limits<double>::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 <int64_t n> +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>(); +} + +// Used for testing the factory overloads. +template <typename T> +struct ImplicitlyConvertible { + T n_; + explicit ImplicitlyConvertible(T n) : n_(n) {} + // Marking this conversion operator with 'explicit' will cause the test to + // fail (as desired). + operator T() { return n_; } +}; + +TEST(Duration, FactoryOverloads) { +#define TEST_FACTORY_OVERLOADS(NAME) \ + EXPECT_EQ(1, NAME(static_cast<int8_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(static_cast<int16_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(static_cast<int32_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(static_cast<int64_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(static_cast<uint8_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(static_cast<uint16_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(static_cast<uint32_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(static_cast<uint64_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(ImplicitlyConvertible<int8_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(ImplicitlyConvertible<int16_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(ImplicitlyConvertible<int32_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(ImplicitlyConvertible<int64_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(ImplicitlyConvertible<uint8_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(ImplicitlyConvertible<uint16_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(ImplicitlyConvertible<uint32_t>(1)) / NAME(1)); \ + EXPECT_EQ(1, NAME(ImplicitlyConvertible<uint64_t>(1)) / NAME(1)); \ + EXPECT_EQ(NAME(1) / 2, NAME(static_cast<float>(0.5))); \ + EXPECT_EQ(NAME(1) / 2, NAME(static_cast<double>(0.5))); \ + EXPECT_EQ(1.5, absl::FDivDuration(NAME(static_cast<float>(1.5)), NAME(1))); \ + EXPECT_EQ(1.5, absl::FDivDuration(NAME(static_cast<double>(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<double>::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 //base/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); +} + +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<double>::infinity(); + EXPECT_TRUE(isinf(dbl_inf + dbl_inf)); + EXPECT_TRUE(isnan(dbl_inf + -dbl_inf)); // We return inf + EXPECT_TRUE(isnan(-dbl_inf + dbl_inf)); // We return inf + EXPECT_TRUE(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); + almost_neg_inf -= -absl::Nanoseconds(1); + EXPECT_LT(-inf, almost_neg_inf); + + // For reference: IEEE 754 behavior + const double dbl_inf = std::numeric_limits<double>::infinity(); + EXPECT_TRUE(isnan(dbl_inf - dbl_inf)); // We return inf + EXPECT_TRUE(isinf(dbl_inf - -dbl_inf)); + EXPECT_TRUE(isinf(-dbl_inf - dbl_inf)); + EXPECT_TRUE(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<T>(2)); \ + EXPECT_EQ(-inf, inf * static_cast<T>(-2)); \ + EXPECT_EQ(-inf, -inf * static_cast<T>(2)); \ + EXPECT_EQ(inf, -inf * static_cast<T>(-2)); \ + EXPECT_EQ(inf, inf * static_cast<T>(0)); \ + EXPECT_EQ(-inf, -inf * static_cast<T>(0)); \ + EXPECT_EQ(inf, sec_max * static_cast<T>(2)); \ + EXPECT_EQ(inf, sec_min * static_cast<T>(-2)); \ + EXPECT_EQ(inf, (sec_max / static_cast<T>(2)) * static_cast<T>(3)); \ + EXPECT_EQ(-inf, sec_max * static_cast<T>(-2)); \ + EXPECT_EQ(-inf, sec_min * static_cast<T>(2)); \ + EXPECT_EQ(-inf, (sec_min / static_cast<T>(2)) * static_cast<T>(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<double>::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<double>(kint64max)); + EXPECT_NE(-absl::InfiniteDuration(), absl::Seconds(1) * kint64min); + EXPECT_EQ(-inf, absl::Seconds(1) * static_cast<double>(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<T>(2)); \ + EXPECT_EQ(-inf, inf / static_cast<T>(-2)); \ + EXPECT_EQ(-inf, -inf / static_cast<T>(2)); \ + EXPECT_EQ(inf, -inf / static_cast<T>(-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<double>::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<double>::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(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(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<double>::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<double>::infinity(); + const double dbl_denorm = std::numeric_limits<double>::denorm_min(); + + // IEEE 754 behavior + double z = 0.0, two = 2.0; + EXPECT_TRUE(isinf(two / z)); + EXPECT_TRUE(isnan(z / z)); // We'll return inf + + // 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, 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); +} + +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 +} + +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(7000000000LL); + 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(0.124999999e-9)); + 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)); +} + +TEST(Duration, ConversionSaturation) { + absl::Duration d; + + const auto max_timeval_sec = + std::numeric_limits<decltype(timeval::tv_sec)>::max(); + const auto min_timeval_sec = + std::numeric_limits<decltype(timeval::tv_sec)>::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<decltype(timespec::tv_sec)>::max(); + const auto min_timespec_sec = + std::numeric_limits<decltype(timespec::tv_sec)>::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)); + + // 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); + + // 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); + + // 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 +} +} // namespace |