@@ -221,6 +221,56 @@ TYPED_TEST(TestExecutors, spinWhileAlreadySpinning) {
221
221
executor.remove_node (this ->node , true );
222
222
}
223
223
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
+
224
274
// Check executor exits immediately if future is complete.
225
275
TYPED_TEST (TestExecutors, testSpinUntilFutureComplete) {
226
276
using ExecutorType = TypeParam;
@@ -232,8 +282,7 @@ TYPED_TEST(TestExecutors, testSpinUntilFutureComplete) {
232
282
std::future<bool > future = promise.get_future ();
233
283
promise.set_value (true );
234
284
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
237
286
auto start = std::chrono::steady_clock::now ();
238
287
auto shared_future = future.share ();
239
288
auto ret = executor.spin_until_future_complete (shared_future, 1s);
@@ -482,6 +531,58 @@ TYPED_TEST(TestExecutors, spinSome) {
482
531
spinner.join ();
483
532
}
484
533
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
+
485
586
// Check spin_node_until_future_complete with node base pointer
486
587
TYPED_TEST (TestExecutors, testSpinNodeUntilFutureCompleteNodeBasePtr) {
487
588
using ExecutorType = TypeParam;
0 commit comments