From 064576520b544f9d06d2be698e1dc84d3a39edca Mon Sep 17 00:00:00 2001 From: Uy Ha Date: Sun, 21 May 2023 15:02:17 +0300 Subject: [PATCH 1/4] Add test tags as cmake label This allows people running `cmake -L 'tag'` to run tests matching the tags --- extras/CatchAddTests.cmake | 85 +++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/extras/CatchAddTests.cmake b/extras/CatchAddTests.cmake index 692e340566..342edfd655 100644 --- a/extras/CatchAddTests.cmake +++ b/extras/CatchAddTests.cmake @@ -61,7 +61,7 @@ function(catch_discover_tests_impl) endif() execute_process( - COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" ${spec} --list-tests --verbosity quiet + COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" ${spec} --list-tests --verbosity normal OUTPUT_VARIABLE output RESULT_VARIABLE result WORKING_DIRECTORY "${_TEST_WORKING_DIR}" @@ -78,7 +78,11 @@ function(catch_discover_tests_impl) # that'd break the foreach loop for "Parse output" later and create # wrongly splitted and thus failing test cases (false positives) string(REPLACE ";" "\;" output "${output}") + string(STRIP "${output}" output) string(REPLACE "\n" ";" output "${output}") + list(LENGTH output length) + math(EXPR length "${length} - 2") + list(SUBLIST output 1 "${length}" output) # Prepare reporter if(reporter) @@ -123,44 +127,57 @@ function(catch_discover_tests_impl) # Parse output foreach(line ${output}) - set(test "${line}") - # Escape characters in test case names that would be parsed by Catch2 - # Note that the \ escaping must happen FIRST! Do not change the order. - set(test_name "${test}") - foreach(char \\ , [ ]) - string(REPLACE ${char} "\\${char}" test_name "${test_name}") - endforeach(char) - # ...add output dir - if(output_dir) - string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean "${test_name}") - set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") - endif() - - # ...and add to script - add_command(add_test - "${prefix}${test}${suffix}" - ${_TEST_EXECUTOR} - "${_TEST_EXECUTABLE}" - "${test_name}" - ${extra_args} - "${reporter_arg}" - "${output_dir_arg}" - ) - add_command(set_tests_properties - "${prefix}${test}${suffix}" - PROPERTIES - WORKING_DIRECTORY "${_TEST_WORKING_DIR}" - ${properties} - ) + if(line MATCHES "^ ([^ ].*)$") + set(test ${line}) + # Escape characters in test case names that would be parsed by Catch2 + # Note that the \ escaping must happen FIRST! Do not change the order. + set(test_name ${test}) + foreach(char \\ , [ ]) + string(REPLACE ${char} "\\${char}" test_name ${test_name}) + endforeach(char) + # ...add output dir + if(output_dir) + string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name}) + set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") + endif() + + # ...and add to script + add_command(add_test + "${prefix}${test}${suffix}" + ${_TEST_EXECUTOR} + "${_TEST_EXECUTABLE}" + "${test_name}" + ${extra_args} + "${reporter_arg}" + "${output_dir_arg}" + ) + add_command(set_tests_properties + "${prefix}${test}${suffix}" + PROPERTIES + WORKING_DIRECTORY "${_TEST_WORKING_DIR}" + ${properties} + ) + + if(environment_modifications) + add_command(set_tests_properties + "${prefix}${test}${suffix}" + PROPERTIES + ENVIRONMENT_MODIFICATION "${environment_modifications}") + endif() + + list(APPEND tests "${prefix}${test}${suffix}") + elseif(line MATCHES "^ (.*)$") + set(tags "${CMAKE_MATCH_1}") + string(REGEX REPLACE "^\\[" "" tags "${tags}") + string(REGEX REPLACE "\\]$" "" tags "${tags}") + string(REPLACE "][" ";" tags "${tags}") - if(environment_modifications) add_command(set_tests_properties "${prefix}${test}${suffix}" PROPERTIES - ENVIRONMENT_MODIFICATION "${environment_modifications}") + LABELS "${tags}" + ) endif() - - list(APPEND tests "${prefix}${test}${suffix}") endforeach() # Create a list of all discovered tests, which users may use to e.g. set From c541a31bbf1d2ed81e8b771bf77b8531a706b679 Mon Sep 17 00:00:00 2001 From: Uy Ha Date: Tue, 31 Oct 2023 22:05:28 +0000 Subject: [PATCH 2/4] Complete adding tags as labels to tests using the JSON reporter --- extras/CatchAddTests.cmake | 111 +++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/extras/CatchAddTests.cmake b/extras/CatchAddTests.cmake index 342edfd655..9b7592255c 100644 --- a/extras/CatchAddTests.cmake +++ b/extras/CatchAddTests.cmake @@ -61,7 +61,7 @@ function(catch_discover_tests_impl) endif() execute_process( - COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" ${spec} --list-tests --verbosity normal + COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" ${spec} --list-tests --reporter JSON OUTPUT_VARIABLE output RESULT_VARIABLE result WORKING_DIRECTORY "${_TEST_WORKING_DIR}" @@ -74,16 +74,6 @@ function(catch_discover_tests_impl) ) endif() - # Make sure to escape ; (semicolons) in test names first, because - # that'd break the foreach loop for "Parse output" later and create - # wrongly splitted and thus failing test cases (false positives) - string(REPLACE ";" "\;" output "${output}") - string(STRIP "${output}" output) - string(REPLACE "\n" ";" output "${output}") - list(LENGTH output length) - math(EXPR length "${length} - 2") - list(SUBLIST output 1 "${length}" output) - # Prepare reporter if(reporter) set(reporter_arg "--reporter ${reporter}") @@ -125,58 +115,71 @@ function(catch_discover_tests_impl) endforeach() endif() + # Catch2 string escape logic is a bit funky, double quotes are escaped but single + # slash is not, the following line of code tries to handle it but it can be brittle. + string(REGEX REPLACE [[\\([^"])]] [[\\\\\1]] output "${output}") + string(JSON listings GET "${output}" "listings") + string(JSON tests GET "${listings}" "tests") + string(JSON tests_length LENGTH "${tests}") + # CMake foreach loop is inclusive + math(EXPR test_end "${tests_length} - 1") # Parse output - foreach(line ${output}) - if(line MATCHES "^ ([^ ].*)$") - set(test ${line}) - # Escape characters in test case names that would be parsed by Catch2 - # Note that the \ escaping must happen FIRST! Do not change the order. - set(test_name ${test}) - foreach(char \\ , [ ]) - string(REPLACE ${char} "\\${char}" test_name ${test_name}) - endforeach(char) - # ...add output dir - if(output_dir) - string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name}) - set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") - endif() - - # ...and add to script - add_command(add_test - "${prefix}${test}${suffix}" - ${_TEST_EXECUTOR} - "${_TEST_EXECUTABLE}" - "${test_name}" - ${extra_args} - "${reporter_arg}" - "${output_dir_arg}" - ) + foreach(index RANGE "${test_end}") + string(JSON test_spec GET "${tests}" "${index}") + string(JSON test GET "${test_spec}" "name") + # Escape characters in test case names that would be parsed by Catch2 + # Note that the \ escaping must happen FIRST! Do not change the order. + set(test_name "${test}") + foreach(char \\ , [ ]) + string(REPLACE ${char} "\\${char}" test_name "${test_name}") + endforeach(char) + # ...add output dir + if(output_dir) + string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name}) + set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") + endif() + + # ...and add to script + add_command(add_test + "${prefix}${test}${suffix}" + ${_TEST_EXECUTOR} + "${_TEST_EXECUTABLE}" + "${test_name}" + ${extra_args} + "${reporter_arg}" + "${output_dir_arg}" + ) + add_command(set_tests_properties + "${prefix}${test}${suffix}" + PROPERTIES + WORKING_DIRECTORY "${_TEST_WORKING_DIR}" + ${properties} + ) + + if(environment_modifications) add_command(set_tests_properties "${prefix}${test}${suffix}" PROPERTIES - WORKING_DIRECTORY "${_TEST_WORKING_DIR}" - ${properties} - ) + ENVIRONMENT_MODIFICATION "${environment_modifications}" + ) + endif() + + list(APPEND tests "${prefix}${test}${suffix}") + + string(JSON tags GET "${test_spec}" "tags") + string(JSON tags_length LENGTH "${tags}") + + if("${tags_length}" GREATER 0) + math(EXPR tag_end "${tags_length} - 1") - if(environment_modifications) + foreach(tag_index RANGE "${tag_end}") + string(JSON tag GET "${tags}" "${tag_index}") add_command(set_tests_properties "${prefix}${test}${suffix}" PROPERTIES - ENVIRONMENT_MODIFICATION "${environment_modifications}") - endif() - - list(APPEND tests "${prefix}${test}${suffix}") - elseif(line MATCHES "^ (.*)$") - set(tags "${CMAKE_MATCH_1}") - string(REGEX REPLACE "^\\[" "" tags "${tags}") - string(REGEX REPLACE "\\]$" "" tags "${tags}") - string(REPLACE "][" ";" tags "${tags}") - - add_command(set_tests_properties - "${prefix}${test}${suffix}" - PROPERTIES - LABELS "${tags}" + LABELS "${tags}" ) + endforeach() endif() endforeach() From 41ecdb6f55a764fc8c4b1de1c815e6416c44a16d Mon Sep 17 00:00:00 2001 From: Uy Ha Date: Wed, 15 Nov 2023 08:40:31 +0000 Subject: [PATCH 3/4] Remove custom escape logic --- extras/CatchAddTests.cmake | 3 --- 1 file changed, 3 deletions(-) diff --git a/extras/CatchAddTests.cmake b/extras/CatchAddTests.cmake index 9b7592255c..2fd92a1e72 100644 --- a/extras/CatchAddTests.cmake +++ b/extras/CatchAddTests.cmake @@ -115,9 +115,6 @@ function(catch_discover_tests_impl) endforeach() endif() - # Catch2 string escape logic is a bit funky, double quotes are escaped but single - # slash is not, the following line of code tries to handle it but it can be brittle. - string(REGEX REPLACE [[\\([^"])]] [[\\\\\1]] output "${output}") string(JSON listings GET "${output}" "listings") string(JSON tests GET "${listings}" "tests") string(JSON tests_length LENGTH "${tests}") From 3cf405b60d7c49e296e5e235060d96e9692ed4b6 Mon Sep 17 00:00:00 2001 From: Uy Ha Date: Wed, 15 Nov 2023 08:44:26 +0000 Subject: [PATCH 4/4] Quote variable dereference properly --- extras/CatchAddTests.cmake | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extras/CatchAddTests.cmake b/extras/CatchAddTests.cmake index 2fd92a1e72..996492271a 100644 --- a/extras/CatchAddTests.cmake +++ b/extras/CatchAddTests.cmake @@ -132,7 +132,7 @@ function(catch_discover_tests_impl) endforeach(char) # ...add output dir if(output_dir) - string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name}) + string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean "${test_name}") set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") endif() @@ -157,8 +157,7 @@ function(catch_discover_tests_impl) add_command(set_tests_properties "${prefix}${test}${suffix}" PROPERTIES - ENVIRONMENT_MODIFICATION "${environment_modifications}" - ) + ENVIRONMENT_MODIFICATION "${environment_modifications}") endif() list(APPEND tests "${prefix}${test}${suffix}")