diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index fbe9a4c71d..731bda394b 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -274,7 +274,7 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test) if (this->RepeatMode != cmCTest::Repeat::Never) { testRun->SetRepeatMode(this->RepeatMode); - testRun->SetNumberOfRuns(this->RepeatCount); + testRun->SetRunNumber(1, this->RepeatCount); } if (this->UseResourceSpec) { testRun->SetUseAllocatedResources(true); diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 43ccbdaa76..c1399fe0d5 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -424,8 +424,7 @@ bool cmCTestRunTest::StartAgain(std::unique_ptr runner, bool cmCTestRunTest::NeedsToRepeat() { - this->NumberOfRunsLeft--; - if (this->NumberOfRunsLeft == 0) { + if (this->RunNumber == this->RunCount) { return false; } // If a test is marked as NOT_RUN it will not be repeated @@ -433,9 +432,8 @@ bool cmCTestRunTest::NeedsToRepeat() if (this->TestResult.Status == cmCTestTestHandler::NOT_RUN) { return false; } - // if number of runs left is not 0, and we are running until - // we find a failed (or passed) test, then return true so the test can be - // restarted + // The test has runs left, so run it again if we are running until we find + // a failed (or passed) test. if ((this->RepeatMode == cmCTest::Repeat::UntilFail && this->TestResult.Status == cmCTestTestHandler::COMPLETED) || (this->RepeatMode == cmCTest::Repeat::UntilPass && @@ -443,6 +441,7 @@ bool cmCTestRunTest::NeedsToRepeat() (this->RepeatMode == cmCTest::Repeat::AfterTimeout && this->TestResult.Status == cmCTestTestHandler::TIMEOUT)) { this->RunAgain = true; + this->RunNumber++; return true; } return false; @@ -559,11 +558,10 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) { this->TotalNumberOfTests = total; // save for rerun case - std::string runIterationSuffix{}; - if (this->NumberOfRunsTotal > 1) { + std::string runIterationSuffix; + if (this->RunCount > 1) { runIterationSuffix = - cmStrCat(" (run ", 1 + this->NumberOfRunsTotal - this->NumberOfRunsLeft, - '/', this->NumberOfRunsTotal, ')'); + cmStrCat(" (run ", this->RunNumber, '/', this->RunCount, ')'); } if (!this->CTest->GetTestProgressOutput()) { cmCTestLog( @@ -999,18 +997,25 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) { std::ostringstream outputStream; - // If this is the last or only run of this test, or progress output is - // requested, then print out completed / total. - // Only issue is if a test fails and we are running until fail - // 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. - 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()) { + // Print "completed/total" on the run whose result is the one recorded for + // the test, and blanks on its other runs. Which run that is has to be + // decided before the run finishes: with until-fail it is the last run, and + // with until-pass and after-timeout the repetitions may end early, so it + // is the first. + bool countThisRun = true; + switch (this->RepeatMode) { + case cmCTest::Repeat::Never: + break; + case cmCTest::Repeat::UntilFail: + countThisRun = this->RunNumber == this->RunCount; + break; + case cmCTest::Repeat::UntilPass: + CM_FALLTHROUGH; + case cmCTest::Repeat::AfterTimeout: + countThisRun = this->RunNumber == 1; + break; + } + if (countThisRun || 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 7ec6bd0879..3d2cd6527a 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -30,10 +30,13 @@ class cmCTestRunTest public: explicit cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler, int index); - void SetNumberOfRuns(int n) + // Report this run as run `number` of `count` in the test's "(run N/M)" + // suffix. A test that repeats on its own starts at run 1 and counts up + // itself. + void SetRunNumber(int number, int count) { - this->NumberOfRunsLeft = n; - this->NumberOfRunsTotal = n; + this->RunNumber = number; + this->RunCount = count; } void SetRepeatMode(cmCTest::Repeat r) { this->RepeatMode = r; } @@ -158,9 +161,9 @@ private: std::string, std::vector>> AllocatedResources; 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 + int RunNumber = 1; // which run of the test this is + int RunCount = 1; // how many runs it may be given + bool RunAgain = false; bool UseLLVMCov = false; size_t TotalNumberOfTests; };