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