From 4ab0ba44e52356eccd81e262d48e1e96966805ce Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Tue, 16 Jan 2024 14:53:06 +0100 Subject: [PATCH 01/44] Adding some messages to improve debuggability --- srcCxx/shape_main.cxx | 48 ++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 8460381b..2f0c9bb3 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -56,7 +56,9 @@ using namespace DDS; - +#define ERROR_PARSING_ARGUMENTS 1 +#define ERROR_INITIALIZING 2 +#define ERROR_RUNNING 3 /*************************************************************/ int all_done = 0; @@ -309,6 +311,7 @@ class ShapeOptions { //------------------------------------------------------------- bool parse(int argc, char *argv[]) { + logger.log_message("Running parse() function", Verbosity::DEBUG); int opt; bool parse_ok = true; // double d; @@ -733,6 +736,8 @@ class ShapeApplication { #ifndef OBTAIN_DOMAIN_PARTICIPANT_FACTORY #define OBTAIN_DOMAIN_PARTICIPANT_FACTORY DomainParticipantFactory::get_instance() #endif + logger.log_message("Running initialize() function", Verbosity::DEBUG); + DomainParticipantFactory *dpf = OBTAIN_DOMAIN_PARTICIPANT_FACTORY; if (dpf == NULL) { logger.log_message("failed to create participant factory (missing license?).", Verbosity::ERROR); @@ -772,6 +777,7 @@ class ShapeApplication { //------------------------------------------------------------- bool run(ShapeOptions *options) { + logger.log_message("Running run() function", Verbosity::DEBUG); if ( pub != NULL ) { return run_publisher(options); } @@ -785,7 +791,7 @@ class ShapeApplication { //------------------------------------------------------------- bool init_publisher(ShapeOptions *options) { - logger.log_message("Initializing Publisher", Verbosity::DEBUG); + logger.log_message("Running init_publisher() function", Verbosity::DEBUG); PublisherQos pub_qos; DataWriterQos dw_qos; ShapeType shape; @@ -817,7 +823,7 @@ class ShapeApplication { #elif defined(TWINOAKS_COREDX) dw_qos.representation.value.clear( ); dw_qos.representation.value.push_back( options->data_representation ); - + #elif defined(OPENDDS) dw_qos.representation.value.length(1); dw_qos.representation.value[0] = options->data_representation; @@ -883,6 +889,7 @@ class ShapeApplication { //------------------------------------------------------------- bool init_subscriber(ShapeOptions *options) { + logger.log_message("Running init_subscriber() function", Verbosity::DEBUG); SubscriberQos sub_qos; DataReaderQos dr_qos; @@ -926,7 +933,7 @@ class ShapeApplication { logger.log_message(" Ownership = " + QosUtils::to_string(dr_qos.ownership FIELD_ACCESSOR.kind), Verbosity::DEBUG); if ( options->timebasedfilter_interval > 0) { dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME = options->timebasedfilter_interval; - dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec = 0; + dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec = 0; } logger.log_message(" TimeBasedFilter = " + std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME), Verbosity::DEBUG); @@ -962,15 +969,18 @@ class ShapeApplication { sprintf(parameter, "'%s'", options->color); StringSeq_push(cf_params, parameter); cft = dp->create_contentfilteredtopic(filtered_topic_name, topic, "color MATCH %0", cf_params); - logger.log_message(" ContentFilterTopic = color MATCH " + std::string(parameter), Verbosity::DEBUG); + logger.log_message(" ContentFilterTopic = \"color MATCH " + + std::string(parameter) + std::string("\""), Verbosity::DEBUG); #elif defined(TWINOAKS_COREDX) || defined(OPENDDS) StringSeq_push(cf_params, options->color); cft = dp->create_contentfilteredtopic(filtered_topic_name, topic, "color = %0", cf_params); - logger.log_message(" ContentFilterTopic = color = " + std::string(options->color), Verbosity::DEBUG); + logger.log_message(" ContentFilterTopic = \"color = " + + std::string(options->color) + std::string("\""), Verbosity::DEBUG); #elif defined(EPROSIMA_FAST_DDS) cf_params.push_back(std::string("'") + options->color + std::string("'")); cft = dp->create_contentfilteredtopic(filtered_topic_name, topic, "color = %0", cf_params); - logger.log_message(" ContentFilterTopic = color = " + std::string(options->color), Verbosity::DEBUG); + logger.log_message(" ContentFilterTopic = \"color = " + + cf_params[0] + std::string("\""), Verbosity::DEBUG); #endif if (cft == NULL) { logger.log_message("failed to create content filtered topic", Verbosity::ERROR); @@ -997,7 +1007,9 @@ class ShapeApplication { //------------------------------------------------------------- bool run_subscriber() { - while ( ! all_done ) { + logger.log_message("Running run_subscriber() function", Verbosity::DEBUG); + + while ( ! all_done ) { ReturnCode_t retval; SampleInfoSeq sample_infos; @@ -1013,6 +1025,7 @@ class ShapeApplication { InstanceHandle_t previous_handle = HANDLE_NIL; do { + logger.log_message("Calling take_next_instance() function", Verbosity::DEBUG); #if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) || defined(EPROSIMA_FAST_DDS) retval = dr->take_next_instance ( samples, sample_infos, @@ -1033,8 +1046,11 @@ class ShapeApplication { if (retval == RETCODE_OK) { auto n_samples = samples.length(); + logger.log_message("Read " + std::to_string(samples.length()) + + " sample(s), printing them...", Verbosity::DEBUG); for (decltype(n_samples) i = 0; i < n_samples; i++) { - + logger.log_message("Processing sample " + std::to_string(i), + Verbosity::DEBUG); #if defined(RTI_CONNEXT_DDS) ShapeType *sample = &samples[i]; SampleInfo *sample_info = &sample_infos[i]; @@ -1101,6 +1117,7 @@ class ShapeApplication { //------------------------------------------------------------- bool run_publisher(ShapeOptions *options) { + logger.log_message("Running run_publisher() function", Verbosity::DEBUG); ShapeType shape; #if defined(RTI_CONNEXT_DDS) ShapeType_initialize(&shape); @@ -1124,7 +1141,7 @@ class ShapeApplication { xvel = ((random() % 5) + 1) * ((random()%2)?-1:1); yvel = ((random() % 5) + 1) * ((random()%2)?-1:1);; - while ( ! all_done ) { + while ( ! all_done ) { moveShape(&shape); #if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) dw->write( shape, HANDLE_NIL ); @@ -1150,16 +1167,19 @@ int main( int argc, char * argv[] ) install_sig_handlers(); ShapeOptions options; + logger.log_message("Parsing command line parameters...", Verbosity::DEBUG); bool parseResult = options.parse(argc, argv); - if ( !parseResult ) { - exit(1); + if ( !parseResult ) { + exit(ERROR_PARSING_ARGUMENTS); } + logger.log_message("Initializing ShapeApp...", Verbosity::DEBUG); ShapeApplication shapeApp; if ( !shapeApp.initialize(&options) ) { - exit(2); + exit(ERROR_INITIALIZING); } + logger.log_message("Running ShapeApp...", Verbosity::DEBUG); if ( !shapeApp.run(&options) ) { - exit(2); + exit(ERROR_RUNNING); } printf("Done.\n"); From 15fad25423d6ecd29ba3eea9f2c0d4b88d46f2fc Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Tue, 16 Jan 2024 14:59:37 +0100 Subject: [PATCH 02/44] printing only the name of the error instead of the enum element for expected code --- interoperability_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interoperability_report.py b/interoperability_report.py index dd06400a..f1763d53 100644 --- a/interoperability_report.py +++ b/interoperability_report.py @@ -531,7 +531,7 @@ def run_test( else: print(f'{test_case.name} : ERROR') for i in range(0, num_entities): - print(f'{entity_type[i]} expected code: {expected_codes[i]}; ' + print(f'{entity_type[i]} expected code: {expected_codes[i].name}; ' f'Code found: {return_codes[i].name}') log_message(f'\nInformation about {entity_type[i]}:\n ' From a57efcce66f65934f5e48726c0da8076fb12f552 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Tue, 16 Jan 2024 15:54:33 +0100 Subject: [PATCH 03/44] Update srcCxx/shape_main.cxx Co-authored-by: Miguel Company --- srcCxx/shape_main.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 2f0c9bb3..ceb3f313 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -1046,7 +1046,7 @@ class ShapeApplication { if (retval == RETCODE_OK) { auto n_samples = samples.length(); - logger.log_message("Read " + std::to_string(samples.length()) + logger.log_message("Read " + std::to_string(n_samples) + " sample(s), printing them...", Verbosity::DEBUG); for (decltype(n_samples) i = 0; i < n_samples; i++) { logger.log_message("Processing sample " + std::to_string(i), From ada7616470f552a2396f2a3db2666b11965f9c48 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Thu, 29 Feb 2024 15:40:47 +0100 Subject: [PATCH 04/44] Adding preliminary port to micro --- .gitignore | 7 + srcCxx/makefile_rti_connext_micro_linux | 82 +++ srcCxx/shape_configurator_rti_connext_micro.h | 52 ++ srcCxx/shape_main.cxx | 582 ++++++++++-------- srcCxx/shape_micro.idl | 8 + 5 files changed, 467 insertions(+), 264 deletions(-) create mode 100644 srcCxx/makefile_rti_connext_micro_linux create mode 100644 srcCxx/shape_configurator_rti_connext_micro.h create mode 100644 srcCxx/shape_micro.idl diff --git a/.gitignore b/.gitignore index c89dc45b..aad529a3 100644 --- a/.gitignore +++ b/.gitignore @@ -51,7 +51,14 @@ srcCxx/shape.* srcCxx/shapePlugin.* srcCxx/shapeSupport.* +srcCxx/shape_micro.cxx +srcCxx/shape_micro.h +srcCxx/shape_microPlugin.* +srcCxx/shape_microSupport.* + .vscode/ # Generated reports *.html + +.DS_Store diff --git a/srcCxx/makefile_rti_connext_micro_linux b/srcCxx/makefile_rti_connext_micro_linux new file mode 100644 index 00000000..d1c532f4 --- /dev/null +++ b/srcCxx/makefile_rti_connext_micro_linux @@ -0,0 +1,82 @@ +###################################################################### +# To compile, type: +# make -f makefile_rti_connext_dds_linux +# To compile with the Debug option, use: +# make -f makefile_rti_connext_dds_linux DEBUG=1 +# +# This makefile assumes that your build environment is already correctly +# configured. (For example, the correct version of your compiler and +# linker should be on your PATH.) +# +# You should set the environemnt variable RTIMEHOME to point to where +# RTI Connext Micro is installed. +# +###################################################################### + +# If undefined in the environment default RTIMEHOME to install dir +ifndef RTIMEHOME +$(error RTIMEHOME not defined) +endif + +COMPILER_FLAGS = -m64 +LINKER_FLAGS = -m64 -static-libgcc + +split_path_name = $(subst /, , $(RTIMEHOME)) + +version_name = $(lastword $(split_path_name)) +common_name = "_shape_main_linux" +executable_name = $(version_name)$(common_name) + +RTIMEARCH = x64Linux4gcc7.3.0 + +ifndef COMPILER +COMPILER = g++ +endif + +ifndef LINKER +LINKER = g++ +endif + +SYSLIBS = -ldl -lnsl -lm -lpthread -lrt + +ifeq ($(DEBUG),1) +COMPILER_FLAGS += -g -O0 +LINKER_FLAGS += -g +LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ + -lrti_me_cppzd -lrti_me_discdpdezd -lrti_mezd -lrti_me_rhsmzd -lrti_me_whsmzd $(SYSLIBS) +else +# This option strips the executable symbols +LINKER_FLAGS += -s +LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ + -lrti_me_cppz -lrti_me_discdpdez -lrti_mez -lrti_me_rhsmz -lrti_me_whsmz $(SYSLIBS) +endif + +DEFINES = -DRTI_UNIX -DRTI_LINUX -DRTI_CONNEXT_MICRO + +INCLUDES = -I. -I$(RTIMEHOME)/include -I$(RTIMEHOME)/include/rti_me + +OBJDIR := objs/$(RTIMEARCH) + +CDRSOURCES := shape_micro.idl +AUTOGENSOURCES := shape_microSupport.cxx shape_microPlugin.cxx shape_micro.cxx + +EXEC := $(executable_name) +AUTOGENOBJS := $(addprefix $(OBJDIR)/, $(AUTOGENSOURCES:%.cxx=%.o)) + +$(OBJDIR)/$(EXEC) : $(AUTOGENSOURCES) $(AUTOGENOBJS) $(OBJDIR)/shape_main.o + $(LINKER) $(LINKER_FLAGS) -o $@ $(OBJDIR)/shape_main.o $(AUTOGENOBJS) $(LIBS) + +$(OBJDIR)/%.o : %.cxx + $(COMPILER) $(COMPILER_FLAGS) -o $@ $(DEFINES) $(INCLUDES) -c $< + +shape_main.cxx : shape_configurator_rti_connext_dds.h + +# Generate type-specific sources +$(AUTOGENSOURCES) : $(CDRSOURCES) + $(RTIMEHOME)/rtiddsgen/scripts/rtiddsgen $(CDRSOURCES) -replace -micro -language C++ + +$(AUTOGENOBJS): | objs/$(RTIMEARCH)_micro + +objs/$(RTIMEARCH)_micro: + echo "Making directory objs/$(RTIMEARCH)_micro"; + mkdir -p objs/$(RTIMEARCH)_micro diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h new file mode 100644 index 00000000..d3599ac7 --- /dev/null +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -0,0 +1,52 @@ +#include "shape_micro.h" +#include "shape_microSupport.h" + +#ifndef rti_me_cpp_hxx + #include "rti_me_cpp.hxx" +#endif + +#define LISTENER_STATUS_MASK_ALL (DDS_STATUS_MASK_ALL) + +typedef CDR_StringSeq StringSeq; + +typedef DDS_Short DataRepresentationId_t; + +const DataRepresentationId_t XCDR_DATA_REPRESENTATION = (0x00000001 << 0); +const DataRepresentationId_t XCDR2_DATA_REPRESENTATION = (0x00000001 << 2); + +const DDS::DurabilityQosPolicyKind TRANSIENT_DURABILITY_QOS = DDS_TRANSIENT_DURABILITY_QOS; +const DDS::DurabilityQosPolicyKind PERSISTENT_DURABILITY_QOS = DDS_PERSISTENT_DURABILITY_QOS; + +void StringSeq_push(StringSeq &string_seq, const char *elem) +{ + string_seq.ensure_length(string_seq.length()+1, string_seq.length()+1); + string_seq[string_seq.length()-1] = DDS_String_dup(elem); +} + + +const char* get_qos_policy_name(DDS::QosPolicyId_t policy_id) +{ + //case DDS::USERDATA_QOS_POLICY_ID) { return "USERDATA"; + if (policy_id == DDS::DURABILITY_QOS_POLICY_ID) { return "DURABILITY"; } + else if (policy_id == DDS::PRESENTATION_QOS_POLICY_ID) { return "PRESENTATION"; } + else if (policy_id == DDS::DEADLINE_QOS_POLICY_ID) { return "DEADLINE"; } + else if (policy_id == DDS::LATENCYBUDGET_QOS_POLICY_ID) { return "LATENCYBUDGET"; } + else if (policy_id == DDS::OWNERSHIP_QOS_POLICY_ID) { return "OWNERSHIP"; } + else if (policy_id == DDS::OWNERSHIPSTRENGTH_QOS_POLICY_ID) { return "OWNERSHIPSTRENGTH"; } + else if (policy_id == DDS::LIVELINESS_QOS_POLICY_ID) { return "LIVELINESS"; } + else if (policy_id == DDS::TIMEBASEDFILTER_QOS_POLICY_ID) { return "TIMEBASEDFILTER"; } + else if (policy_id == DDS::PARTITION_QOS_POLICY_ID) { return "PARTITION"; } + else if (policy_id == DDS::RELIABILITY_QOS_POLICY_ID) { return "RELIABILITY"; } + else if (policy_id == DDS::DESTINATIONORDER_QOS_POLICY_ID) { return "DESTINATIONORDER"; } + else if (policy_id == DDS::HISTORY_QOS_POLICY_ID) { return "HISTORY"; } + else if (policy_id == DDS::RESOURCELIMITS_QOS_POLICY_ID) { return "RESOURCELIMITS"; } + else if (policy_id == DDS::ENTITYFACTORY_QOS_POLICY_ID) { return "ENTITYFACTORY"; } + else if (policy_id == DDS::WRITERDATALIFECYCLE_QOS_POLICY_ID) { return "WRITERDATALIFECYCLE"; } + else if (policy_id == DDS::READERDATALIFECYCLE_QOS_POLICY_ID) { return "READERDATALIFECYCLE"; } + else if (policy_id == DDS::TOPICDATA_QOS_POLICY_ID) { return "TOPICDATA"; } + else if (policy_id == DDS::GROUPDATA_QOS_POLICY_ID) { return "GROUPDATA"; } + else if (policy_id == DDS::TRANSPORTPRIORITY_QOS_POLICY_ID) { return "TRANSPORTPRIORITY"; } + else if (policy_id == DDS::LIFESPAN_QOS_POLICY_ID) { return "LIFESPAN"; } + else if (policy_id == DDS::DURABILITYSERVICE_QOS_POLICY_ID) { return "DURABILITYSERVICE"; } + else { return "Unknown"; } +} diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index ceb3f313..b8f6314c 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -16,6 +16,7 @@ #include #include #include +#include #if defined(RTI_CONNEXT_DDS) #include "shape_configurator_rti_connext_dds.h" @@ -25,6 +26,8 @@ #include "shape_configurator_opendds.h" #elif defined(EPROSIMA_FAST_DDS) #include "shape_configurator_eprosima_fast_dds.h" +#elif defined(RTI_CONNEXT_MICRO) +#include "shape_configurator_rti_connext_micro.h" #else #error "Must define the DDS vendor" #endif @@ -51,8 +54,12 @@ #define GET_TOPIC_DESCRIPTION(dr) dr->get_topicdescription() #endif #ifndef ADD_PARTITION +#if defined(RTI_CONNEXT_MICRO) +#define ADD_PARTITION(field, value) +#else #define ADD_PARTITION(field, value) StringSeq_push(field.name, value) #endif +#endif using namespace DDS; @@ -224,6 +231,10 @@ class ShapeOptions { bool print_writer_samples; + bool use_read; + + useconds_t write_period_us; + useconds_t read_period_us; public: //------------------------------------------------------------- ShapeOptions() @@ -253,6 +264,12 @@ class ShapeOptions { shapesize = 20; print_writer_samples = false; + + use_read = false; + + write_period_us = 33000; + read_period_us = 100000; + } //------------------------------------------------------------- @@ -267,6 +284,9 @@ class ShapeOptions { void print_usage( const char *prog ) { printf("%s: \n", prog); + printf(" --help, -h : print this menu\n"); + printf(" -P : publish samples\n"); + printf(" -S : subscribe samples\n"); printf(" -d : domain id (default: 0)\n"); printf(" -b : BEST_EFFORT reliability\n"); printf(" -r : RELIABLE reliability\n"); @@ -279,11 +299,15 @@ class ShapeOptions { printf(" -p : set a 'partition' string\n"); printf(" -D [v|l|t|p] : set durability [v: VOLATILE, l: TRANSIENT_LOCAL]\n"); printf(" t: TRANSIENT, p: PERSISTENT]\n"); - printf(" -P : publish samples\n"); - printf(" -S : subscribe samples\n"); printf(" -x [1|2] : set data representation [1: XCDR, 2: XCDR2]\n"); printf(" -w : print Publisher's samples\n"); - printf(" -z : set shapesize (between 10-99)\n"); + printf(" -z : set shapesize (0: increase the size for every sample)\n"); + printf(" -v [e|d] : set log message verbosity [e: ERROR, d: DEBUG]\n"); + printf(" -R : use 'read()' instead of 'take()'\n"); + printf(" --write-period : waiting period between 'write()' operations in ms.\n"); + printf(" Default: 33ms\n"); + printf(" --read-period : waiting period between 'read()' or 'take()' operations\n"); + printf(" in ms. Default: 100ms\n"); printf(" -v [e|d] : set log message verbosity [e: ERROR, d: DEBUG]\n"); } @@ -305,6 +329,13 @@ class ShapeOptions { color = strdup("BLUE"); logger.log_message("warning: color was not specified, defaulting to \"BLUE\"", Verbosity::ERROR); } +#if defined(RTI_CONNEXT_MICRO) + if (!publish && color != NULL) { + free(color); + color = NULL; + logger.log_message("warning: content filtered topic not supported, normal topic used", Verbosity::ERROR); + } +#endif return true; } @@ -314,254 +345,234 @@ class ShapeOptions { logger.log_message("Running parse() function", Verbosity::DEBUG); int opt; bool parse_ok = true; - // double d; - while ((opt = getopt(argc, argv, "hbrc:d:D:f:i:k:p:s:x:t:v:z:wPS")) != -1) - { - switch (opt) - { + static struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"write-period", required_argument, NULL, 'W'}, + {"read-period", required_argument, NULL, 'A'}, + {NULL, 0, NULL, 0 } + }; + + while ((opt = getopt_long(argc, argv, "hPSbrRc:d:D:f:i:k:p:s:x:t:v:z:w", + long_options, NULL)) != -1) { + switch (opt) { case 'v': - { - if (optarg[0] != '\0') - { - switch (optarg[0]) - { - case 'd': - { - logger.verbosity(DEBUG); - break; - } - case 'e': - { - logger.verbosity(ERROR); - break; - } - default: - { - logger.log_message("unrecognized value for verbosity " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - } + if (optarg[0] != '\0') { + switch (optarg[0]) { + case 'd': + logger.verbosity(DEBUG); + break; + case 'e': + logger.verbosity(ERROR); + break; + default: + logger.log_message("unrecognized value for verbosity " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; } - break; } + break; case 'w': - { - print_writer_samples = true; - break; - } + print_writer_samples = true; + break; case 'b': - { - reliability_kind = BEST_EFFORT_RELIABILITY_QOS; - break; - } + reliability_kind = BEST_EFFORT_RELIABILITY_QOS; + break; + case 'R': + use_read = true; + break; case 'c': - { - color = strdup(optarg); - break; - } - case 'd': - { - int converted_param = sscanf(optarg, "%d", &domain_id); - if (converted_param == 0) { - logger.log_message("unrecognized value for domain_id " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - else if (domain_id < 0) { - logger.log_message("incorrect value for domain_id " - + std::to_string(domain_id), - Verbosity::ERROR); - parse_ok = false; - } - break; + color = strdup(optarg); + break; + case 'd': { + int converted_param = sscanf(optarg, "%d", &domain_id); + if (converted_param == 0) { + logger.log_message("unrecognized value for domain_id " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; + } else if (domain_id < 0) { + logger.log_message("incorrect value for domain_id " + + std::to_string(domain_id), + Verbosity::ERROR); + parse_ok = false; } + break; + } case 'D': - { - if (optarg[0] != '\0') - { - switch (optarg[0]) - { - case 'v': - { - durability_kind = VOLATILE_DURABILITY_QOS; - break; - } - case 'l': - { - durability_kind = TRANSIENT_LOCAL_DURABILITY_QOS; - break; - } - case 't': - { - durability_kind = TRANSIENT_DURABILITY_QOS; - break; - } - case 'p': - { - durability_kind = PERSISTENT_DURABILITY_QOS; - break; - } - default: - { - logger.log_message("unrecognized value for durability " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - } + if (optarg[0] != '\0') { + switch (optarg[0]) { + case 'v': + durability_kind = VOLATILE_DURABILITY_QOS; + break; + case 'l': + durability_kind = TRANSIENT_LOCAL_DURABILITY_QOS; + break; + case 't': + durability_kind = TRANSIENT_DURABILITY_QOS; + break; + case 'p': + durability_kind = PERSISTENT_DURABILITY_QOS; + break; + default: + logger.log_message("unrecognized value for durability " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; } break; + } + case 'i': { + int converted_param = sscanf(optarg, "%d", &timebasedfilter_interval); + if (converted_param == 0) { + logger.log_message("unrecognized value for timebasedfilter_interval " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; + } else if (timebasedfilter_interval < 0) { + logger.log_message("incorrect value for timebasedfilter_interval " + + std::to_string(timebasedfilter_interval), + Verbosity::ERROR); + parse_ok = false; } - case 'i': - { - int converted_param = sscanf(optarg, "%d", &timebasedfilter_interval); - if (converted_param == 0) { - logger.log_message("unrecognized value for timebasedfilter_interval " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - else if (timebasedfilter_interval < 0) { - logger.log_message("incorrect value for timebasedfilter_interval " - + std::to_string(timebasedfilter_interval), - Verbosity::ERROR); - parse_ok = false; - } - break; - } - case 'f': - { - int converted_param = sscanf(optarg, "%d", &deadline_interval); - if (converted_param == 0) { - logger.log_message("unrecognized value for deadline_interval " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } else if (deadline_interval < 0) { - logger.log_message("incorrect value for deadline_interval " - + std::to_string(deadline_interval), - Verbosity::ERROR); - parse_ok = false; - } - break; + break; + } + case 'f': { + int converted_param = sscanf(optarg, "%d", &deadline_interval); + if (converted_param == 0) { + logger.log_message("unrecognized value for deadline_interval " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; + } else if (deadline_interval < 0) { + logger.log_message("incorrect value for deadline_interval " + + std::to_string(deadline_interval), + Verbosity::ERROR); + parse_ok = false; } - case 'k': - { - int converted_param = sscanf(optarg, "%d", &history_depth); - if (converted_param == 0){ - logger.log_message("unrecognized value for history_depth " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } else if (history_depth < 0) { - logger.log_message("incorrect value for history_depth " - + std::to_string(history_depth), - Verbosity::ERROR); - parse_ok = false; - } - break; + break; + } + case 'k': { + int converted_param = sscanf(optarg, "%d", &history_depth); + if (converted_param == 0){ + logger.log_message("unrecognized value for history_depth " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; + } else if (history_depth < 0) { + logger.log_message("incorrect value for history_depth " + + std::to_string(history_depth), + Verbosity::ERROR); + parse_ok = false; } + break; + } case 'p': - { - partition = strdup(optarg); - break; - } + partition = strdup(optarg); + break; case 'r': - { - reliability_kind = RELIABLE_RELIABILITY_QOS; - break; - } - case 's': - { - int converted_param = sscanf(optarg, "%d", &ownership_strength); - if (converted_param == 0){ - logger.log_message("unrecognized value for ownership_strength " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } else if (ownership_strength < -1) { - logger.log_message("incorrect value for ownership_strength " - + std::to_string(ownership_strength), - Verbosity::ERROR); - parse_ok = false; - } - break; + reliability_kind = RELIABLE_RELIABILITY_QOS; + break; + case 's': { + int converted_param = sscanf(optarg, "%d", &ownership_strength); + if (converted_param == 0){ + logger.log_message("unrecognized value for ownership_strength " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; + } else if (ownership_strength < -1) { + logger.log_message("incorrect value for ownership_strength " + + std::to_string(ownership_strength), + Verbosity::ERROR); + parse_ok = false; } + break; + } case 't': - { - topic_name = strdup(optarg); - break; - } + topic_name = strdup(optarg); + break; case 'P': - { - publish = true; - break; - } + publish = true; + break; case 'S': - { - subscribe = true; - break; - } + subscribe = true; + break; case 'h': - { - print_usage(argv[0]); - exit(0); - break; - } + print_usage(argv[0]); + exit(0); + break; case 'x': - { - if (optarg[0] != '\0') - { - switch (optarg[0]) - { - case '1': - { - data_representation = XCDR_DATA_REPRESENTATION; - break; - } - case '2': - { - data_representation = XCDR2_DATA_REPRESENTATION; - break; - } - default: - { - logger.log_message("unrecognized value for data representation " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - } - } - break; - } - case 'z': - { - int converted_param = sscanf(optarg, "%d", &shapesize); - if (converted_param == 0){ - logger.log_message("unrecognized value for shapesize " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - else if (shapesize < 10 || shapesize > 99) { - logger.log_message("incorrect value for shapesize " - + std::to_string(shapesize), + if (optarg[0] != '\0') { + switch (optarg[0]) { + case '1': + data_representation = XCDR_DATA_REPRESENTATION; + break; + case '2': + data_representation = XCDR2_DATA_REPRESENTATION; + break; + default: + logger.log_message("unrecognized value for data representation " + + std::string(1, optarg[0]), Verbosity::ERROR); parse_ok = false; } - break; } - case '?': - { + break; + case 'z': { + int converted_param = sscanf(optarg, "%d", &shapesize); + if (converted_param == 0) { + logger.log_message("unrecognized value for shapesize " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; + } else if (shapesize < 0) { + logger.log_message("incorrect value for shapesize " + + std::to_string(shapesize), + Verbosity::ERROR); + parse_ok = false; + } + break; + } + case 'W': { + int converted_param = 0; + sscanf(optarg, "%d", &converted_param); + if (sscanf(optarg, "%d", &converted_param) == 0) { + logger.log_message("unrecognized value for write-period " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; + } + write_period_us = (useconds_t) converted_param * 1000; + if (write_period_us < 0) { + logger.log_message("incorrect value for write-period " + + std::to_string(write_period_us), + Verbosity::ERROR); parse_ok = false; - break; } + break; + } + case 'A': { + int converted_param = 0; + sscanf(optarg, "%d", &converted_param); + if (sscanf(optarg, "%d", &converted_param) == 0) { + logger.log_message("unrecognized value for read-period " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; + } + read_period_us = (useconds_t) converted_param * 1000; + if (read_period_us < 0) { + logger.log_message("incorrect value for read-period " + + std::to_string(read_period_us), + Verbosity::ERROR); + parse_ok = false; + } + break; + } + case '?': + parse_ok = false; + break; } - } if ( parse_ok ) { @@ -582,6 +593,9 @@ class ShapeOptions { "\n TimeBasedFilterInterval = " + std::to_string(timebasedfilter_interval) + "\n DeadlineInterval = " + std::to_string(deadline_interval) + "\n Shapesize = " + std::to_string(shapesize) + + "\n Reading method = " + (use_read ? "read_next_instance" : "take_next_instance") + + "\n Write period = " + std::to_string(write_period_us / 1000) + "ms" + "\n Read period = " + std::to_string(read_period_us / 1000) + "ms" "\n Verbosity = " + QosUtils::to_string(logger.verbosity()), Verbosity::DEBUG); if (topic_name != NULL){ @@ -782,7 +796,7 @@ class ShapeApplication { return run_publisher(options); } else if ( sub != NULL ) { - return run_subscriber(); + return run_subscriber(options); } return false; @@ -828,7 +842,7 @@ class ShapeApplication { dw_qos.representation.value.length(1); dw_qos.representation.value[0] = options->data_representation; #endif -#if !defined(EPROSIMA_FAST_DDS) +#if !defined(EPROSIMA_FAST_DDS) && !defined(RTI_CONNEXT_MICRO) logger.log_message(" Data_Representation = " + QosUtils::to_string(dw_qos.representation FIELD_ACCESSOR.value[0]), Verbosity::DEBUG); #endif if ( options->ownership_strength != -1 ) { @@ -924,19 +938,20 @@ class ShapeApplication { dr_qos.representation.value.length(1); dr_qos.representation.value[0] = options->data_representation; #endif -#if !defined(EPROSIMA_FAST_DDS) +#if !defined(EPROSIMA_FAST_DDS) && !defined(RTI_CONNEXT_MICRO) logger.log_message(" DataRepresentation = " + QosUtils::to_string(dr_qos.representation FIELD_ACCESSOR.value[0]), Verbosity::DEBUG); #endif if ( options->ownership_strength != -1 ) { dr_qos.ownership FIELD_ACCESSOR.kind = EXCLUSIVE_OWNERSHIP_QOS; } logger.log_message(" Ownership = " + QosUtils::to_string(dr_qos.ownership FIELD_ACCESSOR.kind), Verbosity::DEBUG); +#ifndef RTI_CONNEXT_MICRO if ( options->timebasedfilter_interval > 0) { dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME = options->timebasedfilter_interval; dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec = 0; } logger.log_message(" TimeBasedFilter = " + std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME), Verbosity::DEBUG); - +#endif if ( options->deadline_interval > 0 ) { dr_qos.deadline FIELD_ACCESSOR.period.SECONDS_FIELD_NAME = options->deadline_interval; dr_qos.deadline FIELD_ACCESSOR.period.nanosec = 0; @@ -957,10 +972,12 @@ class ShapeApplication { } if ( options->color != NULL ) { + /* For Connext Micro color will be always NULL */ +#if !defined(RTI_CONNEXT_MICRO) /* filter on specified color */ ContentFilteredTopic *cft = NULL; StringSeq cf_params; - + const std::string filtered_topic_name_str = std::string(options->topic_name) + "_filtered"; const char* filtered_topic_name = filtered_topic_name_str.c_str(); @@ -989,6 +1006,7 @@ class ShapeApplication { printf("Create reader for topic: %s color: %s\n", options->topic_name, options->color ); dr = dynamic_cast(sub->create_datareader(cft, dr_qos, NULL, LISTENER_STATUS_MASK_NONE)); +#endif } else { printf("Create reader for topic: %s\n", options->topic_name ); @@ -1005,7 +1023,7 @@ class ShapeApplication { } //------------------------------------------------------------- - bool run_subscriber() + bool run_subscriber(ShapeOptions *options) { logger.log_message("Running run_subscriber() function", Verbosity::DEBUG); @@ -1013,7 +1031,7 @@ class ShapeApplication { ReturnCode_t retval; SampleInfoSeq sample_infos; -#if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) +#if defined(RTI_CONNEXT_DDS) || defined(RTI_CONNEXT_MICRO) || defined(OPENDDS) ShapeTypeSeq samples; #elif defined(TWINOAKS_COREDX) ShapeTypePtrSeq samples; @@ -1025,24 +1043,60 @@ class ShapeApplication { InstanceHandle_t previous_handle = HANDLE_NIL; do { - logger.log_message("Calling take_next_instance() function", Verbosity::DEBUG); + if (!options->use_read) { + logger.log_message("Calling take() function", Verbosity::DEBUG); #if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) || defined(EPROSIMA_FAST_DDS) - retval = dr->take_next_instance ( samples, - sample_infos, - LENGTH_UNLIMITED, - previous_handle, - ANY_SAMPLE_STATE, - ANY_VIEW_STATE, - ANY_INSTANCE_STATE ); + retval = dr->take_next_instance ( samples, + sample_infos, + LENGTH_UNLIMITED, + previous_handle, + ANY_SAMPLE_STATE, + ANY_VIEW_STATE, + ANY_INSTANCE_STATE ); #elif defined(TWINOAKS_COREDX) - retval = dr->take_next_instance ( &samples, - &sample_infos, - LENGTH_UNLIMITED, - previous_handle, - ANY_SAMPLE_STATE, - ANY_VIEW_STATE, - ANY_INSTANCE_STATE ); + retval = dr->take_next_instance ( &samples, + &sample_infos, + LENGTH_UNLIMITED, + previous_handle, + ANY_SAMPLE_STATE, + ANY_VIEW_STATE, + ANY_INSTANCE_STATE ); +#elif defined(RTI_CONNEXT_MICRO) + retval = dr->take ( samples, + sample_infos, + LENGTH_UNLIMITED, + ANY_SAMPLE_STATE, + ANY_VIEW_STATE, + ANY_INSTANCE_STATE ); #endif + } else { /* Use read_next_instance*/ +#if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) || defined(EPROSIMA_FAST_DDS) + logger.log_message("Calling read_next_instance() function", Verbosity::DEBUG); + retval = dr->read_next_instance ( samples, + sample_infos, + LENGTH_UNLIMITED, + previous_handle, + ANY_SAMPLE_STATE, + ANY_VIEW_STATE, + ANY_INSTANCE_STATE ); +#elif defined(TWINOAKS_COREDX) + retval = dr->read_next_instance ( &samples, + &sample_infos, + LENGTH_UNLIMITED, + previous_handle, + ANY_SAMPLE_STATE, + ANY_VIEW_STATE, + ANY_INSTANCE_STATE ); +#elif defined(RTI_CONNEXT_MICRO) + logger.log_message("Calling read() function", Verbosity::DEBUG); + retval = dr->read ( samples, + sample_infos, + LENGTH_UNLIMITED, + ANY_SAMPLE_STATE, + ANY_VIEW_STATE, + ANY_INSTANCE_STATE ); +#endif + } if (retval == RETCODE_OK) { auto n_samples = samples.length(); @@ -1051,7 +1105,7 @@ class ShapeApplication { for (decltype(n_samples) i = 0; i < n_samples; i++) { logger.log_message("Processing sample " + std::to_string(i), Verbosity::DEBUG); -#if defined(RTI_CONNEXT_DDS) +#if defined(RTI_CONNEXT_DDS) || defined(RTI_CONNEXT_MICRO) ShapeType *sample = &samples[i]; SampleInfo *sample_info = &sample_infos[i]; #elif defined(TWINOAKS_COREDX) @@ -1071,7 +1125,7 @@ class ShapeApplication { } } -#if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) || defined(EPROSIMA_FAST_DDS) +#if defined(RTI_CONNEXT_DDS) || defined(RTI_CONNEXT_MICRO) || defined(OPENDDS) || defined(EPROSIMA_FAST_DDS) previous_handle = sample_infos[0].instance_handle; dr->return_loan( samples, sample_infos ); #elif defined(TWINOAKS_COREDX) @@ -1081,7 +1135,7 @@ class ShapeApplication { } } while (retval == RETCODE_OK); - usleep(100000); + usleep(options->read_period_us); } return true; @@ -1089,27 +1143,24 @@ class ShapeApplication { //------------------------------------------------------------- void - moveShape( ShapeType *shape) + moveShape(ShapeType *shape) { - int w2; - - w2 = 1 + shape->shapesize FIELD_ACCESSOR / 2; shape->x FIELD_ACCESSOR = shape->x FIELD_ACCESSOR + xvel; shape->y FIELD_ACCESSOR = shape->y FIELD_ACCESSOR + yvel; - if (shape->x FIELD_ACCESSOR < w2) { - shape->x FIELD_ACCESSOR = w2; + if (shape->x FIELD_ACCESSOR < 0) { + shape->x FIELD_ACCESSOR = 0; xvel = -xvel; } - if (shape->x FIELD_ACCESSOR > da_width - w2) { - shape->x FIELD_ACCESSOR = (da_width - w2); + if (shape->x FIELD_ACCESSOR > da_width) { + shape->x FIELD_ACCESSOR = da_width; xvel = -xvel; } - if (shape->y FIELD_ACCESSOR < w2) { - shape->y FIELD_ACCESSOR = w2; + if (shape->y FIELD_ACCESSOR < 0) { + shape->y FIELD_ACCESSOR = 0; yvel = -yvel; } - if (shape->y FIELD_ACCESSOR > (da_height - w2) ) { - shape->y FIELD_ACCESSOR = (da_height - w2); + if (shape->y FIELD_ACCESSOR > da_height) { + shape->y FIELD_ACCESSOR = da_height; yvel = -yvel; } } @@ -1119,7 +1170,7 @@ class ShapeApplication { { logger.log_message("Running run_publisher() function", Verbosity::DEBUG); ShapeType shape; -#if defined(RTI_CONNEXT_DDS) +#if defined(RTI_CONNEXT_DDS) || defined(RTI_CONNEXT_MICRO) ShapeType_initialize(&shape); #endif @@ -1139,11 +1190,14 @@ class ShapeApplication { shape.x FIELD_ACCESSOR = random() % da_width; shape.y FIELD_ACCESSOR = random() % da_height; xvel = ((random() % 5) + 1) * ((random()%2)?-1:1); - yvel = ((random() % 5) + 1) * ((random()%2)?-1:1);; + yvel = ((random() % 5) + 1) * ((random()%2)?-1:1); while ( ! all_done ) { + if (options->shapesize == 0) { + shape.shapesize FIELD_ACCESSOR += 1; + } moveShape(&shape); -#if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) +#if defined(RTI_CONNEXT_DDS) || defined(RTI_CONNEXT_MICRO) || defined(OPENDDS) dw->write( shape, HANDLE_NIL ); #elif defined(TWINOAKS_COREDX) || defined(EPROSIMA_FAST_DDS) dw->write( &shape, HANDLE_NIL ); @@ -1154,7 +1208,7 @@ class ShapeApplication { shape.x FIELD_ACCESSOR, shape.y FIELD_ACCESSOR, shape.shapesize FIELD_ACCESSOR); - usleep(33000); + usleep(options->write_period_us); } return true; diff --git a/srcCxx/shape_micro.idl b/srcCxx/shape_micro.idl new file mode 100644 index 00000000..312a23a5 --- /dev/null +++ b/srcCxx/shape_micro.idl @@ -0,0 +1,8 @@ +@appendable +struct ShapeType { + @key + string<128> color; + long x; + long y; + long shapesize; +}; From c5d4106b36889f321c91e81b24499378ce7226ae Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 28 Jun 2024 13:08:57 +0200 Subject: [PATCH 05/44] Fixing micro makefile --- srcCxx/makefile_rti_connext_micro_linux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcCxx/makefile_rti_connext_micro_linux b/srcCxx/makefile_rti_connext_micro_linux index d1c532f4..6554ca52 100644 --- a/srcCxx/makefile_rti_connext_micro_linux +++ b/srcCxx/makefile_rti_connext_micro_linux @@ -55,7 +55,7 @@ DEFINES = -DRTI_UNIX -DRTI_LINUX -DRTI_CONNEXT_MICRO INCLUDES = -I. -I$(RTIMEHOME)/include -I$(RTIMEHOME)/include/rti_me -OBJDIR := objs/$(RTIMEARCH) +OBJDIR := objs/$(RTIMEARCH)_micro CDRSOURCES := shape_micro.idl AUTOGENSOURCES := shape_microSupport.cxx shape_microPlugin.cxx shape_micro.cxx From 78ee44f54f55c9bed3db612d0633aacc7a556c82 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 28 Jun 2024 13:09:21 +0200 Subject: [PATCH 06/44] updating gitignore to allow idl files --- .gitignore | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index aad529a3..ff3c6f44 100644 --- a/.gitignore +++ b/.gitignore @@ -48,11 +48,13 @@ GeneratedCode # Generated files srcCxx/shape.* +!srcCxx/shape.idl srcCxx/shapePlugin.* srcCxx/shapeSupport.* -srcCxx/shape_micro.cxx -srcCxx/shape_micro.h +# Generated files Connext Micro +srcCxx/shape_micro.* +!srcCxx/shape_micro.idl srcCxx/shape_microPlugin.* srcCxx/shape_microSupport.* From adf7085071232e6452f558e76d17b13f5ef19ed8 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 28 Jun 2024 18:13:22 +0200 Subject: [PATCH 07/44] Fixing duplicated code from the master merge --- srcCxx/shape_main.cxx | 179 +----------------------------------------- 1 file changed, 2 insertions(+), 177 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 084d2da1..100c4077 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -426,181 +426,6 @@ class ShapeOptions { Verbosity::ERROR); parse_ok = false; } - break; - } - case 'D': - if (optarg[0] != '\0') { - switch (optarg[0]) { - case 'v': - durability_kind = VOLATILE_DURABILITY_QOS; - break; - case 'l': - durability_kind = TRANSIENT_LOCAL_DURABILITY_QOS; - break; - case 't': - durability_kind = TRANSIENT_DURABILITY_QOS; - break; - case 'p': - durability_kind = PERSISTENT_DURABILITY_QOS; - break; - default: - logger.log_message("unrecognized value for durability " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - break; - } - case 'i': { - int converted_param = sscanf(optarg, "%d", &timebasedfilter_interval); - if (converted_param == 0) { - logger.log_message("unrecognized value for timebasedfilter_interval " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } else if (timebasedfilter_interval < 0) { - logger.log_message("incorrect value for timebasedfilter_interval " - + std::to_string(timebasedfilter_interval), - Verbosity::ERROR); - parse_ok = false; - } - break; - } - case 'f': { - int converted_param = sscanf(optarg, "%d", &deadline_interval); - if (converted_param == 0) { - logger.log_message("unrecognized value for deadline_interval " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } else if (deadline_interval < 0) { - logger.log_message("incorrect value for deadline_interval " - + std::to_string(deadline_interval), - Verbosity::ERROR); - parse_ok = false; - } - break; - } - case 'k': { - int converted_param = sscanf(optarg, "%d", &history_depth); - if (converted_param == 0){ - logger.log_message("unrecognized value for history_depth " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } else if (history_depth < 0) { - logger.log_message("incorrect value for history_depth " - + std::to_string(history_depth), - Verbosity::ERROR); - parse_ok = false; - } - break; - } - case 'p': - partition = strdup(optarg); - break; - case 'r': - reliability_kind = RELIABLE_RELIABILITY_QOS; - break; - case 's': { - int converted_param = sscanf(optarg, "%d", &ownership_strength); - if (converted_param == 0){ - logger.log_message("unrecognized value for ownership_strength " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } else if (ownership_strength < -1) { - logger.log_message("incorrect value for ownership_strength " - + std::to_string(ownership_strength), - Verbosity::ERROR); - parse_ok = false; - } - break; - } - case 't': - topic_name = strdup(optarg); - break; - case 'P': - publish = true; - break; - case 'S': - subscribe = true; - break; - case 'h': - print_usage(argv[0]); - exit(0); - break; - case 'x': - if (optarg[0] != '\0') { - switch (optarg[0]) { - case '1': - data_representation = XCDR_DATA_REPRESENTATION; - break; - case '2': - data_representation = XCDR2_DATA_REPRESENTATION; - break; - default: - logger.log_message("unrecognized value for data representation " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - } - break; - case 'z': { - int converted_param = sscanf(optarg, "%d", &shapesize); - if (converted_param == 0) { - logger.log_message("unrecognized value for shapesize " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } else if (shapesize < 0) { - logger.log_message("incorrect value for shapesize " - + std::to_string(shapesize), - Verbosity::ERROR); - parse_ok = false; - } - break; - } - case 'W': { - int converted_param = 0; - sscanf(optarg, "%d", &converted_param); - if (sscanf(optarg, "%d", &converted_param) == 0) { - logger.log_message("unrecognized value for write-period " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - write_period_us = (useconds_t) converted_param * 1000; - if (write_period_us < 0) { - logger.log_message("incorrect value for write-period " - + std::to_string(write_period_us), - Verbosity::ERROR); - parse_ok = false; - } - break; - } - case 'A': { - int converted_param = 0; - sscanf(optarg, "%d", &converted_param); - if (sscanf(optarg, "%d", &converted_param) == 0) { - logger.log_message("unrecognized value for read-period " - + std::string(1, optarg[0]), - Verbosity::ERROR); - parse_ok = false; - } - read_period_us = (useconds_t) converted_param * 1000; - if (read_period_us < 0) { - logger.log_message("incorrect value for read-period " - + std::to_string(read_period_us), - Verbosity::ERROR); - parse_ok = false; - } - break; - } - case '?': - parse_ok = false; - break; } break; case 'i': { @@ -1013,7 +838,7 @@ class ShapeApplication { dw_qos.representation.value = data_representation_seq; #elif defined(TWINOAKS_COREDX) - dw_qos.rtps_writer.apply_filters = 0; + dw_qos.rtps_writer.apply_filters = 0; dw_qos.representation.value.clear( ); dw_qos.representation.value.push_back( options->data_representation ); @@ -1183,7 +1008,7 @@ class ShapeApplication { /* filter on specified color */ ContentFilteredTopic *cft = NULL; StringSeq cf_params; - + const std::string filtered_topic_name_str = std::string(options->topic_name) + "_filtered"; const char* filtered_topic_name = filtered_topic_name_str.c_str(); From 7da104c3784d48427c92544cb601da86793452ad Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Thu, 18 Jul 2024 18:12:28 +0200 Subject: [PATCH 08/44] Adding additional configuration for micro 4 --- srcCxx/makefile_rti_connext_micro_linux | 2 +- srcCxx/shape_configurator_rti_connext_micro.h | 96 ++++++++++++++++++- srcCxx/shape_main.cxx | 61 +++++++++--- 3 files changed, 139 insertions(+), 20 deletions(-) diff --git a/srcCxx/makefile_rti_connext_micro_linux b/srcCxx/makefile_rti_connext_micro_linux index 6554ca52..dfe399f0 100644 --- a/srcCxx/makefile_rti_connext_micro_linux +++ b/srcCxx/makefile_rti_connext_micro_linux @@ -21,7 +21,7 @@ endif COMPILER_FLAGS = -m64 LINKER_FLAGS = -m64 -static-libgcc -split_path_name = $(subst /, , $(RTIMEHOME)) +split_path_name = $(subst /rti_, , $(RTIMEHOME)) version_name = $(lastword $(split_path_name)) common_name = "_shape_main_linux" diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index d3599ac7..e59cc62a 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -5,14 +5,21 @@ #include "rti_me_cpp.hxx" #endif +#define CONFIGURE_PARTICIPANT_FACTORY config_micro(); #define LISTENER_STATUS_MASK_ALL (DDS_STATUS_MASK_ALL) -typedef CDR_StringSeq StringSeq; +#ifndef XCDR_DATA_REPRESENTATION + #define XCDR_DATA_REPRESENTATION DDS_XCDR_DATA_REPRESENTATION +#endif -typedef DDS_Short DataRepresentationId_t; +#ifndef XCDR2_DATA_REPRESENTATION + #define XCDR2_DATA_REPRESENTATION DDS_XCDR2_DATA_REPRESENTATION +#endif -const DataRepresentationId_t XCDR_DATA_REPRESENTATION = (0x00000001 << 0); -const DataRepresentationId_t XCDR2_DATA_REPRESENTATION = (0x00000001 << 2); +#define DataRepresentationId_t DDS_DataRepresentationId_t +#define DataRepresentationIdSeq DDS_DataRepresentationIdSeq + +typedef CDR_StringSeq StringSeq; const DDS::DurabilityQosPolicyKind TRANSIENT_DURABILITY_QOS = DDS_TRANSIENT_DURABILITY_QOS; const DDS::DurabilityQosPolicyKind PERSISTENT_DURABILITY_QOS = DDS_PERSISTENT_DURABILITY_QOS; @@ -50,3 +57,84 @@ const char* get_qos_policy_name(DDS::QosPolicyId_t policy_id) else if (policy_id == DDS::DURABILITYSERVICE_QOS_POLICY_ID) { return "DURABILITYSERVICE"; } else { return "Unknown"; } } + +static void config_micro() +{ + RT::Registry *registry = NULL; + + registry = DDSTheParticipantFactory->get_registry(); + + /* Register Writer History */ + if (!registry->register_component("wh", WHSMHistoryFactory::get_interface(), NULL, NULL)) + { + printf("ERROR: unable to register writer history\n"); + return; + } + + /* Register Reader History */ + if (!registry->register_component("rh", RHSMHistoryFactory::get_interface(), NULL, NULL)) + { + printf("ERROR: unable to register reader history\n"); + return; + } + + /* Configure UDP transport's allowed interfaces */ + if (!registry->unregister(NETIO_DEFAULT_UDP_NAME, NULL, NULL)) + { + printf("ERROR: unable to unregister udp\n"); + return; + } + + UDP_InterfaceFactoryProperty *udp_property = new UDP_InterfaceFactoryProperty(); + if (udp_property == NULL) + { + printf("ERROR: unable to allocate udp properties\n"); + return; + } + + /* For additional allowed interface(s), increase maximum and length, and + set interface below: + */ + if (!udp_property->allow_interface.maximum(1)) + { + printf("ERROR: unable to set allow_interface maximum\n"); + return; + } + if (!udp_property->allow_interface.length(1)) + { + printf("ERROR: unable to set allow_interface length\n"); + return; + } + + udp_property->allow_interface[0] = DDS_String_dup("lo"); + //udp_property->allow_interface[1] = DDS_String_dup("eth0"); + + if (!registry->register_component( + NETIO_DEFAULT_UDP_NAME, + UDPInterfaceFactory::get_interface(), + &udp_property->_parent._parent, + NULL)) + { + printf("ERROR: unable to register udp\n"); + return; + } + + DPDE::DiscoveryPluginProperty discovery_plugin_properties; + + /* Configure properties */ + discovery_plugin_properties.participant_liveliness_assert_period.sec = 5; + discovery_plugin_properties.participant_liveliness_assert_period.nanosec = 0; + discovery_plugin_properties.participant_liveliness_lease_duration.sec = 30; + discovery_plugin_properties.participant_liveliness_lease_duration.nanosec = 0; + + + if (!registry->register_component( + "dpde", + DPDEDiscoveryFactory::get_interface(), + &discovery_plugin_properties._parent, + NULL)) + { + printf("ERROR: unable to register dpde\n"); + return; + } +} diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 100c4077..78093654 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -21,14 +21,14 @@ #if defined(RTI_CONNEXT_DDS) #include "shape_configurator_rti_connext_dds.h" +#elif defined(RTI_CONNEXT_MICRO) +#include "shape_configurator_rti_connext_micro.h" #elif defined(TWINOAKS_COREDX) #include "shape_configurator_toc_coredx_dds.h" #elif defined(OPENDDS) #include "shape_configurator_opendds.h" #elif defined(EPROSIMA_FAST_DDS) #include "shape_configurator_eprosima_fast_dds.h" -#elif defined(RTI_CONNEXT_MICRO) -#include "shape_configurator_rti_connext_micro.h" #elif defined(INTERCOM_DDS) #include "shape_configurator_intercom_dds.h" #else @@ -766,7 +766,37 @@ class ShapeApplication { CONFIGURE_PARTICIPANT_FACTORY #endif +#ifdef RTI_CONNEXT_MICRO + DDS::DomainParticipantQos dp_qos; + + if (!dp_qos.discovery.discovery.name.set_name("dpde")) + { + printf("ERROR: unable to set discovery plugin name\n"); + return false; + } + + dp_qos.discovery.initial_peers.maximum(1); + dp_qos.discovery.initial_peers.length(1); + dp_qos.discovery.initial_peers[0] = DDS_String_dup("127.0.0.1"); + + /* if there are more remote or local endpoints, you need to increase these limits */ + dp_qos.resource_limits.max_destination_ports = 32; + dp_qos.resource_limits.max_receive_ports = 32; + dp_qos.resource_limits.local_topic_allocation = 1; + dp_qos.resource_limits.local_type_allocation = 1; + dp_qos.resource_limits.local_reader_allocation = 1; + dp_qos.resource_limits.local_writer_allocation = 1; + dp_qos.resource_limits.remote_participant_allocation = 8; + dp_qos.resource_limits.remote_reader_allocation = 8; + dp_qos.resource_limits.remote_writer_allocation = 8; + + DDS_StatusMask dp_listener_mask = DDS_STATUS_MASK_ALL & ~DDS_DATA_ON_READERS_STATUS; + + dp = dpf->create_participant( options->domain_id, dp_qos, &dp_listener, dp_listener_mask ); + +#else dp = dpf->create_participant( options->domain_id, PARTICIPANT_QOS_DEFAULT, &dp_listener, LISTENER_STATUS_MASK_ALL ); +#endif if (dp == NULL) { logger.log_message("failed to create participant (missing license?).", Verbosity::ERROR); return false; @@ -831,7 +861,7 @@ class ShapeApplication { dw_qos.durability FIELD_ACCESSOR.kind = options->durability_kind; logger.log_message(" Durability = " + QosUtils::to_string(dw_qos.durability FIELD_ACCESSOR.kind), Verbosity::DEBUG); -#if defined(RTI_CONNEXT_DDS) +#if defined(RTI_CONNEXT_DDS) || defined (RTI_CONNEXT_MICRO) DataRepresentationIdSeq data_representation_seq; data_representation_seq.ensure_length(1,1); data_representation_seq[0] = options->data_representation; @@ -854,12 +884,11 @@ class ShapeApplication { dw_qos.representation().m_value.clear( ); dw_qos.representation().m_value.push_back( options->data_representation ); #endif -#if !defined(RTI_CONNEXT_MICRO) - #if defined(EPROSIMA_FAST_DDS) + +#if defined(EPROSIMA_FAST_DDS) logger.log_message(" Data_Representation = " + QosUtils::to_string(dw_qos.representation FIELD_ACCESSOR.m_value[0]), Verbosity::DEBUG); - #else +#else logger.log_message(" Data_Representation = " + QosUtils::to_string(dw_qos.representation FIELD_ACCESSOR.value[0]), Verbosity::DEBUG); - #endif #endif if ( options->ownership_strength != -1 ) { @@ -942,7 +971,7 @@ class ShapeApplication { dr_qos.durability FIELD_ACCESSOR.kind = options->durability_kind; logger.log_message(" Durability = " + QosUtils::to_string(dr_qos.durability FIELD_ACCESSOR.kind), Verbosity::DEBUG); -#if defined(RTI_CONNEXT_DDS) +#if defined(RTI_CONNEXT_DDS) || defined (RTI_CONNEXT_MICRO) DataRepresentationIdSeq data_representation_seq; data_representation_seq.ensure_length(1,1); data_representation_seq[0] = options->data_representation; @@ -965,12 +994,11 @@ class ShapeApplication { dr_qos.type_consistency().representation.m_value.clear(); dr_qos.type_consistency().representation.m_value.push_back( options->data_representation ); #endif -#if !defined(RTI_CONNEXT_MICRO) - #if defined(EPROSIMA_FAST_DDS) - logger.log_message(" DataRepresentation = " + QosUtils::to_string(dr_qos.type_consistency().representation.m_value[0]), Verbosity::DEBUG); - #else - logger.log_message(" DataRepresentation = " + QosUtils::to_string(dr_qos.representation FIELD_ACCESSOR.value[0]), Verbosity::DEBUG); - #endif + +#if defined(EPROSIMA_FAST_DDS) + logger.log_message(" DataRepresentation = " + QosUtils::to_string(dr_qos.type_consistency().representation.m_value[0]), Verbosity::DEBUG); +#else + logger.log_message(" DataRepresentation = " + QosUtils::to_string(dr_qos.representation FIELD_ACCESSOR.value[0]), Verbosity::DEBUG); #endif if ( options->ownership_strength != -1 ) { dr_qos.ownership FIELD_ACCESSOR.kind = EXCLUSIVE_OWNERSHIP_QOS; @@ -1084,8 +1112,8 @@ class ShapeApplication { do { if (!options->use_read) { - logger.log_message("Calling take_next_instance() function", Verbosity::DEBUG); #if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) || defined(EPROSIMA_FAST_DDS) || defined(INTERCOM_DDS) + logger.log_message("Calling take_next_instance() function", Verbosity::DEBUG); retval = dr->take_next_instance ( samples, sample_infos, LENGTH_UNLIMITED, @@ -1094,6 +1122,7 @@ class ShapeApplication { ANY_VIEW_STATE, ANY_INSTANCE_STATE ); #elif defined(TWINOAKS_COREDX) + logger.log_message("Calling take_next_instance() function", Verbosity::DEBUG); retval = dr->take_next_instance ( &samples, &sample_infos, LENGTH_UNLIMITED, @@ -1102,6 +1131,7 @@ class ShapeApplication { ANY_VIEW_STATE, ANY_INSTANCE_STATE ); #elif defined(RTI_CONNEXT_MICRO) + logger.log_message("Calling take() function", Verbosity::DEBUG); retval = dr->take ( samples, sample_infos, LENGTH_UNLIMITED, @@ -1120,6 +1150,7 @@ class ShapeApplication { ANY_VIEW_STATE, ANY_INSTANCE_STATE ); #elif defined(TWINOAKS_COREDX) + logger.log_message("Calling read_next_instance() function", Verbosity::DEBUG); retval = dr->read_next_instance ( &samples, &sample_infos, LENGTH_UNLIMITED, From 43e237a0fb3e711594ade5b393181f94ad699add Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Mon, 22 Jul 2024 14:27:26 +0200 Subject: [PATCH 09/44] Adding EOF to the pexpect interoperability report --- interoperability_report.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/interoperability_report.py b/interoperability_report.py index 78933407..a24ed878 100644 --- a/interoperability_report.py +++ b/interoperability_report.py @@ -114,12 +114,14 @@ def run_subscriber_shape_main( [ 'Create reader for topic:', # index = 0 pexpect.TIMEOUT, # index = 1 - 'failed to create content filtered topic' # index = 2 + 'failed to create content filtered topic', # index = 2 + pexpect.EOF # index = 3 + ], timeout ) - if index == 1: + if index == 1 or index == 3: produced_code[produced_code_index] = ReturnCode.READER_NOT_CREATED elif index == 2: produced_code[produced_code_index] = ReturnCode.FILTER_NOT_CREATED @@ -127,17 +129,14 @@ def run_subscriber_shape_main( # Step 4: Check if the reader matches the writer log_message(f'Subscriber {subscriber_index}: Waiting for matching ' 'DataWriter', verbosity) - # the normal flow of the application is to find on_subscription_matched() - # and then on_liveliness_changed(). However, in some cases the - # situation is the opposite. This will handle those cases. - # pexpect searches the results in order, so a matching on - # on_subscription_matched() takes precedence over on_liveliness_changed() index = child_sub.expect( [ '\[[0-9]+\]', # index = 0 'on_requested_incompatible_qos()', # index = 1 'on_requested_deadline_missed()', # index = 2 pexpect.TIMEOUT, # index = 3 + pexpect.EOF # index = 4 + ], timeout ) @@ -146,7 +145,7 @@ def run_subscriber_shape_main( produced_code[produced_code_index] = ReturnCode.INCOMPATIBLE_QOS elif index == 2: produced_code[produced_code_index] = ReturnCode.DEADLINE_MISSED - elif index == 3: + elif index == 3 or index == 4: produced_code[produced_code_index] = ReturnCode.DATA_NOT_RECEIVED elif index == 0: # Step 5: Receiving samples @@ -251,11 +250,12 @@ def run_publisher_shape_main( index = child_pub.expect( [ 'Create writer for topic', # index = 0 - pexpect.TIMEOUT # index = 1 + pexpect.TIMEOUT, # index = 1 + pexpect.EOF # index == 2 ], timeout ) - if index == 1: + if index == 1 or index == 2: produced_code[produced_code_index] = ReturnCode.WRITER_NOT_CREATED elif index == 0: # Step 4: Check if the writer matches the reader @@ -265,11 +265,12 @@ def run_publisher_shape_main( [ 'on_publication_matched()', # index = 0 pexpect.TIMEOUT, # index = 1 - 'on_offered_incompatible_qos' # index = 2 + 'on_offered_incompatible_qos', # index = 2 + pexpect.EOF # index == 3 ], timeout ) - if index == 1: + if index == 1 or index == 3: produced_code[produced_code_index] = ReturnCode.READER_NOT_MATCHED elif index == 2: produced_code[produced_code_index] = ReturnCode.INCOMPATIBLE_QOS @@ -285,12 +286,13 @@ def run_publisher_shape_main( index = child_pub.expect([ '\[[0-9]+\]', # index = 0 'on_offered_deadline_missed()', # index = 1 - pexpect.TIMEOUT # index = 2 + pexpect.TIMEOUT, # index = 2 + pexpect.EOF # index == 3 ], timeout) if index == 1: produced_code[produced_code_index] = ReturnCode.DEADLINE_MISSED - elif index == 2: + elif index == 2 or index == 3: produced_code[produced_code_index] = ReturnCode.DATA_NOT_SENT elif index == 0: produced_code[produced_code_index] = ReturnCode.OK From c5c451dbce7cb7b5be055e70e056436da236e52e Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Mon, 22 Jul 2024 14:51:41 +0200 Subject: [PATCH 10/44] Fixing test_color_receivers function --- test_suite.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test_suite.py b/test_suite.py index 490f558f..9d30085f 100644 --- a/test_suite.py +++ b/test_suite.py @@ -46,7 +46,7 @@ # This constant is used to limit the maximum number of samples that tests that # check the behavior needs to read. For example, checking that the data # is received in order, or that OWNERSHIP works properly, etc... -MAX_SAMPLES_READ = 500 +MAX_SAMPLES_READ = 200 def test_ownership_receivers(child_sub, samples_sent, timeout): @@ -127,7 +127,7 @@ def test_ownership_receivers(child_sub, samples_sent, timeout): index = child_sub.expect( [ '\[[0-9]+\]', # index = 0 - pexpect.TIMEOUT # index = 1 + pexpect.TIMEOUT, # index = 1 ], timeout ) @@ -186,12 +186,14 @@ def test_color_receivers(child_sub, samples_sent, timeout): """ sub_string = re.search('\w\s+(\w+)\s+[0-9]+ [0-9]+ \[[0-9]+\]', child_sub.before + child_sub.after) - last_color = current_color = sub_string.group(1) + current_color = sub_string.group(1) max_samples_received = MAX_SAMPLES_READ samples_read = 0 while sub_string is not None and samples_read < max_samples_received: + last_color = sub_string.group(1) + # Check that all received samples have the same color if last_color != current_color: return ReturnCode.RECEIVING_FROM_BOTH From be85a24c4ba347648abed08ecc35d01c4c2cb914 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Mon, 22 Jul 2024 14:55:57 +0200 Subject: [PATCH 11/44] Incresed resource limits --- srcCxx/shape_main.cxx | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 78093654..c5c68a56 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -778,19 +778,18 @@ class ShapeApplication { dp_qos.discovery.initial_peers.maximum(1); dp_qos.discovery.initial_peers.length(1); dp_qos.discovery.initial_peers[0] = DDS_String_dup("127.0.0.1"); - /* if there are more remote or local endpoints, you need to increase these limits */ dp_qos.resource_limits.max_destination_ports = 32; dp_qos.resource_limits.max_receive_ports = 32; - dp_qos.resource_limits.local_topic_allocation = 1; - dp_qos.resource_limits.local_type_allocation = 1; - dp_qos.resource_limits.local_reader_allocation = 1; - dp_qos.resource_limits.local_writer_allocation = 1; + dp_qos.resource_limits.local_topic_allocation = 2; + dp_qos.resource_limits.local_type_allocation = 2; + dp_qos.resource_limits.local_reader_allocation = 2; + dp_qos.resource_limits.local_writer_allocation = 2; dp_qos.resource_limits.remote_participant_allocation = 8; dp_qos.resource_limits.remote_reader_allocation = 8; dp_qos.resource_limits.remote_writer_allocation = 8; - DDS_StatusMask dp_listener_mask = DDS_STATUS_MASK_ALL & ~DDS_DATA_ON_READERS_STATUS; + DDS_StatusMask dp_listener_mask = (DDS_STATUS_MASK_ALL & ~DDS_DATA_ON_READERS_STATUS) & ~DDS_LIVELINESS_CHANGED_STATUS; dp = dpf->create_participant( options->domain_id, dp_qos, &dp_listener, dp_listener_mask ); @@ -856,6 +855,13 @@ class ShapeApplication { logger.log_message("Publisher created", Verbosity::DEBUG); logger.log_message("Data Writer QoS:", Verbosity::DEBUG); pub->get_default_datawriter_qos( dw_qos ); + +#if defined (RTI_CONNEXT_MICRO) + dw_qos.resource_limits.max_instances = 500; + dw_qos.resource_limits.max_samples = 500; + dw_qos.resource_limits.max_samples_per_instance = 500; +#endif + dw_qos.reliability FIELD_ACCESSOR.kind = options->reliability_kind; logger.log_message(" Reliability = " + QosUtils::to_string(dw_qos.reliability FIELD_ACCESSOR.kind), Verbosity::DEBUG); dw_qos.durability FIELD_ACCESSOR.kind = options->durability_kind; @@ -963,9 +969,19 @@ class ShapeApplication { logger.log_message("failed to create subscriber", Verbosity::ERROR); return false; } + logger.log_message("Subscriber created", Verbosity::DEBUG); logger.log_message("Data Reader QoS:", Verbosity::DEBUG); sub->get_default_datareader_qos( dr_qos ); + +#if defined (RTI_CONNEXT_MICRO) + dr_qos.resource_limits.max_instances = 500; + dr_qos.resource_limits.max_samples = 500; + dr_qos.resource_limits.max_samples_per_instance = 500; + dr_qos.reader_resource_limits.max_remote_writers = 2; + dr_qos.reader_resource_limits.max_samples_per_remote_writer = 500; +#endif + dr_qos.reliability FIELD_ACCESSOR.kind = options->reliability_kind; logger.log_message(" Reliability = " + QosUtils::to_string(dr_qos.reliability FIELD_ACCESSOR.kind), Verbosity::DEBUG); dr_qos.durability FIELD_ACCESSOR.kind = options->durability_kind; From ba1765e4de084edb5fbb884a8dd7786b6da84415 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 24 Jul 2024 11:59:29 +0200 Subject: [PATCH 12/44] Fixed Micro name in the generate_report --- generate_xlsx_report.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generate_xlsx_report.py b/generate_xlsx_report.py index edf0523a..2a78c8cd 100644 --- a/generate_xlsx_report.py +++ b/generate_xlsx_report.py @@ -68,6 +68,8 @@ def get_company_name(product:str) -> str: def get_product_name(product:str) -> str: """Returns a beautified product name and version""" # set the beautified name and version + if 'connext' in product.lower() and 'micro' in product.lower(): + return 'Connext DDS Micro ' + re.search(r'([\d.]+)', product).group(1) if 'connext' in product.lower(): return 'Connext DDS' + re.search(r'([\d.]+)', product).group(1) elif 'opendds' in product.lower(): From 898631f97d69256fec7683c54ab2928f0ef663b4 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 24 Jul 2024 11:59:42 +0200 Subject: [PATCH 13/44] Fixing micro partitions --- srcCxx/shape_main.cxx | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index c5c68a56..60338f0c 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -57,12 +57,8 @@ #define GET_TOPIC_DESCRIPTION(dr) dr->get_topicdescription() #endif #ifndef ADD_PARTITION -#if defined(RTI_CONNEXT_MICRO) -#define ADD_PARTITION(field, value) -#else #define ADD_PARTITION(field, value) StringSeq_push(field.name, value) #endif -#endif using namespace DDS; @@ -857,9 +853,9 @@ class ShapeApplication { pub->get_default_datawriter_qos( dw_qos ); #if defined (RTI_CONNEXT_MICRO) - dw_qos.resource_limits.max_instances = 500; - dw_qos.resource_limits.max_samples = 500; - dw_qos.resource_limits.max_samples_per_instance = 500; + dw_qos.resource_limits.max_instances = 500; + dw_qos.resource_limits.max_samples = 500; + dw_qos.resource_limits.max_samples_per_instance = 500; #endif dw_qos.reliability FIELD_ACCESSOR.kind = options->reliability_kind; @@ -922,7 +918,12 @@ class ShapeApplication { dw_qos.history FIELD_ACCESSOR.depth = options->history_depth; } else if ( options->history_depth == 0 ) { +#if defined (RTI_CONNEXT_MICRO) + dw_qos.history FIELD_ACCESSOR.kind = KEEP_LAST_HISTORY_QOS; + dw_qos.history FIELD_ACCESSOR.depth = 500; +#else dw_qos.history FIELD_ACCESSOR.kind = KEEP_ALL_HISTORY_QOS; +#endif } logger.log_message(" History = " + QosUtils::to_string(dw_qos.history FIELD_ACCESSOR.kind), Verbosity::DEBUG); if (dw_qos.history FIELD_ACCESSOR.kind == KEEP_LAST_HISTORY_QOS){ @@ -975,11 +976,11 @@ class ShapeApplication { sub->get_default_datareader_qos( dr_qos ); #if defined (RTI_CONNEXT_MICRO) - dr_qos.resource_limits.max_instances = 500; - dr_qos.resource_limits.max_samples = 500; - dr_qos.resource_limits.max_samples_per_instance = 500; - dr_qos.reader_resource_limits.max_remote_writers = 2; - dr_qos.reader_resource_limits.max_samples_per_remote_writer = 500; + dr_qos.resource_limits.max_instances = 500; + dr_qos.resource_limits.max_samples = 500; + dr_qos.resource_limits.max_samples_per_instance = 500; + dr_qos.reader_resource_limits.max_remote_writers = 2; + dr_qos.reader_resource_limits.max_samples_per_remote_writer = 500; #endif dr_qos.reliability FIELD_ACCESSOR.kind = options->reliability_kind; From ef3d06ed12e1f4c2b43d2e359f83f130651b4cfd Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Tue, 2 Dec 2025 17:05:48 +0100 Subject: [PATCH 14/44] Adding support for micro 4.0.2 --- generate_xlsx_report.py | 6 +- interoperability_report.py | 8 +- srcCxx/makefile_rti_connext_micro_linux | 10 +- srcCxx/makefile_rti_connext_micro_macos | 86 ++++++++++++ srcCxx/shape_configurator_rti_connext_micro.h | 96 +++++++++++-- srcCxx/shape_main.cxx | 127 +++++++++++------- srcCxx/shape_micro.idl | 1 + 7 files changed, 264 insertions(+), 70 deletions(-) create mode 100644 srcCxx/makefile_rti_connext_micro_macos diff --git a/generate_xlsx_report.py b/generate_xlsx_report.py index f2cf6d21..9c77ee66 100644 --- a/generate_xlsx_report.py +++ b/generate_xlsx_report.py @@ -9,6 +9,7 @@ ################################################################# import argparse +from io import BytesIO import junitparser import lxml import pathlib @@ -168,8 +169,11 @@ def __init__(self, input: pathlib.Path): @staticmethod def xml_parser(file): """Function to parse the XML file""" + # Remove null bytes from the file + with open(file, "rb") as f: + data = f.read().replace(b"\x00", b"") parser = lxml.etree.XMLParser(huge_tree=True) - return lxml.etree.parse(file, parser) + return lxml.etree.parse(BytesIO(data), parser) def update_value_aggregated_data_dict(self, dictionary: dict, diff --git a/interoperability_report.py b/interoperability_report.py index e592a175..e846eb0b 100644 --- a/interoperability_report.py +++ b/interoperability_report.py @@ -170,7 +170,7 @@ def run_subscriber_shape_main( log_message(f'Subscriber {subscriber_index}: Waiting for data', verbosity) index = child_sub.expect( [ - '\[[0-9]+\]', # index = 0 + r'\[[0-9]+\]', # index = 0 'on_requested_incompatible_qos()', # index = 1 'on_requested_deadline_missed()', # index = 2 pexpect.TIMEOUT, # index = 3 @@ -330,7 +330,7 @@ def run_publisher_shape_main( if '-w ' in parameters or parameters.endswith('-w'): # Step 5: Check whether the writer sends the samples index = child_pub.expect([ - '\[[0-9]+\]', # index = 0 + r'\[[0-9]+\]', # index = 0 'on_offered_deadline_missed()', # index = 1 pexpect.TIMEOUT, # index = 2 pexpect.EOF # index == 3 @@ -348,12 +348,12 @@ def run_publisher_shape_main( for x in range(0, MAX_SAMPLES_SAVED, 1): # At this point, at least one sample has been printed # Therefore, that sample is added to samples_sent. - pub_string = re.search('[0-9]+ [0-9]+ \[[0-9]+\]', + pub_string = re.search(r'[0-9]+ [0-9]+ \[[0-9]+\]', child_pub.before + child_pub.after) last_sample = pub_string.group(0) samples_sent.put(last_sample) index = child_pub.expect([ - '\[[0-9]+\]', # index = 0 + r'\[[0-9]+\]', # index = 0 'on_offered_deadline_missed()', # index = 1 pexpect.TIMEOUT # index = 2 ], diff --git a/srcCxx/makefile_rti_connext_micro_linux b/srcCxx/makefile_rti_connext_micro_linux index dfe399f0..ef58ef04 100644 --- a/srcCxx/makefile_rti_connext_micro_linux +++ b/srcCxx/makefile_rti_connext_micro_linux @@ -43,15 +43,19 @@ ifeq ($(DEBUG),1) COMPILER_FLAGS += -g -O0 LINKER_FLAGS += -g LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ - -lrti_me_cppzd -lrti_me_discdpdezd -lrti_mezd -lrti_me_rhsmzd -lrti_me_whsmzd $(SYSLIBS) + -lrti_me_cppzd -lrti_me_netiosdmzd \ + -lrti_me_discdpdez -lrti_me_ddsfilterzd -lrti_me_rhsmzd \ + -lrti_me_whsmzd -lrti_mezd -lrti_me_ddsxtypeszd $(SYSLIBS) else # This option strips the executable symbols LINKER_FLAGS += -s LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ - -lrti_me_cppz -lrti_me_discdpdez -lrti_mez -lrti_me_rhsmz -lrti_me_whsmz $(SYSLIBS) + -lrti_me_cppz -lrti_me_netiosdmz \ + -lrti_me_discdpdez -lrti_me_ddsfilterz -lrti_me_rhsmz \ + -lrti_me_whsmz -lrti_mez -lrti_me_ddsxtypesz $(SYSLIBS) endif -DEFINES = -DRTI_UNIX -DRTI_LINUX -DRTI_CONNEXT_MICRO +DEFINES = -DRTI_UNIX -DRTI_LINUX -DRTI_CONNEXT_MICRO -DOSAPI_CC_DEF_H=osapi/osapi_cc_gcc.h INCLUDES = -I. -I$(RTIMEHOME)/include -I$(RTIMEHOME)/include/rti_me diff --git a/srcCxx/makefile_rti_connext_micro_macos b/srcCxx/makefile_rti_connext_micro_macos new file mode 100644 index 00000000..077ac27f --- /dev/null +++ b/srcCxx/makefile_rti_connext_micro_macos @@ -0,0 +1,86 @@ +###################################################################### +# To compile, type: +# make -f makefile_rti_connext_dds_linux +# To compile with the Debug option, use: +# make -f makefile_rti_connext_dds_linux DEBUG=1 +# +# This makefile assumes that your build environment is already correctly +# configured. (For example, the correct version of your compiler and +# linker should be on your PATH.) +# +# You should set the environemnt variable RTIMEHOME to point to where +# RTI Connext Micro is installed. +# +###################################################################### + +# If undefined in the environment default RTIMEHOME to install dir +ifndef RTIMEHOME +$(error RTIMEHOME not defined) +endif + +COMPILER_FLAGS = -std=c++11 +LINKER_FLAGS = + +split_path_name = $(subst /rti_, , $(RTIMEHOME)) + +version_name = $(lastword $(split_path_name)) +common_name = "_shape_main_macos" +executable_name = $(version_name)$(common_name) + +RTIMEARCH = arm64Darwin23clang15.0 + +ifndef COMPILER +COMPILER = clang++ +endif + +ifndef LINKER +LINKER = clang++ +endif + +#SYSLIBS = + +ifeq ($(DEBUG),1) +COMPILER_FLAGS += -g -O0 +LINKER_FLAGS += -g +LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ + -lrti_me_cppzd -lrti_me_netiosdmzd \ + -lrti_me_discdpdez -lrti_me_ddsfilterzd -lrti_me_rhsmzd \ + -lrti_me_whsmzd -lrti_mezd -lrti_me_ddsxtypeszd $(SYSLIBS) +else +# This option strips the executable symbols +#LINKER_FLAGS += -s +LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ + -lrti_me_cppz -lrti_me_netiosdmz \ + -lrti_me_discdpdez -lrti_me_ddsfilterz -lrti_me_rhsmz \ + -lrti_me_whsmz -lrti_mez -lrti_me_ddsxtypesz $(SYSLIBS) +endif + +DEFINES = -DRTI_UNIX -DRTI_DARWIN -DRTI_CONNEXT_MICRO -DOSAPI_CC_DEF_H=osapi/osapi_cc_gcc.h + +INCLUDES = -I. -I$(RTIMEHOME)/include -I$(RTIMEHOME)/include/rti_me + +OBJDIR := objs/$(RTIMEARCH)_micro + +CDRSOURCES := shape_micro.idl +AUTOGENSOURCES := shape_microSupport.cxx shape_microPlugin.cxx shape_micro.cxx + +EXEC := $(executable_name) +AUTOGENOBJS := $(addprefix $(OBJDIR)/, $(AUTOGENSOURCES:%.cxx=%.o)) + +$(OBJDIR)/$(EXEC) : $(AUTOGENSOURCES) $(AUTOGENOBJS) $(OBJDIR)/shape_main.o + $(LINKER) $(LINKER_FLAGS) -o $@ $(OBJDIR)/shape_main.o $(AUTOGENOBJS) $(LIBS) + +$(OBJDIR)/%.o : %.cxx + $(COMPILER) $(COMPILER_FLAGS) -o $@ $(DEFINES) $(INCLUDES) -c $< + +shape_main.cxx : shape_configurator_rti_connext_dds.h + +# Generate type-specific sources +$(AUTOGENSOURCES) : $(CDRSOURCES) + $(RTIMEHOME)/rtiddsgen/scripts/rtiddsgen $(CDRSOURCES) -replace -micro -language C++ + +$(AUTOGENOBJS): | objs/$(RTIMEARCH)_micro + +objs/$(RTIMEARCH)_micro: + echo "Making directory objs/$(RTIMEARCH)_micro"; + mkdir -p objs/$(RTIMEARCH)_micro diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index e59cc62a..ec238c61 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -1,9 +1,11 @@ #include "shape_micro.h" #include "shape_microSupport.h" -#ifndef rti_me_cpp_hxx - #include "rti_me_cpp.hxx" -#endif +#include "rti_me_cpp.hxx" +#include "dds_cpp/dds_cpp_netio.hxx" + +#include +#include #define CONFIGURE_PARTICIPANT_FACTORY config_micro(); #define LISTENER_STATUS_MASK_ALL (DDS_STATUS_MASK_ALL) @@ -16,6 +18,23 @@ #define XCDR2_DATA_REPRESENTATION DDS_XCDR2_DATA_REPRESENTATION #endif +#ifndef PresentationQosPolicyAccessScopeKind + #define PresentationQosPolicyAccessScopeKind DDS_PresentationQosPolicyAccessScopeKind +#endif + +#ifndef INSTANCE_PRESENTATION_QOS + #define INSTANCE_PRESENTATION_QOS DDS_INSTANCE_PRESENTATION_QOS +#endif + +#ifndef TOPIC_PRESENTATION_QOS + #define TOPIC_PRESENTATION_QOS DDS_TOPIC_PRESENTATION_QOS +#endif + +#ifndef GROUP_PRESENTATION_QOS + #define GROUP_PRESENTATION_QOS DDS_GROUP_PRESENTATION_QOS +#endif + + #define DataRepresentationId_t DDS_DataRepresentationId_t #define DataRepresentationIdSeq DDS_DataRepresentationIdSeq @@ -106,7 +125,13 @@ static void config_micro() return; } - udp_property->allow_interface[0] = DDS_String_dup("lo"); +#if defined(RTI_LINUX) + udp_property->allow_interface[0] = DDS_String_dup("lo"); + printf("Configured UDP to allow interface lo\n"); +#elif defined(RTI_DARWIN) + udp_property->allow_interface[0] = DDS_String_dup("lo0"); + printf("Configured UDP to allow interface lo0\n"); +#endif //udp_property->allow_interface[1] = DDS_String_dup("eth0"); if (!registry->register_component( @@ -119,22 +144,73 @@ static void config_micro() return; } - DPDE::DiscoveryPluginProperty discovery_plugin_properties; + DPDE::DiscoveryPluginProperty *discovery_plugin_properties = new DPDE::DiscoveryPluginProperty(); /* Configure properties */ - discovery_plugin_properties.participant_liveliness_assert_period.sec = 5; - discovery_plugin_properties.participant_liveliness_assert_period.nanosec = 0; - discovery_plugin_properties.participant_liveliness_lease_duration.sec = 30; - discovery_plugin_properties.participant_liveliness_lease_duration.nanosec = 0; + discovery_plugin_properties->participant_liveliness_assert_period.sec = 5; + discovery_plugin_properties->participant_liveliness_assert_period.nanosec = 0; + discovery_plugin_properties->participant_liveliness_lease_duration.sec = 30; + discovery_plugin_properties->participant_liveliness_lease_duration.nanosec = 0; if (!registry->register_component( "dpde", DPDEDiscoveryFactory::get_interface(), - &discovery_plugin_properties._parent, + &discovery_plugin_properties->_parent, NULL)) { printf("ERROR: unable to register dpde\n"); return; } } + +static bool configure_dp_qos(DDS::DomainParticipantQos &dp_qos) +{ + if (!dp_qos.discovery.discovery.name.set_name("dpde")) + { + printf("ERROR: unable to set discovery plugin name\n"); + return false; + } + + dp_qos.discovery.initial_peers.maximum(1); + dp_qos.discovery.initial_peers.length(1); + dp_qos.discovery.initial_peers[0] = DDS_String_dup("127.0.0.1"); + /* if there are more remote or local endpoints, you need to increase these limits */ + dp_qos.resource_limits.max_destination_ports = 32; + dp_qos.resource_limits.max_receive_ports = 32; + dp_qos.resource_limits.local_topic_allocation = 2; + dp_qos.resource_limits.local_type_allocation = 2; + //TODO we need to increase this + dp_qos.resource_limits.local_reader_allocation = 2; + dp_qos.resource_limits.local_writer_allocation = 2; + dp_qos.resource_limits.remote_participant_allocation = 8; + dp_qos.resource_limits.remote_reader_allocation = 8; + dp_qos.resource_limits.remote_writer_allocation = 8; + return true; +} + +uint64_t DDS_UInt8Seq_get_length(DDS_OctetSeq * seq) +{ + return seq->length(); +} + +void DDS_UInt8Seq_ensure_length(DDS_OctetSeq * seq, uint64_t length, uint64_t max) +{ + seq->ensure_length(length, max); +} + +unsigned char* DDS_UInt8Seq_get_reference(DDS_OctetSeq * seq, uint64_t index) +{ + return DDS_OctetSeq_get_reference(seq, index); +} + +const unsigned char* DDS_UInt8Seq_get_reference(const DDS_OctetSeq * seq, uint64_t index) +{ + return DDS_OctetSeq_get_reference(seq, index); +} + +struct InstanceHandle_t_less_op { + bool operator()(const DDS::InstanceHandle_t& a, const DDS::InstanceHandle_t& b) const { + return std::memcmp(a.octet, b.octet, 16); + } +}; diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index c68dc5fc..88e7e54c 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -329,7 +329,11 @@ class ShapeOptions { additional_payload_size = 0; +#if defined(RTI_CONNEXT_MICRO) + take_read_next_instance = false; +#else take_read_next_instance = true; +#endif periodic_announcement_period_us = 0; } @@ -1056,6 +1060,10 @@ class ShapeApplication { pub = NULL; sub = NULL; color = NULL; + + topics = NULL; + drs = NULL; + dws = NULL; } //------------------------------------------------------------- @@ -1084,23 +1092,26 @@ class ShapeApplication { topics[i] = NULL; } - drs = (ShapeTypeDataReader**) malloc(sizeof(ShapeTypeDataReader*) * options->num_topics); - if (drs == NULL) { - logger.log_message("Error allocating memory for DataReaders", Verbosity::ERROR); - return false; - } - for (unsigned int i = 0; i < options->num_topics; ++i) { - drs[i] = NULL; + if (options->publish) { + dws = (ShapeTypeDataWriter**) malloc(sizeof(ShapeTypeDataWriter*) * options->num_topics); + if (dws == NULL) { + logger.log_message("Error allocating memory for DataWriters", Verbosity::ERROR); + return false; + } + for (unsigned int i = 0; i < options->num_topics; ++i) { + dws[i] = NULL; + } + } else { + drs = (ShapeTypeDataReader**) malloc(sizeof(ShapeTypeDataReader*) * options->num_topics); + if (drs == NULL) { + logger.log_message("Error allocating memory for DataReaders", Verbosity::ERROR); + return false; + } + for (unsigned int i = 0; i < options->num_topics; ++i) { + drs[i] = NULL; + } } - dws = (ShapeTypeDataWriter**) malloc(sizeof(ShapeTypeDataWriter*) * options->num_topics); - if (dws == NULL) { - logger.log_message("Error allocating memory for DataWriters", Verbosity::ERROR); - return false; - } - for (unsigned int i = 0; i < options->num_topics; ++i) { - dws[i] = NULL; - } #ifndef OBTAIN_DOMAIN_PARTICIPANT_FACTORY #define OBTAIN_DOMAIN_PARTICIPANT_FACTORY DomainParticipantFactory::get_instance() @@ -1117,34 +1128,14 @@ class ShapeApplication { CONFIGURE_PARTICIPANT_FACTORY #endif -#ifdef RTI_CONNEXT_MICRO DDS::DomainParticipantQos dp_qos; + dpf->get_default_participant_qos(dp_qos); - if (!dp_qos.discovery.discovery.name.set_name("dpde")) - { - printf("ERROR: unable to set discovery plugin name\n"); +#ifdef RTI_CONNEXT_MICRO + if (!configure_dp_qos(dp_qos)) { return false; } - - dp_qos.discovery.initial_peers.maximum(1); - dp_qos.discovery.initial_peers.length(1); - dp_qos.discovery.initial_peers[0] = DDS_String_dup("127.0.0.1"); - /* if there are more remote or local endpoints, you need to increase these limits */ - dp_qos.resource_limits.max_destination_ports = 32; - dp_qos.resource_limits.max_receive_ports = 32; - dp_qos.resource_limits.local_topic_allocation = 2; - dp_qos.resource_limits.local_type_allocation = 2; - dp_qos.resource_limits.local_reader_allocation = 2; - dp_qos.resource_limits.local_writer_allocation = 2; - dp_qos.resource_limits.remote_participant_allocation = 8; - dp_qos.resource_limits.remote_reader_allocation = 8; - dp_qos.resource_limits.remote_writer_allocation = 8; - - DDS_StatusMask dp_listener_mask = (DDS_STATUS_MASK_ALL & ~DDS_DATA_ON_READERS_STATUS) & ~DDS_LIVELINESS_CHANGED_STATUS; - - dp = dpf->create_participant( options->domain_id, dp_qos, &dp_listener, dp_listener_mask ); - -#else +#endif #ifdef RTI_CONNEXT_DDS configure_participant_announcements_period(dp_qos, options->periodic_announcement_period_us); @@ -1156,7 +1147,6 @@ class ShapeApplication { return false; } logger.log_message("Participant created", Verbosity::DEBUG); -#endif #ifndef REGISTER_TYPE #define REGISTER_TYPE ShapeTypeTypeSupport::register_type @@ -1337,9 +1327,10 @@ class ShapeApplication { dw_qos.history FIELD_ACCESSOR.depth = options->history_depth; } else if ( options->history_depth == 0 ) { + //TODO check if KEEP_ALL is supported with micro #if defined (RTI_CONNEXT_MICRO) - dw_qos.history FIELD_ACCESSOR.kind = KEEP_LAST_HISTORY_QOS; - dw_qos.history FIELD_ACCESSOR.depth = 500; + dw_qos.history FIELD_ACCESSOR.kind = KEEP_ALL_HISTORY_QOS; + //dw_qos.history FIELD_ACCESSOR.depth = 500; #else dw_qos.history FIELD_ACCESSOR.kind = KEEP_ALL_HISTORY_QOS; #endif @@ -1350,6 +1341,7 @@ class ShapeApplication { } if (options->lifespan_us > 0) { + #if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) || defined(TWINOAKS_COREDX) || defined(INTERCOM_DDS) dw_qos.lifespan FIELD_ACCESSOR.duration.SECONDS_FIELD_NAME = options->lifespan_us / 1000000; dw_qos.lifespan FIELD_ACCESSOR.duration.nanosec = (options->lifespan_us % 1000000) * 1000; @@ -1357,9 +1349,14 @@ class ShapeApplication { dw_qos.lifespan FIELD_ACCESSOR.duration = Duration_t(options->lifespan_us * 1e-6); #endif } +#if !defined(RTI_CONNEXT_MICRO) logger.log_message(" Lifespan = " + std::to_string(dw_qos.lifespan FIELD_ACCESSOR.duration.SECONDS_FIELD_NAME) + " secs", Verbosity::DEBUG); logger.log_message(" " + std::to_string(dw_qos.lifespan FIELD_ACCESSOR.duration.nanosec) + " nanosecs", Verbosity::DEBUG); +#else + logger.log_message(" Lifespan = Not supported", Verbosity::ERROR); +#endif + #if defined(RTI_CONNEXT_DDS) // usage of large data if (PropertyQosPolicyHelper::assert_property( @@ -1377,11 +1374,13 @@ class ShapeApplication { ? "ASYNCHRONOUS_PUBLISH_MODE_QOS" : "SYNCHRONOUS_PUBLISH_MODE_QOS"), Verbosity::DEBUG); #endif +#if !defined(RTI_CONNEXT_MICRO) if (options->unregister) { dw_qos.writer_data_lifecycle FIELD_ACCESSOR .autodispose_unregistered_instances = DDS_BOOLEAN_FALSE; } logger.log_message(" Autodispose_unregistered_instances = " + std::string(dw_qos.writer_data_lifecycle FIELD_ACCESSOR .autodispose_unregistered_instances ? "true" : "false"), Verbosity::DEBUG); +#endif // Create different DataWriters (depending on the number of entities) // The DWs are attached to the same array index of the topics. @@ -1527,12 +1526,12 @@ class ShapeApplication { } logger.log_message(" Ownership = " + QosUtils::to_string(dr_qos.ownership FIELD_ACCESSOR.kind), Verbosity::DEBUG); if ( options->timebasedfilter_interval_us > 0) { -#if defined(EPROSIMA_FAST_DDS) - logger.log_message(" Time based filter not supported", Verbosity::ERROR); +#if defined(EPROSIMA_FAST_DDS) || defined(RTI_CONNEXT_MICRO) + logger.log_message(" TimeBasedFilter = not supported", Verbosity::ERROR); #else dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME = options->timebasedfilter_interval_us / 1000000; dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec = (options->timebasedfilter_interval_us % 1000000) * 1000; -#endif + } logger.log_message(" TimeBasedFilter = " + std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME) + "secs", @@ -1540,7 +1539,8 @@ class ShapeApplication { logger.log_message(" " + std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec) + "nanosecs", Verbosity::DEBUG); - if ( options->deadline_interval_us > 0 ) { +#endif + if ( options->deadline_interval_us > 0 ) { dr_qos.deadline FIELD_ACCESSOR.period.SECONDS_FIELD_NAME = options->deadline_interval_us / 1000000; dr_qos.deadline FIELD_ACCESSOR.period.nanosec = (options->deadline_interval_us % 1000000) * 1000;; } @@ -1575,7 +1575,7 @@ class ShapeApplication { (i > 0 ? std::to_string(i) : "") + "_filtered"; const char* filtered_topic_name = filtered_topic_name_str.c_str(); -#if defined(RTI_CONNEXT_DDS) + #if defined(RTI_CONNEXT_DDS) char parameter[64]; snprintf(parameter, 64, "'%s'", options->color); StringSeq_push(cf_params, parameter); @@ -1583,7 +1583,7 @@ class ShapeApplication { cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color MATCH %0", cf_params); logger.log_message(" ContentFilterTopic = \"color MATCH " + std::string(parameter) + std::string("\""), Verbosity::DEBUG); -#elif defined(INTERCOM_DDS) + #elif defined(INTERCOM_DDS) char parameter[64]; snprintf(parameter, 64, "'%s'", options->color); StringSeq_push(cf_params, parameter); @@ -1591,17 +1591,17 @@ class ShapeApplication { cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color = %0", cf_params); logger.log_message(" ContentFilterTopic = \"color = " + std::string(parameter) + std::string("\""), Verbosity::DEBUG); -#elif defined(TWINOAKS_COREDX) || defined(OPENDDS) + #elif defined(TWINOAKS_COREDX) || defined(OPENDDS) StringSeq_push(cf_params, options->color); cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color = %0", cf_params); logger.log_message(" ContentFilterTopic = \"color = " + std::string(options->color) + std::string("\""), Verbosity::DEBUG); -#elif defined(EPROSIMA_FAST_DDS) + #elif defined(EPROSIMA_FAST_DDS) cf_params.push_back(std::string("'") + options->color + std::string("'")); cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color = %0", cf_params); logger.log_message(" ContentFilterTopic = \"color = " + cf_params[0] + std::string("\""), Verbosity::DEBUG); -#endif + #endif if (cft == NULL) { logger.log_message("failed to create content filtered topic", Verbosity::ERROR); return false; @@ -1613,7 +1613,9 @@ class ShapeApplication { logger.log_message("failed to create datareader[" + std::to_string(i) + "] topic: " + topics[i]->get_name(), Verbosity::ERROR); return false; } +#endif } + } else { // Create different DataReaders (depending on the number of entities) // The DRs are attached to the same array index of the topics. @@ -1680,6 +1682,8 @@ class ShapeApplication { #if defined(EPROSIMA_FAST_DDS) // TODO: Remove when Fast DDS supports `get_key_value()` std::map instance_handle_color; +#elif defined(RTI_CONNEXT_MICRO) + std::map instance_handle_color; #endif while ( ! all_done ) { @@ -1702,7 +1706,9 @@ class ShapeApplication { printf("Reading with ordered access, iteration %d\n",n); } if (options->coherent_set_enabled || options->ordered_access_enabled) { +#if !defined(RTI_CONNEXT_MICRO) sub->begin_access(); +#endif } for (unsigned int i = 0; i < options->num_topics; ++i) { previous_handles[i] = HANDLE_NIL; @@ -1710,6 +1716,7 @@ class ShapeApplication { if (!options->use_read) { if (options->take_read_next_instance) { logger.log_message("Calling take_next_instance() function", Verbosity::DEBUG); +#if !defined(RTI_CONNEXT_MICRO) retval = drs[i]->take_next_instance ( samples, sample_infos, LENGTH_UNLIMITED, @@ -1717,6 +1724,7 @@ class ShapeApplication { ANY_SAMPLE_STATE, ANY_VIEW_STATE, ANY_INSTANCE_STATE ); +#endif } else { logger.log_message("Calling take() function", Verbosity::DEBUG); retval = drs[i]->take ( samples, @@ -1728,6 +1736,7 @@ class ShapeApplication { } } else { /* Use read_next_instance*/ if (options->take_read_next_instance) { +#if !defined(RTI_CONNEXT_MICRO) logger.log_message("Calling read_next_instance() function", Verbosity::DEBUG); retval = drs[i]->read_next_instance ( samples, sample_infos, @@ -1736,6 +1745,7 @@ class ShapeApplication { ANY_SAMPLE_STATE, ANY_VIEW_STATE, ANY_INSTANCE_STATE ); +#endif } else { logger.log_message("Calling read() function", Verbosity::DEBUG); retval = drs[i]->read ( samples, @@ -1788,12 +1798,17 @@ class ShapeApplication { printf("\n"); #if defined(EPROSIMA_FAST_DDS) instance_handle_color[sample_info->instance_handle] = sample->color FIELD_ACCESSOR STRING_IN; +#elif defined(RTI_CONNEXT_MICRO) + instance_handle_color[sample_info->instance_handle] = + std::string(sample->color FIELD_ACCESSOR STRING_IN); #endif } else { ShapeType shape_key; shape_initialize_w_color(shape_key, NULL); #if defined(EPROSIMA_FAST_DDS) shape_key.color FIELD_ACCESSOR = instance_handle_color[sample_info->instance_handle] NAME_ACCESSOR; +#elif defined(RTI_CONNEXT_MICRO) + strncpy(shape_key.color, instance_handle_color[sample_info->instance_handle].c_str(), sizeof(shape_key.color)); #else drs[i]->get_key_value(shape_key, sample_info->instance_handle); #endif @@ -1821,7 +1836,9 @@ class ShapeApplication { } if (options->coherent_set_enabled || options->ordered_access_enabled) { +#if !defined(RTI_CONNEXT_MICRO) sub->end_access(); +#endif } // increasing number of iterations @@ -1898,6 +1915,7 @@ class ShapeApplication { shape.shapesize FIELD_ACCESSOR += 1; } +#if !defined(RTI_CONNEXT_MICRO) if (options->coherent_set_enabled || options->ordered_access_enabled) { // n also represents the number of samples written per publisher per instance if (options->coherent_set_sample_count != 0 && n % options->coherent_set_sample_count == 0) { @@ -1905,6 +1923,7 @@ class ShapeApplication { pub->begin_coherent_changes(); } } +#endif for (unsigned int i = 0; i < options->num_topics; ++i) { for (unsigned int j = 0; j < options->num_instances; ++j) { @@ -1935,6 +1954,7 @@ class ShapeApplication { } } +#if !defined(RTI_CONNEXT_MICRO) if (options->coherent_set_enabled || options->ordered_access_enabled) { // n also represents the number of samples written per publisher per instance if (options->coherent_set_sample_count != 0 @@ -1943,6 +1963,7 @@ class ShapeApplication { pub->end_coherent_changes(); } } +#endif usleep(options->write_period_us); // increase number of iterations @@ -1986,13 +2007,15 @@ class ShapeApplication { /* ensure that all updates have been acked by reader[s] */ /* otherwise the app may terminate before reader has seen all updates */ -#if defined(RTI_CONNEXT_DDS) || defined (OPENDDS) +#if defined(RTI_CONNEXT_DDS) || defined (RTI_CONNEXT_MICRO) || defined (OPENDDS) Duration_t max_wait = {1, 0}; /* should not take long... */ #else Duration_t max_wait( 1, 0 ); /* should not take long... */ #endif for (unsigned int i = 0; i < options->num_topics; ++i) { +#if !defined(RTI_CONNEXT_MICRO) dws[i]->wait_for_acknowledgments( max_wait ); +#endif } return true; diff --git a/srcCxx/shape_micro.idl b/srcCxx/shape_micro.idl index 312a23a5..bcd8c4fd 100644 --- a/srcCxx/shape_micro.idl +++ b/srcCxx/shape_micro.idl @@ -5,4 +5,5 @@ struct ShapeType { long x; long y; long shapesize; + sequence additional_payload_size; }; From 83e93128269cf02c28ab8c4e4fa53445d48fd001 Mon Sep 17 00:00:00 2001 From: Arul Moondra Date: Tue, 2 Dec 2025 15:48:45 -0800 Subject: [PATCH 15/44] Fix braces which caused some of the setting to not take effect for the reader --- srcCxx/shape_main.cxx | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 88e7e54c..493552fa 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -1532,15 +1532,15 @@ class ShapeApplication { dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME = options->timebasedfilter_interval_us / 1000000; dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec = (options->timebasedfilter_interval_us % 1000000) * 1000; - } - logger.log_message(" TimeBasedFilter = " + + logger.log_message(" TimeBasedFilter = " + std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME) + "secs", Verbosity::DEBUG); - logger.log_message(" " + + logger.log_message(" " + std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec) + "nanosecs", Verbosity::DEBUG); #endif - if ( options->deadline_interval_us > 0 ) { + } + if ( options->deadline_interval_us > 0 ) { dr_qos.deadline FIELD_ACCESSOR.period.SECONDS_FIELD_NAME = options->deadline_interval_us / 1000000; dr_qos.deadline FIELD_ACCESSOR.period.nanosec = (options->deadline_interval_us % 1000000) * 1000;; } @@ -1569,12 +1569,12 @@ class ShapeApplication { ContentFilteredTopic *cft = NULL; StringSeq cf_params; - for (unsigned int i = 0; i < options->num_topics; ++i) { - const std::string filtered_topic_name_str = + for (unsigned int i = 0; i < options->num_topics; ++i) { + const std::string filtered_topic_name_str = std::string(options->topic_name) + (i > 0 ? std::to_string(i) : "") + "_filtered"; - const char* filtered_topic_name = filtered_topic_name_str.c_str(); + const char* filtered_topic_name = filtered_topic_name_str.c_str(); #if defined(RTI_CONNEXT_DDS) char parameter[64]; snprintf(parameter, 64, "'%s'", options->color); @@ -1613,8 +1613,9 @@ class ShapeApplication { logger.log_message("failed to create datareader[" + std::to_string(i) + "] topic: " + topics[i]->get_name(), Verbosity::ERROR); return false; } -#endif } +#endif + } else { // Create different DataReaders (depending on the number of entities) @@ -1729,10 +1730,14 @@ class ShapeApplication { logger.log_message("Calling take() function", Verbosity::DEBUG); retval = drs[i]->take ( samples, sample_infos, - LENGTH_UNLIMITED, - ANY_SAMPLE_STATE, - ANY_VIEW_STATE, - ANY_INSTANCE_STATE ); + DDS_LENGTH_UNLIMITED, + DDS_ANY_SAMPLE_STATE, + DDS_ANY_VIEW_STATE, + DDS_ANY_INSTANCE_STATE ); + if (retval == DDS_RETCODE_OK) { + logger.log_message("Taken " + std::to_string(samples.length()) + + " sample(s)", Verbosity::DEBUG); + } } } else { /* Use read_next_instance*/ if (options->take_read_next_instance) { From 1afc3925e5195a1c224ac89a703ab66935c34638 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 3 Dec 2025 15:13:27 +0100 Subject: [PATCH 16/44] Disabled logging for Micro messages as they print a NUL char and fixed some small issues --- generate_xlsx_report.py | 7 ++-- srcCxx/shape_configurator_rti_connext_micro.h | 2 ++ srcCxx/shape_main.cxx | 32 +++++++++++-------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/generate_xlsx_report.py b/generate_xlsx_report.py index 9c77ee66..4cdb90b7 100644 --- a/generate_xlsx_report.py +++ b/generate_xlsx_report.py @@ -9,7 +9,6 @@ ################################################################# import argparse -from io import BytesIO import junitparser import lxml import pathlib @@ -169,11 +168,9 @@ def __init__(self, input: pathlib.Path): @staticmethod def xml_parser(file): """Function to parse the XML file""" - # Remove null bytes from the file - with open(file, "rb") as f: - data = f.read().replace(b"\x00", b"") + parser = lxml.etree.XMLParser(huge_tree=True) - return lxml.etree.parse(BytesIO(data), parser) + return lxml.etree.parse(file, parser) def update_value_aggregated_data_dict(self, dictionary: dict, diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index ec238c61..c9ac72ec 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -81,6 +81,8 @@ static void config_micro() { RT::Registry *registry = NULL; + OSAPI_Log_set_verbosity(OSAPI_LOG_VERBOSITY_SILENT); + registry = DDSTheParticipantFactory->get_registry(); /* Register Writer History */ diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 493552fa..cf20ece1 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -1519,27 +1519,32 @@ class ShapeApplication { #if defined(EPROSIMA_FAST_DDS) logger.log_message(" DataRepresentation = " + QosUtils::to_string(dr_qos.representation().m_value[0]), Verbosity::DEBUG); #else - logger.log_message(" DataRepresentation = " + QosUtils::to_string(dr_qos.representation FIELD_ACCESSOR.value[0]), Verbosity::DEBUG); + logger.log_message(" DataRepresentation = " + QosUtils::to_string(dr_qos.representation FIELD_ACCESSOR.value[0]), Verbosity::DEBUG); #endif if ( options->ownership_strength != -1 ) { dr_qos.ownership FIELD_ACCESSOR.kind = EXCLUSIVE_OWNERSHIP_QOS; } logger.log_message(" Ownership = " + QosUtils::to_string(dr_qos.ownership FIELD_ACCESSOR.kind), Verbosity::DEBUG); + + if ( options->timebasedfilter_interval_us > 0) { #if defined(EPROSIMA_FAST_DDS) || defined(RTI_CONNEXT_MICRO) logger.log_message(" TimeBasedFilter = not supported", Verbosity::ERROR); #else dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME = options->timebasedfilter_interval_us / 1000000; dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec = (options->timebasedfilter_interval_us % 1000000) * 1000; - - logger.log_message(" TimeBasedFilter = " + - std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME) + "secs", - Verbosity::DEBUG); - logger.log_message(" " + - std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec) + "nanosecs", - Verbosity::DEBUG); #endif } + +#if !defined(EPROSIMA_FAST_DDS) && !defined(RTI_CONNEXT_MICRO) + logger.log_message(" TimeBasedFilter = " + + std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME) + "secs", + Verbosity::DEBUG); + logger.log_message(" " + + std::to_string(dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec) + "nanosecs", + Verbosity::DEBUG); +#endif + if ( options->deadline_interval_us > 0 ) { dr_qos.deadline FIELD_ACCESSOR.period.SECONDS_FIELD_NAME = options->deadline_interval_us / 1000000; dr_qos.deadline FIELD_ACCESSOR.period.nanosec = (options->deadline_interval_us % 1000000) * 1000;; @@ -1730,10 +1735,10 @@ class ShapeApplication { logger.log_message("Calling take() function", Verbosity::DEBUG); retval = drs[i]->take ( samples, sample_infos, - DDS_LENGTH_UNLIMITED, - DDS_ANY_SAMPLE_STATE, - DDS_ANY_VIEW_STATE, - DDS_ANY_INSTANCE_STATE ); + LENGTH_UNLIMITED, + ANY_SAMPLE_STATE, + ANY_VIEW_STATE, + ANY_INSTANCE_STATE ); if (retval == DDS_RETCODE_OK) { logger.log_message("Taken " + std::to_string(samples.length()) + " sample(s)", Verbosity::DEBUG); @@ -1813,7 +1818,8 @@ class ShapeApplication { #if defined(EPROSIMA_FAST_DDS) shape_key.color FIELD_ACCESSOR = instance_handle_color[sample_info->instance_handle] NAME_ACCESSOR; #elif defined(RTI_CONNEXT_MICRO) - strncpy(shape_key.color, instance_handle_color[sample_info->instance_handle].c_str(), sizeof(shape_key.color)); + // 128 is the max length of the color string + strncpy(shape_key.color, instance_handle_color[sample_info->instance_handle].c_str(), 128); #else drs[i]->get_key_value(shape_key, sample_info->instance_handle); #endif From 13448580a32a2ff0e283277320d1ac372c1d4947 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Thu, 11 Dec 2025 18:26:38 +0100 Subject: [PATCH 17/44] Printing 'not supported' messages only when enabling something that is not supported --- srcCxx/shape_configurator_rti_connext_micro.h | 31 +++-- srcCxx/shape_main.cxx | 121 +++++++++++------- 2 files changed, 95 insertions(+), 57 deletions(-) diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index c9ac72ec..99d14ff2 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -129,12 +129,9 @@ static void config_micro() #if defined(RTI_LINUX) udp_property->allow_interface[0] = DDS_String_dup("lo"); - printf("Configured UDP to allow interface lo\n"); #elif defined(RTI_DARWIN) udp_property->allow_interface[0] = DDS_String_dup("lo0"); - printf("Configured UDP to allow interface lo0\n"); #endif - //udp_property->allow_interface[1] = DDS_String_dup("eth0"); if (!registry->register_component( NETIO_DEFAULT_UDP_NAME, @@ -180,17 +177,31 @@ static bool configure_dp_qos(DDS::DomainParticipantQos &dp_qos) /* if there are more remote or local endpoints, you need to increase these limits */ dp_qos.resource_limits.max_destination_ports = 32; dp_qos.resource_limits.max_receive_ports = 32; - dp_qos.resource_limits.local_topic_allocation = 2; - dp_qos.resource_limits.local_type_allocation = 2; + dp_qos.resource_limits.local_topic_allocation = 8; + dp_qos.resource_limits.local_type_allocation = 8; //TODO we need to increase this - dp_qos.resource_limits.local_reader_allocation = 2; - dp_qos.resource_limits.local_writer_allocation = 2; - dp_qos.resource_limits.remote_participant_allocation = 8; - dp_qos.resource_limits.remote_reader_allocation = 8; - dp_qos.resource_limits.remote_writer_allocation = 8; + dp_qos.resource_limits.local_reader_allocation = 8; + dp_qos.resource_limits.local_writer_allocation = 8; + dp_qos.resource_limits.remote_participant_allocation = 16; + dp_qos.resource_limits.remote_reader_allocation = 16; + dp_qos.resource_limits.remote_writer_allocation = 16; return true; } +void config_dw_qos(DDS::DataWriterQos &dw_qos) { + dw_qos.resource_limits.max_instances = 500; + dw_qos.resource_limits.max_samples = 500; + dw_qos.resource_limits.max_samples_per_instance = 500; +} + +void config_dr_qos(DDS::DataReaderQos &dr_qos) { + dr_qos.resource_limits.max_instances = 500; + dr_qos.resource_limits.max_samples = 500; + dr_qos.resource_limits.max_samples_per_instance = 500; + dr_qos.reader_resource_limits.max_remote_writers = 16; + dr_qos.reader_resource_limits.max_samples_per_remote_writer = 500; +} + uint64_t DDS_UInt8Seq_get_length(DDS_OctetSeq * seq) { return seq->length(); diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index cf20ece1..f31b63f3 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -329,11 +329,7 @@ class ShapeOptions { additional_payload_size = 0; -#if defined(RTI_CONNEXT_MICRO) - take_read_next_instance = false; -#else take_read_next_instance = true; -#endif periodic_announcement_period_us = 0; } @@ -429,16 +425,6 @@ class ShapeOptions { color = strdup("BLUE"); logger.log_message("warning: color was not specified, defaulting to \"BLUE\"", Verbosity::ERROR); } -#if defined(RTI_CONNEXT_MICRO) - if (!publish && color != NULL) { - free(color); - color = NULL; - logger.log_message("warning: content filtered topic not supported, normal topic used", Verbosity::ERROR); - } - if (!publish && take_read_next_instance == true ) { - logger.log_message("warning: use of take/read_next_instance() not supported, using take/read()", Verbosity::ERROR); - } -#endif if (publish && timebasedfilter_interval_us > 0) { logger.log_message("warning: time base filter [--time-filter] ignored on publisher applications", Verbosity::ERROR); } @@ -472,6 +458,17 @@ class ShapeOptions { if (!coherent_set_enabled && !ordered_access_enabled && coherent_set_access_scope_set) { logger.log_message("warning: --access-scope ignored because not coherent, or ordered access enabled", Verbosity::ERROR); } +#if defined(RTI_CONNEXT_MICRO) + if (!publish && color != NULL) { + free(color); + color = NULL; + logger.log_message("warning: content filtered topic not supported, normal topic used", Verbosity::ERROR); + } + if (!publish && take_read_next_instance == true ) { + take_read_next_instance = false; + logger.log_message("warning: use of take/read_next_instance() not available, using take/read()", Verbosity::ERROR); + } +#endif return true; } @@ -1223,7 +1220,8 @@ class ShapeApplication { { logger.log_message(" Presentation Access Scope " + QosUtils::to_string(pub_qos.presentation.access_scope) - + std::string(" : Not supported"), Verbosity::ERROR); + + std::string(" : not supported"), Verbosity::ERROR); + return false; } #endif #if defined(INTERCOM_DDS) @@ -1231,22 +1229,31 @@ class ShapeApplication { { logger.log_message(" Coherent Access with Presentation Access Scope " + QosUtils::to_string(pub_qos.presentation.access_scope) - + std::string(" : Not supported"), Verbosity::ERROR); + + std::string(" : not supported"), Verbosity::ERROR); + return false; } #endif } - logger.log_message(" Presentation Coherent Access = " + std::string(pub_qos.presentation.coherent_access ? "true" : "false"), Verbosity::DEBUG); logger.log_message(" Presentation Ordered Access = " + std::string(pub_qos.presentation.ordered_access ? "true" : "false"), Verbosity::DEBUG); logger.log_message(" Presentation Access Scope = " + QosUtils::to_string(pub_qos.presentation.access_scope), Verbosity::DEBUG); - #else - logger.log_message(" Presentation Coherent Access = Not supported", Verbosity::ERROR); - logger.log_message(" Presentation Ordered Access = Not supported", Verbosity::ERROR); - logger.log_message(" Presentation Access Scope = Not supported", Verbosity::ERROR); + if (options->coherent_set_enabled) { + logger.log_message(" Presentation Coherent Access = not supported", Verbosity::ERROR); + return false; + } + if (options->ordered_access_enabled) { + logger.log_message(" Presentation Ordered Access = not supported", Verbosity::ERROR); + return false; + } + if ((options->coherent_set_enabled || options->ordered_access_enabled) + && (options->coherent_set_access_scope != INSTANCE_PRESENTATION_QOS)) { + logger.log_message(" Presentation Access Scope = not supported", Verbosity::ERROR); + return false; + } #endif pub = dp->create_publisher(pub_qos, NULL, LISTENER_STATUS_MASK_NONE); @@ -1259,14 +1266,21 @@ class ShapeApplication { pub->get_default_datawriter_qos( dw_qos ); #if defined (RTI_CONNEXT_MICRO) - dw_qos.resource_limits.max_instances = 500; - dw_qos.resource_limits.max_samples = 500; - dw_qos.resource_limits.max_samples_per_instance = 500; + config_dw_qos(dw_qos); #endif dw_qos.reliability FIELD_ACCESSOR.kind = options->reliability_kind; logger.log_message(" Reliability = " + QosUtils::to_string(dw_qos.reliability FIELD_ACCESSOR.kind), Verbosity::DEBUG); dw_qos.durability FIELD_ACCESSOR.kind = options->durability_kind; +#if defined(RTI_CONNEXT_MICRO) + if (dw_qos.durability FIELD_ACCESSOR.kind == TRANSIENT_DURABILITY_QOS) { + logger.log_message(" Durability = TRANSIENT_DURABILITY_QOS : not supported", Verbosity::ERROR); + return false; + } else if (dw_qos.durability FIELD_ACCESSOR.kind == PERSISTENT_DURABILITY_QOS) { + logger.log_message(" Durability = PERSISTENT_DURABILITY_QOS : not supported", Verbosity::ERROR); + return false; + } +#endif logger.log_message(" Durability = " + QosUtils::to_string(dw_qos.durability FIELD_ACCESSOR.kind), Verbosity::DEBUG); #if defined(RTI_CONNEXT_DDS) || defined (RTI_CONNEXT_MICRO) @@ -1327,13 +1341,7 @@ class ShapeApplication { dw_qos.history FIELD_ACCESSOR.depth = options->history_depth; } else if ( options->history_depth == 0 ) { - //TODO check if KEEP_ALL is supported with micro -#if defined (RTI_CONNEXT_MICRO) - dw_qos.history FIELD_ACCESSOR.kind = KEEP_ALL_HISTORY_QOS; - //dw_qos.history FIELD_ACCESSOR.depth = 500; -#else dw_qos.history FIELD_ACCESSOR.kind = KEEP_ALL_HISTORY_QOS; -#endif } logger.log_message(" History = " + QosUtils::to_string(dw_qos.history FIELD_ACCESSOR.kind), Verbosity::DEBUG); if (dw_qos.history FIELD_ACCESSOR.kind == KEEP_LAST_HISTORY_QOS){ @@ -1341,8 +1349,10 @@ class ShapeApplication { } if (options->lifespan_us > 0) { - -#if defined(RTI_CONNEXT_DDS) || defined(OPENDDS) || defined(TWINOAKS_COREDX) || defined(INTERCOM_DDS) +#if defined (RTI_CONNEXT_MICRO) + logger.log_message(" Lifespan = not supported", Verbosity::ERROR); + return false; +#elif defined(RTI_CONNEXT_DDS) || defined(OPENDDS) || defined(TWINOAKS_COREDX) || defined(INTERCOM_DDS) dw_qos.lifespan FIELD_ACCESSOR.duration.SECONDS_FIELD_NAME = options->lifespan_us / 1000000; dw_qos.lifespan FIELD_ACCESSOR.duration.nanosec = (options->lifespan_us % 1000000) * 1000; #elif defined(EPROSIMA_FAST_DDS) @@ -1350,11 +1360,10 @@ class ShapeApplication { #endif } #if !defined(RTI_CONNEXT_MICRO) - logger.log_message(" Lifespan = " + std::to_string(dw_qos.lifespan FIELD_ACCESSOR.duration.SECONDS_FIELD_NAME) + " secs", Verbosity::DEBUG); - logger.log_message(" " + std::to_string(dw_qos.lifespan FIELD_ACCESSOR.duration.nanosec) + " nanosecs", Verbosity::DEBUG); - -#else - logger.log_message(" Lifespan = Not supported", Verbosity::ERROR); + logger.log_message(" Lifespan = " + std::to_string(dw_qos.lifespan FIELD_ACCESSOR.duration.SECONDS_FIELD_NAME) + " secs", + Verbosity::DEBUG); + logger.log_message(" " + std::to_string(dw_qos.lifespan FIELD_ACCESSOR.duration.nanosec) + " nanosecs", + Verbosity::DEBUG); #endif #if defined(RTI_CONNEXT_DDS) @@ -1443,7 +1452,8 @@ class ShapeApplication { { logger.log_message(" Presentation Access Scope " + QosUtils::to_string(sub_qos.presentation.access_scope) - + std::string(" : Not supported"), Verbosity::ERROR); + + std::string(" : not supported"), Verbosity::ERROR); + return false; } #endif #if defined(INTERCOM_DDS) @@ -1451,7 +1461,8 @@ class ShapeApplication { { logger.log_message(" Coherent Access with Presentation Access Scope " + QosUtils::to_string(sub_qos.presentation.access_scope) - + std::string(" : Not supported"), Verbosity::ERROR); + + std::string(" : not supported"), Verbosity::ERROR); + return false; } #endif } @@ -1464,9 +1475,19 @@ class ShapeApplication { QosUtils::to_string(sub_qos.presentation.access_scope), Verbosity::DEBUG); #else - logger.log_message(" Presentation Coherent Access = Not supported", Verbosity::ERROR); - logger.log_message(" Presentation Ordered Access = Not supported", Verbosity::ERROR); - logger.log_message(" Presentation Access Scope = Not supported", Verbosity::ERROR); + if (options->coherent_set_enabled) { + logger.log_message(" Presentation Coherent Access = not supported", Verbosity::ERROR); + return false; + } + if (options->ordered_access_enabled) { + logger.log_message(" Presentation Ordered Access = not supported", Verbosity::ERROR); + return false; + } + if ((options->coherent_set_enabled || options->ordered_access_enabled) + && (options->coherent_set_access_scope != INSTANCE_PRESENTATION_QOS)) { + logger.log_message(" Presentation Access Scope = not supported", Verbosity::ERROR); + return false; + } #endif sub = dp->create_subscriber( sub_qos, NULL, LISTENER_STATUS_MASK_NONE ); @@ -1480,16 +1501,21 @@ class ShapeApplication { sub->get_default_datareader_qos( dr_qos ); #if defined (RTI_CONNEXT_MICRO) - dr_qos.resource_limits.max_instances = 500; - dr_qos.resource_limits.max_samples = 500; - dr_qos.resource_limits.max_samples_per_instance = 500; - dr_qos.reader_resource_limits.max_remote_writers = 2; - dr_qos.reader_resource_limits.max_samples_per_remote_writer = 500; + config_dr_qos(dr_qos); #endif dr_qos.reliability FIELD_ACCESSOR.kind = options->reliability_kind; logger.log_message(" Reliability = " + QosUtils::to_string(dr_qos.reliability FIELD_ACCESSOR.kind), Verbosity::DEBUG); dr_qos.durability FIELD_ACCESSOR.kind = options->durability_kind; +#if defined(RTI_CONNEXT_MICRO) + if (dr_qos.durability FIELD_ACCESSOR.kind == TRANSIENT_DURABILITY_QOS) { + logger.log_message(" Durability = TRANSIENT_DURABILITY_QOS : not supported", Verbosity::ERROR); + return false; + } else if (dr_qos.durability FIELD_ACCESSOR.kind == PERSISTENT_DURABILITY_QOS) { + logger.log_message(" Durability = PERSISTENT_DURABILITY_QOS : not supported", Verbosity::ERROR); + return false; + } +#endif logger.log_message(" Durability = " + QosUtils::to_string(dr_qos.durability FIELD_ACCESSOR.kind), Verbosity::DEBUG); #if defined(RTI_CONNEXT_DDS) || defined (RTI_CONNEXT_MICRO) @@ -1530,6 +1556,7 @@ class ShapeApplication { if ( options->timebasedfilter_interval_us > 0) { #if defined(EPROSIMA_FAST_DDS) || defined(RTI_CONNEXT_MICRO) logger.log_message(" TimeBasedFilter = not supported", Verbosity::ERROR); + return false; #else dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.SECONDS_FIELD_NAME = options->timebasedfilter_interval_us / 1000000; dr_qos.time_based_filter FIELD_ACCESSOR.minimum_separation.nanosec = (options->timebasedfilter_interval_us % 1000000) * 1000; From e7139f5dc97d77de97e89a49e6c7a8bc06c9af00 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Thu, 11 Dec 2025 18:36:01 +0100 Subject: [PATCH 18/44] Added a way of checking if a feature is not supported and report the test result accordingly --- generate_xlsx_report.py | 177 ++++++++++++++++++++++++------------- interoperability_report.py | 77 ++++++++++------ rtps_test_utilities.py | 2 + 3 files changed, 171 insertions(+), 85 deletions(-) diff --git a/generate_xlsx_report.py b/generate_xlsx_report.py index 4cdb90b7..3eaaa389 100644 --- a/generate_xlsx_report.py +++ b/generate_xlsx_report.py @@ -19,6 +19,12 @@ import datetime from rtps_test_utilities import log_message import test_suite +from enum import Enum + +class TestStatus(Enum): + PASSED = 1 + FAILED = 2 + UNSUPPORTED = 3 class XlxsReportArgumentParser: """Class that parse the arguments of the application.""" @@ -90,14 +96,15 @@ def get_product_name(product:str) -> str: class JunitAggregatedData: """ - Class that contains the JUnit aggregated data as a tuple of 2 integers - [tests_passed, total_tests]. This identifies one cell in the summary - table that shows the product and the amount of tests passed and total. + Class that contains the JUnit aggregated data as a tuple of 3 integers + [tests_passed, total_tests, tests_unsupported]. This identifies one cell in + the summary table that shows the product and the amount of tests passed, + total and unsupported. """ - data: tuple[int,int] # [tests_passed, total_tests] + data: tuple[int,int, int] # [tests_passed, total_tests, tests_unsupported] - def __init__(self, passed_tests: int, total_tests: int) -> None: - self.data = [passed_tests, total_tests] + def __init__(self, passed_tests: int, total_tests: int, unsupported_tests: int) -> None: + self.data = [passed_tests, total_tests, unsupported_tests] def get_passed_tests(self): return self.data[0] @@ -105,8 +112,11 @@ def get_passed_tests(self): def get_total_tests(self): return self.data[1] + def get_unsupported_tests(self): + return self.data[2] + def __str__(self) -> str: - return f'({self.data[0]}, {self.data[1]})' + return f'({self.data[0]}, {self.data[1]}, {self.data[2]})' class JunitTestCaseAggregatedData: """ @@ -115,14 +125,13 @@ class JunitTestCaseAggregatedData: Publisher or Subscriber) and with all other products (as Subscribers or Publishers, the opposite). This tuple is composed by 2 strings that identifies the other product - (Publisher or Subscriber), the test name and whether the test was - successful or not. + (Publisher or Subscriber), the test name and the status of the test. """ - # [publisher or subscriber name, test_name, passed_tests] - data: tuple[str,str,bool] = None + # [publisher or subscriber name, test_name, status] + data: tuple[str,str,TestStatus] = None - def __init__(self, product: str, test_name: str, passed: bool) -> None: - self.data = (product, test_name, passed) + def __init__(self, product: str, test_name: str, status: TestStatus) -> None: + self.data = (product, test_name, status) def get_product_name(self): return self.data[0] @@ -130,7 +139,7 @@ def get_product_name(self): def get_test_name(self): return self.data[1] - def get_passed(self): + def get_status(self): return self.data[2] def __str__(self) -> str: @@ -185,6 +194,7 @@ def update_value_aggregated_data_dict(self, updated_data = JunitAggregatedData( dictionary[key].get_passed_tests() + value.get_passed_tests(), dictionary[key].get_total_tests() + value.get_total_tests(), + dictionary[key].get_unsupported_tests() + value.get_unsupported_tests() ) dictionary[key] = updated_data else: @@ -221,47 +231,30 @@ def get_info(self, input: pathlib.Path = None): publisher_name = ProductUtils.get_product_name(product_names.group(1)) subscriber_name = ProductUtils.get_product_name(product_names.group(2)) - # get the value of the passed_tests and total_tests as a - # JunitAggregatedData - element = JunitAggregatedData( - suite.tests - suite.failures - suite.skipped - suite.errors, - suite.tests - ) - - # update the information of the product in the summary_dict with - # the information of the publisher and the subscriber - self.update_value_aggregated_data_dict( - self.summary_dict, publisher_name, element) - # do not add duplicated data if the publisher and subscriber names - # are the same - if publisher_name != subscriber_name: - self.update_value_aggregated_data_dict( - self.summary_dict, subscriber_name, element) - - # Get table with the summary of the test passed/total_tests for - # every product as publisher and as subscriber - product_dict_key = (publisher_name, subscriber_name) - product_test_data = JunitAggregatedData( - suite.tests - suite.failures - suite.skipped - suite.errors, - suite.tests) - self.update_value_aggregated_data_dict( - self.product_summary_dict, - product_dict_key, - product_test_data) - # for each test case in the test suite, fill out the dictionaries # that contains information about the product as publisher and # subscriber + unsupported_tests_count = 0 for case in list(iter(suite)): + this_test_unsupported = False test_name = re.search(r'((?:Test_)[\S]+_\d+)', case.name).group(1) + # count number of unsupported tests for the summary + # result array is not empty and the message contains 'UNSUPPORTED_FEATURE' + if case.result and len(case.result) > 0 \ + and 'UNSUPPORTED_FEATURE' in case.result[0].message.upper(): + unsupported_tests_count += 1 + this_test_unsupported = True + # update the value of the publisher_name as publisher with # all products as subscribers. - # the tuple is (subscriber_name, test_name, is_passed) + # the tuple is (subscriber_name, test_name, status) publisher_test_result = JunitTestCaseAggregatedData( product=subscriber_name, test_name=test_name, - passed=case.is_passed + status=TestStatus.PASSED if case.is_passed + else TestStatus.FAILED if not this_test_unsupported + else TestStatus.UNSUPPORTED ) # add the resulting tuple to the publisher dictionary, the key @@ -275,11 +268,13 @@ def get_info(self, input: pathlib.Path = None): # update the value of the subscriber_name as subscriber with # all products as publishers. - # the tuple is (publisher_name, test_name, is_passed) + # the tuple is (publisher_name, test_name, status) subscriber_test_result = JunitTestCaseAggregatedData( product=publisher_name, test_name=test_name, - passed=case.is_passed + status=TestStatus.PASSED if case.is_passed + else TestStatus.FAILED if not this_test_unsupported + else TestStatus.UNSUPPORTED ) # add the resulting tuple to the subscriber dictionary, the key @@ -291,6 +286,37 @@ def get_info(self, input: pathlib.Path = None): product_dict=self.subscriber_product_dict ) + # get the value of the passed_tests, total_tests and + # unsupported_tests as a JunitAggregatedData + element = JunitAggregatedData( + suite.tests - suite.failures - suite.skipped - suite.errors, + suite.tests, + unsupported_tests_count + ) + + # update the information of the product in the summary_dict with + # the information of the publisher and the subscriber + self.update_value_aggregated_data_dict( + self.summary_dict, publisher_name, element) + # do not add duplicated data if the publisher and subscriber names + # are the same + if publisher_name != subscriber_name: + self.update_value_aggregated_data_dict( + self.summary_dict, subscriber_name, element) + + # Get table with the summary of the test + # passed/total_tests/unsupported_tests for every product as + # publisher and as subscriber + product_dict_key = (publisher_name, subscriber_name) + product_test_data = JunitAggregatedData( + suite.tests - suite.failures - suite.skipped - suite.errors, + suite.tests, + unsupported_tests_count) + self.update_value_aggregated_data_dict( + self.product_summary_dict, + product_dict_key, + product_test_data) + class ColorUtils: """Set specific colors""" GREEN = '#4EB168' @@ -437,17 +463,20 @@ def get_format_color(self, index: int, num_elements: int): else: # ratio == 1 return self.__formats['result_green'] - def get_format_color_bool(self, passed: bool): + def get_format_color_bool(self, status: TestStatus): """ - Get the corresponding color format depending on 'passed'. - Green if passed is True, Red otherwise + Get the corresponding color format depending on 'status'. + Green if status is PASSED, Red if FAILED, Yellow if UNSUPPORTED """ - if passed: + if status == TestStatus.PASSED: # Return GREEN - return self.get_format_color(1,1) + return self.__formats['result_green'] + elif status == TestStatus.FAILED: + # Return RED + return self.__formats['result_red'] else: - # Return FALSE - return self.get_format_color(0,1) + # Return YELLOW + return self.__formats['result_yellow'] def add_static_data_test(self, worksheet: xlsxwriter.Workbook.worksheet_class, @@ -607,7 +636,7 @@ def add_product_table(self, 'Test', self.__formats['bold_w_border']) - # This column dictionary will keep the colum for the subscriber product + # This column dictionary will keep the column for the subscriber product column_dict = {} row_dict = {} # for all elements (test results), add the corresponding value to the @@ -649,12 +678,14 @@ def add_product_table(self, self.__formats['bold_w_border']) # set OK or ERROR if the test passed or not - str_result = 'OK' if element.get_passed() else 'ERROR' + str_result = 'OK' if element.get_status() == TestStatus.PASSED \ + else 'ERROR' if element.get_status() == TestStatus.FAILED \ + else 'UNSUPPORTED' worksheet.write( process_row, process_column, str_result, - self.get_format_color_bool(element.get_passed())) + self.get_format_color_bool(element.get_status())) return (current_row, current_column) def add_data_summary_worksheet(self, @@ -677,32 +708,59 @@ def add_data_summary_worksheet(self, worksheet.write( current_row, current_column + 2, 'Test Passed', self.__formats['bold_w_border']) + worksheet.write( + current_row, current_column + 3, + 'Unsupported Test', self.__formats['bold_w_border']) + worksheet.write( + current_row, current_column + 4, + 'Supported Test Passed', self.__formats['bold_w_border']) current_row += 1 # Create table with the total passed_tests/total_tests per product for product_name, value in self.__data.summary_dict.items(): + # company name worksheet.write( current_row, current_column, ProductUtils.get_company_name(product_name), self.__formats['bold_w_border']) + # product name worksheet.write( current_row, current_column + 1, product_name, self.__formats['bold_w_border']) + # test passed worksheet.write( current_row, current_column + 2, str(value.get_passed_tests()) + ' / ' + - str(value.get_total_tests()), + str(value.get_total_tests()), self.get_format_color(value.get_passed_tests(), value.get_total_tests())) + # unsupported tests + worksheet.write( + current_row, current_column + 3, + str(value.get_unsupported_tests()) + ' / ' + + str(value.get_total_tests()), + self.__formats['result_yellow'] if value.get_unsupported_tests() > 0 + else self.__formats['result_green']) + # supported tests passed + worksheet.write( + current_row, current_column + 4, + str(value.get_passed_tests()) + ' / ' + + str(value.get_total_tests() - value.get_unsupported_tests()), + self.get_format_color(value.get_passed_tests(), + value.get_total_tests() - value.get_unsupported_tests())) current_row += 1 # Add 2 rows of gap for the next table current_row += 2 worksheet.write( current_row, current_column, - 'Publisher/Subscriber', self.__formats['bold_w_border']) + 'Test Result: passed / total / unsupported', self.__formats['bold_w_border']) + current_row += 1 + worksheet.write( + current_row, current_column, + 'Publisher (row)/Subscriber (column)', self.__formats['bold_w_border']) # create a dictionary to store the row/column of the product name # for example, row_dict['Connext DDS 6.1.2'] = 30 means that the @@ -747,7 +805,8 @@ def add_data_summary_worksheet(self, worksheet.write(process_row, process_column, str(value.get_passed_tests()) + ' / ' + - str(value.get_total_tests()), + str(value.get_total_tests()) + ' / ' + + str(value.get_unsupported_tests()), self.get_format_color(value.get_passed_tests(), value.get_total_tests())) def add_static_data_summary_worksheet(self, diff --git a/interoperability_report.py b/interoperability_report.py index e846eb0b..3b645903 100644 --- a/interoperability_report.py +++ b/interoperability_report.py @@ -138,14 +138,17 @@ def run_subscriber_shape_main( index = child_sub.expect( [ 'Create topic:', # index = 0 - pexpect.TIMEOUT, # index = 1 - pexpect.EOF # index = 2 + re.compile('not supported', re.IGNORECASE), # index = 1 + pexpect.TIMEOUT, # index = 2 + pexpect.EOF # index = 3 ], timeout ) - if index == 1 or index == 2: + if index == 2 or index == 3: produced_code[produced_code_index] = ReturnCode.TOPIC_NOT_CREATED + elif index == 1: + produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE elif index == 0: # Step 3: Check if the reader is created log_message(f'Subscriber {subscriber_index}: Waiting for DataReader ' @@ -153,18 +156,21 @@ def run_subscriber_shape_main( index = child_sub.expect( [ 'Create reader for topic:', # index = 0 - pexpect.TIMEOUT, # index = 1 - 'failed to create content filtered topic', # index = 2 - pexpect.EOF # index = 3 + 'failed to create content filtered topic', # index = 1 + re.compile('not supported', re.IGNORECASE), # index = 2 + pexpect.TIMEOUT, # index = 3 + pexpect.EOF # index = 4 ], timeout ) - if index == 1 or index == 3: + if index == 3 or index == 4: produced_code[produced_code_index] = ReturnCode.READER_NOT_CREATED - elif index == 2: + elif index == 1: produced_code[produced_code_index] = ReturnCode.FILTER_NOT_CREATED + elif index == 2: + produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE elif index == 0: # Step 4: Read data or incompatible qos or deadline missed log_message(f'Subscriber {subscriber_index}: Waiting for data', verbosity) @@ -173,8 +179,9 @@ def run_subscriber_shape_main( r'\[[0-9]+\]', # index = 0 'on_requested_incompatible_qos()', # index = 1 'on_requested_deadline_missed()', # index = 2 - pexpect.TIMEOUT, # index = 3 - pexpect.EOF # index = 4 + re.compile('not supported', re.IGNORECASE), # index = 3 + pexpect.TIMEOUT, # index = 4 + pexpect.EOF # index = 5 ], timeout @@ -184,8 +191,10 @@ def run_subscriber_shape_main( produced_code[produced_code_index] = ReturnCode.INCOMPATIBLE_QOS elif index == 2: produced_code[produced_code_index] = ReturnCode.DEADLINE_MISSED - elif index == 3 or index == 4: + elif index == 4 or index == 5: produced_code[produced_code_index] = ReturnCode.DATA_NOT_RECEIVED + elif index == 3: + produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE elif index == 0: # Step 5: Receiving samples log_message(f'Subscriber {subscriber_index}: Receiving samples', @@ -281,14 +290,17 @@ def run_publisher_shape_main( index = child_pub.expect( [ 'Create topic:', # index == 0 - pexpect.TIMEOUT, # index == 1 - pexpect.EOF # index == 2 + re.compile('not supported', re.IGNORECASE), # index = 1 + pexpect.TIMEOUT, # index == 2 + pexpect.EOF # index == 3 ], timeout ) - if index == 1 or index == 2: + if index == 2 or index == 3: produced_code[produced_code_index] = ReturnCode.TOPIC_NOT_CREATED + elif index == 1: + produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE elif index == 0: # Step 3: Check if the writer is created log_message(f'Publisher {publisher_index}: Waiting for DataWriter ' @@ -296,13 +308,16 @@ def run_publisher_shape_main( index = child_pub.expect( [ 'Create writer for topic', # index = 0 - pexpect.TIMEOUT, # index = 1 - pexpect.EOF # index == 2 + re.compile('not supported', re.IGNORECASE), # index = 1 + pexpect.TIMEOUT, # index = 2 + pexpect.EOF # index == 3 ], timeout ) - if index == 1 or index == 2: + if index == 2 or index == 3: produced_code[produced_code_index] = ReturnCode.WRITER_NOT_CREATED + elif index == 1: + produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE elif index == 0: # Step 4: Check if the writer matches the reader log_message(f'Publisher {publisher_index}: Waiting for matching ' @@ -310,16 +325,19 @@ def run_publisher_shape_main( index = child_pub.expect( [ 'on_publication_matched()', # index = 0 - pexpect.TIMEOUT, # index = 1 - 'on_offered_incompatible_qos', # index = 2 - pexpect.EOF # index == 3 + 'on_offered_incompatible_qos', # index = 1 + re.compile('not supported', re.IGNORECASE), # index = 2 + pexpect.TIMEOUT, # index = 3 + pexpect.EOF # index == 4 ], timeout ) - if index == 1 or index == 3: + if index == 3 or index == 4: produced_code[produced_code_index] = ReturnCode.READER_NOT_MATCHED - elif index == 2: + elif index == 1: produced_code[produced_code_index] = ReturnCode.INCOMPATIBLE_QOS + elif index == 2: + produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE elif index == 0: # In the case that the option -w is selected, the Publisher # saves the samples sent in order, so the Subscriber can check @@ -332,14 +350,17 @@ def run_publisher_shape_main( index = child_pub.expect([ r'\[[0-9]+\]', # index = 0 'on_offered_deadline_missed()', # index = 1 - pexpect.TIMEOUT, # index = 2 - pexpect.EOF # index == 3 + re.compile('not supported', re.IGNORECASE), # index = 2 + pexpect.TIMEOUT, # index = 3 + pexpect.EOF # index == 4 ], timeout) if index == 1: produced_code[produced_code_index] = ReturnCode.DEADLINE_MISSED - elif index == 2 or index == 3: + elif index == 3 or index == 4: produced_code[produced_code_index] = ReturnCode.DATA_NOT_SENT + elif index == 2: + produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE elif index == 0: produced_code[produced_code_index] = ReturnCode.OK log_message(f'Publisher {publisher_index}: Sending ' @@ -355,13 +376,17 @@ def run_publisher_shape_main( index = child_pub.expect([ r'\[[0-9]+\]', # index = 0 'on_offered_deadline_missed()', # index = 1 - pexpect.TIMEOUT # index = 2 + re.compile('not supported', re.IGNORECASE), # index = 2 + pexpect.TIMEOUT # index = 3 ], timeout) if index == 1: produced_code[produced_code_index] = ReturnCode.DEADLINE_MISSED break elif index == 2: + produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE + break + elif index == 3: produced_code[produced_code_index] = ReturnCode.DATA_NOT_SENT break last_sample_saved.put(last_sample) diff --git a/rtps_test_utilities.py b/rtps_test_utilities.py index 7e9068ea..66a77f25 100644 --- a/rtps_test_utilities.py +++ b/rtps_test_utilities.py @@ -28,6 +28,7 @@ class ReturnCode(Enum): DEADLINE_MISSED : Publisher/Subscriber missed the deadline period ORDERED_ACCESS_INSTANCE : Subscriber reading with ordered access and access scope INSTANCE ORDERED_ACCESS_TOPIC : Subscriber reading with ordered access and access scope TOPIC + UNSUPPORTED_FEATURE : The test requires a feature not supported by the implementation """ OK = 0 TOPIC_NOT_CREATED = 1 @@ -44,6 +45,7 @@ class ReturnCode(Enum): DEADLINE_MISSED = 14 ORDERED_ACCESS_INSTANCE = 15 ORDERED_ACCESS_TOPIC = 16 + UNSUPPORTED_FEATURE = 17 def log_message(message, verbosity): if verbosity: From 5128c095a6093d0cf6a87b5fcafb8bf4e8e8f64b Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Mon, 15 Dec 2025 13:58:57 +0100 Subject: [PATCH 19/44] Added a way of identifying if the pub or sub is the one that does not support a feature --- generate_xlsx_report.py | 66 +++++++++++++++++++++++++++++--------- interoperability_report.py | 16 ++++----- rtps_test_utilities.py | 6 ++-- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/generate_xlsx_report.py b/generate_xlsx_report.py index 3eaaa389..040b3ac9 100644 --- a/generate_xlsx_report.py +++ b/generate_xlsx_report.py @@ -22,9 +22,19 @@ from enum import Enum class TestStatus(Enum): + """ + Enumeration of the test status. + PASSED: The test has passed + FAILED: The test has failed + PUB_UNSUPPORTED: The test is unsupported for the Publisher + SUB_UNSUPPORTED: The test is unsupported for the Subscriber + PUB_SUB_UNSUPPORTED: The test is unsupported for both Publisher and Subscriber + """ PASSED = 1 FAILED = 2 - UNSUPPORTED = 3 + PUB_UNSUPPORTED = 3 + SUB_UNSUPPORTED = 4 + PUB_SUB_UNSUPPORTED = 5 class XlxsReportArgumentParser: """Class that parse the arguments of the application.""" @@ -236,15 +246,34 @@ def get_info(self, input: pathlib.Path = None): # subscriber unsupported_tests_count = 0 for case in list(iter(suite)): - this_test_unsupported = False + is_pub_unsupported = False + is_sub_unsupported = False + status = None test_name = re.search(r'((?:Test_)[\S]+_\d+)', case.name).group(1) # count number of unsupported tests for the summary # result array is not empty and the message contains 'UNSUPPORTED_FEATURE' - if case.result and len(case.result) > 0 \ - and 'UNSUPPORTED_FEATURE' in case.result[0].message.upper(): + if case.result and len(case.result) > 0: + if 'PUB_UNSUPPORTED_FEATURE' in case.result[0].message.upper(): + is_pub_unsupported = True + if 'SUB_UNSUPPORTED_FEATURE' in case.result[0].message.upper(): + is_sub_unsupported = True + + if is_pub_unsupported or is_sub_unsupported: unsupported_tests_count += 1 - this_test_unsupported = True + + # Get test status + if case.is_passed: + status = TestStatus.PASSED + elif is_pub_unsupported and is_sub_unsupported: + status = TestStatus.PUB_SUB_UNSUPPORTED + elif is_pub_unsupported: + status = TestStatus.PUB_UNSUPPORTED + elif is_sub_unsupported: + status = TestStatus.SUB_UNSUPPORTED + else: + status = TestStatus.FAILED + # update the value of the publisher_name as publisher with # all products as subscribers. @@ -252,9 +281,7 @@ def get_info(self, input: pathlib.Path = None): publisher_test_result = JunitTestCaseAggregatedData( product=subscriber_name, test_name=test_name, - status=TestStatus.PASSED if case.is_passed - else TestStatus.FAILED if not this_test_unsupported - else TestStatus.UNSUPPORTED + status=status ) # add the resulting tuple to the publisher dictionary, the key @@ -272,9 +299,7 @@ def get_info(self, input: pathlib.Path = None): subscriber_test_result = JunitTestCaseAggregatedData( product=publisher_name, test_name=test_name, - status=TestStatus.PASSED if case.is_passed - else TestStatus.FAILED if not this_test_unsupported - else TestStatus.UNSUPPORTED + status=status ) # add the resulting tuple to the subscriber dictionary, the key @@ -677,10 +702,21 @@ def add_product_table(self, element.get_test_name(), self.__formats['bold_w_border']) - # set OK or ERROR if the test passed or not - str_result = 'OK' if element.get_status() == TestStatus.PASSED \ - else 'ERROR' if element.get_status() == TestStatus.FAILED \ - else 'UNSUPPORTED' + # get status string of the test result + if element.get_status() == TestStatus.PASSED: + str_result = 'OK' + elif element.get_status() == TestStatus.FAILED: + str_result = 'ERROR' + elif element.get_status() == TestStatus.PUB_UNSUPPORTED: + str_result = 'PUB UNSUPPORTED' + elif element.get_status() == TestStatus.SUB_UNSUPPORTED: + str_result = 'SUB UNSUPPORTED' + elif element.get_status() == TestStatus.PUB_SUB_UNSUPPORTED: + str_result = 'PUB/SUB UNSUPPORTED' + else: + str_result = 'UNKNOWN' + + # write status string to the test result worksheet.write( process_row, process_column, diff --git a/interoperability_report.py b/interoperability_report.py index 3b645903..772a7b94 100644 --- a/interoperability_report.py +++ b/interoperability_report.py @@ -148,7 +148,7 @@ def run_subscriber_shape_main( if index == 2 or index == 3: produced_code[produced_code_index] = ReturnCode.TOPIC_NOT_CREATED elif index == 1: - produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE + produced_code[produced_code_index] = ReturnCode.SUB_UNSUPPORTED_FEATURE elif index == 0: # Step 3: Check if the reader is created log_message(f'Subscriber {subscriber_index}: Waiting for DataReader ' @@ -170,7 +170,7 @@ def run_subscriber_shape_main( elif index == 1: produced_code[produced_code_index] = ReturnCode.FILTER_NOT_CREATED elif index == 2: - produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE + produced_code[produced_code_index] = ReturnCode.SUB_UNSUPPORTED_FEATURE elif index == 0: # Step 4: Read data or incompatible qos or deadline missed log_message(f'Subscriber {subscriber_index}: Waiting for data', verbosity) @@ -194,7 +194,7 @@ def run_subscriber_shape_main( elif index == 4 or index == 5: produced_code[produced_code_index] = ReturnCode.DATA_NOT_RECEIVED elif index == 3: - produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE + produced_code[produced_code_index] = ReturnCode.SUB_UNSUPPORTED_FEATURE elif index == 0: # Step 5: Receiving samples log_message(f'Subscriber {subscriber_index}: Receiving samples', @@ -300,7 +300,7 @@ def run_publisher_shape_main( if index == 2 or index == 3: produced_code[produced_code_index] = ReturnCode.TOPIC_NOT_CREATED elif index == 1: - produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE + produced_code[produced_code_index] = ReturnCode.PUB_UNSUPPORTED_FEATURE elif index == 0: # Step 3: Check if the writer is created log_message(f'Publisher {publisher_index}: Waiting for DataWriter ' @@ -317,7 +317,7 @@ def run_publisher_shape_main( if index == 2 or index == 3: produced_code[produced_code_index] = ReturnCode.WRITER_NOT_CREATED elif index == 1: - produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE + produced_code[produced_code_index] = ReturnCode.PUB_UNSUPPORTED_FEATURE elif index == 0: # Step 4: Check if the writer matches the reader log_message(f'Publisher {publisher_index}: Waiting for matching ' @@ -337,7 +337,7 @@ def run_publisher_shape_main( elif index == 1: produced_code[produced_code_index] = ReturnCode.INCOMPATIBLE_QOS elif index == 2: - produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE + produced_code[produced_code_index] = ReturnCode.PUB_UNSUPPORTED_FEATURE elif index == 0: # In the case that the option -w is selected, the Publisher # saves the samples sent in order, so the Subscriber can check @@ -360,7 +360,7 @@ def run_publisher_shape_main( elif index == 3 or index == 4: produced_code[produced_code_index] = ReturnCode.DATA_NOT_SENT elif index == 2: - produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE + produced_code[produced_code_index] = ReturnCode.PUB_UNSUPPORTED_FEATURE elif index == 0: produced_code[produced_code_index] = ReturnCode.OK log_message(f'Publisher {publisher_index}: Sending ' @@ -384,7 +384,7 @@ def run_publisher_shape_main( produced_code[produced_code_index] = ReturnCode.DEADLINE_MISSED break elif index == 2: - produced_code[produced_code_index] = ReturnCode.UNSUPPORTED_FEATURE + produced_code[produced_code_index] = ReturnCode.PUB_UNSUPPORTED_FEATURE break elif index == 3: produced_code[produced_code_index] = ReturnCode.DATA_NOT_SENT diff --git a/rtps_test_utilities.py b/rtps_test_utilities.py index 66a77f25..0c2321cc 100644 --- a/rtps_test_utilities.py +++ b/rtps_test_utilities.py @@ -28,7 +28,8 @@ class ReturnCode(Enum): DEADLINE_MISSED : Publisher/Subscriber missed the deadline period ORDERED_ACCESS_INSTANCE : Subscriber reading with ordered access and access scope INSTANCE ORDERED_ACCESS_TOPIC : Subscriber reading with ordered access and access scope TOPIC - UNSUPPORTED_FEATURE : The test requires a feature not supported by the implementation + PUB_UNSUPPORTED_FEATURE : The test requires a feature not supported by the publisher implementation + SUB_UNSUPPORTED_FEATURE : The test requires a feature not supported by the subscriber implementation """ OK = 0 TOPIC_NOT_CREATED = 1 @@ -45,7 +46,8 @@ class ReturnCode(Enum): DEADLINE_MISSED = 14 ORDERED_ACCESS_INSTANCE = 15 ORDERED_ACCESS_TOPIC = 16 - UNSUPPORTED_FEATURE = 17 + PUB_UNSUPPORTED_FEATURE = 17 + SUB_UNSUPPORTED_FEATURE = 18 def log_message(message, verbosity): if verbosity: From f5b290bd003a2f400039a0d75ace2c097d6c9e50 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Tue, 16 Dec 2025 14:09:42 +0100 Subject: [PATCH 20/44] Fixed issue when there are 0 tests to get the format color --- generate_xlsx_report.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/generate_xlsx_report.py b/generate_xlsx_report.py index 040b3ac9..b01e4bc0 100644 --- a/generate_xlsx_report.py +++ b/generate_xlsx_report.py @@ -476,7 +476,13 @@ def get_format_color(self, index: int, num_elements: int): Return the corresponding color format depending on the ratio of passed_tests/total_tests """ + # this might only happen for supported tests when the total supported + # scenarios is 0 + if num_elements == 0: + return self.__formats['result_red'] + ratio = index / num_elements + if ratio < 0.25: return self.__formats['result_red'] elif ratio < 0.5: @@ -488,7 +494,7 @@ def get_format_color(self, index: int, num_elements: int): else: # ratio == 1 return self.__formats['result_green'] - def get_format_color_bool(self, status: TestStatus): + def get_format_color_test_status(self, status: TestStatus): """ Get the corresponding color format depending on 'status'. Green if status is PASSED, Red if FAILED, Yellow if UNSUPPORTED @@ -721,7 +727,7 @@ def add_product_table(self, process_row, process_column, str_result, - self.get_format_color_bool(element.get_status())) + self.get_format_color_test_status(element.get_status())) return (current_row, current_column) def add_data_summary_worksheet(self, From d7ec0225a9a3b88a73b3a87be241771b972f0538 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Tue, 16 Dec 2025 14:10:18 +0100 Subject: [PATCH 21/44] Added multicast and use the default interface in micro --- srcCxx/shape_configurator_rti_connext_micro.h | 28 ++++--------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index 99d14ff2..deea7af4 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -113,26 +113,6 @@ static void config_micro() return; } - /* For additional allowed interface(s), increase maximum and length, and - set interface below: - */ - if (!udp_property->allow_interface.maximum(1)) - { - printf("ERROR: unable to set allow_interface maximum\n"); - return; - } - if (!udp_property->allow_interface.length(1)) - { - printf("ERROR: unable to set allow_interface length\n"); - return; - } - -#if defined(RTI_LINUX) - udp_property->allow_interface[0] = DDS_String_dup("lo"); -#elif defined(RTI_DARWIN) - udp_property->allow_interface[0] = DDS_String_dup("lo0"); -#endif - if (!registry->register_component( NETIO_DEFAULT_UDP_NAME, UDPInterfaceFactory::get_interface(), @@ -171,15 +151,17 @@ static bool configure_dp_qos(DDS::DomainParticipantQos &dp_qos) return false; } - dp_qos.discovery.initial_peers.maximum(1); - dp_qos.discovery.initial_peers.length(1); + dp_qos.discovery.initial_peers.maximum(2); + dp_qos.discovery.initial_peers.length(2); dp_qos.discovery.initial_peers[0] = DDS_String_dup("127.0.0.1"); + dp_qos.discovery.initial_peers[1] = DDS_String_dup("_udp://239.255.0.1"); + /* if there are more remote or local endpoints, you need to increase these limits */ dp_qos.resource_limits.max_destination_ports = 32; dp_qos.resource_limits.max_receive_ports = 32; dp_qos.resource_limits.local_topic_allocation = 8; dp_qos.resource_limits.local_type_allocation = 8; - //TODO we need to increase this + dp_qos.resource_limits.local_reader_allocation = 8; dp_qos.resource_limits.local_writer_allocation = 8; dp_qos.resource_limits.remote_participant_allocation = 16; From 8ea07b21146db8d766f272dc70ecb535ee187078 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 17 Dec 2025 10:31:46 +0100 Subject: [PATCH 22/44] Fixing debugging messages --- srcCxx/shape_main.cxx | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index f31b63f3..544b70df 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -905,7 +905,9 @@ class ShapeOptions { "\n TimeBasedFilterInterval = " + std::to_string(timebasedfilter_interval_us / 1000) + "ms" + "\n DeadlineInterval = " + std::to_string(deadline_interval_us / 1000) + "ms" + "\n Shapesize = " + std::to_string(shapesize) + - "\n Reading method = " + (use_read ? "read_next_instance" : "take_next_instance") + + "\n Reading method = " + (use_read + ? (take_read_next_instance ? "read_next_instance" : "read") + : (take_read_next_instance ? "take_next_instance" : "take")) + "\n Write period = " + std::to_string(write_period_us / 1000) + "ms" + "\n Read period = " + std::to_string(read_period_us / 1000) + "ms" + "\n Lifespan = " + std::to_string(lifespan_us / 1000) + "ms" + @@ -1166,7 +1168,7 @@ class ShapeApplication { logger.log_message("Topics created:", Verbosity::DEBUG); for (unsigned int i = 0; i < options->num_topics; ++i) { if (logger.verbosity() == Verbosity::DEBUG) { - printf(" topic[%d]=%p\n",i,(void*)topics[i]); + printf(" topic(%d)=%p\n",i,(void*)topics[i]); } } @@ -1330,9 +1332,9 @@ class ShapeApplication { dw_qos.deadline FIELD_ACCESSOR.period.SECONDS_FIELD_NAME = options->deadline_interval_us / 1000000; dw_qos.deadline FIELD_ACCESSOR.period.nanosec = (options->deadline_interval_us % 1000000) * 1000; } - logger.log_message(" DeadlinePeriod = " + std::to_string(dw_qos.deadline FIELD_ACCESSOR.period.SECONDS_FIELD_NAME) + "secs", + logger.log_message(" DeadlinePeriod = " + std::to_string(dw_qos.deadline FIELD_ACCESSOR.period.SECONDS_FIELD_NAME) + " secs", Verbosity::DEBUG); - logger.log_message(" " + std::to_string(dw_qos.deadline FIELD_ACCESSOR.period.nanosec) + "nanosecs", + logger.log_message(" " + std::to_string(dw_qos.deadline FIELD_ACCESSOR.period.nanosec) + " nanosecs", Verbosity::DEBUG); // options->history_depth < 0 means leave default value @@ -1405,7 +1407,7 @@ class ShapeApplication { logger.log_message("DataWriters created:", Verbosity::DEBUG); for (unsigned int i = 0; i < options->num_topics; ++i) { if (logger.verbosity() == Verbosity::DEBUG) { - printf(" dws[%d]=%p\n",i,(void*)dws[i]); + printf(" dws(%d)=%p\n",i,(void*)dws[i]); } } @@ -1664,7 +1666,7 @@ class ShapeApplication { logger.log_message("DataReaders created:", Verbosity::DEBUG); for (unsigned int i = 0; i < options->num_topics; ++i) { if (logger.verbosity() == Verbosity::DEBUG) { - printf(" drs[%d]=%p\n",i,(void*)drs[i]); + printf(" drs(%d)=%p\n",i,(void*)drs[i]); } } @@ -1732,6 +1734,7 @@ class ShapeApplication { DataSeq samples; #endif +#if defined(RTI_CONNEXT_DDS) || defined(TWINOAKS_COREDX) || defined(INTERCOM_DDS) if (options->coherent_set_enabled) { printf("Reading coherent sets, iteration %d\n",n); } @@ -1739,10 +1742,9 @@ class ShapeApplication { printf("Reading with ordered access, iteration %d\n",n); } if (options->coherent_set_enabled || options->ordered_access_enabled) { -#if !defined(RTI_CONNEXT_MICRO) sub->begin_access(); -#endif } +#endif for (unsigned int i = 0; i < options->num_topics; ++i) { previous_handles[i] = HANDLE_NIL; do { @@ -1836,8 +1838,7 @@ class ShapeApplication { #if defined(EPROSIMA_FAST_DDS) instance_handle_color[sample_info->instance_handle] = sample->color FIELD_ACCESSOR STRING_IN; #elif defined(RTI_CONNEXT_MICRO) - instance_handle_color[sample_info->instance_handle] = - std::string(sample->color FIELD_ACCESSOR STRING_IN); + instance_handle_color[sample_info->instance_handle] = std::string(sample->color); #endif } else { ShapeType shape_key; @@ -1873,11 +1874,11 @@ class ShapeApplication { } while (retval == RETCODE_OK); } +#if defined(RTI_CONNEXT_DDS) || defined(TWINOAKS_COREDX) || defined(INTERCOM_DDS) if (options->coherent_set_enabled || options->ordered_access_enabled) { -#if !defined(RTI_CONNEXT_MICRO) sub->end_access(); -#endif } +#endif // increasing number of iterations n++; From 0b666e02224c1a26dd6ec18e0626c797d0297a46 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 17 Dec 2025 10:33:16 +0100 Subject: [PATCH 23/44] Fixed the way in which process are stopped, now it shows the full log --- interoperability_report.py | 9 ++++++--- test_suite.py | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/interoperability_report.py b/interoperability_report.py index 772a7b94..5d6c25ca 100644 --- a/interoperability_report.py +++ b/interoperability_report.py @@ -51,16 +51,19 @@ def stop_process(child_process, timeout=30, poll_interval=0.2): else: return True # Process already exited - start_time = time.time() + return_value = True + start_time = time.time() while child_process.isalive() and (time.time() - start_time < timeout): time.sleep(poll_interval) if child_process.isalive(): child_process.terminate(force=True) - return False # Process was forcefully terminated + return_value = False # Process was forcefully terminated + + child_process.expect(pexpect.EOF, timeout=5) - return True + return return_value def run_subscriber_shape_main( name_executable: str, diff --git a/test_suite.py b/test_suite.py index ee0198f6..56740467 100644 --- a/test_suite.py +++ b/test_suite.py @@ -122,7 +122,7 @@ # RELIABILITY 'Test_Reliability_0' : { - 'apps' : ['-P -t Square -b -z 0', '-S -t Square -b -z 0'], + 'apps' : ['-P -t Square -b -z 0', '-S -t Square -b'], 'expected_codes' : [ReturnCode.OK, ReturnCode.OK], 'check_function' : tsf.test_reliability_order, 'title' : 'Communication between BEST_EFFORT publisher and subscriber', From f31cd8f25be66466d82cf5bf93b78eff6857a4a4 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 17 Dec 2025 11:16:34 +0100 Subject: [PATCH 24/44] Added a basic check for received samples --- interoperability_report.py | 4 ++-- rtps_test_utilities.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/interoperability_report.py b/interoperability_report.py index 5d6c25ca..9c1bfedb 100644 --- a/interoperability_report.py +++ b/interoperability_report.py @@ -24,7 +24,7 @@ if __name__ == "__main__" and platform.system() == "Darwin": multiprocessing.set_start_method('fork') -from rtps_test_utilities import ReturnCode, log_message, no_check, remove_ansi_colors +from rtps_test_utilities import ReturnCode, log_message, basic_check, remove_ansi_colors # This parameter is used to save the samples the Publisher sends. # MAX_SAMPLES_SAVED is the maximum number of samples saved. @@ -846,7 +846,7 @@ def main(): raise RuntimeError('Cannot process function of ' f'test case: {test_case_name}') else: - check_function = no_check + check_function = basic_check assert(len(parameters) == len(expected_codes)) diff --git a/rtps_test_utilities.py b/rtps_test_utilities.py index 0c2321cc..c77bf9dd 100644 --- a/rtps_test_utilities.py +++ b/rtps_test_utilities.py @@ -60,3 +60,15 @@ def remove_ansi_colors(text): def no_check(child_sub, samples_sent, last_sample_saved, timeout): return ReturnCode.OK + +def basic_check(child_sub, samples_sent, last_sample_saved, timeout): + sub_string = re.search('[0-9]+ [0-9]+ \[([0-9]+)\]', + child_sub.before + child_sub.after) + + # check the sample contains some info, just checking the size is different + # than zero is enough + if sub_string is not None: + if int(sub_string.group(1)) != 0: + return ReturnCode.OK + + return ReturnCode.DATA_NOT_CORRECT From d125be33fdf3f2e90354fdc730bea7bdf392a223 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 19 Dec 2025 17:23:18 +0100 Subject: [PATCH 25/44] Fixed micro makefiles --- srcCxx/makefile_rti_connext_micro_linux | 13 +++++++------ srcCxx/makefile_rti_connext_micro_macos | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/srcCxx/makefile_rti_connext_micro_linux b/srcCxx/makefile_rti_connext_micro_linux index ef58ef04..4216290b 100644 --- a/srcCxx/makefile_rti_connext_micro_linux +++ b/srcCxx/makefile_rti_connext_micro_linux @@ -1,8 +1,8 @@ ###################################################################### # To compile, type: -# make -f makefile_rti_connext_dds_linux +# make -f makefile_rti_connext_micro_linux # To compile with the Debug option, use: -# make -f makefile_rti_connext_dds_linux DEBUG=1 +# make -f makefile_rti_connext_micro_linux DEBUG=1 # # This makefile assumes that your build environment is already correctly # configured. (For example, the correct version of your compiler and @@ -21,9 +21,10 @@ endif COMPILER_FLAGS = -m64 LINKER_FLAGS = -m64 -static-libgcc -split_path_name = $(subst /rti_, , $(RTIMEHOME)) +product_name = $(notdir $(RTIMEHOME)) +product_name := $(subst _dds,,$(product_name)) -version_name = $(lastword $(split_path_name)) +version_name = $(lastword $(product_name)) common_name = "_shape_main_linux" executable_name = $(version_name)$(common_name) @@ -44,7 +45,7 @@ COMPILER_FLAGS += -g -O0 LINKER_FLAGS += -g LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ -lrti_me_cppzd -lrti_me_netiosdmzd \ - -lrti_me_discdpdez -lrti_me_ddsfilterzd -lrti_me_rhsmzd \ + -lrti_me_discdpdezd -lrti_me_ddsfilterzd -lrti_me_rhsmzd \ -lrti_me_whsmzd -lrti_mezd -lrti_me_ddsxtypeszd $(SYSLIBS) else # This option strips the executable symbols @@ -73,7 +74,7 @@ $(OBJDIR)/$(EXEC) : $(AUTOGENSOURCES) $(AUTOGENOBJS) $(OBJDIR)/shape_main.o $(OBJDIR)/%.o : %.cxx $(COMPILER) $(COMPILER_FLAGS) -o $@ $(DEFINES) $(INCLUDES) -c $< -shape_main.cxx : shape_configurator_rti_connext_dds.h +shape_main.cxx : shape_configurator_rti_connext_micro.h # Generate type-specific sources $(AUTOGENSOURCES) : $(CDRSOURCES) diff --git a/srcCxx/makefile_rti_connext_micro_macos b/srcCxx/makefile_rti_connext_micro_macos index 077ac27f..80b70279 100644 --- a/srcCxx/makefile_rti_connext_micro_macos +++ b/srcCxx/makefile_rti_connext_micro_macos @@ -1,8 +1,8 @@ ###################################################################### # To compile, type: -# make -f makefile_rti_connext_dds_linux +# make -f makefile_rti_connext_micro_linux # To compile with the Debug option, use: -# make -f makefile_rti_connext_dds_linux DEBUG=1 +# make -f makefile_rti_connext_micro_linux DEBUG=1 # # This makefile assumes that your build environment is already correctly # configured. (For example, the correct version of your compiler and @@ -21,9 +21,10 @@ endif COMPILER_FLAGS = -std=c++11 LINKER_FLAGS = -split_path_name = $(subst /rti_, , $(RTIMEHOME)) +product_name = $(notdir $(RTIMEHOME)) +product_name := $(subst _dds,,$(product_name)) -version_name = $(lastword $(split_path_name)) +version_name = $(lastword $(product_name)) common_name = "_shape_main_macos" executable_name = $(version_name)$(common_name) @@ -44,7 +45,7 @@ COMPILER_FLAGS += -g -O0 LINKER_FLAGS += -g LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ -lrti_me_cppzd -lrti_me_netiosdmzd \ - -lrti_me_discdpdez -lrti_me_ddsfilterzd -lrti_me_rhsmzd \ + -lrti_me_discdpdezd -lrti_me_ddsfilterzd -lrti_me_rhsmzd \ -lrti_me_whsmzd -lrti_mezd -lrti_me_ddsxtypeszd $(SYSLIBS) else # This option strips the executable symbols @@ -73,7 +74,7 @@ $(OBJDIR)/$(EXEC) : $(AUTOGENSOURCES) $(AUTOGENOBJS) $(OBJDIR)/shape_main.o $(OBJDIR)/%.o : %.cxx $(COMPILER) $(COMPILER_FLAGS) -o $@ $(DEFINES) $(INCLUDES) -c $< -shape_main.cxx : shape_configurator_rti_connext_dds.h +shape_main.cxx : shape_configurator_rti_connext_micro.h # Generate type-specific sources $(AUTOGENSOURCES) : $(CDRSOURCES) From 5ff43fd72c502ee524b7f33e253346284aba0712 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Mon, 12 Jan 2026 18:49:37 +0100 Subject: [PATCH 26/44] Fixed run_tests script and micro makefiles --- run_tests.sh | 2 +- srcCxx/makefile_rti_connext_micro_linux | 4 +++- srcCxx/makefile_rti_connext_micro_macos | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/run_tests.sh b/run_tests.sh index be90102e..e12659d6 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -81,7 +81,7 @@ for i in $publisher; do subscriber_name=$(basename "$j" _shape_main_linux) echo "Testing Publisher $publisher_name --- Subscriber $subscriber_name" extra_args="" - if [[ "${subscriber,,}" == *opendds* && "${publisher,,}" == *connext* ]]; then + if [[ "${subscriber_name,,}" == *opendds* && "${publisher_name,,}" == *connext_dds* ]]; then extra_args="--periodic-announcement 5000" fi; if [[ -n $output ]]; then diff --git a/srcCxx/makefile_rti_connext_micro_linux b/srcCxx/makefile_rti_connext_micro_linux index 4216290b..751ed924 100644 --- a/srcCxx/makefile_rti_connext_micro_linux +++ b/srcCxx/makefile_rti_connext_micro_linux @@ -21,7 +21,9 @@ endif COMPILER_FLAGS = -m64 LINKER_FLAGS = -m64 -static-libgcc -product_name = $(notdir $(RTIMEHOME)) +split_path_name = $(subst /rti_, , $(RTIMEHOME)) +# from connext_dds_micro-x.y.z remove _dds to get connext_micro-x.y.z +product_name = $(notdir $(split_path_name)) product_name := $(subst _dds,,$(product_name)) version_name = $(lastword $(product_name)) diff --git a/srcCxx/makefile_rti_connext_micro_macos b/srcCxx/makefile_rti_connext_micro_macos index 80b70279..752fe5b1 100644 --- a/srcCxx/makefile_rti_connext_micro_macos +++ b/srcCxx/makefile_rti_connext_micro_macos @@ -21,7 +21,9 @@ endif COMPILER_FLAGS = -std=c++11 LINKER_FLAGS = -product_name = $(notdir $(RTIMEHOME)) +split_path_name = $(subst /rti_, , $(RTIMEHOME)) +# from connext_dds_micro-x.y.z remove _dds to get connext_micro-x.y.z +product_name = $(notdir $(split_path_name)) product_name := $(subst _dds,,$(product_name)) version_name = $(lastword $(product_name)) From bbf8a86bc074b3b732fee9f126ae52ee058b1967 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Mon, 12 Jan 2026 18:52:37 +0100 Subject: [PATCH 27/44] Changed the unsupported tests by supported tests --- generate_xlsx_report.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/generate_xlsx_report.py b/generate_xlsx_report.py index b01e4bc0..af54edca 100644 --- a/generate_xlsx_report.py +++ b/generate_xlsx_report.py @@ -125,6 +125,9 @@ def get_total_tests(self): def get_unsupported_tests(self): return self.data[2] + def get_supported_tests(self): + return self.data[1] - self.data[2] + def __str__(self) -> str: return f'({self.data[0]}, {self.data[1]}, {self.data[2]})' @@ -749,13 +752,13 @@ def add_data_summary_worksheet(self, 'Product', self.__formats['bold_w_border']) worksheet.write( current_row, current_column + 2, - 'Test Passed', self.__formats['bold_w_border']) + 'Tests Passed', self.__formats['bold_w_border']) worksheet.write( current_row, current_column + 3, - 'Unsupported Test', self.__formats['bold_w_border']) + 'Supported Tests', self.__formats['bold_w_border']) worksheet.write( current_row, current_column + 4, - 'Supported Test Passed', self.__formats['bold_w_border']) + 'Supported Tests Passed', self.__formats['bold_w_border']) current_row += 1 @@ -778,10 +781,10 @@ def add_data_summary_worksheet(self, str(value.get_total_tests()), self.get_format_color(value.get_passed_tests(), value.get_total_tests())) - # unsupported tests + # supported tests worksheet.write( current_row, current_column + 3, - str(value.get_unsupported_tests()) + ' / ' + + str(value.get_supported_tests()) + ' / ' + str(value.get_total_tests()), self.__formats['result_yellow'] if value.get_unsupported_tests() > 0 else self.__formats['result_green']) @@ -789,16 +792,16 @@ def add_data_summary_worksheet(self, worksheet.write( current_row, current_column + 4, str(value.get_passed_tests()) + ' / ' + - str(value.get_total_tests() - value.get_unsupported_tests()), + str(value.get_supported_tests()), self.get_format_color(value.get_passed_tests(), - value.get_total_tests() - value.get_unsupported_tests())) + value.get_supported_tests())) current_row += 1 # Add 2 rows of gap for the next table current_row += 2 worksheet.write( current_row, current_column, - 'Test Result: passed / total / unsupported', self.__formats['bold_w_border']) + 'Test Result: passed / supported / total', self.__formats['bold_w_border']) current_row += 1 worksheet.write( current_row, current_column, @@ -846,10 +849,10 @@ def add_data_summary_worksheet(self, process_column = column_dict[subscriber_name] worksheet.write(process_row, process_column, - str(value.get_passed_tests()) + ' / ' + - str(value.get_total_tests()) + ' / ' + - str(value.get_unsupported_tests()), - self.get_format_color(value.get_passed_tests(), value.get_total_tests())) + str(value.get_passed_tests()) + ' / ' + + str(value.get_supported_tests()) + ' / ' + + str(value.get_total_tests()), + self.get_format_color(value.get_passed_tests(), value.get_supported_tests())) def add_static_data_summary_worksheet(self, worksheet: xlsxwriter.Workbook.worksheet_class, From 81496cf7e95d8267da8889f176398866fc77b8df Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Tue, 13 Jan 2026 14:38:46 +0100 Subject: [PATCH 28/44] Changed micro datatype to be bounded --- srcCxx/shape_micro.idl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcCxx/shape_micro.idl b/srcCxx/shape_micro.idl index bcd8c4fd..3ffde7e5 100644 --- a/srcCxx/shape_micro.idl +++ b/srcCxx/shape_micro.idl @@ -5,5 +5,5 @@ struct ShapeType { long x; long y; long shapesize; - sequence additional_payload_size; + sequence additional_payload_size; }; From 727a72312b2f90ae6c774b29216748aff94c8597 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Tue, 13 Jan 2026 15:04:38 +0100 Subject: [PATCH 29/44] Fixed resources limits for large data --- srcCxx/shape_configurator_rti_connext_micro.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index deea7af4..5a0083e0 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -113,6 +113,8 @@ static void config_micro() return; } + udp_property->max_message_size = 131072; //128KB + if (!registry->register_component( NETIO_DEFAULT_UDP_NAME, UDPInterfaceFactory::get_interface(), @@ -182,6 +184,8 @@ void config_dr_qos(DDS::DataReaderQos &dr_qos) { dr_qos.resource_limits.max_samples_per_instance = 500; dr_qos.reader_resource_limits.max_remote_writers = 16; dr_qos.reader_resource_limits.max_samples_per_remote_writer = 500; + dr_qos.reader_resource_limits.max_fragmented_samples = 64; + dr_qos.reader_resource_limits.max_fragmented_samples_per_remote_writer = 32; } uint64_t DDS_UInt8Seq_get_length(DDS_OctetSeq * seq) From 451b469a50ed172cfef88b97dbcf6926e4704a72 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 14 Jan 2026 20:47:34 +0100 Subject: [PATCH 30/44] Fixing an issue with micro instance_handle/color --- srcCxx/shape_configurator_rti_connext_dds.h | 11 ++++++++ srcCxx/shape_configurator_rti_connext_micro.h | 27 ++++++++++++++++--- srcCxx/shape_main.cxx | 16 +++-------- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/srcCxx/shape_configurator_rti_connext_dds.h b/srcCxx/shape_configurator_rti_connext_dds.h index 590cbd05..e137f5a0 100644 --- a/srcCxx/shape_configurator_rti_connext_dds.h +++ b/srcCxx/shape_configurator_rti_connext_dds.h @@ -26,3 +26,14 @@ void configure_participant_announcements_period( dp_qos.discovery_config.participant_liveliness_assert_period.nanosec = (announcement_period_us % 1000000) * 1000; } + +void configure_large_data(DDS::DataWriterQos &dw_qos) { + if (DDS::PropertyQosPolicyHelper::assert_property( + dw_qos.property, + "dds.data_writer.history.memory_manager.fast_pool.pool_buffer_max_size", + "65536", + DDS_BOOLEAN_FALSE) != DDS_RETCODE_OK) { + printf("failed to set property pool_buffer_max_size\n"); + } + dw_qos.publish_mode.kind = DDS::ASYNCHRONOUS_PUBLISH_MODE_QOS; +} diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index 5a0083e0..39f1beda 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -208,8 +208,27 @@ const unsigned char* DDS_UInt8Seq_get_reference(const DDS_OctetSeq * seq, uint64 return DDS_OctetSeq_get_reference(seq, index); } -struct InstanceHandle_t_less_op { - bool operator()(const DDS::InstanceHandle_t& a, const DDS::InstanceHandle_t& b) const { - return std::memcmp(a.octet, b.octet, 16); +void set_instance_color( + std::vector>& vec, + const DDS::InstanceHandle_t handle, + const std::string& color) { + // Check if the handle already exists + for (auto& p : vec) { + if (DDS_InstanceHandle_equals(&p.first, &handle)) { + return; + } } -}; + // If it doesn't exist, add it + vec.push_back(std::make_pair(handle, color)); +} + +std::string get_instance_color( + const std::vector>& vec, + const DDS::InstanceHandle_t handle) { + for (const auto& p : vec) { + if (DDS_InstanceHandle_equals(&p.first, &handle)) { + return p.second; + } + } + return ""; +} \ No newline at end of file diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 544b70df..1d7ba597 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -1369,16 +1369,8 @@ class ShapeApplication { #endif #if defined(RTI_CONNEXT_DDS) - // usage of large data - if (PropertyQosPolicyHelper::assert_property( - dw_qos.property, - "dds.data_writer.history.memory_manager.fast_pool.pool_buffer_max_size", - "65536", - DDS_BOOLEAN_FALSE) != DDS_RETCODE_OK) { - logger.log_message("failed to set property pool_buffer_max_size", Verbosity::ERROR); - } if (options->additional_payload_size > 64000) { - dw_qos.publish_mode.kind = ASYNCHRONOUS_PUBLISH_MODE_QOS; + configure_large_data(dw_qos); } logger.log_message(" Publish Mode kind = " + std::string(dw_qos.publish_mode.kind == ASYNCHRONOUS_PUBLISH_MODE_QOS @@ -1718,7 +1710,7 @@ class ShapeApplication { // TODO: Remove when Fast DDS supports `get_key_value()` std::map instance_handle_color; #elif defined(RTI_CONNEXT_MICRO) - std::map instance_handle_color; + std::vector> instance_handle_color; #endif while ( ! all_done ) { @@ -1838,7 +1830,7 @@ class ShapeApplication { #if defined(EPROSIMA_FAST_DDS) instance_handle_color[sample_info->instance_handle] = sample->color FIELD_ACCESSOR STRING_IN; #elif defined(RTI_CONNEXT_MICRO) - instance_handle_color[sample_info->instance_handle] = std::string(sample->color); + set_instance_color(instance_handle_color, sample_info->instance_handle, sample->color); #endif } else { ShapeType shape_key; @@ -1847,7 +1839,7 @@ class ShapeApplication { shape_key.color FIELD_ACCESSOR = instance_handle_color[sample_info->instance_handle] NAME_ACCESSOR; #elif defined(RTI_CONNEXT_MICRO) // 128 is the max length of the color string - strncpy(shape_key.color, instance_handle_color[sample_info->instance_handle].c_str(), 128); + strncpy(shape_key.color, get_instance_color(instance_handle_color, sample_info->instance_handle).c_str(), 128); #else drs[i]->get_key_value(shape_key, sample_info->instance_handle); #endif From d95223f1b8f28eac6e01a40878ee1a19e2dbc5e1 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Thu, 22 Jan 2026 20:17:00 +0100 Subject: [PATCH 31/44] Updated basic_check function --- rtps_test_utilities.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/rtps_test_utilities.py b/rtps_test_utilities.py index c77bf9dd..4b2e746b 100644 --- a/rtps_test_utilities.py +++ b/rtps_test_utilities.py @@ -62,13 +62,16 @@ def no_check(child_sub, samples_sent, last_sample_saved, timeout): return ReturnCode.OK def basic_check(child_sub, samples_sent, last_sample_saved, timeout): - sub_string = re.search('[0-9]+ [0-9]+ \[([0-9]+)\]', + """ Only checks that the data is well formed and size is not zero.""" + sub_string = re.search('\w\s+\w+\s+[0-9]+ [0-9]+ \[([0-9]+)\]', child_sub.before + child_sub.after) - # check the sample contains some info, just checking the size is different - # than zero is enough - if sub_string is not None: - if int(sub_string.group(1)) != 0: - return ReturnCode.OK + if sub_string is None: + return ReturnCode.DATA_NOT_RECEIVED - return ReturnCode.DATA_NOT_CORRECT + sample_size = int(sub_string.group(1)) + + if sample_size == 0: + return ReturnCode.DATA_NOT_CORRECT + + return ReturnCode.OK From 2b5c663b23bacb744fb297fab889bf71e1dbad13 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Thu, 22 Jan 2026 20:21:08 +0100 Subject: [PATCH 32/44] Added some changes for Micro --- srcCxx/makefile_rti_connext_micro_linux | 2 +- srcCxx/makefile_rti_connext_micro_macos | 2 +- srcCxx/shape_configurator_rti_connext_micro.h | 2 +- srcCxx/shape_main.cxx | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/srcCxx/makefile_rti_connext_micro_linux b/srcCxx/makefile_rti_connext_micro_linux index 751ed924..e53ec1aa 100644 --- a/srcCxx/makefile_rti_connext_micro_linux +++ b/srcCxx/makefile_rti_connext_micro_linux @@ -58,7 +58,7 @@ LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ -lrti_me_whsmz -lrti_mez -lrti_me_ddsxtypesz $(SYSLIBS) endif -DEFINES = -DRTI_UNIX -DRTI_LINUX -DRTI_CONNEXT_MICRO -DOSAPI_CC_DEF_H=osapi/osapi_cc_gcc.h +DEFINES = -DRTI_UNIX -DRTI_LINUX -DRTI_CONNEXT_MICRO INCLUDES = -I. -I$(RTIMEHOME)/include -I$(RTIMEHOME)/include/rti_me diff --git a/srcCxx/makefile_rti_connext_micro_macos b/srcCxx/makefile_rti_connext_micro_macos index 752fe5b1..c397f418 100644 --- a/srcCxx/makefile_rti_connext_micro_macos +++ b/srcCxx/makefile_rti_connext_micro_macos @@ -58,7 +58,7 @@ LIBS = -L$(RTIMEHOME)/lib/$(RTIMEARCH) \ -lrti_me_whsmz -lrti_mez -lrti_me_ddsxtypesz $(SYSLIBS) endif -DEFINES = -DRTI_UNIX -DRTI_DARWIN -DRTI_CONNEXT_MICRO -DOSAPI_CC_DEF_H=osapi/osapi_cc_gcc.h +DEFINES = -DRTI_UNIX -DRTI_DARWIN -DRTI_CONNEXT_MICRO INCLUDES = -I. -I$(RTIMEHOME)/include -I$(RTIMEHOME)/include/rti_me diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index 39f1beda..93a04f7d 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -113,7 +113,7 @@ static void config_micro() return; } - udp_property->max_message_size = 131072; //128KB + udp_property->max_message_size = 64 * 1024; //64KB if (!registry->register_component( NETIO_DEFAULT_UDP_NAME, diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 1d7ba597..b3344f58 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -19,6 +19,8 @@ #include #include +#include + #if defined(RTI_CONNEXT_DDS) #include "shape_configurator_rti_connext_dds.h" #elif defined(RTI_CONNEXT_MICRO) From 5b45bc0b9118920db1f1127d7145e4f99db3d5f0 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 23 Jan 2026 19:10:40 +0100 Subject: [PATCH 33/44] Removed duplicated error check --- srcCxx/shape_main.cxx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index b3344f58..8c0a002e 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -1762,10 +1762,6 @@ class ShapeApplication { ANY_SAMPLE_STATE, ANY_VIEW_STATE, ANY_INSTANCE_STATE ); - if (retval == DDS_RETCODE_OK) { - logger.log_message("Taken " + std::to_string(samples.length()) - + " sample(s)", Verbosity::DEBUG); - } } } else { /* Use read_next_instance*/ if (options->take_read_next_instance) { From 1b8ec2cf20fba097c8399c970017fa59126ebcdc Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Mon, 2 Feb 2026 21:06:50 +0100 Subject: [PATCH 34/44] Added a way of configuring the datafrag size --- srcCxx/shape_configurator_rti_connext_dds.h | 17 ++++++++ srcCxx/shape_configurator_rti_connext_micro.h | 29 +++++++++++++ srcCxx/shape_main.cxx | 43 ++++++++++++++++++- 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/srcCxx/shape_configurator_rti_connext_dds.h b/srcCxx/shape_configurator_rti_connext_dds.h index e137f5a0..c9990f08 100644 --- a/srcCxx/shape_configurator_rti_connext_dds.h +++ b/srcCxx/shape_configurator_rti_connext_dds.h @@ -1,3 +1,5 @@ +#include + #include "shape.h" #include "shapeSupport.h" #include "ndds/ndds_namespace_cpp.h" @@ -15,12 +17,27 @@ const char *get_qos_policy_name(DDS_QosPolicyId_t policy_id) return DDS_QosPolicyId_to_string(policy_id); // not standard... } +void configure_datafrag_size( + DDS::DomainParticipantQos &dp_qos, + size_t datafrag_size) { + if (datafrag_size == 0) { + return; + } else { + DDS_PropertyQosPolicyHelper_add_property( + &dp_qos.property, + "dds.transport.UDPv4.builtin.parent.message_size_max", + std::to_string(datafrag_size).c_str(), + DDS_BOOLEAN_FALSE); + } +} + void configure_participant_announcements_period( DDS::DomainParticipantQos &dp_qos, useconds_t announcement_period_us) { if (announcement_period_us == 0) { return; } + dp_qos.discovery_config.participant_liveliness_assert_period.sec = announcement_period_us / 1000000; dp_qos.discovery_config.participant_liveliness_assert_period.nanosec = diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index 93a04f7d..4229cf04 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -145,6 +145,35 @@ static void config_micro() } } +static void configure_datafrag_size(unsigned int datafrag_size) { + + RT::Registry *registry = NULL; + + registry = DDSTheParticipantFactory->get_registry(); + + if (!registry->unregister(NETIO_DEFAULT_UDP_NAME, NULL, NULL)) { + printf("ERROR: unable to unregister udp\n"); + return; + } + + UDP_InterfaceFactoryProperty *udp_property = new UDP_InterfaceFactoryProperty(); + if (udp_property == NULL) { + printf("ERROR: unable to allocate udp properties\n"); + return; + } + + udp_property->max_message_size = datafrag_size; + + if (!registry->register_component( + NETIO_DEFAULT_UDP_NAME, + UDPInterfaceFactory::get_interface(), + &udp_property->_parent._parent, + NULL)) { + printf("ERROR: unable to register udp\n"); + return; + } +} + static bool configure_dp_qos(DDS::DomainParticipantQos &dp_qos) { if (!dp_qos.discovery.discovery.name.set_name("dpde")) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 8c0a002e..0e3fee82 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -280,6 +280,8 @@ class ShapeOptions { useconds_t periodic_announcement_period_us; + unsigned int datafrag_size; + public: //------------------------------------------------------------- ShapeOptions() @@ -334,6 +336,8 @@ class ShapeOptions { take_read_next_instance = true; periodic_announcement_period_us = 0; + + datafrag_size = 0; // Default: 0 (means not set) } //------------------------------------------------------------- @@ -407,6 +411,8 @@ class ShapeOptions { printf(" read_next_instance()\n"); printf(" --periodic-announcement : indicates the periodic participant\n"); printf(" announcement period in ms. Default 0 (off)\n"); + printf(" --datafrag-size : set the data fragment size (default: 0, means\n"); + printf(" not set)\n"); } //------------------------------------------------------------- @@ -498,6 +504,7 @@ class ShapeOptions { {"take-read", no_argument, NULL, 'K'}, {"time-filter", required_argument, NULL, 'i'}, {"periodic-announcement", required_argument, NULL, 'N'}, + {"datafrag-size", required_argument, NULL, 'F'}, {NULL, 0, NULL, 0 } }; @@ -882,6 +889,26 @@ class ShapeOptions { periodic_announcement_period_us = (useconds_t) converted_param * 1000; break; } + case 'F': { + unsigned int converted_param = 0; + if (sscanf(optarg, "%u", &converted_param) == 0) { + logger.log_message("unrecognized value for datafrag-size " + + std::string(1, optarg[0]), + Verbosity::ERROR); + parse_ok = false; + } + // the spec mentions that the fragment size must satisfy: + // fragment size <= 65536 bytes. + if (converted_param > 65536) { + logger.log_message("incorrect value for datafrag-size, " + "it must be <= 65536 bytes" + + std::to_string(converted_param), + Verbosity::ERROR); + parse_ok = false; + } + datafrag_size = converted_param; + break; + } case '?': parse_ok = false; break; @@ -924,7 +951,8 @@ class ShapeOptions { "\n Final Instance State = " + (unregister ? "Unregister" : (dispose ? "Dispose" : "not specified")) + "\n Periodic Announcement Period = " - + std::to_string(periodic_announcement_period_us / 1000) + "ms", + + std::to_string(periodic_announcement_period_us / 1000) + "ms" + + "\n Data Fragmentation Size = " + std::to_string(datafrag_size) + "ms", Verbosity::DEBUG); if (topic_name != NULL){ logger.log_message(" Topic = " + std::string(topic_name), @@ -1132,6 +1160,19 @@ class ShapeApplication { DDS::DomainParticipantQos dp_qos; dpf->get_default_participant_qos(dp_qos); + if (options->datafrag_size > 0) { +#if defined(RTI_CONNEXT_DDS) + configure_datafrag_size(dp_qos, options->datafrag_size); +#elif defined(RTI_CONNEXT_MICRO) + configure_datafrag_size(options->datafrag_size); +#else + configure_datafrag_size(); +#endif + + logger.log_message("Data Fragmentation Size = " + + std::to_string(options->datafrag_size), Verbosity::DEBUG); + } + #ifdef RTI_CONNEXT_MICRO if (!configure_dp_qos(dp_qos)) { return false; From cbc9ac33720c7322841d9785260935327267e170 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Mon, 2 Feb 2026 21:58:01 +0100 Subject: [PATCH 35/44] Fixed potential memory leak when configuring micro --- srcCxx/shape_configurator_rti_connext_dds.h | 7 +- srcCxx/shape_configurator_rti_connext_micro.h | 74 ++++++++++++------- srcCxx/shape_main.cxx | 22 +++++- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/srcCxx/shape_configurator_rti_connext_dds.h b/srcCxx/shape_configurator_rti_connext_dds.h index c9990f08..e2a905fb 100644 --- a/srcCxx/shape_configurator_rti_connext_dds.h +++ b/srcCxx/shape_configurator_rti_connext_dds.h @@ -17,18 +17,21 @@ const char *get_qos_policy_name(DDS_QosPolicyId_t policy_id) return DDS_QosPolicyId_to_string(policy_id); // not standard... } -void configure_datafrag_size( +bool configure_datafrag_size( DDS::DomainParticipantQos &dp_qos, size_t datafrag_size) { + bool ok = false; if (datafrag_size == 0) { - return; + ok = false; } else { DDS_PropertyQosPolicyHelper_add_property( &dp_qos.property, "dds.transport.UDPv4.builtin.parent.message_size_max", std::to_string(datafrag_size).c_str(), DDS_BOOLEAN_FALSE); + ok = true; } + return ok; } void configure_participant_announcements_period( diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index 4229cf04..38e2e6a3 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -7,7 +7,6 @@ #include #include -#define CONFIGURE_PARTICIPANT_FACTORY config_micro(); #define LISTENER_STATUS_MASK_ALL (DDS_STATUS_MASK_ALL) #ifndef XCDR_DATA_REPRESENTATION @@ -77,9 +76,12 @@ const char* get_qos_policy_name(DDS::QosPolicyId_t policy_id) else { return "Unknown"; } } -static void config_micro() +static bool config_micro() { + bool ok = false; RT::Registry *registry = NULL; + DPDE::DiscoveryPluginProperty *discovery_plugin_properties = NULL; + UDP_InterfaceFactoryProperty *udp_property = NULL; OSAPI_Log_set_verbosity(OSAPI_LOG_VERBOSITY_SILENT); @@ -89,43 +91,42 @@ static void config_micro() if (!registry->register_component("wh", WHSMHistoryFactory::get_interface(), NULL, NULL)) { printf("ERROR: unable to register writer history\n"); - return; + goto done; } /* Register Reader History */ if (!registry->register_component("rh", RHSMHistoryFactory::get_interface(), NULL, NULL)) { - printf("ERROR: unable to register reader history\n"); - return; + printf("ERROR: unable to register reader history\n"); + goto done; } /* Configure UDP transport's allowed interfaces */ if (!registry->unregister(NETIO_DEFAULT_UDP_NAME, NULL, NULL)) { printf("ERROR: unable to unregister udp\n"); - return; + goto done; } - UDP_InterfaceFactoryProperty *udp_property = new UDP_InterfaceFactoryProperty(); + udp_property = new UDP_InterfaceFactoryProperty(); if (udp_property == NULL) { printf("ERROR: unable to allocate udp properties\n"); - return; + goto done; } udp_property->max_message_size = 64 * 1024; //64KB if (!registry->register_component( - NETIO_DEFAULT_UDP_NAME, - UDPInterfaceFactory::get_interface(), - &udp_property->_parent._parent, - NULL)) - { + NETIO_DEFAULT_UDP_NAME, + UDPInterfaceFactory::get_interface(), + &udp_property->_parent._parent, + NULL)) { printf("ERROR: unable to register udp\n"); - return; + goto done; } - DPDE::DiscoveryPluginProperty *discovery_plugin_properties = new DPDE::DiscoveryPluginProperty(); + discovery_plugin_properties = new DPDE::DiscoveryPluginProperty(); /* Configure properties */ discovery_plugin_properties->participant_liveliness_assert_period.sec = 5; @@ -135,31 +136,44 @@ static void config_micro() if (!registry->register_component( - "dpde", - DPDEDiscoveryFactory::get_interface(), - &discovery_plugin_properties->_parent, - NULL)) - { + "dpde", + DPDEDiscoveryFactory::get_interface(), + &discovery_plugin_properties->_parent, + NULL)) { printf("ERROR: unable to register dpde\n"); - return; + goto done; + } + + ok = true; +done: + if (!ok) { + if (udp_property != NULL) { + delete udp_property; + } + if (discovery_plugin_properties != NULL) { + delete discovery_plugin_properties; + } } + return ok; } -static void configure_datafrag_size(unsigned int datafrag_size) { +static bool configure_datafrag_size(unsigned int datafrag_size) { + bool ok = false; RT::Registry *registry = NULL; + UDP_InterfaceFactoryProperty *udp_property = NULL; registry = DDSTheParticipantFactory->get_registry(); if (!registry->unregister(NETIO_DEFAULT_UDP_NAME, NULL, NULL)) { printf("ERROR: unable to unregister udp\n"); - return; + goto done; } - UDP_InterfaceFactoryProperty *udp_property = new UDP_InterfaceFactoryProperty(); + udp_property = new UDP_InterfaceFactoryProperty(); if (udp_property == NULL) { printf("ERROR: unable to allocate udp properties\n"); - return; + goto done; } udp_property->max_message_size = datafrag_size; @@ -170,8 +184,16 @@ static void configure_datafrag_size(unsigned int datafrag_size) { &udp_property->_parent._parent, NULL)) { printf("ERROR: unable to register udp\n"); - return; + goto done; + } + ok = true; +done: + if (!ok) { + if (udp_property != NULL) { + delete udp_property; + } } + return ok; } static bool configure_dp_qos(DDS::DomainParticipantQos &dp_qos) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 0e3fee82..05be284f 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -1157,20 +1157,34 @@ class ShapeApplication { CONFIGURE_PARTICIPANT_FACTORY #endif +#ifdef RTI_CONNEXT_MICRO + if (!config_micro()) { + logger.log_message("Error configuring Connext Micro", Verbosity::ERROR); + return false; + } +#endif + DDS::DomainParticipantQos dp_qos; dpf->get_default_participant_qos(dp_qos); if (options->datafrag_size > 0) { + bool result = false; #if defined(RTI_CONNEXT_DDS) - configure_datafrag_size(dp_qos, options->datafrag_size); + result = configure_datafrag_size(dp_qos, options->datafrag_size); #elif defined(RTI_CONNEXT_MICRO) - configure_datafrag_size(options->datafrag_size); + result = configure_datafrag_size(options->datafrag_size); #else - configure_datafrag_size(); + result = configure_datafrag_size(); #endif - logger.log_message("Data Fragmentation Size = " + if (!result) { + logger.log_message("Error configuring Data Fragmentation Size = " + + std::to_string(options->datafrag_size), Verbosity::ERROR); + return false; + } else { + logger.log_message("Data Fragmentation Size = " + std::to_string(options->datafrag_size), Verbosity::DEBUG); + } } #ifdef RTI_CONNEXT_MICRO From 8a60559e099bda37147380be572abab5991561ca Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 6 Feb 2026 19:49:43 +0100 Subject: [PATCH 36/44] Update shape_micro.idl name to shape_bounded.idl --- srcCxx/makefile_rti_connext_micro_linux | 4 ++-- srcCxx/makefile_rti_connext_micro_macos | 4 ++-- srcCxx/{shape_micro.idl => shape_bounded.idl} | 0 srcCxx/shape_configurator_rti_connext_micro.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename srcCxx/{shape_micro.idl => shape_bounded.idl} (100%) diff --git a/srcCxx/makefile_rti_connext_micro_linux b/srcCxx/makefile_rti_connext_micro_linux index e53ec1aa..1475c322 100644 --- a/srcCxx/makefile_rti_connext_micro_linux +++ b/srcCxx/makefile_rti_connext_micro_linux @@ -64,8 +64,8 @@ INCLUDES = -I. -I$(RTIMEHOME)/include -I$(RTIMEHOME)/include/rti_me OBJDIR := objs/$(RTIMEARCH)_micro -CDRSOURCES := shape_micro.idl -AUTOGENSOURCES := shape_microSupport.cxx shape_microPlugin.cxx shape_micro.cxx +CDRSOURCES := shape_bounded.idl +AUTOGENSOURCES := shape_boundedSupport.cxx shape_boundedPlugin.cxx shape_bounded.cxx EXEC := $(executable_name) AUTOGENOBJS := $(addprefix $(OBJDIR)/, $(AUTOGENSOURCES:%.cxx=%.o)) diff --git a/srcCxx/makefile_rti_connext_micro_macos b/srcCxx/makefile_rti_connext_micro_macos index c397f418..25ca9b5c 100644 --- a/srcCxx/makefile_rti_connext_micro_macos +++ b/srcCxx/makefile_rti_connext_micro_macos @@ -64,8 +64,8 @@ INCLUDES = -I. -I$(RTIMEHOME)/include -I$(RTIMEHOME)/include/rti_me OBJDIR := objs/$(RTIMEARCH)_micro -CDRSOURCES := shape_micro.idl -AUTOGENSOURCES := shape_microSupport.cxx shape_microPlugin.cxx shape_micro.cxx +CDRSOURCES := shape_bounded.idl +AUTOGENSOURCES := shape_boundedSupport.cxx shape_boundedPlugin.cxx shape_bounded.cxx EXEC := $(executable_name) AUTOGENOBJS := $(addprefix $(OBJDIR)/, $(AUTOGENSOURCES:%.cxx=%.o)) diff --git a/srcCxx/shape_micro.idl b/srcCxx/shape_bounded.idl similarity index 100% rename from srcCxx/shape_micro.idl rename to srcCxx/shape_bounded.idl diff --git a/srcCxx/shape_configurator_rti_connext_micro.h b/srcCxx/shape_configurator_rti_connext_micro.h index 38e2e6a3..46dae675 100644 --- a/srcCxx/shape_configurator_rti_connext_micro.h +++ b/srcCxx/shape_configurator_rti_connext_micro.h @@ -1,5 +1,5 @@ -#include "shape_micro.h" -#include "shape_microSupport.h" +#include "shape_bounded.h" +#include "shape_boundedSupport.h" #include "rti_me_cpp.hxx" #include "dds_cpp/dds_cpp_netio.hxx" From 7fe819af03de51366ea7dd40e153058f38b0ee5c Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 6 Feb 2026 19:51:10 +0100 Subject: [PATCH 37/44] Make the datafrag-size parameter optional since it wont be used in any tests --- srcCxx/shape_main.cxx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 05be284f..b8d1cd22 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -1169,13 +1169,11 @@ class ShapeApplication { if (options->datafrag_size > 0) { bool result = false; -#if defined(RTI_CONNEXT_DDS) + #if defined(RTI_CONNEXT_DDS) result = configure_datafrag_size(dp_qos, options->datafrag_size); -#elif defined(RTI_CONNEXT_MICRO) + #elif defined(RTI_CONNEXT_MICRO) result = configure_datafrag_size(options->datafrag_size); -#else - result = configure_datafrag_size(); -#endif + #endif if (!result) { logger.log_message("Error configuring Data Fragmentation Size = " From 384170cbd55e5bdbf8c5fd42fa6f7763802d203b Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 6 Feb 2026 19:52:25 +0100 Subject: [PATCH 38/44] Update gitignore to the new name shape_bounded --- .gitignore | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 528357ed..4897f53d 100644 --- a/.gitignore +++ b/.gitignore @@ -53,10 +53,10 @@ srcCxx/shapePlugin.* srcCxx/shapeSupport.* # Generated files Connext Micro -srcCxx/shape_micro.* -!srcCxx/shape_micro.idl -srcCxx/shape_microPlugin.* -srcCxx/shape_microSupport.* +srcCxx/shape_bounded.* +!srcCxx/shape_bounded.idl +srcCxx/shape_boundedPlugin.* +srcCxx/shape_boundedSupport.* # VSCode default folders .vscode/ From 7c284917b047dc9c915b58b787351af6b0a529fa Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Fri, 6 Feb 2026 21:26:21 +0100 Subject: [PATCH 39/44] NOT_ALIVE messages are now printed independently of the value of valid_data --- srcCxx/shape_main.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index b8d1cd22..b91d3069 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -1883,7 +1883,9 @@ class ShapeApplication { #elif defined(RTI_CONNEXT_MICRO) set_instance_color(instance_handle_color, sample_info->instance_handle, sample->color); #endif - } else { + } + + if (sample_info->instance_state != ALIVE_INSTANCE_STATE) { ShapeType shape_key; shape_initialize_w_color(shape_key, NULL); #if defined(EPROSIMA_FAST_DDS) From c86efced094b592b3c304a86fe520eea112fd62a Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 11 Feb 2026 15:06:30 +0100 Subject: [PATCH 40/44] Apply suggestions from code review Co-authored-by: Miguel Company --- srcCxx/shape_main.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index b91d3069..2c533089 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -898,10 +898,10 @@ class ShapeOptions { parse_ok = false; } // the spec mentions that the fragment size must satisfy: - // fragment size <= 65536 bytes. - if (converted_param > 65536) { + // fragment size <= 65535 bytes. + if (converted_param > 65535) { logger.log_message("incorrect value for datafrag-size, " - "it must be <= 65536 bytes" + "it must be <= 65535 bytes" + std::to_string(converted_param), Verbosity::ERROR); parse_ok = false; @@ -952,7 +952,7 @@ class ShapeOptions { + (unregister ? "Unregister" : (dispose ? "Dispose" : "not specified")) + "\n Periodic Announcement Period = " + std::to_string(periodic_announcement_period_us / 1000) + "ms" + - "\n Data Fragmentation Size = " + std::to_string(datafrag_size) + "ms", + "\n Data Fragmentation Size = " + std::to_string(datafrag_size) + " bytes", Verbosity::DEBUG); if (topic_name != NULL){ logger.log_message(" Topic = " + std::string(topic_name), From d1ce949ee05ab226d6412dd87c72ed1fe97fd8b0 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 11 Feb 2026 15:36:15 +0100 Subject: [PATCH 41/44] Fix missing brace after merge --- srcCxx/shape_main.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 2e3f30d4..aeec4538 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -933,6 +933,7 @@ class ShapeOptions { parse_ok = false; } datafrag_size = converted_param; + } case 'F': cft_expression = strdup(optarg); break; From fba7a84036b36ef1c2c929129cdeddfc15c4287e Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 11 Feb 2026 15:44:55 +0100 Subject: [PATCH 42/44] Fixing merged code --- srcCxx/shape_main.cxx | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index aeec4538..5ce59107 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -1702,32 +1702,34 @@ class ShapeApplication { logger.log_message(" ContentFilterTopic = \"" + std::string(filter_expr) + "\"", Verbosity::DEBUG); } else if (options->color != NULL) { #if defined(RTI_CONNEXT_DDS) - char parameter[64]; - snprintf(parameter, 64, "'%s'", options->color); - StringSeq_push(cf_params, parameter); + char parameter[64]; + snprintf(parameter, 64, "'%s'", options->color); + StringSeq_push(cf_params, parameter); - cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color MATCH %0", cf_params); - logger.log_message(" ContentFilterTopic = \"color MATCH " - + std::string(parameter) + std::string("\""), Verbosity::DEBUG); + cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color MATCH %0", cf_params); + logger.log_message(" ContentFilterTopic = \"color MATCH " + + std::string(parameter) + std::string("\""), Verbosity::DEBUG); #elif defined(INTERCOM_DDS) - char parameter[64]; - snprintf(parameter, 64, "'%s'", options->color); - StringSeq_push(cf_params, parameter); + char parameter[64]; + snprintf(parameter, 64, "'%s'", options->color); + StringSeq_push(cf_params, parameter); - cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color = %0", cf_params); - logger.log_message(" ContentFilterTopic = \"color = " - + std::string(parameter) + std::string("\""), Verbosity::DEBUG); + cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color = %0", cf_params); + logger.log_message(" ContentFilterTopic = \"color = " + + std::string(parameter) + std::string("\""), Verbosity::DEBUG); #elif defined(TWINOAKS_COREDX) || defined(OPENDDS) - StringSeq_push(cf_params, options->color); - cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color = %0", cf_params); - logger.log_message(" ContentFilterTopic = \"color = " - + std::string(options->color) + std::string("\""), Verbosity::DEBUG); + StringSeq_push(cf_params, options->color); + cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color = %0", cf_params); + logger.log_message(" ContentFilterTopic = \"color = " + + std::string(options->color) + std::string("\""), Verbosity::DEBUG); #elif defined(EPROSIMA_FAST_DDS) - cf_params.push_back(std::string("'") + options->color + std::string("'")); - cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color = %0", cf_params); - logger.log_message(" ContentFilterTopic = \"color = " - + cf_params[0] + std::string("\""), Verbosity::DEBUG); + cf_params.push_back(std::string("'") + options->color + std::string("'")); + cft = dp->create_contentfilteredtopic(filtered_topic_name, topics[i], "color = %0", cf_params); + logger.log_message(" ContentFilterTopic = \"color = " + + cf_params[0] + std::string("\""), Verbosity::DEBUG); #endif + } + if (cft == NULL) { logger.log_message("failed to create content filtered topic", Verbosity::ERROR); return false; @@ -1742,7 +1744,6 @@ class ShapeApplication { } #endif - } else { // Create different DataReaders (depending on the number of entities) // The DRs are attached to the same array index of the topics. From 74ae72ec96d1a27045d38ffa309b3a60b1e2aa88 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Wed, 11 Feb 2026 15:55:46 +0100 Subject: [PATCH 43/44] Handle new cft parameter in micro --- srcCxx/shape_main.cxx | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 5ce59107..4f31fbd2 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -483,24 +483,27 @@ class ShapeOptions { if (!coherent_set_enabled && !ordered_access_enabled && coherent_set_access_scope_set) { logger.log_message("warning: --access-scope ignored because not coherent, or ordered access enabled", Verbosity::ERROR); } + if (size_modulo > 0 && shapesize != 0) { + logger.log_message("warning: --size-modulo has no effect unless shapesize (-z) is set to 0", Verbosity::ERROR); + } + if (subscribe && color != NULL && cft_expression != NULL) { + logger.log_message("error: cannot specify both --cft and -c for subscriber applications", Verbosity::ERROR); + return false; + } + #if defined(RTI_CONNEXT_MICRO) - if (!publish && color != NULL) { - free(color); + if (subscribe && (color != NULL || cft_expression != NULL)) { + STRING_FREE(color); color = NULL; + STRING_FREE(cft_expression); + cft_expression = NULL; logger.log_message("warning: content filtered topic not supported, normal topic used", Verbosity::ERROR); } - if (!publish && take_read_next_instance == true ) { + if (subscribe && take_read_next_instance == true ) { take_read_next_instance = false; logger.log_message("warning: use of take/read_next_instance() not available, using take/read()", Verbosity::ERROR); } #endif - if (size_modulo > 0 && shapesize != 0) { - logger.log_message("warning: --size-modulo has no effect unless shapesize (-z) is set to 0", Verbosity::ERROR); - } - if (subscribe && color != NULL && cft_expression != NULL) { - logger.log_message("error: cannot specify both --cft and -c/--color for subscriber applications", Verbosity::ERROR); - return false; - } return true; } @@ -1682,7 +1685,7 @@ class ShapeApplication { } if ( options->cft_expression != NULL || options->color != NULL) { - /* For Connext Micro color will be always NULL */ + /* For Connext Micro color and cft_expression will be always NULL */ #if !defined(RTI_CONNEXT_MICRO) /* filter on specified color */ ContentFilteredTopic *cft = NULL; From d6a9d3897bd058106d31b1a3ee004b72e97da580 Mon Sep 17 00:00:00 2001 From: Angel Martinez Date: Thu, 12 Feb 2026 20:47:46 +0100 Subject: [PATCH 44/44] Update srcCxx/shape_main.cxx Co-authored-by: Adam Mitz --- srcCxx/shape_main.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srcCxx/shape_main.cxx b/srcCxx/shape_main.cxx index 4f31fbd2..88c092ae 100644 --- a/srcCxx/shape_main.cxx +++ b/srcCxx/shape_main.cxx @@ -499,7 +499,7 @@ class ShapeOptions { cft_expression = NULL; logger.log_message("warning: content filtered topic not supported, normal topic used", Verbosity::ERROR); } - if (subscribe && take_read_next_instance == true ) { + if (subscribe && take_read_next_instance) { take_read_next_instance = false; logger.log_message("warning: use of take/read_next_instance() not available, using take/read()", Verbosity::ERROR); }