|
@@ -35,6 +35,7 @@
|
|
|
#include "cmCTestRunTest.h"
|
|
|
#include "cmCTestTestHandler.h"
|
|
|
#include "cmDuration.h"
|
|
|
+#include "cmJSONState.h"
|
|
|
#include "cmListFileCache.h"
|
|
|
#include "cmRange.h"
|
|
|
#include "cmStringAlgorithms.h"
|
|
@@ -75,6 +76,7 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
|
|
|
this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable();
|
|
|
this->HaveAffinity = this->ProcessorsAvailable.size();
|
|
|
this->HasCycles = false;
|
|
|
+ this->HasInvalidGeneratedResourceSpec = false;
|
|
|
this->SerialTestRunning = false;
|
|
|
}
|
|
|
|
|
@@ -95,7 +97,9 @@ void cmCTestMultiProcessHandler::SetTests(TestMap& tests,
|
|
|
if (!this->CTest->GetShowOnly()) {
|
|
|
this->ReadCostData();
|
|
|
this->HasCycles = !this->CheckCycles();
|
|
|
- if (this->HasCycles) {
|
|
|
+ this->HasInvalidGeneratedResourceSpec =
|
|
|
+ !this->CheckGeneratedResourceSpec();
|
|
|
+ if (this->HasCycles || this->HasInvalidGeneratedResourceSpec) {
|
|
|
return;
|
|
|
}
|
|
|
this->CreateTestCostList();
|
|
@@ -125,7 +129,7 @@ void cmCTestMultiProcessHandler::SetTestLoad(unsigned long load)
|
|
|
void cmCTestMultiProcessHandler::RunTests()
|
|
|
{
|
|
|
this->CheckResume();
|
|
|
- if (this->HasCycles) {
|
|
|
+ if (this->HasCycles || this->HasInvalidGeneratedResourceSpec) {
|
|
|
return;
|
|
|
}
|
|
|
#ifdef CMAKE_UV_SIGNAL_HACK
|
|
@@ -180,7 +184,7 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
|
|
|
}
|
|
|
testRun->SetIndex(test);
|
|
|
testRun->SetTestProperties(this->Properties[test]);
|
|
|
- if (this->TestHandler->UseResourceSpec) {
|
|
|
+ if (this->UseResourceSpec) {
|
|
|
testRun->SetUseAllocatedResources(true);
|
|
|
testRun->SetAllocatedResources(this->AllocatedResources[test]);
|
|
|
}
|
|
@@ -229,7 +233,7 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
|
|
|
}
|
|
|
e << "\n";
|
|
|
}
|
|
|
- e << "Resource spec file:\n\n " << this->TestHandler->ResourceSpecFile;
|
|
|
+ e << "Resource spec file:\n\n " << this->ResourceSpecFile;
|
|
|
cmCTestRunTest::StartFailure(std::move(testRun), this->Total, e.str(),
|
|
|
"Insufficient resources");
|
|
|
return false;
|
|
@@ -253,7 +257,7 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
|
|
|
|
|
|
bool cmCTestMultiProcessHandler::AllocateResources(int index)
|
|
|
{
|
|
|
- if (!this->TestHandler->UseResourceSpec) {
|
|
|
+ if (!this->UseResourceSpec) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -322,7 +326,7 @@ bool cmCTestMultiProcessHandler::TryAllocateResources(
|
|
|
|
|
|
void cmCTestMultiProcessHandler::DeallocateResources(int index)
|
|
|
{
|
|
|
- if (!this->TestHandler->UseResourceSpec) {
|
|
|
+ if (!this->UseResourceSpec) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -358,7 +362,7 @@ bool cmCTestMultiProcessHandler::AllResourcesAvailable()
|
|
|
|
|
|
void cmCTestMultiProcessHandler::CheckResourcesAvailable()
|
|
|
{
|
|
|
- if (this->TestHandler->UseResourceSpec) {
|
|
|
+ if (this->UseResourceSpec) {
|
|
|
for (auto test : this->SortedTests) {
|
|
|
std::map<std::string, std::vector<cmCTestBinPackerAllocation>>
|
|
|
allocations;
|
|
@@ -1445,3 +1449,81 @@ bool cmCTestMultiProcessHandler::CheckCycles()
|
|
|
this->Quiet);
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
+bool cmCTestMultiProcessHandler::CheckGeneratedResourceSpec()
|
|
|
+{
|
|
|
+ for (auto& test : this->Properties) {
|
|
|
+ if (!test.second->GeneratedResourceSpecFile.empty()) {
|
|
|
+ if (this->ResourceSpecSetupTest) {
|
|
|
+ cmCTestLog(
|
|
|
+ this->CTest, ERROR_MESSAGE,
|
|
|
+ "Only one test may define the GENERATED_RESOURCE_SPEC_FILE property"
|
|
|
+ << std::endl);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (test.second->FixturesSetup.size() != 1) {
|
|
|
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
|
|
|
+ "Test that defines GENERATED_RESOURCE_SPEC_FILE must have "
|
|
|
+ "exactly one FIXTURES_SETUP"
|
|
|
+ << std::endl);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cmSystemTools::FileIsFullPath(
|
|
|
+ test.second->GeneratedResourceSpecFile)) {
|
|
|
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
|
|
|
+ "GENERATED_RESOURCE_SPEC_FILE must be an absolute path"
|
|
|
+ << std::endl);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ this->ResourceSpecSetupTest = test.first;
|
|
|
+ this->ResourceSpecSetupFixture = *test.second->FixturesSetup.begin();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this->ResourceSpecSetupFixture.empty()) {
|
|
|
+ for (auto& test : this->Properties) {
|
|
|
+ if (!test.second->ResourceGroups.empty() &&
|
|
|
+ !test.second->FixturesRequired.count(
|
|
|
+ this->ResourceSpecSetupFixture)) {
|
|
|
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
|
|
|
+ "All tests that have RESOURCE_GROUPS must include the "
|
|
|
+ "resource spec generator fixture in their FIXTURES_REQUIRED"
|
|
|
+ << std::endl);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this->ResourceSpecFile.empty()) {
|
|
|
+ if (this->ResourceSpecSetupTest) {
|
|
|
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
|
|
|
+ "GENERATED_RESOURCE_SPEC_FILE test property cannot be used "
|
|
|
+ "in conjunction with ResourceSpecFile option"
|
|
|
+ << std::endl);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ std::string error;
|
|
|
+ if (!this->InitResourceAllocator(error)) {
|
|
|
+ cmCTestLog(this->CTest, ERROR_MESSAGE, error << std::endl);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+bool cmCTestMultiProcessHandler::InitResourceAllocator(std::string& error)
|
|
|
+{
|
|
|
+ if (!this->ResourceSpec.ReadFromJSONFile(this->ResourceSpecFile)) {
|
|
|
+ error = cmStrCat("Could not read/parse resource spec file ",
|
|
|
+ this->ResourceSpecFile, ": ",
|
|
|
+ this->ResourceSpec.parseState.GetErrorMessage());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ this->UseResourceSpec = true;
|
|
|
+ this->ResourceAllocator.InitializeFromResourceSpec(this->ResourceSpec);
|
|
|
+ return true;
|
|
|
+}
|