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