3636#include " rclcpp/duration.hpp"
3737#include " rclcpp/guard_condition.hpp"
3838#include " rclcpp/rclcpp.hpp"
39+ #include " rclcpp/time_source.hpp"
3940
4041#include " test_msgs/msg/empty.hpp"
42+ #include " rosgraph_msgs/msg/clock.hpp"
4143
4244using namespace std ::chrono_literals;
4345
@@ -881,6 +883,89 @@ class TimerNode : public rclcpp::Node
881883 int cnt2_ = 0 ;
882884};
883885
886+ // Sets up a separate thread to publish /clock messages.
887+ // Clock rate relative to real clock is controlled by realtime_update_rate.
888+ // This is set conservatively slow to ensure unit tests are reliable on Windows
889+ // environments, where timing performance is subpar.
890+ //
891+ // Use `sleep_for` in tests to advance the clock. Clock should run and be published
892+ // in separate thread continuously to ensure correct behavior in node under test.
893+ class ClockPublisher : public rclcpp ::Node
894+ {
895+ public:
896+ explicit ClockPublisher (float simulated_clock_step = .001f , float realtime_update_rate = 0 .25f )
897+ : Node(" clock_publisher" ),
898+ ros_update_duration_(0 , 0 ),
899+ realtime_clock_step_(0 , 0 ),
900+ rostime_(0 , 0 )
901+ {
902+ clock_publisher_ = this ->create_publisher <rosgraph_msgs::msg::Clock>(" clock" , 10 );
903+ realtime_clock_step_ =
904+ rclcpp::Duration::from_seconds (simulated_clock_step / realtime_update_rate);
905+ ros_update_duration_ = rclcpp::Duration::from_seconds (simulated_clock_step);
906+
907+ timer_thread_ = std::thread (&ClockPublisher::RunTimer, this );
908+ }
909+
910+ ~ClockPublisher ()
911+ {
912+ running_ = false ;
913+ if (timer_thread_.joinable ()) {
914+ timer_thread_.join ();
915+ }
916+ }
917+
918+ void sleep_for (rclcpp::Duration duration)
919+ {
920+ rclcpp::Time start_time (0 , 0 , RCL_ROS_TIME);
921+ {
922+ const std::lock_guard<std::mutex> lock (mutex_);
923+ start_time = rostime_;
924+ }
925+ rclcpp::Time current_time = start_time;
926+
927+ while (true ) {
928+ {
929+ const std::lock_guard<std::mutex> lock (mutex_);
930+ current_time = rostime_;
931+ }
932+ if ((current_time - start_time) >= duration) {
933+ return ;
934+ }
935+ std::this_thread::sleep_for (realtime_clock_step_.to_chrono <std::chrono::milliseconds>());
936+ rostime_ += ros_update_duration_;
937+ }
938+ }
939+
940+ private:
941+ void RunTimer ()
942+ {
943+ while (running_) {
944+ PublishClock ();
945+ std::this_thread::sleep_for (realtime_clock_step_.to_chrono <std::chrono::milliseconds>());
946+ }
947+ }
948+
949+ void PublishClock ()
950+ {
951+ const std::lock_guard<std::mutex> lock (mutex_);
952+ auto message = rosgraph_msgs::msg::Clock ();
953+ message.clock = rostime_;
954+ clock_publisher_->publish (message);
955+ }
956+
957+ rclcpp::Publisher<rosgraph_msgs::msg::Clock>::SharedPtr clock_publisher_;
958+
959+ rclcpp::Duration ros_update_duration_;
960+ rclcpp::Duration realtime_clock_step_;
961+ // Rostime must be guarded by a mutex, since accessible in running thread
962+ // as well as sleep_for
963+ rclcpp::Time rostime_;
964+ std::mutex mutex_;
965+ std::thread timer_thread_;
966+ std::atomic<bool > running_ = true ;
967+ };
968+
884969
885970template <typename T>
886971class TestTimerCancelBehavior : public ::testing::Test
@@ -902,6 +987,17 @@ class TestTimerCancelBehavior : public ::testing::Test
902987 std::stringstream test_name;
903988 test_name << test_info->test_case_name () << " _" << test_info->name ();
904989 node = std::make_shared<TimerNode>(test_name.str ());
990+ param_client = std::make_shared<rclcpp::SyncParametersClient>(node);
991+ ASSERT_TRUE (param_client->wait_for_service (5s));
992+
993+ auto set_parameters_results = param_client->set_parameters (
994+ {rclcpp::Parameter (" use_sim_time" , false )});
995+ for (auto & result : set_parameters_results) {
996+ ASSERT_TRUE (result.successful );
997+ }
998+
999+ // Run standalone thread to publish clock time
1000+ sim_clock_node = std::make_shared<ClockPublisher>();
9051001
9061002 // Spin the executor in a standalone thread
9071003 executor.add_node (this ->node );
@@ -922,6 +1018,8 @@ class TestTimerCancelBehavior : public ::testing::Test
9221018 }
9231019
9241020 std::shared_ptr<TimerNode> node;
1021+ std::shared_ptr<ClockPublisher> sim_clock_node;
1022+ rclcpp::SyncParametersClient::SharedPtr param_client;
9251023 std::thread standalone_thread;
9261024 T executor;
9271025};
@@ -934,16 +1032,16 @@ TYPED_TEST(TestTimerCancelBehavior, testTimer1CancelledWithExecutorSpin) {
9341032 // executor, which is the most common usecase.
9351033
9361034 // Cancel to stop the spin after some time.
937- std::this_thread:: sleep_for (100ms );
1035+ this -> sim_clock_node -> sleep_for (50ms );
9381036 this ->node ->CancelTimer1 ();
939- std::this_thread:: sleep_for (300ms );
1037+ this -> sim_clock_node -> sleep_for (150ms );
9401038 this ->executor .cancel ();
9411039
9421040 int t1_runs = this ->node ->GetTimer1Cnt ();
9431041 int t2_runs = this ->node ->GetTimer2Cnt ();
9441042 EXPECT_NE (t1_runs, t2_runs);
9451043 // Check that t2 has significantly more calls
946- EXPECT_LT (t1_runs + 150 , t2_runs);
1044+ EXPECT_LT (t1_runs + 50 , t2_runs);
9471045}
9481046
9491047TYPED_TEST (TestTimerCancelBehavior, testTimer2CancelledWithExecutorSpin) {
@@ -952,97 +1050,97 @@ TYPED_TEST(TestTimerCancelBehavior, testTimer2CancelledWithExecutorSpin) {
9521050 // executor, which is the most common usecase.
9531051
9541052 // Cancel to stop the spin after some time.
955- std::this_thread:: sleep_for (100ms );
1053+ this -> sim_clock_node -> sleep_for (50ms );
9561054 this ->node ->CancelTimer2 ();
957- std::this_thread:: sleep_for (300ms );
1055+ this -> sim_clock_node -> sleep_for (150ms );
9581056 this ->executor .cancel ();
9591057
9601058 int t1_runs = this ->node ->GetTimer1Cnt ();
9611059 int t2_runs = this ->node ->GetTimer2Cnt ();
9621060 EXPECT_NE (t1_runs, t2_runs);
9631061 // Check that t1 has significantly more calls
964- EXPECT_LT (t2_runs + 150 , t1_runs);
1062+ EXPECT_LT (t2_runs + 50 , t1_runs);
9651063}
9661064
9671065TYPED_TEST (TestTimerCancelBehavior, testHeadTimerCancelThenResetBehavior) {
9681066 // Validate that cancelling timer doesn't affect operation of other timers,
9691067 // and that the cancelled timer starts executing normally once reset manually.
9701068
9711069 // Cancel to stop the spin after some time.
972- std::this_thread:: sleep_for (100ms );
1070+ this -> sim_clock_node -> sleep_for (50ms );
9731071 this ->node ->CancelTimer1 ();
974- std::this_thread:: sleep_for (300ms );
1072+ this -> sim_clock_node -> sleep_for (150ms );
9751073 int t1_runs_initial = this ->node ->GetTimer1Cnt ();
9761074 int t2_runs_initial = this ->node ->GetTimer2Cnt ();
9771075
9781076 // Manually reset timer 1, then sleep again
9791077 // Counts should update.
9801078 this ->node ->ResetTimer1 ();
981- std::this_thread:: sleep_for (300ms );
1079+ this -> sim_clock_node -> sleep_for (150ms );
9821080 int t1_runs_final = this ->node ->GetTimer1Cnt ();
9831081 int t2_runs_final = this ->node ->GetTimer2Cnt ();
9841082
9851083 this ->executor .cancel ();
9861084
9871085 // T1 should have been restarted, and execute about 15 additional times.
9881086 // Check 10 greater than initial, to account for some timing jitter.
989- EXPECT_LT (t1_runs_initial + 150 , t1_runs_final);
1087+ EXPECT_LT (t1_runs_initial + 50 , t1_runs_final);
9901088
991- EXPECT_LT (t1_runs_initial + 150 , t2_runs_initial);
1089+ EXPECT_LT (t1_runs_initial + 50 , t2_runs_initial);
9921090 // Check that t2 has significantly more calls, and keeps getting called.
993- EXPECT_LT (t2_runs_initial + 150 , t2_runs_final);
1091+ EXPECT_LT (t2_runs_initial + 50 , t2_runs_final);
9941092}
9951093
9961094TYPED_TEST (TestTimerCancelBehavior, testBackTimerCancelThenResetBehavior) {
9971095 // Validate that cancelling timer doesn't affect operation of other timers,
9981096 // and that the cancelled timer starts executing normally once reset manually.
9991097
10001098 // Cancel to stop the spin after some time.
1001- std::this_thread:: sleep_for (100ms );
1099+ this -> sim_clock_node -> sleep_for (50ms );
10021100 this ->node ->CancelTimer2 ();
1003- std::this_thread:: sleep_for (300ms );
1101+ this -> sim_clock_node -> sleep_for (150ms );
10041102 int t1_runs_initial = this ->node ->GetTimer1Cnt ();
10051103 int t2_runs_initial = this ->node ->GetTimer2Cnt ();
10061104
10071105 // Manually reset timer 1, then sleep again
10081106 // Counts should update.
10091107 this ->node ->ResetTimer2 ();
1010- std::this_thread:: sleep_for (300ms );
1108+ this -> sim_clock_node -> sleep_for (150ms );
10111109 int t1_runs_final = this ->node ->GetTimer1Cnt ();
10121110 int t2_runs_final = this ->node ->GetTimer2Cnt ();
10131111
10141112 this ->executor .cancel ();
10151113
10161114 // T2 should have been restarted, and execute about 15 additional times.
10171115 // Check 10 greater than initial, to account for some timing jitter.
1018- EXPECT_LT (t2_runs_initial + 150 , t2_runs_final);
1116+ EXPECT_LT (t2_runs_initial + 50 , t2_runs_final);
10191117
1020- EXPECT_LT (t2_runs_initial + 150 , t1_runs_initial);
1118+ EXPECT_LT (t2_runs_initial + 50 , t1_runs_initial);
10211119 // Check that t1 has significantly more calls, and keeps getting called.
1022- EXPECT_LT (t1_runs_initial + 150 , t1_runs_final);
1120+ EXPECT_LT (t1_runs_initial + 50 , t1_runs_final);
10231121}
10241122
10251123TYPED_TEST (TestTimerCancelBehavior, testBothTimerCancelThenResetT1Behavior) {
10261124 // Validate behavior from cancelling 2 timers, then only re-enabling one of them.
10271125 // Ensure that only the reset timer is executed.
10281126
10291127 // Cancel to stop the spin after some time.
1030- std::this_thread:: sleep_for (100ms );
1128+ this -> sim_clock_node -> sleep_for (50ms );
10311129 this ->node ->CancelTimer1 ();
10321130 this ->node ->CancelTimer2 ();
1033- std::this_thread:: sleep_for (300ms );
1131+ this -> sim_clock_node -> sleep_for (150ms );
10341132 int t1_runs_initial = this ->node ->GetTimer1Cnt ();
10351133 int t2_runs_initial = this ->node ->GetTimer2Cnt ();
10361134
10371135 // Manually reset timer 1, then sleep again
10381136 // Counts should update.
10391137 this ->node ->ResetTimer1 ();
1040- std::this_thread:: sleep_for (300ms );
1138+ this -> sim_clock_node -> sleep_for (150ms );
10411139 int t1_runs_intermediate = this ->node ->GetTimer1Cnt ();
10421140 int t2_runs_intermediate = this ->node ->GetTimer2Cnt ();
10431141
10441142 this ->node ->ResetTimer2 ();
1045- std::this_thread:: sleep_for (300ms );
1143+ this -> sim_clock_node -> sleep_for (150ms );
10461144 int t1_runs_final = this ->node ->GetTimer1Cnt ();
10471145 int t2_runs_final = this ->node ->GetTimer2Cnt ();
10481146
@@ -1054,34 +1152,34 @@ TYPED_TEST(TestTimerCancelBehavior, testBothTimerCancelThenResetT1Behavior) {
10541152 // Expect that T1 has up to 15 more calls than t2. Add some buffer
10551153 // to account for jitter.
10561154 EXPECT_EQ (t2_runs_initial, t2_runs_intermediate);
1057- EXPECT_LT (t1_runs_initial + 150 , t1_runs_intermediate);
1155+ EXPECT_LT (t1_runs_initial + 50 , t1_runs_intermediate);
10581156
10591157 // Expect that by end of test, both are running properly again.
1060- EXPECT_LT (t1_runs_intermediate + 150 , t1_runs_final);
1061- EXPECT_LT (t2_runs_intermediate + 150 , t2_runs_final);
1158+ EXPECT_LT (t1_runs_intermediate + 50 , t1_runs_final);
1159+ EXPECT_LT (t2_runs_intermediate + 50 , t2_runs_final);
10621160}
10631161
10641162TYPED_TEST (TestTimerCancelBehavior, testBothTimerCancelThenResetT2Behavior) {
10651163 // Validate behavior from cancelling 2 timers, then only re-enabling one of them.
10661164 // Ensure that only the reset timer is executed.
10671165
10681166 // Cancel to stop the spin after some time.
1069- std::this_thread:: sleep_for (100ms );
1167+ this -> sim_clock_node -> sleep_for (50ms );
10701168 this ->node ->CancelTimer1 ();
10711169 this ->node ->CancelTimer2 ();
1072- std::this_thread:: sleep_for (300ms );
1170+ this -> sim_clock_node -> sleep_for (150ms );
10731171 int t1_runs_initial = this ->node ->GetTimer1Cnt ();
10741172 int t2_runs_initial = this ->node ->GetTimer2Cnt ();
10751173
10761174 // Manually reset timer 1, then sleep again
10771175 // Counts should update.
10781176 this ->node ->ResetTimer2 ();
1079- std::this_thread:: sleep_for (300ms );
1177+ this -> sim_clock_node -> sleep_for (150ms );
10801178 int t1_runs_intermediate = this ->node ->GetTimer1Cnt ();
10811179 int t2_runs_intermediate = this ->node ->GetTimer2Cnt ();
10821180
10831181 this ->node ->ResetTimer1 ();
1084- std::this_thread:: sleep_for (300ms );
1182+ this -> sim_clock_node -> sleep_for (150ms );
10851183 int t1_runs_final = this ->node ->GetTimer1Cnt ();
10861184 int t2_runs_final = this ->node ->GetTimer2Cnt ();
10871185
@@ -1093,9 +1191,9 @@ TYPED_TEST(TestTimerCancelBehavior, testBothTimerCancelThenResetT2Behavior) {
10931191 // Expect that T1 has up to 15 more calls than t2. Add some buffer
10941192 // to account for jitter.
10951193 EXPECT_EQ (t1_runs_initial, t1_runs_intermediate);
1096- EXPECT_LT (t2_runs_initial + 150 , t2_runs_intermediate);
1194+ EXPECT_LT (t2_runs_initial + 50 , t2_runs_intermediate);
10971195
10981196 // Expect that by end of test, both are running properly again.
1099- EXPECT_LT (t1_runs_intermediate + 150 , t1_runs_final);
1100- EXPECT_LT (t2_runs_intermediate + 150 , t2_runs_final);
1197+ EXPECT_LT (t1_runs_intermediate + 50 , t1_runs_final);
1198+ EXPECT_LT (t2_runs_intermediate + 50 , t2_runs_final);
11011199}
0 commit comments