@@ -321,6 +321,147 @@ TEST_F(WaitSetTestFixture, zero_timeout_overrun_timer) {
321321 EXPECT_LE (diff, RCL_MS_TO_NS (50 ));
322322}
323323
324+ // Test rcl_wait with a timeout value and an overrun timer
325+ TEST_F (WaitSetTestFixture, no_wakeup_on_override_timer) {
326+ rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set ();
327+ rcl_ret_t ret =
328+ rcl_wait_set_init (&wait_set, 0 , 0 , 1 , 0 , 0 , 0 , context_ptr, rcl_get_default_allocator ());
329+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
330+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
331+ {
332+ ret = rcl_wait_set_fini (&wait_set);
333+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
334+ });
335+ rcl_clock_t clock;
336+ rcl_allocator_t allocator = rcl_get_default_allocator ();
337+ ret = rcl_clock_init (RCL_ROS_TIME, &clock, &allocator);
338+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
339+ {
340+ ret = rcl_clock_fini (&clock);
341+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
342+ });
343+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
344+
345+ ret = rcl_enable_ros_time_override (&clock);
346+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
347+
348+ rcl_timer_t timer = rcl_get_zero_initialized_timer ();
349+ ret = rcl_timer_init2 (
350+ &timer, &clock, this ->context_ptr , RCL_MS_TO_NS (10 ), nullptr , rcl_get_default_allocator (),
351+ true );
352+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
353+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
354+ {
355+ ret = rcl_timer_fini (&timer);
356+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
357+ });
358+ ret = rcl_wait_set_add_timer (&wait_set, &timer, NULL );
359+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
360+
361+ // Time spent during wait should be negligible, definitely less than the given timeout
362+ std::chrono::steady_clock::time_point before_sc = std::chrono::steady_clock::now ();
363+ ret = rcl_wait (&wait_set, RCL_MS_TO_NS (100 ));
364+ std::chrono::steady_clock::time_point after_sc = std::chrono::steady_clock::now ();
365+ // We don't expect a timeout here (since the guard condition had already been triggered)
366+ ASSERT_EQ (RCL_RET_TIMEOUT, ret) << rcl_get_error_string ().str ;
367+ int64_t diff = std::chrono::duration_cast<std::chrono::nanoseconds>(after_sc - before_sc).count ();
368+ EXPECT_GE (diff, RCL_MS_TO_NS (100 ));
369+ }
370+
371+ // Test rcl_wait with a timeout value and an overrun timer
372+ TEST_F (WaitSetTestFixture, wakeup_on_override_timer) {
373+ rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set ();
374+ rcl_ret_t ret =
375+ rcl_wait_set_init (&wait_set, 0 , 0 , 1 , 0 , 0 , 0 , context_ptr, rcl_get_default_allocator ());
376+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
377+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
378+ {
379+ ret = rcl_wait_set_fini (&wait_set);
380+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
381+ });
382+ rcl_clock_t clock;
383+ rcl_allocator_t allocator = rcl_get_default_allocator ();
384+ ret = rcl_clock_init (RCL_ROS_TIME, &clock, &allocator);
385+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
386+ {
387+ ret = rcl_clock_fini (&clock);
388+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
389+ });
390+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
391+
392+ ret = rcl_enable_ros_time_override (&clock);
393+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
394+
395+ rcl_timer_t timer = rcl_get_zero_initialized_timer ();
396+ ret = rcl_timer_init2 (
397+ &timer, &clock, this ->context_ptr , RCL_MS_TO_NS (10 ), nullptr , rcl_get_default_allocator (),
398+ true );
399+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
400+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
401+ {
402+ ret = rcl_timer_fini (&timer);
403+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
404+ });
405+ ret = rcl_wait_set_add_timer (&wait_set, &timer, NULL );
406+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
407+
408+ // Time spent during wait should be negligible, definitely less than the given timeout
409+ std::chrono::steady_clock::time_point before_sc = std::chrono::steady_clock::now ();
410+
411+ rcl_ret_t wait_ret = RCL_RET_ERROR;
412+ std::atomic_bool wait_done = false ;
413+ std::thread t ([&wait_ret, &wait_set, &wait_done]() {
414+ wait_ret = rcl_wait (&wait_set, RCL_MS_TO_NS (100 ));
415+ wait_done = true ;
416+ });
417+
418+ ret = rcl_set_ros_time_override (&clock, RCL_MS_TO_NS (5 ));
419+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
420+
421+ std::this_thread::sleep_for (std::chrono::milliseconds (15 ));
422+ EXPECT_EQ (wait_done, false ) << " Error, wait terminated to early" ;
423+
424+ ret = rcl_set_ros_time_override (&clock, RCL_MS_TO_NS (15 ));
425+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
426+
427+ std::this_thread::sleep_for (std::chrono::milliseconds (5 ));
428+
429+ EXPECT_EQ (wait_done, true ) << " Error, wait waken up by time jump" ;
430+
431+ EXPECT_NE (wait_ret, RCL_RET_TIMEOUT);
432+
433+ t.join ();
434+
435+ wait_done = false ;
436+ wait_ret = RCL_RET_ERROR;
437+
438+ ret = rcl_wait_set_clear (&wait_set);
439+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
440+ ret = rcl_wait_set_add_timer (&wait_set, &timer, NULL );
441+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
442+
443+ // now all guard conditions are cleared, if we wait again,
444+ // we should still wake up instantly as next call time was not advance yet
445+ // and therefore the timer should still be ready
446+ t = std::thread (
447+ [&wait_ret, &wait_set, &wait_done]() {
448+ wait_ret = rcl_wait (&wait_set, RCL_MS_TO_NS (100 ));
449+ wait_done = true ;
450+ });
451+
452+ std::this_thread::sleep_for (std::chrono::milliseconds (5 ));
453+
454+ EXPECT_EQ (wait_done, true ) << " Error, wait waken up by time jump" ;
455+
456+ EXPECT_NE (wait_ret, RCL_RET_TIMEOUT);
457+
458+ t.join ();
459+
460+ std::chrono::steady_clock::time_point after_sc = std::chrono::steady_clock::now ();
461+ int64_t diff = std::chrono::duration_cast<std::chrono::nanoseconds>(after_sc - before_sc).count ();
462+ EXPECT_LT (diff, RCL_MS_TO_NS (100 ));
463+ }
464+
324465// Check that a canceled timer doesn't wake up rcl_wait
325466TEST_F (WaitSetTestFixture, canceled_timer) {
326467 rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set ();
0 commit comments