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