From f9c831dad968758cee8c85f3112351e417f58ddd Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Thu, 7 May 2026 15:18:34 -0400 Subject: [PATCH] ctest: encapsulate loading of options from test preset Encapsulate the assignment of cmCTestTestOptions from a test preset. --- Source/CTest/cmCTestTestHandler.cxx | 64 +++++++++++++++++++++++++ Source/CTest/cmCTestTestHandler.h | 13 +++++ Source/cmCTest.cxx | 74 +---------------------------- 3 files changed, 78 insertions(+), 73 deletions(-) diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 9731a1755c..5f211600cc 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -35,6 +35,7 @@ #include "cm_utf8.h" #include "cmArgumentParser.h" +#include "cmCMakePresetsGraph.h" #include "cmCTest.h" #include "cmCTestDiscoverTests.h" #include "cmCTestMultiProcessHandler.h" @@ -59,6 +60,69 @@ #include "cmXMLWriter.h" #include "cmake.h" +void cmCTestApplyTestPresetToOptions( + cmCTestTestOptions& opts, cmCMakePresetsGraph::TestPreset const& preset) +{ + if (preset.Filter) { + if (preset.Filter->Include) { + auto const& inc = *preset.Filter->Include; + opts.IncludeRegularExpression = inc.Name; + if (!inc.Label.empty()) { + opts.LabelRegularExpression.push_back(inc.Label); + } + opts.UseUnion = inc.UseUnion.value_or(false); + if (inc.Index) { + auto const& idx = *inc.Index; + if (!idx.IndexFile.empty()) { + opts.TestsToRunInformation = idx.IndexFile; + } else { + opts.TestsToRunInformation = cmStrCat( + (idx.Start ? std::to_string(*idx.Start) : std::string{}), ',', + (idx.End ? std::to_string(*idx.End) : std::string{}), ',', + (idx.Stride ? std::to_string(*idx.Stride) : std::string{}), ',', + cmJoin(idx.SpecificTests, ",")); + } + } + } + if (preset.Filter->Exclude) { + auto const& exc = *preset.Filter->Exclude; + opts.ExcludeRegularExpression = exc.Name; + if (!exc.Label.empty()) { + opts.ExcludeLabelRegularExpression.push_back(exc.Label); + } + if (exc.Fixtures) { + opts.ExcludeFixtureRegularExpression = exc.Fixtures->Any; + opts.ExcludeFixtureSetupRegularExpression = exc.Fixtures->Setup; + opts.ExcludeFixtureCleanupRegularExpression = exc.Fixtures->Cleanup; + } + } + } + + if (preset.Execution) { + auto const& exec = *preset.Execution; + opts.StopOnFailure = exec.StopOnFailure.value_or(false); + opts.ResourceSpecFile = exec.ResourceSpecFile; + opts.ScheduleRandom = exec.ScheduleRandom.value_or(false); + opts.TestPassthroughArguments = exec.TestPassthroughArguments; + } + + if (preset.Output) { + auto const& output = *preset.Output; + if (!output.OutputJUnitFile.empty()) { + opts.JUnitXMLFileName = output.OutputJUnitFile; + } + if (output.MaxPassedTestOutputSize) { + opts.OutputSizePassed = *output.MaxPassedTestOutputSize; + } + if (output.MaxFailedTestOutputSize) { + opts.OutputSizeFailed = *output.MaxFailedTestOutputSize; + } + if (output.TestOutputTruncation) { + opts.OutputTruncation = *output.TestOutputTruncation; + } + } +} + namespace { class cmCTestCommand diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index c6238dab29..276ad16045 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -19,6 +19,7 @@ #include "cmsys/RegularExpression.hxx" +#include "cmCMakePresetsGraph.h" #include "cmCTest.h" #include "cmCTestGenericHandler.h" #include "cmCTestTypes.h" // IWYU pragma: keep @@ -61,6 +62,18 @@ struct cmCTestTestOptions std::vector TestPassthroughArguments; }; +/** Apply a resolved TestPreset's fields to \a opts. + * + * Both the \c ctest \c --preset CLI path and the \c ctest_test(PRESET) + * script-command path call this to keep the mapping in one place and avoid + * drift when new preset fields are added. + * + * Fields that do not live in cmCTestTestOptions (e.g. ParallelLevel, Repeat, + * Timeout, NoTestsAction) are handled separately at each call site. + */ +void cmCTestApplyTestPresetToOptions( + cmCTestTestOptions& opts, cmCMakePresetsGraph::TestPreset const& preset); + /** \class cmCTestTestHandler * \brief A class that handles ctest -S invocations * diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index caf450e4c5..6ead9771bb 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1618,76 +1618,12 @@ bool cmCTest::SetArgsFromPreset(cmCMakePresetsArgs const& args) this->Impl->SubprojectSummary = expandedPreset->Output->SubprojectSummary.value_or(true); - if (expandedPreset->Output->MaxPassedTestOutputSize) { - this->Impl->TestOptions.OutputSizePassed = - *expandedPreset->Output->MaxPassedTestOutputSize; - } - - if (expandedPreset->Output->MaxFailedTestOutputSize) { - this->Impl->TestOptions.OutputSizeFailed = - *expandedPreset->Output->MaxFailedTestOutputSize; - } - - if (expandedPreset->Output->TestOutputTruncation) { - this->Impl->TestOptions.OutputTruncation = - *expandedPreset->Output->TestOutputTruncation; - } - if (expandedPreset->Output->MaxTestNameWidth) { this->Impl->MaxTestNameWidth = *expandedPreset->Output->MaxTestNameWidth; } } - if (expandedPreset->Filter) { - if (expandedPreset->Filter->Include) { - this->Impl->TestOptions.IncludeRegularExpression = - expandedPreset->Filter->Include->Name; - if (!expandedPreset->Filter->Include->Label.empty()) { - this->Impl->TestOptions.LabelRegularExpression.push_back( - expandedPreset->Filter->Include->Label); - } - - if (expandedPreset->Filter->Include->Index) { - if (expandedPreset->Filter->Include->Index->IndexFile.empty()) { - auto const& start = expandedPreset->Filter->Include->Index->Start; - auto const& end = expandedPreset->Filter->Include->Index->End; - auto const& stride = expandedPreset->Filter->Include->Index->Stride; - std::string indexOptions = cmStrCat( - (start ? std::to_string(*start) : std::string{}), ',', - (end ? std::to_string(*end) : std::string{}), ',', - (stride ? std::to_string(*stride) : std::string{}), ',', - cmJoin(expandedPreset->Filter->Include->Index->SpecificTests, - ",")); - - this->Impl->TestOptions.TestsToRunInformation = indexOptions; - } else { - this->Impl->TestOptions.TestsToRunInformation = - expandedPreset->Filter->Include->Index->IndexFile; - } - } - - this->Impl->TestOptions.UseUnion = - expandedPreset->Filter->Include->UseUnion.value_or(false); - } - - if (expandedPreset->Filter->Exclude) { - this->Impl->TestOptions.ExcludeRegularExpression = - expandedPreset->Filter->Exclude->Name; - if (!expandedPreset->Filter->Exclude->Label.empty()) { - this->Impl->TestOptions.ExcludeLabelRegularExpression.push_back( - expandedPreset->Filter->Exclude->Label); - } - - if (expandedPreset->Filter->Exclude->Fixtures) { - this->Impl->TestOptions.ExcludeFixtureRegularExpression = - expandedPreset->Filter->Exclude->Fixtures->Any; - this->Impl->TestOptions.ExcludeFixtureSetupRegularExpression = - expandedPreset->Filter->Exclude->Fixtures->Setup; - this->Impl->TestOptions.ExcludeFixtureCleanupRegularExpression = - expandedPreset->Filter->Exclude->Fixtures->Cleanup; - } - } - } + cmCTestApplyTestPresetToOptions(this->Impl->TestOptions, *expandedPreset); if (expandedPreset->Execution) { this->Impl->StopOnFailure = @@ -1705,9 +1641,6 @@ bool cmCTest::SetArgsFromPreset(cmCMakePresetsArgs const& args) this->Impl->ParallelLevelSetInCli = true; } - this->Impl->TestOptions.ResourceSpecFile = - expandedPreset->Execution->ResourceSpecFile; - if (expandedPreset->Execution->TestLoad) { auto testLoad = *expandedPreset->Execution->TestLoad; this->SetTestLoad(testLoad); @@ -1784,11 +1717,6 @@ bool cmCTest::SetArgsFromPreset(cmCMakePresetsArgs const& args) 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;