From e06169bdd0da39592a31aea62476d0b98bbd6f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Ferenc=20Nagy-Egri?= Date: Mon, 23 Feb 2026 18:04:51 +0100 Subject: [PATCH] GoogleTest: Add LIST_SEPARATOR for properties --- Help/release/dev/googletest-listseparator.rst | 5 ++ Modules/GoogleTest.cmake | 11 +++++ Modules/GoogleTestAddTests.cmake | 48 +++++++++++++++---- Tests/GoogleTest/Test/CMakeLists.txt | 12 +++++ Tests/GoogleTest/Test/main5.cxx | 9 ++++ 5 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 Help/release/dev/googletest-listseparator.rst create mode 100644 Tests/GoogleTest/Test/main5.cxx diff --git a/Help/release/dev/googletest-listseparator.rst b/Help/release/dev/googletest-listseparator.rst new file mode 100644 index 0000000000..50a98ac070 --- /dev/null +++ b/Help/release/dev/googletest-listseparator.rst @@ -0,0 +1,5 @@ +googletest-listseparator +------------------------ + +* The :module:`GoogleTest` module :command:`gtest_discover_tests` command + gained a ``LIST_SEPARATOR`` option. diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index 5f4eaf84e9..3093cd0424 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -174,6 +174,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also [TEST_SUFFIX suffix] [TEST_FILTER expr] [NO_PRETTY_TYPES] [NO_PRETTY_VALUES] + [LIST_SEPARATOR sep] [PROPERTIES name1 value1...] [TEST_LIST var] [DISCOVERY_TIMEOUT seconds] @@ -328,6 +329,14 @@ same as the Google Test name (i.e. ``suite.testcase``); see also :prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are preserved, see policy :policy:`CMP0178`. + ``LIST_SEPARATOR`` + .. versionadded:: 4.4 + + By default, ``PROPERTIES`` key-value pairs cannot have lists as their + values. By providing a non-semicolon character delimiter, it is possible to + pass lists as property values. Note that when doing so, the chosen character + cannot appear in any of the property values. + #]=======================================================================] # Save project's policies @@ -562,6 +571,7 @@ function(gtest_discover_tests target) DISCOVERY_TIMEOUT XML_OUTPUT_DIR DISCOVERY_MODE + LIST_SEPARATOR ) set(multiValueArgs EXTRA_ARGS @@ -699,6 +709,7 @@ function(gtest_discover_tests target) -D "TEST_FILTER=${arg_TEST_FILTER}" -D "NO_PRETTY_TYPES=${arg_NO_PRETTY_TYPES}" -D "NO_PRETTY_VALUES=${arg_NO_PRETTY_VALUES}" + -D "LIST_SEPARATOR=${arg_LIST_SEPARATOR}" -D "TEST_LIST=${arg_TEST_LIST}" -D "CTEST_FILE=${ctest_tests_file}" -D "TEST_DISCOVERY_TIMEOUT=${arg_DISCOVERY_TIMEOUT}" diff --git a/Modules/GoogleTestAddTests.cmake b/Modules/GoogleTestAddTests.cmake index b12a3365d9..7dacb38ff7 100644 --- a/Modules/GoogleTestAddTests.cmake +++ b/Modules/GoogleTestAddTests.cmake @@ -52,7 +52,7 @@ macro(write_test_to_file) # Handle disabled tests set(maybe_DISABLED "") if(pretty_test_suite MATCHES "^DISABLED_" OR pretty_test_name MATCHES "^DISABLED_") - set(maybe_DISABLED DISABLED YES) + set(maybe_DISABLED "DISABLED YES") string(REGEX REPLACE "^DISABLED_" "" pretty_test_suite "${pretty_test_suite}") string(REGEX REPLACE "^DISABLED_" "" pretty_test_name "${pretty_test_name}") endif() @@ -98,6 +98,10 @@ macro(write_test_to_file) # Add to script. Do not use add_command() here because it messes up the # handling of empty values when forwarding arguments, and we need to # preserve those carefully for arg_TEST_EXECUTOR and arg_EXTRA_ARGS. + # Test properties with values that are lists are also not handled + # correctly because the properties need to be expressed as a list + # of key-value pairs, but that list is flattened, so any values + # that are lists can't be differentiated from the next key. string(APPEND script "add_test(${guarded_testname} ${launcherArgs}") foreach(arg IN ITEMS "${arg_TEST_EXECUTABLE}" @@ -121,18 +125,40 @@ macro(write_test_to_file) set(maybe_LOCATION "") if(NOT current_test_file STREQUAL "" AND NOT current_test_line STREQUAL "") - set(maybe_LOCATION DEF_SOURCE_LINE "${current_test_file}:${current_test_line}") + set(maybe_LOCATION "DEF_SOURCE_LINE [==[${current_test_file}:${current_test_line}]==]") endif() - add_command(set_tests_properties - "${guarded_testname}" - PROPERTIES - ${maybe_DISABLED} - ${maybe_LOCATION} - WORKING_DIRECTORY "${arg_TEST_WORKING_DIR}" - SKIP_REGULAR_EXPRESSION "\\[ SKIPPED \\]" - ${arg_TEST_PROPERTIES} + string(APPEND script + "set_tests_properties(${guarded_testname}\n" + " PROPERTIES\n" + " ${maybe_DISABLED}\n" + " ${maybe_LOCATION}\n" + " WORKING_DIRECTORY [==[${arg_TEST_WORKING_DIR}]==]\n" + " SKIP_REGULAR_EXPRESSION [==[\\[ SKIPPED \\]]==]\n" ) + if(arg_TEST_PROPERTIES) + # Making local copy of arg_TEST_PROPERTIES, as write_test_to_file is + # called in a loop and we don't want to destroy the parsed arg value + # by POP_FRONT-ing from it. + set(test_properties "${arg_TEST_PROPERTIES}") + list(LENGTH test_properties test_properties_length) + math(EXPR test_properties_length_mod2 "${test_properties_length} % 2") + if(NOT test_properties_length_mod2 EQUAL 0) + message(FATAL_ERROR + "gtest_discover_tests() received a key-value list of properties with an uneven number of elements.\n" + "Check the supplied TEST_PROPERTIES argument and LIST_SEPARATOR if used." + ) + endif() + while(NOT test_properties_length EQUAL 0) + list(POP_FRONT test_properties property_name property_value) + list(LENGTH test_properties test_properties_length) + if(NOT "${arg_LIST_SEPARATOR}" STREQUAL "") + string(REPLACE "${arg_LIST_SEPARATOR}" ";" property_value "${property_value}") + endif() + string(APPEND script " ${property_name} [==[${property_value}]==]\n") + endwhile() + endif() + string(APPEND script ")\n") # possibly unbalanced square brackets render lists invalid so skip such # tests in ${arg_TEST_LIST} @@ -281,6 +307,7 @@ function(gtest_discover_tests_impl) set(oneValueArgs NO_PRETTY_TYPES # These two take a value, unlike gtest_discover_tests() NO_PRETTY_VALUES # + LIST_SEPARATOR TEST_TARGET TEST_EXECUTABLE TEST_WORKING_DIR @@ -435,5 +462,6 @@ if(CMAKE_SCRIPT_MODE_FILE) TEST_EXTRA_ARGS "${TEST_EXTRA_ARGS}" TEST_DISCOVERY_EXTRA_ARGS "${TEST_DISCOVERY_EXTRA_ARGS}" TEST_PROPERTIES "${TEST_PROPERTIES}" + LIST_SEPARATOR "${LIST_SEPARATOR}" ) endif() diff --git a/Tests/GoogleTest/Test/CMakeLists.txt b/Tests/GoogleTest/Test/CMakeLists.txt index 0735496537..43848c0ef6 100644 --- a/Tests/GoogleTest/Test/CMakeLists.txt +++ b/Tests/GoogleTest/Test/CMakeLists.txt @@ -114,3 +114,15 @@ gtest_add_tests($ "" main4.h) if(NOT TEST GoogleTest.NoKeywords) message(FATAL_ERROR "Test case GoogleTest.NoKeywords not defined") endif() + +# Check if LIST_SEPARATOR allows passing both ENVIRONMENT values to test +add_executable(test_gtest5 main5.cxx) +target_link_libraries(test_gtest5 GTest::Main) +set(environment VALX=1 VALY=2) +set(list_separator ",") +list(JOIN environment ${list_separator} environment) +gtest_discover_tests(test_gtest5 + LIST_SEPARATOR ${list_separator} + PROPERTIES + ENVIRONMENT "${environment}" +) diff --git a/Tests/GoogleTest/Test/main5.cxx b/Tests/GoogleTest/Test/main5.cxx new file mode 100644 index 0000000000..28fa374674 --- /dev/null +++ b/Tests/GoogleTest/Test/main5.cxx @@ -0,0 +1,9 @@ +#include + +#include + +TEST(GoogleTest, Add) +{ + EXPECT_STREQ(std::getenv("VALX"), "1"); + EXPECT_STREQ(std::getenv("VALY"), "2"); +}