blob: e4f591c73a0a536bbcc45d4ba792de572456b83c [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 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 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(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 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(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 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(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 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(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 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(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 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(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 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(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 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(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 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(JSONParserUtilsTests, 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(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");
}
}