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
clock_gettime(clockid_t c,struct timespec * ts)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.
TEST(KernelTimeout,DISABLED_FiniteTimes)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
TEST(KernelTimeout,InfiniteFuture)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
TEST(KernelTimeout,DefaultConstructor)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
TEST(KernelTimeout,TimeMaxNanos)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
TEST(KernelTimeout,Never)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
TEST(KernelTimeout,InfinitePast)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.
TEST(KernelTimeout,DISABLED_FiniteDurations)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.
TEST(KernelTimeout,DISABLED_NegativeDurations)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
TEST(KernelTimeout,InfiniteDuration)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
TEST(KernelTimeout,DurationMaxNanos)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
TEST(KernelTimeout,OverflowNanos)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
397