Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/abseil-cpp/absl/time/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 76 kB image not shown  

Quelle  duration_test.cc   Sprache: C

 
// 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 <winsock2.h>  // 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 <version>
#endif

#include <array>
#include <cfloat>
#include <chrono>  // NOLINT(build/c++11)
#ifdef __cpp_lib_three_way_comparison
#include <compare>
#endif  // __cpp_lib_three_way_comparison
#include <cmath>
#include <cstdint>
#include <ctime>
#include <iomanip>
#include <limits>
#include <random>
#include <string>

#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<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, 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<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>();
}

template <int64_t N>
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 <int64_t N>
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<kint64min>();
  TestToChrono<-1>();
  TestToChrono<0>();
  TestToChrono<1>();
  TestToChrono<kint64max>();

  // 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<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(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 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<double>::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<double>::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<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(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<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();

  // 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<double>::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, intconst 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<double> 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<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) +
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.