From 8776b8e8adbf86bcb3b3124eb237f3a823aa2958 Mon Sep 17 00:00:00 2001 From: "Dennis Lambe Jr." Date: Mon, 14 Apr 2025 15:16:57 -0400 Subject: [PATCH 1/4] add DEF_SOURCE_LINE to ctests GoogleTest sets this property on ctest tests, and vscode-cmake-tools will use it to dramatically improve the Test Explorer user experience. CppUTest doesn't record file paths or line numbers for test groups, only for tests, so when CPPUTEST_TESTS_DETAILED=0, use the lowest line number of the tests in that group. --- cmake/Modules/_CppUTestDiscovery.cmake | 75 ++++++++++++++++++-------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/cmake/Modules/_CppUTestDiscovery.cmake b/cmake/Modules/_CppUTestDiscovery.cmake index c4e94003e..88f1961e3 100644 --- a/cmake/Modules/_CppUTestDiscovery.cmake +++ b/cmake/Modules/_CppUTestDiscovery.cmake @@ -1,4 +1,4 @@ -set(script) +set(script "" CACHE INTERNAL "") function(add_command NAME) set(_args "") @@ -12,7 +12,7 @@ function(add_command NAME) set(_args "${_args} ${_arg}") endif() endforeach() - set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE) + set(script "${script}${NAME}(${_args})\n" CACHE INTERNAL "") endfunction() if(NOT EXISTS "${EXECUTABLE}") @@ -21,16 +21,27 @@ if(NOT EXISTS "${EXECUTABLE}") ) endif() -if(TESTS_DETAILED) - set(discovery_arg "-ln") - set(select_arg "-st") -else() - set(discovery_arg "-lg") - set(select_arg "-sg") -endif() +function (add_test_to_script TEST_NAME TEST_LOCATION SELECT_ARG) + add_command( + add_test + "${TEST_NAME}" + ${EMULATOR} + "${EXECUTABLE}" + ${ARGS} + ${SELECT_ARG} + ${TEST_NAME} + ) + add_command( + set_tests_properties + "${TEST_NAME}" + PROPERTIES + DEF_SOURCE_LINE + "${TEST_LOCATION}" + ) +endfunction() execute_process( - COMMAND ${EMULATOR} "${EXECUTABLE}" ${discovery_arg} + COMMAND ${EMULATOR} "${EXECUTABLE}" -ll OUTPUT_VARIABLE discovered_tests RESULT_VARIABLE result ERROR_VARIABLE error @@ -41,17 +52,37 @@ if(NOT ${result} EQUAL 0) "${error}" ) endif() -separate_arguments(discovered_tests) -foreach(test_name IN LISTS discovered_tests) - add_command( - add_test - "${test_name}" - ${EMULATOR} - "${EXECUTABLE}" - ${ARGS} - ${select_arg} - ${test_name} - ) -endforeach() + +set(LL_LINE_REGEX "^([^.]*)\\.([^.]*)\\.(.*)\\.([^.]*)\n") +string(REGEX MATCHALL "[^\n]+\n" discovered_test_lines "${discovered_tests}") +if(TESTS_DETAILED) + foreach(line IN LISTS discovered_test_lines) + string(REGEX MATCH "${LL_LINE_REGEX}" __ign "${line}") + set(test_name "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}") + set(test_location "${CMAKE_MATCH_3}:${CMAKE_MATCH_4}") + add_test_to_script("${test_name}" "${test_location}" -st) + endforeach() +else() + foreach(line IN LISTS discovered_test_lines) + string(REGEX MATCH "${LL_LINE_REGEX}" __ign "${line}") + set(test_name "${CMAKE_MATCH_1}") + set(test_file "${CMAKE_MATCH_3}") + set(test_line "${CMAKE_MATCH_4}") + if (NOT _${test_name}_file) + # if the group spans two files, arbitrarily choose the first one encountered + set(_${test_name}_file "${test_file}") + set(_${test_name}_line "${test_line}") + elseif(test_file STREQUAL _${test_name}_file AND test_line LESS _${test_name}_line) + # line number will eventually be the first line of the first test in the group's file + set(_${test_name}_line ${test_line}) + endif() + list(APPEND groups_seen ${test_name}) + endforeach() + list(REMOVE_DUPLICATES groups_seen) + foreach(test_name IN LISTS groups_seen) + set(test_location "${_${test_name}_file}:${_${test_name}_line}") + add_test_to_script("${test_name}" "${test_location}" -sg) + endforeach() +endif() file(WRITE "${CTEST_FILE}" "${script}") From 8dd7f6d4e518d3e7e0bd3caf4464df6e53448852 Mon Sep 17 00:00:00 2001 From: "Dennis Lambe Jr." Date: Mon, 14 Apr 2025 23:39:29 -0400 Subject: [PATCH 2/4] document ctest -ll parsing regex --- cmake/Modules/_CppUTestDiscovery.cmake | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmake/Modules/_CppUTestDiscovery.cmake b/cmake/Modules/_CppUTestDiscovery.cmake index 88f1961e3..df7aed8f9 100644 --- a/cmake/Modules/_CppUTestDiscovery.cmake +++ b/cmake/Modules/_CppUTestDiscovery.cmake @@ -53,7 +53,16 @@ if(NOT ${result} EQUAL 0) ) endif() -set(LL_LINE_REGEX "^([^.]*)\\.([^.]*)\\.(.*)\\.([^.]*)\n") +string(CONCAT LL_LINE_REGEX + "^([^.]*)" # test group + "\\." + "([^.]*)" # test name + "\\." + "(.*)" # file name (only this field is allowed to contain dots) + "\\." + "([^.]*)" # line number + "\n" +) string(REGEX MATCHALL "[^\n]+\n" discovered_test_lines "${discovered_tests}") if(TESTS_DETAILED) foreach(line IN LISTS discovered_test_lines) From cde20a40779e13a2362d9ae4e616f68b504c262f Mon Sep 17 00:00:00 2001 From: "Dennis Lambe Jr." Date: Mon, 14 Apr 2025 23:43:11 -0400 Subject: [PATCH 3/4] clearer ident names in ctest -ll regex application addresses review comment from @thetic. --- cmake/Modules/_CppUTestDiscovery.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/_CppUTestDiscovery.cmake b/cmake/Modules/_CppUTestDiscovery.cmake index df7aed8f9..3a7bb66f5 100644 --- a/cmake/Modules/_CppUTestDiscovery.cmake +++ b/cmake/Modules/_CppUTestDiscovery.cmake @@ -66,14 +66,14 @@ string(CONCAT LL_LINE_REGEX string(REGEX MATCHALL "[^\n]+\n" discovered_test_lines "${discovered_tests}") if(TESTS_DETAILED) foreach(line IN LISTS discovered_test_lines) - string(REGEX MATCH "${LL_LINE_REGEX}" __ign "${line}") + string(REGEX MATCH "${LL_LINE_REGEX}" __unused "${line}") set(test_name "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}") set(test_location "${CMAKE_MATCH_3}:${CMAKE_MATCH_4}") add_test_to_script("${test_name}" "${test_location}" -st) endforeach() else() foreach(line IN LISTS discovered_test_lines) - string(REGEX MATCH "${LL_LINE_REGEX}" __ign "${line}") + string(REGEX MATCH "${LL_LINE_REGEX}" __unused "${line}") set(test_name "${CMAKE_MATCH_1}") set(test_file "${CMAKE_MATCH_3}") set(test_line "${CMAKE_MATCH_4}") From 7395fe067d786e1e5852b8d7e47a05c0e17934b2 Mon Sep 17 00:00:00 2001 From: "Dennis Lambe Jr." Date: Mon, 14 Apr 2025 23:51:25 -0400 Subject: [PATCH 4/4] convert add_test_to_script() to macro This avoids creating an additional scope, meaning I can revert my previous complicating changes to add_command(). addresses review comment from @thetic. --- cmake/Modules/_CppUTestDiscovery.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/Modules/_CppUTestDiscovery.cmake b/cmake/Modules/_CppUTestDiscovery.cmake index 3a7bb66f5..2b36a73ed 100644 --- a/cmake/Modules/_CppUTestDiscovery.cmake +++ b/cmake/Modules/_CppUTestDiscovery.cmake @@ -1,4 +1,4 @@ -set(script "" CACHE INTERNAL "") +set(script) function(add_command NAME) set(_args "") @@ -12,7 +12,7 @@ function(add_command NAME) set(_args "${_args} ${_arg}") endif() endforeach() - set(script "${script}${NAME}(${_args})\n" CACHE INTERNAL "") + set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE) endfunction() if(NOT EXISTS "${EXECUTABLE}") @@ -21,7 +21,7 @@ if(NOT EXISTS "${EXECUTABLE}") ) endif() -function (add_test_to_script TEST_NAME TEST_LOCATION SELECT_ARG) +macro(add_test_to_script TEST_NAME TEST_LOCATION SELECT_ARG) add_command( add_test "${TEST_NAME}" @@ -38,7 +38,7 @@ function (add_test_to_script TEST_NAME TEST_LOCATION SELECT_ARG) DEF_SOURCE_LINE "${TEST_LOCATION}" ) -endfunction() +endmacro() execute_process( COMMAND ${EMULATOR} "${EXECUTABLE}" -ll