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