Skip to content

Commit f2869e0

Browse files
committed
fix flakiness in TestTimersManager check_one_timer_cancel_doesnt_affect_other_timers
the previous version of the test was relying on the assumption that a timer with 1ms period gets called at least 6 times if the main thread waits 15ms. this is true most of the times, but it's not guaranteed, especially when running the test on windows CI servers. the new version of the test makes no assumptions on how much time it takes for the timers manager to invoke the timers, but rather focuses on ensuring that they are called the right amount of times, which is what's important for the purpose of the test Signed-off-by: Alberto Soragna <[email protected]>
1 parent 6c7764e commit f2869e0

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

rclcpp/test/rclcpp/test_timers_manager.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -367,22 +367,23 @@ TEST_F(TestTimersManager, check_one_timer_cancel_doesnt_affect_other_timers)
367367
auto timers_manager = std::make_shared<TimersManager>(
368368
rclcpp::contexts::get_global_default_context());
369369

370-
size_t t1_runs = 0;
370+
std::atomic<size_t> t1_runs = 0;
371+
const size_t cancel_iter = 5;
371372
std::shared_ptr<TimerT> t1;
372373
// After a while cancel t1. Don't remove it though.
373374
// Simulates typical usage in a Node where a timer is cancelled but not removed,
374375
// since typical users aren't going to mess around with the timer manager.
375376
t1 = TimerT::make_shared(
376377
1ms,
377-
[&t1_runs, &t1]() {
378+
[&t1_runs, &t1, cancel_iter]() {
378379
t1_runs++;
379-
if (t1_runs == 5) {
380+
if (t1_runs == cancel_iter) {
380381
t1->cancel();
381382
}
382383
},
383384
rclcpp::contexts::get_global_default_context());
384385

385-
size_t t2_runs = 0;
386+
std::atomic<size_t> t2_runs = 0;
386387
auto t2 = TimerT::make_shared(
387388
1ms,
388389
[&t2_runs]() {
@@ -397,11 +398,30 @@ TEST_F(TestTimersManager, check_one_timer_cancel_doesnt_affect_other_timers)
397398
// Start timers thread
398399
timers_manager->start();
399400

400-
std::this_thread::sleep_for(15ms);
401+
// Wait for t1 to be canceled
402+
while (!t1->is_canceled()) {
403+
std::this_thread::sleep_for(3ms);
404+
}
405+
406+
EXPECT_TRUE(t1->is_canceled());
407+
EXPECT_FALSE(t2->is_canceled());
408+
EXPECT_EQ(t1_runs, cancel_iter);
409+
410+
// Verify that t2 is still being invoked
411+
const size_t start_t2_runs = t2_runs;
412+
const size_t num_t2_extra_runs = 6;
413+
while (t2_runs < start_t2_runs + num_t2_extra_runs) {
414+
std::this_thread::sleep_for(3ms);
415+
}
416+
417+
EXPECT_TRUE(t1->is_canceled());
418+
EXPECT_FALSE(t2->is_canceled());
419+
// t1 hasn't run since before
420+
EXPECT_EQ(t1_runs, cancel_iter);
421+
// t2 has run the expected additional number of times
422+
EXPECT_GE(t2_runs, start_t2_runs + num_t2_extra_runs);
423+
// the t2 runs are strictly more than the t1 runs
424+
EXPECT_GT(t2_runs, t1_runs);
401425

402-
// t1 has stopped running
403-
EXPECT_NE(t1_runs, t2_runs);
404-
// Check that t2 has significantly more calls
405-
EXPECT_LT(t1_runs + 5, t2_runs);
406426
timers_manager->stop();
407427
}

0 commit comments

Comments
 (0)