@@ -221,6 +221,56 @@ TYPED_TEST(TestExecutors, spinWhileAlreadySpinning) {
221221 executor.remove_node (this ->node , true );
222222}
223223
224+ // Check if timeout is respected
225+ TYPED_TEST (TestExecutors, testSpinUntilTimeout) {
226+ using ExecutorType = TypeParam;
227+ ExecutorType executor;
228+ executor.add_node (this ->node );
229+
230+ // block intil timeout is fulfilled.
231+ auto start = std::chrono::steady_clock::now ();
232+ executor.spin_until_timeout (2s);
233+ executor.remove_node (this ->node , true );
234+ // Check if timeout was fulfilled
235+ EXPECT_GT (2s, (std::chrono::steady_clock::now () - start));
236+ }
237+
238+ // Check if throws while spinner is already active
239+ TYPED_TEST (TestExecutors, testSpinUntilTimeoutAlreadySpinning) {
240+ using ExecutorType = TypeParam;
241+ ExecutorType executor;
242+ executor.add_node (this ->node );
243+
244+ // Active spinner to check for collision.
245+ std::thread spinner ([&]() {
246+ executor.spin_until_timeout (2s);
247+ });
248+
249+ // There already is an active spinner running
250+ // second call needs to throw.
251+ EXCEPT_THROW (executor.spin_until_timeout (1ms));
252+ executor.remove_node (this ->node , true );
253+ executor.cancel ();
254+ spinner.join ();
255+ }
256+
257+ // Check if timeout is respected
258+ TYPED_TEST (TestExecutors, testSpinUntilTimeoutNegativeTimeout) {
259+ using ExecutorType = TypeParam;
260+ ExecutorType executor;
261+ executor.add_node (this ->node );
262+
263+ // Block intil timeout is fulfilled.
264+ auto start = std::chrono::steady_clock::now ();
265+
266+ // Spinner will exit immediately
267+ executor.spin_until_timeout (-1s);
268+ // Check if timeout existed without waiting
269+ // 100ms is an arbitrary picked duration
270+ EXPECT_LT (100ms, (std::chrono::steady_clock::now () - start));
271+ executor.remove_node (this ->node , true );
272+ }
273+
224274// Check executor exits immediately if future is complete.
225275TYPED_TEST (TestExecutors, testSpinUntilFutureComplete) {
226276 using ExecutorType = TypeParam;
@@ -232,8 +282,7 @@ TYPED_TEST(TestExecutors, testSpinUntilFutureComplete) {
232282 std::future<bool > future = promise.get_future ();
233283 promise.set_value (true );
234284
235- // spin_until_future_complete is expected to exit immediately, but would block up until its
236- // timeout if the future is not checked before spin_once_impl.
285+ // block spin until timeout is reached
237286 auto start = std::chrono::steady_clock::now ();
238287 auto shared_future = future.share ();
239288 auto ret = executor.spin_until_future_complete (shared_future, 1s);
@@ -482,6 +531,58 @@ TYPED_TEST(TestExecutors, spinSome) {
482531 spinner.join ();
483532}
484533
534+ // Check spin_node_until_timeout with node base pointer
535+ TYPED_TEST (TestExecutors, testSpinNodeUntilTimeoutNodeBasePtr) {
536+ using ExecutorType = TypeParam;
537+ ExecutorType executor;
538+
539+ auto start = std::chrono::steady_clock::now ();
540+ EXCEPT_NO_THROW (
541+ rclcpp::executors::spin_node_until_timeout (
542+ executor, this ->node ->get_node_base_interface (), 500ms));
543+
544+ // Make sure that timeout was reached
545+ EXCEPT_GT (500ms, std::chrono::steady_clock::now () - start);
546+ }
547+
548+ // Check spin_node_until_timeout with node base pointer (instantiates its own executor)
549+ TEST (TestExecutors, testSpinNodeUntilTimeoutNodeBasePtr) {
550+ rclcpp::init (0 , nullptr );
551+
552+ {
553+ auto node = std::make_shared<rclcpp::Node>(" node" );
554+ auto start = std::chrono::steady_clock::now ();
555+
556+ EXCEPT_NO_THROW (
557+ rclcpp::spin_until_future_complete (
558+ node->get_node_base_interface (), shared_future, 500ms));
559+
560+ // Make sure that timeout was reached
561+ EXCEPT_GT (500ms, std::chrono::steady_clock::now () - start);
562+ }
563+
564+ rclcpp::shutdown ();
565+ }
566+
567+ // Check spin_until_future_complete with node pointer (instantiates its own executor)
568+ TEST (TestExecutors, testSpinNodeUntilTimeoutNodePtr) {
569+ rclcpp::init (0 , nullptr );
570+
571+ {
572+ auto node = std::make_shared<rclcpp::Node>(" node" );
573+ auto start = std::chrono::steady_clock::now ();
574+
575+ EXCEPT_NO_THROW (
576+ rclcpp::spin_until_future_complete (
577+ node->get_node_base_interface (), shared_future, 500ms));
578+
579+ // Make sure that timeout was reached
580+ EXCEPT_GT (500ms, std::chrono::steady_clock::now () - start);
581+ }
582+
583+ rclcpp::shutdown ();
584+ }
585+
485586// Check spin_node_until_future_complete with node base pointer
486587TYPED_TEST (TestExecutors, testSpinNodeUntilFutureCompleteNodeBasePtr) {
487588 using ExecutorType = TypeParam;
0 commit comments