summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZach Mullen <zach.mullen@kitware.com>2009-10-29 19:30:12 (GMT)
committerZach Mullen <zach.mullen@kitware.com>2009-10-29 19:30:12 (GMT)
commit8612aa10b681fb31bcf3e4959b151fc7f3a5442e (patch)
tree60854e460425b7becc46e2ca93f9626a4262f2f1
parente183581b1459aba72758f395d7e1b74ff8f6aade (diff)
downloadCMake-8612aa10b681fb31bcf3e4959b151fc7f3a5442e.zip
CMake-8612aa10b681fb31bcf3e4959b151fc7f3a5442e.tar.gz
CMake-8612aa10b681fb31bcf3e4959b151fc7f3a5442e.tar.bz2
Hook for scheduling tests in a random order
This may help statistically detect implicit dependencies among unit tests while running in parallel.
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx6
-rw-r--r--Source/CTest/cmCTestTestCommand.h8
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx18
-rw-r--r--Source/cmCTest.cxx6
-rw-r--r--Source/cmCTest.h4
-rw-r--r--Source/ctest.cxx3
-rw-r--r--Tests/CTestTest3/test.cmake.in4
7 files changed, 44 insertions, 5 deletions
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index a719b09..23cc20e 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -24,6 +24,7 @@ cmCTestTestCommand::cmCTestTestCommand()
this->Arguments[ctt_EXCLUDE_LABEL] = "EXCLUDE_LABEL";
this->Arguments[ctt_INCLUDE_LABEL] = "INCLUDE_LABEL";
this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL";
+ this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM";
this->Arguments[ctt_LAST] = 0;
this->Last = ctt_LAST;
}
@@ -91,6 +92,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
handler->SetOption("ParallelLevel",
this->Values[ctt_PARALLEL_LEVEL]);
}
+ if(this->Values[ctt_SCHEDULE_RANDOM])
+ {
+ handler->SetOption("ScheduleRandom",
+ this->Values[ctt_SCHEDULE_RANDOM]);
+ }
return handler;
}
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index 73ce913..12314df 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -61,7 +61,8 @@ public:
" [INCLUDE include regex] [RETURN_VALUE res] \n"
" [EXCLUDE_LABEL exclude regex] \n"
" [INCLUDE_LABEL label regex] \n"
- " [PARALLEL_LEVEL level]) \n"
+ " [PARALLEL_LEVEL level] \n"
+ " [SCHEDULE_RANDOM on]) \n"
"Tests the given build directory and stores results in Test.xml. The "
"second argument is a variable that will hold value. Optionally, "
"you can specify the starting test number START, the ending test number "
@@ -70,7 +71,9 @@ public:
"to not run EXCLUDE. EXCLUDE_LABEL and INCLUDE_LABEL are regular "
"expression for test to be included or excluded by the test "
"property LABEL. PARALLEL_LEVEL should be set to a positive number "
- "representing the number of tests to be run in parallel."
+ "representing the number of tests to be run in parallel. "
+ "SCHEDULE_RANDOM will launch tests in a random order, and is "
+ "typically used to detect implicit test dependencies."
"\n"
CTEST_COMMAND_APPEND_OPTION_DOCS;
}
@@ -92,6 +95,7 @@ protected:
ctt_EXCLUDE_LABEL,
ctt_INCLUDE_LABEL,
ctt_PARALLEL_LEVEL,
+ ctt_SCHEDULE_RANDOM,
ctt_LAST
};
};
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 3572b11..56ddec7 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -491,11 +491,16 @@ int cmCTestTestHandler::ProcessHandler()
{
// Update internal data structure from generic one
this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation"));
- this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));
+ this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));
+ if(cmSystemTools::IsOn(this->GetOption("ScheduleRandom")))
+ {
+ this->CTest->SetScheduleType("Random");
+ }
if(this->GetOption("ParallelLevel"))
{
this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel")));
}
+
const char* val;
val = this->GetOption("LabelRegularExpression");
if ( val )
@@ -1021,12 +1026,23 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
cmCTestMultiProcessHandler::TestMap tests;
cmCTestMultiProcessHandler::PropertiesMap properties;
+ bool randomSchedule = this->CTest->GetScheduleType() == "Random";
+ if(randomSchedule)
+ {
+ srand((unsigned)time(0));
+ }
+
for (ListOfTests::iterator it = this->TestList.begin();
it != this->TestList.end(); ++it)
{
cmCTestTestProperties& p = *it;
cmCTestMultiProcessHandler::TestSet depends;
+ if(randomSchedule)
+ {
+ p.Cost = rand();
+ }
+
if(p.Depends.size())
{
for(std::vector<std::string>::iterator i = p.Depends.begin();
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 6d21ab5..fee94d1 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -225,6 +225,7 @@ cmCTest::cmCTest()
this->TimeOut = 0;
this->CompressXMLFiles = false;
this->CTestConfigFile = "";
+ this->ScheduleType = "";
this->OutputLogFile = 0;
this->OutputLogFileLastTag = -1;
this->SuppressUpdatingCTestConfiguration = false;
@@ -2027,6 +2028,11 @@ int cmCTest::Run(std::vector<std::string> &args, std::string* output)
cmakeAndTest = true;
}
+ if(this->CheckArgument(arg, "--schedule-random"))
+ {
+ this->ScheduleType = "Random";
+ }
+
// pass the argument to all the handlers as well, but i may no longer be
// set to what it was originally so I'm not sure this is working as
// intended
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index f401c55..47023f1 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -191,6 +191,9 @@ public:
///! Should we only show what we would do?
bool GetShowOnly();
+ //Used for parallel ctest job scheduling
+ std::string GetScheduleType() { return this->ScheduleType; }
+ void SetScheduleType(std::string type) { this->ScheduleType = type; }
///! The max output width
int GetMaxTestNameWidth() const;
@@ -374,6 +377,7 @@ public:
bool GetLabelSummary() { return this->LabelSummary;}
private:
std::string ConfigType;
+ std::string ScheduleType;
bool Verbose;
bool ExtraVerbose;
bool ProduceXML;
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 2f99410..893e9cb 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -208,6 +208,9 @@ static const char * cmDocumentationOptions[][3] =
"By default CTest will run child CTest instances within the same process. "
"If this behavior is not desired, this argument will enforce new "
"processes for child CTest processes." },
+ {"--schedule-random", "Use a random order for scheduling tests",
+ "This option will run the tests in a random order. It is commonly used to "
+ "detect implicit dependencies in a test suite." },
{"--submit-index", "Submit individual dashboard tests with specific index",
"This option allows performing the same CTest action (such as test) "
"multiple times and submit all stages to the same dashboard (Dart2 "
diff --git a/Tests/CTestTest3/test.cmake.in b/Tests/CTestTest3/test.cmake.in
index 734bdf4..d0a1f88 100644
--- a/Tests/CTestTest3/test.cmake.in
+++ b/Tests/CTestTest3/test.cmake.in
@@ -50,7 +50,7 @@ CTEST_UPDATE(SOURCE "${CTEST_SOURCE_DIRECTORY}" RETURN_VALUE res)
CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
CTEST_READ_CUSTOM_FILES("${CTEST_BINARY_DIRECTORY}")
CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
-CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
+CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res PARALLEL_LEVEL 5 SCHEDULE_RANDOM ON)
CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
CTEST_COVERAGE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
CTEST_SUBMIT(RETURN_VALUE res)
@@ -97,7 +97,7 @@ IF(svncommand)
CTEST_UPDATE(SOURCE "${CTEST_SOURCE_DIRECTORY}" RETURN_VALUE res)
CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
- CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res PARALLEL_LEVEL 5)
+ CTEST_TEST(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res PARALLEL_LEVEL 5 SCHEDULE_RANDOM ON)
CTEST_MEMCHECK(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res PARALLEL_LEVEL 5)
CTEST_COVERAGE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
CTEST_SUBMIT(RETURN_VALUE res)