Skip to content
62 changes: 54 additions & 8 deletions controller_manager/test/test_controller_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <gtest/gtest.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "./test_controller/test_controller.hpp"
Expand All @@ -26,17 +27,32 @@
using ::testing::_;
using ::testing::Return;

class TestControllerManager : public ControllerManagerFixture
struct Strictness
{
int strictness = STRICT;
controller_interface::return_type expected_return;
unsigned int expected_counter;
};
class TestControllerManager : public ControllerManagerFixture,
public testing::WithParamInterface<Strictness>
{
};

TEST_F(TestControllerManager, controller_lifecycle)
TEST_P(TestControllerManager, controller_lifecycle)
{
const auto param = GetParam();
auto strictness = param.strictness;
auto expected_return = param.expected_return;
auto expected_counter = param.expected_counter;
Comment thread
Xi-HHHM marked this conversation as resolved.
Outdated
auto test_controller = std::make_shared<test_controller::TestController>();
auto test_controller2 = std::make_shared<test_controller::TestController>();
constexpr char TEST_CONTROLLER2_NAME[] = "test_controller2_name";
cm_->add_controller(
test_controller, test_controller::TEST_CONTROLLER_NAME,
test_controller::TEST_CONTROLLER_CLASS_NAME);
EXPECT_EQ(1u, cm_->get_loaded_controllers().size());
cm_->add_controller(
test_controller2, TEST_CONTROLLER2_NAME, test_controller::TEST_CONTROLLER_CLASS_NAME);
EXPECT_EQ(2u, cm_->get_loaded_controllers().size());
EXPECT_EQ(2, test_controller.use_count());

EXPECT_EQ(
Expand All @@ -50,19 +66,43 @@ TEST_F(TestControllerManager, controller_lifecycle)

// configure controller
cm_->configure_controller(test_controller::TEST_CONTROLLER_NAME);
// Comment out this line on purpose. Otherwise, the test will crash.
Comment thread
Xi-HHHM marked this conversation as resolved.
Outdated
cm_->configure_controller(TEST_CONTROLLER2_NAME);
EXPECT_EQ(
controller_interface::return_type::OK,
cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)));
EXPECT_EQ(0u, test_controller->internal_counter) << "Controller is not started";
EXPECT_EQ(0u, test_controller2->internal_counter) << "Controller is not started";

EXPECT_EQ(lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE, test_controller->get_state().id());

// Start controller, will take effect at the end of the update function
std::vector<std::string> start_controllers = {test_controller::TEST_CONTROLLER_NAME};
std::vector<std::string> start_controllers = {"fake_controller", TEST_CONTROLLER2_NAME};
std::vector<std::string> stop_controllers = {};
auto switch_future = std::async(
std::launch::async, &controller_manager::ControllerManager::switch_controller, cm_,
start_controllers, stop_controllers, STRICT, true, rclcpp::Duration(0, 0));
start_controllers, stop_controllers, strictness, true, rclcpp::Duration(0, 0));

EXPECT_EQ(
controller_interface::return_type::OK,
cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)));
EXPECT_EQ(0u, test_controller2->internal_counter) << "Controller is started at the end of update";
{
ControllerManagerRunner cm_runner(this);
EXPECT_EQ(expected_return, switch_future.get());
Comment thread
Xi-HHHM marked this conversation as resolved.
Outdated
}

EXPECT_EQ(
controller_interface::return_type::OK,
cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)));
EXPECT_GE(test_controller2->internal_counter, expected_counter);
Comment thread
Xi-HHHM marked this conversation as resolved.
Outdated

// Start the real test controller, will take effect at the end of the update function
start_controllers = {test_controller::TEST_CONTROLLER_NAME};
stop_controllers = {};
switch_future = std::async(
std::launch::async, &controller_manager::ControllerManager::switch_controller, cm_,
start_controllers, stop_controllers, strictness, true, rclcpp::Duration(0, 0));
Comment thread
Xi-HHHM marked this conversation as resolved.
Outdated

ASSERT_EQ(std::future_status::timeout, switch_future.wait_for(std::chrono::milliseconds(100)))
<< "switch_controller should be blocking until next update cycle";
Expand All @@ -88,7 +128,7 @@ TEST_F(TestControllerManager, controller_lifecycle)
stop_controllers = {test_controller::TEST_CONTROLLER_NAME};
switch_future = std::async(
std::launch::async, &controller_manager::ControllerManager::switch_controller, cm_,
start_controllers, stop_controllers, STRICT, true, rclcpp::Duration(0, 0));
start_controllers, stop_controllers, strictness, true, rclcpp::Duration(0, 0));
Comment thread
Xi-HHHM marked this conversation as resolved.
Outdated

ASSERT_EQ(std::future_status::timeout, switch_future.wait_for(std::chrono::milliseconds(100)))
<< "switch_controller should be blocking until next update cycle";
Expand Down Expand Up @@ -118,8 +158,9 @@ TEST_F(TestControllerManager, controller_lifecycle)
EXPECT_EQ(1, test_controller.use_count());
}

TEST_F(TestControllerManager, per_controller_update_rate)
TEST_P(TestControllerManager, per_controller_update_rate)
{
auto strictness = GetParam().strictness;
auto test_controller = std::make_shared<test_controller::TestController>();
cm_->add_controller(
test_controller, test_controller::TEST_CONTROLLER_NAME,
Expand Down Expand Up @@ -151,7 +192,7 @@ TEST_F(TestControllerManager, per_controller_update_rate)
std::vector<std::string> stop_controllers = {};
auto switch_future = std::async(
std::launch::async, &controller_manager::ControllerManager::switch_controller, cm_,
start_controllers, stop_controllers, STRICT, true, rclcpp::Duration(0, 0));
start_controllers, stop_controllers, strictness, true, rclcpp::Duration(0, 0));

ASSERT_EQ(std::future_status::timeout, switch_future.wait_for(std::chrono::milliseconds(100)))
<< "switch_controller should be blocking until next update cycle";
Expand All @@ -173,3 +214,8 @@ TEST_F(TestControllerManager, per_controller_update_rate)
EXPECT_GE(test_controller->internal_counter, 1u);
EXPECT_EQ(test_controller->get_update_rate(), 4u);
}

Strictness strict{STRICT, controller_interface::return_type::ERROR, 0u};
Strictness best_effort{BEST_EFFORT, controller_interface::return_type::OK, 1u};
INSTANTIATE_TEST_SUITE_P(
test_strict_best_effort, TestControllerManager, testing::Values(strict, best_effort));