Abseil Common Libraries (C++) (grcp 依赖) https://abseil.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1813 lines
73 KiB

Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
// 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 <chrono> // NOLINT(build/c++11)
#include <cmath>
#include <cstdint>
#include <ctime>
#include <iomanip>
#include <limits>
#include <random>
#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, 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);
}
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);
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(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);
}
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(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(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));
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));
}
void VerifyApproxSameAsMul(double time_as_seconds, int* const misses) {
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
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)) {
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
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.)
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
TEST(Duration, ToDoubleSecondsCheckEdgeCases) {
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);
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
}
}
}
}
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);
Export of internal Abseil changes -- f012012ef78234a6a4585321b67d7b7c92ebc266 by Laramie Leavitt <lar@google.com>: Slight restructuring of absl/random/internal randen implementation. Convert round-keys.inc into randen_round_keys.cc file. Consistently use a 128-bit pointer type for internal method parameters. This allows simpler pointer arithmetic in C++ & permits removal of some constants and casts. Remove some redundancy in comments & constexpr variables. Specifically, all references to Randen algorithm parameters use RandenTraits; duplication in RandenSlow removed. PiperOrigin-RevId: 312190313 -- dc8b42e054046741e9ed65335bfdface997c6063 by Abseil Team <absl-team@google.com>: Internal change. PiperOrigin-RevId: 312167304 -- f13d248fafaf206492c1362c3574031aea3abaf7 by Matthew Brown <matthewbr@google.com>: Cleanup StrFormat extensions a little. PiperOrigin-RevId: 312166336 -- 9d9117589667afe2332bb7ad42bc967ca7c54502 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 312105213 -- 9a12b9b3aa0e59b8ee6cf9408ed0029045543a9b by Abseil Team <absl-team@google.com>: Complete IGNORE_TYPE macro renaming. PiperOrigin-RevId: 311999699 -- 64756f20d61021d999bd0d4c15e9ad3857382f57 by Gennadiy Rozental <rogeeff@google.com>: Switch to fixed bytes specific default value. This fixes the Abseil Flags for big endian platforms. PiperOrigin-RevId: 311844448 -- bdbe6b5b29791dbc3816ada1828458b3010ff1e9 by Laramie Leavitt <lar@google.com>: Change many distribution tests to use pcg_engine as a deterministic source of entropy. It's reasonable to test that the BitGen itself has good entropy, however when testing the cross product of all random distributions x all the architecture variations x all submitted changes results in a large number of tests. In order to account for these failures while still using good entropy requires that our allowed sigma need to account for all of these independent tests. Our current sigma values are too restrictive, and we see a lot of failures, so we have to either relax the sigma values or convert some of the statistical tests to use deterministic values. This changelist does the latter. PiperOrigin-RevId: 311840096 GitOrigin-RevId: f012012ef78234a6a4585321b67d7b7c92ebc266 Change-Id: Ic84886f38ff30d7d72c126e9b63c9a61eb729a1a
5 years ago
}
}
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));
EXPECT_FALSE(absl::ParseDuration("1e3s", &d));
// One unit type.
EXPECT_TRUE(absl::ParseDuration("1ns", &d));
EXPECT_EQ(absl::Nanoseconds(1), d);
EXPECT_TRUE(absl::ParseDuration("1us", &d));
EXPECT_EQ(absl::Microseconds(1), d);
EXPECT_TRUE(absl::ParseDuration("1ms", &d));
EXPECT_EQ(absl::Milliseconds(1), d);
EXPECT_TRUE(absl::ParseDuration("1s", &d));
EXPECT_EQ(absl::Seconds(1), d);
EXPECT_TRUE(absl::ParseDuration("2m", &d));
EXPECT_EQ(absl::Minutes(2), d);
EXPECT_TRUE(absl::ParseDuration("2h", &d));
EXPECT_EQ(absl::Hours(2), d);
// Huge counts of a unit.
EXPECT_TRUE(absl::ParseDuration("9223372036854775807us", &d));
EXPECT_EQ(absl::Microseconds(9223372036854775807), d);
EXPECT_TRUE(absl::ParseDuration("-9223372036854775807us", &d));
EXPECT_EQ(absl::Microseconds(-9223372036854775807), d);
// Multiple units.
EXPECT_TRUE(absl::ParseDuration("2h3m4s", &d));
EXPECT_EQ(absl::Hours(2) + absl::Minutes(3) + absl::Seconds(4), d);
EXPECT_TRUE(absl::ParseDuration("3m4s5us", &d));
EXPECT_EQ(absl::Minutes(3) + absl::Seconds(4) + absl::Microseconds(5), d);
EXPECT_TRUE(absl::ParseDuration("2h3m4s5ms6us7ns", &d));
EXPECT_EQ(absl::Hours(2) + absl::Minutes(3) + absl::Seconds(4) +
absl::Milliseconds(5) + absl::Microseconds(6) +
absl::Nanoseconds(7),
d);
// Multiple units out of order.
EXPECT_TRUE(absl::ParseDuration("2us3m4s5h", &d));
EXPECT_EQ(absl::Hours(5) + absl::Minutes(3) + absl::Seconds(4) +
absl::Microseconds(2),
d);
// Fractional values of units.
EXPECT_TRUE(absl::ParseDuration("1.5ns", &d));
EXPECT_EQ(1.5 * absl::Nanoseconds(1), d);
EXPECT_TRUE(absl::ParseDuration("1.5us", &d));
EXPECT_EQ(1.5 * absl::Microseconds(1), d);
EXPECT_TRUE(absl::ParseDuration("1.5ms", &d));
EXPECT_EQ(1.5 * absl::Milliseconds(1), d);
EXPECT_TRUE(absl::ParseDuration("1.5s", &d));
EXPECT_EQ(1.5 * absl::Seconds(1), d);
EXPECT_TRUE(absl::ParseDuration("1.5m", &d));
EXPECT_EQ(1.5 * absl::Minutes(1), d);
EXPECT_TRUE(absl::ParseDuration("1.5h", &d));
EXPECT_EQ(1.5 * absl::Hours(1), d);
// Huge fractional counts of a unit.
EXPECT_TRUE(absl::ParseDuration("0.4294967295s", &d));
EXPECT_EQ(absl::Nanoseconds(429496729) + absl::Nanoseconds(1) / 2, d);
EXPECT_TRUE(absl::ParseDuration("0.429496729501234567890123456789s", &d));
EXPECT_EQ(absl::Nanoseconds(429496729) + absl::Nanoseconds(1) / 2, d);
// Negative durations.
EXPECT_TRUE(absl::ParseDuration("-1s", &d));
EXPECT_EQ(absl::Seconds(-1), d);
EXPECT_TRUE(absl::ParseDuration("-1m", &d));
EXPECT_EQ(absl::Minutes(-1), d);
EXPECT_TRUE(absl::ParseDuration("-1h", &d));
EXPECT_EQ(absl::Hours(-1), d);
EXPECT_TRUE(absl::ParseDuration("-1h2s", &d));
EXPECT_EQ(-(absl::Hours(1) + absl::Seconds(2)), d);
EXPECT_FALSE(absl::ParseDuration("1h-2s", &d));
EXPECT_FALSE(absl::ParseDuration("-1h-2s", &d));
EXPECT_FALSE(absl::ParseDuration("-1h -2s", &d));
}
TEST(Duration, FormatParseRoundTrip) {
#define TEST_PARSE_ROUNDTRIP(d) \
do { \
std::string s = absl::FormatDuration(d); \
absl::Duration dur; \
EXPECT_TRUE(absl::ParseDuration(s, &dur)); \
EXPECT_EQ(d, dur); \
} while (0)
TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(1));
TEST_PARSE_ROUNDTRIP(absl::Microseconds(1));
TEST_PARSE_ROUNDTRIP(absl::Milliseconds(1));
TEST_PARSE_ROUNDTRIP(absl::Seconds(1));
TEST_PARSE_ROUNDTRIP(absl::Minutes(1));
TEST_PARSE_ROUNDTRIP(absl::Hours(1));
TEST_PARSE_ROUNDTRIP(absl::Hours(1) + absl::Nanoseconds(2));
TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(-1));
TEST_PARSE_ROUNDTRIP(absl::Microseconds(-1));
TEST_PARSE_ROUNDTRIP(absl::Milliseconds(-1));
TEST_PARSE_ROUNDTRIP(absl::Seconds(-1));
TEST_PARSE_ROUNDTRIP(absl::Minutes(-1));
TEST_PARSE_ROUNDTRIP(absl::Hours(-1));
TEST_PARSE_ROUNDTRIP(absl::Hours(-1) + absl::Nanoseconds(2));
TEST_PARSE_ROUNDTRIP(absl::Hours(1) + absl::Nanoseconds(-2));
TEST_PARSE_ROUNDTRIP(absl::Hours(-1) + absl::Nanoseconds(-2));
TEST_PARSE_ROUNDTRIP(absl::Nanoseconds(1) +
absl::Nanoseconds(1) / 4); // 1.25ns
const absl::Duration huge_range = ApproxYears(100000000000);
TEST_PARSE_ROUNDTRIP(huge_range);
TEST_PARSE_ROUNDTRIP(huge_range + (absl::Seconds(1) - absl::Nanoseconds(1)));
#undef TEST_PARSE_ROUNDTRIP
}
} // namespace