proxygen
AsyncTimeoutSetTest.cpp File Reference

Go to the source code of this file.

Classes

class  MockTimeoutClock
 
class  TestTimeout
 
class  TimeoutTest
 

Typedefs

using StackTimeoutSet = folly::UndelayedDestruction< AsyncTimeoutSet >
 

Functions

 TEST_F (TimeoutTest, FireOnce)
 
 TEST_F (TimeoutTest, SwitchTimeoutSet)
 
 TEST_F (TimeoutTest, CancelTimeout)
 
 TEST_F (TimeoutTest, DestroyTimeoutSet)
 
 TEST_F (TimeoutTest, AtMostEveryN)
 

Typedef Documentation

Function Documentation

TEST_F ( TimeoutTest  ,
FireOnce   
)

Definition at line 146 of file AsyncTimeoutSetTest.cpp.

References ASSERT_EQ, and TestTimeout::timestamps.

146  {
147  StackTimeoutSet ts10(&timeoutManager_, milliseconds(10), milliseconds(0),
148  &timeoutClock_);
149  StackTimeoutSet ts5(&timeoutManager_, milliseconds(5), milliseconds(0),
150  &timeoutClock_);
151 
152  const AsyncTimeoutSet::Callback* nullCallback = nullptr;
153  ASSERT_EQ(ts10.front(), nullCallback);
154  ASSERT_EQ(ts5.front(), nullCallback);
155 
156  TestTimeout t1;
157  TestTimeout t2;
158  TestTimeout t3;
159 
160  ts5.scheduleTimeout(&t1); // fires at time=5
161 
162  // tick forward to time=2 and schedule another 5ms (@7ms) and a
163  // 10ms (12ms) timeout
164 
165  setClock(milliseconds(2));
166 
167  ts5.scheduleTimeout(&t2);
168  ts10.scheduleTimeout(&t3);
169 
170  ASSERT_EQ(ts10.front(), &t3);
171  ASSERT_EQ(ts5.front(), &t1);
172 
173  setClock(milliseconds(5));
174  ASSERT_EQ(ts5.front(), &t2);
175 
176  setClock(milliseconds(7));
177  ASSERT_EQ(ts5.front(), nullCallback);
178 
179  ASSERT_EQ(t1.timestamps.size(), 1);
180  ASSERT_EQ(t2.timestamps.size(), 1);
181 
182  setClock(milliseconds(12));
183 
184  ASSERT_EQ(t3.timestamps.size(), 1);
185 
186  ASSERT_EQ(ts10.front(), nullCallback);
187 
188  ASSERT_EQ(t1.timestamps[0], milliseconds(5));
189  ASSERT_EQ(t2.timestamps[0], milliseconds(7));
190  ASSERT_EQ(t3.timestamps[0], milliseconds(12));
191 }
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
std::deque< TimePoint > timestamps
bool scheduleTimeout(uint32_t milliseconds)
TEST_F ( TimeoutTest  ,
SwitchTimeoutSet   
)

Definition at line 197 of file AsyncTimeoutSetTest.cpp.

References ASSERT_EQ, loop(), and TestTimeout::timestamps.

197  {
198  StackTimeoutSet ts10(&timeoutManager_, milliseconds(10), milliseconds(0),
199  &timeoutClock_);
200  StackTimeoutSet ts5(&timeoutManager_, milliseconds(5), milliseconds(0),
201  &timeoutClock_);
202 
203  TestTimeout t1(&ts5, &ts10, &ts5);
204  TestTimeout t2(&ts10, &ts10, &ts5);
205  TestTimeout t3(&ts5, &ts5, &ts10, &ts5);
206 
207  ts5.scheduleTimeout(&t1);
208 
209  loop();
210 
211  ASSERT_EQ(t1.timestamps.size(), 3);
212  ASSERT_EQ(t2.timestamps.size(), 3);
213  ASSERT_EQ(t3.timestamps.size(), 4);
214 
215  ASSERT_EQ(t1.timestamps[0], milliseconds(5));
216  ASSERT_EQ(t1.timestamps[1] - t1.timestamps[0], milliseconds(10));
217  ASSERT_EQ(t1.timestamps[2] - t1.timestamps[1], milliseconds(5));
218 
219  ASSERT_EQ(t2.timestamps[0], milliseconds(10));
220  ASSERT_EQ(t2.timestamps[1] - t2.timestamps[0], milliseconds(10));
221  ASSERT_EQ(t2.timestamps[2] - t2.timestamps[1], milliseconds(5));
222 
223  ASSERT_EQ(t3.timestamps[0], milliseconds(5));
224  ASSERT_EQ(t3.timestamps[1] - t3.timestamps[0], milliseconds(5));
225  ASSERT_EQ(t3.timestamps[2] - t3.timestamps[1], milliseconds(10));
226  ASSERT_EQ(t3.timestamps[3] - t3.timestamps[2], milliseconds(5));
227  ASSERT_EQ(timeoutClock_.millisecondsSinceEpoch(), milliseconds(25));
228 }
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
void loop(int iters)
TEST_F ( TimeoutTest  ,
CancelTimeout   
)

Definition at line 233 of file AsyncTimeoutSetTest.cpp.

References ASSERT_EQ, proxygen::AsyncTimeoutSet::Callback::cancelTimeout(), TestTimeout::fn, loop(), folly::gen::move, and TestTimeout::timestamps.

233  {
234  StackTimeoutSet ts5(&timeoutManager_, milliseconds(5), milliseconds(0),
235  &timeoutClock_);
236  StackTimeoutSet ts10(&timeoutManager_, milliseconds(10), milliseconds(0),
237  &timeoutClock_);
238  StackTimeoutSet ts20(&timeoutManager_, milliseconds(20), milliseconds(0),
239  &timeoutClock_);
240 
241  // Create several timeouts that will all fire in 5ms.
242  TestTimeout t5_1(&ts5);
243  TestTimeout t5_2(&ts5);
244  TestTimeout t5_3(&ts5);
245  TestTimeout t5_4(&ts5);
246  TestTimeout t5_5(&ts5);
247 
248  // Also create a few timeouts to fire in 10ms
249  TestTimeout t10_1(&ts10);
250  TestTimeout t10_2(&ts10);
251  TestTimeout t10_3(&ts10);
252 
253  TestTimeout t20_1(&ts20);
254  TestTimeout t20_2(&ts20);
255 
256  // Have t5_1 cancel t5_2 and t5_4.
257  //
258  // Cancelling t5_2 will test cancelling a timeout that is at the head of the
259  // list and ready to be fired.
260  //
261  // Cancelling t5_4 will test cancelling a timeout in the middle of the list
262  t5_1.fn = [&] {
263  t5_2.cancelTimeout();
264  t5_4.cancelTimeout();
265  };
266 
267  // Have t5_3 cancel t5_5.
268  // This will test cancelling the last remaining timeout.
269  //
270  // Then have t5_3 reschedule itself.
271  t5_3.fn = [&] {
272  t5_5.cancelTimeout();
273  // Reset our function so we won't continually reschedule ourself
274  auto fn = std::move(t5_3.fn);
275  ts5.scheduleTimeout(&t5_3);
276 
277  // Also test cancelling timeouts in another timeset that isn't ready to
278  // fire yet.
279  //
280  // Cancel the middle timeout in ts10.
281  t10_2.cancelTimeout();
282  // Cancel both the timeouts in ts20.
283  t20_1.cancelTimeout();
284  t20_2.cancelTimeout();
285  };
286 
287  loop();
288 
289  ASSERT_EQ(t5_1.timestamps.size(), 1);
290  ASSERT_EQ(t5_1.timestamps[0], milliseconds(5));
291 
292  ASSERT_EQ(t5_3.timestamps.size(), 2);
293  ASSERT_EQ(t5_3.timestamps[0], milliseconds(5));
294  ASSERT_EQ(t5_3.timestamps[1] - t5_3.timestamps[0], milliseconds(5));
295 
296  ASSERT_EQ(t10_1.timestamps.size(), 1);
297  ASSERT_EQ(t10_1.timestamps[0], milliseconds(10));
298 
299  ASSERT_EQ(t10_3.timestamps.size(), 1);
300  ASSERT_EQ(t10_3.timestamps[0], milliseconds(10));
301 
302  // Cancelled timeouts
303  ASSERT_EQ(t5_2.timestamps.size(), 0);
304  ASSERT_EQ(t5_4.timestamps.size(), 0);
305  ASSERT_EQ(t5_5.timestamps.size(), 0);
306  ASSERT_EQ(t10_2.timestamps.size(), 0);
307  ASSERT_EQ(t20_1.timestamps.size(), 0);
308  ASSERT_EQ(t20_2.timestamps.size(), 0);
309  ASSERT_EQ(timeoutClock_.millisecondsSinceEpoch(), milliseconds(10));
310 }
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void loop(int iters)
TEST_F ( TimeoutTest  ,
DestroyTimeoutSet   
)

Definition at line 315 of file AsyncTimeoutSetTest.cpp.

References ASSERT_EQ, TestTimeout::fn, and loop().

315  {
317  &timeoutManager_, milliseconds(5), milliseconds(0), &timeoutClock_));
319  &timeoutManager_, milliseconds(10), milliseconds(0), &timeoutClock_));
320 
321  TestTimeout t5_1(ts5.get());
322  TestTimeout t5_2(ts5.get());
323  TestTimeout t5_3(ts5.get());
324 
325  TestTimeout t10_1(ts10.get());
326  TestTimeout t10_2(ts10.get());
327 
328  // Have t5_1 destroy ts10
329  t5_1.fn = [&] { ts10.reset(); };
330  // Have t5_2 destroy ts5
331  // Note that this will call destroy() on ts5 inside ts5's timeoutExpired()
332  // method.
333  t5_2.fn = [&] { ts5.reset(); };
334 
335  loop();
336 
337  ASSERT_EQ(t5_1.timestamps.size(), 1);
338  ASSERT_EQ(t5_1.timestamps[0], milliseconds(5));
339  ASSERT_EQ(t5_2.timestamps.size(), 1);
340  ASSERT_EQ(t5_2.timestamps[0], milliseconds(5));
341 
342  ASSERT_EQ(t5_3.timestamps.size(), 0);
343  ASSERT_EQ(t10_1.timestamps.size(), 0);
344  ASSERT_EQ(t10_2.timestamps.size(), 0);
345  ASSERT_EQ(timeoutClock_.millisecondsSinceEpoch(), milliseconds(5));
346 }
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
void loop(int iters)
std::unique_ptr< AsyncTimeoutSet, Destructor > UniquePtr
std::function< void()> fn
TEST_F ( TimeoutTest  ,
AtMostEveryN   
)

Definition at line 352 of file AsyncTimeoutSetTest.cpp.

References ASSERT_EQ, ASSERT_GE, ASSERT_LE, ASSERT_LT, loop(), and uint32_t.

352  {
353  // Create a timeout set with a 25ms interval, to fire no more than once
354  // every 6ms.
355  milliseconds interval(25);
356  milliseconds atMostEveryN(6);
357  StackTimeoutSet ts25(&timeoutManager_, interval, atMostEveryN,
358  &timeoutClock_);
359 
360  // Create 60 timeouts to be added to ts25 at 1ms intervals.
361  uint32_t numTimeouts = 60;
362  std::vector<TestTimeout> timeouts(numTimeouts);
363 
364  // Create a scheduler timeout to add the timeouts 1ms apart.
365  // Note, these will start firing partway through scheduling them
366  for (uint32_t index = 0; index < numTimeouts; index++) {
367  setClock(milliseconds(index));
368  timeouts[index].timeoutExpired();
369  ts25.scheduleTimeout(&timeouts[index]);
370  }
371 
372  loop();
373 
374  // We scheduled timeouts 1ms apart, when the AsyncTimeoutSet is only allowed
375  // to wake up at most once every 3ms. It will therefore wake up every 3ms
376  // and fire groups of approximately 3 timeouts at a time.
377  //
378  // This is "approximately 3" since it may get slightly behind and fire 4 in
379  // one interval, etc. CHECK_TIMEOUT normally allows a few milliseconds of
380  // tolerance. We have to add the same into our checking algorithm here.
381  for (uint32_t idx = 0; idx < numTimeouts; ++idx) {
382  ASSERT_EQ(timeouts[idx].timestamps.size(), 2);
383 
384  auto scheduledTime = timeouts[idx].timestamps[0] + interval;
385  auto firedTime = timeouts[idx].timestamps[1];
386  // Assert that the timeout fired at roughly the right time.
387  // CHECK_TIMEOUT() normally has a tolerance of 5ms. Allow an additional
388  // atMostEveryN.
389  milliseconds tolerance = atMostEveryN;
390  ASSERT_GE(firedTime, scheduledTime);
391  ASSERT_LT(firedTime, scheduledTime + tolerance);
392 
393  // Assert that the difference between the previous timeout and now was
394  // either very small (fired in the same event loop), or larger than
395  // atMostEveryN.
396  if (idx == 0) {
397  // no previous value
398  continue;
399  }
400  auto prev = timeouts[idx - 1].timestamps[1];
401 
402  auto delta = firedTime - prev;
403  if (delta >= milliseconds(1)) {
404  ASSERT_GE(delta, atMostEveryN);
405  }
406  }
407  ASSERT_LE(timeoutClock_.millisecondsSinceEpoch(),
408  milliseconds(numTimeouts) + interval + atMostEveryN);
409 }
#define ASSERT_GE(val1, val2)
Definition: gtest.h:1972
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
#define ASSERT_LT(val1, val2)
Definition: gtest.h:1968
#define ASSERT_LE(val1, val2)
Definition: gtest.h:1964
void loop(int iters)