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*/, QuicUdpSocketFd /*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 clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(timeout));
74 return QuicPollEventLoop::PollSyscall(fds, nfds, timeout);
75 }
76
TriggerEintrAfter(QuicTime::Delta time)77 void TriggerEintrAfter(QuicTime::Delta time) { eintr_after_ = time; }
78
timeouts() const79 const std::vector<int>& timeouts() const { return timeouts_; }
80
81 private:
82 MockClock* clock_;
83 QuicTime::Delta eintr_after_ = QuicTime::Delta::Infinite();
84 std::vector<int> timeouts_;
85 };
86
87 class QuicPollEventLoopTest : public QuicTest {
88 public:
QuicPollEventLoopTest()89 QuicPollEventLoopTest()
90 : loop_(&clock_), factory_(loop_.CreateAlarmFactory()) {
91 int fds[2];
92 int result = ::pipe(fds);
93 QUICHE_CHECK(result >= 0) << "Failed to create a pipe, errno: " << errno;
94 read_fd_ = fds[0];
95 write_fd_ = fds[1];
96
97 QUICHE_CHECK(::fcntl(read_fd_, F_SETFL,
98 ::fcntl(read_fd_, F_GETFL) | O_NONBLOCK) == 0)
99 << "Failed to mark pipe FD non-blocking, errno: " << errno;
100 QUICHE_CHECK(::fcntl(write_fd_, F_SETFL,
101 ::fcntl(write_fd_, F_GETFL) | O_NONBLOCK) == 0)
102 << "Failed to mark pipe FD non-blocking, errno: " << errno;
103
104 clock_.AdvanceTime(10 * kDefaultTimeout);
105 }
106
~QuicPollEventLoopTest()107 ~QuicPollEventLoopTest() {
108 close(read_fd_);
109 close(write_fd_);
110 }
111
ComputePollTimeout()112 QuicTime::Delta ComputePollTimeout() {
113 return QuicPollEventLoopPeer::ComputePollTimeout(loop_, clock_.Now(),
114 kDefaultTimeout);
115 }
116
CreateAlarm()117 std::pair<std::unique_ptr<QuicAlarm>, MockDelegate*> CreateAlarm() {
118 auto delegate = std::make_unique<testing::StrictMock<MockDelegate>>();
119 MockDelegate* delegate_unowned = delegate.get();
120 auto alarm = absl::WrapUnique(factory_->CreateAlarm(delegate.release()));
121 return std::make_pair(std::move(alarm), delegate_unowned);
122 }
123
124 protected:
125 MockClock clock_;
126 QuicPollEventLoopForTest loop_;
127 std::unique_ptr<QuicAlarmFactory> factory_;
128 int read_fd_;
129 int write_fd_;
130 };
131
TEST_F(QuicPollEventLoopTest,NothingHappens)132 TEST_F(QuicPollEventLoopTest, NothingHappens) {
133 testing::StrictMock<MockQuicSocketEventListener> listener;
134 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
135 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
136
137 // Attempt double-registration.
138 EXPECT_FALSE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
139
140 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
141
142 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
143 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(4));
144 // Expect no further calls.
145 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(5));
146 EXPECT_THAT(loop_.timeouts(), ElementsAre(4, 5));
147 }
148
TEST_F(QuicPollEventLoopTest,RearmWriter)149 TEST_F(QuicPollEventLoopTest, RearmWriter) {
150 testing::StrictMock<MockQuicSocketEventListener> listener;
151 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
152
153 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable))
154 .Times(2);
155 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
156 ASSERT_TRUE(loop_.RearmSocket(write_fd_, kSocketEventWritable));
157 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
158 }
159
TEST_F(QuicPollEventLoopTest,Readable)160 TEST_F(QuicPollEventLoopTest, Readable) {
161 testing::StrictMock<MockQuicSocketEventListener> listener;
162 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
163
164 ASSERT_EQ(4, write(write_fd_, "test", 4));
165 EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable));
166 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
167 // Expect no further calls.
168 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
169 }
170
TEST_F(QuicPollEventLoopTest,RearmReader)171 TEST_F(QuicPollEventLoopTest, RearmReader) {
172 testing::StrictMock<MockQuicSocketEventListener> listener;
173 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
174
175 ASSERT_EQ(4, write(write_fd_, "test", 4));
176 EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable));
177 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
178 // Expect no further calls.
179 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
180 }
181
TEST_F(QuicPollEventLoopTest,WriterUnblocked)182 TEST_F(QuicPollEventLoopTest, WriterUnblocked) {
183 testing::StrictMock<MockQuicSocketEventListener> listener;
184 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
185
186 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
187 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
188 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
189
190 int io_result;
191 std::string data(2048, 'a');
192 do {
193 io_result = write(write_fd_, data.data(), data.size());
194 } while (io_result > 0);
195 ASSERT_EQ(errno, EAGAIN);
196
197 // Rearm and expect no immediate calls.
198 ASSERT_TRUE(loop_.RearmSocket(write_fd_, kSocketEventWritable));
199 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
200
201 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
202 do {
203 io_result = read(read_fd_, data.data(), data.size());
204 } while (io_result > 0);
205 ASSERT_EQ(errno, EAGAIN);
206 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
207 }
208
TEST_F(QuicPollEventLoopTest,ArtificialEvent)209 TEST_F(QuicPollEventLoopTest, ArtificialEvent) {
210 testing::StrictMock<MockQuicSocketEventListener> listener;
211 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
212 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
213
214 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
215 ASSERT_TRUE(loop_.ArtificiallyNotifyEvent(read_fd_, kSocketEventReadable));
216 EXPECT_EQ(ComputePollTimeout(), QuicTime::Delta::Zero());
217
218 {
219 testing::InSequence s;
220 EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable));
221 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable));
222 }
223 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
224 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
225 }
226
TEST_F(QuicPollEventLoopTest,Unregister)227 TEST_F(QuicPollEventLoopTest, Unregister) {
228 testing::StrictMock<MockQuicSocketEventListener> listener;
229 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
230 ASSERT_TRUE(loop_.UnregisterSocket(write_fd_));
231
232 // Expect nothing to happen.
233 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
234
235 EXPECT_FALSE(loop_.UnregisterSocket(write_fd_));
236 EXPECT_FALSE(loop_.RearmSocket(write_fd_, kSocketEventWritable));
237 EXPECT_FALSE(loop_.ArtificiallyNotifyEvent(write_fd_, kSocketEventWritable));
238 }
239
TEST_F(QuicPollEventLoopTest,UnregisterInsideEventHandler)240 TEST_F(QuicPollEventLoopTest, UnregisterInsideEventHandler) {
241 testing::StrictMock<MockQuicSocketEventListener> listener;
242 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
243 ASSERT_TRUE(loop_.RegisterSocket(write_fd_, kAllEvents, &listener));
244
245 EXPECT_CALL(listener, OnSocketEvent(_, read_fd_, kSocketEventReadable))
246 .WillOnce([this]() { ASSERT_TRUE(loop_.UnregisterSocket(write_fd_)); });
247 EXPECT_CALL(listener, OnSocketEvent(_, write_fd_, kSocketEventWritable))
248 .Times(0);
249 ASSERT_TRUE(loop_.ArtificiallyNotifyEvent(read_fd_, kSocketEventReadable));
250 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(1));
251 }
252
TEST_F(QuicPollEventLoopTest,EintrHandler)253 TEST_F(QuicPollEventLoopTest, EintrHandler) {
254 testing::StrictMock<MockQuicSocketEventListener> listener;
255 ASSERT_TRUE(loop_.RegisterSocket(read_fd_, kAllEvents, &listener));
256
257 loop_.TriggerEintrAfter(QuicTime::Delta::FromMilliseconds(25));
258 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
259 EXPECT_THAT(loop_.timeouts(), ElementsAre(100, 75));
260 }
261
TEST_F(QuicPollEventLoopTest,AlarmInFuture)262 TEST_F(QuicPollEventLoopTest, AlarmInFuture) {
263 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
264
265 constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
266 auto [alarm, delegate] = CreateAlarm();
267 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
268
269 alarm->Set(clock_.Now() + kAlarmTimeout);
270 EXPECT_EQ(ComputePollTimeout(), kAlarmTimeout);
271
272 EXPECT_CALL(*delegate, OnAlarm());
273 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
274 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
275 }
276
TEST_F(QuicPollEventLoopTest,AlarmsInPast)277 TEST_F(QuicPollEventLoopTest, AlarmsInPast) {
278 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
279
280 constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
281 auto [alarm1, delegate1] = CreateAlarm();
282 auto [alarm2, delegate2] = CreateAlarm();
283
284 alarm1->Set(clock_.Now() - 2 * kAlarmTimeout);
285 alarm2->Set(clock_.Now() - kAlarmTimeout);
286
287 {
288 testing::InSequence s;
289 EXPECT_CALL(*delegate1, OnAlarm());
290 EXPECT_CALL(*delegate2, OnAlarm());
291 }
292 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
293 }
294
TEST_F(QuicPollEventLoopTest,AlarmCancelled)295 TEST_F(QuicPollEventLoopTest, AlarmCancelled) {
296 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
297
298 constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
299 auto [alarm, delegate] = CreateAlarm();
300 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
301
302 alarm->Set(clock_.Now() + kAlarmTimeout);
303 alarm->Cancel();
304 alarm->Set(clock_.Now() + 2 * kAlarmTimeout);
305 EXPECT_EQ(ComputePollTimeout(), kAlarmTimeout);
306
307 EXPECT_CALL(*delegate, OnAlarm());
308 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
309 EXPECT_THAT(loop_.timeouts(), ElementsAre(10));
310 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
311 }
312
TEST_F(QuicPollEventLoopTest,AlarmCancelsAnotherAlarm)313 TEST_F(QuicPollEventLoopTest, AlarmCancelsAnotherAlarm) {
314 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
315
316 constexpr auto kAlarmTimeout = QuicTime::Delta::FromMilliseconds(5);
317 auto [alarm1_ptr, delegate1] = CreateAlarm();
318 auto [alarm2_ptr, delegate2] = CreateAlarm();
319
320 QuicAlarm& alarm1 = *alarm1_ptr;
321 QuicAlarm& alarm2 = *alarm2_ptr;
322 alarm1.Set(clock_.Now() - kAlarmTimeout);
323 alarm2.Set(clock_.Now() - kAlarmTimeout);
324
325 int alarms_called = 0;
326 // Since the order in which alarms are cancelled is not well-determined, make
327 // each one cancel another.
328 EXPECT_CALL(*delegate1, OnAlarm()).Times(AtMost(1)).WillOnce([&]() {
329 alarm2.Cancel();
330 ++alarms_called;
331 });
332 EXPECT_CALL(*delegate2, OnAlarm()).Times(AtMost(1)).WillOnce([&]() {
333 alarm1.Cancel();
334 ++alarms_called;
335 });
336 loop_.RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(100));
337 EXPECT_EQ(alarms_called, 1);
338 EXPECT_EQ(ComputePollTimeout(), kDefaultTimeout);
339 }
340
341 } // namespace
342 } // namespace quic::test
343