blob: 46ffd6aa090bf5e810e907dd691aa4308394a7cc [file] [log] [blame]
Bob King386d33f2019-12-26 17:28:56 +08001/**
Bob King0dcbdf52020-01-20 17:19:39 +08002 * Copyright c 2020 IBM Corporation
Bob King386d33f2019-12-26 17:28:56 +08003 *
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 <errno.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/wait.h>
20
Bob King386d33f2019-12-26 17:28:56 +080021#include <nlohmann/json.hpp>
22
Bob King0dcbdf52020-01-20 17:19:39 +080023#include <fstream>
24
Bob King386d33f2019-12-26 17:28:56 +080025#include <gtest/gtest.h>
26
27#define EXPECT_FILE_VALID(configFile) expectFileValid(configFile)
28#define EXPECT_FILE_INVALID(configFile, expectedErrorMessage, \
29 expectedOutputMessage) \
30 expectFileInvalid(configFile, expectedErrorMessage, expectedOutputMessage)
31#define EXPECT_JSON_VALID(configFileJson) expectJsonValid(configFileJson)
32#define EXPECT_JSON_INVALID(configFileJson, expectedErrorMessage, \
33 expectedOutputMessage) \
34 expectJsonInvalid(configFileJson, expectedErrorMessage, \
35 expectedOutputMessage)
36
37using json = nlohmann::json;
38
39const json validConfigFile = R"(
40 {
41 "comments": [ "Config file for a FooBar one-chassis system" ],
42
43 "rules": [
44 {
45 "comments": [ "Sets output voltage for a PMBus regulator rail" ],
46 "id": "set_voltage_rule",
47 "actions": [
48 {
49 "pmbus_write_vout_command": {
50 "format": "linear"
51 }
52 }
53 ]
54 }
55 ],
56
57 "chassis": [
58 {
59 "comments": [ "Chassis number 1 containing CPUs and memory" ],
60 "number": 1,
61 "devices": [
62 {
63 "comments": [ "IR35221 regulator producing the Vdd rail" ],
64 "id": "vdd_regulator",
65 "is_regulator": true,
66 "fru": "/system/chassis/motherboard/regulator1",
67 "i2c_interface": {
68 "bus": 1,
69 "address": "0x70"
70 },
71 "rails": [
72 {
73 "comments": [ "Vdd rail" ],
74 "id": "vdd",
75 "configuration": {
76 "volts": 1.03,
77 "rule_id": "set_voltage_rule"
78 },
79 "sensor_monitoring": {
80 "rule_id": "read_sensors_rule"
81 }
82 }
83 ]
84 }
85 ]
86 }
87 ]
88 }
89)"_json;
90
91std::string createTmpFile()
92{
93 // create temporary file using mkstemp under /tmp/. random name for XXXXXX
94 char fileName[] = "/tmp/temp-XXXXXX";
95 int fd = mkstemp(fileName);
96 if (fd == -1)
97 {
98 perror("Can't create temporary file");
99 }
100 close(fd);
101 return fileName;
102}
103
104std::string getValidationToolCommand(const std::string& configFileName)
105{
106 std::string command = "python ../tools/validate-regulators-config.py -s \
107 ../schema/config_schema.json -c ";
108 command += configFileName;
109 return command;
110}
111
112int runToolForOutput(const std::string& configFileName, std::string& output,
113 bool isReadingStderr = false)
114{
115 // run the validation tool with the temporary file and return the output
116 // of the validation tool.
117 std::string command = getValidationToolCommand(configFileName);
118 // reading the stderr while isReadingStderr is true.
119 if (isReadingStderr == true)
120 {
121 command += " 2>&1 >/dev/null";
122 }
123 // get the jsonschema print from validation tool.
124 char buffer[256];
125 std::string result = "";
126 // to get the stdout from the validation tool.
127 FILE* pipe = popen(command.c_str(), "r");
128 if (!pipe)
129 {
130 throw std::runtime_error("popen() failed!");
131 }
132 while (!std::feof(pipe))
133 {
134 if (fgets(buffer, sizeof buffer, pipe) != NULL)
135 {
136 result += buffer;
137 }
138 }
139 int returnValue = pclose(pipe);
140 // Check if pclose() failed
141 if (returnValue == -1)
142 {
143 // unable to close pipe. Print error and exit function.
144 throw std::runtime_error("pclose() failed!");
145 }
146 std::string firstLine = result.substr(0, result.find('\n'));
147 output = firstLine;
148 // Get command exit status from return value
149 int exitStatus = WEXITSTATUS(returnValue);
150 return exitStatus;
151}
152
153void expectFileValid(const std::string& configFileName)
154{
155 std::string errorMessage = "";
156 std::string outputMessage = "";
157 EXPECT_EQ(runToolForOutput(configFileName, errorMessage, true), 0);
158 EXPECT_EQ(runToolForOutput(configFileName, outputMessage), 0);
159 EXPECT_EQ(errorMessage, "");
160 EXPECT_EQ(outputMessage, "");
161}
162
163void expectFileInvalid(const std::string& configFileName,
164 const std::string& expectedErrorMessage,
165 const std::string& expectedOutputMessage)
166{
167 std::string errorMessage = "";
168 std::string outputMessage = "";
169 EXPECT_EQ(runToolForOutput(configFileName, errorMessage, true), 1);
170 EXPECT_EQ(runToolForOutput(configFileName, outputMessage), 1);
171 EXPECT_EQ(errorMessage, expectedErrorMessage);
172 EXPECT_EQ(outputMessage, expectedOutputMessage);
173}
174
175void expectJsonValid(const json configFileJson)
176{
177 std::string fileName;
178 fileName = createTmpFile();
179 std::string jsonData = configFileJson.dump();
180 std::ofstream out(fileName);
181 out << jsonData;
182 out.close();
183
184 EXPECT_FILE_VALID(fileName);
185 unlink(fileName.c_str());
186}
187
188void expectJsonInvalid(const json configFileJson,
189 const std::string& expectedErrorMessage,
190 const std::string& expectedOutputMessage)
191{
192 std::string fileName;
193 fileName = createTmpFile();
194 std::string jsonData = configFileJson.dump();
195 std::ofstream out(fileName);
196 out << jsonData;
197 out.close();
198
199 EXPECT_FILE_INVALID(fileName, expectedErrorMessage, expectedOutputMessage);
200 unlink(fileName.c_str());
201}
202
Bob Kingbeaf6532020-01-21 11:03:49 +0800203TEST(ValidateRegulatorsConfigTest, And)
204{
205 // Valid.
206 {
207 json configFile = validConfigFile;
208 json andAction =
209 R"(
210 {
211 "and": [
212 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
213 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
214 ]
215 }
216 )"_json;
217 configFile["rules"][0]["actions"].push_back(andAction);
218 EXPECT_JSON_VALID(configFile);
219 }
220
221 // Invalid: actions property value is an empty array.
222 {
223 json configFile = validConfigFile;
224 json andAction =
225 R"(
226 {
227 "and": []
228 }
229 )"_json;
230 configFile["rules"][0]["actions"].push_back(andAction);
231 EXPECT_JSON_INVALID(configFile, "Validation failed.",
232 "[] is too short");
233 }
234
235 // Invalid: actions property has incorrect value data type.
236 {
237 json configFile = validConfigFile;
238 json andAction =
239 R"(
240 {
241 "and": true
242 }
243 )"_json;
244 configFile["rules"][0]["actions"].push_back(andAction);
245 EXPECT_JSON_INVALID(configFile, "Validation failed.",
246 "True is not of type u'array'");
247 }
248
249 // Invalid: actions property value contains wrong element type
250 {
251 json configFile = validConfigFile;
252 json andAction =
253 R"(
254 {
255 "and": ["foo"]
256 }
257 )"_json;
258 configFile["rules"][0]["actions"].push_back(andAction);
259 EXPECT_JSON_INVALID(configFile, "Validation failed.",
260 "u'foo' is not of type u'object'");
261 }
262}
Bob King3728f562020-01-21 11:35:31 +0800263TEST(ValidateRegulatorsConfigTest, Chassis)
264{
265 // Valid: test chassis.
266 {
267 json configFile = validConfigFile;
268 EXPECT_JSON_VALID(configFile);
269 }
270 // Valid: test chassis with required properties.
271 {
272 json configFile = validConfigFile;
273 configFile["chassis"][0].erase("comments");
274 configFile["chassis"][0].erase("devices");
275 EXPECT_JSON_VALID(configFile);
276 }
277 // Invalid: test chassis with no number.
278 {
279 json configFile = validConfigFile;
280 configFile["chassis"][0].erase("number");
281 EXPECT_JSON_INVALID(configFile, "Validation failed.",
282 "u'number' is a required property");
283 }
284 // Invalid: test chassis with property comments wrong type.
285 {
286 json configFile = validConfigFile;
287 configFile["chassis"][0]["comments"] = true;
288 EXPECT_JSON_INVALID(configFile, "Validation failed.",
289 "True is not of type u'array'");
290 }
291 // Invalid: test chassis with property number wrong type.
292 {
293 json configFile = validConfigFile;
294 configFile["chassis"][0]["number"] = 1.3;
295 EXPECT_JSON_INVALID(configFile, "Validation failed.",
296 "1.3 is not of type u'integer'");
297 }
298 // Invalid: test chassis with property devices wrong type.
299 {
300 json configFile = validConfigFile;
301 configFile["chassis"][0]["devices"] = true;
302 EXPECT_JSON_INVALID(configFile, "Validation failed.",
303 "True is not of type u'array'");
304 }
305 // Invalid: test chassis with property comments empty array.
306 {
307 json configFile = validConfigFile;
308 configFile["chassis"][0]["comments"] = json::array();
309 EXPECT_JSON_INVALID(configFile, "Validation failed.",
310 "[] is too short");
311 }
312 // Invalid: test chassis with property devices empty array.
313 {
314 json configFile = validConfigFile;
315 configFile["chassis"][0]["devices"] = json::array();
316 EXPECT_JSON_INVALID(configFile, "Validation failed.",
317 "[] is too short");
318 }
319 // Invalid: test chassis with property number less than 1.
320 {
321 json configFile = validConfigFile;
322 configFile["chassis"][0]["number"] = 0;
323 EXPECT_JSON_INVALID(configFile, "Validation failed.",
324 "0 is less than the minimum of 1");
325 }
326}
Bob Kingbf1cbea2020-01-21 11:08:50 +0800327TEST(ValidateRegulatorsConfigTest, ComparePresence)
328{
329 json comparePresenceFile = validConfigFile;
330 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
331 "/system/chassis/motherboard/regulator2";
332 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
333 true;
334 // Valid.
335 {
336 json configFile = comparePresenceFile;
337 EXPECT_JSON_VALID(configFile);
338 }
339
340 // Invalid: no FRU property.
341 {
342 json configFile = comparePresenceFile;
343 configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru");
344 EXPECT_JSON_INVALID(configFile, "Validation failed.",
345 "u'fru' is a required property");
346 }
347
348 // Invalid: FRU property length is string less than 1.
349 {
350 json configFile = comparePresenceFile;
351 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = "";
352 EXPECT_JSON_INVALID(configFile, "Validation failed.",
353 "u'' is too short");
354 }
355
356 // Invalid: no value property.
357 {
358 json configFile = comparePresenceFile;
359 configFile["rules"][0]["actions"][1]["compare_presence"].erase("value");
360 EXPECT_JSON_INVALID(configFile, "Validation failed.",
361 "u'value' is a required property");
362 }
363
364 // Invalid: value property type is not boolean.
365 {
366 json configFile = comparePresenceFile;
367 configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1";
368 EXPECT_JSON_INVALID(configFile, "Validation failed.",
369 "u'1' is not of type u'boolean'");
370 }
371
372 // Invalid: FRU property type is not string.
373 {
374 json configFile = comparePresenceFile;
375 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1;
376 EXPECT_JSON_INVALID(configFile, "Validation failed.",
377 "1 is not of type u'string'");
378 }
379}
Bob Kingf8b77a02020-01-21 11:09:47 +0800380TEST(ValidateRegulatorsConfigTest, CompareVpd)
381{
382 json compareVpdFile = validConfigFile;
383 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
384 "/system/chassis/motherboard/regulator2";
385 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
386 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
387
388 // Valid.
389 {
390 json configFile = compareVpdFile;
391 EXPECT_JSON_VALID(configFile);
392 }
393
394 // Invalid: no FRU property.
395 {
396 json configFile = compareVpdFile;
397 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru");
398 EXPECT_JSON_INVALID(configFile, "Validation failed.",
399 "u'fru' is a required property");
400 }
401
402 // Invalid: no keyword property.
403 {
404 json configFile = compareVpdFile;
405 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword");
406 EXPECT_JSON_INVALID(configFile, "Validation failed.",
407 "u'keyword' is a required property");
408 }
409
410 // Invalid: no value property.
411 {
412 json configFile = compareVpdFile;
413 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
414 EXPECT_JSON_INVALID(configFile, "Validation failed.",
415 "u'value' is a required property");
416 }
417
418 // Invalid: property FRU wrong type.
419 {
420 json configFile = compareVpdFile;
421 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1;
422 EXPECT_JSON_INVALID(configFile, "Validation failed.",
423 "1 is not of type u'string'");
424 }
425
426 // Invalid: property FRU is string less than 1.
427 {
428 json configFile = compareVpdFile;
429 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = "";
430 EXPECT_JSON_INVALID(configFile, "Validation failed.",
431 "u'' is too short");
432 }
433
434 // Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
435 // "PartNumber"
436 {
437 json configFile = compareVpdFile;
438 configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
439 "Number";
440 EXPECT_JSON_INVALID(configFile, "Validation failed.",
441 "u'Number' is not one of [u'CCIN', "
442 "u'Manufacturer', u'Model', u'PartNumber']");
443 }
444
445 // Invalid: property value wrong type.
446 {
447 json configFile = compareVpdFile;
448 configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1;
449 EXPECT_JSON_INVALID(configFile, "Validation failed.",
450 "1 is not of type u'string'");
451 }
452}
Bob King4c67a3a2020-02-07 09:48:11 +0800453TEST(ValidateRegulatorsConfigTest, Configuration)
454{
455 json configurationFile = validConfigFile;
456 configurationFile["chassis"][0]["devices"][0]["configuration"]["comments"]
457 [0] = "Set rail to 1.25V using standard rule";
458 configurationFile["chassis"][0]["devices"][0]["configuration"]["volts"] =
459 1.25;
460 configurationFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
461 "set_voltage_rule";
462 // Valid: test configuration with property rule_id and with no actions.
463 {
464 json configFile = configurationFile;
465 EXPECT_JSON_VALID(configFile);
466 }
467 // Valid: test configuration with property actions and with no rule_id.
468 {
469 json configFile = configurationFile;
470 configFile["chassis"][0]["devices"][0]["configuration"].erase(
471 "rule_id");
472 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
473 ["compare_presence"]["fru"] =
474 "/system/chassis/motherboard/cpu3";
475 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
476 ["compare_presence"]["value"] = true;
477 EXPECT_JSON_VALID(configFile);
478 }
479 // Valid: comments not specified (optional property).
480 {
481 json configFile = configurationFile;
482 configFile["chassis"][0]["devices"][0]["configuration"].erase(
483 "comments");
484 EXPECT_JSON_VALID(configFile);
485 }
486 // Valid: volts not specified (optional property).
487 {
488 json configFile = configurationFile;
489 configFile["chassis"][0]["devices"][0]["configuration"].erase("volts");
490 EXPECT_JSON_VALID(configFile);
491 }
492 // Valid: configuration is property of a rail (vs. a device).
493 {
494 json configFile = validConfigFile;
495 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
496 ["comments"][0] = "Set rail to 1.25V using standard rule";
497 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
498 ["volts"] = 1.25;
499 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
500 ["rule_id"] = "set_voltage_rule";
501 EXPECT_JSON_VALID(configFile);
502 }
503 // Invalid: comments property has wrong data type (not an array).
504 {
505 json configFile = configurationFile;
506 configFile["chassis"][0]["devices"][0]["configuration"]["comments"] = 1;
507 EXPECT_JSON_INVALID(configFile, "Validation failed.",
508 "1 is not of type u'array'");
509 }
510 // Invalid: test configuration with both actions and rule_id properties.
511 {
512 json configFile = configurationFile;
513 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
514 ["compare_presence"]["fru"] =
515 "/system/chassis/motherboard/cpu3";
516 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
517 ["compare_presence"]["value"] = true;
518 EXPECT_JSON_INVALID(
519 configFile, "Validation failed.",
520 "{u'volts': 1.25, u'comments': [u'Set rail to 1.25V using standard "
521 "rule'], u'actions': [{u'compare_presence': {u'value': True, "
522 "u'fru': u'/system/chassis/motherboard/cpu3'}}], u'rule_id': "
523 "u'set_voltage_rule'} is valid under each of {u'required': "
524 "[u'actions']}, {u'required': [u'rule_id']}");
525 }
526 // Invalid: test configuration with no rule_id and actions.
527 {
528 json configFile = configurationFile;
529 configFile["chassis"][0]["devices"][0]["configuration"].erase(
530 "rule_id");
531 EXPECT_JSON_INVALID(configFile, "Validation failed.",
532 "u'rule_id' is a required property");
533 }
534 // Invalid: test configuration with property volts wrong type.
535 {
536 json configFile = configurationFile;
537 configFile["chassis"][0]["devices"][0]["configuration"]["volts"] = true;
538 EXPECT_JSON_INVALID(configFile, "Validation failed.",
539 "True is not of type u'number'");
540 }
541 // Invalid: test configuration with property rule_id wrong type.
542 {
543 json configFile = configurationFile;
544 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
545 true;
546 EXPECT_JSON_INVALID(configFile, "Validation failed.",
547 "True is not of type u'string'");
548 }
549 // Invalid: test configuration with property actions wrong type.
550 {
551 json configFile = configurationFile;
552 configFile["chassis"][0]["devices"][0]["configuration"].erase(
553 "rule_id");
554 configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
555 true;
556 EXPECT_JSON_INVALID(configFile, "Validation failed.",
557 "True is not of type u'array'");
558 }
559 // Invalid: test configuration with property comments empty array.
560 {
561 json configFile = configurationFile;
562 configFile["chassis"][0]["devices"][0]["configuration"]["comments"] =
563 json::array();
564 EXPECT_JSON_INVALID(configFile, "Validation failed.",
565 "[] is too short");
566 }
567 // Invalid: test configuration with property rule_id wrong format.
568 {
569 json configFile = configurationFile;
570 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
571 "id!";
572 EXPECT_JSON_INVALID(configFile, "Validation failed.",
573 "u'id!' does not match u'^[A-Za-z0-9_]+$'");
574 }
575 // Invalid: test configuration with property actions empty array.
576 {
577 json configFile = configurationFile;
578 configFile["chassis"][0]["devices"][0]["configuration"].erase(
579 "rule_id");
580 configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
581 json::array();
582 EXPECT_JSON_INVALID(configFile, "Validation failed.",
583 "[] is too short");
584 }
585}
Bob Kinga2ba2df2020-02-04 14:38:44 +0800586TEST(ValidateRegulatorsConfigTest, Device)
587{
588
589 // Valid: test devices.
590 {
591 json configFile = validConfigFile;
592 EXPECT_JSON_VALID(configFile);
593 }
594 // Valid: test devices with required properties.
595 {
596 json configFile = validConfigFile;
597 configFile["chassis"][0]["devices"][0].erase("comments");
598 configFile["chassis"][0]["devices"][0].erase("presence_detection");
599 configFile["chassis"][0]["devices"][0].erase("configuration");
600 configFile["chassis"][0]["devices"][0].erase("rails");
601 EXPECT_JSON_VALID(configFile);
602 }
603 // Invalid: test devices with no id.
604 {
605 json configFile = validConfigFile;
606 configFile["chassis"][0]["devices"][0].erase("id");
607 EXPECT_JSON_INVALID(configFile, "Validation failed.",
608 "u'id' is a required property");
609 }
610 // Invalid: test devices with no is_regulator.
611 {
612 json configFile = validConfigFile;
613 configFile["chassis"][0]["devices"][0].erase("is_regulator");
614 EXPECT_JSON_INVALID(configFile, "Validation failed.",
615 "u'is_regulator' is a required property");
616 }
617 // Invalid: test devices with no fru.
618 {
619 json configFile = validConfigFile;
620 configFile["chassis"][0]["devices"][0].erase("fru");
621 EXPECT_JSON_INVALID(configFile, "Validation failed.",
622 "u'fru' is a required property");
623 }
624 // Invalid: test devices with no i2c_interface.
625 {
626 json configFile = validConfigFile;
627 configFile["chassis"][0]["devices"][0].erase("i2c_interface");
628 EXPECT_JSON_INVALID(configFile, "Validation failed.",
629 "u'i2c_interface' is a required property");
630 }
631 // Invalid: test devices with property comments wrong type.
632 {
633 json configFile = validConfigFile;
634 configFile["chassis"][0]["devices"][0]["comments"] = true;
635 EXPECT_JSON_INVALID(configFile, "Validation failed.",
636 "True is not of type u'array'");
637 }
638 // Invalid: test devices with property id wrong type.
639 {
640 json configFile = validConfigFile;
641 configFile["chassis"][0]["devices"][0]["id"] = true;
642 EXPECT_JSON_INVALID(configFile, "Validation failed.",
643 "True is not of type u'string'");
644 }
645 // Invalid: test devices with property is_regulator wrong type.
646 {
647 json configFile = validConfigFile;
648 configFile["chassis"][0]["devices"][0]["is_regulator"] = 1;
649 EXPECT_JSON_INVALID(configFile, "Validation failed.",
650 "1 is not of type u'boolean'");
651 }
652 // Invalid: test devices with property fru wrong type.
653 {
654 json configFile = validConfigFile;
655 configFile["chassis"][0]["devices"][0]["fru"] = true;
656 EXPECT_JSON_INVALID(configFile, "Validation failed.",
657 "True is not of type u'string'");
658 }
659 // Invalid: test devices with property i2c_interface wrong type.
660 {
661 json configFile = validConfigFile;
662 configFile["chassis"][0]["devices"][0]["i2c_interface"] = true;
663 EXPECT_JSON_INVALID(configFile, "Validation failed.",
664 "True is not of type u'object'");
665 }
666 // Invalid: test devices with property presence_detection wrong
667 // type.
668 {
669 json configFile = validConfigFile;
670 configFile["chassis"][0]["devices"][0]["presence_detection"] = true;
671 EXPECT_JSON_INVALID(configFile, "Validation failed.",
672 "True is not of type u'object'");
673 }
674 // Invalid: test devices with property configuration wrong type.
675 {
676 json configFile = validConfigFile;
677 configFile["chassis"][0]["devices"][0]["configuration"] = true;
678 EXPECT_JSON_INVALID(configFile, "Validation failed.",
679 "True is not of type u'object'");
680 }
681 // Invalid: test devices with property rails wrong type.
682 {
683 json configFile = validConfigFile;
684 configFile["chassis"][0]["devices"][0]["rails"] = true;
685 EXPECT_JSON_INVALID(configFile, "Validation failed.",
686 "True is not of type u'array'");
687 }
688 // Invalid: test devices with property comments empty array.
689 {
690 json configFile = validConfigFile;
691 configFile["chassis"][0]["devices"][0]["comments"] = json::array();
692 EXPECT_JSON_INVALID(configFile, "Validation failed.",
693 "[] is too short");
694 }
695 // Invalid: test devices with property fru length less than 1.
696 {
697 json configFile = validConfigFile;
698 configFile["chassis"][0]["devices"][0]["fru"] = "";
699 EXPECT_JSON_INVALID(configFile, "Validation failed.",
700 "u'' is too short");
701 }
702 // Invalid: test devices with property id wrong format.
703 {
704 json configFile = validConfigFile;
705 configFile["chassis"][0]["devices"][0]["id"] = "id#";
706 EXPECT_JSON_INVALID(configFile, "Validation failed.",
707 "u'id#' does not match u'^[A-Za-z0-9_]+$'");
708 }
709 // Invalid: test devices with property rails empty array.
710 {
711 json configFile = validConfigFile;
712 configFile["chassis"][0]["devices"][0]["rails"] = json::array();
713 EXPECT_JSON_INVALID(configFile, "Validation failed.",
714 "[] is too short");
715 }
716}
Bob King4ab8cbb2020-01-21 11:10:48 +0800717TEST(ValidateRegulatorsConfigTest, I2CCompareBit)
718{
719 json i2cCompareBitFile = validConfigFile;
720 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
721 "0xA0";
722 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
723 3;
724 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
725 // Valid: test rule actions i2c_compare_bit.
726 {
727 json configFile = i2cCompareBitFile;
728 EXPECT_JSON_VALID(configFile);
729 }
730 // Invalid: test i2c_compare_bit with no register.
731 {
732 json configFile = i2cCompareBitFile;
733 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
734 "register");
735 EXPECT_JSON_INVALID(configFile, "Validation failed.",
736 "u'register' is a required property");
737 }
738 // Invalid: test i2c_compare_bit with no position.
739 {
740 json configFile = i2cCompareBitFile;
741 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
742 "position");
743 EXPECT_JSON_INVALID(configFile, "Validation failed.",
744 "u'position' is a required property");
745 }
746 // Invalid: test i2c_compare_bit with no value.
747 {
748 json configFile = i2cCompareBitFile;
749 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value");
750 EXPECT_JSON_INVALID(configFile, "Validation failed.",
751 "u'value' is a required property");
752 }
753 // Invalid: test i2c_compare_bit with register wrong type.
754 {
755 json configFile = i2cCompareBitFile;
756 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1;
757 EXPECT_JSON_INVALID(configFile, "Validation failed.",
758 "1 is not of type u'string'");
759 }
760 // Invalid: test i2c_compare_bit with register wrong format.
761 {
762 json configFile = i2cCompareBitFile;
763 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
764 "0xA00";
765 EXPECT_JSON_INVALID(configFile, "Validation failed.",
766 "u'0xA00' does not match u'^0x[0-9A-Fa-f]{2}$'");
767 }
768 // Invalid: test i2c_compare_bit with position wrong type.
769 {
770 json configFile = i2cCompareBitFile;
771 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
772 3.1;
773 EXPECT_JSON_INVALID(configFile, "Validation failed.",
774 "3.1 is not of type u'integer'");
775 }
776 // Invalid: test i2c_compare_bit with position greater than 7.
777 {
778 json configFile = i2cCompareBitFile;
779 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8;
780 EXPECT_JSON_INVALID(configFile, "Validation failed.",
781 "8 is greater than the maximum of 7");
782 }
783 // Invalid: test i2c_compare_bit with position less than 0.
784 {
785 json configFile = i2cCompareBitFile;
786 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
787 -1;
788 EXPECT_JSON_INVALID(configFile, "Validation failed.",
789 "-1 is less than the minimum of 0");
790 }
791 // Invalid: test i2c_compare_bit with value wrong type.
792 {
793 json configFile = i2cCompareBitFile;
794 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1";
795 EXPECT_JSON_INVALID(configFile, "Validation failed.",
796 "u'1' is not of type u'integer'");
797 }
798 // Invalid: test i2c_compare_bit with value greater than 1.
799 {
800 json configFile = i2cCompareBitFile;
801 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2;
802 EXPECT_JSON_INVALID(configFile, "Validation failed.",
803 "2 is greater than the maximum of 1");
804 }
805 // Invalid: test i2c_compare_bit with value less than 0.
806 {
807 json configFile = i2cCompareBitFile;
808 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1;
809 EXPECT_JSON_INVALID(configFile, "Validation failed.",
810 "-1 is less than the minimum of 0");
811 }
812}
Bob King514023d2020-01-21 11:13:05 +0800813TEST(ValidateRegulatorsConfigTest, I2CCompareByte)
814{
815 json i2cCompareByteFile = validConfigFile;
816 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]
817 ["register"] = "0x82";
818 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
819 "0x40";
820 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
821 "0x7F";
822 // Valid: test i2c_compare_byte with all properties.
823 {
824 json configFile = i2cCompareByteFile;
825 EXPECT_JSON_VALID(configFile);
826 }
827 // Valid: test i2c_compare_byte with all required properties.
828 {
829 json configFile = i2cCompareByteFile;
830 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask");
831 EXPECT_JSON_VALID(configFile);
832 }
833 // Invalid: test i2c_compare_byte with no register.
834 {
835 json configFile = i2cCompareByteFile;
836 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase(
837 "register");
838 EXPECT_JSON_INVALID(configFile, "Validation failed.",
839 "u'register' is a required property");
840 }
841 // Invalid: test i2c_compare_byte with no value.
842 {
843 json configFile = i2cCompareByteFile;
844 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value");
845 EXPECT_JSON_INVALID(configFile, "Validation failed.",
846 "u'value' is a required property");
847 }
848 // Invalid: test i2c_compare_byte with property register wrong type.
849 {
850 json configFile = i2cCompareByteFile;
851 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
852 1;
853 EXPECT_JSON_INVALID(configFile, "Validation failed.",
854 "1 is not of type u'string'");
855 }
856 // Invalid: test i2c_compare_byte with property value wrong type.
857 {
858 json configFile = i2cCompareByteFile;
859 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1;
860 EXPECT_JSON_INVALID(configFile, "Validation failed.",
861 "1 is not of type u'string'");
862 }
863 // Invalid: test i2c_compare_byte with property mask wrong type.
864 {
865 json configFile = i2cCompareByteFile;
866 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1;
867 EXPECT_JSON_INVALID(configFile, "Validation failed.",
868 "1 is not of type u'string'");
869 }
870 // Invalid: test i2c_compare_byte with property register more than 2 hex
871 // digits.
872 {
873 json configFile = i2cCompareByteFile;
874 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
875 "0x820";
876 EXPECT_JSON_INVALID(configFile, "Validation failed.",
877 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
878 }
879 // Invalid: test i2c_compare_byte with property value more than 2 hex
880 // digits.
881 {
882 json configFile = i2cCompareByteFile;
883 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
884 "0x820";
885 EXPECT_JSON_INVALID(configFile, "Validation failed.",
886 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
887 }
888 // Invalid: test i2c_compare_byte with property mask more than 2 hex digits.
889 {
890 json configFile = i2cCompareByteFile;
891 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
892 "0x820";
893 EXPECT_JSON_INVALID(configFile, "Validation failed.",
894 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
895 }
896 // Invalid: test i2c_compare_byte with property register less than 2 hex
897 // digits.
898 {
899 json configFile = i2cCompareByteFile;
900 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
901 "0x8";
902 EXPECT_JSON_INVALID(configFile, "Validation failed.",
903 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
904 }
905 // Invalid: test i2c_compare_byte with property value less than 2 hex
906 // digits.
907 {
908 json configFile = i2cCompareByteFile;
909 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
910 "0x8";
911 EXPECT_JSON_INVALID(configFile, "Validation failed.",
912 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
913 }
914 // Invalid: test i2c_compare_byte with property mask less than 2 hex digits.
915 {
916 json configFile = i2cCompareByteFile;
917 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
918 "0x8";
919 EXPECT_JSON_INVALID(configFile, "Validation failed.",
920 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
921 }
922 // Invalid: test i2c_compare_byte with property register no leading prefix.
923 {
924 json configFile = i2cCompareByteFile;
925 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
926 "82";
927 EXPECT_JSON_INVALID(configFile, "Validation failed.",
928 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
929 }
930 // Invalid: test i2c_compare_byte with property value no leading prefix.
931 {
932 json configFile = i2cCompareByteFile;
933 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
934 "82";
935 EXPECT_JSON_INVALID(configFile, "Validation failed.",
936 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
937 }
938 // Invalid: test i2c_compare_byte with property mask no leading prefix.
939 {
940 json configFile = i2cCompareByteFile;
941 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82";
942 EXPECT_JSON_INVALID(configFile, "Validation failed.",
943 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
944 }
945 // Invalid: test i2c_compare_byte with property register invalid hex digit.
946 {
947 json configFile = i2cCompareByteFile;
948 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
949 "0xG1";
950 EXPECT_JSON_INVALID(configFile, "Validation failed.",
951 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
952 }
953 // Invalid: test i2c_compare_byte with property value invalid hex digit.
954 {
955 json configFile = i2cCompareByteFile;
956 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
957 "0xG1";
958 EXPECT_JSON_INVALID(configFile, "Validation failed.",
959 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
960 }
961 // Invalid: test i2c_compare_byte with property mask invalid hex digit.
962 {
963 json configFile = i2cCompareByteFile;
964 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
965 "0xG1";
966 EXPECT_JSON_INVALID(configFile, "Validation failed.",
967 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
968 }
969}
Bob Kingfb162bb2020-01-21 11:28:07 +0800970TEST(ValidateRegulatorsConfigTest, I2CCompareBytes)
971{
972 json i2cCompareBytesFile = validConfigFile;
973 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
974 ["register"] = "0x82";
975 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
976 ["values"] = {"0x02", "0x73"};
977 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
978 ["masks"] = {"0x7F", "0x7F"};
979 // Valid: test i2c_compare_bytes.
980 {
981 json configFile = i2cCompareBytesFile;
982 EXPECT_JSON_VALID(configFile);
983 }
984 // Valid: test i2c_compare_bytes with all required properties.
985 {
986 json configFile = i2cCompareBytesFile;
987 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
988 "masks");
989 EXPECT_JSON_VALID(configFile);
990 }
991 // Invalid: test i2c_compare_bytes with no register.
992 {
993 json configFile = i2cCompareBytesFile;
994 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
995 "register");
996 EXPECT_JSON_INVALID(configFile, "Validation failed.",
997 "u'register' is a required property");
998 }
999 // Invalid: test i2c_compare_bytes with no values.
1000 {
1001 json configFile = i2cCompareBytesFile;
1002 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1003 "values");
1004 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1005 "u'values' is a required property");
1006 }
1007 // Invalid: test i2c_compare_bytes with property values as empty array.
1008 {
1009 json configFile = i2cCompareBytesFile;
1010 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] =
1011 json::array();
1012 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1013 "[] is too short");
1014 }
1015 // Invalid: test i2c_compare_bytes with property masks as empty array.
1016 {
1017 json configFile = i2cCompareBytesFile;
1018 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] =
1019 json::array();
1020 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1021 "[] is too short");
1022 }
1023 // Invalid: test i2c_compare_bytes with property register wrong type.
1024 {
1025 json configFile = i2cCompareBytesFile;
1026 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1027 1;
1028 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1029 "1 is not of type u'string'");
1030 }
1031 // Invalid: test i2c_compare_bytes with property values wrong type.
1032 {
1033 json configFile = i2cCompareBytesFile;
1034 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1;
1035 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1036 "1 is not of type u'array'");
1037 }
1038 // Invalid: test i2c_compare_bytes with property masks wrong type.
1039 {
1040 json configFile = i2cCompareBytesFile;
1041 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1;
1042 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1043 "1 is not of type u'array'");
1044 }
1045 // Invalid: test i2c_compare_bytes with property register more than 2 hex
1046 // digits.
1047 {
1048 json configFile = i2cCompareBytesFile;
1049 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1050 "0x820";
1051 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1052 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1053 }
1054 // Invalid: test i2c_compare_bytes with property values more than 2 hex
1055 // digits.
1056 {
1057 json configFile = i2cCompareBytesFile;
1058 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1059 "0x820";
1060 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1061 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1062 }
1063 // Invalid: test i2c_compare_bytes with property masks more than 2 hex
1064 // digits.
1065 {
1066 json configFile = i2cCompareBytesFile;
1067 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1068 "0x820";
1069 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1070 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1071 }
1072 // Invalid: test i2c_compare_bytes with property register less than 2 hex
1073 // digits.
1074 {
1075 json configFile = i2cCompareBytesFile;
1076 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1077 "0x8";
1078 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1079 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1080 }
1081 // Invalid: test i2c_compare_bytes with property values less than 2 hex
1082 // digits.
1083 {
1084 json configFile = i2cCompareBytesFile;
1085 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1086 "0x8";
1087 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1088 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1089 }
1090 // Invalid: test i2c_compare_bytes with property masks less than 2 hex
1091 // digits.
1092 {
1093 json configFile = i2cCompareBytesFile;
1094 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1095 "0x8";
1096 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1097 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1098 }
1099 // Invalid: test i2c_compare_bytes with property register no leading prefix.
1100 {
1101 json configFile = i2cCompareBytesFile;
1102 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1103 "82";
1104 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1105 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1106 }
1107 // Invalid: test i2c_compare_bytes with property values no leading prefix.
1108 {
1109 json configFile = i2cCompareBytesFile;
1110 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1111 "82";
1112 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1113 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1114 }
1115 // Invalid: test i2c_compare_bytes with property masks no leading prefix.
1116 {
1117 json configFile = i2cCompareBytesFile;
1118 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1119 "82";
1120 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1121 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1122 }
1123 // Invalid: test i2c_compare_bytes with property register invalid hex digit.
1124 {
1125 json configFile = i2cCompareBytesFile;
1126 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1127 "0xG1";
1128 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1129 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1130 }
1131 // Invalid: test i2c_compare_bytes with property values invalid hex digit.
1132 {
1133 json configFile = i2cCompareBytesFile;
1134 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1135 "0xG1";
1136 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1137 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1138 }
1139 // Invalid: test i2c_compare_bytes with property masks invalid hex digit.
1140 {
1141 json configFile = i2cCompareBytesFile;
1142 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1143 "0xG1";
1144 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1145 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1146 }
1147}
Bob Kingca93f1f2020-01-31 11:21:16 +08001148TEST(ValidateRegulatorsConfigTest, I2CInterface)
1149{
1150 // Valid: test i2c_interface.
1151 {
1152 json configFile = validConfigFile;
1153 EXPECT_JSON_VALID(configFile);
1154 }
1155 // Invalid: testi2c_interface with no bus.
1156 {
1157 json configFile = validConfigFile;
1158 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase("bus");
1159 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1160 "u'bus' is a required property");
1161 }
1162 // Invalid: test i2c_interface with no address.
1163 {
1164 json configFile = validConfigFile;
1165 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase(
1166 "address");
1167 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1168 "u'address' is a required property");
1169 }
1170 // Invalid: test i2c_interface with property bus wrong type.
1171 {
1172 json configFile = validConfigFile;
1173 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = true;
1174 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1175 "True is not of type u'integer'");
1176 }
1177 // Invalid: test i2c_interface with property address wrong
1178 // type.
1179 {
1180 json configFile = validConfigFile;
1181 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1182 true;
1183 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1184 "True is not of type u'string'");
1185 }
1186 // Invalid: test i2c_interface with property bus less than
1187 // 0.
1188 {
1189 json configFile = validConfigFile;
1190 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = -1;
1191 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1192 "-1 is less than the minimum of 0");
1193 }
1194 // Invalid: test i2c_interface with property address wrong
1195 // format.
1196 {
1197 json configFile = validConfigFile;
1198 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1199 "0x700";
1200 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1201 "u'0x700' does not match u'^0x[0-9A-Fa-f]{2}$'");
1202 }
1203}
Bob Kingead0b052020-01-21 11:29:03 +08001204TEST(ValidateRegulatorsConfigTest, If)
1205{
1206 json ifFile = validConfigFile;
1207 ifFile["rules"][0]["actions"][1]["if"]["condition"]["run_rule"] =
1208 "is_downlevel_regulator";
1209 ifFile["rules"][0]["actions"][1]["if"]["then"][0]["run_rule"] =
1210 "configure_downlevel_regulator";
1211 ifFile["rules"][0]["actions"][1]["if"]["else"][0]["run_rule"] =
1212 "configure_downlevel_regulator";
1213 // Valid: test if.
1214 {
1215 json configFile = ifFile;
1216 EXPECT_JSON_VALID(configFile);
1217 }
1218 // Valid: test if with required properties.
1219 {
1220 json configFile = ifFile;
1221 configFile["rules"][0]["actions"][1]["if"].erase("else");
1222 EXPECT_JSON_VALID(configFile);
1223 }
1224 // Invalid: test if with no property condition.
1225 {
1226 json configFile = ifFile;
1227 configFile["rules"][0]["actions"][1]["if"].erase("condition");
1228 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1229 "u'condition' is a required property");
1230 }
1231 // Invalid: test if with no property then.
1232 {
1233 json configFile = ifFile;
1234 configFile["rules"][0]["actions"][1]["if"].erase("then");
1235 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1236 "u'then' is a required property");
1237 }
1238 // Invalid: test if with property then empty array.
1239 {
1240 json configFile = ifFile;
1241 configFile["rules"][0]["actions"][1]["if"]["then"] = json::array();
1242 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1243 "[] is too short");
1244 }
1245 // Invalid: test if with property else empty array.
1246 {
1247 json configFile = ifFile;
1248 configFile["rules"][0]["actions"][1]["if"]["else"] = json::array();
1249 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1250 "[] is too short");
1251 }
1252 // Invalid: test if with property condition wrong type.
1253 {
1254 json configFile = ifFile;
1255 configFile["rules"][0]["actions"][1]["if"]["condition"] = 1;
1256 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1257 "1 is not of type u'object'");
1258 }
1259 // Invalid: test if with property then wrong type.
1260 {
1261 json configFile = ifFile;
1262 configFile["rules"][0]["actions"][1]["if"]["then"] = 1;
1263 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1264 "1 is not of type u'array'");
1265 }
1266 // Invalid: test if with property else wrong type.
1267 {
1268 json configFile = ifFile;
1269 configFile["rules"][0]["actions"][1]["if"]["else"] = 1;
1270 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1271 "1 is not of type u'array'");
1272 }
1273}
Bob Kingbfe9fe72020-01-21 11:29:57 +08001274TEST(ValidateRegulatorsConfigTest, Not)
1275{
1276 json notFile = validConfigFile;
1277 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] =
1278 "0xA0";
1279 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] =
1280 "0xFF";
1281 // Valid: test not.
1282 {
1283 json configFile = notFile;
1284 EXPECT_JSON_VALID(configFile);
1285 }
1286 // Invalid: test not with wrong type.
1287 {
1288 json configFile = notFile;
1289 configFile["rules"][0]["actions"][1]["not"] = 1;
1290 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1291 "1 is not of type u'object'");
1292 }
1293}
Bob Kingcfc29d02020-01-21 11:30:50 +08001294TEST(ValidateRegulatorsConfigTest, Or)
1295{
1296 json orFile = validConfigFile;
1297 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] =
1298 "0xA0";
1299 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] =
1300 "0x00";
1301 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] =
1302 "0xA1";
1303 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] =
1304 "0x00";
1305 // Valid: test or.
1306 {
1307 json configFile = orFile;
1308 EXPECT_JSON_VALID(configFile);
1309 }
1310 // Invalid: test or with empty array.
1311 {
1312 json configFile = orFile;
1313 configFile["rules"][0]["actions"][1]["or"] = json::array();
1314 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1315 "[] is too short");
1316 }
1317 // Invalid: test or with wrong type.
1318 {
1319 json configFile = orFile;
1320 configFile["rules"][0]["actions"][1]["or"] = 1;
1321 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1322 "1 is not of type u'array'");
1323 }
1324}
Bob Kingd6618092020-01-21 11:31:46 +08001325TEST(ValidateRegulatorsConfigTest, PmbusReadSensor)
1326{
1327 json pmbusReadSensorFile = validConfigFile;
1328 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1329 "vout";
1330 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1331 ["command"] = "0x8B";
1332 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1333 ["format"] = "linear_16";
1334 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1335 ["exponent"] = -8;
1336 // Valid: test pmbus_read_sensor.
1337 {
1338 json configFile = pmbusReadSensorFile;
1339 EXPECT_JSON_VALID(configFile);
1340 }
1341 // Valid: test pmbus_read_sensor with required properties.
1342 {
1343 json configFile = pmbusReadSensorFile;
1344 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1345 "exponent");
1346 EXPECT_JSON_VALID(configFile);
1347 }
1348 // Invalid: test pmbus_read_sensor with no type.
1349 {
1350 json configFile = pmbusReadSensorFile;
1351 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type");
1352 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1353 "u'type' is a required property");
1354 }
1355 // Invalid: test pmbus_read_sensor with no command.
1356 {
1357 json configFile = pmbusReadSensorFile;
1358 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1359 "command");
1360 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1361 "u'command' is a required property");
1362 }
1363 // Invalid: test pmbus_read_sensor with no format.
1364 {
1365 json configFile = pmbusReadSensorFile;
1366 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1367 "format");
1368 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1369 "u'format' is a required property");
1370 }
1371 // Invalid: test pmbus_read_sensor with property type wrong type.
1372 {
1373 json configFile = pmbusReadSensorFile;
1374 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1375 true;
1376 EXPECT_JSON_INVALID(
1377 configFile, "Validation failed.",
1378 "True is not one of [u'iout', u'iout_peak', u'iout_valley', "
1379 "u'pout', u'temperature', u'temperature_peak', u'vout', "
1380 "u'vout_peak', u'vout_valley']");
1381 }
1382 // Invalid: test pmbus_read_sensor with property command wrong type.
1383 {
1384 json configFile = pmbusReadSensorFile;
1385 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1386 true;
1387 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1388 "True is not of type u'string'");
1389 }
1390 // Invalid: test pmbus_read_sensor with property format wrong type.
1391 {
1392 json configFile = pmbusReadSensorFile;
1393 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1394 true;
1395 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1396 "True is not one of [u'linear_11', u'linear_16']");
1397 }
1398 // Invalid: test pmbus_read_sensor with property exponent wrong type.
1399 {
1400 json configFile = pmbusReadSensorFile;
1401 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] =
1402 true;
1403 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1404 "True is not of type u'integer'");
1405 }
1406 // Invalid: test pmbus_read_sensor with property type wrong format.
1407 {
1408 json configFile = pmbusReadSensorFile;
1409 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1410 "foo";
1411 EXPECT_JSON_INVALID(
1412 configFile, "Validation failed.",
1413 "u'foo' is not one of [u'iout', u'iout_peak', u'iout_valley', "
1414 "u'pout', u'temperature', u'temperature_peak', u'vout', "
1415 "u'vout_peak', u'vout_valley']");
1416 }
1417 // Invalid: test pmbus_read_sensor with property command wrong format.
1418 {
1419 json configFile = pmbusReadSensorFile;
1420 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1421 "0x8B0";
1422 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1423 "u'0x8B0' does not match u'^0x[0-9a-fA-F]{2}$'");
1424 }
1425 // Invalid: test pmbus_read_sensor with property format wrong format.
1426 {
1427 json configFile = pmbusReadSensorFile;
1428 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1429 "foo";
1430 EXPECT_JSON_INVALID(
1431 configFile, "Validation failed.",
1432 "u'foo' is not one of [u'linear_11', u'linear_16']");
1433 }
1434}
Bob King02179c62020-01-21 11:32:36 +08001435TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand)
1436{
1437 json pmbusWriteVoutCommandFile = validConfigFile;
1438 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1439 ["pmbus_write_vout_command"]["volts"] = 1.03;
1440 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1441 ["pmbus_write_vout_command"]["format"] = "linear";
1442 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1443 ["pmbus_write_vout_command"]["exponent"] = -8;
1444 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1445 ["pmbus_write_vout_command"]["is_verified"] = true;
1446 // Valid: test pmbus_write_vout_command.
1447 {
1448 json configFile = pmbusWriteVoutCommandFile;
1449 EXPECT_JSON_VALID(configFile);
1450 }
1451 // Valid: test pmbus_write_vout_command with required properties.
1452 {
1453 json configFile = pmbusWriteVoutCommandFile;
1454 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1455 "volts");
1456 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1457 "exponent");
1458 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1459 "is_verified");
1460 EXPECT_JSON_VALID(configFile);
1461 }
1462 // Invalid: test pmbus_write_vout_command with no format.
1463 {
1464 json configFile = pmbusWriteVoutCommandFile;
1465 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1466 "format");
1467 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1468 "u'format' is a required property");
1469 }
1470 // Invalid: test pmbus_write_vout_command with property volts wrong type.
1471 {
1472 json configFile = pmbusWriteVoutCommandFile;
1473 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1474 ["volts"] = true;
1475 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1476 "True is not of type u'number'");
1477 }
1478 // Invalid: test pmbus_write_vout_command with property format wrong type.
1479 {
1480 json configFile = pmbusWriteVoutCommandFile;
1481 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1482 ["format"] = true;
1483 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1484 "True is not one of [u'linear']");
1485 }
1486 // Invalid: test pmbus_write_vout_command with property exponent wrong type.
1487 {
1488 json configFile = pmbusWriteVoutCommandFile;
1489 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1490 ["exponent"] = 1.3;
1491 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1492 "1.3 is not of type u'integer'");
1493 }
1494 // Invalid: test pmbus_write_vout_command with property is_verified wrong
1495 // type.
1496 {
1497 json configFile = pmbusWriteVoutCommandFile;
1498 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1499 ["is_verified"] = 1;
1500 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1501 "1 is not of type u'boolean'");
1502 }
1503 // Invalid: test pmbus_write_vout_command with property format wrong format.
1504 {
1505 json configFile = pmbusWriteVoutCommandFile;
1506 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1507 ["format"] = "foo";
1508 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1509 "u'foo' is not one of [u'linear']");
1510 }
1511}
Bob King99d8fa12020-01-31 11:23:40 +08001512TEST(ValidateRegulatorsConfigTest, PresenceDetection)
1513{
1514 json presenceDetectionFile = validConfigFile;
1515 presenceDetectionFile
1516 ["chassis"][0]["devices"][0]["presence_detection"]["comments"][0] =
1517 "Regulator is only present on the FooBar backplane";
1518 presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
1519 ["rule_id"] = "is_foobar_backplane_installed_rule";
1520 // Valid: test presence_detection with only property rule_id.
1521 {
1522 json configFile = presenceDetectionFile;
1523 EXPECT_JSON_VALID(configFile);
1524 }
1525 // Valid: test presence_detection with only property actions.
1526 {
1527 json configFile = presenceDetectionFile;
1528 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1529 "rule_id");
1530 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1531 [0]["compare_presence"]["fru"] =
1532 "/system/chassis/motherboard/cpu3";
1533 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1534 [0]["compare_presence"]["value"] = true;
1535 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1536 "comments");
1537 EXPECT_JSON_VALID(configFile);
1538 }
1539 // Invalid: test presence_detection with both property rule_id and actions.
1540 {
1541 json configFile = presenceDetectionFile;
1542 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1543 [0]["compare_presence"]["fru"] =
1544 "/system/chassis/motherboard/cpu3";
1545 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1546 [0]["compare_presence"]["value"] = true;
1547 EXPECT_JSON_INVALID(
1548 configFile, "Validation failed.",
1549 "{u'comments': [u'Regulator is only present on the FooBar "
1550 "backplane'], u'actions': [{u'compare_presence': {u'value': True, "
1551 "u'fru': u'/system/chassis/motherboard/cpu3'}}], u'rule_id': "
1552 "u'is_foobar_backplane_installed_rule'} is valid under each of "
1553 "{u'required': [u'actions']}, {u'required': [u'rule_id']}");
1554 }
1555 // Invalid: test presence_detection with no rule_id and actions.
1556 {
1557 json configFile = presenceDetectionFile;
1558 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1559 "rule_id");
1560 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1561 "u'rule_id' is a required property");
1562 }
1563 // Invalid: test presence_detection with property comments wrong type.
1564 {
1565 json configFile = presenceDetectionFile;
1566 configFile["chassis"][0]["devices"][0]["presence_detection"]
1567 ["comments"] = true;
1568 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1569 "True is not of type u'array'");
1570 }
1571 // Invalid: test presence_detection with property rule_id wrong type.
1572 {
1573 json configFile = presenceDetectionFile;
1574 configFile["chassis"][0]["devices"][0]["presence_detection"]
1575 ["rule_id"] = true;
1576 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1577 "True is not of type u'string'");
1578 }
1579 // Invalid: test presence_detection with property actions wrong type.
1580 {
1581 json configFile = presenceDetectionFile;
1582 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1583 "rule_id");
1584 configFile["chassis"][0]["devices"][0]["presence_detection"]
1585 ["actions"] = true;
1586 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1587 "True is not of type u'array'");
1588 }
1589 // Invalid: test presence_detection with property rule_id wrong format.
1590 {
1591 json configFile = presenceDetectionFile;
1592 configFile["chassis"][0]["devices"][0]["presence_detection"]
1593 ["rule_id"] = "id@";
1594 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1595 "u'id@' does not match u'^[A-Za-z0-9_]+$'");
1596 }
1597 // Invalid: test presence_detection with property comments empty array.
1598 {
1599 json configFile = presenceDetectionFile;
1600 configFile["chassis"][0]["devices"][0]["presence_detection"]
1601 ["comments"] = json::array();
1602 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1603 "[] is too short");
1604 }
1605 // Invalid: test presence_detection with property actions empty array.
1606 {
1607 json configFile = presenceDetectionFile;
1608 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1609 "rule_id");
1610 configFile["chassis"][0]["devices"][0]["presence_detection"]
1611 ["actions"] = json::array();
1612 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1613 "[] is too short");
1614 }
1615}
Bob Kinge9260b52020-01-21 11:46:13 +08001616TEST(ValidateRegulatorsConfigTest, Rail)
1617{
1618 // Valid: test rail.
1619 {
1620 json configFile = validConfigFile;
1621 EXPECT_JSON_VALID(configFile);
1622 }
1623 // Valid: test rail with required properties.
1624 {
1625 json configFile = validConfigFile;
1626 configFile["chassis"][0]["devices"][0]["rails"][0].erase("comments");
1627 configFile["chassis"][0]["devices"][0]["rails"][0].erase(
1628 "configuration");
1629 configFile["chassis"][0]["devices"][0]["rails"][0].erase(
1630 "sensor_monitoring");
1631 EXPECT_JSON_VALID(configFile);
1632 }
1633 // Invalid: test rail with no id.
1634 {
1635 json configFile = validConfigFile;
1636 configFile["chassis"][0]["devices"][0]["rails"][0].erase("id");
1637 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1638 "u'id' is a required property");
1639 }
1640 // Invalid: test rail with comments wrong type.
1641 {
1642 json configFile = validConfigFile;
1643 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = true;
1644 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1645 "True is not of type u'array'");
1646 }
1647 // Invalid: test rail with id wrong type.
1648 {
1649 json configFile = validConfigFile;
1650 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = true;
1651 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1652 "True is not of type u'string'");
1653 }
1654 // Invalid: test rail with configuration wrong type.
1655 {
1656 json configFile = validConfigFile;
1657 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] =
1658 true;
1659 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1660 "True is not of type u'object'");
1661 }
1662 // Invalid: test rail with sensor_monitoring wrong type.
1663 {
1664 json configFile = validConfigFile;
1665 configFile["chassis"][0]["devices"][0]["rails"][0]
1666 ["sensor_monitoring"] = true;
1667 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1668 "True is not of type u'object'");
1669 }
1670 // Invalid: test rail with comments empty array.
1671 {
1672 json configFile = validConfigFile;
1673 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] =
1674 json::array();
1675 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1676 "[] is too short");
1677 }
1678 // Invalid: test rail with id wrong format.
1679 {
1680 json configFile = validConfigFile;
1681 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = "id~";
1682 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1683 "u'id~' does not match u'^[A-Za-z0-9_]+$'");
1684 }
1685}
Bob King64df7da2020-01-31 12:04:12 +08001686TEST(ValidateRegulatorsConfigTest, Rule)
1687{
1688 // valid test comments property, id property,
1689 // action property specified.
1690 {
1691 json configFile = validConfigFile;
1692 EXPECT_JSON_VALID(configFile);
1693 }
1694
1695 // valid test rule with no comments
1696 {
1697 json configFile = validConfigFile;
1698 configFile["rules"][0].erase("comments");
1699 EXPECT_JSON_VALID(configFile);
1700 }
1701
1702 // invalid test comments property has invalid value type
1703 {
1704 json configFile = validConfigFile;
1705 configFile["rules"][0]["comments"] = {1};
1706 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1707 "1 is not of type u'string'");
1708 }
1709
1710 // invalid test rule with no ID
1711 {
1712 json configFile = validConfigFile;
1713 configFile["rules"][0].erase("id");
1714 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1715 "u'id' is a required property");
1716 }
1717
1718 // invalid test id property has invalid value type (not string)
1719 {
1720 json configFile = validConfigFile;
1721 configFile["rules"][0]["id"] = true;
1722 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1723 "True is not of type u'string'");
1724 }
1725
1726 // invalid test id property has invalid value
1727 {
1728 json configFile = validConfigFile;
1729 configFile["rules"][0]["id"] = "foo%";
1730 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1731 "u'foo%' does not match u'^[A-Za-z0-9_]+$'");
1732 }
1733
1734 // invalid test rule with no actions property
1735 {
1736 json configFile = validConfigFile;
1737 configFile["rules"][0].erase("actions");
1738 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1739 "u'actions' is a required property");
1740 }
1741
1742 // valid test rule with multiple actions
1743 {
1744 json configFile = validConfigFile;
1745 configFile["rules"][0]["actions"][1]["run_rule"] =
1746 "set_page0_voltage_rule";
1747 EXPECT_JSON_VALID(configFile);
1748 }
1749
1750 // invalid test actions property has invalid value type (not an array)
1751 {
1752 json configFile = validConfigFile;
1753 configFile["rules"][0]["actions"] = 1;
1754 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1755 "1 is not of type u'array'");
1756 }
1757
1758 // invalid test actions property has invalid value of action
1759 {
1760 json configFile = validConfigFile;
1761 configFile["rules"][0]["actions"][0] = "foo";
1762 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1763 "u'foo' is not of type u'object'");
1764 }
1765
1766 // invalid test actions property has empty array
1767 {
1768 json configFile = validConfigFile;
1769 configFile["rules"][0]["actions"] = json::array();
1770 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1771 "[] is too short");
1772 }
1773}
Bob Kinge86c2e52020-01-21 11:33:32 +08001774TEST(ValidateRegulatorsConfigTest, RunRule)
1775{
1776 json runRuleFile = validConfigFile;
1777 runRuleFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule1";
1778 // Valid: test run_rule.
1779 {
1780 json configFile = runRuleFile;
1781 EXPECT_JSON_VALID(configFile);
1782 }
1783 // Invalid: test run_rule wrong type.
1784 {
1785 json configFile = runRuleFile;
1786 configFile["rules"][0]["actions"][1]["run_rule"] = true;
1787 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1788 "True is not of type u'string'");
1789 }
1790 // Invalid: test run_rule wrong format.
1791 {
1792 json configFile = runRuleFile;
1793 configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%";
1794 EXPECT_JSON_INVALID(
1795 configFile, "Validation failed.",
1796 "u'set_voltage_rule%' does not match u'^[A-Za-z0-9_]+$'");
1797 }
1798}
Bob Kingfcc2a2f2020-01-31 11:29:45 +08001799TEST(ValidateRegulatorsConfigTest, SensorMonitoring)
1800{
1801 // Valid: test rails sensor_monitoring with only property rule id.
1802 {
1803 json configFile = validConfigFile;
1804 EXPECT_JSON_VALID(configFile);
1805 }
1806 // Valid: test rails sensor_monitoring with only property actions.
1807 {
1808 json configFile = validConfigFile;
1809 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1810 .erase("rule_id");
1811 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1812 ["actions"][0]["compare_presence"]["fru"] =
1813 "/system/chassis/motherboard/cpu3";
1814 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1815 ["actions"][0]["compare_presence"]["value"] = true;
1816 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1817 ["comments"][0] = "comments";
1818 EXPECT_JSON_VALID(configFile);
1819 }
1820 // Invalid: test rails sensor_monitoring with both property rule_id and
1821 // actions.
1822 {
1823 json configFile = validConfigFile;
1824 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1825 ["actions"][0]["compare_presence"]["fru"] =
1826 "/system/chassis/motherboard/cpu3";
1827 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1828 ["actions"][0]["compare_presence"]["value"] = true;
1829 EXPECT_JSON_INVALID(
1830 configFile, "Validation failed.",
1831 "{u'rule_id': u'read_sensors_rule', u'actions': "
1832 "[{u'compare_presence': {u'value': True, u'fru': "
1833 "u'/system/chassis/motherboard/cpu3'}}]} is valid under each of "
1834 "{u'required': [u'actions']}, {u'required': [u'rule_id']}");
1835 }
1836 // Invalid: test rails sensor_monitoring with no rule_id and actions.
1837 {
1838 json configFile = validConfigFile;
1839 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1840 .erase("rule_id");
1841 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1842 "u'rule_id' is a required property");
1843 }
1844 // Invalid: test rails sensor_monitoring with property comments wrong type.
1845 {
1846 json configFile = validConfigFile;
1847 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1848 ["comments"] = true;
1849 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1850 "True is not of type u'array'");
1851 }
1852 // Invalid: test rails sensor_monitoring with property rule_id wrong type.
1853 {
1854 json configFile = validConfigFile;
1855 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1856 ["rule_id"] = true;
1857 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1858 "True is not of type u'string'");
1859 }
1860 // Invalid: test rails sensor_monitoring with property actions wrong type.
1861 {
1862 json configFile = validConfigFile;
1863 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1864 .erase("rule_id");
1865 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1866 ["actions"] = true;
1867 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1868 "True is not of type u'array'");
1869 }
1870 // Invalid: test rails sensor_monitoring with property rule_id wrong format.
1871 {
1872 json configFile = validConfigFile;
1873 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1874 ["rule_id"] = "id@";
1875 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1876 "u'id@' does not match u'^[A-Za-z0-9_]+$'");
1877 }
1878 // Invalid: test rails sensor_monitoring with property comments empty array.
1879 {
1880 json configFile = validConfigFile;
1881 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1882 ["comments"] = json::array();
1883 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1884 "[] is too short");
1885 }
1886 // Invalid: test rails sensor_monitoring with property actions empty array.
1887 {
1888 json configFile = validConfigFile;
1889 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1890 .erase("rule_id");
1891 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
1892 ["actions"] = json::array();
1893 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1894 "[] is too short");
1895 }
1896}
Bob King68230aa2020-01-21 11:34:33 +08001897TEST(ValidateRegulatorsConfigTest, SetDevice)
1898{
1899 json setDeviceFile = validConfigFile;
1900 setDeviceFile["rules"][0]["actions"][1]["set_device"] = "io_expander2";
1901 // Valid: test set_device.
1902 {
1903 json configFile = setDeviceFile;
1904 EXPECT_JSON_VALID(configFile);
1905 }
1906 // Invalid: test set_device wrong type.
1907 {
1908 json configFile = setDeviceFile;
1909 configFile["rules"][0]["actions"][1]["set_device"] = true;
1910 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1911 "True is not of type u'string'");
1912 }
1913 // Invalid: test set_device wrong format.
1914 {
1915 json configFile = setDeviceFile;
1916 configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%";
1917 EXPECT_JSON_INVALID(
1918 configFile, "Validation failed.",
1919 "u'io_expander2%' does not match u'^[A-Za-z0-9_]+$'");
1920 }
1921}
Bob King3643cc02020-01-31 11:32:56 +08001922TEST(ValidateRegulatorsConfigTest, DuplicateRuleID)
1923{
1924 // Invalid: test duplicate ID in rule.
1925 {
1926 json configFile = validConfigFile;
1927 configFile["rules"][1]["id"] = "set_voltage_rule";
1928 configFile["rules"][1]["actions"][0]["pmbus_write_vout_command"]
1929 ["format"] = "linear";
1930 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rule ID.", "");
1931 }
1932}
1933TEST(ValidateRegulatorsConfigTest, DuplicateChassisNumber)
1934{
1935 // Invalid: test duplicate number in chassis.
1936 {
1937 json configFile = validConfigFile;
1938 configFile["chassis"][1]["number"] = 1;
1939 EXPECT_JSON_INVALID(configFile, "Error: Duplicate chassis number.", "");
1940 }
1941}
1942TEST(ValidateRegulatorsConfigTest, DuplicateDeviceID)
1943{
1944 // Invalid: test duplicate ID in device.
1945 {
1946 json configFile = validConfigFile;
1947 configFile["chassis"][0]["devices"][1]["id"] = "vdd_regulator";
1948 configFile["chassis"][0]["devices"][1]["is_regulator"] = true;
1949 configFile["chassis"][0]["devices"][1]["fru"] =
1950 "/system/chassis/motherboard/regulator1";
1951 configFile["chassis"][0]["devices"][1]["i2c_interface"]["bus"] = 2;
1952 configFile["chassis"][0]["devices"][1]["i2c_interface"]["address"] =
1953 "0x71";
1954 EXPECT_JSON_INVALID(configFile, "Error: Duplicate device ID.", "");
1955 }
1956}
1957TEST(ValidateRegulatorsConfigTest, DuplicateRailID)
1958{
1959 // Invalid: test duplicate ID in rail.
1960 {
1961 json configFile = validConfigFile;
1962 configFile["chassis"][0]["devices"][0]["rails"][1]["id"] = "vdd";
1963 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rail ID.", "");
1964 }
1965}
1966TEST(ValidateRegulatorsConfigTest, InfiniteLoops)
1967{
1968 // Invalid: test run_rule with infinite loop (rules run each other).
1969 {
1970 json configFile = validConfigFile;
1971 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2";
1972 configFile["rules"][2]["id"] = "set_voltage_rule1";
1973 configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule1";
1974 configFile["rules"][3]["id"] = "set_voltage_rule2";
1975 EXPECT_JSON_INVALID(configFile,
1976 "Infinite loop caused by run_rule actions.", "");
1977 }
1978 // Invalid: test run_rule with infinite loop (rule runs itself).
1979 {
1980 json configFile = validConfigFile;
1981 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule1";
1982 configFile["rules"][2]["id"] = "set_voltage_rule1";
1983 EXPECT_JSON_INVALID(configFile,
1984 "Infinite loop caused by run_rule actions.", "");
1985 }
1986 // Invalid: test run_rule with infinite loop (indirect loop).
1987 {
1988 json configFile = validConfigFile;
1989 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2";
1990 configFile["rules"][2]["id"] = "set_voltage_rule1";
1991 configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule3";
1992 configFile["rules"][3]["id"] = "set_voltage_rule2";
1993 configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule1";
1994 configFile["rules"][4]["id"] = "set_voltage_rule3";
1995 EXPECT_JSON_INVALID(configFile,
1996 "Infinite loop caused by run_rule actions.", "");
1997 }
1998}