summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2024-10-02 12:11:37 (GMT)
committerKitware Robot <kwrobot@kitware.com>2024-10-02 12:11:57 (GMT)
commit823e0a3a6187f02c06b86c32d6966eff25b9abc8 (patch)
tree8215f0d010f3bcc7fb50bef49c29a937b80f4884
parentd8bdc9f3af34173c240e7209f2a0c0303f832e8e (diff)
parentfc7aa3cd69eee1cdb001e6a28f36ddd01cefe720 (diff)
downloadCMake-823e0a3a6187f02c06b86c32d6966eff25b9abc8.zip
CMake-823e0a3a6187f02c06b86c32d6966eff25b9abc8.tar.gz
CMake-823e0a3a6187f02c06b86c32d6966eff25b9abc8.tar.bz2
Merge topic 'preserve-empty-args-test-command-lines'
fc7aa3cd69 tests: Preserve empty arguments in test command lines 9f1703530b Help: Add pre-test to prose for gtest_discover_tests() Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !9575
-rw-r--r--Help/manual/cmake-policies.7.rst1
-rw-r--r--Help/policy/CMP0178.rst37
-rw-r--r--Help/release/dev/preserve-empty-args-test-command-lines.rst19
-rw-r--r--Modules/AndroidTestUtilities.cmake2
-rw-r--r--Modules/ExternalData.cmake18
-rw-r--r--Modules/FindCxxTest.cmake2
-rw-r--r--Modules/FindMatlab.cmake4
-rw-r--r--Modules/FindSquish.cmake4
-rw-r--r--Modules/FindXCTest.cmake2
-rw-r--r--Modules/GoogleTest.cmake148
-rw-r--r--Modules/GoogleTestAddTests.cmake82
-rw-r--r--Source/cmAddTestCommand.cxx48
-rw-r--r--Source/cmPolicies.h2
-rw-r--r--Source/cmTest.cxx1
-rw-r--r--Source/cmTest.h13
-rw-r--r--Source/cmTestGenerator.cxx27
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTestLauncher-test-stdout.txt17
-rw-r--r--Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-test-stdout.txt38
-rw-r--r--Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW.cmake2
-rw-r--r--Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-test-stdout.txt35
-rw-r--r--Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD.cmake2
-rw-r--r--Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-stderr.txt38
-rw-r--r--Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-test-stdout.txt35
-rw-r--r--Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN.cmake1
-rw-r--r--Tests/RunCMake/GoogleTest/Launcher.cmake (renamed from Tests/RunCMake/GoogleTest/GoogleTestLauncher.cmake)10
-rw-r--r--Tests/RunCMake/GoogleTest/RunCMakeTest.cmake20
-rw-r--r--Tests/RunCMake/GoogleTest/launcher_test.c2
27 files changed, 521 insertions, 89 deletions
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index 3b97848..796ce8b 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.31
.. toctree::
:maxdepth: 1
+ CMP0178: Test command lines preserve empty arguments. </policy/CMP0178>
CMP0177: install() DESTINATION paths are normalized. </policy/CMP0177>
CMP0176: execute_process() ENCODING is UTF-8 by default. </policy/CMP0176>
CMP0175: add_custom_command() rejects invalid arguments. </policy/CMP0175>
diff --git a/Help/policy/CMP0178.rst b/Help/policy/CMP0178.rst
new file mode 100644
index 0000000..f6152eb
--- /dev/null
+++ b/Help/policy/CMP0178.rst
@@ -0,0 +1,37 @@
+CMP0178
+-------
+
+.. versionadded:: 3.31
+
+Test command lines preserve empty arguments.
+
+Empty values in the :prop_tgt:`TEST_LAUNCHER` and
+:prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are now preserved
+for tests added by the following:
+
+* The :command:`add_test` command.
+* The :command:`ExternalData_Add_Test` command from the :module:`ExternalData`
+ module.
+* The :command:`gtest_add_tests` or :command:`gtest_discover_tests` commands
+ from the :module:`GoogleTest` module.
+
+For the :command:`gtest_add_tests` and :command:`gtest_discover_tests`
+commands, empty elements in the values passed after the ``EXTRA_ARGS``
+keyword are also now preserved.
+
+The ``OLD`` behavior of this policy silently discards empty list items
+from the :prop_tgt:`TEST_LAUNCHER` and :prop_tgt:`CROSSCOMPILING_EMULATOR`
+target properties in the above-mentioned cases. It also silently discards
+empty items from the values given after ``EXTRA_ARGS`` for the
+:command:`gtest_add_tests` and :command:`gtest_discover_tests` commands.
+
+The ``NEW`` behavior of this policy preserves empty list items in the
+:prop_tgt:`TEST_LAUNCHER` and :prop_tgt:`CROSSCOMPILING_EMULATOR` target
+properties, and in values given after ``EXTRA_ARGS`` for
+:command:`gtest_add_tests` and :command:`gtest_discover_tests`.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.31
+.. |WARNS_OR_DOES_NOT_WARN| replace:: warns
+.. include:: STANDARD_ADVICE.txt
+
+.. include:: DEPRECATED.txt
diff --git a/Help/release/dev/preserve-empty-args-test-command-lines.rst b/Help/release/dev/preserve-empty-args-test-command-lines.rst
new file mode 100644
index 0000000..a533ac8
--- /dev/null
+++ b/Help/release/dev/preserve-empty-args-test-command-lines.rst
@@ -0,0 +1,19 @@
+preserve-empty-args-test-command-lines
+--------------------------------------
+
+* Empty list elements in the :prop_tgt:`TEST_LAUNCHER` and
+ :prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are now preserved
+ when the executable for a command given to :command:`add_test` is a CMake
+ target. See policy :policy:`CMP0178`.
+
+* Empty list elements in the :prop_tgt:`TEST_LAUNCHER` and
+ :prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are now preserved
+ for the test created by :command:`ExternalData_Add_Test` from the
+ :module:`ExternalData` module. See policy :policy:`CMP0178`.
+
+* Empty list elements in the :prop_tgt:`TEST_LAUNCHER` and
+ :prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are now preserved
+ for tests created by :command:`gtest_add_tests` and
+ :command:`gtest_discover_tests` from the :module:`GoogleTest` module.
+ Empty list elements after the ``EXTRA_ARGS`` keyword of these two commands
+ are also now preserved. See policy :policy:`CMP0178`.
diff --git a/Modules/AndroidTestUtilities.cmake b/Modules/AndroidTestUtilities.cmake
index 55efb36..319710b 100644
--- a/Modules/AndroidTestUtilities.cmake
+++ b/Modules/AndroidTestUtilities.cmake
@@ -147,6 +147,8 @@ function(android_add_test_data test_name)
if(ANDROID)
string(REGEX REPLACE "DATA{([^ ;]+)}" "\\1" processed_FILES "${AST_FILES}")
+ # There's no target used for this command, so we don't need to do anything
+ # here for CMP0178.
add_test(
NAME ${test_name}
COMMAND ${CMAKE_COMMAND}
diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 6826c7b..055a0ee 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -72,6 +72,12 @@ Module Functions
It passes its arguments through ``ExternalData_Expand_Arguments`` and then
invokes the :command:`add_test` command using the results.
+ .. versionchanged:: 3.31
+ If the arguments after ``<target>`` define a test with an executable
+ that is a CMake target, empty values in the :prop_tgt:`TEST_LAUNCHER`
+ and :prop_tgt:`CROSSCOMPILING_EMULATOR` properties of that target are
+ preserved. See policy :policy:`CMP0178`.
+
.. command:: ExternalData_Add_Target
The ``ExternalData_Add_Target`` function creates a custom target to
@@ -353,7 +359,17 @@ file or set a variable:
function(ExternalData_add_test target)
# Expand all arguments as a single string to preserve escaped semicolons.
ExternalData_expand_arguments("${target}" testArgs "${ARGN}")
- add_test(${testArgs})
+
+ # We need the caller's CMP0178 policy setting to apply here
+ cmake_policy(GET CMP0178 cmp0178
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
+
+ # ExternalData_expand_arguments() escapes semicolons, so we should still be
+ # preserving empty elements from ARGN here. But CMP0178 is still important
+ # for correctly handling TEST_LAUNCHER and CROSSCOMPILING_EMULATOR target
+ # properties that contain empty elements.
+ add_test(${testArgs} __CMP0178 "${cmp0178}")
endfunction()
function(ExternalData_add_target target)
diff --git a/Modules/FindCxxTest.cmake b/Modules/FindCxxTest.cmake
index a3283fa..ceb6e29 100644
--- a/Modules/FindCxxTest.cmake
+++ b/Modules/FindCxxTest.cmake
@@ -163,6 +163,8 @@ macro(CXXTEST_ADD_TEST _cxxtest_testname _cxxtest_outfname)
set_source_files_properties(${_cxxtest_real_outfname} PROPERTIES GENERATED true)
add_executable(${_cxxtest_testname} ${_cxxtest_real_outfname} ${ARGN})
+ # There's no target used for these commands, so we don't need to do
+ # anything here for CMP0178.
if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
add_test(${_cxxtest_testname} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_cxxtest_testname})
elseif(EXECUTABLE_OUTPUT_PATH)
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index 91aee5e..c94ef72 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -1012,6 +1012,10 @@ function(matlab_add_unit_test)
endif()
endif()
+ # The ${${prefix}_TEST_ARGS} and ${${prefix}_UNPARSED_ARGUMENTS} used below
+ # should have semicolons escaped, so empty arguments should be preserved.
+ # There's also no target used for the command, so we don't need to do
+ # anything here for CMP0178.
add_test(NAME ${${prefix}_NAME}
COMMAND ${CMAKE_COMMAND}
"-Dtest_name=${${prefix}_NAME}"
diff --git a/Modules/FindSquish.cmake b/Modules/FindSquish.cmake
index 9a17fdb..bb4caa1 100644
--- a/Modules/FindSquish.cmake
+++ b/Modules/FindSquish.cmake
@@ -200,6 +200,8 @@ macro(squish_v3_add_test testName testAUT testCase envVars testWraper)
message(STATUS "Using squish_v3_add_test(), but SQUISH_VERSION_MAJOR is ${SQUISH_VERSION_MAJOR}.\nThis may not work.")
endif()
+ # There's no target used for this command, so we don't need to do anything
+ # here for CMP0178.
add_test(${testName}
${CMAKE_COMMAND} -V -VV
"-Dsquish_version:STRING=3"
@@ -258,6 +260,8 @@ function(squish_v4_add_test testName)
message("SETTINGSGROUP is deprecated and will be ignored.")
endif()
+ # There's no target used for this command, so we don't need to do anything
+ # here for CMP0178.
add_test(NAME ${testName}
COMMAND ${CMAKE_COMMAND} -V -VV
"-Dsquish_version:STRING=4"
diff --git a/Modules/FindXCTest.cmake b/Modules/FindXCTest.cmake
index a01c010..92ee25d 100644
--- a/Modules/FindXCTest.cmake
+++ b/Modules/FindXCTest.cmake
@@ -210,6 +210,8 @@ function(xctest_add_test name bundle)
# register test
+ # There's no target used for this command, so we don't need to do anything
+ # here for CMP0178.
add_test(
NAME ${name}
COMMAND ${XCTest_EXECUTABLE} $<TARGET_BUNDLE_DIR:${bundle}>)
diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake
index b959c53..1c45161 100644
--- a/Modules/GoogleTest.cmake
+++ b/Modules/GoogleTest.cmake
@@ -42,7 +42,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
gtest_add_tests(TARGET target
[SOURCES src1...]
- [EXTRA_ARGS arg1...]
+ [EXTRA_ARGS args...]
[WORKING_DIRECTORY dir]
[TEST_PREFIX prefix]
[TEST_SUFFIX suffix]
@@ -72,9 +72,12 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
this option is not given, the :prop_tgt:`SOURCES` property of the
specified ``target`` will be used to obtain the list of sources.
- ``EXTRA_ARGS arg1...``
+ ``EXTRA_ARGS args...``
Any extra arguments to pass on the command line to each test case.
+ .. versionchanged:: 3.31
+ Empty values in ``args...`` are preserved, see :policy:`CMP0178`.
+
``WORKING_DIRECTORY dir``
Specifies the directory in which to run the discovered test cases. If this
option is not provided, the current binary directory is used.
@@ -101,6 +104,11 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
with the list of discovered test cases. This allows the caller to do
things like manipulate test properties of the discovered tests.
+ .. versionchanged:: 3.31
+ Empty values in the :prop_tgt:`TEST_LAUNCHER` and
+ :prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are preserved,
+ see policy :policy:`CMP0178`.
+
Usage example:
.. code-block:: cmake
@@ -147,7 +155,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
for available tests::
gtest_discover_tests(target
- [EXTRA_ARGS arg1...]
+ [EXTRA_ARGS args...]
[WORKING_DIRECTORY dir]
[TEST_PREFIX prefix]
[TEST_SUFFIX suffix]
@@ -162,15 +170,15 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
.. versionadded:: 3.10
- ``gtest_discover_tests()`` sets up a post-build command on the test executable
- that generates the list of tests by parsing the output from running the test
- with the ``--gtest_list_tests`` argument. Compared to the source parsing
- approach of :command:`gtest_add_tests`, this ensures that the full list of
- tests, including instantiations of parameterized tests, is obtained. Since
- test discovery occurs at build time, it is not necessary to re-run CMake when
- the list of tests changes.
- However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set
- in order to function in a cross-compiling environment.
+ ``gtest_discover_tests()`` sets up a post-build or pre-test command on the
+ test executable that generates the list of tests by parsing the output from
+ running the test executable with the ``--gtest_list_tests`` argument.
+ Compared to the source parsing approach of :command:`gtest_add_tests`,
+ this ensures that the full list of tests, including instantiations of
+ parameterized tests, is obtained. Since test discovery occurs at build
+ or test time, it is not necessary to re-run CMake when the list of tests
+ changes. However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR`
+ is properly set in order to function in a cross-compiling environment.
Additionally, setting properties on tests is somewhat less convenient, since
the tests are not available at CMake time. Additional test properties may be
@@ -187,9 +195,12 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
executable target. CMake will substitute the location of the built
executable when running the test.
- ``EXTRA_ARGS arg1...``
+ ``EXTRA_ARGS args...``
Any extra arguments to pass on the command line to each test case.
+ .. versionchanged:: 3.31
+ Empty values in ``args...`` are preserved, see :policy:`CMP0178`.
+
``WORKING_DIRECTORY dir``
Specifies the directory in which to run the discovered test cases. If this
option is not provided, the current binary directory is used.
@@ -283,6 +294,15 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
for globally selecting a preferred test discovery behavior without having
to modify each call site.
+ .. versionadded:: 3.29
+ The :prop_tgt:`TEST_LAUNCHER` target property is honored during test
+ discovery and test execution.
+
+ .. versionchanged:: 3.31
+ Empty values in the :prop_tgt:`TEST_LAUNCHER` and
+ :prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are preserved,
+ see policy :policy:`CMP0178`.
+
#]=======================================================================]
# Save project's policies
@@ -312,9 +332,41 @@ function(gtest_add_tests)
)
set(allKeywords ${options} ${oneValueArgs} ${multiValueArgs})
+ cmake_policy(GET CMP0178 cmp0178
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
+
unset(sources)
if("${ARGV0}" IN_LIST allKeywords)
- cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ if(cmp0178 STREQUAL "NEW")
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${options}" "${oneValueArgs}" "${multiValueArgs}"
+ )
+ else()
+ cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ if(NOT cmp0178 STREQUAL "OLD")
+ block(SCOPE_FOR VARIABLES)
+ cmake_parse_arguments(PARSE_ARGV 0 arg_new
+ "${options}" "${oneValueArgs}" "${multiValueArgs}"
+ )
+ # Due to a quirk of cmake_parse_arguments(PARSE_ARGV),
+ # arg_new_EXTRA_ARGS will have semicolons already escaped, but
+ # arg_EXTRA_ARGS won't. We need to pass the former through one round
+ # of command argument parsing to de-escape them for comparison with
+ # the latter.
+ set(__newArgs ${arg_new_EXTRA_ARGS})
+ if(NOT "${arg_EXTRA_ARGS}" STREQUAL "${__newArgs}")
+ cmake_policy(GET_WARNING CMP0178 cmp0178_warning)
+ message(AUTHOR_WARNING
+ "The EXTRA_ARGS contain one or more empty values. Those empty "
+ "values are being silently discarded to preserve backward "
+ "compatibility.\n"
+ "${cmp0178_warning}"
+ )
+ endif()
+ endblock()
+ endif()
+ endif()
set(autoAddSources YES)
else()
# Non-keyword syntax, convert to keyword form
@@ -408,6 +460,11 @@ function(gtest_add_tests)
continue()
endif()
+ set(extra_args "")
+ foreach(arg IN LISTS arg_EXTRA_ARGS)
+ string(APPEND extra_args " [==[${arg}]==]")
+ endforeach()
+
# Make sure tests disabled in GTest get disabled in CTest
if(gtest_test_name MATCHES "(^|\\.)DISABLED_")
# Add the disabled test if CMake is new enough
@@ -422,12 +479,15 @@ function(gtest_add_tests)
set(ctest_test_name
${arg_TEST_PREFIX}${orig_test_name}${arg_TEST_SUFFIX}
)
- add_test(NAME ${ctest_test_name}
- ${workDir}
- COMMAND ${arg_TARGET}
- --gtest_also_run_disabled_tests
- --gtest_filter=${gtest_test_name}
- ${arg_EXTRA_ARGS}
+ cmake_language(EVAL CODE "
+ add_test(NAME ${ctest_test_name}
+ ${workDir}
+ COMMAND ${arg_TARGET}
+ --gtest_also_run_disabled_tests
+ --gtest_filter=${gtest_test_name}
+ ${extra_args}
+ __CMP0178 [==[${cmp0178}]==]
+ )"
)
set_tests_properties(${ctest_test_name} PROPERTIES DISABLED TRUE
DEF_SOURCE_LINE "${source}:${accumulate_line}")
@@ -435,11 +495,14 @@ function(gtest_add_tests)
endif()
else()
set(ctest_test_name ${arg_TEST_PREFIX}${gtest_test_name}${arg_TEST_SUFFIX})
- add_test(NAME ${ctest_test_name}
- ${workDir}
- COMMAND ${arg_TARGET}
- --gtest_filter=${gtest_test_name}
- ${arg_EXTRA_ARGS}
+ cmake_language(EVAL CODE "
+ add_test(NAME ${ctest_test_name}
+ ${workDir}
+ COMMAND ${arg_TARGET}
+ --gtest_filter=${gtest_test_name}
+ ${extra_args}
+ __CMP0178 [==[${cmp0178}]==]
+ )"
)
# Makes sure a skipped GTest is reported as so by CTest
set_tests_properties(
@@ -480,9 +543,8 @@ function(gtest_discover_tests target)
PROPERTIES
TEST_FILTER
)
- cmake_parse_arguments(arg
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${options}" "${oneValueArgs}" "${multiValueArgs}"
- ${ARGN}
)
if(NOT arg_WORKING_DIRECTORY)
@@ -551,6 +613,38 @@ function(gtest_discover_tests target)
set(test_executor "")
endif()
+ cmake_policy(GET CMP0178 cmp0178
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
+ if(NOT cmp0178 STREQUAL "NEW")
+ # Preserve old behavior where empty list items are silently discarded
+ set(test_executor_orig "${test_executor}")
+ set(test_executor ${test_executor})
+ set(arg_EXTRA_ARGS_orig "${arg_EXTRA_ARGS}")
+ set(arg_EXTRA_ARGS ${arg_EXTRA_ARGS})
+ if(NOT cmp0178 STREQUAL "OLD")
+ if(NOT "${test_executor}" STREQUAL "${test_executor_orig}")
+ cmake_policy(GET_WARNING CMP0178 cmp0178_warning)
+ message(AUTHOR_WARNING
+ "The '${target}' target's TEST_LAUNCHER or CROSSCOMPILING_EMULATOR "
+ "test properties contain one or more empty values. Those empty "
+ "values are being silently discarded to preserve backward "
+ "compatibility.\n"
+ "${cmp0178_warning}"
+ )
+ endif()
+ if(NOT "${arg_EXTRA_ARGS}" STREQUAL "${arg_EXTRA_ARGS_orig}")
+ cmake_policy(GET_WARNING CMP0178 cmp0178_warning)
+ message(AUTHOR_WARNING
+ "The EXTRA_ARGS value contains one or more empty values. "
+ "Those empty values are being silently discarded to preserve "
+ "backward compatibility.\n"
+ "${cmp0178_warning}"
+ )
+ endif()
+ endif()
+ endif()
+
if(arg_DISCOVERY_MODE STREQUAL "POST_BUILD")
add_custom_command(
TARGET ${target} POST_BUILD
diff --git a/Modules/GoogleTestAddTests.cmake b/Modules/GoogleTestAddTests.cmake
index b654bb0..b8ca3fc 100644
--- a/Modules/GoogleTestAddTests.cmake
+++ b/Modules/GoogleTestAddTests.cmake
@@ -2,6 +2,7 @@
# file Copyright.txt or https://cmake.org/licensing for details.
cmake_minimum_required(VERSION 3.30)
+cmake_policy(SET CMP0174 NEW) # TODO: Remove this when we can update the above to 3.31
# Overwrite possibly existing ${arg_CTEST_FILE} with empty file
set(flush_tests_MODE WRITE)
@@ -65,9 +66,9 @@ endfunction()
function(gtest_discover_tests_impl)
- set(options )
+ set(options "")
set(oneValueArgs
- NO_PRETTY_TYPES # These two take a value, unlike gtest_discover_tests
+ NO_PRETTY_TYPES # These two take a value, unlike gtest_discover_tests()
NO_PRETTY_VALUES #
TEST_EXECUTABLE
TEST_WORKING_DIR
@@ -77,22 +78,21 @@ function(gtest_discover_tests_impl)
CTEST_FILE
TEST_DISCOVERY_TIMEOUT
TEST_XML_OUTPUT_DIR
- TEST_FILTER # This is a multi-value argument in gtest_discover_tests
- )
- set(multiValueArgs
+ # The following are all multi-value arguments in gtest_discover_tests(),
+ # but they are each given to us as a single argument. We parse them that
+ # way to avoid problems with preserving empty list values and escaping.
+ TEST_FILTER
TEST_EXTRA_ARGS
TEST_PROPERTIES
TEST_EXECUTOR
)
- cmake_parse_arguments(arg
+ set(multiValueArgs "")
+ cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}" "${oneValueArgs}" "${multiValueArgs}"
- ${ARGN}
)
set(prefix "${arg_TEST_PREFIX}")
set(suffix "${arg_TEST_SUFFIX}")
- set(extra_args ${arg_TEST_EXTRA_ARGS})
- set(properties ${arg_TEST_PROPERTIES})
set(script)
set(suite)
set(tests)
@@ -104,6 +104,16 @@ function(gtest_discover_tests_impl)
set(filter)
endif()
+ # CMP0178 has already been handled in gtest_discover_tests(), so we only need
+ # to implement NEW behavior here. This means preserving empty arguments for
+ # TEST_EXECUTOR. For OLD or WARN, gtest_discover_tests() already removed any
+ # empty arguments.
+ set(launcherArgs "")
+ if(NOT "${arg_TEST_EXECUTOR}" STREQUAL "")
+ list(JOIN arg_TEST_EXECUTOR "]==] [==[" launcherArgs)
+ set(launcherArgs "[==[${launcherArgs}]==]")
+ endif()
+
# Run test executable to get list of available tests
if(NOT EXISTS "${arg_TEST_EXECUTABLE}")
message(FATAL_ERROR
@@ -111,12 +121,14 @@ function(gtest_discover_tests_impl)
" Path: '${arg_TEST_EXECUTABLE}'"
)
endif()
- execute_process(
- COMMAND ${arg_TEST_EXECUTOR} "${arg_TEST_EXECUTABLE}" --gtest_list_tests ${filter}
- WORKING_DIRECTORY "${arg_TEST_WORKING_DIR}"
- TIMEOUT ${arg_TEST_DISCOVERY_TIMEOUT}
- OUTPUT_VARIABLE output
- RESULT_VARIABLE result
+ cmake_language(EVAL CODE
+ "execute_process(
+ COMMAND ${launcherArgs} [==[${arg_TEST_EXECUTABLE}]==] --gtest_list_tests ${filter}
+ WORKING_DIRECTORY [==[${arg_TEST_WORKING_DIR}]==]
+ TIMEOUT ${arg_TEST_DISCOVERY_TIMEOUT}
+ OUTPUT_VARIABLE output
+ RESULT_VARIABLE result
+ )"
)
if(NOT ${result} EQUAL 0)
string(REPLACE "\n" "\n " output "${output}")
@@ -188,16 +200,36 @@ function(gtest_discover_tests_impl)
endif()
set(guarded_testname "${open_guard}${testname}${close_guard}")
- # add to script
- add_command(add_test
- "${guarded_testname}"
- ${arg_TEST_EXECUTOR}
+ # 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.
+ string(APPEND script "add_test(${guarded_testname} ${launcherArgs}")
+ foreach(arg IN ITEMS
"${arg_TEST_EXECUTABLE}"
"--gtest_filter=${suite}.${test}"
"--gtest_also_run_disabled_tests"
${TEST_XML_OUTPUT_PARAM}
- ${extra_args}
- )
+ )
+ if(arg MATCHES "[^-./:a-zA-Z0-9_]")
+ string(APPEND script " [==[${arg}]==]")
+ else()
+ string(APPEND script " ${arg}")
+ endif()
+ endforeach()
+ if(arg_TEST_EXTRA_ARGS)
+ list(JOIN arg_TEST_EXTRA_ARGS "]==] [==[" extra_args)
+ string(APPEND script " [==[${extra_args}]==]")
+ endif()
+ string(APPEND script ")\n")
+ string(LENGTH "${script}" script_len)
+ if(${script_len} GREATER "50000")
+ # flush_script() expects to set variables in the parent scope, so we
+ # need to create one since we actually want the changes in our scope
+ block(SCOPE_FOR VARIABLES)
+ flush_script()
+ endblock()
+ endif()
+
if(suite MATCHES "^DISABLED_" OR test MATCHES "^DISABLED_")
add_command(set_tests_properties
"${guarded_testname}"
@@ -210,7 +242,7 @@ function(gtest_discover_tests_impl)
PROPERTIES
WORKING_DIRECTORY "${arg_TEST_WORKING_DIR}"
SKIP_REGULAR_EXPRESSION "\\[ SKIPPED \\]"
- ${properties}
+ ${arg_TEST_PROPERTIES}
)
# possibly unbalanced square brackets render lists invalid so skip such
@@ -244,7 +276,7 @@ if(CMAKE_SCRIPT_MODE_FILE)
NO_PRETTY_TYPES ${NO_PRETTY_TYPES}
NO_PRETTY_VALUES ${NO_PRETTY_VALUES}
TEST_EXECUTABLE ${TEST_EXECUTABLE}
- TEST_EXECUTOR ${TEST_EXECUTOR}
+ TEST_EXECUTOR "${TEST_EXECUTOR}"
TEST_WORKING_DIR ${TEST_WORKING_DIR}
TEST_PREFIX ${TEST_PREFIX}
TEST_SUFFIX ${TEST_SUFFIX}
@@ -253,7 +285,7 @@ if(CMAKE_SCRIPT_MODE_FILE)
CTEST_FILE ${CTEST_FILE}
TEST_DISCOVERY_TIMEOUT ${TEST_DISCOVERY_TIMEOUT}
TEST_XML_OUTPUT_DIR ${TEST_XML_OUTPUT_DIR}
- TEST_EXTRA_ARGS ${TEST_EXTRA_ARGS}
- TEST_PROPERTIES ${TEST_PROPERTIES}
+ TEST_EXTRA_ARGS "${TEST_EXTRA_ARGS}"
+ TEST_PROPERTIES "${TEST_PROPERTIES}"
)
endif()
diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx
index a0d5732..ff17e87 100644
--- a/Source/cmAddTestCommand.cxx
+++ b/Source/cmAddTestCommand.cxx
@@ -2,14 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddTestCommand.h"
+#include <algorithm>
+
#include <cm/memory>
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
#include "cmStringAlgorithms.h"
#include "cmTest.h"
#include "cmTestGenerator.h"
+static std::string const keywordCMP0178 = "__CMP0178";
+
static bool cmAddTestCommandHandleNameMode(
std::vector<std::string> const& args, cmExecutionStatus& status);
@@ -29,8 +34,30 @@ bool cmAddTestCommand(std::vector<std::string> const& args,
}
cmMakefile& mf = status.GetMakefile();
+ cmPolicies::PolicyStatus cmp0178;
+
+ // If the __CMP0178 keyword is present, it is always at the end
+ auto endOfCommandIter =
+ std::find(args.begin() + 2, args.end(), keywordCMP0178);
+ if (endOfCommandIter != args.end()) {
+ auto cmp0178Iter = endOfCommandIter + 1;
+ if (cmp0178Iter == args.end()) {
+ status.SetError(cmStrCat(keywordCMP0178, " keyword missing value"));
+ return false;
+ }
+ if (*cmp0178Iter == "NEW") {
+ cmp0178 = cmPolicies::PolicyStatus::NEW;
+ } else if (*cmp0178Iter == "OLD") {
+ cmp0178 = cmPolicies::PolicyStatus::OLD;
+ } else {
+ cmp0178 = cmPolicies::PolicyStatus::WARN;
+ }
+ } else {
+ cmp0178 = mf.GetPolicyStatus(cmPolicies::CMP0178);
+ }
+
// Collect the command with arguments.
- std::vector<std::string> command(args.begin() + 1, args.end());
+ std::vector<std::string> command(args.begin() + 1, endOfCommandIter);
// Create the test but add a generator only the first time it is
// seen. This preserves behavior from before test generators.
@@ -46,6 +73,7 @@ bool cmAddTestCommand(std::vector<std::string> const& args,
} else {
test = mf.CreateTest(args[0]);
test->SetOldStyle(true);
+ test->SetCMP0178(cmp0178);
mf.AddTestGenerator(cm::make_unique<cmTestGenerator>(test));
}
test->SetCommand(command);
@@ -56,11 +84,14 @@ bool cmAddTestCommand(std::vector<std::string> const& args,
bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
+ cmMakefile& mf = status.GetMakefile();
+
std::string name;
std::vector<std::string> configurations;
std::string working_directory;
std::vector<std::string> command;
bool command_expand_lists = false;
+ cmPolicies::PolicyStatus cmp0178 = mf.GetPolicyStatus(cmPolicies::CMP0178);
// Read the arguments.
enum Doing
@@ -69,6 +100,7 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args,
DoingCommand,
DoingConfigs,
DoingWorkingDirectory,
+ DoingCmp0178,
DoingNone
};
Doing doing = DoingName;
@@ -91,6 +123,8 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args,
return false;
}
doing = DoingWorkingDirectory;
+ } else if (args[i] == keywordCMP0178) {
+ doing = DoingCmp0178;
} else if (args[i] == "COMMAND_EXPAND_LISTS") {
if (command_expand_lists) {
status.SetError(" may be given at most one COMMAND_EXPAND_LISTS.");
@@ -108,6 +142,15 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args,
} else if (doing == DoingWorkingDirectory) {
working_directory = args[i];
doing = DoingNone;
+ } else if (doing == DoingCmp0178) {
+ if (args[i] == "NEW") {
+ cmp0178 = cmPolicies::PolicyStatus::NEW;
+ } else if (args[i] == "OLD") {
+ cmp0178 = cmPolicies::PolicyStatus::OLD;
+ } else {
+ cmp0178 = cmPolicies::PolicyStatus::WARN;
+ }
+ doing = DoingNone;
} else {
status.SetError(cmStrCat(" given unknown argument:\n ", args[i], "\n"));
return false;
@@ -126,8 +169,6 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args,
return false;
}
- cmMakefile& mf = status.GetMakefile();
-
// Require a unique test name within the directory.
if (mf.GetTest(name)) {
status.SetError(cmStrCat(" given test NAME \"", name,
@@ -138,6 +179,7 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args,
// Add the test.
cmTest* test = mf.CreateTest(name);
test->SetOldStyle(false);
+ test->SetCMP0178(cmp0178);
test->SetCommand(command);
if (!working_directory.empty()) {
test->SetProperty("WORKING_DIRECTORY", working_directory);
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 88ced3f..e2254fe 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -543,6 +543,8 @@ class cmMakefile;
SELECT(POLICY, CMP0176, "execute_process() ENCODING is UTF-8 by default.", \
3, 31, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0177, "install() DESTINATION paths are normalized.", 3, \
+ 31, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0178, "Test command lines preserve empty arguments.", 3, \
31, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx
index 8a39144..c72e020 100644
--- a/Source/cmTest.cxx
+++ b/Source/cmTest.cxx
@@ -10,6 +10,7 @@
cmTest::cmTest(cmMakefile* mf)
: Backtrace(mf->GetBacktrace())
, PolicyStatusCMP0158(mf->GetPolicyStatus(cmPolicies::CMP0158))
+ , PolicyStatusCMP0178(mf->GetPolicyStatus(cmPolicies::CMP0178))
{
this->Makefile = mf;
this->OldStyle = true;
diff --git a/Source/cmTest.h b/Source/cmTest.h
index 480966a..244aa62 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -61,12 +61,22 @@ public:
bool GetOldStyle() const { return this->OldStyle; }
void SetOldStyle(bool b) { this->OldStyle = b; }
- /** Get/Set if CMP0158 policy is NEW */
+ /** Get if CMP0158 policy is NEW */
bool GetCMP0158IsNew() const
{
return this->PolicyStatusCMP0158 == cmPolicies::NEW;
}
+ /** Get/Set the CMP0178 policy setting */
+ cmPolicies::PolicyStatus GetCMP0178() const
+ {
+ return this->PolicyStatusCMP0178;
+ }
+ void SetCMP0178(cmPolicies::PolicyStatus p)
+ {
+ this->PolicyStatusCMP0178 = p;
+ }
+
/** Set/Get whether lists in command lines should be expanded. */
bool GetCommandExpandLists() const;
void SetCommandExpandLists(bool b);
@@ -82,4 +92,5 @@ private:
cmMakefile* Makefile;
cmListFileBacktrace Backtrace;
cmPolicies::PolicyStatus PolicyStatusCMP0158;
+ cmPolicies::PolicyStatus PolicyStatusCMP0178;
};
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 840d8cf..ffb5e21 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -174,15 +174,36 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
if (!cmNonempty(launcher)) {
return;
}
- cmList launcherWithArgs{ ge.Parse(*launcher)->Evaluate(this->LG,
- config) };
+ const auto propVal = ge.Parse(*launcher)->Evaluate(this->LG, config);
+ cmList launcherWithArgs(propVal, cmList::ExpandElements::Yes,
+ this->Test->GetCMP0178() == cmPolicies::NEW
+ ? cmList::EmptyElements::Yes
+ : cmList::EmptyElements::No);
if (!launcherWithArgs.empty() && !launcherWithArgs[0].empty()) {
+ if (this->Test->GetCMP0178() == cmPolicies::WARN) {
+ cmList argsWithEmptyValuesPreserved(
+ propVal, cmList::ExpandElements::Yes, cmList::EmptyElements::Yes);
+ if (launcherWithArgs != argsWithEmptyValuesPreserved) {
+ this->Test->GetMakefile()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat("The ", propertyName, " property of target '",
+ target->GetName(),
+ "' contains empty list items. Those empty items are "
+ "being silently discarded to preserve backward "
+ "compatibility.\n",
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0178)));
+ }
+ }
std::string launcherExe(launcherWithArgs[0]);
cmSystemTools::ConvertToUnixSlashes(launcherExe);
os << cmOutputConverter::EscapeForCMake(launcherExe) << " ";
for (std::string const& arg :
cmMakeRange(launcherWithArgs).advance(1)) {
- os << cmOutputConverter::EscapeForCMake(arg) << " ";
+ if (arg.empty()) {
+ os << "\"\" ";
+ } else {
+ os << cmOutputConverter::EscapeForCMake(arg) << " ";
+ }
}
}
};
diff --git a/Tests/RunCMake/GoogleTest/GoogleTestLauncher-test-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTestLauncher-test-stdout.txt
deleted file mode 100644
index 6313151..0000000
--- a/Tests/RunCMake/GoogleTest/GoogleTestLauncher-test-stdout.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-1: Test command: "?[^
-]*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]GoogleTestLauncher-build([/\]Debug)?[/\]test_launcher(\.exe)?"? "launcherparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/GoogleTestLauncher-build(/Debug)?/test_launcher(\.exe)?" "emulatorparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/GoogleTestLauncher-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests"
-1: Working Directory: [^
-]*/Tests/RunCMake/GoogleTest/GoogleTestLauncher-build
-1: Test timeout computed to be: [0-9]+
-1: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]GoogleTestLauncher-build([/\]Debug)?[/\]test_launcher(\.exe)?'
-1: test_launcher: got arg 1 'launcherparam'
-1: test_launcher: got arg 2 '--'
-1: test_launcher: got arg 3 '[^']*/Tests/RunCMake/GoogleTest/GoogleTestLauncher-build(/Debug)?/test_launcher(\.exe)?'
-1: launching: "[^"]*/Tests/RunCMake/GoogleTest/GoogleTestLauncher-build(/Debug)?/test_launcher(\.exe)?" "emulatorparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/GoogleTestLauncher-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests"
-1: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]GoogleTestLauncher-build([/\]Debug)?[/\]test_launcher(\.exe)?'
-1: test_launcher: got arg 1 'emulatorparam'
-1: test_launcher: got arg 2 '--'
-1: test_launcher: got arg 3 '[^']*/Tests/RunCMake/GoogleTest/GoogleTestLauncher-build(/Debug)?/launcher_test(\.exe)?'
-1: launching: "[^"]*/Tests/RunCMake/GoogleTest/GoogleTestLauncher-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests"
-1: launcher_test\.test1
-1/1 Test #1: launcher_test\.test1 [.]+ +Passed +[0-9.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-test-stdout.txt b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-test-stdout.txt
new file mode 100644
index 0000000..24cb1b1
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-test-stdout.txt
@@ -0,0 +1,38 @@
+test 1
+ Start 1: launcher_test\.test1
+
+1: Test command: [^
+]*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-NEW-build([/\]Debug)?[/\]test_launcher(\.exe)?"? "" "launcherparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/test_launcher(\.exe)?" "" "emulatorparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests" "a" "" "b"
+1: Working Directory: [^
+]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build
+1: Test timeout computed to be: [0-9]+
+1: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-NEW-build([/\]Debug)?[/\]test_launcher(\.exe)?'
+1: test_launcher: got arg 1 ''
+1: test_launcher: got arg 2 'launcherparam'
+1: test_launcher: got arg 3 '--'
+1: test_launcher: got arg 4 '[^']*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/test_launcher(\.exe)?'
+1: launching: "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/test_launcher(\.exe)?" "" "emulatorparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests" "a" "" "b"
+1: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-NEW-build([/\]Debug)?[/\]test_launcher(\.exe)?'
+1: test_launcher: got arg 1 ''
+1: test_launcher: got arg 2 'emulatorparam'
+1: test_launcher: got arg 3 '--'
+1: test_launcher: got arg 4 '[^']*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/launcher_test(\.exe)?'
+1: launching: "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests" "a" "" "b"
+1: launcher_test\.test1
+1/2 Test #1: launcher_test\.test1 [.]+ +Passed +[0-9.]+ sec
+test 2
+ Start 2: launcher_test\.test1
+
+2: Test command: [^
+]*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-NEW-build([/\]Debug)?[/\]test_launcher(\.exe)?"? "" "launcherparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "a" "" "b"
+2: Working Directory: [^
+]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build
+2: Test timeout computed to be: [0-9]+
+2: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-NEW-build([/\]Debug)?[/\]test_launcher(\.exe)?'
+2: test_launcher: got arg 1 ''
+2: test_launcher: got arg 2 'launcherparam'
+2: test_launcher: got arg 3 '--'
+2: test_launcher: got arg 4 '[^']*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/launcher_test(\.exe)?'
+2: launching: "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "a" "" "b"
+2: launcher_test.test1
+2/2 Test #2: launcher_test\.test1 [.]+ +Passed +[0-9.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW.cmake b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW.cmake
new file mode 100644
index 0000000..1621abc
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0178 NEW)
+include(Launcher.cmake)
diff --git a/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-test-stdout.txt b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-test-stdout.txt
new file mode 100644
index 0000000..0b76200
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-test-stdout.txt
@@ -0,0 +1,35 @@
+test 1
+ Start 1: launcher_test\.test1
+
+1: Test command: "?[^
+]*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-OLD-build([/\]Debug)?[/\]test_launcher(\.exe)?"? "launcherparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/test_launcher(\.exe)?" "emulatorparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests" "a" "b"
+1: Working Directory: [^
+]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build
+1: Test timeout computed to be: [0-9]+
+1: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-OLD-build([/\]Debug)?[/\]test_launcher(\.exe)?'
+1: test_launcher: got arg 1 'launcherparam'
+1: test_launcher: got arg 2 '--'
+1: test_launcher: got arg 3 '[^']*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/test_launcher(\.exe)?'
+1: launching: "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/test_launcher(\.exe)?" "emulatorparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests" "a" "b"
+1: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-OLD-build([/\]Debug)?[/\]test_launcher(\.exe)?'
+1: test_launcher: got arg 1 'emulatorparam'
+1: test_launcher: got arg 2 '--'
+1: test_launcher: got arg 3 '[^']*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/launcher_test(\.exe)?'
+1: launching: "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests" "a" "b"
+1: launcher_test\.test1
+1/2 Test #1: launcher_test\.test1 [.]+ +Passed +[0-9.]+ sec
+test 2
+ Start 2: launcher_test\.test1
+
+2: Test command: [^
+]*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-OLD-build([/\]Debug)?[/\]test_launcher(\.exe)?"? "launcherparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "a" "b"
+2: Working Directory: [^
+]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build
+2: Test timeout computed to be: [0-9]+
+2: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-OLD-build([/\]Debug)?[/\]test_launcher(\.exe)?'
+2: test_launcher: got arg 1 'launcherparam'
+2: test_launcher: got arg 2 '--'
+2: test_launcher: got arg 3 '[^']*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/launcher_test(\.exe)?'
+2: launching: "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "a" "b"
+2: launcher_test.test1
+2/2 Test #2: launcher_test\.test1 [.]+ +Passed +[0-9.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD.cmake b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD.cmake
new file mode 100644
index 0000000..8830cd0
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0178 OLD)
+include(Launcher.cmake)
diff --git a/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-stderr.txt b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-stderr.txt
new file mode 100644
index 0000000..00b4939
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-stderr.txt
@@ -0,0 +1,38 @@
+CMake Warning \(dev\) at [^
+]*/Modules/GoogleTest\.cmake:[0-9]+ \(message\):
+ The 'launcher_test' target's TEST_LAUNCHER or CROSSCOMPILING_EMULATOR test
+ properties contain one or more empty values\. Those empty values are being
+ silently discarded to preserve backward compatibility\.
+
+ Policy CMP0178 is not set: Test command lines preserve empty arguments\.
+ Run "cmake --help-policy CMP0178" for policy details\. Use the cmake_policy
+ command to set the policy and suppress this warning\.
+Call Stack \(most recent call first\):
+ Launcher\.cmake:[0-9]+ \(gtest_discover_tests\)
+ Launcher-CMP0178-WARN\.cmake:1 \(include\)
+ CMakeLists\.txt:3 \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at [^
+]*/Modules/GoogleTest\.cmake:[0-9]+ \(message\):
+ The EXTRA_ARGS value contains one or more empty values\. Those empty values
+ are being silently discarded to preserve backward compatibility\.
+
+ Policy CMP0178 is not set: Test command lines preserve empty arguments\.
+ Run "cmake --help-policy CMP0178" for policy details\. Use the cmake_policy
+ command to set the policy and suppress this warning\.
+Call Stack \(most recent call first\):
+ Launcher\.cmake:[0-9]+ \(gtest_discover_tests\)
+ Launcher-CMP0178-WARN\.cmake:1 \(include\)
+ CMakeLists\.txt:3 \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) in CMakeLists\.txt:
+ The TEST_LAUNCHER property of target 'launcher_test' contains empty list
+ items\. Those empty items are being silently discarded to preserve backward
+ compatibility\.
+
+ Policy CMP0178 is not set: Test command lines preserve empty arguments\.
+ Run "cmake --help-policy CMP0178" for policy details\. Use the cmake_policy
+ command to set the policy and suppress this warning\.
+This warning is for project developers\. Use -Wno-dev to suppress it\.
diff --git a/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-test-stdout.txt b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-test-stdout.txt
new file mode 100644
index 0000000..1db6f50
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-test-stdout.txt
@@ -0,0 +1,35 @@
+test 1
+ Start 1: launcher_test\.test1
+
+1: Test command: "?[^
+]*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-WARN-build([/\]Debug)?[/\]test_launcher(\.exe)?"? "launcherparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/test_launcher(\.exe)?" "emulatorparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests" "a" "b"
+1: Working Directory: [^
+]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build
+1: Test timeout computed to be: [0-9]+
+1: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-WARN-build([/\]Debug)?[/\]test_launcher(\.exe)?'
+1: test_launcher: got arg 1 'launcherparam'
+1: test_launcher: got arg 2 '--'
+1: test_launcher: got arg 3 '[^']*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/test_launcher(\.exe)?'
+1: launching: "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/test_launcher(\.exe)?" "emulatorparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests" "a" "b"
+1: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-WARN-build([/\]Debug)?[/\]test_launcher(\.exe)?'
+1: test_launcher: got arg 1 'emulatorparam'
+1: test_launcher: got arg 2 '--'
+1: test_launcher: got arg 3 '[^']*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/launcher_test(\.exe)?'
+1: launching: "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "--gtest_also_run_disabled_tests" "a" "b"
+1: launcher_test\.test1
+1/2 Test #1: launcher_test\.test1 [.]+ +Passed +[0-9.]+ sec
+test 2
+ Start 2: launcher_test\.test1
+
+2: Test command: [^
+]*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-WARN-build([/\]Debug)?[/\]test_launcher(\.exe)?"? "launcherparam" "--" "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "a" "b"
+2: Working Directory: [^
+]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build
+2: Test timeout computed to be: [0-9]+
+2: test_launcher: got arg 0 '[^']*[/\]Tests[/\]RunCMake[/\]GoogleTest[/\]Launcher-CMP0178-WARN-build([/\]Debug)?[/\]test_launcher(\.exe)?'
+2: test_launcher: got arg 1 'launcherparam'
+2: test_launcher: got arg 2 '--'
+2: test_launcher: got arg 3 '[^']*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/launcher_test(\.exe)?'
+2: launching: "[^"]*/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN-build(/Debug)?/launcher_test(\.exe)?" "--gtest_filter=launcher_test\.test1" "a" "b"
+2: launcher_test.test1
+2/2 Test #2: launcher_test\.test1 [.]+ +Passed +[0-9.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN.cmake b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN.cmake
new file mode 100644
index 0000000..e109075
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/Launcher-CMP0178-WARN.cmake
@@ -0,0 +1 @@
+include(Launcher.cmake)
diff --git a/Tests/RunCMake/GoogleTest/GoogleTestLauncher.cmake b/Tests/RunCMake/GoogleTest/Launcher.cmake
index 5f4e6eb..11ba87e 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTestLauncher.cmake
+++ b/Tests/RunCMake/GoogleTest/Launcher.cmake
@@ -11,14 +11,14 @@ add_executable(launcher_test launcher_test.c)
xcode_sign_adhoc(launcher_test)
set(launcher
"$<TARGET_FILE:test_launcher>"
- "" # Verify that an empty list item will be preserved
+ "" # Verify CMP0178's handling of an empty list item
"launcherparam"
"--"
)
set_property(TARGET launcher_test PROPERTY TEST_LAUNCHER "${launcher}")
set(emulator
"$<TARGET_FILE:test_launcher>"
- "" # Verify that an empty list item will be preserved
+ "" # Verify CMP0178's handling of an empty list item
"emulatorparam"
"--"
)
@@ -26,4 +26,10 @@ set_property(TARGET launcher_test PROPERTY CROSSCOMPILING_EMULATOR "${emulator}"
gtest_discover_tests(
launcher_test
+ EXTRA_ARGS a "" b
+)
+
+gtest_add_tests(
+ TARGET launcher_test
+ EXTRA_ARGS a "" b
)
diff --git a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake
index 08cc274..e1bff64 100644
--- a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake
@@ -101,7 +101,7 @@ function(run_GoogleTest DISCOVERY_MODE)
)
endfunction()
-function(run_GoogleTestLauncher DISCOVERY_MODE)
+function(run_Launcher_CMP0178 DISCOVERY_MODE cmp0178)
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "14.0")
return()
endif()
@@ -110,12 +110,12 @@ function(run_GoogleTestLauncher DISCOVERY_MODE)
endif()
# Use a single build tree for a few tests without cleaning.
- set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTestLauncher-build)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Launcher-CMP0178-${cmp0178}-build)
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
endif()
- run_cmake_with_options(GoogleTestLauncher
+ run_cmake_with_options(Launcher-CMP0178-${cmp0178}
-DCMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE=${DISCOVERY_MODE}
)
@@ -123,14 +123,14 @@ function(run_GoogleTestLauncher DISCOVERY_MODE)
# do not issue any warnings on stderr that would cause the build to fail
set(RunCMake_TEST_OUTPUT_MERGE 1)
- run_cmake_command(GoogleTestLauncher-build
+ run_cmake_command(Launcher-CMP0178-${cmp0178}-build
${CMAKE_COMMAND}
--build .
--config Debug
)
unset(RunCMake_TEST_OUTPUT_MERGE)
- run_cmake_command(GoogleTestLauncher-test
+ run_cmake_command(Launcher-CMP0178-${cmp0178}-test
${CMAKE_CTEST_COMMAND}
-C Debug
-V
@@ -356,11 +356,13 @@ function(run_GoogleTest_discovery_test_list_scoped DISCOVERY_MODE)
endfunction()
foreach(DISCOVERY_MODE POST_BUILD PRE_TEST)
- message("Testing ${DISCOVERY_MODE} discovery mode via CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE global override...")
+ message(STATUS "Testing ${DISCOVERY_MODE} discovery mode via CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE global override...")
run_GoogleTest(${DISCOVERY_MODE})
- run_GoogleTestLauncher(${DISCOVERY_MODE})
run_GoogleTestXML(${DISCOVERY_MODE})
- message("Testing ${DISCOVERY_MODE} discovery mode via DISCOVERY_MODE option...")
+ run_Launcher_CMP0178(${DISCOVERY_MODE} NEW)
+ run_Launcher_CMP0178(${DISCOVERY_MODE} OLD)
+ run_Launcher_CMP0178(${DISCOVERY_MODE} WARN)
+ message(STATUS "Testing ${DISCOVERY_MODE} discovery mode via DISCOVERY_MODE option...")
run_GoogleTest_discovery_timeout(${DISCOVERY_MODE})
run_GoogleTest_discovery_arg_change(${DISCOVERY_MODE})
run_GoogleTest_discovery_test_list(${DISCOVERY_MODE})
@@ -369,6 +371,6 @@ foreach(DISCOVERY_MODE POST_BUILD PRE_TEST)
endforeach()
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
- message("Testing PRE_TEST discovery multi configuration...")
+ message(STATUS "Testing PRE_TEST discovery multi configuration...")
run_GoogleTest_discovery_multi_config()
endif()
diff --git a/Tests/RunCMake/GoogleTest/launcher_test.c b/Tests/RunCMake/GoogleTest/launcher_test.c
index ce91565..eed6206 100644
--- a/Tests/RunCMake/GoogleTest/launcher_test.c
+++ b/Tests/RunCMake/GoogleTest/launcher_test.c
@@ -10,7 +10,7 @@ TEST_F( launcher_test, test1 )
int main(int argc, char** argv)
{
- /* Note: GoogleTest.cmake doesn't actually depend on Google Test as such;
+ /* Note: Launcher.cmake doesn't actually depend on Google Test as such;
* it only requires that we produces output in the expected format when
* invoked with --gtest_list_tests. Thus, we fake that here. This allows us
* to test the module without actually needing Google Test. */