diff options
Diffstat (limited to 'Source/CTest/cmCTestMultiProcessHandler.cxx')
-rw-r--r-- | Source/CTest/cmCTestMultiProcessHandler.cxx | 100 |
1 files changed, 91 insertions, 9 deletions
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 7d22a87..ca07a08 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -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,15 +233,15 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) } e << "\n"; } - e << "Resource spec file:\n\n " << this->TestHandler->ResourceSpecFile; - cmCTestRunTest::StartFailure(std::move(testRun), e.str(), + e << "Resource spec file:\n\n " << this->ResourceSpecFile; + cmCTestRunTest::StartFailure(std::move(testRun), this->Total, e.str(), "Insufficient resources"); return false; } cmWorkingDirectory workdir(this->Properties[test]->Directory); if (workdir.Failed()) { - cmCTestRunTest::StartFailure(std::move(testRun), + cmCTestRunTest::StartFailure(std::move(testRun), this->Total, "Failed to change working directory to " + this->Properties[test]->Directory + " : " + std::strerror(workdir.GetLastResult()), @@ -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; +} |