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