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
getValidationToolCommand(const std::string & configFileName)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
runToolForOutputWithCommand(std::string command,std::string & standardOutput,std::string & standardError)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
runToolForOutput(const std::string & configFileName,std::string & output,std::string & error)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
expectFileValid(const std::string & configFileName)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
expectFileInvalid(const std::string & configFileName,const std::string & expectedErrorMessage,const std::string & expectedOutputMessage)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
writeDataToFile(const json configFileJson,std::string fileName)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
expectJsonValid(const json configFileJson)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
expectJsonInvalid(const json configFileJson,const std::string & expectedErrorMessage,const std::string & expectedOutputMessage)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
expectCommandLineSyntax(const std::string & expectedErrorMessage,const std::string & expectedOutputMessage,const std::string & command,int status)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
TEST(ValidateRegulatorsConfigTest,Action)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
TEST(ValidateRegulatorsConfigTest,And)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
TEST(ValidateRegulatorsConfigTest,Chassis)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
TEST(ValidateRegulatorsConfigTest,ComparePresence)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
TEST(ValidateRegulatorsConfigTest,CompareVpd)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
TEST(ValidateRegulatorsConfigTest,ConfigFile)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
TEST(ValidateRegulatorsConfigTest,Configuration)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
TEST(ValidateRegulatorsConfigTest,Device)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
TEST(ValidateRegulatorsConfigTest,I2CCaptureBytes)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
TEST(ValidateRegulatorsConfigTest,I2CCompareBit)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
TEST(ValidateRegulatorsConfigTest,I2CCompareByte)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
TEST(ValidateRegulatorsConfigTest,I2CCompareBytes)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
TEST(ValidateRegulatorsConfigTest,I2CInterface)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
TEST(ValidateRegulatorsConfigTest,I2CWriteBit)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
TEST(ValidateRegulatorsConfigTest,I2CWriteByte)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
TEST(ValidateRegulatorsConfigTest,I2CWriteBytes)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
TEST(ValidateRegulatorsConfigTest,If)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
TEST(ValidateRegulatorsConfigTest,LogPhaseFault)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
TEST(ValidateRegulatorsConfigTest,Not)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
TEST(ValidateRegulatorsConfigTest,Or)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
TEST(ValidateRegulatorsConfigTest,PhaseFaultDetection)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
TEST(ValidateRegulatorsConfigTest,PmbusReadSensor)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
TEST(ValidateRegulatorsConfigTest,PmbusWriteVoutCommand)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
TEST(ValidateRegulatorsConfigTest,PresenceDetection)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
TEST(ValidateRegulatorsConfigTest,Rail)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
TEST(ValidateRegulatorsConfigTest,Rule)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
TEST(ValidateRegulatorsConfigTest,RunRule)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
TEST(ValidateRegulatorsConfigTest,SensorMonitoring)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
TEST(ValidateRegulatorsConfigTest,SetDevice)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
TEST(ValidateRegulatorsConfigTest,DuplicateRuleID)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
TEST(ValidateRegulatorsConfigTest,DuplicateChassisNumber)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
TEST(ValidateRegulatorsConfigTest,DuplicateDeviceID)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
TEST(ValidateRegulatorsConfigTest,DuplicateRailID)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
TEST(ValidateRegulatorsConfigTest,DuplicateObjectID)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
TEST(ValidateRegulatorsConfigTest,InfiniteLoops)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
TEST(ValidateRegulatorsConfigTest,RunRuleValueExists)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
TEST(ValidateRegulatorsConfigTest,SetDeviceValueExists)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
TEST(ValidateRegulatorsConfigTest,RuleIDExists)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
TEST(ValidateRegulatorsConfigTest,DeviceIDExists)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
TEST(ValidateRegulatorsConfigTest,NumberOfElementsInMasks)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
TEST(ValidateRegulatorsConfigTest,CommandLineSyntax)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