diff --git a/.gitignore b/.gitignore
index e43b0f9..64eef94 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
.DS_Store
+__pycache__
+*.pyc
diff --git a/rosidl_generator_dds_idl/CMakeLists.txt b/rosidl_generator_dds_idl/CMakeLists.txt
index a12e451..c6feaf6 100644
--- a/rosidl_generator_dds_idl/CMakeLists.txt
+++ b/rosidl_generator_dds_idl/CMakeLists.txt
@@ -8,8 +8,10 @@ find_package(ament_cmake_python REQUIRED)
ament_python_install_package(${PROJECT_NAME})
if(BUILD_TESTING)
+ find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ ament_add_pytest_test(pytest test)
endif()
ament_package(
diff --git a/rosidl_generator_dds_idl/bin/rosidl_generator_dds_idl b/rosidl_generator_dds_idl/bin/rosidl_generator_dds_idl
index d551150..c9872c1 100755
--- a/rosidl_generator_dds_idl/bin/rosidl_generator_dds_idl
+++ b/rosidl_generator_dds_idl/bin/rosidl_generator_dds_idl
@@ -29,13 +29,13 @@ def main(argv=sys.argv[1:]):
help='The Python module extending the generator')
args = parser.parse_args(argv)
- return generate_dds_idl(
+ generate_dds_idl(
args.generator_arguments_file,
args.subfolders,
args.extension,
args.additional_service_templates,
)
-
+ return 0
if __name__ == '__main__':
sys.exit(main())
diff --git a/rosidl_generator_dds_idl/package.xml b/rosidl_generator_dds_idl/package.xml
index 6b9722b..86980c7 100644
--- a/rosidl_generator_dds_idl/package.xml
+++ b/rosidl_generator_dds_idl/package.xml
@@ -13,6 +13,10 @@
ament_cmake
rosidl_cmake
+ ament_index_python
+ rosidl_cli
+
+ ament_cmake_pytest
ament_lint_auto
ament_lint_common
diff --git a/rosidl_generator_dds_idl/pytest.ini b/rosidl_generator_dds_idl/pytest.ini
new file mode 100644
index 0000000..fe55d2e
--- /dev/null
+++ b/rosidl_generator_dds_idl/pytest.ini
@@ -0,0 +1,2 @@
+[pytest]
+junit_family=xunit2
diff --git a/rosidl_generator_dds_idl/rosidl_generator_dds_idl/__init__.py b/rosidl_generator_dds_idl/rosidl_generator_dds_idl/__init__.py
index 00cd04d..1ffc21f 100644
--- a/rosidl_generator_dds_idl/rosidl_generator_dds_idl/__init__.py
+++ b/rosidl_generator_dds_idl/rosidl_generator_dds_idl/__init__.py
@@ -48,8 +48,7 @@ def generate_dds_idl(
if hasattr(module, entity_name):
additional_context[entity_name] = \
getattr(module, entity_name)
- generate_files(generator_arguments_file, mapping, additional_context, keep_case=True)
- return 0
+ return generate_files(generator_arguments_file, mapping, additional_context, keep_case=True)
# used by the template
diff --git a/rosidl_generator_dds_idl/rosidl_generator_dds_idl/cli.py b/rosidl_generator_dds_idl/rosidl_generator_dds_idl/cli.py
new file mode 100644
index 0000000..5bd5d06
--- /dev/null
+++ b/rosidl_generator_dds_idl/rosidl_generator_dds_idl/cli.py
@@ -0,0 +1,60 @@
+# Copyright 2021 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.
+
+import pathlib
+
+from ament_index_python import get_package_share_directory
+from rosidl_cli.command.helpers import legacy_generator_arguments_file
+from rosidl_cli.command.translate.extensions import TranslateCommandExtension
+
+from rosidl_generator_dds_idl import generate_dds_idl
+
+
+class TranslateIDLToDDSIDL(TranslateCommandExtension):
+
+ input_format = 'idl'
+ output_format = 'dds_idl'
+
+ def translate(
+ self,
+ package_name,
+ interface_files,
+ include_paths,
+ output_path
+ ):
+ package_share_path = pathlib.Path(
+ get_package_share_directory('rosidl_generator_dds_idl'))
+ templates_path = package_share_path / 'resource'
+
+ with legacy_generator_arguments_file(
+ package_name=package_name,
+ interface_files=interface_files,
+ include_paths=include_paths,
+ templates_path=templates_path,
+ output_path=output_path
+ ) as path_to_arguments_file:
+ generated_files = generate_dds_idl(
+ path_to_arguments_file,
+ subfolders=[],
+ extension_module_name=None,
+ additional_service_templates=[]
+ )
+ translated_interface_files = []
+ for path in generated_files:
+ path = pathlib.Path(path)
+ relative_path = path.relative_to(output_path)
+ translated_interface_files.append(
+ f'{output_path}:{relative_path.as_posix()}'
+ )
+ return translated_interface_files
diff --git a/rosidl_generator_dds_idl/setup.cfg b/rosidl_generator_dds_idl/setup.cfg
new file mode 100644
index 0000000..c374238
--- /dev/null
+++ b/rosidl_generator_dds_idl/setup.cfg
@@ -0,0 +1,3 @@
+[options.entry_points]
+rosidl_cli.command.translate.extensions =
+ idl2ddsidl = rosidl_generator_dds_idl.cli:TranslateIDLToDDSIDL
diff --git a/rosidl_generator_dds_idl/test/data/msg/Test.idl b/rosidl_generator_dds_idl/test/data/msg/Test.idl
new file mode 100644
index 0000000..71694d3
--- /dev/null
+++ b/rosidl_generator_dds_idl/test/data/msg/Test.idl
@@ -0,0 +1,36 @@
+// generated from rosidl_adapter/resource/msg.idl.em
+// with input from test_msgs/msg/Test.msg
+// generated code does not contain a copyright notice
+
+
+module test_msgs {
+ module msg {
+ struct Test {
+ boolean bool_value;
+
+ octet byte_value;
+
+ uint8 char_value;
+
+ float float32_value;
+
+ double float64_value;
+
+ int8 int8_value;
+
+ uint8 uint8_value;
+
+ int16 int16_value;
+
+ uint16 uint16_value;
+
+ int32 int32_value;
+
+ uint32 uint32_value;
+
+ int64 int64_value;
+
+ uint64 uint64_value;
+ };
+ };
+};
diff --git a/rosidl_generator_dds_idl/test/data/msg/Test_.expected.idl b/rosidl_generator_dds_idl/test/data/msg/Test_.expected.idl
new file mode 100644
index 0000000..bbee4a3
--- /dev/null
+++ b/rosidl_generator_dds_idl/test/data/msg/Test_.expected.idl
@@ -0,0 +1,41 @@
+// generated from rosidl_generator_dds_idl/resource/idl.idl.em
+// with input from test_msgs:msg/Test.idl
+// generated code does not contain a copyright notice
+
+#ifndef __test_msgs__msg__test__idl__
+#define __test_msgs__msg__test__idl__
+
+
+module test_msgs {
+
+module msg {
+
+module dds_ {
+
+
+struct Test_ {
+boolean bool_value_;
+octet byte_value_;
+octet char_value_;
+float float32_value_;
+double float64_value_;
+octet int8_value_;
+octet uint8_value_;
+short int16_value_;
+unsigned short uint16_value_;
+long int32_value_;
+unsigned long uint32_value_;
+long long int64_value_;
+unsigned long long uint64_value_;
+
+};
+
+
+}; // module dds_
+
+}; // module msg
+
+}; // module test_msgs
+
+
+#endif // __test_msgs__msg__test__idl__
diff --git a/rosidl_generator_dds_idl/test/test_cli_extensions.py b/rosidl_generator_dds_idl/test/test_cli_extensions.py
new file mode 100644
index 0000000..3f17444
--- /dev/null
+++ b/rosidl_generator_dds_idl/test/test_cli_extensions.py
@@ -0,0 +1,49 @@
+# Copyright 2021 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.
+
+import filecmp
+import pathlib
+
+from rosidl_cli.command.translate.api import translate
+
+
+DATA_PATH = pathlib.Path(__file__).parent / 'data'
+
+
+def test_idl2ddsidl_translation(tmp_path, capsys):
+ # NOTE(hidmic): pytest and empy do not play along,
+ # the latter expects some proxy will stay in sys.stdout
+ # and the former insists in overwriting it
+ import sys
+ print(sys.path)
+
+ with capsys.disabled():
+ # Test .idl to _.idl translation
+ idl_files = translate(
+ package_name='test_msgs',
+ interface_files=[
+ f'{DATA_PATH}:msg/Test.idl'],
+ output_path=tmp_path,
+ output_format='dds_idl',
+ translators=['idl2ddsidl']
+ )
+
+ assert len(idl_files) == 1
+ idl_file = idl_files[0]
+ assert idl_file == f'{tmp_path}:msg/Test_.idl'
+ assert filecmp.cmp(
+ tmp_path / 'msg' / 'Test_.idl',
+ DATA_PATH / 'msg' / 'Test_.expected.idl',
+ shallow=False
+ )