Skip to content

Commit c52a938

Browse files
hidmicahcorde
authored andcommitted
Improve rcl timer test coverage. (#680)
Signed-off-by: Michel Hidalgo <[email protected]>
1 parent b254630 commit c52a938

File tree

2 files changed

+219
-9
lines changed

2 files changed

+219
-9
lines changed

rcl/test/CMakeLists.txt

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,23 @@ function(test_target_function)
5050
AMENT_DEPENDENCIES ${rmw_implementation}
5151
)
5252

53+
# TODO(hidmic): re-enable timer tests against RTI Connext once
54+
# https://github.com/ros2/rcl/issues/687 is resolved
55+
set(AMENT_GTEST_ARGS "")
56+
if(rmw_implementation STREQUAL "rmw_connext_cpp")
57+
message(STATUS "Skipping test_timer${target_suffix} test.")
58+
set(AMENT_GTEST_ARGS "SKIP_TEST")
59+
endif()
60+
61+
rcl_add_custom_gtest(test_timer${target_suffix}
62+
SRCS rcl/test_timer.cpp
63+
ENV ${rmw_implementation_env_var}
64+
APPEND_LIBRARY_DIRS ${extra_lib_dirs}
65+
LIBRARIES ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools
66+
AMENT_DEPENDENCIES ${rmw_implementation}
67+
${AMENT_GTEST_ARGS}
68+
)
69+
5370
rcl_add_custom_gtest(test_context${target_suffix}
5471
SRCS rcl/test_context.cpp
5572
ENV ${rmw_implementation_env_var} ${memory_tools_ld_preload_env_var}
@@ -350,13 +367,6 @@ rcl_add_custom_gtest(test_expand_topic_name
350367
LIBRARIES ${PROJECT_NAME}
351368
)
352369

353-
rcl_add_custom_gtest(test_timer${target_suffix}
354-
SRCS rcl/test_timer.cpp
355-
APPEND_LIBRARY_DIRS ${extra_lib_dirs}
356-
LIBRARIES ${PROJECT_NAME}
357-
AMENT_DEPENDENCIES "osrf_testing_tools_cpp"
358-
)
359-
360370
rcl_add_custom_gtest(test_security
361371
SRCS rcl/test_security.cpp
362372
APPEND_LIBRARY_DIRS ${extra_lib_dirs}

rcl/test/rcl/test_timer.cpp

Lines changed: 202 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
117213
TEST_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+
277463
TEST_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

572759
TEST_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

666862
TEST_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

675873
TEST_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

Comments
 (0)