diff options
| author | Frédéric Desbiens <[email protected]> | 2026-10-02 10:42:44 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-10-02 10:42:44 -0400 |
| commit | 93387b0a60382a29579bbad5045c68328e3751df (patch) | |
| tree | 42be790d602cb76f55090e5a7c418df7ea2b3428 /test/smp/cmake | |
| parent | 44d7c95c582d415c4ad84527180b29c93c3bf664 (diff) | |
| parent | 28281cd5647d4671236ca08d19bd18ed15b2265a (diff) | |
Merge pull request #783 from eclipse-threadx/devv6.5.2.202603_rel
Merged changes ahead of the v6.5.2.202603 release
Diffstat (limited to 'test/smp/cmake')
| -rw-r--r-- | test/smp/cmake/CMakeLists.txt | 16 | ||||
| -rwxr-xr-x | test/smp/cmake/coverage.sh | 146 | ||||
| -rw-r--r-- | test/smp/cmake/regression/CMakeLists.txt | 24 | ||||
| -rw-r--r-- | test/smp/cmake/threadx_smp/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | test/smp/cmake/threadx_smp/common_smp/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | test/smp/cmake/threadx_smp/ports_smp/linux/gnu/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | test/smp/cmake/threadx_smp/ports_smp/win64/vs_2022/CMakeLists.txt | 1 |
7 files changed, 185 insertions, 5 deletions
diff --git a/test/smp/cmake/CMakeLists.txt b/test/smp/cmake/CMakeLists.txt index e2ca8627..3a0d9638 100644 --- a/test/smp/cmake/CMakeLists.txt +++ b/test/smp/cmake/CMakeLists.txt @@ -64,7 +64,21 @@ add_subdirectory(regression) add_subdirectory(samples) # Coverage -if(CMAKE_BUILD_TYPE MATCHES ".*_coverage") +# +# The gate here used to be the build type alone, and only one of the five +# configurations -- default_build_coverage -- has a name matching "*_coverage". +# So four configurations built and ran every test and their coverage was thrown +# away. That is not redundancy discarded: each configuration selects a different +# set of TX_ feature macros, so the code the other four compile is *absent from +# the denominator* rather than reported as uncovered. A figure taken from one of +# them is the executable-line count of one configuration, not of the kernel. +# +# TX_COVERAGE instruments a build regardless of its name. It defaults to OFF and +# the build-type match is kept, so configuring a single configuration by hand +# behaves exactly as it did before; the regression run turns it on for all five +# and merges the results. +option(TX_COVERAGE "Instrument this build for coverage regardless of build type" OFF) +if(TX_COVERAGE OR CMAKE_BUILD_TYPE MATCHES ".*_coverage") if(NOT MSVC) target_compile_options(threadx_smp PRIVATE -fprofile-arcs -ftest-coverage) target_link_options(threadx_smp PRIVATE -fprofile-arcs -ftest-coverage) diff --git a/test/smp/cmake/coverage.sh b/test/smp/cmake/coverage.sh index d35284f5..88de4f04 100755 --- a/test/smp/cmake/coverage.sh +++ b/test/smp/cmake/coverage.sh @@ -14,7 +14,145 @@ set -e cd $(dirname $0) -threadx_smp=$(realpath ../../../common_smp/src) -mkdir -p coverage_report/$1 -gcovr --object-directory=build/$1/threadx_smp/CMakeFiles/threadx_smp.dir/$threadx_smp -r build/$1 -f ../../../common_smp/src --xml-pretty --output coverage_report/$1.xml -gcovr --object-directory=build/$1/threadx_smp/CMakeFiles/threadx_smp.dir/$threadx_smp -r build/$1 -f ../../../common_smp/src --html --html-details --output coverage_report/$1/index.html + +# gcov reads a data format tied to the compiler that produced it, so gcov has to match +# the gcc that built the objects. Since cmake/linux.cmake began honouring CC, taking +# whatever gcov happens to be first on PATH is no longer safe: building with gcc-14 and +# reading with gcov-13 gives "version 'B42*', prefer 'B33*'" from gcov, and gcovr turns +# that into "GCOV returncode was 3" and exits 64. The tests pass and then the coverage +# step fails with a Python traceback, which reads like a coverage bug rather than a +# toolchain mismatch. +# +# So derive gcov from CC rather than asking the caller to remember both. GCOV still +# overrides, for a toolchain that does not follow the gcc/gcov naming. +: "${CC:=gcc}" +if [ -z "${GCOV:-}" ]; then + cc_base=$(basename "$CC") + case "$cc_base" in + gcc*) GCOV="gcov${cc_base#gcc}" ;; + *) GCOV="gcov" ;; + esac +fi + +if ! command -v "$GCOV" >/dev/null 2>&1; then + echo "coverage.sh: '$GCOV' not found, derived from CC='$CC'." >&2 + echo "Install it, or set GCOV to the gcov matching that compiler." >&2 + exit 1 +fi + +# The repository root, needed by every mode below. It has to be absolute: see the +# note on the per-configuration paths further down. +repo_root=$(cd ../../.. && pwd) +filter=$repo_root/common_smp/src + +# --merge unions the per-configuration reports into the one number that means +# something. Each configuration writes an intermediate JSON beside its XML, and +# this pass adds them all together. +# +# Reporting five separate percentages instead would invite a reader to average +# them, and an average is not a coverage figure -- a line covered only by +# trace_build is covered, and only the union says so. +# +# Do not be alarmed when the merged percentage is lower than the single +# configuration this used to report. That is the point: the denominator now +# includes code the old report never counted at all, because it was compiled out +# of the only instrumented build. +if [ "$1" = "--merge" ]; then + shopt -s nullglob + tracefiles=(coverage_report/per_configuration/*.json) + shopt -u nullglob + if [ ${#tracefiles[@]} -eq 0 ]; then + echo "coverage.sh --merge: no JSON in coverage_report/per_configuration/." >&2 + echo "Run the suites with TX_COVERAGE=ON first." >&2 + exit 1 + fi + + add_args=() + for t in "${tracefiles[@]}"; do + add_args+=(--add-tracefile "$t") + done + + mkdir -p coverage_report/merged + gcovr -r "$repo_root" "${add_args[@]}" --xml-pretty --output coverage_report/merged.xml + gcovr -r "$repo_root" "${add_args[@]}" --html --html-details --output coverage_report/merged/index.html + + if ! grep -q "<class " coverage_report/merged.xml; then + echo "coverage.sh --merge: the merged report contains no files." >&2 + exit 1 + fi + + # Named, not just counted. coverage_report/ is not cleaned between runs, so a + # tracefile left by an earlier run of a different set of configurations would + # otherwise be merged in without anything saying so. + echo "coverage.sh --merge: SMP, ${#tracefiles[@]} configuration(s):" + for t in "${tracefiles[@]}"; do + echo " $(basename "$t" .json)" + done + exit 0 +fi + +# gcovr is given three paths below, and each of them has to be absolute, for a +# different reason. +# +# -r is the repository root rather than the build directory, so the report names +# files the way the repository does -- "common_smp/src/tx_block_allocate.c" +# instead of "/home/runner/work/threadx/threadx/common_smp/src/tx_block_allocate.c". +# With -r inside build/, gcovr cannot express the sources relative to it, because +# they are outside it, and falls back to absolute paths. Those paths then differ +# on every machine and disagree with the <source> element written beside them in +# the same file, so anything that maps coverage back to the repository -- PR +# annotations, Codecov, SonarQube -- cannot follow them. +# +# Both -r and -f must be absolute. "-r ../../.. -f common_smp/src" produces a +# report containing zero files and exits 0, which is the worst failure mode +# available here: a green run carrying an empty report. Measured, not assumed. +repo_root=$(cd ../../.. && pwd) + +# This is what actually scopes the report to one build configuration, and it is +# the positional search path -- not --object-directory, which used to be here +# and was doing nothing at all. That flag tells gcovr how to get from a gcda +# file back to the compiler's working directory; it does not restrict which gcda +# files are found. Pointed at an empty directory it still produced the full +# report, because gcovr searches -r as well. +# +# That matters more now than it did before. While -r was build/$1 it happened to +# constrain the search to this configuration by accident. -r is the repository +# root now, and every configuration's gcda lies somewhere under it, so without +# an explicit search path the report would silently merge all five. +# +# The odd shape of this path is CMake's, not ours: common_smp/src sits outside +# this directory's source tree, so CMake mangles each source file's absolute +# path into the object path, minus the leading slash. Hence the concatenation +# rather than a join -- $repo_root already begins with one. +objdir=$PWD/build/$1/threadx_smp/CMakeFiles/threadx_smp.dir$repo_root/common_smp/src + +# The Linux port's own sources are deliberately outside -f. gcno files exist for +# two directories -- common_smp/src and ports_smp/linux/gnu/src -- and only the +# first is reported. The kernel is what this suite is here to cover; the +# architecture ports are validated functionally rather than structurally, and +# linux/gnu is a development host port that nothing ships on. Written down +# because a filter argument on its own is not a decision the next reader can see. + +# Per-configuration output is kept in a subdirectory of its own, and the merged +# report sits alongside it at the top. That is not tidiness: the Pages deploy +# uploads coverage_report wholesale and merges the ThreadX and SMP artifacts +# into one tree, and every configuration directory has the same name in both +# suites. Left at the top level, default_build_coverage/ from one suite would +# overwrite the other's on the published site. Nested here, the top level still +# holds exactly the one suite directory the deploy expects. +mkdir -p coverage_report/per_configuration/$1 +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" \ + --json coverage_report/per_configuration/$1.json \ + --xml-pretty --output coverage_report/per_configuration/$1.xml +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --html --html-details --output coverage_report/per_configuration/$1/index.html + +# An empty report is not an error as far as gcovr is concerned: it warns and +# exits 0. Worse, it advertises line-rate="1.0" alongside lines-valid="0", so +# every downstream consumer reads "no data at all" as "100% covered". A coverage +# threshold cannot catch that, because an empty report passes any threshold. So +# the assertion belongs here, next to the paths that would cause it. +if ! grep -q "<class " coverage_report/per_configuration/$1.xml; then + echo "coverage.sh: the report for '$1' contains no files." >&2 + echo "Expected gcda files under $objdir." >&2 + exit 1 +fi diff --git a/test/smp/cmake/regression/CMakeLists.txt b/test/smp/cmake/regression/CMakeLists.txt index b448ae3e..cdf0c585 100644 --- a/test/smp/cmake/regression/CMakeLists.txt +++ b/test/smp/cmake/regression/CMakeLists.txt @@ -25,6 +25,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_block_memory_thread_terminate_test.c ${SOURCE_DIR}/threadx_byte_memory_basic_test.c ${SOURCE_DIR}/threadx_byte_memory_information_test.c + ${SOURCE_DIR}/threadx_byte_memory_long_search_test.c ${SOURCE_DIR}/threadx_byte_memory_prioritize_test.c ${SOURCE_DIR}/threadx_byte_memory_suspension_test.c ${SOURCE_DIR}/threadx_byte_memory_suspension_timeout_test.c @@ -52,6 +53,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_mutex_proritize_test.c ${SOURCE_DIR}/threadx_mutex_suspension_timeout_test.c ${SOURCE_DIR}/threadx_mutex_thread_terminate_test.c + ${SOURCE_DIR}/threadx_object_delete_suspension_test.c ${SOURCE_DIR}/threadx_queue_basic_eight_word_test.c ${SOURCE_DIR}/threadx_queue_basic_four_word_test.c ${SOURCE_DIR}/threadx_queue_basic_one_word_test.c @@ -84,6 +86,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_smp_random_resume_suspend_exclusion_test.c ${SOURCE_DIR}/threadx_smp_random_resume_suspend_test.c ${SOURCE_DIR}/threadx_smp_rebalance_exclusion_test.c + ${SOURCE_DIR}/threadx_smp_relinquish_rebalance_test.c ${SOURCE_DIR}/threadx_smp_relinquish_test.c ${SOURCE_DIR}/threadx_smp_resume_suspend_ascending_order_test.c ${SOURCE_DIR}/threadx_smp_resume_suspend_descending_order_test.c @@ -95,6 +98,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_thread_create_preemption_threshold_test.c ${SOURCE_DIR}/threadx_thread_delayed_suspension_test.c ${SOURCE_DIR}/threadx_thread_information_test.c + ${SOURCE_DIR}/threadx_thread_misaligned_stack_test.c ${SOURCE_DIR}/threadx_thread_multi_level_preemption_threshold_test.c ${SOURCE_DIR}/threadx_thread_multiple_non_current_test.c ${SOURCE_DIR}/threadx_thread_multiple_sleep_test.c @@ -111,7 +115,10 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_thread_sleep_for_100ticks_test.c ${SOURCE_DIR}/threadx_thread_sleep_terminate_test.c ${SOURCE_DIR}/threadx_thread_stack_checking_test.c + ${SOURCE_DIR}/threadx_thread_stack_fill_value_test.c ${SOURCE_DIR}/threadx_thread_terminate_delete_test.c + ${SOURCE_DIR}/threadx_thread_exit_callback_transition_test.c + ${SOURCE_DIR}/threadx_smp_thread_exit_callback_remote_test.c ${SOURCE_DIR}/threadx_thread_time_slice_change_test.c ${SOURCE_DIR}/threadx_thread_wait_abort_and_isr_test.c ${SOURCE_DIR}/threadx_thread_wait_abort_test.c @@ -124,6 +131,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_timer_multiple_test.c ${SOURCE_DIR}/threadx_timer_simple_test.c ${SOURCE_DIR}/threadx_trace_basic_test.c + ${SOURCE_DIR}/threadx_trace_entry_update_test.c ${SOURCE_DIR}/threadx_initialize_kernel_setup_test.c) add_custom_command( @@ -162,3 +170,19 @@ foreach(test_case ${regression_test_cases}) target_link_libraries(${test_name} PRIVATE azrtos::threadx_smp) add_test(${CMAKE_BUILD_TYPE}::${test_name} ${test_name}) endforeach() + +add_executable(threadx_smp_execution_profile_get_test + ${SOURCE_DIR}/threadx_smp_execution_profile_get_test.c + ${REPO_ROOT}/utility/execution_profile_kit/smp_version/tx_execution_profile.c) +target_include_directories(threadx_smp_execution_profile_get_test + PRIVATE + ${SOURCE_DIR}/execution_profile_test + ${REPO_ROOT}/utility/execution_profile_kit/smp_version) +target_compile_definitions(threadx_smp_execution_profile_get_test + PRIVATE CTEST BATCH_TEST TEST_STACK_SIZE_PRINTF=4096) +if(NOT MSVC) + target_compile_options(threadx_smp_execution_profile_get_test PRIVATE -m64) + target_link_options(threadx_smp_execution_profile_get_test PRIVATE -m64) +endif() +add_test(${CMAKE_BUILD_TYPE}::threadx_smp_execution_profile_get_test + threadx_smp_execution_profile_get_test) diff --git a/test/smp/cmake/threadx_smp/CMakeLists.txt b/test/smp/cmake/threadx_smp/CMakeLists.txt index 568fece4..a2e17636 100644 --- a/test/smp/cmake/threadx_smp/CMakeLists.txt +++ b/test/smp/cmake/threadx_smp/CMakeLists.txt @@ -45,6 +45,7 @@ else() endif() configure_file(${TX_USER_FILE} ${CUSTOM_INC_DIR}/tx_user.h COPYONLY) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CUSTOM_INC_DIR} ) diff --git a/test/smp/cmake/threadx_smp/common_smp/CMakeLists.txt b/test/smp/cmake/threadx_smp/common_smp/CMakeLists.txt index 646b200b..770379af 100644 --- a/test/smp/cmake/threadx_smp/common_smp/CMakeLists.txt +++ b/test/smp/cmake/threadx_smp/common_smp/CMakeLists.txt @@ -214,6 +214,7 @@ target_sources(${PROJECT_NAME} # Add the Common/inc directory to the project include list target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CURRENT_DIR}/inc ) diff --git a/test/smp/cmake/threadx_smp/ports_smp/linux/gnu/CMakeLists.txt b/test/smp/cmake/threadx_smp/ports_smp/linux/gnu/CMakeLists.txt index 9c51522c..64d97255 100644 --- a/test/smp/cmake/threadx_smp/ports_smp/linux/gnu/CMakeLists.txt +++ b/test/smp/cmake/threadx_smp/ports_smp/linux/gnu/CMakeLists.txt @@ -25,6 +25,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CURRENT_DIR}/inc ) diff --git a/test/smp/cmake/threadx_smp/ports_smp/win64/vs_2022/CMakeLists.txt b/test/smp/cmake/threadx_smp/ports_smp/win64/vs_2022/CMakeLists.txt index 6b219bb2..8635647a 100644 --- a/test/smp/cmake/threadx_smp/ports_smp/win64/vs_2022/CMakeLists.txt +++ b/test/smp/cmake/threadx_smp/ports_smp/win64/vs_2022/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CURRENT_DIR}/inc ) |
