tests: Preserve empty arguments in test command lines

This will now preserve empty values in the TEST_LAUNCHER and
CROSSCOMPILING_EMULATOR target properties for tests added by:

- The add_test() command.
- The ExternalData_Add_Test() command from the ExternalData module.
- The gtest_add_tests() or gtest_discover_tests() commands from the
  GoogleTest module.

For the gtest_add_tests() and gtest_discover_tests() commands,
empty elements in the values passed after the EXTRA_ARGS keyword
are also now preserved.

Policy CMP0178 is added to provide backward compatibility with the
old behavior where empty values were silently discarded from the
above cases.

Fixes: #26337
This commit is contained in:
Craig Scott 2024-09-30 21:13:13 +10:00
parent 9f1703530b
commit fc7aa3cd69
No known key found for this signature in database
GPG Key ID: 6FF37CBDCCADED9F
27 changed files with 512 additions and 80 deletions

View File

@ -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>

37
Help/policy/CMP0178.rst Normal file
View File

@ -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

View File

@ -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`.

View File

@ -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}

View File

@ -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)

View File

@ -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)

View File

@ -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}"

View File

@ -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"

View File

@ -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}>)

View File

@ -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]
@ -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

View File

@ -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()

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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;
};

View File

@ -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) << " ";
}
}
}
};

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,2 @@
cmake_policy(SET CMP0178 NEW)
include(Launcher.cmake)

View File

@ -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

View File

@ -0,0 +1,2 @@
cmake_policy(SET CMP0178 OLD)
include(Launcher.cmake)

View File

@ -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\.

View File

@ -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

View File

@ -0,0 +1 @@
include(Launcher.cmake)

View File

@ -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
)

View File

@ -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()

View File

@ -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. */