| /** |
| * 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); |
| } |
| } |