xref: /openbmc/phosphor-power/phosphor-regulators/test/validate-regulators-config_tests.cpp (revision e86c2e5eaedebbfa991bbe26d0b2a020dd3465d8)
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, ComparePresence)
352 {
353     json comparePresenceFile = validConfigFile;
354     comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
355         "/system/chassis/motherboard/regulator2";
356     comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
357         true;
358     // Valid.
359     {
360         json configFile = comparePresenceFile;
361         EXPECT_JSON_VALID(configFile);
362     }
363 
364     // Invalid: no FRU property.
365     {
366         json configFile = comparePresenceFile;
367         configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru");
368         EXPECT_JSON_INVALID(configFile, "Validation failed.",
369                             "u'fru' is a required property");
370     }
371 
372     // Invalid: FRU property length is string less than 1.
373     {
374         json configFile = comparePresenceFile;
375         configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = "";
376         EXPECT_JSON_INVALID(configFile, "Validation failed.",
377                             "u'' is too short");
378     }
379 
380     // Invalid: no value property.
381     {
382         json configFile = comparePresenceFile;
383         configFile["rules"][0]["actions"][1]["compare_presence"].erase("value");
384         EXPECT_JSON_INVALID(configFile, "Validation failed.",
385                             "u'value' is a required property");
386     }
387 
388     // Invalid: value property type is not boolean.
389     {
390         json configFile = comparePresenceFile;
391         configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1";
392         EXPECT_JSON_INVALID(configFile, "Validation failed.",
393                             "u'1' is not of type u'boolean'");
394     }
395 
396     // Invalid: FRU property type is not string.
397     {
398         json configFile = comparePresenceFile;
399         configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1;
400         EXPECT_JSON_INVALID(configFile, "Validation failed.",
401                             "1 is not of type u'string'");
402     }
403 }
404 TEST(ValidateRegulatorsConfigTest, CompareVpd)
405 {
406     json compareVpdFile = validConfigFile;
407     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
408         "/system/chassis/motherboard/regulator2";
409     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
410     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
411 
412     // Valid.
413     {
414         json configFile = compareVpdFile;
415         EXPECT_JSON_VALID(configFile);
416     }
417 
418     // Invalid: no FRU property.
419     {
420         json configFile = compareVpdFile;
421         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru");
422         EXPECT_JSON_INVALID(configFile, "Validation failed.",
423                             "u'fru' is a required property");
424     }
425 
426     // Invalid: no keyword property.
427     {
428         json configFile = compareVpdFile;
429         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword");
430         EXPECT_JSON_INVALID(configFile, "Validation failed.",
431                             "u'keyword' is a required property");
432     }
433 
434     // Invalid: no value property.
435     {
436         json configFile = compareVpdFile;
437         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
438         EXPECT_JSON_INVALID(configFile, "Validation failed.",
439                             "u'value' is a required property");
440     }
441 
442     // Invalid: property FRU wrong type.
443     {
444         json configFile = compareVpdFile;
445         configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1;
446         EXPECT_JSON_INVALID(configFile, "Validation failed.",
447                             "1 is not of type u'string'");
448     }
449 
450     // Invalid: property FRU is string less than 1.
451     {
452         json configFile = compareVpdFile;
453         configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = "";
454         EXPECT_JSON_INVALID(configFile, "Validation failed.",
455                             "u'' is too short");
456     }
457 
458     // Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
459     // "PartNumber"
460     {
461         json configFile = compareVpdFile;
462         configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
463             "Number";
464         EXPECT_JSON_INVALID(configFile, "Validation failed.",
465                             "u'Number' is not one of [u'CCIN', "
466                             "u'Manufacturer', u'Model', u'PartNumber']");
467     }
468 
469     // Invalid: property value wrong type.
470     {
471         json configFile = compareVpdFile;
472         configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1;
473         EXPECT_JSON_INVALID(configFile, "Validation failed.",
474                             "1 is not of type u'string'");
475     }
476 }
477 TEST(ValidateRegulatorsConfigTest, I2CCompareBit)
478 {
479     json i2cCompareBitFile = validConfigFile;
480     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
481         "0xA0";
482     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
483         3;
484     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
485     // Valid: test rule actions i2c_compare_bit.
486     {
487         json configFile = i2cCompareBitFile;
488         EXPECT_JSON_VALID(configFile);
489     }
490     // Invalid: test i2c_compare_bit with no register.
491     {
492         json configFile = i2cCompareBitFile;
493         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
494             "register");
495         EXPECT_JSON_INVALID(configFile, "Validation failed.",
496                             "u'register' is a required property");
497     }
498     // Invalid: test i2c_compare_bit with no position.
499     {
500         json configFile = i2cCompareBitFile;
501         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
502             "position");
503         EXPECT_JSON_INVALID(configFile, "Validation failed.",
504                             "u'position' is a required property");
505     }
506     // Invalid: test i2c_compare_bit with no value.
507     {
508         json configFile = i2cCompareBitFile;
509         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value");
510         EXPECT_JSON_INVALID(configFile, "Validation failed.",
511                             "u'value' is a required property");
512     }
513     // Invalid: test i2c_compare_bit with register wrong type.
514     {
515         json configFile = i2cCompareBitFile;
516         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1;
517         EXPECT_JSON_INVALID(configFile, "Validation failed.",
518                             "1 is not of type u'string'");
519     }
520     // Invalid: test i2c_compare_bit with register wrong format.
521     {
522         json configFile = i2cCompareBitFile;
523         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
524             "0xA00";
525         EXPECT_JSON_INVALID(configFile, "Validation failed.",
526                             "u'0xA00' does not match u'^0x[0-9A-Fa-f]{2}$'");
527     }
528     // Invalid: test i2c_compare_bit with position wrong type.
529     {
530         json configFile = i2cCompareBitFile;
531         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
532             3.1;
533         EXPECT_JSON_INVALID(configFile, "Validation failed.",
534                             "3.1 is not of type u'integer'");
535     }
536     // Invalid: test i2c_compare_bit with position greater than 7.
537     {
538         json configFile = i2cCompareBitFile;
539         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8;
540         EXPECT_JSON_INVALID(configFile, "Validation failed.",
541                             "8 is greater than the maximum of 7");
542     }
543     // Invalid: test i2c_compare_bit with position less than 0.
544     {
545         json configFile = i2cCompareBitFile;
546         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
547             -1;
548         EXPECT_JSON_INVALID(configFile, "Validation failed.",
549                             "-1 is less than the minimum of 0");
550     }
551     // Invalid: test i2c_compare_bit with value wrong type.
552     {
553         json configFile = i2cCompareBitFile;
554         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1";
555         EXPECT_JSON_INVALID(configFile, "Validation failed.",
556                             "u'1' is not of type u'integer'");
557     }
558     // Invalid: test i2c_compare_bit with value greater than 1.
559     {
560         json configFile = i2cCompareBitFile;
561         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2;
562         EXPECT_JSON_INVALID(configFile, "Validation failed.",
563                             "2 is greater than the maximum of 1");
564     }
565     // Invalid: test i2c_compare_bit with value less than 0.
566     {
567         json configFile = i2cCompareBitFile;
568         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1;
569         EXPECT_JSON_INVALID(configFile, "Validation failed.",
570                             "-1 is less than the minimum of 0");
571     }
572 }
573 TEST(ValidateRegulatorsConfigTest, I2CCompareByte)
574 {
575     json i2cCompareByteFile = validConfigFile;
576     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]
577                       ["register"] = "0x82";
578     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
579         "0x40";
580     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
581         "0x7F";
582     // Valid: test i2c_compare_byte with all properties.
583     {
584         json configFile = i2cCompareByteFile;
585         EXPECT_JSON_VALID(configFile);
586     }
587     // Valid: test i2c_compare_byte with all required properties.
588     {
589         json configFile = i2cCompareByteFile;
590         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask");
591         EXPECT_JSON_VALID(configFile);
592     }
593     // Invalid: test i2c_compare_byte with no register.
594     {
595         json configFile = i2cCompareByteFile;
596         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase(
597             "register");
598         EXPECT_JSON_INVALID(configFile, "Validation failed.",
599                             "u'register' is a required property");
600     }
601     // Invalid: test i2c_compare_byte with no value.
602     {
603         json configFile = i2cCompareByteFile;
604         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value");
605         EXPECT_JSON_INVALID(configFile, "Validation failed.",
606                             "u'value' is a required property");
607     }
608     // Invalid: test i2c_compare_byte with property register wrong type.
609     {
610         json configFile = i2cCompareByteFile;
611         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
612             1;
613         EXPECT_JSON_INVALID(configFile, "Validation failed.",
614                             "1 is not of type u'string'");
615     }
616     // Invalid: test i2c_compare_byte with property value wrong type.
617     {
618         json configFile = i2cCompareByteFile;
619         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1;
620         EXPECT_JSON_INVALID(configFile, "Validation failed.",
621                             "1 is not of type u'string'");
622     }
623     // Invalid: test i2c_compare_byte with property mask wrong type.
624     {
625         json configFile = i2cCompareByteFile;
626         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1;
627         EXPECT_JSON_INVALID(configFile, "Validation failed.",
628                             "1 is not of type u'string'");
629     }
630     // Invalid: test i2c_compare_byte with property register more than 2 hex
631     // digits.
632     {
633         json configFile = i2cCompareByteFile;
634         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
635             "0x820";
636         EXPECT_JSON_INVALID(configFile, "Validation failed.",
637                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
638     }
639     // Invalid: test i2c_compare_byte with property value more than 2 hex
640     // digits.
641     {
642         json configFile = i2cCompareByteFile;
643         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
644             "0x820";
645         EXPECT_JSON_INVALID(configFile, "Validation failed.",
646                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
647     }
648     // Invalid: test i2c_compare_byte with property mask more than 2 hex digits.
649     {
650         json configFile = i2cCompareByteFile;
651         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
652             "0x820";
653         EXPECT_JSON_INVALID(configFile, "Validation failed.",
654                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
655     }
656     // Invalid: test i2c_compare_byte with property register less than 2 hex
657     // digits.
658     {
659         json configFile = i2cCompareByteFile;
660         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
661             "0x8";
662         EXPECT_JSON_INVALID(configFile, "Validation failed.",
663                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
664     }
665     // Invalid: test i2c_compare_byte with property value less than 2 hex
666     // digits.
667     {
668         json configFile = i2cCompareByteFile;
669         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
670             "0x8";
671         EXPECT_JSON_INVALID(configFile, "Validation failed.",
672                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
673     }
674     // Invalid: test i2c_compare_byte with property mask less than 2 hex digits.
675     {
676         json configFile = i2cCompareByteFile;
677         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
678             "0x8";
679         EXPECT_JSON_INVALID(configFile, "Validation failed.",
680                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
681     }
682     // Invalid: test i2c_compare_byte with property register no leading prefix.
683     {
684         json configFile = i2cCompareByteFile;
685         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
686             "82";
687         EXPECT_JSON_INVALID(configFile, "Validation failed.",
688                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
689     }
690     // Invalid: test i2c_compare_byte with property value no leading prefix.
691     {
692         json configFile = i2cCompareByteFile;
693         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
694             "82";
695         EXPECT_JSON_INVALID(configFile, "Validation failed.",
696                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
697     }
698     // Invalid: test i2c_compare_byte with property mask no leading prefix.
699     {
700         json configFile = i2cCompareByteFile;
701         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82";
702         EXPECT_JSON_INVALID(configFile, "Validation failed.",
703                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
704     }
705     // Invalid: test i2c_compare_byte with property register invalid hex digit.
706     {
707         json configFile = i2cCompareByteFile;
708         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
709             "0xG1";
710         EXPECT_JSON_INVALID(configFile, "Validation failed.",
711                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
712     }
713     // Invalid: test i2c_compare_byte with property value invalid hex digit.
714     {
715         json configFile = i2cCompareByteFile;
716         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
717             "0xG1";
718         EXPECT_JSON_INVALID(configFile, "Validation failed.",
719                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
720     }
721     // Invalid: test i2c_compare_byte with property mask invalid hex digit.
722     {
723         json configFile = i2cCompareByteFile;
724         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
725             "0xG1";
726         EXPECT_JSON_INVALID(configFile, "Validation failed.",
727                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
728     }
729 }
730 TEST(ValidateRegulatorsConfigTest, I2CCompareBytes)
731 {
732     json i2cCompareBytesFile = validConfigFile;
733     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
734                        ["register"] = "0x82";
735     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
736                        ["values"] = {"0x02", "0x73"};
737     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
738                        ["masks"] = {"0x7F", "0x7F"};
739     // Valid: test i2c_compare_bytes.
740     {
741         json configFile = i2cCompareBytesFile;
742         EXPECT_JSON_VALID(configFile);
743     }
744     // Valid: test i2c_compare_bytes with all required properties.
745     {
746         json configFile = i2cCompareBytesFile;
747         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
748             "masks");
749         EXPECT_JSON_VALID(configFile);
750     }
751     // Invalid: test i2c_compare_bytes with no register.
752     {
753         json configFile = i2cCompareBytesFile;
754         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
755             "register");
756         EXPECT_JSON_INVALID(configFile, "Validation failed.",
757                             "u'register' is a required property");
758     }
759     // Invalid: test i2c_compare_bytes with no values.
760     {
761         json configFile = i2cCompareBytesFile;
762         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
763             "values");
764         EXPECT_JSON_INVALID(configFile, "Validation failed.",
765                             "u'values' is a required property");
766     }
767     // Invalid: test i2c_compare_bytes with property values as empty array.
768     {
769         json configFile = i2cCompareBytesFile;
770         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] =
771             json::array();
772         EXPECT_JSON_INVALID(configFile, "Validation failed.",
773                             "[] is too short");
774     }
775     // Invalid: test i2c_compare_bytes with property masks as empty array.
776     {
777         json configFile = i2cCompareBytesFile;
778         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] =
779             json::array();
780         EXPECT_JSON_INVALID(configFile, "Validation failed.",
781                             "[] is too short");
782     }
783     // Invalid: test i2c_compare_bytes with property register wrong type.
784     {
785         json configFile = i2cCompareBytesFile;
786         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
787             1;
788         EXPECT_JSON_INVALID(configFile, "Validation failed.",
789                             "1 is not of type u'string'");
790     }
791     // Invalid: test i2c_compare_bytes with property values wrong type.
792     {
793         json configFile = i2cCompareBytesFile;
794         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1;
795         EXPECT_JSON_INVALID(configFile, "Validation failed.",
796                             "1 is not of type u'array'");
797     }
798     // Invalid: test i2c_compare_bytes with property masks wrong type.
799     {
800         json configFile = i2cCompareBytesFile;
801         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1;
802         EXPECT_JSON_INVALID(configFile, "Validation failed.",
803                             "1 is not of type u'array'");
804     }
805     // Invalid: test i2c_compare_bytes with property register more than 2 hex
806     // digits.
807     {
808         json configFile = i2cCompareBytesFile;
809         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
810             "0x820";
811         EXPECT_JSON_INVALID(configFile, "Validation failed.",
812                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
813     }
814     // Invalid: test i2c_compare_bytes with property values more than 2 hex
815     // digits.
816     {
817         json configFile = i2cCompareBytesFile;
818         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
819             "0x820";
820         EXPECT_JSON_INVALID(configFile, "Validation failed.",
821                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
822     }
823     // Invalid: test i2c_compare_bytes with property masks more than 2 hex
824     // digits.
825     {
826         json configFile = i2cCompareBytesFile;
827         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
828             "0x820";
829         EXPECT_JSON_INVALID(configFile, "Validation failed.",
830                             "u'0x820' does not match u'^0x[0-9A-Fa-f]{2}$'");
831     }
832     // Invalid: test i2c_compare_bytes with property register less than 2 hex
833     // digits.
834     {
835         json configFile = i2cCompareBytesFile;
836         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
837             "0x8";
838         EXPECT_JSON_INVALID(configFile, "Validation failed.",
839                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
840     }
841     // Invalid: test i2c_compare_bytes with property values less than 2 hex
842     // digits.
843     {
844         json configFile = i2cCompareBytesFile;
845         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
846             "0x8";
847         EXPECT_JSON_INVALID(configFile, "Validation failed.",
848                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
849     }
850     // Invalid: test i2c_compare_bytes with property masks less than 2 hex
851     // digits.
852     {
853         json configFile = i2cCompareBytesFile;
854         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
855             "0x8";
856         EXPECT_JSON_INVALID(configFile, "Validation failed.",
857                             "u'0x8' does not match u'^0x[0-9A-Fa-f]{2}$'");
858     }
859     // Invalid: test i2c_compare_bytes with property register no leading prefix.
860     {
861         json configFile = i2cCompareBytesFile;
862         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
863             "82";
864         EXPECT_JSON_INVALID(configFile, "Validation failed.",
865                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
866     }
867     // Invalid: test i2c_compare_bytes with property values no leading prefix.
868     {
869         json configFile = i2cCompareBytesFile;
870         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
871             "82";
872         EXPECT_JSON_INVALID(configFile, "Validation failed.",
873                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
874     }
875     // Invalid: test i2c_compare_bytes with property masks no leading prefix.
876     {
877         json configFile = i2cCompareBytesFile;
878         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
879             "82";
880         EXPECT_JSON_INVALID(configFile, "Validation failed.",
881                             "u'82' does not match u'^0x[0-9A-Fa-f]{2}$'");
882     }
883     // Invalid: test i2c_compare_bytes with property register invalid hex digit.
884     {
885         json configFile = i2cCompareBytesFile;
886         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
887             "0xG1";
888         EXPECT_JSON_INVALID(configFile, "Validation failed.",
889                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
890     }
891     // Invalid: test i2c_compare_bytes with property values invalid hex digit.
892     {
893         json configFile = i2cCompareBytesFile;
894         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
895             "0xG1";
896         EXPECT_JSON_INVALID(configFile, "Validation failed.",
897                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
898     }
899     // Invalid: test i2c_compare_bytes with property masks invalid hex digit.
900     {
901         json configFile = i2cCompareBytesFile;
902         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
903             "0xG1";
904         EXPECT_JSON_INVALID(configFile, "Validation failed.",
905                             "u'0xG1' does not match u'^0x[0-9A-Fa-f]{2}$'");
906     }
907 }
908 TEST(ValidateRegulatorsConfigTest, If)
909 {
910     json ifFile = validConfigFile;
911     ifFile["rules"][0]["actions"][1]["if"]["condition"]["run_rule"] =
912         "is_downlevel_regulator";
913     ifFile["rules"][0]["actions"][1]["if"]["then"][0]["run_rule"] =
914         "configure_downlevel_regulator";
915     ifFile["rules"][0]["actions"][1]["if"]["else"][0]["run_rule"] =
916         "configure_downlevel_regulator";
917     // Valid: test if.
918     {
919         json configFile = ifFile;
920         EXPECT_JSON_VALID(configFile);
921     }
922     // Valid: test if with required properties.
923     {
924         json configFile = ifFile;
925         configFile["rules"][0]["actions"][1]["if"].erase("else");
926         EXPECT_JSON_VALID(configFile);
927     }
928     // Invalid: test if with no property condition.
929     {
930         json configFile = ifFile;
931         configFile["rules"][0]["actions"][1]["if"].erase("condition");
932         EXPECT_JSON_INVALID(configFile, "Validation failed.",
933                             "u'condition' is a required property");
934     }
935     // Invalid: test if with no property then.
936     {
937         json configFile = ifFile;
938         configFile["rules"][0]["actions"][1]["if"].erase("then");
939         EXPECT_JSON_INVALID(configFile, "Validation failed.",
940                             "u'then' is a required property");
941     }
942     // Invalid: test if with property then empty array.
943     {
944         json configFile = ifFile;
945         configFile["rules"][0]["actions"][1]["if"]["then"] = json::array();
946         EXPECT_JSON_INVALID(configFile, "Validation failed.",
947                             "[] is too short");
948     }
949     // Invalid: test if with property else empty array.
950     {
951         json configFile = ifFile;
952         configFile["rules"][0]["actions"][1]["if"]["else"] = json::array();
953         EXPECT_JSON_INVALID(configFile, "Validation failed.",
954                             "[] is too short");
955     }
956     // Invalid: test if with property condition wrong type.
957     {
958         json configFile = ifFile;
959         configFile["rules"][0]["actions"][1]["if"]["condition"] = 1;
960         EXPECT_JSON_INVALID(configFile, "Validation failed.",
961                             "1 is not of type u'object'");
962     }
963     // Invalid: test if with property then wrong type.
964     {
965         json configFile = ifFile;
966         configFile["rules"][0]["actions"][1]["if"]["then"] = 1;
967         EXPECT_JSON_INVALID(configFile, "Validation failed.",
968                             "1 is not of type u'array'");
969     }
970     // Invalid: test if with property else wrong type.
971     {
972         json configFile = ifFile;
973         configFile["rules"][0]["actions"][1]["if"]["else"] = 1;
974         EXPECT_JSON_INVALID(configFile, "Validation failed.",
975                             "1 is not of type u'array'");
976     }
977 }
978 TEST(ValidateRegulatorsConfigTest, Not)
979 {
980     json notFile = validConfigFile;
981     notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] =
982         "0xA0";
983     notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] =
984         "0xFF";
985     // Valid: test not.
986     {
987         json configFile = notFile;
988         EXPECT_JSON_VALID(configFile);
989     }
990     // Invalid: test not with wrong type.
991     {
992         json configFile = notFile;
993         configFile["rules"][0]["actions"][1]["not"] = 1;
994         EXPECT_JSON_INVALID(configFile, "Validation failed.",
995                             "1 is not of type u'object'");
996     }
997 }
998 TEST(ValidateRegulatorsConfigTest, Or)
999 {
1000     json orFile = validConfigFile;
1001     orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] =
1002         "0xA0";
1003     orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] =
1004         "0x00";
1005     orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] =
1006         "0xA1";
1007     orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] =
1008         "0x00";
1009     // Valid: test or.
1010     {
1011         json configFile = orFile;
1012         EXPECT_JSON_VALID(configFile);
1013     }
1014     // Invalid: test or with empty array.
1015     {
1016         json configFile = orFile;
1017         configFile["rules"][0]["actions"][1]["or"] = json::array();
1018         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1019                             "[] is too short");
1020     }
1021     // Invalid: test or with wrong type.
1022     {
1023         json configFile = orFile;
1024         configFile["rules"][0]["actions"][1]["or"] = 1;
1025         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1026                             "1 is not of type u'array'");
1027     }
1028 }
1029 TEST(ValidateRegulatorsConfigTest, PmbusReadSensor)
1030 {
1031     json pmbusReadSensorFile = validConfigFile;
1032     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1033         "vout";
1034     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1035                        ["command"] = "0x8B";
1036     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1037                        ["format"] = "linear_16";
1038     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1039                        ["exponent"] = -8;
1040     // Valid: test pmbus_read_sensor.
1041     {
1042         json configFile = pmbusReadSensorFile;
1043         EXPECT_JSON_VALID(configFile);
1044     }
1045     // Valid: test pmbus_read_sensor with required properties.
1046     {
1047         json configFile = pmbusReadSensorFile;
1048         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1049             "exponent");
1050         EXPECT_JSON_VALID(configFile);
1051     }
1052     // Invalid: test pmbus_read_sensor with no type.
1053     {
1054         json configFile = pmbusReadSensorFile;
1055         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type");
1056         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1057                             "u'type' is a required property");
1058     }
1059     // Invalid: test pmbus_read_sensor with no command.
1060     {
1061         json configFile = pmbusReadSensorFile;
1062         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1063             "command");
1064         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1065                             "u'command' is a required property");
1066     }
1067     // Invalid: test pmbus_read_sensor with no format.
1068     {
1069         json configFile = pmbusReadSensorFile;
1070         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1071             "format");
1072         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1073                             "u'format' is a required property");
1074     }
1075     // Invalid: test pmbus_read_sensor with property type wrong type.
1076     {
1077         json configFile = pmbusReadSensorFile;
1078         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1079             true;
1080         EXPECT_JSON_INVALID(
1081             configFile, "Validation failed.",
1082             "True is not one of [u'iout', u'iout_peak', u'iout_valley', "
1083             "u'pout', u'temperature', u'temperature_peak', u'vout', "
1084             "u'vout_peak', u'vout_valley']");
1085     }
1086     // Invalid: test pmbus_read_sensor with property command wrong type.
1087     {
1088         json configFile = pmbusReadSensorFile;
1089         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1090             true;
1091         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1092                             "True is not of type u'string'");
1093     }
1094     // Invalid: test pmbus_read_sensor with property format wrong type.
1095     {
1096         json configFile = pmbusReadSensorFile;
1097         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1098             true;
1099         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1100                             "True is not one of [u'linear_11', u'linear_16']");
1101     }
1102     // Invalid: test pmbus_read_sensor with property exponent wrong type.
1103     {
1104         json configFile = pmbusReadSensorFile;
1105         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] =
1106             true;
1107         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1108                             "True is not of type u'integer'");
1109     }
1110     // Invalid: test pmbus_read_sensor with property type wrong format.
1111     {
1112         json configFile = pmbusReadSensorFile;
1113         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1114             "foo";
1115         EXPECT_JSON_INVALID(
1116             configFile, "Validation failed.",
1117             "u'foo' is not one of [u'iout', u'iout_peak', u'iout_valley', "
1118             "u'pout', u'temperature', u'temperature_peak', u'vout', "
1119             "u'vout_peak', u'vout_valley']");
1120     }
1121     // Invalid: test pmbus_read_sensor with property command wrong format.
1122     {
1123         json configFile = pmbusReadSensorFile;
1124         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1125             "0x8B0";
1126         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1127                             "u'0x8B0' does not match u'^0x[0-9a-fA-F]{2}$'");
1128     }
1129     // Invalid: test pmbus_read_sensor with property format wrong format.
1130     {
1131         json configFile = pmbusReadSensorFile;
1132         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1133             "foo";
1134         EXPECT_JSON_INVALID(
1135             configFile, "Validation failed.",
1136             "u'foo' is not one of [u'linear_11', u'linear_16']");
1137     }
1138 }
1139 TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand)
1140 {
1141     json pmbusWriteVoutCommandFile = validConfigFile;
1142     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1143                              ["pmbus_write_vout_command"]["volts"] = 1.03;
1144     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1145                              ["pmbus_write_vout_command"]["format"] = "linear";
1146     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1147                              ["pmbus_write_vout_command"]["exponent"] = -8;
1148     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1149                              ["pmbus_write_vout_command"]["is_verified"] = true;
1150     // Valid: test pmbus_write_vout_command.
1151     {
1152         json configFile = pmbusWriteVoutCommandFile;
1153         EXPECT_JSON_VALID(configFile);
1154     }
1155     // Valid: test pmbus_write_vout_command with required properties.
1156     {
1157         json configFile = pmbusWriteVoutCommandFile;
1158         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1159             "volts");
1160         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1161             "exponent");
1162         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1163             "is_verified");
1164         EXPECT_JSON_VALID(configFile);
1165     }
1166     // Invalid: test pmbus_write_vout_command with no format.
1167     {
1168         json configFile = pmbusWriteVoutCommandFile;
1169         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1170             "format");
1171         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1172                             "u'format' is a required property");
1173     }
1174     // Invalid: test pmbus_write_vout_command with property volts wrong type.
1175     {
1176         json configFile = pmbusWriteVoutCommandFile;
1177         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1178                   ["volts"] = true;
1179         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1180                             "True is not of type u'number'");
1181     }
1182     // Invalid: test pmbus_write_vout_command with property format wrong type.
1183     {
1184         json configFile = pmbusWriteVoutCommandFile;
1185         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1186                   ["format"] = true;
1187         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1188                             "True is not one of [u'linear']");
1189     }
1190     // Invalid: test pmbus_write_vout_command with property exponent wrong type.
1191     {
1192         json configFile = pmbusWriteVoutCommandFile;
1193         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1194                   ["exponent"] = 1.3;
1195         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1196                             "1.3 is not of type u'integer'");
1197     }
1198     // Invalid: test pmbus_write_vout_command with property is_verified wrong
1199     // type.
1200     {
1201         json configFile = pmbusWriteVoutCommandFile;
1202         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1203                   ["is_verified"] = 1;
1204         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1205                             "1 is not of type u'boolean'");
1206     }
1207     // Invalid: test pmbus_write_vout_command with property format wrong format.
1208     {
1209         json configFile = pmbusWriteVoutCommandFile;
1210         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1211                   ["format"] = "foo";
1212         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1213                             "u'foo' is not one of [u'linear']");
1214     }
1215 }
1216 TEST(ValidateRegulatorsConfigTest, RunRule)
1217 {
1218     json runRuleFile = validConfigFile;
1219     runRuleFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule1";
1220     // Valid: test run_rule.
1221     {
1222         json configFile = runRuleFile;
1223         EXPECT_JSON_VALID(configFile);
1224     }
1225     // Invalid: test run_rule wrong type.
1226     {
1227         json configFile = runRuleFile;
1228         configFile["rules"][0]["actions"][1]["run_rule"] = true;
1229         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1230                             "True is not of type u'string'");
1231     }
1232     // Invalid: test run_rule wrong format.
1233     {
1234         json configFile = runRuleFile;
1235         configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%";
1236         EXPECT_JSON_INVALID(
1237             configFile, "Validation failed.",
1238             "u'set_voltage_rule%' does not match u'^[A-Za-z0-9_]+$'");
1239     }
1240 }
1241