xref: /openbmc/phosphor-power/phosphor-regulators/test/validate-regulators-config_tests.cpp (revision a2ba2dfbca85725a217ae865e0fa683214548069)
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 
57       "chassis": [
58         {
59           "comments": [ "Chassis number 1 containing CPUs and memory" ],
60           "number": 1,
61           "devices": [
62             {
63               "comments": [ "IR35221 regulator producing the Vdd rail" ],
64               "id": "vdd_regulator",
65               "is_regulator": true,
66               "fru": "/system/chassis/motherboard/regulator1",
67               "i2c_interface": {
68                 "bus": 1,
69                 "address": "0x70"
70               },
71               "rails": [
72                 {
73                   "comments": [ "Vdd rail" ],
74                   "id": "vdd",
75                   "configuration": {
76                     "volts": 1.03,
77                     "rule_id": "set_voltage_rule"
78                   },
79                   "sensor_monitoring": {
80                     "rule_id": "read_sensors_rule"
81                   }
82                 }
83               ]
84             }
85           ]
86         }
87       ]
88     }
89 )"_json;
90 
91 std::string createTmpFile()
92 {
93     // create temporary file using mkstemp under /tmp/. random name for XXXXXX
94     char fileName[] = "/tmp/temp-XXXXXX";
95     int fd = mkstemp(fileName);
96     if (fd == -1)
97     {
98         perror("Can't create temporary file");
99     }
100     close(fd);
101     return fileName;
102 }
103 
104 std::string getValidationToolCommand(const std::string& configFileName)
105 {
106     std::string command = "python ../tools/validate-regulators-config.py -s \
107                            ../schema/config_schema.json -c ";
108     command += configFileName;
109     return command;
110 }
111 
112 int runToolForOutput(const std::string& configFileName, std::string& output,
113                      bool isReadingStderr = false)
114 {
115     // run the validation tool with the temporary file and return the output
116     // of the validation tool.
117     std::string command = getValidationToolCommand(configFileName);
118     // reading the stderr while isReadingStderr is true.
119     if (isReadingStderr == true)
120     {
121         command += " 2>&1 >/dev/null";
122     }
123     // get the jsonschema print from validation tool.
124     char buffer[256];
125     std::string result = "";
126     // to get the stdout from the validation tool.
127     FILE* pipe = popen(command.c_str(), "r");
128     if (!pipe)
129     {
130         throw std::runtime_error("popen() failed!");
131     }
132     while (!std::feof(pipe))
133     {
134         if (fgets(buffer, sizeof buffer, pipe) != NULL)
135         {
136             result += buffer;
137         }
138     }
139     int returnValue = pclose(pipe);
140     // Check if pclose() failed
141     if (returnValue == -1)
142     {
143         // unable to close pipe.  Print error and exit function.
144         throw std::runtime_error("pclose() failed!");
145     }
146     std::string firstLine = result.substr(0, result.find('\n'));
147     output = firstLine;
148     // Get command exit status from return value
149     int exitStatus = WEXITSTATUS(returnValue);
150     return exitStatus;
151 }
152 
153 void expectFileValid(const std::string& configFileName)
154 {
155     std::string errorMessage = "";
156     std::string outputMessage = "";
157     EXPECT_EQ(runToolForOutput(configFileName, errorMessage, true), 0);
158     EXPECT_EQ(runToolForOutput(configFileName, outputMessage), 0);
159     EXPECT_EQ(errorMessage, "");
160     EXPECT_EQ(outputMessage, "");
161 }
162 
163 void expectFileInvalid(const std::string& configFileName,
164                        const std::string& expectedErrorMessage,
165                        const std::string& expectedOutputMessage)
166 {
167     std::string errorMessage = "";
168     std::string outputMessage = "";
169     EXPECT_EQ(runToolForOutput(configFileName, errorMessage, true), 1);
170     EXPECT_EQ(runToolForOutput(configFileName, outputMessage), 1);
171     EXPECT_EQ(errorMessage, expectedErrorMessage);
172     EXPECT_EQ(outputMessage, expectedOutputMessage);
173 }
174 
175 void expectJsonValid(const json configFileJson)
176 {
177     std::string fileName;
178     fileName = createTmpFile();
179     std::string jsonData = configFileJson.dump();
180     std::ofstream out(fileName);
181     out << jsonData;
182     out.close();
183 
184     EXPECT_FILE_VALID(fileName);
185     unlink(fileName.c_str());
186 }
187 
188 void expectJsonInvalid(const json configFileJson,
189                        const std::string& expectedErrorMessage,
190                        const std::string& expectedOutputMessage)
191 {
192     std::string fileName;
193     fileName = createTmpFile();
194     std::string jsonData = configFileJson.dump();
195     std::ofstream out(fileName);
196     out << jsonData;
197     out.close();
198 
199     EXPECT_FILE_INVALID(fileName, expectedErrorMessage, expectedOutputMessage);
200     unlink(fileName.c_str());
201 }
202 
203 TEST(ValidateRegulatorsConfigTest, Rule)
204 {
205     // valid test comments property, id property,
206     // action property specified.
207     {
208         json configFile = validConfigFile;
209         EXPECT_JSON_VALID(configFile);
210     }
211 
212     // valid test rule with no comments
213     {
214         json configFile = validConfigFile;
215         configFile["rules"][0].erase("comments");
216         EXPECT_JSON_VALID(configFile);
217     }
218 
219     // invalid test comments property has invalid value type
220     {
221         json configFile = validConfigFile;
222         configFile["rules"][0]["comments"] = {1};
223         EXPECT_JSON_INVALID(configFile, "Validation failed.",
224                             "1 is not of type u'string'");
225     }
226 
227     // invalid test rule with no ID
228     {
229         json configFile = validConfigFile;
230         configFile["rules"][0].erase("id");
231         EXPECT_JSON_INVALID(configFile, "Validation failed.",
232                             "u'id' is a required property");
233     }
234 
235     // invalid test id property has invalid value type (not string)
236     {
237         json configFile = validConfigFile;
238         configFile["rules"][0]["id"] = true;
239         EXPECT_JSON_INVALID(configFile, "Validation failed.",
240                             "True is not of type u'string'");
241     }
242 
243     // invalid test id property has invalid value
244     {
245         json configFile = validConfigFile;
246         configFile["rules"][0]["id"] = "foo%";
247         EXPECT_JSON_INVALID(configFile, "Validation failed.",
248                             "u'foo%' does not match u'^[A-Za-z0-9_]+$'");
249     }
250 
251     // invalid test rule with no actions property
252     {
253         json configFile = validConfigFile;
254         configFile["rules"][0].erase("actions");
255         EXPECT_JSON_INVALID(configFile, "Validation failed.",
256                             "u'actions' is a required property");
257     }
258 
259     // valid test rule with multiple actions
260     {
261         json configFile = validConfigFile;
262         configFile["rules"][0]["actions"][1]["run_rule"] =
263             "set_page0_voltage_rule";
264         EXPECT_JSON_VALID(configFile);
265     }
266 
267     // invalid test actions property has invalid value type (not an array)
268     {
269         json configFile = validConfigFile;
270         configFile["rules"][0]["actions"] = 1;
271         EXPECT_JSON_INVALID(configFile, "Validation failed.",
272                             "1 is not of type u'array'");
273     }
274 
275     // invalid test actions property has invalid value of action
276     {
277         json configFile = validConfigFile;
278         configFile["rules"][0]["actions"][0] = "foo";
279         EXPECT_JSON_INVALID(configFile, "Validation failed.",
280                             "u'foo' is not of type u'object'");
281     }
282 
283     // invalid test actions property has empty array
284     {
285         json configFile = validConfigFile;
286         configFile["rules"][0]["actions"] = json::array();
287         EXPECT_JSON_INVALID(configFile, "Validation failed.",
288                             "[] is too short");
289     }
290 }
291 TEST(ValidateRegulatorsConfigTest, And)
292 {
293     // Valid.
294     {
295         json configFile = validConfigFile;
296         json andAction =
297             R"(
298                 {
299                  "and": [
300                     { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
301                     { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
302                   ]
303                 }
304             )"_json;
305         configFile["rules"][0]["actions"].push_back(andAction);
306         EXPECT_JSON_VALID(configFile);
307     }
308 
309     // Invalid: actions property value is an empty array.
310     {
311         json configFile = validConfigFile;
312         json andAction =
313             R"(
314                 {
315                  "and": []
316                 }
317             )"_json;
318         configFile["rules"][0]["actions"].push_back(andAction);
319         EXPECT_JSON_INVALID(configFile, "Validation failed.",
320                             "[] is too short");
321     }
322 
323     // Invalid: actions property has incorrect value data type.
324     {
325         json configFile = validConfigFile;
326         json andAction =
327             R"(
328                 {
329                  "and": true
330                 }
331             )"_json;
332         configFile["rules"][0]["actions"].push_back(andAction);
333         EXPECT_JSON_INVALID(configFile, "Validation failed.",
334                             "True is not of type u'array'");
335     }
336 
337     // Invalid: actions property value contains wrong element type
338     {
339         json configFile = validConfigFile;
340         json andAction =
341             R"(
342                 {
343                  "and": ["foo"]
344                 }
345             )"_json;
346         configFile["rules"][0]["actions"].push_back(andAction);
347         EXPECT_JSON_INVALID(configFile, "Validation failed.",
348                             "u'foo' is not of type u'object'");
349     }
350 }
351 TEST(ValidateRegulatorsConfigTest, Chassis)
352 {
353     // Valid: test chassis.
354     {
355         json configFile = validConfigFile;
356         EXPECT_JSON_VALID(configFile);
357     }
358     // Valid: test chassis with required properties.
359     {
360         json configFile = validConfigFile;
361         configFile["chassis"][0].erase("comments");
362         configFile["chassis"][0].erase("devices");
363         EXPECT_JSON_VALID(configFile);
364     }
365     // Invalid: test chassis with no number.
366     {
367         json configFile = validConfigFile;
368         configFile["chassis"][0].erase("number");
369         EXPECT_JSON_INVALID(configFile, "Validation failed.",
370                             "u'number' is a required property");
371     }
372     // Invalid: test chassis with property comments wrong type.
373     {
374         json configFile = validConfigFile;
375         configFile["chassis"][0]["comments"] = true;
376         EXPECT_JSON_INVALID(configFile, "Validation failed.",
377                             "True is not of type u'array'");
378     }
379     // Invalid: test chassis with property number wrong type.
380     {
381         json configFile = validConfigFile;
382         configFile["chassis"][0]["number"] = 1.3;
383         EXPECT_JSON_INVALID(configFile, "Validation failed.",
384                             "1.3 is not of type u'integer'");
385     }
386     // Invalid: test chassis with property devices wrong type.
387     {
388         json configFile = validConfigFile;
389         configFile["chassis"][0]["devices"] = true;
390         EXPECT_JSON_INVALID(configFile, "Validation failed.",
391                             "True is not of type u'array'");
392     }
393     // Invalid: test chassis with property comments empty array.
394     {
395         json configFile = validConfigFile;
396         configFile["chassis"][0]["comments"] = json::array();
397         EXPECT_JSON_INVALID(configFile, "Validation failed.",
398                             "[] is too short");
399     }
400     // Invalid: test chassis with property devices empty array.
401     {
402         json configFile = validConfigFile;
403         configFile["chassis"][0]["devices"] = json::array();
404         EXPECT_JSON_INVALID(configFile, "Validation failed.",
405                             "[] is too short");
406     }
407     // Invalid: test chassis with property number less than 1.
408     {
409         json configFile = validConfigFile;
410         configFile["chassis"][0]["number"] = 0;
411         EXPECT_JSON_INVALID(configFile, "Validation failed.",
412                             "0 is less than the minimum of 1");
413     }
414 }
415 TEST(ValidateRegulatorsConfigTest, ComparePresence)
416 {
417     json comparePresenceFile = validConfigFile;
418     comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
419         "/system/chassis/motherboard/regulator2";
420     comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
421         true;
422     // Valid.
423     {
424         json configFile = comparePresenceFile;
425         EXPECT_JSON_VALID(configFile);
426     }
427 
428     // Invalid: no FRU property.
429     {
430         json configFile = comparePresenceFile;
431         configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru");
432         EXPECT_JSON_INVALID(configFile, "Validation failed.",
433                             "u'fru' is a required property");
434     }
435 
436     // Invalid: FRU property length is string less than 1.
437     {
438         json configFile = comparePresenceFile;
439         configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = "";
440         EXPECT_JSON_INVALID(configFile, "Validation failed.",
441                             "u'' is too short");
442     }
443 
444     // Invalid: no value property.
445     {
446         json configFile = comparePresenceFile;
447         configFile["rules"][0]["actions"][1]["compare_presence"].erase("value");
448         EXPECT_JSON_INVALID(configFile, "Validation failed.",
449                             "u'value' is a required property");
450     }
451 
452     // Invalid: value property type is not boolean.
453     {
454         json configFile = comparePresenceFile;
455         configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1";
456         EXPECT_JSON_INVALID(configFile, "Validation failed.",
457                             "u'1' is not of type u'boolean'");
458     }
459 
460     // Invalid: FRU property type is not string.
461     {
462         json configFile = comparePresenceFile;
463         configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1;
464         EXPECT_JSON_INVALID(configFile, "Validation failed.",
465                             "1 is not of type u'string'");
466     }
467 }
468 TEST(ValidateRegulatorsConfigTest, CompareVpd)
469 {
470     json compareVpdFile = validConfigFile;
471     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
472         "/system/chassis/motherboard/regulator2";
473     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
474     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
475 
476     // Valid.
477     {
478         json configFile = compareVpdFile;
479         EXPECT_JSON_VALID(configFile);
480     }
481 
482     // Invalid: no FRU property.
483     {
484         json configFile = compareVpdFile;
485         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru");
486         EXPECT_JSON_INVALID(configFile, "Validation failed.",
487                             "u'fru' is a required property");
488     }
489 
490     // Invalid: no keyword property.
491     {
492         json configFile = compareVpdFile;
493         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword");
494         EXPECT_JSON_INVALID(configFile, "Validation failed.",
495                             "u'keyword' is a required property");
496     }
497 
498     // Invalid: no value property.
499     {
500         json configFile = compareVpdFile;
501         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
502         EXPECT_JSON_INVALID(configFile, "Validation failed.",
503                             "u'value' is a required property");
504     }
505 
506     // Invalid: property FRU wrong type.
507     {
508         json configFile = compareVpdFile;
509         configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1;
510         EXPECT_JSON_INVALID(configFile, "Validation failed.",
511                             "1 is not of type u'string'");
512     }
513 
514     // Invalid: property FRU is string less than 1.
515     {
516         json configFile = compareVpdFile;
517         configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = "";
518         EXPECT_JSON_INVALID(configFile, "Validation failed.",
519                             "u'' is too short");
520     }
521 
522     // Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
523     // "PartNumber"
524     {
525         json configFile = compareVpdFile;
526         configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
527             "Number";
528         EXPECT_JSON_INVALID(configFile, "Validation failed.",
529                             "u'Number' is not one of [u'CCIN', "
530                             "u'Manufacturer', u'Model', u'PartNumber']");
531     }
532 
533     // Invalid: property value wrong type.
534     {
535         json configFile = compareVpdFile;
536         configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1;
537         EXPECT_JSON_INVALID(configFile, "Validation failed.",
538                             "1 is not of type u'string'");
539     }
540 }
541 TEST(ValidateRegulatorsConfigTest, Device)
542 {
543 
544     // Valid: test devices.
545     {
546         json configFile = validConfigFile;
547         EXPECT_JSON_VALID(configFile);
548     }
549     // Valid: test devices with required properties.
550     {
551         json configFile = validConfigFile;
552         configFile["chassis"][0]["devices"][0].erase("comments");
553         configFile["chassis"][0]["devices"][0].erase("presence_detection");
554         configFile["chassis"][0]["devices"][0].erase("configuration");
555         configFile["chassis"][0]["devices"][0].erase("rails");
556         EXPECT_JSON_VALID(configFile);
557     }
558     // Invalid: test devices with no id.
559     {
560         json configFile = validConfigFile;
561         configFile["chassis"][0]["devices"][0].erase("id");
562         EXPECT_JSON_INVALID(configFile, "Validation failed.",
563                             "u'id' is a required property");
564     }
565     // Invalid: test devices with no is_regulator.
566     {
567         json configFile = validConfigFile;
568         configFile["chassis"][0]["devices"][0].erase("is_regulator");
569         EXPECT_JSON_INVALID(configFile, "Validation failed.",
570                             "u'is_regulator' is a required property");
571     }
572     // Invalid: test devices with no fru.
573     {
574         json configFile = validConfigFile;
575         configFile["chassis"][0]["devices"][0].erase("fru");
576         EXPECT_JSON_INVALID(configFile, "Validation failed.",
577                             "u'fru' is a required property");
578     }
579     // Invalid: test devices with no i2c_interface.
580     {
581         json configFile = validConfigFile;
582         configFile["chassis"][0]["devices"][0].erase("i2c_interface");
583         EXPECT_JSON_INVALID(configFile, "Validation failed.",
584                             "u'i2c_interface' is a required property");
585     }
586     // Invalid: test devices with property comments wrong type.
587     {
588         json configFile = validConfigFile;
589         configFile["chassis"][0]["devices"][0]["comments"] = true;
590         EXPECT_JSON_INVALID(configFile, "Validation failed.",
591                             "True is not of type u'array'");
592     }
593     // Invalid: test devices with property id wrong type.
594     {
595         json configFile = validConfigFile;
596         configFile["chassis"][0]["devices"][0]["id"] = true;
597         EXPECT_JSON_INVALID(configFile, "Validation failed.",
598                             "True is not of type u'string'");
599     }
600     // Invalid: test devices with property is_regulator wrong type.
601     {
602         json configFile = validConfigFile;
603         configFile["chassis"][0]["devices"][0]["is_regulator"] = 1;
604         EXPECT_JSON_INVALID(configFile, "Validation failed.",
605                             "1 is not of type u'boolean'");
606     }
607     // Invalid: test devices with property fru wrong type.
608     {
609         json configFile = validConfigFile;
610         configFile["chassis"][0]["devices"][0]["fru"] = true;
611         EXPECT_JSON_INVALID(configFile, "Validation failed.",
612                             "True is not of type u'string'");
613     }
614     // Invalid: test devices with property i2c_interface wrong type.
615     {
616         json configFile = validConfigFile;
617         configFile["chassis"][0]["devices"][0]["i2c_interface"] = true;
618         EXPECT_JSON_INVALID(configFile, "Validation failed.",
619                             "True is not of type u'object'");
620     }
621     // Invalid: test devices with property presence_detection wrong
622     // type.
623     {
624         json configFile = validConfigFile;
625         configFile["chassis"][0]["devices"][0]["presence_detection"] = true;
626         EXPECT_JSON_INVALID(configFile, "Validation failed.",
627                             "True is not of type u'object'");
628     }
629     // Invalid: test devices with property configuration wrong type.
630     {
631         json configFile = validConfigFile;
632         configFile["chassis"][0]["devices"][0]["configuration"] = true;
633         EXPECT_JSON_INVALID(configFile, "Validation failed.",
634                             "True is not of type u'object'");
635     }
636     // Invalid: test devices with property rails wrong type.
637     {
638         json configFile = validConfigFile;
639         configFile["chassis"][0]["devices"][0]["rails"] = true;
640         EXPECT_JSON_INVALID(configFile, "Validation failed.",
641                             "True is not of type u'array'");
642     }
643     // Invalid: test devices with property comments empty array.
644     {
645         json configFile = validConfigFile;
646         configFile["chassis"][0]["devices"][0]["comments"] = json::array();
647         EXPECT_JSON_INVALID(configFile, "Validation failed.",
648                             "[] is too short");
649     }
650     // Invalid: test devices with property fru length less than 1.
651     {
652         json configFile = validConfigFile;
653         configFile["chassis"][0]["devices"][0]["fru"] = "";
654         EXPECT_JSON_INVALID(configFile, "Validation failed.",
655                             "u'' is too short");
656     }
657     // Invalid: test devices with property id wrong format.
658     {
659         json configFile = validConfigFile;
660         configFile["chassis"][0]["devices"][0]["id"] = "id#";
661         EXPECT_JSON_INVALID(configFile, "Validation failed.",
662                             "u'id#' does not match u'^[A-Za-z0-9_]+$'");
663     }
664     // Invalid: test devices with property rails empty array.
665     {
666         json configFile = validConfigFile;
667         configFile["chassis"][0]["devices"][0]["rails"] = json::array();
668         EXPECT_JSON_INVALID(configFile, "Validation failed.",
669                             "[] is too short");
670     }
671 }
672 TEST(ValidateRegulatorsConfigTest, I2CCompareBit)
673 {
674     json i2cCompareBitFile = validConfigFile;
675     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
676         "0xA0";
677     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
678         3;
679     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
680     // Valid: test rule actions i2c_compare_bit.
681     {
682         json configFile = i2cCompareBitFile;
683         EXPECT_JSON_VALID(configFile);
684     }
685     // Invalid: test i2c_compare_bit with no register.
686     {
687         json configFile = i2cCompareBitFile;
688         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
689             "register");
690         EXPECT_JSON_INVALID(configFile, "Validation failed.",
691                             "u'register' is a required property");
692     }
693     // Invalid: test i2c_compare_bit with no position.
694     {
695         json configFile = i2cCompareBitFile;
696         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
697             "position");
698         EXPECT_JSON_INVALID(configFile, "Validation failed.",
699                             "u'position' is a required property");
700     }
701     // Invalid: test i2c_compare_bit with no value.
702     {
703         json configFile = i2cCompareBitFile;
704         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value");
705         EXPECT_JSON_INVALID(configFile, "Validation failed.",
706                             "u'value' is a required property");
707     }
708     // Invalid: test i2c_compare_bit with register wrong type.
709     {
710         json configFile = i2cCompareBitFile;
711         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1;
712         EXPECT_JSON_INVALID(configFile, "Validation failed.",
713                             "1 is not of type u'string'");
714     }
715     // Invalid: test i2c_compare_bit with register wrong format.
716     {
717         json configFile = i2cCompareBitFile;
718         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
719             "0xA00";
720         EXPECT_JSON_INVALID(configFile, "Validation failed.",
721                             "u'0xA00' does not match u'^0x[0-9A-Fa-f]{2}$'");
722     }
723     // Invalid: test i2c_compare_bit with position wrong type.
724     {
725         json configFile = i2cCompareBitFile;
726         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
727             3.1;
728         EXPECT_JSON_INVALID(configFile, "Validation failed.",
729                             "3.1 is not of type u'integer'");
730     }
731     // Invalid: test i2c_compare_bit with position greater than 7.
732     {
733         json configFile = i2cCompareBitFile;
734         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8;
735         EXPECT_JSON_INVALID(configFile, "Validation failed.",
736                             "8 is greater than the maximum of 7");
737     }
738     // Invalid: test i2c_compare_bit with position less than 0.
739     {
740         json configFile = i2cCompareBitFile;
741         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
742             -1;
743         EXPECT_JSON_INVALID(configFile, "Validation failed.",
744                             "-1 is less than the minimum of 0");
745     }
746     // Invalid: test i2c_compare_bit with value wrong type.
747     {
748         json configFile = i2cCompareBitFile;
749         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1";
750         EXPECT_JSON_INVALID(configFile, "Validation failed.",
751                             "u'1' is not of type u'integer'");
752     }
753     // Invalid: test i2c_compare_bit with value greater than 1.
754     {
755         json configFile = i2cCompareBitFile;
756         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2;
757         EXPECT_JSON_INVALID(configFile, "Validation failed.",
758                             "2 is greater than the maximum of 1");
759     }
760     // Invalid: test i2c_compare_bit with value less than 0.
761     {
762         json configFile = i2cCompareBitFile;
763         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1;
764         EXPECT_JSON_INVALID(configFile, "Validation failed.",
765                             "-1 is less than the minimum of 0");
766     }
767 }
768 TEST(ValidateRegulatorsConfigTest, I2CCompareByte)
769 {
770     json i2cCompareByteFile = validConfigFile;
771     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]
772                       ["register"] = "0x82";
773     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
774         "0x40";
775     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
776         "0x7F";
777     // Valid: test i2c_compare_byte with all properties.
778     {
779         json configFile = i2cCompareByteFile;
780         EXPECT_JSON_VALID(configFile);
781     }
782     // Valid: test i2c_compare_byte with all required properties.
783     {
784         json configFile = i2cCompareByteFile;
785         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask");
786         EXPECT_JSON_VALID(configFile);
787     }
788     // Invalid: test i2c_compare_byte with no register.
789     {
790         json configFile = i2cCompareByteFile;
791         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase(
792             "register");
793         EXPECT_JSON_INVALID(configFile, "Validation failed.",
794                             "u'register' is a required property");
795     }
796     // Invalid: test i2c_compare_byte with no value.
797     {
798         json configFile = i2cCompareByteFile;
799         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value");
800         EXPECT_JSON_INVALID(configFile, "Validation failed.",
801                             "u'value' is a required property");
802     }
803     // Invalid: test i2c_compare_byte with property register wrong type.
804     {
805         json configFile = i2cCompareByteFile;
806         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
807             1;
808         EXPECT_JSON_INVALID(configFile, "Validation failed.",
809                             "1 is not of type u'string'");
810     }
811     // Invalid: test i2c_compare_byte with property value wrong type.
812     {
813         json configFile = i2cCompareByteFile;
814         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1;
815         EXPECT_JSON_INVALID(configFile, "Validation failed.",
816                             "1 is not of type u'string'");
817     }
818     // Invalid: test i2c_compare_byte with property mask wrong type.
819     {
820         json configFile = i2cCompareByteFile;
821         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1;
822         EXPECT_JSON_INVALID(configFile, "Validation failed.",
823                             "1 is not of type u'string'");
824     }
825     // Invalid: test i2c_compare_byte with property register more than 2 hex
826     // digits.
827     {
828         json configFile = i2cCompareByteFile;
829         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
830             "0x820";
831         EXPECT_JSON_INVALID(configFile, "Validation failed.",
832                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
833     }
834     // Invalid: test i2c_compare_byte with property value more than 2 hex
835     // digits.
836     {
837         json configFile = i2cCompareByteFile;
838         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
839             "0x820";
840         EXPECT_JSON_INVALID(configFile, "Validation failed.",
841                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
842     }
843     // Invalid: test i2c_compare_byte with property mask more than 2 hex digits.
844     {
845         json configFile = i2cCompareByteFile;
846         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
847             "0x820";
848         EXPECT_JSON_INVALID(configFile, "Validation failed.",
849                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
850     }
851     // Invalid: test i2c_compare_byte with property register less than 2 hex
852     // digits.
853     {
854         json configFile = i2cCompareByteFile;
855         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
856             "0x8";
857         EXPECT_JSON_INVALID(configFile, "Validation failed.",
858                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
859     }
860     // Invalid: test i2c_compare_byte with property value less than 2 hex
861     // digits.
862     {
863         json configFile = i2cCompareByteFile;
864         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
865             "0x8";
866         EXPECT_JSON_INVALID(configFile, "Validation failed.",
867                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
868     }
869     // Invalid: test i2c_compare_byte with property mask less than 2 hex digits.
870     {
871         json configFile = i2cCompareByteFile;
872         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
873             "0x8";
874         EXPECT_JSON_INVALID(configFile, "Validation failed.",
875                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
876     }
877     // Invalid: test i2c_compare_byte with property register no leading prefix.
878     {
879         json configFile = i2cCompareByteFile;
880         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
881             "82";
882         EXPECT_JSON_INVALID(configFile, "Validation failed.",
883                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
884     }
885     // Invalid: test i2c_compare_byte with property value no leading prefix.
886     {
887         json configFile = i2cCompareByteFile;
888         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
889             "82";
890         EXPECT_JSON_INVALID(configFile, "Validation failed.",
891                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
892     }
893     // Invalid: test i2c_compare_byte with property mask no leading prefix.
894     {
895         json configFile = i2cCompareByteFile;
896         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82";
897         EXPECT_JSON_INVALID(configFile, "Validation failed.",
898                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
899     }
900     // Invalid: test i2c_compare_byte with property register invalid hex digit.
901     {
902         json configFile = i2cCompareByteFile;
903         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
904             "0xG1";
905         EXPECT_JSON_INVALID(configFile, "Validation failed.",
906                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
907     }
908     // Invalid: test i2c_compare_byte with property value invalid hex digit.
909     {
910         json configFile = i2cCompareByteFile;
911         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
912             "0xG1";
913         EXPECT_JSON_INVALID(configFile, "Validation failed.",
914                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
915     }
916     // Invalid: test i2c_compare_byte with property mask invalid hex digit.
917     {
918         json configFile = i2cCompareByteFile;
919         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
920             "0xG1";
921         EXPECT_JSON_INVALID(configFile, "Validation failed.",
922                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
923     }
924 }
925 TEST(ValidateRegulatorsConfigTest, I2CCompareBytes)
926 {
927     json i2cCompareBytesFile = validConfigFile;
928     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
929                        ["register"] = "0x82";
930     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
931                        ["values"] = {"0x02", "0x73"};
932     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
933                        ["masks"] = {"0x7F", "0x7F"};
934     // Valid: test i2c_compare_bytes.
935     {
936         json configFile = i2cCompareBytesFile;
937         EXPECT_JSON_VALID(configFile);
938     }
939     // Valid: test i2c_compare_bytes with all required properties.
940     {
941         json configFile = i2cCompareBytesFile;
942         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
943             "masks");
944         EXPECT_JSON_VALID(configFile);
945     }
946     // Invalid: test i2c_compare_bytes with no register.
947     {
948         json configFile = i2cCompareBytesFile;
949         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
950             "register");
951         EXPECT_JSON_INVALID(configFile, "Validation failed.",
952                             "u'register' is a required property");
953     }
954     // Invalid: test i2c_compare_bytes with no values.
955     {
956         json configFile = i2cCompareBytesFile;
957         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
958             "values");
959         EXPECT_JSON_INVALID(configFile, "Validation failed.",
960                             "u'values' is a required property");
961     }
962     // Invalid: test i2c_compare_bytes with property values as empty array.
963     {
964         json configFile = i2cCompareBytesFile;
965         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] =
966             json::array();
967         EXPECT_JSON_INVALID(configFile, "Validation failed.",
968                             "[] is too short");
969     }
970     // Invalid: test i2c_compare_bytes with property masks as empty array.
971     {
972         json configFile = i2cCompareBytesFile;
973         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] =
974             json::array();
975         EXPECT_JSON_INVALID(configFile, "Validation failed.",
976                             "[] is too short");
977     }
978     // Invalid: test i2c_compare_bytes with property register wrong type.
979     {
980         json configFile = i2cCompareBytesFile;
981         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
982             1;
983         EXPECT_JSON_INVALID(configFile, "Validation failed.",
984                             "1 is not of type u'string'");
985     }
986     // Invalid: test i2c_compare_bytes with property values wrong type.
987     {
988         json configFile = i2cCompareBytesFile;
989         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1;
990         EXPECT_JSON_INVALID(configFile, "Validation failed.",
991                             "1 is not of type u'array'");
992     }
993     // Invalid: test i2c_compare_bytes with property masks wrong type.
994     {
995         json configFile = i2cCompareBytesFile;
996         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1;
997         EXPECT_JSON_INVALID(configFile, "Validation failed.",
998                             "1 is not of type u'array'");
999     }
1000     // Invalid: test i2c_compare_bytes with property register more than 2 hex
1001     // digits.
1002     {
1003         json configFile = i2cCompareBytesFile;
1004         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1005             "0x820";
1006         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1007                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1008     }
1009     // Invalid: test i2c_compare_bytes with property values more than 2 hex
1010     // digits.
1011     {
1012         json configFile = i2cCompareBytesFile;
1013         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1014             "0x820";
1015         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1016                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1017     }
1018     // Invalid: test i2c_compare_bytes with property masks more than 2 hex
1019     // digits.
1020     {
1021         json configFile = i2cCompareBytesFile;
1022         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1023             "0x820";
1024         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1025                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
1026     }
1027     // Invalid: test i2c_compare_bytes with property register less than 2 hex
1028     // digits.
1029     {
1030         json configFile = i2cCompareBytesFile;
1031         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1032             "0x8";
1033         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1034                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1035     }
1036     // Invalid: test i2c_compare_bytes with property values less than 2 hex
1037     // digits.
1038     {
1039         json configFile = i2cCompareBytesFile;
1040         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1041             "0x8";
1042         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1043                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1044     }
1045     // Invalid: test i2c_compare_bytes with property masks less than 2 hex
1046     // digits.
1047     {
1048         json configFile = i2cCompareBytesFile;
1049         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1050             "0x8";
1051         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1052                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
1053     }
1054     // Invalid: test i2c_compare_bytes with property register no leading prefix.
1055     {
1056         json configFile = i2cCompareBytesFile;
1057         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1058             "82";
1059         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1060                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1061     }
1062     // Invalid: test i2c_compare_bytes with property values no leading prefix.
1063     {
1064         json configFile = i2cCompareBytesFile;
1065         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1066             "82";
1067         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1068                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1069     }
1070     // Invalid: test i2c_compare_bytes with property masks no leading prefix.
1071     {
1072         json configFile = i2cCompareBytesFile;
1073         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1074             "82";
1075         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1076                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
1077     }
1078     // Invalid: test i2c_compare_bytes with property register invalid hex digit.
1079     {
1080         json configFile = i2cCompareBytesFile;
1081         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1082             "0xG1";
1083         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1084                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1085     }
1086     // Invalid: test i2c_compare_bytes with property values invalid hex digit.
1087     {
1088         json configFile = i2cCompareBytesFile;
1089         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1090             "0xG1";
1091         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1092                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1093     }
1094     // Invalid: test i2c_compare_bytes with property masks invalid hex digit.
1095     {
1096         json configFile = i2cCompareBytesFile;
1097         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1098             "0xG1";
1099         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1100                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
1101     }
1102 }
1103 TEST(ValidateRegulatorsConfigTest, If)
1104 {
1105     json ifFile = validConfigFile;
1106     ifFile["rules"][0]["actions"][1]["if"]["condition"]["run_rule"] =
1107         "is_downlevel_regulator";
1108     ifFile["rules"][0]["actions"][1]["if"]["then"][0]["run_rule"] =
1109         "configure_downlevel_regulator";
1110     ifFile["rules"][0]["actions"][1]["if"]["else"][0]["run_rule"] =
1111         "configure_downlevel_regulator";
1112     // Valid: test if.
1113     {
1114         json configFile = ifFile;
1115         EXPECT_JSON_VALID(configFile);
1116     }
1117     // Valid: test if with required properties.
1118     {
1119         json configFile = ifFile;
1120         configFile["rules"][0]["actions"][1]["if"].erase("else");
1121         EXPECT_JSON_VALID(configFile);
1122     }
1123     // Invalid: test if with no property condition.
1124     {
1125         json configFile = ifFile;
1126         configFile["rules"][0]["actions"][1]["if"].erase("condition");
1127         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1128                             "u'condition' is a required property");
1129     }
1130     // Invalid: test if with no property then.
1131     {
1132         json configFile = ifFile;
1133         configFile["rules"][0]["actions"][1]["if"].erase("then");
1134         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1135                             "u'then' is a required property");
1136     }
1137     // Invalid: test if with property then empty array.
1138     {
1139         json configFile = ifFile;
1140         configFile["rules"][0]["actions"][1]["if"]["then"] = json::array();
1141         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1142                             "[] is too short");
1143     }
1144     // Invalid: test if with property else empty array.
1145     {
1146         json configFile = ifFile;
1147         configFile["rules"][0]["actions"][1]["if"]["else"] = json::array();
1148         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1149                             "[] is too short");
1150     }
1151     // Invalid: test if with property condition wrong type.
1152     {
1153         json configFile = ifFile;
1154         configFile["rules"][0]["actions"][1]["if"]["condition"] = 1;
1155         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1156                             "1 is not of type u'object'");
1157     }
1158     // Invalid: test if with property then wrong type.
1159     {
1160         json configFile = ifFile;
1161         configFile["rules"][0]["actions"][1]["if"]["then"] = 1;
1162         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1163                             "1 is not of type u'array'");
1164     }
1165     // Invalid: test if with property else wrong type.
1166     {
1167         json configFile = ifFile;
1168         configFile["rules"][0]["actions"][1]["if"]["else"] = 1;
1169         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1170                             "1 is not of type u'array'");
1171     }
1172 }
1173 TEST(ValidateRegulatorsConfigTest, Not)
1174 {
1175     json notFile = validConfigFile;
1176     notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] =
1177         "0xA0";
1178     notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] =
1179         "0xFF";
1180     // Valid: test not.
1181     {
1182         json configFile = notFile;
1183         EXPECT_JSON_VALID(configFile);
1184     }
1185     // Invalid: test not with wrong type.
1186     {
1187         json configFile = notFile;
1188         configFile["rules"][0]["actions"][1]["not"] = 1;
1189         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1190                             "1 is not of type u'object'");
1191     }
1192 }
1193 TEST(ValidateRegulatorsConfigTest, Or)
1194 {
1195     json orFile = validConfigFile;
1196     orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] =
1197         "0xA0";
1198     orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] =
1199         "0x00";
1200     orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] =
1201         "0xA1";
1202     orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] =
1203         "0x00";
1204     // Valid: test or.
1205     {
1206         json configFile = orFile;
1207         EXPECT_JSON_VALID(configFile);
1208     }
1209     // Invalid: test or with empty array.
1210     {
1211         json configFile = orFile;
1212         configFile["rules"][0]["actions"][1]["or"] = json::array();
1213         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1214                             "[] is too short");
1215     }
1216     // Invalid: test or with wrong type.
1217     {
1218         json configFile = orFile;
1219         configFile["rules"][0]["actions"][1]["or"] = 1;
1220         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1221                             "1 is not of type u'array'");
1222     }
1223 }
1224 TEST(ValidateRegulatorsConfigTest, PmbusReadSensor)
1225 {
1226     json pmbusReadSensorFile = validConfigFile;
1227     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1228         "vout";
1229     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1230                        ["command"] = "0x8B";
1231     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1232                        ["format"] = "linear_16";
1233     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1234                        ["exponent"] = -8;
1235     // Valid: test pmbus_read_sensor.
1236     {
1237         json configFile = pmbusReadSensorFile;
1238         EXPECT_JSON_VALID(configFile);
1239     }
1240     // Valid: test pmbus_read_sensor with required properties.
1241     {
1242         json configFile = pmbusReadSensorFile;
1243         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1244             "exponent");
1245         EXPECT_JSON_VALID(configFile);
1246     }
1247     // Invalid: test pmbus_read_sensor with no type.
1248     {
1249         json configFile = pmbusReadSensorFile;
1250         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type");
1251         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1252                             "u'type' is a required property");
1253     }
1254     // Invalid: test pmbus_read_sensor with no command.
1255     {
1256         json configFile = pmbusReadSensorFile;
1257         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1258             "command");
1259         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1260                             "u'command' is a required property");
1261     }
1262     // Invalid: test pmbus_read_sensor with no format.
1263     {
1264         json configFile = pmbusReadSensorFile;
1265         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1266             "format");
1267         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1268                             "u'format' is a required property");
1269     }
1270     // Invalid: test pmbus_read_sensor with property type wrong type.
1271     {
1272         json configFile = pmbusReadSensorFile;
1273         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1274             true;
1275         EXPECT_JSON_INVALID(
1276             configFile, "Validation failed.",
1277             "True is not one of [u'iout', u'iout_peak', u'iout_valley', "
1278             "u'pout', u'temperature', u'temperature_peak', u'vout', "
1279             "u'vout_peak', u'vout_valley']");
1280     }
1281     // Invalid: test pmbus_read_sensor with property command wrong type.
1282     {
1283         json configFile = pmbusReadSensorFile;
1284         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1285             true;
1286         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1287                             "True is not of type u'string'");
1288     }
1289     // Invalid: test pmbus_read_sensor with property format wrong type.
1290     {
1291         json configFile = pmbusReadSensorFile;
1292         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1293             true;
1294         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1295                             "True is not one of [u'linear_11', u'linear_16']");
1296     }
1297     // Invalid: test pmbus_read_sensor with property exponent wrong type.
1298     {
1299         json configFile = pmbusReadSensorFile;
1300         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] =
1301             true;
1302         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1303                             "True is not of type u'integer'");
1304     }
1305     // Invalid: test pmbus_read_sensor with property type wrong format.
1306     {
1307         json configFile = pmbusReadSensorFile;
1308         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1309             "foo";
1310         EXPECT_JSON_INVALID(
1311             configFile, "Validation failed.",
1312             "u'foo' is not one of [u'iout', u'iout_peak', u'iout_valley', "
1313             "u'pout', u'temperature', u'temperature_peak', u'vout', "
1314             "u'vout_peak', u'vout_valley']");
1315     }
1316     // Invalid: test pmbus_read_sensor with property command wrong format.
1317     {
1318         json configFile = pmbusReadSensorFile;
1319         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1320             "0x8B0";
1321         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1322                             "u'0x8B0' does not match u'^0x[0-9a-fA-F]{2}$'");
1323     }
1324     // Invalid: test pmbus_read_sensor with property format wrong format.
1325     {
1326         json configFile = pmbusReadSensorFile;
1327         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1328             "foo";
1329         EXPECT_JSON_INVALID(
1330             configFile, "Validation failed.",
1331             "u'foo' is not one of [u'linear_11', u'linear_16']");
1332     }
1333 }
1334 TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand)
1335 {
1336     json pmbusWriteVoutCommandFile = validConfigFile;
1337     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1338                              ["pmbus_write_vout_command"]["volts"] = 1.03;
1339     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1340                              ["pmbus_write_vout_command"]["format"] = "linear";
1341     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1342                              ["pmbus_write_vout_command"]["exponent"] = -8;
1343     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1344                              ["pmbus_write_vout_command"]["is_verified"] = true;
1345     // Valid: test pmbus_write_vout_command.
1346     {
1347         json configFile = pmbusWriteVoutCommandFile;
1348         EXPECT_JSON_VALID(configFile);
1349     }
1350     // Valid: test pmbus_write_vout_command with required properties.
1351     {
1352         json configFile = pmbusWriteVoutCommandFile;
1353         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1354             "volts");
1355         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1356             "exponent");
1357         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1358             "is_verified");
1359         EXPECT_JSON_VALID(configFile);
1360     }
1361     // Invalid: test pmbus_write_vout_command with no format.
1362     {
1363         json configFile = pmbusWriteVoutCommandFile;
1364         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1365             "format");
1366         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1367                             "u'format' is a required property");
1368     }
1369     // Invalid: test pmbus_write_vout_command with property volts wrong type.
1370     {
1371         json configFile = pmbusWriteVoutCommandFile;
1372         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1373                   ["volts"] = true;
1374         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1375                             "True is not of type u'number'");
1376     }
1377     // Invalid: test pmbus_write_vout_command with property format wrong type.
1378     {
1379         json configFile = pmbusWriteVoutCommandFile;
1380         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1381                   ["format"] = true;
1382         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1383                             "True is not one of [u'linear']");
1384     }
1385     // Invalid: test pmbus_write_vout_command with property exponent wrong type.
1386     {
1387         json configFile = pmbusWriteVoutCommandFile;
1388         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1389                   ["exponent"] = 1.3;
1390         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1391                             "1.3 is not of type u'integer'");
1392     }
1393     // Invalid: test pmbus_write_vout_command with property is_verified wrong
1394     // type.
1395     {
1396         json configFile = pmbusWriteVoutCommandFile;
1397         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1398                   ["is_verified"] = 1;
1399         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1400                             "1 is not of type u'boolean'");
1401     }
1402     // Invalid: test pmbus_write_vout_command with property format wrong format.
1403     {
1404         json configFile = pmbusWriteVoutCommandFile;
1405         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1406                   ["format"] = "foo";
1407         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1408                             "u'foo' is not one of [u'linear']");
1409     }
1410 }
1411 TEST(ValidateRegulatorsConfigTest, RunRule)
1412 {
1413     json runRuleFile = validConfigFile;
1414     runRuleFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule1";
1415     // Valid: test run_rule.
1416     {
1417         json configFile = runRuleFile;
1418         EXPECT_JSON_VALID(configFile);
1419     }
1420     // Invalid: test run_rule wrong type.
1421     {
1422         json configFile = runRuleFile;
1423         configFile["rules"][0]["actions"][1]["run_rule"] = true;
1424         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1425                             "True is not of type u'string'");
1426     }
1427     // Invalid: test run_rule wrong format.
1428     {
1429         json configFile = runRuleFile;
1430         configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%";
1431         EXPECT_JSON_INVALID(
1432             configFile, "Validation failed.",
1433             "u'set_voltage_rule%' does not match u'^[A-Za-z0-9_]+$'");
1434     }
1435 }
1436 TEST(ValidateRegulatorsConfigTest, SetDevice)
1437 {
1438     json setDeviceFile = validConfigFile;
1439     setDeviceFile["rules"][0]["actions"][1]["set_device"] = "io_expander2";
1440     // Valid: test set_device.
1441     {
1442         json configFile = setDeviceFile;
1443         EXPECT_JSON_VALID(configFile);
1444     }
1445     // Invalid: test set_device wrong type.
1446     {
1447         json configFile = setDeviceFile;
1448         configFile["rules"][0]["actions"][1]["set_device"] = true;
1449         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1450                             "True is not of type u'string'");
1451     }
1452     // Invalid: test set_device wrong format.
1453     {
1454         json configFile = setDeviceFile;
1455         configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%";
1456         EXPECT_JSON_INVALID(
1457             configFile, "Validation failed.",
1458             "u'io_expander2%' does not match u'^[A-Za-z0-9_]+$'");
1459     }
1460 }
1461