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