@@ -447,6 +447,146 @@ TEST_F(TestDefaultStateMachine, bad_mood) {
447447 EXPECT_EQ (1u , test_node->number_of_callbacks );
448448}
449449
450+
451+ TEST_F (TestDefaultStateMachine, shutdown_from_each_primary_state) {
452+ auto success = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
453+ auto reset_key = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
454+
455+ // PRIMARY_STATE_UNCONFIGURED to shutdown
456+ {
457+ auto ret = reset_key;
458+ auto test_node = std::make_shared<EmptyLifecycleNode>(" testnode" );
459+ auto finalized = test_node->shutdown (ret);
460+ EXPECT_EQ (success, ret);
461+ EXPECT_EQ (finalized.id (), State::PRIMARY_STATE_FINALIZED);
462+ }
463+
464+ // PRIMARY_STATE_INACTIVE to shutdown
465+ {
466+ auto ret = reset_key;
467+ auto test_node = std::make_shared<EmptyLifecycleNode>(" testnode" );
468+ auto configured = test_node->configure (ret);
469+ EXPECT_EQ (success, ret);
470+ EXPECT_EQ (configured.id (), State::PRIMARY_STATE_INACTIVE);
471+ ret = reset_key;
472+ auto finalized = test_node->shutdown (ret);
473+ EXPECT_EQ (success, ret);
474+ EXPECT_EQ (finalized.id (), State::PRIMARY_STATE_FINALIZED);
475+ }
476+
477+ // PRIMARY_STATE_ACTIVE to shutdown
478+ {
479+ auto ret = reset_key;
480+ auto test_node = std::make_shared<EmptyLifecycleNode>(" testnode" );
481+ auto configured = test_node->configure (ret);
482+ EXPECT_EQ (success, ret);
483+ EXPECT_EQ (configured.id (), State::PRIMARY_STATE_INACTIVE);
484+ ret = reset_key;
485+ auto activated = test_node->activate (ret);
486+ EXPECT_EQ (success, ret);
487+ EXPECT_EQ (activated.id (), State::PRIMARY_STATE_ACTIVE);
488+ ret = reset_key;
489+ auto finalized = test_node->shutdown (ret);
490+ EXPECT_EQ (success, ret);
491+ EXPECT_EQ (finalized.id (), State::PRIMARY_STATE_FINALIZED);
492+ }
493+
494+ // PRIMARY_STATE_FINALIZED to shutdown
495+ {
496+ auto ret = reset_key;
497+ auto test_node = std::make_shared<EmptyLifecycleNode>(" testnode" );
498+ auto configured = test_node->configure (ret);
499+ EXPECT_EQ (success, ret);
500+ EXPECT_EQ (configured.id (), State::PRIMARY_STATE_INACTIVE);
501+ ret = reset_key;
502+ auto activated = test_node->activate (ret);
503+ EXPECT_EQ (success, ret);
504+ EXPECT_EQ (activated.id (), State::PRIMARY_STATE_ACTIVE);
505+ ret = reset_key;
506+ auto finalized = test_node->shutdown (ret);
507+ EXPECT_EQ (success, ret);
508+ EXPECT_EQ (finalized.id (), State::PRIMARY_STATE_FINALIZED);
509+ ret = reset_key;
510+ auto finalized_again = test_node->shutdown (ret);
511+ EXPECT_EQ (reset_key, ret);
512+ EXPECT_EQ (finalized_again.id (), State::PRIMARY_STATE_FINALIZED);
513+ }
514+ }
515+
516+ TEST_F (TestDefaultStateMachine, test_shutdown_on_dtor) {
517+ auto success = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
518+ auto reset_key = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
519+
520+ bool shutdown_cb_called = false ;
521+ auto on_shutdown_callback =
522+ [&shutdown_cb_called](const rclcpp_lifecycle::State &) ->
523+ rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn {
524+ shutdown_cb_called = true ;
525+ return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
526+ };
527+
528+ // PRIMARY_STATE_UNCONFIGURED to shutdown via dtor
529+ shutdown_cb_called = false ;
530+ {
531+ auto test_node = std::make_shared<rclcpp_lifecycle::LifecycleNode>(" testnode" );
532+ test_node->register_on_shutdown (std::bind (on_shutdown_callback, std::placeholders::_1));
533+ EXPECT_EQ (State::PRIMARY_STATE_UNCONFIGURED, test_node->get_current_state ().id ());
534+ EXPECT_FALSE (shutdown_cb_called);
535+ }
536+ EXPECT_TRUE (shutdown_cb_called);
537+
538+ // PRIMARY_STATE_INACTIVE to shutdown via dtor
539+ shutdown_cb_called = false ;
540+ {
541+ auto ret = reset_key;
542+ auto test_node = std::make_shared<rclcpp_lifecycle::LifecycleNode>(" testnode" );
543+ test_node->register_on_shutdown (std::bind (on_shutdown_callback, std::placeholders::_1));
544+ auto configured = test_node->configure (ret);
545+ EXPECT_EQ (success, ret);
546+ EXPECT_EQ (configured.id (), State::PRIMARY_STATE_INACTIVE);
547+ EXPECT_FALSE (shutdown_cb_called);
548+ }
549+ EXPECT_TRUE (shutdown_cb_called);
550+
551+ // PRIMARY_STATE_ACTIVE to shutdown via dtor
552+ shutdown_cb_called = false ;
553+ {
554+ auto ret = reset_key;
555+ auto test_node = std::make_shared<rclcpp_lifecycle::LifecycleNode>(" testnode" );
556+ test_node->register_on_shutdown (std::bind (on_shutdown_callback, std::placeholders::_1));
557+ auto configured = test_node->configure (ret);
558+ EXPECT_EQ (success, ret);
559+ EXPECT_EQ (configured.id (), State::PRIMARY_STATE_INACTIVE);
560+ ret = reset_key;
561+ auto activated = test_node->activate (ret);
562+ EXPECT_EQ (success, ret);
563+ EXPECT_EQ (activated.id (), State::PRIMARY_STATE_ACTIVE);
564+ EXPECT_FALSE (shutdown_cb_called);
565+ }
566+ EXPECT_TRUE (shutdown_cb_called);
567+
568+ // PRIMARY_STATE_FINALIZED to shutdown via dtor
569+ shutdown_cb_called = false ;
570+ {
571+ auto ret = reset_key;
572+ auto test_node = std::make_shared<rclcpp_lifecycle::LifecycleNode>(" testnode" );
573+ test_node->register_on_shutdown (std::bind (on_shutdown_callback, std::placeholders::_1));
574+ auto configured = test_node->configure (ret);
575+ EXPECT_EQ (success, ret);
576+ EXPECT_EQ (configured.id (), State::PRIMARY_STATE_INACTIVE);
577+ ret = reset_key;
578+ auto activated = test_node->activate (ret);
579+ EXPECT_EQ (success, ret);
580+ EXPECT_EQ (activated.id (), State::PRIMARY_STATE_ACTIVE);
581+ ret = reset_key;
582+ auto finalized = test_node->shutdown (ret);
583+ EXPECT_EQ (success, ret);
584+ EXPECT_EQ (finalized.id (), State::PRIMARY_STATE_FINALIZED);
585+ EXPECT_TRUE (shutdown_cb_called); // should be called already
586+ }
587+ EXPECT_TRUE (shutdown_cb_called);
588+ }
589+
450590TEST_F (TestDefaultStateMachine, lifecycle_subscriber) {
451591 auto test_node = std::make_shared<MoodyLifecycleNode<GoodMood>>(" testnode" );
452592
0 commit comments