From af9ed543b0f9d032158f91cdce7ad6908ff9365b Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 4 Nov 2019 16:11:11 -0500 Subject: CTest: Rename PROCESSES test property to RESOURCE_GROUPS The `PROCESSES` test property name added for CMake 3.16 is too close to the existing `PROCESSORS` test property. Furthermore, the property in principle specifies groups of resources organized in a way that is meaningful to a particular test. The groups may often correspond to processes but they could have other meanings. Since the property name `PROCESSES` has not been in a final 3.16 release yet, simply rename it to `RESOURCE_GROUPS`. Fixes: #19914 --- Help/manual/cmake-properties.7.rst | 2 +- Help/manual/ctest.1.rst | 76 ++++++------ Help/prop_test/PROCESSES.rst | 54 -------- Help/prop_test/RESOURCE_GROUPS.rst | 54 ++++++++ Help/prop_test/RESOURCE_LOCK.rst | 14 +-- Source/CTest/cmCTestMultiProcessHandler.cxx | 25 ++-- Source/CTest/cmCTestRunTest.cxx | 6 +- Source/CTest/cmCTestTestHandler.cxx | 10 +- Source/CTest/cmCTestTestHandler.h | 6 +- Tests/CMakeLib/CMakeLists.txt | 2 +- Tests/CMakeLib/testCTestProcesses.cxx | 137 -------------------- Tests/CMakeLib/testCTestResourceGroups.cxx | 138 +++++++++++++++++++++ Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake | 2 +- .../CTestCommandLine/show-only_json-v1_check.py | 6 +- .../CTestHardwareAllocation/HardwareCommon.cmake | 2 +- .../CTestHardwareAllocation/RunCMakeTest.cmake | 84 ++++++------- .../RunCMake/CTestHardwareAllocation/cthwalloc.cxx | 65 +++++----- 17 files changed, 345 insertions(+), 338 deletions(-) delete mode 100644 Help/prop_test/PROCESSES.rst create mode 100644 Help/prop_test/RESOURCE_GROUPS.rst delete mode 100644 Tests/CMakeLib/testCTestProcesses.cxx create mode 100644 Tests/CMakeLib/testCTestResourceGroups.cxx diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 1369aa3..a59dd6b 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -414,10 +414,10 @@ Properties on Tests /prop_test/LABELS /prop_test/MEASUREMENT /prop_test/PASS_REGULAR_EXPRESSION - /prop_test/PROCESSES /prop_test/PROCESSOR_AFFINITY /prop_test/PROCESSORS /prop_test/REQUIRED_FILES + /prop_test/RESOURCE_GROUPS /prop_test/RESOURCE_LOCK /prop_test/RUN_SERIAL /prop_test/SKIP_REGULAR_EXPRESSION diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index a18d43f..569f0f7 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -1317,8 +1317,8 @@ The CTest hardware allocation feature consists of two inputs: * The :ref:`hardware specification file `, described below, which describes the hardware resources available on the system, and -* The :prop_test:`PROCESSES` property of tests, which describes the resources - required by the test +* The :prop_test:`RESOURCE_GROUPS` property of tests, which describes the + resources required by the test When CTest runs a test, the hardware allocated to that test is passed in the form of a set of @@ -1326,11 +1326,11 @@ form of a set of described below. Using this information to decide which resource to connect to is left to the test writer. -Please note that these processes are not spawned by CTest. The ``PROCESSES`` -property merely tells CTest what processes the test expects to launch. It is up -to the test itself to do this process spawning, and read the :ref:`environment -variables ` to determine which resources -each process has been allocated. +The ``RESOURCE_GROUPS`` property tells CTest what resources a test expects +to use grouped in a way meaningful to the test. The test itself must read +the :ref:`environment variables ` to +determine which resources have been allocated to each group. For example, +each group may correspond to a process the test will spawn when executed. .. _`ctest-hardware-specification-file`: @@ -1423,10 +1423,10 @@ In the example file above, there are four GPUs with ID's 0 through 3. GPU 0 has 2 slots, GPU 1 has 4, GPU 2 has 2, and GPU 3 has a default of 1 slot. There is also one cryptography chip with 4 slots. -``PROCESSES`` Property ----------------------- +``RESOURCE_GROUPS`` Property +---------------------------- -See :prop_test:`PROCESSES` for a description of this property. +See :prop_test:`RESOURCE_GROUPS` for a description of this property. .. _`ctest-hardware-environment-variables`: @@ -1436,65 +1436,67 @@ Environment Variables Once CTest has decided which resources to allocate to a test, it passes this information to the test executable as a series of environment variables. For each example below, we will assume that the test in question has a -:prop_test:`PROCESSES` property of ``2,gpus:2;gpus:4,gpus:1,crypto_chips:2``. +:prop_test:`RESOURCE_GROUPS` property of +``2,gpus:2;gpus:4,gpus:1,crypto_chips:2``. The following variables are passed to the test process: -.. envvar:: CTEST_PROCESS_COUNT +.. envvar:: CTEST_RESOURCE_GROUP_COUNT - The total number of processes specified by the :prop_test:`PROCESSES` + The total number of groups specified by the :prop_test:`RESOURCE_GROUPS` property. For example: - * ``CTEST_PROCESS_COUNT=3`` + * ``CTEST_RESOURCE_GROUP_COUNT=3`` This variable will only be defined if :manual:`ctest(1)` has been given a ``--hardware-spec-file``, or if :command:`ctest_test` has been given a ``HARDWARE_SPEC_FILE``. If no hardware specification file has been given, this variable will not be defined. -.. envvar:: CTEST_PROCESS_ +.. envvar:: CTEST_RESOURCE_GROUP_ - The list of resource types allocated to each process, with each item + The list of resource types allocated to each group, with each item separated by a comma. ```` is a number from zero to - ``CTEST_PROCESS_COUNT`` minus one. ``CTEST_PROCESS_`` is defined for - each ```` in this range. For example: + ``CTEST_RESOURCE_GROUP_COUNT`` minus one. ``CTEST_RESOURCE_GROUP_`` + is defined for each ```` in this range. For example: - * ``CTEST_PROCESS_0=gpus`` - * ``CTEST_PROCESS_1=gpus`` - * ``CTEST_PROCESS_2=crypto_chips,gpus`` + * ``CTEST_RESOURCE_GROUP_0=gpus`` + * ``CTEST_RESOURCE_GROUP_1=gpus`` + * ``CTEST_RESOURCE_GROUP_2=crypto_chips,gpus`` -.. envvar:: CTEST_PROCESS__ +.. envvar:: CTEST_RESOURCE_GROUP__ The list of resource IDs and number of slots from each ID allocated to each - process for a given resource type. This variable consists of a series of + group for a given resource type. This variable consists of a series of pairs, each pair separated by a semicolon, and with the two items in the pair separated by a comma. The first item in each pair is ``id:`` followed by the ID of a resource of type ````, and the second item is ``slots:`` followed by the number of slots from that resource allocated to - the given process. For example: + the given group. For example: - * ``CTEST_PROCESS_0_GPUS=id:0,slots:2`` - * ``CTEST_PROCESS_1_GPUS=id:2,slots:2`` - * ``CTEST_PROCESS_2_GPUS=id:1,slots:4;id:3,slots:1`` - * ``CTEST_PROCESS_2_CRYPTO_CHIPS=id:card0,slots:2`` + * ``CTEST_RESOURCE_GROUP_0_GPUS=id:0,slots:2`` + * ``CTEST_RESOURCE_GROUP_1_GPUS=id:2,slots:2`` + * ``CTEST_RESOURCE_GROUP_2_GPUS=id:1,slots:4;id:3,slots:1`` + * ``CTEST_RESOURCE_GROUP_2_CRYPTO_CHIPS=id:card0,slots:2`` - In this example, process 0 gets 2 slots from GPU ``0``, process 1 gets 2 slots - from GPU ``2``, and process 2 gets 4 slots from GPU ``1`` and 2 slots from + In this example, group 0 gets 2 slots from GPU ``0``, group 1 gets 2 slots + from GPU ``2``, and group 2 gets 4 slots from GPU ``1`` and 2 slots from cryptography chip ``card0``. - ```` is a number from zero to ``CTEST_PROCESS_COUNT`` minus one. + ```` is a number from zero to ``CTEST_RESOURCE_GROUP_COUNT`` minus one. ```` is the name of a resource type, converted to uppercase. - ``CTEST_PROCESS__`` is defined for the product of each - ```` in the range listed above and each resource type listed in - ``CTEST_PROCESS_``. + ``CTEST_RESOURCE_GROUP__`` is defined for the product + of each ```` in the range listed above and each resource type listed in + ``CTEST_RESOURCE_GROUP_``. Because some platforms have case-insensitive names for environment variables, the names of resource types may not clash in a case-insensitive environment. Because of this, for the sake of simplicity, all resource types must be listed in all lowercase in the - :ref:`hardware specification file ` and in - the :prop_test:`PROCESSES` property, and they are converted to all uppercase - in the ``CTEST_PROCESS__`` environment variable. + :ref:`hardware specification file ` and + in the :prop_test:`RESOURCE_GROUPS` property, and they are converted to all + uppercase in the ``CTEST_RESOURCE_GROUP__`` environment + variable. See Also ======== diff --git a/Help/prop_test/PROCESSES.rst b/Help/prop_test/PROCESSES.rst deleted file mode 100644 index d09c6d1..0000000 --- a/Help/prop_test/PROCESSES.rst +++ /dev/null @@ -1,54 +0,0 @@ -PROCESSES ----------- - -Set to specify the number of processes spawned by a test, and the resources -that they require. See :ref:`hardware allocation ` -for more information on how this property integrates into the CTest hardware -allocation feature. - -The ``PROCESSES`` property is a :ref:`semicolon-separated list ` of process descriptions. Each process description consists of an -optional number of processes for the description followed by a series of -resource requirements for those processes. These requirements (and the number -of processes) are separated by commas. The resource requirements consist of the -name of a resource type, followed by a colon, followed by an unsigned integer -specifying the number of slots required on one resource of the given type. - -Please note that these processes are not spawned by CTest. The ``PROCESSES`` -property merely tells CTest what processes the test expects to launch. It is up -to the test itself to do this process spawning, and read the :ref:`environment -variables ` to determine which resources -each process has been allocated. - -Consider the following example: - -.. code-block:: cmake - - add_test(NAME MyTest COMMAND MyExe) - set_property(TEST MyTest PROPERTY PROCESSES - "2,gpus:2" - "gpus:4,crypto_chips:2") - -In this example, there are two process descriptions (implicitly separated by a -semicolon.) The content of the first description is ``2,gpus:2``. This -description spawns 2 processes, each of which requires 2 slots from a single -GPU. The content of the second description is ``gpus:4,crypto_chips:2``. This -description does not specify a process count, so a default of 1 is assumed. -This single process requires 4 slots from a single GPU and 2 slots from a -single cryptography chip. In total, 3 processes are spawned from this test, -each with their own unique requirements. - -When CTest sets the :ref:`environment variables -` for a test, it assigns a process number -based on the process description, starting at 0 on the left and the number of -processes minus 1 on the right. For example, in the example above, the two -processes in the first description would have IDs of 0 and 1, and the single -process in the second description would have an ID of 2. - -Both the ``PROCESSES`` and :prop_test:`RESOURCE_LOCK` properties serve similar -purposes, but they are distinct and orthogonal. Resources specified by -``PROCESSES`` do not affect :prop_test:`RESOURCE_LOCK`, and vice versa. Whereas -:prop_test:`RESOURCE_LOCK` is a simpler property that is used for locking one -global resource, ``PROCESSES`` is a more advanced property that allows multiple -tests to simultaneously use multiple resources of the same type, specifying -their requirements in a fine-grained manner. diff --git a/Help/prop_test/RESOURCE_GROUPS.rst b/Help/prop_test/RESOURCE_GROUPS.rst new file mode 100644 index 0000000..6fdbd03 --- /dev/null +++ b/Help/prop_test/RESOURCE_GROUPS.rst @@ -0,0 +1,54 @@ +RESOURCE_GROUPS +--------------- + +Specify resources required by a test, grouped in a way that is meaningful to +the test. See :ref:`hardware allocation ` +for more information on how this property integrates into the CTest hardware +allocation feature. + +The ``RESOURCE_GROUPS`` property is a :ref:`semicolon-separated list ` of group descriptions. Each entry consists of an optional +number of groups using the description followed by a series of resource +requirements for those groups. These requirements (and the number of groups) +are separated by commas. The resource requirements consist of the name of a +resource type, followed by a colon, followed by an unsigned integer +specifying the number of slots required on one resource of the given type. + +The ``RESOURCE_GROUPS`` property tells CTest what resources a test expects +to use grouped in a way meaningful to the test. The test itself must read +the :ref:`environment variables ` to +determine which resources have been allocated to each group. For example, +each group may correspond to a process the test will spawn when executed. + +Consider the following example: + +.. code-block:: cmake + + add_test(NAME MyTest COMMAND MyExe) + set_property(TEST MyTest PROPERTY RESOURCE_GROUPS + "2,gpus:2" + "gpus:4,crypto_chips:2") + +In this example, there are two group descriptions (implicitly separated by a +semicolon.) The content of the first description is ``2,gpus:2``. This +description specifies 2 groups, each of which requires 2 slots from a single +GPU. The content of the second description is ``gpus:4,crypto_chips:2``. This +description does not specify a group count, so a default of 1 is assumed. +This single group requires 4 slots from a single GPU and 2 slots from a +single cryptography chip. In total, 3 resource groups are specified for this +test, each with its own unique requirements. + +When CTest sets the :ref:`environment variables +` for a test, it assigns a group number +based on the group description, starting at 0 on the left and the number of +groups minus 1 on the right. For example, in the example above, the two +groups in the first description would have IDs of 0 and 1, and the single +group in the second description would have an ID of 2. + +Both the ``RESOURCE_GROUPS`` and :prop_test:`RESOURCE_LOCK` properties serve +similar purposes, but they are distinct and orthogonal. Resources specified by +``RESOURCE_GROUPS`` do not affect :prop_test:`RESOURCE_LOCK`, and vice versa. +Whereas :prop_test:`RESOURCE_LOCK` is a simpler property that is used for +locking one global resource, ``RESOURCE_GROUPS`` is a more advanced property +that allows multiple tests to simultaneously use multiple resources of the +same type, specifying their requirements in a fine-grained manner. diff --git a/Help/prop_test/RESOURCE_LOCK.rst b/Help/prop_test/RESOURCE_LOCK.rst index 7d61f77..8b13a01 100644 --- a/Help/prop_test/RESOURCE_LOCK.rst +++ b/Help/prop_test/RESOURCE_LOCK.rst @@ -9,10 +9,10 @@ not to run concurrently. See also :prop_test:`FIXTURES_REQUIRED` if the resource requires any setup or cleanup steps. -Both the :prop_test:`PROCESSES` and ``RESOURCE_LOCK`` properties serve similar -purposes, but they are distinct and orthogonal. Resources specified by -:prop_test:`PROCESSES` do not affect ``RESOURCE_LOCK``, and vice versa. Whereas -``RESOURCE_LOCK`` is a simpler property that is used for locking one global -resource, :prop_test:`PROCESSES` is a more advanced property that allows -multiple tests to simultaneously use multiple resources of the same type, -specifying their requirements in a fine-grained manner. +Both the :prop_test:`RESOURCE_GROUPS` and ``RESOURCE_LOCK`` properties serve +similar purposes, but they are distinct and orthogonal. Resources specified by +:prop_test:`RESOURCE_GROUPS` do not affect ``RESOURCE_LOCK``, and vice versa. +Whereas ``RESOURCE_LOCK`` is a simpler property that is used for locking one +global resource, :prop_test:`RESOURCE_GROUPS` is a more advanced property +that allows multiple tests to simultaneously use multiple resources of the +same type, specifying their requirements in a fine-grained manner. diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 7e8d548..c71ae7b 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -230,7 +230,7 @@ bool cmCTestMultiProcessHandler::AllocateHardware(int index) } auto& allocatedHardware = this->AllocatedHardware[index]; - allocatedHardware.resize(this->Properties[index]->Processes.size()); + allocatedHardware.resize(this->Properties[index]->ResourceGroups.size()); for (auto const& it : allocations) { for (auto const& alloc : it.second) { bool result = this->HardwareAllocator.AllocateResource( @@ -252,7 +252,7 @@ bool cmCTestMultiProcessHandler::TryAllocateHardware( allocations.clear(); std::size_t processIndex = 0; - for (auto const& process : this->Properties[index]->Processes) { + for (auto const& process : this->Properties[index]->ResourceGroups) { for (auto const& requirement : process) { for (int i = 0; i < requirement.UnitsNeeded; ++i) { allocations[requirement.ResourceType].push_back( @@ -912,14 +912,14 @@ static Json::Value DumpTimeoutAfterMatch( return timeoutAfterMatch; } -static Json::Value DumpProcessesToJsonArray( +static Json::Value DumpResourceGroupsToJsonArray( const std::vector< std::vector>& - processes) + resourceGroups) { - Json::Value jsonProcesses = Json::arrayValue; - for (auto const& it : processes) { - Json::Value jsonProcess = Json::objectValue; + Json::Value jsonResourceGroups = Json::arrayValue; + for (auto const& it : resourceGroups) { + Json::Value jsonResourceGroup = Json::objectValue; Json::Value requirements = Json::arrayValue; for (auto const& it2 : it) { Json::Value res = Json::objectValue; @@ -928,10 +928,10 @@ static Json::Value DumpProcessesToJsonArray( res["slots"] = it2.SlotsNeeded; requirements.append(res); } - jsonProcess["requirements"] = requirements; - jsonProcesses.append(jsonProcess); + jsonResourceGroup["requirements"] = requirements; + jsonResourceGroups.append(jsonResourceGroup); } - return jsonProcesses; + return jsonResourceGroups; } static Json::Value DumpCTestProperty(std::string const& name, @@ -1005,9 +1005,10 @@ static Json::Value DumpCTestProperties( "PASS_REGULAR_EXPRESSION", DumpRegExToJsonArray(testProperties.RequiredRegularExpressions))); } - if (!testProperties.Processes.empty()) { + if (!testProperties.ResourceGroups.empty()) { properties.append(DumpCTestProperty( - "PROCESSES", DumpProcessesToJsonArray(testProperties.Processes))); + "RESOURCE_GROUPS", + DumpResourceGroupsToJsonArray(testProperties.ResourceGroups))); } if (testProperties.WantAffinity) { properties.append( diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 7f7f736..91eeb71 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -693,7 +693,7 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, if (this->UseAllocatedHardware) { this->SetupHardwareEnvironment(); } else { - cmSystemTools::UnsetEnv("CTEST_PROCESS_COUNT"); + cmSystemTools::UnsetEnv("CTEST_RESOURCE_GROUP_COUNT"); } return this->TestProcess->StartProcess(this->MultiTestHandler.Loop, @@ -702,13 +702,13 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, void cmCTestRunTest::SetupHardwareEnvironment() { - std::string processCount = "CTEST_PROCESS_COUNT="; + std::string processCount = "CTEST_RESOURCE_GROUP_COUNT="; processCount += std::to_string(this->AllocatedHardware.size()); cmSystemTools::PutEnv(processCount); std::size_t i = 0; for (auto const& process : this->AllocatedHardware) { - std::string prefix = "CTEST_PROCESS_"; + std::string prefix = "CTEST_RESOURCE_GROUP_"; prefix += std::to_string(i); std::string resourceList = prefix + '='; prefix += '_'; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 2be62ae..0f21f91 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1626,11 +1626,11 @@ std::string cmCTestTestHandler::FindExecutable( return fullPath; } -bool cmCTestTestHandler::ParseProcessesProperty( +bool cmCTestTestHandler::ParseResourceGroupsProperty( const std::string& val, - std::vector>& processes) + std::vector>& resourceGroups) { - cmCTestProcessesLexerHelper lexer(processes); + cmCTestProcessesLexerHelper lexer(resourceGroups); return lexer.ParseString(val); } @@ -2203,8 +2203,8 @@ bool cmCTestTestHandler::SetTestsProperties( if (key == "PROCESSOR_AFFINITY") { rt.WantAffinity = cmIsOn(val); } - if (key == "PROCESSES") { - if (!ParseProcessesProperty(val, rt.Processes)) { + if (key == "RESOURCE_GROUPS") { + if (!ParseResourceGroupsProperty(val, rt.ResourceGroups)) { return false; } } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 525215c..e2fde42 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -158,7 +158,7 @@ public: std::set FixturesCleanup; std::set FixturesRequired; std::set RequireSuccessDepends; - std::vector> Processes; + std::vector> ResourceGroups; // Private test generator properties used to track backtraces cmListFileBacktrace Backtrace; }; @@ -202,9 +202,9 @@ public: std::vector& extraPaths, std::vector& failed); - static bool ParseProcessesProperty( + static bool ParseResourceGroupsProperty( const std::string& val, - std::vector>& processes); + std::vector>& resourceGroups); using ListOfTests = std::vector; diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index bc2079f..8e11fdf 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -8,9 +8,9 @@ include_directories( set(CMakeLib_TESTS testArgumentParser.cxx testCTestBinPacker.cxx - testCTestProcesses.cxx testCTestHardwareAllocator.cxx testCTestHardwareSpec.cxx + testCTestResourceGroups.cxx testGeneratedFileStream.cxx testRST.cxx testRange.cxx diff --git a/Tests/CMakeLib/testCTestProcesses.cxx b/Tests/CMakeLib/testCTestProcesses.cxx deleted file mode 100644 index acf4f67..0000000 --- a/Tests/CMakeLib/testCTestProcesses.cxx +++ /dev/null @@ -1,137 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ - -#include -#include -#include - -#include "cmCTestTestHandler.h" - -struct ExpectedParseResult -{ - std::string String; - bool ExpectedReturnValue; - std::vector> - ExpectedValue; -}; - -static const std::vector expectedResults{ - /* clang-format off */ - { "threads:2", true, { - { { "threads", 2, 1 } }, - } }, - { "3,threads:2", true, { - { { "threads", 2, 1 } }, - { { "threads", 2, 1 } }, - { { "threads", 2, 1 } }, - } }, - { "3,threads:2,gpus:4", true, { - { { "threads", 2, 1 }, { "gpus", 4, 1 } }, - { { "threads", 2, 1 }, { "gpus", 4, 1 } }, - { { "threads", 2, 1 }, { "gpus", 4, 1 } }, - } }, - { "2,threads:2;gpus:4", true, { - { { "threads", 2, 1 } }, - { { "threads", 2, 1 } }, - { { "gpus", 4, 1 } }, - } }, - { "threads:2;2,gpus:4", true, { - { { "threads", 2, 1 } }, - { { "gpus", 4, 1 } }, - { { "gpus", 4, 1 } }, - } }, - { "threads:2;gpus:4", true, { - { { "threads", 2, 1 } }, - { { "gpus", 4, 1 } }, - } }, - { "1,threads:2;0,gpus:4", true, { - { { "threads", 2, 1 } }, - } }, - { "1,_:1", true, { - { { "_", 1, 1 } }, - } }, - { "1,a:1", true, { - { { "a", 1, 1 } }, - } }, - { "2", true, { - {}, - {}, - } }, - { "1;2,threads:1", true, { - {}, - { { "threads", 1, 1 } }, - { { "threads", 1, 1 } }, - } }, - { "1,,threads:1", true, { - { { "threads", 1, 1 } }, - } }, - { ";1,threads:1", true, { - { { "threads", 1, 1 } }, - } }, - { "1,threads:1;", true, { - { { "threads", 1, 1 } }, - } }, - { "1,threads:1,", true, { - { { "threads", 1, 1 } }, - } }, - { "threads:1;;threads:2", true, { - { { "threads", 1, 1 } }, - { { "threads", 2, 1 } }, - } }, - { "1,", true, { - {}, - } }, - { ";", true, {} }, - { "", true, {} }, - { ",", false, {} }, - { "1,0:1", false, {} }, - { "1,A:1", false, {} }, - { "1,a-b:1", false, {} }, - { "invalid", false, {} }, - { ",1,invalid:1", false, {} }, - { "1,1", false, {} }, - { "-1,invalid:1", false, {} }, - { "1,invalid:*", false, {} }, - { "1,invalid:-1", false, {} }, - { "1,invalid:-", false, {} }, - { "1,invalid:ab2", false, {} }, - { "1,invalid :2", false, {} }, - { "1, invalid:2", false, {} }, - { "1,invalid:ab", false, {} }, - /* clang-format on */ -}; - -bool TestExpectedParseResult(const ExpectedParseResult& expected) -{ - std::vector> - result; - bool retval; - if ((retval = cmCTestTestHandler::ParseProcessesProperty( - expected.String, result)) != expected.ExpectedReturnValue) { - std::cout << "ParseProcessesProperty(\"" << expected.String - << "\") returned " << retval << ", should be " - << expected.ExpectedReturnValue << std::endl; - return false; - } - - if (result != expected.ExpectedValue) { - std::cout << "ParseProcessesProperty(\"" << expected.String - << "\") did not yield expected set of processes" << std::endl; - return false; - } - - return true; -} - -int testCTestProcesses(int /*unused*/, char* /*unused*/ []) -{ - int retval = 0; - - for (auto const& expected : expectedResults) { - if (!TestExpectedParseResult(expected)) { - retval = 1; - } - } - - return retval; -} diff --git a/Tests/CMakeLib/testCTestResourceGroups.cxx b/Tests/CMakeLib/testCTestResourceGroups.cxx new file mode 100644 index 0000000..5fd7d4a --- /dev/null +++ b/Tests/CMakeLib/testCTestResourceGroups.cxx @@ -0,0 +1,138 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include +#include +#include + +#include "cmCTestTestHandler.h" + +struct ExpectedParseResult +{ + std::string String; + bool ExpectedReturnValue; + std::vector> + ExpectedValue; +}; + +static const std::vector expectedResults{ + /* clang-format off */ + { "threads:2", true, { + { { "threads", 2, 1 } }, + } }, + { "3,threads:2", true, { + { { "threads", 2, 1 } }, + { { "threads", 2, 1 } }, + { { "threads", 2, 1 } }, + } }, + { "3,threads:2,gpus:4", true, { + { { "threads", 2, 1 }, { "gpus", 4, 1 } }, + { { "threads", 2, 1 }, { "gpus", 4, 1 } }, + { { "threads", 2, 1 }, { "gpus", 4, 1 } }, + } }, + { "2,threads:2;gpus:4", true, { + { { "threads", 2, 1 } }, + { { "threads", 2, 1 } }, + { { "gpus", 4, 1 } }, + } }, + { "threads:2;2,gpus:4", true, { + { { "threads", 2, 1 } }, + { { "gpus", 4, 1 } }, + { { "gpus", 4, 1 } }, + } }, + { "threads:2;gpus:4", true, { + { { "threads", 2, 1 } }, + { { "gpus", 4, 1 } }, + } }, + { "1,threads:2;0,gpus:4", true, { + { { "threads", 2, 1 } }, + } }, + { "1,_:1", true, { + { { "_", 1, 1 } }, + } }, + { "1,a:1", true, { + { { "a", 1, 1 } }, + } }, + { "2", true, { + {}, + {}, + } }, + { "1;2,threads:1", true, { + {}, + { { "threads", 1, 1 } }, + { { "threads", 1, 1 } }, + } }, + { "1,,threads:1", true, { + { { "threads", 1, 1 } }, + } }, + { ";1,threads:1", true, { + { { "threads", 1, 1 } }, + } }, + { "1,threads:1;", true, { + { { "threads", 1, 1 } }, + } }, + { "1,threads:1,", true, { + { { "threads", 1, 1 } }, + } }, + { "threads:1;;threads:2", true, { + { { "threads", 1, 1 } }, + { { "threads", 2, 1 } }, + } }, + { "1,", true, { + {}, + } }, + { ";", true, {} }, + { "", true, {} }, + { ",", false, {} }, + { "1,0:1", false, {} }, + { "1,A:1", false, {} }, + { "1,a-b:1", false, {} }, + { "invalid", false, {} }, + { ",1,invalid:1", false, {} }, + { "1,1", false, {} }, + { "-1,invalid:1", false, {} }, + { "1,invalid:*", false, {} }, + { "1,invalid:-1", false, {} }, + { "1,invalid:-", false, {} }, + { "1,invalid:ab2", false, {} }, + { "1,invalid :2", false, {} }, + { "1, invalid:2", false, {} }, + { "1,invalid:ab", false, {} }, + /* clang-format on */ +}; + +bool TestExpectedParseResult(const ExpectedParseResult& expected) +{ + std::vector> + result; + bool retval; + if ((retval = cmCTestTestHandler::ParseResourceGroupsProperty( + expected.String, result)) != expected.ExpectedReturnValue) { + std::cout << "ParseResourceGroupsProperty(\"" << expected.String + << "\") returned " << retval << ", should be " + << expected.ExpectedReturnValue << std::endl; + return false; + } + + if (result != expected.ExpectedValue) { + std::cout << "ParseResourceGroupsProperty(\"" << expected.String + << "\") did not yield expected set of resource groups" + << std::endl; + return false; + } + + return true; +} + +int testCTestResourceGroups(int /*unused*/, char* /*unused*/ []) +{ + int retval = 0; + + for (auto const& expected : expectedResults) { + if (!TestExpectedParseResult(expected)) { + retval = 1; + } + } + + return retval; +} diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake index fd2c97f..6b23162 100644 --- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -258,7 +258,7 @@ function(run_ShowOnly) add_test(ShowOnly \"${CMAKE_COMMAND}\" -E echo) set_tests_properties(ShowOnly PROPERTIES WILL_FAIL true - PROCESSES \"2,threads:2,gpus:4;gpus:2,threads:4\" + RESOURCE_GROUPS \"2,threads:2,gpus:4;gpus:2,threads:4\" REQUIRED_FILES RequiredFileDoesNotExist _BACKTRACE_TRIPLES \"file1;1;add_test;file0;;\" ) diff --git a/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py b/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py index 6eb8624..b818650 100644 --- a/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py +++ b/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py @@ -80,12 +80,12 @@ def check_willfail_property(p): assert p["name"] == "WILL_FAIL" assert p["value"] == True -def check_processes_property(p): +def check_resource_groups_property(p): assert is_dict(p) assert sorted(p.keys()) == ["name", "value"] assert is_string(p["name"]) assert is_list(p["value"]) - assert p["name"] == "PROCESSES" + assert p["name"] == "RESOURCE_GROUPS" assert len(p["value"]) == 3 assert is_dict(p["value"][0]) @@ -147,7 +147,7 @@ def check_workingdir_property(p): def check_properties(p): assert is_list(p) assert len(p) == 4 - check_processes_property(p[0]) + check_resource_groups_property(p[0]) check_reqfiles_property(p[1]) check_willfail_property(p[2]) check_workingdir_property(p[3]) diff --git a/Tests/RunCMake/CTestHardwareAllocation/HardwareCommon.cmake b/Tests/RunCMake/CTestHardwareAllocation/HardwareCommon.cmake index 3893d40..3288f35 100644 --- a/Tests/RunCMake/CTestHardwareAllocation/HardwareCommon.cmake +++ b/Tests/RunCMake/CTestHardwareAllocation/HardwareCommon.cmake @@ -11,7 +11,7 @@ function(add_hardware_test name sleep_time proc) else() add_test(NAME "${name}" COMMAND "${CTHWALLOC_COMMAND}" write "${CMAKE_BINARY_DIR}/cthwalloc.log" "${name}" "${sleep_time}") endif() - set_property(TEST "${name}" PROPERTY PROCESSES "${proc}") + set_property(TEST "${name}" PROPERTY RESOURCE_GROUPS "${proc}") list(APPEND HARDWARE_TESTS "${name}") set(HARDWARE_TESTS "${HARDWARE_TESTS}" PARENT_SCOPE) endfunction() diff --git a/Tests/RunCMake/CTestHardwareAllocation/RunCMakeTest.cmake b/Tests/RunCMake/CTestHardwareAllocation/RunCMakeTest.cmake index d666922..f69afc7 100644 --- a/Tests/RunCMake/CTestHardwareAllocation/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestHardwareAllocation/RunCMakeTest.cmake @@ -38,7 +38,7 @@ function(run_cthwalloc_verify name tests) run_cmake_command(${name} "${CTHWALLOC_COMMAND}" verify "${RunCMake_SOURCE_DIR}/${name}.log" "${CMAKE_CURRENT_LIST_DIR}/hwspec.json" "${tests}") endfunction() -unset(ENV{CTEST_PROCESS_COUNT}) +unset(ENV{CTEST_RESOURCE_GROUP_COUNT}) set(RunCMake_TEST_NO_CLEAN 1) file(REMOVE_RECURSE "${RunCMake_BINARY_DIR}/cthwalloc-write-proc-good1-build") file(MAKE_DIRECTORY "${RunCMake_BINARY_DIR}/cthwalloc-write-proc-good1-build") @@ -49,75 +49,75 @@ dealloc widgets 0 1 end test1 ]]) run_cthwalloc_write_proc_nodel(cthwalloc-write-proc-good1 "1,widgets:2,transmogrifiers:1;2,widgets:1,widgets:2" - CTEST_PROCESS_COUNT=3 - CTEST_PROCESS_0=widgets,transmogrifiers - CTEST_PROCESS_0_WIDGETS=id:0,slots:2 - CTEST_PROCESS_0_TRANSMOGRIFIERS=id:calvin,slots:1 - CTEST_PROCESS_1=widgets - "CTEST_PROCESS_1_WIDGETS=id:0,slots:1\\;id:2,slots:2" - CTEST_PROCESS_2=widgets - "CTEST_PROCESS_2_WIDGETS=id:0,slots:1\\;id:2,slots:2" + CTEST_RESOURCE_GROUP_COUNT=3 + CTEST_RESOURCE_GROUP_0=widgets,transmogrifiers + CTEST_RESOURCE_GROUP_0_WIDGETS=id:0,slots:2 + CTEST_RESOURCE_GROUP_0_TRANSMOGRIFIERS=id:calvin,slots:1 + CTEST_RESOURCE_GROUP_1=widgets + "CTEST_RESOURCE_GROUP_1_WIDGETS=id:0,slots:1\\;id:2,slots:2" + CTEST_RESOURCE_GROUP_2=widgets + "CTEST_RESOURCE_GROUP_2_WIDGETS=id:0,slots:1\\;id:2,slots:2" ) set(RunCMake_TEST_NO_CLEAN 0) run_cthwalloc_write_proc(cthwalloc-write-proc-good2 "widgets:8" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets - CTEST_PROCESS_0_WIDGETS=id:3,slots:8 + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets + CTEST_RESOURCE_GROUP_0_WIDGETS=id:3,slots:8 ) run_cthwalloc_write_proc(cthwalloc-write-proc-nocount "widgets:8") run_cthwalloc_write_proc(cthwalloc-write-proc-badcount "widgets:8" - CTEST_PROCESS_COUNT=2 + CTEST_RESOURCE_GROUP_COUNT=2 ) run_cthwalloc_write_proc(cthwalloc-write-proc-nores "widgets:8" - CTEST_PROCESS_COUNT=1 + CTEST_RESOURCE_GROUP_COUNT=1 ) run_cthwalloc_write_proc(cthwalloc-write-proc-badres "widgets:8" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets,transmogrifiers + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets,transmogrifiers ) run_cthwalloc_write_proc(cthwalloc-write-proc-nowidgets "widgets:8" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets ) run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets1 "widgets:8" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets - CTEST_PROCESS_0_WIDGETS= + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets + CTEST_RESOURCE_GROUP_0_WIDGETS= ) run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets2 "widgets:8" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets - "CTEST_PROCESS_0_WIDGETS=id:3,slots:8\\;id:0,slots:1" + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets + "CTEST_RESOURCE_GROUP_0_WIDGETS=id:3,slots:8\\;id:0,slots:1" ) run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets3 "widgets:8" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets - CTEST_PROCESS_0_WIDGETS=id:3,slots:7 + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets + CTEST_RESOURCE_GROUP_0_WIDGETS=id:3,slots:7 ) run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets4 "widgets:8" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets - CTEST_PROCESS_0_WIDGETS=invalid + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets + CTEST_RESOURCE_GROUP_0_WIDGETS=invalid ) run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets5 "widgets:2,widgets:2" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets - "CTEST_PROCESS_0_WIDGETS=id:0,slots:2\\;id:0,slots:1" + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets + "CTEST_RESOURCE_GROUP_0_WIDGETS=id:0,slots:2\\;id:0,slots:1" ) run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets6 "widgets:2" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets - "CTEST_PROCESS_0_WIDGETS=id:0,slots:2\\;id:0,slots:1" + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets + "CTEST_RESOURCE_GROUP_0_WIDGETS=id:0,slots:2\\;id:0,slots:1" ) run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets7 "widgets:2,widgets:2" - CTEST_PROCESS_COUNT=1 - CTEST_PROCESS_0=widgets - CTEST_PROCESS_0_WIDGETS=id:0,slots:2 + CTEST_RESOURCE_GROUP_COUNT=1 + CTEST_RESOURCE_GROUP_0=widgets + CTEST_RESOURCE_GROUP_0_WIDGETS=id:0,slots:2 ) run_cthwalloc_write_noproc(cthwalloc-write-noproc-good1) run_cthwalloc_write_noproc(cthwalloc-write-noproc-count - CTEST_PROCESS_COUNT=1 + CTEST_RESOURCE_GROUP_COUNT=1 ) run_cthwalloc_verify(cthwalloc-verify-good1 "test1;test2") @@ -162,6 +162,6 @@ run_ctest_hardware(notenough1 1 0) run_ctest_hardware(notenough2 1 0) run_ctest_hardware(ensure_parallel 2 0) -set(ENV{CTEST_PROCESS_COUNT} 2) +set(ENV{CTEST_RESOURCE_GROUP_COUNT} 2) run_ctest_hardware(process_count 1 0) -unset(ENV{CTEST_PROCESS_COUNT}) +unset(ENV{CTEST_RESOURCE_GROUP_COUNT}) diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc.cxx b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc.cxx index eee2c7f..e5f0283 100644 --- a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc.cxx +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc.cxx @@ -26,11 +26,11 @@ * This helper program is used to verify that the CTest hardware allocation * feature is working correctly. It consists of two stages: * - * 1) write - This stage receives the PROCESSES property of the test and - * compares it with the values passed in the CTEST_PROCESS_* environment - * variables. If it received all of the resources it expected, then it - * writes this information to a log file, which will be read in the verify - * stage. + * 1) write - This stage receives the RESOURCE_GROUPS property of the test and + * compares it with the values passed in the CTEST_RESOURCE_GROUP_* + * environment variables. If it received all of the resources it expected, + * then it writes this information to a log file, which will be read in + * the verify stage. * 2) verify - This stage compares the log file with the hardware spec file to * make sure that no resources were over-subscribed, deallocated without * being allocated, or allocated without being deallocated. @@ -46,7 +46,7 @@ static int usageWrite(const char* argv0) { std::cout << "Usage: " << argv0 << " write " - " []" + " []" << std::endl; return 1; } @@ -71,28 +71,30 @@ static int doWrite(int argc, char const* const* argv) std::string, std::vector>> hardware; if (argc == 6) { - // Parse processes property - std::string processesProperty = argv[5]; + // Parse RESOURCE_GROUPS property + std::string resourceGroupsProperty = argv[5]; std::vector< std::vector> - processes; - bool result = - cmCTestTestHandler::ParseProcessesProperty(processesProperty, processes); + resourceGroups; + bool result = cmCTestTestHandler::ParseResourceGroupsProperty( + resourceGroupsProperty, resourceGroups); (void)result; assert(result); - // Verify process count - const char* processCountEnv = cmSystemTools::GetEnv("CTEST_PROCESS_COUNT"); - if (!processCountEnv) { - std::cout << "CTEST_PROCESS_COUNT should be defined" << std::endl; + // Verify group count + const char* resourceGroupCountEnv = + cmSystemTools::GetEnv("CTEST_RESOURCE_GROUP_COUNT"); + if (!resourceGroupCountEnv) { + std::cout << "CTEST_RESOURCE_GROUP_COUNT should be defined" << std::endl; return 1; } - int processCount = std::atoi(processCountEnv); - if (processes.size() != std::size_t(processCount)) { - std::cout << "CTEST_PROCESS_COUNT does not match expected processes" - << std::endl - << "Expected: " << processes.size() << std::endl - << "Actual: " << processCount << std::endl; + int resourceGroupCount = std::atoi(resourceGroupCountEnv); + if (resourceGroups.size() != std::size_t(resourceGroupCount)) { + std::cout + << "CTEST_RESOURCE_GROUP_COUNT does not match expected resource groups" + << std::endl + << "Expected: " << resourceGroups.size() << std::endl + << "Actual: " << resourceGroupCount << std::endl; return 1; } @@ -110,15 +112,15 @@ static int doWrite(int argc, char const* const* argv) std::size_t i = 0; cmsys::ofstream fout(logFile.c_str(), std::ios::app); fout << "begin " << testName << std::endl; - for (auto& process : processes) { + for (auto& resourceGroup : resourceGroups) { try { // Build and verify set of expected resources std::set expectedResources; - for (auto const& it : process) { + for (auto const& it : resourceGroup) { expectedResources.insert(it.ResourceType); } - std::string prefix = "CTEST_PROCESS_"; + std::string prefix = "CTEST_RESOURCE_GROUP_"; prefix += std::to_string(i); const char* actualResourcesCStr = cmSystemTools::GetEnv(prefix); if (!actualResourcesCStr) { @@ -147,7 +149,7 @@ static int doWrite(int argc, char const* const* argv) std::vector> hwEntry; for (auto const& type : actualResources) { - auto it = process.begin(); + auto it = resourceGroup.begin(); std::string varName = prefix; varName += cmSystemTools::UpperCase(type); @@ -161,7 +163,7 @@ static int doWrite(int argc, char const* const* argv) for (auto const& r : received) { while (it->ResourceType != type || it->UnitsNeeded == 0) { ++it; - if (it == process.end()) { + if (it == resourceGroup.end()) { std::cout << varName << " did not list expected resources" << std::endl; return 1; @@ -198,7 +200,7 @@ static int doWrite(int argc, char const* const* argv) bool ended = false; while (it->ResourceType != type || it->UnitsNeeded == 0) { ++it; - if (it == process.end()) { + if (it == resourceGroup.end()) { ended = true; break; } @@ -225,8 +227,9 @@ static int doWrite(int argc, char const* const* argv) return 1; } } else { - if (cmSystemTools::GetEnv("CTEST_PROCESS_COUNT")) { - std::cout << "CTEST_PROCESS_COUNT should not be defined" << std::endl; + if (cmSystemTools::GetEnv("CTEST_RESOURCE_GROUP_COUNT")) { + std::cout << "CTEST_RESOURCE_GROUP_COUNT should not be defined" + << std::endl; return 1; } } @@ -246,8 +249,8 @@ static int doWrite(int argc, char const* const* argv) return 1; } cmsys::ofstream fout(logFile.c_str(), std::ios::app); - for (auto const& process : hardware) { - for (auto const& it : process) { + for (auto const& group : hardware) { + for (auto const& it : group) { for (auto const& it2 : it.second) { fout << "dealloc " << it.first << " " << it2.Id << " " << it2.Slots << std::endl; -- cgit v0.12