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