blob: 4660aa07bc1151b73a32113c0c2053f1a99d95dc [file] [log] [blame]
/**
* 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 <nlohmann/json.hpp>
#include <cstdint>
#include <exception>
#include <stdexcept>
#include <string>
#include <vector>
#include <gtest/gtest.h>
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<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(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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<uint8_t> hexBytes = parseHexByteArray(element);
std::vector<uint8_t> expected = {0xcc, 0xff};
EXPECT_EQ(hexBytes, expected);
}
// Test where works: Variables specified
{
std::map<std::string, std::string> variables{{"var1", "0xCC"},
{"var2", "0xFF"}};
const json element = R"( [ "${var1}", "${var2}" ] )"_json;
std::vector<uint8_t> hexBytes = parseHexByteArray(element, variables);
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 where fails: Variables specified: Invalid byte value
try
{
std::map<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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, ParseUint16)
{
// Test where works: 0
{
const json element = R"( 0 )"_json;
uint16_t value = parseUint16(element);
EXPECT_EQ(value, 0);
}
// Test where works: UINT16_MAX
{
const json element = R"( 65535 )"_json;
uint16_t value = parseUint16(element);
EXPECT_EQ(value, 65535);
}
// Test where works: Variable specified
{
std::map<std::string, std::string> variables{{"var", "24699"}};
const json element = R"( "${var}" )"_json;
uint16_t value = parseUint16(element, variables);
EXPECT_EQ(value, 24699);
}
// Test where fails: Element is not an integer
try
{
const json element = R"( 1.03 )"_json;
parseUint16(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;
parseUint16(element);
ADD_FAILURE() << "Should not have reached this line.";
}
catch (const std::invalid_argument& e)
{
EXPECT_STREQ(e.what(), "Element is not a 16-bit unsigned integer");
}
// Test where fails: Value > UINT16_MAX
try
{
const json element = R"( 65536 )"_json;
parseUint16(element);
ADD_FAILURE() << "Should not have reached this line.";
}
catch (const std::invalid_argument& e)
{
EXPECT_STREQ(e.what(), "Element is not a 16-bit unsigned integer");
}
// Test where fails: Variable specified: Value > UINT16_MAX
try
{
std::map<std::string, std::string> variables{{"var", "65536"}};
const json element = R"( "${var}" )"_json;
parseUint16(element, variables);
ADD_FAILURE() << "Should not have reached this line.";
}
catch (const std::invalid_argument& e)
{
EXPECT_STREQ(e.what(), "Element is not a 16-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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> variables{};
std::string value{"${var}_rail"};
expandVariables(value, variables);
EXPECT_EQ(value, "${var}_rail");
}
// Test where fails: Variable missing $
{
std::map<std::string, std::string> variables{{"var", "vio_reg"}};
std::string value{"{var}_rail"};
expandVariables(value, variables);
EXPECT_EQ(value, "{var}_rail");
}
// Test where fails: Variable missing {
{
std::map<std::string, std::string> variables{{"var", "vio_reg"}};
std::string value{"$var}_rail"};
expandVariables(value, variables);
EXPECT_EQ(value, "$var}_rail");
}
// Test where fails: Variable missing }
{
std::map<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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");
}
}