diff options
-rw-r--r-- | Source/CTest/cmCTestMultiProcessHandler.cxx | 26 | ||||
-rw-r--r-- | Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake | 1 | ||||
-rw-r--r-- | Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py | 65 |
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) |