Merge branch 'release-3.29'
[kiteware-cmake.git] / Source / ctest.cxx
blobf6a11b4c389d3ffb702723869a2338d7c495e5c5
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
4 #include <cstring>
5 #include <iostream>
6 #include <string>
7 #include <vector>
9 #include "cmsys/Encoding.hxx"
11 #include "cmCTest.h"
12 #include "cmConsoleBuf.h"
13 #include "cmDocumentation.h"
14 #include "cmDocumentationEntry.h"
15 #include "cmSystemTools.h"
17 #include "CTest/cmCTestLaunch.h"
18 #include "CTest/cmCTestScriptHandler.h"
20 namespace {
21 const cmDocumentationEntry cmDocumentationName = {
22 {},
23 " ctest - Testing driver provided by CMake."
26 const cmDocumentationEntry cmDocumentationUsage = { {}, " ctest [options]" };
28 const cmDocumentationEntry cmDocumentationOptions[] = {
29 { "--preset <preset>, --preset=<preset>",
30 "Read arguments from a test preset." },
31 { "--list-presets", "List available test presets." },
32 { "-C <cfg>, --build-config <cfg>", "Choose configuration to test." },
33 { "--progress", "Enable short progress output from tests." },
34 { "-V,--verbose", "Enable verbose output from tests." },
35 { "-VV,--extra-verbose", "Enable more verbose output from tests." },
36 { "--debug", "Displaying more verbose internals of CTest." },
37 { "--output-on-failure",
38 "Output anything outputted by the test program "
39 "if the test should fail." },
40 { "--stop-on-failure", "Stop running the tests after one has failed." },
41 { "--test-output-size-passed <size>",
42 "Limit the output for passed tests "
43 "to <size> bytes" },
44 { "--test-output-size-failed <size>",
45 "Limit the output for failed tests "
46 "to <size> bytes" },
47 { "--test-output-truncation <mode>",
48 "Truncate 'tail' (default), 'middle' or 'head' of test output once "
49 "maximum output size is reached" },
50 { "-F", "Enable failover." },
51 { "-j [<level>], --parallel [<level>]",
52 "Run tests in parallel, "
53 "optionally limited to a given level of parallelism." },
54 { "-Q,--quiet", "Make ctest quiet." },
55 { "-O <file>, --output-log <file>", "Output to log file" },
56 { "--output-junit <file>", "Output test results to JUnit XML file." },
57 { "-N,--show-only[=format]",
58 "Disable actual execution of tests. The optional 'format' defines the "
59 "format of the test information and can be 'human' for the current text "
60 "format or 'json-v1' for json format. Defaults to 'human'." },
61 { "-L <regex>, --label-regex <regex>",
62 "Run tests with labels matching regular expression. "
63 "With multiple -L, run tests where each "
64 "regular expression matches at least one label." },
65 { "-R <regex>, --tests-regex <regex>",
66 "Run tests matching regular "
67 "expression." },
68 { "-E <regex>, --exclude-regex <regex>",
69 "Exclude tests matching regular "
70 "expression." },
71 { "-LE <regex>, --label-exclude <regex>",
72 "Exclude tests with labels matching regular expression. "
73 "With multiple -LE, exclude tests where each "
74 "regular expression matches at least one label." },
75 { "-FA <regex>, --fixture-exclude-any <regex>",
76 "Do not automatically "
77 "add any tests for "
78 "fixtures matching "
79 "regular expression." },
80 { "-FS <regex>, --fixture-exclude-setup <regex>",
81 "Do not automatically "
82 "add setup tests for "
83 "fixtures matching "
84 "regular expression." },
85 { "-FC <regex>, --fixture-exclude-cleanup <regex>",
86 "Do not automatically "
87 "add cleanup tests for "
88 "fixtures matching "
89 "regular expression." },
90 { "-D <dashboard>, --dashboard <dashboard>", "Execute dashboard test" },
91 { "-D <var>:<type>=<value>", "Define a variable for script mode" },
92 { "-M <model>, --test-model <model>", "Sets the model for a dashboard" },
93 { "-T <action>, --test-action <action>",
94 "Sets the dashboard action to "
95 "perform" },
96 { "--group <group>",
97 "Specify what build group on the dashboard you'd like to "
98 "submit results to." },
99 { "-S <script>, --script <script>",
100 "Execute a dashboard for a "
101 "configuration" },
102 { "-SP <script>, --script-new-process <script>",
103 "Execute a dashboard for a "
104 "configuration" },
105 { "-A <file>, --add-notes <file>", "Add a notes file with submission" },
106 { "-I [Start,End,Stride,test#,test#|Test file], --tests-information",
107 "Run a specific number of tests by number." },
108 { "-U, --union", "Take the Union of -I and -R" },
109 { "--rerun-failed", "Run only the tests that failed previously" },
110 { "--tests-from-file <file>", "Run the tests listed in the given file" },
111 { "--exclude-from-file <file>",
112 "Run tests except those listed in the given file" },
113 { "--repeat until-fail:<n>, --repeat-until-fail <n>",
114 "Require each test to run <n> times without failing in order to pass" },
115 { "--repeat until-pass:<n>",
116 "Allow each test to run up to <n> times in order to pass" },
117 { "--repeat after-timeout:<n>",
118 "Allow each test to run up to <n> times if it times out" },
119 { "--max-width <width>", "Set the max width for a test name to output" },
120 { "--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1." },
121 { "--resource-spec-file <file>", "Set the resource spec file to use." },
122 { "--no-label-summary", "Disable timing summary information for labels." },
123 { "--no-subproject-summary",
124 "Disable timing summary information for "
125 "subprojects." },
126 { "--test-dir <dir>", "Specify the directory in which to look for tests." },
127 { "--build-and-test", "Configure, build and run a test." },
128 { "--build-target", "Specify a specific target to build." },
129 { "--build-nocmake", "Run the build without running cmake first." },
130 { "--build-run-dir", "Specify directory to run programs from." },
131 { "--build-two-config", "Run CMake twice" },
132 { "--build-exe-dir", "Specify the directory for the executable." },
133 { "--build-generator", "Specify the generator to use." },
134 { "--build-generator-platform", "Specify the generator-specific platform." },
135 { "--build-generator-toolset", "Specify the generator-specific toolset." },
136 { "--build-project", "Specify the name of the project to build." },
137 { "--build-makeprogram", "Specify the make program to use." },
138 { "--build-noclean", "Skip the make clean step." },
139 { "--build-config-sample",
140 "A sample executable to use to determine the configuration" },
141 { "--build-options", "Add extra options to the build step." },
143 { "--test-command", "The test to run with the --build-and-test option." },
144 { "--test-timeout", "The time limit in seconds, internal use only." },
145 { "--test-load", "CPU load threshold for starting new parallel tests." },
146 { "--tomorrow-tag", "Nightly or experimental starts with next day tag." },
147 { "--overwrite", "Overwrite CTest configuration option." },
148 { "--extra-submit <file>[;<file>]", "Submit extra files to the dashboard." },
149 { "--http-header <header>", "Append HTTP header when submitting" },
150 { "--force-new-ctest-process",
151 "Run child CTest instances as new processes" },
152 { "--schedule-random", "Use a random order for scheduling tests" },
153 { "--submit-index",
154 "Submit individual dashboard tests with specific index" },
155 { "--timeout <seconds>", "Set the default test timeout." },
156 { "--stop-time <time>",
157 "Set a time at which all tests should stop running." },
158 { "--http1.0", "Submit using HTTP 1.0." },
159 { "--no-compress-output", "Do not compress test output when submitting." },
160 { "--print-labels", "Print all available test labels." },
161 { "--no-tests=<[error|ignore]>",
162 "Regard no tests found either as 'error' or 'ignore' it." }
164 } // anonymous namespace
166 // this is a test driver program for cmCTest.
167 int main(int argc, char const* const* argv)
169 cmSystemTools::EnsureStdPipes();
171 // Replace streambuf so we can output Unicode to console
172 cmConsoleBuf consoleBuf;
173 consoleBuf.SetUTF8Pipes();
175 cmsys::Encoding::CommandLineArguments encoding_args =
176 cmsys::Encoding::CommandLineArguments::Main(argc, argv);
177 argc = encoding_args.argc();
178 argv = encoding_args.argv();
180 cmSystemTools::DoNotInheritStdPipes();
181 cmSystemTools::InitializeLibUV();
182 cmSystemTools::FindCMakeResources(argv[0]);
184 // Dispatch 'ctest --launch' mode directly.
185 if (argc >= 2 && strcmp(argv[1], "--launch") == 0) {
186 return cmCTestLaunch::Main(argc, argv);
189 cmCTest inst;
191 if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
192 cmCTestLog(&inst, ERROR_MESSAGE,
193 "Current working directory cannot be established.\n");
194 return 1;
197 // If there is a testing input file, check for documentation options
198 // only if there are actually arguments. We want running without
199 // arguments to run tests.
200 if (argc > 1 ||
201 !(cmSystemTools::FileExists("CTestTestfile.cmake") ||
202 cmSystemTools::FileExists("DartTestfile.txt"))) {
203 if (argc == 1) {
204 cmCTestLog(&inst, ERROR_MESSAGE,
205 "*********************************\n"
206 "No test configuration file found!\n"
207 "*********************************\n");
209 cmDocumentation doc;
210 doc.addCTestStandardDocSections();
211 if (doc.CheckOptions(argc, argv)) {
212 // Construct and print requested documentation.
213 cmCTestScriptHandler* ch = inst.GetScriptHandler();
214 ch->CreateCMake();
216 doc.SetShowGenerators(false);
217 doc.SetName("ctest");
218 doc.SetSection("Name", cmDocumentationName);
219 doc.SetSection("Usage", cmDocumentationUsage);
220 doc.PrependSection("Options", cmDocumentationOptions);
221 return !doc.PrintRequestedDocumentation(std::cout);
225 // copy the args to a vector
226 std::vector<std::string> args;
227 args.reserve(argc);
228 for (int i = 0; i < argc; ++i) {
229 args.emplace_back(argv[i]);
231 // run ctest
232 std::string output;
233 int res = inst.Run(args, &output);
234 cmCTestLog(&inst, OUTPUT, output);
236 return res;