1 /** 2 * Copyright © 2020 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 "action.hpp" 17 #include "and_action.hpp" 18 #include "chassis.hpp" 19 #include "compare_presence_action.hpp" 20 #include "compare_vpd_action.hpp" 21 #include "config_file_parser.hpp" 22 #include "config_file_parser_error.hpp" 23 #include "configuration.hpp" 24 #include "device.hpp" 25 #include "i2c_capture_bytes_action.hpp" 26 #include "i2c_compare_bit_action.hpp" 27 #include "i2c_compare_byte_action.hpp" 28 #include "i2c_compare_bytes_action.hpp" 29 #include "i2c_interface.hpp" 30 #include "i2c_write_bit_action.hpp" 31 #include "i2c_write_byte_action.hpp" 32 #include "i2c_write_bytes_action.hpp" 33 #include "log_phase_fault_action.hpp" 34 #include "not_action.hpp" 35 #include "or_action.hpp" 36 #include "phase_fault.hpp" 37 #include "phase_fault_detection.hpp" 38 #include "pmbus_read_sensor_action.hpp" 39 #include "pmbus_utils.hpp" 40 #include "pmbus_write_vout_command_action.hpp" 41 #include "presence_detection.hpp" 42 #include "rail.hpp" 43 #include "rule.hpp" 44 #include "run_rule_action.hpp" 45 #include "sensor_monitoring.hpp" 46 #include "sensors.hpp" 47 #include "set_device_action.hpp" 48 #include "temporary_file.hpp" 49 50 #include <sys/stat.h> // for chmod() 51 52 #include <nlohmann/json.hpp> 53 54 #include <cstdint> 55 #include <cstring> 56 #include <exception> 57 #include <filesystem> 58 #include <fstream> 59 #include <memory> 60 #include <optional> 61 #include <stdexcept> 62 #include <string> 63 #include <tuple> 64 #include <vector> 65 66 #include <gtest/gtest.h> 67 68 using namespace phosphor::power::regulators; 69 using namespace phosphor::power::regulators::config_file_parser; 70 using namespace phosphor::power::regulators::config_file_parser::internal; 71 using json = nlohmann::json; 72 73 void writeConfigFile(const std::filesystem::path& pathName, 74 const std::string& contents) 75 { 76 std::ofstream file{pathName}; 77 file << contents; 78 } 79 80 void writeConfigFile(const std::filesystem::path& pathName, 81 const json& contents) 82 { 83 std::ofstream file{pathName}; 84 file << contents; 85 } 86 87 TEST(ConfigFileParserTests, Parse) 88 { 89 // Test where works 90 { 91 const json configFileContents = R"( 92 { 93 "rules": [ 94 { 95 "id": "set_voltage_rule1", 96 "actions": [ 97 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } } 98 ] 99 }, 100 { 101 "id": "set_voltage_rule2", 102 "actions": [ 103 { "pmbus_write_vout_command": { "volts": 1.33, "format": "linear" } } 104 ] 105 } 106 ], 107 "chassis": [ 108 { "number": 1 }, 109 { "number": 2 }, 110 { "number": 3 } 111 ] 112 } 113 )"_json; 114 115 TemporaryFile configFile; 116 std::filesystem::path pathName{configFile.getPath()}; 117 writeConfigFile(pathName, configFileContents); 118 119 std::vector<std::unique_ptr<Rule>> rules{}; 120 std::vector<std::unique_ptr<Chassis>> chassis{}; 121 std::tie(rules, chassis) = parse(pathName); 122 123 EXPECT_EQ(rules.size(), 2); 124 EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1"); 125 EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2"); 126 127 EXPECT_EQ(chassis.size(), 3); 128 EXPECT_EQ(chassis[0]->getNumber(), 1); 129 EXPECT_EQ(chassis[1]->getNumber(), 2); 130 EXPECT_EQ(chassis[2]->getNumber(), 3); 131 } 132 133 // Test where fails: File does not exist 134 try 135 { 136 std::filesystem::path pathName{"/tmp/non_existent_file"}; 137 parse(pathName); 138 ADD_FAILURE() << "Should not have reached this line."; 139 } 140 catch (const ConfigFileParserError& e) 141 { 142 // Expected exception; what() message will vary 143 } 144 145 // Test where fails: File is not readable 146 try 147 { 148 const json configFileContents = R"( 149 { 150 "chassis": [ { "number": 1 } ] 151 } 152 )"_json; 153 154 TemporaryFile configFile; 155 std::filesystem::path pathName{configFile.getPath()}; 156 writeConfigFile(pathName, configFileContents); 157 158 chmod(pathName.c_str(), 0222); 159 160 parse(pathName); 161 ADD_FAILURE() << "Should not have reached this line."; 162 } 163 catch (const ConfigFileParserError& e) 164 { 165 // Expected exception; what() message will vary 166 } 167 168 // Test where fails: File is not valid JSON 169 try 170 { 171 const std::string configFileContents = "] foo ["; 172 173 TemporaryFile configFile; 174 std::filesystem::path pathName{configFile.getPath()}; 175 writeConfigFile(pathName, configFileContents); 176 177 parse(pathName); 178 ADD_FAILURE() << "Should not have reached this line."; 179 } 180 catch (const ConfigFileParserError& e) 181 { 182 // Expected exception; what() message will vary 183 } 184 185 // Test where fails: Error when parsing JSON elements 186 try 187 { 188 const json configFileContents = R"( { "foo": "bar" } )"_json; 189 190 TemporaryFile configFile; 191 std::filesystem::path pathName{configFile.getPath()}; 192 writeConfigFile(pathName, configFileContents); 193 194 parse(pathName); 195 ADD_FAILURE() << "Should not have reached this line."; 196 } 197 catch (const ConfigFileParserError& e) 198 { 199 // Expected exception; what() message will vary 200 } 201 } 202 203 TEST(ConfigFileParserTests, GetRequiredProperty) 204 { 205 // Test where property exists 206 { 207 const json element = R"( { "format": "linear" } )"_json; 208 const json& propertyElement = getRequiredProperty(element, "format"); 209 EXPECT_EQ(propertyElement.get<std::string>(), "linear"); 210 } 211 212 // Test where property does not exist 213 try 214 { 215 const json element = R"( { "volts": 1.03 } )"_json; 216 getRequiredProperty(element, "format"); 217 ADD_FAILURE() << "Should not have reached this line."; 218 } 219 catch (const std::invalid_argument& e) 220 { 221 EXPECT_STREQ(e.what(), "Required property missing: format"); 222 } 223 } 224 225 TEST(ConfigFileParserTests, ParseAction) 226 { 227 // Test where works: comments property specified 228 { 229 const json element = R"( 230 { 231 "comments": [ "Set output voltage." ], 232 "pmbus_write_vout_command": { 233 "format": "linear" 234 } 235 } 236 )"_json; 237 std::unique_ptr<Action> action = parseAction(element); 238 EXPECT_NE(action.get(), nullptr); 239 } 240 241 // Test where works: comments property not specified 242 { 243 const json element = R"( 244 { 245 "pmbus_write_vout_command": { 246 "format": "linear" 247 } 248 } 249 )"_json; 250 std::unique_ptr<Action> action = parseAction(element); 251 EXPECT_NE(action.get(), nullptr); 252 } 253 254 // Test where works: and action type specified 255 { 256 const json element = R"( 257 { 258 "and": [ 259 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, 260 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } 261 ] 262 } 263 )"_json; 264 std::unique_ptr<Action> action = parseAction(element); 265 EXPECT_NE(action.get(), nullptr); 266 } 267 268 // Test where works: compare_presence action type specified 269 { 270 const json element = R"( 271 { 272 "compare_presence": 273 { 274 "fru": "system/chassis/motherboard/cpu3", 275 "value": true 276 } 277 } 278 )"_json; 279 std::unique_ptr<Action> action = parseAction(element); 280 EXPECT_NE(action.get(), nullptr); 281 } 282 283 // Test where works: compare_vpd action type specified 284 { 285 const json element = R"( 286 { 287 "compare_vpd": 288 { 289 "fru": "system/chassis/disk_backplane", 290 "keyword": "CCIN", 291 "value": "2D35" 292 } 293 } 294 )"_json; 295 std::unique_ptr<Action> action = parseAction(element); 296 EXPECT_NE(action.get(), nullptr); 297 } 298 299 // Test where works: i2c_capture_bytes action type specified 300 { 301 const json element = R"( 302 { 303 "i2c_capture_bytes": { 304 "register": "0xA0", 305 "count": 2 306 } 307 } 308 )"_json; 309 std::unique_ptr<Action> action = parseAction(element); 310 EXPECT_NE(action.get(), nullptr); 311 } 312 313 // Test where works: i2c_compare_bit action type specified 314 { 315 const json element = R"( 316 { 317 "i2c_compare_bit": { 318 "register": "0xA0", 319 "position": 3, 320 "value": 0 321 } 322 } 323 )"_json; 324 std::unique_ptr<Action> action = parseAction(element); 325 EXPECT_NE(action.get(), nullptr); 326 } 327 328 // Test where works: i2c_compare_byte action type specified 329 { 330 const json element = R"( 331 { 332 "i2c_compare_byte": { 333 "register": "0x0A", 334 "value": "0xCC" 335 } 336 } 337 )"_json; 338 std::unique_ptr<Action> action = parseAction(element); 339 EXPECT_NE(action.get(), nullptr); 340 } 341 342 // Test where works: i2c_compare_bytes action type specified 343 { 344 const json element = R"( 345 { 346 "i2c_compare_bytes": { 347 "register": "0x0A", 348 "values": [ "0xCC", "0xFF" ] 349 } 350 } 351 )"_json; 352 std::unique_ptr<Action> action = parseAction(element); 353 EXPECT_NE(action.get(), nullptr); 354 } 355 356 // Test where works: i2c_write_bit action type specified 357 { 358 const json element = R"( 359 { 360 "i2c_write_bit": { 361 "register": "0xA0", 362 "position": 3, 363 "value": 0 364 } 365 } 366 )"_json; 367 std::unique_ptr<Action> action = parseAction(element); 368 EXPECT_NE(action.get(), nullptr); 369 } 370 371 // Test where works: i2c_write_byte action type specified 372 { 373 const json element = R"( 374 { 375 "i2c_write_byte": { 376 "register": "0x0A", 377 "value": "0xCC" 378 } 379 } 380 )"_json; 381 std::unique_ptr<Action> action = parseAction(element); 382 EXPECT_NE(action.get(), nullptr); 383 } 384 385 // Test where works: i2c_write_bytes action type specified 386 { 387 const json element = R"( 388 { 389 "i2c_write_bytes": { 390 "register": "0x0A", 391 "values": [ "0xCC", "0xFF" ] 392 } 393 } 394 )"_json; 395 std::unique_ptr<Action> action = parseAction(element); 396 EXPECT_NE(action.get(), nullptr); 397 } 398 399 // Test where works: if action type specified 400 { 401 const json element = R"( 402 { 403 "if": 404 { 405 "condition": { "run_rule": "is_downlevel_regulator" }, 406 "then": [ { "run_rule": "configure_downlevel_regulator" } ], 407 "else": [ { "run_rule": "configure_standard_regulator" } ] 408 } 409 } 410 )"_json; 411 std::unique_ptr<Action> action = parseAction(element); 412 EXPECT_NE(action.get(), nullptr); 413 } 414 415 // Test where works: log_phase_fault action type specified 416 { 417 const json element = R"( 418 { 419 "log_phase_fault": { 420 "type": "n+1" 421 } 422 } 423 )"_json; 424 std::unique_ptr<Action> action = parseAction(element); 425 EXPECT_NE(action.get(), nullptr); 426 } 427 428 // Test where works: not action type specified 429 { 430 const json element = R"( 431 { 432 "not": 433 { "i2c_compare_byte": { "register": "0xA0", "value": "0xFF" } } 434 } 435 )"_json; 436 std::unique_ptr<Action> action = parseAction(element); 437 EXPECT_NE(action.get(), nullptr); 438 } 439 440 // Test where works: or action type specified 441 { 442 const json element = R"( 443 { 444 "or": [ 445 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, 446 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } 447 ] 448 } 449 )"_json; 450 std::unique_ptr<Action> action = parseAction(element); 451 EXPECT_NE(action.get(), nullptr); 452 } 453 454 // Test where works: pmbus_read_sensor action type specified 455 { 456 const json element = R"( 457 { 458 "pmbus_read_sensor": { 459 "type": "iout", 460 "command": "0x8C", 461 "format": "linear_11" 462 } 463 } 464 )"_json; 465 std::unique_ptr<Action> action = parseAction(element); 466 EXPECT_NE(action.get(), nullptr); 467 } 468 469 // Test where works: pmbus_write_vout_command action type specified 470 { 471 const json element = R"( 472 { 473 "pmbus_write_vout_command": { 474 "format": "linear" 475 } 476 } 477 )"_json; 478 std::unique_ptr<Action> action = parseAction(element); 479 EXPECT_NE(action.get(), nullptr); 480 } 481 482 // Test where works: run_rule action type specified 483 { 484 const json element = R"( 485 { 486 "run_rule": "set_voltage_rule" 487 } 488 )"_json; 489 std::unique_ptr<Action> action = parseAction(element); 490 EXPECT_NE(action.get(), nullptr); 491 } 492 493 // Test where works: set_device action type specified 494 { 495 const json element = R"( 496 { 497 "set_device": "io_expander2" 498 } 499 )"_json; 500 std::unique_ptr<Action> action = parseAction(element); 501 EXPECT_NE(action.get(), nullptr); 502 } 503 504 // Test where fails: Element is not an object 505 try 506 { 507 const json element = R"( [ "0xFF", "0x01" ] )"_json; 508 parseAction(element); 509 ADD_FAILURE() << "Should not have reached this line."; 510 } 511 catch (const std::invalid_argument& e) 512 { 513 EXPECT_STREQ(e.what(), "Element is not an object"); 514 } 515 516 // Test where fails: No action type specified 517 try 518 { 519 const json element = R"( 520 { 521 "comments": [ "Set output voltage." ] 522 } 523 )"_json; 524 parseAction(element); 525 ADD_FAILURE() << "Should not have reached this line."; 526 } 527 catch (const std::invalid_argument& e) 528 { 529 EXPECT_STREQ(e.what(), "Required action type property missing"); 530 } 531 532 // Test where fails: Multiple action types specified 533 try 534 { 535 const json element = R"( 536 { 537 "pmbus_write_vout_command": { "format": "linear" }, 538 "run_rule": "set_voltage_rule" 539 } 540 )"_json; 541 parseAction(element); 542 ADD_FAILURE() << "Should not have reached this line."; 543 } 544 catch (const std::invalid_argument& e) 545 { 546 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 547 } 548 549 // Test where fails: Invalid property specified 550 try 551 { 552 const json element = R"( 553 { 554 "remarks": [ "Set output voltage." ], 555 "pmbus_write_vout_command": { 556 "format": "linear" 557 } 558 } 559 )"_json; 560 parseAction(element); 561 ADD_FAILURE() << "Should not have reached this line."; 562 } 563 catch (const std::invalid_argument& e) 564 { 565 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 566 } 567 } 568 569 TEST(ConfigFileParserTests, ParseActionArray) 570 { 571 // Test where works 572 { 573 const json element = R"( 574 [ 575 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }, 576 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } } 577 ] 578 )"_json; 579 std::vector<std::unique_ptr<Action>> actions = 580 parseActionArray(element); 581 EXPECT_EQ(actions.size(), 2); 582 } 583 584 // Test where fails: Element is not an array 585 try 586 { 587 const json element = R"( 588 { 589 "foo": "bar" 590 } 591 )"_json; 592 parseActionArray(element); 593 ADD_FAILURE() << "Should not have reached this line."; 594 } 595 catch (const std::invalid_argument& e) 596 { 597 EXPECT_STREQ(e.what(), "Element is not an array"); 598 } 599 } 600 601 TEST(ConfigFileParserTests, ParseAnd) 602 { 603 // Test where works: Element is an array with 2 actions 604 { 605 const json element = R"( 606 [ 607 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, 608 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } 609 ] 610 )"_json; 611 std::unique_ptr<AndAction> action = parseAnd(element); 612 EXPECT_EQ(action->getActions().size(), 2); 613 } 614 615 // Test where fails: Element is an array with 1 action 616 try 617 { 618 const json element = R"( 619 [ 620 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } } 621 ] 622 )"_json; 623 parseAnd(element); 624 ADD_FAILURE() << "Should not have reached this line."; 625 } 626 catch (const std::invalid_argument& e) 627 { 628 EXPECT_STREQ(e.what(), "Array must contain two or more actions"); 629 } 630 631 // Test where fails: Element is not an array 632 try 633 { 634 const json element = R"( 635 { 636 "foo": "bar" 637 } 638 )"_json; 639 parseAnd(element); 640 ADD_FAILURE() << "Should not have reached this line."; 641 } 642 catch (const std::invalid_argument& e) 643 { 644 EXPECT_STREQ(e.what(), "Element is not an array"); 645 } 646 } 647 648 TEST(ConfigFileParserTests, ParseBitPosition) 649 { 650 // Test where works: 0 651 { 652 const json element = R"( 0 )"_json; 653 uint8_t value = parseBitPosition(element); 654 EXPECT_EQ(value, 0); 655 } 656 657 // Test where works: 7 658 { 659 const json element = R"( 7 )"_json; 660 uint8_t value = parseBitPosition(element); 661 EXPECT_EQ(value, 7); 662 } 663 664 // Test where fails: Element is not an integer 665 try 666 { 667 const json element = R"( 1.03 )"_json; 668 parseBitPosition(element); 669 ADD_FAILURE() << "Should not have reached this line."; 670 } 671 catch (const std::invalid_argument& e) 672 { 673 EXPECT_STREQ(e.what(), "Element is not an integer"); 674 } 675 676 // Test where fails: Value < 0 677 try 678 { 679 const json element = R"( -1 )"_json; 680 parseBitPosition(element); 681 ADD_FAILURE() << "Should not have reached this line."; 682 } 683 catch (const std::invalid_argument& e) 684 { 685 EXPECT_STREQ(e.what(), "Element is not a bit position"); 686 } 687 688 // Test where fails: Value > 7 689 try 690 { 691 const json element = R"( 8 )"_json; 692 parseBitPosition(element); 693 ADD_FAILURE() << "Should not have reached this line."; 694 } 695 catch (const std::invalid_argument& e) 696 { 697 EXPECT_STREQ(e.what(), "Element is not a bit position"); 698 } 699 } 700 701 TEST(ConfigFileParserTests, ParseBitValue) 702 { 703 // Test where works: 0 704 { 705 const json element = R"( 0 )"_json; 706 uint8_t value = parseBitValue(element); 707 EXPECT_EQ(value, 0); 708 } 709 710 // Test where works: 1 711 { 712 const json element = R"( 1 )"_json; 713 uint8_t value = parseBitValue(element); 714 EXPECT_EQ(value, 1); 715 } 716 717 // Test where fails: Element is not an integer 718 try 719 { 720 const json element = R"( 0.5 )"_json; 721 parseBitValue(element); 722 ADD_FAILURE() << "Should not have reached this line."; 723 } 724 catch (const std::invalid_argument& e) 725 { 726 EXPECT_STREQ(e.what(), "Element is not an integer"); 727 } 728 729 // Test where fails: Value < 0 730 try 731 { 732 const json element = R"( -1 )"_json; 733 parseBitValue(element); 734 ADD_FAILURE() << "Should not have reached this line."; 735 } 736 catch (const std::invalid_argument& e) 737 { 738 EXPECT_STREQ(e.what(), "Element is not a bit value"); 739 } 740 741 // Test where fails: Value > 1 742 try 743 { 744 const json element = R"( 2 )"_json; 745 parseBitValue(element); 746 ADD_FAILURE() << "Should not have reached this line."; 747 } 748 catch (const std::invalid_argument& e) 749 { 750 EXPECT_STREQ(e.what(), "Element is not a bit value"); 751 } 752 } 753 754 TEST(ConfigFileParserTests, ParseBoolean) 755 { 756 // Test where works: true 757 { 758 const json element = R"( true )"_json; 759 bool value = parseBoolean(element); 760 EXPECT_EQ(value, true); 761 } 762 763 // Test where works: false 764 { 765 const json element = R"( false )"_json; 766 bool value = parseBoolean(element); 767 EXPECT_EQ(value, false); 768 } 769 770 // Test where fails: Element is not a boolean 771 try 772 { 773 const json element = R"( 1 )"_json; 774 parseBoolean(element); 775 ADD_FAILURE() << "Should not have reached this line."; 776 } 777 catch (const std::invalid_argument& e) 778 { 779 EXPECT_STREQ(e.what(), "Element is not a boolean"); 780 } 781 } 782 783 TEST(ConfigFileParserTests, ParseChassis) 784 { 785 // Test where works: Only required properties specified 786 { 787 const json element = R"( 788 { 789 "number": 1 790 } 791 )"_json; 792 std::unique_ptr<Chassis> chassis = parseChassis(element); 793 EXPECT_EQ(chassis->getNumber(), 1); 794 EXPECT_EQ(chassis->getInventoryPath(), 795 "/xyz/openbmc_project/inventory/system/chassis"); 796 EXPECT_EQ(chassis->getDevices().size(), 0); 797 } 798 799 // Test where works: All properties specified 800 { 801 const json element = R"( 802 { 803 "comments": [ "comments property" ], 804 "number": 2, 805 "inventory_path": "system/chassis2", 806 "devices": [ 807 { 808 "id": "vdd_regulator", 809 "is_regulator": true, 810 "fru": "system/chassis/motherboard/regulator2", 811 "i2c_interface": 812 { 813 "bus": 1, 814 "address": "0x70" 815 } 816 } 817 ] 818 } 819 )"_json; 820 std::unique_ptr<Chassis> chassis = parseChassis(element); 821 EXPECT_EQ(chassis->getNumber(), 2); 822 EXPECT_EQ(chassis->getInventoryPath(), 823 "/xyz/openbmc_project/inventory/system/chassis2"); 824 EXPECT_EQ(chassis->getDevices().size(), 1); 825 EXPECT_EQ(chassis->getDevices()[0]->getID(), "vdd_regulator"); 826 } 827 828 // Test where fails: number value is invalid 829 try 830 { 831 const json element = R"( 832 { 833 "number": 0.5 834 } 835 )"_json; 836 parseChassis(element); 837 ADD_FAILURE() << "Should not have reached this line."; 838 } 839 catch (const std::invalid_argument& e) 840 { 841 EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); 842 } 843 844 // Test where fails: inventory_path is invalid: Not a string 845 try 846 { 847 const json element = R"( 848 { 849 "number": 2, 850 "inventory_path": true 851 } 852 )"_json; 853 parseChassis(element); 854 ADD_FAILURE() << "Should not have reached this line."; 855 } 856 catch (const std::invalid_argument& e) 857 { 858 EXPECT_STREQ(e.what(), "Element is not a string"); 859 } 860 861 // Test where fails: inventory_path is invalid: Empty string 862 try 863 { 864 const json element = R"( 865 { 866 "number": 2, 867 "inventory_path": "" 868 } 869 )"_json; 870 parseChassis(element); 871 ADD_FAILURE() << "Should not have reached this line."; 872 } 873 catch (const std::invalid_argument& e) 874 { 875 EXPECT_STREQ(e.what(), "Element contains an empty string"); 876 } 877 878 // Test where fails: Invalid property specified 879 try 880 { 881 const json element = R"( 882 { 883 "number": 1, 884 "foo": 2 885 } 886 )"_json; 887 parseChassis(element); 888 ADD_FAILURE() << "Should not have reached this line."; 889 } 890 catch (const std::invalid_argument& e) 891 { 892 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 893 } 894 895 // Test where fails: Required number property not specified 896 try 897 { 898 const json element = R"( 899 { 900 "devices": [ 901 { 902 "id": "vdd_regulator", 903 "is_regulator": true, 904 "fru": "system/chassis/motherboard/regulator2", 905 "i2c_interface": 906 { 907 "bus": 1, 908 "address": "0x70" 909 } 910 } 911 ] 912 } 913 )"_json; 914 parseChassis(element); 915 ADD_FAILURE() << "Should not have reached this line."; 916 } 917 catch (const std::invalid_argument& e) 918 { 919 EXPECT_STREQ(e.what(), "Required property missing: number"); 920 } 921 922 // Test where fails: Element is not an object 923 try 924 { 925 const json element = R"( [ "0xFF", "0x01" ] )"_json; 926 parseChassis(element); 927 ADD_FAILURE() << "Should not have reached this line."; 928 } 929 catch (const std::invalid_argument& e) 930 { 931 EXPECT_STREQ(e.what(), "Element is not an object"); 932 } 933 934 // Test where fails: number value is < 1 935 try 936 { 937 const json element = R"( 938 { 939 "number": 0 940 } 941 )"_json; 942 parseChassis(element); 943 ADD_FAILURE() << "Should not have reached this line."; 944 } 945 catch (const std::invalid_argument& e) 946 { 947 EXPECT_STREQ(e.what(), "Invalid chassis number: Must be > 0"); 948 } 949 950 // Test where fails: devices value is invalid 951 try 952 { 953 const json element = R"( 954 { 955 "number": 1, 956 "devices": 2 957 } 958 )"_json; 959 parseChassis(element); 960 ADD_FAILURE() << "Should not have reached this line."; 961 } 962 catch (const std::invalid_argument& e) 963 { 964 EXPECT_STREQ(e.what(), "Element is not an array"); 965 } 966 } 967 968 TEST(ConfigFileParserTests, ParseChassisArray) 969 { 970 // Test where works 971 { 972 const json element = R"( 973 [ 974 { "number": 1 }, 975 { "number": 2 } 976 ] 977 )"_json; 978 std::vector<std::unique_ptr<Chassis>> chassis = 979 parseChassisArray(element); 980 EXPECT_EQ(chassis.size(), 2); 981 EXPECT_EQ(chassis[0]->getNumber(), 1); 982 EXPECT_EQ(chassis[1]->getNumber(), 2); 983 } 984 985 // Test where fails: Element is not an array 986 try 987 { 988 const json element = R"( 989 { 990 "foo": "bar" 991 } 992 )"_json; 993 parseChassisArray(element); 994 ADD_FAILURE() << "Should not have reached this line."; 995 } 996 catch (const std::invalid_argument& e) 997 { 998 EXPECT_STREQ(e.what(), "Element is not an array"); 999 } 1000 } 1001 1002 TEST(ConfigFileParserTests, ParseComparePresence) 1003 { 1004 // Test where works 1005 { 1006 const json element = R"( 1007 { 1008 "fru": "system/chassis/motherboard/cpu3", 1009 "value": true 1010 } 1011 )"_json; 1012 std::unique_ptr<ComparePresenceAction> action = 1013 parseComparePresence(element); 1014 EXPECT_EQ( 1015 action->getFRU(), 1016 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3"); 1017 EXPECT_EQ(action->getValue(), true); 1018 } 1019 1020 // Test where fails: Element is not an object 1021 try 1022 { 1023 const json element = R"( [ "0xFF", "0x01" ] )"_json; 1024 parseComparePresence(element); 1025 ADD_FAILURE() << "Should not have reached this line."; 1026 } 1027 catch (const std::invalid_argument& e) 1028 { 1029 EXPECT_STREQ(e.what(), "Element is not an object"); 1030 } 1031 1032 // Test where fails: Invalid property specified 1033 try 1034 { 1035 const json element = R"( 1036 { 1037 "fru": "system/chassis/motherboard/cpu3", 1038 "value": true, 1039 "foo" : true 1040 } 1041 )"_json; 1042 parseComparePresence(element); 1043 ADD_FAILURE() << "Should not have reached this line."; 1044 } 1045 catch (const std::invalid_argument& e) 1046 { 1047 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 1048 } 1049 1050 // Test where fails: Required fru property not specified 1051 try 1052 { 1053 const json element = R"( 1054 { 1055 "value": true 1056 } 1057 )"_json; 1058 parseComparePresence(element); 1059 ADD_FAILURE() << "Should not have reached this line."; 1060 } 1061 catch (const std::invalid_argument& e) 1062 { 1063 EXPECT_STREQ(e.what(), "Required property missing: fru"); 1064 } 1065 1066 // Test where fails: Required value property not specified 1067 try 1068 { 1069 const json element = R"( 1070 { 1071 "fru": "system/chassis/motherboard/cpu3" 1072 } 1073 )"_json; 1074 parseComparePresence(element); 1075 ADD_FAILURE() << "Should not have reached this line."; 1076 } 1077 catch (const std::invalid_argument& e) 1078 { 1079 EXPECT_STREQ(e.what(), "Required property missing: value"); 1080 } 1081 1082 // Test where fails: fru value is invalid 1083 try 1084 { 1085 const json element = R"( 1086 { 1087 "fru": 1, 1088 "value": true 1089 } 1090 )"_json; 1091 parseComparePresence(element); 1092 ADD_FAILURE() << "Should not have reached this line."; 1093 } 1094 catch (const std::invalid_argument& e) 1095 { 1096 EXPECT_STREQ(e.what(), "Element is not a string"); 1097 } 1098 1099 // Test where fails: value value is invalid 1100 try 1101 { 1102 const json element = R"( 1103 { 1104 "fru": "system/chassis/motherboard/cpu3", 1105 "value": 1 1106 } 1107 )"_json; 1108 parseComparePresence(element); 1109 ADD_FAILURE() << "Should not have reached this line."; 1110 } 1111 catch (const std::invalid_argument& e) 1112 { 1113 EXPECT_STREQ(e.what(), "Element is not a boolean"); 1114 } 1115 } 1116 1117 TEST(ConfigFileParserTests, ParseCompareVPD) 1118 { 1119 // Test where works, using "value" 1120 { 1121 const json element = R"( 1122 { 1123 "fru": "system/chassis/disk_backplane", 1124 "keyword": "CCIN", 1125 "value": "2D35" 1126 } 1127 )"_json; 1128 std::unique_ptr<CompareVPDAction> action = parseCompareVPD(element); 1129 EXPECT_EQ( 1130 action->getFRU(), 1131 "/xyz/openbmc_project/inventory/system/chassis/disk_backplane"); 1132 EXPECT_EQ(action->getKeyword(), "CCIN"); 1133 EXPECT_EQ(action->getValue(), 1134 (std::vector<uint8_t>{0x32, 0x44, 0x33, 0x35})); 1135 } 1136 1137 // Test where works, using "byte_values" 1138 { 1139 const json element = R"( 1140 { 1141 "fru": "system/chassis/disk_backplane", 1142 "keyword": "CCIN", 1143 "byte_values": ["0x11", "0x22", "0x33"] 1144 } 1145 )"_json; 1146 std::unique_ptr<CompareVPDAction> action = parseCompareVPD(element); 1147 EXPECT_EQ( 1148 action->getFRU(), 1149 "/xyz/openbmc_project/inventory/system/chassis/disk_backplane"); 1150 EXPECT_EQ(action->getKeyword(), "CCIN"); 1151 EXPECT_EQ(action->getValue(), (std::vector<uint8_t>{0x11, 0x22, 0x33})); 1152 } 1153 1154 // Test where fails: Element is not an object 1155 try 1156 { 1157 const json element = R"( [ "0xFF", "0x01" ] )"_json; 1158 parseCompareVPD(element); 1159 ADD_FAILURE() << "Should not have reached this line."; 1160 } 1161 catch (const std::invalid_argument& e) 1162 { 1163 EXPECT_STREQ(e.what(), "Element is not an object"); 1164 } 1165 1166 // Test where fails: Invalid property specified 1167 try 1168 { 1169 const json element = R"( 1170 { 1171 "fru": "system/chassis/disk_backplane", 1172 "keyword": "CCIN", 1173 "value": "2D35", 1174 "foo" : true 1175 } 1176 )"_json; 1177 parseCompareVPD(element); 1178 ADD_FAILURE() << "Should not have reached this line."; 1179 } 1180 catch (const std::invalid_argument& e) 1181 { 1182 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 1183 } 1184 1185 // Test where fails: Required fru property not specified 1186 try 1187 { 1188 const json element = R"( 1189 { 1190 "keyword": "CCIN", 1191 "value": "2D35" 1192 } 1193 )"_json; 1194 parseCompareVPD(element); 1195 ADD_FAILURE() << "Should not have reached this line."; 1196 } 1197 catch (const std::invalid_argument& e) 1198 { 1199 EXPECT_STREQ(e.what(), "Required property missing: fru"); 1200 } 1201 1202 // Test where fails: Required keyword property not specified 1203 try 1204 { 1205 const json element = R"( 1206 { 1207 "fru": "system/chassis/disk_backplane", 1208 "value": "2D35" 1209 } 1210 )"_json; 1211 parseCompareVPD(element); 1212 ADD_FAILURE() << "Should not have reached this line."; 1213 } 1214 catch (const std::invalid_argument& e) 1215 { 1216 EXPECT_STREQ(e.what(), "Required property missing: keyword"); 1217 } 1218 1219 // Test where fails: Required value property not specified 1220 try 1221 { 1222 const json element = R"( 1223 { 1224 "fru": "system/chassis/disk_backplane", 1225 "keyword": "CCIN" 1226 } 1227 )"_json; 1228 parseCompareVPD(element); 1229 ADD_FAILURE() << "Should not have reached this line."; 1230 } 1231 catch (const std::invalid_argument& e) 1232 { 1233 EXPECT_STREQ(e.what(), "Invalid property: Must contain " 1234 "either value or byte_values"); 1235 } 1236 1237 // Test where fails: both value and byte_value specified 1238 try 1239 { 1240 const json element = R"( 1241 { 1242 "fru": "system/chassis/disk_backplane", 1243 "keyword": "CCIN", 1244 "value": "2D35", 1245 "byte_values": [ "0x01", "0x02" ] 1246 } 1247 )"_json; 1248 parseCompareVPD(element); 1249 ADD_FAILURE() << "Should not have reached this line."; 1250 } 1251 catch (const std::invalid_argument& e) 1252 { 1253 EXPECT_STREQ(e.what(), "Invalid property: Must contain " 1254 "either value or byte_values"); 1255 } 1256 1257 // Test where fails: fru value is invalid 1258 try 1259 { 1260 const json element = R"( 1261 { 1262 "fru": 1, 1263 "keyword": "CCIN", 1264 "value": "2D35" 1265 } 1266 )"_json; 1267 parseCompareVPD(element); 1268 ADD_FAILURE() << "Should not have reached this line."; 1269 } 1270 catch (const std::invalid_argument& e) 1271 { 1272 EXPECT_STREQ(e.what(), "Element is not a string"); 1273 } 1274 1275 // Test where fails: keyword value is invalid 1276 try 1277 { 1278 const json element = R"( 1279 { 1280 "fru": "system/chassis/disk_backplane", 1281 "keyword": 1, 1282 "value": "2D35" 1283 } 1284 )"_json; 1285 parseCompareVPD(element); 1286 ADD_FAILURE() << "Should not have reached this line."; 1287 } 1288 catch (const std::invalid_argument& e) 1289 { 1290 EXPECT_STREQ(e.what(), "Element is not a string"); 1291 } 1292 1293 // Test where fails: value value is invalid 1294 try 1295 { 1296 const json element = R"( 1297 { 1298 "fru": "system/chassis/disk_backplane", 1299 "keyword": "CCIN", 1300 "value": 1 1301 } 1302 )"_json; 1303 parseCompareVPD(element); 1304 ADD_FAILURE() << "Should not have reached this line."; 1305 } 1306 catch (const std::invalid_argument& e) 1307 { 1308 EXPECT_STREQ(e.what(), "Element is not a string"); 1309 } 1310 1311 // Test where fails: byte_values is wrong format 1312 try 1313 { 1314 const json element = R"( 1315 { 1316 "fru": "system/chassis/disk_backplane", 1317 "keyword": "CCIN", 1318 "byte_values": [1, 2, 3] 1319 } 1320 )"_json; 1321 parseCompareVPD(element); 1322 ADD_FAILURE() << "Should not have reached this line."; 1323 } 1324 catch (const std::invalid_argument& e) 1325 { 1326 EXPECT_STREQ(e.what(), "Element is not a string"); 1327 } 1328 } 1329 1330 TEST(ConfigFileParserTests, ParseConfiguration) 1331 { 1332 // Test where works: actions required property specified 1333 { 1334 const json element = R"( 1335 { 1336 "actions": [ 1337 { 1338 "pmbus_write_vout_command": { 1339 "format": "linear" 1340 } 1341 } 1342 ] 1343 } 1344 )"_json; 1345 std::unique_ptr<Configuration> configuration = 1346 parseConfiguration(element); 1347 EXPECT_EQ(configuration->getActions().size(), 1); 1348 EXPECT_EQ(configuration->getVolts().has_value(), false); 1349 } 1350 1351 // Test where works: volts and actions properties specified 1352 { 1353 const json element = R"( 1354 { 1355 "comments": [ "comments property" ], 1356 "volts": 1.03, 1357 "actions": [ 1358 { "pmbus_write_vout_command": { "format": "linear" } }, 1359 { "run_rule": "set_voltage_rule" } 1360 ] 1361 } 1362 )"_json; 1363 std::unique_ptr<Configuration> configuration = 1364 parseConfiguration(element); 1365 EXPECT_EQ(configuration->getVolts().has_value(), true); 1366 EXPECT_EQ(configuration->getVolts().value(), 1.03); 1367 EXPECT_EQ(configuration->getActions().size(), 2); 1368 } 1369 1370 // Test where works: volts and rule_id properties specified 1371 { 1372 const json element = R"( 1373 { 1374 "volts": 1.05, 1375 "rule_id": "set_voltage_rule" 1376 } 1377 )"_json; 1378 std::unique_ptr<Configuration> configuration = 1379 parseConfiguration(element); 1380 EXPECT_EQ(configuration->getVolts().has_value(), true); 1381 EXPECT_EQ(configuration->getVolts().value(), 1.05); 1382 EXPECT_EQ(configuration->getActions().size(), 1); 1383 } 1384 1385 // Test where fails: volts value is invalid 1386 try 1387 { 1388 const json element = R"( 1389 { 1390 "volts": "foo", 1391 "actions": [ 1392 { 1393 "pmbus_write_vout_command": { 1394 "format": "linear" 1395 } 1396 } 1397 ] 1398 } 1399 )"_json; 1400 parseConfiguration(element); 1401 ADD_FAILURE() << "Should not have reached this line."; 1402 } 1403 catch (const std::invalid_argument& e) 1404 { 1405 EXPECT_STREQ(e.what(), "Element is not a number"); 1406 } 1407 1408 // Test where fails: actions object is invalid 1409 try 1410 { 1411 const json element = R"( 1412 { 1413 "volts": 1.03, 1414 "actions": 1 1415 } 1416 )"_json; 1417 parseConfiguration(element); 1418 ADD_FAILURE() << "Should not have reached this line."; 1419 } 1420 catch (const std::invalid_argument& e) 1421 { 1422 EXPECT_STREQ(e.what(), "Element is not an array"); 1423 } 1424 1425 // Test where fails: rule_id value is invalid 1426 try 1427 { 1428 const json element = R"( 1429 { 1430 "volts": 1.05, 1431 "rule_id": 1 1432 } 1433 )"_json; 1434 parseConfiguration(element); 1435 ADD_FAILURE() << "Should not have reached this line."; 1436 } 1437 catch (const std::invalid_argument& e) 1438 { 1439 EXPECT_STREQ(e.what(), "Element is not a string"); 1440 } 1441 1442 // Test where fails: Required actions or rule_id property not specified 1443 try 1444 { 1445 const json element = R"( 1446 { 1447 "volts": 1.03 1448 } 1449 )"_json; 1450 parseConfiguration(element); 1451 ADD_FAILURE() << "Should not have reached this line."; 1452 } 1453 catch (const std::invalid_argument& e) 1454 { 1455 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 1456 "either rule_id or actions"); 1457 } 1458 1459 // Test where fails: Required actions or rule_id property both specified 1460 try 1461 { 1462 const json element = R"( 1463 { 1464 "volts": 1.03, 1465 "rule_id": "set_voltage_rule", 1466 "actions": [ 1467 { 1468 "pmbus_write_vout_command": { 1469 "format": "linear" 1470 } 1471 } 1472 ] 1473 } 1474 )"_json; 1475 parseConfiguration(element); 1476 ADD_FAILURE() << "Should not have reached this line."; 1477 } 1478 catch (const std::invalid_argument& e) 1479 { 1480 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 1481 "either rule_id or actions"); 1482 } 1483 1484 // Test where fails: Element is not an object 1485 try 1486 { 1487 const json element = R"( [ "0xFF", "0x01" ] )"_json; 1488 parseConfiguration(element); 1489 ADD_FAILURE() << "Should not have reached this line."; 1490 } 1491 catch (const std::invalid_argument& e) 1492 { 1493 EXPECT_STREQ(e.what(), "Element is not an object"); 1494 } 1495 1496 // Test where fails: Invalid property specified 1497 try 1498 { 1499 const json element = R"( 1500 { 1501 "volts": 1.03, 1502 "rule_id": "set_voltage_rule", 1503 "foo": 1 1504 } 1505 )"_json; 1506 parseConfiguration(element); 1507 ADD_FAILURE() << "Should not have reached this line."; 1508 } 1509 catch (const std::invalid_argument& e) 1510 { 1511 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 1512 } 1513 } 1514 1515 TEST(ConfigFileParserTests, ParseDevice) 1516 { 1517 // Test where works: Only required properties specified 1518 { 1519 const json element = R"( 1520 { 1521 "id": "vdd_regulator", 1522 "is_regulator": true, 1523 "fru": "system/chassis/motherboard/regulator2", 1524 "i2c_interface": { "bus": 1, "address": "0x70" } 1525 } 1526 )"_json; 1527 std::unique_ptr<Device> device = parseDevice(element); 1528 EXPECT_EQ(device->getID(), "vdd_regulator"); 1529 EXPECT_EQ(device->isRegulator(), true); 1530 EXPECT_EQ(device->getFRU(), "/xyz/openbmc_project/inventory/system/" 1531 "chassis/motherboard/regulator2"); 1532 EXPECT_NE(&(device->getI2CInterface()), nullptr); 1533 EXPECT_EQ(device->getPresenceDetection(), nullptr); 1534 EXPECT_EQ(device->getConfiguration(), nullptr); 1535 EXPECT_EQ(device->getPhaseFaultDetection(), nullptr); 1536 EXPECT_EQ(device->getRails().size(), 0); 1537 } 1538 1539 // Test where works: All properties specified 1540 { 1541 const json element = R"( 1542 { 1543 "comments": [ "VDD Regulator" ], 1544 "id": "vdd_regulator", 1545 "is_regulator": true, 1546 "fru": "system/chassis/motherboard/regulator2", 1547 "i2c_interface": 1548 { 1549 "bus": 1, 1550 "address": "0x70" 1551 }, 1552 "presence_detection": 1553 { 1554 "rule_id": "is_foobar_backplane_installed_rule" 1555 }, 1556 "configuration": 1557 { 1558 "rule_id": "configure_ir35221_rule" 1559 }, 1560 "phase_fault_detection": 1561 { 1562 "rule_id": "detect_phase_fault_rule" 1563 }, 1564 "rails": 1565 [ 1566 { 1567 "id": "vdd" 1568 } 1569 ] 1570 } 1571 )"_json; 1572 std::unique_ptr<Device> device = parseDevice(element); 1573 EXPECT_EQ(device->getID(), "vdd_regulator"); 1574 EXPECT_EQ(device->isRegulator(), true); 1575 EXPECT_EQ(device->getFRU(), "/xyz/openbmc_project/inventory/system/" 1576 "chassis/motherboard/regulator2"); 1577 EXPECT_NE(&(device->getI2CInterface()), nullptr); 1578 EXPECT_NE(device->getPresenceDetection(), nullptr); 1579 EXPECT_NE(device->getConfiguration(), nullptr); 1580 EXPECT_NE(device->getPhaseFaultDetection(), nullptr); 1581 EXPECT_EQ(device->getRails().size(), 1); 1582 } 1583 1584 // Test where fails: phase_fault_detection property exists and is_regulator 1585 // is false 1586 try 1587 { 1588 const json element = R"( 1589 { 1590 "id": "vdd_regulator", 1591 "is_regulator": false, 1592 "fru": "system/chassis/motherboard/regulator2", 1593 "i2c_interface": 1594 { 1595 "bus": 1, 1596 "address": "0x70" 1597 }, 1598 "phase_fault_detection": 1599 { 1600 "rule_id": "detect_phase_fault_rule" 1601 } 1602 } 1603 )"_json; 1604 parseDevice(element); 1605 ADD_FAILURE() << "Should not have reached this line."; 1606 } 1607 catch (const std::invalid_argument& e) 1608 { 1609 EXPECT_STREQ(e.what(), "Invalid phase_fault_detection property when " 1610 "is_regulator is false"); 1611 } 1612 1613 // Test where fails: rails property exists and is_regulator is false 1614 try 1615 { 1616 const json element = R"( 1617 { 1618 "id": "vdd_regulator", 1619 "is_regulator": false, 1620 "fru": "system/chassis/motherboard/regulator2", 1621 "i2c_interface": 1622 { 1623 "bus": 1, 1624 "address": "0x70" 1625 }, 1626 "configuration": 1627 { 1628 "rule_id": "configure_ir35221_rule" 1629 }, 1630 "rails": 1631 [ 1632 { 1633 "id": "vdd" 1634 } 1635 ] 1636 } 1637 )"_json; 1638 parseDevice(element); 1639 ADD_FAILURE() << "Should not have reached this line."; 1640 } 1641 catch (const std::invalid_argument& e) 1642 { 1643 EXPECT_STREQ(e.what(), 1644 "Invalid rails property when is_regulator is false"); 1645 } 1646 1647 // Test where fails: id value is invalid 1648 try 1649 { 1650 const json element = R"( 1651 { 1652 "id": 3, 1653 "is_regulator": true, 1654 "fru": "system/chassis/motherboard/regulator2", 1655 "i2c_interface": 1656 { 1657 "bus": 1, 1658 "address": "0x70" 1659 } 1660 } 1661 )"_json; 1662 parseDevice(element); 1663 ADD_FAILURE() << "Should not have reached this line."; 1664 } 1665 catch (const std::invalid_argument& e) 1666 { 1667 EXPECT_STREQ(e.what(), "Element is not a string"); 1668 } 1669 1670 // Test where fails: is_regulator value is invalid 1671 try 1672 { 1673 const json element = R"( 1674 { 1675 "id": "vdd_regulator", 1676 "is_regulator": 3, 1677 "fru": "system/chassis/motherboard/regulator2", 1678 "i2c_interface": 1679 { 1680 "bus": 1, 1681 "address": "0x70" 1682 } 1683 } 1684 )"_json; 1685 parseDevice(element); 1686 ADD_FAILURE() << "Should not have reached this line."; 1687 } 1688 catch (const std::invalid_argument& e) 1689 { 1690 EXPECT_STREQ(e.what(), "Element is not a boolean"); 1691 } 1692 1693 // Test where fails: fru value is invalid 1694 try 1695 { 1696 const json element = R"( 1697 { 1698 "id": "vdd_regulator", 1699 "is_regulator": true, 1700 "fru": 2, 1701 "i2c_interface": 1702 { 1703 "bus": 1, 1704 "address": "0x70" 1705 } 1706 } 1707 )"_json; 1708 parseDevice(element); 1709 ADD_FAILURE() << "Should not have reached this line."; 1710 } 1711 catch (const std::invalid_argument& e) 1712 { 1713 EXPECT_STREQ(e.what(), "Element is not a string"); 1714 } 1715 1716 // Test where fails: i2c_interface value is invalid 1717 try 1718 { 1719 const json element = R"( 1720 { 1721 "id": "vdd_regulator", 1722 "is_regulator": true, 1723 "fru": "system/chassis/motherboard/regulator2", 1724 "i2c_interface": 3 1725 } 1726 )"_json; 1727 parseDevice(element); 1728 ADD_FAILURE() << "Should not have reached this line."; 1729 } 1730 catch (const std::invalid_argument& e) 1731 { 1732 EXPECT_STREQ(e.what(), "Element is not an object"); 1733 } 1734 1735 // Test where fails: Required id property not specified 1736 try 1737 { 1738 const json element = R"( 1739 { 1740 "is_regulator": true, 1741 "fru": "system/chassis/motherboard/regulator2", 1742 "i2c_interface": 1743 { 1744 "bus": 1, 1745 "address": "0x70" 1746 } 1747 } 1748 )"_json; 1749 parseDevice(element); 1750 ADD_FAILURE() << "Should not have reached this line."; 1751 } 1752 catch (const std::invalid_argument& e) 1753 { 1754 EXPECT_STREQ(e.what(), "Required property missing: id"); 1755 } 1756 1757 // Test where fails: Required is_regulator property not specified 1758 try 1759 { 1760 const json element = R"( 1761 { 1762 "id": "vdd_regulator", 1763 "fru": "system/chassis/motherboard/regulator2", 1764 "i2c_interface": 1765 { 1766 "bus": 1, 1767 "address": "0x70" 1768 } 1769 } 1770 )"_json; 1771 parseDevice(element); 1772 ADD_FAILURE() << "Should not have reached this line."; 1773 } 1774 catch (const std::invalid_argument& e) 1775 { 1776 EXPECT_STREQ(e.what(), "Required property missing: is_regulator"); 1777 } 1778 1779 // Test where fails: Required fru property not specified 1780 try 1781 { 1782 const json element = R"( 1783 { 1784 "id": "vdd_regulator", 1785 "is_regulator": true, 1786 "i2c_interface": 1787 { 1788 "bus": 1, 1789 "address": "0x70" 1790 } 1791 } 1792 )"_json; 1793 parseDevice(element); 1794 ADD_FAILURE() << "Should not have reached this line."; 1795 } 1796 catch (const std::invalid_argument& e) 1797 { 1798 EXPECT_STREQ(e.what(), "Required property missing: fru"); 1799 } 1800 1801 // Test where fails: Required i2c_interface property not specified 1802 try 1803 { 1804 const json element = R"( 1805 { 1806 "id": "vdd_regulator", 1807 "is_regulator": true, 1808 "fru": "system/chassis/motherboard/regulator2" 1809 } 1810 )"_json; 1811 parseDevice(element); 1812 ADD_FAILURE() << "Should not have reached this line."; 1813 } 1814 catch (const std::invalid_argument& e) 1815 { 1816 EXPECT_STREQ(e.what(), "Required property missing: i2c_interface"); 1817 } 1818 1819 // Test where fails: Element is not an object 1820 try 1821 { 1822 const json element = R"( [ "0xFF", "0x01" ] )"_json; 1823 parseDevice(element); 1824 ADD_FAILURE() << "Should not have reached this line."; 1825 } 1826 catch (const std::invalid_argument& e) 1827 { 1828 EXPECT_STREQ(e.what(), "Element is not an object"); 1829 } 1830 1831 // Test where fails: Invalid property specified 1832 try 1833 { 1834 const json element = R"( 1835 { 1836 "id": "vdd_regulator", 1837 "is_regulator": true, 1838 "fru": "system/chassis/motherboard/regulator2", 1839 "i2c_interface": { "bus": 1, "address": "0x70" }, 1840 "foo" : true 1841 } 1842 )"_json; 1843 parseDevice(element); 1844 ADD_FAILURE() << "Should not have reached this line."; 1845 } 1846 catch (const std::invalid_argument& e) 1847 { 1848 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 1849 } 1850 } 1851 1852 TEST(ConfigFileParserTests, ParseDeviceArray) 1853 { 1854 // Test where works 1855 { 1856 const json element = R"( 1857 [ 1858 { 1859 "id": "vdd_regulator", 1860 "is_regulator": true, 1861 "fru": "system/chassis/motherboard/regulator2", 1862 "i2c_interface": { "bus": 1, "address": "0x70" } 1863 }, 1864 { 1865 "id": "vio_regulator", 1866 "is_regulator": true, 1867 "fru": "system/chassis/motherboard/regulator2", 1868 "i2c_interface": { "bus": 1, "address": "0x71" } 1869 } 1870 ] 1871 )"_json; 1872 std::vector<std::unique_ptr<Device>> devices = 1873 parseDeviceArray(element); 1874 EXPECT_EQ(devices.size(), 2); 1875 EXPECT_EQ(devices[0]->getID(), "vdd_regulator"); 1876 EXPECT_EQ(devices[1]->getID(), "vio_regulator"); 1877 } 1878 1879 // Test where fails: Element is not an array 1880 try 1881 { 1882 const json element = R"( 1883 { 1884 "foo": "bar" 1885 } 1886 )"_json; 1887 parseDeviceArray(element); 1888 ADD_FAILURE() << "Should not have reached this line."; 1889 } 1890 catch (const std::invalid_argument& e) 1891 { 1892 EXPECT_STREQ(e.what(), "Element is not an array"); 1893 } 1894 } 1895 1896 TEST(ConfigFileParserTests, ParseDouble) 1897 { 1898 // Test where works: floating point value 1899 { 1900 const json element = R"( 1.03 )"_json; 1901 double value = parseDouble(element); 1902 EXPECT_EQ(value, 1.03); 1903 } 1904 1905 // Test where works: integer value 1906 { 1907 const json element = R"( 24 )"_json; 1908 double value = parseDouble(element); 1909 EXPECT_EQ(value, 24.0); 1910 } 1911 1912 // Test where fails: Element is not a number 1913 try 1914 { 1915 const json element = R"( true )"_json; 1916 parseDouble(element); 1917 ADD_FAILURE() << "Should not have reached this line."; 1918 } 1919 catch (const std::invalid_argument& e) 1920 { 1921 EXPECT_STREQ(e.what(), "Element is not a number"); 1922 } 1923 } 1924 1925 TEST(ConfigFileParserTests, ParseHexByte) 1926 { 1927 // Test where works: "0xFF" 1928 { 1929 const json element = R"( "0xFF" )"_json; 1930 uint8_t value = parseHexByte(element); 1931 EXPECT_EQ(value, 0xFF); 1932 } 1933 1934 // Test where works: "0xff" 1935 { 1936 const json element = R"( "0xff" )"_json; 1937 uint8_t value = parseHexByte(element); 1938 EXPECT_EQ(value, 0xff); 1939 } 1940 1941 // Test where works: "0xf" 1942 { 1943 const json element = R"( "0xf" )"_json; 1944 uint8_t value = parseHexByte(element); 1945 EXPECT_EQ(value, 0xf); 1946 } 1947 1948 // Test where fails: "0xfff" 1949 try 1950 { 1951 const json element = R"( "0xfff" )"_json; 1952 parseHexByte(element); 1953 ADD_FAILURE() << "Should not have reached this line."; 1954 } 1955 catch (const std::invalid_argument& e) 1956 { 1957 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 1958 } 1959 1960 // Test where fails: "0xAG" 1961 try 1962 { 1963 const json element = R"( "0xAG" )"_json; 1964 parseHexByte(element); 1965 ADD_FAILURE() << "Should not have reached this line."; 1966 } 1967 catch (const std::invalid_argument& e) 1968 { 1969 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 1970 } 1971 1972 // Test where fails: "ff" 1973 try 1974 { 1975 const json element = R"( "ff" )"_json; 1976 parseHexByte(element); 1977 ADD_FAILURE() << "Should not have reached this line."; 1978 } 1979 catch (const std::invalid_argument& e) 1980 { 1981 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 1982 } 1983 1984 // Test where fails: "" 1985 try 1986 { 1987 const json element = ""; 1988 parseHexByte(element); 1989 ADD_FAILURE() << "Should not have reached this line."; 1990 } 1991 catch (const std::invalid_argument& e) 1992 { 1993 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 1994 } 1995 1996 // Test where fails: "f" 1997 try 1998 { 1999 const json element = R"( "f" )"_json; 2000 parseHexByte(element); 2001 ADD_FAILURE() << "Should not have reached this line."; 2002 } 2003 catch (const std::invalid_argument& e) 2004 { 2005 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2006 } 2007 2008 // Test where fails: "0x" 2009 try 2010 { 2011 const json element = R"( "0x" )"_json; 2012 parseHexByte(element); 2013 ADD_FAILURE() << "Should not have reached this line."; 2014 } 2015 catch (const std::invalid_argument& e) 2016 { 2017 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2018 } 2019 2020 // Test where fails: "0Xff" 2021 try 2022 { 2023 const json element = R"( "0XFF" )"_json; 2024 parseHexByte(element); 2025 ADD_FAILURE() << "Should not have reached this line."; 2026 } 2027 catch (const std::invalid_argument& e) 2028 { 2029 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2030 } 2031 } 2032 2033 TEST(ConfigFileParserTests, ParseHexByteArray) 2034 { 2035 // Test where works 2036 { 2037 const json element = R"( [ "0xCC", "0xFF" ] )"_json; 2038 std::vector<uint8_t> hexBytes = parseHexByteArray(element); 2039 std::vector<uint8_t> expected = {0xcc, 0xff}; 2040 EXPECT_EQ(hexBytes, expected); 2041 } 2042 2043 // Test where fails: Element is not an array 2044 try 2045 { 2046 const json element = 0; 2047 parseHexByteArray(element); 2048 ADD_FAILURE() << "Should not have reached this line."; 2049 } 2050 catch (const std::invalid_argument& e) 2051 { 2052 EXPECT_STREQ(e.what(), "Element is not an array"); 2053 } 2054 } 2055 2056 TEST(ConfigFileParserTests, ParseI2CCaptureBytes) 2057 { 2058 // Test where works 2059 { 2060 const json element = R"( 2061 { 2062 "register": "0xA0", 2063 "count": 2 2064 } 2065 )"_json; 2066 std::unique_ptr<I2CCaptureBytesAction> action = 2067 parseI2CCaptureBytes(element); 2068 EXPECT_EQ(action->getRegister(), 0xA0); 2069 EXPECT_EQ(action->getCount(), 2); 2070 } 2071 2072 // Test where fails: Element is not an object 2073 try 2074 { 2075 const json element = R"( [ "0xFF", "0x01" ] )"_json; 2076 parseI2CCaptureBytes(element); 2077 ADD_FAILURE() << "Should not have reached this line."; 2078 } 2079 catch (const std::invalid_argument& e) 2080 { 2081 EXPECT_STREQ(e.what(), "Element is not an object"); 2082 } 2083 2084 // Test where fails: register value is invalid 2085 try 2086 { 2087 const json element = R"( 2088 { 2089 "register": "0x0Z", 2090 "count": 2 2091 } 2092 )"_json; 2093 parseI2CCaptureBytes(element); 2094 ADD_FAILURE() << "Should not have reached this line."; 2095 } 2096 catch (const std::invalid_argument& e) 2097 { 2098 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2099 } 2100 2101 // Test where fails: count value is invalid 2102 try 2103 { 2104 const json element = R"( 2105 { 2106 "register": "0xA0", 2107 "count": 0 2108 } 2109 )"_json; 2110 parseI2CCaptureBytes(element); 2111 ADD_FAILURE() << "Should not have reached this line."; 2112 } 2113 catch (const std::invalid_argument& e) 2114 { 2115 EXPECT_STREQ(e.what(), "Invalid byte count: Must be > 0"); 2116 } 2117 2118 // Test where fails: Required register property not specified 2119 try 2120 { 2121 const json element = R"( 2122 { 2123 "count": 2 2124 } 2125 )"_json; 2126 parseI2CCaptureBytes(element); 2127 ADD_FAILURE() << "Should not have reached this line."; 2128 } 2129 catch (const std::invalid_argument& e) 2130 { 2131 EXPECT_STREQ(e.what(), "Required property missing: register"); 2132 } 2133 2134 // Test where fails: Required count property not specified 2135 try 2136 { 2137 const json element = R"( 2138 { 2139 "register": "0xA0" 2140 } 2141 )"_json; 2142 parseI2CCaptureBytes(element); 2143 ADD_FAILURE() << "Should not have reached this line."; 2144 } 2145 catch (const std::invalid_argument& e) 2146 { 2147 EXPECT_STREQ(e.what(), "Required property missing: count"); 2148 } 2149 2150 // Test where fails: Invalid property specified 2151 try 2152 { 2153 const json element = R"( 2154 { 2155 "register": "0xA0", 2156 "count": 2, 2157 "foo": 3 2158 } 2159 )"_json; 2160 parseI2CCaptureBytes(element); 2161 ADD_FAILURE() << "Should not have reached this line."; 2162 } 2163 catch (const std::invalid_argument& e) 2164 { 2165 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 2166 } 2167 } 2168 2169 TEST(ConfigFileParserTests, ParseI2CCompareBit) 2170 { 2171 // Test where works 2172 { 2173 const json element = R"( 2174 { 2175 "register": "0xA0", 2176 "position": 3, 2177 "value": 0 2178 } 2179 )"_json; 2180 std::unique_ptr<I2CCompareBitAction> action = 2181 parseI2CCompareBit(element); 2182 EXPECT_EQ(action->getRegister(), 0xA0); 2183 EXPECT_EQ(action->getPosition(), 3); 2184 EXPECT_EQ(action->getValue(), 0); 2185 } 2186 2187 // Test where fails: Invalid property specified 2188 try 2189 { 2190 const json element = R"( 2191 { 2192 "register": "0xA0", 2193 "position": 3, 2194 "value": 0, 2195 "foo": 3 2196 } 2197 )"_json; 2198 parseI2CCompareBit(element); 2199 ADD_FAILURE() << "Should not have reached this line."; 2200 } 2201 catch (const std::invalid_argument& e) 2202 { 2203 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 2204 } 2205 2206 // Test where fails: Element is not an object 2207 try 2208 { 2209 const json element = R"( [ "0xFF", "0x01" ] )"_json; 2210 parseI2CCompareBit(element); 2211 ADD_FAILURE() << "Should not have reached this line."; 2212 } 2213 catch (const std::invalid_argument& e) 2214 { 2215 EXPECT_STREQ(e.what(), "Element is not an object"); 2216 } 2217 2218 // Test where fails: register value is invalid 2219 try 2220 { 2221 const json element = R"( 2222 { 2223 "register": "0xAG", 2224 "position": 3, 2225 "value": 0 2226 } 2227 )"_json; 2228 parseI2CCompareBit(element); 2229 ADD_FAILURE() << "Should not have reached this line."; 2230 } 2231 catch (const std::invalid_argument& e) 2232 { 2233 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2234 } 2235 2236 // Test where fails: position value is invalid 2237 try 2238 { 2239 const json element = R"( 2240 { 2241 "register": "0xA0", 2242 "position": 8, 2243 "value": 0 2244 } 2245 )"_json; 2246 parseI2CCompareBit(element); 2247 ADD_FAILURE() << "Should not have reached this line."; 2248 } 2249 catch (const std::invalid_argument& e) 2250 { 2251 EXPECT_STREQ(e.what(), "Element is not a bit position"); 2252 } 2253 2254 // Test where fails: value value is invalid 2255 try 2256 { 2257 const json element = R"( 2258 { 2259 "register": "0xA0", 2260 "position": 3, 2261 "value": 2 2262 } 2263 )"_json; 2264 parseI2CCompareBit(element); 2265 ADD_FAILURE() << "Should not have reached this line."; 2266 } 2267 catch (const std::invalid_argument& e) 2268 { 2269 EXPECT_STREQ(e.what(), "Element is not a bit value"); 2270 } 2271 2272 // Test where fails: Required register property not specified 2273 try 2274 { 2275 const json element = R"( 2276 { 2277 "position": 3, 2278 "value": 0 2279 } 2280 )"_json; 2281 parseI2CCompareBit(element); 2282 ADD_FAILURE() << "Should not have reached this line."; 2283 } 2284 catch (const std::invalid_argument& e) 2285 { 2286 EXPECT_STREQ(e.what(), "Required property missing: register"); 2287 } 2288 2289 // Test where fails: Required position property not specified 2290 try 2291 { 2292 const json element = R"( 2293 { 2294 "register": "0xA0", 2295 "value": 0 2296 } 2297 )"_json; 2298 parseI2CCompareBit(element); 2299 ADD_FAILURE() << "Should not have reached this line."; 2300 } 2301 catch (const std::invalid_argument& e) 2302 { 2303 EXPECT_STREQ(e.what(), "Required property missing: position"); 2304 } 2305 2306 // Test where fails: Required value property not specified 2307 try 2308 { 2309 const json element = R"( 2310 { 2311 "register": "0xA0", 2312 "position": 3 2313 } 2314 )"_json; 2315 parseI2CCompareBit(element); 2316 ADD_FAILURE() << "Should not have reached this line."; 2317 } 2318 catch (const std::invalid_argument& e) 2319 { 2320 EXPECT_STREQ(e.what(), "Required property missing: value"); 2321 } 2322 } 2323 2324 TEST(ConfigFileParserTests, ParseI2CCompareByte) 2325 { 2326 // Test where works: Only required properties specified 2327 { 2328 const json element = R"( 2329 { 2330 "register": "0x0A", 2331 "value": "0xCC" 2332 } 2333 )"_json; 2334 std::unique_ptr<I2CCompareByteAction> action = 2335 parseI2CCompareByte(element); 2336 EXPECT_EQ(action->getRegister(), 0x0A); 2337 EXPECT_EQ(action->getValue(), 0xCC); 2338 EXPECT_EQ(action->getMask(), 0xFF); 2339 } 2340 2341 // Test where works: All properties specified 2342 { 2343 const json element = R"( 2344 { 2345 "register": "0x0A", 2346 "value": "0xCC", 2347 "mask": "0xF7" 2348 } 2349 )"_json; 2350 std::unique_ptr<I2CCompareByteAction> action = 2351 parseI2CCompareByte(element); 2352 EXPECT_EQ(action->getRegister(), 0x0A); 2353 EXPECT_EQ(action->getValue(), 0xCC); 2354 EXPECT_EQ(action->getMask(), 0xF7); 2355 } 2356 2357 // Test where fails: Element is not an object 2358 try 2359 { 2360 const json element = R"( [ "0xFF", "0x01" ] )"_json; 2361 parseI2CCompareByte(element); 2362 ADD_FAILURE() << "Should not have reached this line."; 2363 } 2364 catch (const std::invalid_argument& e) 2365 { 2366 EXPECT_STREQ(e.what(), "Element is not an object"); 2367 } 2368 2369 // Test where fails: Invalid property specified 2370 try 2371 { 2372 const json element = R"( 2373 { 2374 "register": "0x0A", 2375 "value": "0xCC", 2376 "mask": "0xF7", 2377 "foo": 1 2378 } 2379 )"_json; 2380 parseI2CCompareByte(element); 2381 ADD_FAILURE() << "Should not have reached this line."; 2382 } 2383 catch (const std::invalid_argument& e) 2384 { 2385 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 2386 } 2387 2388 // Test where fails: register value is invalid 2389 try 2390 { 2391 const json element = R"( 2392 { 2393 "register": "0x0Z", 2394 "value": "0xCC", 2395 "mask": "0xF7" 2396 } 2397 )"_json; 2398 parseI2CCompareByte(element); 2399 ADD_FAILURE() << "Should not have reached this line."; 2400 } 2401 catch (const std::invalid_argument& e) 2402 { 2403 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2404 } 2405 2406 // Test where fails: value value is invalid 2407 try 2408 { 2409 const json element = R"( 2410 { 2411 "register": "0x0A", 2412 "value": "0xCCC", 2413 "mask": "0xF7" 2414 } 2415 )"_json; 2416 parseI2CCompareByte(element); 2417 ADD_FAILURE() << "Should not have reached this line."; 2418 } 2419 catch (const std::invalid_argument& e) 2420 { 2421 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2422 } 2423 2424 // Test where fails: mask value is invalid 2425 try 2426 { 2427 const json element = R"( 2428 { 2429 "register": "0x0A", 2430 "value": "0xCC", 2431 "mask": "F7" 2432 } 2433 )"_json; 2434 parseI2CCompareByte(element); 2435 ADD_FAILURE() << "Should not have reached this line."; 2436 } 2437 catch (const std::invalid_argument& e) 2438 { 2439 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2440 } 2441 2442 // Test where fails: Required register property not specified 2443 try 2444 { 2445 const json element = R"( 2446 { 2447 "value": "0xCC", 2448 "mask": "0xF7" 2449 } 2450 )"_json; 2451 parseI2CCompareByte(element); 2452 ADD_FAILURE() << "Should not have reached this line."; 2453 } 2454 catch (const std::invalid_argument& e) 2455 { 2456 EXPECT_STREQ(e.what(), "Required property missing: register"); 2457 } 2458 2459 // Test where fails: Required value property not specified 2460 try 2461 { 2462 const json element = R"( 2463 { 2464 "register": "0x0A", 2465 "mask": "0xF7" 2466 } 2467 )"_json; 2468 parseI2CCompareByte(element); 2469 ADD_FAILURE() << "Should not have reached this line."; 2470 } 2471 catch (const std::invalid_argument& e) 2472 { 2473 EXPECT_STREQ(e.what(), "Required property missing: value"); 2474 } 2475 } 2476 2477 TEST(ConfigFileParserTests, ParseI2CCompareBytes) 2478 { 2479 // Test where works: Only required properties specified 2480 { 2481 const json element = R"( 2482 { 2483 "register": "0x0A", 2484 "values": [ "0xCC", "0xFF" ] 2485 } 2486 )"_json; 2487 std::unique_ptr<I2CCompareBytesAction> action = 2488 parseI2CCompareBytes(element); 2489 EXPECT_EQ(action->getRegister(), 0x0A); 2490 EXPECT_EQ(action->getValues().size(), 2); 2491 EXPECT_EQ(action->getValues()[0], 0xCC); 2492 EXPECT_EQ(action->getValues()[1], 0xFF); 2493 EXPECT_EQ(action->getMasks().size(), 2); 2494 EXPECT_EQ(action->getMasks()[0], 0xFF); 2495 EXPECT_EQ(action->getMasks()[1], 0xFF); 2496 } 2497 2498 // Test where works: All properties specified 2499 { 2500 const json element = R"( 2501 { 2502 "register": "0x0A", 2503 "values": [ "0xCC", "0xFF" ], 2504 "masks": [ "0x7F", "0x77" ] 2505 } 2506 )"_json; 2507 std::unique_ptr<I2CCompareBytesAction> action = 2508 parseI2CCompareBytes(element); 2509 EXPECT_EQ(action->getRegister(), 0x0A); 2510 EXPECT_EQ(action->getValues().size(), 2); 2511 EXPECT_EQ(action->getValues()[0], 0xCC); 2512 EXPECT_EQ(action->getValues()[1], 0xFF); 2513 EXPECT_EQ(action->getMasks().size(), 2); 2514 EXPECT_EQ(action->getMasks()[0], 0x7F); 2515 EXPECT_EQ(action->getMasks()[1], 0x77); 2516 } 2517 2518 // Test where fails: Element is not an object 2519 try 2520 { 2521 const json element = R"( [ "0xFF", "0x01" ] )"_json; 2522 parseI2CCompareBytes(element); 2523 ADD_FAILURE() << "Should not have reached this line."; 2524 } 2525 catch (const std::invalid_argument& e) 2526 { 2527 EXPECT_STREQ(e.what(), "Element is not an object"); 2528 } 2529 2530 // Test where fails: Invalid property specified 2531 try 2532 { 2533 const json element = R"( 2534 { 2535 "register": "0x0A", 2536 "values": [ "0xCC", "0xFF" ], 2537 "masks": [ "0x7F", "0x7F" ], 2538 "foo": 1 2539 } 2540 )"_json; 2541 parseI2CCompareBytes(element); 2542 ADD_FAILURE() << "Should not have reached this line."; 2543 } 2544 catch (const std::invalid_argument& e) 2545 { 2546 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 2547 } 2548 2549 // Test where fails: register value is invalid 2550 try 2551 { 2552 const json element = R"( 2553 { 2554 "register": "0x0Z", 2555 "values": [ "0xCC", "0xFF" ], 2556 "masks": [ "0x7F", "0x7F" ] 2557 } 2558 )"_json; 2559 parseI2CCompareBytes(element); 2560 ADD_FAILURE() << "Should not have reached this line."; 2561 } 2562 catch (const std::invalid_argument& e) 2563 { 2564 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2565 } 2566 2567 // Test where fails: values value is invalid 2568 try 2569 { 2570 const json element = R"( 2571 { 2572 "register": "0x0A", 2573 "values": [ "0xCCC", "0xFF" ], 2574 "masks": [ "0x7F", "0x7F" ] 2575 } 2576 )"_json; 2577 parseI2CCompareBytes(element); 2578 ADD_FAILURE() << "Should not have reached this line."; 2579 } 2580 catch (const std::invalid_argument& e) 2581 { 2582 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2583 } 2584 2585 // Test where fails: masks value is invalid 2586 try 2587 { 2588 const json element = R"( 2589 { 2590 "register": "0x0A", 2591 "values": [ "0xCC", "0xFF" ], 2592 "masks": [ "F", "0x7F" ] 2593 } 2594 )"_json; 2595 parseI2CCompareBytes(element); 2596 ADD_FAILURE() << "Should not have reached this line."; 2597 } 2598 catch (const std::invalid_argument& e) 2599 { 2600 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2601 } 2602 2603 // Test where fails: number of elements in masks is invalid 2604 try 2605 { 2606 const json element = R"( 2607 { 2608 "register": "0x0A", 2609 "values": [ "0xCC", "0xFF" ], 2610 "masks": [ "0x7F" ] 2611 } 2612 )"_json; 2613 parseI2CCompareBytes(element); 2614 ADD_FAILURE() << "Should not have reached this line."; 2615 } 2616 catch (const std::invalid_argument& e) 2617 { 2618 EXPECT_STREQ(e.what(), "Invalid number of elements in masks"); 2619 } 2620 2621 // Test where fails: Required register property not specified 2622 try 2623 { 2624 const json element = R"( 2625 { 2626 "values": [ "0xCC", "0xFF" ] 2627 } 2628 )"_json; 2629 parseI2CCompareBytes(element); 2630 ADD_FAILURE() << "Should not have reached this line."; 2631 } 2632 catch (const std::invalid_argument& e) 2633 { 2634 EXPECT_STREQ(e.what(), "Required property missing: register"); 2635 } 2636 2637 // Test where fails: Required values property not specified 2638 try 2639 { 2640 const json element = R"( 2641 { 2642 "register": "0x0A" 2643 } 2644 )"_json; 2645 parseI2CCompareBytes(element); 2646 ADD_FAILURE() << "Should not have reached this line."; 2647 } 2648 catch (const std::invalid_argument& e) 2649 { 2650 EXPECT_STREQ(e.what(), "Required property missing: values"); 2651 } 2652 } 2653 2654 TEST(ConfigFileParserTests, ParseI2CWriteBit) 2655 { 2656 // Test where works 2657 { 2658 const json element = R"( 2659 { 2660 "register": "0xA0", 2661 "position": 3, 2662 "value": 0 2663 } 2664 )"_json; 2665 std::unique_ptr<I2CWriteBitAction> action = parseI2CWriteBit(element); 2666 EXPECT_EQ(action->getRegister(), 0xA0); 2667 EXPECT_EQ(action->getPosition(), 3); 2668 EXPECT_EQ(action->getValue(), 0); 2669 } 2670 2671 // Test where fails: Invalid property specified 2672 try 2673 { 2674 const json element = R"( 2675 { 2676 "register": "0xA0", 2677 "position": 3, 2678 "value": 0, 2679 "foo": 3 2680 } 2681 )"_json; 2682 parseI2CWriteBit(element); 2683 ADD_FAILURE() << "Should not have reached this line."; 2684 } 2685 catch (const std::invalid_argument& e) 2686 { 2687 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 2688 } 2689 2690 // Test where fails: Element is not an object 2691 try 2692 { 2693 const json element = R"( [ "0xFF", "0x01" ] )"_json; 2694 parseI2CWriteBit(element); 2695 ADD_FAILURE() << "Should not have reached this line."; 2696 } 2697 catch (const std::invalid_argument& e) 2698 { 2699 EXPECT_STREQ(e.what(), "Element is not an object"); 2700 } 2701 2702 // Test where fails: register value is invalid 2703 try 2704 { 2705 const json element = R"( 2706 { 2707 "register": "0xAG", 2708 "position": 3, 2709 "value": 0 2710 } 2711 )"_json; 2712 parseI2CWriteBit(element); 2713 ADD_FAILURE() << "Should not have reached this line."; 2714 } 2715 catch (const std::invalid_argument& e) 2716 { 2717 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2718 } 2719 2720 // Test where fails: position value is invalid 2721 try 2722 { 2723 const json element = R"( 2724 { 2725 "register": "0xA0", 2726 "position": 8, 2727 "value": 0 2728 } 2729 )"_json; 2730 parseI2CWriteBit(element); 2731 ADD_FAILURE() << "Should not have reached this line."; 2732 } 2733 catch (const std::invalid_argument& e) 2734 { 2735 EXPECT_STREQ(e.what(), "Element is not a bit position"); 2736 } 2737 2738 // Test where fails: value value is invalid 2739 try 2740 { 2741 const json element = R"( 2742 { 2743 "register": "0xA0", 2744 "position": 3, 2745 "value": 2 2746 } 2747 )"_json; 2748 parseI2CWriteBit(element); 2749 ADD_FAILURE() << "Should not have reached this line."; 2750 } 2751 catch (const std::invalid_argument& e) 2752 { 2753 EXPECT_STREQ(e.what(), "Element is not a bit value"); 2754 } 2755 2756 // Test where fails: Required register property not specified 2757 try 2758 { 2759 const json element = R"( 2760 { 2761 "position": 3, 2762 "value": 0 2763 } 2764 )"_json; 2765 parseI2CWriteBit(element); 2766 ADD_FAILURE() << "Should not have reached this line."; 2767 } 2768 catch (const std::invalid_argument& e) 2769 { 2770 EXPECT_STREQ(e.what(), "Required property missing: register"); 2771 } 2772 2773 // Test where fails: Required position property not specified 2774 try 2775 { 2776 const json element = R"( 2777 { 2778 "register": "0xA0", 2779 "value": 0 2780 } 2781 )"_json; 2782 parseI2CWriteBit(element); 2783 ADD_FAILURE() << "Should not have reached this line."; 2784 } 2785 catch (const std::invalid_argument& e) 2786 { 2787 EXPECT_STREQ(e.what(), "Required property missing: position"); 2788 } 2789 2790 // Test where fails: Required value property not specified 2791 try 2792 { 2793 const json element = R"( 2794 { 2795 "register": "0xA0", 2796 "position": 3 2797 } 2798 )"_json; 2799 parseI2CWriteBit(element); 2800 ADD_FAILURE() << "Should not have reached this line."; 2801 } 2802 catch (const std::invalid_argument& e) 2803 { 2804 EXPECT_STREQ(e.what(), "Required property missing: value"); 2805 } 2806 } 2807 2808 TEST(ConfigFileParserTests, ParseI2CWriteByte) 2809 { 2810 // Test where works: Only required properties specified 2811 { 2812 const json element = R"( 2813 { 2814 "register": "0x0A", 2815 "value": "0xCC" 2816 } 2817 )"_json; 2818 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element); 2819 EXPECT_EQ(action->getRegister(), 0x0A); 2820 EXPECT_EQ(action->getValue(), 0xCC); 2821 EXPECT_EQ(action->getMask(), 0xFF); 2822 } 2823 2824 // Test where works: All properties specified 2825 { 2826 const json element = R"( 2827 { 2828 "register": "0x0A", 2829 "value": "0xCC", 2830 "mask": "0xF7" 2831 } 2832 )"_json; 2833 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element); 2834 EXPECT_EQ(action->getRegister(), 0x0A); 2835 EXPECT_EQ(action->getValue(), 0xCC); 2836 EXPECT_EQ(action->getMask(), 0xF7); 2837 } 2838 2839 // Test where fails: Element is not an object 2840 try 2841 { 2842 const json element = R"( [ "0xFF", "0x01" ] )"_json; 2843 parseI2CWriteByte(element); 2844 ADD_FAILURE() << "Should not have reached this line."; 2845 } 2846 catch (const std::invalid_argument& e) 2847 { 2848 EXPECT_STREQ(e.what(), "Element is not an object"); 2849 } 2850 2851 // Test where fails: Invalid property specified 2852 try 2853 { 2854 const json element = R"( 2855 { 2856 "register": "0x0A", 2857 "value": "0xCC", 2858 "mask": "0xF7", 2859 "foo": 1 2860 } 2861 )"_json; 2862 parseI2CWriteByte(element); 2863 ADD_FAILURE() << "Should not have reached this line."; 2864 } 2865 catch (const std::invalid_argument& e) 2866 { 2867 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 2868 } 2869 2870 // Test where fails: register value is invalid 2871 try 2872 { 2873 const json element = R"( 2874 { 2875 "register": "0x0Z", 2876 "value": "0xCC", 2877 "mask": "0xF7" 2878 } 2879 )"_json; 2880 parseI2CWriteByte(element); 2881 ADD_FAILURE() << "Should not have reached this line."; 2882 } 2883 catch (const std::invalid_argument& e) 2884 { 2885 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2886 } 2887 2888 // Test where fails: value value is invalid 2889 try 2890 { 2891 const json element = R"( 2892 { 2893 "register": "0x0A", 2894 "value": "0xCCC", 2895 "mask": "0xF7" 2896 } 2897 )"_json; 2898 parseI2CWriteByte(element); 2899 ADD_FAILURE() << "Should not have reached this line."; 2900 } 2901 catch (const std::invalid_argument& e) 2902 { 2903 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2904 } 2905 2906 // Test where fails: mask value is invalid 2907 try 2908 { 2909 const json element = R"( 2910 { 2911 "register": "0x0A", 2912 "value": "0xCC", 2913 "mask": "F7" 2914 } 2915 )"_json; 2916 parseI2CWriteByte(element); 2917 ADD_FAILURE() << "Should not have reached this line."; 2918 } 2919 catch (const std::invalid_argument& e) 2920 { 2921 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 2922 } 2923 2924 // Test where fails: Required register property not specified 2925 try 2926 { 2927 const json element = R"( 2928 { 2929 "value": "0xCC", 2930 "mask": "0xF7" 2931 } 2932 )"_json; 2933 parseI2CWriteByte(element); 2934 ADD_FAILURE() << "Should not have reached this line."; 2935 } 2936 catch (const std::invalid_argument& e) 2937 { 2938 EXPECT_STREQ(e.what(), "Required property missing: register"); 2939 } 2940 2941 // Test where fails: Required value property not specified 2942 try 2943 { 2944 const json element = R"( 2945 { 2946 "register": "0x0A", 2947 "mask": "0xF7" 2948 } 2949 )"_json; 2950 parseI2CWriteByte(element); 2951 ADD_FAILURE() << "Should not have reached this line."; 2952 } 2953 catch (const std::invalid_argument& e) 2954 { 2955 EXPECT_STREQ(e.what(), "Required property missing: value"); 2956 } 2957 } 2958 2959 TEST(ConfigFileParserTests, ParseI2CWriteBytes) 2960 { 2961 // Test where works: Only required properties specified 2962 { 2963 const json element = R"( 2964 { 2965 "register": "0x0A", 2966 "values": [ "0xCC", "0xFF" ] 2967 } 2968 )"_json; 2969 std::unique_ptr<I2CWriteBytesAction> action = 2970 parseI2CWriteBytes(element); 2971 EXPECT_EQ(action->getRegister(), 0x0A); 2972 EXPECT_EQ(action->getValues().size(), 2); 2973 EXPECT_EQ(action->getValues()[0], 0xCC); 2974 EXPECT_EQ(action->getValues()[1], 0xFF); 2975 EXPECT_EQ(action->getMasks().size(), 0); 2976 } 2977 2978 // Test where works: All properties specified 2979 { 2980 const json element = R"( 2981 { 2982 "register": "0x0A", 2983 "values": [ "0xCC", "0xFF" ], 2984 "masks": [ "0x7F", "0x77" ] 2985 } 2986 )"_json; 2987 std::unique_ptr<I2CWriteBytesAction> action = 2988 parseI2CWriteBytes(element); 2989 EXPECT_EQ(action->getRegister(), 0x0A); 2990 EXPECT_EQ(action->getValues().size(), 2); 2991 EXPECT_EQ(action->getValues()[0], 0xCC); 2992 EXPECT_EQ(action->getValues()[1], 0xFF); 2993 EXPECT_EQ(action->getMasks().size(), 2); 2994 EXPECT_EQ(action->getMasks()[0], 0x7F); 2995 EXPECT_EQ(action->getMasks()[1], 0x77); 2996 } 2997 2998 // Test where fails: Element is not an object 2999 try 3000 { 3001 const json element = R"( [ "0xFF", "0x01" ] )"_json; 3002 parseI2CWriteBytes(element); 3003 ADD_FAILURE() << "Should not have reached this line."; 3004 } 3005 catch (const std::invalid_argument& e) 3006 { 3007 EXPECT_STREQ(e.what(), "Element is not an object"); 3008 } 3009 3010 // Test where fails: Invalid property specified 3011 try 3012 { 3013 const json element = R"( 3014 { 3015 "register": "0x0A", 3016 "values": [ "0xCC", "0xFF" ], 3017 "masks": [ "0x7F", "0x7F" ], 3018 "foo": 1 3019 } 3020 )"_json; 3021 parseI2CWriteBytes(element); 3022 ADD_FAILURE() << "Should not have reached this line."; 3023 } 3024 catch (const std::invalid_argument& e) 3025 { 3026 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 3027 } 3028 3029 // Test where fails: register value is invalid 3030 try 3031 { 3032 const json element = R"( 3033 { 3034 "register": "0x0Z", 3035 "values": [ "0xCC", "0xFF" ], 3036 "masks": [ "0x7F", "0x7F" ] 3037 } 3038 )"_json; 3039 parseI2CWriteBytes(element); 3040 ADD_FAILURE() << "Should not have reached this line."; 3041 } 3042 catch (const std::invalid_argument& e) 3043 { 3044 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 3045 } 3046 3047 // Test where fails: values value is invalid 3048 try 3049 { 3050 const json element = R"( 3051 { 3052 "register": "0x0A", 3053 "values": [ "0xCCC", "0xFF" ], 3054 "masks": [ "0x7F", "0x7F" ] 3055 } 3056 )"_json; 3057 parseI2CWriteBytes(element); 3058 ADD_FAILURE() << "Should not have reached this line."; 3059 } 3060 catch (const std::invalid_argument& e) 3061 { 3062 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 3063 } 3064 3065 // Test where fails: masks value is invalid 3066 try 3067 { 3068 const json element = R"( 3069 { 3070 "register": "0x0A", 3071 "values": [ "0xCC", "0xFF" ], 3072 "masks": [ "F", "0x7F" ] 3073 } 3074 )"_json; 3075 parseI2CWriteBytes(element); 3076 ADD_FAILURE() << "Should not have reached this line."; 3077 } 3078 catch (const std::invalid_argument& e) 3079 { 3080 EXPECT_STREQ(e.what(), "Element is not hexadecimal string"); 3081 } 3082 3083 // Test where fails: number of elements in masks is invalid 3084 try 3085 { 3086 const json element = R"( 3087 { 3088 "register": "0x0A", 3089 "values": [ "0xCC", "0xFF" ], 3090 "masks": [ "0x7F" ] 3091 } 3092 )"_json; 3093 parseI2CWriteBytes(element); 3094 ADD_FAILURE() << "Should not have reached this line."; 3095 } 3096 catch (const std::invalid_argument& e) 3097 { 3098 EXPECT_STREQ(e.what(), "Invalid number of elements in masks"); 3099 } 3100 3101 // Test where fails: Required register property not specified 3102 try 3103 { 3104 const json element = R"( 3105 { 3106 "values": [ "0xCC", "0xFF" ] 3107 } 3108 )"_json; 3109 parseI2CWriteBytes(element); 3110 ADD_FAILURE() << "Should not have reached this line."; 3111 } 3112 catch (const std::invalid_argument& e) 3113 { 3114 EXPECT_STREQ(e.what(), "Required property missing: register"); 3115 } 3116 3117 // Test where fails: Required values property not specified 3118 try 3119 { 3120 const json element = R"( 3121 { 3122 "register": "0x0A" 3123 } 3124 )"_json; 3125 parseI2CWriteBytes(element); 3126 ADD_FAILURE() << "Should not have reached this line."; 3127 } 3128 catch (const std::invalid_argument& e) 3129 { 3130 EXPECT_STREQ(e.what(), "Required property missing: values"); 3131 } 3132 } 3133 3134 TEST(ConfigFileParserTests, ParseIf) 3135 { 3136 // Test where works: Only required properties specified 3137 { 3138 const json element = R"( 3139 { 3140 "condition": { "run_rule": "is_downlevel_regulator" }, 3141 "then": [ { "run_rule": "configure_downlevel_regulator" }, 3142 { "run_rule": "configure_standard_regulator" } ] 3143 } 3144 )"_json; 3145 std::unique_ptr<IfAction> action = parseIf(element); 3146 EXPECT_NE(action->getConditionAction().get(), nullptr); 3147 EXPECT_EQ(action->getThenActions().size(), 2); 3148 EXPECT_EQ(action->getElseActions().size(), 0); 3149 } 3150 3151 // Test where works: All properties specified 3152 { 3153 const json element = R"( 3154 { 3155 "condition": { "run_rule": "is_downlevel_regulator" }, 3156 "then": [ { "run_rule": "configure_downlevel_regulator" } ], 3157 "else": [ { "run_rule": "configure_standard_regulator" } ] 3158 } 3159 )"_json; 3160 std::unique_ptr<IfAction> action = parseIf(element); 3161 EXPECT_NE(action->getConditionAction().get(), nullptr); 3162 EXPECT_EQ(action->getThenActions().size(), 1); 3163 EXPECT_EQ(action->getElseActions().size(), 1); 3164 } 3165 3166 // Test where fails: Required condition property not specified 3167 try 3168 { 3169 const json element = R"( 3170 { 3171 "then": [ { "run_rule": "configure_downlevel_regulator" } ], 3172 "else": [ { "run_rule": "configure_standard_regulator" } ] 3173 } 3174 )"_json; 3175 parseIf(element); 3176 ADD_FAILURE() << "Should not have reached this line."; 3177 } 3178 catch (const std::invalid_argument& e) 3179 { 3180 EXPECT_STREQ(e.what(), "Required property missing: condition"); 3181 } 3182 3183 // Test where fails: Required then property not specified 3184 try 3185 { 3186 const json element = R"( 3187 { 3188 "condition": { "run_rule": "is_downlevel_regulator" }, 3189 "else": [ { "run_rule": "configure_standard_regulator" } ] 3190 } 3191 )"_json; 3192 parseIf(element); 3193 ADD_FAILURE() << "Should not have reached this line."; 3194 } 3195 catch (const std::invalid_argument& e) 3196 { 3197 EXPECT_STREQ(e.what(), "Required property missing: then"); 3198 } 3199 3200 // Test where fails: condition value is invalid 3201 try 3202 { 3203 const json element = R"( 3204 { 3205 "condition": 1, 3206 "then": [ { "run_rule": "configure_downlevel_regulator" } ], 3207 "else": [ { "run_rule": "configure_standard_regulator" } ] 3208 } 3209 )"_json; 3210 parseIf(element); 3211 ADD_FAILURE() << "Should not have reached this line."; 3212 } 3213 catch (const std::invalid_argument& e) 3214 { 3215 EXPECT_STREQ(e.what(), "Element is not an object"); 3216 } 3217 3218 // Test where fails: then value is invalid 3219 try 3220 { 3221 const json element = R"( 3222 { 3223 "condition": { "run_rule": "is_downlevel_regulator" }, 3224 "then": "foo", 3225 "else": [ { "run_rule": "configure_standard_regulator" } ] 3226 } 3227 )"_json; 3228 parseIf(element); 3229 ADD_FAILURE() << "Should not have reached this line."; 3230 } 3231 catch (const std::invalid_argument& e) 3232 { 3233 EXPECT_STREQ(e.what(), "Element is not an array"); 3234 } 3235 3236 // Test where fails: else value is invalid 3237 try 3238 { 3239 const json element = R"( 3240 { 3241 "condition": { "run_rule": "is_downlevel_regulator" }, 3242 "then": [ { "run_rule": "configure_downlevel_regulator" } ], 3243 "else": 1 3244 } 3245 )"_json; 3246 parseIf(element); 3247 ADD_FAILURE() << "Should not have reached this line."; 3248 } 3249 catch (const std::invalid_argument& e) 3250 { 3251 EXPECT_STREQ(e.what(), "Element is not an array"); 3252 } 3253 3254 // Test where fails: Invalid property specified 3255 try 3256 { 3257 const json element = R"( 3258 { 3259 "condition": { "run_rule": "is_downlevel_regulator" }, 3260 "then": [ { "run_rule": "configure_downlevel_regulator" } ], 3261 "foo": "bar" 3262 } 3263 )"_json; 3264 parseIf(element); 3265 ADD_FAILURE() << "Should not have reached this line."; 3266 } 3267 catch (const std::invalid_argument& e) 3268 { 3269 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 3270 } 3271 3272 // Test where fails: Element is not an object 3273 try 3274 { 3275 const json element = R"( [ "0xFF", "0x01" ] )"_json; 3276 parseIf(element); 3277 ADD_FAILURE() << "Should not have reached this line."; 3278 } 3279 catch (const std::invalid_argument& e) 3280 { 3281 EXPECT_STREQ(e.what(), "Element is not an object"); 3282 } 3283 } 3284 3285 TEST(ConfigFileParserTests, ParseInt8) 3286 { 3287 // Test where works: INT8_MIN 3288 { 3289 const json element = R"( -128 )"_json; 3290 int8_t value = parseInt8(element); 3291 EXPECT_EQ(value, -128); 3292 } 3293 3294 // Test where works: INT8_MAX 3295 { 3296 const json element = R"( 127 )"_json; 3297 int8_t value = parseInt8(element); 3298 EXPECT_EQ(value, 127); 3299 } 3300 3301 // Test where fails: Element is not an integer 3302 try 3303 { 3304 const json element = R"( 1.03 )"_json; 3305 parseInt8(element); 3306 ADD_FAILURE() << "Should not have reached this line."; 3307 } 3308 catch (const std::invalid_argument& e) 3309 { 3310 EXPECT_STREQ(e.what(), "Element is not an integer"); 3311 } 3312 3313 // Test where fails: Value < INT8_MIN 3314 try 3315 { 3316 const json element = R"( -129 )"_json; 3317 parseInt8(element); 3318 ADD_FAILURE() << "Should not have reached this line."; 3319 } 3320 catch (const std::invalid_argument& e) 3321 { 3322 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); 3323 } 3324 3325 // Test where fails: Value > INT8_MAX 3326 try 3327 { 3328 const json element = R"( 128 )"_json; 3329 parseInt8(element); 3330 ADD_FAILURE() << "Should not have reached this line."; 3331 } 3332 catch (const std::invalid_argument& e) 3333 { 3334 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer"); 3335 } 3336 } 3337 3338 TEST(ConfigFileParserTests, ParseInventoryPath) 3339 { 3340 // Test where works: Inventory path has a leading '/' 3341 { 3342 const json element = "/system/chassis/motherboard/cpu3"; 3343 std::string value = parseInventoryPath(element); 3344 EXPECT_EQ( 3345 value, 3346 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3"); 3347 } 3348 3349 // Test where works: Inventory path does not have a leading '/' 3350 { 3351 const json element = "system/chassis/motherboard/cpu1"; 3352 std::string value = parseInventoryPath(element); 3353 EXPECT_EQ( 3354 value, 3355 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1"); 3356 } 3357 3358 // Test where fails: JSON element is not a string 3359 try 3360 { 3361 const json element = R"( { "foo": "bar" } )"_json; 3362 parseInventoryPath(element); 3363 ADD_FAILURE() << "Should not have reached this line."; 3364 } 3365 catch (const std::invalid_argument& e) 3366 { 3367 EXPECT_STREQ(e.what(), "Element is not a string"); 3368 } 3369 3370 // Test where fails: JSON element contains an empty string 3371 try 3372 { 3373 const json element = ""; 3374 parseInventoryPath(element); 3375 ADD_FAILURE() << "Should not have reached this line."; 3376 } 3377 catch (const std::invalid_argument& e) 3378 { 3379 EXPECT_STREQ(e.what(), "Element contains an empty string"); 3380 } 3381 } 3382 3383 TEST(ConfigFileParserTests, ParseLogPhaseFault) 3384 { 3385 // Test where works 3386 { 3387 const json element = R"( 3388 { 3389 "type": "n+1" 3390 } 3391 )"_json; 3392 std::unique_ptr<LogPhaseFaultAction> action = 3393 parseLogPhaseFault(element); 3394 EXPECT_EQ(action->getType(), PhaseFaultType::n_plus_1); 3395 } 3396 3397 // Test where fails: Element is not an object 3398 try 3399 { 3400 const json element = R"( [ "0xFF", "0x01" ] )"_json; 3401 parseLogPhaseFault(element); 3402 ADD_FAILURE() << "Should not have reached this line."; 3403 } 3404 catch (const std::invalid_argument& e) 3405 { 3406 EXPECT_STREQ(e.what(), "Element is not an object"); 3407 } 3408 3409 // Test where fails: Required type property not specified 3410 try 3411 { 3412 const json element = R"( 3413 { 3414 } 3415 )"_json; 3416 parseLogPhaseFault(element); 3417 ADD_FAILURE() << "Should not have reached this line."; 3418 } 3419 catch (const std::invalid_argument& e) 3420 { 3421 EXPECT_STREQ(e.what(), "Required property missing: type"); 3422 } 3423 3424 // Test where fails: type value is invalid 3425 try 3426 { 3427 const json element = R"( 3428 { 3429 "type": "n+2" 3430 } 3431 )"_json; 3432 parseLogPhaseFault(element); 3433 ADD_FAILURE() << "Should not have reached this line."; 3434 } 3435 catch (const std::invalid_argument& e) 3436 { 3437 EXPECT_STREQ(e.what(), "Element is not a phase fault type"); 3438 } 3439 3440 // Test where fails: Invalid property specified 3441 try 3442 { 3443 const json element = R"( 3444 { 3445 "type": "n+1", 3446 "foo": 1 3447 } 3448 )"_json; 3449 parseLogPhaseFault(element); 3450 ADD_FAILURE() << "Should not have reached this line."; 3451 } 3452 catch (const std::invalid_argument& e) 3453 { 3454 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 3455 } 3456 } 3457 3458 TEST(ConfigFileParserTests, ParseNot) 3459 { 3460 // Test where works 3461 { 3462 const json element = R"( 3463 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } } 3464 )"_json; 3465 std::unique_ptr<NotAction> action = parseNot(element); 3466 EXPECT_NE(action->getAction().get(), nullptr); 3467 } 3468 3469 // Test where fails: Element is not an object 3470 try 3471 { 3472 const json element = R"( [ "0xFF", "0x01" ] )"_json; 3473 parseNot(element); 3474 ADD_FAILURE() << "Should not have reached this line."; 3475 } 3476 catch (const std::invalid_argument& e) 3477 { 3478 EXPECT_STREQ(e.what(), "Element is not an object"); 3479 } 3480 } 3481 3482 TEST(ConfigFileParserTests, ParseOr) 3483 { 3484 // Test where works: Element is an array with 2 actions 3485 { 3486 const json element = R"( 3487 [ 3488 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, 3489 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } 3490 ] 3491 )"_json; 3492 std::unique_ptr<OrAction> action = parseOr(element); 3493 EXPECT_EQ(action->getActions().size(), 2); 3494 } 3495 3496 // Test where fails: Element is an array with 1 action 3497 try 3498 { 3499 const json element = R"( 3500 [ 3501 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } } 3502 ] 3503 )"_json; 3504 parseOr(element); 3505 ADD_FAILURE() << "Should not have reached this line."; 3506 } 3507 catch (const std::invalid_argument& e) 3508 { 3509 EXPECT_STREQ(e.what(), "Array must contain two or more actions"); 3510 } 3511 3512 // Test where fails: Element is not an array 3513 try 3514 { 3515 const json element = R"( 3516 { 3517 "foo": "bar" 3518 } 3519 )"_json; 3520 parseOr(element); 3521 ADD_FAILURE() << "Should not have reached this line."; 3522 } 3523 catch (const std::invalid_argument& e) 3524 { 3525 EXPECT_STREQ(e.what(), "Element is not an array"); 3526 } 3527 } 3528 3529 TEST(ConfigFileParserTests, ParsePhaseFaultDetection) 3530 { 3531 // Test where works: actions specified: optional properties not specified 3532 { 3533 const json element = R"( 3534 { 3535 "actions": [ 3536 { "run_rule": "detect_phase_fault_rule" } 3537 ] 3538 } 3539 )"_json; 3540 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection = 3541 parsePhaseFaultDetection(element); 3542 EXPECT_EQ(phaseFaultDetection->getActions().size(), 1); 3543 EXPECT_EQ(phaseFaultDetection->getDeviceID(), ""); 3544 } 3545 3546 // Test where works: rule_id specified: optional properties specified 3547 { 3548 const json element = R"( 3549 { 3550 "comments": [ "Detect phase fault using I/O expander" ], 3551 "device_id": "io_expander", 3552 "rule_id": "detect_phase_fault_rule" 3553 } 3554 )"_json; 3555 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection = 3556 parsePhaseFaultDetection(element); 3557 EXPECT_EQ(phaseFaultDetection->getActions().size(), 1); 3558 EXPECT_EQ(phaseFaultDetection->getDeviceID(), "io_expander"); 3559 } 3560 3561 // Test where fails: Element is not an object 3562 try 3563 { 3564 const json element = R"( [ "foo", "bar" ] )"_json; 3565 parsePhaseFaultDetection(element); 3566 ADD_FAILURE() << "Should not have reached this line."; 3567 } 3568 catch (const std::invalid_argument& e) 3569 { 3570 EXPECT_STREQ(e.what(), "Element is not an object"); 3571 } 3572 3573 // Test where fails: device_id value is invalid 3574 try 3575 { 3576 const json element = R"( 3577 { 3578 "device_id": 1, 3579 "rule_id": "detect_phase_fault_rule" 3580 } 3581 )"_json; 3582 parsePhaseFaultDetection(element); 3583 ADD_FAILURE() << "Should not have reached this line."; 3584 } 3585 catch (const std::invalid_argument& e) 3586 { 3587 EXPECT_STREQ(e.what(), "Element is not a string"); 3588 } 3589 3590 // Test where fails: rule_id value is invalid 3591 try 3592 { 3593 const json element = R"( 3594 { 3595 "rule_id": 1 3596 } 3597 )"_json; 3598 parsePhaseFaultDetection(element); 3599 ADD_FAILURE() << "Should not have reached this line."; 3600 } 3601 catch (const std::invalid_argument& e) 3602 { 3603 EXPECT_STREQ(e.what(), "Element is not a string"); 3604 } 3605 3606 // Test where fails: actions object is invalid 3607 try 3608 { 3609 const json element = R"( 3610 { 3611 "actions": 1 3612 } 3613 )"_json; 3614 parsePhaseFaultDetection(element); 3615 ADD_FAILURE() << "Should not have reached this line."; 3616 } 3617 catch (const std::invalid_argument& e) 3618 { 3619 EXPECT_STREQ(e.what(), "Element is not an array"); 3620 } 3621 3622 // Test where fails: Required actions or rule_id property not specified 3623 try 3624 { 3625 const json element = R"( 3626 { 3627 "device_id": "io_expander" 3628 } 3629 )"_json; 3630 parsePhaseFaultDetection(element); 3631 ADD_FAILURE() << "Should not have reached this line."; 3632 } 3633 catch (const std::invalid_argument& e) 3634 { 3635 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 3636 "either rule_id or actions"); 3637 } 3638 3639 // Test where fails: Required actions or rule_id property both specified 3640 try 3641 { 3642 const json element = R"( 3643 { 3644 "rule_id": "detect_phase_fault_rule", 3645 "actions": [ 3646 { "run_rule": "detect_phase_fault_rule" } 3647 ] 3648 } 3649 )"_json; 3650 parsePhaseFaultDetection(element); 3651 ADD_FAILURE() << "Should not have reached this line."; 3652 } 3653 catch (const std::invalid_argument& e) 3654 { 3655 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 3656 "either rule_id or actions"); 3657 } 3658 3659 // Test where fails: Invalid property specified 3660 try 3661 { 3662 const json element = R"( 3663 { 3664 "foo": "bar", 3665 "actions": [ 3666 { "run_rule": "detect_phase_fault_rule" } 3667 ] 3668 } 3669 )"_json; 3670 parsePhaseFaultDetection(element); 3671 ADD_FAILURE() << "Should not have reached this line."; 3672 } 3673 catch (const std::invalid_argument& e) 3674 { 3675 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 3676 } 3677 } 3678 3679 TEST(ConfigFileParserTests, ParsePhaseFaultType) 3680 { 3681 // Test where works: n 3682 { 3683 const json element = "n"; 3684 PhaseFaultType type = parsePhaseFaultType(element); 3685 EXPECT_EQ(type, PhaseFaultType::n); 3686 } 3687 3688 // Test where works: n+1 3689 { 3690 const json element = "n+1"; 3691 PhaseFaultType type = parsePhaseFaultType(element); 3692 EXPECT_EQ(type, PhaseFaultType::n_plus_1); 3693 } 3694 3695 // Test where fails: Element is not a phase fault type 3696 try 3697 { 3698 const json element = "n+2"; 3699 parsePhaseFaultType(element); 3700 ADD_FAILURE() << "Should not have reached this line."; 3701 } 3702 catch (const std::invalid_argument& e) 3703 { 3704 EXPECT_STREQ(e.what(), "Element is not a phase fault type"); 3705 } 3706 3707 // Test where fails: Element is not a string 3708 try 3709 { 3710 const json element = R"( { "foo": "bar" } )"_json; 3711 parsePhaseFaultType(element); 3712 ADD_FAILURE() << "Should not have reached this line."; 3713 } 3714 catch (const std::invalid_argument& e) 3715 { 3716 EXPECT_STREQ(e.what(), "Element is not a string"); 3717 } 3718 } 3719 3720 TEST(ConfigFileParserTests, ParsePMBusReadSensor) 3721 { 3722 // Test where works: Only required properties specified 3723 { 3724 const json element = R"( 3725 { 3726 "type": "iout", 3727 "command": "0x8C", 3728 "format": "linear_11" 3729 } 3730 )"_json; 3731 std::unique_ptr<PMBusReadSensorAction> action = 3732 parsePMBusReadSensor(element); 3733 EXPECT_EQ(action->getType(), SensorType::iout); 3734 EXPECT_EQ(action->getCommand(), 0x8C); 3735 EXPECT_EQ(action->getFormat(), 3736 pmbus_utils::SensorDataFormat::linear_11); 3737 EXPECT_EQ(action->getExponent().has_value(), false); 3738 } 3739 3740 // Test where works: All properties specified 3741 { 3742 const json element = R"( 3743 { 3744 "type": "temperature", 3745 "command": "0x7A", 3746 "format": "linear_16", 3747 "exponent": -8 3748 } 3749 )"_json; 3750 std::unique_ptr<PMBusReadSensorAction> action = 3751 parsePMBusReadSensor(element); 3752 EXPECT_EQ(action->getType(), SensorType::temperature); 3753 EXPECT_EQ(action->getCommand(), 0x7A); 3754 EXPECT_EQ(action->getFormat(), 3755 pmbus_utils::SensorDataFormat::linear_16); 3756 EXPECT_EQ(action->getExponent().has_value(), true); 3757 EXPECT_EQ(action->getExponent().value(), -8); 3758 } 3759 3760 // Test where fails: Element is not an object 3761 try 3762 { 3763 const json element = R"( [ "0xFF", "0x01" ] )"_json; 3764 parsePMBusReadSensor(element); 3765 ADD_FAILURE() << "Should not have reached this line."; 3766 } 3767 catch (const std::invalid_argument& e) 3768 { 3769 EXPECT_STREQ(e.what(), "Element is not an object"); 3770 } 3771 3772 // Test where fails: Invalid property specified 3773 try 3774 { 3775 const json element = R"( 3776 { 3777 "type": "iout", 3778 "command": "0x8C", 3779 "format": "linear_11", 3780 "foo": 1 3781 } 3782 )"_json; 3783 parsePMBusReadSensor(element); 3784 ADD_FAILURE() << "Should not have reached this line."; 3785 } 3786 catch (const std::invalid_argument& e) 3787 { 3788 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 3789 } 3790 3791 // Test where fails: Required type property not specified 3792 try 3793 { 3794 const json element = R"( 3795 { 3796 "command": "0x8C", 3797 "format": "linear_11" 3798 } 3799 )"_json; 3800 parsePMBusReadSensor(element); 3801 ADD_FAILURE() << "Should not have reached this line."; 3802 } 3803 catch (const std::invalid_argument& e) 3804 { 3805 EXPECT_STREQ(e.what(), "Required property missing: type"); 3806 } 3807 3808 // Test where fails: Required command property not specified 3809 try 3810 { 3811 const json element = R"( 3812 { 3813 "type": "iout", 3814 "format": "linear_11" 3815 } 3816 )"_json; 3817 parsePMBusReadSensor(element); 3818 ADD_FAILURE() << "Should not have reached this line."; 3819 } 3820 catch (const std::invalid_argument& e) 3821 { 3822 EXPECT_STREQ(e.what(), "Required property missing: command"); 3823 } 3824 3825 // Test where fails: Required format property not specified 3826 try 3827 { 3828 const json element = R"( 3829 { 3830 "type": "iout", 3831 "command": "0x8C" 3832 } 3833 )"_json; 3834 parsePMBusReadSensor(element); 3835 ADD_FAILURE() << "Should not have reached this line."; 3836 } 3837 catch (const std::invalid_argument& e) 3838 { 3839 EXPECT_STREQ(e.what(), "Required property missing: format"); 3840 } 3841 3842 // Test where fails: type value is invalid 3843 try 3844 { 3845 const json element = R"( 3846 { 3847 "type": 1, 3848 "command": "0x7A", 3849 "format": "linear_16" 3850 } 3851 )"_json; 3852 parsePMBusReadSensor(element); 3853 ADD_FAILURE() << "Should not have reached this line."; 3854 } 3855 catch (const std::invalid_argument& e) 3856 { 3857 EXPECT_STREQ(e.what(), "Element is not a string"); 3858 } 3859 3860 // Test where fails: command value is invalid 3861 try 3862 { 3863 const json element = R"( 3864 { 3865 "type": "temperature", 3866 "command": 0, 3867 "format": "linear_16" 3868 } 3869 )"_json; 3870 parsePMBusReadSensor(element); 3871 ADD_FAILURE() << "Should not have reached this line."; 3872 } 3873 catch (const std::invalid_argument& e) 3874 { 3875 EXPECT_STREQ(e.what(), "Element is not a string"); 3876 } 3877 3878 // Test where fails: format value is invalid 3879 try 3880 { 3881 const json element = R"( 3882 { 3883 "type": "temperature", 3884 "command": "0x7A", 3885 "format": 1 3886 } 3887 )"_json; 3888 parsePMBusReadSensor(element); 3889 ADD_FAILURE() << "Should not have reached this line."; 3890 } 3891 catch (const std::invalid_argument& e) 3892 { 3893 EXPECT_STREQ(e.what(), "Element is not a string"); 3894 } 3895 3896 // Test where fails: exponent value is invalid 3897 try 3898 { 3899 const json element = R"( 3900 { 3901 "type": "temperature", 3902 "command": "0x7A", 3903 "format": "linear_16", 3904 "exponent": 1.3 3905 } 3906 )"_json; 3907 parsePMBusReadSensor(element); 3908 ADD_FAILURE() << "Should not have reached this line."; 3909 } 3910 catch (const std::invalid_argument& e) 3911 { 3912 EXPECT_STREQ(e.what(), "Element is not an integer"); 3913 } 3914 } 3915 3916 TEST(ConfigFileParserTests, ParsePMBusWriteVoutCommand) 3917 { 3918 // Test where works: Only required properties specified 3919 { 3920 const json element = R"( 3921 { 3922 "format": "linear" 3923 } 3924 )"_json; 3925 std::unique_ptr<PMBusWriteVoutCommandAction> action = 3926 parsePMBusWriteVoutCommand(element); 3927 EXPECT_EQ(action->getVolts().has_value(), false); 3928 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear); 3929 EXPECT_EQ(action->getExponent().has_value(), false); 3930 EXPECT_EQ(action->isVerified(), false); 3931 } 3932 3933 // Test where works: All properties specified 3934 { 3935 const json element = R"( 3936 { 3937 "volts": 1.03, 3938 "format": "linear", 3939 "exponent": -8, 3940 "is_verified": true 3941 } 3942 )"_json; 3943 std::unique_ptr<PMBusWriteVoutCommandAction> action = 3944 parsePMBusWriteVoutCommand(element); 3945 EXPECT_EQ(action->getVolts().has_value(), true); 3946 EXPECT_EQ(action->getVolts().value(), 1.03); 3947 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear); 3948 EXPECT_EQ(action->getExponent().has_value(), true); 3949 EXPECT_EQ(action->getExponent().value(), -8); 3950 EXPECT_EQ(action->isVerified(), true); 3951 } 3952 3953 // Test where fails: Element is not an object 3954 try 3955 { 3956 const json element = R"( [ "0xFF", "0x01" ] )"_json; 3957 parsePMBusWriteVoutCommand(element); 3958 ADD_FAILURE() << "Should not have reached this line."; 3959 } 3960 catch (const std::invalid_argument& e) 3961 { 3962 EXPECT_STREQ(e.what(), "Element is not an object"); 3963 } 3964 3965 // Test where fails: volts value is invalid 3966 try 3967 { 3968 const json element = R"( 3969 { 3970 "volts": "foo", 3971 "format": "linear" 3972 } 3973 )"_json; 3974 parsePMBusWriteVoutCommand(element); 3975 ADD_FAILURE() << "Should not have reached this line."; 3976 } 3977 catch (const std::invalid_argument& e) 3978 { 3979 EXPECT_STREQ(e.what(), "Element is not a number"); 3980 } 3981 3982 // Test where fails: Required format property not specified 3983 try 3984 { 3985 const json element = R"( 3986 { 3987 "volts": 1.03, 3988 "is_verified": true 3989 } 3990 )"_json; 3991 parsePMBusWriteVoutCommand(element); 3992 ADD_FAILURE() << "Should not have reached this line."; 3993 } 3994 catch (const std::invalid_argument& e) 3995 { 3996 EXPECT_STREQ(e.what(), "Required property missing: format"); 3997 } 3998 3999 // Test where fails: format value is invalid 4000 try 4001 { 4002 const json element = R"( 4003 { 4004 "format": "linear_11" 4005 } 4006 )"_json; 4007 parsePMBusWriteVoutCommand(element); 4008 ADD_FAILURE() << "Should not have reached this line."; 4009 } 4010 catch (const std::invalid_argument& e) 4011 { 4012 EXPECT_STREQ(e.what(), "Invalid format value: linear_11"); 4013 } 4014 4015 // Test where fails: exponent value is invalid 4016 try 4017 { 4018 const json element = R"( 4019 { 4020 "format": "linear", 4021 "exponent": 1.3 4022 } 4023 )"_json; 4024 parsePMBusWriteVoutCommand(element); 4025 ADD_FAILURE() << "Should not have reached this line."; 4026 } 4027 catch (const std::invalid_argument& e) 4028 { 4029 EXPECT_STREQ(e.what(), "Element is not an integer"); 4030 } 4031 4032 // Test where fails: is_verified value is invalid 4033 try 4034 { 4035 const json element = R"( 4036 { 4037 "format": "linear", 4038 "is_verified": "true" 4039 } 4040 )"_json; 4041 parsePMBusWriteVoutCommand(element); 4042 ADD_FAILURE() << "Should not have reached this line."; 4043 } 4044 catch (const std::invalid_argument& e) 4045 { 4046 EXPECT_STREQ(e.what(), "Element is not a boolean"); 4047 } 4048 4049 // Test where fails: Invalid property specified 4050 try 4051 { 4052 const json element = R"( 4053 { 4054 "format": "linear", 4055 "foo": "bar" 4056 } 4057 )"_json; 4058 parsePMBusWriteVoutCommand(element); 4059 ADD_FAILURE() << "Should not have reached this line."; 4060 } 4061 catch (const std::invalid_argument& e) 4062 { 4063 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 4064 } 4065 } 4066 4067 TEST(ConfigFileParserTests, ParsePresenceDetection) 4068 { 4069 // Test where works: actions property specified 4070 { 4071 const json element = R"( 4072 { 4073 "actions": [ 4074 { "run_rule": "read_sensors_rule" } 4075 ] 4076 } 4077 )"_json; 4078 std::unique_ptr<PresenceDetection> presenceDetection = 4079 parsePresenceDetection(element); 4080 EXPECT_EQ(presenceDetection->getActions().size(), 1); 4081 } 4082 4083 // Test where works: rule_id property specified 4084 { 4085 const json element = R"( 4086 { 4087 "comments": [ "comments property" ], 4088 "rule_id": "set_voltage_rule" 4089 } 4090 )"_json; 4091 std::unique_ptr<PresenceDetection> presenceDetection = 4092 parsePresenceDetection(element); 4093 EXPECT_EQ(presenceDetection->getActions().size(), 1); 4094 } 4095 4096 // Test where fails: actions object is invalid 4097 try 4098 { 4099 const json element = R"( 4100 { 4101 "actions": 1 4102 } 4103 )"_json; 4104 parsePresenceDetection(element); 4105 ADD_FAILURE() << "Should not have reached this line."; 4106 } 4107 catch (const std::invalid_argument& e) 4108 { 4109 EXPECT_STREQ(e.what(), "Element is not an array"); 4110 } 4111 4112 // Test where fails: rule_id value is invalid 4113 try 4114 { 4115 const json element = R"( 4116 { 4117 "rule_id": 1 4118 } 4119 )"_json; 4120 parsePresenceDetection(element); 4121 ADD_FAILURE() << "Should not have reached this line."; 4122 } 4123 catch (const std::invalid_argument& e) 4124 { 4125 EXPECT_STREQ(e.what(), "Element is not a string"); 4126 } 4127 4128 // Test where fails: Required actions or rule_id property not specified 4129 try 4130 { 4131 const json element = R"( 4132 { 4133 "comments": [ "comments property" ] 4134 } 4135 )"_json; 4136 parsePresenceDetection(element); 4137 ADD_FAILURE() << "Should not have reached this line."; 4138 } 4139 catch (const std::invalid_argument& e) 4140 { 4141 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 4142 "either rule_id or actions"); 4143 } 4144 4145 // Test where fails: Required actions or rule_id property both specified 4146 try 4147 { 4148 const json element = R"( 4149 { 4150 "rule_id": "set_voltage_rule", 4151 "actions": [ 4152 { "run_rule": "read_sensors_rule" } 4153 ] 4154 } 4155 )"_json; 4156 parsePresenceDetection(element); 4157 ADD_FAILURE() << "Should not have reached this line."; 4158 } 4159 catch (const std::invalid_argument& e) 4160 { 4161 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 4162 "either rule_id or actions"); 4163 } 4164 4165 // Test where fails: Element is not an object 4166 try 4167 { 4168 const json element = R"( [ "foo", "bar" ] )"_json; 4169 parsePresenceDetection(element); 4170 ADD_FAILURE() << "Should not have reached this line."; 4171 } 4172 catch (const std::invalid_argument& e) 4173 { 4174 EXPECT_STREQ(e.what(), "Element is not an object"); 4175 } 4176 4177 // Test where fails: Invalid property specified 4178 try 4179 { 4180 const json element = R"( 4181 { 4182 "foo": "bar", 4183 "actions": [ 4184 { "run_rule": "read_sensors_rule" } 4185 ] 4186 } 4187 )"_json; 4188 parsePresenceDetection(element); 4189 ADD_FAILURE() << "Should not have reached this line."; 4190 } 4191 catch (const std::invalid_argument& e) 4192 { 4193 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 4194 } 4195 } 4196 4197 TEST(ConfigFileParserTests, ParseRail) 4198 { 4199 // Test where works: Only required properties specified 4200 { 4201 const json element = R"( 4202 { 4203 "id": "vdd" 4204 } 4205 )"_json; 4206 std::unique_ptr<Rail> rail = parseRail(element); 4207 EXPECT_EQ(rail->getID(), "vdd"); 4208 EXPECT_EQ(rail->getConfiguration(), nullptr); 4209 EXPECT_EQ(rail->getSensorMonitoring(), nullptr); 4210 } 4211 4212 // Test where works: All properties specified 4213 { 4214 const json element = R"( 4215 { 4216 "comments": [ "comments property" ], 4217 "id": "vdd", 4218 "configuration": { 4219 "volts": 1.1, 4220 "actions": [ 4221 { 4222 "pmbus_write_vout_command": { 4223 "format": "linear" 4224 } 4225 } 4226 ] 4227 }, 4228 "sensor_monitoring": { 4229 "actions": [ 4230 { "run_rule": "read_sensors_rule" } 4231 ] 4232 } 4233 } 4234 )"_json; 4235 std::unique_ptr<Rail> rail = parseRail(element); 4236 EXPECT_EQ(rail->getID(), "vdd"); 4237 EXPECT_NE(rail->getConfiguration(), nullptr); 4238 EXPECT_NE(rail->getSensorMonitoring(), nullptr); 4239 } 4240 4241 // Test where fails: id property not specified 4242 try 4243 { 4244 const json element = R"( 4245 { 4246 "configuration": { 4247 "volts": 1.1, 4248 "actions": [ 4249 { 4250 "pmbus_write_vout_command": { 4251 "format": "linear" 4252 } 4253 } 4254 ] 4255 } 4256 } 4257 )"_json; 4258 parseRail(element); 4259 ADD_FAILURE() << "Should not have reached this line."; 4260 } 4261 catch (const std::invalid_argument& e) 4262 { 4263 EXPECT_STREQ(e.what(), "Required property missing: id"); 4264 } 4265 4266 // Test where fails: id property is invalid 4267 try 4268 { 4269 const json element = R"( 4270 { 4271 "id": "", 4272 "configuration": { 4273 "volts": 1.1, 4274 "actions": [ 4275 { 4276 "pmbus_write_vout_command": { 4277 "format": "linear" 4278 } 4279 } 4280 ] 4281 } 4282 } 4283 )"_json; 4284 parseRail(element); 4285 ADD_FAILURE() << "Should not have reached this line."; 4286 } 4287 catch (const std::invalid_argument& e) 4288 { 4289 EXPECT_STREQ(e.what(), "Element contains an empty string"); 4290 } 4291 4292 // Test where fails: Element is not an object 4293 try 4294 { 4295 const json element = R"( [ "0xFF", "0x01" ] )"_json; 4296 parseRail(element); 4297 ADD_FAILURE() << "Should not have reached this line."; 4298 } 4299 catch (const std::invalid_argument& e) 4300 { 4301 EXPECT_STREQ(e.what(), "Element is not an object"); 4302 } 4303 4304 // Test where fails: configuration value is invalid 4305 try 4306 { 4307 const json element = R"( 4308 { 4309 "id": "vdd", 4310 "configuration": "config" 4311 } 4312 )"_json; 4313 parseRail(element); 4314 ADD_FAILURE() << "Should not have reached this line."; 4315 } 4316 catch (const std::invalid_argument& e) 4317 { 4318 EXPECT_STREQ(e.what(), "Element is not an object"); 4319 } 4320 4321 // Test where fails: sensor_monitoring value is invalid 4322 try 4323 { 4324 const json element = R"( 4325 { 4326 "comments": [ "comments property" ], 4327 "id": "vdd", 4328 "configuration": { 4329 "volts": 1.1, 4330 "actions": [ 4331 { 4332 "pmbus_write_vout_command": { 4333 "format": "linear" 4334 } 4335 } 4336 ] 4337 }, 4338 "sensor_monitoring": 1 4339 } 4340 )"_json; 4341 parseRail(element); 4342 ADD_FAILURE() << "Should not have reached this line."; 4343 } 4344 catch (const std::invalid_argument& e) 4345 { 4346 EXPECT_STREQ(e.what(), "Element is not an object"); 4347 } 4348 4349 // Test where fails: Invalid property specified 4350 try 4351 { 4352 const json element = R"( 4353 { 4354 "id": "vdd", 4355 "foo" : true 4356 } 4357 )"_json; 4358 parseRail(element); 4359 ADD_FAILURE() << "Should not have reached this line."; 4360 } 4361 catch (const std::invalid_argument& e) 4362 { 4363 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 4364 } 4365 } 4366 4367 TEST(ConfigFileParserTests, ParseRailArray) 4368 { 4369 // Test where works 4370 { 4371 const json element = R"( 4372 [ 4373 { "id": "vdd" }, 4374 { "id": "vio" } 4375 ] 4376 )"_json; 4377 std::vector<std::unique_ptr<Rail>> rails = parseRailArray(element); 4378 EXPECT_EQ(rails.size(), 2); 4379 EXPECT_EQ(rails[0]->getID(), "vdd"); 4380 EXPECT_EQ(rails[1]->getID(), "vio"); 4381 } 4382 4383 // Test where fails: Element is not an array 4384 try 4385 { 4386 const json element = R"( 4387 { 4388 "foo": "bar" 4389 } 4390 )"_json; 4391 parseRailArray(element); 4392 ADD_FAILURE() << "Should not have reached this line."; 4393 } 4394 catch (const std::invalid_argument& e) 4395 { 4396 EXPECT_STREQ(e.what(), "Element is not an array"); 4397 } 4398 } 4399 4400 TEST(ConfigFileParserTests, ParseRoot) 4401 { 4402 // Test where works: Only required properties specified 4403 { 4404 const json element = R"( 4405 { 4406 "chassis": [ 4407 { "number": 1 } 4408 ] 4409 } 4410 )"_json; 4411 std::vector<std::unique_ptr<Rule>> rules{}; 4412 std::vector<std::unique_ptr<Chassis>> chassis{}; 4413 std::tie(rules, chassis) = parseRoot(element); 4414 EXPECT_EQ(rules.size(), 0); 4415 EXPECT_EQ(chassis.size(), 1); 4416 } 4417 4418 // Test where works: All properties specified 4419 { 4420 const json element = R"( 4421 { 4422 "comments": [ "Config file for a FooBar one-chassis system" ], 4423 "rules": [ 4424 { 4425 "id": "set_voltage_rule", 4426 "actions": [ 4427 { "pmbus_write_vout_command": { "format": "linear" } } 4428 ] 4429 } 4430 ], 4431 "chassis": [ 4432 { "number": 1 }, 4433 { "number": 3 } 4434 ] 4435 } 4436 )"_json; 4437 std::vector<std::unique_ptr<Rule>> rules{}; 4438 std::vector<std::unique_ptr<Chassis>> chassis{}; 4439 std::tie(rules, chassis) = parseRoot(element); 4440 EXPECT_EQ(rules.size(), 1); 4441 EXPECT_EQ(chassis.size(), 2); 4442 } 4443 4444 // Test where fails: Element is not an object 4445 try 4446 { 4447 const json element = R"( [ "0xFF", "0x01" ] )"_json; 4448 parseRoot(element); 4449 ADD_FAILURE() << "Should not have reached this line."; 4450 } 4451 catch (const std::invalid_argument& e) 4452 { 4453 EXPECT_STREQ(e.what(), "Element is not an object"); 4454 } 4455 4456 // Test where fails: chassis property not specified 4457 try 4458 { 4459 const json element = R"( 4460 { 4461 "rules": [ 4462 { 4463 "id": "set_voltage_rule", 4464 "actions": [ 4465 { "pmbus_write_vout_command": { "format": "linear" } } 4466 ] 4467 } 4468 ] 4469 } 4470 )"_json; 4471 parseRoot(element); 4472 ADD_FAILURE() << "Should not have reached this line."; 4473 } 4474 catch (const std::invalid_argument& e) 4475 { 4476 EXPECT_STREQ(e.what(), "Required property missing: chassis"); 4477 } 4478 4479 // Test where fails: Invalid property specified 4480 try 4481 { 4482 const json element = R"( 4483 { 4484 "remarks": [ "Config file for a FooBar one-chassis system" ], 4485 "chassis": [ 4486 { "number": 1 } 4487 ] 4488 } 4489 )"_json; 4490 parseRoot(element); 4491 ADD_FAILURE() << "Should not have reached this line."; 4492 } 4493 catch (const std::invalid_argument& e) 4494 { 4495 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 4496 } 4497 } 4498 4499 TEST(ConfigFileParserTests, ParseRule) 4500 { 4501 // Test where works: comments property specified 4502 { 4503 const json element = R"( 4504 { 4505 "comments": [ "Set voltage rule" ], 4506 "id": "set_voltage_rule", 4507 "actions": [ 4508 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }, 4509 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } } 4510 ] 4511 } 4512 )"_json; 4513 std::unique_ptr<Rule> rule = parseRule(element); 4514 EXPECT_EQ(rule->getID(), "set_voltage_rule"); 4515 EXPECT_EQ(rule->getActions().size(), 2); 4516 } 4517 4518 // Test where works: comments property not specified 4519 { 4520 const json element = R"( 4521 { 4522 "id": "set_voltage_rule", 4523 "actions": [ 4524 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }, 4525 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }, 4526 { "pmbus_write_vout_command": { "volts": 1.05, "format": "linear" } } 4527 ] 4528 } 4529 )"_json; 4530 std::unique_ptr<Rule> rule = parseRule(element); 4531 EXPECT_EQ(rule->getID(), "set_voltage_rule"); 4532 EXPECT_EQ(rule->getActions().size(), 3); 4533 } 4534 4535 // Test where fails: Element is not an object 4536 try 4537 { 4538 const json element = R"( [ "0xFF", "0x01" ] )"_json; 4539 parseRule(element); 4540 ADD_FAILURE() << "Should not have reached this line."; 4541 } 4542 catch (const std::invalid_argument& e) 4543 { 4544 EXPECT_STREQ(e.what(), "Element is not an object"); 4545 } 4546 4547 // Test where fails: id property not specified 4548 try 4549 { 4550 const json element = R"( 4551 { 4552 "actions": [ 4553 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } } 4554 ] 4555 } 4556 )"_json; 4557 parseRule(element); 4558 ADD_FAILURE() << "Should not have reached this line."; 4559 } 4560 catch (const std::invalid_argument& e) 4561 { 4562 EXPECT_STREQ(e.what(), "Required property missing: id"); 4563 } 4564 4565 // Test where fails: id property is invalid 4566 try 4567 { 4568 const json element = R"( 4569 { 4570 "id": "", 4571 "actions": [ 4572 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } } 4573 ] 4574 } 4575 )"_json; 4576 parseRule(element); 4577 ADD_FAILURE() << "Should not have reached this line."; 4578 } 4579 catch (const std::invalid_argument& e) 4580 { 4581 EXPECT_STREQ(e.what(), "Element contains an empty string"); 4582 } 4583 4584 // Test where fails: actions property not specified 4585 try 4586 { 4587 const json element = R"( 4588 { 4589 "comments": [ "Set voltage rule" ], 4590 "id": "set_voltage_rule" 4591 } 4592 )"_json; 4593 parseRule(element); 4594 ADD_FAILURE() << "Should not have reached this line."; 4595 } 4596 catch (const std::invalid_argument& e) 4597 { 4598 EXPECT_STREQ(e.what(), "Required property missing: actions"); 4599 } 4600 4601 // Test where fails: actions property is invalid 4602 try 4603 { 4604 const json element = R"( 4605 { 4606 "id": "set_voltage_rule", 4607 "actions": true 4608 } 4609 )"_json; 4610 parseRule(element); 4611 ADD_FAILURE() << "Should not have reached this line."; 4612 } 4613 catch (const std::invalid_argument& e) 4614 { 4615 EXPECT_STREQ(e.what(), "Element is not an array"); 4616 } 4617 4618 // Test where fails: Invalid property specified 4619 try 4620 { 4621 const json element = R"( 4622 { 4623 "remarks": [ "Set voltage rule" ], 4624 "id": "set_voltage_rule", 4625 "actions": [ 4626 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } } 4627 ] 4628 } 4629 )"_json; 4630 parseRule(element); 4631 ADD_FAILURE() << "Should not have reached this line."; 4632 } 4633 catch (const std::invalid_argument& e) 4634 { 4635 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 4636 } 4637 } 4638 4639 TEST(ConfigFileParserTests, ParseRuleArray) 4640 { 4641 // Test where works 4642 { 4643 const json element = R"( 4644 [ 4645 { 4646 "id": "set_voltage_rule1", 4647 "actions": [ 4648 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } } 4649 ] 4650 }, 4651 { 4652 "id": "set_voltage_rule2", 4653 "actions": [ 4654 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }, 4655 { "pmbus_write_vout_command": { "volts": 1.11, "format": "linear" } } 4656 ] 4657 } 4658 ] 4659 )"_json; 4660 std::vector<std::unique_ptr<Rule>> rules = parseRuleArray(element); 4661 EXPECT_EQ(rules.size(), 2); 4662 EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1"); 4663 EXPECT_EQ(rules[0]->getActions().size(), 1); 4664 EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2"); 4665 EXPECT_EQ(rules[1]->getActions().size(), 2); 4666 } 4667 4668 // Test where fails: Element is not an array 4669 try 4670 { 4671 const json element = R"( { "id": "set_voltage_rule" } )"_json; 4672 parseRuleArray(element); 4673 ADD_FAILURE() << "Should not have reached this line."; 4674 } 4675 catch (const std::invalid_argument& e) 4676 { 4677 EXPECT_STREQ(e.what(), "Element is not an array"); 4678 } 4679 } 4680 4681 TEST(ConfigFileParserTests, ParseRuleIDOrActionsProperty) 4682 { 4683 // Test where works: actions specified 4684 { 4685 const json element = R"( 4686 { 4687 "actions": [ 4688 { "pmbus_write_vout_command": { "format": "linear" } }, 4689 { "run_rule": "set_voltage_rule" } 4690 ] 4691 } 4692 )"_json; 4693 std::vector<std::unique_ptr<Action>> actions = 4694 parseRuleIDOrActionsProperty(element); 4695 EXPECT_EQ(actions.size(), 2); 4696 } 4697 4698 // Test where works: rule_id specified 4699 { 4700 const json element = R"( 4701 { 4702 "rule_id": "set_voltage_rule" 4703 } 4704 )"_json; 4705 std::vector<std::unique_ptr<Action>> actions = 4706 parseRuleIDOrActionsProperty(element); 4707 EXPECT_EQ(actions.size(), 1); 4708 } 4709 4710 // Test where fails: Element is not an object 4711 try 4712 { 4713 const json element = R"( [ "foo", "bar" ] )"_json; 4714 parseRuleIDOrActionsProperty(element); 4715 ADD_FAILURE() << "Should not have reached this line."; 4716 } 4717 catch (const std::invalid_argument& e) 4718 { 4719 EXPECT_STREQ(e.what(), "Element is not an object"); 4720 } 4721 4722 // Test where fails: rule_id is invalid 4723 try 4724 { 4725 const json element = R"( 4726 { "rule_id": 1 } 4727 )"_json; 4728 parseRuleIDOrActionsProperty(element); 4729 ADD_FAILURE() << "Should not have reached this line."; 4730 } 4731 catch (const std::invalid_argument& e) 4732 { 4733 EXPECT_STREQ(e.what(), "Element is not a string"); 4734 } 4735 4736 // Test where fails: actions is invalid 4737 try 4738 { 4739 const json element = R"( 4740 { "actions": 1 } 4741 )"_json; 4742 parseRuleIDOrActionsProperty(element); 4743 ADD_FAILURE() << "Should not have reached this line."; 4744 } 4745 catch (const std::invalid_argument& e) 4746 { 4747 EXPECT_STREQ(e.what(), "Element is not an array"); 4748 } 4749 4750 // Test where fails: Neither rule_id nor actions specified 4751 try 4752 { 4753 const json element = R"( 4754 { 4755 "volts": 1.03 4756 } 4757 )"_json; 4758 parseRuleIDOrActionsProperty(element); 4759 ADD_FAILURE() << "Should not have reached this line."; 4760 } 4761 catch (const std::invalid_argument& e) 4762 { 4763 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 4764 "either rule_id or actions"); 4765 } 4766 4767 // Test where fails: Both rule_id and actions specified 4768 try 4769 { 4770 const json element = R"( 4771 { 4772 "volts": 1.03, 4773 "rule_id": "set_voltage_rule", 4774 "actions": [ 4775 { 4776 "pmbus_write_vout_command": { 4777 "format": "linear" 4778 } 4779 } 4780 ] 4781 } 4782 )"_json; 4783 parseRuleIDOrActionsProperty(element); 4784 ADD_FAILURE() << "Should not have reached this line."; 4785 } 4786 catch (const std::invalid_argument& e) 4787 { 4788 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 4789 "either rule_id or actions"); 4790 } 4791 } 4792 4793 TEST(ConfigFileParserTests, ParseRunRule) 4794 { 4795 // Test where works 4796 { 4797 const json element = "vdd_regulator"; 4798 std::unique_ptr<RunRuleAction> action = parseRunRule(element); 4799 EXPECT_EQ(action->getRuleID(), "vdd_regulator"); 4800 } 4801 4802 // Test where fails: Element is not a string 4803 try 4804 { 4805 const json element = 1; 4806 parseRunRule(element); 4807 ADD_FAILURE() << "Should not have reached this line."; 4808 } 4809 catch (const std::invalid_argument& e) 4810 { 4811 EXPECT_STREQ(e.what(), "Element is not a string"); 4812 } 4813 4814 // Test where fails: Empty string 4815 try 4816 { 4817 const json element = ""; 4818 parseRunRule(element); 4819 ADD_FAILURE() << "Should not have reached this line."; 4820 } 4821 catch (const std::invalid_argument& e) 4822 { 4823 EXPECT_STREQ(e.what(), "Element contains an empty string"); 4824 } 4825 } 4826 4827 TEST(ConfigFileParserTests, ParseSensorDataFormat) 4828 { 4829 // Test where works: linear_11 4830 { 4831 const json element = "linear_11"; 4832 pmbus_utils::SensorDataFormat value = parseSensorDataFormat(element); 4833 pmbus_utils::SensorDataFormat format = 4834 pmbus_utils::SensorDataFormat::linear_11; 4835 EXPECT_EQ(value, format); 4836 } 4837 4838 // Test where works: linear_16 4839 { 4840 const json element = "linear_16"; 4841 pmbus_utils::SensorDataFormat value = parseSensorDataFormat(element); 4842 pmbus_utils::SensorDataFormat format = 4843 pmbus_utils::SensorDataFormat::linear_16; 4844 EXPECT_EQ(value, format); 4845 } 4846 4847 // Test where fails: Element is not a sensor data format 4848 try 4849 { 4850 const json element = "foo"; 4851 parseSensorDataFormat(element); 4852 ADD_FAILURE() << "Should not have reached this line."; 4853 } 4854 catch (const std::invalid_argument& e) 4855 { 4856 EXPECT_STREQ(e.what(), "Element is not a sensor data format"); 4857 } 4858 4859 // Test where fails: Element is not a string 4860 try 4861 { 4862 const json element = R"( { "foo": "bar" } )"_json; 4863 parseSensorDataFormat(element); 4864 ADD_FAILURE() << "Should not have reached this line."; 4865 } 4866 catch (const std::invalid_argument& e) 4867 { 4868 EXPECT_STREQ(e.what(), "Element is not a string"); 4869 } 4870 } 4871 4872 TEST(ConfigFileParserTests, ParseSensorMonitoring) 4873 { 4874 // Test where works: actions property specified 4875 { 4876 const json element = R"( 4877 { 4878 "actions": [ 4879 { "run_rule": "read_sensors_rule" } 4880 ] 4881 } 4882 )"_json; 4883 std::unique_ptr<SensorMonitoring> sensorMonitoring = 4884 parseSensorMonitoring(element); 4885 EXPECT_EQ(sensorMonitoring->getActions().size(), 1); 4886 } 4887 4888 // Test where works: rule_id property specified 4889 { 4890 const json element = R"( 4891 { 4892 "comments": [ "comments property" ], 4893 "rule_id": "set_voltage_rule" 4894 } 4895 )"_json; 4896 std::unique_ptr<SensorMonitoring> sensorMonitoring = 4897 parseSensorMonitoring(element); 4898 EXPECT_EQ(sensorMonitoring->getActions().size(), 1); 4899 } 4900 4901 // Test where fails: actions object is invalid 4902 try 4903 { 4904 const json element = R"( 4905 { 4906 "actions": 1 4907 } 4908 )"_json; 4909 parseSensorMonitoring(element); 4910 ADD_FAILURE() << "Should not have reached this line."; 4911 } 4912 catch (const std::invalid_argument& e) 4913 { 4914 EXPECT_STREQ(e.what(), "Element is not an array"); 4915 } 4916 4917 // Test where fails: rule_id value is invalid 4918 try 4919 { 4920 const json element = R"( 4921 { 4922 "rule_id": 1 4923 } 4924 )"_json; 4925 parseSensorMonitoring(element); 4926 ADD_FAILURE() << "Should not have reached this line."; 4927 } 4928 catch (const std::invalid_argument& e) 4929 { 4930 EXPECT_STREQ(e.what(), "Element is not a string"); 4931 } 4932 4933 // Test where fails: Required actions or rule_id property not specified 4934 try 4935 { 4936 const json element = R"( 4937 { 4938 "comments": [ "comments property" ] 4939 } 4940 )"_json; 4941 parseSensorMonitoring(element); 4942 ADD_FAILURE() << "Should not have reached this line."; 4943 } 4944 catch (const std::invalid_argument& e) 4945 { 4946 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 4947 "either rule_id or actions"); 4948 } 4949 4950 // Test where fails: Required actions or rule_id property both specified 4951 try 4952 { 4953 const json element = R"( 4954 { 4955 "rule_id": "set_voltage_rule", 4956 "actions": [ 4957 { "run_rule": "read_sensors_rule" } 4958 ] 4959 } 4960 )"_json; 4961 parseSensorMonitoring(element); 4962 ADD_FAILURE() << "Should not have reached this line."; 4963 } 4964 catch (const std::invalid_argument& e) 4965 { 4966 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain " 4967 "either rule_id or actions"); 4968 } 4969 4970 // Test where fails: Element is not an object 4971 try 4972 { 4973 const json element = R"( [ "foo", "bar" ] )"_json; 4974 parseSensorMonitoring(element); 4975 ADD_FAILURE() << "Should not have reached this line."; 4976 } 4977 catch (const std::invalid_argument& e) 4978 { 4979 EXPECT_STREQ(e.what(), "Element is not an object"); 4980 } 4981 4982 // Test where fails: Invalid property specified 4983 try 4984 { 4985 const json element = R"( 4986 { 4987 "foo": "bar", 4988 "actions": [ 4989 { "run_rule": "read_sensors_rule" } 4990 ] 4991 } 4992 )"_json; 4993 parseSensorMonitoring(element); 4994 ADD_FAILURE() << "Should not have reached this line."; 4995 } 4996 catch (const std::invalid_argument& e) 4997 { 4998 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 4999 } 5000 } 5001 5002 TEST(ConfigFileParserTests, ParseSensorType) 5003 { 5004 // Test where works: iout 5005 { 5006 const json element = "iout"; 5007 SensorType type = parseSensorType(element); 5008 EXPECT_EQ(type, SensorType::iout); 5009 } 5010 5011 // Test where works: iout_peak 5012 { 5013 const json element = "iout_peak"; 5014 SensorType type = parseSensorType(element); 5015 EXPECT_EQ(type, SensorType::iout_peak); 5016 } 5017 5018 // Test where works: iout_valley 5019 { 5020 const json element = "iout_valley"; 5021 SensorType type = parseSensorType(element); 5022 EXPECT_EQ(type, SensorType::iout_valley); 5023 } 5024 5025 // Test where works: pout 5026 { 5027 const json element = "pout"; 5028 SensorType type = parseSensorType(element); 5029 EXPECT_EQ(type, SensorType::pout); 5030 } 5031 5032 // Test where works: temperature 5033 { 5034 const json element = "temperature"; 5035 SensorType type = parseSensorType(element); 5036 EXPECT_EQ(type, SensorType::temperature); 5037 } 5038 5039 // Test where works: temperature_peak 5040 { 5041 const json element = "temperature_peak"; 5042 SensorType type = parseSensorType(element); 5043 EXPECT_EQ(type, SensorType::temperature_peak); 5044 } 5045 5046 // Test where works: vout 5047 { 5048 const json element = "vout"; 5049 SensorType type = parseSensorType(element); 5050 EXPECT_EQ(type, SensorType::vout); 5051 } 5052 5053 // Test where works: vout_peak 5054 { 5055 const json element = "vout_peak"; 5056 SensorType type = parseSensorType(element); 5057 EXPECT_EQ(type, SensorType::vout_peak); 5058 } 5059 5060 // Test where works: vout_valley 5061 { 5062 const json element = "vout_valley"; 5063 SensorType type = parseSensorType(element); 5064 EXPECT_EQ(type, SensorType::vout_valley); 5065 } 5066 5067 // Test where fails: Element is not a sensor type 5068 try 5069 { 5070 const json element = "foo"; 5071 parseSensorType(element); 5072 ADD_FAILURE() << "Should not have reached this line."; 5073 } 5074 catch (const std::invalid_argument& e) 5075 { 5076 EXPECT_STREQ(e.what(), "Element is not a sensor type"); 5077 } 5078 5079 // Test where fails: Element is not a string 5080 try 5081 { 5082 const json element = R"( { "foo": "bar" } )"_json; 5083 parseSensorType(element); 5084 ADD_FAILURE() << "Should not have reached this line."; 5085 } 5086 catch (const std::invalid_argument& e) 5087 { 5088 EXPECT_STREQ(e.what(), "Element is not a string"); 5089 } 5090 } 5091 5092 TEST(ConfigFileParserTests, ParseSetDevice) 5093 { 5094 // Test where works 5095 { 5096 const json element = "regulator1"; 5097 std::unique_ptr<SetDeviceAction> action = parseSetDevice(element); 5098 EXPECT_EQ(action->getDeviceID(), "regulator1"); 5099 } 5100 5101 // Test where fails: Element is not a string 5102 try 5103 { 5104 const json element = 1; 5105 parseSetDevice(element); 5106 ADD_FAILURE() << "Should not have reached this line."; 5107 } 5108 catch (const std::invalid_argument& e) 5109 { 5110 EXPECT_STREQ(e.what(), "Element is not a string"); 5111 } 5112 5113 // Test where fails: Empty string 5114 try 5115 { 5116 const json element = ""; 5117 parseSetDevice(element); 5118 ADD_FAILURE() << "Should not have reached this line."; 5119 } 5120 catch (const std::invalid_argument& e) 5121 { 5122 EXPECT_STREQ(e.what(), "Element contains an empty string"); 5123 } 5124 } 5125 5126 TEST(ConfigFileParserTests, ParseString) 5127 { 5128 // Test where works: Empty string 5129 { 5130 const json element = ""; 5131 std::string value = parseString(element, true); 5132 EXPECT_EQ(value, ""); 5133 } 5134 5135 // Test where works: Non-empty string 5136 { 5137 const json element = "vdd_regulator"; 5138 std::string value = parseString(element, false); 5139 EXPECT_EQ(value, "vdd_regulator"); 5140 } 5141 5142 // Test where fails: Element is not a string 5143 try 5144 { 5145 const json element = R"( { "foo": "bar" } )"_json; 5146 parseString(element); 5147 ADD_FAILURE() << "Should not have reached this line."; 5148 } 5149 catch (const std::invalid_argument& e) 5150 { 5151 EXPECT_STREQ(e.what(), "Element is not a string"); 5152 } 5153 5154 // Test where fails: Empty string 5155 try 5156 { 5157 const json element = ""; 5158 parseString(element); 5159 ADD_FAILURE() << "Should not have reached this line."; 5160 } 5161 catch (const std::invalid_argument& e) 5162 { 5163 EXPECT_STREQ(e.what(), "Element contains an empty string"); 5164 } 5165 } 5166 5167 TEST(ConfigFileParserTests, ParseUint8) 5168 { 5169 // Test where works: 0 5170 { 5171 const json element = R"( 0 )"_json; 5172 uint8_t value = parseUint8(element); 5173 EXPECT_EQ(value, 0); 5174 } 5175 5176 // Test where works: UINT8_MAX 5177 { 5178 const json element = R"( 255 )"_json; 5179 uint8_t value = parseUint8(element); 5180 EXPECT_EQ(value, 255); 5181 } 5182 5183 // Test where fails: Element is not an integer 5184 try 5185 { 5186 const json element = R"( 1.03 )"_json; 5187 parseUint8(element); 5188 ADD_FAILURE() << "Should not have reached this line."; 5189 } 5190 catch (const std::invalid_argument& e) 5191 { 5192 EXPECT_STREQ(e.what(), "Element is not an integer"); 5193 } 5194 5195 // Test where fails: Value < 0 5196 try 5197 { 5198 const json element = R"( -1 )"_json; 5199 parseUint8(element); 5200 ADD_FAILURE() << "Should not have reached this line."; 5201 } 5202 catch (const std::invalid_argument& e) 5203 { 5204 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); 5205 } 5206 5207 // Test where fails: Value > UINT8_MAX 5208 try 5209 { 5210 const json element = R"( 256 )"_json; 5211 parseUint8(element); 5212 ADD_FAILURE() << "Should not have reached this line."; 5213 } 5214 catch (const std::invalid_argument& e) 5215 { 5216 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer"); 5217 } 5218 } 5219 5220 TEST(ConfigFileParserTests, ParseUnsignedInteger) 5221 { 5222 // Test where works: 1 5223 { 5224 const json element = R"( 1 )"_json; 5225 unsigned int value = parseUnsignedInteger(element); 5226 EXPECT_EQ(value, 1); 5227 } 5228 5229 // Test where fails: Element is not an integer 5230 try 5231 { 5232 const json element = R"( 1.5 )"_json; 5233 parseUnsignedInteger(element); 5234 ADD_FAILURE() << "Should not have reached this line."; 5235 } 5236 catch (const std::invalid_argument& e) 5237 { 5238 EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); 5239 } 5240 5241 // Test where fails: Value < 0 5242 try 5243 { 5244 const json element = R"( -1 )"_json; 5245 parseUnsignedInteger(element); 5246 ADD_FAILURE() << "Should not have reached this line."; 5247 } 5248 catch (const std::invalid_argument& e) 5249 { 5250 EXPECT_STREQ(e.what(), "Element is not an unsigned integer"); 5251 } 5252 } 5253 5254 TEST(ConfigFileParserTests, ParseVoutDataFormat) 5255 { 5256 // Test where works: linear 5257 { 5258 const json element = "linear"; 5259 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element); 5260 pmbus_utils::VoutDataFormat format = 5261 pmbus_utils::VoutDataFormat::linear; 5262 EXPECT_EQ(value, format); 5263 } 5264 5265 // Test where works: vid 5266 { 5267 const json element = "vid"; 5268 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element); 5269 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::vid; 5270 EXPECT_EQ(value, format); 5271 } 5272 5273 // Test where works: direct 5274 { 5275 const json element = "direct"; 5276 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element); 5277 pmbus_utils::VoutDataFormat format = 5278 pmbus_utils::VoutDataFormat::direct; 5279 EXPECT_EQ(value, format); 5280 } 5281 5282 // Test where works: ieee 5283 { 5284 const json element = "ieee"; 5285 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element); 5286 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::ieee; 5287 EXPECT_EQ(value, format); 5288 } 5289 5290 // Test where fails: Element is not a vout data format 5291 try 5292 { 5293 const json element = "foo"; 5294 parseVoutDataFormat(element); 5295 ADD_FAILURE() << "Should not have reached this line."; 5296 } 5297 catch (const std::invalid_argument& e) 5298 { 5299 EXPECT_STREQ(e.what(), "Element is not a vout data format"); 5300 } 5301 5302 // Test where fails: Element is not a string 5303 try 5304 { 5305 const json element = R"( { "foo": "bar" } )"_json; 5306 parseVoutDataFormat(element); 5307 ADD_FAILURE() << "Should not have reached this line."; 5308 } 5309 catch (const std::invalid_argument& e) 5310 { 5311 EXPECT_STREQ(e.what(), "Element is not a string"); 5312 } 5313 } 5314 5315 TEST(ConfigFileParserTests, VerifyIsArray) 5316 { 5317 // Test where element is an array 5318 try 5319 { 5320 const json element = R"( [ "foo", "bar" ] )"_json; 5321 verifyIsArray(element); 5322 } 5323 catch (const std::exception& e) 5324 { 5325 ADD_FAILURE() << "Should not have caught exception."; 5326 } 5327 5328 // Test where element is not an array 5329 try 5330 { 5331 const json element = R"( { "foo": "bar" } )"_json; 5332 verifyIsArray(element); 5333 ADD_FAILURE() << "Should not have reached this line."; 5334 } 5335 catch (const std::invalid_argument& e) 5336 { 5337 EXPECT_STREQ(e.what(), "Element is not an array"); 5338 } 5339 } 5340 5341 TEST(ConfigFileParserTests, VerifyIsObject) 5342 { 5343 // Test where element is an object 5344 try 5345 { 5346 const json element = R"( { "foo": "bar" } )"_json; 5347 verifyIsObject(element); 5348 } 5349 catch (const std::exception& e) 5350 { 5351 ADD_FAILURE() << "Should not have caught exception."; 5352 } 5353 5354 // Test where element is not an object 5355 try 5356 { 5357 const json element = R"( [ "foo", "bar" ] )"_json; 5358 verifyIsObject(element); 5359 ADD_FAILURE() << "Should not have reached this line."; 5360 } 5361 catch (const std::invalid_argument& e) 5362 { 5363 EXPECT_STREQ(e.what(), "Element is not an object"); 5364 } 5365 } 5366 5367 TEST(ConfigFileParserTests, VerifyPropertyCount) 5368 { 5369 // Test where element has expected number of properties 5370 try 5371 { 5372 const json element = R"( 5373 { 5374 "comments": [ "Set voltage rule" ], 5375 "id": "set_voltage_rule" 5376 } 5377 )"_json; 5378 verifyPropertyCount(element, 2); 5379 } 5380 catch (const std::exception& e) 5381 { 5382 ADD_FAILURE() << "Should not have caught exception."; 5383 } 5384 5385 // Test where element has unexpected number of properties 5386 try 5387 { 5388 const json element = R"( 5389 { 5390 "comments": [ "Set voltage rule" ], 5391 "id": "set_voltage_rule", 5392 "foo": 1.3 5393 } 5394 )"_json; 5395 verifyPropertyCount(element, 2); 5396 ADD_FAILURE() << "Should not have reached this line."; 5397 } 5398 catch (const std::invalid_argument& e) 5399 { 5400 EXPECT_STREQ(e.what(), "Element contains an invalid property"); 5401 } 5402 } 5403