@@ -612,8 +612,33 @@ TEST_F(TestLoadController, unload_on_kill_does_not_block_other_spawners)
612612 cm_->set_parameter (rclcpp::Parameter (" ctrl_1.type" , test_controller::TEST_CONTROLLER_CLASS_NAME));
613613 cm_->set_parameter (rclcpp::Parameter (" ctrl_2.type" , test_controller::TEST_CONTROLLER_CLASS_NAME));
614614
615+ auto get_active_controller_names = [this ]()
616+ {
617+ std::vector<std::string> active_controller_names;
618+ for (const auto & ctrl : cm_->get_loaded_controllers ())
619+ {
620+ if (
621+ ctrl.c ->get_lifecycle_state ().id () ==
622+ lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE)
623+ {
624+ active_controller_names.push_back (ctrl.info .name );
625+ }
626+ }
627+ return active_controller_names;
628+ };
629+
630+ auto get_loaded_controller_names = [this ]()
631+ {
632+ std::vector<std::string> loaded_controller_names;
633+ for (const auto & ctrl : cm_->get_loaded_controllers ())
634+ {
635+ loaded_controller_names.push_back (ctrl.info .name );
636+ }
637+ return loaded_controller_names;
638+ };
639+
615640 // Run Spawner A with --unload-on-kill in background, keep it alive long enough to ensure
616- // Spawner B cannot succeed by waiting for Spawner A's timeout.
641+ // Spawner B should succeed, in spite of the waiting for Spawner A's timeout.
617642 std::string spawner_a_cmd =
618643 " timeout --signal=INT 12 "
619644 " $(ros2 pkg prefix controller_manager)/lib/controller_manager/spawner "
@@ -655,11 +680,20 @@ TEST_F(TestLoadController, unload_on_kill_does_not_block_other_spawners)
655680 int spawner_b_exit_code = std::system (spawner_b_cmd.c_str ());
656681 EXPECT_EQ (spawner_b_exit_code, 0 )
657682 << " Spawner B should not be blocked by Spawner A's --unload-on-kill lock" ;
683+ ASSERT_THAT (
684+ get_active_controller_names (), testing::UnorderedElementsAre (" ctrl_1" , " ctrl_2" ));
685+
686+ EXPECT_EQ (spawner_a_future.wait_for (std::chrono::seconds (0 )), std::future_status::timeout)
687+ << " Spawner A exited already; lock-contention scenario might not be exercised" ;
658688
659689 // Wait for Spawner A to be killed by timeout and verify it did not exit successfully
660690 int spawner_a_exit_code = spawner_a_future.get ();
661691 EXPECT_NE (spawner_a_exit_code, 0 )
662692 << " Spawner A (wrapped by timeout) unexpectedly exited with success status" ;
693+
694+ // After Spawner A times out, ctrl_1 should be unloaded, leaving only ctrl_2 active.
695+ ASSERT_THAT (get_loaded_controller_names (), testing::UnorderedElementsAre (" ctrl_2" ));
696+ ASSERT_THAT (get_active_controller_names (), testing::UnorderedElementsAre (" ctrl_2" ));
663697}
664698
665699TEST_F (TestLoadController, spawner_test_to_check_parameter_overriding)
0 commit comments