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