Merge topic 'ctest-repeat-until-fail'
6bce0276
Help: Add notes for topic 'ctest-repeat-until-fail'fde70a1b
ctest: Add a new --repeat-until-fail option
This commit is contained in:
commit
cc8b8cdc75
|
@ -194,6 +194,11 @@ Options
|
||||||
subsequent calls to ctest with the --rerun-failed option will run
|
subsequent calls to ctest with the --rerun-failed option will run
|
||||||
the set of tests that most recently failed (if any).
|
the set of tests that most recently failed (if any).
|
||||||
|
|
||||||
|
``--repeat-until-fail <n>``
|
||||||
|
Require each test to run ``<n>`` times without failing in order to pass.
|
||||||
|
|
||||||
|
This is useful in finding sporadic failures in test cases.
|
||||||
|
|
||||||
``--max-width <width>``
|
``--max-width <width>``
|
||||||
Set the max width for a test name to output
|
Set the max width for a test name to output
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
ctest-repeat-until-fail
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
* The :manual:`ctest(1)` tool learned a new ``--repeat-until-fail <n>``
|
||||||
|
option to help find sporadic test failures.
|
|
@ -121,6 +121,11 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test)
|
||||||
this->RunningCount += GetProcessorsUsed(test);
|
this->RunningCount += GetProcessorsUsed(test);
|
||||||
|
|
||||||
cmCTestRunTest* testRun = new cmCTestRunTest(this->TestHandler);
|
cmCTestRunTest* testRun = new cmCTestRunTest(this->TestHandler);
|
||||||
|
if(this->CTest->GetRepeatUntilFail())
|
||||||
|
{
|
||||||
|
testRun->SetRunUntilFailOn();
|
||||||
|
testRun->SetNumberOfRuns(this->CTest->GetTestRepeat());
|
||||||
|
}
|
||||||
testRun->SetIndex(test);
|
testRun->SetIndex(test);
|
||||||
testRun->SetTestProperties(this->Properties[test]);
|
testRun->SetTestProperties(this->Properties[test]);
|
||||||
|
|
||||||
|
@ -289,7 +294,13 @@ bool cmCTestMultiProcessHandler::CheckOutput()
|
||||||
cmCTestRunTest* p = *i;
|
cmCTestRunTest* p = *i;
|
||||||
int test = p->GetIndex();
|
int test = p->GetIndex();
|
||||||
|
|
||||||
if(p->EndTest(this->Completed, this->Total, true))
|
bool testResult = p->EndTest(this->Completed, this->Total, true);
|
||||||
|
if(p->StartAgain())
|
||||||
|
{
|
||||||
|
this->Completed--; // remove the completed test because run again
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(testResult)
|
||||||
{
|
{
|
||||||
this->Passed->push_back(p->GetTestProperties()->Name);
|
this->Passed->push_back(p->GetTestProperties()->Name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,9 @@ cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler)
|
||||||
this->CompressedOutput = "";
|
this->CompressedOutput = "";
|
||||||
this->CompressionRatio = 2;
|
this->CompressionRatio = 2;
|
||||||
this->StopTimePassed = false;
|
this->StopTimePassed = false;
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
cmCTestRunTest::~cmCTestRunTest()
|
cmCTestRunTest::~cmCTestRunTest()
|
||||||
|
@ -357,13 +360,50 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
|
||||||
this->MemCheckPostProcess();
|
this->MemCheckPostProcess();
|
||||||
this->ComputeWeightedCost();
|
this->ComputeWeightedCost();
|
||||||
}
|
}
|
||||||
// Always push the current TestResult onto the
|
// If the test does not need to rerun push the current TestResult onto the
|
||||||
// TestHandler vector
|
// TestHandler vector
|
||||||
this->TestHandler->TestResults.push_back(this->TestResult);
|
if(!this->NeedsToRerun())
|
||||||
|
{
|
||||||
|
this->TestHandler->TestResults.push_back(this->TestResult);
|
||||||
|
}
|
||||||
delete this->TestProcess;
|
delete this->TestProcess;
|
||||||
return passed;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cmCTestRunTest::StartAgain()
|
||||||
|
{
|
||||||
|
if(!this->RunAgain)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->RunAgain = false; // reset
|
||||||
|
// change to tests directory
|
||||||
|
std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
|
||||||
|
cmSystemTools::ChangeDirectory(this->TestProperties->Directory);
|
||||||
|
this->StartTest(this->TotalNumberOfTests);
|
||||||
|
// change back
|
||||||
|
cmSystemTools::ChangeDirectory(current_dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cmCTestRunTest::NeedsToRerun()
|
||||||
|
{
|
||||||
|
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
|
||||||
|
// restarted
|
||||||
|
if(this->RunUntilFail
|
||||||
|
&& this->TestResult.Status == cmCTestTestHandler::COMPLETED)
|
||||||
|
{
|
||||||
|
this->RunAgain = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void cmCTestRunTest::ComputeWeightedCost()
|
void cmCTestRunTest::ComputeWeightedCost()
|
||||||
{
|
{
|
||||||
|
@ -400,6 +440,7 @@ void cmCTestRunTest::MemCheckPostProcess()
|
||||||
// Starts the execution of a test. Returns once it has started
|
// Starts the execution of a test. Returns once it has started
|
||||||
bool cmCTestRunTest::StartTest(size_t total)
|
bool cmCTestRunTest::StartTest(size_t total)
|
||||||
{
|
{
|
||||||
|
this->TotalNumberOfTests = total; // save for rerun case
|
||||||
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(2*getNumWidth(total) + 8)
|
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(2*getNumWidth(total) + 8)
|
||||||
<< "Start "
|
<< "Start "
|
||||||
<< std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
|
<< std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
|
||||||
|
@ -494,10 +535,10 @@ bool cmCTestRunTest::StartTest(size_t total)
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void cmCTestRunTest::ComputeArguments()
|
void cmCTestRunTest::ComputeArguments()
|
||||||
{
|
{
|
||||||
|
this->Arguments.clear(); // reset becaue this might be a rerun
|
||||||
std::vector<std::string>::const_iterator j =
|
std::vector<std::string>::const_iterator j =
|
||||||
this->TestProperties->Args.begin();
|
this->TestProperties->Args.begin();
|
||||||
++j; // skip test name
|
++j; // skip test name
|
||||||
|
|
||||||
// find the test executable
|
// find the test executable
|
||||||
if(this->TestHandler->MemCheck)
|
if(this->TestHandler->MemCheck)
|
||||||
{
|
{
|
||||||
|
@ -697,10 +738,28 @@ bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
|
||||||
|
|
||||||
void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
|
void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
|
||||||
{
|
{
|
||||||
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
|
// if this is the last or only run of this test
|
||||||
<< completed << "/");
|
// then print out completed / total
|
||||||
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
|
// Only issue is if a test fails and we are running until fail
|
||||||
<< 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)
|
||||||
|
{
|
||||||
|
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
|
||||||
|
<< completed << "/");
|
||||||
|
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
|
||||||
|
<< total << " ");
|
||||||
|
}
|
||||||
|
// if this is one of several runs of a test just print blank space
|
||||||
|
// to keep things neat
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
|
||||||
|
<< " " << " ");
|
||||||
|
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
|
||||||
|
<< " " << " ");
|
||||||
|
}
|
||||||
|
|
||||||
if ( this->TestHandler->MemCheck )
|
if ( this->TestHandler->MemCheck )
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,8 @@ public:
|
||||||
cmCTestRunTest(cmCTestTestHandler* handler);
|
cmCTestRunTest(cmCTestTestHandler* handler);
|
||||||
~cmCTestRunTest();
|
~cmCTestRunTest();
|
||||||
|
|
||||||
|
void SetNumberOfRuns(int n) {this->NumberOfRunsLeft = n;}
|
||||||
|
void SetRunUntilFailOn() { this->RunUntilFail = true;}
|
||||||
void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties * prop)
|
void SetTestProperties(cmCTestTestHandler::cmCTestTestProperties * prop)
|
||||||
{ this->TestProperties = prop; }
|
{ this->TestProperties = prop; }
|
||||||
|
|
||||||
|
@ -58,7 +60,10 @@ public:
|
||||||
void ComputeArguments();
|
void ComputeArguments();
|
||||||
|
|
||||||
void ComputeWeightedCost();
|
void ComputeWeightedCost();
|
||||||
|
|
||||||
|
bool StartAgain();
|
||||||
private:
|
private:
|
||||||
|
bool NeedsToRerun();
|
||||||
void DartProcessing();
|
void DartProcessing();
|
||||||
void ExeNotFound(std::string exe);
|
void ExeNotFound(std::string exe);
|
||||||
// Figures out a final timeout which is min(STOP_TIME, NOW+TIMEOUT)
|
// Figures out a final timeout which is min(STOP_TIME, NOW+TIMEOUT)
|
||||||
|
@ -92,6 +97,10 @@ private:
|
||||||
std::string ActualCommand;
|
std::string ActualCommand;
|
||||||
std::vector<std::string> Arguments;
|
std::vector<std::string> Arguments;
|
||||||
bool StopTimePassed;
|
bool StopTimePassed;
|
||||||
|
bool RunUntilFail;
|
||||||
|
int NumberOfRunsLeft;
|
||||||
|
bool RunAgain;
|
||||||
|
size_t TotalNumberOfTests;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int getNumWidth(size_t n)
|
inline int getNumWidth(size_t n)
|
||||||
|
|
|
@ -329,6 +329,8 @@ cmCTest::cmCTest()
|
||||||
this->OutputTestOutputOnTestFailure = false;
|
this->OutputTestOutputOnTestFailure = false;
|
||||||
this->ComputedCompressTestOutput = false;
|
this->ComputedCompressTestOutput = false;
|
||||||
this->ComputedCompressMemCheckOutput = false;
|
this->ComputedCompressMemCheckOutput = false;
|
||||||
|
this->RepeatTests = 1; // default to run each test once
|
||||||
|
this->RepeatUntilFail = false;
|
||||||
if(cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE"))
|
if(cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE"))
|
||||||
{
|
{
|
||||||
this->OutputTestOutputOnTestFailure = true;
|
this->OutputTestOutputOnTestFailure = true;
|
||||||
|
@ -1984,11 +1986,11 @@ bool cmCTest::CheckArgument(const std::string& arg, const char* varg1,
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Processes one command line argument (and its arguments if any)
|
// Processes one command line argument (and its arguments if any)
|
||||||
// for many simple options and then returns
|
// for many simple options and then returns
|
||||||
void cmCTest::HandleCommandLineArguments(size_t &i,
|
bool cmCTest::HandleCommandLineArguments(size_t &i,
|
||||||
std::vector<std::string> &args)
|
std::vector<std::string> &args,
|
||||||
|
std::string& errormsg)
|
||||||
{
|
{
|
||||||
std::string arg = args[i];
|
std::string arg = args[i];
|
||||||
|
|
||||||
if(this->CheckArgument(arg, "-F"))
|
if(this->CheckArgument(arg, "-F"))
|
||||||
{
|
{
|
||||||
this->Failover = true;
|
this->Failover = true;
|
||||||
|
@ -2006,6 +2008,27 @@ void cmCTest::HandleCommandLineArguments(size_t &i,
|
||||||
this->SetParallelLevel(plevel);
|
this->SetParallelLevel(plevel);
|
||||||
this->ParallelLevelSetInCli = true;
|
this->ParallelLevelSetInCli = true;
|
||||||
}
|
}
|
||||||
|
if(this->CheckArgument(arg, "--repeat-until-fail"))
|
||||||
|
{
|
||||||
|
if( i >= args.size() - 1)
|
||||||
|
{
|
||||||
|
errormsg = "'--repeat-until-fail' requires an argument";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
long repeat = 1;
|
||||||
|
if(!cmSystemTools::StringToLong(args[i].c_str(), &repeat))
|
||||||
|
{
|
||||||
|
errormsg = "'--repeat-until-fail' given non-integer value '"
|
||||||
|
+ args[i] + "'";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->RepeatTests = static_cast<int>(repeat);
|
||||||
|
if(repeat > 1)
|
||||||
|
{
|
||||||
|
this->RepeatUntilFail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(this->CheckArgument(arg, "--no-compress-output"))
|
if(this->CheckArgument(arg, "--no-compress-output"))
|
||||||
{
|
{
|
||||||
|
@ -2191,6 +2214,7 @@ void cmCTest::HandleCommandLineArguments(size_t &i,
|
||||||
this->GetHandler("test")->SetPersistentOption("RerunFailed", "true");
|
this->GetHandler("test")->SetPersistentOption("RerunFailed", "true");
|
||||||
this->GetHandler("memcheck")->SetPersistentOption("RerunFailed", "true");
|
this->GetHandler("memcheck")->SetPersistentOption("RerunFailed", "true");
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
@ -2273,7 +2297,12 @@ int cmCTest::Run(std::vector<std::string> &args, std::string* output)
|
||||||
for(size_t i=1; i < args.size(); ++i)
|
for(size_t i=1; i < args.size(); ++i)
|
||||||
{
|
{
|
||||||
// handle the simple commandline arguments
|
// handle the simple commandline arguments
|
||||||
this->HandleCommandLineArguments(i,args);
|
std::string errormsg;
|
||||||
|
if(!this->HandleCommandLineArguments(i,args, errormsg))
|
||||||
|
{
|
||||||
|
cmSystemTools::Error(errormsg.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// handle the script arguments -S -SR -SP
|
// handle the script arguments -S -SR -SP
|
||||||
this->HandleScriptArguments(i,args,SRArgumentSpecified);
|
this->HandleScriptArguments(i,args,SRArgumentSpecified);
|
||||||
|
|
|
@ -429,8 +429,13 @@ public:
|
||||||
{
|
{
|
||||||
return this->Definitions;
|
return this->Definitions;
|
||||||
}
|
}
|
||||||
|
// return the number of times a test should be run
|
||||||
|
int GetTestRepeat() { return this->RepeatTests;}
|
||||||
|
// return true if test should run until fail
|
||||||
|
bool GetRepeatUntilFail() { return this->RepeatUntilFail;}
|
||||||
private:
|
private:
|
||||||
|
int RepeatTests;
|
||||||
|
bool RepeatUntilFail;
|
||||||
std::string ConfigType;
|
std::string ConfigType;
|
||||||
std::string ScheduleType;
|
std::string ScheduleType;
|
||||||
std::string StopTime;
|
std::string StopTime;
|
||||||
|
@ -535,8 +540,9 @@ private:
|
||||||
bool AddVariableDefinition(const std::string &arg);
|
bool AddVariableDefinition(const std::string &arg);
|
||||||
|
|
||||||
//! parse and process most common command line arguments
|
//! parse and process most common command line arguments
|
||||||
void HandleCommandLineArguments(size_t &i,
|
bool HandleCommandLineArguments(size_t &i,
|
||||||
std::vector<std::string> &args);
|
std::vector<std::string> &args,
|
||||||
|
std::string& errormsg);
|
||||||
|
|
||||||
//! hande the -S -SP and -SR arguments
|
//! hande the -S -SP and -SR arguments
|
||||||
void HandleScriptArguments(size_t &i,
|
void HandleScriptArguments(size_t &i,
|
||||||
|
|
|
@ -75,6 +75,8 @@ static const char * cmDocumentationOptions[][2] =
|
||||||
"Run a specific number of tests by number."},
|
"Run a specific number of tests by number."},
|
||||||
{"-U, --union", "Take the Union of -I and -R"},
|
{"-U, --union", "Take the Union of -I and -R"},
|
||||||
{"--rerun-failed", "Run only the tests that failed previously"},
|
{"--rerun-failed", "Run only the tests that failed previously"},
|
||||||
|
{"--repeat-until-fail <n>", "Require each test to run <n> "
|
||||||
|
"times without failing in order to pass"},
|
||||||
{"--max-width <width>", "Set the max width for a test name to output"},
|
{"--max-width <width>", "Set the max width for a test name to output"},
|
||||||
{"--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1."},
|
{"--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1."},
|
||||||
{"--no-label-summary", "Disable timing summary information for labels."},
|
{"--no-label-summary", "Disable timing summary information for labels."},
|
||||||
|
|
|
@ -199,6 +199,7 @@ add_RunCMake_test(CommandLine)
|
||||||
add_RunCMake_test(install)
|
add_RunCMake_test(install)
|
||||||
add_RunCMake_test(CPackInstallProperties)
|
add_RunCMake_test(CPackInstallProperties)
|
||||||
add_RunCMake_test(ExternalProject)
|
add_RunCMake_test(ExternalProject)
|
||||||
|
add_RunCMake_test(CTestCommandLine)
|
||||||
|
|
||||||
set(IfacePaths_INCLUDE_DIRECTORIES_ARGS -DTEST_PROP=INCLUDE_DIRECTORIES)
|
set(IfacePaths_INCLUDE_DIRECTORIES_ARGS -DTEST_PROP=INCLUDE_DIRECTORIES)
|
||||||
add_RunCMake_test(IfacePaths_INCLUDE_DIRECTORIES TEST_DIR IfacePaths)
|
add_RunCMake_test(IfacePaths_INCLUDE_DIRECTORIES TEST_DIR IfacePaths)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(${RunCMake_TEST} NONE)
|
||||||
|
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1,25 @@
|
||||||
|
include(RunCMake)
|
||||||
|
|
||||||
|
run_cmake_command(repeat-until-fail-bad1
|
||||||
|
${CMAKE_CTEST_COMMAND} --repeat-until-fail
|
||||||
|
)
|
||||||
|
run_cmake_command(repeat-until-fail-bad2
|
||||||
|
${CMAKE_CTEST_COMMAND} --repeat-until-fail foo
|
||||||
|
)
|
||||||
|
run_cmake_command(repeat-until-fail-good
|
||||||
|
${CMAKE_CTEST_COMMAND} --repeat-until-fail 2
|
||||||
|
)
|
||||||
|
|
||||||
|
function(run_repeat_until_fail_tests)
|
||||||
|
# Use a single build tree for a few tests without cleaning.
|
||||||
|
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/repeat-until-fail-build)
|
||||||
|
set(RunCMake_TEST_NO_CLEAN 1)
|
||||||
|
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||||
|
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||||
|
|
||||||
|
run_cmake(repeat-until-fail-cmake)
|
||||||
|
run_cmake_command(repeat-until-fail-ctest
|
||||||
|
${CMAKE_CTEST_COMMAND} -C Debug --repeat-until-fail 3
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
run_repeat_until_fail_tests()
|
|
@ -0,0 +1,3 @@
|
||||||
|
# This is run by test initialization in repeat-until-fail-cmake.cmake
|
||||||
|
# with cmake -P. It creates TEST_OUTPUT_FILE with a 0 in it.
|
||||||
|
file(WRITE "${TEST_OUTPUT_FILE}" "0")
|
|
@ -0,0 +1 @@
|
||||||
|
1
|
|
@ -0,0 +1 @@
|
||||||
|
^CMake Error: '--repeat-until-fail' requires an argument$
|
|
@ -0,0 +1 @@
|
||||||
|
1
|
|
@ -0,0 +1 @@
|
||||||
|
^CMake Error: '--repeat-until-fail' given non-integer value 'foo'$
|
|
@ -0,0 +1,15 @@
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
set(TEST_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/test_output.txt")
|
||||||
|
add_test(NAME initialization
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
"-DTEST_OUTPUT_FILE=${TEST_OUTPUT_FILE}"
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/init.cmake")
|
||||||
|
add_test(NAME test1
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
"-DTEST_OUTPUT_FILE=${TEST_OUTPUT_FILE}"
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/test1.cmake")
|
||||||
|
set_tests_properties(test1 PROPERTIES DEPENDS "initialization")
|
||||||
|
|
||||||
|
add_test(hello ${CMAKE_COMMAND} -E echo hello)
|
||||||
|
add_test(goodbye ${CMAKE_COMMAND} -E echo goodbye)
|
|
@ -0,0 +1 @@
|
||||||
|
8
|
|
@ -0,0 +1 @@
|
||||||
|
^Errors while running CTest$
|
|
@ -0,0 +1,30 @@
|
||||||
|
^Test project .*/Tests/RunCMake/CTestCommandLine/repeat-until-fail-build
|
||||||
|
Start 1: initialization
|
||||||
|
Test #1: initialization ................... Passed [0-9.]+ sec
|
||||||
|
Start 1: initialization
|
||||||
|
Test #1: initialization ................... Passed [0-9.]+ sec
|
||||||
|
Start 1: initialization
|
||||||
|
1/4 Test #1: initialization ................... Passed [0-9.]+ sec
|
||||||
|
Start 2: test1
|
||||||
|
Test #2: test1 ............................ Passed [0-9.]+ sec
|
||||||
|
Start 2: test1
|
||||||
|
Test #2: test1 ............................\*\*\*Failed [0-9.]+ sec
|
||||||
|
Start 3: hello
|
||||||
|
Test #3: hello ............................ Passed [0-9.]+ sec
|
||||||
|
Start 3: hello
|
||||||
|
Test #3: hello ............................ Passed [0-9.]+ sec
|
||||||
|
Start 3: hello
|
||||||
|
3/4 Test #3: hello ............................ Passed [0-9.]+ sec
|
||||||
|
Start 4: goodbye
|
||||||
|
Test #4: goodbye .......................... Passed [0-9.]+ sec
|
||||||
|
Start 4: goodbye
|
||||||
|
Test #4: goodbye .......................... Passed [0-9.]+ sec
|
||||||
|
Start 4: goodbye
|
||||||
|
4/4 Test #4: goodbye .......................... Passed [0-9.]+ sec
|
||||||
|
+
|
||||||
|
75% tests passed, 1 tests failed out of 4
|
||||||
|
+
|
||||||
|
Total Test time \(real\) = +[0-9.]+ sec
|
||||||
|
+
|
||||||
|
The following tests FAILED:
|
||||||
|
[ ]+2 - test1 \(Failed\)$
|
|
@ -0,0 +1 @@
|
||||||
|
^No tests were found!!!$
|
|
@ -0,0 +1,13 @@
|
||||||
|
# This is run by test test1 in repeat-until-fail-cmake.cmake with cmake -P.
|
||||||
|
# It reads the file TEST_OUTPUT_FILE and increments the number
|
||||||
|
# found in the file by 1. When the number is 2, then the
|
||||||
|
# code sends out a cmake error causing the test to fail
|
||||||
|
# the second time it is run.
|
||||||
|
message("TEST_OUTPUT_FILE = ${TEST_OUTPUT_FILE}")
|
||||||
|
file(READ "${TEST_OUTPUT_FILE}" COUNT)
|
||||||
|
message("COUNT= ${COUNT}")
|
||||||
|
math(EXPR COUNT "${COUNT} + 1")
|
||||||
|
file(WRITE "${TEST_OUTPUT_FILE}" "${COUNT}")
|
||||||
|
if(${COUNT} EQUAL 2)
|
||||||
|
message(FATAL_ERROR "this test fails on the 2nd run")
|
||||||
|
endif()
|
Loading…
Reference in New Issue