summaryrefslogtreecommitdiffstats
path: root/Source/CTest
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CTest')
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx6
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h10
-rw-r--r--Source/CTest/cmCTestRunTest.cxx24
-rw-r--r--Source/CTest/cmCTestRunTest.h21
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx4
-rw-r--r--Source/CTest/cmCTestTestCommand.h1
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx30
-rw-r--r--Source/CTest/cmCTestTestHandler.h4
8 files changed, 78 insertions, 22 deletions
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 02d396e..04abf98 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -171,9 +171,9 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
this->RunningCount += GetProcessorsUsed(test);
cmCTestRunTest* testRun = new cmCTestRunTest(*this);
- if (this->CTest->GetRepeatUntilFail()) {
- testRun->SetRunUntilFailOn();
- testRun->SetNumberOfRuns(this->CTest->GetTestRepeat());
+ if (this->RepeatMode != cmCTest::Repeat::Never) {
+ testRun->SetRepeatMode(this->RepeatMode);
+ testRun->SetNumberOfRuns(this->RepeatCount);
}
testRun->SetIndex(test);
testRun->SetTestProperties(this->Properties[test]);
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index 1db4bfd..4837401 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -14,11 +14,11 @@
#include "cm_uv.h"
+#include "cmCTest.h"
#include "cmCTestResourceAllocator.h"
#include "cmCTestTestHandler.h"
#include "cmUVHandlePtr.h"
-class cmCTest;
struct cmCTestBinPackerAllocation;
class cmCTestResourceSpec;
class cmCTestRunTest;
@@ -85,6 +85,12 @@ public:
cmCTestTestHandler* GetTestHandler() { return this->TestHandler; }
+ void SetRepeatMode(cmCTest::Repeat mode, int count)
+ {
+ this->RepeatMode = mode;
+ this->RepeatCount = count;
+ }
+
void SetQuiet(bool b) { this->Quiet = b; }
void InitResourceAllocator(const cmCTestResourceSpec& spec)
@@ -179,6 +185,8 @@ protected:
cmCTestTestHandler* TestHandler;
cmCTest* CTest;
bool HasCycles;
+ cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never;
+ int RepeatCount = 1;
bool Quiet;
bool SerialTestRunning;
};
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 3091050..cc5de43 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -34,9 +34,6 @@ cmCTestRunTest::cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler)
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
this->TestResult.TestCount = 0;
this->TestResult.Properties = nullptr;
- this->NumberOfRunsLeft = 1; // default to 1 run of the test
- this->RunUntilFail = false; // default to run the test once
- this->RunAgain = false; // default to not having to run again
}
void cmCTestRunTest::CheckOutput(std::string const& line)
@@ -310,7 +307,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
}
// If the test does not need to rerun push the current TestResult onto the
// TestHandler vector
- if (!this->NeedsToRerun()) {
+ if (!this->NeedsToRepeat()) {
this->TestHandler->TestResults.push_back(this->TestResult);
}
this->TestProcess.reset();
@@ -336,17 +333,21 @@ bool cmCTestRunTest::StartAgain(size_t completed)
return true;
}
-bool cmCTestRunTest::NeedsToRerun()
+bool cmCTestRunTest::NeedsToRepeat()
{
this->NumberOfRunsLeft--;
if (this->NumberOfRunsLeft == 0) {
return false;
}
// if number of runs left is not 0, and we are running until
- // we find a failed test, then return true so the test can be
+ // we find a failed (or passed) test, then return true so the test can be
// restarted
- if (this->RunUntilFail &&
- this->TestResult.Status == cmCTestTestHandler::COMPLETED) {
+ if ((this->RepeatMode == cmCTest::Repeat::UntilFail &&
+ this->TestResult.Status == cmCTestTestHandler::COMPLETED) ||
+ (this->RepeatMode == cmCTest::Repeat::UntilPass &&
+ this->TestResult.Status != cmCTestTestHandler::COMPLETED) ||
+ (this->RepeatMode == cmCTest::Repeat::AfterTimeout &&
+ this->TestResult.Status == cmCTestTestHandler::TIMEOUT)) {
this->RunAgain = true;
return true;
}
@@ -746,7 +747,12 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
// then it will never print out the completed / total, same would
// got for run until pass. Trick is when this is called we don't
// yet know if we are passing or failing.
- if (this->NumberOfRunsLeft == 1 || this->CTest->GetTestProgressOutput()) {
+ bool const progressOnLast =
+ (this->RepeatMode != cmCTest::Repeat::UntilPass &&
+ this->RepeatMode != cmCTest::Repeat::AfterTimeout);
+ if ((progressOnLast && this->NumberOfRunsLeft == 1) ||
+ (!progressOnLast && this->NumberOfRunsLeft == this->NumberOfRunsTotal) ||
+ this->CTest->GetTestProgressOutput()) {
outputStream << std::setw(getNumWidth(total)) << completed << "/";
outputStream << std::setw(getNumWidth(total)) << total << " ";
}
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index f781c7a..7eeaebd 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -13,13 +13,12 @@
#include <stddef.h>
+#include "cmCTest.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmCTestTestHandler.h"
#include "cmDuration.h"
#include "cmProcess.h"
-class cmCTest;
-
/** \class cmRunTest
* \brief represents a single test to be run
*
@@ -30,8 +29,13 @@ class cmCTestRunTest
public:
explicit cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler);
- void SetNumberOfRuns(int n) { this->NumberOfRunsLeft = n; }
- void SetRunUntilFailOn() { this->RunUntilFail = true; }
+ void SetNumberOfRuns(int n)
+ {
+ this->NumberOfRunsLeft = n;
+ this->NumberOfRunsTotal = n;
+ }
+
+ void SetRepeatMode(cmCTest::Repeat r) { this->RepeatMode = r; }
void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties* prop)
{
this->TestProperties = prop;
@@ -98,7 +102,7 @@ public:
}
private:
- bool NeedsToRerun();
+ bool NeedsToRepeat();
void DartProcessing();
void ExeNotFound(std::string exe);
bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
@@ -132,9 +136,10 @@ private:
std::vector<std::map<
std::string, std::vector<cmCTestMultiProcessHandler::ResourceAllocation>>>
AllocatedResources;
- bool RunUntilFail;
- int NumberOfRunsLeft;
- bool RunAgain;
+ cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never;
+ int NumberOfRunsLeft = 1; // default to 1 run of the test
+ int NumberOfRunsTotal = 1; // default to 1 run of the test
+ bool RunAgain = false; // default to not having to run again
size_t TotalNumberOfTests;
};
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 9784214..0f9b695 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -29,6 +29,7 @@ void cmCTestTestCommand::BindArguments()
this->Bind("EXCLUDE_FIXTURE_SETUP"_s, this->ExcludeFixtureSetup);
this->Bind("EXCLUDE_FIXTURE_CLEANUP"_s, this->ExcludeFixtureCleanup);
this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel);
+ this->Bind("REPEAT"_s, this->Repeat);
this->Bind("SCHEDULE_RANDOM"_s, this->ScheduleRandom);
this->Bind("STOP_TIME"_s, this->StopTime);
this->Bind("TEST_LOAD"_s, this->TestLoad);
@@ -85,6 +86,9 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
if (!this->ParallelLevel.empty()) {
handler->SetOption("ParallelLevel", this->ParallelLevel.c_str());
}
+ if (!this->Repeat.empty()) {
+ handler->SetOption("Repeat", this->Repeat.c_str());
+ }
if (!this->ScheduleRandom.empty()) {
handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str());
}
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index 4019694..2345afb 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -55,6 +55,7 @@ protected:
std::string ExcludeFixtureSetup;
std::string ExcludeFixtureCleanup;
std::string ParallelLevel;
+ std::string Repeat;
std::string ScheduleRandom;
std::string StopTime;
std::string TestLoad;
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 8e3ac22..37c7154 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -471,6 +471,30 @@ bool cmCTestTestHandler::ProcessOptions()
if (cmIsOn(this->GetOption("ScheduleRandom"))) {
this->CTest->SetScheduleType("Random");
}
+ if (const char* repeat = this->GetOption("Repeat")) {
+ cmsys::RegularExpression repeatRegex(
+ "^(UNTIL_FAIL|UNTIL_PASS|AFTER_TIMEOUT):([0-9]+)$");
+ if (repeatRegex.find(repeat)) {
+ std::string const& count = repeatRegex.match(2);
+ unsigned long n = 1;
+ cmStrToULong(count, &n); // regex guarantees success
+ this->RepeatCount = static_cast<int>(n);
+ if (this->RepeatCount > 1) {
+ std::string const& mode = repeatRegex.match(1);
+ if (mode == "UNTIL_FAIL") {
+ this->RepeatMode = cmCTest::Repeat::UntilFail;
+ } else if (mode == "UNTIL_PASS") {
+ this->RepeatMode = cmCTest::Repeat::UntilPass;
+ } else if (mode == "AFTER_TIMEOUT") {
+ this->RepeatMode = cmCTest::Repeat::AfterTimeout;
+ }
+ }
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Repeat option invalid value: " << repeat << std::endl);
+ return false;
+ }
+ }
if (this->GetOption("ParallelLevel")) {
this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel")));
}
@@ -1231,6 +1255,12 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
parallel->SetCTest(this->CTest);
parallel->SetParallelLevel(this->CTest->GetParallelLevel());
parallel->SetTestHandler(this);
+ if (this->RepeatMode != cmCTest::Repeat::Never) {
+ parallel->SetRepeatMode(this->RepeatMode, this->RepeatCount);
+ } else {
+ parallel->SetRepeatMode(this->CTest->GetRepeatMode(),
+ this->CTest->GetRepeatCount());
+ }
parallel->SetQuiet(this->Quiet);
if (this->TestLoad > 0) {
parallel->SetTestLoad(this->TestLoad);
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index eab75d0..55237f9 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -18,12 +18,12 @@
#include "cmsys/RegularExpression.hxx"
+#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
#include "cmCTestResourceSpec.h"
#include "cmDuration.h"
#include "cmListFileCache.h"
-class cmCTest;
class cmMakefile;
class cmXMLWriter;
@@ -353,6 +353,8 @@ private:
std::ostream* LogFile;
+ cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never;
+ int RepeatCount = 1;
bool RerunFailed;
};