xref: /aosp_15_r20/external/abseil-cpp/absl/synchronization/internal/kernel_timeout_test.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
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