/** * Copyright © 2025 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 "json_parser_utils.hpp" #include #include #include #include #include #include #include using namespace phosphor::power::json_parser_utils; using namespace phosphor::power::json_parser_utils::internal; using json = nlohmann::json; TEST(JSONParserUtilsTests, GetRequiredProperty) { // Test where property exists { const json element = R"( { "format": "linear" } )"_json; const json& propertyElement = getRequiredProperty(element, "format"); EXPECT_EQ(propertyElement.get(), "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(JSONParserUtilsTests, 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 works: Variable specified { std::map variables{{"bit_pos", "3"}}; const json element = R"( "${bit_pos}" )"_json; uint8_t value = parseBitPosition(element, variables); EXPECT_EQ(value, 3); } // 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 where fails: Variable specified: Value < 0 try { std::map variables{{"bit_pos", "-1"}}; const json element = R"( "${bit_pos}" )"_json; parseBitPosition(element, variables); 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(JSONParserUtilsTests, 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 works: Variable specified { std::map variables{{"bit_val", "1"}}; const json element = R"( "${bit_val}" )"_json; uint8_t value = parseBitValue(element, variables); 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 where fails: Variable specified: Not an integer try { std::map variables{{"bit_val", "one"}}; const json element = R"( "${bit_val}" )"_json; parseBitValue(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not an integer"); } } TEST(JSONParserUtilsTests, 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 works: Variable specified: true { std::map variables{{"bool_val", "true"}}; const json element = R"( "${bool_val}" )"_json; bool value = parseBoolean(element, variables); EXPECT_EQ(value, true); } // Test where works: Variable specified: false { std::map variables{{"bool_val", "false"}}; const json element = R"( "${bool_val}" )"_json; bool value = parseBoolean(element, variables); 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 where fails: Variable specified: Variables map not specified try { const json element = R"( "${bool_val}" )"_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 where fails: Variable specified: Value is not a boolean try { std::map variables{{"bool_val", "3.2"}}; const json element = R"( "${bool_val}" )"_json; parseBoolean(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not a boolean"); } } TEST(JSONParserUtilsTests, 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 works: Variable specified: Floating point value { std::map variables{{"var", "-1.03"}}; const json element = R"( "${var}" )"_json; double value = parseDouble(element, variables); EXPECT_EQ(value, -1.03); } // Test where works: Variable specified: Integer value { std::map variables{{"var", "24"}}; const json element = R"( "${var}" )"_json; double value = parseDouble(element, variables); EXPECT_EQ(value, 24.0); } // Test where fails: Element is not a double 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 double"); } // Test where fails: Variable specified: Variables map not specified try { const json element = R"( "${var}" )"_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 double"); } // Test where fails: Variable specified: Leading whitespace try { std::map variables{{"var", " -1.03"}}; const json element = R"( "${var}" )"_json; parseDouble(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not a double"); } // Test where fails: Variable specified: Trailing whitespace try { std::map variables{{"var", "-1.03 "}}; const json element = R"( "${var}" )"_json; parseDouble(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not a double"); } // Test where fails: Variable specified: Starts with non-number character try { std::map variables{{"var", "x-1.03"}}; const json element = R"( "${var}" )"_json; parseDouble(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not a double"); } // Test where fails: Variable specified: Ends with non-number character try { std::map variables{{"var", "-1.03x"}}; const json element = R"( "${var}" )"_json; parseDouble(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not a double"); } // Test where fails: Variable specified: Not a double try { std::map variables{{"var", "foo"}}; const json element = R"( "${var}" )"_json; parseDouble(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not a double"); } } TEST(JSONParserUtilsTests, 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 works: Variable specified { std::map variables{{"var", "ed"}}; const json element = R"( "0x${var}" )"_json; uint8_t value = parseHexByte(element, variables); EXPECT_EQ(value, 0xed); } // 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 where fails: Variable specified: Not a hex string try { std::map variables{{"var", "0xsz"}}; const json element = R"( "${var}" )"_json; parseHexByte(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); } } TEST(JSONParserUtilsTests, ParseHexByteArray) { // Test where works { const json element = R"( [ "0xCC", "0xFF" ] )"_json; std::vector hexBytes = parseHexByteArray(element); std::vector expected = {0xcc, 0xff}; EXPECT_EQ(hexBytes, expected); } // Test where works: Variables specified { std::map variables{{"var1", "0xCC"}, {"var2", "0xFF"}}; const json element = R"( [ "${var1}", "${var2}" ] )"_json; std::vector hexBytes = parseHexByteArray(element, variables); std::vector 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 where fails: Variables specified: Invalid byte value try { std::map variables{{"var1", "0xCC"}, {"var2", "99"}}; const json element = R"( [ "${var1}", "${var2}" ] )"_json; parseHexByteArray(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); } } TEST(JSONParserUtilsTests, 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 works: Variable specified { std::map variables{{"var", "-23"}}; const json element = R"( "${var}" )"_json; int8_t value = parseInt8(element, variables); EXPECT_EQ(value, -23); } // 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 where fails: Variable specified: Value > INT8_MAX try { std::map variables{{"var", "128"}}; const json element = R"( "${var}" )"_json; parseInt8(element, variables); 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(JSONParserUtilsTests, ParseInteger) { // Test where works: Zero { const json element = R"( 0 )"_json; int value = parseInteger(element); EXPECT_EQ(value, 0); } // Test where works: Positive value { const json element = R"( 103 )"_json; int value = parseInteger(element); EXPECT_EQ(value, 103); } // Test where works: Negative value { const json element = R"( -24 )"_json; int value = parseInteger(element); EXPECT_EQ(value, -24); } // Test where works: Variable specified: Positive value { std::map variables{{"var", "1024"}}; const json element = R"( "${var}" )"_json; int value = parseInteger(element, variables); EXPECT_EQ(value, 1024); } // Test where works: Variable specified: Negative value { std::map variables{{"var", "-9924"}}; const json element = R"( "${var}" )"_json; int value = parseInteger(element, variables); EXPECT_EQ(value, -9924); } // Test where fails: Element is not a integer try { const json element = R"( true )"_json; parseInteger(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: Variable specified: Variables map not specified try { const json element = R"( "${var}" )"_json; parseInteger(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: Variable specified: Leading whitespace try { std::map variables{{"var", " -13"}}; const json element = R"( "${var}" )"_json; parseInteger(element, variables); 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: Variable specified: Trailing whitespace try { std::map variables{{"var", "-13 "}}; const json element = R"( "${var}" )"_json; parseInteger(element, variables); 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: Variable specified: Starts with non-number character try { std::map variables{{"var", "x-13"}}; const json element = R"( "${var}" )"_json; parseInteger(element, variables); 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: Variable specified: Ends with non-number character try { std::map variables{{"var", "-13x"}}; const json element = R"( "${var}" )"_json; parseInteger(element, variables); 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: Variable specified: Not an integer try { std::map variables{{"var", "foo"}}; const json element = R"( "${var}" )"_json; parseInteger(element, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Element is not an integer"); } } TEST(JSONParserUtilsTests, 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 works: Variable specified: Empty string { std::map variables{{"var", ""}}; const json element = R"( "${var}" )"_json; std::string value = parseString(element, true, variables); EXPECT_EQ(value, ""); } // Test where works: Variable specified: Non-empty string { std::map variables{{"var", "vio_regulator"}}; const json element = R"( "${var}" )"_json; std::string value = parseString(element, false, variables); EXPECT_EQ(value, "vio_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 where fails: Variable specified: Empty string try { std::map variables{{"var", ""}}; const json element = R"( "${var}" )"_json; parseString(element, false, variables); 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: Variable specified: Variable not defined try { std::map variables{{"var1", "foo"}}; const json element = R"( "${var2}" )"_json; parseString(element, false, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Undefined variable: var2"); } } TEST(JSONParserUtilsTests, 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 works: Variable specified { std::map variables{{"var", "19"}}; const json element = R"( "${var}" )"_json; uint8_t value = parseUint8(element, variables); EXPECT_EQ(value, 19); } // 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 where fails: Variable specified: Value > UINT8_MAX try { std::map variables{{"var", "256"}}; const json element = R"( "${var}" )"_json; parseUint8(element, variables); 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(JSONParserUtilsTests, ParseUnsignedInteger) { // Test where works: 1 { const json element = R"( 1 )"_json; unsigned int value = parseUnsignedInteger(element); EXPECT_EQ(value, 1); } // Test where works: Variable specified { std::map variables{{"var", "25678"}}; const json element = R"( "${var}" )"_json; unsigned int value = parseUnsignedInteger(element, variables); EXPECT_EQ(value, 25678); } // 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 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 where fails: Variable specified: Value < 0 try { std::map variables{{"var", "-23"}}; const json element = R"( "${var}" )"_json; parseUnsignedInteger(element, variables); 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(JSONParserUtilsTests, VerifyIsArray) { // Test where element is an array { const json element = R"( [ "foo", "bar" ] )"_json; verifyIsArray(element); } // 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(JSONParserUtilsTests, VerifyIsObject) { // Test where element is an object { const json element = R"( { "foo": "bar" } )"_json; verifyIsObject(element); } // 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(JSONParserUtilsTests, VerifyPropertyCount) { // Test where element has expected number of properties { const json element = R"( { "comments": [ "Set voltage rule" ], "id": "set_voltage_rule" } )"_json; verifyPropertyCount(element, 2); } // 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"); } } TEST(JSONParserUtilsTests, ExpandVariables) { // Test where works: Single variable: Variable is entire value: Lower case // in variable name { std::map variables{{"var", "vio_regulator"}}; std::string value{"${var}"}; expandVariables(value, variables); EXPECT_EQ(value, "vio_regulator"); } // Test where works: Multiple variables: Variables are part of value: Upper // case and underscore in variable name { std::map variables{ {"CHASSIS_NUMBER", "1"}, {"REGULATOR", "vcs_vio"}, {"RAIL", "vio"}}; std::string value{ "chassis${CHASSIS_NUMBER}_${REGULATOR}_regulator_${RAIL}_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "chassis1_vcs_vio_regulator_vio_rail"); } // Test where works: Variable at start of value: Number in variable name { std::map variables{{"var1", "vio_regulator"}}; std::string value{"${var1}_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "vio_regulator_rail"); } // Test where works: Variable at end of value { std::map variables{{"chassis_number", "3"}}; std::string value{ "/xyz/openbmc_project/inventory/system/chassis${chassis_number}"}; expandVariables(value, variables); EXPECT_EQ(value, "/xyz/openbmc_project/inventory/system/chassis3"); } // Test where works: Variable has empty value: Start of value { std::map variables{{"chassis_prefix", ""}}; std::string value{"${chassis_prefix}vio_regulator"}; expandVariables(value, variables); EXPECT_EQ(value, "vio_regulator"); } // Test where works: Variable has empty value: Middle of value { std::map variables{{"chassis_number", ""}}; std::string value{"c${chassis_number}_vio_regulator"}; expandVariables(value, variables); EXPECT_EQ(value, "c_vio_regulator"); } // Test where works: Variable has empty value: End of value { std::map variables{{"chassis_number", ""}}; std::string value{ "/xyz/openbmc_project/inventory/system/chassis${chassis_number}"}; expandVariables(value, variables); EXPECT_EQ(value, "/xyz/openbmc_project/inventory/system/chassis"); } // Test where works: No variables specified { std::map variables{{"var", "vio_regulator"}}; std::string value{"vcs_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "vcs_rail"); } // Test where works: Nested variable expansion { std::map variables{{"var1", "${var2}"}, {"var2", "vio_reg"}}; std::string value{"${var1}_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "vio_reg_rail"); } // Test where fails: Variables map is empty { std::map variables{}; std::string value{"${var}_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "${var}_rail"); } // Test where fails: Variable missing $ { std::map variables{{"var", "vio_reg"}}; std::string value{"{var}_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "{var}_rail"); } // Test where fails: Variable missing { { std::map variables{{"var", "vio_reg"}}; std::string value{"$var}_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "$var}_rail"); } // Test where fails: Variable missing } { std::map variables{{"var", "vio_reg"}}; std::string value{"${var_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "${var_rail"); } // Test where fails: Variable missing name { std::map variables{{"var", "vio_reg"}}; std::string value{"${}_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "${}_rail"); } // Test where fails: Variable name has invalid characters { std::map variables{{"var-2", "vio_reg"}}; std::string value{"${var-2}_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "${var-2}_rail"); } // Test where fails: Variable has unexpected whitespace { std::map variables{{"var", "vio_reg"}}; std::string value{"${ var }_rail"}; expandVariables(value, variables); EXPECT_EQ(value, "${ var }_rail"); } // Test where fails: Undefined variable try { std::map variables{{"var", "vio_reg"}}; std::string value{"${foo}_rail"}; expandVariables(value, variables); ADD_FAILURE() << "Should not have reached this line."; } catch (const std::invalid_argument& e) { EXPECT_STREQ(e.what(), "Undefined variable: foo"); } }