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, If) 1104 { 1105 json ifFile = validConfigFile; 1106 ifFile["rules"][0]["actions"][1]["if"]["condition"]["run_rule"] = 1107 "is_downlevel_regulator"; 1108 ifFile["rules"][0]["actions"][1]["if"]["then"][0]["run_rule"] = 1109 "configure_downlevel_regulator"; 1110 ifFile["rules"][0]["actions"][1]["if"]["else"][0]["run_rule"] = 1111 "configure_downlevel_regulator"; 1112 // Valid: test if. 1113 { 1114 json configFile = ifFile; 1115 EXPECT_JSON_VALID(configFile); 1116 } 1117 // Valid: test if with required properties. 1118 { 1119 json configFile = ifFile; 1120 configFile["rules"][0]["actions"][1]["if"].erase("else"); 1121 EXPECT_JSON_VALID(configFile); 1122 } 1123 // Invalid: test if with no property condition. 1124 { 1125 json configFile = ifFile; 1126 configFile["rules"][0]["actions"][1]["if"].erase("condition"); 1127 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1128 "u'condition' is a required property"); 1129 } 1130 // Invalid: test if with no property then. 1131 { 1132 json configFile = ifFile; 1133 configFile["rules"][0]["actions"][1]["if"].erase("then"); 1134 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1135 "u'then' is a required property"); 1136 } 1137 // Invalid: test if with property then empty array. 1138 { 1139 json configFile = ifFile; 1140 configFile["rules"][0]["actions"][1]["if"]["then"] = json::array(); 1141 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1142 "[] is too short"); 1143 } 1144 // Invalid: test if with property else empty array. 1145 { 1146 json configFile = ifFile; 1147 configFile["rules"][0]["actions"][1]["if"]["else"] = json::array(); 1148 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1149 "[] is too short"); 1150 } 1151 // Invalid: test if with property condition wrong type. 1152 { 1153 json configFile = ifFile; 1154 configFile["rules"][0]["actions"][1]["if"]["condition"] = 1; 1155 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1156 "1 is not of type u'object'"); 1157 } 1158 // Invalid: test if with property then wrong type. 1159 { 1160 json configFile = ifFile; 1161 configFile["rules"][0]["actions"][1]["if"]["then"] = 1; 1162 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1163 "1 is not of type u'array'"); 1164 } 1165 // Invalid: test if with property else wrong type. 1166 { 1167 json configFile = ifFile; 1168 configFile["rules"][0]["actions"][1]["if"]["else"] = 1; 1169 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1170 "1 is not of type u'array'"); 1171 } 1172 } 1173 TEST(ValidateRegulatorsConfigTest, Not) 1174 { 1175 json notFile = validConfigFile; 1176 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] = 1177 "0xA0"; 1178 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] = 1179 "0xFF"; 1180 // Valid: test not. 1181 { 1182 json configFile = notFile; 1183 EXPECT_JSON_VALID(configFile); 1184 } 1185 // Invalid: test not with wrong type. 1186 { 1187 json configFile = notFile; 1188 configFile["rules"][0]["actions"][1]["not"] = 1; 1189 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1190 "1 is not of type u'object'"); 1191 } 1192 } 1193 TEST(ValidateRegulatorsConfigTest, Or) 1194 { 1195 json orFile = validConfigFile; 1196 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] = 1197 "0xA0"; 1198 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] = 1199 "0x00"; 1200 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] = 1201 "0xA1"; 1202 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] = 1203 "0x00"; 1204 // Valid: test or. 1205 { 1206 json configFile = orFile; 1207 EXPECT_JSON_VALID(configFile); 1208 } 1209 // Invalid: test or with empty array. 1210 { 1211 json configFile = orFile; 1212 configFile["rules"][0]["actions"][1]["or"] = json::array(); 1213 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1214 "[] is too short"); 1215 } 1216 // Invalid: test or with wrong type. 1217 { 1218 json configFile = orFile; 1219 configFile["rules"][0]["actions"][1]["or"] = 1; 1220 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1221 "1 is not of type u'array'"); 1222 } 1223 } 1224 TEST(ValidateRegulatorsConfigTest, PmbusReadSensor) 1225 { 1226 json pmbusReadSensorFile = validConfigFile; 1227 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1228 "vout"; 1229 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1230 ["command"] = "0x8B"; 1231 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1232 ["format"] = "linear_16"; 1233 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1234 ["exponent"] = -8; 1235 // Valid: test pmbus_read_sensor. 1236 { 1237 json configFile = pmbusReadSensorFile; 1238 EXPECT_JSON_VALID(configFile); 1239 } 1240 // Valid: test pmbus_read_sensor with required properties. 1241 { 1242 json configFile = pmbusReadSensorFile; 1243 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1244 "exponent"); 1245 EXPECT_JSON_VALID(configFile); 1246 } 1247 // Invalid: test pmbus_read_sensor with no type. 1248 { 1249 json configFile = pmbusReadSensorFile; 1250 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type"); 1251 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1252 "u'type' is a required property"); 1253 } 1254 // Invalid: test pmbus_read_sensor with no command. 1255 { 1256 json configFile = pmbusReadSensorFile; 1257 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1258 "command"); 1259 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1260 "u'command' is a required property"); 1261 } 1262 // Invalid: test pmbus_read_sensor with no format. 1263 { 1264 json configFile = pmbusReadSensorFile; 1265 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1266 "format"); 1267 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1268 "u'format' is a required property"); 1269 } 1270 // Invalid: test pmbus_read_sensor with property type wrong type. 1271 { 1272 json configFile = pmbusReadSensorFile; 1273 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1274 true; 1275 EXPECT_JSON_INVALID( 1276 configFile, "Validation failed.", 1277 "True is not one of [u'iout', u'iout_peak', u'iout_valley', " 1278 "u'pout', u'temperature', u'temperature_peak', u'vout', " 1279 "u'vout_peak', u'vout_valley']"); 1280 } 1281 // Invalid: test pmbus_read_sensor with property command wrong type. 1282 { 1283 json configFile = pmbusReadSensorFile; 1284 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1285 true; 1286 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1287 "True is not of type u'string'"); 1288 } 1289 // Invalid: test pmbus_read_sensor with property format wrong type. 1290 { 1291 json configFile = pmbusReadSensorFile; 1292 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1293 true; 1294 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1295 "True is not one of [u'linear_11', u'linear_16']"); 1296 } 1297 // Invalid: test pmbus_read_sensor with property exponent wrong type. 1298 { 1299 json configFile = pmbusReadSensorFile; 1300 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] = 1301 true; 1302 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1303 "True is not of type u'integer'"); 1304 } 1305 // Invalid: test pmbus_read_sensor with property type wrong format. 1306 { 1307 json configFile = pmbusReadSensorFile; 1308 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1309 "foo"; 1310 EXPECT_JSON_INVALID( 1311 configFile, "Validation failed.", 1312 "u'foo' is not one of [u'iout', u'iout_peak', u'iout_valley', " 1313 "u'pout', u'temperature', u'temperature_peak', u'vout', " 1314 "u'vout_peak', u'vout_valley']"); 1315 } 1316 // Invalid: test pmbus_read_sensor with property command wrong format. 1317 { 1318 json configFile = pmbusReadSensorFile; 1319 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1320 "0x8B0"; 1321 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1322 "u'0x8B0' does not match u'^0x[0-9a-fA-F]{2}$'"); 1323 } 1324 // Invalid: test pmbus_read_sensor with property format wrong format. 1325 { 1326 json configFile = pmbusReadSensorFile; 1327 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1328 "foo"; 1329 EXPECT_JSON_INVALID( 1330 configFile, "Validation failed.", 1331 "u'foo' is not one of [u'linear_11', u'linear_16']"); 1332 } 1333 } 1334 TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand) 1335 { 1336 json pmbusWriteVoutCommandFile = validConfigFile; 1337 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1338 ["pmbus_write_vout_command"]["volts"] = 1.03; 1339 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1340 ["pmbus_write_vout_command"]["format"] = "linear"; 1341 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1342 ["pmbus_write_vout_command"]["exponent"] = -8; 1343 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1344 ["pmbus_write_vout_command"]["is_verified"] = true; 1345 // Valid: test pmbus_write_vout_command. 1346 { 1347 json configFile = pmbusWriteVoutCommandFile; 1348 EXPECT_JSON_VALID(configFile); 1349 } 1350 // Valid: test pmbus_write_vout_command with required properties. 1351 { 1352 json configFile = pmbusWriteVoutCommandFile; 1353 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1354 "volts"); 1355 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1356 "exponent"); 1357 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1358 "is_verified"); 1359 EXPECT_JSON_VALID(configFile); 1360 } 1361 // Invalid: test pmbus_write_vout_command with no format. 1362 { 1363 json configFile = pmbusWriteVoutCommandFile; 1364 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1365 "format"); 1366 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1367 "u'format' is a required property"); 1368 } 1369 // Invalid: test pmbus_write_vout_command with property volts wrong type. 1370 { 1371 json configFile = pmbusWriteVoutCommandFile; 1372 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1373 ["volts"] = true; 1374 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1375 "True is not of type u'number'"); 1376 } 1377 // Invalid: test pmbus_write_vout_command with property format wrong type. 1378 { 1379 json configFile = pmbusWriteVoutCommandFile; 1380 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1381 ["format"] = true; 1382 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1383 "True is not one of [u'linear']"); 1384 } 1385 // Invalid: test pmbus_write_vout_command with property exponent wrong type. 1386 { 1387 json configFile = pmbusWriteVoutCommandFile; 1388 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1389 ["exponent"] = 1.3; 1390 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1391 "1.3 is not of type u'integer'"); 1392 } 1393 // Invalid: test pmbus_write_vout_command with property is_verified wrong 1394 // type. 1395 { 1396 json configFile = pmbusWriteVoutCommandFile; 1397 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1398 ["is_verified"] = 1; 1399 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1400 "1 is not of type u'boolean'"); 1401 } 1402 // Invalid: test pmbus_write_vout_command with property format wrong format. 1403 { 1404 json configFile = pmbusWriteVoutCommandFile; 1405 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1406 ["format"] = "foo"; 1407 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1408 "u'foo' is not one of [u'linear']"); 1409 } 1410 } 1411 TEST(ValidateRegulatorsConfigTest, RunRule) 1412 { 1413 json runRuleFile = validConfigFile; 1414 runRuleFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule1"; 1415 // Valid: test run_rule. 1416 { 1417 json configFile = runRuleFile; 1418 EXPECT_JSON_VALID(configFile); 1419 } 1420 // Invalid: test run_rule wrong type. 1421 { 1422 json configFile = runRuleFile; 1423 configFile["rules"][0]["actions"][1]["run_rule"] = true; 1424 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1425 "True is not of type u'string'"); 1426 } 1427 // Invalid: test run_rule wrong format. 1428 { 1429 json configFile = runRuleFile; 1430 configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%"; 1431 EXPECT_JSON_INVALID( 1432 configFile, "Validation failed.", 1433 "u'set_voltage_rule%' does not match u'^[A-Za-z0-9_]+$'"); 1434 } 1435 } 1436 TEST(ValidateRegulatorsConfigTest, SetDevice) 1437 { 1438 json setDeviceFile = validConfigFile; 1439 setDeviceFile["rules"][0]["actions"][1]["set_device"] = "io_expander2"; 1440 // Valid: test set_device. 1441 { 1442 json configFile = setDeviceFile; 1443 EXPECT_JSON_VALID(configFile); 1444 } 1445 // Invalid: test set_device wrong type. 1446 { 1447 json configFile = setDeviceFile; 1448 configFile["rules"][0]["actions"][1]["set_device"] = true; 1449 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1450 "True is not of type u'string'"); 1451 } 1452 // Invalid: test set_device wrong format. 1453 { 1454 json configFile = setDeviceFile; 1455 configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%"; 1456 EXPECT_JSON_INVALID( 1457 configFile, "Validation failed.", 1458 "u'io_expander2%' does not match u'^[A-Za-z0-9_]+$'"); 1459 } 1460 } 1461