summaryrefslogtreecommitdiffstats
path: root/Source/CTest/cmCTestMultiProcessHandler.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CTest/cmCTestMultiProcessHandler.cxx')
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx80
1 files changed, 63 insertions, 17 deletions
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 37679b9..2192843 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -196,8 +196,40 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
// working directory because FinishTestProcess() will try to unlock them
this->LockResources(test);
- if (!this->TestsHaveSufficientResources[test]) {
- testRun->StartFailure("Insufficient resources");
+ if (!this->ResourceAllocationErrors[test].empty()) {
+ std::ostringstream e;
+ e << "Insufficient resources for test " << this->Properties[test]->Name
+ << ":\n\n";
+ for (auto const& it : this->ResourceAllocationErrors[test]) {
+ switch (it.second) {
+ case ResourceAllocationError::NoResourceType:
+ e << " Test requested resources of type '" << it.first
+ << "' which does not exist\n";
+ break;
+
+ case ResourceAllocationError::InsufficientResources:
+ e << " Test requested resources of type '" << it.first
+ << "' in the following amounts:\n";
+ for (auto const& group : this->Properties[test]->ResourceGroups) {
+ for (auto const& requirement : group) {
+ if (requirement.ResourceType == it.first) {
+ e << " " << requirement.SlotsNeeded
+ << (requirement.SlotsNeeded == 1 ? " slot\n" : " slots\n");
+ }
+ }
+ }
+ e << " but only the following units were available:\n";
+ for (auto const& res :
+ this->ResourceAllocator.GetResources().at(it.first)) {
+ e << " '" << res.first << "': " << res.second.Total
+ << (res.second.Total == 1 ? " slot\n" : " slots\n");
+ }
+ break;
+ }
+ e << "\n";
+ }
+ e << "Resource spec file:\n\n " << this->TestHandler->ResourceSpecFile;
+ testRun->StartFailure(e.str(), "Insufficient resources");
this->FinishTestProcess(testRun, false);
return false;
}
@@ -205,8 +237,9 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
cmWorkingDirectory workdir(this->Properties[test]->Directory);
if (workdir.Failed()) {
testRun->StartFailure("Failed to change working directory to " +
- this->Properties[test]->Directory + " : " +
- std::strerror(workdir.GetLastResult()));
+ this->Properties[test]->Directory + " : " +
+ std::strerror(workdir.GetLastResult()),
+ "Failed to change working directory");
} else {
if (testRun->StartTest(this->Completed, this->Total)) {
// Ownership of 'testRun' has moved to another structure.
@@ -249,7 +282,8 @@ bool cmCTestMultiProcessHandler::AllocateResources(int index)
bool cmCTestMultiProcessHandler::TryAllocateResources(
int index,
- std::map<std::string, std::vector<cmCTestBinPackerAllocation>>& allocations)
+ std::map<std::string, std::vector<cmCTestBinPackerAllocation>>& allocations,
+ std::map<std::string, ResourceAllocationError>* errors)
{
allocations.clear();
@@ -264,18 +298,28 @@ bool cmCTestMultiProcessHandler::TryAllocateResources(
++processIndex;
}
+ bool result = true;
auto const& availableResources = this->ResourceAllocator.GetResources();
for (auto& it : allocations) {
if (!availableResources.count(it.first)) {
- return false;
- }
- if (!cmAllocateCTestResourcesRoundRobin(availableResources.at(it.first),
- it.second)) {
- return false;
+ if (errors) {
+ (*errors)[it.first] = ResourceAllocationError::NoResourceType;
+ result = false;
+ } else {
+ return false;
+ }
+ } else if (!cmAllocateCTestResourcesRoundRobin(
+ availableResources.at(it.first), it.second)) {
+ if (errors) {
+ (*errors)[it.first] = ResourceAllocationError::InsufficientResources;
+ result = false;
+ } else {
+ return false;
+ }
}
}
- return true;
+ return result;
}
void cmCTestMultiProcessHandler::DeallocateResources(int index)
@@ -316,11 +360,13 @@ bool cmCTestMultiProcessHandler::AllResourcesAvailable()
void cmCTestMultiProcessHandler::CheckResourcesAvailable()
{
- for (auto test : this->SortedTests) {
- std::map<std::string, std::vector<cmCTestBinPackerAllocation>> allocations;
- this->TestsHaveSufficientResources[test] =
- !this->TestHandler->UseResourceSpec ||
- this->TryAllocateResources(test, allocations);
+ if (this->TestHandler->UseResourceSpec) {
+ for (auto test : this->SortedTests) {
+ std::map<std::string, std::vector<cmCTestBinPackerAllocation>>
+ allocations;
+ this->TryAllocateResources(test, allocations,
+ &this->ResourceAllocationErrors[test]);
+ }
}
}
@@ -407,7 +453,7 @@ bool cmCTestMultiProcessHandler::StartTest(int test)
}
// Allocate resources
- if (this->TestsHaveSufficientResources[test] &&
+ if (this->ResourceAllocationErrors[test].empty() &&
!this->AllocateResources(test)) {
this->DeallocateResources(test);
return false;