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