1*cc02d7e2SAndroid Build Coastguard Worker //
2*cc02d7e2SAndroid Build Coastguard Worker //
3*cc02d7e2SAndroid Build Coastguard Worker // Copyright 2019 gRPC authors.
4*cc02d7e2SAndroid Build Coastguard Worker //
5*cc02d7e2SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
6*cc02d7e2SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
7*cc02d7e2SAndroid Build Coastguard Worker // You may obtain a copy of the License at
8*cc02d7e2SAndroid Build Coastguard Worker //
9*cc02d7e2SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
10*cc02d7e2SAndroid Build Coastguard Worker //
11*cc02d7e2SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
12*cc02d7e2SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
13*cc02d7e2SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*cc02d7e2SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
15*cc02d7e2SAndroid Build Coastguard Worker // limitations under the License.
16*cc02d7e2SAndroid Build Coastguard Worker //
17*cc02d7e2SAndroid Build Coastguard Worker //
18*cc02d7e2SAndroid Build Coastguard Worker
19*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/iomgr/timer.h"
20*cc02d7e2SAndroid Build Coastguard Worker
21*cc02d7e2SAndroid Build Coastguard Worker #include <gtest/gtest.h>
22*cc02d7e2SAndroid Build Coastguard Worker
23*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/grpc.h>
24*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/log.h>
25*cc02d7e2SAndroid Build Coastguard Worker
26*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/gprpp/crash.h"
27*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/gprpp/time.h"
28*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/iomgr/closure.h"
29*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/iomgr/error.h"
30*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/iomgr/exec_ctx.h"
31*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/iomgr/timer_manager.h"
32*cc02d7e2SAndroid Build Coastguard Worker #include "test/core/util/test_config.h"
33*cc02d7e2SAndroid Build Coastguard Worker
34*cc02d7e2SAndroid Build Coastguard Worker #ifdef GRPC_POSIX_SOCKET_EV
35*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/iomgr/ev_posix.h"
36*cc02d7e2SAndroid Build Coastguard Worker #endif
37*cc02d7e2SAndroid Build Coastguard Worker
38*cc02d7e2SAndroid Build Coastguard Worker // MAYBE_SKIP_TEST is a macro to determine if this particular test configuration
39*cc02d7e2SAndroid Build Coastguard Worker // should be skipped based on a decision made at SetUp time.
40*cc02d7e2SAndroid Build Coastguard Worker #define MAYBE_SKIP_TEST \
41*cc02d7e2SAndroid Build Coastguard Worker do { \
42*cc02d7e2SAndroid Build Coastguard Worker if (do_not_test_) { \
43*cc02d7e2SAndroid Build Coastguard Worker return; \
44*cc02d7e2SAndroid Build Coastguard Worker } \
45*cc02d7e2SAndroid Build Coastguard Worker } while (0)
46*cc02d7e2SAndroid Build Coastguard Worker
47*cc02d7e2SAndroid Build Coastguard Worker class TimerTest : public ::testing::Test {
48*cc02d7e2SAndroid Build Coastguard Worker protected:
SetUp()49*cc02d7e2SAndroid Build Coastguard Worker void SetUp() override {
50*cc02d7e2SAndroid Build Coastguard Worker grpc_init();
51*cc02d7e2SAndroid Build Coastguard Worker // Skip test if slowdown factor > 1, or we are
52*cc02d7e2SAndroid Build Coastguard Worker // using event manager.
53*cc02d7e2SAndroid Build Coastguard Worker #ifdef GRPC_POSIX_SOCKET_EV
54*cc02d7e2SAndroid Build Coastguard Worker if (grpc_test_slowdown_factor() != 1 ||
55*cc02d7e2SAndroid Build Coastguard Worker grpc_event_engine_run_in_background()) {
56*cc02d7e2SAndroid Build Coastguard Worker #else
57*cc02d7e2SAndroid Build Coastguard Worker if (grpc_test_slowdown_factor() != 1) {
58*cc02d7e2SAndroid Build Coastguard Worker #endif
59*cc02d7e2SAndroid Build Coastguard Worker do_not_test_ = true;
60*cc02d7e2SAndroid Build Coastguard Worker }
61*cc02d7e2SAndroid Build Coastguard Worker }
62*cc02d7e2SAndroid Build Coastguard Worker
63*cc02d7e2SAndroid Build Coastguard Worker void TearDown() override { grpc_shutdown(); }
64*cc02d7e2SAndroid Build Coastguard Worker
65*cc02d7e2SAndroid Build Coastguard Worker bool do_not_test_{false};
66*cc02d7e2SAndroid Build Coastguard Worker };
67*cc02d7e2SAndroid Build Coastguard Worker
68*cc02d7e2SAndroid Build Coastguard Worker #ifndef GPR_WINDOWS
69*cc02d7e2SAndroid Build Coastguard Worker // the test fails with too many wakeups on windows opt build
70*cc02d7e2SAndroid Build Coastguard Worker // the mechanism by which that happens is described in
71*cc02d7e2SAndroid Build Coastguard Worker // https://github.com/grpc/grpc/issues/20436
TEST_F(TimerTest,NoTimers)72*cc02d7e2SAndroid Build Coastguard Worker TEST_F(TimerTest, NoTimers) {
73*cc02d7e2SAndroid Build Coastguard Worker MAYBE_SKIP_TEST;
74*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
75*cc02d7e2SAndroid Build Coastguard Worker gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1500));
76*cc02d7e2SAndroid Build Coastguard Worker
77*cc02d7e2SAndroid Build Coastguard Worker // We expect to get 1 wakeup per second. Sometimes we also get a wakeup
78*cc02d7e2SAndroid Build Coastguard Worker // during initialization, so in 1.5 seconds we expect to get 1 or 2 wakeups.
79*cc02d7e2SAndroid Build Coastguard Worker int64_t wakeups = grpc_timer_manager_get_wakeups_testonly();
80*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(wakeups == 1 || wakeups == 2);
81*cc02d7e2SAndroid Build Coastguard Worker }
82*cc02d7e2SAndroid Build Coastguard Worker #endif
83*cc02d7e2SAndroid Build Coastguard Worker
TEST_F(TimerTest,OneTimerExpires)84*cc02d7e2SAndroid Build Coastguard Worker TEST_F(TimerTest, OneTimerExpires) {
85*cc02d7e2SAndroid Build Coastguard Worker MAYBE_SKIP_TEST;
86*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
87*cc02d7e2SAndroid Build Coastguard Worker grpc_timer timer;
88*cc02d7e2SAndroid Build Coastguard Worker int timer_fired = 0;
89*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_init(
90*cc02d7e2SAndroid Build Coastguard Worker &timer,
91*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Timestamp::Now() + grpc_core::Duration::Milliseconds(500),
92*cc02d7e2SAndroid Build Coastguard Worker GRPC_CLOSURE_CREATE(
93*cc02d7e2SAndroid Build Coastguard Worker [](void* arg, grpc_error_handle) {
94*cc02d7e2SAndroid Build Coastguard Worker int* timer_fired = static_cast<int*>(arg);
95*cc02d7e2SAndroid Build Coastguard Worker ++*timer_fired;
96*cc02d7e2SAndroid Build Coastguard Worker },
97*cc02d7e2SAndroid Build Coastguard Worker &timer_fired, grpc_schedule_on_exec_ctx));
98*cc02d7e2SAndroid Build Coastguard Worker gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1500));
99*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(1 == timer_fired);
100*cc02d7e2SAndroid Build Coastguard Worker
101*cc02d7e2SAndroid Build Coastguard Worker // We expect to get 1 wakeup/second + 1 wakeup for the expired timer + maybe 1
102*cc02d7e2SAndroid Build Coastguard Worker // wakeup during initialization. i.e. in 1.5 seconds we expect 2 or 3 wakeups.
103*cc02d7e2SAndroid Build Coastguard Worker // Actual number of wakeups is more due to bug
104*cc02d7e2SAndroid Build Coastguard Worker // https://github.com/grpc/grpc/issues/19947
105*cc02d7e2SAndroid Build Coastguard Worker int64_t wakeups = grpc_timer_manager_get_wakeups_testonly();
106*cc02d7e2SAndroid Build Coastguard Worker gpr_log(GPR_DEBUG, "wakeups: %" PRId64 "", wakeups);
107*cc02d7e2SAndroid Build Coastguard Worker }
108*cc02d7e2SAndroid Build Coastguard Worker
TEST_F(TimerTest,MultipleTimersExpire)109*cc02d7e2SAndroid Build Coastguard Worker TEST_F(TimerTest, MultipleTimersExpire) {
110*cc02d7e2SAndroid Build Coastguard Worker MAYBE_SKIP_TEST;
111*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
112*cc02d7e2SAndroid Build Coastguard Worker const int kNumTimers = 10;
113*cc02d7e2SAndroid Build Coastguard Worker grpc_timer timers[kNumTimers];
114*cc02d7e2SAndroid Build Coastguard Worker int timer_fired = 0;
115*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kNumTimers; ++i) {
116*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_init(&timers[i],
117*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Timestamp::Now() +
118*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Duration::Milliseconds(500) +
119*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Duration::Milliseconds(i),
120*cc02d7e2SAndroid Build Coastguard Worker GRPC_CLOSURE_CREATE(
121*cc02d7e2SAndroid Build Coastguard Worker [](void* arg, grpc_error_handle) {
122*cc02d7e2SAndroid Build Coastguard Worker int* timer_fired = static_cast<int*>(arg);
123*cc02d7e2SAndroid Build Coastguard Worker ++*timer_fired;
124*cc02d7e2SAndroid Build Coastguard Worker },
125*cc02d7e2SAndroid Build Coastguard Worker &timer_fired, grpc_schedule_on_exec_ctx));
126*cc02d7e2SAndroid Build Coastguard Worker }
127*cc02d7e2SAndroid Build Coastguard Worker
128*cc02d7e2SAndroid Build Coastguard Worker gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1500));
129*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(kNumTimers == timer_fired);
130*cc02d7e2SAndroid Build Coastguard Worker
131*cc02d7e2SAndroid Build Coastguard Worker // We expect to get 1 wakeup/second + 1 wakeup for per timer fired + maybe 1
132*cc02d7e2SAndroid Build Coastguard Worker // wakeup during initialization. i.e. in 1.5 seconds we expect 11 or 12
133*cc02d7e2SAndroid Build Coastguard Worker // wakeups. Actual number of wakeups is more due to bug
134*cc02d7e2SAndroid Build Coastguard Worker // https://github.com/grpc/grpc/issues/19947
135*cc02d7e2SAndroid Build Coastguard Worker int64_t wakeups = grpc_timer_manager_get_wakeups_testonly();
136*cc02d7e2SAndroid Build Coastguard Worker gpr_log(GPR_DEBUG, "wakeups: %" PRId64 "", wakeups);
137*cc02d7e2SAndroid Build Coastguard Worker }
138*cc02d7e2SAndroid Build Coastguard Worker
TEST_F(TimerTest,CancelSomeTimers)139*cc02d7e2SAndroid Build Coastguard Worker TEST_F(TimerTest, CancelSomeTimers) {
140*cc02d7e2SAndroid Build Coastguard Worker MAYBE_SKIP_TEST;
141*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
142*cc02d7e2SAndroid Build Coastguard Worker const int kNumTimers = 10;
143*cc02d7e2SAndroid Build Coastguard Worker grpc_timer timers[kNumTimers];
144*cc02d7e2SAndroid Build Coastguard Worker std::atomic<int> timer_fired{0};
145*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx::Get()->InvalidateNow();
146*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kNumTimers; ++i) {
147*cc02d7e2SAndroid Build Coastguard Worker // Set a large firing time for timers which are bound to be cancelled
148*cc02d7e2SAndroid Build Coastguard Worker // and set a small firing time for timers which need to execute.
149*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_init(
150*cc02d7e2SAndroid Build Coastguard Worker &timers[i],
151*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Timestamp::Now() +
152*cc02d7e2SAndroid Build Coastguard Worker ((i < kNumTimers / 2) ? grpc_core ::Duration::Milliseconds(60000)
153*cc02d7e2SAndroid Build Coastguard Worker : grpc_core ::Duration::Milliseconds(100) +
154*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Duration::Milliseconds(i)),
155*cc02d7e2SAndroid Build Coastguard Worker GRPC_CLOSURE_CREATE(
156*cc02d7e2SAndroid Build Coastguard Worker [](void* arg, grpc_error_handle error) {
157*cc02d7e2SAndroid Build Coastguard Worker if (error == absl::CancelledError()) {
158*cc02d7e2SAndroid Build Coastguard Worker return;
159*cc02d7e2SAndroid Build Coastguard Worker }
160*cc02d7e2SAndroid Build Coastguard Worker std::atomic<int>* timer_fired =
161*cc02d7e2SAndroid Build Coastguard Worker static_cast<std::atomic<int>*>(arg);
162*cc02d7e2SAndroid Build Coastguard Worker ++*timer_fired;
163*cc02d7e2SAndroid Build Coastguard Worker },
164*cc02d7e2SAndroid Build Coastguard Worker &timer_fired, grpc_schedule_on_exec_ctx));
165*cc02d7e2SAndroid Build Coastguard Worker }
166*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kNumTimers / 2; ++i) {
167*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_cancel(&timers[i]);
168*cc02d7e2SAndroid Build Coastguard Worker }
169*cc02d7e2SAndroid Build Coastguard Worker
170*cc02d7e2SAndroid Build Coastguard Worker gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1500));
171*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(kNumTimers / 2 == timer_fired);
172*cc02d7e2SAndroid Build Coastguard Worker
173*cc02d7e2SAndroid Build Coastguard Worker // We expect to get 1 wakeup/second + 1 wakeup per timer fired + maybe 1
174*cc02d7e2SAndroid Build Coastguard Worker // wakeup during initialization. i.e. in 1.5 seconds we expect 6 or 7 wakeups.
175*cc02d7e2SAndroid Build Coastguard Worker // Actual number of wakeups is more due to bug
176*cc02d7e2SAndroid Build Coastguard Worker // https://github.com/grpc/grpc/issues/19947
177*cc02d7e2SAndroid Build Coastguard Worker int64_t wakeups = grpc_timer_manager_get_wakeups_testonly();
178*cc02d7e2SAndroid Build Coastguard Worker gpr_log(GPR_DEBUG, "wakeups: %" PRId64 "", wakeups);
179*cc02d7e2SAndroid Build Coastguard Worker }
180*cc02d7e2SAndroid Build Coastguard Worker
181*cc02d7e2SAndroid Build Coastguard Worker // Enable the following test after
182*cc02d7e2SAndroid Build Coastguard Worker // https://github.com/grpc/grpc/issues/20049 has been fixed.
TEST_F(TimerTest,DISABLED_TimerNotCanceled)183*cc02d7e2SAndroid Build Coastguard Worker TEST_F(TimerTest, DISABLED_TimerNotCanceled) {
184*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
185*cc02d7e2SAndroid Build Coastguard Worker grpc_timer timer;
186*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_init(
187*cc02d7e2SAndroid Build Coastguard Worker &timer, grpc_core::Timestamp::Now() + grpc_core::Duration::Seconds(10),
188*cc02d7e2SAndroid Build Coastguard Worker GRPC_CLOSURE_CREATE([](void*, grpc_error_handle) {}, nullptr,
189*cc02d7e2SAndroid Build Coastguard Worker grpc_schedule_on_exec_ctx));
190*cc02d7e2SAndroid Build Coastguard Worker }
191*cc02d7e2SAndroid Build Coastguard Worker
192*cc02d7e2SAndroid Build Coastguard Worker // Enable the following test after
193*cc02d7e2SAndroid Build Coastguard Worker // https://github.com/grpc/grpc/issues/20064 has been fixed.
TEST_F(TimerTest,DISABLED_CancelRace)194*cc02d7e2SAndroid Build Coastguard Worker TEST_F(TimerTest, DISABLED_CancelRace) {
195*cc02d7e2SAndroid Build Coastguard Worker MAYBE_SKIP_TEST;
196*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
197*cc02d7e2SAndroid Build Coastguard Worker const int kNumTimers = 10;
198*cc02d7e2SAndroid Build Coastguard Worker grpc_timer timers[kNumTimers];
199*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kNumTimers; ++i) {
200*cc02d7e2SAndroid Build Coastguard Worker grpc_timer* arg = (i != 0) ? &timers[i - 1] : nullptr;
201*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_init(
202*cc02d7e2SAndroid Build Coastguard Worker &timers[i],
203*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Timestamp::Now() + grpc_core::Duration::Milliseconds(100),
204*cc02d7e2SAndroid Build Coastguard Worker GRPC_CLOSURE_CREATE(
205*cc02d7e2SAndroid Build Coastguard Worker [](void* arg, grpc_error_handle /*error*/) {
206*cc02d7e2SAndroid Build Coastguard Worker grpc_timer* timer = static_cast<grpc_timer*>(arg);
207*cc02d7e2SAndroid Build Coastguard Worker if (timer) {
208*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_cancel(timer);
209*cc02d7e2SAndroid Build Coastguard Worker }
210*cc02d7e2SAndroid Build Coastguard Worker },
211*cc02d7e2SAndroid Build Coastguard Worker arg, grpc_schedule_on_exec_ctx));
212*cc02d7e2SAndroid Build Coastguard Worker }
213*cc02d7e2SAndroid Build Coastguard Worker gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
214*cc02d7e2SAndroid Build Coastguard Worker }
215*cc02d7e2SAndroid Build Coastguard Worker
216*cc02d7e2SAndroid Build Coastguard Worker // Enable the following test after
217*cc02d7e2SAndroid Build Coastguard Worker // https://github.com/grpc/grpc/issues/20066 has been fixed.
TEST_F(TimerTest,DISABLED_CancelNextTimer)218*cc02d7e2SAndroid Build Coastguard Worker TEST_F(TimerTest, DISABLED_CancelNextTimer) {
219*cc02d7e2SAndroid Build Coastguard Worker MAYBE_SKIP_TEST;
220*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
221*cc02d7e2SAndroid Build Coastguard Worker const int kNumTimers = 10;
222*cc02d7e2SAndroid Build Coastguard Worker grpc_timer timers[kNumTimers];
223*cc02d7e2SAndroid Build Coastguard Worker
224*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kNumTimers; ++i) {
225*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_init_unset(&timers[i]);
226*cc02d7e2SAndroid Build Coastguard Worker }
227*cc02d7e2SAndroid Build Coastguard Worker
228*cc02d7e2SAndroid Build Coastguard Worker for (int i = 0; i < kNumTimers; ++i) {
229*cc02d7e2SAndroid Build Coastguard Worker grpc_timer* arg = nullptr;
230*cc02d7e2SAndroid Build Coastguard Worker if (i < kNumTimers - 1) {
231*cc02d7e2SAndroid Build Coastguard Worker arg = &timers[i + 1];
232*cc02d7e2SAndroid Build Coastguard Worker }
233*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_init(
234*cc02d7e2SAndroid Build Coastguard Worker &timers[i],
235*cc02d7e2SAndroid Build Coastguard Worker grpc_core::Timestamp::Now() + grpc_core::Duration::Milliseconds(100),
236*cc02d7e2SAndroid Build Coastguard Worker GRPC_CLOSURE_CREATE(
237*cc02d7e2SAndroid Build Coastguard Worker [](void* arg, grpc_error_handle /*error*/) {
238*cc02d7e2SAndroid Build Coastguard Worker grpc_timer* timer = static_cast<grpc_timer*>(arg);
239*cc02d7e2SAndroid Build Coastguard Worker if (timer) {
240*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_cancel(timer);
241*cc02d7e2SAndroid Build Coastguard Worker }
242*cc02d7e2SAndroid Build Coastguard Worker },
243*cc02d7e2SAndroid Build Coastguard Worker arg, grpc_schedule_on_exec_ctx));
244*cc02d7e2SAndroid Build Coastguard Worker }
245*cc02d7e2SAndroid Build Coastguard Worker grpc_timer_cancel(&timers[0]);
246*cc02d7e2SAndroid Build Coastguard Worker gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
247*cc02d7e2SAndroid Build Coastguard Worker }
248*cc02d7e2SAndroid Build Coastguard Worker
main(int argc,char ** argv)249*cc02d7e2SAndroid Build Coastguard Worker int main(int argc, char** argv) {
250*cc02d7e2SAndroid Build Coastguard Worker grpc::testing::TestEnvironment env(&argc, argv);
251*cc02d7e2SAndroid Build Coastguard Worker ::testing::InitGoogleTest(&argc, argv);
252*cc02d7e2SAndroid Build Coastguard Worker return RUN_ALL_TESTS();
253*cc02d7e2SAndroid Build Coastguard Worker }
254