kernel_timeout_test.cc (16683B)
1 // Copyright 2023 The Abseil Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/synchronization/internal/kernel_timeout.h" 16 17 #include <ctime> 18 #include <chrono> // NOLINT(build/c++11) 19 #include <limits> 20 21 #include "absl/base/config.h" 22 #include "absl/random/random.h" 23 #include "absl/time/clock.h" 24 #include "absl/time/time.h" 25 #include "gtest/gtest.h" 26 27 // Test go/btm support by randomizing the value of clock_gettime() for 28 // CLOCK_MONOTONIC. This works by overriding a weak symbol in glibc. 29 // We should be resistant to this randomization when !SupportsSteadyClock(). 30 #if defined(__GOOGLE_GRTE_VERSION__) && \ 31 !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \ 32 !defined(ABSL_HAVE_MEMORY_SANITIZER) && \ 33 !defined(ABSL_HAVE_THREAD_SANITIZER) 34 extern "C" int __clock_gettime(clockid_t c, struct timespec* ts); 35 36 extern "C" int clock_gettime(clockid_t c, struct timespec* ts) { 37 if (c == CLOCK_MONOTONIC && 38 !absl::synchronization_internal::KernelTimeout::SupportsSteadyClock()) { 39 thread_local absl::BitGen gen; // NOLINT 40 ts->tv_sec = absl::Uniform(gen, 0, 1'000'000'000); 41 ts->tv_nsec = absl::Uniform(gen, 0, 1'000'000'000); 42 return 0; 43 } 44 return __clock_gettime(c, ts); 45 } 46 #endif 47 48 namespace { 49 50 #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ 51 defined(ABSL_HAVE_MEMORY_SANITIZER) || \ 52 defined(ABSL_HAVE_THREAD_SANITIZER) || defined(__ANDROID__) || \ 53 defined(__APPLE__) || defined(_WIN32) || defined(_WIN64) 54 constexpr absl::Duration kTimingBound = absl::Milliseconds(5); 55 #else 56 constexpr absl::Duration kTimingBound = absl::Microseconds(250); 57 #endif 58 59 using absl::synchronization_internal::KernelTimeout; 60 61 // TODO(b/348224897): re-enabled when the flakiness is fixed. 62 TEST(KernelTimeout, DISABLED_FiniteTimes) { 63 constexpr absl::Duration kDurationsToTest[] = { 64 absl::ZeroDuration(), 65 absl::Nanoseconds(1), 66 absl::Microseconds(1), 67 absl::Milliseconds(1), 68 absl::Seconds(1), 69 absl::Minutes(1), 70 absl::Hours(1), 71 absl::Hours(1000), 72 -absl::Nanoseconds(1), 73 -absl::Microseconds(1), 74 -absl::Milliseconds(1), 75 -absl::Seconds(1), 76 -absl::Minutes(1), 77 -absl::Hours(1), 78 -absl::Hours(1000), 79 }; 80 81 for (auto duration : kDurationsToTest) { 82 const absl::Time now = absl::Now(); 83 const absl::Time when = now + duration; 84 SCOPED_TRACE(duration); 85 KernelTimeout t(when); 86 EXPECT_TRUE(t.has_timeout()); 87 EXPECT_TRUE(t.is_absolute_timeout()); 88 EXPECT_FALSE(t.is_relative_timeout()); 89 EXPECT_EQ(absl::TimeFromTimespec(t.MakeAbsTimespec()), when); 90 #ifndef _WIN32 91 EXPECT_LE( 92 absl::AbsDuration(absl::Now() + duration - 93 absl::TimeFromTimespec( 94 t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))), 95 absl::Milliseconds(10)); 96 #endif 97 EXPECT_LE( 98 absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) - 99 std::max(duration, absl::ZeroDuration())), 100 kTimingBound); 101 EXPECT_EQ(absl::FromUnixNanos(t.MakeAbsNanos()), when); 102 EXPECT_LE(absl::AbsDuration(absl::Milliseconds(t.InMillisecondsFromNow()) - 103 std::max(duration, absl::ZeroDuration())), 104 absl::Milliseconds(5)); 105 EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoTimePoint()) - when), 106 absl::Microseconds(1)); 107 EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) - 108 std::max(duration, absl::ZeroDuration())), 109 kTimingBound); 110 } 111 } 112 113 TEST(KernelTimeout, InfiniteFuture) { 114 KernelTimeout t(absl::InfiniteFuture()); 115 EXPECT_FALSE(t.has_timeout()); 116 // Callers are expected to check has_timeout() instead of using the methods 117 // below, but we do try to do something reasonable if they don't. We may not 118 // be able to round-trip back to absl::InfiniteDuration() or 119 // absl::InfiniteFuture(), but we should return a very large value. 120 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), 121 absl::Now() + absl::Hours(100000)); 122 #ifndef _WIN32 123 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), 124 absl::Now() + absl::Hours(100000)); 125 #endif 126 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), 127 absl::Hours(100000)); 128 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), 129 absl::Now() + absl::Hours(100000)); 130 EXPECT_EQ(t.InMillisecondsFromNow(), 131 std::numeric_limits<KernelTimeout::DWord>::max()); 132 EXPECT_EQ(t.ToChronoTimePoint(), 133 std::chrono::time_point<std::chrono::system_clock>::max()); 134 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); 135 } 136 137 TEST(KernelTimeout, DefaultConstructor) { 138 // The default constructor is equivalent to absl::InfiniteFuture(). 139 KernelTimeout t; 140 EXPECT_FALSE(t.has_timeout()); 141 // Callers are expected to check has_timeout() instead of using the methods 142 // below, but we do try to do something reasonable if they don't. We may not 143 // be able to round-trip back to absl::InfiniteDuration() or 144 // absl::InfiniteFuture(), but we should return a very large value. 145 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), 146 absl::Now() + absl::Hours(100000)); 147 #ifndef _WIN32 148 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), 149 absl::Now() + absl::Hours(100000)); 150 #endif 151 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), 152 absl::Hours(100000)); 153 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), 154 absl::Now() + absl::Hours(100000)); 155 EXPECT_EQ(t.InMillisecondsFromNow(), 156 std::numeric_limits<KernelTimeout::DWord>::max()); 157 EXPECT_EQ(t.ToChronoTimePoint(), 158 std::chrono::time_point<std::chrono::system_clock>::max()); 159 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); 160 } 161 162 TEST(KernelTimeout, TimeMaxNanos) { 163 // Time >= kMaxNanos should behave as no timeout. 164 KernelTimeout t(absl::FromUnixNanos(std::numeric_limits<int64_t>::max())); 165 EXPECT_FALSE(t.has_timeout()); 166 // Callers are expected to check has_timeout() instead of using the methods 167 // below, but we do try to do something reasonable if they don't. We may not 168 // be able to round-trip back to absl::InfiniteDuration() or 169 // absl::InfiniteFuture(), but we should return a very large value. 170 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), 171 absl::Now() + absl::Hours(100000)); 172 #ifndef _WIN32 173 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), 174 absl::Now() + absl::Hours(100000)); 175 #endif 176 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), 177 absl::Hours(100000)); 178 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), 179 absl::Now() + absl::Hours(100000)); 180 EXPECT_EQ(t.InMillisecondsFromNow(), 181 std::numeric_limits<KernelTimeout::DWord>::max()); 182 EXPECT_EQ(t.ToChronoTimePoint(), 183 std::chrono::time_point<std::chrono::system_clock>::max()); 184 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); 185 } 186 187 TEST(KernelTimeout, Never) { 188 // KernelTimeout::Never() is equivalent to absl::InfiniteFuture(). 189 KernelTimeout t = KernelTimeout::Never(); 190 EXPECT_FALSE(t.has_timeout()); 191 // Callers are expected to check has_timeout() instead of using the methods 192 // below, but we do try to do something reasonable if they don't. We may not 193 // be able to round-trip back to absl::InfiniteDuration() or 194 // absl::InfiniteFuture(), but we should return a very large value. 195 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), 196 absl::Now() + absl::Hours(100000)); 197 #ifndef _WIN32 198 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), 199 absl::Now() + absl::Hours(100000)); 200 #endif 201 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), 202 absl::Hours(100000)); 203 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), 204 absl::Now() + absl::Hours(100000)); 205 EXPECT_EQ(t.InMillisecondsFromNow(), 206 std::numeric_limits<KernelTimeout::DWord>::max()); 207 EXPECT_EQ(t.ToChronoTimePoint(), 208 std::chrono::time_point<std::chrono::system_clock>::max()); 209 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); 210 } 211 212 TEST(KernelTimeout, InfinitePast) { 213 KernelTimeout t(absl::InfinitePast()); 214 EXPECT_TRUE(t.has_timeout()); 215 EXPECT_TRUE(t.is_absolute_timeout()); 216 EXPECT_FALSE(t.is_relative_timeout()); 217 EXPECT_LE(absl::TimeFromTimespec(t.MakeAbsTimespec()), 218 absl::FromUnixNanos(1)); 219 #ifndef _WIN32 220 EXPECT_LE(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), 221 absl::FromUnixSeconds(1)); 222 #endif 223 EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()), 224 absl::ZeroDuration()); 225 EXPECT_LE(absl::FromUnixNanos(t.MakeAbsNanos()), absl::FromUnixNanos(1)); 226 EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0}); 227 EXPECT_LT(t.ToChronoTimePoint(), std::chrono::system_clock::from_time_t(0) + 228 std::chrono::seconds(1)); 229 EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0)); 230 } 231 232 // TODO(b/348224897): re-enabled when the flakiness is fixed. 233 TEST(KernelTimeout, DISABLED_FiniteDurations) { 234 constexpr absl::Duration kDurationsToTest[] = { 235 absl::ZeroDuration(), 236 absl::Nanoseconds(1), 237 absl::Microseconds(1), 238 absl::Milliseconds(1), 239 absl::Seconds(1), 240 absl::Minutes(1), 241 absl::Hours(1), 242 absl::Hours(1000), 243 }; 244 245 for (auto duration : kDurationsToTest) { 246 SCOPED_TRACE(duration); 247 KernelTimeout t(duration); 248 EXPECT_TRUE(t.has_timeout()); 249 EXPECT_FALSE(t.is_absolute_timeout()); 250 EXPECT_TRUE(t.is_relative_timeout()); 251 EXPECT_LE(absl::AbsDuration(absl::Now() + duration - 252 absl::TimeFromTimespec(t.MakeAbsTimespec())), 253 absl::Milliseconds(5)); 254 #ifndef _WIN32 255 EXPECT_LE( 256 absl::AbsDuration(absl::Now() + duration - 257 absl::TimeFromTimespec( 258 t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))), 259 absl::Milliseconds(5)); 260 #endif 261 EXPECT_LE( 262 absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) - 263 duration), 264 kTimingBound); 265 EXPECT_LE(absl::AbsDuration(absl::Now() + duration - 266 absl::FromUnixNanos(t.MakeAbsNanos())), 267 absl::Milliseconds(5)); 268 EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration, 269 absl::Milliseconds(5)); 270 EXPECT_LE(absl::AbsDuration(absl::Now() + duration - 271 absl::FromChrono(t.ToChronoTimePoint())), 272 kTimingBound); 273 EXPECT_LE( 274 absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) - duration), 275 kTimingBound); 276 } 277 } 278 279 // TODO(b/348224897): re-enabled when the flakiness is fixed. 280 TEST(KernelTimeout, DISABLED_NegativeDurations) { 281 constexpr absl::Duration kDurationsToTest[] = { 282 -absl::ZeroDuration(), 283 -absl::Nanoseconds(1), 284 -absl::Microseconds(1), 285 -absl::Milliseconds(1), 286 -absl::Seconds(1), 287 -absl::Minutes(1), 288 -absl::Hours(1), 289 -absl::Hours(1000), 290 -absl::InfiniteDuration(), 291 }; 292 293 for (auto duration : kDurationsToTest) { 294 // Negative durations should all be converted to zero durations or "now". 295 SCOPED_TRACE(duration); 296 KernelTimeout t(duration); 297 EXPECT_TRUE(t.has_timeout()); 298 EXPECT_FALSE(t.is_absolute_timeout()); 299 EXPECT_TRUE(t.is_relative_timeout()); 300 EXPECT_LE(absl::AbsDuration(absl::Now() - 301 absl::TimeFromTimespec(t.MakeAbsTimespec())), 302 absl::Milliseconds(5)); 303 #ifndef _WIN32 304 EXPECT_LE(absl::AbsDuration(absl::Now() - absl::TimeFromTimespec( 305 t.MakeClockAbsoluteTimespec( 306 CLOCK_REALTIME))), 307 absl::Milliseconds(5)); 308 #endif 309 EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()), 310 absl::ZeroDuration()); 311 EXPECT_LE( 312 absl::AbsDuration(absl::Now() - absl::FromUnixNanos(t.MakeAbsNanos())), 313 absl::Milliseconds(5)); 314 EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0}); 315 EXPECT_LE(absl::AbsDuration(absl::Now() - 316 absl::FromChrono(t.ToChronoTimePoint())), 317 absl::Milliseconds(5)); 318 EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0)); 319 } 320 } 321 322 TEST(KernelTimeout, InfiniteDuration) { 323 KernelTimeout t(absl::InfiniteDuration()); 324 EXPECT_FALSE(t.has_timeout()); 325 // Callers are expected to check has_timeout() instead of using the methods 326 // below, but we do try to do something reasonable if they don't. We may not 327 // be able to round-trip back to absl::InfiniteDuration() or 328 // absl::InfiniteFuture(), but we should return a very large value. 329 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), 330 absl::Now() + absl::Hours(100000)); 331 #ifndef _WIN32 332 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), 333 absl::Now() + absl::Hours(100000)); 334 #endif 335 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), 336 absl::Hours(100000)); 337 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), 338 absl::Now() + absl::Hours(100000)); 339 EXPECT_EQ(t.InMillisecondsFromNow(), 340 std::numeric_limits<KernelTimeout::DWord>::max()); 341 EXPECT_EQ(t.ToChronoTimePoint(), 342 std::chrono::time_point<std::chrono::system_clock>::max()); 343 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); 344 } 345 346 TEST(KernelTimeout, DurationMaxNanos) { 347 // Duration >= kMaxNanos should behave as no timeout. 348 KernelTimeout t(absl::Nanoseconds(std::numeric_limits<int64_t>::max())); 349 EXPECT_FALSE(t.has_timeout()); 350 // Callers are expected to check has_timeout() instead of using the methods 351 // below, but we do try to do something reasonable if they don't. We may not 352 // be able to round-trip back to absl::InfiniteDuration() or 353 // absl::InfiniteFuture(), but we should return a very large value. 354 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), 355 absl::Now() + absl::Hours(100000)); 356 #ifndef _WIN32 357 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), 358 absl::Now() + absl::Hours(100000)); 359 #endif 360 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), 361 absl::Hours(100000)); 362 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), 363 absl::Now() + absl::Hours(100000)); 364 EXPECT_EQ(t.InMillisecondsFromNow(), 365 std::numeric_limits<KernelTimeout::DWord>::max()); 366 EXPECT_EQ(t.ToChronoTimePoint(), 367 std::chrono::time_point<std::chrono::system_clock>::max()); 368 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max()); 369 } 370 371 TEST(KernelTimeout, OverflowNanos) { 372 // Test what happens when KernelTimeout is constructed with an absl::Duration 373 // that would overflow now_nanos + duration. 374 int64_t now_nanos = absl::ToUnixNanos(absl::Now()); 375 int64_t limit = std::numeric_limits<int64_t>::max() - now_nanos; 376 absl::Duration duration = absl::Nanoseconds(limit) + absl::Seconds(1); 377 KernelTimeout t(duration); 378 // Timeouts should still be far in the future. 379 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()), 380 absl::Now() + absl::Hours(100000)); 381 #ifndef _WIN32 382 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)), 383 absl::Now() + absl::Hours(100000)); 384 #endif 385 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()), 386 absl::Hours(100000)); 387 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()), 388 absl::Now() + absl::Hours(100000)); 389 EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration, 390 absl::Milliseconds(5)); 391 EXPECT_GT(t.ToChronoTimePoint(), 392 std::chrono::system_clock::now() + std::chrono::hours(100000)); 393 EXPECT_GT(t.ToChronoDuration(), std::chrono::hours(100000)); 394 } 395 396 } // namespace