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/wait.h> 20 21 #include <nlohmann/json.hpp> 22 23 #include <fstream> 24 25 #include <gtest/gtest.h> 26 27 #define EXPECT_FILE_VALID(configFile) expectFileValid(configFile) 28 #define EXPECT_FILE_INVALID(configFile, expectedErrorMessage, \ 29 expectedOutputMessage) \ 30 expectFileInvalid(configFile, expectedErrorMessage, expectedOutputMessage) 31 #define EXPECT_JSON_VALID(configFileJson) expectJsonValid(configFileJson) 32 #define EXPECT_JSON_INVALID(configFileJson, expectedErrorMessage, \ 33 expectedOutputMessage) \ 34 expectJsonInvalid(configFileJson, expectedErrorMessage, \ 35 expectedOutputMessage) 36 37 using json = nlohmann::json; 38 39 const json validConfigFile = R"( 40 { 41 "comments": [ "Config file for a FooBar one-chassis system" ], 42 43 "rules": [ 44 { 45 "comments": [ "Sets output voltage for a PMBus regulator rail" ], 46 "id": "set_voltage_rule", 47 "actions": [ 48 { 49 "pmbus_write_vout_command": { 50 "format": "linear" 51 } 52 } 53 ] 54 } 55 ], 56 57 "chassis": [ 58 { 59 "comments": [ "Chassis number 1 containing CPUs and memory" ], 60 "number": 1, 61 "devices": [ 62 { 63 "comments": [ "IR35221 regulator producing the Vdd rail" ], 64 "id": "vdd_regulator", 65 "is_regulator": true, 66 "fru": "/system/chassis/motherboard/regulator1", 67 "i2c_interface": { 68 "bus": 1, 69 "address": "0x70" 70 }, 71 "rails": [ 72 { 73 "comments": [ "Vdd rail" ], 74 "id": "vdd", 75 "configuration": { 76 "volts": 1.03, 77 "rule_id": "set_voltage_rule" 78 }, 79 "sensor_monitoring": { 80 "rule_id": "read_sensors_rule" 81 } 82 } 83 ] 84 } 85 ] 86 } 87 ] 88 } 89 )"_json; 90 91 std::string createTmpFile() 92 { 93 // create temporary file using mkstemp under /tmp/. random name for XXXXXX 94 char fileName[] = "/tmp/temp-XXXXXX"; 95 int fd = mkstemp(fileName); 96 if (fd == -1) 97 { 98 perror("Can't create temporary file"); 99 } 100 close(fd); 101 return fileName; 102 } 103 104 std::string getValidationToolCommand(const std::string& configFileName) 105 { 106 std::string command = "python ../tools/validate-regulators-config.py -s \ 107 ../schema/config_schema.json -c "; 108 command += configFileName; 109 return command; 110 } 111 112 int runToolForOutput(const std::string& configFileName, std::string& output, 113 bool isReadingStderr = false) 114 { 115 // run the validation tool with the temporary file and return the output 116 // of the validation tool. 117 std::string command = getValidationToolCommand(configFileName); 118 // reading the stderr while isReadingStderr is true. 119 if (isReadingStderr == true) 120 { 121 command += " 2>&1 >/dev/null"; 122 } 123 // get the jsonschema print from validation tool. 124 char buffer[256]; 125 std::string result = ""; 126 // to get the stdout from the validation tool. 127 FILE* pipe = popen(command.c_str(), "r"); 128 if (!pipe) 129 { 130 throw std::runtime_error("popen() failed!"); 131 } 132 while (!std::feof(pipe)) 133 { 134 if (fgets(buffer, sizeof buffer, pipe) != NULL) 135 { 136 result += buffer; 137 } 138 } 139 int returnValue = pclose(pipe); 140 // Check if pclose() failed 141 if (returnValue == -1) 142 { 143 // unable to close pipe. Print error and exit function. 144 throw std::runtime_error("pclose() failed!"); 145 } 146 std::string firstLine = result.substr(0, result.find('\n')); 147 output = firstLine; 148 // Get command exit status from return value 149 int exitStatus = WEXITSTATUS(returnValue); 150 return exitStatus; 151 } 152 153 void expectFileValid(const std::string& configFileName) 154 { 155 std::string errorMessage = ""; 156 std::string outputMessage = ""; 157 EXPECT_EQ(runToolForOutput(configFileName, errorMessage, true), 0); 158 EXPECT_EQ(runToolForOutput(configFileName, outputMessage), 0); 159 EXPECT_EQ(errorMessage, ""); 160 EXPECT_EQ(outputMessage, ""); 161 } 162 163 void expectFileInvalid(const std::string& configFileName, 164 const std::string& expectedErrorMessage, 165 const std::string& expectedOutputMessage) 166 { 167 std::string errorMessage = ""; 168 std::string outputMessage = ""; 169 EXPECT_EQ(runToolForOutput(configFileName, errorMessage, true), 1); 170 EXPECT_EQ(runToolForOutput(configFileName, outputMessage), 1); 171 EXPECT_EQ(errorMessage, expectedErrorMessage); 172 EXPECT_EQ(outputMessage, expectedOutputMessage); 173 } 174 175 void expectJsonValid(const json configFileJson) 176 { 177 std::string fileName; 178 fileName = createTmpFile(); 179 std::string jsonData = configFileJson.dump(); 180 std::ofstream out(fileName); 181 out << jsonData; 182 out.close(); 183 184 EXPECT_FILE_VALID(fileName); 185 unlink(fileName.c_str()); 186 } 187 188 void expectJsonInvalid(const json configFileJson, 189 const std::string& expectedErrorMessage, 190 const std::string& expectedOutputMessage) 191 { 192 std::string fileName; 193 fileName = createTmpFile(); 194 std::string jsonData = configFileJson.dump(); 195 std::ofstream out(fileName); 196 out << jsonData; 197 out.close(); 198 199 EXPECT_FILE_INVALID(fileName, expectedErrorMessage, expectedOutputMessage); 200 unlink(fileName.c_str()); 201 } 202 203 TEST(ValidateRegulatorsConfigTest, Rule) 204 { 205 // valid test comments property, id property, 206 // action property specified. 207 { 208 json configFile = validConfigFile; 209 EXPECT_JSON_VALID(configFile); 210 } 211 212 // valid test rule with no comments 213 { 214 json configFile = validConfigFile; 215 configFile["rules"][0].erase("comments"); 216 EXPECT_JSON_VALID(configFile); 217 } 218 219 // invalid test comments property has invalid value type 220 { 221 json configFile = validConfigFile; 222 configFile["rules"][0]["comments"] = {1}; 223 EXPECT_JSON_INVALID(configFile, "Validation failed.", 224 "1 is not of type u'string'"); 225 } 226 227 // invalid test rule with no ID 228 { 229 json configFile = validConfigFile; 230 configFile["rules"][0].erase("id"); 231 EXPECT_JSON_INVALID(configFile, "Validation failed.", 232 "u'id' is a required property"); 233 } 234 235 // invalid test id property has invalid value type (not string) 236 { 237 json configFile = validConfigFile; 238 configFile["rules"][0]["id"] = true; 239 EXPECT_JSON_INVALID(configFile, "Validation failed.", 240 "True is not of type u'string'"); 241 } 242 243 // invalid test id property has invalid value 244 { 245 json configFile = validConfigFile; 246 configFile["rules"][0]["id"] = "foo%"; 247 EXPECT_JSON_INVALID(configFile, "Validation failed.", 248 "u'foo%' does not match u'^[A-Za-z0-9_]+$'"); 249 } 250 251 // invalid test rule with no actions property 252 { 253 json configFile = validConfigFile; 254 configFile["rules"][0].erase("actions"); 255 EXPECT_JSON_INVALID(configFile, "Validation failed.", 256 "u'actions' is a required property"); 257 } 258 259 // valid test rule with multiple actions 260 { 261 json configFile = validConfigFile; 262 configFile["rules"][0]["actions"][1]["run_rule"] = 263 "set_page0_voltage_rule"; 264 EXPECT_JSON_VALID(configFile); 265 } 266 267 // invalid test actions property has invalid value type (not an array) 268 { 269 json configFile = validConfigFile; 270 configFile["rules"][0]["actions"] = 1; 271 EXPECT_JSON_INVALID(configFile, "Validation failed.", 272 "1 is not of type u'array'"); 273 } 274 275 // invalid test actions property has invalid value of action 276 { 277 json configFile = validConfigFile; 278 configFile["rules"][0]["actions"][0] = "foo"; 279 EXPECT_JSON_INVALID(configFile, "Validation failed.", 280 "u'foo' is not of type u'object'"); 281 } 282 283 // invalid test actions property has empty array 284 { 285 json configFile = validConfigFile; 286 configFile["rules"][0]["actions"] = json::array(); 287 EXPECT_JSON_INVALID(configFile, "Validation failed.", 288 "[] is too short"); 289 } 290 } 291 TEST(ValidateRegulatorsConfigTest, And) 292 { 293 // Valid. 294 { 295 json configFile = validConfigFile; 296 json andAction = 297 R"( 298 { 299 "and": [ 300 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }, 301 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } } 302 ] 303 } 304 )"_json; 305 configFile["rules"][0]["actions"].push_back(andAction); 306 EXPECT_JSON_VALID(configFile); 307 } 308 309 // Invalid: actions property value is an empty array. 310 { 311 json configFile = validConfigFile; 312 json andAction = 313 R"( 314 { 315 "and": [] 316 } 317 )"_json; 318 configFile["rules"][0]["actions"].push_back(andAction); 319 EXPECT_JSON_INVALID(configFile, "Validation failed.", 320 "[] is too short"); 321 } 322 323 // Invalid: actions property has incorrect value data type. 324 { 325 json configFile = validConfigFile; 326 json andAction = 327 R"( 328 { 329 "and": true 330 } 331 )"_json; 332 configFile["rules"][0]["actions"].push_back(andAction); 333 EXPECT_JSON_INVALID(configFile, "Validation failed.", 334 "True is not of type u'array'"); 335 } 336 337 // Invalid: actions property value contains wrong element type 338 { 339 json configFile = validConfigFile; 340 json andAction = 341 R"( 342 { 343 "and": ["foo"] 344 } 345 )"_json; 346 configFile["rules"][0]["actions"].push_back(andAction); 347 EXPECT_JSON_INVALID(configFile, "Validation failed.", 348 "u'foo' is not of type u'object'"); 349 } 350 } 351 TEST(ValidateRegulatorsConfigTest, Chassis) 352 { 353 // Valid: test chassis. 354 { 355 json configFile = validConfigFile; 356 EXPECT_JSON_VALID(configFile); 357 } 358 // Valid: test chassis with required properties. 359 { 360 json configFile = validConfigFile; 361 configFile["chassis"][0].erase("comments"); 362 configFile["chassis"][0].erase("devices"); 363 EXPECT_JSON_VALID(configFile); 364 } 365 // Invalid: test chassis with no number. 366 { 367 json configFile = validConfigFile; 368 configFile["chassis"][0].erase("number"); 369 EXPECT_JSON_INVALID(configFile, "Validation failed.", 370 "u'number' is a required property"); 371 } 372 // Invalid: test chassis with property comments wrong type. 373 { 374 json configFile = validConfigFile; 375 configFile["chassis"][0]["comments"] = true; 376 EXPECT_JSON_INVALID(configFile, "Validation failed.", 377 "True is not of type u'array'"); 378 } 379 // Invalid: test chassis with property number wrong type. 380 { 381 json configFile = validConfigFile; 382 configFile["chassis"][0]["number"] = 1.3; 383 EXPECT_JSON_INVALID(configFile, "Validation failed.", 384 "1.3 is not of type u'integer'"); 385 } 386 // Invalid: test chassis with property devices wrong type. 387 { 388 json configFile = validConfigFile; 389 configFile["chassis"][0]["devices"] = true; 390 EXPECT_JSON_INVALID(configFile, "Validation failed.", 391 "True is not of type u'array'"); 392 } 393 // Invalid: test chassis with property comments empty array. 394 { 395 json configFile = validConfigFile; 396 configFile["chassis"][0]["comments"] = json::array(); 397 EXPECT_JSON_INVALID(configFile, "Validation failed.", 398 "[] is too short"); 399 } 400 // Invalid: test chassis with property devices empty array. 401 { 402 json configFile = validConfigFile; 403 configFile["chassis"][0]["devices"] = json::array(); 404 EXPECT_JSON_INVALID(configFile, "Validation failed.", 405 "[] is too short"); 406 } 407 // Invalid: test chassis with property number less than 1. 408 { 409 json configFile = validConfigFile; 410 configFile["chassis"][0]["number"] = 0; 411 EXPECT_JSON_INVALID(configFile, "Validation failed.", 412 "0 is less than the minimum of 1"); 413 } 414 } 415 TEST(ValidateRegulatorsConfigTest, ComparePresence) 416 { 417 json comparePresenceFile = validConfigFile; 418 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 419 "/system/chassis/motherboard/regulator2"; 420 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] = 421 true; 422 // Valid. 423 { 424 json configFile = comparePresenceFile; 425 EXPECT_JSON_VALID(configFile); 426 } 427 428 // Invalid: no FRU property. 429 { 430 json configFile = comparePresenceFile; 431 configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru"); 432 EXPECT_JSON_INVALID(configFile, "Validation failed.", 433 "u'fru' is a required property"); 434 } 435 436 // Invalid: FRU property length is string less than 1. 437 { 438 json configFile = comparePresenceFile; 439 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = ""; 440 EXPECT_JSON_INVALID(configFile, "Validation failed.", 441 "u'' is too short"); 442 } 443 444 // Invalid: no value property. 445 { 446 json configFile = comparePresenceFile; 447 configFile["rules"][0]["actions"][1]["compare_presence"].erase("value"); 448 EXPECT_JSON_INVALID(configFile, "Validation failed.", 449 "u'value' is a required property"); 450 } 451 452 // Invalid: value property type is not boolean. 453 { 454 json configFile = comparePresenceFile; 455 configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1"; 456 EXPECT_JSON_INVALID(configFile, "Validation failed.", 457 "u'1' is not of type u'boolean'"); 458 } 459 460 // Invalid: FRU property type is not string. 461 { 462 json configFile = comparePresenceFile; 463 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1; 464 EXPECT_JSON_INVALID(configFile, "Validation failed.", 465 "1 is not of type u'string'"); 466 } 467 } 468 TEST(ValidateRegulatorsConfigTest, CompareVpd) 469 { 470 json compareVpdFile = validConfigFile; 471 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 472 "/system/chassis/motherboard/regulator2"; 473 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN"; 474 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35"; 475 476 // Valid. 477 { 478 json configFile = compareVpdFile; 479 EXPECT_JSON_VALID(configFile); 480 } 481 482 // Invalid: no FRU property. 483 { 484 json configFile = compareVpdFile; 485 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru"); 486 EXPECT_JSON_INVALID(configFile, "Validation failed.", 487 "u'fru' is a required property"); 488 } 489 490 // Invalid: no keyword property. 491 { 492 json configFile = compareVpdFile; 493 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword"); 494 EXPECT_JSON_INVALID(configFile, "Validation failed.", 495 "u'keyword' is a required property"); 496 } 497 498 // Invalid: no value property. 499 { 500 json configFile = compareVpdFile; 501 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value"); 502 EXPECT_JSON_INVALID(configFile, "Validation failed.", 503 "u'value' is a required property"); 504 } 505 506 // Invalid: property FRU wrong type. 507 { 508 json configFile = compareVpdFile; 509 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1; 510 EXPECT_JSON_INVALID(configFile, "Validation failed.", 511 "1 is not of type u'string'"); 512 } 513 514 // Invalid: property FRU is string less than 1. 515 { 516 json configFile = compareVpdFile; 517 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = ""; 518 EXPECT_JSON_INVALID(configFile, "Validation failed.", 519 "u'' is too short"); 520 } 521 522 // Invalid: property keyword is not "CCIN", "Manufacturer", "Model", 523 // "PartNumber" 524 { 525 json configFile = compareVpdFile; 526 configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = 527 "Number"; 528 EXPECT_JSON_INVALID(configFile, "Validation failed.", 529 "u'Number' is not one of [u'CCIN', " 530 "u'Manufacturer', u'Model', u'PartNumber']"); 531 } 532 533 // Invalid: property value wrong type. 534 { 535 json configFile = compareVpdFile; 536 configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1; 537 EXPECT_JSON_INVALID(configFile, "Validation failed.", 538 "1 is not of type u'string'"); 539 } 540 } 541 TEST(ValidateRegulatorsConfigTest, Device) 542 { 543 544 // Valid: test devices. 545 { 546 json configFile = validConfigFile; 547 EXPECT_JSON_VALID(configFile); 548 } 549 // Valid: test devices with required properties. 550 { 551 json configFile = validConfigFile; 552 configFile["chassis"][0]["devices"][0].erase("comments"); 553 configFile["chassis"][0]["devices"][0].erase("presence_detection"); 554 configFile["chassis"][0]["devices"][0].erase("configuration"); 555 configFile["chassis"][0]["devices"][0].erase("rails"); 556 EXPECT_JSON_VALID(configFile); 557 } 558 // Invalid: test devices with no id. 559 { 560 json configFile = validConfigFile; 561 configFile["chassis"][0]["devices"][0].erase("id"); 562 EXPECT_JSON_INVALID(configFile, "Validation failed.", 563 "u'id' is a required property"); 564 } 565 // Invalid: test devices with no is_regulator. 566 { 567 json configFile = validConfigFile; 568 configFile["chassis"][0]["devices"][0].erase("is_regulator"); 569 EXPECT_JSON_INVALID(configFile, "Validation failed.", 570 "u'is_regulator' is a required property"); 571 } 572 // Invalid: test devices with no fru. 573 { 574 json configFile = validConfigFile; 575 configFile["chassis"][0]["devices"][0].erase("fru"); 576 EXPECT_JSON_INVALID(configFile, "Validation failed.", 577 "u'fru' is a required property"); 578 } 579 // Invalid: test devices with no i2c_interface. 580 { 581 json configFile = validConfigFile; 582 configFile["chassis"][0]["devices"][0].erase("i2c_interface"); 583 EXPECT_JSON_INVALID(configFile, "Validation failed.", 584 "u'i2c_interface' is a required property"); 585 } 586 // Invalid: test devices with property comments wrong type. 587 { 588 json configFile = validConfigFile; 589 configFile["chassis"][0]["devices"][0]["comments"] = true; 590 EXPECT_JSON_INVALID(configFile, "Validation failed.", 591 "True is not of type u'array'"); 592 } 593 // Invalid: test devices with property id wrong type. 594 { 595 json configFile = validConfigFile; 596 configFile["chassis"][0]["devices"][0]["id"] = true; 597 EXPECT_JSON_INVALID(configFile, "Validation failed.", 598 "True is not of type u'string'"); 599 } 600 // Invalid: test devices with property is_regulator wrong type. 601 { 602 json configFile = validConfigFile; 603 configFile["chassis"][0]["devices"][0]["is_regulator"] = 1; 604 EXPECT_JSON_INVALID(configFile, "Validation failed.", 605 "1 is not of type u'boolean'"); 606 } 607 // Invalid: test devices with property fru wrong type. 608 { 609 json configFile = validConfigFile; 610 configFile["chassis"][0]["devices"][0]["fru"] = true; 611 EXPECT_JSON_INVALID(configFile, "Validation failed.", 612 "True is not of type u'string'"); 613 } 614 // Invalid: test devices with property i2c_interface wrong type. 615 { 616 json configFile = validConfigFile; 617 configFile["chassis"][0]["devices"][0]["i2c_interface"] = true; 618 EXPECT_JSON_INVALID(configFile, "Validation failed.", 619 "True is not of type u'object'"); 620 } 621 // Invalid: test devices with property presence_detection wrong 622 // type. 623 { 624 json configFile = validConfigFile; 625 configFile["chassis"][0]["devices"][0]["presence_detection"] = true; 626 EXPECT_JSON_INVALID(configFile, "Validation failed.", 627 "True is not of type u'object'"); 628 } 629 // Invalid: test devices with property configuration wrong type. 630 { 631 json configFile = validConfigFile; 632 configFile["chassis"][0]["devices"][0]["configuration"] = true; 633 EXPECT_JSON_INVALID(configFile, "Validation failed.", 634 "True is not of type u'object'"); 635 } 636 // Invalid: test devices with property rails wrong type. 637 { 638 json configFile = validConfigFile; 639 configFile["chassis"][0]["devices"][0]["rails"] = true; 640 EXPECT_JSON_INVALID(configFile, "Validation failed.", 641 "True is not of type u'array'"); 642 } 643 // Invalid: test devices with property comments empty array. 644 { 645 json configFile = validConfigFile; 646 configFile["chassis"][0]["devices"][0]["comments"] = json::array(); 647 EXPECT_JSON_INVALID(configFile, "Validation failed.", 648 "[] is too short"); 649 } 650 // Invalid: test devices with property fru length less than 1. 651 { 652 json configFile = validConfigFile; 653 configFile["chassis"][0]["devices"][0]["fru"] = ""; 654 EXPECT_JSON_INVALID(configFile, "Validation failed.", 655 "u'' is too short"); 656 } 657 // Invalid: test devices with property id wrong format. 658 { 659 json configFile = validConfigFile; 660 configFile["chassis"][0]["devices"][0]["id"] = "id#"; 661 EXPECT_JSON_INVALID(configFile, "Validation failed.", 662 "u'id#' does not match u'^[A-Za-z0-9_]+$'"); 663 } 664 // Invalid: test devices with property rails empty array. 665 { 666 json configFile = validConfigFile; 667 configFile["chassis"][0]["devices"][0]["rails"] = json::array(); 668 EXPECT_JSON_INVALID(configFile, "Validation failed.", 669 "[] is too short"); 670 } 671 } 672 TEST(ValidateRegulatorsConfigTest, I2CCompareBit) 673 { 674 json i2cCompareBitFile = validConfigFile; 675 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 676 "0xA0"; 677 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 678 3; 679 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1; 680 // Valid: test rule actions i2c_compare_bit. 681 { 682 json configFile = i2cCompareBitFile; 683 EXPECT_JSON_VALID(configFile); 684 } 685 // Invalid: test i2c_compare_bit with no register. 686 { 687 json configFile = i2cCompareBitFile; 688 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase( 689 "register"); 690 EXPECT_JSON_INVALID(configFile, "Validation failed.", 691 "u'register' is a required property"); 692 } 693 // Invalid: test i2c_compare_bit with no position. 694 { 695 json configFile = i2cCompareBitFile; 696 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase( 697 "position"); 698 EXPECT_JSON_INVALID(configFile, "Validation failed.", 699 "u'position' is a required property"); 700 } 701 // Invalid: test i2c_compare_bit with no value. 702 { 703 json configFile = i2cCompareBitFile; 704 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value"); 705 EXPECT_JSON_INVALID(configFile, "Validation failed.", 706 "u'value' is a required property"); 707 } 708 // Invalid: test i2c_compare_bit with register wrong type. 709 { 710 json configFile = i2cCompareBitFile; 711 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1; 712 EXPECT_JSON_INVALID(configFile, "Validation failed.", 713 "1 is not of type u'string'"); 714 } 715 // Invalid: test i2c_compare_bit with register wrong format. 716 { 717 json configFile = i2cCompareBitFile; 718 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 719 "0xA00"; 720 EXPECT_JSON_INVALID(configFile, "Validation failed.", 721 "u'0xA00' does not match u'^0x[0-9A-Fa-f]{2}$'"); 722 } 723 // Invalid: test i2c_compare_bit with position wrong type. 724 { 725 json configFile = i2cCompareBitFile; 726 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 727 3.1; 728 EXPECT_JSON_INVALID(configFile, "Validation failed.", 729 "3.1 is not of type u'integer'"); 730 } 731 // Invalid: test i2c_compare_bit with position greater than 7. 732 { 733 json configFile = i2cCompareBitFile; 734 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8; 735 EXPECT_JSON_INVALID(configFile, "Validation failed.", 736 "8 is greater than the maximum of 7"); 737 } 738 // Invalid: test i2c_compare_bit with position less than 0. 739 { 740 json configFile = i2cCompareBitFile; 741 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 742 -1; 743 EXPECT_JSON_INVALID(configFile, "Validation failed.", 744 "-1 is less than the minimum of 0"); 745 } 746 // Invalid: test i2c_compare_bit with value wrong type. 747 { 748 json configFile = i2cCompareBitFile; 749 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1"; 750 EXPECT_JSON_INVALID(configFile, "Validation failed.", 751 "u'1' is not of type u'integer'"); 752 } 753 // Invalid: test i2c_compare_bit with value greater than 1. 754 { 755 json configFile = i2cCompareBitFile; 756 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2; 757 EXPECT_JSON_INVALID(configFile, "Validation failed.", 758 "2 is greater than the maximum of 1"); 759 } 760 // Invalid: test i2c_compare_bit with value less than 0. 761 { 762 json configFile = i2cCompareBitFile; 763 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1; 764 EXPECT_JSON_INVALID(configFile, "Validation failed.", 765 "-1 is less than the minimum of 0"); 766 } 767 } 768 TEST(ValidateRegulatorsConfigTest, I2CCompareByte) 769 { 770 json i2cCompareByteFile = validConfigFile; 771 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"] 772 ["register"] = "0x82"; 773 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 774 "0x40"; 775 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 776 "0x7F"; 777 // Valid: test i2c_compare_byte with all properties. 778 { 779 json configFile = i2cCompareByteFile; 780 EXPECT_JSON_VALID(configFile); 781 } 782 // Valid: test i2c_compare_byte with all required properties. 783 { 784 json configFile = i2cCompareByteFile; 785 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask"); 786 EXPECT_JSON_VALID(configFile); 787 } 788 // Invalid: test i2c_compare_byte with no register. 789 { 790 json configFile = i2cCompareByteFile; 791 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase( 792 "register"); 793 EXPECT_JSON_INVALID(configFile, "Validation failed.", 794 "u'register' is a required property"); 795 } 796 // Invalid: test i2c_compare_byte with no value. 797 { 798 json configFile = i2cCompareByteFile; 799 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value"); 800 EXPECT_JSON_INVALID(configFile, "Validation failed.", 801 "u'value' is a required property"); 802 } 803 // Invalid: test i2c_compare_byte with property register wrong type. 804 { 805 json configFile = i2cCompareByteFile; 806 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 807 1; 808 EXPECT_JSON_INVALID(configFile, "Validation failed.", 809 "1 is not of type u'string'"); 810 } 811 // Invalid: test i2c_compare_byte with property value wrong type. 812 { 813 json configFile = i2cCompareByteFile; 814 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1; 815 EXPECT_JSON_INVALID(configFile, "Validation failed.", 816 "1 is not of type u'string'"); 817 } 818 // Invalid: test i2c_compare_byte with property mask wrong type. 819 { 820 json configFile = i2cCompareByteFile; 821 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1; 822 EXPECT_JSON_INVALID(configFile, "Validation failed.", 823 "1 is not of type u'string'"); 824 } 825 // Invalid: test i2c_compare_byte with property register more than 2 hex 826 // digits. 827 { 828 json configFile = i2cCompareByteFile; 829 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 830 "0x820"; 831 EXPECT_JSON_INVALID(configFile, "Validation failed.", 832 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 833 } 834 // Invalid: test i2c_compare_byte with property value more than 2 hex 835 // digits. 836 { 837 json configFile = i2cCompareByteFile; 838 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 839 "0x820"; 840 EXPECT_JSON_INVALID(configFile, "Validation failed.", 841 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 842 } 843 // Invalid: test i2c_compare_byte with property mask more than 2 hex digits. 844 { 845 json configFile = i2cCompareByteFile; 846 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 847 "0x820"; 848 EXPECT_JSON_INVALID(configFile, "Validation failed.", 849 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 850 } 851 // Invalid: test i2c_compare_byte with property register less than 2 hex 852 // digits. 853 { 854 json configFile = i2cCompareByteFile; 855 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 856 "0x8"; 857 EXPECT_JSON_INVALID(configFile, "Validation failed.", 858 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 859 } 860 // Invalid: test i2c_compare_byte with property value less than 2 hex 861 // digits. 862 { 863 json configFile = i2cCompareByteFile; 864 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 865 "0x8"; 866 EXPECT_JSON_INVALID(configFile, "Validation failed.", 867 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 868 } 869 // Invalid: test i2c_compare_byte with property mask less than 2 hex digits. 870 { 871 json configFile = i2cCompareByteFile; 872 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 873 "0x8"; 874 EXPECT_JSON_INVALID(configFile, "Validation failed.", 875 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 876 } 877 // Invalid: test i2c_compare_byte with property register no leading prefix. 878 { 879 json configFile = i2cCompareByteFile; 880 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 881 "82"; 882 EXPECT_JSON_INVALID(configFile, "Validation failed.", 883 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 884 } 885 // Invalid: test i2c_compare_byte with property value no leading prefix. 886 { 887 json configFile = i2cCompareByteFile; 888 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 889 "82"; 890 EXPECT_JSON_INVALID(configFile, "Validation failed.", 891 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 892 } 893 // Invalid: test i2c_compare_byte with property mask no leading prefix. 894 { 895 json configFile = i2cCompareByteFile; 896 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82"; 897 EXPECT_JSON_INVALID(configFile, "Validation failed.", 898 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 899 } 900 // Invalid: test i2c_compare_byte with property register invalid hex digit. 901 { 902 json configFile = i2cCompareByteFile; 903 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 904 "0xG1"; 905 EXPECT_JSON_INVALID(configFile, "Validation failed.", 906 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 907 } 908 // Invalid: test i2c_compare_byte with property value invalid hex digit. 909 { 910 json configFile = i2cCompareByteFile; 911 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 912 "0xG1"; 913 EXPECT_JSON_INVALID(configFile, "Validation failed.", 914 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 915 } 916 // Invalid: test i2c_compare_byte with property mask invalid hex digit. 917 { 918 json configFile = i2cCompareByteFile; 919 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 920 "0xG1"; 921 EXPECT_JSON_INVALID(configFile, "Validation failed.", 922 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 923 } 924 } 925 TEST(ValidateRegulatorsConfigTest, I2CCompareBytes) 926 { 927 json i2cCompareBytesFile = validConfigFile; 928 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"] 929 ["register"] = "0x82"; 930 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"] 931 ["values"] = {"0x02", "0x73"}; 932 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"] 933 ["masks"] = {"0x7F", "0x7F"}; 934 // Valid: test i2c_compare_bytes. 935 { 936 json configFile = i2cCompareBytesFile; 937 EXPECT_JSON_VALID(configFile); 938 } 939 // Valid: test i2c_compare_bytes with all required properties. 940 { 941 json configFile = i2cCompareBytesFile; 942 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase( 943 "masks"); 944 EXPECT_JSON_VALID(configFile); 945 } 946 // Invalid: test i2c_compare_bytes with no register. 947 { 948 json configFile = i2cCompareBytesFile; 949 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase( 950 "register"); 951 EXPECT_JSON_INVALID(configFile, "Validation failed.", 952 "u'register' is a required property"); 953 } 954 // Invalid: test i2c_compare_bytes with no values. 955 { 956 json configFile = i2cCompareBytesFile; 957 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase( 958 "values"); 959 EXPECT_JSON_INVALID(configFile, "Validation failed.", 960 "u'values' is a required property"); 961 } 962 // Invalid: test i2c_compare_bytes with property values as empty array. 963 { 964 json configFile = i2cCompareBytesFile; 965 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 966 json::array(); 967 EXPECT_JSON_INVALID(configFile, "Validation failed.", 968 "[] is too short"); 969 } 970 // Invalid: test i2c_compare_bytes with property masks as empty array. 971 { 972 json configFile = i2cCompareBytesFile; 973 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 974 json::array(); 975 EXPECT_JSON_INVALID(configFile, "Validation failed.", 976 "[] is too short"); 977 } 978 // Invalid: test i2c_compare_bytes with property register wrong type. 979 { 980 json configFile = i2cCompareBytesFile; 981 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 982 1; 983 EXPECT_JSON_INVALID(configFile, "Validation failed.", 984 "1 is not of type u'string'"); 985 } 986 // Invalid: test i2c_compare_bytes with property values wrong type. 987 { 988 json configFile = i2cCompareBytesFile; 989 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1; 990 EXPECT_JSON_INVALID(configFile, "Validation failed.", 991 "1 is not of type u'array'"); 992 } 993 // Invalid: test i2c_compare_bytes with property masks wrong type. 994 { 995 json configFile = i2cCompareBytesFile; 996 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1; 997 EXPECT_JSON_INVALID(configFile, "Validation failed.", 998 "1 is not of type u'array'"); 999 } 1000 // Invalid: test i2c_compare_bytes with property register more than 2 hex 1001 // digits. 1002 { 1003 json configFile = i2cCompareBytesFile; 1004 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 1005 "0x820"; 1006 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1007 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1008 } 1009 // Invalid: test i2c_compare_bytes with property values more than 2 hex 1010 // digits. 1011 { 1012 json configFile = i2cCompareBytesFile; 1013 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 1014 "0x820"; 1015 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1016 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1017 } 1018 // Invalid: test i2c_compare_bytes with property masks more than 2 hex 1019 // digits. 1020 { 1021 json configFile = i2cCompareBytesFile; 1022 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 1023 "0x820"; 1024 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1025 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1026 } 1027 // Invalid: test i2c_compare_bytes with property register less than 2 hex 1028 // digits. 1029 { 1030 json configFile = i2cCompareBytesFile; 1031 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 1032 "0x8"; 1033 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1034 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1035 } 1036 // Invalid: test i2c_compare_bytes with property values less than 2 hex 1037 // digits. 1038 { 1039 json configFile = i2cCompareBytesFile; 1040 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 1041 "0x8"; 1042 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1043 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1044 } 1045 // Invalid: test i2c_compare_bytes with property masks less than 2 hex 1046 // digits. 1047 { 1048 json configFile = i2cCompareBytesFile; 1049 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 1050 "0x8"; 1051 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1052 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1053 } 1054 // Invalid: test i2c_compare_bytes with property register no leading prefix. 1055 { 1056 json configFile = i2cCompareBytesFile; 1057 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 1058 "82"; 1059 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1060 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1061 } 1062 // Invalid: test i2c_compare_bytes with property values no leading prefix. 1063 { 1064 json configFile = i2cCompareBytesFile; 1065 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 1066 "82"; 1067 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1068 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1069 } 1070 // Invalid: test i2c_compare_bytes with property masks no leading prefix. 1071 { 1072 json configFile = i2cCompareBytesFile; 1073 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 1074 "82"; 1075 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1076 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1077 } 1078 // Invalid: test i2c_compare_bytes with property register invalid hex digit. 1079 { 1080 json configFile = i2cCompareBytesFile; 1081 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 1082 "0xG1"; 1083 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1084 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1085 } 1086 // Invalid: test i2c_compare_bytes with property values invalid hex digit. 1087 { 1088 json configFile = i2cCompareBytesFile; 1089 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 1090 "0xG1"; 1091 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1092 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1093 } 1094 // Invalid: test i2c_compare_bytes with property masks invalid hex digit. 1095 { 1096 json configFile = i2cCompareBytesFile; 1097 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 1098 "0xG1"; 1099 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1100 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1101 } 1102 } 1103 TEST(ValidateRegulatorsConfigTest, I2CInterface) 1104 { 1105 // Valid: test i2c_interface. 1106 { 1107 json configFile = validConfigFile; 1108 EXPECT_JSON_VALID(configFile); 1109 } 1110 // Invalid: testi2c_interface with no bus. 1111 { 1112 json configFile = validConfigFile; 1113 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase("bus"); 1114 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1115 "u'bus' is a required property"); 1116 } 1117 // Invalid: test i2c_interface with no address. 1118 { 1119 json configFile = validConfigFile; 1120 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase( 1121 "address"); 1122 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1123 "u'address' is a required property"); 1124 } 1125 // Invalid: test i2c_interface with property bus wrong type. 1126 { 1127 json configFile = validConfigFile; 1128 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = true; 1129 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1130 "True is not of type u'integer'"); 1131 } 1132 // Invalid: test i2c_interface with property address wrong 1133 // type. 1134 { 1135 json configFile = validConfigFile; 1136 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] = 1137 true; 1138 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1139 "True is not of type u'string'"); 1140 } 1141 // Invalid: test i2c_interface with property bus less than 1142 // 0. 1143 { 1144 json configFile = validConfigFile; 1145 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = -1; 1146 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1147 "-1 is less than the minimum of 0"); 1148 } 1149 // Invalid: test i2c_interface with property address wrong 1150 // format. 1151 { 1152 json configFile = validConfigFile; 1153 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] = 1154 "0x700"; 1155 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1156 "u'0x700' does not match u'^0x[0-9A-Fa-f]{2}$'"); 1157 } 1158 } 1159 TEST(ValidateRegulatorsConfigTest, If) 1160 { 1161 json ifFile = validConfigFile; 1162 ifFile["rules"][0]["actions"][1]["if"]["condition"]["run_rule"] = 1163 "is_downlevel_regulator"; 1164 ifFile["rules"][0]["actions"][1]["if"]["then"][0]["run_rule"] = 1165 "configure_downlevel_regulator"; 1166 ifFile["rules"][0]["actions"][1]["if"]["else"][0]["run_rule"] = 1167 "configure_downlevel_regulator"; 1168 // Valid: test if. 1169 { 1170 json configFile = ifFile; 1171 EXPECT_JSON_VALID(configFile); 1172 } 1173 // Valid: test if with required properties. 1174 { 1175 json configFile = ifFile; 1176 configFile["rules"][0]["actions"][1]["if"].erase("else"); 1177 EXPECT_JSON_VALID(configFile); 1178 } 1179 // Invalid: test if with no property condition. 1180 { 1181 json configFile = ifFile; 1182 configFile["rules"][0]["actions"][1]["if"].erase("condition"); 1183 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1184 "u'condition' is a required property"); 1185 } 1186 // Invalid: test if with no property then. 1187 { 1188 json configFile = ifFile; 1189 configFile["rules"][0]["actions"][1]["if"].erase("then"); 1190 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1191 "u'then' is a required property"); 1192 } 1193 // Invalid: test if with property then empty array. 1194 { 1195 json configFile = ifFile; 1196 configFile["rules"][0]["actions"][1]["if"]["then"] = json::array(); 1197 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1198 "[] is too short"); 1199 } 1200 // Invalid: test if with property else empty array. 1201 { 1202 json configFile = ifFile; 1203 configFile["rules"][0]["actions"][1]["if"]["else"] = json::array(); 1204 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1205 "[] is too short"); 1206 } 1207 // Invalid: test if with property condition wrong type. 1208 { 1209 json configFile = ifFile; 1210 configFile["rules"][0]["actions"][1]["if"]["condition"] = 1; 1211 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1212 "1 is not of type u'object'"); 1213 } 1214 // Invalid: test if with property then wrong type. 1215 { 1216 json configFile = ifFile; 1217 configFile["rules"][0]["actions"][1]["if"]["then"] = 1; 1218 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1219 "1 is not of type u'array'"); 1220 } 1221 // Invalid: test if with property else wrong type. 1222 { 1223 json configFile = ifFile; 1224 configFile["rules"][0]["actions"][1]["if"]["else"] = 1; 1225 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1226 "1 is not of type u'array'"); 1227 } 1228 } 1229 TEST(ValidateRegulatorsConfigTest, Not) 1230 { 1231 json notFile = validConfigFile; 1232 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] = 1233 "0xA0"; 1234 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] = 1235 "0xFF"; 1236 // Valid: test not. 1237 { 1238 json configFile = notFile; 1239 EXPECT_JSON_VALID(configFile); 1240 } 1241 // Invalid: test not with wrong type. 1242 { 1243 json configFile = notFile; 1244 configFile["rules"][0]["actions"][1]["not"] = 1; 1245 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1246 "1 is not of type u'object'"); 1247 } 1248 } 1249 TEST(ValidateRegulatorsConfigTest, Or) 1250 { 1251 json orFile = validConfigFile; 1252 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] = 1253 "0xA0"; 1254 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] = 1255 "0x00"; 1256 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] = 1257 "0xA1"; 1258 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] = 1259 "0x00"; 1260 // Valid: test or. 1261 { 1262 json configFile = orFile; 1263 EXPECT_JSON_VALID(configFile); 1264 } 1265 // Invalid: test or with empty array. 1266 { 1267 json configFile = orFile; 1268 configFile["rules"][0]["actions"][1]["or"] = json::array(); 1269 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1270 "[] is too short"); 1271 } 1272 // Invalid: test or with wrong type. 1273 { 1274 json configFile = orFile; 1275 configFile["rules"][0]["actions"][1]["or"] = 1; 1276 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1277 "1 is not of type u'array'"); 1278 } 1279 } 1280 TEST(ValidateRegulatorsConfigTest, PmbusReadSensor) 1281 { 1282 json pmbusReadSensorFile = validConfigFile; 1283 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1284 "vout"; 1285 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1286 ["command"] = "0x8B"; 1287 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1288 ["format"] = "linear_16"; 1289 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1290 ["exponent"] = -8; 1291 // Valid: test pmbus_read_sensor. 1292 { 1293 json configFile = pmbusReadSensorFile; 1294 EXPECT_JSON_VALID(configFile); 1295 } 1296 // Valid: test pmbus_read_sensor with required properties. 1297 { 1298 json configFile = pmbusReadSensorFile; 1299 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1300 "exponent"); 1301 EXPECT_JSON_VALID(configFile); 1302 } 1303 // Invalid: test pmbus_read_sensor with no type. 1304 { 1305 json configFile = pmbusReadSensorFile; 1306 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type"); 1307 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1308 "u'type' is a required property"); 1309 } 1310 // Invalid: test pmbus_read_sensor with no command. 1311 { 1312 json configFile = pmbusReadSensorFile; 1313 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1314 "command"); 1315 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1316 "u'command' is a required property"); 1317 } 1318 // Invalid: test pmbus_read_sensor with no format. 1319 { 1320 json configFile = pmbusReadSensorFile; 1321 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1322 "format"); 1323 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1324 "u'format' is a required property"); 1325 } 1326 // Invalid: test pmbus_read_sensor with property type wrong type. 1327 { 1328 json configFile = pmbusReadSensorFile; 1329 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1330 true; 1331 EXPECT_JSON_INVALID( 1332 configFile, "Validation failed.", 1333 "True is not one of [u'iout', u'iout_peak', u'iout_valley', " 1334 "u'pout', u'temperature', u'temperature_peak', u'vout', " 1335 "u'vout_peak', u'vout_valley']"); 1336 } 1337 // Invalid: test pmbus_read_sensor with property command wrong type. 1338 { 1339 json configFile = pmbusReadSensorFile; 1340 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1341 true; 1342 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1343 "True is not of type u'string'"); 1344 } 1345 // Invalid: test pmbus_read_sensor with property format wrong type. 1346 { 1347 json configFile = pmbusReadSensorFile; 1348 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1349 true; 1350 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1351 "True is not one of [u'linear_11', u'linear_16']"); 1352 } 1353 // Invalid: test pmbus_read_sensor with property exponent wrong type. 1354 { 1355 json configFile = pmbusReadSensorFile; 1356 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] = 1357 true; 1358 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1359 "True is not of type u'integer'"); 1360 } 1361 // Invalid: test pmbus_read_sensor with property type wrong format. 1362 { 1363 json configFile = pmbusReadSensorFile; 1364 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1365 "foo"; 1366 EXPECT_JSON_INVALID( 1367 configFile, "Validation failed.", 1368 "u'foo' is not one of [u'iout', u'iout_peak', u'iout_valley', " 1369 "u'pout', u'temperature', u'temperature_peak', u'vout', " 1370 "u'vout_peak', u'vout_valley']"); 1371 } 1372 // Invalid: test pmbus_read_sensor with property command wrong format. 1373 { 1374 json configFile = pmbusReadSensorFile; 1375 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1376 "0x8B0"; 1377 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1378 "u'0x8B0' does not match u'^0x[0-9a-fA-F]{2}$'"); 1379 } 1380 // Invalid: test pmbus_read_sensor with property format wrong format. 1381 { 1382 json configFile = pmbusReadSensorFile; 1383 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1384 "foo"; 1385 EXPECT_JSON_INVALID( 1386 configFile, "Validation failed.", 1387 "u'foo' is not one of [u'linear_11', u'linear_16']"); 1388 } 1389 } 1390 TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand) 1391 { 1392 json pmbusWriteVoutCommandFile = validConfigFile; 1393 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1394 ["pmbus_write_vout_command"]["volts"] = 1.03; 1395 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1396 ["pmbus_write_vout_command"]["format"] = "linear"; 1397 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1398 ["pmbus_write_vout_command"]["exponent"] = -8; 1399 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1400 ["pmbus_write_vout_command"]["is_verified"] = true; 1401 // Valid: test pmbus_write_vout_command. 1402 { 1403 json configFile = pmbusWriteVoutCommandFile; 1404 EXPECT_JSON_VALID(configFile); 1405 } 1406 // Valid: test pmbus_write_vout_command with required properties. 1407 { 1408 json configFile = pmbusWriteVoutCommandFile; 1409 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1410 "volts"); 1411 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1412 "exponent"); 1413 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1414 "is_verified"); 1415 EXPECT_JSON_VALID(configFile); 1416 } 1417 // Invalid: test pmbus_write_vout_command with no format. 1418 { 1419 json configFile = pmbusWriteVoutCommandFile; 1420 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1421 "format"); 1422 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1423 "u'format' is a required property"); 1424 } 1425 // Invalid: test pmbus_write_vout_command with property volts wrong type. 1426 { 1427 json configFile = pmbusWriteVoutCommandFile; 1428 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1429 ["volts"] = true; 1430 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1431 "True is not of type u'number'"); 1432 } 1433 // Invalid: test pmbus_write_vout_command with property format wrong type. 1434 { 1435 json configFile = pmbusWriteVoutCommandFile; 1436 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1437 ["format"] = true; 1438 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1439 "True is not one of [u'linear']"); 1440 } 1441 // Invalid: test pmbus_write_vout_command with property exponent wrong type. 1442 { 1443 json configFile = pmbusWriteVoutCommandFile; 1444 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1445 ["exponent"] = 1.3; 1446 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1447 "1.3 is not of type u'integer'"); 1448 } 1449 // Invalid: test pmbus_write_vout_command with property is_verified wrong 1450 // type. 1451 { 1452 json configFile = pmbusWriteVoutCommandFile; 1453 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1454 ["is_verified"] = 1; 1455 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1456 "1 is not of type u'boolean'"); 1457 } 1458 // Invalid: test pmbus_write_vout_command with property format wrong format. 1459 { 1460 json configFile = pmbusWriteVoutCommandFile; 1461 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1462 ["format"] = "foo"; 1463 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1464 "u'foo' is not one of [u'linear']"); 1465 } 1466 } 1467 TEST(ValidateRegulatorsConfigTest, RunRule) 1468 { 1469 json runRuleFile = validConfigFile; 1470 runRuleFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule1"; 1471 // Valid: test run_rule. 1472 { 1473 json configFile = runRuleFile; 1474 EXPECT_JSON_VALID(configFile); 1475 } 1476 // Invalid: test run_rule wrong type. 1477 { 1478 json configFile = runRuleFile; 1479 configFile["rules"][0]["actions"][1]["run_rule"] = true; 1480 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1481 "True is not of type u'string'"); 1482 } 1483 // Invalid: test run_rule wrong format. 1484 { 1485 json configFile = runRuleFile; 1486 configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%"; 1487 EXPECT_JSON_INVALID( 1488 configFile, "Validation failed.", 1489 "u'set_voltage_rule%' does not match u'^[A-Za-z0-9_]+$'"); 1490 } 1491 } 1492 TEST(ValidateRegulatorsConfigTest, SetDevice) 1493 { 1494 json setDeviceFile = validConfigFile; 1495 setDeviceFile["rules"][0]["actions"][1]["set_device"] = "io_expander2"; 1496 // Valid: test set_device. 1497 { 1498 json configFile = setDeviceFile; 1499 EXPECT_JSON_VALID(configFile); 1500 } 1501 // Invalid: test set_device wrong type. 1502 { 1503 json configFile = setDeviceFile; 1504 configFile["rules"][0]["actions"][1]["set_device"] = true; 1505 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1506 "True is not of type u'string'"); 1507 } 1508 // Invalid: test set_device wrong format. 1509 { 1510 json configFile = setDeviceFile; 1511 configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%"; 1512 EXPECT_JSON_INVALID( 1513 configFile, "Validation failed.", 1514 "u'io_expander2%' does not match u'^[A-Za-z0-9_]+$'"); 1515 } 1516 } 1517