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