|
|
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
|
|
#ifndef cmCTestMultiProcessHandler_h
|
|
|
|
#define cmCTestMultiProcessHandler_h
|
|
|
|
|
|
|
|
#include "cmConfigure.h" // IWYU pragma: keep
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <set>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
#include "cm_uv.h"
|
|
|
|
|
|
|
|
#include "cmCTestResourceAllocator.h"
|
|
|
|
#include "cmCTestTestHandler.h"
|
|
|
|
#include "cmUVHandlePtr.h"
|
|
|
|
|
|
|
|
class cmCTest;
|
|
|
|
struct cmCTestBinPackerAllocation;
|
|
|
|
class cmCTestResourceSpec;
|
|
|
|
class cmCTestRunTest;
|
|
|
|
|
|
|
|
/** \class cmCTestMultiProcessHandler
|
|
|
|
* \brief run parallel ctest
|
|
|
|
*
|
|
|
|
* cmCTestMultiProcessHandler
|
|
|
|
*/
|
|
|
|
class cmCTestMultiProcessHandler
|
|
|
|
{
|
|
|
|
friend class TestComparator;
|
|
|
|
friend class cmCTestRunTest;
|
|
|
|
|
|
|
|
public:
|
|
|
|
struct TestSet : public std::set<int>
|
|
|
|
{
|
|
|
|
};
|
|
|
|
struct TestMap : public std::map<int, TestSet>
|
|
|
|
{
|
|
|
|
};
|
|
|
|
struct TestList : public std::vector<int>
|
|
|
|
{
|
|
|
|
};
|
|
|
|
struct PropertiesMap
|
|
|
|
: public std::map<int, cmCTestTestHandler::cmCTestTestProperties*>
|
|
|
|
{
|
|
|
|
};
|
|
|
|
struct ResourceAllocation
|
|
|
|
{
|
|
|
|
std::string Id;
|
|
|
|
unsigned int Slots;
|
|
|
|
};
|
|
|
|
|
|
|
|
cmCTestMultiProcessHandler();
|
|
|
|
virtual ~cmCTestMultiProcessHandler();
|
|
|
|
// Set the tests
|
|
|
|
void SetTests(TestMap& tests, PropertiesMap& properties);
|
|
|
|
// Set the max number of tests that can be run at the same time.
|
|
|
|
void SetParallelLevel(size_t);
|
|
|
|
void SetTestLoad(unsigned long load);
|
|
|
|
virtual void RunTests();
|
|
|
|
void PrintOutputAsJson();
|
|
|
|
void PrintTestList();
|
|
|
|
void PrintLabels();
|
|
|
|
|
|
|
|
void SetPassFailVectors(std::vector<std::string>* passed,
|
|
|
|
std::vector<std::string>* failed)
|
|
|
|
{
|
|
|
|
this->Passed = passed;
|
|
|
|
this->Failed = failed;
|
|
|
|
}
|
|
|
|
void SetTestResults(std::vector<cmCTestTestHandler::cmCTestTestResult>* r)
|
|
|
|
{
|
|
|
|
this->TestResults = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetCTest(cmCTest* ctest) { this->CTest = ctest; }
|
|
|
|
|
|
|
|
void SetTestHandler(cmCTestTestHandler* handler)
|
|
|
|
{
|
|
|
|
this->TestHandler = handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmCTestTestHandler* GetTestHandler() { return this->TestHandler; }
|
|
|
|
|
|
|
|
void SetQuiet(bool b) { this->Quiet = b; }
|
|
|
|
|
|
|
|
void InitResourceAllocator(const cmCTestResourceSpec& spec)
|
|
|
|
{
|
|
|
|
this->ResourceAllocator.InitializeFromResourceSpec(spec);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CheckResourcesAvailable();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
// Start the next test or tests as many as are allowed by
|
|
|
|
// ParallelLevel
|
|
|
|
void StartNextTests();
|
|
|
|
bool StartTestProcess(int test);
|
|
|
|
bool StartTest(int test);
|
|
|
|
// Mark the checkpoint for the given test
|
|
|
|
void WriteCheckpoint(int index);
|
|
|
|
|
|
|
|
void UpdateCostData();
|
|
|
|
void ReadCostData();
|
|
|
|
// Return index of a test based on its name
|
|
|
|
int SearchByName(std::string const& name);
|
|
|
|
|
|
|
|
void CreateTestCostList();
|
|
|
|
|
|
|
|
void GetAllTestDependencies(int test, TestList& dependencies);
|
|
|
|
void CreateSerialTestCostList();
|
|
|
|
|
|
|
|
void CreateParallelTestCostList();
|
|
|
|
|
|
|
|
// Removes the checkpoint file
|
|
|
|
void MarkFinished();
|
|
|
|
void EraseTest(int index);
|
|
|
|
void FinishTestProcess(cmCTestRunTest* runner, bool started);
|
|
|
|
|
|
|
|
static void OnTestLoadRetryCB(uv_timer_t* timer);
|
|
|
|
|
|
|
|
void RemoveTest(int index);
|
|
|
|
// Check if we need to resume an interrupted test set
|
|
|
|
void CheckResume();
|
|
|
|
// Check if there are any circular dependencies
|
|
|
|
bool CheckCycles();
|
|
|
|
int FindMaxIndex();
|
|
|
|
inline size_t GetProcessorsUsed(int index);
|
|
|
|
std::string GetName(int index);
|
|
|
|
|
|
|
|
bool CheckStopTimePassed();
|
|
|
|
void SetStopTimePassed();
|
|
|
|
|
|
|
|
void LockResources(int index);
|
|
|
|
void UnlockResources(int index);
|
|
|
|
|
|
|
|
bool AllocateResources(int index);
|
|
|
|
bool TryAllocateResources(
|
|
|
|
int index,
|
|
|
|
std::map<std::string, std::vector<cmCTestBinPackerAllocation>>&
|
|
|
|
allocations);
|
|
|
|
void DeallocateResources(int index);
|
|
|
|
bool AllResourcesAvailable();
|
|
|
|
|
|
|
|
// map from test number to set of depend tests
|
|
|
|
TestMap Tests;
|
|
|
|
TestList SortedTests;
|
|
|
|
// Total number of tests we'll be running
|
|
|
|
size_t Total;
|
|
|
|
// Number of tests that are complete
|
|
|
|
size_t Completed;
|
|
|
|
size_t RunningCount;
|
|
|
|
std::set<size_t> ProcessorsAvailable;
|
|
|
|
size_t HaveAffinity;
|
|
|
|
bool StopTimePassed = false;
|
|
|
|
// list of test properties (indices concurrent to the test map)
|
|
|
|
PropertiesMap Properties;
|
|
|
|
std::map<int, bool> TestRunningMap;
|
|
|
|
std::map<int, bool> TestFinishMap;
|
|
|
|
std::map<int, std::string> TestOutput;
|
|
|
|
std::vector<std::string>* Passed;
|
|
|
|
std::vector<std::string>* Failed;
|
|
|
|
std::vector<std::string> LastTestsFailed;
|
|
|
|
std::set<std::string> LockedResources;
|
|
|
|
std::map<int,
|
|
|
|
std::vector<std::map<std::string, std::vector<ResourceAllocation>>>>
|
|
|
|
AllocatedResources;
|
|
|
|
std::map<int, bool> TestsHaveSufficientResources;
|
|
|
|
cmCTestResourceAllocator ResourceAllocator;
|
|
|
|
std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults;
|
|
|
|
size_t ParallelLevel; // max number of process that can be run at once
|
|
|
|
unsigned long TestLoad;
|
|
|
|
unsigned long FakeLoadForTesting;
|
|
|
|
uv_loop_t Loop;
|
|
|
|
cm::uv_timer_ptr TestLoadRetryTimer;
|
|
|
|
cmCTestTestHandler* TestHandler;
|
|
|
|
cmCTest* CTest;
|
|
|
|
bool HasCycles;
|
|
|
|
bool Quiet;
|
|
|
|
bool SerialTestRunning;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|