@@ -114,6 +114,102 @@ class TestPreInitTimer : public TestTimerFixture
114114 }
115115};
116116
117+ TEST_F (TestTimerFixture, test_timer_init_with_invalid_arguments) {
118+ rcl_clock_t clock;
119+ rcl_allocator_t allocator = rcl_get_default_allocator ();
120+ rcl_ret_t ret = rcl_clock_init (RCL_STEADY_TIME, &clock, &allocator);
121+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
122+ rcl_timer_t timer = rcl_get_zero_initialized_timer ();
123+
124+ ret = rcl_timer_init (
125+ nullptr , &clock, this ->context_ptr , RCL_MS_TO_NS (50 ), nullptr , allocator);
126+ EXPECT_EQ (RCL_RET_INVALID_ARGUMENT, ret);
127+ rcl_reset_error ();
128+
129+ ret = rcl_timer_init (
130+ &timer, nullptr , this ->context_ptr , RCL_MS_TO_NS (50 ), nullptr , allocator);
131+ EXPECT_EQ (RCL_RET_INVALID_ARGUMENT, ret);
132+ rcl_reset_error ();
133+
134+ ret = rcl_timer_init (
135+ &timer, &clock, nullptr , RCL_MS_TO_NS (50 ), nullptr , allocator);
136+ EXPECT_EQ (RCL_RET_INVALID_ARGUMENT, ret);
137+ rcl_reset_error ();
138+
139+ ret = rcl_timer_init (
140+ &timer, &clock, this ->context_ptr , -1 , nullptr , allocator);
141+ EXPECT_EQ (RCL_RET_INVALID_ARGUMENT, ret);
142+ rcl_reset_error ();
143+
144+ rcl_allocator_t invalid_allocator = rcutils_get_zero_initialized_allocator ();
145+ ret = rcl_timer_init (
146+ &timer, &clock, this ->context_ptr , RCL_MS_TO_NS (50 ), nullptr , invalid_allocator);
147+ EXPECT_EQ (RCL_RET_INVALID_ARGUMENT, ret);
148+ rcl_reset_error ();
149+ }
150+
151+ TEST_F (TestTimerFixture, test_timer_with_invalid_clock) {
152+ rcl_clock_t clock;
153+ rcl_allocator_t allocator = rcl_get_default_allocator ();
154+ rcl_ret_t ret = rcl_clock_init (RCL_CLOCK_UNINITIALIZED, &clock, &allocator);
155+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
156+
157+ rcl_timer_t timer = rcl_get_zero_initialized_timer ();
158+ ret = rcl_timer_init (
159+ &timer, &clock, this ->context_ptr , 0 , nullptr , allocator);
160+ EXPECT_EQ (RCL_RET_ERROR, ret);
161+ rcl_reset_error ();
162+
163+ ret = rcl_clock_init (RCL_ROS_TIME, &clock, &allocator);
164+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
165+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
166+ {
167+ rcl_ret_t ret = rcl_clock_fini (&clock);
168+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
169+ });
170+
171+ ret = rcl_timer_init (
172+ &timer, &clock, this ->context_ptr , 0 , nullptr , allocator);
173+ ASSERT_EQ (RCL_RET_OK, ret);
174+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
175+ {
176+ rcl_ret_t ret = rcl_timer_fini (&timer);
177+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
178+ });
179+
180+ rcl_clock_t * timer_clock;
181+ ret = rcl_timer_clock (&timer, &timer_clock);
182+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
183+ timer_clock->get_now = nullptr ;
184+
185+ // Trigger clock jump callbacks
186+ ret = rcl_enable_ros_time_override (timer_clock);
187+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
188+
189+ ret = rcl_timer_call (&timer);
190+ EXPECT_EQ (RCL_RET_ERROR, ret);
191+ rcl_reset_error ();
192+
193+ int64_t time_until_next_call;
194+ ret = rcl_timer_get_time_until_next_call (&timer, &time_until_next_call);
195+ EXPECT_EQ (RCL_RET_ERROR, ret);
196+ rcl_reset_error ();
197+
198+ bool ready;
199+ ret = rcl_timer_is_ready (&timer, &ready);
200+ EXPECT_EQ (RCL_RET_ERROR, ret);
201+ rcl_reset_error ();
202+
203+ rcl_time_point_value_t time_since_last_call;
204+ ret = rcl_timer_get_time_since_last_call (&timer, &time_since_last_call);
205+ EXPECT_EQ (RCL_RET_ERROR, ret);
206+ rcl_reset_error ();
207+
208+ ret = rcl_timer_reset (&timer);
209+ EXPECT_EQ (RCL_RET_ERROR, ret);
210+ rcl_reset_error ();
211+ }
212+
117213TEST_F (TestTimerFixture, test_two_timers) {
118214 rcl_ret_t ret;
119215
@@ -182,8 +278,9 @@ TEST_F(TestTimerFixture, test_two_timers_ready_before_timeout) {
182278 rcl_timer_t timer = rcl_get_zero_initialized_timer ();
183279 rcl_timer_t timer2 = rcl_get_zero_initialized_timer ();
184280
281+ // Keep the first timer period low enough so that rcl_wait() doesn't timeout too early.
185282 ret = rcl_timer_init (
186- &timer, &clock, this ->context_ptr , RCL_MS_TO_NS (50 ), nullptr , rcl_get_default_allocator ());
283+ &timer, &clock, this ->context_ptr , RCL_MS_TO_NS (10 ), nullptr , rcl_get_default_allocator ());
187284 ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
188285
189286 ret = rcl_timer_init (
@@ -274,6 +371,95 @@ TEST_F(TestTimerFixture, test_timer_not_ready) {
274371 EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
275372}
276373
374+ TEST_F (TestTimerFixture, test_timer_overrun) {
375+ rcl_clock_t clock;
376+ rcl_allocator_t allocator = rcl_get_default_allocator ();
377+ rcl_ret_t ret = rcl_clock_init (RCL_STEADY_TIME, &clock, &allocator);
378+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
379+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
380+ {
381+ rcl_ret_t ret = rcl_clock_fini (&clock);
382+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
383+ });
384+
385+ rcl_timer_t timer = rcl_get_zero_initialized_timer ();
386+ ret = rcl_timer_init (
387+ &timer, &clock, this ->context_ptr , RCL_MS_TO_NS (200 ), nullptr , rcl_get_default_allocator ());
388+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
389+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
390+ {
391+ rcl_ret_t ret = rcl_timer_fini (&timer);
392+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
393+ });
394+
395+ rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set ();
396+ ret = rcl_wait_set_init (&wait_set, 0 , 0 , 1 , 0 , 0 , 0 , context_ptr, rcl_get_default_allocator ());
397+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
398+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
399+ {
400+ rcl_ret_t ret = rcl_wait_set_fini (&wait_set);
401+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
402+ });
403+
404+ // Force multiple timer timeouts.
405+ ret = rcl_wait (&wait_set, RCL_MS_TO_NS (500 ));
406+ EXPECT_EQ (RCL_RET_TIMEOUT, ret) << rcl_get_error_string ().str ;
407+ rcl_reset_error ();
408+
409+ bool is_ready = false ;
410+ ret = rcl_timer_is_ready (&timer, &is_ready);
411+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
412+ EXPECT_TRUE (is_ready);
413+
414+ EXPECT_EQ (RCL_RET_OK, rcl_timer_call (&timer)) << rcl_get_error_string ().str ;
415+
416+ ret = rcl_wait_set_add_timer (&wait_set, &timer, NULL );
417+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
418+
419+ // Ensure period is re-aligned.
420+ ret = rcl_wait (&wait_set, RCL_MS_TO_NS (10 ));
421+ EXPECT_EQ (RCL_RET_TIMEOUT, ret) << rcl_get_error_string ().str ;
422+ rcl_reset_error ();
423+
424+ ret = rcl_timer_is_ready (&timer, &is_ready);
425+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
426+ EXPECT_FALSE (is_ready);
427+ }
428+
429+ TEST_F (TestTimerFixture, test_timer_with_zero_period) {
430+ rcl_clock_t clock;
431+ rcl_allocator_t allocator = rcl_get_default_allocator ();
432+ rcl_ret_t ret = rcl_clock_init (RCL_STEADY_TIME, &clock, &allocator);
433+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
434+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
435+ {
436+ rcl_ret_t ret = rcl_clock_fini (&clock);
437+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
438+ });
439+
440+ rcl_timer_t timer = rcl_get_zero_initialized_timer ();
441+ ret = rcl_timer_init (
442+ &timer, &clock, this ->context_ptr , 0 , nullptr , rcl_get_default_allocator ());
443+ ASSERT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
444+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
445+ {
446+ rcl_ret_t ret = rcl_timer_fini (&timer);
447+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
448+ });
449+
450+ bool is_ready = false ;
451+ ret = rcl_timer_is_ready (&timer, &is_ready);
452+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
453+ EXPECT_TRUE (is_ready) << rcl_get_error_string ().str ;
454+
455+ int64_t time_until_next_call = 0 ;
456+ ret = rcl_timer_get_time_until_next_call (&timer, &time_until_next_call);
457+ EXPECT_EQ (RCL_RET_OK, ret) << rcl_get_error_string ().str ;
458+ EXPECT_LE (time_until_next_call, 0 );
459+
460+ EXPECT_EQ (RCL_RET_OK, rcl_timer_call (&timer)) << rcl_get_error_string ().str ;
461+ }
462+
277463TEST_F (TestTimerFixture, test_canceled_timer) {
278464 rcl_ret_t ret;
279465
@@ -567,6 +753,7 @@ TEST_F(TestPreInitTimer, test_timer_get_allocator) {
567753 EXPECT_TRUE (rcutils_allocator_is_valid (allocator_returned));
568754
569755 EXPECT_EQ (NULL , rcl_timer_get_allocator (nullptr ));
756+ rcl_reset_error ();
570757}
571758
572759TEST_F (TestPreInitTimer, test_timer_clock) {
@@ -599,8 +786,15 @@ TEST_F(TestPreInitTimer, test_timer_call) {
599786 EXPECT_EQ (RCL_RET_OK, rcl_timer_get_time_until_next_call (&timer, &next_call_end));
600787 EXPECT_GT (next_call_start, next_call_end);
601788
789+ EXPECT_EQ (RCL_RET_OK, rcl_enable_ros_time_override (&this ->clock )) << rcl_get_error_string ().str ;
790+ EXPECT_EQ (RCL_RET_OK, rcl_set_ros_time_override (&this ->clock , -1 )) << rcl_get_error_string ().str ;
791+ EXPECT_EQ (RCL_RET_ERROR, rcl_timer_call (&timer));
792+ rcl_reset_error ();
793+ EXPECT_EQ (times_called, 4 );
794+
602795 EXPECT_EQ (RCL_RET_OK, rcl_timer_cancel (&timer)) << rcl_get_error_string ().str ;
603796 EXPECT_EQ (RCL_RET_TIMER_CANCELED, rcl_timer_call (&timer));
797+ rcl_reset_error ();
604798 EXPECT_EQ (times_called, 4 );
605799}
606800
@@ -654,13 +848,15 @@ TEST_F(TestPreInitTimer, test_invalid_init_fini) {
654848 RCL_RET_ALREADY_INIT, rcl_timer_init (
655849 &timer, &clock, this ->context_ptr , 500 , nullptr ,
656850 rcl_get_default_allocator ())) << rcl_get_error_string ().str ;
851+ rcl_reset_error ();
657852
658853 ASSERT_EQ (
659854 RCL_RET_BAD_ALLOC, rcl_timer_init (
660855 &timer_fail, &clock, this ->context_ptr , RCL_S_TO_NS (1 ), timer_callback_test,
661856 bad_allocator)) << rcl_get_error_string ().str ;
857+ rcl_reset_error ();
662858
663- EXPECT_EQ (RCL_RET_OK, rcl_timer_fini (nullptr ));
859+ EXPECT_EQ (RCL_RET_OK, rcl_timer_fini (nullptr )) << rcl_get_error_string (). str ;
664860}
665861
666862TEST_F (TestPreInitTimer, test_timer_get_period) {
@@ -669,14 +865,18 @@ TEST_F(TestPreInitTimer, test_timer_get_period) {
669865 EXPECT_EQ (RCL_S_TO_NS (1 ), period);
670866
671867 EXPECT_EQ (RCL_RET_INVALID_ARGUMENT, rcl_timer_get_period (nullptr , &period));
868+ rcl_reset_error ();
672869 EXPECT_EQ (RCL_RET_INVALID_ARGUMENT, rcl_timer_get_period (&timer, nullptr ));
870+ rcl_reset_error ();
673871}
674872
675873TEST_F (TestPreInitTimer, test_time_since_last_call) {
676874 rcl_time_point_value_t time_sice_next_call_start = 0u ;
677875 rcl_time_point_value_t time_sice_next_call_end = 0u ;
678876
679877 ASSERT_EQ (RCL_RET_OK, rcl_timer_get_time_since_last_call (&timer, &time_sice_next_call_start));
878+ // Cope with coarse system time resolution.
879+ std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
680880 ASSERT_EQ (RCL_RET_OK, rcl_timer_get_time_since_last_call (&timer, &time_sice_next_call_end));
681881 EXPECT_GT (time_sice_next_call_end, time_sice_next_call_start);
682882}
0 commit comments