I have built a very simple test, something like:
#include <ros/node_handle.h>
#include <gtest/gtest.h>
struct SimpleTicker {
SimpleTicker(ros::NodeHandle &nh) : _nh(nh) {
_stateTickTimer = _nh.createTimer(ros::Duration(0.25f),
&SimpleTicker::incrementVal, this, false, true);
}
void incrementVal(const ros::TimerEvent&) {
val++;
}
int val = 0;
ros::Timer _stateTickTimer;
ros::NodeHandle _nh;
};
TEST(SlamManagerTest, run_simple_tick) {
ros::NodeHandle nh(~);
SimpleTicker s(nh);
ros::Duration{1}.sleep();
ASSERT_GT(s.val, 0);
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
ros::init(argc, argv, "simple_timer_test");
ros::NodeHandle nh;
if (ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME,
ros::console::levels::Debug))
{
ros::console::notifyLoggerLevelsChanged(); // show debug output in tests
}
return RUN_ALL_TESTS();
}
This extremely simple test, starts a class with a timer that should call back to increment a value every 0.25 seconds. I launch this with the test file:
<launch>
<test test-name="simple_timer_test" pkg="manager" type="simple_timer_test">
</test>
</launch>
Launched simply with
rostest src/manager/test/simple_timer.test
But the test fails and the value is never incremented. I suspect something is wrong with how I setup rostest to use the clock. Any ideas about this?
So it looks like the system is not spinning. I guess because of this specific way of running rostest
the node, never calls to ros::spin() because it is busy running the tests. So wherever a sleep needs to occur, we need to spin instead, something like this:
template <typename F>
void spin_sleep(ros::Duration duration, F break_condition) {
auto end = ros::Time::now() + duration;
while (end > ros::Time::now() && !break_condition()) {
ros::spinOnce();
}
}
void spin_sleep(ros::Duration duration) {
spin_sleep(duration, []() { return false;});
}
Then instead of sleeping do something like this:
ros::NodeHandle nh(~);
SimpleTicker s(nh);
spin_sleep(ros::Duration{1});
ASSERT_GT(s.val, 0);