xref: /openbmc/phosphor-power/phosphor-regulators/test/validate-regulators-config_tests.cpp (revision 5b27a95bec8bdcd84728fbf3415e1760aa95ebe5)
1 /**
2  * Copyright c 2020 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <errno.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/wait.h>
20 
21 #include <nlohmann/json.hpp>
22 
23 #include <fstream>
24 
25 #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 
37 using json = nlohmann::json;
38 
39 const 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           "comments": [ "Reads sensors from a PMBus regulator rail" ],
57           "id": "read_sensors_rule",
58           "actions": [
59             {
60               "comments": [ "Read output voltage from READ_VOUT." ],
61               "pmbus_read_sensor": {
62                 "type": "vout",
63                 "command": "0x8B",
64                 "format": "linear_16"
65               }
66             }
67           ]
68         }
69       ],
70 
71       "chassis": [
72         {
73           "comments": [ "Chassis number 1 containing CPUs and memory" ],
74           "number": 1,
75           "devices": [
76             {
77               "comments": [ "IR35221 regulator producing the Vdd rail" ],
78               "id": "vdd_regulator",
79               "is_regulator": true,
80               "fru": "/system/chassis/motherboard/regulator1",
81               "i2c_interface": {
82                 "bus": 1,
83                 "address": "0x70"
84               },
85               "rails": [
86                 {
87                   "comments": [ "Vdd rail" ],
88                   "id": "vdd",
89                   "configuration": {
90                     "volts": 1.03,
91                     "rule_id": "set_voltage_rule"
92                   },
93                   "sensor_monitoring": {
94                     "rule_id": "read_sensors_rule"
95                   }
96                 }
97               ]
98             }
99           ]
100         }
101       ]
102     }
103 )"_json;
104 
105 std::string createTmpFile()
106 {
107     // create temporary file using mkstemp under /tmp/. random name for XXXXXX
108     char fileName[] = "/tmp/temp-XXXXXX";
109     int fd = mkstemp(fileName);
110     if (fd == -1)
111     {
112         perror("Can't create temporary file");
113     }
114     close(fd);
115     return fileName;
116 }
117 
118 std::string getValidationToolCommand(const std::string& configFileName)
119 {
120     std::string command = "python ../tools/validate-regulators-config.py -s \
121                            ../schema/config_schema.json -c ";
122     command += configFileName;
123     return command;
124 }
125 
126 int runToolForOutput(const std::string& configFileName, std::string& output,
127                      bool isReadingStderr = false)
128 {
129     // run the validation tool with the temporary file and return the output
130     // of the validation tool.
131     std::string command = getValidationToolCommand(configFileName);
132     // reading the stderr while isReadingStderr is true.
133     if (isReadingStderr == true)
134     {
135         command += " 2>&1 >/dev/null";
136     }
137     // get the jsonschema print from validation tool.
138     char buffer[256];
139     std::string result = "";
140     // to get the stdout from the validation tool.
141     FILE* pipe = popen(command.c_str(), "r");
142     if (!pipe)
143     {
144         throw std::runtime_error("popen() failed!");
145     }
146     while (!std::feof(pipe))
147     {
148         if (fgets(buffer, sizeof buffer, pipe) != NULL)
149         {
150             result += buffer;
151         }
152     }
153     int returnValue = pclose(pipe);
154     // Check if pclose() failed
155     if (returnValue == -1)
156     {
157         // unable to close pipe.  Print error and exit function.
158         throw std::runtime_error("pclose() failed!");
159     }
160     std::string firstLine = result.substr(0, result.find('\n'));
161     output = firstLine;
162     // Get command exit status from return value
163     int exitStatus = WEXITSTATUS(returnValue);
164     return exitStatus;
165 }
166 
167 void expectFileValid(const std::string& configFileName)
168 {
169     std::string errorMessage = "";
170     std::string outputMessage = "";
171     EXPECT_EQ(runToolForOutput(configFileName, errorMessage, true), 0);
172     EXPECT_EQ(runToolForOutput(configFileName, outputMessage), 0);
173     EXPECT_EQ(errorMessage, "");
174     EXPECT_EQ(outputMessage, "");
175 }
176 
177 void expectFileInvalid(const std::string& configFileName,
178                        const std::string& expectedErrorMessage,
179                        const std::string& expectedOutputMessage)
180 {
181     std::string errorMessage = "";
182     std::string outputMessage = "";
183     EXPECT_EQ(runToolForOutput(configFileName, errorMessage, true), 1);
184     EXPECT_EQ(runToolForOutput(configFileName, outputMessage), 1);
185     EXPECT_EQ(errorMessage, expectedErrorMessage);
186     EXPECT_EQ(outputMessage, expectedOutputMessage);
187 }
188 
189 void expectJsonValid(const json configFileJson)
190 {
191     std::string fileName;
192     fileName = createTmpFile();
193     std::string jsonData = configFileJson.dump();
194     std::ofstream out(fileName);
195     out << jsonData;
196     out.close();
197 
198     EXPECT_FILE_VALID(fileName);
199     unlink(fileName.c_str());
200 }
201 
202 void expectJsonInvalid(const json configFileJson,
203                        const std::string& expectedErrorMessage,
204                        const std::string& expectedOutputMessage)
205 {
206     std::string fileName;
207     fileName = createTmpFile();
208     std::string jsonData = configFileJson.dump();
209     std::ofstream out(fileName);
210     out << jsonData;
211     out.close();
212 
213     EXPECT_FILE_INVALID(fileName, expectedErrorMessage, expectedOutputMessage);
214     unlink(fileName.c_str());
215 }
216 
217 TEST(ValidateRegulatorsConfigTest, And)
218 {
219     // Valid.
220     {
221         json configFile = validConfigFile;
222         json andAction =
223             R"(
224                 {
225                  "and": [
226                     { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
227                     { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
228                   ]
229                 }
230             )"_json;
231         configFile["rules"][0]["actions"].push_back(andAction);
232         EXPECT_JSON_VALID(configFile);
233     }
234 
235     // Invalid: actions property value is an empty array.
236     {
237         json configFile = validConfigFile;
238         json andAction =
239             R"(
240                 {
241                  "and": []
242                 }
243             )"_json;
244         configFile["rules"][0]["actions"].push_back(andAction);
245         EXPECT_JSON_INVALID(configFile, "Validation failed.",
246                             "[] is too short");
247     }
248 
249     // Invalid: actions property has incorrect value data type.
250     {
251         json configFile = validConfigFile;
252         json andAction =
253             R"(
254                 {
255                  "and": true
256                 }
257             )"_json;
258         configFile["rules"][0]["actions"].push_back(andAction);
259         EXPECT_JSON_INVALID(configFile, "Validation failed.",
260                             "True is not of type u'array'");
261     }
262 
263     // Invalid: actions property value contains wrong element type
264     {
265         json configFile = validConfigFile;
266         json andAction =
267             R"(
268                 {
269                  "and": ["foo"]
270                 }
271             )"_json;
272         configFile["rules"][0]["actions"].push_back(andAction);
273         EXPECT_JSON_INVALID(configFile, "Validation failed.",
274                             "u'foo' is not of type u'object'");
275     }
276 }
277 TEST(ValidateRegulatorsConfigTest, Chassis)
278 {
279     // Valid: test chassis.
280     {
281         json configFile = validConfigFile;
282         EXPECT_JSON_VALID(configFile);
283     }
284     // Valid: test chassis with required properties.
285     {
286         json configFile = validConfigFile;
287         configFile["chassis"][0].erase("comments");
288         configFile["chassis"][0].erase("devices");
289         EXPECT_JSON_VALID(configFile);
290     }
291     // Invalid: test chassis with no number.
292     {
293         json configFile = validConfigFile;
294         configFile["chassis"][0].erase("number");
295         EXPECT_JSON_INVALID(configFile, "Validation failed.",
296                             "u'number' is a required property");
297     }
298     // Invalid: test chassis with property comments wrong type.
299     {
300         json configFile = validConfigFile;
301         configFile["chassis"][0]["comments"] = true;
302         EXPECT_JSON_INVALID(configFile, "Validation failed.",
303                             "True is not of type u'array'");
304     }
305     // Invalid: test chassis with property number wrong type.
306     {
307         json configFile = validConfigFile;
308         configFile["chassis"][0]["number"] = 1.3;
309         EXPECT_JSON_INVALID(configFile, "Validation failed.",
310                             "1.3 is not of type u'integer'");
311     }
312     // Invalid: test chassis with property devices wrong type.
313     {
314         json configFile = validConfigFile;
315         configFile["chassis"][0]["devices"] = true;
316         EXPECT_JSON_INVALID(configFile, "Validation failed.",
317                             "True is not of type u'array'");
318     }
319     // Invalid: test chassis with property comments empty array.
320     {
321         json configFile = validConfigFile;
322         configFile["chassis"][0]["comments"] = json::array();
323         EXPECT_JSON_INVALID(configFile, "Validation failed.",
324                             "[] is too short");
325     }
326     // Invalid: test chassis with property devices empty array.
327     {
328         json configFile = validConfigFile;
329         configFile["chassis"][0]["devices"] = json::array();
330         EXPECT_JSON_INVALID(configFile, "Validation failed.",
331                             "[] is too short");
332     }
333     // Invalid: test chassis with property number less than 1.
334     {
335         json configFile = validConfigFile;
336         configFile["chassis"][0]["number"] = 0;
337         EXPECT_JSON_INVALID(configFile, "Validation failed.",
338                             "0 is less than the minimum of 1");
339     }
340 }
341 TEST(ValidateRegulatorsConfigTest, ComparePresence)
342 {
343     json comparePresenceFile = validConfigFile;
344     comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
345         "/system/chassis/motherboard/regulator2";
346     comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
347         true;
348     // Valid.
349     {
350         json configFile = comparePresenceFile;
351         EXPECT_JSON_VALID(configFile);
352     }
353 
354     // Invalid: no FRU property.
355     {
356         json configFile = comparePresenceFile;
357         configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru");
358         EXPECT_JSON_INVALID(configFile, "Validation failed.",
359                             "u'fru' is a required property");
360     }
361 
362     // Invalid: FRU property length is string less than 1.
363     {
364         json configFile = comparePresenceFile;
365         configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = "";
366         EXPECT_JSON_INVALID(configFile, "Validation failed.",
367                             "u'' is too short");
368     }
369 
370     // Invalid: no value property.
371     {
372         json configFile = comparePresenceFile;
373         configFile["rules"][0]["actions"][1]["compare_presence"].erase("value");
374         EXPECT_JSON_INVALID(configFile, "Validation failed.",
375                             "u'value' is a required property");
376     }
377 
378     // Invalid: value property type is not boolean.
379     {
380         json configFile = comparePresenceFile;
381         configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1";
382         EXPECT_JSON_INVALID(configFile, "Validation failed.",
383                             "u'1' is not of type u'boolean'");
384     }
385 
386     // Invalid: FRU property type is not string.
387     {
388         json configFile = comparePresenceFile;
389         configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1;
390         EXPECT_JSON_INVALID(configFile, "Validation failed.",
391                             "1 is not of type u'string'");
392     }
393 }
394 TEST(ValidateRegulatorsConfigTest, CompareVpd)
395 {
396     json compareVpdFile = validConfigFile;
397     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
398         "/system/chassis/motherboard/regulator2";
399     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
400     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
401 
402     // Valid.
403     {
404         json configFile = compareVpdFile;
405         EXPECT_JSON_VALID(configFile);
406     }
407 
408     // Invalid: no FRU property.
409     {
410         json configFile = compareVpdFile;
411         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru");
412         EXPECT_JSON_INVALID(configFile, "Validation failed.",
413                             "u'fru' is a required property");
414     }
415 
416     // Invalid: no keyword property.
417     {
418         json configFile = compareVpdFile;
419         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword");
420         EXPECT_JSON_INVALID(configFile, "Validation failed.",
421                             "u'keyword' is a required property");
422     }
423 
424     // Invalid: no value property.
425     {
426         json configFile = compareVpdFile;
427         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
428         EXPECT_JSON_INVALID(configFile, "Validation failed.",
429                             "u'value' is a required property");
430     }
431 
432     // Invalid: property FRU wrong type.
433     {
434         json configFile = compareVpdFile;
435         configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1;
436         EXPECT_JSON_INVALID(configFile, "Validation failed.",
437                             "1 is not of type u'string'");
438     }
439 
440     // Invalid: property FRU is string less than 1.
441     {
442         json configFile = compareVpdFile;
443         configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = "";
444         EXPECT_JSON_INVALID(configFile, "Validation failed.",
445                             "u'' is too short");
446     }
447 
448     // Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
449     // "PartNumber"
450     {
451         json configFile = compareVpdFile;
452         configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
453             "Number";
454         EXPECT_JSON_INVALID(configFile, "Validation failed.",
455                             "u'Number' is not one of [u'CCIN', "
456                             "u'Manufacturer', u'Model', u'PartNumber']");
457     }
458 
459     // Invalid: property value wrong type.
460     {
461         json configFile = compareVpdFile;
462         configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1;
463         EXPECT_JSON_INVALID(configFile, "Validation failed.",
464                             "1 is not of type u'string'");
465     }
466 }
467 TEST(ValidateRegulatorsConfigTest, Configuration)
468 {
469     json configurationFile = validConfigFile;
470     configurationFile["chassis"][0]["devices"][0]["configuration"]["comments"]
471                      [0] = "Set rail to 1.25V using standard rule";
472     configurationFile["chassis"][0]["devices"][0]["configuration"]["volts"] =
473         1.25;
474     configurationFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
475         "set_voltage_rule";
476     // Valid: test configuration with property rule_id and with no actions.
477     {
478         json configFile = configurationFile;
479         EXPECT_JSON_VALID(configFile);
480     }
481     // Valid: test configuration with property actions and with no rule_id.
482     {
483         json configFile = configurationFile;
484         configFile["chassis"][0]["devices"][0]["configuration"].erase(
485             "rule_id");
486         configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
487                   ["compare_presence"]["fru"] =
488                       "/system/chassis/motherboard/cpu3";
489         configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
490                   ["compare_presence"]["value"] = true;
491         EXPECT_JSON_VALID(configFile);
492     }
493     // Valid: comments not specified (optional property).
494     {
495         json configFile = configurationFile;
496         configFile["chassis"][0]["devices"][0]["configuration"].erase(
497             "comments");
498         EXPECT_JSON_VALID(configFile);
499     }
500     // Valid: volts not specified (optional property).
501     {
502         json configFile = configurationFile;
503         configFile["chassis"][0]["devices"][0]["configuration"].erase("volts");
504         EXPECT_JSON_VALID(configFile);
505     }
506     // Valid: configuration is property of a rail (vs. a device).
507     {
508         json configFile = validConfigFile;
509         configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
510                   ["comments"][0] = "Set rail to 1.25V using standard rule";
511         configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
512                   ["volts"] = 1.25;
513         configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
514                   ["rule_id"] = "set_voltage_rule";
515         EXPECT_JSON_VALID(configFile);
516     }
517     // Invalid: comments property has wrong data type (not an array).
518     {
519         json configFile = configurationFile;
520         configFile["chassis"][0]["devices"][0]["configuration"]["comments"] = 1;
521         EXPECT_JSON_INVALID(configFile, "Validation failed.",
522                             "1 is not of type u'array'");
523     }
524     // Invalid: test configuration with both actions and rule_id properties.
525     {
526         json configFile = configurationFile;
527         configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
528                   ["compare_presence"]["fru"] =
529                       "/system/chassis/motherboard/cpu3";
530         configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
531                   ["compare_presence"]["value"] = true;
532         EXPECT_JSON_INVALID(
533             configFile, "Validation failed.",
534             "{u'volts': 1.25, u'comments': [u'Set rail to 1.25V using standard "
535             "rule'], u'actions': [{u'compare_presence': {u'value': True, "
536             "u'fru': u'/system/chassis/motherboard/cpu3'}}], u'rule_id': "
537             "u'set_voltage_rule'} is valid under each of {u'required': "
538             "[u'actions']}, {u'required': [u'rule_id']}");
539     }
540     // Invalid: test configuration with no rule_id and actions.
541     {
542         json configFile = configurationFile;
543         configFile["chassis"][0]["devices"][0]["configuration"].erase(
544             "rule_id");
545         EXPECT_JSON_INVALID(configFile, "Validation failed.",
546                             "u'rule_id' is a required property");
547     }
548     // Invalid: test configuration with property volts wrong type.
549     {
550         json configFile = configurationFile;
551         configFile["chassis"][0]["devices"][0]["configuration"]["volts"] = true;
552         EXPECT_JSON_INVALID(configFile, "Validation failed.",
553                             "True is not of type u'number'");
554     }
555     // Invalid: test configuration with property rule_id wrong type.
556     {
557         json configFile = configurationFile;
558         configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
559             true;
560         EXPECT_JSON_INVALID(configFile, "Validation failed.",
561                             "True is not of type u'string'");
562     }
563     // Invalid: test configuration with property actions wrong type.
564     {
565         json configFile = configurationFile;
566         configFile["chassis"][0]["devices"][0]["configuration"].erase(
567             "rule_id");
568         configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
569             true;
570         EXPECT_JSON_INVALID(configFile, "Validation failed.",
571                             "True is not of type u'array'");
572     }
573     // Invalid: test configuration with property comments empty array.
574     {
575         json configFile = configurationFile;
576         configFile["chassis"][0]["devices"][0]["configuration"]["comments"] =
577             json::array();
578         EXPECT_JSON_INVALID(configFile, "Validation failed.",
579                             "[] is too short");
580     }
581     // Invalid: test configuration with property rule_id wrong format.
582     {
583         json configFile = configurationFile;
584         configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
585             "id!";
586         EXPECT_JSON_INVALID(configFile, "Validation failed.",
587                             "u'id!' does not match u'^[A-Za-z0-9_]+$'");
588     }
589     // Invalid: test configuration with property actions empty array.
590     {
591         json configFile = configurationFile;
592         configFile["chassis"][0]["devices"][0]["configuration"].erase(
593             "rule_id");
594         configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
595             json::array();
596         EXPECT_JSON_INVALID(configFile, "Validation failed.",
597                             "[] is too short");
598     }
599 }
600 TEST(ValidateRegulatorsConfigTest, Device)
601 {
602 
603     // Valid: test devices.
604     {
605         json configFile = validConfigFile;
606         EXPECT_JSON_VALID(configFile);
607     }
608     // Valid: test devices with required properties.
609     {
610         json configFile = validConfigFile;
611         configFile["chassis"][0]["devices"][0].erase("comments");
612         configFile["chassis"][0]["devices"][0].erase("presence_detection");
613         configFile["chassis"][0]["devices"][0].erase("configuration");
614         configFile["chassis"][0]["devices"][0].erase("rails");
615         EXPECT_JSON_VALID(configFile);
616     }
617     // Invalid: test devices with no id.
618     {
619         json configFile = validConfigFile;
620         configFile["chassis"][0]["devices"][0].erase("id");
621         EXPECT_JSON_INVALID(configFile, "Validation failed.",
622                             "u'id' is a required property");
623     }
624     // Invalid: test devices with no is_regulator.
625     {
626         json configFile = validConfigFile;
627         configFile["chassis"][0]["devices"][0].erase("is_regulator");
628         EXPECT_JSON_INVALID(configFile, "Validation failed.",
629                             "u'is_regulator' is a required property");
630     }
631     // Invalid: test devices with no fru.
632     {
633         json configFile = validConfigFile;
634         configFile["chassis"][0]["devices"][0].erase("fru");
635         EXPECT_JSON_INVALID(configFile, "Validation failed.",
636                             "u'fru' is a required property");
637     }
638     // Invalid: test devices with no i2c_interface.
639     {
640         json configFile = validConfigFile;
641         configFile["chassis"][0]["devices"][0].erase("i2c_interface");
642         EXPECT_JSON_INVALID(configFile, "Validation failed.",
643                             "u'i2c_interface' is a required property");
644     }
645     // Invalid: test devices with property comments wrong type.
646     {
647         json configFile = validConfigFile;
648         configFile["chassis"][0]["devices"][0]["comments"] = true;
649         EXPECT_JSON_INVALID(configFile, "Validation failed.",
650                             "True is not of type u'array'");
651     }
652     // Invalid: test devices with property id wrong type.
653     {
654         json configFile = validConfigFile;
655         configFile["chassis"][0]["devices"][0]["id"] = true;
656         EXPECT_JSON_INVALID(configFile, "Validation failed.",
657                             "True is not of type u'string'");
658     }
659     // Invalid: test devices with property is_regulator wrong type.
660     {
661         json configFile = validConfigFile;
662         configFile["chassis"][0]["devices"][0]["is_regulator"] = 1;
663         EXPECT_JSON_INVALID(configFile, "Validation failed.",
664                             "1 is not of type u'boolean'");
665     }
666     // Invalid: test devices with property fru wrong type.
667     {
668         json configFile = validConfigFile;
669         configFile["chassis"][0]["devices"][0]["fru"] = true;
670         EXPECT_JSON_INVALID(configFile, "Validation failed.",
671                             "True is not of type u'string'");
672     }
673     // Invalid: test devices with property i2c_interface wrong type.
674     {
675         json configFile = validConfigFile;
676         configFile["chassis"][0]["devices"][0]["i2c_interface"] = true;
677         EXPECT_JSON_INVALID(configFile, "Validation failed.",
678                             "True is not of type u'object'");
679     }
680     // Invalid: test devices with property presence_detection wrong
681     // type.
682     {
683         json configFile = validConfigFile;
684         configFile["chassis"][0]["devices"][0]["presence_detection"] = true;
685         EXPECT_JSON_INVALID(configFile, "Validation failed.",
686                             "True is not of type u'object'");
687     }
688     // Invalid: test devices with property configuration wrong type.
689     {
690         json configFile = validConfigFile;
691         configFile["chassis"][0]["devices"][0]["configuration"] = true;
692         EXPECT_JSON_INVALID(configFile, "Validation failed.",
693                             "True is not of type u'object'");
694     }
695     // Invalid: test devices with property rails wrong type.
696     {
697         json configFile = validConfigFile;
698         configFile["chassis"][0]["devices"][0]["rails"] = true;
699         EXPECT_JSON_INVALID(configFile, "Validation failed.",
700                             "True is not of type u'array'");
701     }
702     // Invalid: test devices with property comments empty array.
703     {
704         json configFile = validConfigFile;
705         configFile["chassis"][0]["devices"][0]["comments"] = json::array();
706         EXPECT_JSON_INVALID(configFile, "Validation failed.",
707                             "[] is too short");
708     }
709     // Invalid: test devices with property fru length less than 1.
710     {
711         json configFile = validConfigFile;
712         configFile["chassis"][0]["devices"][0]["fru"] = "";
713         EXPECT_JSON_INVALID(configFile, "Validation failed.",
714                             "u'' is too short");
715     }
716     // Invalid: test devices with property id wrong format.
717     {
718         json configFile = validConfigFile;
719         configFile["chassis"][0]["devices"][0]["id"] = "id#";
720         EXPECT_JSON_INVALID(configFile, "Validation failed.",
721                             "u'id#' does not match u'^[A-Za-z0-9_]+$'");
722     }
723     // Invalid: test devices with property rails empty array.
724     {
725         json configFile = validConfigFile;
726         configFile["chassis"][0]["devices"][0]["rails"] = json::array();
727         EXPECT_JSON_INVALID(configFile, "Validation failed.",
728                             "[] is too short");
729     }
730 }
731 TEST(ValidateRegulatorsConfigTest, I2CCompareBit)
732 {
733     json i2cCompareBitFile = validConfigFile;
734     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
735         "0xA0";
736     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
737         3;
738     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
739     // Valid: test rule actions i2c_compare_bit.
740     {
741         json configFile = i2cCompareBitFile;
742         EXPECT_JSON_VALID(configFile);
743     }
744     // Invalid: test i2c_compare_bit with no register.
745     {
746         json configFile = i2cCompareBitFile;
747         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
748             "register");
749         EXPECT_JSON_INVALID(configFile, "Validation failed.",
750                             "u'register' is a required property");
751     }
752     // Invalid: test i2c_compare_bit with no position.
753     {
754         json configFile = i2cCompareBitFile;
755         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
756             "position");
757         EXPECT_JSON_INVALID(configFile, "Validation failed.",
758                             "u'position' is a required property");
759     }
760     // Invalid: test i2c_compare_bit with no value.
761     {
762         json configFile = i2cCompareBitFile;
763         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value");
764         EXPECT_JSON_INVALID(configFile, "Validation failed.",
765                             "u'value' is a required property");
766     }
767     // Invalid: test i2c_compare_bit with register wrong type.
768     {
769         json configFile = i2cCompareBitFile;
770         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1;
771         EXPECT_JSON_INVALID(configFile, "Validation failed.",
772                             "1 is not of type u'string'");
773     }
774     // Invalid: test i2c_compare_bit with register wrong format.
775     {
776         json configFile = i2cCompareBitFile;
777         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
778             "0xA00";
779         EXPECT_JSON_INVALID(configFile, "Validation failed.",
780                             "u'0xA00' does not match u'^0x[0-9A-Fa-f]{2}$'");
781     }
782     // Invalid: test i2c_compare_bit with position wrong type.
783     {
784         json configFile = i2cCompareBitFile;
785         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
786             3.1;
787         EXPECT_JSON_INVALID(configFile, "Validation failed.",
788                             "3.1 is not of type u'integer'");
789     }
790     // Invalid: test i2c_compare_bit with position greater than 7.
791     {
792         json configFile = i2cCompareBitFile;
793         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8;
794         EXPECT_JSON_INVALID(configFile, "Validation failed.",
795                             "8 is greater than the maximum of 7");
796     }
797     // Invalid: test i2c_compare_bit with position less than 0.
798     {
799         json configFile = i2cCompareBitFile;
800         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
801             -1;
802         EXPECT_JSON_INVALID(configFile, "Validation failed.",
803                             "-1 is less than the minimum of 0");
804     }
805     // Invalid: test i2c_compare_bit with value wrong type.
806     {
807         json configFile = i2cCompareBitFile;
808         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1";
809         EXPECT_JSON_INVALID(configFile, "Validation failed.",
810                             "u'1' is not of type u'integer'");
811     }
812     // Invalid: test i2c_compare_bit with value greater than 1.
813     {
814         json configFile = i2cCompareBitFile;
815         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2;
816         EXPECT_JSON_INVALID(configFile, "Validation failed.",
817                             "2 is greater than the maximum of 1");
818     }
819     // Invalid: test i2c_compare_bit with value less than 0.
820     {
821         json configFile = i2cCompareBitFile;
822         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1;
823         EXPECT_JSON_INVALID(configFile, "Validation failed.",
824                             "-1 is less than the minimum of 0");
825     }
826 }
827 TEST(ValidateRegulatorsConfigTest, I2CCompareByte)
828 {
829     json i2cCompareByteFile = validConfigFile;
830     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]
831                       ["register"] = "0x82";
832     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
833         "0x40";
834     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
835         "0x7F";
836     // Valid: test i2c_compare_byte with all properties.
837     {
838         json configFile = i2cCompareByteFile;
839         EXPECT_JSON_VALID(configFile);
840     }
841     // Valid: test i2c_compare_byte with all required properties.
842     {
843         json configFile = i2cCompareByteFile;
844         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask");
845         EXPECT_JSON_VALID(configFile);
846     }
847     // Invalid: test i2c_compare_byte with no register.
848     {
849         json configFile = i2cCompareByteFile;
850         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase(
851             "register");
852         EXPECT_JSON_INVALID(configFile, "Validation failed.",
853                             "u'register' is a required property");
854     }
855     // Invalid: test i2c_compare_byte with no value.
856     {
857         json configFile = i2cCompareByteFile;
858         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value");
859         EXPECT_JSON_INVALID(configFile, "Validation failed.",
860                             "u'value' is a required property");
861     }
862     // Invalid: test i2c_compare_byte with property register wrong type.
863     {
864         json configFile = i2cCompareByteFile;
865         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
866             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 value wrong type.
871     {
872         json configFile = i2cCompareByteFile;
873         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1;
874         EXPECT_JSON_INVALID(configFile, "Validation failed.",
875                             "1 is not of type u'string'");
876     }
877     // Invalid: test i2c_compare_byte with property mask wrong type.
878     {
879         json configFile = i2cCompareByteFile;
880         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1;
881         EXPECT_JSON_INVALID(configFile, "Validation failed.",
882                             "1 is not of type u'string'");
883     }
884     // Invalid: test i2c_compare_byte with property register more than 2 hex
885     // digits.
886     {
887         json configFile = i2cCompareByteFile;
888         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
889             "0x820";
890         EXPECT_JSON_INVALID(configFile, "Validation failed.",
891                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
892     }
893     // Invalid: test i2c_compare_byte with property value more than 2 hex
894     // digits.
895     {
896         json configFile = i2cCompareByteFile;
897         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
898             "0x820";
899         EXPECT_JSON_INVALID(configFile, "Validation failed.",
900                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
901     }
902     // Invalid: test i2c_compare_byte with property mask more than 2 hex digits.
903     {
904         json configFile = i2cCompareByteFile;
905         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
906             "0x820";
907         EXPECT_JSON_INVALID(configFile, "Validation failed.",
908                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
909     }
910     // Invalid: test i2c_compare_byte with property register less than 2 hex
911     // digits.
912     {
913         json configFile = i2cCompareByteFile;
914         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
915             "0x8";
916         EXPECT_JSON_INVALID(configFile, "Validation failed.",
917                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
918     }
919     // Invalid: test i2c_compare_byte with property value less than 2 hex
920     // digits.
921     {
922         json configFile = i2cCompareByteFile;
923         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
924             "0x8";
925         EXPECT_JSON_INVALID(configFile, "Validation failed.",
926                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
927     }
928     // Invalid: test i2c_compare_byte with property mask less than 2 hex digits.
929     {
930         json configFile = i2cCompareByteFile;
931         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
932             "0x8";
933         EXPECT_JSON_INVALID(configFile, "Validation failed.",
934                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
935     }
936     // Invalid: test i2c_compare_byte with property register no leading prefix.
937     {
938         json configFile = i2cCompareByteFile;
939         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
940             "82";
941         EXPECT_JSON_INVALID(configFile, "Validation failed.",
942                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
943     }
944     // Invalid: test i2c_compare_byte with property value no leading prefix.
945     {
946         json configFile = i2cCompareByteFile;
947         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
948             "82";
949         EXPECT_JSON_INVALID(configFile, "Validation failed.",
950                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
951     }
952     // Invalid: test i2c_compare_byte with property mask no leading prefix.
953     {
954         json configFile = i2cCompareByteFile;
955         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82";
956         EXPECT_JSON_INVALID(configFile, "Validation failed.",
957                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
958     }
959     // Invalid: test i2c_compare_byte with property register invalid hex digit.
960     {
961         json configFile = i2cCompareByteFile;
962         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
963             "0xG1";
964         EXPECT_JSON_INVALID(configFile, "Validation failed.",
965                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
966     }
967     // Invalid: test i2c_compare_byte with property value invalid hex digit.
968     {
969         json configFile = i2cCompareByteFile;
970         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
971             "0xG1";
972         EXPECT_JSON_INVALID(configFile, "Validation failed.",
973                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
974     }
975     // Invalid: test i2c_compare_byte with property mask invalid hex digit.
976     {
977         json configFile = i2cCompareByteFile;
978         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
979             "0xG1";
980         EXPECT_JSON_INVALID(configFile, "Validation failed.",
981                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
982     }
983 }
984 TEST(ValidateRegulatorsConfigTest, I2CCompareBytes)
985 {
986     json i2cCompareBytesFile = validConfigFile;
987     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
988                        ["register"] = "0x82";
989     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
990                        ["values"] = {"0x02", "0x73"};
991     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
992                        ["masks"] = {"0x7F", "0x7F"};
993     // Valid: test i2c_compare_bytes.
994     {
995         json configFile = i2cCompareBytesFile;
996         EXPECT_JSON_VALID(configFile);
997     }
998     // Valid: test i2c_compare_bytes with all required properties.
999     {
1000         json configFile = i2cCompareBytesFile;
1001         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1002             "masks");
1003         EXPECT_JSON_VALID(configFile);
1004     }
1005     // Invalid: test i2c_compare_bytes with no register.
1006     {
1007         json configFile = i2cCompareBytesFile;
1008         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1009             "register");
1010         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1011                             "u'register' is a required property");
1012     }
1013     // Invalid: test i2c_compare_bytes with no values.
1014     {
1015         json configFile = i2cCompareBytesFile;
1016         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1017             "values");
1018         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1019                             "u'values' is a required property");
1020     }
1021     // Invalid: test i2c_compare_bytes with property values as empty array.
1022     {
1023         json configFile = i2cCompareBytesFile;
1024         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] =
1025             json::array();
1026         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1027                             "[] is too short");
1028     }
1029     // Invalid: test i2c_compare_bytes with property masks as empty array.
1030     {
1031         json configFile = i2cCompareBytesFile;
1032         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] =
1033             json::array();
1034         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1035                             "[] is too short");
1036     }
1037     // Invalid: test i2c_compare_bytes with property register wrong type.
1038     {
1039         json configFile = i2cCompareBytesFile;
1040         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1041             1;
1042         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1043                             "1 is not of type u'string'");
1044     }
1045     // Invalid: test i2c_compare_bytes with property values wrong type.
1046     {
1047         json configFile = i2cCompareBytesFile;
1048         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1;
1049         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1050                             "1 is not of type u'array'");
1051     }
1052     // Invalid: test i2c_compare_bytes with property masks wrong type.
1053     {
1054         json configFile = i2cCompareBytesFile;
1055         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1;
1056         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1057                             "1 is not of type u'array'");
1058     }
1059     // Invalid: test i2c_compare_bytes with property register more than 2 hex
1060     // digits.
1061     {
1062         json configFile = i2cCompareBytesFile;
1063         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1064             "0x820";
1065         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1066                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1067     }
1068     // Invalid: test i2c_compare_bytes with property values more than 2 hex
1069     // digits.
1070     {
1071         json configFile = i2cCompareBytesFile;
1072         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1073             "0x820";
1074         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1075                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1076     }
1077     // Invalid: test i2c_compare_bytes with property masks more than 2 hex
1078     // digits.
1079     {
1080         json configFile = i2cCompareBytesFile;
1081         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1082             "0x820";
1083         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1084                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1085     }
1086     // Invalid: test i2c_compare_bytes with property register less than 2 hex
1087     // digits.
1088     {
1089         json configFile = i2cCompareBytesFile;
1090         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1091             "0x8";
1092         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1093                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1094     }
1095     // Invalid: test i2c_compare_bytes with property values less than 2 hex
1096     // digits.
1097     {
1098         json configFile = i2cCompareBytesFile;
1099         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1100             "0x8";
1101         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1102                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1103     }
1104     // Invalid: test i2c_compare_bytes with property masks less than 2 hex
1105     // digits.
1106     {
1107         json configFile = i2cCompareBytesFile;
1108         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1109             "0x8";
1110         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1111                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1112     }
1113     // Invalid: test i2c_compare_bytes with property register no leading prefix.
1114     {
1115         json configFile = i2cCompareBytesFile;
1116         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1117             "82";
1118         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1119                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1120     }
1121     // Invalid: test i2c_compare_bytes with property values no leading prefix.
1122     {
1123         json configFile = i2cCompareBytesFile;
1124         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1125             "82";
1126         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1127                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1128     }
1129     // Invalid: test i2c_compare_bytes with property masks no leading prefix.
1130     {
1131         json configFile = i2cCompareBytesFile;
1132         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1133             "82";
1134         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1135                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1136     }
1137     // Invalid: test i2c_compare_bytes with property register invalid hex digit.
1138     {
1139         json configFile = i2cCompareBytesFile;
1140         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1141             "0xG1";
1142         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1143                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1144     }
1145     // Invalid: test i2c_compare_bytes with property values invalid hex digit.
1146     {
1147         json configFile = i2cCompareBytesFile;
1148         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1149             "0xG1";
1150         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1151                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1152     }
1153     // Invalid: test i2c_compare_bytes with property masks invalid hex digit.
1154     {
1155         json configFile = i2cCompareBytesFile;
1156         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1157             "0xG1";
1158         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1159                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1160     }
1161 }
1162 TEST(ValidateRegulatorsConfigTest, I2CInterface)
1163 {
1164     // Valid: test i2c_interface.
1165     {
1166         json configFile = validConfigFile;
1167         EXPECT_JSON_VALID(configFile);
1168     }
1169     // Invalid: testi2c_interface with no bus.
1170     {
1171         json configFile = validConfigFile;
1172         configFile["chassis"][0]["devices"][0]["i2c_interface"].erase("bus");
1173         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1174                             "u'bus' is a required property");
1175     }
1176     // Invalid: test i2c_interface with no address.
1177     {
1178         json configFile = validConfigFile;
1179         configFile["chassis"][0]["devices"][0]["i2c_interface"].erase(
1180             "address");
1181         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1182                             "u'address' is a required property");
1183     }
1184     // Invalid: test i2c_interface with property bus wrong type.
1185     {
1186         json configFile = validConfigFile;
1187         configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = true;
1188         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1189                             "True is not of type u'integer'");
1190     }
1191     // Invalid: test i2c_interface with property address wrong
1192     // type.
1193     {
1194         json configFile = validConfigFile;
1195         configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1196             true;
1197         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1198                             "True is not of type u'string'");
1199     }
1200     // Invalid: test i2c_interface with property bus less than
1201     // 0.
1202     {
1203         json configFile = validConfigFile;
1204         configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = -1;
1205         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1206                             "-1 is less than the minimum of 0");
1207     }
1208     // Invalid: test i2c_interface with property address wrong
1209     // format.
1210     {
1211         json configFile = validConfigFile;
1212         configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1213             "0x700";
1214         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1215                             "u'0x700' does not match u'^0x[0-9A-Fa-f]{2}$'");
1216     }
1217 }
1218 TEST(ValidateRegulatorsConfigTest, I2CWriteBit)
1219 {
1220     json i2cWriteBitFile = validConfigFile;
1221     i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
1222         "0xA0";
1223     i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3;
1224     i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 1;
1225     // Valid: test rule actions i2c_write_bit.
1226     {
1227         json configFile = i2cWriteBitFile;
1228         EXPECT_JSON_VALID(configFile);
1229     }
1230     // Invalid: test i2c_write_bit with no register.
1231     {
1232         json configFile = i2cWriteBitFile;
1233         configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("register");
1234         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1235                             "u'register' is a required property");
1236     }
1237     // Invalid: test i2c_write_bit with no position.
1238     {
1239         json configFile = i2cWriteBitFile;
1240         configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("position");
1241         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1242                             "u'position' is a required property");
1243     }
1244     // Invalid: test i2c_write_bit with no value.
1245     {
1246         json configFile = i2cWriteBitFile;
1247         configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("value");
1248         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1249                             "u'value' is a required property");
1250     }
1251     // Invalid: test i2c_write_bit with register wrong type.
1252     {
1253         json configFile = i2cWriteBitFile;
1254         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] = 1;
1255         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1256                             "1 is not of type u'string'");
1257     }
1258     // Invalid: test i2c_write_bit with register wrong format.
1259     {
1260         json configFile = i2cWriteBitFile;
1261         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
1262             "0xA00";
1263         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1264                             "u'0xA00' does not match u'^0x[0-9A-Fa-f]{2}$'");
1265     }
1266     // Invalid: test i2c_write_bit with position wrong type.
1267     {
1268         json configFile = i2cWriteBitFile;
1269         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3.1;
1270         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1271                             "3.1 is not of type u'integer'");
1272     }
1273     // Invalid: test i2c_write_bit with position greater than 7.
1274     {
1275         json configFile = i2cWriteBitFile;
1276         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 8;
1277         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1278                             "8 is greater than the maximum of 7");
1279     }
1280     // Invalid: test i2c_write_bit with position less than 0.
1281     {
1282         json configFile = i2cWriteBitFile;
1283         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = -1;
1284         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1285                             "-1 is less than the minimum of 0");
1286     }
1287     // Invalid: test i2c_write_bit with value wrong type.
1288     {
1289         json configFile = i2cWriteBitFile;
1290         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = "1";
1291         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1292                             "u'1' is not of type u'integer'");
1293     }
1294     // Invalid: test i2c_write_bit with value greater than 1.
1295     {
1296         json configFile = i2cWriteBitFile;
1297         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 2;
1298         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1299                             "2 is greater than the maximum of 1");
1300     }
1301     // Invalid: test i2c_write_bit with value less than 0.
1302     {
1303         json configFile = i2cWriteBitFile;
1304         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = -1;
1305         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1306                             "-1 is less than the minimum of 0");
1307     }
1308 }
1309 TEST(ValidateRegulatorsConfigTest, I2CWriteByte)
1310 {
1311     json i2cWriteByteFile = validConfigFile;
1312     i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1313         "0x82";
1314     i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1315         "0x40";
1316     i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
1317         "0x7F";
1318     // Valid: test i2c_write_byte with all properties.
1319     {
1320         json configFile = i2cWriteByteFile;
1321         EXPECT_JSON_VALID(configFile);
1322     }
1323     // Valid: test i2c_write_byte with all required properties.
1324     {
1325         json configFile = i2cWriteByteFile;
1326         configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("mask");
1327         EXPECT_JSON_VALID(configFile);
1328     }
1329     // Invalid: test i2c_write_byte with no register.
1330     {
1331         json configFile = i2cWriteByteFile;
1332         configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase(
1333             "register");
1334         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1335                             "u'register' is a required property");
1336     }
1337     // Invalid: test i2c_write_byte with no value.
1338     {
1339         json configFile = i2cWriteByteFile;
1340         configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("value");
1341         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1342                             "u'value' is a required property");
1343     }
1344     // Invalid: test i2c_write_byte with property register wrong type.
1345     {
1346         json configFile = i2cWriteByteFile;
1347         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1;
1348         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1349                             "1 is not of type u'string'");
1350     }
1351     // Invalid: test i2c_write_byte with property value wrong type.
1352     {
1353         json configFile = i2cWriteByteFile;
1354         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = 1;
1355         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1356                             "1 is not of type u'string'");
1357     }
1358     // Invalid: test i2c_write_byte with property mask wrong type.
1359     {
1360         json configFile = i2cWriteByteFile;
1361         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = 1;
1362         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1363                             "1 is not of type u'string'");
1364     }
1365     // Invalid: test i2c_write_byte with property register more than 2 hex
1366     // digits.
1367     {
1368         json configFile = i2cWriteByteFile;
1369         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1370             "0x820";
1371         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1372                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1373     }
1374     // Invalid: test i2c_write_byte with property value more than 2 hex
1375     // digits.
1376     {
1377         json configFile = i2cWriteByteFile;
1378         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1379             "0x820";
1380         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1381                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1382     }
1383     // Invalid: test i2c_write_byte with property mask more than 2 hex digits.
1384     {
1385         json configFile = i2cWriteByteFile;
1386         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
1387             "0x820";
1388         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1389                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1390     }
1391     // Invalid: test i2c_write_byte with property register less than 2 hex
1392     // digits.
1393     {
1394         json configFile = i2cWriteByteFile;
1395         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1396             "0x8";
1397         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1398                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1399     }
1400     // Invalid: test i2c_write_byte with property value less than 2 hex
1401     // digits.
1402     {
1403         json configFile = i2cWriteByteFile;
1404         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "0x8";
1405         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1406                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1407     }
1408     // Invalid: test i2c_write_byte with property mask less than 2 hex digits.
1409     {
1410         json configFile = i2cWriteByteFile;
1411         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0x8";
1412         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1413                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1414     }
1415     // Invalid: test i2c_write_byte with property register no leading prefix.
1416     {
1417         json configFile = i2cWriteByteFile;
1418         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1419             "82";
1420         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1421                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1422     }
1423     // Invalid: test i2c_write_byte with property value no leading prefix.
1424     {
1425         json configFile = i2cWriteByteFile;
1426         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "82";
1427         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1428                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1429     }
1430     // Invalid: test i2c_write_byte with property mask no leading prefix.
1431     {
1432         json configFile = i2cWriteByteFile;
1433         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "82";
1434         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1435                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1436     }
1437     // Invalid: test i2c_write_byte with property register invalid hex digit.
1438     {
1439         json configFile = i2cWriteByteFile;
1440         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1441             "0xG1";
1442         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1443                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1444     }
1445     // Invalid: test i2c_write_byte with property value invalid hex digit.
1446     {
1447         json configFile = i2cWriteByteFile;
1448         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1449             "0xG1";
1450         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1451                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1452     }
1453     // Invalid: test i2c_write_byte with property mask invalid hex digit.
1454     {
1455         json configFile = i2cWriteByteFile;
1456         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0xG1";
1457         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1458                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1459     }
1460 }
1461 TEST(ValidateRegulatorsConfigTest, I2CWriteBytes)
1462 {
1463     json i2cWriteBytesFile = validConfigFile;
1464     i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1465         "0x82";
1466     i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
1467         "0x02", "0x73"};
1468     i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
1469         "0x7F", "0x7F"};
1470     // Valid: test i2c_write_bytes.
1471     {
1472         json configFile = i2cWriteBytesFile;
1473         EXPECT_JSON_VALID(configFile);
1474     }
1475     // Valid: test i2c_write_bytes with all required properties.
1476     {
1477         json configFile = i2cWriteBytesFile;
1478         configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("masks");
1479         EXPECT_JSON_VALID(configFile);
1480     }
1481     // Invalid: test i2c_write_bytes with no register.
1482     {
1483         json configFile = i2cWriteBytesFile;
1484         configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase(
1485             "register");
1486         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1487                             "u'register' is a required property");
1488     }
1489     // Invalid: test i2c_write_bytes with no values.
1490     {
1491         json configFile = i2cWriteBytesFile;
1492         configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("values");
1493         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1494                             "u'values' is a required property");
1495     }
1496     // Invalid: test i2c_write_bytes with property values as empty array.
1497     {
1498         json configFile = i2cWriteBytesFile;
1499         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] =
1500             json::array();
1501         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1502                             "[] is too short");
1503     }
1504     // Invalid: test i2c_write_bytes with property masks as empty array.
1505     {
1506         json configFile = i2cWriteBytesFile;
1507         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] =
1508             json::array();
1509         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1510                             "[] is too short");
1511     }
1512     // Invalid: test i2c_write_bytes with property register wrong type.
1513     {
1514         json configFile = i2cWriteBytesFile;
1515         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1;
1516         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1517                             "1 is not of type u'string'");
1518     }
1519     // Invalid: test i2c_write_bytes with property values wrong type.
1520     {
1521         json configFile = i2cWriteBytesFile;
1522         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = 1;
1523         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1524                             "1 is not of type u'array'");
1525     }
1526     // Invalid: test i2c_write_bytes with property masks wrong type.
1527     {
1528         json configFile = i2cWriteBytesFile;
1529         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = 1;
1530         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1531                             "1 is not of type u'array'");
1532     }
1533     // Invalid: test i2c_write_bytes with property register more than 2 hex
1534     // digits.
1535     {
1536         json configFile = i2cWriteBytesFile;
1537         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1538             "0x820";
1539         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1540                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1541     }
1542     // Invalid: test i2c_write_bytes with property values more than 2 hex
1543     // digits.
1544     {
1545         json configFile = i2cWriteBytesFile;
1546         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
1547             "0x820";
1548         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1549                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1550     }
1551     // Invalid: test i2c_write_bytes with property masks more than 2 hex
1552     // digits.
1553     {
1554         json configFile = i2cWriteBytesFile;
1555         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
1556             "0x820";
1557         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1558                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1559     }
1560     // Invalid: test i2c_write_bytes with property register less than 2 hex
1561     // digits.
1562     {
1563         json configFile = i2cWriteBytesFile;
1564         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1565             "0x8";
1566         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1567                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1568     }
1569     // Invalid: test i2c_write_bytes with property values less than 2 hex
1570     // digits.
1571     {
1572         json configFile = i2cWriteBytesFile;
1573         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
1574             "0x8";
1575         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1576                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1577     }
1578     // Invalid: test i2c_write_bytes with property masks less than 2 hex
1579     // digits.
1580     {
1581         json configFile = i2cWriteBytesFile;
1582         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
1583             "0x8";
1584         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1585                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1586     }
1587     // Invalid: test i2c_write_bytes with property register no leading prefix.
1588     {
1589         json configFile = i2cWriteBytesFile;
1590         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1591             "82";
1592         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1593                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1594     }
1595     // Invalid: test i2c_write_bytes with property values no leading prefix.
1596     {
1597         json configFile = i2cWriteBytesFile;
1598         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
1599             "82";
1600         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1601                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1602     }
1603     // Invalid: test i2c_write_bytes with property masks no leading prefix.
1604     {
1605         json configFile = i2cWriteBytesFile;
1606         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
1607             "82";
1608         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1609                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1610     }
1611     // Invalid: test i2c_write_bytes with property register invalid hex digit.
1612     {
1613         json configFile = i2cWriteBytesFile;
1614         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1615             "0xG1";
1616         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1617                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1618     }
1619     // Invalid: test i2c_write_bytes with property values invalid hex digit.
1620     {
1621         json configFile = i2cWriteBytesFile;
1622         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
1623             "0xG1";
1624         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1625                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1626     }
1627     // Invalid: test i2c_write_bytes with property masks invalid hex digit.
1628     {
1629         json configFile = i2cWriteBytesFile;
1630         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
1631             "0xG1";
1632         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1633                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1634     }
1635 }
1636 TEST(ValidateRegulatorsConfigTest, If)
1637 {
1638     json ifFile = validConfigFile;
1639     ifFile["rules"][2]["actions"][0]["if"]["condition"]["run_rule"] =
1640         "set_voltage_rule";
1641     ifFile["rules"][2]["actions"][0]["if"]["then"][0]["run_rule"] =
1642         "read_sensors_rule";
1643     ifFile["rules"][2]["actions"][0]["if"]["else"][0]["run_rule"] =
1644         "read_sensors_rule";
1645     ifFile["rules"][2]["id"] = "rule_if";
1646     // Valid: test if.
1647     {
1648         json configFile = ifFile;
1649         EXPECT_JSON_VALID(configFile);
1650     }
1651     // Valid: test if with required properties.
1652     {
1653         json configFile = ifFile;
1654         configFile["rules"][2]["actions"][0]["if"].erase("else");
1655         EXPECT_JSON_VALID(configFile);
1656     }
1657     // Invalid: test if with no property condition.
1658     {
1659         json configFile = ifFile;
1660         configFile["rules"][2]["actions"][0]["if"].erase("condition");
1661         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1662                             "u'condition' is a required property");
1663     }
1664     // Invalid: test if with no property then.
1665     {
1666         json configFile = ifFile;
1667         configFile["rules"][2]["actions"][0]["if"].erase("then");
1668         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1669                             "u'then' is a required property");
1670     }
1671     // Invalid: test if with property then empty array.
1672     {
1673         json configFile = ifFile;
1674         configFile["rules"][2]["actions"][0]["if"]["then"] = json::array();
1675         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1676                             "[] is too short");
1677     }
1678     // Invalid: test if with property else empty array.
1679     {
1680         json configFile = ifFile;
1681         configFile["rules"][2]["actions"][0]["if"]["else"] = json::array();
1682         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1683                             "[] is too short");
1684     }
1685     // Invalid: test if with property condition wrong type.
1686     {
1687         json configFile = ifFile;
1688         configFile["rules"][2]["actions"][0]["if"]["condition"] = 1;
1689         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1690                             "1 is not of type u'object'");
1691     }
1692     // Invalid: test if with property then wrong type.
1693     {
1694         json configFile = ifFile;
1695         configFile["rules"][2]["actions"][0]["if"]["then"] = 1;
1696         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1697                             "1 is not of type u'array'");
1698     }
1699     // Invalid: test if with property else wrong type.
1700     {
1701         json configFile = ifFile;
1702         configFile["rules"][2]["actions"][0]["if"]["else"] = 1;
1703         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1704                             "1 is not of type u'array'");
1705     }
1706 }
1707 TEST(ValidateRegulatorsConfigTest, Not)
1708 {
1709     json notFile = validConfigFile;
1710     notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] =
1711         "0xA0";
1712     notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] =
1713         "0xFF";
1714     // Valid: test not.
1715     {
1716         json configFile = notFile;
1717         EXPECT_JSON_VALID(configFile);
1718     }
1719     // Invalid: test not with wrong type.
1720     {
1721         json configFile = notFile;
1722         configFile["rules"][0]["actions"][1]["not"] = 1;
1723         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1724                             "1 is not of type u'object'");
1725     }
1726 }
1727 TEST(ValidateRegulatorsConfigTest, Or)
1728 {
1729     json orFile = validConfigFile;
1730     orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] =
1731         "0xA0";
1732     orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] =
1733         "0x00";
1734     orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] =
1735         "0xA1";
1736     orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] =
1737         "0x00";
1738     // Valid: test or.
1739     {
1740         json configFile = orFile;
1741         EXPECT_JSON_VALID(configFile);
1742     }
1743     // Invalid: test or with empty array.
1744     {
1745         json configFile = orFile;
1746         configFile["rules"][0]["actions"][1]["or"] = json::array();
1747         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1748                             "[] is too short");
1749     }
1750     // Invalid: test or with wrong type.
1751     {
1752         json configFile = orFile;
1753         configFile["rules"][0]["actions"][1]["or"] = 1;
1754         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1755                             "1 is not of type u'array'");
1756     }
1757 }
1758 TEST(ValidateRegulatorsConfigTest, PmbusReadSensor)
1759 {
1760     json pmbusReadSensorFile = validConfigFile;
1761     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1762         "vout";
1763     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1764                        ["command"] = "0x8B";
1765     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1766                        ["format"] = "linear_16";
1767     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1768                        ["exponent"] = -8;
1769     // Valid: test pmbus_read_sensor.
1770     {
1771         json configFile = pmbusReadSensorFile;
1772         EXPECT_JSON_VALID(configFile);
1773     }
1774     // Valid: test pmbus_read_sensor with required properties.
1775     {
1776         json configFile = pmbusReadSensorFile;
1777         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1778             "exponent");
1779         EXPECT_JSON_VALID(configFile);
1780     }
1781     // Invalid: test pmbus_read_sensor with no type.
1782     {
1783         json configFile = pmbusReadSensorFile;
1784         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type");
1785         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1786                             "u'type' is a required property");
1787     }
1788     // Invalid: test pmbus_read_sensor with no command.
1789     {
1790         json configFile = pmbusReadSensorFile;
1791         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1792             "command");
1793         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1794                             "u'command' is a required property");
1795     }
1796     // Invalid: test pmbus_read_sensor with no format.
1797     {
1798         json configFile = pmbusReadSensorFile;
1799         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1800             "format");
1801         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1802                             "u'format' is a required property");
1803     }
1804     // Invalid: test pmbus_read_sensor with property type wrong type.
1805     {
1806         json configFile = pmbusReadSensorFile;
1807         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1808             true;
1809         EXPECT_JSON_INVALID(
1810             configFile, "Validation failed.",
1811             "True is not one of [u'iout', u'iout_peak', u'iout_valley', "
1812             "u'pout', u'temperature', u'temperature_peak', u'vout', "
1813             "u'vout_peak', u'vout_valley']");
1814     }
1815     // Invalid: test pmbus_read_sensor with property command wrong type.
1816     {
1817         json configFile = pmbusReadSensorFile;
1818         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1819             true;
1820         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1821                             "True is not of type u'string'");
1822     }
1823     // Invalid: test pmbus_read_sensor with property format wrong type.
1824     {
1825         json configFile = pmbusReadSensorFile;
1826         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1827             true;
1828         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1829                             "True is not one of [u'linear_11', u'linear_16']");
1830     }
1831     // Invalid: test pmbus_read_sensor with property exponent wrong type.
1832     {
1833         json configFile = pmbusReadSensorFile;
1834         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] =
1835             true;
1836         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1837                             "True is not of type u'integer'");
1838     }
1839     // Invalid: test pmbus_read_sensor with property type wrong format.
1840     {
1841         json configFile = pmbusReadSensorFile;
1842         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1843             "foo";
1844         EXPECT_JSON_INVALID(
1845             configFile, "Validation failed.",
1846             "u'foo' is not one of [u'iout', u'iout_peak', u'iout_valley', "
1847             "u'pout', u'temperature', u'temperature_peak', u'vout', "
1848             "u'vout_peak', u'vout_valley']");
1849     }
1850     // Invalid: test pmbus_read_sensor with property command wrong format.
1851     {
1852         json configFile = pmbusReadSensorFile;
1853         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1854             "0x8B0";
1855         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1856                             "u'0x8B0' does not match u'^0x[0-9a-fA-F]{2}$'");
1857     }
1858     // Invalid: test pmbus_read_sensor with property format wrong format.
1859     {
1860         json configFile = pmbusReadSensorFile;
1861         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1862             "foo";
1863         EXPECT_JSON_INVALID(
1864             configFile, "Validation failed.",
1865             "u'foo' is not one of [u'linear_11', u'linear_16']");
1866     }
1867 }
1868 TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand)
1869 {
1870     json pmbusWriteVoutCommandFile = validConfigFile;
1871     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1872                              ["pmbus_write_vout_command"]["volts"] = 1.03;
1873     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1874                              ["pmbus_write_vout_command"]["format"] = "linear";
1875     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1876                              ["pmbus_write_vout_command"]["exponent"] = -8;
1877     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1878                              ["pmbus_write_vout_command"]["is_verified"] = true;
1879     // Valid: test pmbus_write_vout_command.
1880     {
1881         json configFile = pmbusWriteVoutCommandFile;
1882         EXPECT_JSON_VALID(configFile);
1883     }
1884     // Valid: test pmbus_write_vout_command with required properties.
1885     {
1886         json configFile = pmbusWriteVoutCommandFile;
1887         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1888             "volts");
1889         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1890             "exponent");
1891         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1892             "is_verified");
1893         EXPECT_JSON_VALID(configFile);
1894     }
1895     // Invalid: test pmbus_write_vout_command with no format.
1896     {
1897         json configFile = pmbusWriteVoutCommandFile;
1898         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1899             "format");
1900         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1901                             "u'format' is a required property");
1902     }
1903     // Invalid: test pmbus_write_vout_command with property volts wrong type.
1904     {
1905         json configFile = pmbusWriteVoutCommandFile;
1906         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1907                   ["volts"] = true;
1908         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1909                             "True is not of type u'number'");
1910     }
1911     // Invalid: test pmbus_write_vout_command with property format wrong type.
1912     {
1913         json configFile = pmbusWriteVoutCommandFile;
1914         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1915                   ["format"] = true;
1916         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1917                             "True is not one of [u'linear']");
1918     }
1919     // Invalid: test pmbus_write_vout_command with property exponent wrong type.
1920     {
1921         json configFile = pmbusWriteVoutCommandFile;
1922         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1923                   ["exponent"] = 1.3;
1924         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1925                             "1.3 is not of type u'integer'");
1926     }
1927     // Invalid: test pmbus_write_vout_command with property is_verified wrong
1928     // type.
1929     {
1930         json configFile = pmbusWriteVoutCommandFile;
1931         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1932                   ["is_verified"] = 1;
1933         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1934                             "1 is not of type u'boolean'");
1935     }
1936     // Invalid: test pmbus_write_vout_command with property format wrong format.
1937     {
1938         json configFile = pmbusWriteVoutCommandFile;
1939         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1940                   ["format"] = "foo";
1941         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1942                             "u'foo' is not one of [u'linear']");
1943     }
1944 }
1945 TEST(ValidateRegulatorsConfigTest, PresenceDetection)
1946 {
1947     json presenceDetectionFile = validConfigFile;
1948     presenceDetectionFile
1949         ["chassis"][0]["devices"][0]["presence_detection"]["comments"][0] =
1950             "Regulator is only present on the FooBar backplane";
1951     presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
1952                          ["rule_id"] = "set_voltage_rule";
1953     // Valid: test presence_detection with only property rule_id.
1954     {
1955         json configFile = presenceDetectionFile;
1956         EXPECT_JSON_VALID(configFile);
1957     }
1958     // Valid: test presence_detection with only property actions.
1959     {
1960         json configFile = presenceDetectionFile;
1961         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1962             "rule_id");
1963         configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1964                   [0]["compare_presence"]["fru"] =
1965                       "/system/chassis/motherboard/cpu3";
1966         configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1967                   [0]["compare_presence"]["value"] = true;
1968         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1969             "comments");
1970         EXPECT_JSON_VALID(configFile);
1971     }
1972     // Invalid: test presence_detection with both property rule_id and actions.
1973     {
1974         json configFile = presenceDetectionFile;
1975         configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1976                   [0]["compare_presence"]["fru"] =
1977                       "/system/chassis/motherboard/cpu3";
1978         configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
1979                   [0]["compare_presence"]["value"] = true;
1980         EXPECT_JSON_INVALID(
1981             configFile, "Validation failed.",
1982             "{u'comments': [u'Regulator is only present on the FooBar "
1983             "backplane'], u'actions': [{u'compare_presence': {u'value': True, "
1984             "u'fru': u'/system/chassis/motherboard/cpu3'}}], u'rule_id': "
1985             "u'set_voltage_rule'} is valid under each of "
1986             "{u'required': [u'actions']}, {u'required': [u'rule_id']}");
1987     }
1988     // Invalid: test presence_detection with no rule_id and actions.
1989     {
1990         json configFile = presenceDetectionFile;
1991         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
1992             "rule_id");
1993         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1994                             "u'rule_id' is a required property");
1995     }
1996     // Invalid: test presence_detection with property comments wrong type.
1997     {
1998         json configFile = presenceDetectionFile;
1999         configFile["chassis"][0]["devices"][0]["presence_detection"]
2000                   ["comments"] = true;
2001         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2002                             "True is not of type u'array'");
2003     }
2004     // Invalid: test presence_detection with property rule_id wrong type.
2005     {
2006         json configFile = presenceDetectionFile;
2007         configFile["chassis"][0]["devices"][0]["presence_detection"]
2008                   ["rule_id"] = true;
2009         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2010                             "True is not of type u'string'");
2011     }
2012     // Invalid: test presence_detection with property actions wrong type.
2013     {
2014         json configFile = presenceDetectionFile;
2015         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2016             "rule_id");
2017         configFile["chassis"][0]["devices"][0]["presence_detection"]
2018                   ["actions"] = true;
2019         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2020                             "True is not of type u'array'");
2021     }
2022     // Invalid: test presence_detection with property rule_id wrong format.
2023     {
2024         json configFile = presenceDetectionFile;
2025         configFile["chassis"][0]["devices"][0]["presence_detection"]
2026                   ["rule_id"] = "id@";
2027         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2028                             "u'id@' does not match u'^[A-Za-z0-9_]+$'");
2029     }
2030     // Invalid: test presence_detection with property comments empty array.
2031     {
2032         json configFile = presenceDetectionFile;
2033         configFile["chassis"][0]["devices"][0]["presence_detection"]
2034                   ["comments"] = json::array();
2035         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2036                             "[] is too short");
2037     }
2038     // Invalid: test presence_detection with property actions empty array.
2039     {
2040         json configFile = presenceDetectionFile;
2041         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2042             "rule_id");
2043         configFile["chassis"][0]["devices"][0]["presence_detection"]
2044                   ["actions"] = json::array();
2045         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2046                             "[] is too short");
2047     }
2048 }
2049 TEST(ValidateRegulatorsConfigTest, Rail)
2050 {
2051     // Valid: test rail.
2052     {
2053         json configFile = validConfigFile;
2054         EXPECT_JSON_VALID(configFile);
2055     }
2056     // Valid: test rail with required properties.
2057     {
2058         json configFile = validConfigFile;
2059         configFile["chassis"][0]["devices"][0]["rails"][0].erase("comments");
2060         configFile["chassis"][0]["devices"][0]["rails"][0].erase(
2061             "configuration");
2062         configFile["chassis"][0]["devices"][0]["rails"][0].erase(
2063             "sensor_monitoring");
2064         EXPECT_JSON_VALID(configFile);
2065     }
2066     // Invalid: test rail with no id.
2067     {
2068         json configFile = validConfigFile;
2069         configFile["chassis"][0]["devices"][0]["rails"][0].erase("id");
2070         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2071                             "u'id' is a required property");
2072     }
2073     // Invalid: test rail with comments wrong type.
2074     {
2075         json configFile = validConfigFile;
2076         configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = true;
2077         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2078                             "True is not of type u'array'");
2079     }
2080     // Invalid: test rail with id wrong type.
2081     {
2082         json configFile = validConfigFile;
2083         configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = true;
2084         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2085                             "True is not of type u'string'");
2086     }
2087     // Invalid: test rail with configuration wrong type.
2088     {
2089         json configFile = validConfigFile;
2090         configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] =
2091             true;
2092         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2093                             "True is not of type u'object'");
2094     }
2095     // Invalid: test rail with sensor_monitoring wrong type.
2096     {
2097         json configFile = validConfigFile;
2098         configFile["chassis"][0]["devices"][0]["rails"][0]
2099                   ["sensor_monitoring"] = true;
2100         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2101                             "True is not of type u'object'");
2102     }
2103     // Invalid: test rail with comments empty array.
2104     {
2105         json configFile = validConfigFile;
2106         configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] =
2107             json::array();
2108         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2109                             "[] is too short");
2110     }
2111     // Invalid: test rail with id wrong format.
2112     {
2113         json configFile = validConfigFile;
2114         configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = "id~";
2115         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2116                             "u'id~' does not match u'^[A-Za-z0-9_]+$'");
2117     }
2118 }
2119 TEST(ValidateRegulatorsConfigTest, Rule)
2120 {
2121     // valid test comments property, id property,
2122     // action property specified.
2123     {
2124         json configFile = validConfigFile;
2125         EXPECT_JSON_VALID(configFile);
2126     }
2127 
2128     // valid test rule with no comments
2129     {
2130         json configFile = validConfigFile;
2131         configFile["rules"][0].erase("comments");
2132         EXPECT_JSON_VALID(configFile);
2133     }
2134 
2135     // invalid test comments property has invalid value type
2136     {
2137         json configFile = validConfigFile;
2138         configFile["rules"][0]["comments"] = {1};
2139         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2140                             "1 is not of type u'string'");
2141     }
2142 
2143     // invalid test rule with no ID
2144     {
2145         json configFile = validConfigFile;
2146         configFile["rules"][0].erase("id");
2147         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2148                             "u'id' is a required property");
2149     }
2150 
2151     // invalid test id property has invalid value type (not string)
2152     {
2153         json configFile = validConfigFile;
2154         configFile["rules"][0]["id"] = true;
2155         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2156                             "True is not of type u'string'");
2157     }
2158 
2159     // invalid test id property has invalid value
2160     {
2161         json configFile = validConfigFile;
2162         configFile["rules"][0]["id"] = "foo%";
2163         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2164                             "u'foo%' does not match u'^[A-Za-z0-9_]+$'");
2165     }
2166 
2167     // invalid test rule with no actions property
2168     {
2169         json configFile = validConfigFile;
2170         configFile["rules"][0].erase("actions");
2171         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2172                             "u'actions' is a required property");
2173     }
2174 
2175     // valid test rule with multiple actions
2176     {
2177         json configFile = validConfigFile;
2178         configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
2179         EXPECT_JSON_VALID(configFile);
2180     }
2181 
2182     // invalid test actions property has invalid value type (not an array)
2183     {
2184         json configFile = validConfigFile;
2185         configFile["rules"][0]["actions"] = 1;
2186         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2187                             "1 is not of type u'array'");
2188     }
2189 
2190     // invalid test actions property has invalid value of action
2191     {
2192         json configFile = validConfigFile;
2193         configFile["rules"][0]["actions"][0] = "foo";
2194         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2195                             "u'foo' is not of type u'object'");
2196     }
2197 
2198     // invalid test actions property has empty array
2199     {
2200         json configFile = validConfigFile;
2201         configFile["rules"][0]["actions"] = json::array();
2202         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2203                             "[] is too short");
2204     }
2205 }
2206 TEST(ValidateRegulatorsConfigTest, RunRule)
2207 {
2208     json runRuleFile = validConfigFile;
2209     runRuleFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
2210     // Valid: test run_rule.
2211     {
2212         json configFile = runRuleFile;
2213         EXPECT_JSON_VALID(configFile);
2214     }
2215     // Invalid: test run_rule wrong type.
2216     {
2217         json configFile = runRuleFile;
2218         configFile["rules"][0]["actions"][1]["run_rule"] = true;
2219         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2220                             "True is not of type u'string'");
2221     }
2222     // Invalid: test run_rule wrong format.
2223     {
2224         json configFile = runRuleFile;
2225         configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%";
2226         EXPECT_JSON_INVALID(
2227             configFile, "Validation failed.",
2228             "u'set_voltage_rule%' does not match u'^[A-Za-z0-9_]+$'");
2229     }
2230 }
2231 TEST(ValidateRegulatorsConfigTest, SensorMonitoring)
2232 {
2233     // Valid: test rails sensor_monitoring with only property rule id.
2234     {
2235         json configFile = validConfigFile;
2236         EXPECT_JSON_VALID(configFile);
2237     }
2238     // Valid: test rails sensor_monitoring with only property actions.
2239     {
2240         json configFile = validConfigFile;
2241         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2242             .erase("rule_id");
2243         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2244                   ["actions"][0]["compare_presence"]["fru"] =
2245                       "/system/chassis/motherboard/cpu3";
2246         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2247                   ["actions"][0]["compare_presence"]["value"] = true;
2248         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2249                   ["comments"][0] = "comments";
2250         EXPECT_JSON_VALID(configFile);
2251     }
2252     // Invalid: test rails sensor_monitoring with both property rule_id and
2253     // actions.
2254     {
2255         json configFile = validConfigFile;
2256         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2257                   ["actions"][0]["compare_presence"]["fru"] =
2258                       "/system/chassis/motherboard/cpu3";
2259         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2260                   ["actions"][0]["compare_presence"]["value"] = true;
2261         EXPECT_JSON_INVALID(
2262             configFile, "Validation failed.",
2263             "{u'rule_id': u'read_sensors_rule', u'actions': "
2264             "[{u'compare_presence': {u'value': True, u'fru': "
2265             "u'/system/chassis/motherboard/cpu3'}}]} is valid under each of "
2266             "{u'required': [u'actions']}, {u'required': [u'rule_id']}");
2267     }
2268     // Invalid: test rails sensor_monitoring with no rule_id and actions.
2269     {
2270         json configFile = validConfigFile;
2271         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2272             .erase("rule_id");
2273         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2274                             "u'rule_id' is a required property");
2275     }
2276     // Invalid: test rails sensor_monitoring with property comments wrong type.
2277     {
2278         json configFile = validConfigFile;
2279         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2280                   ["comments"] = true;
2281         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2282                             "True is not of type u'array'");
2283     }
2284     // Invalid: test rails sensor_monitoring with property rule_id wrong type.
2285     {
2286         json configFile = validConfigFile;
2287         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2288                   ["rule_id"] = true;
2289         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2290                             "True is not of type u'string'");
2291     }
2292     // Invalid: test rails sensor_monitoring with property actions wrong type.
2293     {
2294         json configFile = validConfigFile;
2295         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2296             .erase("rule_id");
2297         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2298                   ["actions"] = true;
2299         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2300                             "True is not of type u'array'");
2301     }
2302     // Invalid: test rails sensor_monitoring with property rule_id wrong format.
2303     {
2304         json configFile = validConfigFile;
2305         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2306                   ["rule_id"] = "id@";
2307         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2308                             "u'id@' does not match u'^[A-Za-z0-9_]+$'");
2309     }
2310     // Invalid: test rails sensor_monitoring with property comments empty array.
2311     {
2312         json configFile = validConfigFile;
2313         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2314                   ["comments"] = json::array();
2315         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2316                             "[] is too short");
2317     }
2318     // Invalid: test rails sensor_monitoring with property actions empty array.
2319     {
2320         json configFile = validConfigFile;
2321         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2322             .erase("rule_id");
2323         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2324                   ["actions"] = json::array();
2325         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2326                             "[] is too short");
2327     }
2328 }
2329 TEST(ValidateRegulatorsConfigTest, SetDevice)
2330 {
2331     json setDeviceFile = validConfigFile;
2332     setDeviceFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator";
2333     // Valid: test set_device.
2334     {
2335         json configFile = setDeviceFile;
2336         EXPECT_JSON_VALID(configFile);
2337     }
2338     // Invalid: test set_device wrong type.
2339     {
2340         json configFile = setDeviceFile;
2341         configFile["rules"][0]["actions"][1]["set_device"] = true;
2342         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2343                             "True is not of type u'string'");
2344     }
2345     // Invalid: test set_device wrong format.
2346     {
2347         json configFile = setDeviceFile;
2348         configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%";
2349         EXPECT_JSON_INVALID(
2350             configFile, "Validation failed.",
2351             "u'io_expander2%' does not match u'^[A-Za-z0-9_]+$'");
2352     }
2353 }
2354 TEST(ValidateRegulatorsConfigTest, DuplicateRuleID)
2355 {
2356     // Invalid: test duplicate ID in rule.
2357     {
2358         json configFile = validConfigFile;
2359         configFile["rules"][2]["id"] = "set_voltage_rule";
2360         configFile["rules"][2]["actions"][0]["pmbus_write_vout_command"]
2361                   ["format"] = "linear";
2362         EXPECT_JSON_INVALID(configFile, "Error: Duplicate rule ID.", "");
2363     }
2364 }
2365 TEST(ValidateRegulatorsConfigTest, DuplicateChassisNumber)
2366 {
2367     // Invalid: test duplicate number in chassis.
2368     {
2369         json configFile = validConfigFile;
2370         configFile["chassis"][1]["number"] = 1;
2371         EXPECT_JSON_INVALID(configFile, "Error: Duplicate chassis number.", "");
2372     }
2373 }
2374 TEST(ValidateRegulatorsConfigTest, DuplicateDeviceID)
2375 {
2376     // Invalid: test duplicate ID in device.
2377     {
2378         json configFile = validConfigFile;
2379         configFile["chassis"][0]["devices"][1]["id"] = "vdd_regulator";
2380         configFile["chassis"][0]["devices"][1]["is_regulator"] = true;
2381         configFile["chassis"][0]["devices"][1]["fru"] =
2382             "/system/chassis/motherboard/regulator1";
2383         configFile["chassis"][0]["devices"][1]["i2c_interface"]["bus"] = 2;
2384         configFile["chassis"][0]["devices"][1]["i2c_interface"]["address"] =
2385             "0x71";
2386         EXPECT_JSON_INVALID(configFile, "Error: Duplicate device ID.", "");
2387     }
2388 }
2389 TEST(ValidateRegulatorsConfigTest, DuplicateRailID)
2390 {
2391     // Invalid: test duplicate ID in rail.
2392     {
2393         json configFile = validConfigFile;
2394         configFile["chassis"][0]["devices"][0]["rails"][1]["id"] = "vdd";
2395         EXPECT_JSON_INVALID(configFile, "Error: Duplicate rail ID.", "");
2396     }
2397 }
2398 TEST(ValidateRegulatorsConfigTest, InfiniteLoops)
2399 {
2400     // Invalid: test run_rule with infinite loop (rules run each other).
2401     {
2402         json configFile = validConfigFile;
2403         configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2";
2404         configFile["rules"][2]["id"] = "set_voltage_rule1";
2405         configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule1";
2406         configFile["rules"][3]["id"] = "set_voltage_rule2";
2407         EXPECT_JSON_INVALID(configFile,
2408                             "Infinite loop caused by run_rule actions.", "");
2409     }
2410     // Invalid: test run_rule with infinite loop (rule runs itself).
2411     {
2412         json configFile = validConfigFile;
2413         configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule1";
2414         configFile["rules"][2]["id"] = "set_voltage_rule1";
2415         EXPECT_JSON_INVALID(configFile,
2416                             "Infinite loop caused by run_rule actions.", "");
2417     }
2418     // Invalid: test run_rule with infinite loop (indirect loop).
2419     {
2420         json configFile = validConfigFile;
2421         configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2";
2422         configFile["rules"][2]["id"] = "set_voltage_rule1";
2423         configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule3";
2424         configFile["rules"][3]["id"] = "set_voltage_rule2";
2425         configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule1";
2426         configFile["rules"][4]["id"] = "set_voltage_rule3";
2427         EXPECT_JSON_INVALID(configFile,
2428                             "Infinite loop caused by run_rule actions.", "");
2429     }
2430 }
2431