1 /** 2 * Copyright c 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 <errno.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <sys/stat.h> 20 #include <sys/wait.h> 21 22 #include <nlohmann/json.hpp> 23 24 #include <fstream> 25 26 #include <gtest/gtest.h> 27 28 #define EXPECT_FILE_VALID(configFile) expectFileValid(configFile) 29 #define EXPECT_FILE_INVALID(configFile, expectedErrorMessage, \ 30 expectedOutputMessage) \ 31 expectFileInvalid(configFile, expectedErrorMessage, expectedOutputMessage) 32 #define EXPECT_JSON_VALID(configFileJson) expectJsonValid(configFileJson) 33 #define EXPECT_JSON_INVALID(configFileJson, expectedErrorMessage, \ 34 expectedOutputMessage) \ 35 expectJsonInvalid(configFileJson, expectedErrorMessage, \ 36 expectedOutputMessage) 37 38 using json = nlohmann::json; 39 40 const json validConfigFile = R"( 41 { 42 "comments": [ "Config file for a FooBar one-chassis system" ], 43 44 "rules": [ 45 { 46 "comments": [ "Sets output voltage for a PMBus regulator rail" ], 47 "id": "set_voltage_rule", 48 "actions": [ 49 { 50 "pmbus_write_vout_command": { 51 "format": "linear" 52 } 53 } 54 ] 55 }, 56 { 57 "comments": [ "Reads sensors from a PMBus regulator rail" ], 58 "id": "read_sensors_rule", 59 "actions": [ 60 { 61 "comments": [ "Read output voltage from READ_VOUT." ], 62 "pmbus_read_sensor": { 63 "type": "vout", 64 "command": "0x8B", 65 "format": "linear_16" 66 } 67 } 68 ] 69 } 70 ], 71 72 "chassis": [ 73 { 74 "comments": [ "Chassis number 1 containing CPUs and memory" ], 75 "number": 1, 76 "devices": [ 77 { 78 "comments": [ "IR35221 regulator producing the Vdd rail" ], 79 "id": "vdd_regulator", 80 "is_regulator": true, 81 "fru": "/system/chassis/motherboard/regulator1", 82 "i2c_interface": { 83 "bus": 1, 84 "address": "0x70" 85 }, 86 "rails": [ 87 { 88 "comments": [ "Vdd rail" ], 89 "id": "vdd", 90 "configuration": { 91 "volts": 1.03, 92 "rule_id": "set_voltage_rule" 93 }, 94 "sensor_monitoring": { 95 "rule_id": "read_sensors_rule" 96 } 97 } 98 ] 99 } 100 ] 101 } 102 ] 103 } 104 )"_json; 105 106 class TmpFile 107 { 108 public: 109 TmpFile() 110 { 111 int fd = mkstemp(fileName); 112 if (fd == -1) 113 { 114 perror("Can't create temporary file"); 115 } 116 close(fd); 117 } 118 119 std::string getName() 120 { 121 return fileName; 122 } 123 124 ~TmpFile() 125 { 126 unlink(fileName); 127 } 128 129 private: 130 char fileName[17] = "/tmp/temp-XXXXXX"; 131 }; 132 133 std::string getValidationToolCommand(const std::string& configFileName) 134 { 135 std::string command = 136 "../phosphor-regulators/tools/validate-regulators-config.py -s \ 137 ../phosphor-regulators/schema/config_schema.json -c "; 138 command += configFileName; 139 return command; 140 } 141 142 int runToolForOutputWithCommand(std::string command, 143 std::string& standardOutput, 144 std::string& standardError) 145 { 146 // run the validation tool with the temporary file and return the output 147 // of the validation tool. 148 TmpFile tmpFile; 149 command += " 2> " + tmpFile.getName(); 150 // get the jsonschema print from validation tool. 151 char buffer[256]; 152 std::string result; 153 // to get the stdout from the validation tool. 154 FILE* pipe = popen(command.c_str(), "r"); 155 if (!pipe) 156 { 157 throw std::runtime_error("popen() failed!"); 158 } 159 while (!std::feof(pipe)) 160 { 161 if (fgets(buffer, sizeof buffer, pipe) != NULL) 162 { 163 result += buffer; 164 } 165 } 166 int returnValue = pclose(pipe); 167 // Check if pclose() failed 168 if (returnValue == -1) 169 { 170 // unable to close pipe. Print error and exit function. 171 throw std::runtime_error("pclose() failed!"); 172 } 173 std::string firstLine = result.substr(0, result.find('\n')); 174 standardOutput = firstLine; 175 // Get command exit status from return value 176 int exitStatus = WEXITSTATUS(returnValue); 177 178 // Read the standardError from tmpFile. 179 std::ifstream input(tmpFile.getName().c_str()); 180 std::string line; 181 182 if (std::getline(input, line)) 183 { 184 standardError = line; 185 } 186 187 return exitStatus; 188 } 189 190 int runToolForOutput(const std::string& configFileName, std::string& output, 191 std::string& error) 192 { 193 std::string command = getValidationToolCommand(configFileName); 194 return runToolForOutputWithCommand(command, output, error); 195 } 196 197 void expectFileValid(const std::string& configFileName) 198 { 199 std::string errorMessage; 200 std::string outputMessage; 201 EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 0); 202 EXPECT_EQ(errorMessage, ""); 203 EXPECT_EQ(outputMessage, ""); 204 } 205 206 void expectFileInvalid(const std::string& configFileName, 207 const std::string& expectedErrorMessage, 208 const std::string& expectedOutputMessage) 209 { 210 std::string errorMessage; 211 std::string outputMessage; 212 EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 1); 213 EXPECT_EQ(errorMessage, expectedErrorMessage); 214 EXPECT_EQ(outputMessage, expectedOutputMessage); 215 } 216 217 void writeDataToFile(const json configFileJson, std::string fileName) 218 { 219 std::string jsonData = configFileJson.dump(); 220 std::ofstream out(fileName); 221 out << jsonData; 222 out.close(); 223 } 224 225 void expectJsonValid(const json configFileJson) 226 { 227 std::string fileName; 228 TmpFile tmpFile; 229 fileName = tmpFile.getName(); 230 writeDataToFile(configFileJson, fileName); 231 232 EXPECT_FILE_VALID(fileName); 233 } 234 235 void expectJsonInvalid(const json configFileJson, 236 const std::string& expectedErrorMessage, 237 const std::string& expectedOutputMessage) 238 { 239 std::string fileName; 240 TmpFile tmpFile; 241 fileName = tmpFile.getName(); 242 writeDataToFile(configFileJson, fileName); 243 244 EXPECT_FILE_INVALID(fileName, expectedErrorMessage, expectedOutputMessage); 245 } 246 247 void expectCommandLineSyntax(const std::string& expectedErrorMessage, 248 const std::string& expectedOutputMessage, 249 std::string command, int status) 250 { 251 std::string errorMessage; 252 std::string outputMessage; 253 EXPECT_EQ(runToolForOutputWithCommand(command, outputMessage, errorMessage), 254 status); 255 EXPECT_EQ(errorMessage, expectedErrorMessage); 256 EXPECT_EQ(outputMessage, expectedOutputMessage); 257 } 258 259 TEST(ValidateRegulatorsConfigTest, And) 260 { 261 // Valid. 262 { 263 json configFile = validConfigFile; 264 json andAction = 265 R"( 266 { 267 "and": [ 268 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, 269 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } 270 ] 271 } 272 )"_json; 273 configFile["rules"][0]["actions"].push_back(andAction); 274 EXPECT_JSON_VALID(configFile); 275 } 276 277 // Invalid: actions property value is an empty array. 278 { 279 json configFile = validConfigFile; 280 json andAction = 281 R"( 282 { 283 "and": [] 284 } 285 )"_json; 286 configFile["rules"][0]["actions"].push_back(andAction); 287 EXPECT_JSON_INVALID(configFile, "Validation failed.", 288 "[] is too short"); 289 } 290 291 // Invalid: actions property has incorrect value data type. 292 { 293 json configFile = validConfigFile; 294 json andAction = 295 R"( 296 { 297 "and": true 298 } 299 )"_json; 300 configFile["rules"][0]["actions"].push_back(andAction); 301 EXPECT_JSON_INVALID(configFile, "Validation failed.", 302 "True is not of type 'array'"); 303 } 304 305 // Invalid: actions property value contains wrong element type 306 { 307 json configFile = validConfigFile; 308 json andAction = 309 R"( 310 { 311 "and": ["foo"] 312 } 313 )"_json; 314 configFile["rules"][0]["actions"].push_back(andAction); 315 EXPECT_JSON_INVALID(configFile, "Validation failed.", 316 "'foo' is not of type 'object'"); 317 } 318 } 319 TEST(ValidateRegulatorsConfigTest, Chassis) 320 { 321 // Valid: test chassis. 322 { 323 json configFile = validConfigFile; 324 EXPECT_JSON_VALID(configFile); 325 } 326 // Valid: test chassis with required properties. 327 { 328 json configFile = validConfigFile; 329 configFile["chassis"][0].erase("comments"); 330 configFile["chassis"][0].erase("devices"); 331 EXPECT_JSON_VALID(configFile); 332 } 333 // Invalid: test chassis with no number. 334 { 335 json configFile = validConfigFile; 336 configFile["chassis"][0].erase("number"); 337 EXPECT_JSON_INVALID(configFile, "Validation failed.", 338 "'number' is a required property"); 339 } 340 // Invalid: test chassis with property comments wrong type. 341 { 342 json configFile = validConfigFile; 343 configFile["chassis"][0]["comments"] = true; 344 EXPECT_JSON_INVALID(configFile, "Validation failed.", 345 "True is not of type 'array'"); 346 } 347 // Invalid: test chassis with property number wrong type. 348 { 349 json configFile = validConfigFile; 350 configFile["chassis"][0]["number"] = 1.3; 351 EXPECT_JSON_INVALID(configFile, "Validation failed.", 352 "1.3 is not of type 'integer'"); 353 } 354 // Invalid: test chassis with property devices wrong type. 355 { 356 json configFile = validConfigFile; 357 configFile["chassis"][0]["devices"] = true; 358 EXPECT_JSON_INVALID(configFile, "Validation failed.", 359 "True is not of type 'array'"); 360 } 361 // Invalid: test chassis with property comments empty array. 362 { 363 json configFile = validConfigFile; 364 configFile["chassis"][0]["comments"] = json::array(); 365 EXPECT_JSON_INVALID(configFile, "Validation failed.", 366 "[] is too short"); 367 } 368 // Invalid: test chassis with property devices empty array. 369 { 370 json configFile = validConfigFile; 371 configFile["chassis"][0]["devices"] = json::array(); 372 EXPECT_JSON_INVALID(configFile, "Validation failed.", 373 "[] is too short"); 374 } 375 // Invalid: test chassis with property number less than 1. 376 { 377 json configFile = validConfigFile; 378 configFile["chassis"][0]["number"] = 0; 379 EXPECT_JSON_INVALID(configFile, "Validation failed.", 380 "0 is less than the minimum of 1"); 381 } 382 } 383 TEST(ValidateRegulatorsConfigTest, ComparePresence) 384 { 385 json comparePresenceFile = validConfigFile; 386 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 387 "/system/chassis/motherboard/regulator2"; 388 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] = 389 true; 390 // Valid. 391 { 392 json configFile = comparePresenceFile; 393 EXPECT_JSON_VALID(configFile); 394 } 395 396 // Invalid: no FRU property. 397 { 398 json configFile = comparePresenceFile; 399 configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru"); 400 EXPECT_JSON_INVALID(configFile, "Validation failed.", 401 "'fru' is a required property"); 402 } 403 404 // Invalid: FRU property length is string less than 1. 405 { 406 json configFile = comparePresenceFile; 407 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = ""; 408 EXPECT_JSON_INVALID(configFile, "Validation failed.", 409 "'' is too short"); 410 } 411 412 // Invalid: no value property. 413 { 414 json configFile = comparePresenceFile; 415 configFile["rules"][0]["actions"][1]["compare_presence"].erase("value"); 416 EXPECT_JSON_INVALID(configFile, "Validation failed.", 417 "'value' is a required property"); 418 } 419 420 // Invalid: value property type is not boolean. 421 { 422 json configFile = comparePresenceFile; 423 configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1"; 424 EXPECT_JSON_INVALID(configFile, "Validation failed.", 425 "'1' is not of type 'boolean'"); 426 } 427 428 // Invalid: FRU property type is not string. 429 { 430 json configFile = comparePresenceFile; 431 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1; 432 EXPECT_JSON_INVALID(configFile, "Validation failed.", 433 "1 is not of type 'string'"); 434 } 435 } 436 TEST(ValidateRegulatorsConfigTest, CompareVpd) 437 { 438 json compareVpdFile = validConfigFile; 439 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 440 "/system/chassis/motherboard/regulator2"; 441 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN"; 442 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35"; 443 444 // Valid. 445 { 446 json configFile = compareVpdFile; 447 EXPECT_JSON_VALID(configFile); 448 } 449 450 // Invalid: no FRU property. 451 { 452 json configFile = compareVpdFile; 453 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru"); 454 EXPECT_JSON_INVALID(configFile, "Validation failed.", 455 "'fru' is a required property"); 456 } 457 458 // Invalid: no keyword property. 459 { 460 json configFile = compareVpdFile; 461 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword"); 462 EXPECT_JSON_INVALID(configFile, "Validation failed.", 463 "'keyword' is a required property"); 464 } 465 466 // Invalid: no value property. 467 { 468 json configFile = compareVpdFile; 469 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value"); 470 EXPECT_JSON_INVALID(configFile, "Validation failed.", 471 "'value' is a required property"); 472 } 473 474 // Invalid: property FRU wrong type. 475 { 476 json configFile = compareVpdFile; 477 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1; 478 EXPECT_JSON_INVALID(configFile, "Validation failed.", 479 "1 is not of type 'string'"); 480 } 481 482 // Invalid: property FRU is string less than 1. 483 { 484 json configFile = compareVpdFile; 485 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = ""; 486 EXPECT_JSON_INVALID(configFile, "Validation failed.", 487 "'' is too short"); 488 } 489 490 // Invalid: property keyword is not "CCIN", "Manufacturer", "Model", 491 // "PartNumber" 492 { 493 json configFile = compareVpdFile; 494 configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = 495 "Number"; 496 EXPECT_JSON_INVALID(configFile, "Validation failed.", 497 "'Number' is not one of ['CCIN', " 498 "'Manufacturer', 'Model', 'PartNumber']"); 499 } 500 501 // Invalid: property value wrong type. 502 { 503 json configFile = compareVpdFile; 504 configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1; 505 EXPECT_JSON_INVALID(configFile, "Validation failed.", 506 "1 is not of type 'string'"); 507 } 508 } 509 TEST(ValidateRegulatorsConfigTest, Configuration) 510 { 511 json configurationFile = validConfigFile; 512 configurationFile["chassis"][0]["devices"][0]["configuration"]["comments"] 513 [0] = "Set rail to 1.25V using standard rule"; 514 configurationFile["chassis"][0]["devices"][0]["configuration"]["volts"] = 515 1.25; 516 configurationFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] = 517 "set_voltage_rule"; 518 // Valid: test configuration with property rule_id and with no actions. 519 { 520 json configFile = configurationFile; 521 EXPECT_JSON_VALID(configFile); 522 } 523 // Valid: test configuration with property actions and with no rule_id. 524 { 525 json configFile = configurationFile; 526 configFile["chassis"][0]["devices"][0]["configuration"].erase( 527 "rule_id"); 528 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0] 529 ["compare_presence"]["fru"] = 530 "/system/chassis/motherboard/cpu3"; 531 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0] 532 ["compare_presence"]["value"] = true; 533 EXPECT_JSON_VALID(configFile); 534 } 535 // Valid: comments not specified (optional property). 536 { 537 json configFile = configurationFile; 538 configFile["chassis"][0]["devices"][0]["configuration"].erase( 539 "comments"); 540 EXPECT_JSON_VALID(configFile); 541 } 542 // Valid: volts not specified (optional property). 543 { 544 json configFile = configurationFile; 545 configFile["chassis"][0]["devices"][0]["configuration"].erase("volts"); 546 EXPECT_JSON_VALID(configFile); 547 } 548 // Valid: configuration is property of a rail (vs. a device). 549 { 550 json configFile = validConfigFile; 551 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] 552 ["comments"][0] = "Set rail to 1.25V using standard rule"; 553 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] 554 ["volts"] = 1.25; 555 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] 556 ["rule_id"] = "set_voltage_rule"; 557 EXPECT_JSON_VALID(configFile); 558 } 559 // Invalid: comments property has wrong data type (not an array). 560 { 561 json configFile = configurationFile; 562 configFile["chassis"][0]["devices"][0]["configuration"]["comments"] = 1; 563 EXPECT_JSON_INVALID(configFile, "Validation failed.", 564 "1 is not of type 'array'"); 565 } 566 // Invalid: test configuration with both actions and rule_id properties. 567 { 568 json configFile = configurationFile; 569 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0] 570 ["compare_presence"]["fru"] = 571 "/system/chassis/motherboard/cpu3"; 572 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0] 573 ["compare_presence"]["value"] = true; 574 EXPECT_JSON_INVALID( 575 configFile, "Validation failed.", 576 "{'actions': [{'compare_presence': {'fru': " 577 "'/system/chassis/motherboard/cpu3', 'value': True}}], 'comments': " 578 "['Set rail to 1.25V using standard rule'], 'rule_id': " 579 "'set_voltage_rule', 'volts': 1.25} is valid under each of " 580 "{'required': ['actions']}, {'required': ['rule_id']}"); 581 } 582 // Invalid: test configuration with no rule_id and actions. 583 { 584 json configFile = configurationFile; 585 configFile["chassis"][0]["devices"][0]["configuration"].erase( 586 "rule_id"); 587 EXPECT_JSON_INVALID(configFile, "Validation failed.", 588 "'rule_id' is a required property"); 589 } 590 // Invalid: test configuration with property volts wrong type. 591 { 592 json configFile = configurationFile; 593 configFile["chassis"][0]["devices"][0]["configuration"]["volts"] = true; 594 EXPECT_JSON_INVALID(configFile, "Validation failed.", 595 "True is not of type 'number'"); 596 } 597 // Invalid: test configuration with property rule_id wrong type. 598 { 599 json configFile = configurationFile; 600 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] = 601 true; 602 EXPECT_JSON_INVALID(configFile, "Validation failed.", 603 "True is not of type 'string'"); 604 } 605 // Invalid: test configuration with property actions wrong type. 606 { 607 json configFile = configurationFile; 608 configFile["chassis"][0]["devices"][0]["configuration"].erase( 609 "rule_id"); 610 configFile["chassis"][0]["devices"][0]["configuration"]["actions"] = 611 true; 612 EXPECT_JSON_INVALID(configFile, "Validation failed.", 613 "True is not of type 'array'"); 614 } 615 // Invalid: test configuration with property comments empty array. 616 { 617 json configFile = configurationFile; 618 configFile["chassis"][0]["devices"][0]["configuration"]["comments"] = 619 json::array(); 620 EXPECT_JSON_INVALID(configFile, "Validation failed.", 621 "[] is too short"); 622 } 623 // Invalid: test configuration with property rule_id wrong format. 624 { 625 json configFile = configurationFile; 626 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] = 627 "id!"; 628 EXPECT_JSON_INVALID(configFile, "Validation failed.", 629 "'id!' does not match '^[A-Za-z0-9_]+$'"); 630 } 631 // Invalid: test configuration with property actions empty array. 632 { 633 json configFile = configurationFile; 634 configFile["chassis"][0]["devices"][0]["configuration"].erase( 635 "rule_id"); 636 configFile["chassis"][0]["devices"][0]["configuration"]["actions"] = 637 json::array(); 638 EXPECT_JSON_INVALID(configFile, "Validation failed.", 639 "[] is too short"); 640 } 641 } 642 TEST(ValidateRegulatorsConfigTest, Device) 643 { 644 645 // Valid: test devices. 646 { 647 json configFile = validConfigFile; 648 EXPECT_JSON_VALID(configFile); 649 } 650 // Valid: test devices with required properties. 651 { 652 json configFile = validConfigFile; 653 configFile["chassis"][0]["devices"][0].erase("comments"); 654 configFile["chassis"][0]["devices"][0].erase("presence_detection"); 655 configFile["chassis"][0]["devices"][0].erase("configuration"); 656 configFile["chassis"][0]["devices"][0].erase("rails"); 657 EXPECT_JSON_VALID(configFile); 658 } 659 // Invalid: test devices with no id. 660 { 661 json configFile = validConfigFile; 662 configFile["chassis"][0]["devices"][0].erase("id"); 663 EXPECT_JSON_INVALID(configFile, "Validation failed.", 664 "'id' is a required property"); 665 } 666 // Invalid: test devices with no is_regulator. 667 { 668 json configFile = validConfigFile; 669 configFile["chassis"][0]["devices"][0].erase("is_regulator"); 670 EXPECT_JSON_INVALID(configFile, "Validation failed.", 671 "'is_regulator' is a required property"); 672 } 673 // Invalid: test devices with no fru. 674 { 675 json configFile = validConfigFile; 676 configFile["chassis"][0]["devices"][0].erase("fru"); 677 EXPECT_JSON_INVALID(configFile, "Validation failed.", 678 "'fru' is a required property"); 679 } 680 // Invalid: test devices with no i2c_interface. 681 { 682 json configFile = validConfigFile; 683 configFile["chassis"][0]["devices"][0].erase("i2c_interface"); 684 EXPECT_JSON_INVALID(configFile, "Validation failed.", 685 "'i2c_interface' is a required property"); 686 } 687 // Invalid: test devices with property comments wrong type. 688 { 689 json configFile = validConfigFile; 690 configFile["chassis"][0]["devices"][0]["comments"] = true; 691 EXPECT_JSON_INVALID(configFile, "Validation failed.", 692 "True is not of type 'array'"); 693 } 694 // Invalid: test devices with property id wrong type. 695 { 696 json configFile = validConfigFile; 697 configFile["chassis"][0]["devices"][0]["id"] = true; 698 EXPECT_JSON_INVALID(configFile, "Validation failed.", 699 "True is not of type 'string'"); 700 } 701 // Invalid: test devices with property is_regulator wrong type. 702 { 703 json configFile = validConfigFile; 704 configFile["chassis"][0]["devices"][0]["is_regulator"] = 1; 705 EXPECT_JSON_INVALID(configFile, "Validation failed.", 706 "1 is not of type 'boolean'"); 707 } 708 // Invalid: test devices with property fru wrong type. 709 { 710 json configFile = validConfigFile; 711 configFile["chassis"][0]["devices"][0]["fru"] = true; 712 EXPECT_JSON_INVALID(configFile, "Validation failed.", 713 "True is not of type 'string'"); 714 } 715 // Invalid: test devices with property i2c_interface wrong type. 716 { 717 json configFile = validConfigFile; 718 configFile["chassis"][0]["devices"][0]["i2c_interface"] = true; 719 EXPECT_JSON_INVALID(configFile, "Validation failed.", 720 "True is not of type 'object'"); 721 } 722 // Invalid: test devices with property presence_detection wrong 723 // type. 724 { 725 json configFile = validConfigFile; 726 configFile["chassis"][0]["devices"][0]["presence_detection"] = true; 727 EXPECT_JSON_INVALID(configFile, "Validation failed.", 728 "True is not of type 'object'"); 729 } 730 // Invalid: test devices with property configuration wrong type. 731 { 732 json configFile = validConfigFile; 733 configFile["chassis"][0]["devices"][0]["configuration"] = true; 734 EXPECT_JSON_INVALID(configFile, "Validation failed.", 735 "True is not of type 'object'"); 736 } 737 // Invalid: test devices with property rails wrong type. 738 { 739 json configFile = validConfigFile; 740 configFile["chassis"][0]["devices"][0]["rails"] = true; 741 EXPECT_JSON_INVALID(configFile, "Validation failed.", 742 "True is not of type 'array'"); 743 } 744 // Invalid: test devices with property comments empty array. 745 { 746 json configFile = validConfigFile; 747 configFile["chassis"][0]["devices"][0]["comments"] = json::array(); 748 EXPECT_JSON_INVALID(configFile, "Validation failed.", 749 "[] is too short"); 750 } 751 // Invalid: test devices with property fru length less than 1. 752 { 753 json configFile = validConfigFile; 754 configFile["chassis"][0]["devices"][0]["fru"] = ""; 755 EXPECT_JSON_INVALID(configFile, "Validation failed.", 756 "'' is too short"); 757 } 758 // Invalid: test devices with property id wrong format. 759 { 760 json configFile = validConfigFile; 761 configFile["chassis"][0]["devices"][0]["id"] = "id#"; 762 EXPECT_JSON_INVALID(configFile, "Validation failed.", 763 "'id#' does not match '^[A-Za-z0-9_]+$'"); 764 } 765 // Invalid: test devices with property rails empty array. 766 { 767 json configFile = validConfigFile; 768 configFile["chassis"][0]["devices"][0]["rails"] = json::array(); 769 EXPECT_JSON_INVALID(configFile, "Validation failed.", 770 "[] is too short"); 771 } 772 } 773 TEST(ValidateRegulatorsConfigTest, I2CCompareBit) 774 { 775 json i2cCompareBitFile = validConfigFile; 776 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 777 "0xA0"; 778 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 779 3; 780 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1; 781 // Valid: test rule actions i2c_compare_bit. 782 { 783 json configFile = i2cCompareBitFile; 784 EXPECT_JSON_VALID(configFile); 785 } 786 // Invalid: test i2c_compare_bit with no register. 787 { 788 json configFile = i2cCompareBitFile; 789 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase( 790 "register"); 791 EXPECT_JSON_INVALID(configFile, "Validation failed.", 792 "'register' is a required property"); 793 } 794 // Invalid: test i2c_compare_bit with no position. 795 { 796 json configFile = i2cCompareBitFile; 797 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase( 798 "position"); 799 EXPECT_JSON_INVALID(configFile, "Validation failed.", 800 "'position' is a required property"); 801 } 802 // Invalid: test i2c_compare_bit with no value. 803 { 804 json configFile = i2cCompareBitFile; 805 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value"); 806 EXPECT_JSON_INVALID(configFile, "Validation failed.", 807 "'value' is a required property"); 808 } 809 // Invalid: test i2c_compare_bit with register wrong type. 810 { 811 json configFile = i2cCompareBitFile; 812 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1; 813 EXPECT_JSON_INVALID(configFile, "Validation failed.", 814 "1 is not of type 'string'"); 815 } 816 // Invalid: test i2c_compare_bit with register wrong format. 817 { 818 json configFile = i2cCompareBitFile; 819 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 820 "0xA00"; 821 EXPECT_JSON_INVALID(configFile, "Validation failed.", 822 "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'"); 823 } 824 // Invalid: test i2c_compare_bit with position wrong type. 825 { 826 json configFile = i2cCompareBitFile; 827 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 828 3.1; 829 EXPECT_JSON_INVALID(configFile, "Validation failed.", 830 "3.1 is not of type 'integer'"); 831 } 832 // Invalid: test i2c_compare_bit with position greater than 7. 833 { 834 json configFile = i2cCompareBitFile; 835 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8; 836 EXPECT_JSON_INVALID(configFile, "Validation failed.", 837 "8 is greater than the maximum of 7"); 838 } 839 // Invalid: test i2c_compare_bit with position less than 0. 840 { 841 json configFile = i2cCompareBitFile; 842 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 843 -1; 844 EXPECT_JSON_INVALID(configFile, "Validation failed.", 845 "-1 is less than the minimum of 0"); 846 } 847 // Invalid: test i2c_compare_bit with value wrong type. 848 { 849 json configFile = i2cCompareBitFile; 850 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1"; 851 EXPECT_JSON_INVALID(configFile, "Validation failed.", 852 "'1' is not of type 'integer'"); 853 } 854 // Invalid: test i2c_compare_bit with value greater than 1. 855 { 856 json configFile = i2cCompareBitFile; 857 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2; 858 EXPECT_JSON_INVALID(configFile, "Validation failed.", 859 "2 is greater than the maximum of 1"); 860 } 861 // Invalid: test i2c_compare_bit with value less than 0. 862 { 863 json configFile = i2cCompareBitFile; 864 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1; 865 EXPECT_JSON_INVALID(configFile, "Validation failed.", 866 "-1 is less than the minimum of 0"); 867 } 868 } 869 TEST(ValidateRegulatorsConfigTest, I2CCompareByte) 870 { 871 json i2cCompareByteFile = validConfigFile; 872 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"] 873 ["register"] = "0x82"; 874 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 875 "0x40"; 876 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 877 "0x7F"; 878 // Valid: test i2c_compare_byte with all properties. 879 { 880 json configFile = i2cCompareByteFile; 881 EXPECT_JSON_VALID(configFile); 882 } 883 // Valid: test i2c_compare_byte with all required properties. 884 { 885 json configFile = i2cCompareByteFile; 886 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask"); 887 EXPECT_JSON_VALID(configFile); 888 } 889 // Invalid: test i2c_compare_byte with no register. 890 { 891 json configFile = i2cCompareByteFile; 892 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase( 893 "register"); 894 EXPECT_JSON_INVALID(configFile, "Validation failed.", 895 "'register' is a required property"); 896 } 897 // Invalid: test i2c_compare_byte with no value. 898 { 899 json configFile = i2cCompareByteFile; 900 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value"); 901 EXPECT_JSON_INVALID(configFile, "Validation failed.", 902 "'value' is a required property"); 903 } 904 // Invalid: test i2c_compare_byte with property register wrong type. 905 { 906 json configFile = i2cCompareByteFile; 907 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 908 1; 909 EXPECT_JSON_INVALID(configFile, "Validation failed.", 910 "1 is not of type 'string'"); 911 } 912 // Invalid: test i2c_compare_byte with property value wrong type. 913 { 914 json configFile = i2cCompareByteFile; 915 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1; 916 EXPECT_JSON_INVALID(configFile, "Validation failed.", 917 "1 is not of type 'string'"); 918 } 919 // Invalid: test i2c_compare_byte with property mask wrong type. 920 { 921 json configFile = i2cCompareByteFile; 922 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1; 923 EXPECT_JSON_INVALID(configFile, "Validation failed.", 924 "1 is not of type 'string'"); 925 } 926 // Invalid: test i2c_compare_byte with property register more than 2 hex 927 // digits. 928 { 929 json configFile = i2cCompareByteFile; 930 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 931 "0x820"; 932 EXPECT_JSON_INVALID(configFile, "Validation failed.", 933 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 934 } 935 // Invalid: test i2c_compare_byte with property value more than 2 hex 936 // digits. 937 { 938 json configFile = i2cCompareByteFile; 939 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 940 "0x820"; 941 EXPECT_JSON_INVALID(configFile, "Validation failed.", 942 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 943 } 944 // Invalid: test i2c_compare_byte with property mask more than 2 hex digits. 945 { 946 json configFile = i2cCompareByteFile; 947 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 948 "0x820"; 949 EXPECT_JSON_INVALID(configFile, "Validation failed.", 950 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 951 } 952 // Invalid: test i2c_compare_byte with property register less than 2 hex 953 // digits. 954 { 955 json configFile = i2cCompareByteFile; 956 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 957 "0x8"; 958 EXPECT_JSON_INVALID(configFile, "Validation failed.", 959 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 960 } 961 // Invalid: test i2c_compare_byte with property value less than 2 hex 962 // digits. 963 { 964 json configFile = i2cCompareByteFile; 965 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 966 "0x8"; 967 EXPECT_JSON_INVALID(configFile, "Validation failed.", 968 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 969 } 970 // Invalid: test i2c_compare_byte with property mask less than 2 hex digits. 971 { 972 json configFile = i2cCompareByteFile; 973 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 974 "0x8"; 975 EXPECT_JSON_INVALID(configFile, "Validation failed.", 976 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 977 } 978 // Invalid: test i2c_compare_byte with property register no leading prefix. 979 { 980 json configFile = i2cCompareByteFile; 981 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 982 "82"; 983 EXPECT_JSON_INVALID(configFile, "Validation failed.", 984 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 985 } 986 // Invalid: test i2c_compare_byte with property value no leading prefix. 987 { 988 json configFile = i2cCompareByteFile; 989 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 990 "82"; 991 EXPECT_JSON_INVALID(configFile, "Validation failed.", 992 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 993 } 994 // Invalid: test i2c_compare_byte with property mask no leading prefix. 995 { 996 json configFile = i2cCompareByteFile; 997 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82"; 998 EXPECT_JSON_INVALID(configFile, "Validation failed.", 999 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1000 } 1001 // Invalid: test i2c_compare_byte with property register invalid hex digit. 1002 { 1003 json configFile = i2cCompareByteFile; 1004 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 1005 "0xG1"; 1006 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1007 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1008 } 1009 // Invalid: test i2c_compare_byte with property value invalid hex digit. 1010 { 1011 json configFile = i2cCompareByteFile; 1012 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1013 "0xG1"; 1014 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1015 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1016 } 1017 // Invalid: test i2c_compare_byte with property mask invalid hex digit. 1018 { 1019 json configFile = i2cCompareByteFile; 1020 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1021 "0xG1"; 1022 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1023 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1024 } 1025 } 1026 TEST(ValidateRegulatorsConfigTest, I2CCompareBytes) 1027 { 1028 json i2cCompareBytesFile = validConfigFile; 1029 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"] 1030 ["register"] = "0x82"; 1031 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"] 1032 ["values"] = {"0x02", "0x73"}; 1033 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"] 1034 ["masks"] = {"0x7F", "0x7F"}; 1035 // Valid: test i2c_compare_bytes. 1036 { 1037 json configFile = i2cCompareBytesFile; 1038 EXPECT_JSON_VALID(configFile); 1039 } 1040 // Valid: test i2c_compare_bytes with all required properties. 1041 { 1042 json configFile = i2cCompareBytesFile; 1043 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase( 1044 "masks"); 1045 EXPECT_JSON_VALID(configFile); 1046 } 1047 // Invalid: test i2c_compare_bytes with no register. 1048 { 1049 json configFile = i2cCompareBytesFile; 1050 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase( 1051 "register"); 1052 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1053 "'register' is a required property"); 1054 } 1055 // Invalid: test i2c_compare_bytes with no values. 1056 { 1057 json configFile = i2cCompareBytesFile; 1058 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase( 1059 "values"); 1060 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1061 "'values' is a required property"); 1062 } 1063 // Invalid: test i2c_compare_bytes with property values as empty array. 1064 { 1065 json configFile = i2cCompareBytesFile; 1066 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1067 json::array(); 1068 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1069 "[] is too short"); 1070 } 1071 // Invalid: test i2c_compare_bytes with property masks as empty array. 1072 { 1073 json configFile = i2cCompareBytesFile; 1074 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1075 json::array(); 1076 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1077 "[] is too short"); 1078 } 1079 // Invalid: test i2c_compare_bytes with property register wrong type. 1080 { 1081 json configFile = i2cCompareBytesFile; 1082 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 1083 1; 1084 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1085 "1 is not of type 'string'"); 1086 } 1087 // Invalid: test i2c_compare_bytes with property values wrong type. 1088 { 1089 json configFile = i2cCompareBytesFile; 1090 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1; 1091 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1092 "1 is not of type 'array'"); 1093 } 1094 // Invalid: test i2c_compare_bytes with property masks wrong type. 1095 { 1096 json configFile = i2cCompareBytesFile; 1097 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1; 1098 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1099 "1 is not of type 'array'"); 1100 } 1101 // Invalid: test i2c_compare_bytes with property register more than 2 hex 1102 // digits. 1103 { 1104 json configFile = i2cCompareBytesFile; 1105 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 1106 "0x820"; 1107 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1108 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 1109 } 1110 // Invalid: test i2c_compare_bytes with property values more than 2 hex 1111 // digits. 1112 { 1113 json configFile = i2cCompareBytesFile; 1114 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 1115 "0x820"; 1116 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1117 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 1118 } 1119 // Invalid: test i2c_compare_bytes with property masks more than 2 hex 1120 // digits. 1121 { 1122 json configFile = i2cCompareBytesFile; 1123 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 1124 "0x820"; 1125 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1126 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 1127 } 1128 // Invalid: test i2c_compare_bytes with property register less than 2 hex 1129 // digits. 1130 { 1131 json configFile = i2cCompareBytesFile; 1132 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 1133 "0x8"; 1134 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1135 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 1136 } 1137 // Invalid: test i2c_compare_bytes with property values less than 2 hex 1138 // digits. 1139 { 1140 json configFile = i2cCompareBytesFile; 1141 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 1142 "0x8"; 1143 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1144 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 1145 } 1146 // Invalid: test i2c_compare_bytes with property masks less than 2 hex 1147 // digits. 1148 { 1149 json configFile = i2cCompareBytesFile; 1150 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 1151 "0x8"; 1152 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1153 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 1154 } 1155 // Invalid: test i2c_compare_bytes with property register no leading prefix. 1156 { 1157 json configFile = i2cCompareBytesFile; 1158 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 1159 "82"; 1160 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1161 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1162 } 1163 // Invalid: test i2c_compare_bytes with property values no leading prefix. 1164 { 1165 json configFile = i2cCompareBytesFile; 1166 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 1167 "82"; 1168 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1169 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1170 } 1171 // Invalid: test i2c_compare_bytes with property masks no leading prefix. 1172 { 1173 json configFile = i2cCompareBytesFile; 1174 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 1175 "82"; 1176 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1177 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1178 } 1179 // Invalid: test i2c_compare_bytes with property register invalid hex digit. 1180 { 1181 json configFile = i2cCompareBytesFile; 1182 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 1183 "0xG1"; 1184 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1185 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1186 } 1187 // Invalid: test i2c_compare_bytes with property values invalid hex digit. 1188 { 1189 json configFile = i2cCompareBytesFile; 1190 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 1191 "0xG1"; 1192 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1193 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1194 } 1195 // Invalid: test i2c_compare_bytes with property masks invalid hex digit. 1196 { 1197 json configFile = i2cCompareBytesFile; 1198 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 1199 "0xG1"; 1200 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1201 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1202 } 1203 } 1204 TEST(ValidateRegulatorsConfigTest, I2CInterface) 1205 { 1206 // Valid: test i2c_interface. 1207 { 1208 json configFile = validConfigFile; 1209 EXPECT_JSON_VALID(configFile); 1210 } 1211 // Invalid: testi2c_interface with no bus. 1212 { 1213 json configFile = validConfigFile; 1214 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase("bus"); 1215 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1216 "'bus' is a required property"); 1217 } 1218 // Invalid: test i2c_interface with no address. 1219 { 1220 json configFile = validConfigFile; 1221 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase( 1222 "address"); 1223 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1224 "'address' is a required property"); 1225 } 1226 // Invalid: test i2c_interface with property bus wrong type. 1227 { 1228 json configFile = validConfigFile; 1229 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = true; 1230 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1231 "True is not of type 'integer'"); 1232 } 1233 // Invalid: test i2c_interface with property address wrong 1234 // type. 1235 { 1236 json configFile = validConfigFile; 1237 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] = 1238 true; 1239 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1240 "True is not of type 'string'"); 1241 } 1242 // Invalid: test i2c_interface with property bus less than 1243 // 0. 1244 { 1245 json configFile = validConfigFile; 1246 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = -1; 1247 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1248 "-1 is less than the minimum of 0"); 1249 } 1250 // Invalid: test i2c_interface with property address wrong 1251 // format. 1252 { 1253 json configFile = validConfigFile; 1254 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] = 1255 "0x700"; 1256 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1257 "'0x700' does not match '^0x[0-9A-Fa-f]{2}$'"); 1258 } 1259 } 1260 TEST(ValidateRegulatorsConfigTest, I2CWriteBit) 1261 { 1262 json i2cWriteBitFile = validConfigFile; 1263 i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] = 1264 "0xA0"; 1265 i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3; 1266 i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 1; 1267 // Valid: test rule actions i2c_write_bit. 1268 { 1269 json configFile = i2cWriteBitFile; 1270 EXPECT_JSON_VALID(configFile); 1271 } 1272 // Invalid: test i2c_write_bit with no register. 1273 { 1274 json configFile = i2cWriteBitFile; 1275 configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("register"); 1276 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1277 "'register' is a required property"); 1278 } 1279 // Invalid: test i2c_write_bit with no position. 1280 { 1281 json configFile = i2cWriteBitFile; 1282 configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("position"); 1283 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1284 "'position' is a required property"); 1285 } 1286 // Invalid: test i2c_write_bit with no value. 1287 { 1288 json configFile = i2cWriteBitFile; 1289 configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("value"); 1290 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1291 "'value' is a required property"); 1292 } 1293 // Invalid: test i2c_write_bit with register wrong type. 1294 { 1295 json configFile = i2cWriteBitFile; 1296 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] = 1; 1297 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1298 "1 is not of type 'string'"); 1299 } 1300 // Invalid: test i2c_write_bit with register wrong format. 1301 { 1302 json configFile = i2cWriteBitFile; 1303 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] = 1304 "0xA00"; 1305 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1306 "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'"); 1307 } 1308 // Invalid: test i2c_write_bit with position wrong type. 1309 { 1310 json configFile = i2cWriteBitFile; 1311 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3.1; 1312 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1313 "3.1 is not of type 'integer'"); 1314 } 1315 // Invalid: test i2c_write_bit with position greater than 7. 1316 { 1317 json configFile = i2cWriteBitFile; 1318 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 8; 1319 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1320 "8 is greater than the maximum of 7"); 1321 } 1322 // Invalid: test i2c_write_bit with position less than 0. 1323 { 1324 json configFile = i2cWriteBitFile; 1325 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = -1; 1326 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1327 "-1 is less than the minimum of 0"); 1328 } 1329 // Invalid: test i2c_write_bit with value wrong type. 1330 { 1331 json configFile = i2cWriteBitFile; 1332 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = "1"; 1333 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1334 "'1' is not of type 'integer'"); 1335 } 1336 // Invalid: test i2c_write_bit with value greater than 1. 1337 { 1338 json configFile = i2cWriteBitFile; 1339 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 2; 1340 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1341 "2 is greater than the maximum of 1"); 1342 } 1343 // Invalid: test i2c_write_bit with value less than 0. 1344 { 1345 json configFile = i2cWriteBitFile; 1346 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = -1; 1347 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1348 "-1 is less than the minimum of 0"); 1349 } 1350 } 1351 TEST(ValidateRegulatorsConfigTest, I2CWriteByte) 1352 { 1353 json i2cWriteByteFile = validConfigFile; 1354 i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1355 "0x82"; 1356 i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = 1357 "0x40"; 1358 i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = 1359 "0x7F"; 1360 // Valid: test i2c_write_byte with all properties. 1361 { 1362 json configFile = i2cWriteByteFile; 1363 EXPECT_JSON_VALID(configFile); 1364 } 1365 // Valid: test i2c_write_byte with all required properties. 1366 { 1367 json configFile = i2cWriteByteFile; 1368 configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("mask"); 1369 EXPECT_JSON_VALID(configFile); 1370 } 1371 // Invalid: test i2c_write_byte with no register. 1372 { 1373 json configFile = i2cWriteByteFile; 1374 configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase( 1375 "register"); 1376 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1377 "'register' is a required property"); 1378 } 1379 // Invalid: test i2c_write_byte with no value. 1380 { 1381 json configFile = i2cWriteByteFile; 1382 configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("value"); 1383 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1384 "'value' is a required property"); 1385 } 1386 // Invalid: test i2c_write_byte with property register wrong type. 1387 { 1388 json configFile = i2cWriteByteFile; 1389 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1; 1390 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1391 "1 is not of type 'string'"); 1392 } 1393 // Invalid: test i2c_write_byte with property value wrong type. 1394 { 1395 json configFile = i2cWriteByteFile; 1396 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = 1; 1397 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1398 "1 is not of type 'string'"); 1399 } 1400 // Invalid: test i2c_write_byte with property mask wrong type. 1401 { 1402 json configFile = i2cWriteByteFile; 1403 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = 1; 1404 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1405 "1 is not of type 'string'"); 1406 } 1407 // Invalid: test i2c_write_byte with property register more than 2 hex 1408 // digits. 1409 { 1410 json configFile = i2cWriteByteFile; 1411 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1412 "0x820"; 1413 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1414 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 1415 } 1416 // Invalid: test i2c_write_byte with property value more than 2 hex 1417 // digits. 1418 { 1419 json configFile = i2cWriteByteFile; 1420 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = 1421 "0x820"; 1422 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1423 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 1424 } 1425 // Invalid: test i2c_write_byte with property mask more than 2 hex digits. 1426 { 1427 json configFile = i2cWriteByteFile; 1428 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = 1429 "0x820"; 1430 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1431 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 1432 } 1433 // Invalid: test i2c_write_byte with property register less than 2 hex 1434 // digits. 1435 { 1436 json configFile = i2cWriteByteFile; 1437 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1438 "0x8"; 1439 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1440 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 1441 } 1442 // Invalid: test i2c_write_byte with property value less than 2 hex 1443 // digits. 1444 { 1445 json configFile = i2cWriteByteFile; 1446 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "0x8"; 1447 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1448 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 1449 } 1450 // Invalid: test i2c_write_byte with property mask less than 2 hex digits. 1451 { 1452 json configFile = i2cWriteByteFile; 1453 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0x8"; 1454 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1455 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 1456 } 1457 // Invalid: test i2c_write_byte with property register no leading prefix. 1458 { 1459 json configFile = i2cWriteByteFile; 1460 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1461 "82"; 1462 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1463 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1464 } 1465 // Invalid: test i2c_write_byte with property value no leading prefix. 1466 { 1467 json configFile = i2cWriteByteFile; 1468 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "82"; 1469 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1470 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1471 } 1472 // Invalid: test i2c_write_byte with property mask no leading prefix. 1473 { 1474 json configFile = i2cWriteByteFile; 1475 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "82"; 1476 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1477 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1478 } 1479 // Invalid: test i2c_write_byte with property register invalid hex digit. 1480 { 1481 json configFile = i2cWriteByteFile; 1482 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1483 "0xG1"; 1484 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1485 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1486 } 1487 // Invalid: test i2c_write_byte with property value invalid hex digit. 1488 { 1489 json configFile = i2cWriteByteFile; 1490 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = 1491 "0xG1"; 1492 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1493 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1494 } 1495 // Invalid: test i2c_write_byte with property mask invalid hex digit. 1496 { 1497 json configFile = i2cWriteByteFile; 1498 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0xG1"; 1499 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1500 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1501 } 1502 } 1503 TEST(ValidateRegulatorsConfigTest, I2CWriteBytes) 1504 { 1505 json i2cWriteBytesFile = validConfigFile; 1506 i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1507 "0x82"; 1508 i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = { 1509 "0x02", "0x73"}; 1510 i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = { 1511 "0x7F", "0x7F"}; 1512 // Valid: test i2c_write_bytes. 1513 { 1514 json configFile = i2cWriteBytesFile; 1515 EXPECT_JSON_VALID(configFile); 1516 } 1517 // Valid: test i2c_write_bytes with all required properties. 1518 { 1519 json configFile = i2cWriteBytesFile; 1520 configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("masks"); 1521 EXPECT_JSON_VALID(configFile); 1522 } 1523 // Invalid: test i2c_write_bytes with no register. 1524 { 1525 json configFile = i2cWriteBytesFile; 1526 configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase( 1527 "register"); 1528 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1529 "'register' is a required property"); 1530 } 1531 // Invalid: test i2c_write_bytes with no values. 1532 { 1533 json configFile = i2cWriteBytesFile; 1534 configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("values"); 1535 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1536 "'values' is a required property"); 1537 } 1538 // Invalid: test i2c_write_bytes with property values as empty array. 1539 { 1540 json configFile = i2cWriteBytesFile; 1541 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = 1542 json::array(); 1543 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1544 "[] is too short"); 1545 } 1546 // Invalid: test i2c_write_bytes with property masks as empty array. 1547 { 1548 json configFile = i2cWriteBytesFile; 1549 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = 1550 json::array(); 1551 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1552 "[] is too short"); 1553 } 1554 // Invalid: test i2c_write_bytes with property register wrong type. 1555 { 1556 json configFile = i2cWriteBytesFile; 1557 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1; 1558 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1559 "1 is not of type 'string'"); 1560 } 1561 // Invalid: test i2c_write_bytes with property values wrong type. 1562 { 1563 json configFile = i2cWriteBytesFile; 1564 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = 1; 1565 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1566 "1 is not of type 'array'"); 1567 } 1568 // Invalid: test i2c_write_bytes with property masks wrong type. 1569 { 1570 json configFile = i2cWriteBytesFile; 1571 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = 1; 1572 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1573 "1 is not of type 'array'"); 1574 } 1575 // Invalid: test i2c_write_bytes with property register more than 2 hex 1576 // digits. 1577 { 1578 json configFile = i2cWriteBytesFile; 1579 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1580 "0x820"; 1581 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1582 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 1583 } 1584 // Invalid: test i2c_write_bytes with property values more than 2 hex 1585 // digits. 1586 { 1587 json configFile = i2cWriteBytesFile; 1588 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] = 1589 "0x820"; 1590 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1591 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 1592 } 1593 // Invalid: test i2c_write_bytes with property masks more than 2 hex 1594 // digits. 1595 { 1596 json configFile = i2cWriteBytesFile; 1597 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] = 1598 "0x820"; 1599 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1600 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'"); 1601 } 1602 // Invalid: test i2c_write_bytes with property register less than 2 hex 1603 // digits. 1604 { 1605 json configFile = i2cWriteBytesFile; 1606 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1607 "0x8"; 1608 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1609 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 1610 } 1611 // Invalid: test i2c_write_bytes with property values less than 2 hex 1612 // digits. 1613 { 1614 json configFile = i2cWriteBytesFile; 1615 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] = 1616 "0x8"; 1617 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1618 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 1619 } 1620 // Invalid: test i2c_write_bytes with property masks less than 2 hex 1621 // digits. 1622 { 1623 json configFile = i2cWriteBytesFile; 1624 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] = 1625 "0x8"; 1626 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1627 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'"); 1628 } 1629 // Invalid: test i2c_write_bytes with property register no leading prefix. 1630 { 1631 json configFile = i2cWriteBytesFile; 1632 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1633 "82"; 1634 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1635 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1636 } 1637 // Invalid: test i2c_write_bytes with property values no leading prefix. 1638 { 1639 json configFile = i2cWriteBytesFile; 1640 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] = 1641 "82"; 1642 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1643 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1644 } 1645 // Invalid: test i2c_write_bytes with property masks no leading prefix. 1646 { 1647 json configFile = i2cWriteBytesFile; 1648 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] = 1649 "82"; 1650 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1651 "'82' does not match '^0x[0-9A-Fa-f]{2}$'"); 1652 } 1653 // Invalid: test i2c_write_bytes with property register invalid hex digit. 1654 { 1655 json configFile = i2cWriteBytesFile; 1656 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1657 "0xG1"; 1658 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1659 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1660 } 1661 // Invalid: test i2c_write_bytes with property values invalid hex digit. 1662 { 1663 json configFile = i2cWriteBytesFile; 1664 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] = 1665 "0xG1"; 1666 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1667 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1668 } 1669 // Invalid: test i2c_write_bytes with property masks invalid hex digit. 1670 { 1671 json configFile = i2cWriteBytesFile; 1672 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] = 1673 "0xG1"; 1674 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1675 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'"); 1676 } 1677 } 1678 TEST(ValidateRegulatorsConfigTest, If) 1679 { 1680 json ifFile = validConfigFile; 1681 ifFile["rules"][2]["actions"][0]["if"]["condition"]["run_rule"] = 1682 "set_voltage_rule"; 1683 ifFile["rules"][2]["actions"][0]["if"]["then"][0]["run_rule"] = 1684 "read_sensors_rule"; 1685 ifFile["rules"][2]["actions"][0]["if"]["else"][0]["run_rule"] = 1686 "read_sensors_rule"; 1687 ifFile["rules"][2]["id"] = "rule_if"; 1688 // Valid: test if. 1689 { 1690 json configFile = ifFile; 1691 EXPECT_JSON_VALID(configFile); 1692 } 1693 // Valid: test if with required properties. 1694 { 1695 json configFile = ifFile; 1696 configFile["rules"][2]["actions"][0]["if"].erase("else"); 1697 EXPECT_JSON_VALID(configFile); 1698 } 1699 // Invalid: test if with no property condition. 1700 { 1701 json configFile = ifFile; 1702 configFile["rules"][2]["actions"][0]["if"].erase("condition"); 1703 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1704 "'condition' is a required property"); 1705 } 1706 // Invalid: test if with no property then. 1707 { 1708 json configFile = ifFile; 1709 configFile["rules"][2]["actions"][0]["if"].erase("then"); 1710 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1711 "'then' is a required property"); 1712 } 1713 // Invalid: test if with property then empty array. 1714 { 1715 json configFile = ifFile; 1716 configFile["rules"][2]["actions"][0]["if"]["then"] = json::array(); 1717 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1718 "[] is too short"); 1719 } 1720 // Invalid: test if with property else empty array. 1721 { 1722 json configFile = ifFile; 1723 configFile["rules"][2]["actions"][0]["if"]["else"] = json::array(); 1724 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1725 "[] is too short"); 1726 } 1727 // Invalid: test if with property condition wrong type. 1728 { 1729 json configFile = ifFile; 1730 configFile["rules"][2]["actions"][0]["if"]["condition"] = 1; 1731 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1732 "1 is not of type 'object'"); 1733 } 1734 // Invalid: test if with property then wrong type. 1735 { 1736 json configFile = ifFile; 1737 configFile["rules"][2]["actions"][0]["if"]["then"] = 1; 1738 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1739 "1 is not of type 'array'"); 1740 } 1741 // Invalid: test if with property else wrong type. 1742 { 1743 json configFile = ifFile; 1744 configFile["rules"][2]["actions"][0]["if"]["else"] = 1; 1745 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1746 "1 is not of type 'array'"); 1747 } 1748 } 1749 TEST(ValidateRegulatorsConfigTest, Not) 1750 { 1751 json notFile = validConfigFile; 1752 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] = 1753 "0xA0"; 1754 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] = 1755 "0xFF"; 1756 // Valid: test not. 1757 { 1758 json configFile = notFile; 1759 EXPECT_JSON_VALID(configFile); 1760 } 1761 // Invalid: test not with wrong type. 1762 { 1763 json configFile = notFile; 1764 configFile["rules"][0]["actions"][1]["not"] = 1; 1765 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1766 "1 is not of type 'object'"); 1767 } 1768 } 1769 TEST(ValidateRegulatorsConfigTest, Or) 1770 { 1771 json orFile = validConfigFile; 1772 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] = 1773 "0xA0"; 1774 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] = 1775 "0x00"; 1776 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] = 1777 "0xA1"; 1778 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] = 1779 "0x00"; 1780 // Valid: test or. 1781 { 1782 json configFile = orFile; 1783 EXPECT_JSON_VALID(configFile); 1784 } 1785 // Invalid: test or with empty array. 1786 { 1787 json configFile = orFile; 1788 configFile["rules"][0]["actions"][1]["or"] = json::array(); 1789 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1790 "[] is too short"); 1791 } 1792 // Invalid: test or with wrong type. 1793 { 1794 json configFile = orFile; 1795 configFile["rules"][0]["actions"][1]["or"] = 1; 1796 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1797 "1 is not of type 'array'"); 1798 } 1799 } 1800 TEST(ValidateRegulatorsConfigTest, PmbusReadSensor) 1801 { 1802 json pmbusReadSensorFile = validConfigFile; 1803 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1804 "vout"; 1805 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1806 ["command"] = "0x8B"; 1807 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1808 ["format"] = "linear_16"; 1809 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1810 ["exponent"] = -8; 1811 // Valid: test pmbus_read_sensor. 1812 { 1813 json configFile = pmbusReadSensorFile; 1814 EXPECT_JSON_VALID(configFile); 1815 } 1816 // Valid: test pmbus_read_sensor with required properties. 1817 { 1818 json configFile = pmbusReadSensorFile; 1819 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1820 "exponent"); 1821 EXPECT_JSON_VALID(configFile); 1822 } 1823 // Invalid: test pmbus_read_sensor with no type. 1824 { 1825 json configFile = pmbusReadSensorFile; 1826 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type"); 1827 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1828 "'type' is a required property"); 1829 } 1830 // Invalid: test pmbus_read_sensor with no command. 1831 { 1832 json configFile = pmbusReadSensorFile; 1833 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1834 "command"); 1835 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1836 "'command' is a required property"); 1837 } 1838 // Invalid: test pmbus_read_sensor with no format. 1839 { 1840 json configFile = pmbusReadSensorFile; 1841 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1842 "format"); 1843 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1844 "'format' is a required property"); 1845 } 1846 // Invalid: test pmbus_read_sensor with property type wrong type. 1847 { 1848 json configFile = pmbusReadSensorFile; 1849 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1850 true; 1851 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1852 "True is not of type 'string'"); 1853 } 1854 // Invalid: test pmbus_read_sensor with property command wrong type. 1855 { 1856 json configFile = pmbusReadSensorFile; 1857 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1858 true; 1859 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1860 "True is not of type 'string'"); 1861 } 1862 // Invalid: test pmbus_read_sensor with property format wrong type. 1863 { 1864 json configFile = pmbusReadSensorFile; 1865 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1866 true; 1867 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1868 "True is not of type 'string'"); 1869 } 1870 // Invalid: test pmbus_read_sensor with property exponent wrong type. 1871 { 1872 json configFile = pmbusReadSensorFile; 1873 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] = 1874 true; 1875 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1876 "True is not of type 'integer'"); 1877 } 1878 // Invalid: test pmbus_read_sensor with property type wrong format. 1879 { 1880 json configFile = pmbusReadSensorFile; 1881 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1882 "foo"; 1883 EXPECT_JSON_INVALID( 1884 configFile, "Validation failed.", 1885 "'foo' is not one of ['iout', 'iout_peak', 'iout_valley', " 1886 "'pout', 'temperature', 'temperature_peak', 'vout', " 1887 "'vout_peak', 'vout_valley']"); 1888 } 1889 // Invalid: test pmbus_read_sensor with property command wrong format. 1890 { 1891 json configFile = pmbusReadSensorFile; 1892 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1893 "0x8B0"; 1894 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1895 "'0x8B0' does not match '^0x[0-9a-fA-F]{2}$'"); 1896 } 1897 // Invalid: test pmbus_read_sensor with property format wrong format. 1898 { 1899 json configFile = pmbusReadSensorFile; 1900 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1901 "foo"; 1902 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1903 "'foo' is not one of ['linear_11', 'linear_16']"); 1904 } 1905 } 1906 TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand) 1907 { 1908 json pmbusWriteVoutCommandFile = validConfigFile; 1909 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1910 ["pmbus_write_vout_command"]["volts"] = 1.03; 1911 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1912 ["pmbus_write_vout_command"]["format"] = "linear"; 1913 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1914 ["pmbus_write_vout_command"]["exponent"] = -8; 1915 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1916 ["pmbus_write_vout_command"]["is_verified"] = true; 1917 // Valid: test pmbus_write_vout_command. 1918 { 1919 json configFile = pmbusWriteVoutCommandFile; 1920 EXPECT_JSON_VALID(configFile); 1921 } 1922 // Valid: test pmbus_write_vout_command with required properties. 1923 { 1924 json configFile = pmbusWriteVoutCommandFile; 1925 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1926 "volts"); 1927 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1928 "exponent"); 1929 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1930 "is_verified"); 1931 EXPECT_JSON_VALID(configFile); 1932 } 1933 // Invalid: test pmbus_write_vout_command with no format. 1934 { 1935 json configFile = pmbusWriteVoutCommandFile; 1936 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1937 "format"); 1938 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1939 "'format' is a required property"); 1940 } 1941 // Invalid: test pmbus_write_vout_command with property volts wrong type. 1942 { 1943 json configFile = pmbusWriteVoutCommandFile; 1944 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1945 ["volts"] = true; 1946 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1947 "True is not of type 'number'"); 1948 } 1949 // Invalid: test pmbus_write_vout_command with property format wrong type. 1950 { 1951 json configFile = pmbusWriteVoutCommandFile; 1952 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1953 ["format"] = true; 1954 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1955 "True is not of type 'string'"); 1956 } 1957 // Invalid: test pmbus_write_vout_command with property exponent wrong type. 1958 { 1959 json configFile = pmbusWriteVoutCommandFile; 1960 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1961 ["exponent"] = 1.3; 1962 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1963 "1.3 is not of type 'integer'"); 1964 } 1965 // Invalid: test pmbus_write_vout_command with property is_verified wrong 1966 // type. 1967 { 1968 json configFile = pmbusWriteVoutCommandFile; 1969 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1970 ["is_verified"] = 1; 1971 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1972 "1 is not of type 'boolean'"); 1973 } 1974 // Invalid: test pmbus_write_vout_command with property format wrong format. 1975 { 1976 json configFile = pmbusWriteVoutCommandFile; 1977 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1978 ["format"] = "foo"; 1979 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1980 "'foo' is not one of ['linear']"); 1981 } 1982 } 1983 TEST(ValidateRegulatorsConfigTest, PresenceDetection) 1984 { 1985 json presenceDetectionFile = validConfigFile; 1986 presenceDetectionFile 1987 ["chassis"][0]["devices"][0]["presence_detection"]["comments"][0] = 1988 "Regulator is only present on the FooBar backplane"; 1989 presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"] 1990 ["rule_id"] = "set_voltage_rule"; 1991 // Valid: test presence_detection with only property rule_id. 1992 { 1993 json configFile = presenceDetectionFile; 1994 EXPECT_JSON_VALID(configFile); 1995 } 1996 // Valid: test presence_detection with only property actions. 1997 { 1998 json configFile = presenceDetectionFile; 1999 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2000 "rule_id"); 2001 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"] 2002 [0]["compare_presence"]["fru"] = 2003 "/system/chassis/motherboard/cpu3"; 2004 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"] 2005 [0]["compare_presence"]["value"] = true; 2006 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2007 "comments"); 2008 EXPECT_JSON_VALID(configFile); 2009 } 2010 // Invalid: test presence_detection with both property rule_id and actions. 2011 { 2012 json configFile = presenceDetectionFile; 2013 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"] 2014 [0]["compare_presence"]["fru"] = 2015 "/system/chassis/motherboard/cpu3"; 2016 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"] 2017 [0]["compare_presence"]["value"] = true; 2018 EXPECT_JSON_INVALID( 2019 configFile, "Validation failed.", 2020 "{'actions': [{'compare_presence': {'fru': " 2021 "'/system/chassis/motherboard/cpu3', 'value': True}}], 'comments': " 2022 "['Regulator is only present on the FooBar backplane'], 'rule_id': " 2023 "'set_voltage_rule'} is valid under each of {'required': " 2024 "['actions']}, {'required': ['rule_id']}"); 2025 } 2026 // Invalid: test presence_detection with no rule_id and actions. 2027 { 2028 json configFile = presenceDetectionFile; 2029 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2030 "rule_id"); 2031 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2032 "'rule_id' is a required property"); 2033 } 2034 // Invalid: test presence_detection with property comments wrong type. 2035 { 2036 json configFile = presenceDetectionFile; 2037 configFile["chassis"][0]["devices"][0]["presence_detection"] 2038 ["comments"] = true; 2039 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2040 "True is not of type 'array'"); 2041 } 2042 // Invalid: test presence_detection with property rule_id wrong type. 2043 { 2044 json configFile = presenceDetectionFile; 2045 configFile["chassis"][0]["devices"][0]["presence_detection"] 2046 ["rule_id"] = true; 2047 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2048 "True is not of type 'string'"); 2049 } 2050 // Invalid: test presence_detection with property actions wrong type. 2051 { 2052 json configFile = presenceDetectionFile; 2053 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2054 "rule_id"); 2055 configFile["chassis"][0]["devices"][0]["presence_detection"] 2056 ["actions"] = true; 2057 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2058 "True is not of type 'array'"); 2059 } 2060 // Invalid: test presence_detection with property rule_id wrong format. 2061 { 2062 json configFile = presenceDetectionFile; 2063 configFile["chassis"][0]["devices"][0]["presence_detection"] 2064 ["rule_id"] = "id@"; 2065 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2066 "'id@' does not match '^[A-Za-z0-9_]+$'"); 2067 } 2068 // Invalid: test presence_detection with property comments empty array. 2069 { 2070 json configFile = presenceDetectionFile; 2071 configFile["chassis"][0]["devices"][0]["presence_detection"] 2072 ["comments"] = json::array(); 2073 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2074 "[] is too short"); 2075 } 2076 // Invalid: test presence_detection with property actions empty array. 2077 { 2078 json configFile = presenceDetectionFile; 2079 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2080 "rule_id"); 2081 configFile["chassis"][0]["devices"][0]["presence_detection"] 2082 ["actions"] = json::array(); 2083 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2084 "[] is too short"); 2085 } 2086 } 2087 TEST(ValidateRegulatorsConfigTest, Rail) 2088 { 2089 // Valid: test rail. 2090 { 2091 json configFile = validConfigFile; 2092 EXPECT_JSON_VALID(configFile); 2093 } 2094 // Valid: test rail with required properties. 2095 { 2096 json configFile = validConfigFile; 2097 configFile["chassis"][0]["devices"][0]["rails"][0].erase("comments"); 2098 configFile["chassis"][0]["devices"][0]["rails"][0].erase( 2099 "configuration"); 2100 configFile["chassis"][0]["devices"][0]["rails"][0].erase( 2101 "sensor_monitoring"); 2102 EXPECT_JSON_VALID(configFile); 2103 } 2104 // Invalid: test rail with no id. 2105 { 2106 json configFile = validConfigFile; 2107 configFile["chassis"][0]["devices"][0]["rails"][0].erase("id"); 2108 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2109 "'id' is a required property"); 2110 } 2111 // Invalid: test rail with comments wrong type. 2112 { 2113 json configFile = validConfigFile; 2114 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = true; 2115 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2116 "True is not of type 'array'"); 2117 } 2118 // Invalid: test rail with id wrong type. 2119 { 2120 json configFile = validConfigFile; 2121 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = true; 2122 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2123 "True is not of type 'string'"); 2124 } 2125 // Invalid: test rail with configuration wrong type. 2126 { 2127 json configFile = validConfigFile; 2128 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] = 2129 true; 2130 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2131 "True is not of type 'object'"); 2132 } 2133 // Invalid: test rail with sensor_monitoring wrong type. 2134 { 2135 json configFile = validConfigFile; 2136 configFile["chassis"][0]["devices"][0]["rails"][0] 2137 ["sensor_monitoring"] = true; 2138 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2139 "True is not of type 'object'"); 2140 } 2141 // Invalid: test rail with comments empty array. 2142 { 2143 json configFile = validConfigFile; 2144 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = 2145 json::array(); 2146 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2147 "[] is too short"); 2148 } 2149 // Invalid: test rail with id wrong format. 2150 { 2151 json configFile = validConfigFile; 2152 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = "id~"; 2153 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2154 "'id~' does not match '^[A-Za-z0-9_]+$'"); 2155 } 2156 } 2157 TEST(ValidateRegulatorsConfigTest, Rule) 2158 { 2159 // valid test comments property, id property, 2160 // action property specified. 2161 { 2162 json configFile = validConfigFile; 2163 EXPECT_JSON_VALID(configFile); 2164 } 2165 2166 // valid test rule with no comments 2167 { 2168 json configFile = validConfigFile; 2169 configFile["rules"][0].erase("comments"); 2170 EXPECT_JSON_VALID(configFile); 2171 } 2172 2173 // invalid test comments property has invalid value type 2174 { 2175 json configFile = validConfigFile; 2176 configFile["rules"][0]["comments"] = {1}; 2177 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2178 "1 is not of type 'string'"); 2179 } 2180 2181 // invalid test rule with no ID 2182 { 2183 json configFile = validConfigFile; 2184 configFile["rules"][0].erase("id"); 2185 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2186 "'id' is a required property"); 2187 } 2188 2189 // invalid test id property has invalid value type (not string) 2190 { 2191 json configFile = validConfigFile; 2192 configFile["rules"][0]["id"] = true; 2193 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2194 "True is not of type 'string'"); 2195 } 2196 2197 // invalid test id property has invalid value 2198 { 2199 json configFile = validConfigFile; 2200 configFile["rules"][0]["id"] = "foo%"; 2201 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2202 "'foo%' does not match '^[A-Za-z0-9_]+$'"); 2203 } 2204 2205 // invalid test rule with no actions property 2206 { 2207 json configFile = validConfigFile; 2208 configFile["rules"][0].erase("actions"); 2209 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2210 "'actions' is a required property"); 2211 } 2212 2213 // valid test rule with multiple actions 2214 { 2215 json configFile = validConfigFile; 2216 configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule"; 2217 EXPECT_JSON_VALID(configFile); 2218 } 2219 2220 // invalid test actions property has invalid value type (not an array) 2221 { 2222 json configFile = validConfigFile; 2223 configFile["rules"][0]["actions"] = 1; 2224 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2225 "1 is not of type 'array'"); 2226 } 2227 2228 // invalid test actions property has invalid value of action 2229 { 2230 json configFile = validConfigFile; 2231 configFile["rules"][0]["actions"][0] = "foo"; 2232 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2233 "'foo' is not of type 'object'"); 2234 } 2235 2236 // invalid test actions property has empty array 2237 { 2238 json configFile = validConfigFile; 2239 configFile["rules"][0]["actions"] = json::array(); 2240 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2241 "[] is too short"); 2242 } 2243 } 2244 TEST(ValidateRegulatorsConfigTest, RunRule) 2245 { 2246 json runRuleFile = validConfigFile; 2247 runRuleFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule"; 2248 // Valid: test run_rule. 2249 { 2250 json configFile = runRuleFile; 2251 EXPECT_JSON_VALID(configFile); 2252 } 2253 // Invalid: test run_rule wrong type. 2254 { 2255 json configFile = runRuleFile; 2256 configFile["rules"][0]["actions"][1]["run_rule"] = true; 2257 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2258 "True is not of type 'string'"); 2259 } 2260 // Invalid: test run_rule wrong format. 2261 { 2262 json configFile = runRuleFile; 2263 configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%"; 2264 EXPECT_JSON_INVALID( 2265 configFile, "Validation failed.", 2266 "'set_voltage_rule%' does not match '^[A-Za-z0-9_]+$'"); 2267 } 2268 } 2269 TEST(ValidateRegulatorsConfigTest, SensorMonitoring) 2270 { 2271 // Valid: test rails sensor_monitoring with only property rule id. 2272 { 2273 json configFile = validConfigFile; 2274 EXPECT_JSON_VALID(configFile); 2275 } 2276 // Valid: test rails sensor_monitoring with only property actions. 2277 { 2278 json configFile = validConfigFile; 2279 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2280 .erase("rule_id"); 2281 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2282 ["actions"][0]["compare_presence"]["fru"] = 2283 "/system/chassis/motherboard/cpu3"; 2284 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2285 ["actions"][0]["compare_presence"]["value"] = true; 2286 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2287 ["comments"][0] = "comments"; 2288 EXPECT_JSON_VALID(configFile); 2289 } 2290 // Invalid: test rails sensor_monitoring with both property rule_id and 2291 // actions. 2292 { 2293 json configFile = validConfigFile; 2294 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2295 ["actions"][0]["compare_presence"]["fru"] = 2296 "/system/chassis/motherboard/cpu3"; 2297 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2298 ["actions"][0]["compare_presence"]["value"] = true; 2299 EXPECT_JSON_INVALID( 2300 configFile, "Validation failed.", 2301 "{'actions': [{'compare_presence': {'fru': " 2302 "'/system/chassis/motherboard/cpu3', 'value': True}}], 'rule_id': " 2303 "'read_sensors_rule'} is valid under each of {'required': " 2304 "['actions']}, {'required': ['rule_id']}"); 2305 } 2306 // Invalid: test rails sensor_monitoring with no rule_id and actions. 2307 { 2308 json configFile = validConfigFile; 2309 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2310 .erase("rule_id"); 2311 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2312 "'rule_id' is a required property"); 2313 } 2314 // Invalid: test rails sensor_monitoring with property comments wrong type. 2315 { 2316 json configFile = validConfigFile; 2317 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2318 ["comments"] = true; 2319 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2320 "True is not of type 'array'"); 2321 } 2322 // Invalid: test rails sensor_monitoring with property rule_id wrong type. 2323 { 2324 json configFile = validConfigFile; 2325 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2326 ["rule_id"] = true; 2327 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2328 "True is not of type 'string'"); 2329 } 2330 // Invalid: test rails sensor_monitoring with property actions wrong type. 2331 { 2332 json configFile = validConfigFile; 2333 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2334 .erase("rule_id"); 2335 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2336 ["actions"] = true; 2337 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2338 "True is not of type 'array'"); 2339 } 2340 // Invalid: test rails sensor_monitoring with property rule_id wrong format. 2341 { 2342 json configFile = validConfigFile; 2343 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2344 ["rule_id"] = "id@"; 2345 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2346 "'id@' does not match '^[A-Za-z0-9_]+$'"); 2347 } 2348 // Invalid: test rails sensor_monitoring with property comments empty array. 2349 { 2350 json configFile = validConfigFile; 2351 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2352 ["comments"] = json::array(); 2353 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2354 "[] is too short"); 2355 } 2356 // Invalid: test rails sensor_monitoring with property actions empty array. 2357 { 2358 json configFile = validConfigFile; 2359 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2360 .erase("rule_id"); 2361 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2362 ["actions"] = json::array(); 2363 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2364 "[] is too short"); 2365 } 2366 } 2367 TEST(ValidateRegulatorsConfigTest, SetDevice) 2368 { 2369 json setDeviceFile = validConfigFile; 2370 setDeviceFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator"; 2371 // Valid: test set_device. 2372 { 2373 json configFile = setDeviceFile; 2374 EXPECT_JSON_VALID(configFile); 2375 } 2376 // Invalid: test set_device wrong type. 2377 { 2378 json configFile = setDeviceFile; 2379 configFile["rules"][0]["actions"][1]["set_device"] = true; 2380 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2381 "True is not of type 'string'"); 2382 } 2383 // Invalid: test set_device wrong format. 2384 { 2385 json configFile = setDeviceFile; 2386 configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%"; 2387 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2388 "'io_expander2%' does not match '^[A-Za-z0-9_]+$'"); 2389 } 2390 } 2391 TEST(ValidateRegulatorsConfigTest, DuplicateRuleID) 2392 { 2393 // Invalid: test duplicate ID in rule. 2394 { 2395 json configFile = validConfigFile; 2396 configFile["rules"][2]["id"] = "set_voltage_rule"; 2397 configFile["rules"][2]["actions"][0]["pmbus_write_vout_command"] 2398 ["format"] = "linear"; 2399 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rule ID.", ""); 2400 } 2401 } 2402 TEST(ValidateRegulatorsConfigTest, DuplicateChassisNumber) 2403 { 2404 // Invalid: test duplicate number in chassis. 2405 { 2406 json configFile = validConfigFile; 2407 configFile["chassis"][1]["number"] = 1; 2408 EXPECT_JSON_INVALID(configFile, "Error: Duplicate chassis number.", ""); 2409 } 2410 } 2411 TEST(ValidateRegulatorsConfigTest, DuplicateDeviceID) 2412 { 2413 // Invalid: test duplicate ID in device. 2414 { 2415 json configFile = validConfigFile; 2416 configFile["chassis"][0]["devices"][1]["id"] = "vdd_regulator"; 2417 configFile["chassis"][0]["devices"][1]["is_regulator"] = true; 2418 configFile["chassis"][0]["devices"][1]["fru"] = 2419 "/system/chassis/motherboard/regulator1"; 2420 configFile["chassis"][0]["devices"][1]["i2c_interface"]["bus"] = 2; 2421 configFile["chassis"][0]["devices"][1]["i2c_interface"]["address"] = 2422 "0x71"; 2423 EXPECT_JSON_INVALID(configFile, "Error: Duplicate device ID.", ""); 2424 } 2425 } 2426 TEST(ValidateRegulatorsConfigTest, DuplicateRailID) 2427 { 2428 // Invalid: test duplicate ID in rail. 2429 { 2430 json configFile = validConfigFile; 2431 configFile["chassis"][0]["devices"][0]["rails"][1]["id"] = "vdd"; 2432 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rail ID.", ""); 2433 } 2434 } 2435 TEST(ValidateRegulatorsConfigTest, InfiniteLoops) 2436 { 2437 // Invalid: test run_rule with infinite loop (rules run each other). 2438 { 2439 json configFile = validConfigFile; 2440 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2"; 2441 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2442 configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule1"; 2443 configFile["rules"][3]["id"] = "set_voltage_rule2"; 2444 EXPECT_JSON_INVALID(configFile, 2445 "Infinite loop caused by run_rule actions.", ""); 2446 } 2447 // Invalid: test run_rule with infinite loop (rule runs itself). 2448 { 2449 json configFile = validConfigFile; 2450 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule1"; 2451 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2452 EXPECT_JSON_INVALID(configFile, 2453 "Infinite loop caused by run_rule actions.", ""); 2454 } 2455 // Invalid: test run_rule with infinite loop (indirect loop). 2456 { 2457 json configFile = validConfigFile; 2458 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2"; 2459 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2460 configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule3"; 2461 configFile["rules"][3]["id"] = "set_voltage_rule2"; 2462 configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule1"; 2463 configFile["rules"][4]["id"] = "set_voltage_rule3"; 2464 EXPECT_JSON_INVALID(configFile, 2465 "Infinite loop caused by run_rule actions.", ""); 2466 } 2467 } 2468 TEST(ValidateRegulatorsConfigTest, RunRuleValueExists) 2469 { 2470 // Invalid: test run_rule actions specify a rule ID that does not exist. 2471 { 2472 json configFile = validConfigFile; 2473 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2"; 2474 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2475 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", ""); 2476 } 2477 } 2478 TEST(ValidateRegulatorsConfigTest, SetDeviceValueExists) 2479 { 2480 // Invalid: test set_device actions specify a device ID that does not exist. 2481 { 2482 json configFile = validConfigFile; 2483 configFile["rules"][2]["actions"][0]["set_device"] = "vdd_regulator2"; 2484 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2485 EXPECT_JSON_INVALID(configFile, "Error: Device ID does not exist.", ""); 2486 } 2487 } 2488 TEST(ValidateRegulatorsConfigTest, RuleIDExists) 2489 { 2490 // Invalid: test rule_id property in configuration specifies a rule ID that 2491 // does not exist. 2492 { 2493 json configFile = validConfigFile; 2494 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] = 2495 "set_voltage_rule2"; 2496 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", ""); 2497 } 2498 // Invalid: test rule_id property in presence_detection specifies a rule ID 2499 // that does not exist. 2500 { 2501 json configFile = validConfigFile; 2502 configFile["chassis"][0]["devices"][0]["presence_detection"] 2503 ["rule_id"] = "set_voltage_rule2"; 2504 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", ""); 2505 } 2506 // Invalid: test rule_id property in sensor_monitoring specifies a rule ID 2507 // that does not exist. 2508 { 2509 json configFile = validConfigFile; 2510 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2511 ["rule_id"] = "set_voltage_rule2"; 2512 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", ""); 2513 } 2514 } 2515 TEST(ValidateRegulatorsConfigTest, NumberOfElementsInMasks) 2516 { 2517 // Invalid: test number of elements in masks not equal to number in values 2518 // in i2c_compare_bytes. 2519 { 2520 json configFile = validConfigFile; 2521 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 2522 "0x82"; 2523 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = { 2524 "0x02", "0x73"}; 2525 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = { 2526 "0x7F"}; 2527 EXPECT_JSON_INVALID(configFile, 2528 "Error: Invalid i2c_compare_bytes action.", ""); 2529 } 2530 // Invalid: test number of elements in masks not equal to number in values 2531 // in i2c_write_bytes. 2532 { 2533 json configFile = validConfigFile; 2534 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 2535 "0x82"; 2536 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = { 2537 "0x02", "0x73"}; 2538 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = { 2539 "0x7F"}; 2540 EXPECT_JSON_INVALID(configFile, 2541 "Error: Invalid i2c_write_bytes action.", ""); 2542 } 2543 } 2544 TEST(ValidateRegulatorsConfigTest, CommandLineSyntax) 2545 { 2546 std::string validateTool = 2547 " ../phosphor-regulators/tools/validate-regulators-config.py "; 2548 std::string schema = " -s "; 2549 std::string schemaFile = 2550 " ../phosphor-regulators/schema/config_schema.json "; 2551 std::string configuration = " -c "; 2552 std::string command; 2553 std::string errorMessage; 2554 std::string outputMessage; 2555 std::string outputMessageHelp = 2556 "usage: validate-regulators-config.py [-h] [-s SCHEMA_FILE]"; 2557 int valid = 0; 2558 2559 std::string fileName; 2560 TmpFile tmpFile; 2561 fileName = tmpFile.getName(); 2562 writeDataToFile(validConfigFile, fileName); 2563 // Valid: -s specified 2564 { 2565 command = validateTool + "-s " + schemaFile + configuration + fileName; 2566 expectCommandLineSyntax(errorMessage, outputMessage, command, valid); 2567 } 2568 // Valid: --schema-file specified 2569 { 2570 command = validateTool + "--schema-file " + schemaFile + configuration + 2571 fileName; 2572 expectCommandLineSyntax(errorMessage, outputMessage, command, valid); 2573 } 2574 // Valid: -c specified 2575 { 2576 command = validateTool + schema + schemaFile + "-c " + fileName; 2577 expectCommandLineSyntax(errorMessage, outputMessage, command, valid); 2578 } 2579 // Valid: --configuration-file specified 2580 { 2581 command = validateTool + schema + schemaFile + "--configuration-file " + 2582 fileName; 2583 expectCommandLineSyntax(errorMessage, outputMessage, command, valid); 2584 } 2585 // Valid: -h specified 2586 { 2587 command = validateTool + "-h "; 2588 expectCommandLineSyntax(errorMessage, outputMessageHelp, command, 2589 valid); 2590 } 2591 // Valid: --help specified 2592 { 2593 command = validateTool + "--help "; 2594 expectCommandLineSyntax(errorMessage, outputMessageHelp, command, 2595 valid); 2596 } 2597 // Invalid: -c/--configuration-file not specified 2598 { 2599 command = validateTool + schema + schemaFile; 2600 expectCommandLineSyntax("Error: Configuration file is required.", 2601 outputMessageHelp, command, 1); 2602 } 2603 // Invalid: -s/--schema-file not specified 2604 { 2605 command = validateTool + configuration + fileName; 2606 expectCommandLineSyntax("Error: Schema file is required.", 2607 outputMessageHelp, command, 1); 2608 } 2609 // Invalid: -s specified more than once 2610 { 2611 command = 2612 validateTool + "-s -s " + schemaFile + configuration + fileName; 2613 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2614 } 2615 // Invalid: -c specified more than once 2616 { 2617 command = validateTool + schema + schemaFile + "-c -c " + fileName; 2618 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2619 } 2620 // Invalid: No file name specified after -c 2621 { 2622 command = validateTool + schema + schemaFile + configuration; 2623 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2624 } 2625 // Invalid: No file name specified after -s 2626 { 2627 command = validateTool + schema + configuration + fileName; 2628 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2629 } 2630 // Invalid: File specified after -c does not exist 2631 { 2632 command = validateTool + schema + schemaFile + configuration + 2633 "../notExistFile"; 2634 expectCommandLineSyntax( 2635 "Traceback (most recent call last):", outputMessage, command, 1); 2636 } 2637 // Invalid: File specified after -s does not exist 2638 { 2639 command = validateTool + schema + "../notExistFile " + configuration + 2640 fileName; 2641 expectCommandLineSyntax( 2642 "Traceback (most recent call last):", outputMessage, command, 1); 2643 } 2644 // Invalid: File specified after -s is not right data format 2645 { 2646 std::string wrongFormatFileName; 2647 TmpFile wrongFormatFile; 2648 wrongFormatFileName = wrongFormatFile.getName(); 2649 std::ofstream out(wrongFormatFileName); 2650 out << "foo"; 2651 out.close(); 2652 command = validateTool + schema + wrongFormatFileName + configuration + 2653 fileName; 2654 expectCommandLineSyntax( 2655 "Traceback (most recent call last):", outputMessage, command, 1); 2656 } 2657 // Invalid: File specified after -c is not readable 2658 { 2659 std::string notReadableFileName; 2660 TmpFile notReadableFile; 2661 notReadableFileName = notReadableFile.getName(); 2662 writeDataToFile(validConfigFile, notReadableFileName); 2663 command = validateTool + schema + schemaFile + configuration + 2664 notReadableFileName; 2665 chmod(notReadableFileName.c_str(), 0222); 2666 expectCommandLineSyntax( 2667 "Traceback (most recent call last):", outputMessage, command, 1); 2668 } 2669 // Invalid: File specified after -s is not readable 2670 { 2671 std::string notReadableFileName; 2672 TmpFile notReadableFile; 2673 notReadableFileName = notReadableFile.getName(); 2674 writeDataToFile(validConfigFile, notReadableFileName); 2675 command = validateTool + schema + notReadableFileName + configuration + 2676 fileName; 2677 chmod(notReadableFileName.c_str(), 0222); 2678 expectCommandLineSyntax( 2679 "Traceback (most recent call last):", outputMessage, command, 1); 2680 } 2681 // Invalid: Unexpected parameter specified (like -g) 2682 { 2683 command = validateTool + schema + schemaFile + configuration + 2684 fileName + " -g"; 2685 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2686 } 2687 } 2688