• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(KernelTimeout,FiniteTimes)61 TEST(KernelTimeout, FiniteTimes) {
62   constexpr absl::Duration kDurationsToTest[] = {
63     absl::ZeroDuration(),
64     absl::Nanoseconds(1),
65     absl::Microseconds(1),
66     absl::Milliseconds(1),
67     absl::Seconds(1),
68     absl::Minutes(1),
69     absl::Hours(1),
70     absl::Hours(1000),
71     -absl::Nanoseconds(1),
72     -absl::Microseconds(1),
73     -absl::Milliseconds(1),
74     -absl::Seconds(1),
75     -absl::Minutes(1),
76     -absl::Hours(1),
77     -absl::Hours(1000),
78   };
79 
80   for (auto duration : kDurationsToTest) {
81     const absl::Time now = absl::Now();
82     const absl::Time when = now + duration;
83     SCOPED_TRACE(duration);
84     KernelTimeout t(when);
85     EXPECT_TRUE(t.has_timeout());
86     EXPECT_TRUE(t.is_absolute_timeout());
87     EXPECT_FALSE(t.is_relative_timeout());
88     EXPECT_EQ(absl::TimeFromTimespec(t.MakeAbsTimespec()), when);
89 #ifndef _WIN32
90     EXPECT_LE(
91         absl::AbsDuration(absl::Now() + duration -
92                           absl::TimeFromTimespec(
93                               t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))),
94         absl::Milliseconds(10));
95 #endif
96     EXPECT_LE(
97         absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) -
98                           std::max(duration, absl::ZeroDuration())),
99         kTimingBound);
100     EXPECT_EQ(absl::FromUnixNanos(t.MakeAbsNanos()), when);
101     EXPECT_LE(absl::AbsDuration(absl::Milliseconds(t.InMillisecondsFromNow()) -
102                                 std::max(duration, absl::ZeroDuration())),
103               absl::Milliseconds(5));
104     EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoTimePoint()) - when),
105               absl::Microseconds(1));
106     EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) -
107                                 std::max(duration, absl::ZeroDuration())),
108               kTimingBound);
109   }
110 }
111 
TEST(KernelTimeout,InfiniteFuture)112 TEST(KernelTimeout, InfiniteFuture) {
113   KernelTimeout t(absl::InfiniteFuture());
114   EXPECT_FALSE(t.has_timeout());
115   // Callers are expected to check has_timeout() instead of using the methods
116   // below, but we do try to do something reasonable if they don't. We may not
117   // be able to round-trip back to absl::InfiniteDuration() or
118   // absl::InfiniteFuture(), but we should return a very large value.
119   EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
120             absl::Now() + absl::Hours(100000));
121 #ifndef _WIN32
122   EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
123             absl::Now() + absl::Hours(100000));
124 #endif
125   EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
126             absl::Hours(100000));
127   EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
128             absl::Now() + absl::Hours(100000));
129   EXPECT_EQ(t.InMillisecondsFromNow(),
130             std::numeric_limits<KernelTimeout::DWord>::max());
131   EXPECT_EQ(t.ToChronoTimePoint(),
132             std::chrono::time_point<std::chrono::system_clock>::max());
133   EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
134 }
135 
TEST(KernelTimeout,DefaultConstructor)136 TEST(KernelTimeout, DefaultConstructor) {
137   // The default constructor is equivalent to absl::InfiniteFuture().
138   KernelTimeout t;
139   EXPECT_FALSE(t.has_timeout());
140   // Callers are expected to check has_timeout() instead of using the methods
141   // below, but we do try to do something reasonable if they don't. We may not
142   // be able to round-trip back to absl::InfiniteDuration() or
143   // absl::InfiniteFuture(), but we should return a very large value.
144   EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
145             absl::Now() + absl::Hours(100000));
146 #ifndef _WIN32
147   EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
148             absl::Now() + absl::Hours(100000));
149 #endif
150   EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
151             absl::Hours(100000));
152   EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
153             absl::Now() + absl::Hours(100000));
154   EXPECT_EQ(t.InMillisecondsFromNow(),
155             std::numeric_limits<KernelTimeout::DWord>::max());
156   EXPECT_EQ(t.ToChronoTimePoint(),
157             std::chrono::time_point<std::chrono::system_clock>::max());
158   EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
159 }
160 
TEST(KernelTimeout,TimeMaxNanos)161 TEST(KernelTimeout, TimeMaxNanos) {
162   // Time >= kMaxNanos should behave as no timeout.
163   KernelTimeout t(absl::FromUnixNanos(std::numeric_limits<int64_t>::max()));
164   EXPECT_FALSE(t.has_timeout());
165   // Callers are expected to check has_timeout() instead of using the methods
166   // below, but we do try to do something reasonable if they don't. We may not
167   // be able to round-trip back to absl::InfiniteDuration() or
168   // absl::InfiniteFuture(), but we should return a very large value.
169   EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
170             absl::Now() + absl::Hours(100000));
171 #ifndef _WIN32
172   EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
173             absl::Now() + absl::Hours(100000));
174 #endif
175   EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
176             absl::Hours(100000));
177   EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
178             absl::Now() + absl::Hours(100000));
179   EXPECT_EQ(t.InMillisecondsFromNow(),
180             std::numeric_limits<KernelTimeout::DWord>::max());
181   EXPECT_EQ(t.ToChronoTimePoint(),
182             std::chrono::time_point<std::chrono::system_clock>::max());
183   EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
184 }
185 
TEST(KernelTimeout,Never)186 TEST(KernelTimeout, Never) {
187   // KernelTimeout::Never() is equivalent to absl::InfiniteFuture().
188   KernelTimeout t = KernelTimeout::Never();
189   EXPECT_FALSE(t.has_timeout());
190   // Callers are expected to check has_timeout() instead of using the methods
191   // below, but we do try to do something reasonable if they don't. We may not
192   // be able to round-trip back to absl::InfiniteDuration() or
193   // absl::InfiniteFuture(), but we should return a very large value.
194   EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
195             absl::Now() + absl::Hours(100000));
196 #ifndef _WIN32
197   EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
198             absl::Now() + absl::Hours(100000));
199 #endif
200   EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
201             absl::Hours(100000));
202   EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
203             absl::Now() + absl::Hours(100000));
204   EXPECT_EQ(t.InMillisecondsFromNow(),
205             std::numeric_limits<KernelTimeout::DWord>::max());
206   EXPECT_EQ(t.ToChronoTimePoint(),
207             std::chrono::time_point<std::chrono::system_clock>::max());
208   EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
209 }
210 
TEST(KernelTimeout,InfinitePast)211 TEST(KernelTimeout, InfinitePast) {
212   KernelTimeout t(absl::InfinitePast());
213   EXPECT_TRUE(t.has_timeout());
214   EXPECT_TRUE(t.is_absolute_timeout());
215   EXPECT_FALSE(t.is_relative_timeout());
216   EXPECT_LE(absl::TimeFromTimespec(t.MakeAbsTimespec()),
217             absl::FromUnixNanos(1));
218 #ifndef _WIN32
219   EXPECT_LE(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
220             absl::FromUnixSeconds(1));
221 #endif
222   EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
223             absl::ZeroDuration());
224   EXPECT_LE(absl::FromUnixNanos(t.MakeAbsNanos()), absl::FromUnixNanos(1));
225   EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0});
226   EXPECT_LT(t.ToChronoTimePoint(), std::chrono::system_clock::from_time_t(0) +
227                                        std::chrono::seconds(1));
228   EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0));
229 }
230 
TEST(KernelTimeout,FiniteDurations)231 TEST(KernelTimeout, FiniteDurations) {
232   constexpr absl::Duration kDurationsToTest[] = {
233     absl::ZeroDuration(),
234     absl::Nanoseconds(1),
235     absl::Microseconds(1),
236     absl::Milliseconds(1),
237     absl::Seconds(1),
238     absl::Minutes(1),
239     absl::Hours(1),
240     absl::Hours(1000),
241   };
242 
243   for (auto duration : kDurationsToTest) {
244     SCOPED_TRACE(duration);
245     KernelTimeout t(duration);
246     EXPECT_TRUE(t.has_timeout());
247     EXPECT_FALSE(t.is_absolute_timeout());
248     EXPECT_TRUE(t.is_relative_timeout());
249     EXPECT_LE(absl::AbsDuration(absl::Now() + duration -
250                                 absl::TimeFromTimespec(t.MakeAbsTimespec())),
251               absl::Milliseconds(5));
252 #ifndef _WIN32
253     EXPECT_LE(
254         absl::AbsDuration(absl::Now() + duration -
255                           absl::TimeFromTimespec(
256                               t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))),
257         absl::Milliseconds(5));
258 #endif
259     EXPECT_LE(
260         absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) -
261                           duration),
262         kTimingBound);
263     EXPECT_LE(absl::AbsDuration(absl::Now() + duration -
264                                 absl::FromUnixNanos(t.MakeAbsNanos())),
265               absl::Milliseconds(5));
266     EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration,
267               absl::Milliseconds(5));
268     EXPECT_LE(absl::AbsDuration(absl::Now() + duration -
269                                 absl::FromChrono(t.ToChronoTimePoint())),
270               kTimingBound);
271     EXPECT_LE(
272         absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) - duration),
273         kTimingBound);
274   }
275 }
276 
TEST(KernelTimeout,NegativeDurations)277 TEST(KernelTimeout, NegativeDurations) {
278   constexpr absl::Duration kDurationsToTest[] = {
279     -absl::ZeroDuration(),
280     -absl::Nanoseconds(1),
281     -absl::Microseconds(1),
282     -absl::Milliseconds(1),
283     -absl::Seconds(1),
284     -absl::Minutes(1),
285     -absl::Hours(1),
286     -absl::Hours(1000),
287     -absl::InfiniteDuration(),
288   };
289 
290   for (auto duration : kDurationsToTest) {
291     // Negative durations should all be converted to zero durations or "now".
292     SCOPED_TRACE(duration);
293     KernelTimeout t(duration);
294     EXPECT_TRUE(t.has_timeout());
295     EXPECT_FALSE(t.is_absolute_timeout());
296     EXPECT_TRUE(t.is_relative_timeout());
297     EXPECT_LE(absl::AbsDuration(absl::Now() -
298                                 absl::TimeFromTimespec(t.MakeAbsTimespec())),
299               absl::Milliseconds(5));
300 #ifndef _WIN32
301     EXPECT_LE(absl::AbsDuration(absl::Now() - absl::TimeFromTimespec(
302                                                   t.MakeClockAbsoluteTimespec(
303                                                       CLOCK_REALTIME))),
304               absl::Milliseconds(5));
305 #endif
306     EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
307               absl::ZeroDuration());
308     EXPECT_LE(
309         absl::AbsDuration(absl::Now() - absl::FromUnixNanos(t.MakeAbsNanos())),
310         absl::Milliseconds(5));
311     EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0});
312     EXPECT_LE(absl::AbsDuration(absl::Now() -
313                                 absl::FromChrono(t.ToChronoTimePoint())),
314               absl::Milliseconds(5));
315     EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0));
316   }
317 }
318 
TEST(KernelTimeout,InfiniteDuration)319 TEST(KernelTimeout, InfiniteDuration) {
320   KernelTimeout t(absl::InfiniteDuration());
321   EXPECT_FALSE(t.has_timeout());
322   // Callers are expected to check has_timeout() instead of using the methods
323   // below, but we do try to do something reasonable if they don't. We may not
324   // be able to round-trip back to absl::InfiniteDuration() or
325   // absl::InfiniteFuture(), but we should return a very large value.
326   EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
327             absl::Now() + absl::Hours(100000));
328 #ifndef _WIN32
329   EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
330             absl::Now() + absl::Hours(100000));
331 #endif
332   EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
333             absl::Hours(100000));
334   EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
335             absl::Now() + absl::Hours(100000));
336   EXPECT_EQ(t.InMillisecondsFromNow(),
337             std::numeric_limits<KernelTimeout::DWord>::max());
338   EXPECT_EQ(t.ToChronoTimePoint(),
339             std::chrono::time_point<std::chrono::system_clock>::max());
340   EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
341 }
342 
TEST(KernelTimeout,DurationMaxNanos)343 TEST(KernelTimeout, DurationMaxNanos) {
344   // Duration >= kMaxNanos should behave as no timeout.
345   KernelTimeout t(absl::Nanoseconds(std::numeric_limits<int64_t>::max()));
346   EXPECT_FALSE(t.has_timeout());
347   // Callers are expected to check has_timeout() instead of using the methods
348   // below, but we do try to do something reasonable if they don't. We may not
349   // be able to round-trip back to absl::InfiniteDuration() or
350   // absl::InfiniteFuture(), but we should return a very large value.
351   EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
352             absl::Now() + absl::Hours(100000));
353 #ifndef _WIN32
354   EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
355             absl::Now() + absl::Hours(100000));
356 #endif
357   EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
358             absl::Hours(100000));
359   EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
360             absl::Now() + absl::Hours(100000));
361   EXPECT_EQ(t.InMillisecondsFromNow(),
362             std::numeric_limits<KernelTimeout::DWord>::max());
363   EXPECT_EQ(t.ToChronoTimePoint(),
364             std::chrono::time_point<std::chrono::system_clock>::max());
365   EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
366 }
367 
TEST(KernelTimeout,OverflowNanos)368 TEST(KernelTimeout, OverflowNanos) {
369   // Test what happens when KernelTimeout is constructed with an absl::Duration
370   // that would overflow now_nanos + duration.
371   int64_t now_nanos = absl::ToUnixNanos(absl::Now());
372   int64_t limit = std::numeric_limits<int64_t>::max() - now_nanos;
373   absl::Duration duration = absl::Nanoseconds(limit) + absl::Seconds(1);
374   KernelTimeout t(duration);
375   // Timeouts should still be far in the future.
376   EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
377             absl::Now() + absl::Hours(100000));
378 #ifndef _WIN32
379   EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
380             absl::Now() + absl::Hours(100000));
381 #endif
382   EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
383             absl::Hours(100000));
384   EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
385             absl::Now() + absl::Hours(100000));
386   EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration,
387             absl::Milliseconds(5));
388   EXPECT_GT(t.ToChronoTimePoint(),
389             std::chrono::system_clock::now() + std::chrono::hours(100000));
390   EXPECT_GT(t.ToChronoDuration(), std::chrono::hours(100000));
391 }
392 
393 }  // namespace
394