xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/io/quic_all_event_loops_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // A universal test for all event loops supported by the build of QUICHE in
6 // question.
7 //
8 // This test is very similar to QuicPollEventLoopTest, however, there are some
9 // notable differences:
10 //   (1) This test uses the real clock, since the event loop implementation may
11 //       not support accepting a mock clock.
12 //   (2) This test covers both level-triggered and edge-triggered event loops.
13 
14 #include <fcntl.h>
15 #include <unistd.h>
16 
17 #include "absl/cleanup/cleanup.h"
18 #include "absl/memory/memory.h"
19 #include "absl/strings/string_view.h"
20 #include "quiche/quic/core/io/quic_default_event_loop.h"
21 #include "quiche/quic/core/io/quic_event_loop.h"
22 #include "quiche/quic/core/quic_alarm.h"
23 #include "quiche/quic/core/quic_alarm_factory.h"
24 #include "quiche/quic/core/quic_default_clock.h"
25 #include "quiche/quic/core/quic_time.h"
26 #include "quiche/quic/platform/api/quic_test.h"
27 #include "quiche/quic/test_tools/quic_test_utils.h"
28 
29 namespace quic::test {
30 namespace {
31 
32 using testing::_;
33 using testing::AtMost;
34 
35 MATCHER_P(HasFlagSet, value, "Checks a flag in a bit mask") {
36   return (arg & value) != 0;
37 }
38 
39 constexpr QuicSocketEventMask kAllEvents =
40     kSocketEventReadable | kSocketEventWritable | kSocketEventError;
41 
42 class MockQuicSocketEventListener : public QuicSocketEventListener {
43  public:
44   MOCK_METHOD(void, OnSocketEvent,
45               (QuicEventLoop* /*event_loop*/, SocketFd /*fd*/,
46                QuicSocketEventMask /*events*/),
47               (override));
48 };
49 
50 class MockDelegate : public QuicAlarm::Delegate {
51  public:
GetConnectionContext()52   QuicConnectionContext* GetConnectionContext() override { return nullptr; }
53   MOCK_METHOD(void, OnAlarm, (), (override));
54 };
55 
SetNonBlocking(int fd)56 void SetNonBlocking(int fd) {
57   QUICHE_CHECK(::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK) == 0)
58       << "Failed to mark FD non-blocking, errno: " << errno;
59 }
60 
61 class QuicEventLoopFactoryTest
62     : public QuicTestWithParam<QuicEventLoopFactory*> {
63  public:
SetUp()64   void SetUp() override {
65     loop_ = GetParam()->Create(&clock_);
66     factory_ = loop_->CreateAlarmFactory();
67     int fds[2];
68     int result = ::pipe(fds);
69     QUICHE_CHECK(result >= 0) << "Failed to create a pipe, errno: " << errno;
70     read_fd_ = fds[0];
71     write_fd_ = fds[1];
72 
73     SetNonBlocking(read_fd_);
74     SetNonBlocking(write_fd_);
75   }
76 
TearDown()77   void TearDown() override {
78     factory_.reset();
79     loop_.reset();
80     // Epoll-based event loop automatically removes registered FDs from the
81     // Epoll set, which should happen before these FDs are closed.
82     close(read_fd_);
83     close(write_fd_);
84   }
85 
CreateAlarm()86   std::pair<std::unique_ptr<QuicAlarm>, MockDelegate*> CreateAlarm() {
87     auto delegate = std::make_unique<testing::StrictMock<MockDelegate>>();
88     MockDelegate* delegate_unowned = delegate.get();
89     auto alarm = absl::WrapUnique(factory_->CreateAlarm(delegate.release()));
90     return std::make_pair(std::move(alarm), delegate_unowned);
91   }
92 
93   template <typename Condition>
RunEventLoopUntil(Condition condition,QuicTime::Delta timeout)94   void RunEventLoopUntil(Condition condition, QuicTime::Delta timeout) {
95     const QuicTime end = clock_.Now() + timeout;
96     while (!condition() && clock_.Now() < end) {
97       loop_->RunEventLoopOnce(end - clock_.Now());
98     }
99   }
100 
101  protected:
102   QuicDefaultClock clock_;
103   std::unique_ptr<QuicEventLoop> loop_;
104   std::unique_ptr<QuicAlarmFactory> factory_;
105   int read_fd_;
106   int write_fd_;
107 };
108 
GetTestParamName(::testing::TestParamInfo<QuicEventLoopFactory * > info)109 std::string GetTestParamName(
110     ::testing::TestParamInfo<QuicEventLoopFactory*> info) {
111   return EscapeTestParamName(info.param->GetName());
112 }
113 
114 INSTANTIATE_TEST_SUITE_P(QuicEventLoopFactoryTests, QuicEventLoopFactoryTest,
115                          ::testing::ValuesIn(GetAllSupportedEventLoops()),
116                          GetTestParamName);
117 
TEST_P(QuicEventLoopFactoryTest,NothingHappens)118 TEST_P(QuicEventLoopFactoryTest, NothingHappens) {
119   testing::StrictMock<MockQuicSocketEventListener> listener;
120   ASSERT_TRUE(loop_->RegisterSocket(read_fd_, kAllEvents, &listener));
121   ASSERT_TRUE(loop_->RegisterSocket(write_fd_, kAllEvents, &listener));
122 
123   // Attempt double-registration.
124   EXPECT_FALSE(loop_->RegisterSocket(write_fd_, kAllEvents, &listener));
125 
126   EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
127   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(4));
128   // Expect no further calls.
129   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(5));
130 }
131 
TEST_P(QuicEventLoopFactoryTest,RearmWriter)132 TEST_P(QuicEventLoopFactoryTest, RearmWriter) {
133   testing::StrictMock<MockQuicSocketEventListener> listener;
134   ASSERT_TRUE(loop_->RegisterSocket(write_fd_, kAllEvents, &listener));
135 
136   if (loop_->SupportsEdgeTriggered()) {
137     EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable))
138         .Times(1);
139     loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
140     loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
141   } else {
142     EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable))
143         .Times(2);
144     loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
145     ASSERT_TRUE(loop_->RearmSocket(write_fd_, kSocketEventWritable));
146     loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
147   }
148 }
149 
TEST_P(QuicEventLoopFactoryTest,Readable)150 TEST_P(QuicEventLoopFactoryTest, Readable) {
151   testing::StrictMock<MockQuicSocketEventListener> listener;
152   ASSERT_TRUE(loop_->RegisterSocket(read_fd_, kAllEvents, &listener));
153 
154   ASSERT_EQ(4, write(write_fd_, "test", 4));
155   EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable));
156   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
157   // Expect no further calls.
158   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
159 }
160 
161 // A common pattern: read a limited amount of data from an FD, and expect to
162 // read the remainder on the next operation.
TEST_P(QuicEventLoopFactoryTest,ArtificialNotifyFromCallback)163 TEST_P(QuicEventLoopFactoryTest, ArtificialNotifyFromCallback) {
164   testing::StrictMock<MockQuicSocketEventListener> listener;
165   ASSERT_TRUE(loop_->RegisterSocket(read_fd_, kSocketEventReadable, &listener));
166 
167   constexpr absl::string_view kData = "test test test test test test test ";
168   constexpr size_t kTimes = kData.size() / 5;
169   ASSERT_EQ(kData.size(), write(write_fd_, kData.data(), kData.size()));
170   EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable))
171       .Times(loop_->SupportsEdgeTriggered() ? (kTimes + 1) : kTimes)
172       .WillRepeatedly([&]() {
173         char buf[5];
174         int read_result = read(read_fd_, buf, sizeof(buf));
175         if (read_result > 0) {
176           ASSERT_EQ(read_result, 5);
177           if (loop_->SupportsEdgeTriggered()) {
178             EXPECT_TRUE(
179                 loop_->ArtificiallyNotifyEvent(read_fd_, kSocketEventReadable));
180           } else {
181             EXPECT_TRUE(loop_->RearmSocket(read_fd_, kSocketEventReadable));
182           }
183         } else {
184           EXPECT_EQ(errno, EAGAIN);
185         }
186       });
187   for (size_t i = 0; i < kTimes + 2; i++) {
188     loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
189   }
190 }
191 
TEST_P(QuicEventLoopFactoryTest,WriterUnblocked)192 TEST_P(QuicEventLoopFactoryTest, WriterUnblocked) {
193   testing::StrictMock<MockQuicSocketEventListener> listener;
194   ASSERT_TRUE(loop_->RegisterSocket(write_fd_, kAllEvents, &listener));
195 
196   EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
197   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
198   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
199 
200   int io_result;
201   std::string data(2048, 'a');
202   do {
203     io_result = write(write_fd_, data.data(), data.size());
204   } while (io_result > 0);
205   ASSERT_EQ(errno, EAGAIN);
206 
207   // Rearm if necessary and expect no immediate calls.
208   if (!loop_->SupportsEdgeTriggered()) {
209     ASSERT_TRUE(loop_->RearmSocket(write_fd_, kSocketEventWritable));
210   }
211   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
212 
213   EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
214   do {
215     io_result = read(read_fd_, data.data(), data.size());
216   } while (io_result > 0);
217   ASSERT_EQ(errno, EAGAIN);
218   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
219 }
220 
TEST_P(QuicEventLoopFactoryTest,ArtificialEvent)221 TEST_P(QuicEventLoopFactoryTest, ArtificialEvent) {
222   testing::StrictMock<MockQuicSocketEventListener> listener;
223   ASSERT_TRUE(loop_->RegisterSocket(read_fd_, kAllEvents, &listener));
224   ASSERT_TRUE(loop_->RegisterSocket(write_fd_, kAllEvents, &listener));
225 
226   ASSERT_TRUE(loop_->ArtificiallyNotifyEvent(read_fd_, kSocketEventReadable));
227 
228   EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable));
229   EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
230   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
231 }
232 
TEST_P(QuicEventLoopFactoryTest,Unregister)233 TEST_P(QuicEventLoopFactoryTest, Unregister) {
234   testing::StrictMock<MockQuicSocketEventListener> listener;
235   ASSERT_TRUE(loop_->RegisterSocket(write_fd_, kAllEvents, &listener));
236   ASSERT_TRUE(loop_->UnregisterSocket(write_fd_));
237 
238   // Expect nothing to happen.
239   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
240 
241   EXPECT_FALSE(loop_->UnregisterSocket(write_fd_));
242   if (!loop_->SupportsEdgeTriggered()) {
243     EXPECT_FALSE(loop_->RearmSocket(write_fd_, kSocketEventWritable));
244   }
245   EXPECT_FALSE(loop_->ArtificiallyNotifyEvent(write_fd_, kSocketEventWritable));
246 }
247 
TEST_P(QuicEventLoopFactoryTest,UnregisterInsideEventHandler)248 TEST_P(QuicEventLoopFactoryTest, UnregisterInsideEventHandler) {
249   testing::StrictMock<MockQuicSocketEventListener> listener;
250   ASSERT_TRUE(loop_->RegisterSocket(read_fd_, kAllEvents, &listener));
251   ASSERT_TRUE(loop_->RegisterSocket(write_fd_, kAllEvents, &listener));
252 
253   // We are not guaranteed the order in which those events will happen, so we
254   // try to accommodate both possibilities.
255   int total_called = 0;
256   EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable))
257       .Times(AtMost(1))
258       .WillOnce([&]() {
259         ++total_called;
260         ASSERT_TRUE(loop_->UnregisterSocket(write_fd_));
261       });
262   EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable))
263       .Times(AtMost(1))
264       .WillOnce([&]() {
265         ++total_called;
266         ASSERT_TRUE(loop_->UnregisterSocket(read_fd_));
267       });
268   ASSERT_TRUE(loop_->ArtificiallyNotifyEvent(read_fd_, kSocketEventReadable));
269   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
270   EXPECT_EQ(total_called, 1);
271 }
272 
TEST_P(QuicEventLoopFactoryTest,UnregisterSelfInsideEventHandler)273 TEST_P(QuicEventLoopFactoryTest, UnregisterSelfInsideEventHandler) {
274   testing::StrictMock<MockQuicSocketEventListener> listener;
275   ASSERT_TRUE(loop_->RegisterSocket(write_fd_, kAllEvents, &listener));
276 
277   EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable))
278       .WillOnce([&]() { ASSERT_TRUE(loop_->UnregisterSocket(write_fd_)); });
279   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
280 }
281 
282 // Creates a bidirectional socket and tests its behavior when it's both readable
283 // and writable.
TEST_P(QuicEventLoopFactoryTest,ReadWriteSocket)284 TEST_P(QuicEventLoopFactoryTest, ReadWriteSocket) {
285   int sockets[2];
286   ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), 0);
287   SetNonBlocking(sockets[0]);
288   SetNonBlocking(sockets[1]);
289 
290   testing::StrictMock<MockQuicSocketEventListener> listener;
291   ASSERT_TRUE(loop_->RegisterSocket(sockets[0], kAllEvents, &listener));
292   EXPECT_CALL(listener, OnSocketEvent(_, sockets[0], kSocketEventWritable));
293   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(4));
294 
295   int io_result;
296   std::string data(2048, 'a');
297   do {
298     io_result = write(sockets[0], data.data(), data.size());
299   } while (io_result > 0);
300   ASSERT_EQ(errno, EAGAIN);
301 
302   if (!loop_->SupportsEdgeTriggered()) {
303     ASSERT_TRUE(loop_->RearmSocket(sockets[0], kSocketEventWritable));
304   }
305   // We are not write-blocked, so this should not notify.
306   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(4));
307 
308   EXPECT_GT(write(sockets[1], data.data(), data.size()), 0);
309   EXPECT_CALL(listener, OnSocketEvent(_, sockets[0], kSocketEventReadable));
310   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(4));
311 
312   do {
313     char buffer[2048];
314     io_result = read(sockets[1], buffer, sizeof(buffer));
315   } while (io_result > 0);
316   ASSERT_EQ(errno, EAGAIN);
317   // Here, we can receive either "writable" or "readable and writable"
318   // notification depending on the backend in question.
319   EXPECT_CALL(listener,
320               OnSocketEvent(_, sockets[0], HasFlagSet(kSocketEventWritable)));
321   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(4));
322 
323   EXPECT_TRUE(loop_->UnregisterSocket(sockets[0]));
324   close(sockets[0]);
325   close(sockets[1]);
326 }
327 
TEST_P(QuicEventLoopFactoryTest,AlarmInFuture)328 TEST_P(QuicEventLoopFactoryTest, AlarmInFuture) {
329   constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
330   auto [alarm, delegate] = CreateAlarm();
331 
332   alarm->Set(clock_.Now() + kAlarmTimeout);
333 
334   bool alarm_called = false;
335   EXPECT_CALL(*delegate, OnAlarm()).WillOnce([&]() { alarm_called = true; });
336   RunEventLoopUntil([&]() { return alarm_called; },
337                     QuicTime::Delta::FromMilliseconds(100));
338 }
339 
TEST_P(QuicEventLoopFactoryTest,AlarmsInPast)340 TEST_P(QuicEventLoopFactoryTest, AlarmsInPast) {
341   constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
342   auto [alarm1, delegate1] = CreateAlarm();
343   auto [alarm2, delegate2] = CreateAlarm();
344 
345   alarm1->Set(clock_.Now() - 2 * kAlarmTimeout);
346   alarm2->Set(clock_.Now() - kAlarmTimeout);
347 
348   {
349     testing::InSequence s;
350     EXPECT_CALL(*delegate1, OnAlarm());
351     EXPECT_CALL(*delegate2, OnAlarm());
352   }
353   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
354 }
355 
TEST_P(QuicEventLoopFactoryTest,AlarmCancelled)356 TEST_P(QuicEventLoopFactoryTest, AlarmCancelled) {
357   constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
358   auto [alarm, delegate] = CreateAlarm();
359 
360   alarm->Set(clock_.Now() + kAlarmTimeout);
361   alarm->Cancel();
362 
363   loop_->RunEventLoopOnce(kAlarmTimeout * 2);
364 }
365 
TEST_P(QuicEventLoopFactoryTest,AlarmCancelledAndSetAgain)366 TEST_P(QuicEventLoopFactoryTest, AlarmCancelledAndSetAgain) {
367   constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
368   auto [alarm, delegate] = CreateAlarm();
369 
370   alarm->Set(clock_.Now() + kAlarmTimeout);
371   alarm->Cancel();
372   alarm->Set(clock_.Now() + 2 * kAlarmTimeout);
373 
374   bool alarm_called = false;
375   EXPECT_CALL(*delegate, OnAlarm()).WillOnce([&]() { alarm_called = true; });
376   RunEventLoopUntil([&]() { return alarm_called; },
377                     QuicTime::Delta::FromMilliseconds(100));
378 }
379 
TEST_P(QuicEventLoopFactoryTest,AlarmCancelsAnotherAlarm)380 TEST_P(QuicEventLoopFactoryTest, AlarmCancelsAnotherAlarm) {
381   constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
382   auto [alarm1_ptr, delegate1] = CreateAlarm();
383   auto [alarm2_ptr, delegate2] = CreateAlarm();
384 
385   QuicAlarm& alarm1 = *alarm1_ptr;
386   QuicAlarm& alarm2 = *alarm2_ptr;
387   alarm1.Set(clock_.Now() - kAlarmTimeout);
388   alarm2.Set(clock_.Now() - kAlarmTimeout);
389 
390   int alarms_called = 0;
391   // Since the order in which alarms are cancelled is not well-determined, make
392   // each one cancel another.
393   EXPECT_CALL(*delegate1, OnAlarm()).Times(AtMost(1)).WillOnce([&]() {
394     alarm2.Cancel();
395     ++alarms_called;
396   });
397   EXPECT_CALL(*delegate2, OnAlarm()).Times(AtMost(1)).WillOnce([&]() {
398     alarm1.Cancel();
399     ++alarms_called;
400   });
401   // Run event loop twice to ensure the second alarm is not called after two
402   // iterations.
403   loop_->RunEventLoopOnce(kAlarmTimeout * 2);
404   loop_->RunEventLoopOnce(kAlarmTimeout * 2);
405   EXPECT_EQ(alarms_called, 1);
406 }
407 
TEST_P(QuicEventLoopFactoryTest,DestructorWithPendingAlarm)408 TEST_P(QuicEventLoopFactoryTest, DestructorWithPendingAlarm) {
409   constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
410   auto [alarm1_ptr, delegate1] = CreateAlarm();
411 
412   alarm1_ptr->Set(clock_.Now() + kAlarmTimeout);
413   // Expect destructor to cleanly unregister itself before the event loop is
414   // gone.
415 }
416 
TEST_P(QuicEventLoopFactoryTest,NegativeTimeout)417 TEST_P(QuicEventLoopFactoryTest, NegativeTimeout) {
418   constexpr auto kAlarmTimeout = QuicTime::Delta::FromSeconds(300);
419   auto [alarm1_ptr, delegate1] = CreateAlarm();
420 
421   alarm1_ptr->Set(clock_.Now() + kAlarmTimeout);
422 
423   loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(-1));
424 }
425 
TEST_P(QuicEventLoopFactoryTest,ScheduleAlarmInPastFromInsideAlarm)426 TEST_P(QuicEventLoopFactoryTest, ScheduleAlarmInPastFromInsideAlarm) {
427   constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(20);
428   auto [alarm1_ptr, delegate1] = CreateAlarm();
429   auto [alarm2_ptr, delegate2] = CreateAlarm();
430 
431   alarm1_ptr->Set(clock_.Now() - kAlarmTimeout);
432   EXPECT_CALL(*delegate1, OnAlarm())
433       .WillOnce([&, alarm2_unowned = alarm2_ptr.get()]() {
434         alarm2_unowned->Set(clock_.Now() - 2 * kAlarmTimeout);
435       });
436   bool fired = false;
437   EXPECT_CALL(*delegate2, OnAlarm()).WillOnce([&]() { fired = true; });
438 
439   RunEventLoopUntil([&]() { return fired; },
440                     QuicTime::Delta::FromMilliseconds(100));
441 }
442 
443 }  // namespace
444 }  // namespace quic::test
445