1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker #include "absl/time/clock.h"
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
18*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ALARM)
19*9356374aSAndroid Build Coastguard Worker #include <signal.h>
20*9356374aSAndroid Build Coastguard Worker #include <unistd.h>
21*9356374aSAndroid Build Coastguard Worker #ifdef _AIX
22*9356374aSAndroid Build Coastguard Worker // sig_t is not defined in AIX.
23*9356374aSAndroid Build Coastguard Worker typedef void (*sig_t)(int);
24*9356374aSAndroid Build Coastguard Worker #endif
25*9356374aSAndroid Build Coastguard Worker #elif defined(__linux__) || defined(__APPLE__)
26*9356374aSAndroid Build Coastguard Worker #error all known Linux and Apple targets have alarm
27*9356374aSAndroid Build Coastguard Worker #endif
28*9356374aSAndroid Build Coastguard Worker
29*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
30*9356374aSAndroid Build Coastguard Worker #include "absl/time/time.h"
31*9356374aSAndroid Build Coastguard Worker
32*9356374aSAndroid Build Coastguard Worker namespace {
33*9356374aSAndroid Build Coastguard Worker
TEST(Time,Now)34*9356374aSAndroid Build Coastguard Worker TEST(Time, Now) {
35*9356374aSAndroid Build Coastguard Worker const absl::Time before = absl::FromUnixNanos(absl::GetCurrentTimeNanos());
36*9356374aSAndroid Build Coastguard Worker const absl::Time now = absl::Now();
37*9356374aSAndroid Build Coastguard Worker const absl::Time after = absl::FromUnixNanos(absl::GetCurrentTimeNanos());
38*9356374aSAndroid Build Coastguard Worker EXPECT_GE(now, before);
39*9356374aSAndroid Build Coastguard Worker EXPECT_GE(after, now);
40*9356374aSAndroid Build Coastguard Worker }
41*9356374aSAndroid Build Coastguard Worker
42*9356374aSAndroid Build Coastguard Worker enum class AlarmPolicy { kWithoutAlarm, kWithAlarm };
43*9356374aSAndroid Build Coastguard Worker
44*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ALARM)
45*9356374aSAndroid Build Coastguard Worker bool alarm_handler_invoked = false;
46*9356374aSAndroid Build Coastguard Worker
AlarmHandler(int signo)47*9356374aSAndroid Build Coastguard Worker void AlarmHandler(int signo) {
48*9356374aSAndroid Build Coastguard Worker ASSERT_EQ(signo, SIGALRM);
49*9356374aSAndroid Build Coastguard Worker alarm_handler_invoked = true;
50*9356374aSAndroid Build Coastguard Worker }
51*9356374aSAndroid Build Coastguard Worker #endif
52*9356374aSAndroid Build Coastguard Worker
53*9356374aSAndroid Build Coastguard Worker // Does SleepFor(d) take between lower_bound and upper_bound at least
54*9356374aSAndroid Build Coastguard Worker // once between now and (now + timeout)? If requested (and supported),
55*9356374aSAndroid Build Coastguard Worker // add an alarm for the middle of the sleep period and expect it to fire.
SleepForBounded(absl::Duration d,absl::Duration lower_bound,absl::Duration upper_bound,absl::Duration timeout,AlarmPolicy alarm_policy,int * attempts)56*9356374aSAndroid Build Coastguard Worker bool SleepForBounded(absl::Duration d, absl::Duration lower_bound,
57*9356374aSAndroid Build Coastguard Worker absl::Duration upper_bound, absl::Duration timeout,
58*9356374aSAndroid Build Coastguard Worker AlarmPolicy alarm_policy, int* attempts) {
59*9356374aSAndroid Build Coastguard Worker const absl::Time deadline = absl::Now() + timeout;
60*9356374aSAndroid Build Coastguard Worker while (absl::Now() < deadline) {
61*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ALARM)
62*9356374aSAndroid Build Coastguard Worker sig_t old_alarm = SIG_DFL;
63*9356374aSAndroid Build Coastguard Worker if (alarm_policy == AlarmPolicy::kWithAlarm) {
64*9356374aSAndroid Build Coastguard Worker alarm_handler_invoked = false;
65*9356374aSAndroid Build Coastguard Worker old_alarm = signal(SIGALRM, AlarmHandler);
66*9356374aSAndroid Build Coastguard Worker alarm(absl::ToInt64Seconds(d / 2));
67*9356374aSAndroid Build Coastguard Worker }
68*9356374aSAndroid Build Coastguard Worker #else
69*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(alarm_policy, AlarmPolicy::kWithoutAlarm);
70*9356374aSAndroid Build Coastguard Worker #endif
71*9356374aSAndroid Build Coastguard Worker ++*attempts;
72*9356374aSAndroid Build Coastguard Worker absl::Time start = absl::Now();
73*9356374aSAndroid Build Coastguard Worker absl::SleepFor(d);
74*9356374aSAndroid Build Coastguard Worker absl::Duration actual = absl::Now() - start;
75*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ALARM)
76*9356374aSAndroid Build Coastguard Worker if (alarm_policy == AlarmPolicy::kWithAlarm) {
77*9356374aSAndroid Build Coastguard Worker signal(SIGALRM, old_alarm);
78*9356374aSAndroid Build Coastguard Worker if (!alarm_handler_invoked) continue;
79*9356374aSAndroid Build Coastguard Worker }
80*9356374aSAndroid Build Coastguard Worker #endif
81*9356374aSAndroid Build Coastguard Worker if (lower_bound <= actual && actual <= upper_bound) {
82*9356374aSAndroid Build Coastguard Worker return true; // yes, the SleepFor() was correctly bounded
83*9356374aSAndroid Build Coastguard Worker }
84*9356374aSAndroid Build Coastguard Worker }
85*9356374aSAndroid Build Coastguard Worker return false;
86*9356374aSAndroid Build Coastguard Worker }
87*9356374aSAndroid Build Coastguard Worker
AssertSleepForBounded(absl::Duration d,absl::Duration early,absl::Duration late,absl::Duration timeout,AlarmPolicy alarm_policy)88*9356374aSAndroid Build Coastguard Worker testing::AssertionResult AssertSleepForBounded(absl::Duration d,
89*9356374aSAndroid Build Coastguard Worker absl::Duration early,
90*9356374aSAndroid Build Coastguard Worker absl::Duration late,
91*9356374aSAndroid Build Coastguard Worker absl::Duration timeout,
92*9356374aSAndroid Build Coastguard Worker AlarmPolicy alarm_policy) {
93*9356374aSAndroid Build Coastguard Worker const absl::Duration lower_bound = d - early;
94*9356374aSAndroid Build Coastguard Worker const absl::Duration upper_bound = d + late;
95*9356374aSAndroid Build Coastguard Worker int attempts = 0;
96*9356374aSAndroid Build Coastguard Worker if (SleepForBounded(d, lower_bound, upper_bound, timeout, alarm_policy,
97*9356374aSAndroid Build Coastguard Worker &attempts)) {
98*9356374aSAndroid Build Coastguard Worker return testing::AssertionSuccess();
99*9356374aSAndroid Build Coastguard Worker }
100*9356374aSAndroid Build Coastguard Worker return testing::AssertionFailure()
101*9356374aSAndroid Build Coastguard Worker << "SleepFor(" << d << ") did not return within [" << lower_bound
102*9356374aSAndroid Build Coastguard Worker << ":" << upper_bound << "] in " << attempts << " attempt"
103*9356374aSAndroid Build Coastguard Worker << (attempts == 1 ? "" : "s") << " over " << timeout
104*9356374aSAndroid Build Coastguard Worker << (alarm_policy == AlarmPolicy::kWithAlarm ? " with" : " without")
105*9356374aSAndroid Build Coastguard Worker << " an alarm";
106*9356374aSAndroid Build Coastguard Worker }
107*9356374aSAndroid Build Coastguard Worker
108*9356374aSAndroid Build Coastguard Worker // Tests that SleepFor() returns neither too early nor too late.
TEST(SleepFor,Bounded)109*9356374aSAndroid Build Coastguard Worker TEST(SleepFor, Bounded) {
110*9356374aSAndroid Build Coastguard Worker const absl::Duration d = absl::Milliseconds(2500);
111*9356374aSAndroid Build Coastguard Worker const absl::Duration early = absl::Milliseconds(100);
112*9356374aSAndroid Build Coastguard Worker const absl::Duration late = absl::Milliseconds(300);
113*9356374aSAndroid Build Coastguard Worker const absl::Duration timeout = 48 * d;
114*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(AssertSleepForBounded(d, early, late, timeout,
115*9356374aSAndroid Build Coastguard Worker AlarmPolicy::kWithoutAlarm));
116*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_ALARM)
117*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(AssertSleepForBounded(d, early, late, timeout,
118*9356374aSAndroid Build Coastguard Worker AlarmPolicy::kWithAlarm));
119*9356374aSAndroid Build Coastguard Worker #endif
120*9356374aSAndroid Build Coastguard Worker }
121*9356374aSAndroid Build Coastguard Worker
122*9356374aSAndroid Build Coastguard Worker } // namespace
123