1 /** 2 * Copyright © 2025 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "json_parser_utils.hpp" 17 18 #include <nlohmann/json.hpp> 19 20 #include <cstdint> 21 #include <exception> 22 #include <stdexcept> 23 #include <string> 24 #include <vector> 25 26 #include <gtest/gtest.h> 27 28 using namespace phosphor::power::json_parser_utils; 29 using namespace phosphor::power::json_parser_utils::internal; 30 using json = nlohmann::json; 31 32 TEST(JSONParserUtilsTests, GetRequiredProperty) 33 { 34 // Test where property exists 35 { 36 const json element = R"( { "format": "linear" } )"_json; 37 const json& propertyElement = getRequiredProperty(element, "format"); 38 EXPECT_EQ(propertyElement.get<std::string>(), "linear"); 39 } 40 41 // Test where property does not exist 42 try 43 { 44 const json element = R"( { "volts": 1.03 } )"_json; 45 getRequiredProperty(element, "format"); 46 ADD_FAILURE() << "Should not have reached this line."; 47 } 48 catch (const std::invalid_argument& e) 49 { 50 EXPECT_STREQ(e.what(), "Required property missing: format"); 51 } 52 } 53 54 TEST(JSONParserUtilsTests, ParseBitPosition) 55 { 56 // Test where works: 0 57 { 58 const json element = R"( 0 )"_json; 59 uint8_t value = parseBitPosition(element); 60 EXPECT_EQ(value, 0); 61 } 62 63 // Test where works: 7 64 { 65 const json element = R"( 7 )"_json; 66 uint8_t value = parseBitPosition(element); 67 EXPECT_EQ(value, 7); 68 } 69 70 // Test where works: Variable specified 71 { 72 std::map<std::string, std::string> variables{{"bit_pos", "3"}}; 73 const json element = R"( "${bit_pos}" )"_json; 74 uint8_t value = parseBitPosition(element, variables); 75 EXPECT_EQ(value, 3); 76 } 77 78 // Test where fails: Element is not an integer 79 try 80 { 81 const json element = R"( 1.03 )"_json; 82 parseBitPosition(element); 83 ADD_FAILURE() << "Should not have reached this line."; 84 } 85 catch (const std::invalid_argument& e) 86 { 87 EXPECT_STREQ(e.what(), "Element is not an integer"); 88 } 89 90 // Test where fails: Value < 0 91 try 92 { 93 const json element = R"( -1 )"_json; 94 parseBitPosition(element); 95 ADD_FAILURE() << "Should not have reached this line."; 96 } 97 catch (const std::invalid_argument& e) 98 { 99 EXPECT_STREQ(e.what(), "Element is not a bit position"); 100 } 101 102 // Test where fails: Value > 7 103 try 104 { 105 const json element = R"( 8 )"_json; 106 parseBitPosition(element); 107 ADD_FAILURE() << "Should not have reached this line."; 108 } 109 catch (const std::invalid_argument& e) 110 { 111 EXPECT_STREQ(e.what(), "Element is not a bit position"); 112 } 113 114 // Test where fails: Variable specified: Value < 0 115 try 116 { 117 std::map<std::string, std::string> variables{{"bit_pos", "-1"}}; 118 const json element = R"( "${bit_pos}" )"_json; 119 parseBitPosition(element, variables); 120 ADD_FAILURE() << "Should not have reached this line."; 121 } 122 catch (const std::invalid_argument& e) 123 { 124 EXPECT_STREQ(e.what(), "Element is not a bit position"); 125 } 126 } 127 128 TEST(JSONParserUtilsTests, ParseBitValue) 129 { 130 // Test where works: 0 131 { 132 const json element = R"( 0 )"_json; 133 uint8_t value = parseBitValue(element); 134 EXPECT_EQ(value, 0); 135 } 136 137 // Test where works: 1 138 { 139 const json element = R"( 1 )"_json; 140 uint8_t value = parseBitValue(element); 141 EXPECT_EQ(value, 1); 142 } 143 144 // Test where works: Variable specified 145 { 146 std::map<std::string, std::string> variables{{"bit_val", "1"}}; 147 const json element = R"( "${bit_val}" )"_json; 148 uint8_t value = parseBitValue(element, variables); 149 EXPECT_EQ(value, 1); 150 } 151 152 // Test where fails: Element is not an integer 153 try 154 { 155 const json element = R"( 0.5 )"_json; 156 parseBitValue(element); 157 ADD_FAILURE() << "Should not have reached this line."; 158 } 159 catch (const std::invalid_argument& e) 160 { 161 EXPECT_STREQ(e.what(), "Element is not an integer"); 162 } 163 164 // Test where fails: Value < 0 165 try 166 { 167 const json element = R"( -1 )"_json; 168 parseBitValue(element); 169 ADD_FAILURE() << "Should not have reached this line."; 170 } 171 catch (const std::invalid_argument& e) 172 { 173 EXPECT_STREQ(e.what(), "Element is not a bit value"); 174 } 175 176 // Test where fails: Value > 1 177 try 178 { 179 const json element = R"( 2 )"_json; 180 parseBitValue(element); 181 ADD_FAILURE() << "Should not have reached this line."; 182 } 183 catch (const std::invalid_argument& e) 184 { 185 EXPECT_STREQ(e.what(), "Element is not a bit value"); 186 } 187 188 // Test where fails: Variable specified: Not an integer 189 try 190 { 191 std::map<std::string, std::string> variables{{"bit_val", "one"}}; 192 const json element = R"( "${bit_val}" )"_json; 193 parseBitValue(element, variables); 194 ADD_FAILURE() << "Should not have reached this line."; 195 } 196 catch (const std::invalid_argument& e) 197 { 198 EXPECT_STREQ(e.what(), "Element is not an integer"); 199 } 200 } 201 202 TEST(JSONParserUtilsTests, ParseBoolean) 203 { 204 // Test where works: true 205 { 206 const json element = R"( true )"_json; 207 bool value = parseBoolean(element); 208 EXPECT_EQ(value, true); 209 } 210 211 // Test where works: false 212 { 213 const json element = R"( false )"_json; 214 bool value = parseBoolean(element); 215 EXPECT_EQ(value, false); 216 } 217 218 // Test where works: Variable specified: true 219 { 220 std::map<std::string, std::string> variables{{"bool_val", "true"}}; 221 const json element = R"( "${bool_val}" )"_json; 222 bool value = parseBoolean(element, variables); 223 EXPECT_EQ(value, true); 224 } 225 226 // Test where works: Variable specified: false 227 { 228 std::map<std::string, std::string> variables{{"bool_val", "false"}}; 229 const json element = R"( "${bool_val}" )"_json; 230 bool value = parseBoolean(element, variables); 231 EXPECT_EQ(value, false); 232 } 233 234 // Test where fails: Element is not a boolean 235 try 236 { 237 const json element = R"( 1 )"_json; 238 parseBoolean(element); 239 ADD_FAILURE() << "Should not have reached this line."; 240 } 241 catch (const std::invalid_argument& e) 242 { 243 EXPECT_STREQ(e.what(), "Element is not a boolean"); 244 } 245 246 // Test where fails: Variable specified: Variables map not specified 247 try 248 { 249 const json element = R"( "${bool_val}" )"_json; 250 parseBoolean(element); 251 ADD_FAILURE() << "Should not have reached this line."; 252 } 253 catch (const std::invalid_argument& e) 254 { 255 EXPECT_STREQ(e.what(), "Element is not a boolean"); 256 } 257 258 // Test where fails: Variable specified: Value is not a boolean 259 try 260 { 261 std::map<std::string, std::string> variables{{"bool_val", "3.2"}}; 262 const json element = R"( "${bool_val}" )"_json; 263 parseBoolean(element, variables); 264 ADD_FAILURE() << "Should not have reached this line."; 265 } 266 catch (const std::invalid_argument& e) 267 { 268 EXPECT_STREQ(e.what(), "Element is not a boolean"); 269 } 270 } 271 272 TEST(JSONParserUtilsTests, ParseDouble) 273 { 274 // Test where works: Floating point value 275 { 276 const json element = R"( 1.03 )"_json; 277 double value = parseDouble(element); 278 EXPECT_EQ(value, 1.03); 279 } 280 281 // Test where works: Integer value 282 { 283 const json element = R"( -24 )"_json; 284 double value = parseDouble(element); 285 EXPECT_EQ(value, -24.0); 286 } 287 288 // Test where works: Variable specified: Floating point value 289 { 290 std::map<std::string, std::string> variables{{"var", "-1.03"}}; 291 const json element = R"( "${var}" )"_json; 292 double value = parseDouble(element, variables); 293 EXPECT_EQ(value, -1.03); 294 } 295 296 // Test where works: Variable specified: Integer value 297 { 298 std::map<std::string, std::string> variables{{"var", "24"}}; 299 const json element = R"( "${var}" )"_json; 300 double value = parseDouble(element, variables); 301 EXPECT_EQ(value, 24.0); 302 } 303 304 // Test where fails: Element is not a double 305 try 306 { 307 const json element = R"( true )"_json; 308 parseDouble(element); 309 ADD_FAILURE() << "Should not have reached this line."; 310 } 311 catch (const std::invalid_argument& e) 312 { 313 EXPECT_STREQ(e.what(), "Element is not a double"); 314 } 315 316 // Test where fails: Variable specified: Variables map not specified 317 try 318 { 319 const json element = R"( "${var}" )"_json; 320 parseDouble(element); 321 ADD_FAILURE() << "Should not have reached this line."; 322 } 323 catch (const std::invalid_argument& e) 324 { 325 EXPECT_STREQ(e.what(), "Element is not a double"); 326 } 327 328 // Test where fails: Variable specified: Leading whitespace 329 try 330 { 331 std::map<std::string, std::string> variables{{"var", " -1.03"}}; 332 const json element = R"( "${var}" )"_json; 333 parseDouble(element, variables); 334 ADD_FAILURE() << "Should not have reached this line."; 335 } 336 catch (const std::invalid_argument& e) 337 { 338 EXPECT_STREQ(e.what(), "Element is not a double"); 339 } 340 341 // Test where fails: Variable specified: Trailing whitespace 342 try 343 { 344 std::map<std::string, std::string> variables{{"var", "-1.03 "}}; 345 const json element = R"( "${var}" )"_json; 346 parseDouble(element, variables); 347 ADD_FAILURE() << "Should not have reached this line."; 348 } 349 catch (const std::invalid_argument& e) 350 { 351 EXPECT_STREQ(e.what(), "Element is not a double"); 352 } 353 354 // Test where fails: Variable specified: Starts with non-number character 355 try 356 { 357 std::map<std::string, std::string> variables{{"var", "x-1.03"}}; 358 const json element = R"( "${var}" )"_json; 359 parseDouble(element, variables); 360 ADD_FAILURE() << "Should not have reached this line."; 361 } 362 catch (const std::invalid_argument& e) 363 { 364 EXPECT_STREQ(e.what(), "Element is not a double"); 365 } 366 367 // Test where fails: Variable specified: Ends with non-number character 368 try 369 { 370 std::map<std::string, std::string> variables{{"var", "-1.03x"}}; 371 const json element = R"( "${var}" )"_json; 372 parseDouble(element, variables); 373 ADD_FAILURE() << "Should not have reached this line."; 374 } 375 catch (const std::invalid_argument& e) 376 { 377 EXPECT_STREQ(e.what(), "Element is not a double"); 378 } 379 380 // Test where fails: Variable specified: Not a double 381 try 382 { 383 std::map<std::string, std::string> variables{{"var", "foo"}}; 384 const json element = R"( "${var}" )"_json; 385 parseDouble(element, variables); 386 ADD_FAILURE() << "Should not have reached this line."; 387 } 388 catch (const std::invalid_argument& e) 389 { 390 EXPECT_STREQ(e.what(), "Element is not a double"); 391 } 392 } 393 394 TEST(JSONParserUtilsTests, ParseHexByte) 395 { 396 // Test where works: "0xFF" 397 { 398 const json element = R"( "0xFF" )"_json; 399 uint8_t value = parseHexByte(element); 400 EXPECT_EQ(value, 0xFF); 401 } 402 403 // Test where works: "0xff" 404 { 405 const json element = R"( "0xff" )"_json; 406 uint8_t value = parseHexByte(element); 407 EXPECT_EQ(value, 0xff); 408 } 409 410 // Test where works: "0xf" 411 { 412 const json element = R"( "0xf" )"_json; 413 uint8_t value = parseHexByte(element); 414 EXPECT_EQ(value, 0xf); 415 } 416 417 // Test where works: Variable specified 418 { 419 std::map<std::string, std::string> variables{{"var", "ed"}}; 420 const json element = R"( "0x${var}" )"_json; 421 uint8_t value = parseHexByte(element, variables); 422 EXPECT_EQ(value, 0xed); 423 } 424 425 // Test where fails: "0xfff" 426 try 427 { 428 const json element = R"( "0xfff" )"_json; 429 parseHexByte(element); 430 ADD_FAILURE() << "Should not have reached this line."; 431 } 432 catch (const std::invalid_argument& e) 433 { 434 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 435 } 436 437 // Test where fails: "0xAG" 438 try 439 { 440 const json element = R"( "0xAG" )"_json; 441 parseHexByte(element); 442 ADD_FAILURE() << "Should not have reached this line."; 443 } 444 catch (const std::invalid_argument& e) 445 { 446 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 447 } 448 449 // Test where fails: "ff" 450 try 451 { 452 const json element = R"( "ff" )"_json; 453 parseHexByte(element); 454 ADD_FAILURE() << "Should not have reached this line."; 455 } 456 catch (const std::invalid_argument& e) 457 { 458 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 459 } 460 461 // Test where fails: "" 462 try 463 { 464 const json element = ""; 465 parseHexByte(element); 466 ADD_FAILURE() << "Should not have reached this line."; 467 } 468 catch (const std::invalid_argument& e) 469 { 470 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 471 } 472 473 // Test where fails: "f" 474 try 475 { 476 const json element = R"( "f" )"_json; 477 parseHexByte(element); 478 ADD_FAILURE() << "Should not have reached this line."; 479 } 480 catch (const std::invalid_argument& e) 481 { 482 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 483 } 484 485 // Test where fails: "0x" 486 try 487 { 488 const json element = R"( "0x" )"_json; 489 parseHexByte(element); 490 ADD_FAILURE() << "Should not have reached this line."; 491 } 492 catch (const std::invalid_argument& e) 493 { 494 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 495 } 496 497 // Test where fails: "0Xff" 498 try 499 { 500 const json element = R"( "0XFF" )"_json; 501 parseHexByte(element); 502 ADD_FAILURE() << "Should not have reached this line."; 503 } 504 catch (const std::invalid_argument& e) 505 { 506 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 507 } 508 509 // Test where fails: Variable specified: Not a hex string 510 try 511 { 512 std::map<std::string, std::string> variables{{"var", "0xsz"}}; 513 const json element = R"( "${var}" )"_json; 514 parseHexByte(element, variables); 515 ADD_FAILURE() << "Should not have reached this line."; 516 } 517 catch (const std::invalid_argument& e) 518 { 519 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 520 } 521 } 522 523 TEST(JSONParserUtilsTests, ParseHexByteArray) 524 { 525 // Test where works 526 { 527 const json element = R"( [ "0xCC", "0xFF" ] )"_json; 528 std::vector<uint8_t> hexBytes = parseHexByteArray(element); 529 std::vector<uint8_t> expected = {0xcc, 0xff}; 530 EXPECT_EQ(hexBytes, expected); 531 } 532 533 // Test where works: Variables specified 534 { 535 std::map<std::string, std::string> variables{{"var1", "0xCC"}, 536 {"var2", "0xFF"}}; 537 const json element = R"( [ "${var1}", "${var2}" ] )"_json; 538 std::vector<uint8_t> hexBytes = parseHexByteArray(element, variables); 539 std::vector<uint8_t> expected = {0xcc, 0xff}; 540 EXPECT_EQ(hexBytes, expected); 541 } 542 543 // Test where fails: Element is not an array 544 try 545 { 546 const json element = 0; 547 parseHexByteArray(element); 548 ADD_FAILURE() << "Should not have reached this line."; 549 } 550 catch (const std::invalid_argument& e) 551 { 552 EXPECT_STREQ(e.what(), "Element is not an array"); 553 } 554 555 // Test where fails: Variables specified: Invalid byte value 556 try 557 { 558 std::map<std::string, std::string> variables{{"var1", "0xCC"}, 559 {"var2", "99"}}; 560 const json element = R"( [ "${var1}", "${var2}" ] )"_json; 561 parseHexByteArray(element, variables); 562 ADD_FAILURE() << "Should not have reached this line."; 563 } 564 catch (const std::invalid_argument& e) 565 { 566 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 567 } 568 } 569 570 TEST(JSONParserUtilsTests, ParseInt8) 571 { 572 // Test where works: INT8_MIN 573 { 574 const json element = R"( -128 )"_json; 575 int8_t value = parseInt8(element); 576 EXPECT_EQ(value, -128); 577 } 578 579 // Test where works: INT8_MAX 580 { 581 const json element = R"( 127 )"_json; 582 int8_t value = parseInt8(element); 583 EXPECT_EQ(value, 127); 584 } 585 586 // Test where works: Variable specified 587 { 588 std::map<std::string, std::string> variables{{"var", "-23"}}; 589 const json element = R"( "${var}" )"_json; 590 int8_t value = parseInt8(element, variables); 591 EXPECT_EQ(value, -23); 592 } 593 594 // Test where fails: Element is not an integer 595 try 596 { 597 const json element = R"( 1.03 )"_json; 598 parseInt8(element); 599 ADD_FAILURE() << "Should not have reached this line."; 600 } 601 catch (const std::invalid_argument& e) 602 { 603 EXPECT_STREQ(e.what(), "Element is not an integer"); 604 } 605 606 // Test where fails: Value < INT8_MIN 607 try 608 { 609 const json element = R"( -129 )"_json; 610 parseInt8(element); 611 ADD_FAILURE() << "Should not have reached this line."; 612 } 613 catch (const std::invalid_argument& e) 614 { 615 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); 616 } 617 618 // Test where fails: Value > INT8_MAX 619 try 620 { 621 const json element = R"( 128 )"_json; 622 parseInt8(element); 623 ADD_FAILURE() << "Should not have reached this line."; 624 } 625 catch (const std::invalid_argument& e) 626 { 627 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); 628 } 629 630 // Test where fails: Variable specified: Value > INT8_MAX 631 try 632 { 633 std::map<std::string, std::string> variables{{"var", "128"}}; 634 const json element = R"( "${var}" )"_json; 635 parseInt8(element, variables); 636 ADD_FAILURE() << "Should not have reached this line."; 637 } 638 catch (const std::invalid_argument& e) 639 { 640 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); 641 } 642 } 643 644 TEST(JSONParserUtilsTests, ParseInteger) 645 { 646 // Test where works: Zero 647 { 648 const json element = R"( 0 )"_json; 649 int value = parseInteger(element); 650 EXPECT_EQ(value, 0); 651 } 652 653 // Test where works: Positive value 654 { 655 const json element = R"( 103 )"_json; 656 int value = parseInteger(element); 657 EXPECT_EQ(value, 103); 658 } 659 660 // Test where works: Negative value 661 { 662 const json element = R"( -24 )"_json; 663 int value = parseInteger(element); 664 EXPECT_EQ(value, -24); 665 } 666 667 // Test where works: Variable specified: Positive value 668 { 669 std::map<std::string, std::string> variables{{"var", "1024"}}; 670 const json element = R"( "${var}" )"_json; 671 int value = parseInteger(element, variables); 672 EXPECT_EQ(value, 1024); 673 } 674 675 // Test where works: Variable specified: Negative value 676 { 677 std::map<std::string, std::string> variables{{"var", "-9924"}}; 678 const json element = R"( "${var}" )"_json; 679 int value = parseInteger(element, variables); 680 EXPECT_EQ(value, -9924); 681 } 682 683 // Test where fails: Element is not a integer 684 try 685 { 686 const json element = R"( true )"_json; 687 parseInteger(element); 688 ADD_FAILURE() << "Should not have reached this line."; 689 } 690 catch (const std::invalid_argument& e) 691 { 692 EXPECT_STREQ(e.what(), "Element is not an integer"); 693 } 694 695 // Test where fails: Variable specified: Variables map not specified 696 try 697 { 698 const json element = R"( "${var}" )"_json; 699 parseInteger(element); 700 ADD_FAILURE() << "Should not have reached this line."; 701 } 702 catch (const std::invalid_argument& e) 703 { 704 EXPECT_STREQ(e.what(), "Element is not an integer"); 705 } 706 707 // Test where fails: Variable specified: Leading whitespace 708 try 709 { 710 std::map<std::string, std::string> variables{{"var", " -13"}}; 711 const json element = R"( "${var}" )"_json; 712 parseInteger(element, variables); 713 ADD_FAILURE() << "Should not have reached this line."; 714 } 715 catch (const std::invalid_argument& e) 716 { 717 EXPECT_STREQ(e.what(), "Element is not an integer"); 718 } 719 720 // Test where fails: Variable specified: Trailing whitespace 721 try 722 { 723 std::map<std::string, std::string> variables{{"var", "-13 "}}; 724 const json element = R"( "${var}" )"_json; 725 parseInteger(element, variables); 726 ADD_FAILURE() << "Should not have reached this line."; 727 } 728 catch (const std::invalid_argument& e) 729 { 730 EXPECT_STREQ(e.what(), "Element is not an integer"); 731 } 732 733 // Test where fails: Variable specified: Starts with non-number character 734 try 735 { 736 std::map<std::string, std::string> variables{{"var", "x-13"}}; 737 const json element = R"( "${var}" )"_json; 738 parseInteger(element, variables); 739 ADD_FAILURE() << "Should not have reached this line."; 740 } 741 catch (const std::invalid_argument& e) 742 { 743 EXPECT_STREQ(e.what(), "Element is not an integer"); 744 } 745 746 // Test where fails: Variable specified: Ends with non-number character 747 try 748 { 749 std::map<std::string, std::string> variables{{"var", "-13x"}}; 750 const json element = R"( "${var}" )"_json; 751 parseInteger(element, variables); 752 ADD_FAILURE() << "Should not have reached this line."; 753 } 754 catch (const std::invalid_argument& e) 755 { 756 EXPECT_STREQ(e.what(), "Element is not an integer"); 757 } 758 759 // Test where fails: Variable specified: Not an integer 760 try 761 { 762 std::map<std::string, std::string> variables{{"var", "foo"}}; 763 const json element = R"( "${var}" )"_json; 764 parseInteger(element, variables); 765 ADD_FAILURE() << "Should not have reached this line."; 766 } 767 catch (const std::invalid_argument& e) 768 { 769 EXPECT_STREQ(e.what(), "Element is not an integer"); 770 } 771 } 772 773 TEST(JSONParserUtilsTests, ParseString) 774 { 775 // Test where works: Empty string 776 { 777 const json element = ""; 778 std::string value = parseString(element, true); 779 EXPECT_EQ(value, ""); 780 } 781 782 // Test where works: Non-empty string 783 { 784 const json element = "vdd_regulator"; 785 std::string value = parseString(element, false); 786 EXPECT_EQ(value, "vdd_regulator"); 787 } 788 789 // Test where works: Variable specified: Empty string 790 { 791 std::map<std::string, std::string> variables{{"var", ""}}; 792 const json element = R"( "${var}" )"_json; 793 std::string value = parseString(element, true, variables); 794 EXPECT_EQ(value, ""); 795 } 796 797 // Test where works: Variable specified: Non-empty string 798 { 799 std::map<std::string, std::string> variables{{"var", "vio_regulator"}}; 800 const json element = R"( "${var}" )"_json; 801 std::string value = parseString(element, false, variables); 802 EXPECT_EQ(value, "vio_regulator"); 803 } 804 805 // Test where fails: Element is not a string 806 try 807 { 808 const json element = R"( { "foo": "bar" } )"_json; 809 parseString(element); 810 ADD_FAILURE() << "Should not have reached this line."; 811 } 812 catch (const std::invalid_argument& e) 813 { 814 EXPECT_STREQ(e.what(), "Element is not a string"); 815 } 816 817 // Test where fails: Empty string 818 try 819 { 820 const json element = ""; 821 parseString(element); 822 ADD_FAILURE() << "Should not have reached this line."; 823 } 824 catch (const std::invalid_argument& e) 825 { 826 EXPECT_STREQ(e.what(), "Element contains an empty string"); 827 } 828 829 // Test where fails: Variable specified: Empty string 830 try 831 { 832 std::map<std::string, std::string> variables{{"var", ""}}; 833 const json element = R"( "${var}" )"_json; 834 parseString(element, false, variables); 835 ADD_FAILURE() << "Should not have reached this line."; 836 } 837 catch (const std::invalid_argument& e) 838 { 839 EXPECT_STREQ(e.what(), "Element contains an empty string"); 840 } 841 842 // Test where fails: Variable specified: Variable not defined 843 try 844 { 845 std::map<std::string, std::string> variables{{"var1", "foo"}}; 846 const json element = R"( "${var2}" )"_json; 847 parseString(element, false, variables); 848 ADD_FAILURE() << "Should not have reached this line."; 849 } 850 catch (const std::invalid_argument& e) 851 { 852 EXPECT_STREQ(e.what(), "Undefined variable: var2"); 853 } 854 } 855 856 TEST(JSONParserUtilsTests, ParseUint8) 857 { 858 // Test where works: 0 859 { 860 const json element = R"( 0 )"_json; 861 uint8_t value = parseUint8(element); 862 EXPECT_EQ(value, 0); 863 } 864 865 // Test where works: UINT8_MAX 866 { 867 const json element = R"( 255 )"_json; 868 uint8_t value = parseUint8(element); 869 EXPECT_EQ(value, 255); 870 } 871 872 // Test where works: Variable specified 873 { 874 std::map<std::string, std::string> variables{{"var", "19"}}; 875 const json element = R"( "${var}" )"_json; 876 uint8_t value = parseUint8(element, variables); 877 EXPECT_EQ(value, 19); 878 } 879 880 // Test where fails: Element is not an integer 881 try 882 { 883 const json element = R"( 1.03 )"_json; 884 parseUint8(element); 885 ADD_FAILURE() << "Should not have reached this line."; 886 } 887 catch (const std::invalid_argument& e) 888 { 889 EXPECT_STREQ(e.what(), "Element is not an integer"); 890 } 891 892 // Test where fails: Value < 0 893 try 894 { 895 const json element = R"( -1 )"_json; 896 parseUint8(element); 897 ADD_FAILURE() << "Should not have reached this line."; 898 } 899 catch (const std::invalid_argument& e) 900 { 901 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); 902 } 903 904 // Test where fails: Value > UINT8_MAX 905 try 906 { 907 const json element = R"( 256 )"_json; 908 parseUint8(element); 909 ADD_FAILURE() << "Should not have reached this line."; 910 } 911 catch (const std::invalid_argument& e) 912 { 913 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); 914 } 915 916 // Test where fails: Variable specified: Value > UINT8_MAX 917 try 918 { 919 std::map<std::string, std::string> variables{{"var", "256"}}; 920 const json element = R"( "${var}" )"_json; 921 parseUint8(element, variables); 922 ADD_FAILURE() << "Should not have reached this line."; 923 } 924 catch (const std::invalid_argument& e) 925 { 926 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); 927 } 928 } 929 930 TEST(JSONParserUtilsTests, ParseUnsignedInteger) 931 { 932 // Test where works: 1 933 { 934 const json element = R"( 1 )"_json; 935 unsigned int value = parseUnsignedInteger(element); 936 EXPECT_EQ(value, 1); 937 } 938 939 // Test where works: Variable specified 940 { 941 std::map<std::string, std::string> variables{{"var", "25678"}}; 942 const json element = R"( "${var}" )"_json; 943 unsigned int value = parseUnsignedInteger(element, variables); 944 EXPECT_EQ(value, 25678); 945 } 946 947 // Test where fails: Element is not an integer 948 try 949 { 950 const json element = R"( 1.5 )"_json; 951 parseUnsignedInteger(element); 952 ADD_FAILURE() << "Should not have reached this line."; 953 } 954 catch (const std::invalid_argument& e) 955 { 956 EXPECT_STREQ(e.what(), "Element is not an integer"); 957 } 958 959 // Test where fails: Value < 0 960 try 961 { 962 const json element = R"( -1 )"_json; 963 parseUnsignedInteger(element); 964 ADD_FAILURE() << "Should not have reached this line."; 965 } 966 catch (const std::invalid_argument& e) 967 { 968 EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); 969 } 970 971 // Test where fails: Variable specified: Value < 0 972 try 973 { 974 std::map<std::string, std::string> variables{{"var", "-23"}}; 975 const json element = R"( "${var}" )"_json; 976 parseUnsignedInteger(element, variables); 977 ADD_FAILURE() << "Should not have reached this line."; 978 } 979 catch (const std::invalid_argument& e) 980 { 981 EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); 982 } 983 } 984 985 TEST(JSONParserUtilsTests, VerifyIsArray) 986 { 987 // Test where element is an array 988 { 989 const json element = R"( [ "foo", "bar" ] )"_json; 990 verifyIsArray(element); 991 } 992 993 // Test where element is not an array 994 try 995 { 996 const json element = R"( { "foo": "bar" } )"_json; 997 verifyIsArray(element); 998 ADD_FAILURE() << "Should not have reached this line."; 999 } 1000 catch (const std::invalid_argument& e) 1001 { 1002 EXPECT_STREQ(e.what(), "Element is not an array"); 1003 } 1004 } 1005 1006 TEST(JSONParserUtilsTests, VerifyIsObject) 1007 { 1008 // Test where element is an object 1009 { 1010 const json element = R"( { "foo": "bar" } )"_json; 1011 verifyIsObject(element); 1012 } 1013 1014 // Test where element is not an object 1015 try 1016 { 1017 const json element = R"( [ "foo", "bar" ] )"_json; 1018 verifyIsObject(element); 1019 ADD_FAILURE() << "Should not have reached this line."; 1020 } 1021 catch (const std::invalid_argument& e) 1022 { 1023 EXPECT_STREQ(e.what(), "Element is not an object"); 1024 } 1025 } 1026 1027 TEST(JSONParserUtilsTests, VerifyPropertyCount) 1028 { 1029 // Test where element has expected number of properties 1030 { 1031 const json element = R"( 1032 { 1033 "comments": [ "Set voltage rule" ], 1034 "id": "set_voltage_rule" 1035 } 1036 )"_json; 1037 verifyPropertyCount(element, 2); 1038 } 1039 1040 // Test where element has unexpected number of properties 1041 try 1042 { 1043 const json element = R"( 1044 { 1045 "comments": [ "Set voltage rule" ], 1046 "id": "set_voltage_rule", 1047 "foo": 1.3 1048 } 1049 )"_json; 1050 verifyPropertyCount(element, 2); 1051 ADD_FAILURE() << "Should not have reached this line."; 1052 } 1053 catch (const std::invalid_argument& e) 1054 { 1055 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 1056 } 1057 } 1058 1059 TEST(JSONParserUtilsTests, ExpandVariables) 1060 { 1061 // Test where works: Single variable: Variable is entire value: Lower case 1062 // in variable name 1063 { 1064 std::map<std::string, std::string> variables{{"var", "vio_regulator"}}; 1065 std::string value{"${var}"}; 1066 expandVariables(value, variables); 1067 EXPECT_EQ(value, "vio_regulator"); 1068 } 1069 1070 // Test where works: Multiple variables: Variables are part of value: Upper 1071 // case and underscore in variable name 1072 { 1073 std::map<std::string, std::string> variables{ 1074 {"CHASSIS_NUMBER", "1"}, {"REGULATOR", "vcs_vio"}, {"RAIL", "vio"}}; 1075 std::string value{ 1076 "chassis${CHASSIS_NUMBER}_${REGULATOR}_regulator_${RAIL}_rail"}; 1077 expandVariables(value, variables); 1078 EXPECT_EQ(value, "chassis1_vcs_vio_regulator_vio_rail"); 1079 } 1080 1081 // Test where works: Variable at start of value: Number in variable name 1082 { 1083 std::map<std::string, std::string> variables{{"var1", "vio_regulator"}}; 1084 std::string value{"${var1}_rail"}; 1085 expandVariables(value, variables); 1086 EXPECT_EQ(value, "vio_regulator_rail"); 1087 } 1088 1089 // Test where works: Variable at end of value 1090 { 1091 std::map<std::string, std::string> variables{{"chassis_number", "3"}}; 1092 std::string value{ 1093 "/xyz/openbmc_project/inventory/system/chassis${chassis_number}"}; 1094 expandVariables(value, variables); 1095 EXPECT_EQ(value, "/xyz/openbmc_project/inventory/system/chassis3"); 1096 } 1097 1098 // Test where works: Variable has empty value: Start of value 1099 { 1100 std::map<std::string, std::string> variables{{"chassis_prefix", ""}}; 1101 std::string value{"${chassis_prefix}vio_regulator"}; 1102 expandVariables(value, variables); 1103 EXPECT_EQ(value, "vio_regulator"); 1104 } 1105 1106 // Test where works: Variable has empty value: Middle of value 1107 { 1108 std::map<std::string, std::string> variables{{"chassis_number", ""}}; 1109 std::string value{"c${chassis_number}_vio_regulator"}; 1110 expandVariables(value, variables); 1111 EXPECT_EQ(value, "c_vio_regulator"); 1112 } 1113 1114 // Test where works: Variable has empty value: End of value 1115 { 1116 std::map<std::string, std::string> variables{{"chassis_number", ""}}; 1117 std::string value{ 1118 "/xyz/openbmc_project/inventory/system/chassis${chassis_number}"}; 1119 expandVariables(value, variables); 1120 EXPECT_EQ(value, "/xyz/openbmc_project/inventory/system/chassis"); 1121 } 1122 1123 // Test where works: No variables specified 1124 { 1125 std::map<std::string, std::string> variables{{"var", "vio_regulator"}}; 1126 std::string value{"vcs_rail"}; 1127 expandVariables(value, variables); 1128 EXPECT_EQ(value, "vcs_rail"); 1129 } 1130 1131 // Test where works: Nested variable expansion 1132 { 1133 std::map<std::string, std::string> variables{{"var1", "${var2}"}, 1134 {"var2", "vio_reg"}}; 1135 std::string value{"${var1}_rail"}; 1136 expandVariables(value, variables); 1137 EXPECT_EQ(value, "vio_reg_rail"); 1138 } 1139 1140 // Test where fails: Variables map is empty 1141 { 1142 std::map<std::string, std::string> variables{}; 1143 std::string value{"${var}_rail"}; 1144 expandVariables(value, variables); 1145 EXPECT_EQ(value, "${var}_rail"); 1146 } 1147 1148 // Test where fails: Variable missing $ 1149 { 1150 std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1151 std::string value{"{var}_rail"}; 1152 expandVariables(value, variables); 1153 EXPECT_EQ(value, "{var}_rail"); 1154 } 1155 1156 // Test where fails: Variable missing { 1157 { 1158 std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1159 std::string value{"$var}_rail"}; 1160 expandVariables(value, variables); 1161 EXPECT_EQ(value, "$var}_rail"); 1162 } 1163 1164 // Test where fails: Variable missing } 1165 { 1166 std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1167 std::string value{"${var_rail"}; 1168 expandVariables(value, variables); 1169 EXPECT_EQ(value, "${var_rail"); 1170 } 1171 1172 // Test where fails: Variable missing name 1173 { 1174 std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1175 std::string value{"${}_rail"}; 1176 expandVariables(value, variables); 1177 EXPECT_EQ(value, "${}_rail"); 1178 } 1179 1180 // Test where fails: Variable name has invalid characters 1181 { 1182 std::map<std::string, std::string> variables{{"var-2", "vio_reg"}}; 1183 std::string value{"${var-2}_rail"}; 1184 expandVariables(value, variables); 1185 EXPECT_EQ(value, "${var-2}_rail"); 1186 } 1187 1188 // Test where fails: Variable has unexpected whitespace 1189 { 1190 std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1191 std::string value{"${ var }_rail"}; 1192 expandVariables(value, variables); 1193 EXPECT_EQ(value, "${ var }_rail"); 1194 } 1195 1196 // Test where fails: Undefined variable 1197 try 1198 { 1199 std::map<std::string, std::string> variables{{"var", "vio_reg"}}; 1200 std::string value{"${foo}_rail"}; 1201 expandVariables(value, variables); 1202 ADD_FAILURE() << "Should not have reached this line."; 1203 } 1204 catch (const std::invalid_argument& e) 1205 { 1206 EXPECT_STREQ(e.what(), "Undefined variable: foo"); 1207 } 1208 } 1209