cmake/Source/CTest/cmCTestResourceSpec.cxx

169 lines
4.7 KiB
C++
Raw Normal View History

2020-02-01 23:06:01 +01:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestResourceSpec.h"
2021-09-14 00:13:48 +02:00
#include <functional>
2020-02-01 23:06:01 +01:00
#include <map>
#include <string>
#include <utility>
#include <vector>
2021-09-14 00:13:48 +02:00
#include <cmext/string_view>
2020-08-30 11:54:41 +02:00
#include <cm3p/json/value.h>
2020-02-01 23:06:01 +01:00
#include "cmsys/RegularExpression.hxx"
2021-09-14 00:13:48 +02:00
#include "cmJSONHelpers.h"
namespace {
2023-07-02 19:51:09 +02:00
using JSONHelperBuilder = cmJSONHelperBuilder;
2021-09-14 00:13:48 +02:00
const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" };
const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" };
struct Version
{
int Major = 1;
int Minor = 0;
};
struct TopVersion
{
struct Version Version;
};
auto const VersionFieldHelper =
2023-07-02 19:51:09 +02:00
JSONHelperBuilder::Int(cmCTestResourceSpecErrors::INVALID_VERSION);
2021-09-14 00:13:48 +02:00
2022-08-04 22:12:04 +02:00
auto const VersionHelper = JSONHelperBuilder::Required<Version>(
2023-07-02 19:51:09 +02:00
cmCTestResourceSpecErrors::NO_VERSION,
JSONHelperBuilder::Object<Version>()
2022-08-04 22:12:04 +02:00
.Bind("major"_s, &Version::Major, VersionFieldHelper)
.Bind("minor"_s, &Version::Minor, VersionFieldHelper));
2021-09-14 00:13:48 +02:00
2023-07-02 19:51:09 +02:00
auto const RootVersionHelper = JSONHelperBuilder::Object<TopVersion>().Bind(
"version"_s, &TopVersion::Version, VersionHelper, false);
2021-09-14 00:13:48 +02:00
2023-07-02 19:51:09 +02:00
bool ResourceIdHelper(std::string& out, const Json::Value* value,
cmJSONState* state)
2021-09-14 00:13:48 +02:00
{
2023-07-02 19:51:09 +02:00
if (!JSONHelperBuilder::String(cmCTestResourceSpecErrors::INVALID_RESOURCE)(
out, value, state)) {
return false;
2021-09-14 00:13:48 +02:00
}
cmsys::RegularExpressionMatch match;
if (!IdRegex.find(out.c_str(), match)) {
2023-07-02 19:51:09 +02:00
cmCTestResourceSpecErrors::INVALID_RESOURCE(value, state);
return false;
2021-09-14 00:13:48 +02:00
}
2023-07-02 19:51:09 +02:00
return true;
2021-09-14 00:13:48 +02:00
}
auto const ResourceHelper =
2023-07-02 19:51:09 +02:00
JSONHelperBuilder::Object<cmCTestResourceSpec::Resource>()
2021-09-14 00:13:48 +02:00
.Bind("id"_s, &cmCTestResourceSpec::Resource::Id, ResourceIdHelper)
2023-07-02 19:51:09 +02:00
.Bind(
"slots"_s, &cmCTestResourceSpec::Resource::Capacity,
JSONHelperBuilder::UInt(cmCTestResourceSpecErrors::INVALID_RESOURCE, 1),
false);
2021-09-14 00:13:48 +02:00
auto const ResourceListHelper =
2022-08-04 22:12:04 +02:00
JSONHelperBuilder::Vector<cmCTestResourceSpec::Resource>(
2023-07-02 19:51:09 +02:00
cmCTestResourceSpecErrors::INVALID_RESOURCE_TYPE, ResourceHelper);
2021-09-14 00:13:48 +02:00
auto const ResourceMapHelper =
2022-08-04 22:12:04 +02:00
JSONHelperBuilder::MapFilter<std::vector<cmCTestResourceSpec::Resource>>(
2023-07-02 19:51:09 +02:00
cmCTestResourceSpecErrors::INVALID_SOCKET_SPEC, ResourceListHelper,
[](const std::string& key) -> bool {
2021-09-14 00:13:48 +02:00
cmsys::RegularExpressionMatch match;
return IdentifierRegex.find(key.c_str(), match);
});
2022-08-04 22:12:04 +02:00
auto const SocketSetHelper = JSONHelperBuilder::Vector<
2021-09-14 00:13:48 +02:00
std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>(
2023-07-02 19:51:09 +02:00
cmCTestResourceSpecErrors::INVALID_SOCKET_SPEC, ResourceMapHelper);
2021-09-14 00:13:48 +02:00
2023-07-02 19:51:09 +02:00
bool SocketHelper(cmCTestResourceSpec::Socket& out, const Json::Value* value,
cmJSONState* state)
2021-09-14 00:13:48 +02:00
{
std::vector<
std::map<std::string, std::vector<cmCTestResourceSpec::Resource>>>
sockets;
2023-07-02 19:51:09 +02:00
if (!SocketSetHelper(sockets, value, state)) {
return false;
2021-09-14 00:13:48 +02:00
}
if (sockets.size() > 1) {
2023-07-02 19:51:09 +02:00
cmCTestResourceSpecErrors::INVALID_SOCKET_SPEC(value, state);
return false;
2021-09-14 00:13:48 +02:00
}
if (sockets.empty()) {
out.Resources.clear();
} else {
out.Resources = std::move(sockets[0]);
}
2023-07-02 19:51:09 +02:00
return true;
2021-09-14 00:13:48 +02:00
}
auto const LocalRequiredHelper =
2022-08-04 22:12:04 +02:00
JSONHelperBuilder::Required<cmCTestResourceSpec::Socket>(
2023-07-02 19:51:09 +02:00
cmCTestResourceSpecErrors::INVALID_SOCKET_SPEC, SocketHelper);
2021-09-14 00:13:48 +02:00
2023-07-02 19:51:09 +02:00
auto const RootHelper = JSONHelperBuilder::Object<cmCTestResourceSpec>().Bind(
"local", &cmCTestResourceSpec::LocalSocket, LocalRequiredHelper, false);
2021-09-14 00:13:48 +02:00
}
2020-02-01 23:06:01 +01:00
2023-07-02 19:51:09 +02:00
bool cmCTestResourceSpec::ReadFromJSONFile(const std::string& filename)
2020-02-01 23:06:01 +01:00
{
Json::Value root;
2023-07-02 19:51:09 +02:00
this->parseState = cmJSONState(filename, &root);
if (!this->parseState.errors.empty()) {
return false;
2020-02-01 23:06:01 +01:00
}
2021-09-14 00:13:48 +02:00
TopVersion version;
2023-07-02 19:51:09 +02:00
bool result;
if ((result = RootVersionHelper(version, &root, &parseState)) != true) {
2021-09-14 00:13:48 +02:00
return result;
2020-02-01 23:06:01 +01:00
}
2021-09-14 00:13:48 +02:00
if (version.Version.Major != 1 || version.Version.Minor != 0) {
2023-07-02 19:51:09 +02:00
return false;
2020-02-01 23:06:01 +01:00
}
2023-07-02 19:51:09 +02:00
return RootHelper(*this, &root, &parseState);
2020-02-01 23:06:01 +01:00
}
bool cmCTestResourceSpec::operator==(const cmCTestResourceSpec& other) const
{
return this->LocalSocket == other.LocalSocket;
}
bool cmCTestResourceSpec::operator!=(const cmCTestResourceSpec& other) const
{
return !(*this == other);
}
bool cmCTestResourceSpec::Socket::operator==(
const cmCTestResourceSpec::Socket& other) const
{
return this->Resources == other.Resources;
}
bool cmCTestResourceSpec::Socket::operator!=(
const cmCTestResourceSpec::Socket& other) const
{
return !(*this == other);
}
bool cmCTestResourceSpec::Resource::operator==(
const cmCTestResourceSpec::Resource& other) const
{
return this->Id == other.Id && this->Capacity == other.Capacity;
}
bool cmCTestResourceSpec::Resource::operator!=(
const cmCTestResourceSpec::Resource& other) const
{
return !(*this == other);
}