mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-10-04 04:03:22 +03:00
ctest: Add support for forwarding arguments to tests via --
Add support for `ctest [options] -- <args>` to forward extra arguments
to every executed test's command line. Arguments after `--` are appended
after each test's own arguments in the order given.
This enables passing options to test frameworks like Google Test or
doctest without needing per-test ARGS properties:
ctest -R my_test -- --gtest_filter=SomeTest.Case
ctest --verbose -- --success
An error is raised if `--` is combined with `--build-and-test`, `-S`,
or `-D`/`-T`/`-M` modes, which have their own argument forwarding.
A bare `--` with no following arguments is silently ignored.
Fixes: #20470
This commit is contained in:
1 parent
116272e296
commit
b3980bf703
15 files changed
+141
-2
No files matched your search
+23
-2
@@ -11,7 +11,7 @@ Synopsis
|
||||
.. parsed-literal::
|
||||
|
||||
`Run Tests`_
|
||||
ctest [<options>...] [--test-dir <path-to-build>]
|
||||
ctest [<options>...] [--test-dir <path-to-build>] [-- <test-args>...]
|
||||
|
||||
`Build and Test Mode`_
|
||||
ctest --build-and-test <path-to-source> <path-to-build>
|
||||
@@ -47,7 +47,7 @@ typically in a build tree generated by :manual:`cmake(1)`:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ctest [<options>...] [--test-dir <path-to-build>]
|
||||
ctest [<options>...] [--test-dir <path-to-build>] [-- <test-args>...]
|
||||
|
||||
If all tests pass, the exit code is ``0``. The exit code is non-zero
|
||||
in the following cases:
|
||||
@@ -536,6 +536,27 @@ The options for running tests are:
|
||||
the :ref:`cmake-instrumentation Indexing` section of CMake instrumentation for
|
||||
more details.
|
||||
|
||||
.. option:: -- <test-args>...
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Forward extra arguments to test executables.
|
||||
|
||||
All arguments after ``--`` are appended to the end of every executed
|
||||
test's command line. This is useful for passing options to test
|
||||
frameworks like Google Test or doctest. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ctest -R my_test -- --gtest_filter=SomeTest.Case
|
||||
ctest --verbose -- --success
|
||||
|
||||
All selected tests receive the same extra arguments.
|
||||
Use :option:`-R <ctest -R>` or :option:`-L <ctest -L>` to limit
|
||||
which tests are executed.
|
||||
|
||||
A bare ``--`` with no following arguments is silently ignored.
|
||||
|
||||
View Help
|
||||
=========
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
ctest-passthrough-args
|
||||
----------------------
|
||||
|
||||
* :manual:`ctest(1)` gained support for forwarding extra arguments to test
|
||||
executables using a :option:`-- <ctest -->` separator.
|
||||
@@ -707,6 +707,12 @@ void cmCTestRunTest::ComputeArguments()
|
||||
testCommand += "\"";
|
||||
this->Arguments.push_back(*j);
|
||||
}
|
||||
// Append passthrough arguments from ctest command line (after --)
|
||||
for (std::string const& arg :
|
||||
this->TestHandler->TestOptions.TestPassthroughArguments) {
|
||||
testCommand = cmStrCat(std::move(testCommand), " \"", arg, '"');
|
||||
this->Arguments.push_back(arg);
|
||||
}
|
||||
this->TestResult.FullCommandLine = testCommand;
|
||||
|
||||
// Print the test command in verbose mode
|
||||
|
||||
@@ -55,6 +55,8 @@ struct cmCTestTestOptions
|
||||
std::string ExcludeTestListFile;
|
||||
std::string ResourceSpecFile;
|
||||
std::string JUnitXMLFileName;
|
||||
|
||||
std::vector<std::string> TestPassthroughArguments;
|
||||
};
|
||||
|
||||
/** \class cmCTestTestHandler
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <ratio>
|
||||
#include <sstream>
|
||||
@@ -2506,8 +2507,20 @@ int cmCTest::Run(std::vector<std::string> const& args)
|
||||
};
|
||||
|
||||
// process the command line arguments
|
||||
bool hadPassthroughDelimiter = false;
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
std::string const& arg = args[i];
|
||||
|
||||
// The "--" argument terminates processing and passes
|
||||
// all remaining arguments through to the tests.
|
||||
if (arg == "--"_s) {
|
||||
hadPassthroughDelimiter = true;
|
||||
std::copy(
|
||||
args.begin() + i + 1, args.end(),
|
||||
std::back_inserter(this->Impl->TestOptions.TestPassthroughArguments));
|
||||
break;
|
||||
}
|
||||
|
||||
bool matched = false;
|
||||
for (auto const& m : arguments) {
|
||||
if (m.matches(arg)) {
|
||||
@@ -2580,6 +2593,27 @@ int cmCTest::Run(std::vector<std::string> const& args)
|
||||
}
|
||||
}
|
||||
|
||||
// Passthrough arguments (after --) are only supported in direct test
|
||||
// execution mode, not --build-and-test, -S, or -D/-T/-M modes.
|
||||
if (hadPassthroughDelimiter) {
|
||||
if (cmakeAndTest) {
|
||||
cmSystemTools::Error(
|
||||
"The -- option cannot be used with --build-and-test. "
|
||||
"Use --build-options or --test-command to forward arguments.");
|
||||
return 1;
|
||||
}
|
||||
if (!runScripts.empty()) {
|
||||
cmSystemTools::Error(
|
||||
"The -- option cannot be used with -S or -SP script mode.");
|
||||
return 1;
|
||||
}
|
||||
if (processSteps) {
|
||||
cmSystemTools::Error(
|
||||
"The -- option cannot be used with -D, -T, or -M dashboard mode.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// TestProgressOutput only supported if console supports it and not logging
|
||||
// to a file
|
||||
this->Impl->TestProgressOutput = this->Impl->TestProgressOutput &&
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
1: Test command: [^
|
||||
]* "-E" "echo" "base_output" "--extra-flag"
|
||||
.*
|
||||
2: Test command: [^
|
||||
]* "-E" "echo" "second_test" "--extra-flag"
|
||||
.*
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
^CMake Error: The -- option cannot be used with --build-and-test\. Use --build-options or --test-command to forward arguments\.$
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
^CMake Error: The -- option cannot be used with --build-and-test\. Use --build-options or --test-command to forward arguments\.$
|
||||
@@ -0,0 +1,6 @@
|
||||
1: Test command: [^
|
||||
]* "-E" "echo" "base_output" "-R" "--verbose"
|
||||
.*
|
||||
2: Test command: [^
|
||||
]* "-E" "echo" "second_test" "-R" "--verbose"
|
||||
.*
|
||||
@@ -0,0 +1,6 @@
|
||||
1: Test command: [^
|
||||
]* "-E" "echo" "base_output"
|
||||
.*
|
||||
2: Test command: [^
|
||||
]* "-E" "echo" "second_test"
|
||||
.*
|
||||
@@ -0,0 +1,6 @@
|
||||
1: Test command: [^
|
||||
]* "-E" "echo" "base_output" "--flag1" "--flag2" "value"
|
||||
.*
|
||||
2: Test command: [^
|
||||
]* "-E" "echo" "second_test" "--flag1" "--flag2" "value"
|
||||
.*
|
||||
@@ -0,0 +1,8 @@
|
||||
Test project [^
|
||||
]*/Tests/RunCMake/CTestCommandLine/Passthrough-with-filter(
|
||||
|
|
||||
[^0-9][^
|
||||
]*)+
|
||||
2: Test command: [^
|
||||
]* "-E" "echo" "second_test" "--extra"
|
||||
.*
|
||||
@@ -734,3 +734,38 @@ endforeach()
|
||||
run_cmake_command(ScheduleRandomSeed1 ${CMAKE_CTEST_COMMAND} --schedule-random --schedule-random-seed 42)
|
||||
run_cmake_command(ScheduleRandomSeed2 ${CMAKE_CTEST_COMMAND} --schedule-random --schedule-random-seed 42)
|
||||
endblock()
|
||||
|
||||
function(run_PassthroughTest case)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Passthrough-${case})
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
|
||||
add_test(echo_test \"${CMAKE_COMMAND}\" -E echo \"base_output\")
|
||||
add_test(echo_test2 \"${CMAKE_COMMAND}\" -E echo \"second_test\")
|
||||
")
|
||||
run_cmake_command(Passthrough-${case} ${CMAKE_CTEST_COMMAND} ${ARGN})
|
||||
endfunction()
|
||||
|
||||
# Basic passthrough
|
||||
run_PassthroughTest(basic -V -- --extra-flag)
|
||||
# Multiple passthrough args
|
||||
run_PassthroughTest(multiple -V -- --flag1 --flag2 value)
|
||||
# Passthrough with -R filter (only echo_test2 should run)
|
||||
run_PassthroughTest(with-filter -V -R echo_test2 -- --extra)
|
||||
# Empty passthrough (bare --)
|
||||
run_PassthroughTest(empty -V --)
|
||||
# Passthrough args that look like ctest flags
|
||||
run_PassthroughTest(ctest-flags -V -- -R --verbose)
|
||||
# -- rejected with --build-and-test
|
||||
run_cmake_command(Passthrough-build-and-test-error ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
${RunCMake_BINARY_DIR}/Passthrough-build-and-test-error/does-not-exist
|
||||
${RunCMake_BINARY_DIR}/Passthrough-build-and-test-error/does-not-exist
|
||||
--build-generator "None" -- --extra-flag)
|
||||
# bare -- rejected with --build-and-test
|
||||
run_cmake_command(Passthrough-build-and-test-empty-error ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
${RunCMake_BINARY_DIR}/Passthrough-build-and-test-empty-error/does-not-exist
|
||||
${RunCMake_BINARY_DIR}/Passthrough-build-and-test-empty-error/does-not-exist
|
||||
--build-generator "None" --)
|
||||
Reference in new issue
Block a user