summaryrefslogtreecommitdiffstats
path: root/Source/cmCTest.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmCTest.cxx')
-rw-r--r--Source/cmCTest.cxx80
1 files changed, 77 insertions, 3 deletions
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 6639787..908eea1 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -24,6 +24,11 @@
#include <time.h>
#include <utility>
#include <vector>
+#if defined(_WIN32)
+# include <windows.h> // IWYU pragma: keep
+#else
+# include <unistd.h> // IWYU pragma: keep
+#endif
#include "cmAlgorithms.h"
#include "cmCTestBuildAndTestHandler.h"
@@ -263,6 +268,8 @@ cmCTest::cmCTest()
this->Failover = false;
this->ForceNewCTestProcess = false;
this->TomorrowTag = false;
+ this->TestProgressOutput = false;
+ this->FlushTestProgressLine = false;
this->Verbose = false;
this->Debug = false;
@@ -290,10 +297,16 @@ cmCTest::cmCTest()
this->OutputTestOutputOnTestFailure = false;
this->RepeatTests = 1; // default to run each test once
this->RepeatUntilFail = false;
- std::string outOnFail;
- if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", outOnFail)) {
- this->OutputTestOutputOnTestFailure = !cmSystemTools::IsOff(outOnFail);
+
+ std::string envValue;
+ if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", envValue)) {
+ this->OutputTestOutputOnTestFailure = !cmSystemTools::IsOff(envValue);
+ }
+ envValue.clear();
+ if (cmSystemTools::GetEnv("CTEST_PROGRESS_OUTPUT", envValue)) {
+ this->TestProgressOutput = !cmSystemTools::IsOff(envValue);
}
+
this->InitStreams();
this->Parts[PartStart].SetName("Start");
@@ -1875,6 +1888,9 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
if (this->CheckArgument(arg, "-Q", "--quiet")) {
this->Quiet = true;
}
+ if (this->CheckArgument(arg, "--progress")) {
+ this->TestProgressOutput = true;
+ }
if (this->CheckArgument(arg, "-V", "--verbose")) {
this->Verbose = true;
}
@@ -2038,6 +2054,23 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
return true;
}
+bool cmCTest::ProgressOutputSupportedByConsole() const
+{
+#if defined(_WIN32)
+ // On Windows we need a console buffer.
+ void* console = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ return GetConsoleScreenBufferInfo(console, &csbi);
+#else
+ // On UNIX we need a non-dumb tty.
+ std::string term_env_variable;
+ if (cmSystemTools::GetEnv("TERM", term_env_variable)) {
+ return isatty(1) && term_env_variable != "dumb";
+ }
+#endif
+ return false;
+}
+
// handle the -S -SR and -SP arguments
void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
bool& SRArgumentSpecified)
@@ -2192,6 +2225,18 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
}
}
+ // TestProgressOutput only supported if console supports it and not logging
+ // to a file
+ this->TestProgressOutput = this->TestProgressOutput &&
+ !this->OutputLogFile && this->ProgressOutputSupportedByConsole();
+#ifdef _WIN32
+ if (this->TestProgressOutput) {
+ // Disable output line buffering so we can print content without
+ // a newline.
+ std::setvbuf(stdout, nullptr, _IONBF, 0);
+ }
+#endif
+
// now what should cmake do? if --build-and-test was specified then
// we run the build and test handler and return
if (cmakeAndTest) {
@@ -2761,6 +2806,7 @@ static const char* cmCTestStringLogType[] = { "DEBUG",
"OUTPUT",
"HANDLER_OUTPUT",
"HANDLER_PROGRESS_OUTPUT",
+ "HANDLER_TEST_PROGRESS_OUTPUT",
"HANDLER_VERBOSE_OUTPUT",
"WARNING",
"ERROR_MESSAGE",
@@ -2821,6 +2867,34 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg,
if (!this->Quiet) {
std::ostream& out = *this->StreamOut;
std::ostream& err = *this->StreamErr;
+
+ if (logType == HANDLER_TEST_PROGRESS_OUTPUT) {
+ if (this->TestProgressOutput) {
+ cmCTestLogOutputFileLine(out);
+ if (this->FlushTestProgressLine) {
+ printf("\r");
+ this->FlushTestProgressLine = false;
+ out.flush();
+ }
+
+ std::string msg_str{ msg };
+ auto const lineBreakIt = msg_str.find('\n');
+ if (lineBreakIt != std::string::npos) {
+ this->FlushTestProgressLine = true;
+ msg_str.erase(std::remove(msg_str.begin(), msg_str.end(), '\n'),
+ msg_str.end());
+ }
+
+ out << msg_str;
+#ifndef _WIN32
+ printf("\x1B[K"); // move caret to end
+#endif
+ out.flush();
+ return;
+ }
+ logType = HANDLER_OUTPUT;
+ }
+
switch (logType) {
case DEBUG:
if (this->Debug) {