• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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