/* 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 #include #include #include #include #include #include "cm_uv.h" #include "cmCTest.h" #include "cmCTestResourceAllocator.h" #include "cmCTestTestHandler.h" #include "cmUVHandlePtr.h" 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 { }; struct TestMap : public std::map { }; struct TestList : public std::vector { }; struct PropertiesMap : public std::map { }; 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* passed, std::vector* failed) { this->Passed = passed; this->Failed = failed; } void SetTestResults(std::vector* r) { this->TestResults = r; } void SetCTest(cmCTest* ctest) { this->CTest = ctest; } void SetTestHandler(cmCTestTestHandler* handler) { this->TestHandler = handler; } cmCTestTestHandler* GetTestHandler() { return this->TestHandler; } void SetRepeatMode(cmCTest::Repeat mode, int count) { this->RepeatMode = mode; this->RepeatCount = count; } 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(std::unique_ptr 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); enum class ResourceAllocationError { NoResourceType, InsufficientResources, }; bool AllocateResources(int index); bool TryAllocateResources( int index, std::map>& allocations, std::map* errors = nullptr); 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 ProcessorsAvailable; size_t HaveAffinity; bool StopTimePassed = false; // list of test properties (indices concurrent to the test map) PropertiesMap Properties; std::map TestRunningMap; std::map TestFinishMap; std::map TestOutput; std::vector* Passed; std::vector* Failed; std::vector LastTestsFailed; std::set LockedResources; std::map>>> AllocatedResources; std::map> ResourceAllocationErrors; cmCTestResourceAllocator ResourceAllocator; std::vector* 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; cmCTest::Repeat RepeatMode = cmCTest::Repeat::Never; int RepeatCount = 1; bool Quiet; bool SerialTestRunning; }; #endif