From 32b25b94d661886794fd7e23e55ea413e9c9a67d Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Fri, 4 Sep 2026 13:35:12 +0000 Subject: [PATCH] CTest: Track one run number for a repeating test cmCTestRunTest counted the repetitions of a test with two members whose meaning overlapped: how many runs were left, and how many there were in total. The "(run N/M)" suffix then had to recover N by subtracting one from the other, and the rule deciding which run prints the "completed/total" prefix read as a pair of conditions on the remaining count. Count up instead. Keep the number of the run being made and the number of runs the test may be given, and let the rule say which run the prefix belongs to. --- Source/CTest/cmCTestMultiProcessHandler.cxx | 2 +- Source/CTest/cmCTestRunTest.cxx | 47 ++++++++++++--------- Source/CTest/cmCTestRunTest.h | 15 ++++--- 3 files changed, 36 insertions(+), 28 deletions(-) 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; };