diff --git a/extras/CatchAddTests.cmake b/extras/CatchAddTests.cmake index 46a81a85..fa75b3d6 100644 --- a/extras/CatchAddTests.cmake +++ b/extras/CatchAddTests.cmake @@ -204,6 +204,23 @@ function(make_temp_file_path OUT_VARIABLE FALLBACK_PATH) set(${OUT_VARIABLE} "${FINAL_TEMP_PATH}" PARENT_SCOPE) endfunction() +# Computes the path of the test-list file based on the path for the main +# CTest script file (passed in `CTEST_FILE`). +# +# It works by replacing the `_tests` part of the original name with +# `_test-list`, or failing that, it appends `-list.cmake` instead. +# +# _tests.cmake -> _test-list.cmake +# _tests-Debug.cmake -> _test-list-Debug.cmake +function(make_test_list_file_path CTEST_FILE OUT_VARIABLE) + if("${CTEST_FILE}" MATCHES "_tests(.*)\\.cmake$") + string(REGEX REPLACE "_tests(.*)\\.cmake$" "_test-list\\1.cmake" list_file "${CTEST_FILE}") + else() + set(list_file "${CTEST_FILE}-list.cmake") + endif() + set(${OUT_VARIABLE} "${list_file}" PARENT_SCOPE) +endfunction() + function(catch_discover_tests_impl) cmake_parse_arguments( "" @@ -213,9 +230,14 @@ function(catch_discover_tests_impl) ${ARGN} ) - # We periodically append to the output file below, so we have to ensure + # We write the list of all discovered tests into a separate file + make_test_list_file_path("${_CTEST_FILE}" _CTEST_LIST_FILE) + + # We periodically append to the output files below, so we have to ensure # that it is empty at the start, or we get duplicated test scripts. file(REMOVE "${_CTEST_FILE}") + file(REMOVE "${_CTEST_LIST_FILE}") + # Size (in Bytes) at which the intermediate `script` var is dumped to file. set(_WriteToFileThreshold 50000) @@ -360,10 +382,19 @@ function(catch_discover_tests_impl) # Exit early if no tests are detected if(NOT tests) - file(WRITE "${_CTEST_FILE}" "") + # Still emit an (empty) test list file and have the main script include + # it, so that consumers relying on the `${_TEST_LIST}` variable and on the + # include structure get consistent behavior regardless of test count. + file(WRITE "${_CTEST_LIST_FILE}" "set(${_TEST_LIST})\n") + file(WRITE "${_CTEST_FILE}" "include(\"${_CTEST_LIST_FILE}\")\n") return() endif() + + # The 'set(VAR` header for the test list has to be written separately, + # so that each test name can be appended file without further processing. + set(test_names "set(${_TEST_LIST}") + # Each element in the tests is JSON-string representing one test object. # We have to parse it and then turn it into CTest script commands. foreach(single_test IN LISTS tests) @@ -374,6 +405,11 @@ function(catch_discover_tests_impl) file(APPEND "${_CTEST_FILE}" "${script}") set(script "") endif() + string(LENGTH "${test_names}" names_len) + if (names_len GREATER _WriteToFileThreshold) + file(APPEND "${_CTEST_LIST_FILE}" "${test_names}") + set(test_names "") + endif() # The elements are still escaped and contain JSON-invalid characters, # they have to be unescaped before parsing them as JSON. @@ -459,18 +495,17 @@ function(catch_discover_tests_impl) if(full_list_name MATCHES "[^-./:a-zA-Z0-9_]") # The space before the start of quote is important, so that we get # space-separated list in the final file. - string(APPEND _test_names " [==[${full_list_name}]==]") + string(APPEND test_names " [==[${full_list_name}]==]") else() - string(APPEND _test_names " ${full_list_name}") + string(APPEND test_names " ${full_list_name}") endif() endforeach() - # Create a list of all discovered tests, which users may use to e.g. set - # properties on the tests - string(APPEND script "set(${_TEST_LIST}${_test_names})\n") - - # Write any script leftovers we have + # Write any test names leftovers we have + file(APPEND "${_CTEST_LIST_FILE}" "${test_names})\n") + # Write any main script leftovers we have, and append the include of test names file(APPEND "${_CTEST_FILE}" "${script}") + file(APPEND "${_CTEST_FILE}" "include(\"${_CTEST_LIST_FILE}\")\n") endfunction() # To enable `include`ing this file in the unit test scripts, we only run