GoogleTest: Fix gtest_discover_tests race on POST_BUILD of multiple targets

Restore the logic from commit 6680df042e (GoogleTest: Avoid POST_BUILD
race condition for gtest_discover_tests(), 2025-10-26, v4.2.0-rc2~15^2)
that was lost in the refactoring in commit 3748ca9fc7 (GoogleTest:
generate single discovery script, 2026-04-08, v4.4.0-rc1~302^2~1). Add
a regression test.

Fixes: #27939, #27319, #27972
This commit is contained in:
Tyler Yankee
2026-07-20 11:21:35 -04:00
committed by Brad King
parent 1f3b0f6c0a
commit fc1b218b37
4 changed files with 72 additions and 0 deletions
+1
View File
@@ -685,6 +685,7 @@ function(gtest_discover_tests target)
string(CONCAT discovery_content
"include(\"${CMAKE_ROOT}/Modules/GoogleTestAddTests.cmake\")" "\n"
"gtest_discover_tests_impl(" "\n"
" TEST_TARGET" " [==[${target}]==]" "\n"
" TEST_EXECUTABLE" " [==[$<TARGET_FILE:${target}>]==]" "\n"
" TEST_EXECUTOR" " [==[${test_executor}]==]" "\n"
" TEST_WORKING_DIR" " [==[${arg_WORKING_DIRECTORY}]==]" "\n"
@@ -0,0 +1,18 @@
if(NOT DEFINED binary_dir)
message(FATAL_ERROR "binary_dir is required")
endif()
if(NOT DEFINED target_count)
message(FATAL_ERROR "target_count is required")
endif()
file(GLOB discovery_json_files "${binary_dir}/cmake_test_discovery_*.json")
list(LENGTH discovery_json_files discovery_json_count)
if(NOT discovery_json_count EQUAL target_count)
message(FATAL_ERROR
"Expected ${target_count} unique discovery JSON files, found ${discovery_json_count}. "
"Likely shared discovery scratch file collision in POST_BUILD discovery."
)
endif()
message(STATUS "Found ${discovery_json_count}/${target_count} unique discovery JSON files")
@@ -0,0 +1,27 @@
enable_language(CXX)
include(GoogleTest)
enable_testing()
include(xcode_sign_adhoc.cmake)
set(race_target_count 16)
set(race_targets)
foreach(i RANGE 1 ${race_target_count})
set(t race_fake_gtest_${i})
add_executable(${t} fake_gtest.cpp)
xcode_sign_adhoc(${t})
# Avoid timeouts on low-resource hardware at high parallelism.
gtest_discover_tests(${t} DISCOVERY_MODE POST_BUILD DISCOVERY_TIMEOUT 30)
list(APPEND race_targets ${t})
endforeach()
add_custom_target(check_discovery_json_files
COMMAND ${CMAKE_COMMAND}
-Dbinary_dir=${CMAKE_CURRENT_BINARY_DIR}
-Dtarget_count=${race_target_count}
-P ${CMAKE_CURRENT_LIST_DIR}/GoogleTest-discovery-post-build-race-check.cmake
DEPENDS ${race_targets}
VERBATIM
)
@@ -357,6 +357,27 @@ function(run_GoogleTest_discovery_flush_script DISCOVERY_MODE)
)
endfunction()
function(run_GoogleTest_discovery_post_build_race)
# Use a single build tree for this test without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-discovery-post-build-race)
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(GoogleTestDiscoveryPostBuildRace)
run_cmake_command(GoogleTest-discovery-post-build-race-build
${CMAKE_COMMAND}
--build .
--config Debug
-j 16
--target check_discovery_json_files
)
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)
@@ -516,3 +537,8 @@ endblock()
run_GoogleTest_LegacyParser()
run_GoogleTest_DEF_SOURCE_LINE()
# This test is meaningful only for generators which support parallel builds.
if (NOT RunCMake_GENERATOR MATCHES "(Borland|NMake|Watcom)")
run_GoogleTest_discovery_post_build_race()
endif()