Skip to content

Commit

Permalink
Add support for parsing middle module name from type (#128)
Browse files Browse the repository at this point in the history
* Add support for parsing middle module name from type
Allows support for message types generated from both msg and idl files.

Signed-off-by: David Hodo <david.hodo@is4s.com>

* test fixups and default behavior

Signed-off-by: Karsten Knese <karsten@openrobotics.org>

* deprecate legacy type extraction and add new

Signed-off-by: David Hodo <david.hodo@is4s.com>

* use pragma to avoid deprecation in test

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
  • Loading branch information
davidhodo authored and clalancette committed Jun 12, 2019
1 parent 8c38b88 commit 53646db
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 11 deletions.
6 changes: 6 additions & 0 deletions rosbag2/include/rosbag2/typesupport_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define ROSBAG2__TYPESUPPORT_HELPERS_HPP_

#include <string>
#include <tuple>
#include <utility>

#include "rosidl_generator_cpp/message_type_support_decl.hpp"
Expand All @@ -28,9 +29,14 @@ ROSBAG2_PUBLIC
const rosidl_message_type_support_t *
get_typesupport(const std::string & type, const std::string & typesupport_identifier);

[[deprecated("use extract_type_identifier(const std::string & full_type) instead")]]
ROSBAG2_PUBLIC
const std::pair<std::string, std::string> extract_type_and_package(const std::string & full_type);

ROSBAG2_PUBLIC
const std::tuple<std::string, std::string, std::string>
extract_type_identifier(const std::string & full_type);

} // namespace rosbag2

#endif // ROSBAG2__TYPESUPPORT_HELPERS_HPP_
24 changes: 21 additions & 3 deletions rosbag2/src/rosbag2/typesupport_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <memory>
#include <stdexcept>
#include <string>
#include <tuple>
#include <utility>

#include "ament_index_cpp/get_resources.hpp"
Expand Down Expand Up @@ -62,6 +63,17 @@ std::string get_typesupport_library_path(
}

const std::pair<std::string, std::string> extract_type_and_package(const std::string & full_type)
{
std::string package_name;
std::string type_name;

std::tie(package_name, std::ignore, type_name) = extract_type_identifier(full_type);

return {package_name, type_name};
}

const std::tuple<std::string, std::string, std::string>
extract_type_identifier(const std::string & full_type)
{
char type_separator = '/';
auto sep_position_back = full_type.find_last_of(type_separator);
Expand All @@ -75,17 +87,23 @@ const std::pair<std::string, std::string> extract_type_and_package(const std::st
}

std::string package_name = full_type.substr(0, sep_position_front);
std::string middle_module = "";
if (sep_position_back - sep_position_front > 0) {
middle_module =
full_type.substr(sep_position_front + 1, sep_position_back - sep_position_front - 1);
}
std::string type_name = full_type.substr(sep_position_back + 1);

return {package_name, type_name};
return std::make_tuple(package_name, middle_module, type_name);
}

const rosidl_message_type_support_t *
get_typesupport(const std::string & type, const std::string & typesupport_identifier)
{
std::string package_name;
std::string middle_module;
std::string type_name;
std::tie(package_name, type_name) = extract_type_and_package(type);
std::tie(package_name, middle_module, type_name) = extract_type_identifier(type);

std::string poco_dynamic_loading_error = "Something went wrong loading the typesupport library "
"for message type " + package_name + "/" + type_name + ".";
Expand All @@ -96,7 +114,7 @@ get_typesupport(const std::string & type, const std::string & typesupport_identi
auto typesupport_library = std::make_shared<Poco::SharedLibrary>(library_path);

auto symbol_name = typesupport_identifier + "__get_message_type_support_handle__" +
package_name + "__msg__" + type_name;
package_name + "__" + (middle_module.empty() ? "msg" : middle_module) + "__" + type_name;

if (!typesupport_library->hasSymbol(symbol_name)) {
throw std::runtime_error(poco_dynamic_loading_error + " Symbol not found.");
Expand Down
60 changes: 52 additions & 8 deletions rosbag2/test/rosbag2/test_typesupport_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,25 @@
using namespace ::testing; // NOLINT

TEST(TypesupportHelpersTest, throws_exception_if_filetype_has_no_type) {
EXPECT_ANY_THROW(rosbag2::extract_type_and_package("just_a_package_name"));
EXPECT_ANY_THROW(rosbag2::extract_type_identifier("just_a_package_name"));
}

TEST(TypesupportHelpersTest, throws_exception_if_filetype_has_slash_at_the_start_only) {
EXPECT_ANY_THROW(rosbag2::extract_type_and_package("/name_with_slash_at_start"));
EXPECT_ANY_THROW(rosbag2::extract_type_identifier("/name_with_slash_at_start"));
}

TEST(TypesupportHelpersTest, throws_exception_if_filetype_has_slash_at_the_end_only) {
EXPECT_ANY_THROW(rosbag2::extract_type_and_package("name_with_slash_at_end/"));
EXPECT_ANY_THROW(rosbag2::extract_type_identifier("name_with_slash_at_end/"));
}

TEST(TypesupportHelpersTest, separates_into_package_and_name_for_correct_package) {
#if !defined(_WIN32)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else // !defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
TEST(TypesupportHelpersTest, separates_into_package_and_name_for_correct_package_legacy) {
std::string package;
std::string name;
std::tie(package, name) = rosbag2::extract_type_and_package("package/name");
Expand All @@ -44,24 +51,61 @@ TEST(TypesupportHelpersTest, separates_into_package_and_name_for_correct_package
EXPECT_THAT(name, StrEq("name"));
}

TEST(TypesupportHelpersTest, separates_into_package_and_name_for_multiple_slashes_legacy) {
std::string package;
std::string name;
std::tie(package, name) =
rosbag2::extract_type_and_package("package/middle_module/name");

EXPECT_THAT(package, StrEq("package"));
EXPECT_THAT(name, StrEq("name"));
}
#if !defined(_WIN32)
# pragma GCC diagnostic pop
#else // !defined(_WIN32)
# pragma warning(pop)
#endif

TEST(TypesupportHelpersTest, separates_into_package_and_name_for_correct_package) {
std::string package;
std::string middle_module;
std::string name;
std::tie(package, middle_module, name) = rosbag2::extract_type_identifier("package/name");

EXPECT_THAT(package, StrEq("package"));
EXPECT_THAT(middle_module, StrEq(""));
EXPECT_THAT(name, StrEq("name"));
}

TEST(TypesupportHelpersTest, separates_into_package_and_name_for_multiple_slashes) {
std::string package;
std::string middle_module;
std::string name;
std::tie(package, name) = rosbag2::extract_type_and_package("name/with/multiple_slashes");
std::tie(package, middle_module, name) =
rosbag2::extract_type_identifier("package/middle_module/name");

EXPECT_THAT(package, StrEq("name"));
EXPECT_THAT(name, StrEq("multiple_slashes"));
EXPECT_THAT(package, StrEq("package"));
EXPECT_THAT(middle_module, StrEq("middle_module"));
EXPECT_THAT(name, StrEq("name"));
}

TEST(TypesupportHelpersTest, throws_exception_if_library_cannot_be_found) {
EXPECT_THROW(
rosbag2::get_typesupport("invalid/message", "rosidl_typesupport_cpp"), std::runtime_error);
}

TEST(TypesupportHelpersTest, returns_c_type_info_for_valid_library) {
TEST(TypesupportHelpersTest, returns_c_type_info_for_valid_legacy_library) {
auto string_typesupport =
rosbag2::get_typesupport("test_msgs/BasicTypes", "rosidl_typesupport_cpp");

EXPECT_THAT(std::string(string_typesupport->typesupport_identifier),
ContainsRegex("rosidl_typesupport"));
}

TEST(TypesupportHelpersTest, returns_c_type_info_for_valid_library) {
auto string_typesupport =
rosbag2::get_typesupport("test_msgs/msg/BasicTypes", "rosidl_typesupport_cpp");

EXPECT_THAT(std::string(string_typesupport->typesupport_identifier),
ContainsRegex("rosidl_typesupport"));
}

0 comments on commit 53646db

Please sign in to comment.