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, I2CCompareBit) 542 { 543 json i2cCompareBitFile = validConfigFile; 544 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 545 "0xA0"; 546 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 547 3; 548 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1; 549 // Valid: test rule actions i2c_compare_bit. 550 { 551 json configFile = i2cCompareBitFile; 552 EXPECT_JSON_VALID(configFile); 553 } 554 // Invalid: test i2c_compare_bit with no register. 555 { 556 json configFile = i2cCompareBitFile; 557 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase( 558 "register"); 559 EXPECT_JSON_INVALID(configFile, "Validation failed.", 560 "u'register' is a required property"); 561 } 562 // Invalid: test i2c_compare_bit with no position. 563 { 564 json configFile = i2cCompareBitFile; 565 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase( 566 "position"); 567 EXPECT_JSON_INVALID(configFile, "Validation failed.", 568 "u'position' is a required property"); 569 } 570 // Invalid: test i2c_compare_bit with no value. 571 { 572 json configFile = i2cCompareBitFile; 573 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value"); 574 EXPECT_JSON_INVALID(configFile, "Validation failed.", 575 "u'value' is a required property"); 576 } 577 // Invalid: test i2c_compare_bit with register wrong type. 578 { 579 json configFile = i2cCompareBitFile; 580 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1; 581 EXPECT_JSON_INVALID(configFile, "Validation failed.", 582 "1 is not of type u'string'"); 583 } 584 // Invalid: test i2c_compare_bit with register wrong format. 585 { 586 json configFile = i2cCompareBitFile; 587 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 588 "0xA00"; 589 EXPECT_JSON_INVALID(configFile, "Validation failed.", 590 "u'0xA00' does not match u'^0x[0-9A-Fa-f]{2}$'"); 591 } 592 // Invalid: test i2c_compare_bit with position wrong type. 593 { 594 json configFile = i2cCompareBitFile; 595 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 596 3.1; 597 EXPECT_JSON_INVALID(configFile, "Validation failed.", 598 "3.1 is not of type u'integer'"); 599 } 600 // Invalid: test i2c_compare_bit with position greater than 7. 601 { 602 json configFile = i2cCompareBitFile; 603 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8; 604 EXPECT_JSON_INVALID(configFile, "Validation failed.", 605 "8 is greater than the maximum of 7"); 606 } 607 // Invalid: test i2c_compare_bit with position less than 0. 608 { 609 json configFile = i2cCompareBitFile; 610 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 611 -1; 612 EXPECT_JSON_INVALID(configFile, "Validation failed.", 613 "-1 is less than the minimum of 0"); 614 } 615 // Invalid: test i2c_compare_bit with value wrong type. 616 { 617 json configFile = i2cCompareBitFile; 618 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1"; 619 EXPECT_JSON_INVALID(configFile, "Validation failed.", 620 "u'1' is not of type u'integer'"); 621 } 622 // Invalid: test i2c_compare_bit with value greater than 1. 623 { 624 json configFile = i2cCompareBitFile; 625 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2; 626 EXPECT_JSON_INVALID(configFile, "Validation failed.", 627 "2 is greater than the maximum of 1"); 628 } 629 // Invalid: test i2c_compare_bit with value less than 0. 630 { 631 json configFile = i2cCompareBitFile; 632 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1; 633 EXPECT_JSON_INVALID(configFile, "Validation failed.", 634 "-1 is less than the minimum of 0"); 635 } 636 } 637 TEST(ValidateRegulatorsConfigTest, I2CCompareByte) 638 { 639 json i2cCompareByteFile = validConfigFile; 640 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"] 641 ["register"] = "0x82"; 642 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 643 "0x40"; 644 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 645 "0x7F"; 646 // Valid: test i2c_compare_byte with all properties. 647 { 648 json configFile = i2cCompareByteFile; 649 EXPECT_JSON_VALID(configFile); 650 } 651 // Valid: test i2c_compare_byte with all required properties. 652 { 653 json configFile = i2cCompareByteFile; 654 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask"); 655 EXPECT_JSON_VALID(configFile); 656 } 657 // Invalid: test i2c_compare_byte with no register. 658 { 659 json configFile = i2cCompareByteFile; 660 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase( 661 "register"); 662 EXPECT_JSON_INVALID(configFile, "Validation failed.", 663 "u'register' is a required property"); 664 } 665 // Invalid: test i2c_compare_byte with no value. 666 { 667 json configFile = i2cCompareByteFile; 668 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value"); 669 EXPECT_JSON_INVALID(configFile, "Validation failed.", 670 "u'value' is a required property"); 671 } 672 // Invalid: test i2c_compare_byte with property register wrong type. 673 { 674 json configFile = i2cCompareByteFile; 675 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 676 1; 677 EXPECT_JSON_INVALID(configFile, "Validation failed.", 678 "1 is not of type u'string'"); 679 } 680 // Invalid: test i2c_compare_byte with property value wrong type. 681 { 682 json configFile = i2cCompareByteFile; 683 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1; 684 EXPECT_JSON_INVALID(configFile, "Validation failed.", 685 "1 is not of type u'string'"); 686 } 687 // Invalid: test i2c_compare_byte with property mask wrong type. 688 { 689 json configFile = i2cCompareByteFile; 690 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1; 691 EXPECT_JSON_INVALID(configFile, "Validation failed.", 692 "1 is not of type u'string'"); 693 } 694 // Invalid: test i2c_compare_byte with property register more than 2 hex 695 // digits. 696 { 697 json configFile = i2cCompareByteFile; 698 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 699 "0x820"; 700 EXPECT_JSON_INVALID(configFile, "Validation failed.", 701 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 702 } 703 // Invalid: test i2c_compare_byte with property value more than 2 hex 704 // digits. 705 { 706 json configFile = i2cCompareByteFile; 707 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 708 "0x820"; 709 EXPECT_JSON_INVALID(configFile, "Validation failed.", 710 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 711 } 712 // Invalid: test i2c_compare_byte with property mask more than 2 hex digits. 713 { 714 json configFile = i2cCompareByteFile; 715 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 716 "0x820"; 717 EXPECT_JSON_INVALID(configFile, "Validation failed.", 718 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 719 } 720 // Invalid: test i2c_compare_byte with property register less than 2 hex 721 // digits. 722 { 723 json configFile = i2cCompareByteFile; 724 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 725 "0x8"; 726 EXPECT_JSON_INVALID(configFile, "Validation failed.", 727 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 728 } 729 // Invalid: test i2c_compare_byte with property value less than 2 hex 730 // digits. 731 { 732 json configFile = i2cCompareByteFile; 733 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 734 "0x8"; 735 EXPECT_JSON_INVALID(configFile, "Validation failed.", 736 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 737 } 738 // Invalid: test i2c_compare_byte with property mask less than 2 hex digits. 739 { 740 json configFile = i2cCompareByteFile; 741 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 742 "0x8"; 743 EXPECT_JSON_INVALID(configFile, "Validation failed.", 744 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 745 } 746 // Invalid: test i2c_compare_byte with property register no leading prefix. 747 { 748 json configFile = i2cCompareByteFile; 749 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 750 "82"; 751 EXPECT_JSON_INVALID(configFile, "Validation failed.", 752 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 753 } 754 // Invalid: test i2c_compare_byte with property value no leading prefix. 755 { 756 json configFile = i2cCompareByteFile; 757 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 758 "82"; 759 EXPECT_JSON_INVALID(configFile, "Validation failed.", 760 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 761 } 762 // Invalid: test i2c_compare_byte with property mask no leading prefix. 763 { 764 json configFile = i2cCompareByteFile; 765 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82"; 766 EXPECT_JSON_INVALID(configFile, "Validation failed.", 767 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 768 } 769 // Invalid: test i2c_compare_byte with property register invalid hex digit. 770 { 771 json configFile = i2cCompareByteFile; 772 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] = 773 "0xG1"; 774 EXPECT_JSON_INVALID(configFile, "Validation failed.", 775 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 776 } 777 // Invalid: test i2c_compare_byte with property value invalid hex digit. 778 { 779 json configFile = i2cCompareByteFile; 780 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 781 "0xG1"; 782 EXPECT_JSON_INVALID(configFile, "Validation failed.", 783 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 784 } 785 // Invalid: test i2c_compare_byte with property mask invalid hex digit. 786 { 787 json configFile = i2cCompareByteFile; 788 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 789 "0xG1"; 790 EXPECT_JSON_INVALID(configFile, "Validation failed.", 791 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 792 } 793 } 794 TEST(ValidateRegulatorsConfigTest, I2CCompareBytes) 795 { 796 json i2cCompareBytesFile = validConfigFile; 797 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"] 798 ["register"] = "0x82"; 799 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"] 800 ["values"] = {"0x02", "0x73"}; 801 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"] 802 ["masks"] = {"0x7F", "0x7F"}; 803 // Valid: test i2c_compare_bytes. 804 { 805 json configFile = i2cCompareBytesFile; 806 EXPECT_JSON_VALID(configFile); 807 } 808 // Valid: test i2c_compare_bytes with all required properties. 809 { 810 json configFile = i2cCompareBytesFile; 811 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase( 812 "masks"); 813 EXPECT_JSON_VALID(configFile); 814 } 815 // Invalid: test i2c_compare_bytes with no register. 816 { 817 json configFile = i2cCompareBytesFile; 818 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase( 819 "register"); 820 EXPECT_JSON_INVALID(configFile, "Validation failed.", 821 "u'register' is a required property"); 822 } 823 // Invalid: test i2c_compare_bytes with no values. 824 { 825 json configFile = i2cCompareBytesFile; 826 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase( 827 "values"); 828 EXPECT_JSON_INVALID(configFile, "Validation failed.", 829 "u'values' is a required property"); 830 } 831 // Invalid: test i2c_compare_bytes with property values as empty array. 832 { 833 json configFile = i2cCompareBytesFile; 834 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 835 json::array(); 836 EXPECT_JSON_INVALID(configFile, "Validation failed.", 837 "[] is too short"); 838 } 839 // Invalid: test i2c_compare_bytes with property masks as empty array. 840 { 841 json configFile = i2cCompareBytesFile; 842 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 843 json::array(); 844 EXPECT_JSON_INVALID(configFile, "Validation failed.", 845 "[] is too short"); 846 } 847 // Invalid: test i2c_compare_bytes with property register wrong type. 848 { 849 json configFile = i2cCompareBytesFile; 850 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 851 1; 852 EXPECT_JSON_INVALID(configFile, "Validation failed.", 853 "1 is not of type u'string'"); 854 } 855 // Invalid: test i2c_compare_bytes with property values wrong type. 856 { 857 json configFile = i2cCompareBytesFile; 858 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1; 859 EXPECT_JSON_INVALID(configFile, "Validation failed.", 860 "1 is not of type u'array'"); 861 } 862 // Invalid: test i2c_compare_bytes with property masks wrong type. 863 { 864 json configFile = i2cCompareBytesFile; 865 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1; 866 EXPECT_JSON_INVALID(configFile, "Validation failed.", 867 "1 is not of type u'array'"); 868 } 869 // Invalid: test i2c_compare_bytes with property register more than 2 hex 870 // digits. 871 { 872 json configFile = i2cCompareBytesFile; 873 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 874 "0x820"; 875 EXPECT_JSON_INVALID(configFile, "Validation failed.", 876 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 877 } 878 // Invalid: test i2c_compare_bytes with property values more than 2 hex 879 // digits. 880 { 881 json configFile = i2cCompareBytesFile; 882 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 883 "0x820"; 884 EXPECT_JSON_INVALID(configFile, "Validation failed.", 885 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 886 } 887 // Invalid: test i2c_compare_bytes with property masks more than 2 hex 888 // digits. 889 { 890 json configFile = i2cCompareBytesFile; 891 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 892 "0x820"; 893 EXPECT_JSON_INVALID(configFile, "Validation failed.", 894 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'"); 895 } 896 // Invalid: test i2c_compare_bytes with property register less than 2 hex 897 // digits. 898 { 899 json configFile = i2cCompareBytesFile; 900 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 901 "0x8"; 902 EXPECT_JSON_INVALID(configFile, "Validation failed.", 903 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 904 } 905 // Invalid: test i2c_compare_bytes with property values less than 2 hex 906 // digits. 907 { 908 json configFile = i2cCompareBytesFile; 909 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 910 "0x8"; 911 EXPECT_JSON_INVALID(configFile, "Validation failed.", 912 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 913 } 914 // Invalid: test i2c_compare_bytes with property masks less than 2 hex 915 // digits. 916 { 917 json configFile = i2cCompareBytesFile; 918 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 919 "0x8"; 920 EXPECT_JSON_INVALID(configFile, "Validation failed.", 921 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'"); 922 } 923 // Invalid: test i2c_compare_bytes with property register no leading prefix. 924 { 925 json configFile = i2cCompareBytesFile; 926 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 927 "82"; 928 EXPECT_JSON_INVALID(configFile, "Validation failed.", 929 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 930 } 931 // Invalid: test i2c_compare_bytes with property values no leading prefix. 932 { 933 json configFile = i2cCompareBytesFile; 934 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 935 "82"; 936 EXPECT_JSON_INVALID(configFile, "Validation failed.", 937 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 938 } 939 // Invalid: test i2c_compare_bytes with property masks no leading prefix. 940 { 941 json configFile = i2cCompareBytesFile; 942 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 943 "82"; 944 EXPECT_JSON_INVALID(configFile, "Validation failed.", 945 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'"); 946 } 947 // Invalid: test i2c_compare_bytes with property register invalid hex digit. 948 { 949 json configFile = i2cCompareBytesFile; 950 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] = 951 "0xG1"; 952 EXPECT_JSON_INVALID(configFile, "Validation failed.", 953 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 954 } 955 // Invalid: test i2c_compare_bytes with property values invalid hex digit. 956 { 957 json configFile = i2cCompareBytesFile; 958 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] = 959 "0xG1"; 960 EXPECT_JSON_INVALID(configFile, "Validation failed.", 961 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 962 } 963 // Invalid: test i2c_compare_bytes with property masks invalid hex digit. 964 { 965 json configFile = i2cCompareBytesFile; 966 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] = 967 "0xG1"; 968 EXPECT_JSON_INVALID(configFile, "Validation failed.", 969 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'"); 970 } 971 } 972 TEST(ValidateRegulatorsConfigTest, If) 973 { 974 json ifFile = validConfigFile; 975 ifFile["rules"][0]["actions"][1]["if"]["condition"]["run_rule"] = 976 "is_downlevel_regulator"; 977 ifFile["rules"][0]["actions"][1]["if"]["then"][0]["run_rule"] = 978 "configure_downlevel_regulator"; 979 ifFile["rules"][0]["actions"][1]["if"]["else"][0]["run_rule"] = 980 "configure_downlevel_regulator"; 981 // Valid: test if. 982 { 983 json configFile = ifFile; 984 EXPECT_JSON_VALID(configFile); 985 } 986 // Valid: test if with required properties. 987 { 988 json configFile = ifFile; 989 configFile["rules"][0]["actions"][1]["if"].erase("else"); 990 EXPECT_JSON_VALID(configFile); 991 } 992 // Invalid: test if with no property condition. 993 { 994 json configFile = ifFile; 995 configFile["rules"][0]["actions"][1]["if"].erase("condition"); 996 EXPECT_JSON_INVALID(configFile, "Validation failed.", 997 "u'condition' is a required property"); 998 } 999 // Invalid: test if with no property then. 1000 { 1001 json configFile = ifFile; 1002 configFile["rules"][0]["actions"][1]["if"].erase("then"); 1003 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1004 "u'then' is a required property"); 1005 } 1006 // Invalid: test if with property then empty array. 1007 { 1008 json configFile = ifFile; 1009 configFile["rules"][0]["actions"][1]["if"]["then"] = json::array(); 1010 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1011 "[] is too short"); 1012 } 1013 // Invalid: test if with property else empty array. 1014 { 1015 json configFile = ifFile; 1016 configFile["rules"][0]["actions"][1]["if"]["else"] = json::array(); 1017 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1018 "[] is too short"); 1019 } 1020 // Invalid: test if with property condition wrong type. 1021 { 1022 json configFile = ifFile; 1023 configFile["rules"][0]["actions"][1]["if"]["condition"] = 1; 1024 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1025 "1 is not of type u'object'"); 1026 } 1027 // Invalid: test if with property then wrong type. 1028 { 1029 json configFile = ifFile; 1030 configFile["rules"][0]["actions"][1]["if"]["then"] = 1; 1031 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1032 "1 is not of type u'array'"); 1033 } 1034 // Invalid: test if with property else wrong type. 1035 { 1036 json configFile = ifFile; 1037 configFile["rules"][0]["actions"][1]["if"]["else"] = 1; 1038 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1039 "1 is not of type u'array'"); 1040 } 1041 } 1042 TEST(ValidateRegulatorsConfigTest, Not) 1043 { 1044 json notFile = validConfigFile; 1045 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] = 1046 "0xA0"; 1047 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] = 1048 "0xFF"; 1049 // Valid: test not. 1050 { 1051 json configFile = notFile; 1052 EXPECT_JSON_VALID(configFile); 1053 } 1054 // Invalid: test not with wrong type. 1055 { 1056 json configFile = notFile; 1057 configFile["rules"][0]["actions"][1]["not"] = 1; 1058 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1059 "1 is not of type u'object'"); 1060 } 1061 } 1062 TEST(ValidateRegulatorsConfigTest, Or) 1063 { 1064 json orFile = validConfigFile; 1065 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] = 1066 "0xA0"; 1067 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] = 1068 "0x00"; 1069 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] = 1070 "0xA1"; 1071 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] = 1072 "0x00"; 1073 // Valid: test or. 1074 { 1075 json configFile = orFile; 1076 EXPECT_JSON_VALID(configFile); 1077 } 1078 // Invalid: test or with empty array. 1079 { 1080 json configFile = orFile; 1081 configFile["rules"][0]["actions"][1]["or"] = json::array(); 1082 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1083 "[] is too short"); 1084 } 1085 // Invalid: test or with wrong type. 1086 { 1087 json configFile = orFile; 1088 configFile["rules"][0]["actions"][1]["or"] = 1; 1089 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1090 "1 is not of type u'array'"); 1091 } 1092 } 1093 TEST(ValidateRegulatorsConfigTest, PmbusReadSensor) 1094 { 1095 json pmbusReadSensorFile = validConfigFile; 1096 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1097 "vout"; 1098 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1099 ["command"] = "0x8B"; 1100 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1101 ["format"] = "linear_16"; 1102 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"] 1103 ["exponent"] = -8; 1104 // Valid: test pmbus_read_sensor. 1105 { 1106 json configFile = pmbusReadSensorFile; 1107 EXPECT_JSON_VALID(configFile); 1108 } 1109 // Valid: test pmbus_read_sensor with required properties. 1110 { 1111 json configFile = pmbusReadSensorFile; 1112 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1113 "exponent"); 1114 EXPECT_JSON_VALID(configFile); 1115 } 1116 // Invalid: test pmbus_read_sensor with no type. 1117 { 1118 json configFile = pmbusReadSensorFile; 1119 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type"); 1120 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1121 "u'type' is a required property"); 1122 } 1123 // Invalid: test pmbus_read_sensor with no command. 1124 { 1125 json configFile = pmbusReadSensorFile; 1126 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1127 "command"); 1128 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1129 "u'command' is a required property"); 1130 } 1131 // Invalid: test pmbus_read_sensor with no format. 1132 { 1133 json configFile = pmbusReadSensorFile; 1134 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase( 1135 "format"); 1136 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1137 "u'format' is a required property"); 1138 } 1139 // Invalid: test pmbus_read_sensor with property type wrong type. 1140 { 1141 json configFile = pmbusReadSensorFile; 1142 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1143 true; 1144 EXPECT_JSON_INVALID( 1145 configFile, "Validation failed.", 1146 "True is not one of [u'iout', u'iout_peak', u'iout_valley', " 1147 "u'pout', u'temperature', u'temperature_peak', u'vout', " 1148 "u'vout_peak', u'vout_valley']"); 1149 } 1150 // Invalid: test pmbus_read_sensor with property command wrong type. 1151 { 1152 json configFile = pmbusReadSensorFile; 1153 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1154 true; 1155 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1156 "True is not of type u'string'"); 1157 } 1158 // Invalid: test pmbus_read_sensor with property format wrong type. 1159 { 1160 json configFile = pmbusReadSensorFile; 1161 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1162 true; 1163 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1164 "True is not one of [u'linear_11', u'linear_16']"); 1165 } 1166 // Invalid: test pmbus_read_sensor with property exponent wrong type. 1167 { 1168 json configFile = pmbusReadSensorFile; 1169 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] = 1170 true; 1171 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1172 "True is not of type u'integer'"); 1173 } 1174 // Invalid: test pmbus_read_sensor with property type wrong format. 1175 { 1176 json configFile = pmbusReadSensorFile; 1177 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] = 1178 "foo"; 1179 EXPECT_JSON_INVALID( 1180 configFile, "Validation failed.", 1181 "u'foo' is not one of [u'iout', u'iout_peak', u'iout_valley', " 1182 "u'pout', u'temperature', u'temperature_peak', u'vout', " 1183 "u'vout_peak', u'vout_valley']"); 1184 } 1185 // Invalid: test pmbus_read_sensor with property command wrong format. 1186 { 1187 json configFile = pmbusReadSensorFile; 1188 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] = 1189 "0x8B0"; 1190 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1191 "u'0x8B0' does not match u'^0x[0-9a-fA-F]{2}$'"); 1192 } 1193 // Invalid: test pmbus_read_sensor with property format wrong format. 1194 { 1195 json configFile = pmbusReadSensorFile; 1196 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] = 1197 "foo"; 1198 EXPECT_JSON_INVALID( 1199 configFile, "Validation failed.", 1200 "u'foo' is not one of [u'linear_11', u'linear_16']"); 1201 } 1202 } 1203 TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand) 1204 { 1205 json pmbusWriteVoutCommandFile = validConfigFile; 1206 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1207 ["pmbus_write_vout_command"]["volts"] = 1.03; 1208 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1209 ["pmbus_write_vout_command"]["format"] = "linear"; 1210 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1211 ["pmbus_write_vout_command"]["exponent"] = -8; 1212 pmbusWriteVoutCommandFile["rules"][0]["actions"][1] 1213 ["pmbus_write_vout_command"]["is_verified"] = true; 1214 // Valid: test pmbus_write_vout_command. 1215 { 1216 json configFile = pmbusWriteVoutCommandFile; 1217 EXPECT_JSON_VALID(configFile); 1218 } 1219 // Valid: test pmbus_write_vout_command with required properties. 1220 { 1221 json configFile = pmbusWriteVoutCommandFile; 1222 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1223 "volts"); 1224 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1225 "exponent"); 1226 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1227 "is_verified"); 1228 EXPECT_JSON_VALID(configFile); 1229 } 1230 // Invalid: test pmbus_write_vout_command with no format. 1231 { 1232 json configFile = pmbusWriteVoutCommandFile; 1233 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase( 1234 "format"); 1235 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1236 "u'format' is a required property"); 1237 } 1238 // Invalid: test pmbus_write_vout_command with property volts wrong type. 1239 { 1240 json configFile = pmbusWriteVoutCommandFile; 1241 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1242 ["volts"] = true; 1243 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1244 "True is not of type u'number'"); 1245 } 1246 // Invalid: test pmbus_write_vout_command with property format wrong type. 1247 { 1248 json configFile = pmbusWriteVoutCommandFile; 1249 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1250 ["format"] = true; 1251 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1252 "True is not one of [u'linear']"); 1253 } 1254 // Invalid: test pmbus_write_vout_command with property exponent wrong type. 1255 { 1256 json configFile = pmbusWriteVoutCommandFile; 1257 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1258 ["exponent"] = 1.3; 1259 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1260 "1.3 is not of type u'integer'"); 1261 } 1262 // Invalid: test pmbus_write_vout_command with property is_verified wrong 1263 // type. 1264 { 1265 json configFile = pmbusWriteVoutCommandFile; 1266 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1267 ["is_verified"] = 1; 1268 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1269 "1 is not of type u'boolean'"); 1270 } 1271 // Invalid: test pmbus_write_vout_command with property format wrong format. 1272 { 1273 json configFile = pmbusWriteVoutCommandFile; 1274 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"] 1275 ["format"] = "foo"; 1276 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1277 "u'foo' is not one of [u'linear']"); 1278 } 1279 } 1280 TEST(ValidateRegulatorsConfigTest, RunRule) 1281 { 1282 json runRuleFile = validConfigFile; 1283 runRuleFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule1"; 1284 // Valid: test run_rule. 1285 { 1286 json configFile = runRuleFile; 1287 EXPECT_JSON_VALID(configFile); 1288 } 1289 // Invalid: test run_rule wrong type. 1290 { 1291 json configFile = runRuleFile; 1292 configFile["rules"][0]["actions"][1]["run_rule"] = true; 1293 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1294 "True is not of type u'string'"); 1295 } 1296 // Invalid: test run_rule wrong format. 1297 { 1298 json configFile = runRuleFile; 1299 configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%"; 1300 EXPECT_JSON_INVALID( 1301 configFile, "Validation failed.", 1302 "u'set_voltage_rule%' does not match u'^[A-Za-z0-9_]+$'"); 1303 } 1304 } 1305 TEST(ValidateRegulatorsConfigTest, SetDevice) 1306 { 1307 json setDeviceFile = validConfigFile; 1308 setDeviceFile["rules"][0]["actions"][1]["set_device"] = "io_expander2"; 1309 // Valid: test set_device. 1310 { 1311 json configFile = setDeviceFile; 1312 EXPECT_JSON_VALID(configFile); 1313 } 1314 // Invalid: test set_device wrong type. 1315 { 1316 json configFile = setDeviceFile; 1317 configFile["rules"][0]["actions"][1]["set_device"] = true; 1318 EXPECT_JSON_INVALID(configFile, "Validation failed.", 1319 "True is not of type u'string'"); 1320 } 1321 // Invalid: test set_device wrong format. 1322 { 1323 json configFile = setDeviceFile; 1324 configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%"; 1325 EXPECT_JSON_INVALID( 1326 configFile, "Validation failed.", 1327 "u'io_expander2%' does not match u'^[A-Za-z0-9_]+$'"); 1328 } 1329 } 1330