diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index c97efa0e45..ed3e56d0c1 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -979,6 +979,17 @@ that may contain the following fields: Equivalent to passing :option:`--no-tests=ignore ` on the command line. +.. _`CMakePresets test testPassthroughArguments`: + + ``testPassthroughArguments`` + An optional array of strings. Each element is forwarded as an argument + to every test executable, equivalent to passing arguments after + :option:`ctest --` on the command line. + This is allowed in preset files specifying version ``12`` or above. + + When both preset and command-line passthrough arguments are specified, + preset arguments appear first, followed by command-line arguments. + Package Preset ^^^^^^^^^^^^^^ @@ -1513,6 +1524,11 @@ they were added and a summary of the new features and changes is given below. regardless of whether it is inherited by another preset in a different directory. + * Changes to `Test Presets `_ + + * The `testPassthroughArguments `_ + field was added to forward arguments to test executables. + Schema ====== diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index c414ae5e98..e54cc9fe3e 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -193,7 +193,7 @@ "vendor": { "$ref": "#/definitions/vendor" }, "configurePresets": { "$ref": "#/definitions/configurePresetsV10" }, "buildPresets": { "$ref": "#/definitions/buildPresetsV11" }, - "testPresets": { "$ref": "#/definitions/testPresetsV11" }, + "testPresets": { "$ref": "#/definitions/testPresetsV12" }, "packagePresets": { "$ref": "#/definitions/packagePresetsV10" }, "workflowPresets": { "$ref": "#/definitions/workflowPresetsV10" }, "include": { "$ref": "#/definitions/include" } @@ -1211,6 +1211,28 @@ } } }, + "testPresetsExecutionV12": { + "type": "object", + "description": "An optional object specifying options for test execution.", + "allOf": [ + { "$ref": "#/definitions/testPresetsExecutionObject" }, + { "$ref": "#/definitions/commentAsProperty" }, + { + "properties": { + "repeat": { "$ref": "#/definitions/testPresetsExecutionRepeatV10" }, + "jobs": { "$ref": "#/definitions/testPresetsExecutionJobsV11" }, + "testPassthroughArguments": { + "type": "array", + "description": "An optional array of strings. Each element is forwarded as an argument to every test executable. Equivalent to passing arguments after -- on the ctest command line.", + "items": { + "type": "string" + } + } + } + } + ], + "unevaluatedProperties": false + }, "testPresetsExecutionV11": { "type": "object", "description": "An optional object specifying options for test execution.", @@ -1413,6 +1435,22 @@ } } }, + "testPresetsAdditionalPropertiesV12": { + "properties": { + "execution": { "$ref": "#/definitions/testPresetsExecutionV12" }, + "filter": { + "type": "object", + "description": "An optional object specifying how to filter the tests to run.", + "properties": { + "include": { "$ref": "#/definitions/testPresetsFilterIncludeV10" }, + "exclude": { "$ref": "#/definitions/testPresetsFilterExcludeV10" }, + "$comment": { "$ref": "#/definitions/$comment" } + } + }, + "output": { "$ref": "#/definitions/testPresetsOutputV6" }, + "condition": { "$ref": "#/definitions/topConditionV10" } + } + }, "testPresetsAdditionalPropertiesV11": { "properties": { "execution": { "$ref": "#/definitions/testPresetsExecutionV11" }, @@ -1555,6 +1593,20 @@ "name" ] }, + "testPresetsV12": { + "type": "array", + "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 12 and higher.", + "items": { + "type": "object", + "description": "A test preset object", + "allOf": [ + { "$ref": "#/definitions/testPresetsItemsV2" }, + { "$ref": "#/definitions/testPresetsAdditionalPropertiesV12" }, + { "$ref": "#/definitions/commentAsProperty" } + ], + "unevaluatedProperties": false + } + }, "testPresetsV11": { "type": "array", "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 11 and higher.", diff --git a/Help/release/dev/ctest-passthrough-args.rst b/Help/release/dev/ctest-passthrough-args.rst index 525b5d0042..93175e4070 100644 --- a/Help/release/dev/ctest-passthrough-args.rst +++ b/Help/release/dev/ctest-passthrough-args.rst @@ -3,3 +3,8 @@ ctest-passthrough-args * :manual:`ctest(1)` gained support for forwarding extra arguments to test executables using a :option:`-- ` separator. + +* :manual:`cmake-presets(7)` gained support for a + ``testPassthroughArguments`` field in the + test preset ``execution`` object for + forwarding arguments to test executables via presets. diff --git a/Source/cmCMakePresetsErrors.cxx b/Source/cmCMakePresetsErrors.cxx index f2cbe84271..99462eb979 100644 --- a/Source/cmCMakePresetsErrors.cxx +++ b/Source/cmCMakePresetsErrors.cxx @@ -189,6 +189,12 @@ void JOBS_PROC_UNSUPPORTED(cmJSONState* state) "processor-count-based jobs preset support"); } +void PASSTHROUGH_ARGS_UNSUPPORTED(cmJSONState* state) +{ + state->AddError("File version must be 12 or higher for " + "testPassthroughArguments preset support"); +} + void CYCLIC_INCLUDE(std::string const& file, cmJSONState* state) { state->AddError(cmStrCat("Cyclic include among preset files: ", file)); diff --git a/Source/cmCMakePresetsErrors.h b/Source/cmCMakePresetsErrors.h index 372ceb8803..8e9a426cc3 100644 --- a/Source/cmCMakePresetsErrors.h +++ b/Source/cmCMakePresetsErrors.h @@ -74,6 +74,8 @@ void GRAPHVIZ_FILE_UNSUPPORTED(cmJSONState* state); void JOBS_PROC_UNSUPPORTED(cmJSONState* state); +void PASSTHROUGH_ARGS_UNSUPPORTED(cmJSONState* state); + void CYCLIC_INCLUDE(std::string const& file, cmJSONState* state); void TEST_OUTPUT_TRUNCATION_UNSUPPORTED(cmJSONState* state); diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx index a3fb908977..56b538575d 100644 --- a/Source/cmCMakePresetsGraph.cxx +++ b/Source/cmCMakePresetsGraph.cxx @@ -1008,6 +1008,8 @@ bool cmCMakePresetsGraph::TestPreset::VisitPresetInherit( InheritOptionalValue(execution.Timeout, parentExecution.Timeout); InheritOptionalValue(execution.NoTestsAction, parentExecution.NoTestsAction); + InheritVector(execution.TestPassthroughArguments, + parentExecution.TestPassthroughArguments); } else { preset.Execution = parent.Execution; } diff --git a/Source/cmCMakePresetsGraph.h b/Source/cmCMakePresetsGraph.h index 4ce0ace626..df195f1a73 100644 --- a/Source/cmCMakePresetsGraph.h +++ b/Source/cmCMakePresetsGraph.h @@ -299,6 +299,7 @@ public: cm::optional ScheduleRandom; cm::optional Timeout; cm::optional NoTestsAction; + std::vector TestPassthroughArguments; }; std::string ConfigurePreset; diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx index 55fd2a14d7..249f84baa6 100644 --- a/Source/cmCMakePresetsGraphReadJSON.cxx +++ b/Source/cmCMakePresetsGraphReadJSON.cxx @@ -719,6 +719,13 @@ bool cmCMakePresetsGraph::ReadJSONFile(std::string const& filename, return false; } + // Support for testPassthroughArguments added in version 12. + if (v < 12 && preset.Execution && + !preset.Execution->TestPassthroughArguments.empty()) { + cmCMakePresetsErrors::PASSTHROUGH_ARGS_UNSUPPORTED(&this->parseState); + return false; + } + this->TestPresetOrder.push_back(preset.Name); } diff --git a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx index d7164452ea..050c701434 100644 --- a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx @@ -353,7 +353,10 @@ auto const TestPresetExecutionHelper = .Bind("timeout"_s, &TestPreset::ExecutionOptions::Timeout, cmCMakePresetsGraphInternal::PresetOptionalIntHelper, false) .Bind("noTestsAction"_s, &TestPreset::ExecutionOptions::NoTestsAction, - TestPresetOptionalExecutionNoTestsActionHelper, false)); + TestPresetOptionalExecutionNoTestsActionHelper, false) + .Bind("testPassthroughArguments"_s, + &TestPreset::ExecutionOptions::TestPassthroughArguments, + cmCMakePresetsGraphInternal::PresetVectorStringHelper, false)); auto const TestPresetFilterHelper = JSONHelperBuilder::Optional( diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index e423b8e6fd..f49712c4b1 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1800,6 +1800,11 @@ bool cmCTest::SetArgsFromPreset(std::string const& presetName, return false; } } + + // Assign passthrough arguments from preset. + // CLI -- args (parsed later in Run()) will be appended after these. + this->Impl->TestOptions.TestPassthroughArguments = + expandedPreset->Execution->TestPassthroughArguments; } return true; diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough-test-basic-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-basic-stdout.txt new file mode 100644 index 0000000000..e600e4c673 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-basic-stdout.txt @@ -0,0 +1,3 @@ +1: Test command: [^ +]* "-E" "echo" "base_output" "--extra-flag" +.* diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough-test-execOnly-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-execOnly-stdout.txt new file mode 100644 index 0000000000..93e76d0f87 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-execOnly-stdout.txt @@ -0,0 +1,3 @@ +1: Test command: [^ +]* "-E" "echo" "base_output" "--only-arg" +.* diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough-test-inherit-stdout.txt b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-inherit-stdout.txt new file mode 100644 index 0000000000..5788920b1d --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/Passthrough-test-inherit-stdout.txt @@ -0,0 +1,3 @@ +1: Test command: [^ +]* "-E" "echo" "base_output" "--parent-arg" +.* diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough.cmake b/Tests/RunCMake/CMakePresetsTest/Passthrough.cmake new file mode 100644 index 0000000000..a398f9e9c2 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/Passthrough.cmake @@ -0,0 +1,2 @@ +enable_testing() +add_test(echo_test ${CMAKE_COMMAND} -E echo base_output) diff --git a/Tests/RunCMake/CMakePresetsTest/Passthrough.json.in b/Tests/RunCMake/CMakePresetsTest/Passthrough.json.in new file mode 100644 index 0000000000..6fe7ac267d --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/Passthrough.json.in @@ -0,0 +1,47 @@ +{ + "version": 12, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build/${presetName}" + } + ], + "testPresets": [ + { + "name": "basic", + "configurePreset": "default", + "output": { + "verbosity": "verbose" + }, + "execution": { + "testPassthroughArguments": ["--extra-flag"] + } + }, + { + "name": "parent", + "hidden": true, + "execution": { + "testPassthroughArguments": ["--parent-arg"] + } + }, + { + "name": "inherit", + "inherits": "parent", + "configurePreset": "default", + "output": { + "verbosity": "verbose" + } + }, + { + "name": "execOnly", + "configurePreset": "default", + "output": { + "verbosity": "verbose" + }, + "execution": { + "testPassthroughArguments": ["--only-arg"] + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughCombined-test-combined-stdout.txt b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined-test-combined-stdout.txt new file mode 100644 index 0000000000..e572da9b43 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined-test-combined-stdout.txt @@ -0,0 +1,3 @@ +1: Test command: [^ +]* "-E" "echo" "base_output" "--preset-arg" "--cli-arg" +.* diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.cmake b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.cmake new file mode 100644 index 0000000000..a398f9e9c2 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.cmake @@ -0,0 +1,2 @@ +enable_testing() +add_test(echo_test ${CMAKE_COMMAND} -E echo base_output) diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.json.in b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.json.in new file mode 100644 index 0000000000..37beede40f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/PassthroughCombined.json.in @@ -0,0 +1,22 @@ +{ + "version": 12, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build/${presetName}" + } + ], + "testPresets": [ + { + "name": "combined", + "configurePreset": "default", + "output": { + "verbosity": "verbose" + }, + "execution": { + "testPassthroughArguments": ["--preset-arg"] + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-result.txt b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-stderr.txt new file mode 100644 index 0000000000..a3aaf4f272 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported-test-x-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported: +File version must be 12 or higher for testPassthroughArguments preset support$ diff --git a/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported.json.in b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported.json.in new file mode 100644 index 0000000000..c6edbcc1c5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/PassthroughUnsupported.json.in @@ -0,0 +1,19 @@ +{ + "version": 11, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ], + "testPresets": [ + { + "name": "default", + "configurePreset": "default", + "execution": { + "testPassthroughArguments": ["--extra"] + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake index d7fcb48d7d..2fbd8af3a3 100644 --- a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake @@ -113,8 +113,13 @@ run_cmake_test_presets(TestOutputTruncationUnsupported "" "" "x") run_cmake_test_presets(OutputJUnitUnsupported "" "" "x") run_cmake_test_presets(InvalidJobs "" "" "x") run_cmake_test_presets(JobsProcUnsupported "" "" "x") +run_cmake_test_presets(PassthroughUnsupported "" "" "x") set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) run_cmake_test_presets(ConfigurePresetUnreachable "" "" "x") set(CMakePresetsTest_NO_CONFIGURE 0) +run_cmake_test_presets(Passthrough "default" "" "basic;inherit;execOnly") +run_cmake_test_presets(PassthroughCombined "default" "" "combined" "--" "--cli-arg") +set(CMakePresetsTest_NO_CONFIGURE 1) + set(CMakePresetsTest_NO_BUILD 0)