1 // Copyright 2023 gRPC 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 // http://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 "src/core/ext/transport/chttp2/transport/ping_callbacks.h"
16
17 #include <chrono>
18
19 #include "absl/random/random.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22
23 #include "src/core/lib/gprpp/crash.h"
24 #include "test/core/event_engine/mock_event_engine.h"
25
26 using grpc_event_engine::experimental::EventEngine;
27 using grpc_event_engine::experimental::MockEventEngine;
28 using testing::_;
29 using testing::Matcher;
30 using testing::Return;
31 using testing::StrictMock;
32
33 namespace grpc_core {
34 namespace {
35
TEST(PingCallbacksTest,RequestPingRequestsPing)36 TEST(PingCallbacksTest, RequestPingRequestsPing) {
37 Chttp2PingCallbacks callbacks;
38 EXPECT_FALSE(callbacks.ping_requested());
39 callbacks.RequestPing();
40 EXPECT_TRUE(callbacks.ping_requested());
41 }
42
TEST(PingCallbacksTest,OnPingRequestsPing)43 TEST(PingCallbacksTest, OnPingRequestsPing) {
44 Chttp2PingCallbacks callbacks;
45 EXPECT_FALSE(callbacks.ping_requested());
46 callbacks.OnPing([] {}, [] {});
47 EXPECT_TRUE(callbacks.ping_requested());
48 }
49
TEST(PingCallbacksTest,OnPingAckRequestsPing)50 TEST(PingCallbacksTest, OnPingAckRequestsPing) {
51 Chttp2PingCallbacks callbacks;
52 EXPECT_FALSE(callbacks.ping_requested());
53 callbacks.OnPingAck([] {});
54 EXPECT_TRUE(callbacks.ping_requested());
55 }
56
TEST(PingCallbacksTest,PingAckBeforeTimerStarted)57 TEST(PingCallbacksTest, PingAckBeforeTimerStarted) {
58 StrictMock<MockEventEngine> event_engine;
59 absl::BitGen bitgen;
60 Chttp2PingCallbacks callbacks;
61 bool started = false;
62 bool acked = false;
63 EXPECT_FALSE(callbacks.ping_requested());
64 EXPECT_FALSE(callbacks.started_new_ping_without_setting_timeout());
65 // Request ping
66 callbacks.OnPing(
67 [&started] {
68 EXPECT_FALSE(started);
69 started = true;
70 },
71 [&acked] {
72 EXPECT_FALSE(acked);
73 acked = true;
74 });
75 EXPECT_TRUE(callbacks.ping_requested());
76 EXPECT_FALSE(callbacks.started_new_ping_without_setting_timeout());
77 EXPECT_EQ(callbacks.pings_inflight(), 0);
78 EXPECT_FALSE(started);
79 EXPECT_FALSE(acked);
80 auto id = callbacks.StartPing(bitgen);
81 EXPECT_TRUE(callbacks.started_new_ping_without_setting_timeout());
82 EXPECT_FALSE(callbacks.ping_requested());
83 EXPECT_EQ(callbacks.pings_inflight(), 1);
84 EXPECT_TRUE(started);
85 EXPECT_FALSE(acked);
86 callbacks.AckPing(id, &event_engine);
87 EXPECT_TRUE(callbacks.started_new_ping_without_setting_timeout());
88 EXPECT_FALSE(callbacks.ping_requested());
89 EXPECT_EQ(callbacks.pings_inflight(), 0);
90 EXPECT_TRUE(started);
91 EXPECT_TRUE(acked);
92 callbacks.OnPingTimeout(Duration::Milliseconds(1), &event_engine,
93 [] { Crash("should never reach here"); });
94 }
95
TEST(PingCallbacksTest,PingRoundtrips)96 TEST(PingCallbacksTest, PingRoundtrips) {
97 StrictMock<MockEventEngine> event_engine;
98 absl::BitGen bitgen;
99 Chttp2PingCallbacks callbacks;
100 bool started = false;
101 bool acked = false;
102 EXPECT_FALSE(callbacks.ping_requested());
103 // Request ping
104 callbacks.OnPing(
105 [&started] {
106 EXPECT_FALSE(started);
107 started = true;
108 },
109 [&acked] {
110 EXPECT_FALSE(acked);
111 acked = true;
112 });
113 EXPECT_TRUE(callbacks.ping_requested());
114 EXPECT_EQ(callbacks.pings_inflight(), 0);
115 EXPECT_FALSE(started);
116 EXPECT_FALSE(acked);
117 // Start ping should call the start methods, set a timeout, and clear the
118 // request
119 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
120 Matcher<absl::AnyInvocable<void()>>(_)))
121 .WillOnce([]() {
122 return EventEngine::TaskHandle{123, 456};
123 });
124 auto id = callbacks.StartPing(bitgen);
125 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
126 [] { Crash("should not reach here"); });
127 EXPECT_FALSE(callbacks.ping_requested());
128 EXPECT_EQ(callbacks.pings_inflight(), 1);
129 EXPECT_TRUE(started);
130 EXPECT_FALSE(acked);
131 // Ack should cancel the timeout
132 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 456}))
133 .WillOnce(Return(true));
134 EXPECT_TRUE(callbacks.AckPing(id, &event_engine));
135 EXPECT_EQ(callbacks.pings_inflight(), 0);
136 EXPECT_FALSE(callbacks.ping_requested());
137 EXPECT_TRUE(started);
138 EXPECT_TRUE(acked);
139 }
140
TEST(PingCallbacksTest,PingRoundtripsWithInfiniteTimeout)141 TEST(PingCallbacksTest, PingRoundtripsWithInfiniteTimeout) {
142 StrictMock<MockEventEngine> event_engine;
143 absl::BitGen bitgen;
144 Chttp2PingCallbacks callbacks;
145 bool started = false;
146 bool acked = false;
147 EXPECT_FALSE(callbacks.ping_requested());
148 // Request ping
149 callbacks.OnPing(
150 [&started] {
151 EXPECT_FALSE(started);
152 started = true;
153 },
154 [&acked] {
155 EXPECT_FALSE(acked);
156 acked = true;
157 });
158 EXPECT_TRUE(callbacks.ping_requested());
159 EXPECT_EQ(callbacks.pings_inflight(), 0);
160 EXPECT_FALSE(started);
161 EXPECT_FALSE(acked);
162 auto id = callbacks.StartPing(bitgen);
163 EXPECT_FALSE(callbacks.ping_requested());
164 EXPECT_EQ(callbacks.pings_inflight(), 1);
165 EXPECT_TRUE(started);
166 EXPECT_FALSE(acked);
167 EXPECT_TRUE(callbacks.AckPing(id, &event_engine));
168 EXPECT_EQ(callbacks.pings_inflight(), 0);
169 EXPECT_FALSE(callbacks.ping_requested());
170 EXPECT_TRUE(started);
171 EXPECT_TRUE(acked);
172 }
173
TEST(PingCallbacksTest,InvalidPingIdFlagsError)174 TEST(PingCallbacksTest, InvalidPingIdFlagsError) {
175 StrictMock<MockEventEngine> event_engine;
176 Chttp2PingCallbacks callbacks;
177 EXPECT_FALSE(callbacks.AckPing(1234, &event_engine));
178 }
179
TEST(PingCallbacksTest,DuplicatePingIdFlagsError)180 TEST(PingCallbacksTest, DuplicatePingIdFlagsError) {
181 StrictMock<MockEventEngine> event_engine;
182 absl::BitGen bitgen;
183 Chttp2PingCallbacks callbacks;
184 bool started = false;
185 bool acked = false;
186 EXPECT_FALSE(callbacks.ping_requested());
187 callbacks.OnPing(
188 [&started] {
189 EXPECT_FALSE(started);
190 started = true;
191 },
192 [&acked] {
193 EXPECT_FALSE(acked);
194 acked = true;
195 });
196 EXPECT_TRUE(callbacks.ping_requested());
197 EXPECT_FALSE(started);
198 EXPECT_FALSE(acked);
199 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
200 Matcher<absl::AnyInvocable<void()>>(_)))
201 .WillOnce([]() {
202 return EventEngine::TaskHandle{123, 456};
203 });
204 auto id = callbacks.StartPing(bitgen);
205 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
206 [] { Crash("should not reach here"); });
207 EXPECT_FALSE(callbacks.ping_requested());
208 EXPECT_TRUE(started);
209 EXPECT_FALSE(acked);
210 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 456}))
211 .WillOnce(Return(true));
212 EXPECT_TRUE(callbacks.AckPing(id, &event_engine));
213 EXPECT_FALSE(callbacks.ping_requested());
214 EXPECT_TRUE(started);
215 EXPECT_TRUE(acked);
216 // Second ping ack on the same id should fail
217 EXPECT_FALSE(callbacks.AckPing(id, &event_engine));
218 }
219
TEST(PingCallbacksTest,OnPingAckCanPiggybackInflightPings)220 TEST(PingCallbacksTest, OnPingAckCanPiggybackInflightPings) {
221 StrictMock<MockEventEngine> event_engine;
222 absl::BitGen bitgen;
223 Chttp2PingCallbacks callbacks;
224 bool started = false;
225 bool acked_first = false;
226 bool acked_second = false;
227 EXPECT_FALSE(callbacks.ping_requested());
228 callbacks.OnPing(
229 [&started] {
230 EXPECT_FALSE(started);
231 started = true;
232 },
233 [&acked_first] {
234 EXPECT_FALSE(acked_first);
235 acked_first = true;
236 });
237 EXPECT_TRUE(callbacks.ping_requested());
238 EXPECT_FALSE(started);
239 EXPECT_FALSE(acked_first);
240 EXPECT_FALSE(acked_second);
241 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
242 Matcher<absl::AnyInvocable<void()>>(_)))
243 .WillOnce([]() {
244 return EventEngine::TaskHandle{123, 456};
245 });
246 auto id = callbacks.StartPing(bitgen);
247 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
248 [] { Crash("should not reach here"); });
249 EXPECT_FALSE(callbacks.ping_requested());
250 EXPECT_TRUE(started);
251 EXPECT_FALSE(acked_first);
252 EXPECT_FALSE(acked_second);
253 callbacks.OnPingAck([&acked_second] {
254 EXPECT_FALSE(acked_second);
255 acked_second = true;
256 });
257 EXPECT_FALSE(callbacks.ping_requested());
258 EXPECT_TRUE(started);
259 EXPECT_FALSE(acked_first);
260 EXPECT_FALSE(acked_second);
261 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 456}))
262 .WillOnce(Return(true));
263 EXPECT_TRUE(callbacks.AckPing(id, &event_engine));
264 EXPECT_FALSE(callbacks.ping_requested());
265 EXPECT_TRUE(started);
266 EXPECT_TRUE(acked_first);
267 EXPECT_TRUE(acked_second);
268 }
269
TEST(PingCallbacksTest,PingAckRoundtrips)270 TEST(PingCallbacksTest, PingAckRoundtrips) {
271 StrictMock<MockEventEngine> event_engine;
272 absl::BitGen bitgen;
273 Chttp2PingCallbacks callbacks;
274 bool acked = false;
275 EXPECT_FALSE(callbacks.ping_requested());
276 callbacks.OnPingAck([&acked] {
277 EXPECT_FALSE(acked);
278 acked = true;
279 });
280 EXPECT_TRUE(callbacks.ping_requested());
281 EXPECT_FALSE(acked);
282 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
283 Matcher<absl::AnyInvocable<void()>>(_)))
284 .WillOnce([]() {
285 return EventEngine::TaskHandle{123, 456};
286 });
287 auto id = callbacks.StartPing(bitgen);
288 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
289 [] { Crash("should not reach here"); });
290 EXPECT_FALSE(callbacks.ping_requested());
291 EXPECT_FALSE(acked);
292 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 456}))
293 .WillOnce(Return(true));
294 EXPECT_TRUE(callbacks.AckPing(id, &event_engine));
295 EXPECT_FALSE(callbacks.ping_requested());
296 EXPECT_TRUE(acked);
297 }
298
TEST(PingCallbacksTest,MultiPingRoundtrips)299 TEST(PingCallbacksTest, MultiPingRoundtrips) {
300 StrictMock<MockEventEngine> event_engine;
301 absl::BitGen bitgen;
302 Chttp2PingCallbacks callbacks;
303 bool started1 = false;
304 bool acked1 = false;
305 bool started2 = false;
306 bool acked2 = false;
307 EXPECT_FALSE(callbacks.ping_requested());
308 callbacks.OnPing(
309 [&started1] {
310 EXPECT_FALSE(started1);
311 started1 = true;
312 },
313 [&acked1] {
314 EXPECT_FALSE(acked1);
315 acked1 = true;
316 });
317 EXPECT_TRUE(callbacks.ping_requested());
318 EXPECT_FALSE(started1);
319 EXPECT_FALSE(acked1);
320 EXPECT_FALSE(started2);
321 EXPECT_FALSE(acked2);
322 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
323 Matcher<absl::AnyInvocable<void()>>(_)))
324 .WillOnce([]() {
325 return EventEngine::TaskHandle{123, 456};
326 });
327 auto id1 = callbacks.StartPing(bitgen);
328 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
329 [] { Crash("should not reach here"); });
330 EXPECT_FALSE(callbacks.ping_requested());
331 EXPECT_TRUE(started1);
332 EXPECT_FALSE(acked1);
333 EXPECT_FALSE(started2);
334 EXPECT_FALSE(acked2);
335 callbacks.OnPing(
336 [&started2] {
337 EXPECT_FALSE(started2);
338 started2 = true;
339 },
340 [&acked2] {
341 EXPECT_FALSE(acked2);
342 acked2 = true;
343 });
344 EXPECT_TRUE(callbacks.ping_requested());
345 EXPECT_TRUE(started1);
346 EXPECT_FALSE(acked1);
347 EXPECT_FALSE(started2);
348 EXPECT_FALSE(acked2);
349 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
350 Matcher<absl::AnyInvocable<void()>>(_)))
351 .WillOnce([]() {
352 return EventEngine::TaskHandle{123, 789};
353 });
354 auto id2 = callbacks.StartPing(bitgen);
355 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
356 [] { Crash("should not reach here"); });
357 EXPECT_NE(id1, id2);
358 EXPECT_TRUE(started1);
359 EXPECT_FALSE(acked1);
360 EXPECT_TRUE(started2);
361 EXPECT_FALSE(acked2);
362 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 456}))
363 .WillOnce(Return(true));
364 EXPECT_TRUE(callbacks.AckPing(id1, &event_engine));
365 EXPECT_FALSE(callbacks.ping_requested());
366 EXPECT_TRUE(started1);
367 EXPECT_TRUE(acked1);
368 EXPECT_TRUE(started2);
369 EXPECT_FALSE(acked2);
370 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 789}))
371 .WillOnce(Return(true));
372 EXPECT_TRUE(callbacks.AckPing(id2, &event_engine));
373 EXPECT_FALSE(callbacks.ping_requested());
374 EXPECT_TRUE(started1);
375 EXPECT_TRUE(acked1);
376 EXPECT_TRUE(started2);
377 EXPECT_TRUE(acked2);
378 }
379
TEST(PingCallbacksTest,MultiPingRoundtripsWithOutOfOrderAcks)380 TEST(PingCallbacksTest, MultiPingRoundtripsWithOutOfOrderAcks) {
381 StrictMock<MockEventEngine> event_engine;
382 absl::BitGen bitgen;
383 Chttp2PingCallbacks callbacks;
384 bool started1 = false;
385 bool acked1 = false;
386 bool started2 = false;
387 bool acked2 = false;
388 EXPECT_FALSE(callbacks.ping_requested());
389 callbacks.OnPing(
390 [&started1] {
391 EXPECT_FALSE(started1);
392 started1 = true;
393 },
394 [&acked1] {
395 EXPECT_FALSE(acked1);
396 acked1 = true;
397 });
398 EXPECT_TRUE(callbacks.ping_requested());
399 EXPECT_FALSE(started1);
400 EXPECT_FALSE(acked1);
401 EXPECT_FALSE(started2);
402 EXPECT_FALSE(acked2);
403 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
404 Matcher<absl::AnyInvocable<void()>>(_)))
405 .WillOnce([]() {
406 return EventEngine::TaskHandle{123, 456};
407 });
408 auto id1 = callbacks.StartPing(bitgen);
409 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
410 [] { Crash("should not reach here"); });
411 EXPECT_FALSE(callbacks.ping_requested());
412 EXPECT_TRUE(started1);
413 EXPECT_FALSE(acked1);
414 EXPECT_FALSE(started2);
415 EXPECT_FALSE(acked2);
416 callbacks.OnPing(
417 [&started2] {
418 EXPECT_FALSE(started2);
419 started2 = true;
420 },
421 [&acked2] {
422 EXPECT_FALSE(acked2);
423 acked2 = true;
424 });
425 EXPECT_TRUE(callbacks.ping_requested());
426 EXPECT_TRUE(started1);
427 EXPECT_FALSE(acked1);
428 EXPECT_FALSE(started2);
429 EXPECT_FALSE(acked2);
430 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
431 Matcher<absl::AnyInvocable<void()>>(_)))
432 .WillOnce([]() {
433 return EventEngine::TaskHandle{123, 789};
434 });
435 auto id2 = callbacks.StartPing(bitgen);
436 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
437 [] { Crash("should not reach here"); });
438 EXPECT_NE(id1, id2);
439 EXPECT_TRUE(started1);
440 EXPECT_FALSE(acked1);
441 EXPECT_TRUE(started2);
442 EXPECT_FALSE(acked2);
443 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 789}))
444 .WillOnce(Return(true));
445 EXPECT_TRUE(callbacks.AckPing(id2, &event_engine));
446 EXPECT_FALSE(callbacks.ping_requested());
447 EXPECT_TRUE(started1);
448 EXPECT_FALSE(acked1);
449 EXPECT_TRUE(started2);
450 EXPECT_TRUE(acked2);
451 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 456}))
452 .WillOnce(Return(true));
453 EXPECT_TRUE(callbacks.AckPing(id1, &event_engine));
454 EXPECT_FALSE(callbacks.ping_requested());
455 EXPECT_TRUE(started1);
456 EXPECT_TRUE(acked1);
457 EXPECT_TRUE(started2);
458 EXPECT_TRUE(acked2);
459 }
460
TEST(PingCallbacksTest,CoalescedPingsRoundtrip)461 TEST(PingCallbacksTest, CoalescedPingsRoundtrip) {
462 StrictMock<MockEventEngine> event_engine;
463 absl::BitGen bitgen;
464 Chttp2PingCallbacks callbacks;
465 bool started1 = false;
466 bool acked1 = false;
467 bool started2 = false;
468 bool acked2 = false;
469 EXPECT_FALSE(callbacks.ping_requested());
470 callbacks.OnPing(
471 [&started1] {
472 EXPECT_FALSE(started1);
473 started1 = true;
474 },
475 [&acked1] {
476 EXPECT_FALSE(acked1);
477 acked1 = true;
478 });
479 callbacks.OnPing(
480 [&started2] {
481 EXPECT_FALSE(started2);
482 started2 = true;
483 },
484 [&acked2] {
485 EXPECT_FALSE(acked2);
486 acked2 = true;
487 });
488 EXPECT_TRUE(callbacks.ping_requested());
489 EXPECT_FALSE(started1);
490 EXPECT_FALSE(acked1);
491 EXPECT_FALSE(started2);
492 EXPECT_FALSE(acked2);
493 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
494 Matcher<absl::AnyInvocable<void()>>(_)))
495 .WillOnce([]() {
496 return EventEngine::TaskHandle{123, 456};
497 });
498 auto id = callbacks.StartPing(bitgen);
499 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
500 [] { Crash("should not reach here"); });
501 EXPECT_FALSE(callbacks.ping_requested());
502 EXPECT_TRUE(started1);
503 EXPECT_FALSE(acked1);
504 EXPECT_TRUE(started2);
505 EXPECT_FALSE(acked2);
506 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 456}))
507 .WillOnce(Return(true));
508 EXPECT_TRUE(callbacks.AckPing(id, &event_engine));
509 EXPECT_FALSE(callbacks.ping_requested());
510 EXPECT_TRUE(started1);
511 EXPECT_TRUE(acked1);
512 EXPECT_TRUE(started2);
513 EXPECT_TRUE(acked2);
514 }
515
TEST(PingCallbacksTest,CancelAllCancelsCallbacks)516 TEST(PingCallbacksTest, CancelAllCancelsCallbacks) {
517 StrictMock<MockEventEngine> event_engine;
518 absl::BitGen bitgen;
519 Chttp2PingCallbacks callbacks;
520 bool started = false;
521 bool acked = false;
522 EXPECT_FALSE(callbacks.ping_requested());
523 callbacks.OnPing(
524 [&started] {
525 EXPECT_FALSE(started);
526 started = true;
527 },
528 [&acked] {
529 EXPECT_FALSE(acked);
530 acked = true;
531 });
532 EXPECT_TRUE(callbacks.ping_requested());
533 callbacks.CancelAll(&event_engine);
534 EXPECT_FALSE(started);
535 EXPECT_FALSE(acked);
536 EXPECT_FALSE(callbacks.ping_requested());
537 // Can still send a ping, no callback should be invoked
538 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
539 Matcher<absl::AnyInvocable<void()>>(_)))
540 .WillOnce([]() {
541 return EventEngine::TaskHandle{123, 456};
542 });
543 auto id = callbacks.StartPing(bitgen);
544 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
545 [] { Crash("should not reach here"); });
546 EXPECT_FALSE(started);
547 EXPECT_FALSE(acked);
548 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 456}))
549 .WillOnce(Return(true));
550 EXPECT_TRUE(callbacks.AckPing(id, &event_engine));
551 EXPECT_FALSE(started);
552 EXPECT_FALSE(acked);
553 EXPECT_FALSE(callbacks.ping_requested());
554 }
555
TEST(PingCallbacksTest,CancelAllCancelsInflightPings)556 TEST(PingCallbacksTest, CancelAllCancelsInflightPings) {
557 StrictMock<MockEventEngine> event_engine;
558 absl::BitGen bitgen;
559 Chttp2PingCallbacks callbacks;
560 bool started = false;
561 bool acked = false;
562 EXPECT_FALSE(callbacks.ping_requested());
563 callbacks.OnPing(
564 [&started] {
565 EXPECT_FALSE(started);
566 started = true;
567 },
568 [&acked] {
569 EXPECT_FALSE(acked);
570 acked = true;
571 });
572 EXPECT_TRUE(callbacks.ping_requested());
573 EXPECT_FALSE(started);
574 EXPECT_FALSE(acked);
575 EXPECT_CALL(event_engine, RunAfter(EventEngine::Duration(Duration::Hours(24)),
576 Matcher<absl::AnyInvocable<void()>>(_)))
577 .WillOnce([]() {
578 return EventEngine::TaskHandle{123, 456};
579 });
580 auto id = callbacks.StartPing(bitgen);
581 callbacks.OnPingTimeout(Duration::Hours(24), &event_engine,
582 [] { Crash("should not reach here"); });
583 EXPECT_FALSE(callbacks.ping_requested());
584 EXPECT_TRUE(started);
585 EXPECT_FALSE(acked);
586 EXPECT_CALL(event_engine, Cancel(EventEngine::TaskHandle{123, 456}))
587 .WillOnce(Return(true));
588 callbacks.CancelAll(&event_engine);
589 // Ensure Cancel call comes from CancelAll
590 ::testing::Mock::VerifyAndClearExpectations(&event_engine);
591 EXPECT_FALSE(acked);
592 EXPECT_FALSE(callbacks.ping_requested());
593 // Ping should still be valid, but no callback should be invoked
594 EXPECT_TRUE(callbacks.AckPing(id, &event_engine));
595 EXPECT_FALSE(acked);
596 EXPECT_FALSE(callbacks.ping_requested());
597 }
598
599 } // namespace
600 } // namespace grpc_core
601
main(int argc,char ** argv)602 int main(int argc, char** argv) {
603 ::testing::InitGoogleTest(&argc, argv);
604 return RUN_ALL_TESTS();
605 }
606