summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx26
-rw-r--r--Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py65
3 files changed, 88 insertions, 4 deletions
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index aee6d67..7e8d548 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -912,6 +912,28 @@ static Json::Value DumpTimeoutAfterMatch(
return timeoutAfterMatch;
}
+static Json::Value DumpProcessesToJsonArray(
+ const std::vector<
+ std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>>&
+ processes)
+{
+ Json::Value jsonProcesses = Json::arrayValue;
+ for (auto const& it : processes) {
+ Json::Value jsonProcess = Json::objectValue;
+ Json::Value requirements = Json::arrayValue;
+ for (auto const& it2 : it) {
+ Json::Value res = Json::objectValue;
+ res[".type"] = it2.ResourceType;
+ // res[".units"] = it2.UnitsNeeded; // Intentionally commented out
+ res["slots"] = it2.SlotsNeeded;
+ requirements.append(res);
+ }
+ jsonProcess["requirements"] = requirements;
+ jsonProcesses.append(jsonProcess);
+ }
+ return jsonProcesses;
+}
+
static Json::Value DumpCTestProperty(std::string const& name,
Json::Value value)
{
@@ -983,6 +1005,10 @@ static Json::Value DumpCTestProperties(
"PASS_REGULAR_EXPRESSION",
DumpRegExToJsonArray(testProperties.RequiredRegularExpressions)));
}
+ if (!testProperties.Processes.empty()) {
+ properties.append(DumpCTestProperty(
+ "PROCESSES", DumpProcessesToJsonArray(testProperties.Processes)));
+ }
if (testProperties.WantAffinity) {
properties.append(
DumpCTestProperty("PROCESSOR_AFFINITY", testProperties.WantAffinity));
diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
index ca2975a..fd2c97f 100644
--- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
@@ -258,6 +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\"
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 3ad5768..6eb8624 100644
--- a/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py
+++ b/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py
@@ -80,6 +80,62 @@ def check_willfail_property(p):
assert p["name"] == "WILL_FAIL"
assert p["value"] == True
+def check_processes_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 len(p["value"]) == 3
+
+ assert is_dict(p["value"][0])
+ assert sorted(p["value"][0].keys()) == ["requirements"]
+ assert is_list(p["value"][0]["requirements"])
+ assert len(p["value"][0]["requirements"]) == 2
+ assert is_dict(p["value"][0]["requirements"][0])
+ assert sorted(p["value"][0]["requirements"][0].keys()) == \
+ [".type", "slots"]
+ assert is_string(p["value"][0]["requirements"][0][".type"])
+ assert p["value"][0]["requirements"][0][".type"] == "threads"
+ assert is_int(p["value"][0]["requirements"][0]["slots"])
+ assert p["value"][0]["requirements"][0]["slots"] == 2
+ assert is_string(p["value"][0]["requirements"][1][".type"])
+ assert p["value"][0]["requirements"][1][".type"] == "gpus"
+ assert is_int(p["value"][0]["requirements"][1]["slots"])
+ assert p["value"][0]["requirements"][1]["slots"] == 4
+
+ assert is_dict(p["value"][1])
+ assert sorted(p["value"][1].keys()) == ["requirements"]
+ assert is_list(p["value"][1]["requirements"])
+ assert len(p["value"][1]["requirements"]) == 2
+ assert is_dict(p["value"][1]["requirements"][0])
+ assert sorted(p["value"][1]["requirements"][0].keys()) == \
+ [".type", "slots"]
+ assert is_string(p["value"][1]["requirements"][0][".type"])
+ assert p["value"][1]["requirements"][0][".type"] == "threads"
+ assert is_int(p["value"][1]["requirements"][0]["slots"])
+ assert p["value"][1]["requirements"][0]["slots"] == 2
+ assert is_string(p["value"][1]["requirements"][1][".type"])
+ assert p["value"][1]["requirements"][1][".type"] == "gpus"
+ assert is_int(p["value"][1]["requirements"][1]["slots"])
+ assert p["value"][1]["requirements"][1]["slots"] == 4
+
+ assert is_dict(p["value"][2])
+ assert sorted(p["value"][2].keys()) == ["requirements"]
+ assert is_list(p["value"][2]["requirements"])
+ assert len(p["value"][2]["requirements"]) == 2
+ assert is_dict(p["value"][2]["requirements"][0])
+ assert sorted(p["value"][2]["requirements"][0].keys()) == \
+ [".type", "slots"]
+ assert is_string(p["value"][2]["requirements"][0][".type"])
+ assert p["value"][2]["requirements"][0][".type"] == "gpus"
+ assert is_int(p["value"][2]["requirements"][0]["slots"])
+ assert p["value"][2]["requirements"][0]["slots"] == 2
+ assert is_string(p["value"][2]["requirements"][1][".type"])
+ assert p["value"][2]["requirements"][1][".type"] == "threads"
+ assert is_int(p["value"][2]["requirements"][1]["slots"])
+ assert p["value"][2]["requirements"][1]["slots"] == 4
+
def check_workingdir_property(p):
assert is_dict(p)
assert sorted(p.keys()) == ["name", "value"]
@@ -90,10 +146,11 @@ def check_workingdir_property(p):
def check_properties(p):
assert is_list(p)
- assert len(p) == 3
- check_reqfiles_property(p[0])
- check_willfail_property(p[1])
- check_workingdir_property(p[2])
+ assert len(p) == 4
+ check_processes_property(p[0])
+ check_reqfiles_property(p[1])
+ check_willfail_property(p[2])
+ check_workingdir_property(p[3])
def check_tests(t):
assert is_list(t)