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 #include "quiche/quic/core/io/quic_poll_event_loop.h"
6
7 #include <fcntl.h>
8 #include <unistd.h>
9
10 #include <cerrno>
11 #include <memory>
12 #include <vector>
13
14 #include "absl/memory/memory.h"
15 #include "quiche/quic/core/io/quic_event_loop.h"
16 #include "quiche/quic/core/quic_alarm.h"
17 #include "quiche/quic/core/quic_alarm_factory.h"
18 #include "quiche/quic/core/quic_time.h"
19 #include "quiche/quic/platform/api/quic_test.h"
20 #include "quiche/quic/test_tools/mock_clock.h"
21
22 namespace quic {
23
24 class QuicPollEventLoopPeer {
25 public:
ComputePollTimeout(const QuicPollEventLoop & loop,QuicTime now,QuicTime::Delta default_timeout)26 static QuicTime::Delta ComputePollTimeout(const QuicPollEventLoop& loop,
27 QuicTime now,
28 QuicTime::Delta default_timeout) {
29 return loop.ComputePollTimeout(now, default_timeout);
30 }
31 };
32
33 } // namespace quic
34
35 namespace quic::test {
36 namespace {
37
38 using testing::_;
39 using testing::AtMost;
40 using testing::ElementsAre;
41
42 constexpr QuicSocketEventMask kAllEvents =
43 kSocketEventReadable | kSocketEventWritable | kSocketEventError;
44 constexpr QuicTime::Delta kDefaultTimeout = QuicTime::Delta::FromSeconds(100);
45
46 class MockQuicSocketEventListener : public QuicSocketEventListener {
47 public:
48 MOCK_METHOD(void, OnSocketEvent,
49 (QuicEventLoop* /*event_loop*/, SocketFd /*fd*/,
50 QuicSocketEventMask /*events*/),
51 (override));
52 };
53
54 class MockDelegate : public QuicAlarm::Delegate {
55 public:
GetConnectionContext()56 QuicConnectionContext* GetConnectionContext() override { return nullptr; }
57 MOCK_METHOD(void, OnAlarm, (), (override));
58 };
59
60 class QuicPollEventLoopForTest : public QuicPollEventLoop {
61 public:
QuicPollEventLoopForTest(MockClock * clock)62 QuicPollEventLoopForTest(MockClock* clock)
63 : QuicPollEventLoop(clock), clock_(clock) {}
64
PollSyscall(pollfd * fds,nfds_t nfds,int timeout)65 int PollSyscall(pollfd* fds, nfds_t nfds, int timeout) override {
66 timeouts_.push_back(timeout);
67 if (eintr_after_ != QuicTime::Delta::Infinite()) {
68 errno = EINTR;
69 clock_->AdvanceTime(eintr_after_);
70 eintr_after_ = QuicTime::Delta::Infinite();
71 return -1;
72 }
73 if (poll_return_after_ != QuicTime::Delta::Infinite()) {
74 clock_->AdvanceTime(poll_return_after_);
75 poll_return_after_ = QuicTime::Delta::Infinite();
76 } else {
77 clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(timeout));
78 }
79
80 return QuicPollEventLoop::PollSyscall(fds, nfds, timeout);
81 }
82
TriggerEintrAfter(QuicTime::Delta time)83 void TriggerEintrAfter(QuicTime::Delta time) { eintr_after_ = time; }
ReturnFromPollAfter(QuicTime::Delta time)84 void ReturnFromPollAfter(QuicTime::Delta time) { poll_return_after_ = time; }
85
timeouts() const86 const std::vector<int>& timeouts() const { return timeouts_; }
87
88 private:
89 MockClock* clock_;
90 QuicTime::Delta eintr_after_ = QuicTime::Delta::Infinite();
91 QuicTime::Delta poll_return_after_ = QuicTime::Delta::Infinite();
92 std::vector<int> timeouts_;
93 };
94
95 class QuicPollEventLoopTest : public QuicTest {
96 public:
QuicPollEventLoopTest()97 QuicPollEventLoopTest()
98 : loop_(&clock_), factory_(loop_.CreateAlarmFactory()) {
99 int fds[2];
100 int result = ::pipe(fds);
101 QUICHE_CHECK(result >= 0) << "Failed to create a pipe, errno: " << errno;
102 read_fd_ = fds[0];
103 write_fd_ = fds[1];
104
105 QUICHE_CHECK(::fcntl(read_fd_, F_SETFL,
106 ::fcntl(read_fd_, F_GETFL) | O_NONBLOCK) == 0)
107 << "Failed to mark pipe FD non-blocking, errno: " << errno;
108 QUICHE_CHECK(::fcntl(write_fd_, F_SETFL,
109 ::fcntl(write_fd_, F_GETFL) | O_NONBLOCK) == 0)
110 << "Failed to mark pipe FD non-blocking, errno: " << errno;
111
112 clock_.AdvanceTime(10 * kDefaultTimeout);
113 }
114
~QuicPollEventLoopTest()115 ~QuicPollEventLoopTest() {
116 close(read_fd_);
117 close(write_fd_);
118 }
119
ComputePollTimeout()120 QuicTime::Delta ComputePollTimeout() {
121 return QuicPollEventLoopPeer::ComputePollTimeout(loop_, clock_.Now(),
122 kDefaultTimeout);
123 }
124
CreateAlarm()125 std::pair<std::unique_ptr<QuicAlarm>, MockDelegate*> CreateAlarm() {
126 auto delegate = std::make_unique<testing::StrictMock<MockDelegate>>();
127 MockDelegate* delegate_unowned = delegate.get();
128 auto alarm = absl::WrapUnique(factory_->CreateAlarm(delegate.release()));
129 return std::make_pair(std::move(alarm), delegate_unowned);
130 }
131
132 protected:
133 MockClock clock_;
134 QuicPollEventLoopForTest loop_;
135 std::unique_ptr<QuicAlarmFactory> factory_;
136 int read_fd_;
137 int write_fd_;
138 };
139
TEST_F(QuicPollEventLoopTest,NothingHappens)140 TEST_F(QuicPollEventLoopTest, NothingHappens) {
141 testing::StrictMock<MockQuicSocketEventListener> listener;
142 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
143 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
144
145 // Attempt double-registration.
146 EXPECT_FALSE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
147
148 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
149
150 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
151 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(4));
152 // Expect no further calls.
153 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(5));
154 EXPECT_THAT(loop_.timeouts(), ElementsAre(4, 5));
155 }
156
TEST_F(QuicPollEventLoopTest,RearmWriter)157 TEST_F(QuicPollEventLoopTest, RearmWriter) {
158 testing::StrictMock<MockQuicSocketEventListener> listener;
159 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
160
161 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable))
162 .Times(2);
163 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
164 ASSERT_TRUE(loop_.RearmSocket(write_fd_, kSocketEventWritable));
165 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
166 }
167
TEST_F(QuicPollEventLoopTest,Readable)168 TEST_F(QuicPollEventLoopTest, Readable) {
169 testing::StrictMock<MockQuicSocketEventListener> listener;
170 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
171
172 ASSERT_EQ(4, write(write_fd_, "test", 4));
173 EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable));
174 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
175 // Expect no further calls.
176 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
177 }
178
TEST_F(QuicPollEventLoopTest,RearmReader)179 TEST_F(QuicPollEventLoopTest, RearmReader) {
180 testing::StrictMock<MockQuicSocketEventListener> listener;
181 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
182
183 ASSERT_EQ(4, write(write_fd_, "test", 4));
184 EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable));
185 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
186 // Expect no further calls.
187 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
188 }
189
TEST_F(QuicPollEventLoopTest,WriterUnblocked)190 TEST_F(QuicPollEventLoopTest, WriterUnblocked) {
191 testing::StrictMock<MockQuicSocketEventListener> listener;
192 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
193
194 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
195 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
196 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
197
198 int io_result;
199 std::string data(2048, 'a');
200 do {
201 io_result = write(write_fd_, data.data(), data.size());
202 } while (io_result > 0);
203 ASSERT_EQ(errno, EAGAIN);
204
205 // Rearm and expect no immediate calls.
206 ASSERT_TRUE(loop_.RearmSocket(write_fd_, kSocketEventWritable));
207 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
208
209 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
210 do {
211 io_result = read(read_fd_, data.data(), data.size());
212 } while (io_result > 0);
213 ASSERT_EQ(errno, EAGAIN);
214 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
215 }
216
TEST_F(QuicPollEventLoopTest,ArtificialEvent)217 TEST_F(QuicPollEventLoopTest, ArtificialEvent) {
218 testing::StrictMock<MockQuicSocketEventListener> listener;
219 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
220 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
221
222 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
223 ASSERT_TRUE(loop_.ArtificiallyNotifyEvent(read_fd_, kSocketEventReadable));
224 EXPECT_EQ(ComputePollTimeout(), QuicTime::Delta::Zero());
225
226 {
227 testing::InSequence s;
228 EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable));
229 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
230 }
231 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
232 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
233 }
234
TEST_F(QuicPollEventLoopTest,Unregister)235 TEST_F(QuicPollEventLoopTest, Unregister) {
236 testing::StrictMock<MockQuicSocketEventListener> listener;
237 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
238 ASSERT_TRUE(loop_.UnregisterSocket(write_fd_));
239
240 // Expect nothing to happen.
241 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
242
243 EXPECT_FALSE(loop_.UnregisterSocket(write_fd_));
244 EXPECT_FALSE(loop_.RearmSocket(write_fd_, kSocketEventWritable));
245 EXPECT_FALSE(loop_.ArtificiallyNotifyEvent(write_fd_, kSocketEventWritable));
246 }
247
TEST_F(QuicPollEventLoopTest,UnregisterInsideEventHandler)248 TEST_F(QuicPollEventLoopTest, 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 EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable))
254 .WillOnce([this]() { ASSERT_TRUE(loop_.UnregisterSocket(write_fd_)); });
255 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable))
256 .Times(0);
257 ASSERT_TRUE(loop_.ArtificiallyNotifyEvent(read_fd_, kSocketEventReadable));
258 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
259 }
260
TEST_F(QuicPollEventLoopTest,EintrHandler)261 TEST_F(QuicPollEventLoopTest, EintrHandler) {
262 testing::StrictMock<MockQuicSocketEventListener> listener;
263 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
264
265 loop_.TriggerEintrAfter(QuicTime::Delta::FromMilliseconds(25));
266 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
267 EXPECT_THAT(loop_.timeouts(), ElementsAre(100, 75));
268 }
269
TEST_F(QuicPollEventLoopTest,PollReturnsEarly)270 TEST_F(QuicPollEventLoopTest, PollReturnsEarly) {
271 testing::StrictMock<MockQuicSocketEventListener> listener;
272 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
273
274 loop_.ReturnFromPollAfter(QuicTime::Delta::FromMilliseconds(25));
275 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
276 EXPECT_THAT(loop_.timeouts(), ElementsAre(100, 75));
277 }
278
TEST_F(QuicPollEventLoopTest,AlarmInFuture)279 TEST_F(QuicPollEventLoopTest, AlarmInFuture) {
280 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
281
282 constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
283 auto [alarm, delegate] = CreateAlarm();
284 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
285
286 alarm->Set(clock_.Now() + kAlarmTimeout);
287 EXPECT_EQ(ComputePollTimeout(), kAlarmTimeout);
288
289 EXPECT_CALL(*delegate, OnAlarm());
290 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
291 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
292 }
293
TEST_F(QuicPollEventLoopTest,AlarmsInPast)294 TEST_F(QuicPollEventLoopTest, AlarmsInPast) {
295 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
296
297 constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
298 auto [alarm1, delegate1] = CreateAlarm();
299 auto [alarm2, delegate2] = CreateAlarm();
300
301 alarm1->Set(clock_.Now() - 2 * kAlarmTimeout);
302 alarm2->Set(clock_.Now() - kAlarmTimeout);
303
304 {
305 testing::InSequence s;
306 EXPECT_CALL(*delegate1, OnAlarm());
307 EXPECT_CALL(*delegate2, OnAlarm());
308 }
309 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
310 }
311
TEST_F(QuicPollEventLoopTest,AlarmCancelled)312 TEST_F(QuicPollEventLoopTest, AlarmCancelled) {
313 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
314
315 constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
316 auto [alarm, delegate] = CreateAlarm();
317 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
318
319 alarm->Set(clock_.Now() + kAlarmTimeout);
320 alarm->Cancel();
321 alarm->Set(clock_.Now() + 2 * kAlarmTimeout);
322 EXPECT_EQ(ComputePollTimeout(), kAlarmTimeout);
323
324 EXPECT_CALL(*delegate, OnAlarm());
325 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
326 EXPECT_THAT(loop_.timeouts(), ElementsAre(10));
327 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
328 }
329
TEST_F(QuicPollEventLoopTest,AlarmCancelsAnotherAlarm)330 TEST_F(QuicPollEventLoopTest, AlarmCancelsAnotherAlarm) {
331 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
332
333 constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
334 auto [alarm1_ptr, delegate1] = CreateAlarm();
335 auto [alarm2_ptr, delegate2] = CreateAlarm();
336
337 QuicAlarm& alarm1 = *alarm1_ptr;
338 QuicAlarm& alarm2 = *alarm2_ptr;
339 alarm1.Set(clock_.Now() - kAlarmTimeout);
340 alarm2.Set(clock_.Now() - kAlarmTimeout);
341
342 int alarms_called = 0;
343 // Since the order in which alarms are cancelled is not well-determined, make
344 // each one cancel another.
345 EXPECT_CALL(*delegate1, OnAlarm()).Times(AtMost(1)).WillOnce([&]() {
346 alarm2.Cancel();
347 ++alarms_called;
348 });
349 EXPECT_CALL(*delegate2, OnAlarm()).Times(AtMost(1)).WillOnce([&]() {
350 alarm1.Cancel();
351 ++alarms_called;
352 });
353 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
354 EXPECT_EQ(alarms_called, 1);
355 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
356 }
357
358 } // namespace
359 } // namespace quic::test
360