diff options
Diffstat (limited to 'abseil-cpp/absl/time/duration_test.cc')
-rw-r--r-- | abseil-cpp/absl/time/duration_test.cc | 47 |
1 files changed, 38 insertions, 9 deletions
diff --git a/abseil-cpp/absl/time/duration_test.cc b/abseil-cpp/absl/time/duration_test.cc index 4d85a2c..dcf7aad 100644 --- a/abseil-cpp/absl/time/duration_test.cc +++ b/abseil-cpp/absl/time/duration_test.cc @@ -16,6 +16,8 @@ #include <winsock2.h> // for timeval #endif +#include <array> +#include <cfloat> #include <chrono> // NOLINT(build/c++11) #include <cmath> #include <cstdint> @@ -27,6 +29,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/strings/str_format.h" #include "absl/time/time.h" namespace { @@ -1320,7 +1323,7 @@ TEST(Duration, SmallConversions) { 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::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)); @@ -1330,7 +1333,7 @@ TEST(Duration, SmallConversions) { 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::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)); @@ -1369,10 +1372,13 @@ TEST(Duration, SmallConversions) { EXPECT_THAT(ToTimeval(absl::Nanoseconds(2000)), TimevalMatcher(tv)); } -void VerifySameAsMul(double time_as_seconds, int* const misses) { +void VerifyApproxSameAsMul(double time_as_seconds, int* const misses) { auto direct_seconds = absl::Seconds(time_as_seconds); auto mul_by_one_second = time_as_seconds * absl::Seconds(1); - if (direct_seconds != mul_by_one_second) { + // 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) @@ -1384,8 +1390,17 @@ void VerifySameAsMul(double time_as_seconds, int* const misses) { // 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 the same duration as point * Seconds(1.0) +// 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; @@ -1423,8 +1438,8 @@ TEST(Duration, ToDoubleSecondsCheckEdgeCases) { } // 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. - VerifySameAsMul(low_edge, &misses); - VerifySameAsMul(high_edge, &misses); + VerifyApproxSameAsMul(low_edge, &misses); + VerifyApproxSameAsMul(high_edge, &misses); } } } @@ -1444,8 +1459,8 @@ TEST(Duration, ToDoubleSecondsCheckRandom) { int misses = 0; for (int i = 0; i < 1000000; ++i) { double d = std::exp(uniform(gen)); - VerifySameAsMul(d, &misses); - VerifySameAsMul(-d, &misses); + VerifyApproxSameAsMul(d, &misses); + VerifyApproxSameAsMul(-d, &misses); } } @@ -1805,4 +1820,18 @@ TEST(Duration, FormatParseRoundTrip) { #undef TEST_PARSE_ROUNDTRIP } +TEST(Duration, AbslStringify) { + // FormatDuration is already well tested, so just use one test case here to + // verify that StrFormat("%v", d) works as expected. + absl::Duration d = absl::Seconds(1); + EXPECT_EQ(absl::StrFormat("%v", d), absl::FormatDuration(d)); +} + +TEST(Duration, NoPadding) { + // Should match the size of a struct with uint32_t alignment and no padding. + using NoPadding = std::array<uint32_t, 3>; + EXPECT_EQ(sizeof(NoPadding), sizeof(absl::Duration)); + EXPECT_EQ(alignof(NoPadding), alignof(absl::Duration)); +} + } // namespace |