138f85004SShawn McCarney /** 238f85004SShawn McCarney * Copyright © 2025 IBM Corporation 338f85004SShawn McCarney * 438f85004SShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License"); 538f85004SShawn McCarney * you may not use this file except in compliance with the License. 638f85004SShawn McCarney * You may obtain a copy of the License at 738f85004SShawn McCarney * 838f85004SShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0 938f85004SShawn McCarney * 1038f85004SShawn McCarney * Unless required by applicable law or agreed to in writing, software 1138f85004SShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS, 1238f85004SShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1338f85004SShawn McCarney * See the License for the specific language governing permissions and 1438f85004SShawn McCarney * limitations under the License. 1538f85004SShawn McCarney */ 1638f85004SShawn McCarney #include "json_parser_utils.hpp" 1738f85004SShawn McCarney 1838f85004SShawn McCarney #include <nlohmann/json.hpp> 1938f85004SShawn McCarney 2038f85004SShawn McCarney #include <cstdint> 2138f85004SShawn McCarney #include <exception> 2238f85004SShawn McCarney #include <stdexcept> 2338f85004SShawn McCarney #include <string> 2438f85004SShawn McCarney #include <vector> 2538f85004SShawn McCarney 2638f85004SShawn McCarney #include <gtest/gtest.h> 2738f85004SShawn McCarney 2838f85004SShawn McCarney using namespace phosphor::power::json_parser_utils; 29*f1845c06SShawn McCarney using namespace phosphor::power::json_parser_utils::internal; 3038f85004SShawn McCarney using json = nlohmann::json; 3138f85004SShawn McCarney 3238f85004SShawn McCarney TEST(JSONParserUtilsTests, GetRequiredProperty) 3338f85004SShawn McCarney { 3438f85004SShawn McCarney // Test where property exists 3538f85004SShawn McCarney { 3638f85004SShawn McCarney const json element = R"( { "format": "linear" } )"_json; 3738f85004SShawn McCarney const json& propertyElement = getRequiredProperty(element, "format"); 3838f85004SShawn McCarney EXPECT_EQ(propertyElement.get<std::string>(), "linear"); 3938f85004SShawn McCarney } 4038f85004SShawn McCarney 4138f85004SShawn McCarney // Test where property does not exist 4238f85004SShawn McCarney try 4338f85004SShawn McCarney { 4438f85004SShawn McCarney const json element = R"( { "volts": 1.03 } )"_json; 4538f85004SShawn McCarney getRequiredProperty(element, "format"); 4638f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 4738f85004SShawn McCarney } 4838f85004SShawn McCarney catch (const std::invalid_argument& e) 4938f85004SShawn McCarney { 5038f85004SShawn McCarney EXPECT_STREQ(e.what(), "Required property missing: format"); 5138f85004SShawn McCarney } 5238f85004SShawn McCarney } 5338f85004SShawn McCarney 5438f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseBitPosition) 5538f85004SShawn McCarney { 5638f85004SShawn McCarney // Test where works: 0 5738f85004SShawn McCarney { 5838f85004SShawn McCarney const json element = R"( 0 )"_json; 5938f85004SShawn McCarney uint8_t value = parseBitPosition(element); 6038f85004SShawn McCarney EXPECT_EQ(value, 0); 6138f85004SShawn McCarney } 6238f85004SShawn McCarney 6338f85004SShawn McCarney // Test where works: 7 6438f85004SShawn McCarney { 6538f85004SShawn McCarney const json element = R"( 7 )"_json; 6638f85004SShawn McCarney uint8_t value = parseBitPosition(element); 6738f85004SShawn McCarney EXPECT_EQ(value, 7); 6838f85004SShawn McCarney } 6938f85004SShawn McCarney 70*f1845c06SShawn McCarney // Test where works: Variable specified 71*f1845c06SShawn McCarney { 72*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"bit_pos", "3"}}; 73*f1845c06SShawn McCarney const json element = R"( "${bit_pos}" )"_json; 74*f1845c06SShawn McCarney uint8_t value = parseBitPosition(element, variables); 75*f1845c06SShawn McCarney EXPECT_EQ(value, 3); 76*f1845c06SShawn McCarney } 77*f1845c06SShawn McCarney 7838f85004SShawn McCarney // Test where fails: Element is not an integer 7938f85004SShawn McCarney try 8038f85004SShawn McCarney { 8138f85004SShawn McCarney const json element = R"( 1.03 )"_json; 8238f85004SShawn McCarney parseBitPosition(element); 8338f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 8438f85004SShawn McCarney } 8538f85004SShawn McCarney catch (const std::invalid_argument& e) 8638f85004SShawn McCarney { 8738f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 8838f85004SShawn McCarney } 8938f85004SShawn McCarney 9038f85004SShawn McCarney // Test where fails: Value < 0 9138f85004SShawn McCarney try 9238f85004SShawn McCarney { 9338f85004SShawn McCarney const json element = R"( -1 )"_json; 9438f85004SShawn McCarney parseBitPosition(element); 9538f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 9638f85004SShawn McCarney } 9738f85004SShawn McCarney catch (const std::invalid_argument& e) 9838f85004SShawn McCarney { 9938f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a bit position"); 10038f85004SShawn McCarney } 10138f85004SShawn McCarney 10238f85004SShawn McCarney // Test where fails: Value > 7 10338f85004SShawn McCarney try 10438f85004SShawn McCarney { 10538f85004SShawn McCarney const json element = R"( 8 )"_json; 10638f85004SShawn McCarney parseBitPosition(element); 10738f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 10838f85004SShawn McCarney } 10938f85004SShawn McCarney catch (const std::invalid_argument& e) 11038f85004SShawn McCarney { 11138f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a bit position"); 11238f85004SShawn McCarney } 113*f1845c06SShawn McCarney 114*f1845c06SShawn McCarney // Test where fails: Variable specified: Value < 0 115*f1845c06SShawn McCarney try 116*f1845c06SShawn McCarney { 117*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"bit_pos", "-1"}}; 118*f1845c06SShawn McCarney const json element = R"( "${bit_pos}" )"_json; 119*f1845c06SShawn McCarney parseBitPosition(element, variables); 120*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 121*f1845c06SShawn McCarney } 122*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 123*f1845c06SShawn McCarney { 124*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a bit position"); 125*f1845c06SShawn McCarney } 12638f85004SShawn McCarney } 12738f85004SShawn McCarney 12838f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseBitValue) 12938f85004SShawn McCarney { 13038f85004SShawn McCarney // Test where works: 0 13138f85004SShawn McCarney { 13238f85004SShawn McCarney const json element = R"( 0 )"_json; 13338f85004SShawn McCarney uint8_t value = parseBitValue(element); 13438f85004SShawn McCarney EXPECT_EQ(value, 0); 13538f85004SShawn McCarney } 13638f85004SShawn McCarney 13738f85004SShawn McCarney // Test where works: 1 13838f85004SShawn McCarney { 13938f85004SShawn McCarney const json element = R"( 1 )"_json; 14038f85004SShawn McCarney uint8_t value = parseBitValue(element); 14138f85004SShawn McCarney EXPECT_EQ(value, 1); 14238f85004SShawn McCarney } 14338f85004SShawn McCarney 144*f1845c06SShawn McCarney // Test where works: Variable specified 145*f1845c06SShawn McCarney { 146*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"bit_val", "1"}}; 147*f1845c06SShawn McCarney const json element = R"( "${bit_val}" )"_json; 148*f1845c06SShawn McCarney uint8_t value = parseBitValue(element, variables); 149*f1845c06SShawn McCarney EXPECT_EQ(value, 1); 150*f1845c06SShawn McCarney } 151*f1845c06SShawn McCarney 15238f85004SShawn McCarney // Test where fails: Element is not an integer 15338f85004SShawn McCarney try 15438f85004SShawn McCarney { 15538f85004SShawn McCarney const json element = R"( 0.5 )"_json; 15638f85004SShawn McCarney parseBitValue(element); 15738f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 15838f85004SShawn McCarney } 15938f85004SShawn McCarney catch (const std::invalid_argument& e) 16038f85004SShawn McCarney { 16138f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 16238f85004SShawn McCarney } 16338f85004SShawn McCarney 16438f85004SShawn McCarney // Test where fails: Value < 0 16538f85004SShawn McCarney try 16638f85004SShawn McCarney { 16738f85004SShawn McCarney const json element = R"( -1 )"_json; 16838f85004SShawn McCarney parseBitValue(element); 16938f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 17038f85004SShawn McCarney } 17138f85004SShawn McCarney catch (const std::invalid_argument& e) 17238f85004SShawn McCarney { 17338f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a bit value"); 17438f85004SShawn McCarney } 17538f85004SShawn McCarney 17638f85004SShawn McCarney // Test where fails: Value > 1 17738f85004SShawn McCarney try 17838f85004SShawn McCarney { 17938f85004SShawn McCarney const json element = R"( 2 )"_json; 18038f85004SShawn McCarney parseBitValue(element); 18138f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 18238f85004SShawn McCarney } 18338f85004SShawn McCarney catch (const std::invalid_argument& e) 18438f85004SShawn McCarney { 18538f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a bit value"); 18638f85004SShawn McCarney } 187*f1845c06SShawn McCarney 188*f1845c06SShawn McCarney // Test where fails: Variable specified: Not an integer 189*f1845c06SShawn McCarney try 190*f1845c06SShawn McCarney { 191*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"bit_val", "one"}}; 192*f1845c06SShawn McCarney const json element = R"( "${bit_val}" )"_json; 193*f1845c06SShawn McCarney parseBitValue(element, variables); 194*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 195*f1845c06SShawn McCarney } 196*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 197*f1845c06SShawn McCarney { 198*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 199*f1845c06SShawn McCarney } 20038f85004SShawn McCarney } 20138f85004SShawn McCarney 20238f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseBoolean) 20338f85004SShawn McCarney { 20438f85004SShawn McCarney // Test where works: true 20538f85004SShawn McCarney { 20638f85004SShawn McCarney const json element = R"( true )"_json; 20738f85004SShawn McCarney bool value = parseBoolean(element); 20838f85004SShawn McCarney EXPECT_EQ(value, true); 20938f85004SShawn McCarney } 21038f85004SShawn McCarney 21138f85004SShawn McCarney // Test where works: false 21238f85004SShawn McCarney { 21338f85004SShawn McCarney const json element = R"( false )"_json; 21438f85004SShawn McCarney bool value = parseBoolean(element); 21538f85004SShawn McCarney EXPECT_EQ(value, false); 21638f85004SShawn McCarney } 21738f85004SShawn McCarney 218*f1845c06SShawn McCarney // Test where works: Variable specified: true 219*f1845c06SShawn McCarney { 220*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"bool_val", "true"}}; 221*f1845c06SShawn McCarney const json element = R"( "${bool_val}" )"_json; 222*f1845c06SShawn McCarney bool value = parseBoolean(element, variables); 223*f1845c06SShawn McCarney EXPECT_EQ(value, true); 224*f1845c06SShawn McCarney } 225*f1845c06SShawn McCarney 226*f1845c06SShawn McCarney // Test where works: Variable specified: false 227*f1845c06SShawn McCarney { 228*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"bool_val", "false"}}; 229*f1845c06SShawn McCarney const json element = R"( "${bool_val}" )"_json; 230*f1845c06SShawn McCarney bool value = parseBoolean(element, variables); 231*f1845c06SShawn McCarney EXPECT_EQ(value, false); 232*f1845c06SShawn McCarney } 233*f1845c06SShawn McCarney 23438f85004SShawn McCarney // Test where fails: Element is not a boolean 23538f85004SShawn McCarney try 23638f85004SShawn McCarney { 23738f85004SShawn McCarney const json element = R"( 1 )"_json; 23838f85004SShawn McCarney parseBoolean(element); 23938f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 24038f85004SShawn McCarney } 24138f85004SShawn McCarney catch (const std::invalid_argument& e) 24238f85004SShawn McCarney { 24338f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a boolean"); 24438f85004SShawn McCarney } 245*f1845c06SShawn McCarney 246*f1845c06SShawn McCarney // Test where fails: Variable specified: Variables map not specified 247*f1845c06SShawn McCarney try 248*f1845c06SShawn McCarney { 249*f1845c06SShawn McCarney const json element = R"( "${bool_val}" )"_json; 250*f1845c06SShawn McCarney parseBoolean(element); 251*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 252*f1845c06SShawn McCarney } 253*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 254*f1845c06SShawn McCarney { 255*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a boolean"); 256*f1845c06SShawn McCarney } 257*f1845c06SShawn McCarney 258*f1845c06SShawn McCarney // Test where fails: Variable specified: Value is not a boolean 259*f1845c06SShawn McCarney try 260*f1845c06SShawn McCarney { 261*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"bool_val", "3.2"}}; 262*f1845c06SShawn McCarney const json element = R"( "${bool_val}" )"_json; 263*f1845c06SShawn McCarney parseBoolean(element, variables); 264*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 265*f1845c06SShawn McCarney } 266*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 267*f1845c06SShawn McCarney { 268*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a boolean"); 269*f1845c06SShawn McCarney } 27038f85004SShawn McCarney } 27138f85004SShawn McCarney 27238f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseDouble) 27338f85004SShawn McCarney { 274*f1845c06SShawn McCarney // Test where works: Floating point value 27538f85004SShawn McCarney { 27638f85004SShawn McCarney const json element = R"( 1.03 )"_json; 27738f85004SShawn McCarney double value = parseDouble(element); 27838f85004SShawn McCarney EXPECT_EQ(value, 1.03); 27938f85004SShawn McCarney } 28038f85004SShawn McCarney 281*f1845c06SShawn McCarney // Test where works: Integer value 28238f85004SShawn McCarney { 283*f1845c06SShawn McCarney const json element = R"( -24 )"_json; 28438f85004SShawn McCarney double value = parseDouble(element); 285*f1845c06SShawn McCarney EXPECT_EQ(value, -24.0); 286*f1845c06SShawn McCarney } 287*f1845c06SShawn McCarney 288*f1845c06SShawn McCarney // Test where works: Variable specified: Floating point value 289*f1845c06SShawn McCarney { 290*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "-1.03"}}; 291*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 292*f1845c06SShawn McCarney double value = parseDouble(element, variables); 293*f1845c06SShawn McCarney EXPECT_EQ(value, -1.03); 294*f1845c06SShawn McCarney } 295*f1845c06SShawn McCarney 296*f1845c06SShawn McCarney // Test where works: Variable specified: Integer value 297*f1845c06SShawn McCarney { 298*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "24"}}; 299*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 300*f1845c06SShawn McCarney double value = parseDouble(element, variables); 30138f85004SShawn McCarney EXPECT_EQ(value, 24.0); 30238f85004SShawn McCarney } 30338f85004SShawn McCarney 304*f1845c06SShawn McCarney // Test where fails: Element is not a double 30538f85004SShawn McCarney try 30638f85004SShawn McCarney { 30738f85004SShawn McCarney const json element = R"( true )"_json; 30838f85004SShawn McCarney parseDouble(element); 30938f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 31038f85004SShawn McCarney } 31138f85004SShawn McCarney catch (const std::invalid_argument& e) 31238f85004SShawn McCarney { 313*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a double"); 314*f1845c06SShawn McCarney } 315*f1845c06SShawn McCarney 316*f1845c06SShawn McCarney // Test where fails: Variable specified: Variables map not specified 317*f1845c06SShawn McCarney try 318*f1845c06SShawn McCarney { 319*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 320*f1845c06SShawn McCarney parseDouble(element); 321*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 322*f1845c06SShawn McCarney } 323*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 324*f1845c06SShawn McCarney { 325*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a double"); 326*f1845c06SShawn McCarney } 327*f1845c06SShawn McCarney 328*f1845c06SShawn McCarney // Test where fails: Variable specified: Leading whitespace 329*f1845c06SShawn McCarney try 330*f1845c06SShawn McCarney { 331*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", " -1.03"}}; 332*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 333*f1845c06SShawn McCarney parseDouble(element, variables); 334*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 335*f1845c06SShawn McCarney } 336*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 337*f1845c06SShawn McCarney { 338*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a double"); 339*f1845c06SShawn McCarney } 340*f1845c06SShawn McCarney 341*f1845c06SShawn McCarney // Test where fails: Variable specified: Trailing whitespace 342*f1845c06SShawn McCarney try 343*f1845c06SShawn McCarney { 344*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "-1.03 "}}; 345*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 346*f1845c06SShawn McCarney parseDouble(element, variables); 347*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 348*f1845c06SShawn McCarney } 349*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 350*f1845c06SShawn McCarney { 351*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a double"); 352*f1845c06SShawn McCarney } 353*f1845c06SShawn McCarney 354*f1845c06SShawn McCarney // Test where fails: Variable specified: Starts with non-number character 355*f1845c06SShawn McCarney try 356*f1845c06SShawn McCarney { 357*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "x-1.03"}}; 358*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 359*f1845c06SShawn McCarney parseDouble(element, variables); 360*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 361*f1845c06SShawn McCarney } 362*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 363*f1845c06SShawn McCarney { 364*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a double"); 365*f1845c06SShawn McCarney } 366*f1845c06SShawn McCarney 367*f1845c06SShawn McCarney // Test where fails: Variable specified: Ends with non-number character 368*f1845c06SShawn McCarney try 369*f1845c06SShawn McCarney { 370*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "-1.03x"}}; 371*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 372*f1845c06SShawn McCarney parseDouble(element, variables); 373*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 374*f1845c06SShawn McCarney } 375*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 376*f1845c06SShawn McCarney { 377*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a double"); 378*f1845c06SShawn McCarney } 379*f1845c06SShawn McCarney 380*f1845c06SShawn McCarney // Test where fails: Variable specified: Not a double 381*f1845c06SShawn McCarney try 382*f1845c06SShawn McCarney { 383*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "foo"}}; 384*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 385*f1845c06SShawn McCarney parseDouble(element, variables); 386*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 387*f1845c06SShawn McCarney } 388*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 389*f1845c06SShawn McCarney { 390*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a double"); 39138f85004SShawn McCarney } 39238f85004SShawn McCarney } 39338f85004SShawn McCarney 39438f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseHexByte) 39538f85004SShawn McCarney { 39638f85004SShawn McCarney // Test where works: "0xFF" 39738f85004SShawn McCarney { 39838f85004SShawn McCarney const json element = R"( "0xFF" )"_json; 39938f85004SShawn McCarney uint8_t value = parseHexByte(element); 40038f85004SShawn McCarney EXPECT_EQ(value, 0xFF); 40138f85004SShawn McCarney } 40238f85004SShawn McCarney 40338f85004SShawn McCarney // Test where works: "0xff" 40438f85004SShawn McCarney { 40538f85004SShawn McCarney const json element = R"( "0xff" )"_json; 40638f85004SShawn McCarney uint8_t value = parseHexByte(element); 40738f85004SShawn McCarney EXPECT_EQ(value, 0xff); 40838f85004SShawn McCarney } 40938f85004SShawn McCarney 41038f85004SShawn McCarney // Test where works: "0xf" 41138f85004SShawn McCarney { 41238f85004SShawn McCarney const json element = R"( "0xf" )"_json; 41338f85004SShawn McCarney uint8_t value = parseHexByte(element); 41438f85004SShawn McCarney EXPECT_EQ(value, 0xf); 41538f85004SShawn McCarney } 41638f85004SShawn McCarney 417*f1845c06SShawn McCarney // Test where works: Variable specified 418*f1845c06SShawn McCarney { 419*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "ed"}}; 420*f1845c06SShawn McCarney const json element = R"( "0x${var}" )"_json; 421*f1845c06SShawn McCarney uint8_t value = parseHexByte(element, variables); 422*f1845c06SShawn McCarney EXPECT_EQ(value, 0xed); 423*f1845c06SShawn McCarney } 424*f1845c06SShawn McCarney 42538f85004SShawn McCarney // Test where fails: "0xfff" 42638f85004SShawn McCarney try 42738f85004SShawn McCarney { 42838f85004SShawn McCarney const json element = R"( "0xfff" )"_json; 42938f85004SShawn McCarney parseHexByte(element); 43038f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 43138f85004SShawn McCarney } 43238f85004SShawn McCarney catch (const std::invalid_argument& e) 43338f85004SShawn McCarney { 43438f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 43538f85004SShawn McCarney } 43638f85004SShawn McCarney 43738f85004SShawn McCarney // Test where fails: "0xAG" 43838f85004SShawn McCarney try 43938f85004SShawn McCarney { 44038f85004SShawn McCarney const json element = R"( "0xAG" )"_json; 44138f85004SShawn McCarney parseHexByte(element); 44238f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 44338f85004SShawn McCarney } 44438f85004SShawn McCarney catch (const std::invalid_argument& e) 44538f85004SShawn McCarney { 44638f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 44738f85004SShawn McCarney } 44838f85004SShawn McCarney 44938f85004SShawn McCarney // Test where fails: "ff" 45038f85004SShawn McCarney try 45138f85004SShawn McCarney { 45238f85004SShawn McCarney const json element = R"( "ff" )"_json; 45338f85004SShawn McCarney parseHexByte(element); 45438f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 45538f85004SShawn McCarney } 45638f85004SShawn McCarney catch (const std::invalid_argument& e) 45738f85004SShawn McCarney { 45838f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 45938f85004SShawn McCarney } 46038f85004SShawn McCarney 46138f85004SShawn McCarney // Test where fails: "" 46238f85004SShawn McCarney try 46338f85004SShawn McCarney { 46438f85004SShawn McCarney const json element = ""; 46538f85004SShawn McCarney parseHexByte(element); 46638f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 46738f85004SShawn McCarney } 46838f85004SShawn McCarney catch (const std::invalid_argument& e) 46938f85004SShawn McCarney { 47038f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 47138f85004SShawn McCarney } 47238f85004SShawn McCarney 47338f85004SShawn McCarney // Test where fails: "f" 47438f85004SShawn McCarney try 47538f85004SShawn McCarney { 47638f85004SShawn McCarney const json element = R"( "f" )"_json; 47738f85004SShawn McCarney parseHexByte(element); 47838f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 47938f85004SShawn McCarney } 48038f85004SShawn McCarney catch (const std::invalid_argument& e) 48138f85004SShawn McCarney { 48238f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 48338f85004SShawn McCarney } 48438f85004SShawn McCarney 48538f85004SShawn McCarney // Test where fails: "0x" 48638f85004SShawn McCarney try 48738f85004SShawn McCarney { 48838f85004SShawn McCarney const json element = R"( "0x" )"_json; 48938f85004SShawn McCarney parseHexByte(element); 49038f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 49138f85004SShawn McCarney } 49238f85004SShawn McCarney catch (const std::invalid_argument& e) 49338f85004SShawn McCarney { 49438f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 49538f85004SShawn McCarney } 49638f85004SShawn McCarney 49738f85004SShawn McCarney // Test where fails: "0Xff" 49838f85004SShawn McCarney try 49938f85004SShawn McCarney { 50038f85004SShawn McCarney const json element = R"( "0XFF" )"_json; 50138f85004SShawn McCarney parseHexByte(element); 50238f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 50338f85004SShawn McCarney } 50438f85004SShawn McCarney catch (const std::invalid_argument& e) 50538f85004SShawn McCarney { 50638f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 50738f85004SShawn McCarney } 508*f1845c06SShawn McCarney 509*f1845c06SShawn McCarney // Test where fails: Variable specified: Not a hex string 510*f1845c06SShawn McCarney try 511*f1845c06SShawn McCarney { 512*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "0xsz"}}; 513*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 514*f1845c06SShawn McCarney parseHexByte(element, variables); 515*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 516*f1845c06SShawn McCarney } 517*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 518*f1845c06SShawn McCarney { 519*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 520*f1845c06SShawn McCarney } 52138f85004SShawn McCarney } 52238f85004SShawn McCarney 52338f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseHexByteArray) 52438f85004SShawn McCarney { 52538f85004SShawn McCarney // Test where works 52638f85004SShawn McCarney { 52738f85004SShawn McCarney const json element = R"( [ "0xCC", "0xFF" ] )"_json; 52838f85004SShawn McCarney std::vector<uint8_t> hexBytes = parseHexByteArray(element); 52938f85004SShawn McCarney std::vector<uint8_t> expected = {0xcc, 0xff}; 53038f85004SShawn McCarney EXPECT_EQ(hexBytes, expected); 53138f85004SShawn McCarney } 53238f85004SShawn McCarney 533*f1845c06SShawn McCarney // Test where works: Variables specified 534*f1845c06SShawn McCarney { 535*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var1", "0xCC"}, 536*f1845c06SShawn McCarney {"var2", "0xFF"}}; 537*f1845c06SShawn McCarney const json element = R"( [ "${var1}", "${var2}" ] )"_json; 538*f1845c06SShawn McCarney std::vector<uint8_t> hexBytes = parseHexByteArray(element, variables); 539*f1845c06SShawn McCarney std::vector<uint8_t> expected = {0xcc, 0xff}; 540*f1845c06SShawn McCarney EXPECT_EQ(hexBytes, expected); 541*f1845c06SShawn McCarney } 542*f1845c06SShawn McCarney 54338f85004SShawn McCarney // Test where fails: Element is not an array 54438f85004SShawn McCarney try 54538f85004SShawn McCarney { 54638f85004SShawn McCarney const json element = 0; 54738f85004SShawn McCarney parseHexByteArray(element); 54838f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 54938f85004SShawn McCarney } 55038f85004SShawn McCarney catch (const std::invalid_argument& e) 55138f85004SShawn McCarney { 55238f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an array"); 55338f85004SShawn McCarney } 554*f1845c06SShawn McCarney 555*f1845c06SShawn McCarney // Test where fails: Variables specified: Invalid byte value 556*f1845c06SShawn McCarney try 557*f1845c06SShawn McCarney { 558*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var1", "0xCC"}, 559*f1845c06SShawn McCarney {"var2", "99"}}; 560*f1845c06SShawn McCarney const json element = R"( [ "${var1}", "${var2}" ] )"_json; 561*f1845c06SShawn McCarney parseHexByteArray(element, variables); 562*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 563*f1845c06SShawn McCarney } 564*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 565*f1845c06SShawn McCarney { 566*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 567*f1845c06SShawn McCarney } 56838f85004SShawn McCarney } 56938f85004SShawn McCarney 57038f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseInt8) 57138f85004SShawn McCarney { 57238f85004SShawn McCarney // Test where works: INT8_MIN 57338f85004SShawn McCarney { 57438f85004SShawn McCarney const json element = R"( -128 )"_json; 57538f85004SShawn McCarney int8_t value = parseInt8(element); 57638f85004SShawn McCarney EXPECT_EQ(value, -128); 57738f85004SShawn McCarney } 57838f85004SShawn McCarney 57938f85004SShawn McCarney // Test where works: INT8_MAX 58038f85004SShawn McCarney { 58138f85004SShawn McCarney const json element = R"( 127 )"_json; 58238f85004SShawn McCarney int8_t value = parseInt8(element); 58338f85004SShawn McCarney EXPECT_EQ(value, 127); 58438f85004SShawn McCarney } 58538f85004SShawn McCarney 586*f1845c06SShawn McCarney // Test where works: Variable specified 587*f1845c06SShawn McCarney { 588*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "-23"}}; 589*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 590*f1845c06SShawn McCarney int8_t value = parseInt8(element, variables); 591*f1845c06SShawn McCarney EXPECT_EQ(value, -23); 592*f1845c06SShawn McCarney } 593*f1845c06SShawn McCarney 59438f85004SShawn McCarney // Test where fails: Element is not an integer 59538f85004SShawn McCarney try 59638f85004SShawn McCarney { 59738f85004SShawn McCarney const json element = R"( 1.03 )"_json; 59838f85004SShawn McCarney parseInt8(element); 59938f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 60038f85004SShawn McCarney } 60138f85004SShawn McCarney catch (const std::invalid_argument& e) 60238f85004SShawn McCarney { 60338f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 60438f85004SShawn McCarney } 60538f85004SShawn McCarney 60638f85004SShawn McCarney // Test where fails: Value < INT8_MIN 60738f85004SShawn McCarney try 60838f85004SShawn McCarney { 60938f85004SShawn McCarney const json element = R"( -129 )"_json; 61038f85004SShawn McCarney parseInt8(element); 61138f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 61238f85004SShawn McCarney } 61338f85004SShawn McCarney catch (const std::invalid_argument& e) 61438f85004SShawn McCarney { 61538f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); 61638f85004SShawn McCarney } 61738f85004SShawn McCarney 61838f85004SShawn McCarney // Test where fails: Value > INT8_MAX 61938f85004SShawn McCarney try 62038f85004SShawn McCarney { 62138f85004SShawn McCarney const json element = R"( 128 )"_json; 62238f85004SShawn McCarney parseInt8(element); 62338f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 62438f85004SShawn McCarney } 62538f85004SShawn McCarney catch (const std::invalid_argument& e) 62638f85004SShawn McCarney { 62738f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); 62838f85004SShawn McCarney } 629*f1845c06SShawn McCarney 630*f1845c06SShawn McCarney // Test where fails: Variable specified: Value > INT8_MAX 631*f1845c06SShawn McCarney try 632*f1845c06SShawn McCarney { 633*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "128"}}; 634*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 635*f1845c06SShawn McCarney parseInt8(element, variables); 636*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 637*f1845c06SShawn McCarney } 638*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 639*f1845c06SShawn McCarney { 640*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); 641*f1845c06SShawn McCarney } 642*f1845c06SShawn McCarney } 643*f1845c06SShawn McCarney 644*f1845c06SShawn McCarney TEST(JSONParserUtilsTests, ParseInteger) 645*f1845c06SShawn McCarney { 646*f1845c06SShawn McCarney // Test where works: Zero 647*f1845c06SShawn McCarney { 648*f1845c06SShawn McCarney const json element = R"( 0 )"_json; 649*f1845c06SShawn McCarney int value = parseInteger(element); 650*f1845c06SShawn McCarney EXPECT_EQ(value, 0); 651*f1845c06SShawn McCarney } 652*f1845c06SShawn McCarney 653*f1845c06SShawn McCarney // Test where works: Positive value 654*f1845c06SShawn McCarney { 655*f1845c06SShawn McCarney const json element = R"( 103 )"_json; 656*f1845c06SShawn McCarney int value = parseInteger(element); 657*f1845c06SShawn McCarney EXPECT_EQ(value, 103); 658*f1845c06SShawn McCarney } 659*f1845c06SShawn McCarney 660*f1845c06SShawn McCarney // Test where works: Negative value 661*f1845c06SShawn McCarney { 662*f1845c06SShawn McCarney const json element = R"( -24 )"_json; 663*f1845c06SShawn McCarney int value = parseInteger(element); 664*f1845c06SShawn McCarney EXPECT_EQ(value, -24); 665*f1845c06SShawn McCarney } 666*f1845c06SShawn McCarney 667*f1845c06SShawn McCarney // Test where works: Variable specified: Positive value 668*f1845c06SShawn McCarney { 669*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "1024"}}; 670*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 671*f1845c06SShawn McCarney int value = parseInteger(element, variables); 672*f1845c06SShawn McCarney EXPECT_EQ(value, 1024); 673*f1845c06SShawn McCarney } 674*f1845c06SShawn McCarney 675*f1845c06SShawn McCarney // Test where works: Variable specified: Negative value 676*f1845c06SShawn McCarney { 677*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "-9924"}}; 678*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 679*f1845c06SShawn McCarney int value = parseInteger(element, variables); 680*f1845c06SShawn McCarney EXPECT_EQ(value, -9924); 681*f1845c06SShawn McCarney } 682*f1845c06SShawn McCarney 683*f1845c06SShawn McCarney // Test where fails: Element is not a integer 684*f1845c06SShawn McCarney try 685*f1845c06SShawn McCarney { 686*f1845c06SShawn McCarney const json element = R"( true )"_json; 687*f1845c06SShawn McCarney parseInteger(element); 688*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 689*f1845c06SShawn McCarney } 690*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 691*f1845c06SShawn McCarney { 692*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 693*f1845c06SShawn McCarney } 694*f1845c06SShawn McCarney 695*f1845c06SShawn McCarney // Test where fails: Variable specified: Variables map not specified 696*f1845c06SShawn McCarney try 697*f1845c06SShawn McCarney { 698*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 699*f1845c06SShawn McCarney parseInteger(element); 700*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 701*f1845c06SShawn McCarney } 702*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 703*f1845c06SShawn McCarney { 704*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 705*f1845c06SShawn McCarney } 706*f1845c06SShawn McCarney 707*f1845c06SShawn McCarney // Test where fails: Variable specified: Leading whitespace 708*f1845c06SShawn McCarney try 709*f1845c06SShawn McCarney { 710*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", " -13"}}; 711*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 712*f1845c06SShawn McCarney parseInteger(element, variables); 713*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 714*f1845c06SShawn McCarney } 715*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 716*f1845c06SShawn McCarney { 717*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 718*f1845c06SShawn McCarney } 719*f1845c06SShawn McCarney 720*f1845c06SShawn McCarney // Test where fails: Variable specified: Trailing whitespace 721*f1845c06SShawn McCarney try 722*f1845c06SShawn McCarney { 723*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "-13 "}}; 724*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 725*f1845c06SShawn McCarney parseInteger(element, variables); 726*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 727*f1845c06SShawn McCarney } 728*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 729*f1845c06SShawn McCarney { 730*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 731*f1845c06SShawn McCarney } 732*f1845c06SShawn McCarney 733*f1845c06SShawn McCarney // Test where fails: Variable specified: Starts with non-number character 734*f1845c06SShawn McCarney try 735*f1845c06SShawn McCarney { 736*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "x-13"}}; 737*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 738*f1845c06SShawn McCarney parseInteger(element, variables); 739*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 740*f1845c06SShawn McCarney } 741*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 742*f1845c06SShawn McCarney { 743*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 744*f1845c06SShawn McCarney } 745*f1845c06SShawn McCarney 746*f1845c06SShawn McCarney // Test where fails: Variable specified: Ends with non-number character 747*f1845c06SShawn McCarney try 748*f1845c06SShawn McCarney { 749*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "-13x"}}; 750*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 751*f1845c06SShawn McCarney parseInteger(element, variables); 752*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 753*f1845c06SShawn McCarney } 754*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 755*f1845c06SShawn McCarney { 756*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 757*f1845c06SShawn McCarney } 758*f1845c06SShawn McCarney 759*f1845c06SShawn McCarney // Test where fails: Variable specified: Not an integer 760*f1845c06SShawn McCarney try 761*f1845c06SShawn McCarney { 762*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "foo"}}; 763*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 764*f1845c06SShawn McCarney parseInteger(element, variables); 765*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 766*f1845c06SShawn McCarney } 767*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 768*f1845c06SShawn McCarney { 769*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 770*f1845c06SShawn McCarney } 77138f85004SShawn McCarney } 77238f85004SShawn McCarney 77338f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseString) 77438f85004SShawn McCarney { 77538f85004SShawn McCarney // Test where works: Empty string 77638f85004SShawn McCarney { 77738f85004SShawn McCarney const json element = ""; 77838f85004SShawn McCarney std::string value = parseString(element, true); 77938f85004SShawn McCarney EXPECT_EQ(value, ""); 78038f85004SShawn McCarney } 78138f85004SShawn McCarney 78238f85004SShawn McCarney // Test where works: Non-empty string 78338f85004SShawn McCarney { 78438f85004SShawn McCarney const json element = "vdd_regulator"; 78538f85004SShawn McCarney std::string value = parseString(element, false); 78638f85004SShawn McCarney EXPECT_EQ(value, "vdd_regulator"); 78738f85004SShawn McCarney } 78838f85004SShawn McCarney 789*f1845c06SShawn McCarney // Test where works: Variable specified: Empty string 790*f1845c06SShawn McCarney { 791*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", ""}}; 792*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 793*f1845c06SShawn McCarney std::string value = parseString(element, true, variables); 794*f1845c06SShawn McCarney EXPECT_EQ(value, ""); 795*f1845c06SShawn McCarney } 796*f1845c06SShawn McCarney 797*f1845c06SShawn McCarney // Test where works: Variable specified: Non-empty string 798*f1845c06SShawn McCarney { 799*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "vio_regulator"}}; 800*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 801*f1845c06SShawn McCarney std::string value = parseString(element, false, variables); 802*f1845c06SShawn McCarney EXPECT_EQ(value, "vio_regulator"); 803*f1845c06SShawn McCarney } 804*f1845c06SShawn McCarney 80538f85004SShawn McCarney // Test where fails: Element is not a string 80638f85004SShawn McCarney try 80738f85004SShawn McCarney { 80838f85004SShawn McCarney const json element = R"( { "foo": "bar" } )"_json; 80938f85004SShawn McCarney parseString(element); 81038f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 81138f85004SShawn McCarney } 81238f85004SShawn McCarney catch (const std::invalid_argument& e) 81338f85004SShawn McCarney { 81438f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not a string"); 81538f85004SShawn McCarney } 81638f85004SShawn McCarney 81738f85004SShawn McCarney // Test where fails: Empty string 81838f85004SShawn McCarney try 81938f85004SShawn McCarney { 82038f85004SShawn McCarney const json element = ""; 82138f85004SShawn McCarney parseString(element); 82238f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 82338f85004SShawn McCarney } 82438f85004SShawn McCarney catch (const std::invalid_argument& e) 82538f85004SShawn McCarney { 82638f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element contains an empty string"); 82738f85004SShawn McCarney } 828*f1845c06SShawn McCarney 829*f1845c06SShawn McCarney // Test where fails: Variable specified: Empty string 830*f1845c06SShawn McCarney try 831*f1845c06SShawn McCarney { 832*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", ""}}; 833*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 834*f1845c06SShawn McCarney parseString(element, false, variables); 835*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 836*f1845c06SShawn McCarney } 837*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 838*f1845c06SShawn McCarney { 839*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element contains an empty string"); 840*f1845c06SShawn McCarney } 841*f1845c06SShawn McCarney 842*f1845c06SShawn McCarney // Test where fails: Variable specified: Variable not defined 843*f1845c06SShawn McCarney try 844*f1845c06SShawn McCarney { 845*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var1", "foo"}}; 846*f1845c06SShawn McCarney const json element = R"( "${var2}" )"_json; 847*f1845c06SShawn McCarney parseString(element, false, variables); 848*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 849*f1845c06SShawn McCarney } 850*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 851*f1845c06SShawn McCarney { 852*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Undefined variable: var2"); 853*f1845c06SShawn McCarney } 85438f85004SShawn McCarney } 85538f85004SShawn McCarney 85638f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseUint8) 85738f85004SShawn McCarney { 85838f85004SShawn McCarney // Test where works: 0 85938f85004SShawn McCarney { 86038f85004SShawn McCarney const json element = R"( 0 )"_json; 86138f85004SShawn McCarney uint8_t value = parseUint8(element); 86238f85004SShawn McCarney EXPECT_EQ(value, 0); 86338f85004SShawn McCarney } 86438f85004SShawn McCarney 86538f85004SShawn McCarney // Test where works: UINT8_MAX 86638f85004SShawn McCarney { 86738f85004SShawn McCarney const json element = R"( 255 )"_json; 86838f85004SShawn McCarney uint8_t value = parseUint8(element); 86938f85004SShawn McCarney EXPECT_EQ(value, 255); 87038f85004SShawn McCarney } 87138f85004SShawn McCarney 872*f1845c06SShawn McCarney // Test where works: Variable specified 873*f1845c06SShawn McCarney { 874*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "19"}}; 875*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 876*f1845c06SShawn McCarney uint8_t value = parseUint8(element, variables); 877*f1845c06SShawn McCarney EXPECT_EQ(value, 19); 878*f1845c06SShawn McCarney } 879*f1845c06SShawn McCarney 88038f85004SShawn McCarney // Test where fails: Element is not an integer 88138f85004SShawn McCarney try 88238f85004SShawn McCarney { 88338f85004SShawn McCarney const json element = R"( 1.03 )"_json; 88438f85004SShawn McCarney parseUint8(element); 88538f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 88638f85004SShawn McCarney } 88738f85004SShawn McCarney catch (const std::invalid_argument& e) 88838f85004SShawn McCarney { 88938f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 89038f85004SShawn McCarney } 89138f85004SShawn McCarney 89238f85004SShawn McCarney // Test where fails: Value < 0 89338f85004SShawn McCarney try 89438f85004SShawn McCarney { 89538f85004SShawn McCarney const json element = R"( -1 )"_json; 89638f85004SShawn McCarney parseUint8(element); 89738f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 89838f85004SShawn McCarney } 89938f85004SShawn McCarney catch (const std::invalid_argument& e) 90038f85004SShawn McCarney { 90138f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); 90238f85004SShawn McCarney } 90338f85004SShawn McCarney 90438f85004SShawn McCarney // Test where fails: Value > UINT8_MAX 90538f85004SShawn McCarney try 90638f85004SShawn McCarney { 90738f85004SShawn McCarney const json element = R"( 256 )"_json; 90838f85004SShawn McCarney parseUint8(element); 90938f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 91038f85004SShawn McCarney } 91138f85004SShawn McCarney catch (const std::invalid_argument& e) 91238f85004SShawn McCarney { 91338f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); 91438f85004SShawn McCarney } 915*f1845c06SShawn McCarney 916*f1845c06SShawn McCarney // Test where fails: Variable specified: Value > UINT8_MAX 917*f1845c06SShawn McCarney try 918*f1845c06SShawn McCarney { 919*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "256"}}; 920*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 921*f1845c06SShawn McCarney parseUint8(element, variables); 922*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 923*f1845c06SShawn McCarney } 924*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 925*f1845c06SShawn McCarney { 926*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); 927*f1845c06SShawn McCarney } 92838f85004SShawn McCarney } 92938f85004SShawn McCarney 93038f85004SShawn McCarney TEST(JSONParserUtilsTests, ParseUnsignedInteger) 93138f85004SShawn McCarney { 93238f85004SShawn McCarney // Test where works: 1 93338f85004SShawn McCarney { 93438f85004SShawn McCarney const json element = R"( 1 )"_json; 93538f85004SShawn McCarney unsigned int value = parseUnsignedInteger(element); 93638f85004SShawn McCarney EXPECT_EQ(value, 1); 93738f85004SShawn McCarney } 93838f85004SShawn McCarney 939*f1845c06SShawn McCarney // Test where works: Variable specified 940*f1845c06SShawn McCarney { 941*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "25678"}}; 942*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 943*f1845c06SShawn McCarney unsigned int value = parseUnsignedInteger(element, variables); 944*f1845c06SShawn McCarney EXPECT_EQ(value, 25678); 945*f1845c06SShawn McCarney } 946*f1845c06SShawn McCarney 94738f85004SShawn McCarney // Test where fails: Element is not an integer 94838f85004SShawn McCarney try 94938f85004SShawn McCarney { 95038f85004SShawn McCarney const json element = R"( 1.5 )"_json; 95138f85004SShawn McCarney parseUnsignedInteger(element); 95238f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 95338f85004SShawn McCarney } 95438f85004SShawn McCarney catch (const std::invalid_argument& e) 95538f85004SShawn McCarney { 956*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an integer"); 95738f85004SShawn McCarney } 95838f85004SShawn McCarney 95938f85004SShawn McCarney // Test where fails: Value < 0 96038f85004SShawn McCarney try 96138f85004SShawn McCarney { 96238f85004SShawn McCarney const json element = R"( -1 )"_json; 96338f85004SShawn McCarney parseUnsignedInteger(element); 96438f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 96538f85004SShawn McCarney } 96638f85004SShawn McCarney catch (const std::invalid_argument& e) 96738f85004SShawn McCarney { 96838f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); 96938f85004SShawn McCarney } 970*f1845c06SShawn McCarney 971*f1845c06SShawn McCarney // Test where fails: Variable specified: Value < 0 972*f1845c06SShawn McCarney try 973*f1845c06SShawn McCarney { 974*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "-23"}}; 975*f1845c06SShawn McCarney const json element = R"( "${var}" )"_json; 976*f1845c06SShawn McCarney parseUnsignedInteger(element, variables); 977*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 978*f1845c06SShawn McCarney } 979*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 980*f1845c06SShawn McCarney { 981*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); 982*f1845c06SShawn McCarney } 98338f85004SShawn McCarney } 98438f85004SShawn McCarney 98538f85004SShawn McCarney TEST(JSONParserUtilsTests, VerifyIsArray) 98638f85004SShawn McCarney { 98738f85004SShawn McCarney // Test where element is an array 98838f85004SShawn McCarney { 98938f85004SShawn McCarney const json element = R"( [ "foo", "bar" ] )"_json; 99038f85004SShawn McCarney verifyIsArray(element); 99138f85004SShawn McCarney } 99238f85004SShawn McCarney 99338f85004SShawn McCarney // Test where element is not an array 99438f85004SShawn McCarney try 99538f85004SShawn McCarney { 99638f85004SShawn McCarney const json element = R"( { "foo": "bar" } )"_json; 99738f85004SShawn McCarney verifyIsArray(element); 99838f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 99938f85004SShawn McCarney } 100038f85004SShawn McCarney catch (const std::invalid_argument& e) 100138f85004SShawn McCarney { 100238f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an array"); 100338f85004SShawn McCarney } 100438f85004SShawn McCarney } 100538f85004SShawn McCarney 100638f85004SShawn McCarney TEST(JSONParserUtilsTests, VerifyIsObject) 100738f85004SShawn McCarney { 100838f85004SShawn McCarney // Test where element is an object 100938f85004SShawn McCarney { 101038f85004SShawn McCarney const json element = R"( { "foo": "bar" } )"_json; 101138f85004SShawn McCarney verifyIsObject(element); 101238f85004SShawn McCarney } 101338f85004SShawn McCarney 101438f85004SShawn McCarney // Test where element is not an object 101538f85004SShawn McCarney try 101638f85004SShawn McCarney { 101738f85004SShawn McCarney const json element = R"( [ "foo", "bar" ] )"_json; 101838f85004SShawn McCarney verifyIsObject(element); 101938f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 102038f85004SShawn McCarney } 102138f85004SShawn McCarney catch (const std::invalid_argument& e) 102238f85004SShawn McCarney { 102338f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element is not an object"); 102438f85004SShawn McCarney } 102538f85004SShawn McCarney } 102638f85004SShawn McCarney 102738f85004SShawn McCarney TEST(JSONParserUtilsTests, VerifyPropertyCount) 102838f85004SShawn McCarney { 102938f85004SShawn McCarney // Test where element has expected number of properties 103038f85004SShawn McCarney { 103138f85004SShawn McCarney const json element = R"( 103238f85004SShawn McCarney { 103338f85004SShawn McCarney "comments": [ "Set voltage rule" ], 103438f85004SShawn McCarney "id": "set_voltage_rule" 103538f85004SShawn McCarney } 103638f85004SShawn McCarney )"_json; 103738f85004SShawn McCarney verifyPropertyCount(element, 2); 103838f85004SShawn McCarney } 103938f85004SShawn McCarney 104038f85004SShawn McCarney // Test where element has unexpected number of properties 104138f85004SShawn McCarney try 104238f85004SShawn McCarney { 104338f85004SShawn McCarney const json element = R"( 104438f85004SShawn McCarney { 104538f85004SShawn McCarney "comments": [ "Set voltage rule" ], 104638f85004SShawn McCarney "id": "set_voltage_rule", 104738f85004SShawn McCarney "foo": 1.3 104838f85004SShawn McCarney } 104938f85004SShawn McCarney )"_json; 105038f85004SShawn McCarney verifyPropertyCount(element, 2); 105138f85004SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 105238f85004SShawn McCarney } 105338f85004SShawn McCarney catch (const std::invalid_argument& e) 105438f85004SShawn McCarney { 105538f85004SShawn McCarney EXPECT_STREQ(e.what(), "Element contains an invalid property"); 105638f85004SShawn McCarney } 105738f85004SShawn McCarney } 1058*f1845c06SShawn McCarney 1059*f1845c06SShawn McCarney TEST(JSONParserUtilsTests, ExpandVariables) 1060*f1845c06SShawn McCarney { 1061*f1845c06SShawn McCarney // Test where works: Single variable: Variable is entire value: Lower case 1062*f1845c06SShawn McCarney // in variable name 1063*f1845c06SShawn McCarney { 1064*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "vio_regulator"}}; 1065*f1845c06SShawn McCarney std::string value{"${var}"}; 1066*f1845c06SShawn McCarney expandVariables(value, variables); 1067*f1845c06SShawn McCarney EXPECT_EQ(value, "vio_regulator"); 1068*f1845c06SShawn McCarney } 1069*f1845c06SShawn McCarney 1070*f1845c06SShawn McCarney // Test where works: Multiple variables: Variables are part of value: Upper 1071*f1845c06SShawn McCarney // case and underscore in variable name 1072*f1845c06SShawn McCarney { 1073*f1845c06SShawn McCarney std::map<std::string, std::string> variables{ 1074*f1845c06SShawn McCarney {"CHASSIS_NUMBER", "1"}, {"REGULATOR", "vcs_vio"}, {"RAIL", "vio"}}; 1075*f1845c06SShawn McCarney std::string value{ 1076*f1845c06SShawn McCarney "chassis${CHASSIS_NUMBER}_${REGULATOR}_regulator_${RAIL}_rail"}; 1077*f1845c06SShawn McCarney expandVariables(value, variables); 1078*f1845c06SShawn McCarney EXPECT_EQ(value, "chassis1_vcs_vio_regulator_vio_rail"); 1079*f1845c06SShawn McCarney } 1080*f1845c06SShawn McCarney 1081*f1845c06SShawn McCarney // Test where works: Variable at start of value: Number in variable name 1082*f1845c06SShawn McCarney { 1083*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var1", "vio_regulator"}}; 1084*f1845c06SShawn McCarney std::string value{"${var1}_rail"}; 1085*f1845c06SShawn McCarney expandVariables(value, variables); 1086*f1845c06SShawn McCarney EXPECT_EQ(value, "vio_regulator_rail"); 1087*f1845c06SShawn McCarney } 1088*f1845c06SShawn McCarney 1089*f1845c06SShawn McCarney // Test where works: Variable at end of value 1090*f1845c06SShawn McCarney { 1091*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"chassis_number", "3"}}; 1092*f1845c06SShawn McCarney std::string value{ 1093*f1845c06SShawn McCarney "/xyz/openbmc_project/inventory/system/chassis${chassis_number}"}; 1094*f1845c06SShawn McCarney expandVariables(value, variables); 1095*f1845c06SShawn McCarney EXPECT_EQ(value, "/xyz/openbmc_project/inventory/system/chassis3"); 1096*f1845c06SShawn McCarney } 1097*f1845c06SShawn McCarney 1098*f1845c06SShawn McCarney // Test where works: Variable has empty value: Start of value 1099*f1845c06SShawn McCarney { 1100*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"chassis_prefix", ""}}; 1101*f1845c06SShawn McCarney std::string value{"${chassis_prefix}vio_regulator"}; 1102*f1845c06SShawn McCarney expandVariables(value, variables); 1103*f1845c06SShawn McCarney EXPECT_EQ(value, "vio_regulator"); 1104*f1845c06SShawn McCarney } 1105*f1845c06SShawn McCarney 1106*f1845c06SShawn McCarney // Test where works: Variable has empty value: Middle of value 1107*f1845c06SShawn McCarney { 1108*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"chassis_number", ""}}; 1109*f1845c06SShawn McCarney std::string value{"c${chassis_number}_vio_regulator"}; 1110*f1845c06SShawn McCarney expandVariables(value, variables); 1111*f1845c06SShawn McCarney EXPECT_EQ(value, "c_vio_regulator"); 1112*f1845c06SShawn McCarney } 1113*f1845c06SShawn McCarney 1114*f1845c06SShawn McCarney // Test where works: Variable has empty value: End of value 1115*f1845c06SShawn McCarney { 1116*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"chassis_number", ""}}; 1117*f1845c06SShawn McCarney std::string value{ 1118*f1845c06SShawn McCarney "/xyz/openbmc_project/inventory/system/chassis${chassis_number}"}; 1119*f1845c06SShawn McCarney expandVariables(value, variables); 1120*f1845c06SShawn McCarney EXPECT_EQ(value, "/xyz/openbmc_project/inventory/system/chassis"); 1121*f1845c06SShawn McCarney } 1122*f1845c06SShawn McCarney 1123*f1845c06SShawn McCarney // Test where works: No variables specified 1124*f1845c06SShawn McCarney { 1125*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "vio_regulator"}}; 1126*f1845c06SShawn McCarney std::string value{"vcs_rail"}; 1127*f1845c06SShawn McCarney expandVariables(value, variables); 1128*f1845c06SShawn McCarney EXPECT_EQ(value, "vcs_rail"); 1129*f1845c06SShawn McCarney } 1130*f1845c06SShawn McCarney 1131*f1845c06SShawn McCarney // Test where works: Nested variable expansion 1132*f1845c06SShawn McCarney { 1133*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var1", "${var2}"}, 1134*f1845c06SShawn McCarney {"var2", "vio_reg"}}; 1135*f1845c06SShawn McCarney std::string value{"${var1}_rail"}; 1136*f1845c06SShawn McCarney expandVariables(value, variables); 1137*f1845c06SShawn McCarney EXPECT_EQ(value, "vio_reg_rail"); 1138*f1845c06SShawn McCarney } 1139*f1845c06SShawn McCarney 1140*f1845c06SShawn McCarney // Test where fails: Variables map is empty 1141*f1845c06SShawn McCarney { 1142*f1845c06SShawn McCarney std::map<std::string, std::string> variables{}; 1143*f1845c06SShawn McCarney std::string value{"${var}_rail"}; 1144*f1845c06SShawn McCarney expandVariables(value, variables); 1145*f1845c06SShawn McCarney EXPECT_EQ(value, "${var}_rail"); 1146*f1845c06SShawn McCarney } 1147*f1845c06SShawn McCarney 1148*f1845c06SShawn McCarney // Test where fails: Variable missing $ 1149*f1845c06SShawn McCarney { 1150*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1151*f1845c06SShawn McCarney std::string value{"{var}_rail"}; 1152*f1845c06SShawn McCarney expandVariables(value, variables); 1153*f1845c06SShawn McCarney EXPECT_EQ(value, "{var}_rail"); 1154*f1845c06SShawn McCarney } 1155*f1845c06SShawn McCarney 1156*f1845c06SShawn McCarney // Test where fails: Variable missing { 1157*f1845c06SShawn McCarney { 1158*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1159*f1845c06SShawn McCarney std::string value{"$var}_rail"}; 1160*f1845c06SShawn McCarney expandVariables(value, variables); 1161*f1845c06SShawn McCarney EXPECT_EQ(value, "$var}_rail"); 1162*f1845c06SShawn McCarney } 1163*f1845c06SShawn McCarney 1164*f1845c06SShawn McCarney // Test where fails: Variable missing } 1165*f1845c06SShawn McCarney { 1166*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1167*f1845c06SShawn McCarney std::string value{"${var_rail"}; 1168*f1845c06SShawn McCarney expandVariables(value, variables); 1169*f1845c06SShawn McCarney EXPECT_EQ(value, "${var_rail"); 1170*f1845c06SShawn McCarney } 1171*f1845c06SShawn McCarney 1172*f1845c06SShawn McCarney // Test where fails: Variable missing name 1173*f1845c06SShawn McCarney { 1174*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1175*f1845c06SShawn McCarney std::string value{"${}_rail"}; 1176*f1845c06SShawn McCarney expandVariables(value, variables); 1177*f1845c06SShawn McCarney EXPECT_EQ(value, "${}_rail"); 1178*f1845c06SShawn McCarney } 1179*f1845c06SShawn McCarney 1180*f1845c06SShawn McCarney // Test where fails: Variable name has invalid characters 1181*f1845c06SShawn McCarney { 1182*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var-2", "vio_reg"}}; 1183*f1845c06SShawn McCarney std::string value{"${var-2}_rail"}; 1184*f1845c06SShawn McCarney expandVariables(value, variables); 1185*f1845c06SShawn McCarney EXPECT_EQ(value, "${var-2}_rail"); 1186*f1845c06SShawn McCarney } 1187*f1845c06SShawn McCarney 1188*f1845c06SShawn McCarney // Test where fails: Variable has unexpected whitespace 1189*f1845c06SShawn McCarney { 1190*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1191*f1845c06SShawn McCarney std::string value{"${ var }_rail"}; 1192*f1845c06SShawn McCarney expandVariables(value, variables); 1193*f1845c06SShawn McCarney EXPECT_EQ(value, "${ var }_rail"); 1194*f1845c06SShawn McCarney } 1195*f1845c06SShawn McCarney 1196*f1845c06SShawn McCarney // Test where fails: Undefined variable 1197*f1845c06SShawn McCarney try 1198*f1845c06SShawn McCarney { 1199*f1845c06SShawn McCarney std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1200*f1845c06SShawn McCarney std::string value{"${foo}_rail"}; 1201*f1845c06SShawn McCarney expandVariables(value, variables); 1202*f1845c06SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 1203*f1845c06SShawn McCarney } 1204*f1845c06SShawn McCarney catch (const std::invalid_argument& e) 1205*f1845c06SShawn McCarney { 1206*f1845c06SShawn McCarney EXPECT_STREQ(e.what(), "Undefined variable: foo"); 1207*f1845c06SShawn McCarney } 1208*f1845c06SShawn McCarney } 1209