| /** |
| * Copyright © 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 "action.hpp" |
| #include "and_action.hpp" |
| #include "chassis.hpp" |
| #include "compare_presence_action.hpp" |
| #include "compare_vpd_action.hpp" |
| #include "config_file_parser.hpp" |
| #include "config_file_parser_error.hpp" |
| #include "configuration.hpp" |
| #include "device.hpp" |
| #include "i2c_compare_bit_action.hpp" |
| #include "i2c_compare_byte_action.hpp" |
| #include "i2c_compare_bytes_action.hpp" |
| #include "i2c_interface.hpp" |
| #include "i2c_write_bit_action.hpp" |
| #include "i2c_write_byte_action.hpp" |
| #include "i2c_write_bytes_action.hpp" |
| #include "not_action.hpp" |
| #include "or_action.hpp" |
| #include "pmbus_read_sensor_action.hpp" |
| #include "pmbus_utils.hpp" |
| #include "pmbus_write_vout_command_action.hpp" |
| #include "presence_detection.hpp" |
| #include "rail.hpp" |
| #include "rule.hpp" |
| #include "run_rule_action.hpp" |
| #include "sensor_monitoring.hpp" |
| #include "set_device_action.hpp" |
| #include "temporary_file.hpp" |
| |
| #include <sys/stat.h> // for chmod() |
| |
| #include <nlohmann/json.hpp> |
| |
| #include <cstdint> |
| #include <cstring> |
| #include <exception> |
| #include <filesystem> |
| #include <fstream> |
| #include <memory> |
| #include <optional> |
| #include <stdexcept> |
| #include <string> |
| #include <tuple> |
| #include <vector> |
| |
| #include <gtest/gtest.h> |
| |
| using namespace phosphor::power::regulators; |
| using namespace phosphor::power::regulators::config_file_parser; |
| using namespace phosphor::power::regulators::config_file_parser::internal; |
| using json = nlohmann::json; |
| |
| void writeConfigFile(const std::filesystem::path& pathName, |
| const std::string& contents) |
| { |
| std::ofstream file{pathName}; |
| file << contents; |
| } |
| |
| void writeConfigFile(const std::filesystem::path& pathName, |
| const json& contents) |
| { |
| std::ofstream file{pathName}; |
| file << contents; |
| } |
| |
| TEST(ConfigFileParserTests, Parse) |
| { |
| // Test where works |
| { |
| const json configFileContents = R"( |
| { |
| "rules": [ |
| { |
| "id": "set_voltage_rule1", |
| "actions": [ |
| { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } } |
| ] |
| }, |
| { |
| "id": "set_voltage_rule2", |
| "actions": [ |
| { "pmbus_write_vout_command": { "volts": 1.33, "format": "linear" } } |
| ] |
| } |
| ], |
| "chassis": [ |
| { "number": 1 }, |
| { "number": 2 }, |
| { "number": 3 } |
| ] |
| } |
| )"_json; |
| |
| TemporaryFile configFile; |
| std::filesystem::path pathName{configFile.getPath()}; |
| writeConfigFile(pathName, configFileContents); |
| |
| std::vector<std::unique_ptr<Rule>> rules{}; |
| std::vector<std::unique_ptr<Chassis>> chassis{}; |
| std::tie(rules, chassis) = parse(pathName); |
| |
| EXPECT_EQ(rules.size(), 2); |
| EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1"); |
| EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2"); |
| |
| EXPECT_EQ(chassis.size(), 3); |
| EXPECT_EQ(chassis[0]->getNumber(), 1); |
| EXPECT_EQ(chassis[1]->getNumber(), 2); |
| EXPECT_EQ(chassis[2]->getNumber(), 3); |
| } |
| |
| // Test where fails: File does not exist |
| try |
| { |
| std::filesystem::path pathName{"/tmp/non_existent_file"}; |
| parse(pathName); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const ConfigFileParserError& e) |
| { |
| // Expected exception; what() message will vary |
| } |
| |
| // Test where fails: File is not readable |
| try |
| { |
| const json configFileContents = R"( |
| { |
| "chassis": [ { "number": 1 } ] |
| } |
| )"_json; |
| |
| TemporaryFile configFile; |
| std::filesystem::path pathName{configFile.getPath()}; |
| writeConfigFile(pathName, configFileContents); |
| |
| chmod(pathName.c_str(), 0222); |
| |
| parse(pathName); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const ConfigFileParserError& e) |
| { |
| // Expected exception; what() message will vary |
| } |
| |
| // Test where fails: File is not valid JSON |
| try |
| { |
| const std::string configFileContents = "] foo ["; |
| |
| TemporaryFile configFile; |
| std::filesystem::path pathName{configFile.getPath()}; |
| writeConfigFile(pathName, configFileContents); |
| |
| parse(pathName); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const ConfigFileParserError& e) |
| { |
| // Expected exception; what() message will vary |
| } |
| |
| // Test where fails: Error when parsing JSON elements |
| try |
| { |
| const json configFileContents = R"( { "foo": "bar" } )"_json; |
| |
| TemporaryFile configFile; |
| std::filesystem::path pathName{configFile.getPath()}; |
| writeConfigFile(pathName, configFileContents); |
| |
| parse(pathName); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const ConfigFileParserError& e) |
| { |
| // Expected exception; what() message will vary |
| } |
| } |
| |
| TEST(ConfigFileParserTests, GetRequiredProperty) |
| { |
| // Test where property exists |
| { |
| const json element = R"( { "format": "linear" } )"_json; |
| const json& propertyElement = getRequiredProperty(element, "format"); |
| EXPECT_EQ(propertyElement.get<std::string>(), "linear"); |
| } |
| |
| // Test where property does not exist |
| try |
| { |
| const json element = R"( { "volts": 1.03 } )"_json; |
| getRequiredProperty(element, "format"); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: format"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseAction) |
| { |
| // Test where works: comments property specified |
| { |
| const json element = R"( |
| { |
| "comments": [ "Set output voltage." ], |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: comments property not specified |
| { |
| const json element = R"( |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: and action type specified |
| { |
| const json element = R"( |
| { |
| "and": [ |
| { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, |
| { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: compare_presence action type specified |
| { |
| const json element = R"( |
| { |
| "compare_presence": |
| { |
| "fru": "system/chassis/motherboard/cpu3", |
| "value": true |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: compare_vpd action type specified |
| { |
| const json element = R"( |
| { |
| "compare_vpd": |
| { |
| "fru": "system/chassis/disk_backplane", |
| "keyword": "CCIN", |
| "value": "2D35" |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: i2c_compare_bit action type specified |
| { |
| const json element = R"( |
| { |
| "i2c_compare_bit": { |
| "register": "0xA0", |
| "position": 3, |
| "value": 0 |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: i2c_compare_byte action type specified |
| { |
| const json element = R"( |
| { |
| "i2c_compare_byte": { |
| "register": "0x0A", |
| "value": "0xCC" |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: i2c_compare_bytes action type specified |
| { |
| const json element = R"( |
| { |
| "i2c_compare_bytes": { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ] |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: i2c_write_bit action type specified |
| { |
| const json element = R"( |
| { |
| "i2c_write_bit": { |
| "register": "0xA0", |
| "position": 3, |
| "value": 0 |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: i2c_write_byte action type specified |
| { |
| const json element = R"( |
| { |
| "i2c_write_byte": { |
| "register": "0x0A", |
| "value": "0xCC" |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: i2c_write_bytes action type specified |
| { |
| const json element = R"( |
| { |
| "i2c_write_bytes": { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ] |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: if action type specified |
| { |
| const json element = R"( |
| { |
| "if": |
| { |
| "condition": { "run_rule": "is_downlevel_regulator" }, |
| "then": [ { "run_rule": "configure_downlevel_regulator" } ], |
| "else": [ { "run_rule": "configure_standard_regulator" } ] |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: not action type specified |
| { |
| const json element = R"( |
| { |
| "not": |
| { "i2c_compare_byte": { "register": "0xA0", "value": "0xFF" } } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: or action type specified |
| { |
| const json element = R"( |
| { |
| "or": [ |
| { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, |
| { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: pmbus_read_sensor action type specified |
| { |
| const json element = R"( |
| { |
| "pmbus_read_sensor": { |
| "type": "iout", |
| "command": "0x8C", |
| "format": "linear_11" |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: pmbus_write_vout_command action type specified |
| { |
| const json element = R"( |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: run_rule action type specified |
| { |
| const json element = R"( |
| { |
| "run_rule": "set_voltage_rule" |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where works: set_device action type specified |
| { |
| const json element = R"( |
| { |
| "set_device": "io_expander2" |
| } |
| )"_json; |
| std::unique_ptr<Action> action = parseAction(element); |
| EXPECT_NE(action.get(), nullptr); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseAction(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: No action type specified |
| try |
| { |
| const json element = R"( |
| { |
| "comments": [ "Set output voltage." ] |
| } |
| )"_json; |
| parseAction(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required action type property missing"); |
| } |
| |
| // Test where fails: Multiple action types specified |
| try |
| { |
| const json element = R"( |
| { |
| "pmbus_write_vout_command": { "format": "linear" }, |
| "run_rule": "set_voltage_rule" |
| } |
| )"_json; |
| parseAction(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "remarks": [ "Set output voltage." ], |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| )"_json; |
| parseAction(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseActionArray) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| [ |
| { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }, |
| { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } } |
| ] |
| )"_json; |
| std::vector<std::unique_ptr<Action>> actions = |
| parseActionArray(element); |
| EXPECT_EQ(actions.size(), 2); |
| } |
| |
| // Test where fails: Element is not an array |
| try |
| { |
| const json element = R"( |
| { |
| "foo": "bar" |
| } |
| )"_json; |
| parseActionArray(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseAnd) |
| { |
| // Test where works: Element is an array with 2 actions |
| { |
| const json element = R"( |
| [ |
| { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, |
| { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } |
| ] |
| )"_json; |
| std::unique_ptr<AndAction> action = parseAnd(element); |
| EXPECT_EQ(action->getActions().size(), 2); |
| } |
| |
| // Test where fails: Element is an array with 1 action |
| try |
| { |
| const json element = R"( |
| [ |
| { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } } |
| ] |
| )"_json; |
| parseAnd(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Array must contain two or more actions"); |
| } |
| |
| // Test where fails: Element is not an array |
| try |
| { |
| const json element = R"( |
| { |
| "foo": "bar" |
| } |
| )"_json; |
| parseAnd(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseBitPosition) |
| { |
| // Test where works: 0 |
| { |
| const json element = R"( 0 )"_json; |
| uint8_t value = parseBitPosition(element); |
| EXPECT_EQ(value, 0); |
| } |
| |
| // Test where works: 7 |
| { |
| const json element = R"( 7 )"_json; |
| uint8_t value = parseBitPosition(element); |
| EXPECT_EQ(value, 7); |
| } |
| |
| // Test where fails: Element is not an integer |
| try |
| { |
| const json element = R"( 1.03 )"_json; |
| parseBitPosition(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an integer"); |
| } |
| |
| // Test where fails: Value < 0 |
| try |
| { |
| const json element = R"( -1 )"_json; |
| parseBitPosition(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a bit position"); |
| } |
| |
| // Test where fails: Value > 7 |
| try |
| { |
| const json element = R"( 8 )"_json; |
| parseBitPosition(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a bit position"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseBitValue) |
| { |
| // Test where works: 0 |
| { |
| const json element = R"( 0 )"_json; |
| uint8_t value = parseBitValue(element); |
| EXPECT_EQ(value, 0); |
| } |
| |
| // Test where works: 1 |
| { |
| const json element = R"( 1 )"_json; |
| uint8_t value = parseBitValue(element); |
| EXPECT_EQ(value, 1); |
| } |
| |
| // Test where fails: Element is not an integer |
| try |
| { |
| const json element = R"( 0.5 )"_json; |
| parseBitValue(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an integer"); |
| } |
| |
| // Test where fails: Value < 0 |
| try |
| { |
| const json element = R"( -1 )"_json; |
| parseBitValue(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a bit value"); |
| } |
| |
| // Test where fails: Value > 1 |
| try |
| { |
| const json element = R"( 2 )"_json; |
| parseBitValue(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a bit value"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseBoolean) |
| { |
| // Test where works: true |
| { |
| const json element = R"( true )"_json; |
| bool value = parseBoolean(element); |
| EXPECT_EQ(value, true); |
| } |
| |
| // Test where works: false |
| { |
| const json element = R"( false )"_json; |
| bool value = parseBoolean(element); |
| EXPECT_EQ(value, false); |
| } |
| |
| // Test where fails: Element is not a boolean |
| try |
| { |
| const json element = R"( 1 )"_json; |
| parseBoolean(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a boolean"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseChassis) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "number": 1 |
| } |
| )"_json; |
| std::unique_ptr<Chassis> chassis = parseChassis(element); |
| EXPECT_EQ(chassis->getNumber(), 1); |
| EXPECT_EQ(chassis->getDevices().size(), 0); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "comments": [ "comments property" ], |
| "number": 2, |
| "devices": [ |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| } |
| } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<Chassis> chassis = parseChassis(element); |
| EXPECT_EQ(chassis->getNumber(), 2); |
| EXPECT_EQ(chassis->getDevices().size(), 1); |
| EXPECT_EQ(chassis->getDevices()[0]->getID(), "vdd_regulator"); |
| } |
| |
| // Test where fails: number value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "number": 0.5 |
| } |
| )"_json; |
| parseChassis(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "number": 1, |
| "foo": 2 |
| } |
| )"_json; |
| parseChassis(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: Required number property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "devices": [ |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| } |
| } |
| ] |
| } |
| )"_json; |
| parseChassis(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: number"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseChassis(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: number value is < 1 |
| try |
| { |
| const json element = R"( |
| { |
| "number": 0 |
| } |
| )"_json; |
| parseChassis(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid chassis number: Must be > 0"); |
| } |
| |
| // Test where fails: devices value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "number": 1, |
| "devices": 2 |
| } |
| )"_json; |
| parseChassis(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseChassisArray) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| [ |
| { "number": 1 }, |
| { "number": 2 } |
| ] |
| )"_json; |
| std::vector<std::unique_ptr<Chassis>> chassis = |
| parseChassisArray(element); |
| EXPECT_EQ(chassis.size(), 2); |
| EXPECT_EQ(chassis[0]->getNumber(), 1); |
| EXPECT_EQ(chassis[1]->getNumber(), 2); |
| } |
| |
| // Test where fails: Element is not an array |
| try |
| { |
| const json element = R"( |
| { |
| "foo": "bar" |
| } |
| )"_json; |
| parseChassisArray(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseComparePresence) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/motherboard/cpu3", |
| "value": true |
| } |
| )"_json; |
| std::unique_ptr<ComparePresenceAction> action = |
| parseComparePresence(element); |
| EXPECT_EQ( |
| action->getFRU(), |
| "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3"); |
| EXPECT_EQ(action->getValue(), true); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseComparePresence(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/motherboard/cpu3", |
| "value": true, |
| "foo" : true |
| } |
| )"_json; |
| parseComparePresence(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: Required fru property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "value": true |
| } |
| )"_json; |
| parseComparePresence(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: fru"); |
| } |
| |
| // Test where fails: Required value property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/motherboard/cpu3" |
| } |
| )"_json; |
| parseComparePresence(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: value"); |
| } |
| |
| // Test where fails: fru value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "fru": 1, |
| "value": true |
| } |
| )"_json; |
| parseComparePresence(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: value value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/motherboard/cpu3", |
| "value": 1 |
| } |
| )"_json; |
| parseComparePresence(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a boolean"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseCompareVPD) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/disk_backplane", |
| "keyword": "CCIN", |
| "value": "2D35" |
| } |
| )"_json; |
| std::unique_ptr<CompareVPDAction> action = parseCompareVPD(element); |
| EXPECT_EQ( |
| action->getFRU(), |
| "/xyz/openbmc_project/inventory/system/chassis/disk_backplane"); |
| EXPECT_EQ(action->getKeyword(), "CCIN"); |
| EXPECT_EQ(action->getValue(), "2D35"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseCompareVPD(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/disk_backplane", |
| "keyword": "CCIN", |
| "value": "2D35", |
| "foo" : true |
| } |
| )"_json; |
| parseCompareVPD(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: Required fru property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "keyword": "CCIN", |
| "value": "2D35" |
| } |
| )"_json; |
| parseCompareVPD(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: fru"); |
| } |
| |
| // Test where fails: Required keyword property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/disk_backplane", |
| "value": "2D35" |
| } |
| )"_json; |
| parseCompareVPD(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: keyword"); |
| } |
| |
| // Test where fails: Required value property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/disk_backplane", |
| "keyword": "CCIN" |
| } |
| )"_json; |
| parseCompareVPD(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: value"); |
| } |
| |
| // Test where fails: fru value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "fru": 1, |
| "keyword": "CCIN", |
| "value": "2D35" |
| } |
| )"_json; |
| parseCompareVPD(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: keyword value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/disk_backplane", |
| "keyword": 1, |
| "value": "2D35" |
| } |
| )"_json; |
| parseCompareVPD(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: value value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "fru": "system/chassis/disk_backplane", |
| "keyword": "CCIN", |
| "value": 1 |
| } |
| )"_json; |
| parseCompareVPD(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseConfiguration) |
| { |
| // Test where works: actions required property specified |
| { |
| const json element = R"( |
| { |
| "actions": [ |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<Configuration> configuration = |
| parseConfiguration(element); |
| EXPECT_EQ(configuration->getActions().size(), 1); |
| EXPECT_EQ(configuration->getVolts().has_value(), false); |
| } |
| |
| // Test where works: volts and actions properties specified |
| { |
| const json element = R"( |
| { |
| "comments": [ "comments property" ], |
| "volts": 1.03, |
| "actions": [ |
| { "pmbus_write_vout_command": { "format": "linear" } }, |
| { "run_rule": "set_voltage_rule" } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<Configuration> configuration = |
| parseConfiguration(element); |
| EXPECT_EQ(configuration->getVolts().has_value(), true); |
| EXPECT_EQ(configuration->getVolts().value(), 1.03); |
| EXPECT_EQ(configuration->getActions().size(), 2); |
| } |
| |
| // Test where works: volts and rule_id properties specified |
| { |
| const json element = R"( |
| { |
| "volts": 1.05, |
| "rule_id": "set_voltage_rule" |
| } |
| )"_json; |
| std::unique_ptr<Configuration> configuration = |
| parseConfiguration(element); |
| EXPECT_EQ(configuration->getVolts().has_value(), true); |
| EXPECT_EQ(configuration->getVolts().value(), 1.05); |
| EXPECT_EQ(configuration->getActions().size(), 1); |
| } |
| |
| // Test where fails: volts value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "volts": "foo", |
| "actions": [ |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| ] |
| } |
| )"_json; |
| parseConfiguration(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a number"); |
| } |
| |
| // Test where fails: actions object is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "volts": 1.03, |
| "actions": 1 |
| } |
| )"_json; |
| parseConfiguration(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| |
| // Test where fails: rule_id value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "volts": 1.05, |
| "rule_id": 1 |
| } |
| )"_json; |
| parseConfiguration(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: Required actions or rule_id property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "volts": 1.03 |
| } |
| )"_json; |
| parseConfiguration(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " |
| "either rule_id or actions"); |
| } |
| |
| // Test where fails: Required actions or rule_id property both specified |
| try |
| { |
| const json element = R"( |
| { |
| "volts": 1.03, |
| "rule_id": "set_voltage_rule", |
| "actions": [ |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| ] |
| } |
| )"_json; |
| parseConfiguration(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " |
| "either rule_id or actions"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseConfiguration(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "volts": 1.03, |
| "rule_id": "set_voltage_rule", |
| "foo": 1 |
| } |
| )"_json; |
| parseConfiguration(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseDevice) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": { "bus": 1, "address": "0x70" } |
| } |
| )"_json; |
| std::unique_ptr<Device> device = parseDevice(element); |
| EXPECT_EQ(device->getID(), "vdd_regulator"); |
| EXPECT_EQ(device->isRegulator(), true); |
| EXPECT_EQ(device->getFRU(), "/xyz/openbmc_project/inventory/system/" |
| "chassis/motherboard/regulator2"); |
| EXPECT_NE(&(device->getI2CInterface()), nullptr); |
| EXPECT_EQ(device->getPresenceDetection(), nullptr); |
| EXPECT_EQ(device->getConfiguration(), nullptr); |
| EXPECT_EQ(device->getRails().size(), 0); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| }, |
| "configuration": |
| { |
| "rule_id": "configure_ir35221_rule" |
| }, |
| "presence_detection": |
| { |
| "rule_id": "is_foobar_backplane_installed_rule" |
| }, |
| "rails": |
| [ |
| { |
| "id": "vdd" |
| } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<Device> device = parseDevice(element); |
| EXPECT_EQ(device->getID(), "vdd_regulator"); |
| EXPECT_EQ(device->isRegulator(), true); |
| EXPECT_EQ(device->getFRU(), "/xyz/openbmc_project/inventory/system/" |
| "chassis/motherboard/regulator2"); |
| EXPECT_NE(&(device->getI2CInterface()), nullptr); |
| EXPECT_NE(device->getPresenceDetection(), nullptr); |
| EXPECT_NE(device->getConfiguration(), nullptr); |
| EXPECT_EQ(device->getRails().size(), 1); |
| } |
| |
| // Test where fails: rails property exists and is_regulator is false |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "is_regulator": false, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| }, |
| "configuration": |
| { |
| "rule_id": "configure_ir35221_rule" |
| }, |
| "rails": |
| [ |
| { |
| "id": "vdd" |
| } |
| ] |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), |
| "Invalid rails property when is_regulator is false"); |
| } |
| |
| // Test where fails: id value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "id": 3, |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| } |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: is_regulator value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "is_regulator": 3, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| } |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a boolean"); |
| } |
| |
| // Test where fails: fru value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "fru": 2, |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| } |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: i2c_interface value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": 3 |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Required id property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| } |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: id"); |
| } |
| |
| // Test where fails: Required is_regulator property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| } |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: is_regulator"); |
| } |
| |
| // Test where fails: Required fru property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "i2c_interface": |
| { |
| "bus": 1, |
| "address": "0x70" |
| } |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: fru"); |
| } |
| |
| // Test where fails: Required i2c_interface property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2" |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: i2c_interface"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": { "bus": 1, "address": "0x70" }, |
| "foo" : true |
| } |
| )"_json; |
| parseDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseDeviceArray) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| [ |
| { |
| "id": "vdd_regulator", |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": { "bus": 1, "address": "0x70" } |
| }, |
| { |
| "id": "vio_regulator", |
| "is_regulator": true, |
| "fru": "system/chassis/motherboard/regulator2", |
| "i2c_interface": { "bus": 1, "address": "0x71" } |
| } |
| ] |
| )"_json; |
| std::vector<std::unique_ptr<Device>> devices = |
| parseDeviceArray(element); |
| EXPECT_EQ(devices.size(), 2); |
| EXPECT_EQ(devices[0]->getID(), "vdd_regulator"); |
| EXPECT_EQ(devices[1]->getID(), "vio_regulator"); |
| } |
| |
| // Test where fails: Element is not an array |
| try |
| { |
| const json element = R"( |
| { |
| "foo": "bar" |
| } |
| )"_json; |
| parseDeviceArray(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseDouble) |
| { |
| // Test where works: floating point value |
| { |
| const json element = R"( 1.03 )"_json; |
| double value = parseDouble(element); |
| EXPECT_EQ(value, 1.03); |
| } |
| |
| // Test where works: integer value |
| { |
| const json element = R"( 24 )"_json; |
| double value = parseDouble(element); |
| EXPECT_EQ(value, 24.0); |
| } |
| |
| // Test where fails: Element is not a number |
| try |
| { |
| const json element = R"( true )"_json; |
| parseDouble(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a number"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseHexByte) |
| { |
| // Test where works: "0xFF" |
| { |
| const json element = R"( "0xFF" )"_json; |
| uint8_t value = parseHexByte(element); |
| EXPECT_EQ(value, 0xFF); |
| } |
| |
| // Test where works: "0xff" |
| { |
| const json element = R"( "0xff" )"_json; |
| uint8_t value = parseHexByte(element); |
| EXPECT_EQ(value, 0xff); |
| } |
| |
| // Test where works: "0xf" |
| { |
| const json element = R"( "0xf" )"_json; |
| uint8_t value = parseHexByte(element); |
| EXPECT_EQ(value, 0xf); |
| } |
| |
| // Test where fails: "0xfff" |
| try |
| { |
| const json element = R"( "0xfff" )"_json; |
| parseHexByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: "0xAG" |
| try |
| { |
| const json element = R"( "0xAG" )"_json; |
| parseHexByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: "ff" |
| try |
| { |
| const json element = R"( "ff" )"_json; |
| parseHexByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: "" |
| try |
| { |
| const json element = ""; |
| parseHexByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: "f" |
| try |
| { |
| const json element = R"( "f" )"_json; |
| parseHexByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: "0x" |
| try |
| { |
| const json element = R"( "0x" )"_json; |
| parseHexByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: "0Xff" |
| try |
| { |
| const json element = R"( "0XFF" )"_json; |
| parseHexByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseHexByteArray) |
| { |
| // Test where works |
| { |
| const json element = R"( [ "0xCC", "0xFF" ] )"_json; |
| std::vector<uint8_t> hexBytes = parseHexByteArray(element); |
| std::vector<uint8_t> expected = {0xcc, 0xff}; |
| EXPECT_EQ(hexBytes, expected); |
| } |
| |
| // Test where fails: Element is not an array |
| try |
| { |
| const json element = 0; |
| parseHexByteArray(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseI2CCompareBit) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 3, |
| "value": 0 |
| } |
| )"_json; |
| std::unique_ptr<I2CCompareBitAction> action = |
| parseI2CCompareBit(element); |
| EXPECT_EQ(action->getRegister(), 0xA0); |
| EXPECT_EQ(action->getPosition(), 3); |
| EXPECT_EQ(action->getValue(), 0); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 3, |
| "value": 0, |
| "foo": 3 |
| } |
| )"_json; |
| parseI2CCompareBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseI2CCompareBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: register value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xAG", |
| "position": 3, |
| "value": 0 |
| } |
| )"_json; |
| parseI2CCompareBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: position value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 8, |
| "value": 0 |
| } |
| )"_json; |
| parseI2CCompareBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a bit position"); |
| } |
| |
| // Test where fails: value value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 3, |
| "value": 2 |
| } |
| )"_json; |
| parseI2CCompareBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a bit value"); |
| } |
| |
| // Test where fails: Required register property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "position": 3, |
| "value": 0 |
| } |
| )"_json; |
| parseI2CCompareBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: register"); |
| } |
| |
| // Test where fails: Required position property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "value": 0 |
| } |
| )"_json; |
| parseI2CCompareBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: position"); |
| } |
| |
| // Test where fails: Required value property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 3 |
| } |
| )"_json; |
| parseI2CCompareBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: value"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseI2CCompareByte) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCC" |
| } |
| )"_json; |
| std::unique_ptr<I2CCompareByteAction> action = |
| parseI2CCompareByte(element); |
| EXPECT_EQ(action->getRegister(), 0x0A); |
| EXPECT_EQ(action->getValue(), 0xCC); |
| EXPECT_EQ(action->getMask(), 0xFF); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCC", |
| "mask": "0xF7" |
| } |
| )"_json; |
| std::unique_ptr<I2CCompareByteAction> action = |
| parseI2CCompareByte(element); |
| EXPECT_EQ(action->getRegister(), 0x0A); |
| EXPECT_EQ(action->getValue(), 0xCC); |
| EXPECT_EQ(action->getMask(), 0xF7); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseI2CCompareByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCC", |
| "mask": "0xF7", |
| "foo": 1 |
| } |
| )"_json; |
| parseI2CCompareByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: register value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0Z", |
| "value": "0xCC", |
| "mask": "0xF7" |
| } |
| )"_json; |
| parseI2CCompareByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: value value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCCC", |
| "mask": "0xF7" |
| } |
| )"_json; |
| parseI2CCompareByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: mask value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCC", |
| "mask": "F7" |
| } |
| )"_json; |
| parseI2CCompareByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: Required register property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "value": "0xCC", |
| "mask": "0xF7" |
| } |
| )"_json; |
| parseI2CCompareByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: register"); |
| } |
| |
| // Test where fails: Required value property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "mask": "0xF7" |
| } |
| )"_json; |
| parseI2CCompareByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: value"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseI2CCompareBytes) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ] |
| } |
| )"_json; |
| std::unique_ptr<I2CCompareBytesAction> action = |
| parseI2CCompareBytes(element); |
| EXPECT_EQ(action->getRegister(), 0x0A); |
| EXPECT_EQ(action->getValues().size(), 2); |
| EXPECT_EQ(action->getValues()[0], 0xCC); |
| EXPECT_EQ(action->getValues()[1], 0xFF); |
| EXPECT_EQ(action->getMasks().size(), 2); |
| EXPECT_EQ(action->getMasks()[0], 0xFF); |
| EXPECT_EQ(action->getMasks()[1], 0xFF); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "0x7F", "0x77" ] |
| } |
| )"_json; |
| std::unique_ptr<I2CCompareBytesAction> action = |
| parseI2CCompareBytes(element); |
| EXPECT_EQ(action->getRegister(), 0x0A); |
| EXPECT_EQ(action->getValues().size(), 2); |
| EXPECT_EQ(action->getValues()[0], 0xCC); |
| EXPECT_EQ(action->getValues()[1], 0xFF); |
| EXPECT_EQ(action->getMasks().size(), 2); |
| EXPECT_EQ(action->getMasks()[0], 0x7F); |
| EXPECT_EQ(action->getMasks()[1], 0x77); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseI2CCompareBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "0x7F", "0x7F" ], |
| "foo": 1 |
| } |
| )"_json; |
| parseI2CCompareBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: register value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0Z", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "0x7F", "0x7F" ] |
| } |
| )"_json; |
| parseI2CCompareBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: values value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCCC", "0xFF" ], |
| "masks": [ "0x7F", "0x7F" ] |
| } |
| )"_json; |
| parseI2CCompareBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: masks value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "F", "0x7F" ] |
| } |
| )"_json; |
| parseI2CCompareBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: number of elements in masks is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "0x7F" ] |
| } |
| )"_json; |
| parseI2CCompareBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid number of elements in masks"); |
| } |
| |
| // Test where fails: Required register property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "values": [ "0xCC", "0xFF" ] |
| } |
| )"_json; |
| parseI2CCompareBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: register"); |
| } |
| |
| // Test where fails: Required values property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A" |
| } |
| )"_json; |
| parseI2CCompareBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: values"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseI2CWriteBit) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 3, |
| "value": 0 |
| } |
| )"_json; |
| std::unique_ptr<I2CWriteBitAction> action = parseI2CWriteBit(element); |
| EXPECT_EQ(action->getRegister(), 0xA0); |
| EXPECT_EQ(action->getPosition(), 3); |
| EXPECT_EQ(action->getValue(), 0); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 3, |
| "value": 0, |
| "foo": 3 |
| } |
| )"_json; |
| parseI2CWriteBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseI2CWriteBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: register value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xAG", |
| "position": 3, |
| "value": 0 |
| } |
| )"_json; |
| parseI2CWriteBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: position value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 8, |
| "value": 0 |
| } |
| )"_json; |
| parseI2CWriteBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a bit position"); |
| } |
| |
| // Test where fails: value value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 3, |
| "value": 2 |
| } |
| )"_json; |
| parseI2CWriteBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a bit value"); |
| } |
| |
| // Test where fails: Required register property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "position": 3, |
| "value": 0 |
| } |
| )"_json; |
| parseI2CWriteBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: register"); |
| } |
| |
| // Test where fails: Required position property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "value": 0 |
| } |
| )"_json; |
| parseI2CWriteBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: position"); |
| } |
| |
| // Test where fails: Required value property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0xA0", |
| "position": 3 |
| } |
| )"_json; |
| parseI2CWriteBit(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: value"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseI2CWriteByte) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCC" |
| } |
| )"_json; |
| std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element); |
| EXPECT_EQ(action->getRegister(), 0x0A); |
| EXPECT_EQ(action->getValue(), 0xCC); |
| EXPECT_EQ(action->getMask(), 0xFF); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCC", |
| "mask": "0xF7" |
| } |
| )"_json; |
| std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element); |
| EXPECT_EQ(action->getRegister(), 0x0A); |
| EXPECT_EQ(action->getValue(), 0xCC); |
| EXPECT_EQ(action->getMask(), 0xF7); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseI2CWriteByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCC", |
| "mask": "0xF7", |
| "foo": 1 |
| } |
| )"_json; |
| parseI2CWriteByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: register value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0Z", |
| "value": "0xCC", |
| "mask": "0xF7" |
| } |
| )"_json; |
| parseI2CWriteByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: value value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCCC", |
| "mask": "0xF7" |
| } |
| )"_json; |
| parseI2CWriteByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: mask value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "value": "0xCC", |
| "mask": "F7" |
| } |
| )"_json; |
| parseI2CWriteByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: Required register property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "value": "0xCC", |
| "mask": "0xF7" |
| } |
| )"_json; |
| parseI2CWriteByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: register"); |
| } |
| |
| // Test where fails: Required value property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "mask": "0xF7" |
| } |
| )"_json; |
| parseI2CWriteByte(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: value"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseI2CWriteBytes) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ] |
| } |
| )"_json; |
| std::unique_ptr<I2CWriteBytesAction> action = |
| parseI2CWriteBytes(element); |
| EXPECT_EQ(action->getRegister(), 0x0A); |
| EXPECT_EQ(action->getValues().size(), 2); |
| EXPECT_EQ(action->getValues()[0], 0xCC); |
| EXPECT_EQ(action->getValues()[1], 0xFF); |
| EXPECT_EQ(action->getMasks().size(), 0); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "0x7F", "0x77" ] |
| } |
| )"_json; |
| std::unique_ptr<I2CWriteBytesAction> action = |
| parseI2CWriteBytes(element); |
| EXPECT_EQ(action->getRegister(), 0x0A); |
| EXPECT_EQ(action->getValues().size(), 2); |
| EXPECT_EQ(action->getValues()[0], 0xCC); |
| EXPECT_EQ(action->getValues()[1], 0xFF); |
| EXPECT_EQ(action->getMasks().size(), 2); |
| EXPECT_EQ(action->getMasks()[0], 0x7F); |
| EXPECT_EQ(action->getMasks()[1], 0x77); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseI2CWriteBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "0x7F", "0x7F" ], |
| "foo": 1 |
| } |
| )"_json; |
| parseI2CWriteBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: register value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0Z", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "0x7F", "0x7F" ] |
| } |
| )"_json; |
| parseI2CWriteBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: values value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCCC", "0xFF" ], |
| "masks": [ "0x7F", "0x7F" ] |
| } |
| )"_json; |
| parseI2CWriteBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: masks value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "F", "0x7F" ] |
| } |
| )"_json; |
| parseI2CWriteBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); |
| } |
| |
| // Test where fails: number of elements in masks is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A", |
| "values": [ "0xCC", "0xFF" ], |
| "masks": [ "0x7F" ] |
| } |
| )"_json; |
| parseI2CWriteBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid number of elements in masks"); |
| } |
| |
| // Test where fails: Required register property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "values": [ "0xCC", "0xFF" ] |
| } |
| )"_json; |
| parseI2CWriteBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: register"); |
| } |
| |
| // Test where fails: Required values property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "register": "0x0A" |
| } |
| )"_json; |
| parseI2CWriteBytes(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: values"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseIf) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "condition": { "run_rule": "is_downlevel_regulator" }, |
| "then": [ { "run_rule": "configure_downlevel_regulator" }, |
| { "run_rule": "configure_standard_regulator" } ] |
| } |
| )"_json; |
| std::unique_ptr<IfAction> action = parseIf(element); |
| EXPECT_NE(action->getConditionAction().get(), nullptr); |
| EXPECT_EQ(action->getThenActions().size(), 2); |
| EXPECT_EQ(action->getElseActions().size(), 0); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "condition": { "run_rule": "is_downlevel_regulator" }, |
| "then": [ { "run_rule": "configure_downlevel_regulator" } ], |
| "else": [ { "run_rule": "configure_standard_regulator" } ] |
| } |
| )"_json; |
| std::unique_ptr<IfAction> action = parseIf(element); |
| EXPECT_NE(action->getConditionAction().get(), nullptr); |
| EXPECT_EQ(action->getThenActions().size(), 1); |
| EXPECT_EQ(action->getElseActions().size(), 1); |
| } |
| |
| // Test where fails: Required condition property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "then": [ { "run_rule": "configure_downlevel_regulator" } ], |
| "else": [ { "run_rule": "configure_standard_regulator" } ] |
| } |
| )"_json; |
| parseIf(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: condition"); |
| } |
| |
| // Test where fails: Required then property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "condition": { "run_rule": "is_downlevel_regulator" }, |
| "else": [ { "run_rule": "configure_standard_regulator" } ] |
| } |
| )"_json; |
| parseIf(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: then"); |
| } |
| |
| // Test where fails: condition value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "condition": 1, |
| "then": [ { "run_rule": "configure_downlevel_regulator" } ], |
| "else": [ { "run_rule": "configure_standard_regulator" } ] |
| } |
| )"_json; |
| parseIf(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: then value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "condition": { "run_rule": "is_downlevel_regulator" }, |
| "then": "foo", |
| "else": [ { "run_rule": "configure_standard_regulator" } ] |
| } |
| )"_json; |
| parseIf(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| |
| // Test where fails: else value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "condition": { "run_rule": "is_downlevel_regulator" }, |
| "then": [ { "run_rule": "configure_downlevel_regulator" } ], |
| "else": 1 |
| } |
| )"_json; |
| parseIf(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "condition": { "run_rule": "is_downlevel_regulator" }, |
| "then": [ { "run_rule": "configure_downlevel_regulator" } ], |
| "foo": "bar" |
| } |
| )"_json; |
| parseIf(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseIf(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseInt8) |
| { |
| // Test where works: INT8_MIN |
| { |
| const json element = R"( -128 )"_json; |
| int8_t value = parseInt8(element); |
| EXPECT_EQ(value, -128); |
| } |
| |
| // Test where works: INT8_MAX |
| { |
| const json element = R"( 127 )"_json; |
| int8_t value = parseInt8(element); |
| EXPECT_EQ(value, 127); |
| } |
| |
| // Test where fails: Element is not an integer |
| try |
| { |
| const json element = R"( 1.03 )"_json; |
| parseInt8(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an integer"); |
| } |
| |
| // Test where fails: Value < INT8_MIN |
| try |
| { |
| const json element = R"( -129 )"_json; |
| parseInt8(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); |
| } |
| |
| // Test where fails: Value > INT8_MAX |
| try |
| { |
| const json element = R"( 128 )"_json; |
| parseInt8(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseInventoryPath) |
| { |
| // Test where works: Inventory path has a leading '/' |
| { |
| const json element = "/system/chassis/motherboard/cpu3"; |
| std::string value = parseInventoryPath(element); |
| EXPECT_EQ( |
| value, |
| "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3"); |
| } |
| |
| // Test where works: Inventory path does not have a leading '/' |
| { |
| const json element = "system/chassis/motherboard/cpu1"; |
| std::string value = parseInventoryPath(element); |
| EXPECT_EQ( |
| value, |
| "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1"); |
| } |
| |
| // Test where fails: JSON element is not a string |
| try |
| { |
| const json element = R"( { "foo": "bar" } )"_json; |
| parseInventoryPath(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: JSON element contains an empty string |
| try |
| { |
| const json element = ""; |
| parseInventoryPath(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an empty string"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseNot) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } } |
| )"_json; |
| std::unique_ptr<NotAction> action = parseNot(element); |
| EXPECT_NE(action->getAction().get(), nullptr); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseNot(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseOr) |
| { |
| // Test where works: Element is an array with 2 actions |
| { |
| const json element = R"( |
| [ |
| { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, |
| { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } |
| ] |
| )"_json; |
| std::unique_ptr<OrAction> action = parseOr(element); |
| EXPECT_EQ(action->getActions().size(), 2); |
| } |
| |
| // Test where fails: Element is an array with 1 action |
| try |
| { |
| const json element = R"( |
| [ |
| { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } } |
| ] |
| )"_json; |
| parseOr(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Array must contain two or more actions"); |
| } |
| |
| // Test where fails: Element is not an array |
| try |
| { |
| const json element = R"( |
| { |
| "foo": "bar" |
| } |
| )"_json; |
| parseOr(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParsePMBusReadSensor) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "type": "iout", |
| "command": "0x8C", |
| "format": "linear_11" |
| } |
| )"_json; |
| std::unique_ptr<PMBusReadSensorAction> action = |
| parsePMBusReadSensor(element); |
| EXPECT_EQ(action->getType(), pmbus_utils::SensorValueType::iout); |
| EXPECT_EQ(action->getCommand(), 0x8C); |
| EXPECT_EQ(action->getFormat(), |
| pmbus_utils::SensorDataFormat::linear_11); |
| EXPECT_EQ(action->getExponent().has_value(), false); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "type": "temperature", |
| "command": "0x7A", |
| "format": "linear_16", |
| "exponent": -8 |
| } |
| )"_json; |
| std::unique_ptr<PMBusReadSensorAction> action = |
| parsePMBusReadSensor(element); |
| EXPECT_EQ(action->getType(), pmbus_utils::SensorValueType::temperature); |
| EXPECT_EQ(action->getCommand(), 0x7A); |
| EXPECT_EQ(action->getFormat(), |
| pmbus_utils::SensorDataFormat::linear_16); |
| EXPECT_EQ(action->getExponent().has_value(), true); |
| EXPECT_EQ(action->getExponent().value(), -8); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parsePMBusReadSensor(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "type": "iout", |
| "command": "0x8C", |
| "format": "linear_11", |
| "foo": 1 |
| } |
| )"_json; |
| parsePMBusReadSensor(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| |
| // Test where fails: Required type property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "command": "0x8C", |
| "format": "linear_11" |
| } |
| )"_json; |
| parsePMBusReadSensor(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: type"); |
| } |
| |
| // Test where fails: Required command property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "type": "iout", |
| "format": "linear_11" |
| } |
| )"_json; |
| parsePMBusReadSensor(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: command"); |
| } |
| |
| // Test where fails: Required format property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "type": "iout", |
| "command": "0x8C" |
| } |
| )"_json; |
| parsePMBusReadSensor(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: format"); |
| } |
| |
| // Test where fails: type value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "type": 1, |
| "command": "0x7A", |
| "format": "linear_16" |
| } |
| )"_json; |
| parsePMBusReadSensor(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: command value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "type": "temperature", |
| "command": 0, |
| "format": "linear_16" |
| } |
| )"_json; |
| parsePMBusReadSensor(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: format value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "type": "temperature", |
| "command": "0x7A", |
| "format": 1 |
| } |
| )"_json; |
| parsePMBusReadSensor(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: exponent value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "type": "temperature", |
| "command": "0x7A", |
| "format": "linear_16", |
| "exponent": 1.3 |
| } |
| )"_json; |
| parsePMBusReadSensor(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an integer"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParsePMBusWriteVoutCommand) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "format": "linear" |
| } |
| )"_json; |
| std::unique_ptr<PMBusWriteVoutCommandAction> action = |
| parsePMBusWriteVoutCommand(element); |
| EXPECT_EQ(action->getVolts().has_value(), false); |
| EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear); |
| EXPECT_EQ(action->getExponent().has_value(), false); |
| EXPECT_EQ(action->isVerified(), false); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "volts": 1.03, |
| "format": "linear", |
| "exponent": -8, |
| "is_verified": true |
| } |
| )"_json; |
| std::unique_ptr<PMBusWriteVoutCommandAction> action = |
| parsePMBusWriteVoutCommand(element); |
| EXPECT_EQ(action->getVolts().has_value(), true); |
| EXPECT_EQ(action->getVolts().value(), 1.03); |
| EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear); |
| EXPECT_EQ(action->getExponent().has_value(), true); |
| EXPECT_EQ(action->getExponent().value(), -8); |
| EXPECT_EQ(action->isVerified(), true); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parsePMBusWriteVoutCommand(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: volts value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "volts": "foo", |
| "format": "linear" |
| } |
| )"_json; |
| parsePMBusWriteVoutCommand(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a number"); |
| } |
| |
| // Test where fails: Required format property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "volts": 1.03, |
| "is_verified": true |
| } |
| )"_json; |
| parsePMBusWriteVoutCommand(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: format"); |
| } |
| |
| // Test where fails: format value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "format": "linear_11" |
| } |
| )"_json; |
| parsePMBusWriteVoutCommand(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid format value: linear_11"); |
| } |
| |
| // Test where fails: exponent value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "format": "linear", |
| "exponent": 1.3 |
| } |
| )"_json; |
| parsePMBusWriteVoutCommand(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an integer"); |
| } |
| |
| // Test where fails: is_verified value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "format": "linear", |
| "is_verified": "true" |
| } |
| )"_json; |
| parsePMBusWriteVoutCommand(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a boolean"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "format": "linear", |
| "foo": "bar" |
| } |
| )"_json; |
| parsePMBusWriteVoutCommand(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParsePresenceDetection) |
| { |
| // Test where works: actions property specified |
| { |
| const json element = R"( |
| { |
| "actions": [ |
| { "run_rule": "read_sensors_rule" } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<PresenceDetection> presenceDetection = |
| parsePresenceDetection(element); |
| EXPECT_EQ(presenceDetection->getActions().size(), 1); |
| } |
| |
| // Test where works: rule_id property specified |
| { |
| const json element = R"( |
| { |
| "comments": [ "comments property" ], |
| "rule_id": "set_voltage_rule" |
| } |
| )"_json; |
| std::unique_ptr<PresenceDetection> presenceDetection = |
| parsePresenceDetection(element); |
| EXPECT_EQ(presenceDetection->getActions().size(), 1); |
| } |
| |
| // Test where fails: actions object is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "actions": 1 |
| } |
| )"_json; |
| parsePresenceDetection(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| |
| // Test where fails: rule_id value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "rule_id": 1 |
| } |
| )"_json; |
| parsePresenceDetection(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: Required actions or rule_id property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "comments": [ "comments property" ] |
| } |
| )"_json; |
| parsePresenceDetection(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " |
| "either rule_id or actions"); |
| } |
| |
| // Test where fails: Required actions or rule_id property both specified |
| try |
| { |
| const json element = R"( |
| { |
| "rule_id": "set_voltage_rule", |
| "actions": [ |
| { "run_rule": "read_sensors_rule" } |
| ] |
| } |
| )"_json; |
| parsePresenceDetection(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " |
| "either rule_id or actions"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "foo", "bar" ] )"_json; |
| parsePresenceDetection(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "foo": "bar", |
| "actions": [ |
| { "run_rule": "read_sensors_rule" } |
| ] |
| } |
| )"_json; |
| parsePresenceDetection(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseRail) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "id": "vdd" |
| } |
| )"_json; |
| std::unique_ptr<Rail> rail = parseRail(element); |
| EXPECT_EQ(rail->getID(), "vdd"); |
| EXPECT_EQ(rail->getConfiguration(), nullptr); |
| EXPECT_EQ(rail->getSensorMonitoring(), nullptr); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "comments": [ "comments property" ], |
| "id": "vdd", |
| "configuration": { |
| "volts": 1.1, |
| "actions": [ |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| ] |
| }, |
| "sensor_monitoring": { |
| "actions": [ |
| { "run_rule": "read_sensors_rule" } |
| ] |
| } |
| } |
| )"_json; |
| std::unique_ptr<Rail> rail = parseRail(element); |
| EXPECT_EQ(rail->getID(), "vdd"); |
| EXPECT_NE(rail->getConfiguration(), nullptr); |
| EXPECT_NE(rail->getSensorMonitoring(), nullptr); |
| } |
| |
| // Test where fails: id property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "configuration": { |
| "volts": 1.1, |
| "actions": [ |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| ] |
| } |
| } |
| )"_json; |
| parseRail(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: id"); |
| } |
| |
| // Test where fails: id property is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "id": "", |
| "configuration": { |
| "volts": 1.1, |
| "actions": [ |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| ] |
| } |
| } |
| )"_json; |
| parseRail(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an empty string"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseRail(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: configuration value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd", |
| "configuration": "config" |
| } |
| )"_json; |
| parseRail(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: sensor_monitoring value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "comments": [ "comments property" ], |
| "id": "vdd", |
| "configuration": { |
| "volts": 1.1, |
| "actions": [ |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| ] |
| }, |
| "sensor_monitoring": 1 |
| } |
| )"_json; |
| parseRail(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "id": "vdd", |
| "foo" : true |
| } |
| )"_json; |
| parseRail(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseRailArray) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| [ |
| { "id": "vdd" }, |
| { "id": "vio" } |
| ] |
| )"_json; |
| std::vector<std::unique_ptr<Rail>> rails = parseRailArray(element); |
| EXPECT_EQ(rails.size(), 2); |
| EXPECT_EQ(rails[0]->getID(), "vdd"); |
| EXPECT_EQ(rails[1]->getID(), "vio"); |
| } |
| |
| // Test where fails: Element is not an array |
| try |
| { |
| const json element = R"( |
| { |
| "foo": "bar" |
| } |
| )"_json; |
| parseRailArray(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseRoot) |
| { |
| // Test where works: Only required properties specified |
| { |
| const json element = R"( |
| { |
| "chassis": [ |
| { "number": 1 } |
| ] |
| } |
| )"_json; |
| std::vector<std::unique_ptr<Rule>> rules{}; |
| std::vector<std::unique_ptr<Chassis>> chassis{}; |
| std::tie(rules, chassis) = parseRoot(element); |
| EXPECT_EQ(rules.size(), 0); |
| EXPECT_EQ(chassis.size(), 1); |
| } |
| |
| // Test where works: All properties specified |
| { |
| const json element = R"( |
| { |
| "comments": [ "Config file for a FooBar one-chassis system" ], |
| "rules": [ |
| { |
| "id": "set_voltage_rule", |
| "actions": [ |
| { "pmbus_write_vout_command": { "format": "linear" } } |
| ] |
| } |
| ], |
| "chassis": [ |
| { "number": 1 }, |
| { "number": 3 } |
| ] |
| } |
| )"_json; |
| std::vector<std::unique_ptr<Rule>> rules{}; |
| std::vector<std::unique_ptr<Chassis>> chassis{}; |
| std::tie(rules, chassis) = parseRoot(element); |
| EXPECT_EQ(rules.size(), 1); |
| EXPECT_EQ(chassis.size(), 2); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseRoot(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: chassis property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "rules": [ |
| { |
| "id": "set_voltage_rule", |
| "actions": [ |
| { "pmbus_write_vout_command": { "format": "linear" } } |
| ] |
| } |
| ] |
| } |
| )"_json; |
| parseRoot(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: chassis"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "remarks": [ "Config file for a FooBar one-chassis system" ], |
| "chassis": [ |
| { "number": 1 } |
| ] |
| } |
| )"_json; |
| parseRoot(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseRule) |
| { |
| // Test where works: comments property specified |
| { |
| const json element = R"( |
| { |
| "comments": [ "Set voltage rule" ], |
| "id": "set_voltage_rule", |
| "actions": [ |
| { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }, |
| { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<Rule> rule = parseRule(element); |
| EXPECT_EQ(rule->getID(), "set_voltage_rule"); |
| EXPECT_EQ(rule->getActions().size(), 2); |
| } |
| |
| // Test where works: comments property not specified |
| { |
| const json element = R"( |
| { |
| "id": "set_voltage_rule", |
| "actions": [ |
| { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }, |
| { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }, |
| { "pmbus_write_vout_command": { "volts": 1.05, "format": "linear" } } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<Rule> rule = parseRule(element); |
| EXPECT_EQ(rule->getID(), "set_voltage_rule"); |
| EXPECT_EQ(rule->getActions().size(), 3); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "0xFF", "0x01" ] )"_json; |
| parseRule(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: id property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "actions": [ |
| { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } } |
| ] |
| } |
| )"_json; |
| parseRule(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: id"); |
| } |
| |
| // Test where fails: id property is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "id": "", |
| "actions": [ |
| { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } } |
| ] |
| } |
| )"_json; |
| parseRule(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an empty string"); |
| } |
| |
| // Test where fails: actions property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "comments": [ "Set voltage rule" ], |
| "id": "set_voltage_rule" |
| } |
| )"_json; |
| parseRule(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Required property missing: actions"); |
| } |
| |
| // Test where fails: actions property is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "id": "set_voltage_rule", |
| "actions": true |
| } |
| )"_json; |
| parseRule(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "remarks": [ "Set voltage rule" ], |
| "id": "set_voltage_rule", |
| "actions": [ |
| { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } } |
| ] |
| } |
| )"_json; |
| parseRule(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseRuleArray) |
| { |
| // Test where works |
| { |
| const json element = R"( |
| [ |
| { |
| "id": "set_voltage_rule1", |
| "actions": [ |
| { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } } |
| ] |
| }, |
| { |
| "id": "set_voltage_rule2", |
| "actions": [ |
| { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }, |
| { "pmbus_write_vout_command": { "volts": 1.11, "format": "linear" } } |
| ] |
| } |
| ] |
| )"_json; |
| std::vector<std::unique_ptr<Rule>> rules = parseRuleArray(element); |
| EXPECT_EQ(rules.size(), 2); |
| EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1"); |
| EXPECT_EQ(rules[0]->getActions().size(), 1); |
| EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2"); |
| EXPECT_EQ(rules[1]->getActions().size(), 2); |
| } |
| |
| // Test where fails: Element is not an array |
| try |
| { |
| const json element = R"( { "id": "set_voltage_rule" } )"_json; |
| parseRuleArray(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseRuleIDOrActionsProperty) |
| { |
| // Test where works: actions specified |
| { |
| const json element = R"( |
| { |
| "actions": [ |
| { "pmbus_write_vout_command": { "format": "linear" } }, |
| { "run_rule": "set_voltage_rule" } |
| ] |
| } |
| )"_json; |
| std::vector<std::unique_ptr<Action>> actions = |
| parseRuleIDOrActionsProperty(element); |
| EXPECT_EQ(actions.size(), 2); |
| } |
| |
| // Test where works: rule_id specified |
| { |
| const json element = R"( |
| { |
| "rule_id": "set_voltage_rule" |
| } |
| )"_json; |
| std::vector<std::unique_ptr<Action>> actions = |
| parseRuleIDOrActionsProperty(element); |
| EXPECT_EQ(actions.size(), 1); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "foo", "bar" ] )"_json; |
| parseRuleIDOrActionsProperty(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: rule_id is invalid |
| try |
| { |
| const json element = R"( |
| { "rule_id": 1 } |
| )"_json; |
| parseRuleIDOrActionsProperty(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: actions is invalid |
| try |
| { |
| const json element = R"( |
| { "actions": 1 } |
| )"_json; |
| parseRuleIDOrActionsProperty(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| |
| // Test where fails: Neither rule_id nor actions specified |
| try |
| { |
| const json element = R"( |
| { |
| "volts": 1.03 |
| } |
| )"_json; |
| parseRuleIDOrActionsProperty(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " |
| "either rule_id or actions"); |
| } |
| |
| // Test where fails: Both rule_id and actions specified |
| try |
| { |
| const json element = R"( |
| { |
| "volts": 1.03, |
| "rule_id": "set_voltage_rule", |
| "actions": [ |
| { |
| "pmbus_write_vout_command": { |
| "format": "linear" |
| } |
| } |
| ] |
| } |
| )"_json; |
| parseRuleIDOrActionsProperty(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " |
| "either rule_id or actions"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseRunRule) |
| { |
| // Test where works |
| { |
| const json element = "vdd_regulator"; |
| std::unique_ptr<RunRuleAction> action = parseRunRule(element); |
| EXPECT_EQ(action->getRuleID(), "vdd_regulator"); |
| } |
| |
| // Test where fails: Element is not a string |
| try |
| { |
| const json element = 1; |
| parseRunRule(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: Empty string |
| try |
| { |
| const json element = ""; |
| parseRunRule(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an empty string"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseSensorDataFormat) |
| { |
| // Test where works: linear_11 |
| { |
| const json element = "linear_11"; |
| pmbus_utils::SensorDataFormat value = parseSensorDataFormat(element); |
| pmbus_utils::SensorDataFormat format = |
| pmbus_utils::SensorDataFormat::linear_11; |
| EXPECT_EQ(value, format); |
| } |
| |
| // Test where works: linear_16 |
| { |
| const json element = "linear_16"; |
| pmbus_utils::SensorDataFormat value = parseSensorDataFormat(element); |
| pmbus_utils::SensorDataFormat format = |
| pmbus_utils::SensorDataFormat::linear_16; |
| EXPECT_EQ(value, format); |
| } |
| |
| // Test where fails: Element is not a sensor data format |
| try |
| { |
| const json element = "foo"; |
| parseSensorDataFormat(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a sensor data format"); |
| } |
| |
| // Test where fails: Element is not a string |
| try |
| { |
| const json element = R"( { "foo": "bar" } )"_json; |
| parseSensorDataFormat(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseSensorMonitoring) |
| { |
| // Test where works: actions property specified |
| { |
| const json element = R"( |
| { |
| "actions": [ |
| { "run_rule": "read_sensors_rule" } |
| ] |
| } |
| )"_json; |
| std::unique_ptr<SensorMonitoring> sensorMonitoring = |
| parseSensorMonitoring(element); |
| EXPECT_EQ(sensorMonitoring->getActions().size(), 1); |
| } |
| |
| // Test where works: rule_id property specified |
| { |
| const json element = R"( |
| { |
| "comments": [ "comments property" ], |
| "rule_id": "set_voltage_rule" |
| } |
| )"_json; |
| std::unique_ptr<SensorMonitoring> sensorMonitoring = |
| parseSensorMonitoring(element); |
| EXPECT_EQ(sensorMonitoring->getActions().size(), 1); |
| } |
| |
| // Test where fails: actions object is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "actions": 1 |
| } |
| )"_json; |
| parseSensorMonitoring(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| |
| // Test where fails: rule_id value is invalid |
| try |
| { |
| const json element = R"( |
| { |
| "rule_id": 1 |
| } |
| )"_json; |
| parseSensorMonitoring(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: Required actions or rule_id property not specified |
| try |
| { |
| const json element = R"( |
| { |
| "comments": [ "comments property" ] |
| } |
| )"_json; |
| parseSensorMonitoring(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " |
| "either rule_id or actions"); |
| } |
| |
| // Test where fails: Required actions or rule_id property both specified |
| try |
| { |
| const json element = R"( |
| { |
| "rule_id": "set_voltage_rule", |
| "actions": [ |
| { "run_rule": "read_sensors_rule" } |
| ] |
| } |
| )"_json; |
| parseSensorMonitoring(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " |
| "either rule_id or actions"); |
| } |
| |
| // Test where fails: Element is not an object |
| try |
| { |
| const json element = R"( [ "foo", "bar" ] )"_json; |
| parseSensorMonitoring(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| |
| // Test where fails: Invalid property specified |
| try |
| { |
| const json element = R"( |
| { |
| "foo": "bar", |
| "actions": [ |
| { "run_rule": "read_sensors_rule" } |
| ] |
| } |
| )"_json; |
| parseSensorMonitoring(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseSensorValueType) |
| { |
| // Test where works: iout |
| { |
| const json element = "iout"; |
| pmbus_utils::SensorValueType value = parseSensorValueType(element); |
| pmbus_utils::SensorValueType type = pmbus_utils::SensorValueType::iout; |
| EXPECT_EQ(value, type); |
| } |
| |
| // Test where works: iout_peak |
| { |
| const json element = "iout_peak"; |
| pmbus_utils::SensorValueType value = parseSensorValueType(element); |
| pmbus_utils::SensorValueType type = |
| pmbus_utils::SensorValueType::iout_peak; |
| EXPECT_EQ(value, type); |
| } |
| |
| // Test where works: iout_valley |
| { |
| const json element = "iout_valley"; |
| pmbus_utils::SensorValueType value = parseSensorValueType(element); |
| pmbus_utils::SensorValueType type = |
| pmbus_utils::SensorValueType::iout_valley; |
| EXPECT_EQ(value, type); |
| } |
| |
| // Test where works: pout |
| { |
| const json element = "pout"; |
| pmbus_utils::SensorValueType value = parseSensorValueType(element); |
| pmbus_utils::SensorValueType type = pmbus_utils::SensorValueType::pout; |
| EXPECT_EQ(value, type); |
| } |
| |
| // Test where works: temperature |
| { |
| const json element = "temperature"; |
| pmbus_utils::SensorValueType value = parseSensorValueType(element); |
| pmbus_utils::SensorValueType type = |
| pmbus_utils::SensorValueType::temperature; |
| EXPECT_EQ(value, type); |
| } |
| |
| // Test where works: temperature_peak |
| { |
| const json element = "temperature_peak"; |
| pmbus_utils::SensorValueType value = parseSensorValueType(element); |
| pmbus_utils::SensorValueType type = |
| pmbus_utils::SensorValueType::temperature_peak; |
| EXPECT_EQ(value, type); |
| } |
| |
| // Test where works: vout |
| { |
| const json element = "vout"; |
| pmbus_utils::SensorValueType value = parseSensorValueType(element); |
| pmbus_utils::SensorValueType type = pmbus_utils::SensorValueType::vout; |
| EXPECT_EQ(value, type); |
| } |
| |
| // Test where works: vout_peak |
| { |
| const json element = "vout_peak"; |
| pmbus_utils::SensorValueType value = parseSensorValueType(element); |
| pmbus_utils::SensorValueType type = |
| pmbus_utils::SensorValueType::vout_peak; |
| EXPECT_EQ(value, type); |
| } |
| |
| // Test where works: vout_valley |
| { |
| const json element = "vout_valley"; |
| pmbus_utils::SensorValueType value = parseSensorValueType(element); |
| pmbus_utils::SensorValueType type = |
| pmbus_utils::SensorValueType::vout_valley; |
| EXPECT_EQ(value, type); |
| } |
| |
| // Test where fails: Element is not a sensor value type |
| try |
| { |
| const json element = "foo"; |
| parseSensorValueType(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a sensor value type"); |
| } |
| |
| // Test where fails: Element is not a string |
| try |
| { |
| const json element = R"( { "foo": "bar" } )"_json; |
| parseSensorValueType(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseSetDevice) |
| { |
| // Test where works |
| { |
| const json element = "regulator1"; |
| std::unique_ptr<SetDeviceAction> action = parseSetDevice(element); |
| EXPECT_EQ(action->getDeviceID(), "regulator1"); |
| } |
| |
| // Test where fails: Element is not a string |
| try |
| { |
| const json element = 1; |
| parseSetDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: Empty string |
| try |
| { |
| const json element = ""; |
| parseSetDevice(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an empty string"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseString) |
| { |
| // Test where works: Empty string |
| { |
| const json element = ""; |
| std::string value = parseString(element, true); |
| EXPECT_EQ(value, ""); |
| } |
| |
| // Test where works: Non-empty string |
| { |
| const json element = "vdd_regulator"; |
| std::string value = parseString(element, false); |
| EXPECT_EQ(value, "vdd_regulator"); |
| } |
| |
| // Test where fails: Element is not a string |
| try |
| { |
| const json element = R"( { "foo": "bar" } )"_json; |
| parseString(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| |
| // Test where fails: Empty string |
| try |
| { |
| const json element = ""; |
| parseString(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an empty string"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseUint8) |
| { |
| // Test where works: 0 |
| { |
| const json element = R"( 0 )"_json; |
| uint8_t value = parseUint8(element); |
| EXPECT_EQ(value, 0); |
| } |
| |
| // Test where works: UINT8_MAX |
| { |
| const json element = R"( 255 )"_json; |
| uint8_t value = parseUint8(element); |
| EXPECT_EQ(value, 255); |
| } |
| |
| // Test where fails: Element is not an integer |
| try |
| { |
| const json element = R"( 1.03 )"_json; |
| parseUint8(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an integer"); |
| } |
| |
| // Test where fails: Value < 0 |
| try |
| { |
| const json element = R"( -1 )"_json; |
| parseUint8(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); |
| } |
| |
| // Test where fails: Value > UINT8_MAX |
| try |
| { |
| const json element = R"( 256 )"_json; |
| parseUint8(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseUnsignedInteger) |
| { |
| // Test where works: 1 |
| { |
| const json element = R"( 1 )"_json; |
| unsigned int value = parseUnsignedInteger(element); |
| EXPECT_EQ(value, 1); |
| } |
| |
| // Test where fails: Element is not an integer |
| try |
| { |
| const json element = R"( 1.5 )"_json; |
| parseUnsignedInteger(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); |
| } |
| |
| // Test where fails: Value < 0 |
| try |
| { |
| const json element = R"( -1 )"_json; |
| parseUnsignedInteger(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, ParseVoutDataFormat) |
| { |
| // Test where works: linear |
| { |
| const json element = "linear"; |
| pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element); |
| pmbus_utils::VoutDataFormat format = |
| pmbus_utils::VoutDataFormat::linear; |
| EXPECT_EQ(value, format); |
| } |
| |
| // Test where works: vid |
| { |
| const json element = "vid"; |
| pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element); |
| pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::vid; |
| EXPECT_EQ(value, format); |
| } |
| |
| // Test where works: direct |
| { |
| const json element = "direct"; |
| pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element); |
| pmbus_utils::VoutDataFormat format = |
| pmbus_utils::VoutDataFormat::direct; |
| EXPECT_EQ(value, format); |
| } |
| |
| // Test where works: ieee |
| { |
| const json element = "ieee"; |
| pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element); |
| pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::ieee; |
| EXPECT_EQ(value, format); |
| } |
| |
| // Test where fails: Element is not a vout data format |
| try |
| { |
| const json element = "foo"; |
| parseVoutDataFormat(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a vout data format"); |
| } |
| |
| // Test where fails: Element is not a string |
| try |
| { |
| const json element = R"( { "foo": "bar" } )"_json; |
| parseVoutDataFormat(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not a string"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, VerifyIsArray) |
| { |
| // Test where element is an array |
| try |
| { |
| const json element = R"( [ "foo", "bar" ] )"_json; |
| verifyIsArray(element); |
| } |
| catch (const std::exception& e) |
| { |
| ADD_FAILURE() << "Should not have caught exception."; |
| } |
| |
| // Test where element is not an array |
| try |
| { |
| const json element = R"( { "foo": "bar" } )"_json; |
| verifyIsArray(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an array"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, VerifyIsObject) |
| { |
| // Test where element is an object |
| try |
| { |
| const json element = R"( { "foo": "bar" } )"_json; |
| verifyIsObject(element); |
| } |
| catch (const std::exception& e) |
| { |
| ADD_FAILURE() << "Should not have caught exception."; |
| } |
| |
| // Test where element is not an object |
| try |
| { |
| const json element = R"( [ "foo", "bar" ] )"_json; |
| verifyIsObject(element); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element is not an object"); |
| } |
| } |
| |
| TEST(ConfigFileParserTests, VerifyPropertyCount) |
| { |
| // Test where element has expected number of properties |
| try |
| { |
| const json element = R"( |
| { |
| "comments": [ "Set voltage rule" ], |
| "id": "set_voltage_rule" |
| } |
| )"_json; |
| verifyPropertyCount(element, 2); |
| } |
| catch (const std::exception& e) |
| { |
| ADD_FAILURE() << "Should not have caught exception."; |
| } |
| |
| // Test where element has unexpected number of properties |
| try |
| { |
| const json element = R"( |
| { |
| "comments": [ "Set voltage rule" ], |
| "id": "set_voltage_rule", |
| "foo": 1.3 |
| } |
| )"_json; |
| verifyPropertyCount(element, 2); |
| ADD_FAILURE() << "Should not have reached this line."; |
| } |
| catch (const std::invalid_argument& e) |
| { |
| EXPECT_STREQ(e.what(), "Element contains an invalid property"); |
| } |
| } |