blob: 3bc52da31d99912eb31b81ff621a2cb0250a2bdf [file] [log] [blame]
/**
* Copyright c 2020 IBM Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "temporary_file.hpp"
#include <stdio.h> // for popen(), pclose(), fgets()
#include <sys/stat.h> // for chmod()
#include <sys/wait.h> // for WEXITSTATUS
#include <nlohmann/json.hpp>
#include <cstdio>
#include <fstream>
#include <gtest/gtest.h>
#define EXPECT_FILE_VALID(configFile) expectFileValid(configFile)
#define EXPECT_FILE_INVALID(configFile, expectedErrorMessage, \
expectedOutputMessage) \
expectFileInvalid(configFile, expectedErrorMessage, expectedOutputMessage)
#define EXPECT_JSON_VALID(configFileJson) expectJsonValid(configFileJson)
#define EXPECT_JSON_INVALID(configFileJson, expectedErrorMessage, \
expectedOutputMessage) \
expectJsonInvalid(configFileJson, expectedErrorMessage, \
expectedOutputMessage)
using json = nlohmann::json;
using TemporaryFile = phosphor::power::util::TemporaryFile;
const json validConfigFile = R"(
{
"comments": [ "Config file for a FooBar one-chassis system" ],
"rules": [
{
"comments": [ "Sets output voltage for a PMBus regulator rail" ],
"id": "set_voltage_rule",
"actions": [
{
"pmbus_write_vout_command": {
"format": "linear"
}
}
]
},
{
"comments": [ "Reads sensors from a PMBus regulator rail" ],
"id": "read_sensors_rule",
"actions": [
{
"comments": [ "Read output voltage from READ_VOUT." ],
"pmbus_read_sensor": {
"type": "vout",
"command": "0x8B",
"format": "linear_16"
}
}
]
},
{
"comments": [ "Detects presence of regulators associated with CPU3" ],
"id": "detect_presence_rule",
"actions": [
{
"compare_presence": {
"fru": "system/chassis/motherboard/cpu3",
"value": true
}
}
]
},
{
"comments": [ "Detects and logs redundant phase faults" ],
"id": "detect_phase_faults_rule",
"actions": [
{
"if": {
"condition": {
"i2c_compare_bit": { "register": "0x02", "position": 3, "value": 1 }
},
"then": [
{ "log_phase_fault": { "type": "n" } }
]
}
}
]
}
],
"chassis": [
{
"comments": [ "Chassis number 1 containing CPUs and memory" ],
"number": 1,
"inventory_path": "system/chassis",
"devices": [
{
"comments": [ "IR35221 regulator producing the Vdd rail" ],
"id": "vdd_regulator",
"is_regulator": true,
"fru": "system/chassis/motherboard/regulator1",
"i2c_interface": {
"bus": 1,
"address": "0x70"
},
"rails": [
{
"comments": [ "Vdd rail" ],
"id": "vdd",
"configuration": {
"volts": 1.03,
"rule_id": "set_voltage_rule"
},
"sensor_monitoring": {
"rule_id": "read_sensors_rule"
}
}
]
}
]
}
]
}
)"_json;
std::string getValidationToolCommand(const std::string& configFileName)
{
std::string command =
"../phosphor-regulators/tools/validate-regulators-config.py -s \
../phosphor-regulators/schema/config_schema.json -c ";
command += configFileName;
return command;
}
int runToolForOutputWithCommand(std::string command,
std::string& standardOutput,
std::string& standardError)
{
// run the validation tool with the temporary file and return the output
// of the validation tool.
TemporaryFile tmpFile;
command += " 2> " + tmpFile.getPath().string();
// get the jsonschema print from validation tool.
char buffer[256];
std::string result;
// to get the stdout from the validation tool.
FILE* pipe = popen(command.c_str(), "r");
if (!pipe)
{
throw std::runtime_error("popen() failed!");
}
while (!std::feof(pipe))
{
if (fgets(buffer, sizeof buffer, pipe) != NULL)
{
result += buffer;
}
}
int returnValue = pclose(pipe);
// Check if pclose() failed
if (returnValue == -1)
{
// unable to close pipe. Print error and exit function.
throw std::runtime_error("pclose() failed!");
}
std::string firstLine = result.substr(0, result.find('\n'));
standardOutput = firstLine;
// Get command exit status from return value
int exitStatus = WEXITSTATUS(returnValue);
// Read the standardError from tmpFile.
std::ifstream input(tmpFile.getPath());
std::string line;
if (std::getline(input, line))
{
standardError = line;
}
return exitStatus;
}
int runToolForOutput(const std::string& configFileName, std::string& output,
std::string& error)
{
std::string command = getValidationToolCommand(configFileName);
return runToolForOutputWithCommand(command, output, error);
}
void expectFileValid(const std::string& configFileName)
{
std::string errorMessage;
std::string outputMessage;
EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 0);
EXPECT_EQ(errorMessage, "");
EXPECT_EQ(outputMessage, "");
}
void expectFileInvalid(const std::string& configFileName,
const std::string& expectedErrorMessage,
const std::string& expectedOutputMessage)
{
std::string errorMessage;
std::string outputMessage;
EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 1);
EXPECT_EQ(errorMessage, expectedErrorMessage);
if (expectedOutputMessage != "")
{
EXPECT_EQ(outputMessage, expectedOutputMessage);
}
}
void writeDataToFile(const json configFileJson, std::string fileName)
{
std::string jsonData = configFileJson.dump();
std::ofstream out(fileName);
out << jsonData;
out.close();
}
void expectJsonValid(const json configFileJson)
{
TemporaryFile tmpFile;
std::string fileName = tmpFile.getPath().string();
writeDataToFile(configFileJson, fileName);
EXPECT_FILE_VALID(fileName);
}
void expectJsonInvalid(const json configFileJson,
const std::string& expectedErrorMessage,
const std::string& expectedOutputMessage)
{
TemporaryFile tmpFile;
std::string fileName = tmpFile.getPath().string();
writeDataToFile(configFileJson, fileName);
EXPECT_FILE_INVALID(fileName, expectedErrorMessage, expectedOutputMessage);
}
void expectCommandLineSyntax(const std::string& expectedErrorMessage,
const std::string& expectedOutputMessage,
const std::string& command, int status)
{
std::string errorMessage;
std::string outputMessage;
EXPECT_EQ(runToolForOutputWithCommand(command, outputMessage, errorMessage),
status);
EXPECT_EQ(errorMessage, expectedErrorMessage);
EXPECT_EQ(outputMessage, expectedOutputMessage);
}
TEST(ValidateRegulatorsConfigTest, Action)
{
// Valid: Comments property not specified
{
json configFile = validConfigFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: Comments property specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][0]["comments"][0] =
"Set VOUT_COMMAND";
EXPECT_JSON_VALID(configFile);
}
// Valid: and action type specified
{
json configFile = validConfigFile;
json andAction =
R"(
{
"and": [
{ "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
{ "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
]
}
)"_json;
configFile["rules"][0]["actions"].push_back(andAction);
EXPECT_JSON_VALID(configFile);
}
// Valid: compare_presence action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
"system/chassis/motherboard/regulator2";
configFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
true;
EXPECT_JSON_VALID(configFile);
}
// Valid: compare_vpd action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
"system/chassis/motherboard/regulator2";
configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
EXPECT_JSON_VALID(configFile);
}
// Valid: i2c_capture_bytes action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
"0xA0";
configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] = 2;
EXPECT_JSON_VALID(configFile);
}
// Valid: i2c_compare_bit action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
"0xA0";
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 3;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
EXPECT_JSON_VALID(configFile);
}
// Valid: i2c_compare_byte action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
"0x82";
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
"0x40";
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
"0x7F";
EXPECT_JSON_VALID(configFile);
}
// Valid: i2c_compare_bytes action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
"0x82";
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = {
"0x02", "0x73"};
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = {
"0x7F", "0x7F"};
EXPECT_JSON_VALID(configFile);
}
// Valid: i2c_write_bit action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
"0xA0";
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 1;
EXPECT_JSON_VALID(configFile);
}
// Valid: i2c_write_byte action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
"0x82";
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
"0x40";
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0x7F";
EXPECT_JSON_VALID(configFile);
}
// Valid: i2c_write_bytes action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
"0x82";
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
"0x02", "0x73"};
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
"0x7F", "0x7F"};
EXPECT_JSON_VALID(configFile);
}
// Valid: if action type specified
{
json configFile = validConfigFile;
configFile["rules"][4]["actions"][0]["if"]["condition"]["run_rule"] =
"set_voltage_rule";
configFile["rules"][4]["actions"][0]["if"]["then"][0]["run_rule"] =
"read_sensors_rule";
configFile["rules"][4]["actions"][0]["if"]["else"][0]["run_rule"] =
"read_sensors_rule";
configFile["rules"][4]["id"] = "rule_if";
EXPECT_JSON_VALID(configFile);
}
// Valid: log_phase_fault action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = "n+1";
EXPECT_JSON_VALID(configFile);
}
// Valid: not action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]
["register"] = "0xA0";
configFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]
["value"] = "0xFF";
EXPECT_JSON_VALID(configFile);
}
// Valid: or action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]
["register"] = "0xA0";
configFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]
["value"] = "0x00";
configFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]
["register"] = "0xA1";
configFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]
["value"] = "0x00";
EXPECT_JSON_VALID(configFile);
}
// Valid: pmbus_read_sensor and pmbus_write_vout_command action type
// specified
{
EXPECT_JSON_VALID(validConfigFile);
}
// Valid: run_rule action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
EXPECT_JSON_VALID(configFile);
}
// Valid: set_device action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator";
EXPECT_JSON_VALID(configFile);
}
// Invalid: Wrong data type for comments (should be array of string)
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][0]["comments"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: Wrong data type for action type (such as "i2c_write_byte": true)
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'object'");
}
// Invalid: Empty comments array
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][0]["comments"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: Comments array has wrong element type (should be string)
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][0]["comments"][0] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: No action type specified
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["comments"][0] =
"Check if bit 3 is on";
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"{'comments': ['Check if bit 3 is on']} is not valid under any of the given schemas");
}
// Invalid: Multiple action types specified (such as both 'compare_presence'
// and 'pmbus_write_vout_command')
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][0]["compare_presence"]["value"] =
true;
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"{'compare_presence': {'value': True}, 'pmbus_write_vout_command': "
"{'format': 'linear'}} is valid under each of {'required': "
"['pmbus_write_vout_command']}, {'required': "
"['compare_presence']}");
}
// Invalid: Unexpected property specified (like 'foo')
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["foo"] = "foo";
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"Additional properties are not allowed ('foo' was unexpected)");
}
}
TEST(ValidateRegulatorsConfigTest, And)
{
// Valid.
{
json configFile = validConfigFile;
json andAction =
R"(
{
"and": [
{ "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
{ "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
]
}
)"_json;
configFile["rules"][0]["actions"].push_back(andAction);
EXPECT_JSON_VALID(configFile);
}
// Invalid: actions property value is an empty array.
{
json configFile = validConfigFile;
json andAction =
R"(
{
"and": []
}
)"_json;
configFile["rules"][0]["actions"].push_back(andAction);
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: actions property has incorrect value data type.
{
json configFile = validConfigFile;
json andAction =
R"(
{
"and": true
}
)"_json;
configFile["rules"][0]["actions"].push_back(andAction);
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: actions property value contains wrong element type
{
json configFile = validConfigFile;
json andAction =
R"(
{
"and": ["foo"]
}
)"_json;
configFile["rules"][0]["actions"].push_back(andAction);
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'foo' is not of type 'object'");
}
}
TEST(ValidateRegulatorsConfigTest, Chassis)
{
// Valid: test chassis.
{
json configFile = validConfigFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test chassis with only required properties.
{
json configFile = validConfigFile;
configFile["chassis"][0].erase("comments");
configFile["chassis"][0].erase("devices");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test chassis with no number.
{
json configFile = validConfigFile;
configFile["chassis"][0].erase("number");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'number' is a required property");
}
// Invalid: test chassis with no inventory_path.
{
json configFile = validConfigFile;
configFile["chassis"][0].erase("inventory_path");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'inventory_path' is a required property");
}
// Invalid: test chassis with property comments wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["comments"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test chassis with property number wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["number"] = 1.3;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1.3 is not of type 'integer'");
}
// Invalid: test chassis with property inventory_path wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["inventory_path"] = 2;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"2 is not of type 'string'");
}
// Invalid: test chassis with property devices wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test chassis with property comments empty array.
{
json configFile = validConfigFile;
configFile["chassis"][0]["comments"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test chassis with property devices empty array.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test chassis with property number less than 1.
{
json configFile = validConfigFile;
configFile["chassis"][0]["number"] = 0;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"0 is less than the minimum of 1");
}
// Invalid: test chassis with property inventory_path empty string.
{
json configFile = validConfigFile;
configFile["chassis"][0]["inventory_path"] = "";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'' is too short");
}
}
TEST(ValidateRegulatorsConfigTest, ComparePresence)
{
json comparePresenceFile = validConfigFile;
comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
"system/chassis/motherboard/regulator2";
comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
true;
// Valid.
{
json configFile = comparePresenceFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: no FRU property.
{
json configFile = comparePresenceFile;
configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'fru' is a required property");
}
// Invalid: FRU property length is string less than 1.
{
json configFile = comparePresenceFile;
configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = "";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'' is too short");
}
// Invalid: no value property.
{
json configFile = comparePresenceFile;
configFile["rules"][0]["actions"][1]["compare_presence"].erase("value");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'value' is a required property");
}
// Invalid: value property type is not boolean.
{
json configFile = comparePresenceFile;
configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'1' is not of type 'boolean'");
}
// Invalid: FRU property type is not string.
{
json configFile = comparePresenceFile;
configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
}
TEST(ValidateRegulatorsConfigTest, CompareVpd)
{
json compareVpdFile = validConfigFile;
compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
"system/chassis/motherboard/regulator2";
compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
// Valid: value property: not empty.
{
json configFile = compareVpdFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: value property: empty.
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "";
EXPECT_JSON_VALID(configFile);
}
// Valid: byte_values property: not empty.
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] = {
"0x01", "0x02"};
EXPECT_JSON_VALID(configFile);
}
// Valid: byte_values property: empty.
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] =
json::array();
EXPECT_JSON_VALID(configFile);
}
// Invalid: no FRU property.
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'fru' is a required property");
}
// Invalid: no keyword property.
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'keyword' is a required property");
}
// Invalid: no value property.
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"{'fru': 'system/chassis/motherboard/regulator2', 'keyword': 'CCIN'} is not valid under any of the given schemas");
}
// Invalid: property FRU wrong type.
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: property FRU is string less than 1.
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = "";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'' is too short");
}
// Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
// "PartNumber", "HW"
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
"Number";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'Number' is not one of ['CCIN', "
"'Manufacturer', 'Model', 'PartNumber', 'HW']");
}
// Invalid: property value wrong type.
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: property byte_values has wrong type
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] =
"0x50";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x50' is not of type 'array'");
}
// Invalid: properties byte_values and value both exist
{
json configFile = compareVpdFile;
configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] = {
"0x01", "0x02"};
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"{'byte_values': ['0x01', '0x02'], 'fru': "
"'system/chassis/motherboard/regulator2', 'keyword': 'CCIN', "
"'value': '2D35'} is valid under each of {'required': "
"['byte_values']}, {'required': ['value']}");
}
}
TEST(ValidateRegulatorsConfigTest, ConfigFile)
{
// Valid: Only required properties specified
{
json configFile;
configFile["chassis"][0]["number"] = 1;
configFile["chassis"][0]["inventory_path"] = "system/chassis";
EXPECT_JSON_VALID(configFile);
}
// Valid: All properties specified
{
json configFile = validConfigFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: Required chassis property not specified
{
json configFile = validConfigFile;
configFile.erase("chassis");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'chassis' is a required property");
}
// Invalid: Wrong data type for comments
{
json configFile = validConfigFile;
configFile["comments"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: Wrong data type for rules
{
json configFile = validConfigFile;
configFile["rules"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: Wrong data type for chassis
{
json configFile = validConfigFile;
configFile["chassis"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: Empty comments array;
{
json configFile = validConfigFile;
configFile["comments"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: Empty rules array
{
json configFile = validConfigFile;
configFile["rules"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: Empty chassis array
{
json configFile = validConfigFile;
configFile["chassis"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: Comments array has wrong element type (should be string)
{
json configFile = validConfigFile;
configFile["comments"][0] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: Rules array has wrong element type (should be rule)
{
json configFile = validConfigFile;
configFile["rules"][0] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'object'");
}
// Invalid: Chassis array has wrong element type (should be chassis)
{
json configFile = validConfigFile;
configFile["chassis"][0] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'object'");
}
// Invalid: Unexpected property specified
{
json configFile = validConfigFile;
configFile["foo"] = json::array();
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"Additional properties are not allowed ('foo' was unexpected)");
}
}
TEST(ValidateRegulatorsConfigTest, Configuration)
{
json configurationFile = validConfigFile;
configurationFile["chassis"][0]["devices"][0]["configuration"]["comments"]
[0] = "Set rail to 1.25V using standard rule";
configurationFile["chassis"][0]["devices"][0]["configuration"]["volts"] =
1.25;
configurationFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
"set_voltage_rule";
// Valid: test configuration with property rule_id and with no actions.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"]["comments"][1] =
"test multiple array elements in comments.";
EXPECT_JSON_VALID(configFile);
}
// Valid: test configuration with property actions and with no rule_id.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"].erase(
"rule_id");
configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
["compare_presence"]["fru"] =
"system/chassis/motherboard/cpu3";
configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
["compare_presence"]["value"] = true;
EXPECT_JSON_VALID(configFile);
}
// Valid: comments not specified (optional property).
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"].erase(
"comments");
EXPECT_JSON_VALID(configFile);
}
// Valid: volts not specified (optional property).
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"].erase("volts");
EXPECT_JSON_VALID(configFile);
}
// Valid: configuration is property of a rail (vs. a device).
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
["comments"][0] = "Set rail to 1.25V using standard rule";
configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
["volts"] = 1.25;
configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
["rule_id"] = "set_voltage_rule";
EXPECT_JSON_VALID(configFile);
}
// Invalid: comments property has wrong data type (not an array).
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"]["comments"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'array'");
}
// Invalid: test configuration with both actions and rule_id properties.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
["compare_presence"]["fru"] =
"system/chassis/motherboard/cpu3";
configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
["compare_presence"]["value"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
}
// Invalid: test configuration with no rule_id and actions.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"].erase(
"rule_id");
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"{'comments': ['Set rail to 1.25V using standard rule'], 'volts': 1.25} is not valid under any of the given schemas");
}
// Invalid: test configuration with property volts wrong type.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"]["volts"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'number'");
}
// Invalid: test configuration with property rule_id wrong type.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test configuration with property actions wrong type.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"].erase(
"rule_id");
configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test configuration with property comments empty array.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"]["comments"] =
json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test configuration with property rule_id wrong format.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
"id!";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id!' does not match '^[A-Za-z0-9_]+$'");
}
// Invalid: test configuration with property actions empty array.
{
json configFile = configurationFile;
configFile["chassis"][0]["devices"][0]["configuration"].erase(
"rule_id");
configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
}
TEST(ValidateRegulatorsConfigTest, Device)
{
// Valid: test devices.
{
json configFile = validConfigFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test devices with required properties.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0].erase("comments");
configFile["chassis"][0]["devices"][0].erase("presence_detection");
configFile["chassis"][0]["devices"][0].erase("configuration");
configFile["chassis"][0]["devices"][0].erase("phase_fault_detection");
configFile["chassis"][0]["devices"][0].erase("rails");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test devices with no id.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0].erase("id");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id' is a required property");
}
// Invalid: test devices with no is_regulator.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0].erase("is_regulator");
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"{'comments': ['IR35221 regulator producing the Vdd rail'], 'fru': 'system/chassis/motherboard/regulator1', 'i2c_interface': {'address': '0x70', 'bus': 1}, 'id': 'vdd_regulator', 'rails': [{'comments': ['Vdd rail'], 'configuration': {'rule_id': 'set_voltage_rule', 'volts': 1.03}, 'id': 'vdd', 'sensor_monitoring': {'rule_id': 'read_sensors_rule'}}]} should not be valid under {'anyOf': [{'required': ['phase_fault_detection']}, {'required': ['rails']}]}");
}
// Invalid: test devices with no fru.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0].erase("fru");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'fru' is a required property");
}
// Invalid: test devices with no i2c_interface.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0].erase("i2c_interface");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'i2c_interface' is a required property");
}
// Invalid: is_regulator=false: phase_fault_detection specified
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["is_regulator"] = false;
configFile["chassis"][0]["devices"][0].erase("rails");
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["rule_id"] = "detect_phase_faults_rule";
EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
}
// Invalid: is_regulator=false: rails specified
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["is_regulator"] = false;
EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
}
// Invalid: is_regulator=false: phase_fault_detection and rails specified
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["is_regulator"] = false;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["rule_id"] = "detect_phase_faults_rule";
EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
}
// Invalid: test devices with property comments wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["comments"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test devices with property id wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["id"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test devices with property is_regulator wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["is_regulator"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'boolean'");
}
// Invalid: test devices with property fru wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["fru"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test devices with property i2c_interface wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["i2c_interface"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'object'");
}
// Invalid: test devices with property presence_detection wrong
// type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["presence_detection"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'object'");
}
// Invalid: test devices with property configuration wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["configuration"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'object'");
}
// Invalid: test devices with property phase_fault_detection wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'object'");
}
// Invalid: test devices with property rails wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test devices with property comments empty array.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["comments"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test devices with property fru length less than 1.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["fru"] = "";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'' is too short");
}
// Invalid: test devices with property id wrong format.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["id"] = "id#";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id#' does not match '^[A-Za-z0-9_]+$'");
}
// Invalid: test devices with property rails empty array.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
}
TEST(ValidateRegulatorsConfigTest, I2CCaptureBytes)
{
json initialFile = validConfigFile;
initialFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
"0xA0";
initialFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] = 2;
// Valid: All required properties
{
json configFile = initialFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: register not specified
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["i2c_capture_bytes"].erase(
"register");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'register' is a required property");
}
// Invalid: count not specified
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["i2c_capture_bytes"].erase(
"count");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'count' is a required property");
}
// Invalid: invalid property specified
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["foo"] = true;
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"Additional properties are not allowed ('foo' was unexpected)");
}
// Invalid: register has wrong data type
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: register has wrong format
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
"0xA00";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: count has wrong data type
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] =
3.1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"3.1 is not of type 'integer'");
}
// Invalid: count < 1
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] = 0;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"0 is less than the minimum of 1");
}
}
TEST(ValidateRegulatorsConfigTest, I2CCompareBit)
{
json i2cCompareBitFile = validConfigFile;
i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
"0xA0";
i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
3;
i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
// Valid: test rule actions i2c_compare_bit.
{
json configFile = i2cCompareBitFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: test i2c_compare_bit with no register.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
"register");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'register' is a required property");
}
// Invalid: test i2c_compare_bit with no position.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
"position");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'position' is a required property");
}
// Invalid: test i2c_compare_bit with no value.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'value' is a required property");
}
// Invalid: test i2c_compare_bit with register wrong type.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_compare_bit with register wrong format.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
"0xA00";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bit with position wrong type.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
3.1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"3.1 is not of type 'integer'");
}
// Invalid: test i2c_compare_bit with position greater than 7.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"8 is greater than the maximum of 7");
}
// Invalid: test i2c_compare_bit with position less than 0.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
-1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"-1 is less than the minimum of 0");
}
// Invalid: test i2c_compare_bit with value wrong type.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'1' is not of type 'integer'");
}
// Invalid: test i2c_compare_bit with value greater than 1.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"2 is greater than the maximum of 1");
}
// Invalid: test i2c_compare_bit with value less than 0.
{
json configFile = i2cCompareBitFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"-1 is less than the minimum of 0");
}
}
TEST(ValidateRegulatorsConfigTest, I2CCompareByte)
{
json i2cCompareByteFile = validConfigFile;
i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]
["register"] = "0x82";
i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
"0x40";
i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
"0x7F";
// Valid: test i2c_compare_byte with all properties.
{
json configFile = i2cCompareByteFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test i2c_compare_byte with all required properties.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test i2c_compare_byte with no register.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase(
"register");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'register' is a required property");
}
// Invalid: test i2c_compare_byte with no value.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'value' is a required property");
}
// Invalid: test i2c_compare_byte with property register wrong type.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_compare_byte with property value wrong type.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_compare_byte with property mask wrong type.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_compare_byte with property register more than 2 hex
// digits.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property value more than 2 hex
// digits.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property mask more than 2 hex digits.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property register less than 2 hex
// digits.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property value less than 2 hex
// digits.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property mask less than 2 hex digits.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property register no leading prefix.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
"82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property value no leading prefix.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
"82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property mask no leading prefix.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property register invalid hex digit.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property value invalid hex digit.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_byte with property mask invalid hex digit.
{
json configFile = i2cCompareByteFile;
configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
}
TEST(ValidateRegulatorsConfigTest, I2CCompareBytes)
{
json i2cCompareBytesFile = validConfigFile;
i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
["register"] = "0x82";
i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
["values"] = {"0x02", "0x73"};
i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
["masks"] = {"0x7F", "0x7F"};
// Valid: test i2c_compare_bytes.
{
json configFile = i2cCompareBytesFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test i2c_compare_bytes with all required properties.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
"masks");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test i2c_compare_bytes with no register.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
"register");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'register' is a required property");
}
// Invalid: test i2c_compare_bytes with no values.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
"values");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'values' is a required property");
}
// Invalid: test i2c_compare_bytes with property values as empty array.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] =
json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test i2c_compare_bytes with property masks as empty array.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] =
json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test i2c_compare_bytes with property register wrong type.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_compare_bytes with property values wrong type.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'array'");
}
// Invalid: test i2c_compare_bytes with property masks wrong type.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'array'");
}
// Invalid: test i2c_compare_bytes with property register more than 2 hex
// digits.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property values more than 2 hex
// digits.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property masks more than 2 hex
// digits.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property register less than 2 hex
// digits.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property values less than 2 hex
// digits.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property masks less than 2 hex
// digits.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property register no leading prefix.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
"82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property values no leading prefix.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
"82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property masks no leading prefix.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
"82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property register invalid hex digit.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property values invalid hex digit.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_compare_bytes with property masks invalid hex digit.
{
json configFile = i2cCompareBytesFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
}
TEST(ValidateRegulatorsConfigTest, I2CInterface)
{
// Valid: test i2c_interface.
{
json configFile = validConfigFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: testi2c_interface with no bus.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["i2c_interface"].erase("bus");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'bus' is a required property");
}
// Invalid: test i2c_interface with no address.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["i2c_interface"].erase(
"address");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'address' is a required property");
}
// Invalid: test i2c_interface with property bus wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'integer'");
}
// Invalid: test i2c_interface with property address wrong
// type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test i2c_interface with property bus less than
// 0.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = -1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"-1 is less than the minimum of 0");
}
// Invalid: test i2c_interface with property address wrong
// format.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
"0x700";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x700' does not match '^0x[0-9A-Fa-f]{2}$'");
}
}
TEST(ValidateRegulatorsConfigTest, I2CWriteBit)
{
json i2cWriteBitFile = validConfigFile;
i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
"0xA0";
i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3;
i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 1;
// Valid: test rule actions i2c_write_bit.
{
json configFile = i2cWriteBitFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: test i2c_write_bit with no register.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("register");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'register' is a required property");
}
// Invalid: test i2c_write_bit with no position.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("position");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'position' is a required property");
}
// Invalid: test i2c_write_bit with no value.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("value");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'value' is a required property");
}
// Invalid: test i2c_write_bit with register wrong type.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_write_bit with register wrong format.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
"0xA00";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bit with position wrong type.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3.1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"3.1 is not of type 'integer'");
}
// Invalid: test i2c_write_bit with position greater than 7.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 8;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"8 is greater than the maximum of 7");
}
// Invalid: test i2c_write_bit with position less than 0.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = -1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"-1 is less than the minimum of 0");
}
// Invalid: test i2c_write_bit with value wrong type.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = "1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'1' is not of type 'integer'");
}
// Invalid: test i2c_write_bit with value greater than 1.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 2;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"2 is greater than the maximum of 1");
}
// Invalid: test i2c_write_bit with value less than 0.
{
json configFile = i2cWriteBitFile;
configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = -1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"-1 is less than the minimum of 0");
}
}
TEST(ValidateRegulatorsConfigTest, I2CWriteByte)
{
json i2cWriteByteFile = validConfigFile;
i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
"0x82";
i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
"0x40";
i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
"0x7F";
// Valid: test i2c_write_byte with all properties.
{
json configFile = i2cWriteByteFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test i2c_write_byte with all required properties.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("mask");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test i2c_write_byte with no register.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase(
"register");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'register' is a required property");
}
// Invalid: test i2c_write_byte with no value.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("value");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'value' is a required property");
}
// Invalid: test i2c_write_byte with property register wrong type.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_write_byte with property value wrong type.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_write_byte with property mask wrong type.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_write_byte with property register more than 2 hex
// digits.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property value more than 2 hex
// digits.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property mask more than 2 hex digits.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property register less than 2 hex
// digits.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property value less than 2 hex
// digits.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property mask less than 2 hex digits.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property register no leading prefix.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
"82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property value no leading prefix.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property mask no leading prefix.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property register invalid hex digit.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property value invalid hex digit.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_byte with property mask invalid hex digit.
{
json configFile = i2cWriteByteFile;
configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
}
TEST(ValidateRegulatorsConfigTest, I2CWriteBytes)
{
json i2cWriteBytesFile = validConfigFile;
i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
"0x82";
i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
"0x02", "0x73"};
i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
"0x7F", "0x7F"};
// Valid: test i2c_write_bytes.
{
json configFile = i2cWriteBytesFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test i2c_write_bytes with all required properties.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("masks");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test i2c_write_bytes with no register.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase(
"register");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'register' is a required property");
}
// Invalid: test i2c_write_bytes with no values.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("values");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'values' is a required property");
}
// Invalid: test i2c_write_bytes with property values as empty array.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] =
json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test i2c_write_bytes with property masks as empty array.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] =
json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test i2c_write_bytes with property register wrong type.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// Invalid: test i2c_write_bytes with property values wrong type.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'array'");
}
// Invalid: test i2c_write_bytes with property masks wrong type.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'array'");
}
// Invalid: test i2c_write_bytes with property register more than 2 hex
// digits.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property values more than 2 hex
// digits.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property masks more than 2 hex
// digits.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
"0x820";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property register less than 2 hex
// digits.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property values less than 2 hex
// digits.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property masks less than 2 hex
// digits.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
"0x8";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property register no leading prefix.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
"82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property values no leading prefix.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
"82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property masks no leading prefix.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
"82";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'82' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property register invalid hex digit.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property values invalid hex digit.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
// Invalid: test i2c_write_bytes with property masks invalid hex digit.
{
json configFile = i2cWriteBytesFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
"0xG1";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
}
}
TEST(ValidateRegulatorsConfigTest, If)
{
json ifFile = validConfigFile;
ifFile["rules"][4]["actions"][0]["if"]["condition"]["run_rule"] =
"set_voltage_rule";
ifFile["rules"][4]["actions"][0]["if"]["then"][0]["run_rule"] =
"read_sensors_rule";
ifFile["rules"][4]["actions"][0]["if"]["else"][0]["run_rule"] =
"read_sensors_rule";
ifFile["rules"][4]["id"] = "rule_if";
// Valid: test if.
{
json configFile = ifFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test if with required properties.
{
json configFile = ifFile;
configFile["rules"][4]["actions"][0]["if"].erase("else");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test if with no property condition.
{
json configFile = ifFile;
configFile["rules"][4]["actions"][0]["if"].erase("condition");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'condition' is a required property");
}
// Invalid: test if with no property then.
{
json configFile = ifFile;
configFile["rules"][4]["actions"][0]["if"].erase("then");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'then' is a required property");
}
// Invalid: test if with property then empty array.
{
json configFile = ifFile;
configFile["rules"][4]["actions"][0]["if"]["then"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test if with property else empty array.
{
json configFile = ifFile;
configFile["rules"][4]["actions"][0]["if"]["else"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test if with property condition wrong type.
{
json configFile = ifFile;
configFile["rules"][4]["actions"][0]["if"]["condition"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'object'");
}
// Invalid: test if with property then wrong type.
{
json configFile = ifFile;
configFile["rules"][4]["actions"][0]["if"]["then"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'array'");
}
// Invalid: test if with property else wrong type.
{
json configFile = ifFile;
configFile["rules"][4]["actions"][0]["if"]["else"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'array'");
}
}
TEST(ValidateRegulatorsConfigTest, LogPhaseFault)
{
json initialFile = validConfigFile;
initialFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = "n";
// Valid: All required properties
{
json configFile = initialFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: type not specified
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["log_phase_fault"].erase("type");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'type' is a required property");
}
// Invalid: invalid property specified
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["log_phase_fault"]["foo"] = true;
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"Additional properties are not allowed ('foo' was unexpected)");
}
// Invalid: type has wrong data type
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: type has invalid value
{
json configFile = initialFile;
configFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = "n+2";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'n+2' is not one of ['n+1', 'n']");
}
}
TEST(ValidateRegulatorsConfigTest, Not)
{
json notFile = validConfigFile;
notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] =
"0xA0";
notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] =
"0xFF";
// Valid: test not.
{
json configFile = notFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: test not with wrong type.
{
json configFile = notFile;
configFile["rules"][0]["actions"][1]["not"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'object'");
}
}
TEST(ValidateRegulatorsConfigTest, Or)
{
json orFile = validConfigFile;
orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] =
"0xA0";
orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] =
"0x00";
orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] =
"0xA1";
orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] =
"0x00";
// Valid: test or.
{
json configFile = orFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: test or with empty array.
{
json configFile = orFile;
configFile["rules"][0]["actions"][1]["or"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test or with wrong type.
{
json configFile = orFile;
configFile["rules"][0]["actions"][1]["or"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'array'");
}
}
TEST(ValidateRegulatorsConfigTest, PhaseFaultDetection)
{
json initialFile = validConfigFile;
initialFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["rule_id"] = "detect_phase_faults_rule";
// Valid: comments specified
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["comments"][0] = "Detect phase faults";
EXPECT_JSON_VALID(configFile);
}
// Valid: device_id specified
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["device_id"] = "vdd_regulator";
EXPECT_JSON_VALID(configFile);
}
// Valid: rule_id specified
{
json configFile = initialFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: actions specified
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
"rule_id");
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["actions"][0]["run_rule"] = "detect_phase_faults_rule";
EXPECT_JSON_VALID(configFile);
}
// Invalid: rule_id and actions specified
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["actions"][0]["run_rule"] = "detect_phase_faults_rule";
EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
}
// Invalid: neither rule_id nor actions specified
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
"rule_id");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"{} is not valid under any of the given schemas");
}
// Invalid: comments has wrong data type
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["comments"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: device_id has wrong data type
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["device_id"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: rule_id has wrong data type
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["rule_id"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: actions has wrong data type
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
"rule_id");
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["actions"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: device_id has invalid format
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["device_id"] = "id@";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id@' does not match '^[A-Za-z0-9_]+$'");
}
// Invalid: rule_id has invalid format
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["rule_id"] = "id@";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id@' does not match '^[A-Za-z0-9_]+$'");
}
// Invalid: comments array is empty
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["comments"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: actions array is empty
{
json configFile = initialFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
"rule_id");
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["actions"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
}
TEST(ValidateRegulatorsConfigTest, PmbusReadSensor)
{
json pmbusReadSensorFile = validConfigFile;
pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
"vout";
pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
["command"] = "0x8B";
pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
["format"] = "linear_16";
pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
["exponent"] = -8;
// Valid: test pmbus_read_sensor.
{
json configFile = pmbusReadSensorFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test pmbus_read_sensor with required properties.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
"exponent");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test pmbus_read_sensor with no type.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'type' is a required property");
}
// Invalid: test pmbus_read_sensor with no command.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
"command");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'command' is a required property");
}
// Invalid: test pmbus_read_sensor with no format.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
"format");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'format' is a required property");
}
// Invalid: test pmbus_read_sensor with property type wrong type.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test pmbus_read_sensor with property command wrong type.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test pmbus_read_sensor with property format wrong type.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test pmbus_read_sensor with property exponent wrong type.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] =
true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'integer'");
}
// Invalid: test pmbus_read_sensor with property type wrong format.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
"foo";
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"'foo' is not one of ['iout', 'iout_peak', 'iout_valley', "
"'pout', 'temperature', 'temperature_peak', 'vout', "
"'vout_peak', 'vout_valley']");
}
// Invalid: test pmbus_read_sensor with property command wrong format.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
"0x8B0";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'0x8B0' does not match '^0x[0-9a-fA-F]{2}$'");
}
// Invalid: test pmbus_read_sensor with property format wrong format.
{
json configFile = pmbusReadSensorFile;
configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
"foo";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'foo' is not one of ['linear_11', 'linear_16']");
}
}
TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand)
{
json pmbusWriteVoutCommandFile = validConfigFile;
pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
["pmbus_write_vout_command"]["volts"] = 1.03;
pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
["pmbus_write_vout_command"]["format"] = "linear";
pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
["pmbus_write_vout_command"]["exponent"] = -8;
pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
["pmbus_write_vout_command"]["is_verified"] = true;
// Valid: test pmbus_write_vout_command.
{
json configFile = pmbusWriteVoutCommandFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test pmbus_write_vout_command with required properties.
{
json configFile = pmbusWriteVoutCommandFile;
configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
"volts");
configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
"exponent");
configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
"is_verified");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test pmbus_write_vout_command with no format.
{
json configFile = pmbusWriteVoutCommandFile;
configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
"format");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'format' is a required property");
}
// Invalid: test pmbus_write_vout_command with property volts wrong type.
{
json configFile = pmbusWriteVoutCommandFile;
configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
["volts"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'number'");
}
// Invalid: test pmbus_write_vout_command with property format wrong type.
{
json configFile = pmbusWriteVoutCommandFile;
configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
["format"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test pmbus_write_vout_command with property exponent wrong type.
{
json configFile = pmbusWriteVoutCommandFile;
configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
["exponent"] = 1.3;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1.3 is not of type 'integer'");
}
// Invalid: test pmbus_write_vout_command with property is_verified wrong
// type.
{
json configFile = pmbusWriteVoutCommandFile;
configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
["is_verified"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'boolean'");
}
// Invalid: test pmbus_write_vout_command with property format wrong format.
{
json configFile = pmbusWriteVoutCommandFile;
configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
["format"] = "foo";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'foo' is not one of ['linear']");
}
}
TEST(ValidateRegulatorsConfigTest, PresenceDetection)
{
json presenceDetectionFile = validConfigFile;
presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
["comments"][0] =
"Regulator is only present if CPU3 is present";
presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
["rule_id"] = "detect_presence_rule";
// Valid: test presence_detection with only property rule_id.
{
json configFile = presenceDetectionFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test presence_detection with only property actions.
{
json configFile = presenceDetectionFile;
configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
"rule_id");
configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
[0]["compare_presence"]["fru"] =
"system/chassis/motherboard/cpu3";
configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
[0]["compare_presence"]["value"] = true;
configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
"comments");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test presence_detection with both property rule_id and actions.
{
json configFile = presenceDetectionFile;
configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
[0]["compare_presence"]["fru"] =
"system/chassis/motherboard/cpu3";
configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
[0]["compare_presence"]["value"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
}
// Invalid: test presence_detection with no rule_id and actions.
{
json configFile = presenceDetectionFile;
configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
"rule_id");
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"{'comments': ['Regulator is only present if CPU3 is present']} is not valid under any of the given schemas");
}
// Invalid: test presence_detection with property comments wrong type.
{
json configFile = presenceDetectionFile;
configFile["chassis"][0]["devices"][0]["presence_detection"]
["comments"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test presence_detection with property rule_id wrong type.
{
json configFile = presenceDetectionFile;
configFile["chassis"][0]["devices"][0]["presence_detection"]
["rule_id"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test presence_detection with property actions wrong type.
{
json configFile = presenceDetectionFile;
configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
"rule_id");
configFile["chassis"][0]["devices"][0]["presence_detection"]
["actions"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test presence_detection with property rule_id wrong format.
{
json configFile = presenceDetectionFile;
configFile["chassis"][0]["devices"][0]["presence_detection"]
["rule_id"] = "id@";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id@' does not match '^[A-Za-z0-9_]+$'");
}
// Invalid: test presence_detection with property comments empty array.
{
json configFile = presenceDetectionFile;
configFile["chassis"][0]["devices"][0]["presence_detection"]
["comments"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test presence_detection with property actions empty array.
{
json configFile = presenceDetectionFile;
configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
"rule_id");
configFile["chassis"][0]["devices"][0]["presence_detection"]
["actions"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
}
TEST(ValidateRegulatorsConfigTest, Rail)
{
// Valid: test rail.
{
json configFile = validConfigFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test rail with required properties.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0].erase("comments");
configFile["chassis"][0]["devices"][0]["rails"][0].erase(
"configuration");
configFile["chassis"][0]["devices"][0]["rails"][0].erase(
"sensor_monitoring");
EXPECT_JSON_VALID(configFile);
}
// Invalid: test rail with no id.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0].erase("id");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id' is a required property");
}
// Invalid: test rail with comments wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test rail with id wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test rail with configuration wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] =
true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'object'");
}
// Invalid: test rail with sensor_monitoring wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]
["sensor_monitoring"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'object'");
}
// Invalid: test rail with comments empty array.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] =
json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test rail with id wrong format.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = "id~";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id~' does not match '^[A-Za-z0-9_]+$'");
}
}
TEST(ValidateRegulatorsConfigTest, Rule)
{
// valid test comments property, id property,
// action property specified.
{
json configFile = validConfigFile;
EXPECT_JSON_VALID(configFile);
}
// valid test rule with no comments
{
json configFile = validConfigFile;
configFile["rules"][0].erase("comments");
EXPECT_JSON_VALID(configFile);
}
// invalid test comments property has invalid value type
{
json configFile = validConfigFile;
configFile["rules"][0]["comments"] = {1};
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'string'");
}
// invalid test rule with no ID
{
json configFile = validConfigFile;
configFile["rules"][0].erase("id");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id' is a required property");
}
// invalid test id property has invalid value type (not string)
{
json configFile = validConfigFile;
configFile["rules"][0]["id"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// invalid test id property has invalid value
{
json configFile = validConfigFile;
configFile["rules"][0]["id"] = "foo%";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'foo%' does not match '^[A-Za-z0-9_]+$'");
}
// invalid test rule with no actions property
{
json configFile = validConfigFile;
configFile["rules"][0].erase("actions");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'actions' is a required property");
}
// valid test rule with multiple actions
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
EXPECT_JSON_VALID(configFile);
}
// invalid test actions property has invalid value type (not an array)
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"] = 1;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"1 is not of type 'array'");
}
// invalid test actions property has invalid value of action
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][0] = "foo";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'foo' is not of type 'object'");
}
// invalid test actions property has empty array
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
}
TEST(ValidateRegulatorsConfigTest, RunRule)
{
json runRuleFile = validConfigFile;
runRuleFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
// Valid: test run_rule.
{
json configFile = runRuleFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: test run_rule wrong type.
{
json configFile = runRuleFile;
configFile["rules"][0]["actions"][1]["run_rule"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test run_rule wrong format.
{
json configFile = runRuleFile;
configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%";
EXPECT_JSON_INVALID(
configFile, "Validation failed.",
"'set_voltage_rule%' does not match '^[A-Za-z0-9_]+$'");
}
}
TEST(ValidateRegulatorsConfigTest, SensorMonitoring)
{
// Valid: test rails sensor_monitoring with only property rule id.
{
json configFile = validConfigFile;
EXPECT_JSON_VALID(configFile);
}
// Valid: test rails sensor_monitoring with only property actions.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
.erase("rule_id");
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["actions"][0]["compare_presence"]["fru"] =
"system/chassis/motherboard/cpu3";
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["actions"][0]["compare_presence"]["value"] = true;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["comments"][0] = "comments";
EXPECT_JSON_VALID(configFile);
}
// Invalid: test rails sensor_monitoring with both property rule_id and
// actions.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["actions"][0]["compare_presence"]["fru"] =
"system/chassis/motherboard/cpu3";
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["actions"][0]["compare_presence"]["value"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
}
// Invalid: test rails sensor_monitoring with no rule_id and actions.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
.erase("rule_id");
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"{} is not valid under any of the given schemas");
}
// Invalid: test rails sensor_monitoring with property comments wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["comments"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test rails sensor_monitoring with property rule_id wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["rule_id"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test rails sensor_monitoring with property actions wrong type.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
.erase("rule_id");
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["actions"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'array'");
}
// Invalid: test rails sensor_monitoring with property rule_id wrong format.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["rule_id"] = "id@";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'id@' does not match '^[A-Za-z0-9_]+$'");
}
// Invalid: test rails sensor_monitoring with property comments empty array.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["comments"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
// Invalid: test rails sensor_monitoring with property actions empty array.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
.erase("rule_id");
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["actions"] = json::array();
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"[] is too short");
}
}
TEST(ValidateRegulatorsConfigTest, SetDevice)
{
json setDeviceFile = validConfigFile;
setDeviceFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator";
// Valid: test set_device.
{
json configFile = setDeviceFile;
EXPECT_JSON_VALID(configFile);
}
// Invalid: test set_device wrong type.
{
json configFile = setDeviceFile;
configFile["rules"][0]["actions"][1]["set_device"] = true;
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"True is not of type 'string'");
}
// Invalid: test set_device wrong format.
{
json configFile = setDeviceFile;
configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%";
EXPECT_JSON_INVALID(configFile, "Validation failed.",
"'io_expander2%' does not match '^[A-Za-z0-9_]+$'");
}
}
TEST(ValidateRegulatorsConfigTest, DuplicateRuleID)
{
// Invalid: test duplicate ID in rule.
{
json configFile = validConfigFile;
configFile["rules"][4]["id"] = "set_voltage_rule";
configFile["rules"][4]["actions"][0]["pmbus_write_vout_command"]
["format"] = "linear";
EXPECT_JSON_INVALID(configFile, "Error: Duplicate rule ID.", "");
}
}
TEST(ValidateRegulatorsConfigTest, DuplicateChassisNumber)
{
// Invalid: test duplicate number in chassis.
{
json configFile = validConfigFile;
configFile["chassis"][1]["number"] = 1;
configFile["chassis"][1]["inventory_path"] = "system/chassis2";
EXPECT_JSON_INVALID(configFile, "Error: Duplicate chassis number.", "");
}
}
TEST(ValidateRegulatorsConfigTest, DuplicateDeviceID)
{
// Invalid: test duplicate ID in device.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][1]["id"] = "vdd_regulator";
configFile["chassis"][0]["devices"][1]["is_regulator"] = true;
configFile["chassis"][0]["devices"][1]["fru"] =
"system/chassis/motherboard/regulator1";
configFile["chassis"][0]["devices"][1]["i2c_interface"]["bus"] = 2;
configFile["chassis"][0]["devices"][1]["i2c_interface"]["address"] =
"0x71";
EXPECT_JSON_INVALID(configFile, "Error: Duplicate device ID.", "");
}
}
TEST(ValidateRegulatorsConfigTest, DuplicateRailID)
{
// Invalid: test duplicate ID in rail.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][1]["id"] = "vdd";
EXPECT_JSON_INVALID(configFile, "Error: Duplicate rail ID.", "");
}
}
TEST(ValidateRegulatorsConfigTest, DuplicateObjectID)
{
// Invalid: test duplicate object ID in device and rail.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][1]["id"] =
"vdd_regulator";
EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
}
// Invalid: test duplicate object ID in device and rule.
{
json configFile = validConfigFile;
configFile["rules"][4]["id"] = "vdd_regulator";
configFile["rules"][4]["actions"][0]["pmbus_write_vout_command"]
["format"] = "linear";
EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
}
// Invalid: test duplicate object ID in rule and rail.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][1]["id"] =
"set_voltage_rule";
EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
}
}
TEST(ValidateRegulatorsConfigTest, InfiniteLoops)
{
// Invalid: test run_rule with infinite loop (rules run each other).
{
json configFile = validConfigFile;
configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule2";
configFile["rules"][4]["id"] = "set_voltage_rule1";
configFile["rules"][5]["actions"][0]["run_rule"] = "set_voltage_rule1";
configFile["rules"][5]["id"] = "set_voltage_rule2";
EXPECT_JSON_INVALID(configFile,
"Infinite loop caused by run_rule actions.", "");
}
// Invalid: test run_rule with infinite loop (rule runs itself).
{
json configFile = validConfigFile;
configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule1";
configFile["rules"][4]["id"] = "set_voltage_rule1";
EXPECT_JSON_INVALID(configFile,
"Infinite loop caused by run_rule actions.", "");
}
// Invalid: test run_rule with infinite loop (indirect loop).
{
json configFile = validConfigFile;
configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule2";
configFile["rules"][4]["id"] = "set_voltage_rule1";
configFile["rules"][5]["actions"][0]["run_rule"] = "set_voltage_rule3";
configFile["rules"][5]["id"] = "set_voltage_rule2";
configFile["rules"][6]["actions"][0]["run_rule"] = "set_voltage_rule1";
configFile["rules"][6]["id"] = "set_voltage_rule3";
EXPECT_JSON_INVALID(configFile,
"Infinite loop caused by run_rule actions.", "");
}
}
TEST(ValidateRegulatorsConfigTest, RunRuleValueExists)
{
// Invalid: test run_rule actions specify a rule ID that does not exist.
{
json configFile = validConfigFile;
configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule2";
configFile["rules"][4]["id"] = "set_voltage_rule1";
EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
}
}
TEST(ValidateRegulatorsConfigTest, SetDeviceValueExists)
{
// Invalid: test set_device actions specify a device ID that does not exist.
{
json configFile = validConfigFile;
configFile["rules"][4]["actions"][0]["set_device"] = "vdd_regulator2";
configFile["rules"][4]["id"] = "set_voltage_rule1";
EXPECT_JSON_INVALID(configFile, "Error: Device ID does not exist.", "");
}
}
TEST(ValidateRegulatorsConfigTest, RuleIDExists)
{
// Invalid: test rule_id property in configuration specifies a rule ID that
// does not exist.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
"set_voltage_rule2";
EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
}
// Invalid: test rule_id property in presence_detection specifies a rule ID
// that does not exist.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["presence_detection"]
["rule_id"] = "detect_presence_rule2";
EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
}
// Invalid: test rule_id property in phase_fault_detection specifies a rule
// ID that does not exist.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["rule_id"] = "detect_phase_faults_rule2";
EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
}
// Invalid: test rule_id property in sensor_monitoring specifies a rule ID
// that does not exist.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
["rule_id"] = "read_sensors_rule2";
EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
}
}
TEST(ValidateRegulatorsConfigTest, DeviceIDExists)
{
// Invalid: test device_id property in phase_fault_detection specifies a
// device ID that does not exist.
{
json configFile = validConfigFile;
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["device_id"] = "vdd_regulator2";
configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
["rule_id"] = "detect_phase_faults_rule";
EXPECT_JSON_INVALID(configFile, "Error: Device ID does not exist.", "");
}
}
TEST(ValidateRegulatorsConfigTest, NumberOfElementsInMasks)
{
// Invalid: test number of elements in masks not equal to number in values
// in i2c_compare_bytes.
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
"0x82";
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = {
"0x02", "0x73"};
configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = {
"0x7F"};
EXPECT_JSON_INVALID(configFile,
"Error: Invalid i2c_compare_bytes action.", "");
}
// Invalid: test number of elements in masks not equal to number in values
// in i2c_write_bytes.
{
json configFile = validConfigFile;
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
"0x82";
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
"0x02", "0x73"};
configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
"0x7F"};
EXPECT_JSON_INVALID(configFile,
"Error: Invalid i2c_write_bytes action.", "");
}
}
TEST(ValidateRegulatorsConfigTest, CommandLineSyntax)
{
std::string validateTool =
" ../phosphor-regulators/tools/validate-regulators-config.py ";
std::string schema = " -s ";
std::string schemaFile =
" ../phosphor-regulators/schema/config_schema.json ";
std::string configuration = " -c ";
std::string command;
std::string errorMessage;
std::string outputMessage;
std::string outputMessageHelp =
"usage: validate-regulators-config.py [-h] [-s SCHEMA_FILE]";
int valid = 0;
TemporaryFile tmpFile;
std::string fileName = tmpFile.getPath().string();
writeDataToFile(validConfigFile, fileName);
// Valid: -s specified
{
command = validateTool + "-s " + schemaFile + configuration + fileName;
expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
}
// Valid: --schema-file specified
{
command = validateTool + "--schema-file " + schemaFile + configuration +
fileName;
expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
}
// Valid: -c specified
{
command = validateTool + schema + schemaFile + "-c " + fileName;
expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
}
// Valid: --configuration-file specified
{
command = validateTool + schema + schemaFile + "--configuration-file " +
fileName;
expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
}
// Valid: -h specified
{
command = validateTool + "-h ";
expectCommandLineSyntax(errorMessage, outputMessageHelp, command,
valid);
}
// Valid: --help specified
{
command = validateTool + "--help ";
expectCommandLineSyntax(errorMessage, outputMessageHelp, command,
valid);
}
// Invalid: -c/--configuration-file not specified
{
command = validateTool + schema + schemaFile;
expectCommandLineSyntax("Error: Configuration file is required.",
outputMessageHelp, command, 1);
}
// Invalid: -s/--schema-file not specified
{
command = validateTool + configuration + fileName;
expectCommandLineSyntax("Error: Schema file is required.",
outputMessageHelp, command, 1);
}
// Invalid: -c specified more than once
{
command = validateTool + schema + schemaFile + "-c -c " + fileName;
expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
}
// Invalid: -s specified more than once
{
command = validateTool + "-s -s " + schemaFile + configuration +
fileName;
expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
}
// Invalid: No file name specified after -c
{
command = validateTool + schema + schemaFile + configuration;
expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
}
// Invalid: No file name specified after -s
{
command = validateTool + schema + configuration + fileName;
expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
}
// Invalid: File specified after -c does not exist
{
command = validateTool + schema + schemaFile + configuration +
"../notExistFile";
expectCommandLineSyntax("Error: Configuration file does not exist.",
outputMessageHelp, command, 1);
}
// Invalid: File specified after -s does not exist
{
command = validateTool + schema + "../notExistFile " + configuration +
fileName;
expectCommandLineSyntax("Error: Schema file does not exist.",
outputMessageHelp, command, 1);
}
// Invalid: File specified after -c is not right data format
{
TemporaryFile wrongFormatFile;
std::string wrongFormatFileName = wrongFormatFile.getPath().string();
std::ofstream out(wrongFormatFileName);
out << "foo";
out.close();
command = validateTool + schema + schemaFile + configuration +
wrongFormatFileName;
expectCommandLineSyntax(
"Error: Configuration file is not in the JSON format.",
outputMessageHelp, command, 1);
}
// Invalid: File specified after -s is not right data format
{
TemporaryFile wrongFormatFile;
std::string wrongFormatFileName = wrongFormatFile.getPath().string();
std::ofstream out(wrongFormatFileName);
out << "foo";
out.close();
command = validateTool + schema + wrongFormatFileName + configuration +
fileName;
expectCommandLineSyntax("Error: Schema file is not in the JSON format.",
outputMessageHelp, command, 1);
}
// Invalid: File specified after -c is not readable
{
TemporaryFile notReadableFile;
std::string notReadableFileName = notReadableFile.getPath().string();
writeDataToFile(validConfigFile, notReadableFileName);
command = validateTool + schema + schemaFile + configuration +
notReadableFileName;
chmod(notReadableFileName.c_str(), 0222);
expectCommandLineSyntax("Error: Configuration file is not readable.",
outputMessageHelp, command, 1);
}
// Invalid: File specified after -s is not readable
{
TemporaryFile notReadableFile;
std::string notReadableFileName = notReadableFile.getPath().string();
writeDataToFile(validConfigFile, notReadableFileName);
command = validateTool + schema + notReadableFileName + configuration +
fileName;
chmod(notReadableFileName.c_str(), 0222);
expectCommandLineSyntax("Error: Schema file is not readable.",
outputMessageHelp, command, 1);
}
// Invalid: Unexpected parameter specified (like -g)
{
command = validateTool + schema + schemaFile + configuration +
fileName + " -g";
expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
}
}