From cb3eba6ed0d0543f139ab32bf5bc51cbeee240a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ferreira=20Gonz=C3=A1lez?= Date: Wed, 3 Jun 2026 15:17:11 +0200 Subject: [PATCH 1/4] Add UBSan workflow and solve its errors (#6386) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refs #24364: Add UBSan workflow Signed-off-by: Carlos Ferreira González * Refs #24365: Add CMake Undefined Behavior option Signed-off-by: Carlos Ferreira González * Refs #24365: Fix building of tests with UBSan Signed-off-by: Carlos Ferreira González * Refs #24365: Compliance with ODR enum type in tests Signed-off-by: Carlos Ferreira González * Refs #24365: Regression Test Malicious Data Signed-off-by: Carlos Ferreira González * Refs #24365: Review - Meta file Signed-off-by: Carlos Ferreira González * Refs #24365: Ensure no duplicates originate in UBSAN report due to addresses Signed-off-by: Carlos Ferreira González * Refs #24365: Avoid calling memcmp with empty payloads Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in TimedEvent ctor Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in SampleLostStatus due to overflow Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in CDRMessage Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in statistics::DomainParticipant Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in ParticipantTests magically Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in UserListenerTests due to downcast Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in PoolConfig due to overflow Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in DataWriterTests magically Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in TCPv4Test due to wrong type cast Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in Security tests with SharedSecretHandle Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in Log Options Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in MonitorServiceTests Signed-off-by: Carlos Ferreira González * Refs #24365: Skip false positive of sqlite3.c Signed-off-by: Carlos Ferreira González * Refs #24365: Fix mac/windows build Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in DataReader/Writer blackbox tests Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in Latency tests Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in StatisticsTests magically Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in RTPSStatisticsTests magically Signed-off-by: Carlos Ferreira González * Refs #24365: Fix UB in SecurityManager Signed-off-by: Carlos Ferreira González --------- Signed-off-by: Carlos Ferreira González (cherry picked from commit 25a43a7c3a28a286d94dc16fa11afe2b2d4eb9a1) Solve conflicts Signed-off-by: Carlos Ferreira González --- .github/workflows/config/ubsan.meta | 17 ++ .github/workflows/reusable-sanitizers-ci.yml | 190 ++++++++++++++++++ .github/workflows/sanitizers-ci.yml | 10 + .github/workflows/utils/log_parser.py | 114 +++++++++-- CMakeLists.txt | 17 ++ include/fastdds/rtps/messages/CDRMessage.hpp | 5 + include/fastdds/rtps/resources/TimedEvent.h | 14 +- .../rtps/security/logging/LogOptions.h | 4 +- .../dds/domain/DomainParticipant.hpp | 9 + .../domain/DomainParticipantFactory.cpp | 7 +- src/cpp/fastdds/publisher/DataWriterImpl.cpp | 2 +- src/cpp/fastdds/subscriber/DataReaderImpl.cpp | 29 ++- src/cpp/rtps/common/SerializedPayload.cpp | 154 ++++++++++++++ src/cpp/rtps/history/PoolConfig.h | 35 +++- src/cpp/rtps/resources/TimedEvent.cpp | 11 + src/cpp/rtps/security/SecurityManager.cpp | 7 +- .../fastdds/domain/DomainParticipant.cpp | 6 + .../common/BlackboxTestsDeadlineQos.cpp | 2 + .../common/BlackboxTestsDiscovery.cpp | 2 + .../common/BlackboxTestsLifespanQoS.cpp | 2 + .../common/BlackboxTestsLivelinessQos.cpp | 2 + .../common/BlackboxTestsNetworkConf.cpp | 2 + .../common/BlackboxTestsPubSubBasic.cpp | 2 + .../common/BlackboxTestsPubSubFragments.cpp | 2 + .../common/BlackboxTestsPubSubHistory.cpp | 2 + .../BlackboxTestsRealtimeAllocations.cpp | 2 + .../blackbox/common/BlackboxTestsSecurity.cpp | 2 + .../common/BlackboxTestsTransportTCP.cpp | 2 + .../common/BlackboxTestsTransportUDP.cpp | 97 ++++++++- .../blackbox/common/BlackboxTestsVolatile.cpp | 2 + .../common/DDSBlackboxTestsDataReader.cpp | 3 +- .../common/DDSBlackboxTestsDataWriter.cpp | 2 + .../common/DDSBlackboxTestsListeners.cpp | 2 + .../common/DDSBlackboxTestsMonitorService.cpp | 2 + .../common/DDSBlackboxTestsOwnershipQos.cpp | 2 + .../common/DDSBlackboxTestsPersistence.cpp | 2 + .../DDSBlackboxTestsPersistenceGuid.cpp | 2 + .../common/DDSBlackboxTestsPropertyQos.cpp | 2 + .../DDSBlackboxTestsTransportSHMUDP.cpp | 2 + .../common/DDSBlackboxTestsUserDataQos.cpp | 2 + .../common/RTPSBlackboxTestsBasic.cpp | 2 + .../common/RTPSBlackboxTestsDiscovery.cpp | 2 + .../common/RTPSBlackboxTestsPersistence.cpp | 2 + .../RTPSBlackboxTestsPersistenceGuid.cpp | 2 + .../common/RTPSBlackboxTestsPools.cpp | 2 + .../common/RTPSBlackboxTestsReader.cpp | 158 +++++++++++++++ .../common/RTPSBlackboxTestsVolatile.cpp | 2 + .../common/RTPSBlackboxTestsWriter.cpp | 158 +++++++++++++++ .../fastdds/publisher/DataWriterHistory.hpp | 6 +- .../rtps/security/common/SharedSecretHandle.h | 176 ++++++++++++++++ .../fastdds/rtps/resources/TimedEvent.h | 8 +- .../latency/LatencyTestPublisher.cpp | 12 +- .../dds/participant/ParticipantTests.cpp | 26 ++- .../dds/publisher/DataWriterTests.cpp | 47 +++-- test/unittest/dds/status/ListenerTests.cpp | 13 +- test/unittest/rtps/discovery/CMakeLists.txt | 2 + test/unittest/rtps/writer/CMakeLists.txt | 2 + .../security/authentication/CMakeLists.txt | 3 + .../StatisticsDomainParticipantMockTests.cpp | 81 +++++--- ...sDomainParticipantStatusQueryableTests.cpp | 107 +++++----- .../statistics/dds/StatisticsQosTests.cpp | 76 ++++--- test/unittest/statistics/rtps/CMakeLists.txt | 2 + .../statistics/rtps/RTPSStatisticsTests.cpp | 26 ++- .../rtps/monitor-service/MonitorService.hpp | 5 +- test/unittest/transport/CMakeLists.txt | 3 + test/unittest/transport/TCPv4Tests.cpp | 2 +- 66 files changed, 1510 insertions(+), 188 deletions(-) create mode 100644 .github/workflows/config/ubsan.meta create mode 100644 src/cpp/rtps/common/SerializedPayload.cpp create mode 100644 test/blackbox/common/RTPSBlackboxTestsReader.cpp create mode 100644 test/blackbox/common/RTPSBlackboxTestsWriter.cpp create mode 100644 test/mock/rtps/SharedSecretHandle/rtps/security/common/SharedSecretHandle.h diff --git a/.github/workflows/config/ubsan.meta b/.github/workflows/config/ubsan.meta new file mode 100644 index 00000000000..336a5cdb615 --- /dev/null +++ b/.github/workflows/config/ubsan.meta @@ -0,0 +1,17 @@ +names: + fastdds: + cmake-args: + - -DNO_TLS=OFF + - -DSECURITY=ON + - -DFASTDDS_STATISTICS=ON + - -DSANITIZER=Undefined + - -DCOMPILE_WARNING_AS_ERROR=ON + - -DEPROSIMA_BUILD_TESTS=ON + - -DRTPS_API_TESTS=ON + - -DFASTDDS_PIM_API_TESTS=ON + - -DPERFORMANCE_TESTS=ON + googletest-distribution: + cmake-args: + - -Dgtest_force_shared_crt=ON + - -DBUILD_SHARED_LIBS=ON + - -DBUILD_GMOCK=ON diff --git a/.github/workflows/reusable-sanitizers-ci.yml b/.github/workflows/reusable-sanitizers-ci.yml index 4adb614580a..59979574c84 100644 --- a/.github/workflows/reusable-sanitizers-ci.yml +++ b/.github/workflows/reusable-sanitizers-ci.yml @@ -19,6 +19,10 @@ on: description: 'Run Thread Sanitizer job for Fast DDS' required: false type: boolean + run_ubsan_fastdds: + description: 'Run Undefined Behavior Sanitizer job for Fast DDS' + required: false + type: boolean colcon_build_args: description: 'Optional colcon build arguments' required: false @@ -547,3 +551,189 @@ jobs: run: | Write-Host ${{ steps.report_summary.outcome }} exit 1 + + ubsan_fastdds_build: + if: ${{ inputs.run_ubsan_fastdds == true }} + runs-on: ubuntu-24.04 + steps: + - name: Free disk space + uses: eProsima/eProsima-CI/ubuntu/free_disk_space@v0 + + - name: Sync eProsima/Fast-DDS repository + uses: eProsima/eProsima-CI/external/checkout@v0 + with: + path: src/fastdds + submodules: true + ref: ${{ inputs.fastdds_ref }} + + - name: Install Fix Python version + uses: eProsima/eProsima-CI/external/setup-python@v0 + with: + python-version: '3.11' + + - name: Get minimum supported version of CMake + uses: eProsima/eProsima-CI/external/get-cmake@v0 + with: + cmakeVersion: '3.28.6' + + - name: Install apt packages + uses: eProsima/eProsima-CI/ubuntu/install_apt_packages@v0 + with: + packages: curl grep libasio-dev libtinyxml2-dev python3 python3-pip software-properties-common wget + + - name: Install colcon + uses: eProsima/eProsima-CI/ubuntu/install_colcon@v0 + + - name: Install Python dependencies + uses: eProsima/eProsima-CI/ubuntu/install_python_packages@v0 + with: + packages: vcstool xmlschema + + - name: Setup CCache + uses: eProsima/eProsima-CI/external/setup-ccache-action@v0 + if: ${{ !always() }} + with: + api_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Get Fast CDR branch + id: get_fastcdr_branch + uses: eProsima/eProsima-CI/ubuntu/get_related_branch_from_repo@v0 + with: + remote_repository: eProsima/Fast-CDR + fallback_branch: ${{ inputs.fastcdr_ref }} + + - name: Download Fast CDR + uses: eProsima/eProsima-CI/external/checkout@v0 + with: + repository: eProsima/Fast-CDR + path: ${{ github.workspace }}/src/fastcdr + ref: ${{ steps.get_fastcdr_branch.outputs.deduced_branch }} + + - name: Fetch Fast DDS dependencies + uses: eProsima/eProsima-CI/ubuntu/vcs_import@v0 + with: + vcs_repos_file: ${{ github.workspace }}/src/fastdds/fastdds.repos + destination_workspace: src + skip_existing: 'true' + + - name: Fetch Fast DDS CI dependencies + uses: eProsima/eProsima-CI/ubuntu/vcs_import@v0 + with: + vcs_repos_file: ${{ github.workspace }}/src/fastdds/.github/workflows/config/fastdds_test.repos + destination_workspace: src + skip_existing: 'true' + + - name: Show .meta file + id: show_meta + run: | + cat ${{ github.workspace }}/src/fastdds/.github/workflows/config/ubsan.meta + + - name: Colcon build + continue-on-error: false + uses: eProsima/eProsima-CI/ubuntu/colcon_build@v0 + with: + colcon_meta_file: ${{ github.workspace }}/src/fastdds/.github/workflows/config/ubsan.meta + colcon_build_args: ${{ inputs.colcon_build_args }} + cmake_args: ${{ inputs.cmake_args }} + cmake_args_default: '' + cmake_build_type: 'Debug' + workspace: ${{ github.workspace }} + workspace_dependencies: '' + + - name: Pack workspace preserving permissions + shell: bash + run: | + tar -C "${{ github.workspace }}" -cpf "${{ runner.temp }}/ubsan_build_${{ inputs.label }}.tar" . + + - name: Upload build artifacts + uses: eProsima/eProsima-CI/external/upload-artifact@v0 + with: + name: build_artifacts_fastdds_ubsan_${{ inputs.label }} + path: ${{ runner.temp }}/ubsan_build_${{ inputs.label }}.tar + + ubsan_fastdds_test: + if: ${{ inputs.run_ubsan_fastdds == true }} + needs: ubsan_fastdds_build + runs-on: ubuntu-24.04 + env: + UBSAN_OPTIONS: halt_on_error=1:abort_on_error=1:print_stacktrace=1 + steps: + - name: Free disk space + uses: eProsima/eProsima-CI/ubuntu/free_disk_space@v0 + + - name: Download build artifact + uses: eProsima/eProsima-CI/external/download-artifact@v0 + with: + name: build_artifacts_fastdds_ubsan_${{ inputs.label }} + path: ${{ runner.temp }} + + - name: Unpack workspace preserving permissions + shell: bash + run: | + tar -C "${{ github.workspace }}" -xpf "${{ runner.temp }}/ubsan_build_${{ inputs.label }}.tar" + + - name: Install Fix Python version + uses: eProsima/eProsima-CI/external/setup-python@v0 + with: + python-version: '3.11' + + - name: Get minimum supported version of CMake + uses: eProsima/eProsima-CI/external/get-cmake@v0 + with: + cmakeVersion: '3.28.6' + + - name: Install apt packages + uses: eProsima/eProsima-CI/ubuntu/install_apt_packages@v0 + with: + packages: curl grep libasio-dev libtinyxml2-dev python3 python3-pip software-properties-common wget + + - name: Install colcon + uses: eProsima/eProsima-CI/ubuntu/install_colcon@v0 + + - name: Install Python dependencies + uses: eProsima/eProsima-CI/ubuntu/install_python_packages@v0 + with: + packages: setuptools gcovr tomark xmltodict jsondiff pandas psutil + + - name: Set up hosts file for DNS testing + run: | + sudo echo "" | sudo tee -a /etc/hosts + sudo echo "127.0.0.1 localhost.test" | sudo tee -a /etc/hosts + sudo echo "::1 localhost.test" | sudo tee -a /etc/hosts + sudo echo "154.56.134.194 www.eprosima.com.test" | sudo tee -a /etc/hosts + sudo echo "216.58.215.164 www.acme.com.test" | sudo tee -a /etc/hosts + sudo echo "2a00:1450:400e:803::2004 www.acme.com.test" | sudo tee -a /etc/hosts + sudo echo "140.82.121.4 www.foo.com.test" | sudo tee -a /etc/hosts + sudo echo "140.82.121.3 www.foo.com.test" | sudo tee -a /etc/hosts + sudo echo "ff1e::ffff:efff:1 acme.org.test" | sudo tee -a /etc/hosts + + - name: Colcon test + id: test + continue-on-error: true + uses: eProsima/eProsima-CI/ubuntu/colcon_test@v0 + with: + colcon_args_default: '' + colcon_test_args: ${{ inputs.colcon_test_args }} + colcon_test_args_default: '--event-handlers=console_direct+ --return-code-on-test-failure' + ctest_args: ${{ inputs.ctest_args }} + ctest_args_default: '--timeout 300 --label-exclude "xfail"' + packages_names: fastdds + workspace: ${{ github.workspace }} + workspace_dependencies: '' + test_report_artifact: ${{ format('test_report_{0}_{1}', inputs.label, github.job) }} + + - name: Report sanitizer errors + run: | + # UBSan finding header lines look like: + # ::: runtime error: + # Filter on ": runtime error:" so we keep one line per finding (the header) + bash src/fastdds/.github/workflows/utils/specific_errors_filter.sh \ + ": runtime error:" \ + log/latest_test/fastdds/stdout_stderr.log \ + _tmp_specific_error_file.log + + python3 src/fastdds/.github/workflows/utils/log_parser.py \ + --log-file log/latest_test/fastdds/stdout_stderr.log \ + --specific-error-file _tmp_specific_error_file.log \ + --output-file $GITHUB_STEP_SUMMARY \ + --sanitizer ubsan diff --git a/.github/workflows/sanitizers-ci.yml b/.github/workflows/sanitizers-ci.yml index 894df06da3e..da82f19d8c8 100644 --- a/.github/workflows/sanitizers-ci.yml +++ b/.github/workflows/sanitizers-ci.yml @@ -19,6 +19,10 @@ on: description: 'Run Thread Sanitizer job for Fast DDS' required: false type: boolean + run_ubsan_fastdds: + description: 'Run Undefined Behavior Sanitizer job for Fast DDS' + required: false + type: boolean colcon_build_args: description: 'Optional colcon build arguments' required: false @@ -80,6 +84,12 @@ jobs: !contains(github.event.pull_request.labels.*.name, 'skip-ci') && !contains(github.event.pull_request.labels.*.name, 'no-test') ) }} + run_ubsan_fastdds: ${{ ((inputs.run_ubsan_fastdds == true) && true) || + ( + (github.event_name == 'pull_request') && + !contains(github.event.pull_request.labels.*.name, 'skip-ci') && + !contains(github.event.pull_request.labels.*.name, 'no-test') + ) }} colcon_build_args: ${{ inputs.colcon_build_args || '' }} colcon_test_args: ${{ inputs.colcon_test_args || '' }} cmake_args: ${{ inputs.cmake_args || '' }} diff --git a/.github/workflows/utils/log_parser.py b/.github/workflows/utils/log_parser.py index 937f71635da..f4ade3573e3 100644 --- a/.github/workflows/utils/log_parser.py +++ b/.github/workflows/utils/log_parser.py @@ -22,6 +22,23 @@ DESCRIPTION = """Script to read a test log and return a summary table""" USAGE = ('python3 log_parser.py') +# Each UBSan finding starts with a source location followed by " runtime error: ". +# We group findings by "::: " so that the same UB at the +# same site collapses into a single row regardless of repetition or ctest line prefixes +_UBSAN_LINE_RE = re.compile( + r'(?P\S+?):(?P\d+):(?P\d+):\s*runtime error:\s*(?P.+?)\s*$' +) +# Strip GitHub Actions ISO-8601 timestamp prefix and/or a ctest line prefix (": "). +# The ctest prefix captures the test id so we can attribute UBSan findings to their test; +# .sub() still strips just the prefix, and .match() exposes the id via the named group. +_GH_TIMESTAMP_RE = re.compile(r'^\d{4}-\d{2}-\d{2}T\S+\s+') +_CTEST_PREFIX_RE = re.compile(r'^(?P\d+):\s*') +# Hex addresses ("0x55ade3179480") differ across runs but represent the same logical UB; +# normalize them to "0x..." so identical findings at the same site collapse into one row. +_HEX_ADDRESS_RE = re.compile(r'0x[0-9a-fA-F]+') +# Path fragments whose UBSan findings are suppressed (thirdparty code we don't maintain). +_UBSAN_IGNORED_PATH_SUBSTRINGS = ('sqlite3.c',) + def parse_options(): """ @@ -49,7 +66,7 @@ def parse_options(): '--specific-error-file', type=str, required=True, - help='Path to file with ASAN or TSAN specific errors.' + help='Path to file with ASAN, TSAN or UBSAN specific errors.' ) required_args.add_argument( '-o', @@ -64,14 +81,17 @@ def parse_options(): '--sanitizer', type=str, required=True, - help='Sanitizer to use. [ASAN|TSAN] no case sensitive.' + help='Sanitizer to use. [ASAN|TSAN|UBSAN] no case sensitive.' ) return parser.parse_args() def failure_test_list( - log_file_path: str): + log_file_path: str, + ignored_test_ids: set = None): + + ignored_test_ids = ignored_test_ids or set() # failed tests saved_lines = [] @@ -93,12 +113,16 @@ def failure_test_list( # Thus, it uses this variable to get the correct # of spaces in error name n_spaces_in_error = len(test[test.find('(')+1:test.find(')')].split()) - 1 + test_id = split_test[- 4 - n_spaces_in_error] + if test_id in ignored_test_ids: + continue + # Insert as failed test (in first place, because we are reading them inversed) # the new test failed with the name and id taken from split line failed_tests.insert( 0, dict({ - 'ID': split_test[- 4 - n_spaces_in_error], + 'ID': test_id, 'Name': split_test[- 2 - n_spaces_in_error], 'Type': test[test.find('(')+1:test.find(')')] })) @@ -117,6 +141,35 @@ def failure_test_list( return failed_tests, n_errors +def tests_failing_only_in_ignored_ubsan_paths( + log_file_path: str, + ignored_path_substrings: tuple): + """ + Return the set of ctest test ids whose UBSan findings are exclusively in files + matching ignored_path_substrings. Tests with no UBSan findings or with at least + one finding outside the ignored paths are excluded (i.e., they remain reported). + """ + test_id_to_paths = {} + with open(log_file_path, 'r', encoding='utf-8', errors='replace') as file: + for line in file: + stripped = _GH_TIMESTAMP_RE.sub('', line.rstrip('\r\n')) + id_match = _CTEST_PREFIX_RE.match(stripped) + if not id_match: + continue + ubsan_match = _UBSAN_LINE_RE.search(stripped[id_match.end():]) + if not ubsan_match: + continue + test_id_to_paths.setdefault(id_match.group('id'), set()).add( + ubsan_match.group('path')) + + return { + test_id for test_id, paths in test_id_to_paths.items() + if paths and all( + any(sub in path for sub in ignored_path_substrings) + for path in paths) + } + + def _common_line_splitter( line: str, text_to_split_start: str, @@ -148,6 +201,22 @@ def tsan_line_splitter( text_to_split_end=' (pid=') +def ubsan_line_splitter( + line: str): + stripped = _GH_TIMESTAMP_RE.sub('', line.rstrip('\r\n')) + stripped = _CTEST_PREFIX_RE.sub('', stripped) + match = _UBSAN_LINE_RE.search(stripped) + if not match: + # Not an UBSan finding header + return None + if any(sub in match.group('path') for sub in _UBSAN_IGNORED_PATH_SUBSTRINGS): + # Ignore UBSan findings in thirdparty code we don't maintain. + return None + basename = match.group('path').rsplit('/', 1)[-1] + desc = _HEX_ADDRESS_RE.sub('0x...', match.group('desc')) + return f"{basename}:{match.group('line')}:{match.group('col')}: {desc}" + + def common_specific_errors_list( errors_file_path: str, line_splitter): @@ -170,11 +239,14 @@ def common_specific_errors_dict( errors_file_path: str, line_splitter): - # failed tests + # Open with newline='' so Python's universal-newline mode does not split a single + # grep-emitted line on bare '\r' characters. errors = {} - with open(errors_file_path, 'r') as file: - for line in file.readlines(): + with open(errors_file_path, 'r', newline='') as file: + for line in file: error_id = line_splitter(line) + if error_id is None: + continue if error_id in errors: errors[error_id] += 1 else: @@ -203,10 +275,19 @@ def main(): # Parse arguments args = parse_options() - # Get specific ASAN or TSAN variables - asan = args.sanitizer.lower() == 'asan' - line_splitter = (asan_line_splitter if asan else tsan_line_splitter) - file_title = ('ASAN' if asan else 'TSAN') + ' Errors Summary' + # Select the splitter and report title for the requested sanitizer. + sanitizer = args.sanitizer.lower() + splitters = { + 'asan': (asan_line_splitter, 'ASAN'), + 'tsan': (tsan_line_splitter, 'TSAN'), + 'ubsan': (ubsan_line_splitter, 'UBSAN'), + } + if sanitizer not in splitters: + raise SystemExit( + f"Unsupported sanitizer '{args.sanitizer}'. Expected one of: " + f"{', '.join(s.upper() for s in splitters)}.") + line_splitter, title_prefix = splitters[sanitizer] + file_title = f'{title_prefix} Errors Summary' # Execute specific errors parse specific_errors, n_errors = common_specific_errors_list( @@ -217,9 +298,18 @@ def main(): result=specific_errors, output_file_path=args.output_file) + # For UBSan, also drop from the "Tests failed" table any test whose findings + # were all in ignored thirdparty paths (matches what we suppress above). + ignored_test_ids = set() + if sanitizer == 'ubsan': + ignored_test_ids = tests_failing_only_in_ignored_ubsan_paths( + log_file_path=args.log_file, + ignored_path_substrings=_UBSAN_IGNORED_PATH_SUBSTRINGS) + # Execute failed tests tests_failed, _ = failure_test_list( - log_file_path=args.log_file) + log_file_path=args.log_file, + ignored_test_ids=ignored_test_ids) print_list_to_markdown( title='Tests failed', result=tests_failed, diff --git a/CMakeLists.txt b/CMakeLists.txt index 98168ad2cbc..ef10c2a44d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,6 +171,23 @@ if (SANITIZER) message(FATAL_ERROR "Thread sanitizer requires Clang or GCC. Aborting.") endif() + elseif(${SANITIZER} STREQUAL "UNDEFINED") + message(STATUS "Enabling undefined behavior sanitizer...") + # Warning/Error messages + if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug")) + message(WARNING "Undefined behavior sanitizer results with an optimized (non-Debug) build may be misleading") + endif() + + if(CMAKE_COMPILER_IS_GNUCXX) + message(STATUS "Building with Undefined behavior sanitizer Tools") + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-omit-frame-pointer -fsanitize=float-cast-overflow -fsanitize=float-divide-by-zero -fsanitize=bounds-strict") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-omit-frame-pointer -fsanitize=float-cast-overflow -fsanitize=float-divide-by-zero -fsanitize=bounds-strict") + + else() + message(FATAL_ERROR "Undefined behavior sanitizer requires GCC. Aborting.") + endif() + else() message(WARNING "Sanitizer option not supported. Continuing without any code instrumentation... ") diff --git a/include/fastdds/rtps/messages/CDRMessage.hpp b/include/fastdds/rtps/messages/CDRMessage.hpp index af5e5e5577c..15c7395136c 100644 --- a/include/fastdds/rtps/messages/CDRMessage.hpp +++ b/include/fastdds/rtps/messages/CDRMessage.hpp @@ -402,6 +402,11 @@ inline void CDRMessage::copyToBuffer( const uint32_t length, bool reverse) { + if (length == 0) + { + return; + } + if (reverse) { for (uint32_t i = 0; i < length; i++) diff --git a/include/fastdds/rtps/resources/TimedEvent.h b/include/fastdds/rtps/resources/TimedEvent.h index 686a5f5d297..c2d36cf596b 100644 --- a/include/fastdds/rtps/resources/TimedEvent.h +++ b/include/fastdds/rtps/resources/TimedEvent.h @@ -106,11 +106,23 @@ class TimedEvent * @param callback Callback called when the event expires. * @param milliseconds Expiration time in milliseconds. */ - TimedEvent( + explicit TimedEvent( ResourceEvent& service, std::function callback, double milliseconds); + /*! + * @brief Construct with an expiration time expressed directly in microseconds. + * + * @param service ResourceEvent object that will operate with the event. + * @param callback Callback called when the event expires. + * @param interval Expiration time in std::chrono::microseconds. + */ + explicit TimedEvent( + ResourceEvent& service, + std::function callback, + std::chrono::microseconds interval); + //! Default destructor. virtual ~TimedEvent(); diff --git a/include/fastdds/rtps/security/logging/LogOptions.h b/include/fastdds/rtps/security/logging/LogOptions.h index 20caf490218..d8428fc4609 100644 --- a/include/fastdds/rtps/security/logging/LogOptions.h +++ b/include/fastdds/rtps/security/logging/LogOptions.h @@ -34,11 +34,11 @@ namespace security { struct LogOptions { //! Whether the log events should be distributed over DDS - bool distribute; + bool distribute = false; //! Level at which log messages will be logged. //! Messages at or below the log_level are logged. - LoggingLevel log_level; + LoggingLevel log_level = LoggingLevel::EMERGENCY_LEVEL; //! Full path to a local file std::string log_file; diff --git a/include/fastdds/statistics/dds/domain/DomainParticipant.hpp b/include/fastdds/statistics/dds/domain/DomainParticipant.hpp index 5f254c9af36..6d953d446bf 100644 --- a/include/fastdds/statistics/dds/domain/DomainParticipant.hpp +++ b/include/fastdds/statistics/dds/domain/DomainParticipant.hpp @@ -22,7 +22,9 @@ #include +#include #include +#include #include #include #include @@ -53,6 +55,13 @@ class DomainParticipant : public eprosima::fastdds::dds::DomainParticipant { DomainParticipant() = delete; +protected: + + DomainParticipant( + const eprosima::fastdds::dds::StatusMask& mask); + + friend class eprosima::fastdds::dds::DomainParticipantFactory; + public: /** diff --git a/src/cpp/fastdds/domain/DomainParticipantFactory.cpp b/src/cpp/fastdds/domain/DomainParticipantFactory.cpp index 063634beeea..3773687dc72 100644 --- a/src/cpp/fastdds/domain/DomainParticipantFactory.cpp +++ b/src/cpp/fastdds/domain/DomainParticipantFactory.cpp @@ -40,6 +40,10 @@ #include #include +#ifdef FASTDDS_STATISTICS +#include +#endif // ifdef FASTDDS_STATISTICS + using namespace eprosima::fastrtps::xmlparser; using eprosima::fastrtps::ParticipantAttributes; @@ -162,10 +166,11 @@ DomainParticipant* DomainParticipantFactory::create_participant( const DomainParticipantQos& pqos = (&qos == &PARTICIPANT_QOS_DEFAULT) ? default_participant_qos_ : qos; - DomainParticipant* dom_part = new DomainParticipant(mask); #ifndef FASTDDS_STATISTICS + DomainParticipant* dom_part = new DomainParticipant(mask); DomainParticipantImpl* dom_part_impl = new DomainParticipantImpl(dom_part, did, pqos, listen); #else + eprosima::fastdds::statistics::dds::DomainParticipant* dom_part = new eprosima::fastdds::statistics::dds::DomainParticipant(mask); eprosima::fastdds::statistics::dds::DomainParticipantImpl* dom_part_impl = new eprosima::fastdds::statistics::dds::DomainParticipantImpl(dom_part, did, pqos, listen); #endif // FASTDDS_STATISTICS diff --git a/src/cpp/fastdds/publisher/DataWriterImpl.cpp b/src/cpp/fastdds/publisher/DataWriterImpl.cpp index 8e0e556b5fb..c19ce6a41b6 100644 --- a/src/cpp/fastdds/publisher/DataWriterImpl.cpp +++ b/src/cpp/fastdds/publisher/DataWriterImpl.cpp @@ -1599,7 +1599,7 @@ void DataWriterImpl::configure_deadline_timer_() return deadline_missed(); }, // Park timer with a huge interval (prevents spurious callbacks); we'll arm/cancel explicitly - std::numeric_limits::max() + std::chrono::microseconds::max() ); } diff --git a/src/cpp/fastdds/subscriber/DataReaderImpl.cpp b/src/cpp/fastdds/subscriber/DataReaderImpl.cpp index b421672aaff..a08de345a2e 100644 --- a/src/cpp/fastdds/subscriber/DataReaderImpl.cpp +++ b/src/cpp/fastdds/subscriber/DataReaderImpl.cpp @@ -17,6 +17,8 @@ */ #include +#include +#include #include #include #if defined(__has_include) && __has_include() @@ -1234,7 +1236,7 @@ void DataReaderImpl::configure_deadline_timer_() return deadline_missed(); }, // Park timer with a huge interval (prevents spurious callbacks); we'll arm/cancel explicitly - std::numeric_limits::max() + std::chrono::microseconds::max() ); } @@ -1528,8 +1530,29 @@ LivelinessChangedStatus& DataReaderImpl::update_liveliness_status( const SampleLostStatus& DataReaderImpl::update_sample_lost_status( int32_t sample_lost_since_last_update) { - sample_lost_status_.total_count += sample_lost_since_last_update; - sample_lost_status_.total_count_change += sample_lost_since_last_update; + constexpr int32_t int32_max = std::numeric_limits::max(); + + // Perform the addition in 64-bit space to avoid signed-integer-overflow UB on int32_t + const int32_t prev_total = sample_lost_status_.total_count; + const int64_t new_total = + static_cast(prev_total) + sample_lost_since_last_update; + const int64_t new_change = + static_cast(sample_lost_status_.total_count_change) + sample_lost_since_last_update; + + // Saturate at int32_t max + sample_lost_status_.total_count = + (new_total > int32_max) ? int32_max : static_cast(new_total); + sample_lost_status_.total_count_change = + (new_change > int32_max) ? int32_max : static_cast(new_change); + + // Warn only when the counter reaches the max value + if (prev_total < int32_max && sample_lost_status_.total_count == int32_max) + { + EPROSIMA_LOG_WARNING(DATA_READER, + "SampleLostStatus counter for DataReader " + << guid() << " reached max value. The cumulative count will remain saturated, " + << "but listener notifications for further lost samples will continue."); + } return sample_lost_status_; } diff --git a/src/cpp/rtps/common/SerializedPayload.cpp b/src/cpp/rtps/common/SerializedPayload.cpp new file mode 100644 index 00000000000..98ea4738373 --- /dev/null +++ b/src/cpp/rtps/common/SerializedPayload.cpp @@ -0,0 +1,154 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file SerializedPayload.cpp + */ + +#include + +namespace eprosima { +namespace fastdds { +namespace rtps { + +SerializedPayload_t& SerializedPayload_t::operator = ( + SerializedPayload_t&& other) noexcept +{ + if (this == &other) + { + return *this; + } + + encapsulation = other.encapsulation; + length = other.length; + data = other.data; + max_size = other.max_size; + pos = other.pos; + payload_owner = other.payload_owner; + is_serialized_key = other.is_serialized_key; + + other.encapsulation = CDR_BE; + other.length = 0; + other.data = nullptr; + other.max_size = 0; + other.pos = 0; + other.payload_owner = nullptr; + other.is_serialized_key = false; + + return *this; +} + +SerializedPayload_t::~SerializedPayload_t() +{ + if (payload_owner != nullptr) + { + payload_owner->release_payload(*this); + } + this->empty(); +} + +bool SerializedPayload_t::operator == ( + const SerializedPayload_t& other) const +{ + return ((encapsulation == other.encapsulation) && + (is_serialized_key == other.is_serialized_key) && + (length == other.length) && + (length == 0 || 0 == memcmp(data, other.data, length))); +} + +bool SerializedPayload_t::copy( + const SerializedPayload_t* serData, + bool with_limit) +{ + length = serData->length; + + if (serData->length > max_size) + { + if (with_limit) + { + return false; + } + else + { + this->reserve(serData->length); + } + } + encapsulation = serData->encapsulation; + is_serialized_key = serData->is_serialized_key; + if (length == 0) + { + return true; + } + memcpy(data, serData->data, length); + return true; +} + +bool SerializedPayload_t::reserve_fragmented( + SerializedPayload_t* serData) +{ + length = serData->length; + max_size = serData->length; + encapsulation = serData->encapsulation; + is_serialized_key = serData->is_serialized_key; + data = (octet*)calloc(length, sizeof(octet)); + return true; +} + +void SerializedPayload_t::empty() +{ + assert(payload_owner == nullptr); + + length = 0; + encapsulation = CDR_BE; + max_size = 0; + if (data != nullptr) + { + free(data); + } + data = nullptr; + is_serialized_key = false; +} + +void SerializedPayload_t::reserve( + uint32_t new_size) +{ + if (new_size <= this->max_size) + { + return; + } + if (data == nullptr) + { + data = (octet*)calloc(new_size, sizeof(octet)); + if (!data) + { + throw std::bad_alloc(); + } + } + else + { + void* old_data = data; + data = (octet*)realloc(data, new_size); + if (!data) + { + free(old_data); + throw std::bad_alloc(); + } + memset(data + max_size, 0, (new_size - max_size) * sizeof(octet)); + } + max_size = new_size; +} + +} /* namespace rtps */ +} /* namespace fastdds */ +} /* namespace eprosima */ diff --git a/src/cpp/rtps/history/PoolConfig.h b/src/cpp/rtps/history/PoolConfig.h index 878ce087b9c..f7494d68284 100644 --- a/src/cpp/rtps/history/PoolConfig.h +++ b/src/cpp/rtps/history/PoolConfig.h @@ -19,6 +19,9 @@ #ifndef RTPS_HISTORY_POOLCONFIG_H_ #define RTPS_HISTORY_POOLCONFIG_H_ +#include +#include + #include #include @@ -56,6 +59,24 @@ struct PoolConfig : public BasicPoolConfig //! Maximum number of elements in the pool. Default value is 0, indicating to make allocations until they fail. uint32_t maximum_size; + /** + * Compute reserved + extra in int64_t and clamp to UINT32_MAX, avoiding the signed overflow + * A reserved value <= 0 means "no preallocation" (initial) or "infinite maximum" (max) + * + * @param reserved initial or maximum reserved caches + * @param extra extra caches to be added to the reserved caches + * @return the sum of reserved and extra, clamped to UINT32_MAX, or 0 if reserved is <= 0 + */ + static constexpr uint32_t clamped_reserved_plus_extra( + int32_t reserved, + int32_t extra) noexcept + { + return reserved <= 0 ? 0u : + (static_cast(reserved) + extra >= + static_cast((std::numeric_limits::max)()) ? (std::numeric_limits::max)() : + static_cast(static_cast(reserved) + extra)); + } + /** * Transform a HistoryAttributes object into a PoolConfig * @@ -70,16 +91,10 @@ struct PoolConfig : public BasicPoolConfig { history_attr.memoryPolicy, history_attr.payloadMaxSize, - // Negative or 0 means no preallocation. - // Otherwise, we need to reserve the extra to avoid dynamic allocations after the pools are created. - static_cast( - history_attr.initialReservedCaches <= 0 ? - 0 : history_attr.initialReservedCaches + history_attr.extraReservedCaches), - // Negative or 0 means infinite maximum. - // Otherwise, we need to allow the extra. - static_cast( - history_attr.maximumReservedCaches <= 0 ? - 0 : history_attr.maximumReservedCaches + history_attr.extraReservedCaches) + clamped_reserved_plus_extra( + history_attr.initialReservedCaches, history_attr.extraReservedCaches), + clamped_reserved_plus_extra( + history_attr.maximumReservedCaches, history_attr.extraReservedCaches) }; } diff --git a/src/cpp/rtps/resources/TimedEvent.cpp b/src/cpp/rtps/resources/TimedEvent.cpp index 5b83b1640ce..1401b26f609 100644 --- a/src/cpp/rtps/resources/TimedEvent.cpp +++ b/src/cpp/rtps/resources/TimedEvent.cpp @@ -39,6 +39,17 @@ TimedEvent::TimedEvent( service_.register_timer(impl_); } +TimedEvent::TimedEvent( + ResourceEvent& service, + std::function callback, + std::chrono::microseconds interval) + : service_(service) + , impl_(nullptr) +{ + impl_ = new TimedEventImpl(callback, interval); + service_.register_timer(impl_); +} + TimedEvent::~TimedEvent() { service_.unregister_timer(impl_); diff --git a/src/cpp/rtps/security/SecurityManager.cpp b/src/cpp/rtps/security/SecurityManager.cpp index efba0480fb1..3eb6b06b0c2 100644 --- a/src/cpp/rtps/security/SecurityManager.cpp +++ b/src/cpp/rtps/security/SecurityManager.cpp @@ -326,10 +326,15 @@ bool SecurityManager::init( { crypto_plugin_->set_logger(logging_plugin_, exception); + // When no access control plugin is configured, local_permissions_handle_ is null + NilHandle nil_permissions_handle; + const PermissionsHandle& permissions_handle = (local_permissions_handle_ != nullptr) ? + *local_permissions_handle_ : nil_permissions_handle; + local_participant_crypto_handle_ = crypto_plugin_->cryptokeyfactory()->register_local_participant( *local_identity_handle_, - *local_permissions_handle_, + permissions_handle, participant_properties.properties(), attributes, exception); diff --git a/src/cpp/statistics/fastdds/domain/DomainParticipant.cpp b/src/cpp/statistics/fastdds/domain/DomainParticipant.cpp index a260fac8c29..a3f743db650 100644 --- a/src/cpp/statistics/fastdds/domain/DomainParticipant.cpp +++ b/src/cpp/statistics/fastdds/domain/DomainParticipant.cpp @@ -31,6 +31,12 @@ namespace fastdds { namespace statistics { namespace dds { +DomainParticipant::DomainParticipant( + const eprosima::fastdds::dds::StatusMask& mask) + : eprosima::fastdds::dds::DomainParticipant(mask) +{ +} + ReturnCode_t DomainParticipant::enable_statistics_datawriter( const std::string& topic_name, const eprosima::fastdds::dds::DataWriterQos& dwqos) diff --git a/test/blackbox/common/BlackboxTestsDeadlineQos.cpp b/test/blackbox/common/BlackboxTestsDeadlineQos.cpp index 99517ad887e..8c6ceb02d3e 100644 --- a/test/blackbox/common/BlackboxTestsDeadlineQos.cpp +++ b/test/blackbox/common/BlackboxTestsDeadlineQos.cpp @@ -31,12 +31,14 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; using fastlog = eprosima::fastdds::dds::Log; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class DeadlineQos : public ::testing::TestWithParam { diff --git a/test/blackbox/common/BlackboxTestsDiscovery.cpp b/test/blackbox/common/BlackboxTestsDiscovery.cpp index a11191f494e..72679be3f27 100644 --- a/test/blackbox/common/BlackboxTestsDiscovery.cpp +++ b/test/blackbox/common/BlackboxTestsDiscovery.cpp @@ -46,12 +46,14 @@ using namespace eprosima::fastrtps::rtps; using test_UDPv4Transport = eprosima::fastdds::rtps::test_UDPv4Transport; using test_UDPv4TransportDescriptor = eprosima::fastdds::rtps::test_UDPv4TransportDescriptor; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class Discovery : public testing::TestWithParam { diff --git a/test/blackbox/common/BlackboxTestsLifespanQoS.cpp b/test/blackbox/common/BlackboxTestsLifespanQoS.cpp index d27f72a2656..24a7cab9d7b 100644 --- a/test/blackbox/common/BlackboxTestsLifespanQoS.cpp +++ b/test/blackbox/common/BlackboxTestsLifespanQoS.cpp @@ -27,12 +27,14 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class LifespanQos : public testing::TestWithParam { diff --git a/test/blackbox/common/BlackboxTestsLivelinessQos.cpp b/test/blackbox/common/BlackboxTestsLivelinessQos.cpp index 2f59c960893..b553bd5f73b 100644 --- a/test/blackbox/common/BlackboxTestsLivelinessQos.cpp +++ b/test/blackbox/common/BlackboxTestsLivelinessQos.cpp @@ -32,12 +32,14 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class LivelinessQos : public testing::TestWithParam { diff --git a/test/blackbox/common/BlackboxTestsNetworkConf.cpp b/test/blackbox/common/BlackboxTestsNetworkConf.cpp index 4feb949f050..9384cfe8f4d 100644 --- a/test/blackbox/common/BlackboxTestsNetworkConf.cpp +++ b/test/blackbox/common/BlackboxTestsNetworkConf.cpp @@ -28,10 +28,12 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT }; +} // namespace class NetworkConfig : public testing::TestWithParam> { diff --git a/test/blackbox/common/BlackboxTestsPubSubBasic.cpp b/test/blackbox/common/BlackboxTestsPubSubBasic.cpp index 913991e1b53..819737f17c1 100644 --- a/test/blackbox/common/BlackboxTestsPubSubBasic.cpp +++ b/test/blackbox/common/BlackboxTestsPubSubBasic.cpp @@ -35,12 +35,14 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class PubSubBasic : public testing::TestWithParam> { diff --git a/test/blackbox/common/BlackboxTestsPubSubFragments.cpp b/test/blackbox/common/BlackboxTestsPubSubFragments.cpp index 4200871f920..6284a85e7e7 100644 --- a/test/blackbox/common/BlackboxTestsPubSubFragments.cpp +++ b/test/blackbox/common/BlackboxTestsPubSubFragments.cpp @@ -27,12 +27,14 @@ using namespace eprosima::fastrtps::rtps; using test_UDPv4Transport = eprosima::fastdds::rtps::test_UDPv4Transport; using test_UDPv4TransportDescriptor = eprosima::fastdds::rtps::test_UDPv4TransportDescriptor; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace using test_params = std::tuple; diff --git a/test/blackbox/common/BlackboxTestsPubSubHistory.cpp b/test/blackbox/common/BlackboxTestsPubSubHistory.cpp index b0f047e95dc..bf420cd8301 100644 --- a/test/blackbox/common/BlackboxTestsPubSubHistory.cpp +++ b/test/blackbox/common/BlackboxTestsPubSubHistory.cpp @@ -28,12 +28,14 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastdds::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace using test_params = std::tuple; diff --git a/test/blackbox/common/BlackboxTestsRealtimeAllocations.cpp b/test/blackbox/common/BlackboxTestsRealtimeAllocations.cpp index 1ccebb749a6..57358d7ea79 100644 --- a/test/blackbox/common/BlackboxTestsRealtimeAllocations.cpp +++ b/test/blackbox/common/BlackboxTestsRealtimeAllocations.cpp @@ -23,12 +23,14 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class RealtimeAllocations : public testing::TestWithParam { diff --git a/test/blackbox/common/BlackboxTestsSecurity.cpp b/test/blackbox/common/BlackboxTestsSecurity.cpp index fe445f3ffc1..bb2262ca418 100644 --- a/test/blackbox/common/BlackboxTestsSecurity.cpp +++ b/test/blackbox/common/BlackboxTestsSecurity.cpp @@ -49,6 +49,7 @@ using test_UDPv4TransportDescriptor = eprosima::fastdds::rtps::test_UDPv4Transpo using DatagramInjectionTransport = eprosima::fastdds::rtps::DatagramInjectionTransport; using DatagramInjectionTransportDescriptor = eprosima::fastdds::rtps::DatagramInjectionTransportDescriptor; +namespace { enum communication_type { TRANSPORT, @@ -60,6 +61,7 @@ enum reliability TEST_BEST_EFFORT, TEST_RELIABLE }; +} // namespace // A LogConsumer that just counts the number of entries consumed struct TestConsumer : public eprosima::fastdds::dds::LogConsumer diff --git a/test/blackbox/common/BlackboxTestsTransportTCP.cpp b/test/blackbox/common/BlackboxTestsTransportTCP.cpp index 3958277dedc..5306cb65c7c 100644 --- a/test/blackbox/common/BlackboxTestsTransportTCP.cpp +++ b/test/blackbox/common/BlackboxTestsTransportTCP.cpp @@ -35,10 +35,12 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT }; +} // namespace class TransportTCP : public testing::TestWithParam> { diff --git a/test/blackbox/common/BlackboxTestsTransportUDP.cpp b/test/blackbox/common/BlackboxTestsTransportUDP.cpp index ac9cf8f8c00..5db056a50ab 100644 --- a/test/blackbox/common/BlackboxTestsTransportUDP.cpp +++ b/test/blackbox/common/BlackboxTestsTransportUDP.cpp @@ -33,10 +33,12 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT }; +} // namespace class TransportUDP : public testing::TestWithParam> { @@ -1177,6 +1179,100 @@ TEST(TransportUDP, MaliciousHeartbeatBigStart) EXPECT_LT(end - start, std::chrono::seconds(15)); } +// Regression test issue #24365: a sequence-number gap larger than INT32_MAX between two DATA submessages +// must not overflow DataReaderImpl::SampleLostStatus::total_count. The expected behavior is saturation at INT32_MAX. +TEST(TransportUDP, MaliciousDataLargeSequenceNumberGap) +{ + auto udp_transport = std::make_shared(); + + PubSubWriter writer(TEST_TOPIC_NAME); + PubSubReader reader(TEST_TOPIC_NAME); + + struct MaliciousData + { + std::array rtps_id{ {'R', 'T', 'P', 'S'} }; + std::array protocol_version{ {2, 3} }; + std::array vendor_id{ {0x01, 0x0F} }; + GuidPrefix_t sender_prefix{}; + + struct DataSubMsg + { + uint8_t submessage_id = 0x15; // DATA +#if FASTDDS_IS_BIG_ENDIAN_TARGET + uint8_t flags = 0x04; // D=1 +#else + uint8_t flags = 0x05; // E=1, D=1 +#endif // FASTDDS_IS_BIG_ENDIAN_TARGET + uint16_t octets_to_next_header = 24; + uint16_t extra_flags = 0; + uint16_t octets_to_inline_qos = 16; + EntityId_t reader_id{}; + EntityId_t writer_id{}; + SequenceNumber_t sn{ 0, 1u }; + // Minimal serialized payload: just the CDR_LE encapsulation header. + std::array serialized_payload{ {0x00, 0x01, 0x00, 0x00} }; + } + data; + }; + + UDPMessageSender fake_msg_sender; + + reader.disable_builtin_transport().add_user_transport_to_pparams(udp_transport) + .history_depth(10) + .reliability(eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS); + writer.history_depth(10).reliability(eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS); + + Locator_t reader_locator; + ASSERT_TRUE(IPLocator::setIPv4(reader_locator, "127.0.0.1")); + reader_locator.port = global_port; + reader.add_to_unicast_locator_list("127.0.0.1", global_port); + + reader.init(); + ASSERT_TRUE(reader.isInitialized()); + writer.init(); + ASSERT_TRUE(writer.isInitialized()); + + reader.wait_discovery(); + writer.wait_discovery(); + + auto send_data_with_sn = [&](const SequenceNumber_t& sn) + { + auto writer_guid = writer.datawriter_guid(); + + MaliciousData malicious_packet{}; + malicious_packet.sender_prefix = writer_guid.guidPrefix; + malicious_packet.data.writer_id = writer_guid.entityId; + malicious_packet.data.reader_id = reader.datareader_guid().entityId; + malicious_packet.data.sn = sn; + + CDRMessage_t msg(0); + uint32_t msg_len = static_cast(sizeof(malicious_packet)); + msg.init(reinterpret_cast(&malicious_packet), msg_len); + msg.length = msg_len; + msg.pos = msg_len; + fake_msg_sender.send(msg, reader_locator); + }; + + // Packet 1: establish baseline (SN = 1). + send_data_with_sn(SequenceNumber_t{ 0, 1u }); + // Packet 2: small gap (SN = 3) -> total_count becomes 1. + send_data_with_sn(SequenceNumber_t{ 0, 3u }); + // Packet 3: SN = 0x80000004 -> per-event lost saturates at INT32_MAX. + // Without saturation in update_sample_lost_status, total_count = 1 + INT32_MAX overflows. + send_data_with_sn(SequenceNumber_t{ 0, 0x80000004u }); + + // Allow the reader thread to drain the three injected packets. + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // If the previous step did not abort the process under UBSan, the counter must remain + // non-negative (no wrap) and within int32_t range (saturated, not overflowed). + // auto status = reader.get_sample_lost_status(); + // EXPECT_GE(status.total_count, 0); + // EXPECT_LE(status.total_count, std::numeric_limits::max()); + + reader.destroy(); +} + // Test for ==operator UDPTransportDescriptor is not required as it is an abstract class and in UDPv4 is same method // Test for copy UDPTransportDescriptor is not required as it is an abstract class and in UDPv4 is same method @@ -1368,4 +1464,3 @@ GTEST_INSTANTIATE_TEST_MACRO(TransportUDP, } }); - diff --git a/test/blackbox/common/BlackboxTestsVolatile.cpp b/test/blackbox/common/BlackboxTestsVolatile.cpp index 6351d0baea1..f7e82fd9ae1 100644 --- a/test/blackbox/common/BlackboxTestsVolatile.cpp +++ b/test/blackbox/common/BlackboxTestsVolatile.cpp @@ -28,12 +28,14 @@ using namespace eprosima::fastrtps; using test_UDPv4Transport = eprosima::fastdds::rtps::test_UDPv4Transport; using test_UDPv4TransportDescriptor = eprosima::fastdds::rtps::test_UDPv4TransportDescriptor; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class Volatile : public testing::TestWithParam { diff --git a/test/blackbox/common/DDSBlackboxTestsDataReader.cpp b/test/blackbox/common/DDSBlackboxTestsDataReader.cpp index 724ce4aed43..14919903d5b 100644 --- a/test/blackbox/common/DDSBlackboxTestsDataReader.cpp +++ b/test/blackbox/common/DDSBlackboxTestsDataReader.cpp @@ -43,12 +43,14 @@ using namespace eprosima::fastrtps::rtps; std::string("incompatible_") + TEST_TOPIC_NAME) +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class DDSDataReader : public testing::TestWithParam { @@ -690,4 +692,3 @@ GTEST_INSTANTIATE_TEST_MACRO(DDSDataReader, } }); - diff --git a/test/blackbox/common/DDSBlackboxTestsDataWriter.cpp b/test/blackbox/common/DDSBlackboxTestsDataWriter.cpp index 14444fe20fe..e4d3f0f6485 100644 --- a/test/blackbox/common/DDSBlackboxTestsDataWriter.cpp +++ b/test/blackbox/common/DDSBlackboxTestsDataWriter.cpp @@ -41,12 +41,14 @@ using namespace eprosima::fastrtps; using test_UDPv4Transport = eprosima::fastdds::rtps::test_UDPv4Transport; using test_UDPv4TransportDescriptor = eprosima::fastdds::rtps::test_UDPv4TransportDescriptor; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class DDSDataWriter : public testing::TestWithParam { diff --git a/test/blackbox/common/DDSBlackboxTestsListeners.cpp b/test/blackbox/common/DDSBlackboxTestsListeners.cpp index 4ace7106557..b44cea3fc6b 100644 --- a/test/blackbox/common/DDSBlackboxTestsListeners.cpp +++ b/test/blackbox/common/DDSBlackboxTestsListeners.cpp @@ -35,12 +35,14 @@ using test_UDPv4TransportDescriptor = eprosima::fastdds::rtps::test_UDPv4Transpo std::string("incompatible_") + TEST_TOPIC_NAME) +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class DDSStatus : public testing::TestWithParam { diff --git a/test/blackbox/common/DDSBlackboxTestsMonitorService.cpp b/test/blackbox/common/DDSBlackboxTestsMonitorService.cpp index 1f42ce96647..db531fd82b5 100644 --- a/test/blackbox/common/DDSBlackboxTestsMonitorService.cpp +++ b/test/blackbox/common/DDSBlackboxTestsMonitorService.cpp @@ -33,12 +33,14 @@ using namespace eprosima::fastdds::dds; using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace using MonitorServiceType = eprosima::fastdds::statistics::MonitorServiceStatusDataPubSubType; using GUIDList = std::vector; diff --git a/test/blackbox/common/DDSBlackboxTestsOwnershipQos.cpp b/test/blackbox/common/DDSBlackboxTestsOwnershipQos.cpp index 49b00a2f2de..a50627f6e8c 100644 --- a/test/blackbox/common/DDSBlackboxTestsOwnershipQos.cpp +++ b/test/blackbox/common/DDSBlackboxTestsOwnershipQos.cpp @@ -26,12 +26,14 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class OwnershipQos : public testing::TestWithParam { diff --git a/test/blackbox/common/DDSBlackboxTestsPersistence.cpp b/test/blackbox/common/DDSBlackboxTestsPersistence.cpp index 801d9d883ff..890392c4eb4 100644 --- a/test/blackbox/common/DDSBlackboxTestsPersistence.cpp +++ b/test/blackbox/common/DDSBlackboxTestsPersistence.cpp @@ -28,12 +28,14 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class PersistenceLargeData : public testing::TestWithParam { diff --git a/test/blackbox/common/DDSBlackboxTestsPersistenceGuid.cpp b/test/blackbox/common/DDSBlackboxTestsPersistenceGuid.cpp index 7a4cfac6029..cd3ff101903 100644 --- a/test/blackbox/common/DDSBlackboxTestsPersistenceGuid.cpp +++ b/test/blackbox/common/DDSBlackboxTestsPersistenceGuid.cpp @@ -32,12 +32,14 @@ using namespace eprosima::fastrtps::rtps; using namespace eprosima::fastdds::dds; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class PersistenceGuid : public ::testing::TestWithParam { diff --git a/test/blackbox/common/DDSBlackboxTestsPropertyQos.cpp b/test/blackbox/common/DDSBlackboxTestsPropertyQos.cpp index 832b8ef1eba..3520898a5a9 100644 --- a/test/blackbox/common/DDSBlackboxTestsPropertyQos.cpp +++ b/test/blackbox/common/DDSBlackboxTestsPropertyQos.cpp @@ -33,12 +33,14 @@ const std::string INTERNAL_PROPERTY_VALUE = "Other Value"; using namespace eprosima::fastrtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class PropertyQos : public testing::TestWithParam { diff --git a/test/blackbox/common/DDSBlackboxTestsTransportSHMUDP.cpp b/test/blackbox/common/DDSBlackboxTestsTransportSHMUDP.cpp index 20cc3129778..a42f82b2282 100644 --- a/test/blackbox/common/DDSBlackboxTestsTransportSHMUDP.cpp +++ b/test/blackbox/common/DDSBlackboxTestsTransportSHMUDP.cpp @@ -36,12 +36,14 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; using test_UDPv4Transport = eprosima::fastdds::rtps::test_UDPv4Transport; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class SHMUDP : public testing::TestWithParam { diff --git a/test/blackbox/common/DDSBlackboxTestsUserDataQos.cpp b/test/blackbox/common/DDSBlackboxTestsUserDataQos.cpp index 34ea870eda6..c531ae95c69 100644 --- a/test/blackbox/common/DDSBlackboxTestsUserDataQos.cpp +++ b/test/blackbox/common/DDSBlackboxTestsUserDataQos.cpp @@ -25,12 +25,14 @@ using namespace eprosima::fastrtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS, DATASHARING }; +} // namespace class UserDataQos : public testing::TestWithParam { diff --git a/test/blackbox/common/RTPSBlackboxTestsBasic.cpp b/test/blackbox/common/RTPSBlackboxTestsBasic.cpp index 409fdc3dff8..5fd8fc853a4 100644 --- a/test/blackbox/common/RTPSBlackboxTestsBasic.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsBasic.cpp @@ -40,11 +40,13 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; using test_UDPv4Transport = eprosima::fastdds::rtps::test_UDPv4Transport; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS }; +} // namespace class RTPS : public testing::TestWithParam { diff --git a/test/blackbox/common/RTPSBlackboxTestsDiscovery.cpp b/test/blackbox/common/RTPSBlackboxTestsDiscovery.cpp index 84befaae27a..c2afc5e79c9 100644 --- a/test/blackbox/common/RTPSBlackboxTestsDiscovery.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsDiscovery.cpp @@ -24,11 +24,13 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS }; +} // namespace class RTPSDiscovery : public testing::TestWithParam { diff --git a/test/blackbox/common/RTPSBlackboxTestsPersistence.cpp b/test/blackbox/common/RTPSBlackboxTestsPersistence.cpp index eaa9ce59e64..737e0943b5a 100644 --- a/test/blackbox/common/RTPSBlackboxTestsPersistence.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsPersistence.cpp @@ -30,11 +30,13 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS }; +} // namespace class Persistence : public ::testing::TestWithParam { diff --git a/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp b/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp index 43c8b63fddb..d836304e571 100644 --- a/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp @@ -30,11 +30,13 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS }; +} // namespace class PersistenceGuid : public ::testing::TestWithParam { diff --git a/test/blackbox/common/RTPSBlackboxTestsPools.cpp b/test/blackbox/common/RTPSBlackboxTestsPools.cpp index d1a5d130dc3..c312f556884 100644 --- a/test/blackbox/common/RTPSBlackboxTestsPools.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsPools.cpp @@ -26,11 +26,13 @@ using namespace eprosima::fastrtps; using namespace eprosima::fastrtps::rtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS }; +} // namespace class RTPSCustomPools : public testing::TestWithParam { diff --git a/test/blackbox/common/RTPSBlackboxTestsReader.cpp b/test/blackbox/common/RTPSBlackboxTestsReader.cpp new file mode 100644 index 00000000000..0695956c544 --- /dev/null +++ b/test/blackbox/common/RTPSBlackboxTestsReader.cpp @@ -0,0 +1,158 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "BlackboxTests.hpp" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "RTPSWithRegistrationReader.hpp" +#include "RTPSWithRegistrationWriter.hpp" + +using namespace eprosima::fastdds; +using namespace eprosima::fastdds::rtps; + +namespace { +enum communication_type +{ + TRANSPORT, + INTRAPROCESS +}; +} // namespace + +class RTPSReaderTests : public testing::TestWithParam +{ +public: + + void SetUp() override + { + eprosima::fastdds::LibrarySettings library_settings; + switch (GetParam()) + { + case INTRAPROCESS: + library_settings.intraprocess_delivery = eprosima::fastdds::IntraprocessDeliveryType::INTRAPROCESS_FULL; + eprosima::fastdds::rtps::RTPSDomain::set_library_settings(library_settings); + break; + case TRANSPORT: + default: + break; + } + } + + void TearDown() override + { + eprosima::fastdds::LibrarySettings library_settings; + switch (GetParam()) + { + case INTRAPROCESS: + library_settings.intraprocess_delivery = eprosima::fastdds::IntraprocessDeliveryType::INTRAPROCESS_OFF; + eprosima::fastdds::rtps::RTPSDomain::set_library_settings(library_settings); + break; + case TRANSPORT: + default: + break; + } + } + +}; + +/** + * @test RTPS-READER-API-MWG-01 + * + * matched_writers_guids() must return true with empty list when the entitiy is not matched. + * matched_writers_guids() must return true with a correct list when the entitiy is matched. + */ +TEST_P(RTPSReaderTests, rtpsreader_matched_writers_guids) +{ + RTPSWithRegistrationReader reader(TEST_TOPIC_NAME); + RTPSWithRegistrationWriter writer(TEST_TOPIC_NAME); + + reader.reliability(eprosima::fastdds::rtps::RELIABLE) + .init(); + + writer.reliability(eprosima::fastdds::rtps::BEST_EFFORT) + .init(); + + ASSERT_TRUE(reader.isInitialized()); + ASSERT_TRUE(writer.isInitialized()); + + // Expect not to discover + reader.wait_discovery(std::chrono::seconds(1)); + ASSERT_FALSE(reader.get_matched()); + + std::vector matched_guids; + auto& native_rtps_reader = reader.get_native_reader(); + ASSERT_TRUE(native_rtps_reader.matched_writers_guids(matched_guids)); + ASSERT_TRUE(matched_guids.empty()); + + writer.destroy(); + reader.wait_undiscovery(); + + const size_t num_matched_writers = 3; + std::vector>> writers; + std::vector expected_matched_guids; + + writers.reserve(num_matched_writers); + expected_matched_guids.reserve(num_matched_writers); + + for (size_t i = 0; i < num_matched_writers; ++i) + { + writers.emplace_back(new RTPSWithRegistrationWriter(TEST_TOPIC_NAME)); + writers.back()->init(); + expected_matched_guids.emplace_back(writers.back()->guid()); + } + + reader.wait_discovery(num_matched_writers, std::chrono::seconds::zero()); + ASSERT_EQ(num_matched_writers, reader.get_matched()); + native_rtps_reader.matched_writers_guids(matched_guids); + ASSERT_EQ(expected_matched_guids.size(), matched_guids.size()); + ASSERT_TRUE(std::is_permutation(expected_matched_guids.begin(), expected_matched_guids.end(), + matched_guids.begin())); +} + +#ifdef INSTANTIATE_TEST_SUITE_P +#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_SUITE_P(x, y, z, w) +#else +#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_CASE_P(x, y, z, w) +#endif // ifdef INSTANTIATE_TEST_SUITE_P + +GTEST_INSTANTIATE_TEST_MACRO(RTPSReaderTests, + RTPSReaderTests, + testing::Values(TRANSPORT, INTRAPROCESS), + [](const testing::TestParamInfo& info) + { + switch (info.param) + { + case INTRAPROCESS: + return "Intraprocess"; + break; + case TRANSPORT: + default: + return "Transport"; + } + + }); diff --git a/test/blackbox/common/RTPSBlackboxTestsVolatile.cpp b/test/blackbox/common/RTPSBlackboxTestsVolatile.cpp index d3981ab4575..a211f525f86 100644 --- a/test/blackbox/common/RTPSBlackboxTestsVolatile.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsVolatile.cpp @@ -26,11 +26,13 @@ using namespace eprosima::fastrtps; +namespace { enum communication_type { TRANSPORT, INTRAPROCESS }; +} // namespace class Volatile : public testing::TestWithParam { diff --git a/test/blackbox/common/RTPSBlackboxTestsWriter.cpp b/test/blackbox/common/RTPSBlackboxTestsWriter.cpp new file mode 100644 index 00000000000..c67cb7a7e25 --- /dev/null +++ b/test/blackbox/common/RTPSBlackboxTestsWriter.cpp @@ -0,0 +1,158 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "BlackboxTests.hpp" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "RTPSWithRegistrationReader.hpp" +#include "RTPSWithRegistrationWriter.hpp" + +using namespace eprosima::fastdds; +using namespace eprosima::fastdds::rtps; + +namespace { +enum communication_type +{ + TRANSPORT, + INTRAPROCESS +}; +} // namespace + +class RTPSWriterTests : public testing::TestWithParam +{ +public: + + void SetUp() override + { + eprosima::fastdds::LibrarySettings library_settings; + switch (GetParam()) + { + case INTRAPROCESS: + library_settings.intraprocess_delivery = eprosima::fastdds::IntraprocessDeliveryType::INTRAPROCESS_FULL; + eprosima::fastdds::rtps::RTPSDomain::set_library_settings(library_settings); + break; + case TRANSPORT: + default: + break; + } + } + + void TearDown() override + { + eprosima::fastdds::LibrarySettings library_settings; + switch (GetParam()) + { + case INTRAPROCESS: + library_settings.intraprocess_delivery = eprosima::fastdds::IntraprocessDeliveryType::INTRAPROCESS_OFF; + eprosima::fastdds::rtps::RTPSDomain::set_library_settings(library_settings); + break; + case TRANSPORT: + default: + break; + } + } + +}; + +/** + * @test RTPS-WRITER-API-MRG-01 + * + * matched_readers_guids() must return true with empty list when the entitiy is not matched. + * matched_readers_guids() must return true with a correct list when the entitiy is matched. + */ +TEST_P(RTPSWriterTests, rtpswriter_matched_readers_guids) +{ + RTPSWithRegistrationWriter writer(TEST_TOPIC_NAME); + RTPSWithRegistrationReader reader(TEST_TOPIC_NAME); + + writer.reliability(eprosima::fastdds::rtps::BEST_EFFORT) + .init(); + + reader.reliability(eprosima::fastdds::rtps::RELIABLE) + .init(); + + ASSERT_TRUE(writer.isInitialized()); + ASSERT_TRUE(reader.isInitialized()); + + // Expect not to discover + writer.wait_discovery(std::chrono::seconds(1)); + ASSERT_FALSE(writer.get_matched()); + + std::vector matched_guids; + auto& native_rtps_writer = writer.get_native_writer(); + ASSERT_TRUE(native_rtps_writer.matched_readers_guids(matched_guids)); + ASSERT_TRUE(matched_guids.empty()); + + reader.destroy(); + writer.wait_undiscovery(); + + const size_t num_matched_readers = 3; + std::vector>> readers; + std::vector expected_matched_guids; + + readers.reserve(num_matched_readers); + expected_matched_guids.reserve(num_matched_readers); + + for (size_t i = 0; i < num_matched_readers; ++i) + { + readers.emplace_back(new RTPSWithRegistrationReader(TEST_TOPIC_NAME)); + readers.back()->init(); + expected_matched_guids.emplace_back(readers.back()->guid()); + } + + writer.wait_discovery(num_matched_readers, std::chrono::seconds::zero()); + ASSERT_EQ(num_matched_readers, writer.get_matched()); + native_rtps_writer.matched_readers_guids(matched_guids); + ASSERT_EQ(expected_matched_guids.size(), matched_guids.size()); + ASSERT_TRUE(std::is_permutation(expected_matched_guids.begin(), expected_matched_guids.end(), + matched_guids.begin())); +} + +#ifdef INSTANTIATE_TEST_SUITE_P +#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_SUITE_P(x, y, z, w) +#else +#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_CASE_P(x, y, z, w) +#endif // ifdef INSTANTIATE_TEST_SUITE_P + +GTEST_INSTANTIATE_TEST_MACRO(RTPSWriterTests, + RTPSWriterTests, + testing::Values(TRANSPORT, INTRAPROCESS), + [](const testing::TestParamInfo& info) + { + switch (info.param) + { + case INTRAPROCESS: + return "Intraprocess"; + break; + case TRANSPORT: + default: + return "Transport"; + } + + }); diff --git a/test/mock/rtps/PublisherHistory/fastdds/publisher/DataWriterHistory.hpp b/test/mock/rtps/PublisherHistory/fastdds/publisher/DataWriterHistory.hpp index 28f4febbc98..6b3cbb9b90d 100644 --- a/test/mock/rtps/PublisherHistory/fastdds/publisher/DataWriterHistory.hpp +++ b/test/mock/rtps/PublisherHistory/fastdds/publisher/DataWriterHistory.hpp @@ -91,17 +91,17 @@ class DataWriterHistory : public WriterHistory { if (resource_limited_qos_.max_samples <= 0) { - resource_limited_qos_.max_samples = std::numeric_limits::max(); + resource_limited_qos_.max_samples = -1; } if (resource_limited_qos_.max_instances <= 0) { - resource_limited_qos_.max_instances = std::numeric_limits::max(); + resource_limited_qos_.max_instances = -1; } if (resource_limited_qos_.max_samples_per_instance <= 0) { - resource_limited_qos_.max_samples_per_instance = std::numeric_limits::max(); + resource_limited_qos_.max_samples_per_instance = -1; } } diff --git a/test/mock/rtps/SharedSecretHandle/rtps/security/common/SharedSecretHandle.h b/test/mock/rtps/SharedSecretHandle/rtps/security/common/SharedSecretHandle.h new file mode 100644 index 00000000000..0c93faabe1f --- /dev/null +++ b/test/mock/rtps/SharedSecretHandle/rtps/security/common/SharedSecretHandle.h @@ -0,0 +1,176 @@ +// Copyright 2026 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file SharedSecretHandle.h (test mock) + * + * Drop-in replacement for the production SharedSecretHandle.h. The only + * difference is the SharedSecretHandle typedef: it instantiates HandleImpl + * with MockAuthenticationPlugin instead of PKIDH, so it matches the dynamic + * type of the SharedSecret-bearing handles created by the test (see + * test/mock/rtps/SecurityPluginFactory/rtps/security/MockAuthenticationPlugin.h). + * + * Without this substitution the production translation unit narrows to a + * different HandleImpl instantiation than the test creates; + * the two share layout but have distinct vtables, so the next virtual call + * (e.g. nil()) trips ubsan with a vptr/type mismatch. + */ +#ifndef _FASTDDS_RTPS_SECURITY_COMMON_SHAREDSECRETHANDLE_H_ +#define _FASTDDS_RTPS_SECURITY_COMMON_SHAREDSECRETHANDLE_H_ + +#include + +#include +#include + +namespace eprosima { +namespace fastdds { +namespace rtps { +namespace security { + +class SharedSecret +{ +public: + + class BinaryData + { + public: + + BinaryData() + { + } + + BinaryData( + const BinaryData& data) + : name_(data.name_) + , value_(data.value_) + { + } + + BinaryData( + BinaryData&& data) + : name_(std::move(data.name_)) + , value_(std::move(data.value_)) + { + } + + BinaryData( + const std::string& name, + const std::vector& value) + : name_(name) + , value_(value) + { + } + + BinaryData( + std::string&& name, + std::vector&& value) + : name_(std::move(name)) + , value_(std::move(value)) + { + } + + BinaryData& operator =( + const BinaryData& data) + { + name_ = data.name_; + value_ = data.value_; + return *this; + } + + BinaryData& operator =( + BinaryData&& data) + { + name_ = std::move(data.name_); + value_ = std::move(data.value_); + return *this; + } + + void name( + const std::string& name) + { + name_ = name; + } + + void name( + std::string&& name) + { + name_ = std::move(name); + } + + const std::string& name() const + { + return name_; + } + + std::string& name() + { + return name_; + } + + void value( + const std::vector& value) + { + value_ = value; + } + + void value( + std::vector&& value) + { + value_ = std::move(value); + } + + const std::vector& value() const + { + return value_; + } + + std::vector& value() + { + return value_; + } + + private: + + std::string name_; + + std::vector value_; + }; + + static const char* const class_id_; + + std::vector data_; +}; + +// Forward declaration is enough. The friend declaration inside HandleImpl +// only requires the elaborated name. +class MockAuthenticationPlugin; + +typedef HandleImpl SharedSecretHandle; + +class SharedSecretHelper +{ +public: + + static const std::vector* find_data_value( + const SecretHandle& sharedsecret, + const std::string& name); +}; + +} //namespace security +} //namespace rtps +} //namespace fastdds +} //namespace eprosima + +#endif // _FASTDDS_RTPS_SECURITY_COMMON_SHAREDSECRETHANDLE_H_ diff --git a/test/mock/rtps/TimedEvent/fastdds/rtps/resources/TimedEvent.h b/test/mock/rtps/TimedEvent/fastdds/rtps/resources/TimedEvent.h index 29e01813ecb..b7e99bda297 100644 --- a/test/mock/rtps/TimedEvent/fastdds/rtps/resources/TimedEvent.h +++ b/test/mock/rtps/TimedEvent/fastdds/rtps/resources/TimedEvent.h @@ -38,6 +38,13 @@ class TimedEvent { } + TimedEvent( + ResourceEvent&, + std::function, + std::chrono::microseconds) + { + } + MOCK_METHOD0(restart_timer, void()); MOCK_METHOD1(restart_timer, void(const std::chrono::steady_clock::time_point& timeout)); MOCK_METHOD0(cancel_timer, void()); @@ -53,4 +60,3 @@ class TimedEvent } // namespace eprosima #endif // _FASTDDS_RTPS_RESOURCES_TIMEDEVENT_H_ - diff --git a/test/performance/latency/LatencyTestPublisher.cpp b/test/performance/latency/LatencyTestPublisher.cpp index 1429814eb2e..ba9a4653cfd 100644 --- a/test/performance/latency/LatencyTestPublisher.cpp +++ b/test/performance/latency/LatencyTestPublisher.cpp @@ -944,8 +944,11 @@ void LatencyTestPublisher::analyze_times( stats.received_ = received_count_ - 1; // Because we are not counting the first one. stats.minimum_ = *min_element(times_.begin(), times_.end()); stats.maximum_ = *max_element(times_.begin(), times_.end()); - stats.mean_ = accumulate(times_.begin(), times_.end(), - std::chrono::duration(0)).count() / times_.size(); + if (times_.size() > 0) + { + stats.mean_ = accumulate(times_.begin(), times_.end(), + std::chrono::duration(0)).count() / times_.size(); + } double aux_stdev = 0; for (std::vector>::iterator tit = times_.begin(); tit != times_.end(); @@ -953,7 +956,10 @@ void LatencyTestPublisher::analyze_times( { aux_stdev += pow(((*tit).count() - stats.mean_), 2); } - aux_stdev = sqrt(aux_stdev / times_.size()); + if (times_.size() > 0) + { + aux_stdev = sqrt(aux_stdev / times_.size()); + } stats.stdev_ = aux_stdev; /* Percentiles */ diff --git a/test/unittest/dds/participant/ParticipantTests.cpp b/test/unittest/dds/participant/ParticipantTests.cpp index 8ac0281faaa..413b4e790ad 100644 --- a/test/unittest/dds/participant/ParticipantTests.cpp +++ b/test/unittest/dds/participant/ParticipantTests.cpp @@ -688,27 +688,35 @@ TEST(ParticipantTests, ChangePSMDomainParticipantQos) } -class DomainParticipantTest : public DomainParticipant -{ -public: +namespace { + +using DomainParticipantImplPtr = DomainParticipantImpl * DomainParticipant::*; + +DomainParticipantImplPtr get_domain_participant_impl_ptr(); - const DomainParticipantImpl* get_impl() const +template +struct DomainParticipantImplAccessor +{ + friend DomainParticipantImplPtr get_domain_participant_impl_ptr() { - return impl_; + return P; } }; +template struct DomainParticipantImplAccessor<&DomainParticipant::impl_>; + +} // namespace + fastrtps::rtps::RTPSParticipantAttributes get_rtps_attributes( const DomainParticipant* participant) { - const DomainParticipantTest* participant_test = static_cast(participant); - EXPECT_NE(nullptr, participant_test); - if (participant_test == nullptr) + EXPECT_NE(nullptr, participant); + if (participant == nullptr) { return {}; } - const DomainParticipantImpl* participant_impl = participant_test->get_impl(); + const DomainParticipantImpl* participant_impl = participant->*get_domain_participant_impl_ptr(); EXPECT_NE(nullptr, participant_impl); if (participant_impl == nullptr) { diff --git a/test/unittest/dds/publisher/DataWriterTests.cpp b/test/unittest/dds/publisher/DataWriterTests.cpp index 6994ef1c5aa..862fe970808 100644 --- a/test/unittest/dds/publisher/DataWriterTests.cpp +++ b/test/unittest/dds/publisher/DataWriterTests.cpp @@ -1954,28 +1954,44 @@ TEST(DataWriterTests, LoanNegativeTests) ASSERT_TRUE(DomainParticipantFactory::get_instance()->delete_participant(participant) == ReturnCode_t::RETCODE_OK); } -class DataWriterTest : public DataWriter -{ -public: +namespace { + +// Accessor to DataWriterImpl from DataWriter +using DataWriterImplPtr = DataWriterImpl * DataWriter::*; - DataWriterImpl* get_impl() const +DataWriterImplPtr get_datawriter_impl_ptr(); + +template +struct DataWriterImplAccessor +{ + friend DataWriterImplPtr get_datawriter_impl_ptr() { - return impl_; + return P; } }; -class DataWriterImplTest : public DataWriterImpl -{ -public: +template struct DataWriterImplAccessor<&DataWriter::impl_>; + +// Accessor to DataWriterHistory unique ptr from DataWriterImpl +using DataWriterHistoryPtr = std::unique_ptr DataWriterImpl::*; + +DataWriterHistoryPtr get_datawriter_history_ptr(); - DataWriterHistory* get_history() +template +struct DataWriterHistoryAccessor +{ + friend DataWriterHistoryPtr get_datawriter_history_ptr() { - return &history_; + return P; } }; +template struct DataWriterHistoryAccessor<&DataWriterImpl::history_>; + +} // namespace + /** * This test checks instance wait_for_acknowledgements API */ @@ -2036,14 +2052,11 @@ TEST(DataWriterTests, InstanceWaitForAcknowledgement) datawriter->get_instance_handle(), max_wait)); #endif // NDEBUG - // Access PublisherHistory - DataWriterTest* instance_datawriter_test = static_cast(instance_datawriter); - ASSERT_NE(nullptr, instance_datawriter_test); - DataWriterImpl* datawriter_impl = instance_datawriter_test->get_impl(); + // Access DataWriterHistory + DataWriterImpl* datawriter_impl = instance_datawriter->*get_datawriter_impl_ptr(); ASSERT_NE(nullptr, datawriter_impl); - DataWriterImplTest* datawriter_impl_test = static_cast(datawriter_impl); - ASSERT_NE(nullptr, datawriter_impl_test); - auto history = datawriter_impl_test->get_history(); + DataWriterHistory* history = (datawriter_impl->*get_datawriter_history_ptr()).get(); + ASSERT_NE(nullptr, history); // 5. Calling wait_for_acknowledgments in a keyed topic with HANDLE_NIL returns // RETCODE_OK diff --git a/test/unittest/dds/status/ListenerTests.cpp b/test/unittest/dds/status/ListenerTests.cpp index 61afbb40dcf..84f5cb15fc8 100644 --- a/test/unittest/dds/status/ListenerTests.cpp +++ b/test/unittest/dds/status/ListenerTests.cpp @@ -37,6 +37,10 @@ #include #include +#include +#include +#include + using ::testing::StrictMock; using ::testing::NiceMock; @@ -112,9 +116,7 @@ class RTPSWriterMock : public eprosima::fastrtps::rtps::RTPSWriter { public: - RTPSWriterMock() - { - } + RTPSWriterMock() = default; virtual ~RTPSWriterMock() = default; @@ -553,6 +555,10 @@ class UserListeners : public ::testing::Test RTPSDomain::writer_ = &writer_mock_; RTPSDomain::reader_ = &reader_mock_; + // BaseWriter::get_participant_impl() must return non-null; some code + // paths (e.g. get_publication_builtin_topic_data) assert on it. + writer_mock_.mp_RTPSParticipant = &participant_impl_mock_; + // Create the DDS entities with the user listeners participant_ = DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT, @@ -603,6 +609,7 @@ class UserListeners : public ::testing::Test NiceMock participant_mock_; NiceMock writer_mock_; NiceMock reader_mock_; + eprosima::fastdds::rtps::RTPSParticipantImpl participant_impl_mock_; // User listeners are strick, we want to track unexpected calls StrictMock participant_listener_; diff --git a/test/unittest/rtps/discovery/CMakeLists.txt b/test/unittest/rtps/discovery/CMakeLists.txt index 7330c455a85..52c840dd860 100644 --- a/test/unittest/rtps/discovery/CMakeLists.txt +++ b/test/unittest/rtps/discovery/CMakeLists.txt @@ -121,6 +121,8 @@ set(TCPTransportInterface_SOURCE ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResource.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResourceBasic.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPTransportInterface.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv4Transport.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv6Transport.cpp ) if(TLS_FOUND) set(TCPTransportInterface_SOURCE diff --git a/test/unittest/rtps/writer/CMakeLists.txt b/test/unittest/rtps/writer/CMakeLists.txt index bcc2f523a80..1adb393a5d3 100644 --- a/test/unittest/rtps/writer/CMakeLists.txt +++ b/test/unittest/rtps/writer/CMakeLists.txt @@ -57,6 +57,8 @@ target_include_directories(ReaderProxyTests PRIVATE ${PROJECT_SOURCE_DIR}/test/mock/rtps/ReaderLocator ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSGapBuilder ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSMessageGroup + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSParticipantImpl + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSReader ${PROJECT_SOURCE_DIR}/test/mock/rtps/TimedEvent ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include diff --git a/test/unittest/security/authentication/CMakeLists.txt b/test/unittest/security/authentication/CMakeLists.txt index b03767f0723..f184435f816 100644 --- a/test/unittest/security/authentication/CMakeLists.txt +++ b/test/unittest/security/authentication/CMakeLists.txt @@ -32,6 +32,7 @@ set(COMMON_SOURCES_AUTH_PLUGIN_TEST_SOURCE ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Time_t.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Token.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/exceptions/Exception.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/FlowControllerConsts.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/ThroughputControllerDescriptor.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/network/utils/netmask_filter.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/network/utils/network.cpp @@ -67,6 +68,8 @@ target_compile_definitions(BuiltinPKIDH PRIVATE target_include_directories(BuiltinPKIDH PRIVATE ${Asio_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/test/mock/rtps/NetworkFactory/ + ${PROJECT_SOURCE_DIR}/test/mock/rtps/ReaderProxyData/ + ${PROJECT_SOURCE_DIR}/test/mock/rtps/WriterProxyData/ ${OPENSSL_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/src/cpp diff --git a/test/unittest/statistics/dds/StatisticsDomainParticipantMockTests.cpp b/test/unittest/statistics/dds/StatisticsDomainParticipantMockTests.cpp index 88c0399fa36..8da0382f664 100644 --- a/test/unittest/statistics/dds/StatisticsDomainParticipantMockTests.cpp +++ b/test/unittest/statistics/dds/StatisticsDomainParticipantMockTests.cpp @@ -49,33 +49,62 @@ class StatisticsDomainParticipantMockTests : public ::testing::Test }; -class DomainParticipantImplTest : public DomainParticipantImpl -{ -public: +namespace { + +// Accessor to DomainParticipantImpl* from DomainParticipant +using DomainParticipantImplPtr = + eprosima::fastdds::dds::DomainParticipantImpl * eprosima::fastdds::dds::DomainParticipant::*; - eprosima::fastdds::dds::Publisher* get_builtin_publisher() const +DomainParticipantImplPtr get_domain_participant_impl_ptr(); + +template +struct DomainParticipantImplAccessor +{ + friend DomainParticipantImplPtr get_domain_participant_impl_ptr() { - return builtin_publisher_; + return P; } - PublisherImpl* get_builtin_publisher_impl() const +}; + +template struct DomainParticipantImplAccessor<&eprosima::fastdds::dds::DomainParticipant::impl_>; + +// Accessor to builtin_publisher_ from statistics DomainParticipantImpl +using BuiltinPublisherPtr = eprosima::fastdds::dds::Publisher * DomainParticipantImpl::*; + +BuiltinPublisherPtr get_builtin_publisher_ptr(); + +template +struct BuiltinPublisherAccessor +{ + friend BuiltinPublisherPtr get_builtin_publisher_ptr() { - return builtin_publisher_impl_; + return P; } }; -class DomainParticipantTest : public eprosima::fastdds::dds::DomainParticipant -{ -public: +template struct BuiltinPublisherAccessor<&DomainParticipantImpl::builtin_publisher_>; + +// Accessor to builtin_publisher_impl_ from statistics DomainParticipantImpl +using BuiltinPublisherImplPtr = PublisherImpl * DomainParticipantImpl::*; - eprosima::fastdds::dds::DomainParticipantImpl* get_impl() const +BuiltinPublisherImplPtr get_builtin_publisher_impl_ptr(); + +template +struct BuiltinPublisherImplAccessor +{ + friend BuiltinPublisherImplPtr get_builtin_publisher_impl_ptr() { - return impl_; + return P; } }; +template struct BuiltinPublisherImplAccessor<&DomainParticipantImpl::builtin_publisher_impl_>; + +} // namespace + /** * This test checks that enable_statistics_datawriter fails returning RETCODE_ERROR when create_datawriter fails * returning a nullptr. @@ -107,12 +136,10 @@ TEST_F(StatisticsDomainParticipantMockTests, EnableStatisticsDataWriterFailureCr ASSERT_NE(statistics_participant, nullptr); // 2. Mock create_datawriter - DomainParticipantTest* participant_test = static_cast(participant); - ASSERT_NE(nullptr, participant_test); - DomainParticipantImplTest* statistics_participant_impl_test = static_cast( - participant_test->get_impl()); + DomainParticipantImpl* statistics_participant_impl_test = static_cast( + participant->*get_domain_participant_impl_ptr()); ASSERT_NE(nullptr, statistics_participant_impl_test); - PublisherImpl* builtin_pub_impl = statistics_participant_impl_test->get_builtin_publisher_impl(); + PublisherImpl* builtin_pub_impl = statistics_participant_impl_test->*get_builtin_publisher_impl_ptr(); EXPECT_CALL(*builtin_pub_impl, create_datawriter_mock()).WillOnce(testing::Return(true)); // 3. enable_statistics_datawriter @@ -154,14 +181,12 @@ TEST_F(StatisticsDomainParticipantMockTests, DisableStatisticsDataWriterFailureD ASSERT_NE(statistics_participant, nullptr); // 2. Mock delete_datawriter - DomainParticipantTest* participant_test = static_cast(participant); - ASSERT_NE(nullptr, participant_test); - DomainParticipantImplTest* statistics_participant_impl_test = static_cast( - participant_test->get_impl()); + DomainParticipantImpl* statistics_participant_impl_test = static_cast( + participant->*get_domain_participant_impl_ptr()); ASSERT_NE(nullptr, statistics_participant_impl_test); - eprosima::fastdds::dds::Publisher* builtin_pub = statistics_participant_impl_test->get_builtin_publisher(); + eprosima::fastdds::dds::Publisher* builtin_pub = statistics_participant_impl_test->*get_builtin_publisher_ptr(); ASSERT_NE(nullptr, builtin_pub); - PublisherImpl* builtin_pub_impl = statistics_participant_impl_test->get_builtin_publisher_impl(); + PublisherImpl* builtin_pub_impl = statistics_participant_impl_test->*get_builtin_publisher_impl_ptr(); ASSERT_NE(nullptr, builtin_pub_impl); EXPECT_CALL(*builtin_pub, delete_datawriter_mock()).WillOnce(testing::Return(true)); EXPECT_CALL(*statistics_participant_impl_test, delete_topic_mock()).WillOnce(testing::Return(false)); @@ -209,14 +234,12 @@ TEST_F(StatisticsDomainParticipantMockTests, DisableStatisticsDataWriterFailureD ASSERT_NE(statistics_participant, nullptr); // 2. Mock delete_topic - DomainParticipantTest* participant_test = static_cast(participant); - ASSERT_NE(nullptr, participant_test); - DomainParticipantImplTest* statistics_participant_impl_test = static_cast( - participant_test->get_impl()); + DomainParticipantImpl* statistics_participant_impl_test = static_cast( + participant->*get_domain_participant_impl_ptr()); ASSERT_NE(nullptr, statistics_participant_impl_test); - eprosima::fastdds::dds::Publisher* builtin_pub = statistics_participant_impl_test->get_builtin_publisher(); + eprosima::fastdds::dds::Publisher* builtin_pub = statistics_participant_impl_test->*get_builtin_publisher_ptr(); ASSERT_NE(nullptr, builtin_pub); - PublisherImpl* builtin_pub_impl = statistics_participant_impl_test->get_builtin_publisher_impl(); + PublisherImpl* builtin_pub_impl = statistics_participant_impl_test->*get_builtin_publisher_impl_ptr(); ASSERT_NE(nullptr, builtin_pub_impl); EXPECT_CALL(*statistics_participant_impl_test, delete_topic_mock()).WillOnce(testing::Return(true)); EXPECT_CALL(*builtin_pub, delete_datawriter_mock()).WillOnce(testing::Return(false)); diff --git a/test/unittest/statistics/dds/StatisticsDomainParticipantStatusQueryableTests.cpp b/test/unittest/statistics/dds/StatisticsDomainParticipantStatusQueryableTests.cpp index e9c3dec1e3f..89b3c9a27b9 100644 --- a/test/unittest/statistics/dds/StatisticsDomainParticipantStatusQueryableTests.cpp +++ b/test/unittest/statistics/dds/StatisticsDomainParticipantStatusQueryableTests.cpp @@ -115,40 +115,64 @@ class StatisticsDomainParticipantStatusQueryableTests : public ::testing::Test }; -class DomainParticipantImplTest : public DomainParticipantImpl -{ -public: +namespace { - eprosima::fastdds::dds::Publisher* get_builtin_publisher() const - { - return builtin_publisher_; - } +// Accessor to DomainParticipantImpl* from DomainParticipant +using DomainParticipantImplPtr = + eprosima::fastdds::dds::DomainParticipantImpl * eprosima::fastdds::dds::DomainParticipant::*; + +DomainParticipantImplPtr get_domain_participant_impl_ptr(); - PublisherImpl* get_builtin_publisher_impl() const +template +struct DomainParticipantImplAccessor +{ + friend DomainParticipantImplPtr get_domain_participant_impl_ptr() { - return builtin_publisher_impl_; + return P; } - bool monitoring_status( - fastrtps::rtps::GUID_t guid, - statistics::MonitorServiceData& status) +}; + +template struct DomainParticipantImplAccessor<&eprosima::fastdds::dds::DomainParticipant::impl_>; + +// Accessor to builtin_publisher_impl_ from statistics DomainParticipantImpl +using BuiltinPublisherImplPtr = PublisherImpl * DomainParticipantImpl::*; + +BuiltinPublisherImplPtr get_builtin_publisher_impl_ptr(); + +template +struct BuiltinPublisherImplAccessor +{ + friend BuiltinPublisherImplPtr get_builtin_publisher_impl_ptr() { - return get_monitoring_status(guid, status); + return P; } }; -class DomainParticipantTest : public eprosima::fastdds::dds::DomainParticipant -{ -public: +template struct BuiltinPublisherImplAccessor<&DomainParticipantImpl::builtin_publisher_impl_>; - eprosima::fastdds::dds::DomainParticipantImpl* get_impl() const +// Accessor to protected get_monitoring_status() member function +using GetMonitoringStatusFn = bool (DomainParticipantImpl::*)( + const fastdds::rtps::GUID_t&, + statistics::MonitorServiceData&); + +GetMonitoringStatusFn get_monitoring_status_fn(); + +template +struct GetMonitoringStatusAccessor +{ + friend GetMonitoringStatusFn get_monitoring_status_fn() { - return impl_; + return F; } }; +template struct GetMonitoringStatusAccessor<&DomainParticipantImpl::get_monitoring_status>; + +} // namespace + TEST_F(StatisticsDomainParticipantStatusQueryableTests, istatus_queryable_get_incompatible_qos) { #ifdef FASTDDS_STATISTICS @@ -161,18 +185,15 @@ TEST_F(StatisticsDomainParticipantStatusQueryableTests, istatus_queryable_get_in DomainParticipant* statistics_participant = DomainParticipant::narrow(participant); ASSERT_NE(statistics_participant, nullptr); - DomainParticipantTest* participant_test = static_cast(participant); - ASSERT_NE(nullptr, participant_test); - DomainParticipantImplTest* statistics_participant_impl_test = static_cast( - participant_test->get_impl()); - + DomainParticipantImpl* statistics_participant_impl_test = static_cast( + participant->*get_domain_participant_impl_ptr()); ASSERT_NE(nullptr, statistics_participant_impl_test); fastdds::dds::TypeSupport type(new TopicDataTypeMock()); type.register_type(statistics_participant); - auto publisher = participant_test->create_publisher(fastdds::dds::PUBLISHER_QOS_DEFAULT); - auto topic = participant_test->create_topic(TEST_TOPIC, "footype", fastdds::dds::TOPIC_QOS_DEFAULT); + auto publisher = participant->create_publisher(fastdds::dds::PUBLISHER_QOS_DEFAULT); + auto topic = participant->create_topic(TEST_TOPIC, "footype", fastdds::dds::TOPIC_QOS_DEFAULT); //! Create DataWriters EXPECT_CALL(*publisher, create_datawriter_mock()).WillRepeatedly(testing::Return(false)); @@ -191,8 +212,8 @@ TEST_F(StatisticsDomainParticipantStatusQueryableTests, istatus_queryable_get_in incomp_qos_status_dw_1.incompatible_qos_status(IncompatibleQoSStatus_s{}); MonitorServiceData incomp_qos_status_dw_2; incomp_qos_status_dw_2.incompatible_qos_status(IncompatibleQoSStatus_s{}); - ASSERT_TRUE(statistics_participant_impl_test->monitoring_status(dw1->guid(), incomp_qos_status_dw_1)); - ASSERT_TRUE(statistics_participant_impl_test->monitoring_status(dw2->guid(), incomp_qos_status_dw_2)); + ASSERT_TRUE((statistics_participant_impl_test->*get_monitoring_status_fn())(dw1->guid(), incomp_qos_status_dw_1)); + ASSERT_TRUE((statistics_participant_impl_test->*get_monitoring_status_fn())(dw2->guid(), incomp_qos_status_dw_2)); //! Expect incompatibilities ASSERT_EQ(1u, incomp_qos_status_dw_1.incompatible_qos_status().total_count()); @@ -224,18 +245,15 @@ TEST_F(StatisticsDomainParticipantStatusQueryableTests, istatus_queryable_get_li DomainParticipant* statistics_participant = DomainParticipant::narrow(participant); ASSERT_NE(statistics_participant, nullptr); - DomainParticipantTest* participant_test = static_cast(participant); - ASSERT_NE(nullptr, participant_test); - DomainParticipantImplTest* statistics_participant_impl_test = static_cast( - participant_test->get_impl()); - + DomainParticipantImpl* statistics_participant_impl_test = static_cast( + participant->*get_domain_participant_impl_ptr()); ASSERT_NE(nullptr, statistics_participant_impl_test); fastdds::dds::TypeSupport type(new TopicDataTypeMock()); type.register_type(statistics_participant); - auto publisher = participant_test->create_publisher(fastdds::dds::PUBLISHER_QOS_DEFAULT); - auto topic = participant_test->create_topic(TEST_TOPIC, "footype", fastdds::dds::TOPIC_QOS_DEFAULT); + auto publisher = participant->create_publisher(fastdds::dds::PUBLISHER_QOS_DEFAULT); + auto topic = participant->create_topic(TEST_TOPIC, "footype", fastdds::dds::TOPIC_QOS_DEFAULT); //! Create DataWriters EXPECT_CALL(*publisher, create_datawriter_mock()).WillRepeatedly(testing::Return(false)); @@ -254,8 +272,8 @@ TEST_F(StatisticsDomainParticipantStatusQueryableTests, istatus_queryable_get_li liv_lost_status_dw_1.liveliness_lost_status(LivelinessLostStatus_s{}); MonitorServiceData liv_lost_status_dw_2; liv_lost_status_dw_2.liveliness_lost_status(LivelinessLostStatus_s{}); - ASSERT_TRUE(statistics_participant_impl_test->monitoring_status(dw1->guid(), liv_lost_status_dw_1)); - ASSERT_TRUE(statistics_participant_impl_test->monitoring_status(dw2->guid(), liv_lost_status_dw_2)); + ASSERT_TRUE((statistics_participant_impl_test->*get_monitoring_status_fn())(dw1->guid(), liv_lost_status_dw_1)); + ASSERT_TRUE((statistics_participant_impl_test->*get_monitoring_status_fn())(dw2->guid(), liv_lost_status_dw_2)); //! Expect incompatibilities ASSERT_EQ(1u, liv_lost_status_dw_1.liveliness_lost_status().total_count()); @@ -283,18 +301,15 @@ TEST_F(StatisticsDomainParticipantStatusQueryableTests, istatus_queryable_get_de DomainParticipant* statistics_participant = DomainParticipant::narrow(participant); ASSERT_NE(statistics_participant, nullptr); - DomainParticipantTest* participant_test = static_cast(participant); - ASSERT_NE(nullptr, participant_test); - DomainParticipantImplTest* statistics_participant_impl_test = static_cast( - participant_test->get_impl()); - + DomainParticipantImpl* statistics_participant_impl_test = static_cast( + participant->*get_domain_participant_impl_ptr()); ASSERT_NE(nullptr, statistics_participant_impl_test); fastdds::dds::TypeSupport type(new TopicDataTypeMock()); type.register_type(statistics_participant); - auto publisher = participant_test->create_publisher(fastdds::dds::PUBLISHER_QOS_DEFAULT); - auto topic = participant_test->create_topic(TEST_TOPIC, "footype", fastdds::dds::TOPIC_QOS_DEFAULT); + auto publisher = participant->create_publisher(fastdds::dds::PUBLISHER_QOS_DEFAULT); + auto topic = participant->create_topic(TEST_TOPIC, "footype", fastdds::dds::TOPIC_QOS_DEFAULT); //! Create DataWriters EXPECT_CALL(*publisher, create_datawriter_mock()).WillRepeatedly(testing::Return(false)); @@ -313,8 +328,10 @@ TEST_F(StatisticsDomainParticipantStatusQueryableTests, istatus_queryable_get_de deadline_missed_status_dw_1.deadline_missed_status(DeadlineMissedStatus_s{}); MonitorServiceData deadline_missed_status_dw_2; deadline_missed_status_dw_2.deadline_missed_status(DeadlineMissedStatus_s{}); - ASSERT_TRUE(statistics_participant_impl_test->monitoring_status(dw1->guid(), deadline_missed_status_dw_1)); - ASSERT_TRUE(statistics_participant_impl_test->monitoring_status(dw2->guid(), deadline_missed_status_dw_2)); + ASSERT_TRUE((statistics_participant_impl_test->*get_monitoring_status_fn())(dw1->guid(), + deadline_missed_status_dw_1)); + ASSERT_TRUE((statistics_participant_impl_test->*get_monitoring_status_fn())(dw2->guid(), + deadline_missed_status_dw_2)); //! Expect incompatibilities ASSERT_EQ(1u, deadline_missed_status_dw_1.deadline_missed_status().total_count()); diff --git a/test/unittest/statistics/dds/StatisticsQosTests.cpp b/test/unittest/statistics/dds/StatisticsQosTests.cpp index d5c1f73d1f1..2f0b2c76a10 100644 --- a/test/unittest/statistics/dds/StatisticsQosTests.cpp +++ b/test/unittest/statistics/dds/StatisticsQosTests.cpp @@ -42,33 +42,53 @@ namespace dds { using ReturnCode_t = eprosima::fastrtps::types::ReturnCode_t; -class StatisticsFromXMLProfileTests : public ::testing::Test -{ -public: - #ifdef FASTDDS_STATISTICS - class TestDomainParticipant : public eprosima::fastdds::statistics::dds::DomainParticipant +namespace { + +// Accessor to DomainParticipantImpl* from DomainParticipant +using DomainParticipantImplPtr = efd::DomainParticipantImpl * efd::DomainParticipant::*; + +DomainParticipantImplPtr get_domain_participant_impl_ptr(); + +template +struct DomainParticipantImplAccessor +{ + friend DomainParticipantImplPtr get_domain_participant_impl_ptr() { - public: + return P; + } + +}; + +template struct DomainParticipantImplAccessor<&efd::DomainParticipant::impl_>; - DomainParticipantImpl* get_domain_participant_impl() - { - return static_cast(impl_); - } +// Accessor to builtin_publisher_ from statistics DomainParticipantImpl +using BuiltinPublisherPtr = + efd::Publisher * eprosima::fastdds::statistics::dds::DomainParticipantImpl::*; - }; +BuiltinPublisherPtr get_builtin_publisher_ptr(); - class TestDomainParticipantImpl : public eprosima::fastdds::statistics::dds::DomainParticipantImpl +template +struct BuiltinPublisherAccessor +{ + friend BuiltinPublisherPtr get_builtin_publisher_ptr() { - public: + return P; + } + +}; - efd::Publisher* get_publisher() - { - return builtin_publisher_; - } +template struct BuiltinPublisherAccessor< + & eprosima::fastdds::statistics::dds::DomainParticipantImpl::builtin_publisher_>; - }; +} // namespace +#endif // ifdef FASTDDS_STATISTICS +class StatisticsFromXMLProfileTests : public ::testing::Test +{ +public: + +#ifdef FASTDDS_STATISTICS eprosima::fastdds::statistics::dds::DomainParticipant* statistics_participant = nullptr; eprosima::fastdds::dds::Publisher* statistics_publisher = nullptr; @@ -92,24 +112,18 @@ class StatisticsFromXMLProfileTests : public ::testing::Test eprosima::fastdds::statistics::dds::DomainParticipant::narrow(participant); ASSERT_NE(_statistics_participant, nullptr); - // Static conversion to child class TestDomainParticipant - TestDomainParticipant* test_statistics_participant = - static_cast(_statistics_participant); - ASSERT_NE(test_statistics_participant, nullptr); + // Get DomainParticipantImpl via accessor (no UB downcast) + efd::DomainParticipantImpl* base_impl = + _statistics_participant->*get_domain_participant_impl_ptr(); + ASSERT_NE(base_impl, nullptr); - // Get DomainParticipantImpl eprosima::fastdds::statistics::dds::DomainParticipantImpl* domain_statistics_participant_impl = - test_statistics_participant->get_domain_participant_impl(); + static_cast(base_impl); ASSERT_NE(domain_statistics_participant_impl, nullptr); - // Static conversion to child class TestDomainParticipantImpl - TestDomainParticipantImpl* test_statistics_domain_participant_impl = - static_cast(domain_statistics_participant_impl); - ASSERT_NE(test_statistics_domain_participant_impl, nullptr); - - // Get Publisher + // Get Publisher via accessor statistics_pub = - test_statistics_domain_participant_impl->get_publisher(); + domain_statistics_participant_impl->*get_builtin_publisher_ptr(); ASSERT_NE(statistics_pub, nullptr); } diff --git a/test/unittest/statistics/rtps/CMakeLists.txt b/test/unittest/statistics/rtps/CMakeLists.txt index 3e99203b9ae..720e06561c8 100644 --- a/test/unittest/statistics/rtps/CMakeLists.txt +++ b/test/unittest/statistics/rtps/CMakeLists.txt @@ -55,6 +55,8 @@ set(TCPTransportInterface_SOURCE ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResource.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResourceBasic.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPTransportInterface.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv4Transport.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv6Transport.cpp ) if(TLS_FOUND) set(TCPTransportInterface_SOURCE diff --git a/test/unittest/statistics/rtps/RTPSStatisticsTests.cpp b/test/unittest/statistics/rtps/RTPSStatisticsTests.cpp index a54d4c88183..feae9a40b04 100644 --- a/test/unittest/statistics/rtps/RTPSStatisticsTests.cpp +++ b/test/unittest/statistics/rtps/RTPSStatisticsTests.cpp @@ -60,21 +60,28 @@ namespace fastdds { namespace statistics { namespace rtps { -class RTPSParticipantMock : public fastrtps::rtps::RTPSParticipant -{ +namespace { -public: +// Accessor to RTPSParticipantImpl* from RTPSParticipant +using RTPSParticipantImplPtr = fastrtps::rtps::RTPSParticipantImpl * fastrtps::rtps::RTPSParticipant::*; - fastrtps::rtps::RTPSParticipantImpl* get_impl() +RTPSParticipantImplPtr get_rtps_part_impl(); + +template +struct RTPSParticipantImplAccessor +{ + friend RTPSParticipantImplPtr get_rtps_part_impl() { - return mp_impl; + return P; } -private: - - ~RTPSParticipantMock(); }; +template struct RTPSParticipantImplAccessor<&fastdds::rtps::RTPSParticipant::mp_impl>; + +} // namespace + + struct MockListener : IListener { MockListener() @@ -1410,8 +1417,7 @@ TEST_F(RTPSStatisticsTests, iconnections_queryable_get_entity_connections) // match writer and reader on a dummy topic match_endpoints(false, "string", "test_topic_name"); - auto participant_mock = static_cast(participant_); - auto part_impl = participant_mock->get_impl(); + eprosima::fastdds::rtps::RTPSParticipantImpl* part_impl = participant_->*get_rtps_part_impl(); part_impl->get_entity_connections(reader_->getGuid(), conns_reader); part_impl->get_entity_connections(writer_->getGuid(), conns_writer); diff --git a/test/unittest/statistics/rtps/mock/StatisticsBase/statistics/rtps/monitor-service/MonitorService.hpp b/test/unittest/statistics/rtps/mock/StatisticsBase/statistics/rtps/monitor-service/MonitorService.hpp index 0160eec3d28..b52d5e7729e 100644 --- a/test/unittest/statistics/rtps/mock/StatisticsBase/statistics/rtps/monitor-service/MonitorService.hpp +++ b/test/unittest/statistics/rtps/mock/StatisticsBase/statistics/rtps/monitor-service/MonitorService.hpp @@ -77,7 +77,7 @@ class MonitorService void set_writer( fastrtps::rtps::RTPSWriter* writer) { - status_writer_ = static_cast(writer); + status_writer_ = writer; } ~MonitorService(); @@ -243,7 +243,7 @@ class MonitorService MonitorServiceListener* listener_; - fastrtps::rtps::StatefulWriter* status_writer_; + fastrtps::rtps::RTPSWriter* status_writer_; std::unique_ptr status_writer_history_; @@ -264,4 +264,3 @@ class MonitorService } // namespace eprosima #endif // _STATISTICS_RTPS_MONITOR_SERVICE_MONITORSERVICE_HPP_ - diff --git a/test/unittest/transport/CMakeLists.txt b/test/unittest/transport/CMakeLists.txt index 350f77fcf2e..7511674d05e 100644 --- a/test/unittest/transport/CMakeLists.txt +++ b/test/unittest/transport/CMakeLists.txt @@ -55,6 +55,8 @@ set(TCPTransportInterface_SOURCE ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResource.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResourceBasic.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPTransportInterface.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv4Transport.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv6Transport.cpp ) if(TLS_FOUND) set(TCPTransportInterface_SOURCE @@ -251,6 +253,7 @@ set(TCPV6TESTS_SOURCE ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResource.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResourceBasic.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPTransportInterface.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv4Transport.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv6Transport.cpp ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TransportInterface.cpp ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPFinder.cpp diff --git a/test/unittest/transport/TCPv4Tests.cpp b/test/unittest/transport/TCPv4Tests.cpp index 01bd4349ee3..52dcd6071e8 100644 --- a/test/unittest/transport/TCPv4Tests.cpp +++ b/test/unittest/transport/TCPv4Tests.cpp @@ -1495,7 +1495,7 @@ TEST_F(TCPv4Tests, secure_non_blocking_send) auto sender_unbound_channel_resources = senderTransportUnderTest.get_unbound_channel_resources(); ASSERT_TRUE(sender_unbound_channel_resources.size() == 1u); auto sender_channel_resource = - std::static_pointer_cast(sender_unbound_channel_resources[0]); + std::static_pointer_cast(sender_unbound_channel_resources[0]); // Prepare the message std::vector message(msg_size, 0); From aaebff8ffd0b2b4c025b104868f9c46272039d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ferreira=20Gonz=C3=A1lez?= Date: Thu, 23 Jul 2026 15:48:53 +0200 Subject: [PATCH 2/4] Solve conflicts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Ferreira González --- .github/workflows/config/ubsan.meta | 2 +- .github/workflows/reusable-sanitizers-ci.yml | 20 +- .../common/RTPSBlackboxTestsReader.cpp | 158 ---------------- .../common/RTPSBlackboxTestsWriter.cpp | 158 ---------------- .../rtps/security/common/SharedSecretHandle.h | 176 ------------------ .../dds/publisher/DataWriterTests.cpp | 6 +- test/unittest/dds/status/ListenerTests.cpp | 6 +- .../security/authentication/CMakeLists.txt | 27 +++ ...sDomainParticipantStatusQueryableTests.cpp | 2 +- .../statistics/rtps/RTPSStatisticsTests.cpp | 4 +- test/unittest/transport/TCPv4Tests.cpp | 2 +- 11 files changed, 47 insertions(+), 514 deletions(-) delete mode 100644 test/blackbox/common/RTPSBlackboxTestsReader.cpp delete mode 100644 test/blackbox/common/RTPSBlackboxTestsWriter.cpp delete mode 100644 test/mock/rtps/SharedSecretHandle/rtps/security/common/SharedSecretHandle.h diff --git a/.github/workflows/config/ubsan.meta b/.github/workflows/config/ubsan.meta index 336a5cdb615..d5f8385468f 100644 --- a/.github/workflows/config/ubsan.meta +++ b/.github/workflows/config/ubsan.meta @@ -1,5 +1,5 @@ names: - fastdds: + fastrtps: cmake-args: - -DNO_TLS=OFF - -DSECURITY=ON diff --git a/.github/workflows/reusable-sanitizers-ci.yml b/.github/workflows/reusable-sanitizers-ci.yml index 59979574c84..c1b4c25ed31 100644 --- a/.github/workflows/reusable-sanitizers-ci.yml +++ b/.github/workflows/reusable-sanitizers-ci.yml @@ -562,7 +562,7 @@ jobs: - name: Sync eProsima/Fast-DDS repository uses: eProsima/eProsima-CI/external/checkout@v0 with: - path: src/fastdds + path: src/fastrtps submodules: true ref: ${{ inputs.fastdds_ref }} @@ -612,27 +612,27 @@ jobs: - name: Fetch Fast DDS dependencies uses: eProsima/eProsima-CI/ubuntu/vcs_import@v0 with: - vcs_repos_file: ${{ github.workspace }}/src/fastdds/fastdds.repos + vcs_repos_file: ${{ github.workspace }}/src/fastrtps/fastrtps.repos destination_workspace: src skip_existing: 'true' - name: Fetch Fast DDS CI dependencies uses: eProsima/eProsima-CI/ubuntu/vcs_import@v0 with: - vcs_repos_file: ${{ github.workspace }}/src/fastdds/.github/workflows/config/fastdds_test.repos + vcs_repos_file: ${{ github.workspace }}/src/fastrtps/.github/workflows/config/fastdds_test.repos destination_workspace: src skip_existing: 'true' - name: Show .meta file id: show_meta run: | - cat ${{ github.workspace }}/src/fastdds/.github/workflows/config/ubsan.meta + cat ${{ github.workspace }}/src/fastrtps/.github/workflows/config/ubsan.meta - name: Colcon build continue-on-error: false uses: eProsima/eProsima-CI/ubuntu/colcon_build@v0 with: - colcon_meta_file: ${{ github.workspace }}/src/fastdds/.github/workflows/config/ubsan.meta + colcon_meta_file: ${{ github.workspace }}/src/fastrtps/.github/workflows/config/ubsan.meta colcon_build_args: ${{ inputs.colcon_build_args }} cmake_args: ${{ inputs.cmake_args }} cmake_args_default: '' @@ -717,7 +717,7 @@ jobs: colcon_test_args_default: '--event-handlers=console_direct+ --return-code-on-test-failure' ctest_args: ${{ inputs.ctest_args }} ctest_args_default: '--timeout 300 --label-exclude "xfail"' - packages_names: fastdds + packages_names: fastrtps workspace: ${{ github.workspace }} workspace_dependencies: '' test_report_artifact: ${{ format('test_report_{0}_{1}', inputs.label, github.job) }} @@ -727,13 +727,13 @@ jobs: # UBSan finding header lines look like: # ::: runtime error: # Filter on ": runtime error:" so we keep one line per finding (the header) - bash src/fastdds/.github/workflows/utils/specific_errors_filter.sh \ + bash src/fastrtps/.github/workflows/utils/specific_errors_filter.sh \ ": runtime error:" \ - log/latest_test/fastdds/stdout_stderr.log \ + log/latest_test/fastrtps/stdout_stderr.log \ _tmp_specific_error_file.log - python3 src/fastdds/.github/workflows/utils/log_parser.py \ - --log-file log/latest_test/fastdds/stdout_stderr.log \ + python3 src/fastrtps/.github/workflows/utils/log_parser.py \ + --log-file log/latest_test/fastrtps/stdout_stderr.log \ --specific-error-file _tmp_specific_error_file.log \ --output-file $GITHUB_STEP_SUMMARY \ --sanitizer ubsan diff --git a/test/blackbox/common/RTPSBlackboxTestsReader.cpp b/test/blackbox/common/RTPSBlackboxTestsReader.cpp deleted file mode 100644 index 0695956c544..00000000000 --- a/test/blackbox/common/RTPSBlackboxTestsReader.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "BlackboxTests.hpp" - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "RTPSWithRegistrationReader.hpp" -#include "RTPSWithRegistrationWriter.hpp" - -using namespace eprosima::fastdds; -using namespace eprosima::fastdds::rtps; - -namespace { -enum communication_type -{ - TRANSPORT, - INTRAPROCESS -}; -} // namespace - -class RTPSReaderTests : public testing::TestWithParam -{ -public: - - void SetUp() override - { - eprosima::fastdds::LibrarySettings library_settings; - switch (GetParam()) - { - case INTRAPROCESS: - library_settings.intraprocess_delivery = eprosima::fastdds::IntraprocessDeliveryType::INTRAPROCESS_FULL; - eprosima::fastdds::rtps::RTPSDomain::set_library_settings(library_settings); - break; - case TRANSPORT: - default: - break; - } - } - - void TearDown() override - { - eprosima::fastdds::LibrarySettings library_settings; - switch (GetParam()) - { - case INTRAPROCESS: - library_settings.intraprocess_delivery = eprosima::fastdds::IntraprocessDeliveryType::INTRAPROCESS_OFF; - eprosima::fastdds::rtps::RTPSDomain::set_library_settings(library_settings); - break; - case TRANSPORT: - default: - break; - } - } - -}; - -/** - * @test RTPS-READER-API-MWG-01 - * - * matched_writers_guids() must return true with empty list when the entitiy is not matched. - * matched_writers_guids() must return true with a correct list when the entitiy is matched. - */ -TEST_P(RTPSReaderTests, rtpsreader_matched_writers_guids) -{ - RTPSWithRegistrationReader reader(TEST_TOPIC_NAME); - RTPSWithRegistrationWriter writer(TEST_TOPIC_NAME); - - reader.reliability(eprosima::fastdds::rtps::RELIABLE) - .init(); - - writer.reliability(eprosima::fastdds::rtps::BEST_EFFORT) - .init(); - - ASSERT_TRUE(reader.isInitialized()); - ASSERT_TRUE(writer.isInitialized()); - - // Expect not to discover - reader.wait_discovery(std::chrono::seconds(1)); - ASSERT_FALSE(reader.get_matched()); - - std::vector matched_guids; - auto& native_rtps_reader = reader.get_native_reader(); - ASSERT_TRUE(native_rtps_reader.matched_writers_guids(matched_guids)); - ASSERT_TRUE(matched_guids.empty()); - - writer.destroy(); - reader.wait_undiscovery(); - - const size_t num_matched_writers = 3; - std::vector>> writers; - std::vector expected_matched_guids; - - writers.reserve(num_matched_writers); - expected_matched_guids.reserve(num_matched_writers); - - for (size_t i = 0; i < num_matched_writers; ++i) - { - writers.emplace_back(new RTPSWithRegistrationWriter(TEST_TOPIC_NAME)); - writers.back()->init(); - expected_matched_guids.emplace_back(writers.back()->guid()); - } - - reader.wait_discovery(num_matched_writers, std::chrono::seconds::zero()); - ASSERT_EQ(num_matched_writers, reader.get_matched()); - native_rtps_reader.matched_writers_guids(matched_guids); - ASSERT_EQ(expected_matched_guids.size(), matched_guids.size()); - ASSERT_TRUE(std::is_permutation(expected_matched_guids.begin(), expected_matched_guids.end(), - matched_guids.begin())); -} - -#ifdef INSTANTIATE_TEST_SUITE_P -#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_SUITE_P(x, y, z, w) -#else -#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_CASE_P(x, y, z, w) -#endif // ifdef INSTANTIATE_TEST_SUITE_P - -GTEST_INSTANTIATE_TEST_MACRO(RTPSReaderTests, - RTPSReaderTests, - testing::Values(TRANSPORT, INTRAPROCESS), - [](const testing::TestParamInfo& info) - { - switch (info.param) - { - case INTRAPROCESS: - return "Intraprocess"; - break; - case TRANSPORT: - default: - return "Transport"; - } - - }); diff --git a/test/blackbox/common/RTPSBlackboxTestsWriter.cpp b/test/blackbox/common/RTPSBlackboxTestsWriter.cpp deleted file mode 100644 index c67cb7a7e25..00000000000 --- a/test/blackbox/common/RTPSBlackboxTestsWriter.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "BlackboxTests.hpp" - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "RTPSWithRegistrationReader.hpp" -#include "RTPSWithRegistrationWriter.hpp" - -using namespace eprosima::fastdds; -using namespace eprosima::fastdds::rtps; - -namespace { -enum communication_type -{ - TRANSPORT, - INTRAPROCESS -}; -} // namespace - -class RTPSWriterTests : public testing::TestWithParam -{ -public: - - void SetUp() override - { - eprosima::fastdds::LibrarySettings library_settings; - switch (GetParam()) - { - case INTRAPROCESS: - library_settings.intraprocess_delivery = eprosima::fastdds::IntraprocessDeliveryType::INTRAPROCESS_FULL; - eprosima::fastdds::rtps::RTPSDomain::set_library_settings(library_settings); - break; - case TRANSPORT: - default: - break; - } - } - - void TearDown() override - { - eprosima::fastdds::LibrarySettings library_settings; - switch (GetParam()) - { - case INTRAPROCESS: - library_settings.intraprocess_delivery = eprosima::fastdds::IntraprocessDeliveryType::INTRAPROCESS_OFF; - eprosima::fastdds::rtps::RTPSDomain::set_library_settings(library_settings); - break; - case TRANSPORT: - default: - break; - } - } - -}; - -/** - * @test RTPS-WRITER-API-MRG-01 - * - * matched_readers_guids() must return true with empty list when the entitiy is not matched. - * matched_readers_guids() must return true with a correct list when the entitiy is matched. - */ -TEST_P(RTPSWriterTests, rtpswriter_matched_readers_guids) -{ - RTPSWithRegistrationWriter writer(TEST_TOPIC_NAME); - RTPSWithRegistrationReader reader(TEST_TOPIC_NAME); - - writer.reliability(eprosima::fastdds::rtps::BEST_EFFORT) - .init(); - - reader.reliability(eprosima::fastdds::rtps::RELIABLE) - .init(); - - ASSERT_TRUE(writer.isInitialized()); - ASSERT_TRUE(reader.isInitialized()); - - // Expect not to discover - writer.wait_discovery(std::chrono::seconds(1)); - ASSERT_FALSE(writer.get_matched()); - - std::vector matched_guids; - auto& native_rtps_writer = writer.get_native_writer(); - ASSERT_TRUE(native_rtps_writer.matched_readers_guids(matched_guids)); - ASSERT_TRUE(matched_guids.empty()); - - reader.destroy(); - writer.wait_undiscovery(); - - const size_t num_matched_readers = 3; - std::vector>> readers; - std::vector expected_matched_guids; - - readers.reserve(num_matched_readers); - expected_matched_guids.reserve(num_matched_readers); - - for (size_t i = 0; i < num_matched_readers; ++i) - { - readers.emplace_back(new RTPSWithRegistrationReader(TEST_TOPIC_NAME)); - readers.back()->init(); - expected_matched_guids.emplace_back(readers.back()->guid()); - } - - writer.wait_discovery(num_matched_readers, std::chrono::seconds::zero()); - ASSERT_EQ(num_matched_readers, writer.get_matched()); - native_rtps_writer.matched_readers_guids(matched_guids); - ASSERT_EQ(expected_matched_guids.size(), matched_guids.size()); - ASSERT_TRUE(std::is_permutation(expected_matched_guids.begin(), expected_matched_guids.end(), - matched_guids.begin())); -} - -#ifdef INSTANTIATE_TEST_SUITE_P -#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_SUITE_P(x, y, z, w) -#else -#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_CASE_P(x, y, z, w) -#endif // ifdef INSTANTIATE_TEST_SUITE_P - -GTEST_INSTANTIATE_TEST_MACRO(RTPSWriterTests, - RTPSWriterTests, - testing::Values(TRANSPORT, INTRAPROCESS), - [](const testing::TestParamInfo& info) - { - switch (info.param) - { - case INTRAPROCESS: - return "Intraprocess"; - break; - case TRANSPORT: - default: - return "Transport"; - } - - }); diff --git a/test/mock/rtps/SharedSecretHandle/rtps/security/common/SharedSecretHandle.h b/test/mock/rtps/SharedSecretHandle/rtps/security/common/SharedSecretHandle.h deleted file mode 100644 index 0c93faabe1f..00000000000 --- a/test/mock/rtps/SharedSecretHandle/rtps/security/common/SharedSecretHandle.h +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2026 Proyectos y Sistemas de Mantenimiento SL (eProsima). -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/*! - * @file SharedSecretHandle.h (test mock) - * - * Drop-in replacement for the production SharedSecretHandle.h. The only - * difference is the SharedSecretHandle typedef: it instantiates HandleImpl - * with MockAuthenticationPlugin instead of PKIDH, so it matches the dynamic - * type of the SharedSecret-bearing handles created by the test (see - * test/mock/rtps/SecurityPluginFactory/rtps/security/MockAuthenticationPlugin.h). - * - * Without this substitution the production translation unit narrows to a - * different HandleImpl instantiation than the test creates; - * the two share layout but have distinct vtables, so the next virtual call - * (e.g. nil()) trips ubsan with a vptr/type mismatch. - */ -#ifndef _FASTDDS_RTPS_SECURITY_COMMON_SHAREDSECRETHANDLE_H_ -#define _FASTDDS_RTPS_SECURITY_COMMON_SHAREDSECRETHANDLE_H_ - -#include - -#include -#include - -namespace eprosima { -namespace fastdds { -namespace rtps { -namespace security { - -class SharedSecret -{ -public: - - class BinaryData - { - public: - - BinaryData() - { - } - - BinaryData( - const BinaryData& data) - : name_(data.name_) - , value_(data.value_) - { - } - - BinaryData( - BinaryData&& data) - : name_(std::move(data.name_)) - , value_(std::move(data.value_)) - { - } - - BinaryData( - const std::string& name, - const std::vector& value) - : name_(name) - , value_(value) - { - } - - BinaryData( - std::string&& name, - std::vector&& value) - : name_(std::move(name)) - , value_(std::move(value)) - { - } - - BinaryData& operator =( - const BinaryData& data) - { - name_ = data.name_; - value_ = data.value_; - return *this; - } - - BinaryData& operator =( - BinaryData&& data) - { - name_ = std::move(data.name_); - value_ = std::move(data.value_); - return *this; - } - - void name( - const std::string& name) - { - name_ = name; - } - - void name( - std::string&& name) - { - name_ = std::move(name); - } - - const std::string& name() const - { - return name_; - } - - std::string& name() - { - return name_; - } - - void value( - const std::vector& value) - { - value_ = value; - } - - void value( - std::vector&& value) - { - value_ = std::move(value); - } - - const std::vector& value() const - { - return value_; - } - - std::vector& value() - { - return value_; - } - - private: - - std::string name_; - - std::vector value_; - }; - - static const char* const class_id_; - - std::vector data_; -}; - -// Forward declaration is enough. The friend declaration inside HandleImpl -// only requires the elaborated name. -class MockAuthenticationPlugin; - -typedef HandleImpl SharedSecretHandle; - -class SharedSecretHelper -{ -public: - - static const std::vector* find_data_value( - const SecretHandle& sharedsecret, - const std::string& name); -}; - -} //namespace security -} //namespace rtps -} //namespace fastdds -} //namespace eprosima - -#endif // _FASTDDS_RTPS_SECURITY_COMMON_SHAREDSECRETHANDLE_H_ diff --git a/test/unittest/dds/publisher/DataWriterTests.cpp b/test/unittest/dds/publisher/DataWriterTests.cpp index 862fe970808..9bfb9d3f454 100644 --- a/test/unittest/dds/publisher/DataWriterTests.cpp +++ b/test/unittest/dds/publisher/DataWriterTests.cpp @@ -1973,8 +1973,8 @@ struct DataWriterImplAccessor template struct DataWriterImplAccessor<&DataWriter::impl_>; -// Accessor to DataWriterHistory unique ptr from DataWriterImpl -using DataWriterHistoryPtr = std::unique_ptr DataWriterImpl::*; +// Accessor to DataWriterHistory from DataWriterImpl +using DataWriterHistoryPtr = DataWriterHistory DataWriterImpl::*; DataWriterHistoryPtr get_datawriter_history_ptr(); @@ -2055,7 +2055,7 @@ TEST(DataWriterTests, InstanceWaitForAcknowledgement) // Access DataWriterHistory DataWriterImpl* datawriter_impl = instance_datawriter->*get_datawriter_impl_ptr(); ASSERT_NE(nullptr, datawriter_impl); - DataWriterHistory* history = (datawriter_impl->*get_datawriter_history_ptr()).get(); + DataWriterHistory* history = &(datawriter_impl->*get_datawriter_history_ptr()); ASSERT_NE(nullptr, history); // 5. Calling wait_for_acknowledgments in a keyed topic with HANDLE_NIL returns diff --git a/test/unittest/dds/status/ListenerTests.cpp b/test/unittest/dds/status/ListenerTests.cpp index 84f5cb15fc8..35fd9b8c7de 100644 --- a/test/unittest/dds/status/ListenerTests.cpp +++ b/test/unittest/dds/status/ListenerTests.cpp @@ -37,9 +37,7 @@ #include #include -#include -#include -#include +#include using ::testing::StrictMock; @@ -609,7 +607,7 @@ class UserListeners : public ::testing::Test NiceMock participant_mock_; NiceMock writer_mock_; NiceMock reader_mock_; - eprosima::fastdds::rtps::RTPSParticipantImpl participant_impl_mock_; + eprosima::fastrtps::rtps::RTPSParticipantImpl participant_impl_mock_; // User listeners are strick, we want to track unexpected calls StrictMock participant_listener_; diff --git a/test/unittest/security/authentication/CMakeLists.txt b/test/unittest/security/authentication/CMakeLists.txt index f184435f816..5ffed53c574 100644 --- a/test/unittest/security/authentication/CMakeLists.txt +++ b/test/unittest/security/authentication/CMakeLists.txt @@ -20,7 +20,34 @@ if(WIN32) endif() set(COMMON_SOURCES_AUTH_PLUGIN_TEST_SOURCE + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/AnnotationDescriptor.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/AnnotationParameterValue.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/BuiltinAnnotationsTypeObject.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicData.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicDataFactory.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicDataPtr.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicPubSubType.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicType.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeBuilder.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeBuilderFactory.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeBuilderPtr.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeMember.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypePtr.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/MemberDescriptor.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeDescriptor.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeIdentifier.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeIdentifierTypes.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeNamesGenerator.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeObject.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeObjectFactory.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeObjectHashId.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypesBase.cpp ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/ParameterList.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/WriterQos.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/ReaderQos.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/TopicDataType.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/ThreadSettings.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/utils/string_convert.cpp ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/Log.cpp ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/OStreamConsumer.cpp ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutConsumer.cpp diff --git a/test/unittest/statistics/dds/StatisticsDomainParticipantStatusQueryableTests.cpp b/test/unittest/statistics/dds/StatisticsDomainParticipantStatusQueryableTests.cpp index 89b3c9a27b9..d37b49d86d9 100644 --- a/test/unittest/statistics/dds/StatisticsDomainParticipantStatusQueryableTests.cpp +++ b/test/unittest/statistics/dds/StatisticsDomainParticipantStatusQueryableTests.cpp @@ -154,7 +154,7 @@ template struct BuiltinPublisherImplAccessor<&DomainParticipantImpl::builtin_pub // Accessor to protected get_monitoring_status() member function using GetMonitoringStatusFn = bool (DomainParticipantImpl::*)( - const fastdds::rtps::GUID_t&, + const fastrtps::rtps::GUID_t&, statistics::MonitorServiceData&); GetMonitoringStatusFn get_monitoring_status_fn(); diff --git a/test/unittest/statistics/rtps/RTPSStatisticsTests.cpp b/test/unittest/statistics/rtps/RTPSStatisticsTests.cpp index feae9a40b04..c9e025e3979 100644 --- a/test/unittest/statistics/rtps/RTPSStatisticsTests.cpp +++ b/test/unittest/statistics/rtps/RTPSStatisticsTests.cpp @@ -77,7 +77,7 @@ struct RTPSParticipantImplAccessor }; -template struct RTPSParticipantImplAccessor<&fastdds::rtps::RTPSParticipant::mp_impl>; +template struct RTPSParticipantImplAccessor<&fastrtps::rtps::RTPSParticipant::mp_impl>; } // namespace @@ -1417,7 +1417,7 @@ TEST_F(RTPSStatisticsTests, iconnections_queryable_get_entity_connections) // match writer and reader on a dummy topic match_endpoints(false, "string", "test_topic_name"); - eprosima::fastdds::rtps::RTPSParticipantImpl* part_impl = participant_->*get_rtps_part_impl(); + eprosima::fastrtps::rtps::RTPSParticipantImpl* part_impl = participant_->*get_rtps_part_impl(); part_impl->get_entity_connections(reader_->getGuid(), conns_reader); part_impl->get_entity_connections(writer_->getGuid(), conns_writer); diff --git a/test/unittest/transport/TCPv4Tests.cpp b/test/unittest/transport/TCPv4Tests.cpp index 52dcd6071e8..65532c5cdfa 100644 --- a/test/unittest/transport/TCPv4Tests.cpp +++ b/test/unittest/transport/TCPv4Tests.cpp @@ -1495,7 +1495,7 @@ TEST_F(TCPv4Tests, secure_non_blocking_send) auto sender_unbound_channel_resources = senderTransportUnderTest.get_unbound_channel_resources(); ASSERT_TRUE(sender_unbound_channel_resources.size() == 1u); auto sender_channel_resource = - std::static_pointer_cast(sender_unbound_channel_resources[0]); + std::static_pointer_cast(sender_unbound_channel_resources[0]); // Prepare the message std::vector message(msg_size, 0); From b8c5606d60a8b96b6f4c08e59d33b3c0bf6d4b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ferreira=20Gonz=C3=A1lez?= Date: Thu, 23 Jul 2026 15:50:04 +0200 Subject: [PATCH 3/4] Uncrustify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Ferreira González --- include/fastdds/rtps/messages/CDRMessage.hpp | 2 +- .../domain/DomainParticipantFactory.cpp | 3 +- .../common/BlackboxTestsDiscovery.cpp | 2 +- .../common/DDSBlackboxTestsDataReader.cpp | 3 +- .../common/DDSBlackboxTestsDataWriter.cpp | 3 +- .../common/DDSBlackboxTestsMonitorService.cpp | 83 ++++++++++--------- .../common/DDSBlackboxTestsPersistence.cpp | 6 +- .../DDSBlackboxTestsPersistenceGuid.cpp | 80 +++++++++--------- .../common/RTPSBlackboxTestsBasic.cpp | 4 +- .../common/RTPSBlackboxTestsPersistence.cpp | 6 +- .../RTPSBlackboxTestsPersistenceGuid.cpp | 58 ++++++------- .../common/RTPSBlackboxTestsPools.cpp | 2 +- test/unittest/transport/TCPv4Tests.cpp | 3 +- 13 files changed, 130 insertions(+), 125 deletions(-) diff --git a/include/fastdds/rtps/messages/CDRMessage.hpp b/include/fastdds/rtps/messages/CDRMessage.hpp index 15c7395136c..02b2d16d7b2 100644 --- a/include/fastdds/rtps/messages/CDRMessage.hpp +++ b/include/fastdds/rtps/messages/CDRMessage.hpp @@ -648,7 +648,7 @@ inline bool CDRMessage::add_string( bool valid = CDRMessage::addUInt32(msg, str_siz); valid &= CDRMessage::addData(msg, (unsigned char*) in_str, str_siz); octet oc = '\0'; - for (; str_siz& 3; ++str_siz) + for (; str_siz & 3; ++str_siz) { valid &= CDRMessage::addOctet(msg, oc); } diff --git a/src/cpp/fastdds/domain/DomainParticipantFactory.cpp b/src/cpp/fastdds/domain/DomainParticipantFactory.cpp index 3773687dc72..201a1ec6f7c 100644 --- a/src/cpp/fastdds/domain/DomainParticipantFactory.cpp +++ b/src/cpp/fastdds/domain/DomainParticipantFactory.cpp @@ -170,7 +170,8 @@ DomainParticipant* DomainParticipantFactory::create_participant( DomainParticipant* dom_part = new DomainParticipant(mask); DomainParticipantImpl* dom_part_impl = new DomainParticipantImpl(dom_part, did, pqos, listen); #else - eprosima::fastdds::statistics::dds::DomainParticipant* dom_part = new eprosima::fastdds::statistics::dds::DomainParticipant(mask); + eprosima::fastdds::statistics::dds::DomainParticipant* dom_part = + new eprosima::fastdds::statistics::dds::DomainParticipant(mask); eprosima::fastdds::statistics::dds::DomainParticipantImpl* dom_part_impl = new eprosima::fastdds::statistics::dds::DomainParticipantImpl(dom_part, did, pqos, listen); #endif // FASTDDS_STATISTICS diff --git a/test/blackbox/common/BlackboxTestsDiscovery.cpp b/test/blackbox/common/BlackboxTestsDiscovery.cpp index 72679be3f27..ce4f7c73ecc 100644 --- a/test/blackbox/common/BlackboxTestsDiscovery.cpp +++ b/test/blackbox/common/BlackboxTestsDiscovery.cpp @@ -1007,7 +1007,7 @@ TEST_P(Discovery, PubSubAsReliableHelloworldEndpointUserData) } //! Auxiliar method for discovering participants tests -template +template static void discoverParticipantsTest( bool avoid_multicast, size_t n_participants, diff --git a/test/blackbox/common/DDSBlackboxTestsDataReader.cpp b/test/blackbox/common/DDSBlackboxTestsDataReader.cpp index 14919903d5b..93f75b07ffa 100644 --- a/test/blackbox/common/DDSBlackboxTestsDataReader.cpp +++ b/test/blackbox/common/DDSBlackboxTestsDataReader.cpp @@ -329,7 +329,8 @@ TEST(DDSDataReader, GetFirstUntakenInfoReturnsTheFirstValidChange) eprosima::fastdds::dds::SampleInfo info; for (size_t i = 0; i < 3; i++) { - ASSERT_NE(eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK, reader.get_native_reader().get_first_untaken_info( + ASSERT_NE(eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK, + reader.get_native_reader().get_first_untaken_info( &info)); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } diff --git a/test/blackbox/common/DDSBlackboxTestsDataWriter.cpp b/test/blackbox/common/DDSBlackboxTestsDataWriter.cpp index e4d3f0f6485..95a32bd0dd6 100644 --- a/test/blackbox/common/DDSBlackboxTestsDataWriter.cpp +++ b/test/blackbox/common/DDSBlackboxTestsDataWriter.cpp @@ -468,7 +468,8 @@ class TestsDataWriterQosCommonUtils qos.resource_limits().max_samples = 1000; qos.transport_priority().value = 1; qos.ownership().kind = eprosima::fastdds::dds::EXCLUSIVE_OWNERSHIP_QOS; - qos.representation().m_value.push_back(eprosima::fastdds::dds::DataRepresentationId_t::XCDR2_DATA_REPRESENTATION); + qos.representation().m_value.push_back( + eprosima::fastdds::dds::DataRepresentationId_t::XCDR2_DATA_REPRESENTATION); qos.history().kind = eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS; qos.lifespan().duration = {5, 0}; } diff --git a/test/blackbox/common/DDSBlackboxTestsMonitorService.cpp b/test/blackbox/common/DDSBlackboxTestsMonitorService.cpp index db531fd82b5..6673647efb1 100644 --- a/test/blackbox/common/DDSBlackboxTestsMonitorService.cpp +++ b/test/blackbox/common/DDSBlackboxTestsMonitorService.cpp @@ -201,8 +201,8 @@ class MonitorServiceParticipant writer_stat_guids_.push_back(statistics::to_statistics_type(writers_.back()->guid())); - std::cout << "Created datawriter " << writers_.back()->guid() << " for topic " << - topics_.back()->get_name() << std::endl; + std::cout << "Created datawriter " << writers_.back()->guid() << " for topic " + << topics_.back()->get_name() << std::endl; } void create_and_add_reader( @@ -224,8 +224,8 @@ class MonitorServiceParticipant reader_stat_guids_.push_back(statistics::to_statistics_type(readers_.back()->guid())); - std::cout << "Created datareader " << readers_.back()->guid() << " for topic " << - topics_.back()->get_name() << std::endl; + std::cout << "Created datareader " << readers_.back()->guid() << " for topic " + << topics_.back()->get_name() << std::endl; } bool delete_writer() @@ -348,8 +348,8 @@ class MonitorServiceParticipant ++cb_counters_[OFFERED_DEADLINE_MISSED_IDX]; } - std::cout << "on_offered_deadline_missed() " << writer->guid() << " total_count " << status.total_count << - std::endl; + std::cout << "on_offered_deadline_missed() " << writer->guid() << " total_count " << status.total_count + << std::endl; } void on_offered_incompatible_qos ( @@ -361,8 +361,8 @@ class MonitorServiceParticipant ++cb_counters_[OFFERED_INCOMPATIBLE_QOS_IDX]; } - std::cout << "on_offered_incompatible_qos " << writer->guid() << " total_count " << status.total_count << - std::endl; + std::cout << "on_offered_incompatible_qos " << writer->guid() << " total_count " << status.total_count + << std::endl; } void on_liveliness_lost ( @@ -386,8 +386,8 @@ class MonitorServiceParticipant ++cb_counters_[PUBLICATION_MATCHED_IDX]; } - std::cout << "on_publication_matched " << writer->guid() << " total_count " << status.total_count << - std::endl; + std::cout << "on_publication_matched " << writer->guid() << " total_count " << status.total_count + << std::endl; } void on_requested_deadline_missed ( @@ -399,8 +399,8 @@ class MonitorServiceParticipant ++cb_counters_[REQUESTED_DEADLINE_MISSED_IDX]; } - std::cout << "on_requested_deadline_missed" << reader->guid() << " total_count " << status.total_count << - std::endl; + std::cout << "on_requested_deadline_missed" << reader->guid() << " total_count " << status.total_count + << std::endl; } void on_requested_incompatible_qos ( @@ -412,8 +412,8 @@ class MonitorServiceParticipant ++cb_counters_[REQUESTED_INCOMPATIBLE_QOS_IDX]; } - std::cout << "on_requested_incompatible_qos" << reader->guid() << " total_count " << status.total_count << - std::endl; + std::cout << "on_requested_incompatible_qos" << reader->guid() << " total_count " << status.total_count + << std::endl; } void on_liveliness_changed ( @@ -425,8 +425,8 @@ class MonitorServiceParticipant ++cb_counters_[LIVELINESS_CHANGED_IDX]; } - std::cout << "on_liveliness_changed " << reader->guid() << " not_alive_count " << status.not_alive_count << - std::endl; + std::cout << "on_liveliness_changed " << reader->guid() << " not_alive_count " << status.not_alive_count + << std::endl; } void on_subscription_matched ( @@ -438,8 +438,8 @@ class MonitorServiceParticipant ++cb_counters_[SUBSCRIPTION_MATCHED_IDX]; } - std::cout << "on_subscription_matched " << reader->guid() << " total_count " << status.total_count << - std::endl; + std::cout << "on_subscription_matched " << reader->guid() << " total_count " << status.total_count + << std::endl; } void on_sample_lost ( @@ -687,13 +687,13 @@ struct ProxySampleValidator : public SampleValidator [&](const MonitorServiceType::type& elem) { return (data.status_kind() == elem.status_kind()) && - data.local_entity() == elem.local_entity(); + data.local_entity() == elem.local_entity(); }); if (it == total_msgs.end()) { - std::cout << "Unexpected proxy " << statistics::to_fastdds_type(data.local_entity()) << - data.status_kind() << std::endl; + std::cout << "Unexpected proxy " << statistics::to_fastdds_type(data.local_entity()) + << data.status_kind() << std::endl; return; } @@ -756,7 +756,7 @@ struct ProxySampleValidator : public SampleValidator [&](const MonitorServiceType::type& elem) { return (data.status_kind() == elem.status_kind()) && - data.local_entity() == elem.local_entity(); + data.local_entity() == elem.local_entity(); }); std::cout << "Received unregistration of instance " @@ -792,8 +792,8 @@ struct ConnectionListSampleValidator : public SampleValidator for (auto& connection : data.value().connection_list()) { - std::cout << "Received Connection: \n\tMode: " << connection.mode() << - "\n\tGuid " << statistics::to_fastdds_type(connection.guid()) << "\n\t" + std::cout << "Received Connection: \n\tMode: " << connection.mode() + << "\n\tGuid " << statistics::to_fastdds_type(connection.guid()) << "\n\t" << "Announced Locators: "; for (auto& locator : connection.used_locators()) { @@ -844,9 +844,10 @@ struct ConnectionListSampleValidator : public SampleValidator EPROSIMA_LOG_ERROR(BBTestsMonitorService, "Locator not found in sample msg " << statistics::to_fastdds_type(total_msgs_elem_connection. - announced_locators()[i]) << - " for local entity " << - statistics::to_fastdds_type(total_msgs_elem.local_entity())); + announced_locators()[i]) + << " for local entity " + << statistics::to_fastdds_type( + total_msgs_elem.local_entity())); same_locators = false; break; } @@ -903,9 +904,9 @@ struct IncompatibleQoSSampleValidator : public SampleValidator [&](const MonitorServiceType::type& elem) { return (data.status_kind() == elem.status_kind()) && - (data.local_entity() == elem.local_entity()) && - (data.value().incompatible_qos_status().last_policy_id() - == elem.value().incompatible_qos_status().last_policy_id()); + (data.local_entity() == elem.local_entity()) && + (data.value().incompatible_qos_status().last_policy_id() + == elem.value().incompatible_qos_status().last_policy_id()); }); if (assert_on_non_expected_msgs_) @@ -942,9 +943,9 @@ struct LivelinessLostSampleValidator : public SampleValidator [&](const MonitorServiceType::type& elem) { return (data.status_kind() == elem.status_kind()) && - (data.local_entity() == elem.local_entity()) && - (data.value().liveliness_lost_status().total_count() - == elem.value().liveliness_lost_status().total_count()); + (data.local_entity() == elem.local_entity()) && + (data.value().liveliness_lost_status().total_count() + == elem.value().liveliness_lost_status().total_count()); }); if (assert_on_non_expected_msgs_) @@ -981,9 +982,9 @@ struct LivelinessChangedSampleValidator : public SampleValidator [&](const MonitorServiceType::type& elem) { return (data.status_kind() == elem.status_kind()) && - (data.local_entity() == elem.local_entity()) && - (data.value().liveliness_changed_status().not_alive_count() - >= elem.value().liveliness_changed_status().not_alive_count()); + (data.local_entity() == elem.local_entity()) && + (data.value().liveliness_changed_status().not_alive_count() + >= elem.value().liveliness_changed_status().not_alive_count()); }); std::cout << "Received Liveliness Changed on local_entity " @@ -1025,9 +1026,9 @@ struct DeadlineMissedSampleValidator : public SampleValidator [&](const MonitorServiceType::type& elem) { return (data.status_kind() == elem.status_kind()) && - (data.local_entity() == elem.local_entity()) && - (data.value().deadline_missed_status().total_count() - >= elem.value().deadline_missed_status().total_count()); + (data.local_entity() == elem.local_entity()) && + (data.value().deadline_missed_status().total_count() + >= elem.value().deadline_missed_status().total_count()); }); std::cout << "Received Deadline Missed on local_entity " @@ -1064,8 +1065,8 @@ struct SampleLostSampleValidator : public SampleValidator [&](const MonitorServiceType::type& elem) { return (data.status_kind() == elem.status_kind()) && - (data.local_entity() == elem.local_entity()) && - (data.value().sample_lost_status().total_count() >= 1); + (data.local_entity() == elem.local_entity()) && + (data.value().sample_lost_status().total_count() >= 1); }); std::cout << "Received Sample Lost on local_entity " diff --git a/test/blackbox/common/DDSBlackboxTestsPersistence.cpp b/test/blackbox/common/DDSBlackboxTestsPersistence.cpp index 890392c4eb4..201e5eeb032 100644 --- a/test/blackbox/common/DDSBlackboxTestsPersistence.cpp +++ b/test/blackbox/common/DDSBlackboxTestsPersistence.cpp @@ -74,9 +74,9 @@ class PersistenceLargeData : public testing::TestWithParam std::ostringstream ss; std::string test_case_name(info->test_case_name()); std::string test_name(info->name()); - ss << - test_case_name.replace(test_case_name.find_first_of('/'), 1, "_") << "_" << - test_name.replace(test_name.find_first_of('/'), 1, "_") << "_" << GET_PID() << ".db"; + ss + << test_case_name.replace(test_case_name.find_first_of('/'), 1, "_") << "_" + << test_name.replace(test_name.find_first_of('/'), 1, "_") << "_" << GET_PID() << ".db"; db_file_name_ = ss.str(); } diff --git a/test/blackbox/common/DDSBlackboxTestsPersistenceGuid.cpp b/test/blackbox/common/DDSBlackboxTestsPersistenceGuid.cpp index cd3ff101903..156009c3491 100644 --- a/test/blackbox/common/DDSBlackboxTestsPersistenceGuid.cpp +++ b/test/blackbox/common/DDSBlackboxTestsPersistenceGuid.cpp @@ -70,9 +70,9 @@ class PersistenceGuid : public ::testing::TestWithParam std::ostringstream ss; std::string test_case_name(info->test_case_name()); std::string test_name(info->name()); - ss << - test_case_name.replace(test_case_name.find_first_of('/'), 1, "_") << "_" << - test_name.replace(test_name.find_first_of('/'), 1, "_") << "_" << GET_PID() << ".db"; + ss + << test_case_name.replace(test_case_name.find_first_of('/'), 1, "_") << "_" + << test_name.replace(test_name.find_first_of('/'), 1, "_") << "_" << GET_PID() << ".db"; db_file_name = ss.str(); } @@ -101,11 +101,11 @@ class PersistenceGuid : public ::testing::TestWithParam int32_t pid = static_cast(GET_PID()); uint8_t* bytes = reinterpret_cast(&pid); std::stringstream gp; - gp << std::hex << - std::setfill('0') << std::setw(2) << static_cast(bytes[0]) << "." << - std::setfill('0') << std::setw(2) << static_cast(bytes[1]) << "." << - std::setfill('0') << std::setw(2) << static_cast(bytes[2]) << "." << - std::setfill('0') << std::setw(2) << static_cast(bytes[3]); + gp << std::hex + << std::setfill('0') << std::setw(2) << static_cast(bytes[0]) << "." + << std::setfill('0') << std::setw(2) << static_cast(bytes[1]) << "." + << std::setfill('0') << std::setw(2) << static_cast(bytes[2]) << "." + << std::setfill('0') << std::setw(2) << static_cast(bytes[3]); return gp.str(); } @@ -183,29 +183,29 @@ TEST_P(PersistenceGuid, SetPersistenceGuidThroughDDSLayer) std::stringstream command; #ifdef WIN32 // Check if there is one entry in the writers database table with the stated persistence guid - command << "python check_guid.py \"" << db_file_name << - "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; + command << "python check_guid.py \"" << db_file_name + << "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result1, 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python check_guid.py \"" << db_file_name << - "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; + command << "python check_guid.py \"" << db_file_name + << "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result2, 1); #else // Check if there is one entry in the writers database table with the stated persistence guid - command << "python3 check_guid.py '" << db_file_name << - "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; + command << "python3 check_guid.py '" << db_file_name + << "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result1 >> 8), 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python3 check_guid.py '" << db_file_name << - "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; + command << "python3 check_guid.py '" << db_file_name + << "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result2 >> 8), 1); @@ -381,28 +381,28 @@ TEST_P(PersistenceGuid, SetPersistenceGuidByXML) std::stringstream command; #ifdef WIN32 // Check if there is one entry in the writers database table with the stated persistence guid - command << "python check_guid.py \"" << db_file_name << - "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; + command << "python check_guid.py \"" << db_file_name + << "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result1, 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python check_guid.py \"" << db_file_name << - "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; + command << "python check_guid.py \"" << db_file_name + << "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result2, 1); #else - command << "python3 check_guid.py '" << db_file_name << - "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; + command << "python3 check_guid.py '" << db_file_name + << "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result1 >> 8), 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python3 check_guid.py '" << db_file_name << - "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; + command << "python3 check_guid.py '" << db_file_name + << "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result2 >> 8), 1); @@ -476,29 +476,29 @@ TEST_P(PersistenceGuid, SetPersistenceForTransientLocal) std::stringstream command; #ifdef WIN32 // Check if there is one entry in the writers database table with the stated persistence guid - command << "python check_guid.py \"" << db_file_name << - "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; + command << "python check_guid.py \"" << db_file_name + << "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result1, 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python check_guid.py \"" << db_file_name << - "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; + command << "python check_guid.py \"" << db_file_name + << "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result2, 1); #else // Check if there is one entry in the writers database table with the stated persistence guid - command << "python3 check_guid.py '" << db_file_name << - "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; + command << "python3 check_guid.py '" << db_file_name + << "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result1 >> 8), 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python3 check_guid.py '" << db_file_name << - "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; + command << "python3 check_guid.py '" << db_file_name + << "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result2 >> 8), 1); @@ -566,29 +566,29 @@ TEST_P(PersistenceGuid, NoSetPersistenceForTransientLocal) std::stringstream command; #ifdef WIN32 // Check if there is no entry in the writers database table with the stated persistence guid - command << "python check_guid.py \"" << db_file_name << - "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70.65.72.73.5f|67.75.69.64\""; + command << "python check_guid.py \"" << db_file_name + << "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70.65.72.73.5f|67.75.69.64\""; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result1, 255); // Check if there is no entry in the readers database table with the stated persistence guid - command << "python check_guid.py \"" << db_file_name << - "\" \"readers\" \"77.65.61.64.65.72.5f.70.65.72.73.5f|68.76.70.65\""; + command << "python check_guid.py \"" << db_file_name + << "\" \"readers\" \"77.65.61.64.65.72.5f.70.65.72.73.5f|68.76.70.65\""; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result2, 255); #else // Check if there is no entry in the writers database table with the stated persistence guid - command << "python3 check_guid.py '" << db_file_name << - "' 'writers_histories' '77.72.69.74.65.72.5f.70.65.72.73.5f|67.75.69.64'"; + command << "python3 check_guid.py '" << db_file_name + << "' 'writers_histories' '77.72.69.74.65.72.5f.70.65.72.73.5f|67.75.69.64'"; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result1 >> 8), 255); // Check if there is no entry in the readers database table with the stated persistence guid - command << "python3 check_guid.py '" << db_file_name << - "' 'readers' '77.65.61.64.65.72.5f.70.65.72.73.5f|68.76.70.65'"; + command << "python3 check_guid.py '" << db_file_name + << "' 'readers' '77.65.61.64.65.72.5f.70.65.72.73.5f|68.76.70.65'"; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result2 >> 8), 255); diff --git a/test/blackbox/common/RTPSBlackboxTestsBasic.cpp b/test/blackbox/common/RTPSBlackboxTestsBasic.cpp index 5fd8fc853a4..5c573a32d1c 100644 --- a/test/blackbox/common/RTPSBlackboxTestsBasic.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsBasic.cpp @@ -775,8 +775,8 @@ TEST(RTPS, MultithreadedWriterCreation) using SchedulerPolicy_t = eprosima::fastdds::rtps::FlowControllerSchedulerPolicy; auto create_flow_controller = [](const char* name, SchedulerPolicy_t scheduler, - int32_t max_bytes_per_period, - uint64_t period_ms) -> std::shared_ptr + int32_t max_bytes_per_period, + uint64_t period_ms) -> std::shared_ptr { std::shared_ptr descriptor = std::make_shared(); descriptor->name = name; diff --git a/test/blackbox/common/RTPSBlackboxTestsPersistence.cpp b/test/blackbox/common/RTPSBlackboxTestsPersistence.cpp index 737e0943b5a..48f82f7f263 100644 --- a/test/blackbox/common/RTPSBlackboxTestsPersistence.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsPersistence.cpp @@ -136,9 +136,9 @@ class Persistence : public ::testing::TestWithParam std::ostringstream ss; std::string test_case_name(info->test_case_name()); std::string test_name(info->name()); - ss << - test_case_name.replace(test_case_name.find_first_of('/'), 1, "_") << "_" << - test_name.replace(test_name.find_first_of('/'), 1, "_") << "_" << GET_PID() << ".db"; + ss + << test_case_name.replace(test_case_name.find_first_of('/'), 1, "_") << "_" + << test_name.replace(test_name.find_first_of('/'), 1, "_") << "_" << GET_PID() << ".db"; db_file_name_ = ss.str(); // Fill guid prefix diff --git a/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp b/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp index d836304e571..6250f362eab 100644 --- a/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp @@ -78,11 +78,11 @@ class PersistenceGuid : public ::testing::TestWithParam int32_t pid = static_cast(GET_PID()); uint8_t* bytes = reinterpret_cast(&pid); std::stringstream gp; - gp << std::hex << - std::setfill('0') << std::setw(2) << static_cast(bytes[0]) << "." << - std::setfill('0') << std::setw(2) << static_cast(bytes[1]) << "." << - std::setfill('0') << std::setw(2) << static_cast(bytes[2]) << "." << - std::setfill('0') << std::setw(2) << static_cast(bytes[3]); + gp << std::hex + << std::setfill('0') << std::setw(2) << static_cast(bytes[0]) << "." + << std::setfill('0') << std::setw(2) << static_cast(bytes[1]) << "." + << std::setfill('0') << std::setw(2) << static_cast(bytes[2]) << "." + << std::setfill('0') << std::setw(2) << static_cast(bytes[3]); return gp.str(); } @@ -153,29 +153,29 @@ TEST_P(PersistenceGuid, SetPersistenceGuidThroughRTPSLayer) std::stringstream command; #ifdef WIN32 // Check if there is one entry in the writers database table with the stated persistence guid - command << "python check_guid.py \"" << persistence_db << - "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; + command << "python check_guid.py \"" << persistence_db + << "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result1, 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python check_guid.py \"" << persistence_db << - "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; + command << "python check_guid.py \"" << persistence_db + << "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result2, 1); #else // Check if there is one entry in the writers database table with the stated persistence guid - command << "python3 check_guid.py '" << persistence_db << - "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; + command << "python3 check_guid.py '" << persistence_db + << "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result1 >> 8), 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python3 check_guid.py '" << persistence_db << - "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; + command << "python3 check_guid.py '" << persistence_db + << "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result2 >> 8), 1); @@ -257,57 +257,57 @@ TEST_P(PersistenceGuid, CheckPrevalenceBetweenManualAndPropertyConfiguration) std::stringstream command; #ifdef WIN32 // Check if there is one entry in the writers database table with the stated persistence guid - command << "python check_guid.py \"" << persistence_db << - "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; + command << "python check_guid.py \"" << persistence_db + << "\" \"writers_histories\" \"77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64\""; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result1, 0); // Check if there is one entry in the writers database table with the stated persistence guid - command << "python check_guid.py \"" << persistence_db << - "\" \"writers_histories\" \"00.00.00.00.00.00.00.00." << guidprefix_4 << "|0.0.0.1\""; + command << "python check_guid.py \"" << persistence_db + << "\" \"writers_histories\" \"00.00.00.00.00.00.00.00." << guidprefix_4 << "|0.0.0.1\""; result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result1, 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python check_guid.py \"" << persistence_db << - "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; + command << "python check_guid.py \"" << persistence_db + << "\" \"readers\" \"77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65\""; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result2, 0); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python check_guid.py \"" << persistence_db << - "\" \"readers\" \"00.00.00.00.00.00.00.00." << guidprefix_4 << "|0.0.0.2\""; + command << "python check_guid.py \"" << persistence_db + << "\" \"readers\" \"00.00.00.00.00.00.00.00." << guidprefix_4 << "|0.0.0.2\""; result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ(result2, 1); #else // Check if there is one entry in the writers database table with the stated persistence guid - command << "python3 check_guid.py '" << persistence_db << - "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; + command << "python3 check_guid.py '" << persistence_db + << "' 'writers_histories' '77.72.69.74.65.72.5f.70." << guidprefix_4 << "|67.75.69.64'"; int result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result1 >> 8), 0); // Check if there is one entry in the writers database table with the stated persistence guid - command << "python3 check_guid.py '" << persistence_db << - "' 'writers_histories' '00.00.00.00.00.00.00.00." << guidprefix_4 << "|0.0.0.1'"; + command << "python3 check_guid.py '" << persistence_db + << "' 'writers_histories' '00.00.00.00.00.00.00.00." << guidprefix_4 << "|0.0.0.1'"; result1 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result1 >> 8), 1); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python3 check_guid.py '" << persistence_db << - "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; + command << "python3 check_guid.py '" << persistence_db + << "' 'readers' '77.65.61.64.65.72.5f.70." << guidprefix_4 << "|68.76.70.65'"; int result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result2 >> 8), 0); // Check if there is one entry in the readers database table with the stated persistence guid - command << "python3 check_guid.py '" << persistence_db << - "' 'readers' '00.00.00.00.00.00.00.00." << guidprefix_4 << "|0.0.0.2'"; + command << "python3 check_guid.py '" << persistence_db + << "' 'readers' '00.00.00.00.00.00.00.00." << guidprefix_4 << "|0.0.0.2'"; result2 = system(command.str().c_str()); command.str(""); ASSERT_EQ((result2 >> 8), 1); diff --git a/test/blackbox/common/RTPSBlackboxTestsPools.cpp b/test/blackbox/common/RTPSBlackboxTestsPools.cpp index c312f556884..2aa4d6c95ac 100644 --- a/test/blackbox/common/RTPSBlackboxTestsPools.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsPools.cpp @@ -240,7 +240,7 @@ class PoolForTest : public IPayloadPool std::vector free_payloads_; }; -template +template void do_test( const std::string& topic_name, std::list& data, diff --git a/test/unittest/transport/TCPv4Tests.cpp b/test/unittest/transport/TCPv4Tests.cpp index 65532c5cdfa..4495ea951ef 100644 --- a/test/unittest/transport/TCPv4Tests.cpp +++ b/test/unittest/transport/TCPv4Tests.cpp @@ -1495,7 +1495,8 @@ TEST_F(TCPv4Tests, secure_non_blocking_send) auto sender_unbound_channel_resources = senderTransportUnderTest.get_unbound_channel_resources(); ASSERT_TRUE(sender_unbound_channel_resources.size() == 1u); auto sender_channel_resource = - std::static_pointer_cast(sender_unbound_channel_resources[0]); + std::static_pointer_cast( + sender_unbound_channel_resources[0]); // Prepare the message std::vector message(msg_size, 0); From 8e3240e510433ad35ca84a684c5697aa98b6fe0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ferreira=20Gonz=C3=A1lez?= Date: Fri, 24 Jul 2026 11:57:50 +0200 Subject: [PATCH 4/4] Build UBSan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Ferreira González --- test/unittest/rtps/flowcontrol/CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/unittest/rtps/flowcontrol/CMakeLists.txt b/test/unittest/rtps/flowcontrol/CMakeLists.txt index b5c706ae2d1..9492c27d84c 100644 --- a/test/unittest/rtps/flowcontrol/CMakeLists.txt +++ b/test/unittest/rtps/flowcontrol/CMakeLists.txt @@ -52,7 +52,10 @@ target_compile_definitions(FlowControllerFactoryTests PRIVATE target_include_directories(FlowControllerFactoryTests PRIVATE ${Asio_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSWriter + ${PROJECT_SOURCE_DIR}/test/mock/rtps/Endpoint + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSReader ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSMessageGroup + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSParticipantImpl ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/src/cpp ) @@ -86,7 +89,10 @@ target_compile_definitions(FlowControllerPublishModesTests PRIVATE target_include_directories(FlowControllerPublishModesTests PRIVATE ${Asio_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSWriter + ${PROJECT_SOURCE_DIR}/test/mock/rtps/Endpoint + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSReader ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSMessageGroup + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSParticipantImpl ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/src/cpp ) @@ -116,7 +122,10 @@ target_compile_definitions(FlowControllerSchedulersTests PRIVATE target_include_directories(FlowControllerSchedulersTests PRIVATE ${Asio_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSWriter + ${PROJECT_SOURCE_DIR}/test/mock/rtps/Endpoint + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSReader ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSMessageGroup + ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSParticipantImpl ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include ${PROJECT_SOURCE_DIR}/src/cpp )