blob: 33e762b8c10e646d04f150e8e3e2e4257bff77dc [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
203TEST(ValidateRegulatorsConfigTest, Rule)
204{
205 // valid test comments property, id property,
206 // action property specified.
207 {
208 json configFile = validConfigFile;
209 EXPECT_JSON_VALID(configFile);
210 }
211
212 // valid test rule with no comments
213 {
214 json configFile = validConfigFile;
215 configFile["rules"][0].erase("comments");
216 EXPECT_JSON_VALID(configFile);
217 }
218
219 // invalid test comments property has invalid value type
220 {
221 json configFile = validConfigFile;
222 configFile["rules"][0]["comments"] = {1};
223 EXPECT_JSON_INVALID(configFile, "Validation failed.",
224 "1 is not of type u'string'");
225 }
226
227 // invalid test rule with no ID
228 {
229 json configFile = validConfigFile;
230 configFile["rules"][0].erase("id");
231 EXPECT_JSON_INVALID(configFile, "Validation failed.",
232 "u'id' is a required property");
233 }
234
235 // invalid test id property has invalid value type (not string)
236 {
237 json configFile = validConfigFile;
238 configFile["rules"][0]["id"] = true;
239 EXPECT_JSON_INVALID(configFile, "Validation failed.",
240 "True is not of type u'string'");
241 }
242
243 // invalid test id property has invalid value
244 {
245 json configFile = validConfigFile;
246 configFile["rules"][0]["id"] = "foo%";
247 EXPECT_JSON_INVALID(configFile, "Validation failed.",
248 "u'foo%' does not match u'^[A-Za-z0-9_]+$'");
249 }
250
251 // invalid test rule with no actions property
252 {
253 json configFile = validConfigFile;
254 configFile["rules"][0].erase("actions");
255 EXPECT_JSON_INVALID(configFile, "Validation failed.",
256 "u'actions' is a required property");
257 }
258
259 // valid test rule with multiple actions
260 {
261 json configFile = validConfigFile;
262 configFile["rules"][0]["actions"][1]["run_rule"] =
263 "set_page0_voltage_rule";
264 EXPECT_JSON_VALID(configFile);
265 }
266
267 // invalid test actions property has invalid value type (not an array)
268 {
269 json configFile = validConfigFile;
270 configFile["rules"][0]["actions"] = 1;
271 EXPECT_JSON_INVALID(configFile, "Validation failed.",
272 "1 is not of type u'array'");
273 }
274
275 // invalid test actions property has invalid value of action
276 {
277 json configFile = validConfigFile;
278 configFile["rules"][0]["actions"][0] = "foo";
279 EXPECT_JSON_INVALID(configFile, "Validation failed.",
280 "u'foo' is not of type u'object'");
281 }
282
283 // invalid test actions property has empty array
284 {
285 json configFile = validConfigFile;
286 configFile["rules"][0]["actions"] = json::array();
287 EXPECT_JSON_INVALID(configFile, "Validation failed.",
288 "[] is too short");
289 }
Bob King0dcbdf52020-01-20 17:19:39 +0800290}
Bob Kingbeaf6532020-01-21 11:03:49 +0800291TEST(ValidateRegulatorsConfigTest, And)
292{
293 // Valid.
294 {
295 json configFile = validConfigFile;
296 json andAction =
297 R"(
298 {
299 "and": [
300 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
301 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
302 ]
303 }
304 )"_json;
305 configFile["rules"][0]["actions"].push_back(andAction);
306 EXPECT_JSON_VALID(configFile);
307 }
308
309 // Invalid: actions property value is an empty array.
310 {
311 json configFile = validConfigFile;
312 json andAction =
313 R"(
314 {
315 "and": []
316 }
317 )"_json;
318 configFile["rules"][0]["actions"].push_back(andAction);
319 EXPECT_JSON_INVALID(configFile, "Validation failed.",
320 "[] is too short");
321 }
322
323 // Invalid: actions property has incorrect value data type.
324 {
325 json configFile = validConfigFile;
326 json andAction =
327 R"(
328 {
329 "and": true
330 }
331 )"_json;
332 configFile["rules"][0]["actions"].push_back(andAction);
333 EXPECT_JSON_INVALID(configFile, "Validation failed.",
334 "True is not of type u'array'");
335 }
336
337 // Invalid: actions property value contains wrong element type
338 {
339 json configFile = validConfigFile;
340 json andAction =
341 R"(
342 {
343 "and": ["foo"]
344 }
345 )"_json;
346 configFile["rules"][0]["actions"].push_back(andAction);
347 EXPECT_JSON_INVALID(configFile, "Validation failed.",
348 "u'foo' is not of type u'object'");
349 }
350}
Bob King3728f562020-01-21 11:35:31 +0800351TEST(ValidateRegulatorsConfigTest, Chassis)
352{
353 // Valid: test chassis.
354 {
355 json configFile = validConfigFile;
356 EXPECT_JSON_VALID(configFile);
357 }
358 // Valid: test chassis with required properties.
359 {
360 json configFile = validConfigFile;
361 configFile["chassis"][0].erase("comments");
362 configFile["chassis"][0].erase("devices");
363 EXPECT_JSON_VALID(configFile);
364 }
365 // Invalid: test chassis with no number.
366 {
367 json configFile = validConfigFile;
368 configFile["chassis"][0].erase("number");
369 EXPECT_JSON_INVALID(configFile, "Validation failed.",
370 "u'number' is a required property");
371 }
372 // Invalid: test chassis with property comments wrong type.
373 {
374 json configFile = validConfigFile;
375 configFile["chassis"][0]["comments"] = true;
376 EXPECT_JSON_INVALID(configFile, "Validation failed.",
377 "True is not of type u'array'");
378 }
379 // Invalid: test chassis with property number wrong type.
380 {
381 json configFile = validConfigFile;
382 configFile["chassis"][0]["number"] = 1.3;
383 EXPECT_JSON_INVALID(configFile, "Validation failed.",
384 "1.3 is not of type u'integer'");
385 }
386 // Invalid: test chassis with property devices wrong type.
387 {
388 json configFile = validConfigFile;
389 configFile["chassis"][0]["devices"] = true;
390 EXPECT_JSON_INVALID(configFile, "Validation failed.",
391 "True is not of type u'array'");
392 }
393 // Invalid: test chassis with property comments empty array.
394 {
395 json configFile = validConfigFile;
396 configFile["chassis"][0]["comments"] = json::array();
397 EXPECT_JSON_INVALID(configFile, "Validation failed.",
398 "[] is too short");
399 }
400 // Invalid: test chassis with property devices empty array.
401 {
402 json configFile = validConfigFile;
403 configFile["chassis"][0]["devices"] = json::array();
404 EXPECT_JSON_INVALID(configFile, "Validation failed.",
405 "[] is too short");
406 }
407 // Invalid: test chassis with property number less than 1.
408 {
409 json configFile = validConfigFile;
410 configFile["chassis"][0]["number"] = 0;
411 EXPECT_JSON_INVALID(configFile, "Validation failed.",
412 "0 is less than the minimum of 1");
413 }
414}
Bob Kingbf1cbea2020-01-21 11:08:50 +0800415TEST(ValidateRegulatorsConfigTest, ComparePresence)
416{
417 json comparePresenceFile = validConfigFile;
418 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
419 "/system/chassis/motherboard/regulator2";
420 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
421 true;
422 // Valid.
423 {
424 json configFile = comparePresenceFile;
425 EXPECT_JSON_VALID(configFile);
426 }
427
428 // Invalid: no FRU property.
429 {
430 json configFile = comparePresenceFile;
431 configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru");
432 EXPECT_JSON_INVALID(configFile, "Validation failed.",
433 "u'fru' is a required property");
434 }
435
436 // Invalid: FRU property length is string less than 1.
437 {
438 json configFile = comparePresenceFile;
439 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = "";
440 EXPECT_JSON_INVALID(configFile, "Validation failed.",
441 "u'' is too short");
442 }
443
444 // Invalid: no value property.
445 {
446 json configFile = comparePresenceFile;
447 configFile["rules"][0]["actions"][1]["compare_presence"].erase("value");
448 EXPECT_JSON_INVALID(configFile, "Validation failed.",
449 "u'value' is a required property");
450 }
451
452 // Invalid: value property type is not boolean.
453 {
454 json configFile = comparePresenceFile;
455 configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1";
456 EXPECT_JSON_INVALID(configFile, "Validation failed.",
457 "u'1' is not of type u'boolean'");
458 }
459
460 // Invalid: FRU property type is not string.
461 {
462 json configFile = comparePresenceFile;
463 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1;
464 EXPECT_JSON_INVALID(configFile, "Validation failed.",
465 "1 is not of type u'string'");
466 }
467}
Bob Kingf8b77a02020-01-21 11:09:47 +0800468TEST(ValidateRegulatorsConfigTest, CompareVpd)
469{
470 json compareVpdFile = validConfigFile;
471 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
472 "/system/chassis/motherboard/regulator2";
473 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
474 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
475
476 // Valid.
477 {
478 json configFile = compareVpdFile;
479 EXPECT_JSON_VALID(configFile);
480 }
481
482 // Invalid: no FRU property.
483 {
484 json configFile = compareVpdFile;
485 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru");
486 EXPECT_JSON_INVALID(configFile, "Validation failed.",
487 "u'fru' is a required property");
488 }
489
490 // Invalid: no keyword property.
491 {
492 json configFile = compareVpdFile;
493 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword");
494 EXPECT_JSON_INVALID(configFile, "Validation failed.",
495 "u'keyword' is a required property");
496 }
497
498 // Invalid: no value property.
499 {
500 json configFile = compareVpdFile;
501 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
502 EXPECT_JSON_INVALID(configFile, "Validation failed.",
503 "u'value' is a required property");
504 }
505
506 // Invalid: property FRU wrong type.
507 {
508 json configFile = compareVpdFile;
509 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1;
510 EXPECT_JSON_INVALID(configFile, "Validation failed.",
511 "1 is not of type u'string'");
512 }
513
514 // Invalid: property FRU is string less than 1.
515 {
516 json configFile = compareVpdFile;
517 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = "";
518 EXPECT_JSON_INVALID(configFile, "Validation failed.",
519 "u'' is too short");
520 }
521
522 // Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
523 // "PartNumber"
524 {
525 json configFile = compareVpdFile;
526 configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
527 "Number";
528 EXPECT_JSON_INVALID(configFile, "Validation failed.",
529 "u'Number' is not one of [u'CCIN', "
530 "u'Manufacturer', u'Model', u'PartNumber']");
531 }
532
533 // Invalid: property value wrong type.
534 {
535 json configFile = compareVpdFile;
536 configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1;
537 EXPECT_JSON_INVALID(configFile, "Validation failed.",
538 "1 is not of type u'string'");
539 }
540}
Bob Kinga2ba2df2020-02-04 14:38:44 +0800541TEST(ValidateRegulatorsConfigTest, Device)
542{
543
544 // Valid: test devices.
545 {
546 json configFile = validConfigFile;
547 EXPECT_JSON_VALID(configFile);
548 }
549 // Valid: test devices with required properties.
550 {
551 json configFile = validConfigFile;
552 configFile["chassis"][0]["devices"][0].erase("comments");
553 configFile["chassis"][0]["devices"][0].erase("presence_detection");
554 configFile["chassis"][0]["devices"][0].erase("configuration");
555 configFile["chassis"][0]["devices"][0].erase("rails");
556 EXPECT_JSON_VALID(configFile);
557 }
558 // Invalid: test devices with no id.
559 {
560 json configFile = validConfigFile;
561 configFile["chassis"][0]["devices"][0].erase("id");
562 EXPECT_JSON_INVALID(configFile, "Validation failed.",
563 "u'id' is a required property");
564 }
565 // Invalid: test devices with no is_regulator.
566 {
567 json configFile = validConfigFile;
568 configFile["chassis"][0]["devices"][0].erase("is_regulator");
569 EXPECT_JSON_INVALID(configFile, "Validation failed.",
570 "u'is_regulator' is a required property");
571 }
572 // Invalid: test devices with no fru.
573 {
574 json configFile = validConfigFile;
575 configFile["chassis"][0]["devices"][0].erase("fru");
576 EXPECT_JSON_INVALID(configFile, "Validation failed.",
577 "u'fru' is a required property");
578 }
579 // Invalid: test devices with no i2c_interface.
580 {
581 json configFile = validConfigFile;
582 configFile["chassis"][0]["devices"][0].erase("i2c_interface");
583 EXPECT_JSON_INVALID(configFile, "Validation failed.",
584 "u'i2c_interface' is a required property");
585 }
586 // Invalid: test devices with property comments wrong type.
587 {
588 json configFile = validConfigFile;
589 configFile["chassis"][0]["devices"][0]["comments"] = true;
590 EXPECT_JSON_INVALID(configFile, "Validation failed.",
591 "True is not of type u'array'");
592 }
593 // Invalid: test devices with property id wrong type.
594 {
595 json configFile = validConfigFile;
596 configFile["chassis"][0]["devices"][0]["id"] = true;
597 EXPECT_JSON_INVALID(configFile, "Validation failed.",
598 "True is not of type u'string'");
599 }
600 // Invalid: test devices with property is_regulator wrong type.
601 {
602 json configFile = validConfigFile;
603 configFile["chassis"][0]["devices"][0]["is_regulator"] = 1;
604 EXPECT_JSON_INVALID(configFile, "Validation failed.",
605 "1 is not of type u'boolean'");
606 }
607 // Invalid: test devices with property fru wrong type.
608 {
609 json configFile = validConfigFile;
610 configFile["chassis"][0]["devices"][0]["fru"] = true;
611 EXPECT_JSON_INVALID(configFile, "Validation failed.",
612 "True is not of type u'string'");
613 }
614 // Invalid: test devices with property i2c_interface wrong type.
615 {
616 json configFile = validConfigFile;
617 configFile["chassis"][0]["devices"][0]["i2c_interface"] = true;
618 EXPECT_JSON_INVALID(configFile, "Validation failed.",
619 "True is not of type u'object'");
620 }
621 // Invalid: test devices with property presence_detection wrong
622 // type.
623 {
624 json configFile = validConfigFile;
625 configFile["chassis"][0]["devices"][0]["presence_detection"] = true;
626 EXPECT_JSON_INVALID(configFile, "Validation failed.",
627 "True is not of type u'object'");
628 }
629 // Invalid: test devices with property configuration wrong type.
630 {
631 json configFile = validConfigFile;
632 configFile["chassis"][0]["devices"][0]["configuration"] = true;
633 EXPECT_JSON_INVALID(configFile, "Validation failed.",
634 "True is not of type u'object'");
635 }
636 // Invalid: test devices with property rails wrong type.
637 {
638 json configFile = validConfigFile;
639 configFile["chassis"][0]["devices"][0]["rails"] = true;
640 EXPECT_JSON_INVALID(configFile, "Validation failed.",
641 "True is not of type u'array'");
642 }
643 // Invalid: test devices with property comments empty array.
644 {
645 json configFile = validConfigFile;
646 configFile["chassis"][0]["devices"][0]["comments"] = json::array();
647 EXPECT_JSON_INVALID(configFile, "Validation failed.",
648 "[] is too short");
649 }
650 // Invalid: test devices with property fru length less than 1.
651 {
652 json configFile = validConfigFile;
653 configFile["chassis"][0]["devices"][0]["fru"] = "";
654 EXPECT_JSON_INVALID(configFile, "Validation failed.",
655 "u'' is too short");
656 }
657 // Invalid: test devices with property id wrong format.
658 {
659 json configFile = validConfigFile;
660 configFile["chassis"][0]["devices"][0]["id"] = "id#";
661 EXPECT_JSON_INVALID(configFile, "Validation failed.",
662 "u'id#' does not match u'^[A-Za-z0-9_]+$'");
663 }
664 // Invalid: test devices with property rails empty array.
665 {
666 json configFile = validConfigFile;
667 configFile["chassis"][0]["devices"][0]["rails"] = json::array();
668 EXPECT_JSON_INVALID(configFile, "Validation failed.",
669 "[] is too short");
670 }
671}
Bob King4ab8cbb2020-01-21 11:10:48 +0800672TEST(ValidateRegulatorsConfigTest, I2CCompareBit)
673{
674 json i2cCompareBitFile = validConfigFile;
675 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
676 "0xA0";
677 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
678 3;
679 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
680 // Valid: test rule actions i2c_compare_bit.
681 {
682 json configFile = i2cCompareBitFile;
683 EXPECT_JSON_VALID(configFile);
684 }
685 // Invalid: test i2c_compare_bit with no register.
686 {
687 json configFile = i2cCompareBitFile;
688 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
689 "register");
690 EXPECT_JSON_INVALID(configFile, "Validation failed.",
691 "u'register' is a required property");
692 }
693 // Invalid: test i2c_compare_bit with no position.
694 {
695 json configFile = i2cCompareBitFile;
696 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
697 "position");
698 EXPECT_JSON_INVALID(configFile, "Validation failed.",
699 "u'position' is a required property");
700 }
701 // Invalid: test i2c_compare_bit with no value.
702 {
703 json configFile = i2cCompareBitFile;
704 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value");
705 EXPECT_JSON_INVALID(configFile, "Validation failed.",
706 "u'value' is a required property");
707 }
708 // Invalid: test i2c_compare_bit with register wrong type.
709 {
710 json configFile = i2cCompareBitFile;
711 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1;
712 EXPECT_JSON_INVALID(configFile, "Validation failed.",
713 "1 is not of type u'string'");
714 }
715 // Invalid: test i2c_compare_bit with register wrong format.
716 {
717 json configFile = i2cCompareBitFile;
718 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
719 "0xA00";
720 EXPECT_JSON_INVALID(configFile, "Validation failed.",
721 "u'0xA00' does not match u'^0x[0-9A-Fa-f]{2}$'");
722 }
723 // Invalid: test i2c_compare_bit with position wrong type.
724 {
725 json configFile = i2cCompareBitFile;
726 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
727 3.1;
728 EXPECT_JSON_INVALID(configFile, "Validation failed.",
729 "3.1 is not of type u'integer'");
730 }
731 // Invalid: test i2c_compare_bit with position greater than 7.
732 {
733 json configFile = i2cCompareBitFile;
734 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8;
735 EXPECT_JSON_INVALID(configFile, "Validation failed.",
736 "8 is greater than the maximum of 7");
737 }
738 // Invalid: test i2c_compare_bit with position less than 0.
739 {
740 json configFile = i2cCompareBitFile;
741 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
742 -1;
743 EXPECT_JSON_INVALID(configFile, "Validation failed.",
744 "-1 is less than the minimum of 0");
745 }
746 // Invalid: test i2c_compare_bit with value wrong type.
747 {
748 json configFile = i2cCompareBitFile;
749 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1";
750 EXPECT_JSON_INVALID(configFile, "Validation failed.",
751 "u'1' is not of type u'integer'");
752 }
753 // Invalid: test i2c_compare_bit with value greater than 1.
754 {
755 json configFile = i2cCompareBitFile;
756 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2;
757 EXPECT_JSON_INVALID(configFile, "Validation failed.",
758 "2 is greater than the maximum of 1");
759 }
760 // Invalid: test i2c_compare_bit with value less than 0.
761 {
762 json configFile = i2cCompareBitFile;
763 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1;
764 EXPECT_JSON_INVALID(configFile, "Validation failed.",
765 "-1 is less than the minimum of 0");
766 }
767}
Bob King514023d2020-01-21 11:13:05 +0800768TEST(ValidateRegulatorsConfigTest, I2CCompareByte)
769{
770 json i2cCompareByteFile = validConfigFile;
771 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]
772 ["register"] = "0x82";
773 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
774 "0x40";
775 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
776 "0x7F";
777 // Valid: test i2c_compare_byte with all properties.
778 {
779 json configFile = i2cCompareByteFile;
780 EXPECT_JSON_VALID(configFile);
781 }
782 // Valid: test i2c_compare_byte with all required properties.
783 {
784 json configFile = i2cCompareByteFile;
785 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask");
786 EXPECT_JSON_VALID(configFile);
787 }
788 // Invalid: test i2c_compare_byte with no register.
789 {
790 json configFile = i2cCompareByteFile;
791 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase(
792 "register");
793 EXPECT_JSON_INVALID(configFile, "Validation failed.",
794 "u'register' is a required property");
795 }
796 // Invalid: test i2c_compare_byte with no value.
797 {
798 json configFile = i2cCompareByteFile;
799 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value");
800 EXPECT_JSON_INVALID(configFile, "Validation failed.",
801 "u'value' is a required property");
802 }
803 // Invalid: test i2c_compare_byte with property register wrong type.
804 {
805 json configFile = i2cCompareByteFile;
806 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
807 1;
808 EXPECT_JSON_INVALID(configFile, "Validation failed.",
809 "1 is not of type u'string'");
810 }
811 // Invalid: test i2c_compare_byte with property value wrong type.
812 {
813 json configFile = i2cCompareByteFile;
814 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1;
815 EXPECT_JSON_INVALID(configFile, "Validation failed.",
816 "1 is not of type u'string'");
817 }
818 // Invalid: test i2c_compare_byte with property mask wrong type.
819 {
820 json configFile = i2cCompareByteFile;
821 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1;
822 EXPECT_JSON_INVALID(configFile, "Validation failed.",
823 "1 is not of type u'string'");
824 }
825 // Invalid: test i2c_compare_byte with property register more than 2 hex
826 // digits.
827 {
828 json configFile = i2cCompareByteFile;
829 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
830 "0x820";
831 EXPECT_JSON_INVALID(configFile, "Validation failed.",
832 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
833 }
834 // Invalid: test i2c_compare_byte with property value more than 2 hex
835 // digits.
836 {
837 json configFile = i2cCompareByteFile;
838 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
839 "0x820";
840 EXPECT_JSON_INVALID(configFile, "Validation failed.",
841 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
842 }
843 // Invalid: test i2c_compare_byte with property mask more than 2 hex digits.
844 {
845 json configFile = i2cCompareByteFile;
846 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
847 "0x820";
848 EXPECT_JSON_INVALID(configFile, "Validation failed.",
849 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
850 }
851 // Invalid: test i2c_compare_byte with property register less than 2 hex
852 // digits.
853 {
854 json configFile = i2cCompareByteFile;
855 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
856 "0x8";
857 EXPECT_JSON_INVALID(configFile, "Validation failed.",
858 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
859 }
860 // Invalid: test i2c_compare_byte with property value less than 2 hex
861 // digits.
862 {
863 json configFile = i2cCompareByteFile;
864 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
865 "0x8";
866 EXPECT_JSON_INVALID(configFile, "Validation failed.",
867 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
868 }
869 // Invalid: test i2c_compare_byte with property mask less than 2 hex digits.
870 {
871 json configFile = i2cCompareByteFile;
872 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
873 "0x8";
874 EXPECT_JSON_INVALID(configFile, "Validation failed.",
875 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
876 }
877 // Invalid: test i2c_compare_byte with property register no leading prefix.
878 {
879 json configFile = i2cCompareByteFile;
880 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
881 "82";
882 EXPECT_JSON_INVALID(configFile, "Validation failed.",
883 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
884 }
885 // Invalid: test i2c_compare_byte with property value no leading prefix.
886 {
887 json configFile = i2cCompareByteFile;
888 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
889 "82";
890 EXPECT_JSON_INVALID(configFile, "Validation failed.",
891 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
892 }
893 // Invalid: test i2c_compare_byte with property mask no leading prefix.
894 {
895 json configFile = i2cCompareByteFile;
896 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82";
897 EXPECT_JSON_INVALID(configFile, "Validation failed.",
898 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
899 }
900 // Invalid: test i2c_compare_byte with property register invalid hex digit.
901 {
902 json configFile = i2cCompareByteFile;
903 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
904 "0xG1";
905 EXPECT_JSON_INVALID(configFile, "Validation failed.",
906 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
907 }
908 // Invalid: test i2c_compare_byte with property value invalid hex digit.
909 {
910 json configFile = i2cCompareByteFile;
911 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
912 "0xG1";
913 EXPECT_JSON_INVALID(configFile, "Validation failed.",
914 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
915 }
916 // Invalid: test i2c_compare_byte with property mask invalid hex digit.
917 {
918 json configFile = i2cCompareByteFile;
919 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
920 "0xG1";
921 EXPECT_JSON_INVALID(configFile, "Validation failed.",
922 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
923 }
924}
Bob Kingfb162bb2020-01-21 11:28:07 +0800925TEST(ValidateRegulatorsConfigTest, I2CCompareBytes)
926{
927 json i2cCompareBytesFile = validConfigFile;
928 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
929 ["register"] = "0x82";
930 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
931 ["values"] = {"0x02", "0x73"};
932 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
933 ["masks"] = {"0x7F", "0x7F"};
934 // Valid: test i2c_compare_bytes.
935 {
936 json configFile = i2cCompareBytesFile;
937 EXPECT_JSON_VALID(configFile);
938 }
939 // Valid: test i2c_compare_bytes with all required properties.
940 {
941 json configFile = i2cCompareBytesFile;
942 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
943 "masks");
944 EXPECT_JSON_VALID(configFile);
945 }
946 // Invalid: test i2c_compare_bytes with no register.
947 {
948 json configFile = i2cCompareBytesFile;
949 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
950 "register");
951 EXPECT_JSON_INVALID(configFile, "Validation failed.",
952 "u'register' is a required property");
953 }
954 // Invalid: test i2c_compare_bytes with no values.
955 {
956 json configFile = i2cCompareBytesFile;
957 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
958 "values");
959 EXPECT_JSON_INVALID(configFile, "Validation failed.",
960 "u'values' is a required property");
961 }
962 // Invalid: test i2c_compare_bytes with property values as empty array.
963 {
964 json configFile = i2cCompareBytesFile;
965 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] =
966 json::array();
967 EXPECT_JSON_INVALID(configFile, "Validation failed.",
968 "[] is too short");
969 }
970 // Invalid: test i2c_compare_bytes with property masks as empty array.
971 {
972 json configFile = i2cCompareBytesFile;
973 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] =
974 json::array();
975 EXPECT_JSON_INVALID(configFile, "Validation failed.",
976 "[] is too short");
977 }
978 // Invalid: test i2c_compare_bytes with property register wrong type.
979 {
980 json configFile = i2cCompareBytesFile;
981 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
982 1;
983 EXPECT_JSON_INVALID(configFile, "Validation failed.",
984 "1 is not of type u'string'");
985 }
986 // Invalid: test i2c_compare_bytes with property values wrong type.
987 {
988 json configFile = i2cCompareBytesFile;
989 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1;
990 EXPECT_JSON_INVALID(configFile, "Validation failed.",
991 "1 is not of type u'array'");
992 }
993 // Invalid: test i2c_compare_bytes with property masks wrong type.
994 {
995 json configFile = i2cCompareBytesFile;
996 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1;
997 EXPECT_JSON_INVALID(configFile, "Validation failed.",
998 "1 is not of type u'array'");
999 }
1000 // Invalid: test i2c_compare_bytes with property register more than 2 hex
1001 // digits.
1002 {
1003 json configFile = i2cCompareBytesFile;
1004 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1005 "0x820";
1006 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1007 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1008 }
1009 // Invalid: test i2c_compare_bytes with property values more than 2 hex
1010 // digits.
1011 {
1012 json configFile = i2cCompareBytesFile;
1013 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1014 "0x820";
1015 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1016 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1017 }
1018 // Invalid: test i2c_compare_bytes with property masks more than 2 hex
1019 // digits.
1020 {
1021 json configFile = i2cCompareBytesFile;
1022 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1023 "0x820";
1024 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1025 "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1026 }
1027 // Invalid: test i2c_compare_bytes with property register less than 2 hex
1028 // digits.
1029 {
1030 json configFile = i2cCompareBytesFile;
1031 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1032 "0x8";
1033 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1034 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1035 }
1036 // Invalid: test i2c_compare_bytes with property values less than 2 hex
1037 // digits.
1038 {
1039 json configFile = i2cCompareBytesFile;
1040 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1041 "0x8";
1042 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1043 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1044 }
1045 // Invalid: test i2c_compare_bytes with property masks less than 2 hex
1046 // digits.
1047 {
1048 json configFile = i2cCompareBytesFile;
1049 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1050 "0x8";
1051 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1052 "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1053 }
1054 // Invalid: test i2c_compare_bytes with property register no leading prefix.
1055 {
1056 json configFile = i2cCompareBytesFile;
1057 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1058 "82";
1059 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1060 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1061 }
1062 // Invalid: test i2c_compare_bytes with property values no leading prefix.
1063 {
1064 json configFile = i2cCompareBytesFile;
1065 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1066 "82";
1067 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1068 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1069 }
1070 // Invalid: test i2c_compare_bytes with property masks no leading prefix.
1071 {
1072 json configFile = i2cCompareBytesFile;
1073 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1074 "82";
1075 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1076 "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1077 }
1078 // Invalid: test i2c_compare_bytes with property register invalid hex digit.
1079 {
1080 json configFile = i2cCompareBytesFile;
1081 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1082 "0xG1";
1083 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1084 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1085 }
1086 // Invalid: test i2c_compare_bytes with property values invalid hex digit.
1087 {
1088 json configFile = i2cCompareBytesFile;
1089 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1090 "0xG1";
1091 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1092 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1093 }
1094 // Invalid: test i2c_compare_bytes with property masks invalid hex digit.
1095 {
1096 json configFile = i2cCompareBytesFile;
1097 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1098 "0xG1";
1099 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1100 "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1101 }
1102}
Bob Kingca93f1f2020-01-31 11:21:16 +08001103TEST(ValidateRegulatorsConfigTest, I2CInterface)
1104{
1105 // Valid: test i2c_interface.
1106 {
1107 json configFile = validConfigFile;
1108 EXPECT_JSON_VALID(configFile);
1109 }
1110 // Invalid: testi2c_interface with no bus.
1111 {
1112 json configFile = validConfigFile;
1113 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase("bus");
1114 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1115 "u'bus' is a required property");
1116 }
1117 // Invalid: test i2c_interface with no address.
1118 {
1119 json configFile = validConfigFile;
1120 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase(
1121 "address");
1122 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1123 "u'address' is a required property");
1124 }
1125 // Invalid: test i2c_interface with property bus wrong type.
1126 {
1127 json configFile = validConfigFile;
1128 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = true;
1129 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1130 "True is not of type u'integer'");
1131 }
1132 // Invalid: test i2c_interface with property address wrong
1133 // type.
1134 {
1135 json configFile = validConfigFile;
1136 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1137 true;
1138 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1139 "True is not of type u'string'");
1140 }
1141 // Invalid: test i2c_interface with property bus less than
1142 // 0.
1143 {
1144 json configFile = validConfigFile;
1145 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = -1;
1146 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1147 "-1 is less than the minimum of 0");
1148 }
1149 // Invalid: test i2c_interface with property address wrong
1150 // format.
1151 {
1152 json configFile = validConfigFile;
1153 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1154 "0x700";
1155 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1156 "u'0x700' does not match u'^0x[0-9A-Fa-f]{2}$'");
1157 }
1158}
Bob Kingead0b052020-01-21 11:29:03 +08001159TEST(ValidateRegulatorsConfigTest, If)
1160{
1161 json ifFile = validConfigFile;
1162 ifFile["rules"][0]["actions"][1]["if"]["condition"]["run_rule"] =
1163 "is_downlevel_regulator";
1164 ifFile["rules"][0]["actions"][1]["if"]["then"][0]["run_rule"] =
1165 "configure_downlevel_regulator";
1166 ifFile["rules"][0]["actions"][1]["if"]["else"][0]["run_rule"] =
1167 "configure_downlevel_regulator";
1168 // Valid: test if.
1169 {
1170 json configFile = ifFile;
1171 EXPECT_JSON_VALID(configFile);
1172 }
1173 // Valid: test if with required properties.
1174 {
1175 json configFile = ifFile;
1176 configFile["rules"][0]["actions"][1]["if"].erase("else");
1177 EXPECT_JSON_VALID(configFile);
1178 }
1179 // Invalid: test if with no property condition.
1180 {
1181 json configFile = ifFile;
1182 configFile["rules"][0]["actions"][1]["if"].erase("condition");
1183 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1184 "u'condition' is a required property");
1185 }
1186 // Invalid: test if with no property then.
1187 {
1188 json configFile = ifFile;
1189 configFile["rules"][0]["actions"][1]["if"].erase("then");
1190 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1191 "u'then' is a required property");
1192 }
1193 // Invalid: test if with property then empty array.
1194 {
1195 json configFile = ifFile;
1196 configFile["rules"][0]["actions"][1]["if"]["then"] = json::array();
1197 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1198 "[] is too short");
1199 }
1200 // Invalid: test if with property else empty array.
1201 {
1202 json configFile = ifFile;
1203 configFile["rules"][0]["actions"][1]["if"]["else"] = json::array();
1204 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1205 "[] is too short");
1206 }
1207 // Invalid: test if with property condition wrong type.
1208 {
1209 json configFile = ifFile;
1210 configFile["rules"][0]["actions"][1]["if"]["condition"] = 1;
1211 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1212 "1 is not of type u'object'");
1213 }
1214 // Invalid: test if with property then wrong type.
1215 {
1216 json configFile = ifFile;
1217 configFile["rules"][0]["actions"][1]["if"]["then"] = 1;
1218 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1219 "1 is not of type u'array'");
1220 }
1221 // Invalid: test if with property else wrong type.
1222 {
1223 json configFile = ifFile;
1224 configFile["rules"][0]["actions"][1]["if"]["else"] = 1;
1225 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1226 "1 is not of type u'array'");
1227 }
1228}
Bob Kingbfe9fe72020-01-21 11:29:57 +08001229TEST(ValidateRegulatorsConfigTest, Not)
1230{
1231 json notFile = validConfigFile;
1232 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] =
1233 "0xA0";
1234 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] =
1235 "0xFF";
1236 // Valid: test not.
1237 {
1238 json configFile = notFile;
1239 EXPECT_JSON_VALID(configFile);
1240 }
1241 // Invalid: test not with wrong type.
1242 {
1243 json configFile = notFile;
1244 configFile["rules"][0]["actions"][1]["not"] = 1;
1245 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1246 "1 is not of type u'object'");
1247 }
1248}
Bob Kingcfc29d02020-01-21 11:30:50 +08001249TEST(ValidateRegulatorsConfigTest, Or)
1250{
1251 json orFile = validConfigFile;
1252 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] =
1253 "0xA0";
1254 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] =
1255 "0x00";
1256 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] =
1257 "0xA1";
1258 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] =
1259 "0x00";
1260 // Valid: test or.
1261 {
1262 json configFile = orFile;
1263 EXPECT_JSON_VALID(configFile);
1264 }
1265 // Invalid: test or with empty array.
1266 {
1267 json configFile = orFile;
1268 configFile["rules"][0]["actions"][1]["or"] = json::array();
1269 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1270 "[] is too short");
1271 }
1272 // Invalid: test or with wrong type.
1273 {
1274 json configFile = orFile;
1275 configFile["rules"][0]["actions"][1]["or"] = 1;
1276 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1277 "1 is not of type u'array'");
1278 }
1279}
Bob Kingd6618092020-01-21 11:31:46 +08001280TEST(ValidateRegulatorsConfigTest, PmbusReadSensor)
1281{
1282 json pmbusReadSensorFile = validConfigFile;
1283 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1284 "vout";
1285 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1286 ["command"] = "0x8B";
1287 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1288 ["format"] = "linear_16";
1289 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1290 ["exponent"] = -8;
1291 // Valid: test pmbus_read_sensor.
1292 {
1293 json configFile = pmbusReadSensorFile;
1294 EXPECT_JSON_VALID(configFile);
1295 }
1296 // Valid: test pmbus_read_sensor with required properties.
1297 {
1298 json configFile = pmbusReadSensorFile;
1299 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1300 "exponent");
1301 EXPECT_JSON_VALID(configFile);
1302 }
1303 // Invalid: test pmbus_read_sensor with no type.
1304 {
1305 json configFile = pmbusReadSensorFile;
1306 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type");
1307 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1308 "u'type' is a required property");
1309 }
1310 // Invalid: test pmbus_read_sensor with no command.
1311 {
1312 json configFile = pmbusReadSensorFile;
1313 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1314 "command");
1315 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1316 "u'command' is a required property");
1317 }
1318 // Invalid: test pmbus_read_sensor with no format.
1319 {
1320 json configFile = pmbusReadSensorFile;
1321 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1322 "format");
1323 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1324 "u'format' is a required property");
1325 }
1326 // Invalid: test pmbus_read_sensor with property type wrong type.
1327 {
1328 json configFile = pmbusReadSensorFile;
1329 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1330 true;
1331 EXPECT_JSON_INVALID(
1332 configFile, "Validation failed.",
1333 "True is not one of [u'iout', u'iout_peak', u'iout_valley', "
1334 "u'pout', u'temperature', u'temperature_peak', u'vout', "
1335 "u'vout_peak', u'vout_valley']");
1336 }
1337 // Invalid: test pmbus_read_sensor with property command wrong type.
1338 {
1339 json configFile = pmbusReadSensorFile;
1340 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1341 true;
1342 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1343 "True is not of type u'string'");
1344 }
1345 // Invalid: test pmbus_read_sensor with property format wrong type.
1346 {
1347 json configFile = pmbusReadSensorFile;
1348 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1349 true;
1350 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1351 "True is not one of [u'linear_11', u'linear_16']");
1352 }
1353 // Invalid: test pmbus_read_sensor with property exponent wrong type.
1354 {
1355 json configFile = pmbusReadSensorFile;
1356 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] =
1357 true;
1358 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1359 "True is not of type u'integer'");
1360 }
1361 // Invalid: test pmbus_read_sensor with property type wrong format.
1362 {
1363 json configFile = pmbusReadSensorFile;
1364 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1365 "foo";
1366 EXPECT_JSON_INVALID(
1367 configFile, "Validation failed.",
1368 "u'foo' is not one of [u'iout', u'iout_peak', u'iout_valley', "
1369 "u'pout', u'temperature', u'temperature_peak', u'vout', "
1370 "u'vout_peak', u'vout_valley']");
1371 }
1372 // Invalid: test pmbus_read_sensor with property command wrong format.
1373 {
1374 json configFile = pmbusReadSensorFile;
1375 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1376 "0x8B0";
1377 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1378 "u'0x8B0' does not match u'^0x[0-9a-fA-F]{2}$'");
1379 }
1380 // Invalid: test pmbus_read_sensor with property format wrong format.
1381 {
1382 json configFile = pmbusReadSensorFile;
1383 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1384 "foo";
1385 EXPECT_JSON_INVALID(
1386 configFile, "Validation failed.",
1387 "u'foo' is not one of [u'linear_11', u'linear_16']");
1388 }
1389}
Bob King02179c62020-01-21 11:32:36 +08001390TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand)
1391{
1392 json pmbusWriteVoutCommandFile = validConfigFile;
1393 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1394 ["pmbus_write_vout_command"]["volts"] = 1.03;
1395 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1396 ["pmbus_write_vout_command"]["format"] = "linear";
1397 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1398 ["pmbus_write_vout_command"]["exponent"] = -8;
1399 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1400 ["pmbus_write_vout_command"]["is_verified"] = true;
1401 // Valid: test pmbus_write_vout_command.
1402 {
1403 json configFile = pmbusWriteVoutCommandFile;
1404 EXPECT_JSON_VALID(configFile);
1405 }
1406 // Valid: test pmbus_write_vout_command with required properties.
1407 {
1408 json configFile = pmbusWriteVoutCommandFile;
1409 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1410 "volts");
1411 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1412 "exponent");
1413 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1414 "is_verified");
1415 EXPECT_JSON_VALID(configFile);
1416 }
1417 // Invalid: test pmbus_write_vout_command with no format.
1418 {
1419 json configFile = pmbusWriteVoutCommandFile;
1420 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1421 "format");
1422 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1423 "u'format' is a required property");
1424 }
1425 // Invalid: test pmbus_write_vout_command with property volts wrong type.
1426 {
1427 json configFile = pmbusWriteVoutCommandFile;
1428 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1429 ["volts"] = true;
1430 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1431 "True is not of type u'number'");
1432 }
1433 // Invalid: test pmbus_write_vout_command with property format wrong type.
1434 {
1435 json configFile = pmbusWriteVoutCommandFile;
1436 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1437 ["format"] = true;
1438 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1439 "True is not one of [u'linear']");
1440 }
1441 // Invalid: test pmbus_write_vout_command with property exponent wrong type.
1442 {
1443 json configFile = pmbusWriteVoutCommandFile;
1444 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1445 ["exponent"] = 1.3;
1446 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1447 "1.3 is not of type u'integer'");
1448 }
1449 // Invalid: test pmbus_write_vout_command with property is_verified wrong
1450 // type.
1451 {
1452 json configFile = pmbusWriteVoutCommandFile;
1453 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1454 ["is_verified"] = 1;
1455 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1456 "1 is not of type u'boolean'");
1457 }
1458 // Invalid: test pmbus_write_vout_command with property format wrong format.
1459 {
1460 json configFile = pmbusWriteVoutCommandFile;
1461 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1462 ["format"] = "foo";
1463 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1464 "u'foo' is not one of [u'linear']");
1465 }
1466}
Bob King99d8fa12020-01-31 11:23:40 +08001467TEST(ValidateRegulatorsConfigTest, PresenceDetection)
1468{
1469 json presenceDetectionFile = validConfigFile;
1470 presenceDetectionFile
1471 ["chassis"][0]["devices"][0]["presence_detection"]["comments"][0] =
1472 "Regulator is only present on the FooBar backplane";
1473 presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
1474 ["rule_id"] = "is_foobar_backplane_installed_rule";
1475 // Valid: test presence_detection with only property rule_id.
1476 {
1477 json configFile = presenceDetectionFile;
1478 EXPECT_JSON_VALID(configFile);
1479 }
1480 // Valid: test presence_detection with only property actions.
1481 {
1482 json configFile = presenceDetectionFile;
1483 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1484 "rule_id");
1485 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1486 [0]["compare_presence"]["fru"] =
1487 "/system/chassis/motherboard/cpu3";
1488 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1489 [0]["compare_presence"]["value"] = true;
1490 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1491 "comments");
1492 EXPECT_JSON_VALID(configFile);
1493 }
1494 // Invalid: test presence_detection with both property rule_id and actions.
1495 {
1496 json configFile = presenceDetectionFile;
1497 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1498 [0]["compare_presence"]["fru"] =
1499 "/system/chassis/motherboard/cpu3";
1500 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1501 [0]["compare_presence"]["value"] = true;
1502 EXPECT_JSON_INVALID(
1503 configFile, "Validation failed.",
1504 "{u'comments': [u'Regulator is only present on the FooBar "
1505 "backplane'], u'actions': [{u'compare_presence': {u'value': True, "
1506 "u'fru': u'/system/chassis/motherboard/cpu3'}}], u'rule_id': "
1507 "u'is_foobar_backplane_installed_rule'} is valid under each of "
1508 "{u'required': [u'actions']}, {u'required': [u'rule_id']}");
1509 }
1510 // Invalid: test presence_detection with no rule_id and actions.
1511 {
1512 json configFile = presenceDetectionFile;
1513 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1514 "rule_id");
1515 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1516 "u'rule_id' is a required property");
1517 }
1518 // Invalid: test presence_detection with property comments wrong type.
1519 {
1520 json configFile = presenceDetectionFile;
1521 configFile["chassis"][0]["devices"][0]["presence_detection"]
1522 ["comments"] = true;
1523 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1524 "True is not of type u'array'");
1525 }
1526 // Invalid: test presence_detection with property rule_id wrong type.
1527 {
1528 json configFile = presenceDetectionFile;
1529 configFile["chassis"][0]["devices"][0]["presence_detection"]
1530 ["rule_id"] = true;
1531 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1532 "True is not of type u'string'");
1533 }
1534 // Invalid: test presence_detection with property actions wrong type.
1535 {
1536 json configFile = presenceDetectionFile;
1537 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1538 "rule_id");
1539 configFile["chassis"][0]["devices"][0]["presence_detection"]
1540 ["actions"] = true;
1541 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1542 "True is not of type u'array'");
1543 }
1544 // Invalid: test presence_detection with property rule_id wrong format.
1545 {
1546 json configFile = presenceDetectionFile;
1547 configFile["chassis"][0]["devices"][0]["presence_detection"]
1548 ["rule_id"] = "id@";
1549 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1550 "u'id@' does not match u'^[A-Za-z0-9_]+$'");
1551 }
1552 // Invalid: test presence_detection with property comments empty array.
1553 {
1554 json configFile = presenceDetectionFile;
1555 configFile["chassis"][0]["devices"][0]["presence_detection"]
1556 ["comments"] = json::array();
1557 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1558 "[] is too short");
1559 }
1560 // Invalid: test presence_detection with property actions empty array.
1561 {
1562 json configFile = presenceDetectionFile;
1563 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1564 "rule_id");
1565 configFile["chassis"][0]["devices"][0]["presence_detection"]
1566 ["actions"] = json::array();
1567 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1568 "[] is too short");
1569 }
1570}
Bob Kinge86c2e52020-01-21 11:33:32 +08001571TEST(ValidateRegulatorsConfigTest, RunRule)
1572{
1573 json runRuleFile = validConfigFile;
1574 runRuleFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule1";
1575 // Valid: test run_rule.
1576 {
1577 json configFile = runRuleFile;
1578 EXPECT_JSON_VALID(configFile);
1579 }
1580 // Invalid: test run_rule wrong type.
1581 {
1582 json configFile = runRuleFile;
1583 configFile["rules"][0]["actions"][1]["run_rule"] = true;
1584 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1585 "True is not of type u'string'");
1586 }
1587 // Invalid: test run_rule wrong format.
1588 {
1589 json configFile = runRuleFile;
1590 configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%";
1591 EXPECT_JSON_INVALID(
1592 configFile, "Validation failed.",
1593 "u'set_voltage_rule%' does not match u'^[A-Za-z0-9_]+$'");
1594 }
1595}
Bob King68230aa2020-01-21 11:34:33 +08001596TEST(ValidateRegulatorsConfigTest, SetDevice)
1597{
1598 json setDeviceFile = validConfigFile;
1599 setDeviceFile["rules"][0]["actions"][1]["set_device"] = "io_expander2";
1600 // Valid: test set_device.
1601 {
1602 json configFile = setDeviceFile;
1603 EXPECT_JSON_VALID(configFile);
1604 }
1605 // Invalid: test set_device wrong type.
1606 {
1607 json configFile = setDeviceFile;
1608 configFile["rules"][0]["actions"][1]["set_device"] = true;
1609 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1610 "True is not of type u'string'");
1611 }
1612 // Invalid: test set_device wrong format.
1613 {
1614 json configFile = setDeviceFile;
1615 configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%";
1616 EXPECT_JSON_INVALID(
1617 configFile, "Validation failed.",
1618 "u'io_expander2%' does not match u'^[A-Za-z0-9_]+$'");
1619 }
1620}