diff --git a/image_tools/CMakeLists.txt b/image_tools/CMakeLists.txt index d854faf70..47695bda5 100644 --- a/image_tools/CMakeLists.txt +++ b/image_tools/CMakeLists.txt @@ -52,26 +52,6 @@ if(BUILD_TESTING) set(RCLCPP_DEMO_CAM2IMAGE_EXPECTED_OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/test/cam2image") macro(testing_targets) - set(SKIP_TEST "") - if( - # TODO(wjwwood): connext and connext_dynamic fail with: - # - # COMMENDSrWriterService_write:!write. Reliable large data requires asynchronous writer. - # - # We can remove this disable for connext when that's fixed. - "${rmw_implementation} " STREQUAL "rmw_connext_cpp " OR - "${rmw_implementation} " STREQUAL "rmw_connext_dynamic_cpp " OR - # TODO(wjwwood): fastrtps fails with: - # - # uncaught exception of type std::runtime_error: vector overcomes the maximum length - # - # We can remove this disable for fastrtps when that's fixed. - "${rmw_implementation} " STREQUAL "rmw_fastrtps_cpp " - ) - message(STATUS "Skipping tests for '${rmw_implementation}'") - set(SKIP_TEST "SKIP_TEST") - endif() - set(RCLCPP_DEMO_CAM2IMAGE_EXECUTABLE $) set(RCLCPP_DEMO_SHOWIMAGE_EXECUTABLE $) @@ -80,15 +60,17 @@ if(BUILD_TESTING) test_showimage_cam2image${target_suffix}.py.genexp @ONLY ) + file(GENERATE OUTPUT test_showimage_cam2image${target_suffix}_$.py INPUT test_showimage_cam2image${target_suffix}.py.genexp) ament_add_nose_test(test_showimage_cam2image${target_suffix} "${CMAKE_CURRENT_BINARY_DIR}/test_showimage_cam2image${target_suffix}_$.py" - ENV RMW_IMPLEMENTATION=${rmw_implementation} - TIMEOUT 60 - ${SKIP_TEST} + ENV + RCL_ASSERT_RMW_ID_MATCHES=${rmw_implementation} + RMW_IMPLEMENTATION=${rmw_implementation} + TIMEOUT 30 ) endmacro() diff --git a/image_tools/src/cam2image.cpp b/image_tools/src/cam2image.cpp index e193361db..514599f1e 100644 --- a/image_tools/src/cam2image.cpp +++ b/image_tools/src/cam2image.cpp @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include #include @@ -85,6 +86,11 @@ int main(int argc, char * argv[]) bool burger_mode = false; std::string topic("image"); + // Force flush of the stdout buffer. + // This ensures a correct sync of all prints + // even when executed simultaneously within a launch file. + setvbuf(stdout, NULL, _IONBF, BUFSIZ); + // Configure demo parameters with command line options. bool success = parse_command_options( argc, argv, &depth, &reliability_policy, &history_policy, &show_camera, &freq, &width, &height, diff --git a/image_tools/src/showimage.cpp b/image_tools/src/showimage.cpp index c84ca9970..5ae07b9a4 100644 --- a/image_tools/src/showimage.cpp +++ b/image_tools/src/showimage.cpp @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include #include @@ -92,6 +93,11 @@ int main(int argc, char * argv[]) bool show_camera = true; std::string topic("image"); + // Force flush of the stdout buffer. + // This ensures a correct sync of all prints + // even when executed simultaneously within a launch file. + setvbuf(stdout, NULL, _IONBF, BUFSIZ); + // Configure demo parameters with command line options. if (!parse_command_options( argc, argv, &depth, &reliability_policy, &history_policy, &show_camera, nullptr, nullptr, diff --git a/image_tools/test/cam2image.regex b/image_tools/test/cam2image.regex deleted file mode 100644 index 917645836..000000000 --- a/image_tools/test/cam2image.regex +++ /dev/null @@ -1 +0,0 @@ -Publishing image #100 diff --git a/image_tools/test/cam2image.txt b/image_tools/test/cam2image.txt new file mode 100644 index 000000000..f03d92ed2 --- /dev/null +++ b/image_tools/test/cam2image.txt @@ -0,0 +1,2 @@ +Publishing data on topic 'image' +Publishing image #1 diff --git a/image_tools/test/test_executables_demo.py.in b/image_tools/test/test_executables_demo.py.in index 23b014430..aec46d070 100644 --- a/image_tools/test/test_executables_demo.py.in +++ b/image_tools/test/test_executables_demo.py.in @@ -15,8 +15,10 @@ import os from launch import LaunchDescriptor -from launch.exit_handler import default_exit_handler +from launch.exit_handler import ignore_exit_handler +from launch.exit_handler import primary_ignore_returncode_exit_handler from launch.launcher import DefaultLauncher +from launch.output_handler import ConsoleOutput from launch_testing import create_handler @@ -24,35 +26,61 @@ def setup(): os.environ['OSPL_VERBOSITY'] = '8' # 8 = OS_NONE -def test_executable(): - output_handlers = [] +def test_reliable_qos(): + pub_executable_args = ['-r', '1', '-s', '0', '-b', '-f', '5'] + sub_executable_args = ['-r', '1', '-s', '0', '-b'] + _test_executables(pub_executable_args, sub_executable_args) + +def _test_executables(publisher_executable_args, subscriber_executable_args): + output_handlers = [] launch_descriptor = LaunchDescriptor() + rmw_implementation = '@rmw_implementation@' + env = dict(os.environ) + env['RMW_IMPLEMENTATION'] = rmw_implementation + + # Launch the process that will receive the images. + # This is the process that gets to decide when to tear the launcher down. + # It will exit when the regex for receiving images is matched. showimage_executable = '@RCLCPP_DEMO_SHOWIMAGE_EXECUTABLE@' showimage_output_file = '@RCLCPP_DEMO_SHOWIMAGE_EXPECTED_OUTPUT@' showimage_name = 'test_showimage' - showimage_handler = create_handler(showimage_name, launch_descriptor, showimage_output_file) + showimage_handler = create_handler( + showimage_name, launch_descriptor, showimage_output_file, exit_on_match=True, + filtered_rmw_implementation=rmw_implementation) assert showimage_handler, 'Cannot find appropriate handler for %s' % showimage_output_file output_handlers.append(showimage_handler) + + command = [showimage_executable] + command.extend(subscriber_executable_args) launch_descriptor.add_process( - cmd=[showimage_executable, '-r', '0', '-s', '0'], + cmd=command, name=showimage_name, - exit_handler=default_exit_handler, - output_handlers=[showimage_handler], + exit_handler=primary_ignore_returncode_exit_handler, + output_handlers=[showimage_handler, ConsoleOutput()], + env=env, ) + # Launch the process that will publish the images. + # This process will be exited when the launcher is torn down. cam2image_executable = '@RCLCPP_DEMO_CAM2IMAGE_EXECUTABLE@' cam2image_output_file = '@RCLCPP_DEMO_CAM2IMAGE_EXPECTED_OUTPUT@' cam2image_name = 'test_cam2image' - cam2image_handler = create_handler(cam2image_name, launch_descriptor, cam2image_output_file) + cam2image_handler = create_handler( + cam2image_name, launch_descriptor, cam2image_output_file, exit_on_match=False, + filtered_rmw_implementation=rmw_implementation) assert cam2image_handler, 'Cannot find appropriate handler for %s' % cam2image_output_file output_handlers.append(cam2image_handler) + + command = [cam2image_executable] + command.extend(publisher_executable_args) launch_descriptor.add_process( - cmd=[cam2image_executable, '-r', '0', '-s', '0', '-b'], + cmd=command, name=cam2image_name, - exit_handler=default_exit_handler, - output_handlers=[cam2image_handler], + exit_handler=ignore_exit_handler, + output_handlers=[cam2image_handler, ConsoleOutput()], + env=env, ) launcher = DefaultLauncher() @@ -60,11 +88,11 @@ def test_executable(): rc = launcher.launch() assert rc == 0, \ - "The launch file failed with exit code '" + str(rc) + "'. " \ - 'Maybe the client did not receive any messages?' + "The launch file failed with exit code '" + str(rc) + "'. " + # Check that the output received by the handlers is what was expected. for handler in output_handlers: handler.check() if __name__ == '__main__': - test_executable() + test_reliable_qos()