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