From e561c43d49ba0c8f28ce98b36ccaf88219d5ea94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Dom=C3=ADnguez=20L=C3=B3pez?= <116071334+Mario-DL@users.noreply.github.com> Date: Fri, 13 Dec 2024 09:19:26 +0100 Subject: [PATCH] Add `flow_control`, `rtps`, `custom_payload_pool` and `content_filter` to windows example ci testing (#5480) * Refs #21660: Flow controller example Signed-off-by: Mario-DL * Refs #21660: RTPS example Signed-off-by: Mario-DL * Refs #21660: Custom PayloadPool example Signed-off-by: Mario-DL * Refs #21660: Additional cmake vars for configuring extra arguments lists Signed-off-by: Mario-DL * Refs #21660: Content Filter example Signed-off-by: Mario-DL * Refs #21660: Add examples to CMakeLists.txt Signed-off-by: Mario-DL --------- Signed-off-by: Mario-DL --- examples/cpp/content_filter/CLIParser.hpp | 7 ++-- examples/cpp/content_filter/SubscriberApp.cpp | 9 ++++- examples/cpp/content_filter/SubscriberApp.hpp | 2 + examples/cpp/rtps/CLIParser.hpp | 40 ++++++++++++++++++- examples/cpp/rtps/WriterApp.cpp | 3 +- examples/cpp/rtps/WriterApp.hpp | 2 + test/examples/CMakeLists.txt | 15 ++++++- test/examples/content_filter.compose.yml | 4 +- test/examples/custom_payload_pool.compose.yml | 2 +- test/examples/rtps.compose.yml | 4 +- test/examples/test_content_filter.py | 26 ++++++------ test/examples/test_custom_payload_pool.py | 2 +- test/examples/test_flow_control.py | 4 +- test/examples/test_rtps.py | 2 +- 14 files changed, 93 insertions(+), 29 deletions(-) diff --git a/examples/cpp/content_filter/CLIParser.hpp b/examples/cpp/content_filter/CLIParser.hpp index de6f13eea3c..e4075588fd5 100644 --- a/examples/cpp/content_filter/CLIParser.hpp +++ b/examples/cpp/content_filter/CLIParser.hpp @@ -64,6 +64,7 @@ class CLIParser //! Subscriber application configuration structure struct subscriber_config { + uint16_t samples = 0; CLIParser::FilterKind filter_kind = CLIParser::FilterKind::DEFAULT; std::string filter_expression = "index between %0 and %1"; std::string upper_bound = "9"; @@ -102,8 +103,8 @@ class CLIParser std::cout << " (Default: Best effort)" << std::endl; std::cout << " --transient-local Set Durability QoS as transient local" << std::endl; std::cout << " (Default: Volatile)" << std::endl; + std::cout << " -s , --samples Number of samples to send/receive" << std::endl; std::cout << "Publisher options:" << std::endl; - std::cout << " -s , --samples Number of samples to send" << std::endl; std::cout << " (Default: 0 [unlimited])" << std::endl; std::cout << " -i , --interval Time between samples in milliseconds" << std::endl; std::cout << " --reader-filters Set the maximum number of readers that the" << std::endl; @@ -191,9 +192,7 @@ class CLIParser } else if (config.entity == CLIParser::EntityKind::SUBSCRIBER) { - EPROSIMA_LOG_ERROR(CLI_PARSER, - "samples option option can only be used with the Publisher"); - print_help(EXIT_FAILURE); + config.sub_config.samples = static_cast(input); } else { diff --git a/examples/cpp/content_filter/SubscriberApp.cpp b/examples/cpp/content_filter/SubscriberApp.cpp index 9c3dc62cdf9..2149555090f 100644 --- a/examples/cpp/content_filter/SubscriberApp.cpp +++ b/examples/cpp/content_filter/SubscriberApp.cpp @@ -46,6 +46,8 @@ SubscriberApp::SubscriberApp( , topic_(nullptr) , reader_(nullptr) , type_(new HelloWorldPubSubType()) + , received_samples_(0) + , samples_(config.samples) , filter_topic_(nullptr) , stop_(false) { @@ -180,6 +182,11 @@ void SubscriberApp::on_subscription_matched( else if (info.current_count_change == -1) { std::cout << "Subscriber unmatched." << std::endl; + + if (received_samples_ > 0 && (received_samples_ >= samples_)) + { + stop(); + } } // Non-valid option else @@ -199,7 +206,7 @@ void SubscriberApp::on_data_available( // Some samples only update the instance state. Only if it is a valid sample (with data) if ((info.instance_state == ALIVE_INSTANCE_STATE) && info.valid_data) { - samples_++; + received_samples_++; // Print structure data std::cout << "Message: '" << hello_.message() << "' with index: '" << hello_.index() << "' RECEIVED" << std::endl; diff --git a/examples/cpp/content_filter/SubscriberApp.hpp b/examples/cpp/content_filter/SubscriberApp.hpp index 256864bead4..07de12cf62b 100644 --- a/examples/cpp/content_filter/SubscriberApp.hpp +++ b/examples/cpp/content_filter/SubscriberApp.hpp @@ -87,6 +87,8 @@ class SubscriberApp : public Application, public DataReaderListener TypeSupport type_; + uint16_t received_samples_; + uint16_t samples_; //! DDS ContentFilteredTopic pointer diff --git a/examples/cpp/rtps/CLIParser.hpp b/examples/cpp/rtps/CLIParser.hpp index 1f95f81b851..3ac3f426947 100644 --- a/examples/cpp/rtps/CLIParser.hpp +++ b/examples/cpp/rtps/CLIParser.hpp @@ -47,6 +47,7 @@ class CLIParser { CLIParser::EntityKind entity = CLIParser::EntityKind::UNDEFINED; uint16_t samples = 0; + uint16_t matched = 1; }; /** @@ -59,7 +60,7 @@ class CLIParser static void print_help( uint8_t return_code) { - std::cout << "Usage: rtps [options]" << std::endl; + std::cout << "Usage: rtps [options]" << std::endl; std::cout << "" << std::endl; std::cout << "Entities:" << std::endl; std::cout << " writer Run a RTPS Writer entity" << std::endl; @@ -70,6 +71,9 @@ class CLIParser std::cout << " -s , --samples Number of samples to send or receive" << std::endl; std::cout << " [0 <= <= 65535]" << std::endl; std::cout << " (Default: 0 [unlimited])" << std::endl; + std::cout << "Writer options:" << std::endl; + std::cout << " -m, --matched Number of readers to match" << std::endl; + std::cout << " before start publishing (Default: 1)" << std::endl; std::exit(return_code); } @@ -152,6 +156,40 @@ class CLIParser print_help(EXIT_FAILURE); } } + else if (arg == "-m" || arg == "--matched") + { + try + { + int input = std::stoi(argv[++i]); + if (input < std::numeric_limits::min() || + input > std::numeric_limits::max()) + { + throw std::out_of_range("matched argument out of range"); + } + else + { + if (config.entity == CLIParser::EntityKind::WRITER) + { + config.matched = static_cast(input); + } + else + { + EPROSIMA_LOG_ERROR(CLI_PARSER, "matched can only be used with the writer entity"); + print_help(EXIT_FAILURE); + } + } + } + catch (const std::invalid_argument& e) + { + EPROSIMA_LOG_ERROR(CLI_PARSER, "invalid sample argument for " + arg + ": " + e.what()); + print_help(EXIT_FAILURE); + } + catch (const std::out_of_range& e) + { + EPROSIMA_LOG_ERROR(CLI_PARSER, "sample argument out of range for " + arg + ": " + e.what()); + print_help(EXIT_FAILURE); + } + } else { EPROSIMA_LOG_ERROR(CLI_PARSER, "unknown option " + arg); diff --git a/examples/cpp/rtps/WriterApp.cpp b/examples/cpp/rtps/WriterApp.cpp index 75acf558f23..611cb10d09e 100644 --- a/examples/cpp/rtps/WriterApp.cpp +++ b/examples/cpp/rtps/WriterApp.cpp @@ -71,6 +71,7 @@ WriterApp::WriterApp( , rtps_writer_(nullptr) , writer_history_(nullptr) , matched_(0) + , expected_matches_(config.matched) , stop_(false) , data_(new HelloWorld) { @@ -210,7 +211,7 @@ bool WriterApp::add_change_to_history() terminate_cv_.wait(matched_lock, [&]() { // at least one has been discovered - return ((matched_ > 0) || is_stopped()); + return ((matched_ >= expected_matches_) || is_stopped()); }); bool ret = false; diff --git a/examples/cpp/rtps/WriterApp.hpp b/examples/cpp/rtps/WriterApp.hpp index b940d5ed56b..572af2881f7 100644 --- a/examples/cpp/rtps/WriterApp.hpp +++ b/examples/cpp/rtps/WriterApp.hpp @@ -86,6 +86,8 @@ class WriterApp : public Application, public WriterListener int16_t matched_; + uint16_t expected_matches_; + std::atomic stop_; mutable std::mutex terminate_cv_mtx_; diff --git a/test/examples/CMakeLists.txt b/test/examples/CMakeLists.txt index bf0c3786b0d..dc5e6484e43 100644 --- a/test/examples/CMakeLists.txt +++ b/test/examples/CMakeLists.txt @@ -61,6 +61,10 @@ if(UNIX AND NOT(APPLE) AND NOT(QNXNTO) AND NOT(ANDROID)) set(COMMAND_CONCATENATE_COMPOSE "&") set(COMMAND_BACKGROUND_JOB_COMPOSE "") + set(SUB_ADDITIONAL_ARGS_COMPOSE "$\${SUB_ADDITIONAL_ARGS_COMPOSE}") + set(PUB_ADDITIONAL_ARGS_COMPOSE "$\${PUB_ADDITIONAL_ARGS_COMPOSE}") + set(SPLIT_ARGS_COMPOSE "") + # Windows configurations elseif(WIN32) # Find pwsh @@ -98,6 +102,10 @@ elseif(WIN32) set(COMMAND_CONCATENATE_COMPOSE "&\" \"") set(COMMAND_BACKGROUND_JOB_COMPOSE "; Receive-Job 1 -Wait") + set(SUB_ADDITIONAL_ARGS_COMPOSE "$\$Env:SUB_ADDITIONAL_ARGS_COMPOSE") + set(PUB_ADDITIONAL_ARGS_COMPOSE "$\$Env:PUB_ADDITIONAL_ARGS_COMPOSE") + set(SPLIT_ARGS_COMPOSE ".split(' ')") + set(WIN_DOCKERFILE ${CMAKE_CURRENT_LIST_DIR}/windows/Dockerfile) # Generate image for testing add_custom_target( @@ -117,7 +125,12 @@ endif() if(WIN32) # Temporarily, test hello world - file(GLOB examples_python_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*world.py) + file(GLOB examples_python_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/test_custom_payload_pool.py + ${CMAKE_CURRENT_SOURCE_DIR}/test_hello_world.py + ${CMAKE_CURRENT_SOURCE_DIR}/test_rtps.py + ${CMAKE_CURRENT_SOURCE_DIR}/test_flow_control.py + ${CMAKE_CURRENT_SOURCE_DIR}/test_content_filter.py) else() # Find all pytest files for testing file(GLOB examples_python_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.py) diff --git a/test/examples/content_filter.compose.yml b/test/examples/content_filter.compose.yml index 8c45f34f2d9..bfd7ef1c590 100644 --- a/test/examples/content_filter.compose.yml +++ b/test/examples/content_filter.compose.yml @@ -23,5 +23,5 @@ services: environment: @PATH_ENVIRONMENT_VARIABLE_COMPOSE@ EXAMPLE_DIR: @EXAMPLE_PREFIX_DIR_COMPOSE@/content_filter/@EXAMPLE_SUFFIX_DIR_COMPOSE@ - SUBSCRIBER_ADDITIONAL_ARGUMENTS: ${SUB_ARGS} - command: @SHELL_EXECUTABLE@ -c "@COMMAND_EXAMPLE_DIR_PREFIX_COMPOSE@/content_filter@FILE_EXTENSION@ subscriber $${SUBSCRIBER_ADDITIONAL_ARGUMENTS} --lower-bound 4 --upper-bound 8 --reliable --transient-local @COMMAND_CONCATENATE_COMPOSE@ @COMMAND_EXAMPLE_DIR_PREFIX_COMPOSE@/content_filter@FILE_EXTENSION@ publisher --samples 15 --interval 100 --reliable --transient-local@COMMAND_BACKGROUND_JOB_COMPOSE@" + SUB_ADDITIONAL_ARGS_COMPOSE: ${SUB_ARGS} + command: @SHELL_EXECUTABLE@ -c "@COMMAND_EXAMPLE_DIR_PREFIX_COMPOSE@/content_filter@FILE_EXTENSION@ subscriber @SUB_ADDITIONAL_ARGS_COMPOSE@@SPLIT_ARGS_COMPOSE@ --lower-bound 4 --upper-bound 8 --reliable --transient-local @COMMAND_CONCATENATE_COMPOSE@ @COMMAND_EXAMPLE_DIR_PREFIX_COMPOSE@/content_filter@FILE_EXTENSION@ publisher --samples 15 --interval 100 --reliable --transient-local@COMMAND_BACKGROUND_JOB_COMPOSE@" diff --git a/test/examples/custom_payload_pool.compose.yml b/test/examples/custom_payload_pool.compose.yml index 1a5aace0654..fc4f8e5621d 100644 --- a/test/examples/custom_payload_pool.compose.yml +++ b/test/examples/custom_payload_pool.compose.yml @@ -23,7 +23,7 @@ services: environment: @PATH_ENVIRONMENT_VARIABLE_COMPOSE@ EXAMPLE_DIR: @EXAMPLE_PREFIX_DIR_COMPOSE@/custom_payload_pool/@EXAMPLE_SUFFIX_DIR_COMPOSE@ - command: @SHELL_EXECUTABLE@ -c "$${EXAMPLE_DIR}/custom_payload_pool@FILE_EXTENSION@ subscriber --samples 10" + command: @SHELL_EXECUTABLE@ -c "@COMMAND_EXAMPLE_DIR_PREFIX_COMPOSE@/custom_payload_pool@FILE_EXTENSION@ subscriber --samples 10" publisher: image: @DOCKER_IMAGE_NAME@ diff --git a/test/examples/rtps.compose.yml b/test/examples/rtps.compose.yml index 71bb61693c4..9d6432b00bc 100644 --- a/test/examples/rtps.compose.yml +++ b/test/examples/rtps.compose.yml @@ -48,7 +48,7 @@ services: environment: @PATH_ENVIRONMENT_VARIABLE_COMPOSE@ EXAMPLE_DIR: @EXAMPLE_PREFIX_DIR_COMPOSE@/rtps/@EXAMPLE_SUFFIX_DIR_COMPOSE@ - command: @SHELL_EXECUTABLE@ -c "@COMMAND_EXAMPLE_DIR_PREFIX_COMPOSE@/rtps@FILE_EXTENSION@ writer --samples 10" + command: @SHELL_EXECUTABLE@ -c "@COMMAND_EXAMPLE_DIR_PREFIX_COMPOSE@/rtps@FILE_EXTENSION@ writer --samples 10 --matched 2" depends_on: - sub-rtps - sub-dds @@ -64,7 +64,7 @@ services: @PATH_ENVIRONMENT_VARIABLE_COMPOSE@ EXAMPLE_DIR: @EXAMPLE_PREFIX_DIR_COMPOSE@/hello_world/@EXAMPLE_SUFFIX_DIR_COMPOSE@ FASTDDS_DEFAULT_PROFILES_FILE: @FASTDDS_DEFAULT_PROFILES_FILE_PREFIX_COMPOSE@/rtps/hello_world_profile.xml - command: @SHELL_EXECUTABLE@ -c "@COMMAND_EXAMPLE_DIR_PREFIX_COMPOSE@/hello_world@FILE_EXTENSION@ publisher --samples 10" + command: @SHELL_EXECUTABLE@ -c "@COMMAND_EXAMPLE_DIR_PREFIX_COMPOSE@/hello_world@FILE_EXTENSION@ publisher --samples 10 --matched 2" depends_on: - sub-rtps - sub-dds diff --git a/test/examples/test_content_filter.py b/test/examples/test_content_filter.py index 058b01ab731..edae21a3f96 100644 --- a/test/examples/test_content_filter.py +++ b/test/examples/test_content_filter.py @@ -15,28 +15,30 @@ import subprocess import pytest import re +import os custom_filter_test_cases = [ - ('', True), - ('', False), - ('--reader-filters 0', True), - ('--reader-filters 0', False)] -@pytest.mark.parametrize("pub_reader_filters, sub_custom_filter", custom_filter_test_cases) -def test_content_filter(pub_reader_filters, sub_custom_filter): + (True), + (False)] +@pytest.mark.parametrize("sub_custom_filter", custom_filter_test_cases) +def test_content_filter(sub_custom_filter): """.""" ret = False out = '' + + menv = dict(os.environ) + if (sub_custom_filter): - command_prerequisites = 'PUB_ARGS="' + ' ' + pub_reader_filters + '" SUB_ARGS="' + ' --filter-kind custom" ' + menv["SUB_ARGS"] = "--filter-kind custom --samples 8" else: - command_prerequisites = 'PUB_ARGS="' + ' ' + pub_reader_filters + '" SUB_ARGS="' + ' --filter-kind default" ' - + menv["SUB_ARGS"] = "--filter-kind default --samples 5" + try: - out = subprocess.check_output(command_prerequisites + - '@DOCKER_EXECUTABLE@ compose -f content_filter.compose.yml up', + out = subprocess.check_output('"@DOCKER_EXECUTABLE@" compose -f content_filter.compose.yml up', stderr=subprocess.STDOUT, shell=True, - timeout=30 + timeout=30, + env=menv ).decode().split('\n') sent = 0 diff --git a/test/examples/test_custom_payload_pool.py b/test/examples/test_custom_payload_pool.py index 12124285310..8831ee61aae 100644 --- a/test/examples/test_custom_payload_pool.py +++ b/test/examples/test_custom_payload_pool.py @@ -20,7 +20,7 @@ def test_custom_payload_pool(): out = '' try: out = subprocess.check_output( - '@DOCKER_EXECUTABLE@ compose -f custom_payload_pool.compose.yml up', + '"@DOCKER_EXECUTABLE@" compose -f custom_payload_pool.compose.yml up', stderr=subprocess.STDOUT, shell=True, timeout=30 diff --git a/test/examples/test_flow_control.py b/test/examples/test_flow_control.py index 6b65995e052..5ffbf511d29 100644 --- a/test/examples/test_flow_control.py +++ b/test/examples/test_flow_control.py @@ -20,10 +20,10 @@ def test_flow_control(): out = '' try: out = subprocess.check_output( - '@DOCKER_EXECUTABLE@ compose -f flow_control.compose.yml up', + '"@DOCKER_EXECUTABLE@" compose -f flow_control.compose.yml up', stderr=subprocess.STDOUT, shell=True, - timeout=30 + timeout=40 ).decode().split('\n') sent = 0 diff --git a/test/examples/test_rtps.py b/test/examples/test_rtps.py index 6fa757ad6d5..fcb274d2727 100644 --- a/test/examples/test_rtps.py +++ b/test/examples/test_rtps.py @@ -20,7 +20,7 @@ def test_rtps(): out = '' try: out = subprocess.check_output( - '@DOCKER_EXECUTABLE@ compose -f rtps.compose.yml up', + '"@DOCKER_EXECUTABLE@" compose -f rtps.compose.yml up', stderr=subprocess.STDOUT, shell=True, timeout=20