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 u'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 "u'foo' is not of type u'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 "u'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 u'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 u'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 u'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 "u'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 "u'' 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 "u'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 "u'1' is not of type u'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 u'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 "u'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 "u'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 "u'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 u'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 "u'' 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 "u'Number' is not one of [u'CCIN', " 498 "u'Manufacturer', u'Model', u'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 u'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 u'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 "{u'volts': 1.25, u'comments': [u'Set rail to 1.25V using standard " 577 "rule'], u'actions': [{u'compare_presence': {u'value': True, " 578 "u'fru': u'/system/chassis/motherboard/cpu3'}}], u'rule_id': " 579 "u'set_voltage_rule'} is valid under each of {u'required': " 580 "[u'actions']}, {u'required': [u'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 "u'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 u'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 u'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 u'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 "u'id!' does not match u'^[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 "u'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 "u'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 "u'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 "u'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 u'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 u'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 u'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 u'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 u'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 u'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 u'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 u'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 "u'' 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 "u'id#' does not match u'^[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 "u'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 "u'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 "u'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 u'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 "u'0xA00' does not match u'^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 u'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 "u'1' is not of type u'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 "u'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 "u'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 u'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 u'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 u'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 "u'0x820' does not match u'^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 "u'0x820' does not match u'^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 "u'0x820' does not match u'^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 "u'0x8' does not match u'^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 "u'0x8' does not match u'^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 "u'0x8' does not match u'^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 "u'82' does not match u'^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 "u'82' does not match u'^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 "u'82' does not match u'^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 "u'0xG1' does not match u'^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 "u'0xG1' does not match u'^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 "u'0xG1' does not match u'^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 "u'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 "u'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 u'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 u'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 u'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 "u'0x820' does not match u'^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 "u'0x820' does not match u'^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 "u'0x820' does not match u'^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 "u'0x8' does not match u'^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 "u'0x8' does not match u'^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 "u'0x8' does not match u'^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 "u'82' does not match u'^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 "u'82' does not match u'^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 "u'82' does not match u'^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 "u'0xG1' does not match u'^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 "u'0xG1' does not match u'^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 "u'0xG1' does not match u'^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 "u'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 "u'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 u'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 u'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 "u'0x700' does not match u'^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 "u'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 "u'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 "u'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 u'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 "u'0xA00' does not match u'^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 u'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 "u'1' is not of type u'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 "u'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 "u'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 u'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 u'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 u'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 "u'0x820' does not match u'^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 "u'0x820' does not match u'^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 "u'0x820' does not match u'^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 "u'0x8' does not match u'^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 "u'0x8' does not match u'^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 "u'0x8' does not match u'^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 "u'82' does not match u'^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 "u'82' does not match u'^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 "u'82' does not match u'^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 "u'0xG1' does not match u'^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 "u'0xG1' does not match u'^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 "u'0xG1' does not match u'^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 "u'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 "u'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 u'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 u'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 u'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 "u'0x820' does not match u'^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 "u'0x820' does not match u'^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 "u'0x820' does not match u'^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 "u'0x8' does not match u'^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 "u'0x8' does not match u'^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 "u'0x8' does not match u'^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 "u'82' does not match u'^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 "u'82' does not match u'^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 "u'82' does not match u'^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 "u'0xG1' does not match u'^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 "u'0xG1' does not match u'^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 "u'0xG1' does not match u'^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 "u'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 "u'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 u'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 u'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 u'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 u'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 u'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 "u'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 "u'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 "u'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( 1852 configFile, "Validation failed.", 1853 "True is not one of [u'iout', u'iout_peak', u'iout_valley', " 1854 "u'pout', u'temperature', u'temperature_peak', u'vout', " 1855 "u'vout_peak', u'vout_valley']"); 1856 } 1857 // Invalid: test pmbus_read_sensor with property command wrong type. 1858 { 1859 json configFile = pmbusReadSensorFile; 1860 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1861 true; 1862 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1863 "True is not of type u'string'"); 1864 } 1865 // Invalid: test pmbus_read_sensor with property format wrong type. 1866 { 1867 json configFile = pmbusReadSensorFile; 1868 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1869 true; 1870 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1871 "True is not one of [u'linear_11', u'linear_16']"); 1872 } 1873 // Invalid: test pmbus_read_sensor with property exponent wrong type. 1874 { 1875 json configFile = pmbusReadSensorFile; 1876 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] = 1877 true; 1878 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1879 "True is not of type u'integer'"); 1880 } 1881 // Invalid: test pmbus_read_sensor with property type wrong format. 1882 { 1883 json configFile = pmbusReadSensorFile; 1884 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1885 "foo"; 1886 EXPECT_JSON_INVALID( 1887 configFile, "Validation failed.", 1888 "u'foo' is not one of [u'iout', u'iout_peak', u'iout_valley', " 1889 "u'pout', u'temperature', u'temperature_peak', u'vout', " 1890 "u'vout_peak', u'vout_valley']"); 1891 } 1892 // Invalid: test pmbus_read_sensor with property command wrong format. 1893 { 1894 json configFile = pmbusReadSensorFile; 1895 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1896 "0x8B0"; 1897 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1898 "u'0x8B0' does not match u'^0x[0-9a-fA-F]{2}$'"); 1899 } 1900 // Invalid: test pmbus_read_sensor with property format wrong format. 1901 { 1902 json configFile = pmbusReadSensorFile; 1903 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1904 "foo"; 1905 EXPECT_JSON_INVALID( 1906 configFile, "Validation failed.", 1907 "u'foo' is not one of [u'linear_11', u'linear_16']"); 1908 } 1909 } 1910 TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand) 1911 { 1912 json pmbusWriteVoutCommandFile = validConfigFile; 1913 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1914 ["pmbus_write_vout_command"]["volts"] = 1.03; 1915 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1916 ["pmbus_write_vout_command"]["format"] = "linear"; 1917 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1918 ["pmbus_write_vout_command"]["exponent"] = -8; 1919 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1920 ["pmbus_write_vout_command"]["is_verified"] = true; 1921 // Valid: test pmbus_write_vout_command. 1922 { 1923 json configFile = pmbusWriteVoutCommandFile; 1924 EXPECT_JSON_VALID(configFile); 1925 } 1926 // Valid: test pmbus_write_vout_command with required properties. 1927 { 1928 json configFile = pmbusWriteVoutCommandFile; 1929 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1930 "volts"); 1931 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1932 "exponent"); 1933 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1934 "is_verified"); 1935 EXPECT_JSON_VALID(configFile); 1936 } 1937 // Invalid: test pmbus_write_vout_command with no format. 1938 { 1939 json configFile = pmbusWriteVoutCommandFile; 1940 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1941 "format"); 1942 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1943 "u'format' is a required property"); 1944 } 1945 // Invalid: test pmbus_write_vout_command with property volts wrong type. 1946 { 1947 json configFile = pmbusWriteVoutCommandFile; 1948 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1949 ["volts"] = true; 1950 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1951 "True is not of type u'number'"); 1952 } 1953 // Invalid: test pmbus_write_vout_command with property format wrong type. 1954 { 1955 json configFile = pmbusWriteVoutCommandFile; 1956 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1957 ["format"] = true; 1958 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1959 "True is not one of [u'linear']"); 1960 } 1961 // Invalid: test pmbus_write_vout_command with property exponent wrong type. 1962 { 1963 json configFile = pmbusWriteVoutCommandFile; 1964 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1965 ["exponent"] = 1.3; 1966 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1967 "1.3 is not of type u'integer'"); 1968 } 1969 // Invalid: test pmbus_write_vout_command with property is_verified wrong 1970 // type. 1971 { 1972 json configFile = pmbusWriteVoutCommandFile; 1973 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1974 ["is_verified"] = 1; 1975 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1976 "1 is not of type u'boolean'"); 1977 } 1978 // Invalid: test pmbus_write_vout_command with property format wrong format. 1979 { 1980 json configFile = pmbusWriteVoutCommandFile; 1981 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1982 ["format"] = "foo"; 1983 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1984 "u'foo' is not one of [u'linear']"); 1985 } 1986 } 1987 TEST(ValidateRegulatorsConfigTest, PresenceDetection) 1988 { 1989 json presenceDetectionFile = validConfigFile; 1990 presenceDetectionFile 1991 ["chassis"][0]["devices"][0]["presence_detection"]["comments"][0] = 1992 "Regulator is only present on the FooBar backplane"; 1993 presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"] 1994 ["rule_id"] = "set_voltage_rule"; 1995 // Valid: test presence_detection with only property rule_id. 1996 { 1997 json configFile = presenceDetectionFile; 1998 EXPECT_JSON_VALID(configFile); 1999 } 2000 // Valid: test presence_detection with only property actions. 2001 { 2002 json configFile = presenceDetectionFile; 2003 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2004 "rule_id"); 2005 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"] 2006 [0]["compare_presence"]["fru"] = 2007 "/system/chassis/motherboard/cpu3"; 2008 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"] 2009 [0]["compare_presence"]["value"] = true; 2010 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2011 "comments"); 2012 EXPECT_JSON_VALID(configFile); 2013 } 2014 // Invalid: test presence_detection with both property rule_id and actions. 2015 { 2016 json configFile = presenceDetectionFile; 2017 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"] 2018 [0]["compare_presence"]["fru"] = 2019 "/system/chassis/motherboard/cpu3"; 2020 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"] 2021 [0]["compare_presence"]["value"] = true; 2022 EXPECT_JSON_INVALID( 2023 configFile, "Validation failed.", 2024 "{u'comments': [u'Regulator is only present on the FooBar " 2025 "backplane'], u'actions': [{u'compare_presence': {u'value': True, " 2026 "u'fru': u'/system/chassis/motherboard/cpu3'}}], u'rule_id': " 2027 "u'set_voltage_rule'} is valid under each of " 2028 "{u'required': [u'actions']}, {u'required': [u'rule_id']}"); 2029 } 2030 // Invalid: test presence_detection with no rule_id and actions. 2031 { 2032 json configFile = presenceDetectionFile; 2033 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2034 "rule_id"); 2035 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2036 "u'rule_id' is a required property"); 2037 } 2038 // Invalid: test presence_detection with property comments wrong type. 2039 { 2040 json configFile = presenceDetectionFile; 2041 configFile["chassis"][0]["devices"][0]["presence_detection"] 2042 ["comments"] = true; 2043 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2044 "True is not of type u'array'"); 2045 } 2046 // Invalid: test presence_detection with property rule_id wrong type. 2047 { 2048 json configFile = presenceDetectionFile; 2049 configFile["chassis"][0]["devices"][0]["presence_detection"] 2050 ["rule_id"] = true; 2051 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2052 "True is not of type u'string'"); 2053 } 2054 // Invalid: test presence_detection with property actions wrong type. 2055 { 2056 json configFile = presenceDetectionFile; 2057 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2058 "rule_id"); 2059 configFile["chassis"][0]["devices"][0]["presence_detection"] 2060 ["actions"] = true; 2061 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2062 "True is not of type u'array'"); 2063 } 2064 // Invalid: test presence_detection with property rule_id wrong format. 2065 { 2066 json configFile = presenceDetectionFile; 2067 configFile["chassis"][0]["devices"][0]["presence_detection"] 2068 ["rule_id"] = "id@"; 2069 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2070 "u'id@' does not match u'^[A-Za-z0-9_]+$'"); 2071 } 2072 // Invalid: test presence_detection with property comments empty array. 2073 { 2074 json configFile = presenceDetectionFile; 2075 configFile["chassis"][0]["devices"][0]["presence_detection"] 2076 ["comments"] = json::array(); 2077 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2078 "[] is too short"); 2079 } 2080 // Invalid: test presence_detection with property actions empty array. 2081 { 2082 json configFile = presenceDetectionFile; 2083 configFile["chassis"][0]["devices"][0]["presence_detection"].erase( 2084 "rule_id"); 2085 configFile["chassis"][0]["devices"][0]["presence_detection"] 2086 ["actions"] = json::array(); 2087 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2088 "[] is too short"); 2089 } 2090 } 2091 TEST(ValidateRegulatorsConfigTest, Rail) 2092 { 2093 // Valid: test rail. 2094 { 2095 json configFile = validConfigFile; 2096 EXPECT_JSON_VALID(configFile); 2097 } 2098 // Valid: test rail with required properties. 2099 { 2100 json configFile = validConfigFile; 2101 configFile["chassis"][0]["devices"][0]["rails"][0].erase("comments"); 2102 configFile["chassis"][0]["devices"][0]["rails"][0].erase( 2103 "configuration"); 2104 configFile["chassis"][0]["devices"][0]["rails"][0].erase( 2105 "sensor_monitoring"); 2106 EXPECT_JSON_VALID(configFile); 2107 } 2108 // Invalid: test rail with no id. 2109 { 2110 json configFile = validConfigFile; 2111 configFile["chassis"][0]["devices"][0]["rails"][0].erase("id"); 2112 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2113 "u'id' is a required property"); 2114 } 2115 // Invalid: test rail with comments wrong type. 2116 { 2117 json configFile = validConfigFile; 2118 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = true; 2119 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2120 "True is not of type u'array'"); 2121 } 2122 // Invalid: test rail with id wrong type. 2123 { 2124 json configFile = validConfigFile; 2125 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = true; 2126 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2127 "True is not of type u'string'"); 2128 } 2129 // Invalid: test rail with configuration wrong type. 2130 { 2131 json configFile = validConfigFile; 2132 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] = 2133 true; 2134 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2135 "True is not of type u'object'"); 2136 } 2137 // Invalid: test rail with sensor_monitoring wrong type. 2138 { 2139 json configFile = validConfigFile; 2140 configFile["chassis"][0]["devices"][0]["rails"][0] 2141 ["sensor_monitoring"] = true; 2142 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2143 "True is not of type u'object'"); 2144 } 2145 // Invalid: test rail with comments empty array. 2146 { 2147 json configFile = validConfigFile; 2148 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = 2149 json::array(); 2150 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2151 "[] is too short"); 2152 } 2153 // Invalid: test rail with id wrong format. 2154 { 2155 json configFile = validConfigFile; 2156 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = "id~"; 2157 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2158 "u'id~' does not match u'^[A-Za-z0-9_]+$'"); 2159 } 2160 } 2161 TEST(ValidateRegulatorsConfigTest, Rule) 2162 { 2163 // valid test comments property, id property, 2164 // action property specified. 2165 { 2166 json configFile = validConfigFile; 2167 EXPECT_JSON_VALID(configFile); 2168 } 2169 2170 // valid test rule with no comments 2171 { 2172 json configFile = validConfigFile; 2173 configFile["rules"][0].erase("comments"); 2174 EXPECT_JSON_VALID(configFile); 2175 } 2176 2177 // invalid test comments property has invalid value type 2178 { 2179 json configFile = validConfigFile; 2180 configFile["rules"][0]["comments"] = {1}; 2181 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2182 "1 is not of type u'string'"); 2183 } 2184 2185 // invalid test rule with no ID 2186 { 2187 json configFile = validConfigFile; 2188 configFile["rules"][0].erase("id"); 2189 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2190 "u'id' is a required property"); 2191 } 2192 2193 // invalid test id property has invalid value type (not string) 2194 { 2195 json configFile = validConfigFile; 2196 configFile["rules"][0]["id"] = true; 2197 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2198 "True is not of type u'string'"); 2199 } 2200 2201 // invalid test id property has invalid value 2202 { 2203 json configFile = validConfigFile; 2204 configFile["rules"][0]["id"] = "foo%"; 2205 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2206 "u'foo%' does not match u'^[A-Za-z0-9_]+$'"); 2207 } 2208 2209 // invalid test rule with no actions property 2210 { 2211 json configFile = validConfigFile; 2212 configFile["rules"][0].erase("actions"); 2213 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2214 "u'actions' is a required property"); 2215 } 2216 2217 // valid test rule with multiple actions 2218 { 2219 json configFile = validConfigFile; 2220 configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule"; 2221 EXPECT_JSON_VALID(configFile); 2222 } 2223 2224 // invalid test actions property has invalid value type (not an array) 2225 { 2226 json configFile = validConfigFile; 2227 configFile["rules"][0]["actions"] = 1; 2228 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2229 "1 is not of type u'array'"); 2230 } 2231 2232 // invalid test actions property has invalid value of action 2233 { 2234 json configFile = validConfigFile; 2235 configFile["rules"][0]["actions"][0] = "foo"; 2236 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2237 "u'foo' is not of type u'object'"); 2238 } 2239 2240 // invalid test actions property has empty array 2241 { 2242 json configFile = validConfigFile; 2243 configFile["rules"][0]["actions"] = json::array(); 2244 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2245 "[] is too short"); 2246 } 2247 } 2248 TEST(ValidateRegulatorsConfigTest, RunRule) 2249 { 2250 json runRuleFile = validConfigFile; 2251 runRuleFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule"; 2252 // Valid: test run_rule. 2253 { 2254 json configFile = runRuleFile; 2255 EXPECT_JSON_VALID(configFile); 2256 } 2257 // Invalid: test run_rule wrong type. 2258 { 2259 json configFile = runRuleFile; 2260 configFile["rules"][0]["actions"][1]["run_rule"] = true; 2261 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2262 "True is not of type u'string'"); 2263 } 2264 // Invalid: test run_rule wrong format. 2265 { 2266 json configFile = runRuleFile; 2267 configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%"; 2268 EXPECT_JSON_INVALID( 2269 configFile, "Validation failed.", 2270 "u'set_voltage_rule%' does not match u'^[A-Za-z0-9_]+$'"); 2271 } 2272 } 2273 TEST(ValidateRegulatorsConfigTest, SensorMonitoring) 2274 { 2275 // Valid: test rails sensor_monitoring with only property rule id. 2276 { 2277 json configFile = validConfigFile; 2278 EXPECT_JSON_VALID(configFile); 2279 } 2280 // Valid: test rails sensor_monitoring with only property actions. 2281 { 2282 json configFile = validConfigFile; 2283 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2284 .erase("rule_id"); 2285 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2286 ["actions"][0]["compare_presence"]["fru"] = 2287 "/system/chassis/motherboard/cpu3"; 2288 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2289 ["actions"][0]["compare_presence"]["value"] = true; 2290 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2291 ["comments"][0] = "comments"; 2292 EXPECT_JSON_VALID(configFile); 2293 } 2294 // Invalid: test rails sensor_monitoring with both property rule_id and 2295 // actions. 2296 { 2297 json configFile = validConfigFile; 2298 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2299 ["actions"][0]["compare_presence"]["fru"] = 2300 "/system/chassis/motherboard/cpu3"; 2301 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2302 ["actions"][0]["compare_presence"]["value"] = true; 2303 EXPECT_JSON_INVALID( 2304 configFile, "Validation failed.", 2305 "{u'rule_id': u'read_sensors_rule', u'actions': " 2306 "[{u'compare_presence': {u'value': True, u'fru': " 2307 "u'/system/chassis/motherboard/cpu3'}}]} is valid under each of " 2308 "{u'required': [u'actions']}, {u'required': [u'rule_id']}"); 2309 } 2310 // Invalid: test rails sensor_monitoring with no rule_id and actions. 2311 { 2312 json configFile = validConfigFile; 2313 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2314 .erase("rule_id"); 2315 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2316 "u'rule_id' is a required property"); 2317 } 2318 // Invalid: test rails sensor_monitoring with property comments wrong type. 2319 { 2320 json configFile = validConfigFile; 2321 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2322 ["comments"] = true; 2323 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2324 "True is not of type u'array'"); 2325 } 2326 // Invalid: test rails sensor_monitoring with property rule_id wrong type. 2327 { 2328 json configFile = validConfigFile; 2329 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2330 ["rule_id"] = true; 2331 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2332 "True is not of type u'string'"); 2333 } 2334 // Invalid: test rails sensor_monitoring with property actions wrong type. 2335 { 2336 json configFile = validConfigFile; 2337 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2338 .erase("rule_id"); 2339 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2340 ["actions"] = true; 2341 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2342 "True is not of type u'array'"); 2343 } 2344 // Invalid: test rails sensor_monitoring with property rule_id wrong format. 2345 { 2346 json configFile = validConfigFile; 2347 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2348 ["rule_id"] = "id@"; 2349 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2350 "u'id@' does not match u'^[A-Za-z0-9_]+$'"); 2351 } 2352 // Invalid: test rails sensor_monitoring with property comments empty array. 2353 { 2354 json configFile = validConfigFile; 2355 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2356 ["comments"] = json::array(); 2357 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2358 "[] is too short"); 2359 } 2360 // Invalid: test rails sensor_monitoring with property actions empty array. 2361 { 2362 json configFile = validConfigFile; 2363 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2364 .erase("rule_id"); 2365 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2366 ["actions"] = json::array(); 2367 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2368 "[] is too short"); 2369 } 2370 } 2371 TEST(ValidateRegulatorsConfigTest, SetDevice) 2372 { 2373 json setDeviceFile = validConfigFile; 2374 setDeviceFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator"; 2375 // Valid: test set_device. 2376 { 2377 json configFile = setDeviceFile; 2378 EXPECT_JSON_VALID(configFile); 2379 } 2380 // Invalid: test set_device wrong type. 2381 { 2382 json configFile = setDeviceFile; 2383 configFile["rules"][0]["actions"][1]["set_device"] = true; 2384 EXPECT_JSON_INVALID(configFile, "Validation failed.", 2385 "True is not of type u'string'"); 2386 } 2387 // Invalid: test set_device wrong format. 2388 { 2389 json configFile = setDeviceFile; 2390 configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%"; 2391 EXPECT_JSON_INVALID( 2392 configFile, "Validation failed.", 2393 "u'io_expander2%' does not match u'^[A-Za-z0-9_]+$'"); 2394 } 2395 } 2396 TEST(ValidateRegulatorsConfigTest, DuplicateRuleID) 2397 { 2398 // Invalid: test duplicate ID in rule. 2399 { 2400 json configFile = validConfigFile; 2401 configFile["rules"][2]["id"] = "set_voltage_rule"; 2402 configFile["rules"][2]["actions"][0]["pmbus_write_vout_command"] 2403 ["format"] = "linear"; 2404 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rule ID.", ""); 2405 } 2406 } 2407 TEST(ValidateRegulatorsConfigTest, DuplicateChassisNumber) 2408 { 2409 // Invalid: test duplicate number in chassis. 2410 { 2411 json configFile = validConfigFile; 2412 configFile["chassis"][1]["number"] = 1; 2413 EXPECT_JSON_INVALID(configFile, "Error: Duplicate chassis number.", ""); 2414 } 2415 } 2416 TEST(ValidateRegulatorsConfigTest, DuplicateDeviceID) 2417 { 2418 // Invalid: test duplicate ID in device. 2419 { 2420 json configFile = validConfigFile; 2421 configFile["chassis"][0]["devices"][1]["id"] = "vdd_regulator"; 2422 configFile["chassis"][0]["devices"][1]["is_regulator"] = true; 2423 configFile["chassis"][0]["devices"][1]["fru"] = 2424 "/system/chassis/motherboard/regulator1"; 2425 configFile["chassis"][0]["devices"][1]["i2c_interface"]["bus"] = 2; 2426 configFile["chassis"][0]["devices"][1]["i2c_interface"]["address"] = 2427 "0x71"; 2428 EXPECT_JSON_INVALID(configFile, "Error: Duplicate device ID.", ""); 2429 } 2430 } 2431 TEST(ValidateRegulatorsConfigTest, DuplicateRailID) 2432 { 2433 // Invalid: test duplicate ID in rail. 2434 { 2435 json configFile = validConfigFile; 2436 configFile["chassis"][0]["devices"][0]["rails"][1]["id"] = "vdd"; 2437 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rail ID.", ""); 2438 } 2439 } 2440 TEST(ValidateRegulatorsConfigTest, InfiniteLoops) 2441 { 2442 // Invalid: test run_rule with infinite loop (rules run each other). 2443 { 2444 json configFile = validConfigFile; 2445 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2"; 2446 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2447 configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule1"; 2448 configFile["rules"][3]["id"] = "set_voltage_rule2"; 2449 EXPECT_JSON_INVALID(configFile, 2450 "Infinite loop caused by run_rule actions.", ""); 2451 } 2452 // Invalid: test run_rule with infinite loop (rule runs itself). 2453 { 2454 json configFile = validConfigFile; 2455 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule1"; 2456 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2457 EXPECT_JSON_INVALID(configFile, 2458 "Infinite loop caused by run_rule actions.", ""); 2459 } 2460 // Invalid: test run_rule with infinite loop (indirect loop). 2461 { 2462 json configFile = validConfigFile; 2463 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2"; 2464 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2465 configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule3"; 2466 configFile["rules"][3]["id"] = "set_voltage_rule2"; 2467 configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule1"; 2468 configFile["rules"][4]["id"] = "set_voltage_rule3"; 2469 EXPECT_JSON_INVALID(configFile, 2470 "Infinite loop caused by run_rule actions.", ""); 2471 } 2472 } 2473 TEST(ValidateRegulatorsConfigTest, RunRuleValueExists) 2474 { 2475 // Invalid: test run_rule actions specify a rule ID that does not exist. 2476 { 2477 json configFile = validConfigFile; 2478 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2"; 2479 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2480 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", ""); 2481 } 2482 } 2483 TEST(ValidateRegulatorsConfigTest, SetDeviceValueExists) 2484 { 2485 // Invalid: test set_device actions specify a device ID that does not exist. 2486 { 2487 json configFile = validConfigFile; 2488 configFile["rules"][2]["actions"][0]["set_device"] = "vdd_regulator2"; 2489 configFile["rules"][2]["id"] = "set_voltage_rule1"; 2490 EXPECT_JSON_INVALID(configFile, "Error: Device ID does not exist.", ""); 2491 } 2492 } 2493 TEST(ValidateRegulatorsConfigTest, RuleIDExists) 2494 { 2495 // Invalid: test rule_id property in configuration specifies a rule ID that 2496 // does not exist. 2497 { 2498 json configFile = validConfigFile; 2499 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] = 2500 "set_voltage_rule2"; 2501 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", ""); 2502 } 2503 // Invalid: test rule_id property in presence_detection specifies a rule ID 2504 // that does not exist. 2505 { 2506 json configFile = validConfigFile; 2507 configFile["chassis"][0]["devices"][0]["presence_detection"] 2508 ["rule_id"] = "set_voltage_rule2"; 2509 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", ""); 2510 } 2511 // Invalid: test rule_id property in sensor_monitoring specifies a rule ID 2512 // that does not exist. 2513 { 2514 json configFile = validConfigFile; 2515 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"] 2516 ["rule_id"] = "set_voltage_rule2"; 2517 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", ""); 2518 } 2519 } 2520 TEST(ValidateRegulatorsConfigTest, NumberOfElementsInMasks) 2521 { 2522 // Invalid: test number of elements in masks not equal to number in values 2523 // in i2c_compare_bytes. 2524 { 2525 json configFile = validConfigFile; 2526 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 2527 "0x82"; 2528 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = { 2529 "0x02", "0x73"}; 2530 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = { 2531 "0x7F"}; 2532 EXPECT_JSON_INVALID(configFile, 2533 "Error: Invalid i2c_compare_bytes action.", ""); 2534 } 2535 // Invalid: test number of elements in masks not equal to number in values 2536 // in i2c_write_bytes. 2537 { 2538 json configFile = validConfigFile; 2539 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 2540 "0x82"; 2541 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = { 2542 "0x02", "0x73"}; 2543 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = { 2544 "0x7F"}; 2545 EXPECT_JSON_INVALID(configFile, 2546 "Error: Invalid i2c_write_bytes action.", ""); 2547 } 2548 } 2549 TEST(ValidateRegulatorsConfigTest, CommandLineSyntax) 2550 { 2551 std::string validateTool = 2552 " ../phosphor-regulators/tools/validate-regulators-config.py "; 2553 std::string schema = " -s "; 2554 std::string schemaFile = 2555 " ../phosphor-regulators/schema/config_schema.json "; 2556 std::string configuration = " -c "; 2557 std::string command; 2558 std::string errorMessage; 2559 std::string outputMessage; 2560 std::string outputMessageHelp = 2561 "usage: validate-regulators-config.py [-h] [-s SCHEMA_FILE]"; 2562 int valid = 0; 2563 2564 std::string fileName; 2565 TmpFile tmpFile; 2566 fileName = tmpFile.getName(); 2567 writeDataToFile(validConfigFile, fileName); 2568 // Valid: -s specified 2569 { 2570 command = validateTool + "-s " + schemaFile + configuration + fileName; 2571 expectCommandLineSyntax(errorMessage, outputMessage, command, valid); 2572 } 2573 // Valid: --schema-file specified 2574 { 2575 command = validateTool + "--schema-file " + schemaFile + configuration + 2576 fileName; 2577 expectCommandLineSyntax(errorMessage, outputMessage, command, valid); 2578 } 2579 // Valid: -c specified 2580 { 2581 command = validateTool + schema + schemaFile + "-c " + fileName; 2582 expectCommandLineSyntax(errorMessage, outputMessage, command, valid); 2583 } 2584 // Valid: --configuration-file specified 2585 { 2586 command = validateTool + schema + schemaFile + "--configuration-file " + 2587 fileName; 2588 expectCommandLineSyntax(errorMessage, outputMessage, command, valid); 2589 } 2590 // Valid: -h specified 2591 { 2592 command = validateTool + "-h "; 2593 expectCommandLineSyntax(errorMessage, outputMessageHelp, command, 2594 valid); 2595 } 2596 // Valid: --help specified 2597 { 2598 command = validateTool + "--help "; 2599 expectCommandLineSyntax(errorMessage, outputMessageHelp, command, 2600 valid); 2601 } 2602 // Invalid: -c/--configuration-file not specified 2603 { 2604 command = validateTool + schema + schemaFile; 2605 expectCommandLineSyntax("Error: Configuration file is required.", 2606 outputMessageHelp, command, 1); 2607 } 2608 // Invalid: -s/--schema-file not specified 2609 { 2610 command = validateTool + configuration + fileName; 2611 expectCommandLineSyntax("Error: Schema file is required.", 2612 outputMessageHelp, command, 1); 2613 } 2614 // Invalid: -s specified more than once 2615 { 2616 command = 2617 validateTool + "-s -s " + schemaFile + configuration + fileName; 2618 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2619 } 2620 // Invalid: -c specified more than once 2621 { 2622 command = validateTool + schema + schemaFile + "-c -c " + fileName; 2623 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2624 } 2625 // Invalid: No file name specified after -c 2626 { 2627 command = validateTool + schema + schemaFile + configuration; 2628 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2629 } 2630 // Invalid: No file name specified after -s 2631 { 2632 command = validateTool + schema + configuration + fileName; 2633 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2634 } 2635 // Invalid: File specified after -c does not exist 2636 { 2637 command = validateTool + schema + schemaFile + configuration + 2638 "../notExistFile"; 2639 expectCommandLineSyntax( 2640 "Traceback (most recent call last):", outputMessage, command, 1); 2641 } 2642 // Invalid: File specified after -s does not exist 2643 { 2644 command = validateTool + schema + "../notExistFile " + configuration + 2645 fileName; 2646 expectCommandLineSyntax( 2647 "Traceback (most recent call last):", outputMessage, command, 1); 2648 } 2649 // Invalid: File specified after -s is not right data format 2650 { 2651 std::string wrongFormatFileName; 2652 TmpFile wrongFormatFile; 2653 wrongFormatFileName = wrongFormatFile.getName(); 2654 std::ofstream out(wrongFormatFileName); 2655 out << "foo"; 2656 out.close(); 2657 command = validateTool + schema + wrongFormatFileName + configuration + 2658 fileName; 2659 expectCommandLineSyntax( 2660 "Traceback (most recent call last):", outputMessage, command, 1); 2661 } 2662 // Invalid: File specified after -c is not readable 2663 { 2664 std::string notReadableFileName; 2665 TmpFile notReadableFile; 2666 notReadableFileName = notReadableFile.getName(); 2667 writeDataToFile(validConfigFile, notReadableFileName); 2668 command = validateTool + schema + schemaFile + configuration + 2669 notReadableFileName; 2670 chmod(notReadableFileName.c_str(), 0222); 2671 expectCommandLineSyntax( 2672 "Traceback (most recent call last):", outputMessage, command, 1); 2673 } 2674 // Invalid: File specified after -s is not readable 2675 { 2676 std::string notReadableFileName; 2677 TmpFile notReadableFile; 2678 notReadableFileName = notReadableFile.getName(); 2679 writeDataToFile(validConfigFile, notReadableFileName); 2680 command = validateTool + schema + notReadableFileName + configuration + 2681 fileName; 2682 chmod(notReadableFileName.c_str(), 0222); 2683 expectCommandLineSyntax( 2684 "Traceback (most recent call last):", outputMessage, command, 1); 2685 } 2686 // Invalid: Unexpected parameter specified (like -g) 2687 { 2688 command = validateTool + schema + schemaFile + configuration + 2689 fileName + " -g"; 2690 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2); 2691 } 2692 } 2693