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