| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "absl/synchronization/internal/kernel_timeout.h" |
|
|
| #include <ctime> |
| #include <chrono> |
| #include <limits> |
|
|
| #include "absl/base/config.h" |
| #include "absl/random/random.h" |
| #include "absl/time/clock.h" |
| #include "absl/time/time.h" |
| #include "gtest/gtest.h" |
|
|
| |
| |
| |
| #if defined(__GOOGLE_GRTE_VERSION__) && \ |
| !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \ |
| !defined(ABSL_HAVE_MEMORY_SANITIZER) && \ |
| !defined(ABSL_HAVE_THREAD_SANITIZER) |
| extern "C" int __clock_gettime(clockid_t c, struct timespec* ts); |
|
|
| extern "C" int clock_gettime(clockid_t c, struct timespec* ts) { |
| if (c == CLOCK_MONOTONIC && |
| !absl::synchronization_internal::KernelTimeout::SupportsSteadyClock()) { |
| absl::SharedBitGen gen; |
| ts->tv_sec = absl::Uniform(gen, 0, 1'000'000'000); |
| ts->tv_nsec = absl::Uniform(gen, 0, 1'000'000'000); |
| return 0; |
| } |
| return __clock_gettime(c, ts); |
| } |
| #endif |
|
|
| namespace { |
|
|
| #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ |
| defined(ABSL_HAVE_MEMORY_SANITIZER) || \ |
| defined(ABSL_HAVE_THREAD_SANITIZER) || defined(__ANDROID__) || \ |
| defined(__APPLE__) || defined(_WIN32) || defined(_WIN64) |
| constexpr absl::Duration kTimingBound = absl::Milliseconds(5); |
| #else |
| constexpr absl::Duration kTimingBound = absl::Microseconds(250); |
| #endif |
|
|
| using absl::synchronization_internal::KernelTimeout; |
|
|
| TEST(KernelTimeout, FiniteTimes) { |
| constexpr absl::Duration kDurationsToTest[] = { |
| absl::ZeroDuration(), |
| absl::Nanoseconds(1), |
| absl::Microseconds(1), |
| absl::Milliseconds(1), |
| absl::Seconds(1), |
| absl::Minutes(1), |
| absl::Hours(1), |
| absl::Hours(1000), |
| -absl::Nanoseconds(1), |
| -absl::Microseconds(1), |
| -absl::Milliseconds(1), |
| -absl::Seconds(1), |
| -absl::Minutes(1), |
| -absl::Hours(1), |
| -absl::Hours(1000), |
| }; |
|
|
| for (auto duration : kDurationsToTest) { |
| const absl::Time now = absl::Now(); |
| const absl::Time when = now + duration; |
| SCOPED_TRACE(duration); |
| KernelTimeout t(when); |
| EXPECT_TRUE(t.has_timeout()); |
| EXPECT_TRUE(t.is_absolute_timeout()); |
| EXPECT_FALSE(t.is_relative_timeout()); |
| EXPECT_EQ(absl::TimeFromTimespec(t.MakeAbsTimespec()), when); |
| #ifndef _WIN32 |
| EXPECT_LE( |
| absl::AbsDuration(absl::Now() + duration - |
| absl::TimeFromTimespec( |
| t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))), |
| absl::Milliseconds(10)); |
| #endif |
| EXPECT_LE( |
| absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) - |
| std::max(duration, absl::ZeroDuration())), |
| kTimingBound); |
| EXPECT_EQ(absl::FromUnixNanos(t.MakeAbsNanos()), when); |
| EXPECT_LE(absl::AbsDuration(absl::Milliseconds(t.InMillisecondsFromNow()) - |
| std::max(duration, absl::ZeroDuration())), |
| absl::Milliseconds(5)); |
| EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoTimePoint()) - when), |
| absl::Microseconds(1)); |
| EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) - |
| std::max(duration, absl::ZeroDuration())), |
| kTimingBound); |
| } |
| } |
|
|
| TEST(KernelTimeout, InfiniteFuture) { |
| KernelTimeout t(absl::InfiniteFuture()); |
| EXPECT_FALSE(t.has_timeout()); |
| |
| |
| |
| |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), |
| absl::Now() + absl::Hours(100000)); |
| #ifndef _WIN32 |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), |
| absl::Now() + absl::Hours(100000)); |
| #endif |
| EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), |
| absl::Hours(100000)); |
| EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), |
| absl::Now() + absl::Hours(100000)); |
| EXPECT_EQ(t.InMillisecondsFromNow(), |
| std::numeric_limits<KernelTimeout::DWord>::max()); |
| EXPECT_EQ(t.ToChronoTimePoint(), |
| std::chrono::time_point<std::chrono::system_clock>::max()); |
| EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); |
| } |
|
|
| TEST(KernelTimeout, DefaultConstructor) { |
| |
| KernelTimeout t; |
| EXPECT_FALSE(t.has_timeout()); |
| |
| |
| |
| |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), |
| absl::Now() + absl::Hours(100000)); |
| #ifndef _WIN32 |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), |
| absl::Now() + absl::Hours(100000)); |
| #endif |
| EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), |
| absl::Hours(100000)); |
| EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), |
| absl::Now() + absl::Hours(100000)); |
| EXPECT_EQ(t.InMillisecondsFromNow(), |
| std::numeric_limits<KernelTimeout::DWord>::max()); |
| EXPECT_EQ(t.ToChronoTimePoint(), |
| std::chrono::time_point<std::chrono::system_clock>::max()); |
| EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); |
| } |
|
|
| TEST(KernelTimeout, TimeMaxNanos) { |
| |
| KernelTimeout t(absl::FromUnixNanos(std::numeric_limits<int64_t>::max())); |
| EXPECT_FALSE(t.has_timeout()); |
| |
| |
| |
| |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), |
| absl::Now() + absl::Hours(100000)); |
| #ifndef _WIN32 |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), |
| absl::Now() + absl::Hours(100000)); |
| #endif |
| EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), |
| absl::Hours(100000)); |
| EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), |
| absl::Now() + absl::Hours(100000)); |
| EXPECT_EQ(t.InMillisecondsFromNow(), |
| std::numeric_limits<KernelTimeout::DWord>::max()); |
| EXPECT_EQ(t.ToChronoTimePoint(), |
| std::chrono::time_point<std::chrono::system_clock>::max()); |
| EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); |
| } |
|
|
| TEST(KernelTimeout, Never) { |
| |
| KernelTimeout t = KernelTimeout::Never(); |
| EXPECT_FALSE(t.has_timeout()); |
| |
| |
| |
| |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), |
| absl::Now() + absl::Hours(100000)); |
| #ifndef _WIN32 |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), |
| absl::Now() + absl::Hours(100000)); |
| #endif |
| EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), |
| absl::Hours(100000)); |
| EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), |
| absl::Now() + absl::Hours(100000)); |
| EXPECT_EQ(t.InMillisecondsFromNow(), |
| std::numeric_limits<KernelTimeout::DWord>::max()); |
| EXPECT_EQ(t.ToChronoTimePoint(), |
| std::chrono::time_point<std::chrono::system_clock>::max()); |
| EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); |
| } |
|
|
| TEST(KernelTimeout, InfinitePast) { |
| KernelTimeout t(absl::InfinitePast()); |
| EXPECT_TRUE(t.has_timeout()); |
| EXPECT_TRUE(t.is_absolute_timeout()); |
| EXPECT_FALSE(t.is_relative_timeout()); |
| EXPECT_LE(absl::TimeFromTimespec(t.MakeAbsTimespec()), |
| absl::FromUnixNanos(1)); |
| #ifndef _WIN32 |
| EXPECT_LE(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), |
| absl::FromUnixSeconds(1)); |
| #endif |
| EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()), |
| absl::ZeroDuration()); |
| EXPECT_LE(absl::FromUnixNanos(t.MakeAbsNanos()), absl::FromUnixNanos(1)); |
| EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0}); |
| EXPECT_LT(t.ToChronoTimePoint(), std::chrono::system_clock::from_time_t(0) + |
| std::chrono::seconds(1)); |
| EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0)); |
| } |
|
|
| TEST(KernelTimeout, FiniteDurations) { |
| constexpr absl::Duration kDurationsToTest[] = { |
| absl::ZeroDuration(), |
| absl::Nanoseconds(1), |
| absl::Microseconds(1), |
| absl::Milliseconds(1), |
| absl::Seconds(1), |
| absl::Minutes(1), |
| absl::Hours(1), |
| absl::Hours(1000), |
| }; |
|
|
| for (auto duration : kDurationsToTest) { |
| SCOPED_TRACE(duration); |
| KernelTimeout t(duration); |
| EXPECT_TRUE(t.has_timeout()); |
| EXPECT_FALSE(t.is_absolute_timeout()); |
| EXPECT_TRUE(t.is_relative_timeout()); |
| EXPECT_LE(absl::AbsDuration(absl::Now() + duration - |
| absl::TimeFromTimespec(t.MakeAbsTimespec())), |
| absl::Milliseconds(5)); |
| #ifndef _WIN32 |
| EXPECT_LE( |
| absl::AbsDuration(absl::Now() + duration - |
| absl::TimeFromTimespec( |
| t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))), |
| absl::Milliseconds(5)); |
| #endif |
| EXPECT_LE( |
| absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) - |
| duration), |
| kTimingBound); |
| EXPECT_LE(absl::AbsDuration(absl::Now() + duration - |
| absl::FromUnixNanos(t.MakeAbsNanos())), |
| absl::Milliseconds(5)); |
| EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration, |
| absl::Milliseconds(5)); |
| EXPECT_LE(absl::AbsDuration(absl::Now() + duration - |
| absl::FromChrono(t.ToChronoTimePoint())), |
| kTimingBound); |
| EXPECT_LE( |
| absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) - duration), |
| kTimingBound); |
| } |
| } |
|
|
| TEST(KernelTimeout, NegativeDurations) { |
| constexpr absl::Duration kDurationsToTest[] = { |
| -absl::ZeroDuration(), |
| -absl::Nanoseconds(1), |
| -absl::Microseconds(1), |
| -absl::Milliseconds(1), |
| -absl::Seconds(1), |
| -absl::Minutes(1), |
| -absl::Hours(1), |
| -absl::Hours(1000), |
| -absl::InfiniteDuration(), |
| }; |
|
|
| for (auto duration : kDurationsToTest) { |
| |
| SCOPED_TRACE(duration); |
| KernelTimeout t(duration); |
| EXPECT_TRUE(t.has_timeout()); |
| EXPECT_FALSE(t.is_absolute_timeout()); |
| EXPECT_TRUE(t.is_relative_timeout()); |
| EXPECT_LE(absl::AbsDuration(absl::Now() - |
| absl::TimeFromTimespec(t.MakeAbsTimespec())), |
| absl::Milliseconds(5)); |
| #ifndef _WIN32 |
| EXPECT_LE(absl::AbsDuration(absl::Now() - absl::TimeFromTimespec( |
| t.MakeClockAbsoluteTimespec( |
| CLOCK_REALTIME))), |
| absl::Milliseconds(5)); |
| #endif |
| EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()), |
| absl::ZeroDuration()); |
| EXPECT_LE( |
| absl::AbsDuration(absl::Now() - absl::FromUnixNanos(t.MakeAbsNanos())), |
| absl::Milliseconds(5)); |
| EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0}); |
| EXPECT_LE(absl::AbsDuration(absl::Now() - |
| absl::FromChrono(t.ToChronoTimePoint())), |
| absl::Milliseconds(5)); |
| EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0)); |
| } |
| } |
|
|
| TEST(KernelTimeout, InfiniteDuration) { |
| KernelTimeout t(absl::InfiniteDuration()); |
| EXPECT_FALSE(t.has_timeout()); |
| |
| |
| |
| |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), |
| absl::Now() + absl::Hours(100000)); |
| #ifndef _WIN32 |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), |
| absl::Now() + absl::Hours(100000)); |
| #endif |
| EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), |
| absl::Hours(100000)); |
| EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), |
| absl::Now() + absl::Hours(100000)); |
| EXPECT_EQ(t.InMillisecondsFromNow(), |
| std::numeric_limits<KernelTimeout::DWord>::max()); |
| EXPECT_EQ(t.ToChronoTimePoint(), |
| std::chrono::time_point<std::chrono::system_clock>::max()); |
| EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); |
| } |
|
|
| TEST(KernelTimeout, DurationMaxNanos) { |
| |
| KernelTimeout t(absl::Nanoseconds(std::numeric_limits<int64_t>::max())); |
| EXPECT_FALSE(t.has_timeout()); |
| |
| |
| |
| |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), |
| absl::Now() + absl::Hours(100000)); |
| #ifndef _WIN32 |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), |
| absl::Now() + absl::Hours(100000)); |
| #endif |
| EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), |
| absl::Hours(100000)); |
| EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), |
| absl::Now() + absl::Hours(100000)); |
| EXPECT_EQ(t.InMillisecondsFromNow(), |
| std::numeric_limits<KernelTimeout::DWord>::max()); |
| EXPECT_EQ(t.ToChronoTimePoint(), |
| std::chrono::time_point<std::chrono::system_clock>::max()); |
| EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); |
| } |
|
|
| TEST(KernelTimeout, OverflowNanos) { |
| |
| |
| int64_t now_nanos = absl::ToUnixNanos(absl::Now()); |
| int64_t limit = std::numeric_limits<int64_t>::max() - now_nanos; |
| absl::Duration duration = absl::Nanoseconds(limit) + absl::Seconds(1); |
| KernelTimeout t(duration); |
| |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), |
| absl::Now() + absl::Hours(100000)); |
| #ifndef _WIN32 |
| EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), |
| absl::Now() + absl::Hours(100000)); |
| #endif |
| EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), |
| absl::Hours(100000)); |
| EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), |
| absl::Now() + absl::Hours(100000)); |
| EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration, |
| absl::Milliseconds(5)); |
| EXPECT_GT(t.ToChronoTimePoint(), |
| std::chrono::system_clock::now() + std::chrono::hours(100000)); |
| EXPECT_GT(t.ToChronoDuration(), std::chrono::hours(100000)); |
| } |
|
|
| } |
|
|