From 0767016eabf17ab124ae7b454b9ca910dcc17c56 Mon Sep 17 00:00:00 2001 From: Moritz Haase Date: Tue, 5 Dec 2023 14:09:37 +0100 Subject: GoogleTest: Avoid silent failures of dynamic test discovery The internal helper variable '_GOOGLETEST_DISCOVER_TESTS_SCRIPT' can have gone out-of-scope when 'gtest_discover_tests()' is called, depending on where the GoogleTest module is actually included. This leads to a silent failure of dynamic test discovery, since the custom post-build commands actually does nothing (it basically invokes 'cmake -P ""'). Ctest will then fail to run the tests, considering them to be 'not built'. Fix this by determining the path to the GoogleTest module based on '${CMAKE_ROOT}' instead, which is always available. A new test case was added to test suite 'RunCMake/GoogleTest' to ensure that 'gtest_discover_tests()' works correctly when invoked in a different variable scope. Fixes: #25477 --- Modules/GoogleTest.cmake | 8 ++----- .../GoogleTestDiscoveryTestListScoped.cmake | 13 +++++++++++ .../CMakeLists.txt | 13 +++++++++++ Tests/RunCMake/GoogleTest/RunCMakeTest.cmake | 27 ++++++++++++++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTestListScoped.cmake create mode 100644 Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTestListScoped/CMakeLists.txt diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index 57a7476..3c12e14 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -500,7 +500,7 @@ function(gtest_discover_tests TARGET) -D "CTEST_FILE=${ctest_tests_file}" -D "TEST_DISCOVERY_TIMEOUT=${_DISCOVERY_TIMEOUT}" -D "TEST_XML_OUTPUT_DIR=${_XML_OUTPUT_DIR}" - -P "${_GOOGLETEST_DISCOVER_TESTS_SCRIPT}" + -P "${CMAKE_ROOT}/Modules/GoogleTestAddTests.cmake" VERBATIM ) @@ -526,7 +526,7 @@ function(gtest_discover_tests TARGET) " if(NOT EXISTS \"${ctest_tests_file}\" OR" "\n" " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$\" OR\n" " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"\${CMAKE_CURRENT_LIST_FILE}\")\n" - " include(\"${_GOOGLETEST_DISCOVER_TESTS_SCRIPT}\")" "\n" + " include(\"${CMAKE_ROOT}/Modules/GoogleTestAddTests.cmake\")" "\n" " gtest_discover_tests_impl(" "\n" " TEST_EXECUTABLE" " [==[" "$" "]==]" "\n" " TEST_EXECUTOR" " [==[" "${crosscompiling_emulator}" "]==]" "\n" @@ -573,9 +573,5 @@ endfunction() ############################################################################### -set(_GOOGLETEST_DISCOVER_TESTS_SCRIPT - ${CMAKE_CURRENT_LIST_DIR}/GoogleTestAddTests.cmake -) - # Restore project's policies cmake_policy(POP) diff --git a/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTestListScoped.cmake b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTestListScoped.cmake new file mode 100644 index 0000000..d65fae8 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTestListScoped.cmake @@ -0,0 +1,13 @@ +enable_language(CXX) + +# 'GoogleTest' module is NOT included here by design to validate that including +# it in a subdirectory will still result in test discovery working correctly if +# 'gtest_discover_tests()' is invoked from a different scope. + +enable_testing() + +include(xcode_sign_adhoc.cmake) + +add_subdirectory(GoogleTestDiscoveryTestListScoped) + +add_gtest_executable(test_list_scoped_test test_list_test.cpp) diff --git a/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTestListScoped/CMakeLists.txt b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTestListScoped/CMakeLists.txt new file mode 100644 index 0000000..762a537 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryTestListScoped/CMakeLists.txt @@ -0,0 +1,13 @@ +# This file mimics one containing GoogleTest-related helper functions. It +# includes the GoogleTest module that (in this test) is NOT included in the +# top-level CMake file. + +include(GoogleTest) + +function(add_gtest_executable TARGET SOURCE) + add_executable(${TARGET} ${SOURCE}) + xcode_sign_adhoc(${TARGET}) + gtest_discover_tests( + ${TARGET} + ) +endfunction() diff --git a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake index b494cef..56bbfc9 100644 --- a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake @@ -292,6 +292,32 @@ function(run_GoogleTest_discovery_flush_script DISCOVERY_MODE) ) endfunction() +function(run_GoogleTest_discovery_test_list_scoped DISCOVERY_MODE) + # Use a single build tree for a few tests without cleaning. + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-discovery-test-list-scoped-build) + set(RunCMake_TEST_NO_CLEAN 1) + if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + endif() + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake_with_options(GoogleTestDiscoveryTestListScoped -DCMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE=${DISCOVERY_MODE}) + + run_cmake_command(GoogleTest-discovery-test-list-scoped-build + ${CMAKE_COMMAND} + --build . + --config Debug + --target test_list_scoped_test + ) + + run_cmake_command(GoogleTest-discovery-test-list-scoped-test + ${CMAKE_CTEST_COMMAND} + -C Debug + --no-label-summary + ) +endfunction() + foreach(DISCOVERY_MODE POST_BUILD PRE_TEST) message("Testing ${DISCOVERY_MODE} discovery mode via CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE global override...") run_GoogleTest(${DISCOVERY_MODE}) @@ -303,6 +329,7 @@ foreach(DISCOVERY_MODE POST_BUILD PRE_TEST) run_GoogleTest_discovery_arg_change(${DISCOVERY_MODE}) endif() run_GoogleTest_discovery_test_list(${DISCOVERY_MODE}) + run_GoogleTest_discovery_test_list_scoped(${DISCOVERY_MODE}) run_GoogleTest_discovery_flush_script(${DISCOVERY_MODE}) endforeach() -- cgit v0.12