diff --git a/rmw/CMakeLists.txt b/rmw/CMakeLists.txt index 23c94572..93b959e1 100644 --- a/rmw/CMakeLists.txt +++ b/rmw/CMakeLists.txt @@ -32,6 +32,7 @@ set(rmw_sources "src/message_sequence.c" "src/names_and_types.c" "src/publisher_options.c" + "src/qos_string_conversions.c" "src/sanity_checks.c" "src/security_options.c" "src/subscription_options.c" diff --git a/rmw/include/rmw/qos_string_conversions.h b/rmw/include/rmw/qos_string_conversions.h new file mode 100644 index 00000000..27d14dfa --- /dev/null +++ b/rmw/include/rmw/qos_string_conversions.h @@ -0,0 +1,128 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RMW__QOS_STRING_CONVERSIONS_H_ +#define RMW__QOS_STRING_CONVERSIONS_H_ + +#include "rmw/types.h" +#include "rmw/visibility_control.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/// Return a string representing the policy value. +/** + * Returns `NULL` when `value` is `RMW_QOS_POLICY_*_UNKNOWN` or an undefined enum value. + * + * The stringified version of the policy value can be obtained doing the follwing conversion: + * RMW_QOS_POLICY__ -> lower_case() + * + * For example, the stringified version of `RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC` is + * "manual_by_topic" and `RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT` is "best_effort". + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] value qos policy value to be stringified. + * \return a null terminated string representing the policy value, or + * \return `NULL` if value is `RMW_QOS_POLICY_*_UNKNOWN` or an undefined enum value. + */ +RMW_PUBLIC +const char * +rmw_qos_durability_policy_to_str(enum rmw_qos_durability_policy_t value); + +/// Return a string representing the policy value. +/** + * See \ref rmw_qos_durability_policy_to_str() for more details. + */ +RMW_PUBLIC +const char * +rmw_qos_history_policy_to_str(enum rmw_qos_history_policy_t value); + +/// Return a string representing the policy value. +/** + * See \ref rmw_qos_durability_policy_to_str() for more details. + */ +RMW_PUBLIC +const char * +rmw_qos_liveliness_policy_to_str(enum rmw_qos_liveliness_policy_t value); + +/// Return a string representing the policy value. +/** + * See \ref rmw_qos_durability_policy_to_str() for more details. + */ +RMW_PUBLIC +const char * +rmw_qos_reliability_policy_to_str(enum rmw_qos_reliability_policy_t value); + +/// Return a enum value based on the provided string. +/** + * Returns the enum value based on the provided string, or + * `RMW_QOS_POLICY_*_UNKNOWN` when the provided string is unexpected. + * + * How policy values are stringified is explained in \ref rmw_qos_durability_policy_to_str. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] str string identifying a qos policy value. + * \return the policy value represented by the string, or + * \return `RMW_QOS_POLICY_*_UNKNOWN` if the string doesn't represent any value. + */ +RMW_PUBLIC +enum rmw_qos_durability_policy_t +rmw_qos_durability_policy_from_str(const char * str); + +/// Return a enum value based on the provided string. +/** + * See \ref rmw_qos_durability_policy_from_str() for more details. + */ +RMW_PUBLIC +enum rmw_qos_history_policy_t +rmw_qos_history_policy_from_str(const char * str); + +/// Return a enum value based on the provided string. +/** + * See \ref rmw_qos_durability_policy_from_str() for more details. + */ +RMW_PUBLIC +enum rmw_qos_liveliness_policy_t +rmw_qos_liveliness_policy_from_str(const char * str); + + +/// Return a enum value based on the provided string. +/** + * See \ref rmw_qos_durability_policy_from_str() for more details. + */ +RMW_PUBLIC +enum rmw_qos_reliability_policy_t +rmw_qos_reliability_policy_from_str(const char * str); + +#ifdef __cplusplus +} +#endif + +#endif // RMW__QOS_STRING_CONVERSIONS_H_ diff --git a/rmw/src/qos_string_conversions.c b/rmw/src/qos_string_conversions.c new file mode 100644 index 00000000..8a8f0942 --- /dev/null +++ b/rmw/src/qos_string_conversions.c @@ -0,0 +1,142 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rmw/qos_string_conversions.h" + +const char * +rmw_qos_durability_policy_to_str(enum rmw_qos_durability_policy_t value) +{ + switch (value) { + case RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT: + return "system_default"; + case RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL: + return "transient_local"; + case RMW_QOS_POLICY_DURABILITY_VOLATILE: + return "volatile"; + case RMW_QOS_POLICY_DURABILITY_UNKNOWN: // fallthrough + default: + return NULL; + } +} + +const char * +rmw_qos_history_policy_to_str(enum rmw_qos_history_policy_t value) +{ + switch (value) { + case RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT: + return "system_default"; + case RMW_QOS_POLICY_HISTORY_KEEP_LAST: + return "keep_last"; + case RMW_QOS_POLICY_HISTORY_KEEP_ALL: + return "keep_all"; + case RMW_QOS_POLICY_HISTORY_UNKNOWN: // fallthrough + default: + return NULL; + } +} + +const char * +rmw_qos_liveliness_policy_to_str(enum rmw_qos_liveliness_policy_t value) +{ + switch (value) { + case RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT: + return "system_default"; + case RMW_QOS_POLICY_LIVELINESS_AUTOMATIC: + return "automatic"; + case RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC: + return "manual_by_topic"; + case RMW_QOS_POLICY_LIVELINESS_UNKNOWN: // fallthrough + default: + return NULL; + } +} + +const char * +rmw_qos_reliability_policy_to_str(enum rmw_qos_reliability_policy_t value) +{ + switch (value) { + case RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT: + return "system_default"; + case RMW_QOS_POLICY_RELIABILITY_RELIABLE: + return "reliable"; + case RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT: + return "best_effort"; + case RMW_QOS_POLICY_RELIABILITY_UNKNOWN: // fallthrough + default: + return NULL; + } +} + +#define RMW_QOS_STREQ_WITH_LITERAL(string_literal, string) \ + (0 == strncmp(string_literal, str, sizeof(string_literal))) + +enum rmw_qos_durability_policy_t +rmw_qos_durability_policy_from_str(const char * str) +{ + if (RMW_QOS_STREQ_WITH_LITERAL("system_default", str)) { + return RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT; + } + if (RMW_QOS_STREQ_WITH_LITERAL("transient_local", str)) { + return RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL; + } + if (RMW_QOS_STREQ_WITH_LITERAL("volatile", str)) { + return RMW_QOS_POLICY_DURABILITY_VOLATILE; + } + return RMW_QOS_POLICY_DURABILITY_UNKNOWN; +} + +enum rmw_qos_history_policy_t +rmw_qos_history_policy_from_str(const char * str) +{ + if (RMW_QOS_STREQ_WITH_LITERAL("system_default", str)) { + return RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT; + } + if (RMW_QOS_STREQ_WITH_LITERAL("keep_last", str)) { + return RMW_QOS_POLICY_HISTORY_KEEP_LAST; + } + if (RMW_QOS_STREQ_WITH_LITERAL("keep_all", str)) { + return RMW_QOS_POLICY_HISTORY_KEEP_ALL; + } + return RMW_QOS_POLICY_HISTORY_UNKNOWN; +} + +enum rmw_qos_liveliness_policy_t +rmw_qos_liveliness_policy_from_str(const char * str) +{ + if (RMW_QOS_STREQ_WITH_LITERAL("system_default", str)) { + return RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT; + } + if (RMW_QOS_STREQ_WITH_LITERAL("automatic", str)) { + return RMW_QOS_POLICY_LIVELINESS_AUTOMATIC; + } + if (RMW_QOS_STREQ_WITH_LITERAL("manual_by_topic", str)) { + return RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC; + } + return RMW_QOS_POLICY_LIVELINESS_UNKNOWN; +} + +enum rmw_qos_reliability_policy_t +rmw_qos_reliability_policy_from_str(const char * str) +{ + if (RMW_QOS_STREQ_WITH_LITERAL("system_default", str)) { + return RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT; + } + if (RMW_QOS_STREQ_WITH_LITERAL("reliable", str)) { + return RMW_QOS_POLICY_RELIABILITY_RELIABLE; + } + if (RMW_QOS_STREQ_WITH_LITERAL("best_effort", str)) { + return RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT; + } + return RMW_QOS_POLICY_RELIABILITY_UNKNOWN; +} diff --git a/rmw/test/CMakeLists.txt b/rmw/test/CMakeLists.txt index f34824c1..cea827e8 100644 --- a/rmw/test/CMakeLists.txt +++ b/rmw/test/CMakeLists.txt @@ -75,6 +75,15 @@ if(TARGET test_publisher_options) target_link_libraries(test_publisher_options ${PROJECT_NAME}) endif() +ament_add_gtest(test_qos_string_conversions +test_qos_string_conversions.cpp + # Append the directory of librmw so it is found at test time. + APPEND_LIBRARY_DIRS "$" +) +if(TARGET test_qos_string_conversions) + target_link_libraries(test_qos_string_conversions ${PROJECT_NAME}) +endif() + ament_add_gmock(test_sanity_checks test_sanity_checks.cpp # Append the directory of librmw so it is found at test time. diff --git a/rmw/test/test_qos_string_conversions.cpp b/rmw/test/test_qos_string_conversions.cpp new file mode 100644 index 00000000..a024c4d9 --- /dev/null +++ b/rmw/test/test_qos_string_conversions.cpp @@ -0,0 +1,55 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "rmw/qos_string_conversions.h" +#include "rmw/types.h" + +// Converts to string and back to the policy value, check that it's the same +#define TEST_QOS_POLICY_VALUE_STRINGIFY(kind, value) \ + do { \ + EXPECT_EQ( \ + value, rmw_qos_ ## kind ## _policy_from_str(rmw_qos_ ## kind ## _policy_to_str(value))); \ + } while (0) + +// Check unrecognized string as input of from_str, check UNKNOWN as input of to_str. +#define TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(kind, kind_upper) \ + do { \ + EXPECT_EQ( \ + NULL, rmw_qos_ ## kind ## _policy_to_str(RMW_QOS_POLICY_ ## kind_upper ## _UNKNOWN)); \ + EXPECT_EQ( \ + RMW_QOS_POLICY_ ## kind_upper ## _UNKNOWN, \ + rmw_qos_ ## kind ## _policy_from_str("this could never be a stringified policy value")); \ + } while (0) + +TEST(test_qos_policy_stringify, test_normal_use) { + TEST_QOS_POLICY_VALUE_STRINGIFY(durability, RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT); + TEST_QOS_POLICY_VALUE_STRINGIFY(durability, RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL); + TEST_QOS_POLICY_VALUE_STRINGIFY(durability, RMW_QOS_POLICY_DURABILITY_VOLATILE); + TEST_QOS_POLICY_VALUE_STRINGIFY(history, RMW_QOS_POLICY_HISTORY_KEEP_LAST); + TEST_QOS_POLICY_VALUE_STRINGIFY(history, RMW_QOS_POLICY_HISTORY_KEEP_ALL); + TEST_QOS_POLICY_VALUE_STRINGIFY(history, RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT); + TEST_QOS_POLICY_VALUE_STRINGIFY(liveliness, RMW_QOS_POLICY_LIVELINESS_AUTOMATIC); + TEST_QOS_POLICY_VALUE_STRINGIFY(liveliness, RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC); + TEST_QOS_POLICY_VALUE_STRINGIFY(liveliness, RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT); + TEST_QOS_POLICY_VALUE_STRINGIFY(reliability, RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT); + TEST_QOS_POLICY_VALUE_STRINGIFY(reliability, RMW_QOS_POLICY_RELIABILITY_RELIABLE); + TEST_QOS_POLICY_VALUE_STRINGIFY(reliability, RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT); + + TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(durability, DURABILITY); + TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(history, HISTORY); + TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(liveliness, LIVELINESS); + TEST_QOS_POLICY_STRINGIFY_CORNER_CASES(reliability, RELIABILITY); +}