diff --git a/rcl/include/rcl/node.h b/rcl/include/rcl/node.h index fafaa04df..6f1c43aa6 100644 --- a/rcl/include/rcl/node.h +++ b/rcl/include/rcl/node.h @@ -33,6 +33,8 @@ extern "C" #include "rcl/types.h" #include "rcl/visibility_control.h" +extern const char * const RCL_DISABLE_LOAN_MSG_ENV_VAR; + typedef struct rcl_node_impl_s rcl_node_impl_t; /// Structure which encapsulates a ROS Node. diff --git a/rcl/src/rcl/node.c b/rcl/src/rcl/node.c index a0aa51d4f..c114cf323 100644 --- a/rcl/src/rcl/node.c +++ b/rcl/src/rcl/node.c @@ -52,6 +52,8 @@ extern "C" #include "./context_impl.h" +const char * const RCL_DISABLE_LOAN_MSG_ENV_VAR = "ROS_DISABLE_LOAN_MSG"; + struct rcl_node_impl_s { rcl_node_options_t options; diff --git a/rcl/src/rcl/publisher.c b/rcl/src/rcl/publisher.c index a3a97471c..7f447257e 100644 --- a/rcl/src/rcl/publisher.c +++ b/rcl/src/rcl/publisher.c @@ -25,6 +25,7 @@ extern "C" #include "rcl/allocator.h" #include "rcl/error_handling.h" #include "rcl/node.h" +#include "rcutils/env.h" #include "rcutils/logging_macros.h" #include "rcutils/macros.h" #include "rcl/time.h" @@ -437,9 +438,19 @@ rcl_publisher_get_actual_qos(const rcl_publisher_t * publisher) bool rcl_publisher_can_loan_messages(const rcl_publisher_t * publisher) { + const char * env_val = NULL; + if (!rcl_publisher_is_valid(publisher)) { return false; // error message already set } + const char * env_error_str = rcutils_get_env(RCL_DISABLE_LOAN_MSG_ENV_VAR, &env_val); + if (NULL != env_error_str) { + RCUTILS_SAFE_FWRITE_TO_STDERR("Error getting env var: "); + RCUTILS_SAFE_FWRITE_TO_STDERR(RCL_DISABLE_LOAN_MSG_ENV_VAR); + RCUTILS_SAFE_FWRITE_TO_STDERR("\n"); + } else if (env_val != NULL && strcmp(env_val, "1") == 0) { + return false; + } return publisher->impl->rmw_handle->can_loan_messages; } diff --git a/rcl/src/rcl/subscription.c b/rcl/src/rcl/subscription.c index fcea1e767..1b5d6bede 100644 --- a/rcl/src/rcl/subscription.c +++ b/rcl/src/rcl/subscription.c @@ -23,6 +23,7 @@ extern "C" #include "rcl/error_handling.h" #include "rcl/node.h" +#include "rcutils/env.h" #include "rcutils/logging_macros.h" #include "rmw/error_handling.h" #include "rmw/validate_full_topic_name.h" @@ -432,9 +433,19 @@ rcl_subscription_get_actual_qos(const rcl_subscription_t * subscription) bool rcl_subscription_can_loan_messages(const rcl_subscription_t * subscription) { + const char * env_val = NULL; + if (!rcl_subscription_is_valid(subscription)) { return false; // error message already set } + const char * env_error_str = rcutils_get_env(RCL_DISABLE_LOAN_MSG_ENV_VAR, &env_val); + if (NULL != env_error_str) { + RCUTILS_SAFE_FWRITE_TO_STDERR("Error getting env var: "); + RCUTILS_SAFE_FWRITE_TO_STDERR(RCL_DISABLE_LOAN_MSG_ENV_VAR); + RCUTILS_SAFE_FWRITE_TO_STDERR("\n"); + } else if (env_val != NULL && strcmp(env_val, "1") == 0) { + return false; + } return subscription->impl->rmw_handle->can_loan_messages; } diff --git a/rcl/test/rcl/test_publisher.cpp b/rcl/test/rcl/test_publisher.cpp index 9c853ccde..d03ccf97a 100644 --- a/rcl/test/rcl/test_publisher.cpp +++ b/rcl/test/rcl/test_publisher.cpp @@ -24,6 +24,8 @@ #include "mimick/mimick.h" #include "osrf_testing_tools_cpp/scope_exit.hpp" #include "rcl/error_handling.h" +#include "rcl/node.h" +#include "rcutils/env.h" #include "rmw/validate_full_topic_name.h" #include "rmw/validate_node_name.h" @@ -370,6 +372,42 @@ TEST_F(CLASSNAME(TestPublisherFixture, RMW_IMPLEMENTATION), test_publisher_loan) } } +TEST_F(CLASSNAME(TestPublisherFixture, RMW_IMPLEMENTATION), test_publisher_loan_disable) { + rcl_publisher_t publisher = rcl_get_zero_initialized_publisher(); + const rosidl_message_type_support_t * ts = + ROSIDL_GET_MSG_TYPE_SUPPORT(test_msgs, msg, BasicTypes); + constexpr char topic_name[] = "pod_msg"; + rcl_publisher_options_t publisher_options = rcl_publisher_get_default_options(); + rcl_ret_t ret = + rcl_publisher_init(&publisher, this->node_ptr, ts, topic_name, &publisher_options); + ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + rcl_ret_t ret = rcl_publisher_fini(&publisher, this->node_ptr); + EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + }); + + if (rcl_publisher_can_loan_messages(&publisher)) { + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "0")); + EXPECT_TRUE(rcl_publisher_can_loan_messages(&publisher)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "1")); + EXPECT_FALSE(rcl_publisher_can_loan_messages(&publisher)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "2")); + EXPECT_TRUE(rcl_publisher_can_loan_messages(&publisher)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "Unexpected")); + EXPECT_TRUE(rcl_publisher_can_loan_messages(&publisher)); + } else { + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "0")); + EXPECT_FALSE(rcl_publisher_can_loan_messages(&publisher)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "1")); + EXPECT_FALSE(rcl_publisher_can_loan_messages(&publisher)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "2")); + EXPECT_FALSE(rcl_publisher_can_loan_messages(&publisher)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "Unexpected")); + EXPECT_FALSE(rcl_publisher_can_loan_messages(&publisher)); + } +} + TEST_F(CLASSNAME(TestPublisherFixture, RMW_IMPLEMENTATION), test_invalid_publisher) { rcl_publisher_t publisher = rcl_get_zero_initialized_publisher(); const rosidl_message_type_support_t * ts = diff --git a/rcl/test/rcl/test_subscription.cpp b/rcl/test/rcl/test_subscription.cpp index adedd7bb9..4641dd735 100644 --- a/rcl/test/rcl/test_subscription.cpp +++ b/rcl/test/rcl/test_subscription.cpp @@ -30,6 +30,8 @@ #include "osrf_testing_tools_cpp/scope_exit.hpp" #include "rcl/error_handling.h" +#include "rcl/node.h" +#include "rcutils/env.h" #include "wait_for_entity_helpers.hpp" #include "./allocator_testing_utils.h" @@ -712,6 +714,42 @@ TEST_F(CLASSNAME(TestSubscriptionFixture, RMW_IMPLEMENTATION), test_subscription } } +TEST_F(CLASSNAME(TestSubscriptionFixture, RMW_IMPLEMENTATION), test_subscription_loan_disable) { + rcl_subscription_t subscription = rcl_get_zero_initialized_subscription(); + const rosidl_message_type_support_t * ts = + ROSIDL_GET_MSG_TYPE_SUPPORT(test_msgs, msg, BasicTypes); + constexpr char topic[] = "pod_msg"; + rcl_subscription_options_t subscription_options = rcl_subscription_get_default_options(); + rcl_ret_t ret = + rcl_subscription_init(&subscription, this->node_ptr, ts, topic, &subscription_options); + ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + rcl_ret_t ret = rcl_subscription_fini(&subscription, this->node_ptr); + EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + }); + + if (rcl_subscription_can_loan_messages(&subscription)) { + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "0")); + EXPECT_TRUE(rcl_subscription_can_loan_messages(&subscription)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "1")); + EXPECT_FALSE(rcl_subscription_can_loan_messages(&subscription)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "2")); + EXPECT_TRUE(rcl_subscription_can_loan_messages(&subscription)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "Unexpected")); + EXPECT_TRUE(rcl_subscription_can_loan_messages(&subscription)); + } else { + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "0")); + EXPECT_FALSE(rcl_subscription_can_loan_messages(&subscription)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "1")); + EXPECT_FALSE(rcl_subscription_can_loan_messages(&subscription)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "2")); + EXPECT_FALSE(rcl_subscription_can_loan_messages(&subscription)); + ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOAN_MSG", "Unexpected")); + EXPECT_FALSE(rcl_subscription_can_loan_messages(&subscription)); + } +} + /* Test for all failure modes in subscription take with loaned messages function. */ TEST_F(CLASSNAME(TestSubscriptionFixture, RMW_IMPLEMENTATION), test_bad_take_loaned_message) {