xref: /openbmc/phosphor-power/phosphor-regulators/test/validate-regulators-config_tests.cpp (revision 5f51444df8acc12f59cf6b0cedbcfe49475c3712)
1386d33ffSBob King /**
20dcbdf57SBob King  * Copyright c 2020 IBM Corporation
3386d33ffSBob King  *
4386d33ffSBob King  * Licensed under the Apache License, Version 2.0 (the "License");
5386d33ffSBob King  * you may not use this file except in compliance with the License.
6386d33ffSBob King  * You may obtain a copy of the License at
7386d33ffSBob King  *
8386d33ffSBob King  *     http://www.apache.org/licenses/LICENSE-2.0
9386d33ffSBob King  *
10386d33ffSBob King  * Unless required by applicable law or agreed to in writing, software
11386d33ffSBob King  * distributed under the License is distributed on an "AS IS" BASIS,
12386d33ffSBob King  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13386d33ffSBob King  * See the License for the specific language governing permissions and
14386d33ffSBob King  * limitations under the License.
15386d33ffSBob King  */
160f6ebadeSShawn McCarney #include "temporary_file.hpp"
1780c0b049SShawn McCarney 
1880c0b049SShawn McCarney #include <stdio.h>    // for popen(), pclose(), fgets()
1980c0b049SShawn McCarney #include <sys/stat.h> // for chmod()
2080c0b049SShawn McCarney #include <sys/wait.h> // for WEXITSTATUS
21386d33ffSBob King 
22386d33ffSBob King #include <nlohmann/json.hpp>
23386d33ffSBob King 
2480c0b049SShawn McCarney #include <cstdio>
250dcbdf57SBob King #include <fstream>
260dcbdf57SBob King 
27386d33ffSBob King #include <gtest/gtest.h>
28386d33ffSBob King 
29386d33ffSBob King #define EXPECT_FILE_VALID(configFile) expectFileValid(configFile)
30386d33ffSBob King #define EXPECT_FILE_INVALID(configFile, expectedErrorMessage,                  \
31386d33ffSBob King                             expectedOutputMessage)                             \
32386d33ffSBob King     expectFileInvalid(configFile, expectedErrorMessage, expectedOutputMessage)
33386d33ffSBob King #define EXPECT_JSON_VALID(configFileJson) expectJsonValid(configFileJson)
34386d33ffSBob King #define EXPECT_JSON_INVALID(configFileJson, expectedErrorMessage,              \
35386d33ffSBob King                             expectedOutputMessage)                             \
36386d33ffSBob King     expectJsonInvalid(configFileJson, expectedErrorMessage,                    \
37386d33ffSBob King                       expectedOutputMessage)
38386d33ffSBob King 
39386d33ffSBob King using json = nlohmann::json;
40*5f51444dSShawn McCarney using TemporaryFile = phosphor::power::util::TemporaryFile;
41386d33ffSBob King 
42386d33ffSBob King const json validConfigFile = R"(
43386d33ffSBob King     {
44386d33ffSBob King       "comments": [ "Config file for a FooBar one-chassis system" ],
45386d33ffSBob King 
46386d33ffSBob King       "rules": [
47386d33ffSBob King         {
48386d33ffSBob King           "comments": [ "Sets output voltage for a PMBus regulator rail" ],
49386d33ffSBob King           "id": "set_voltage_rule",
50386d33ffSBob King           "actions": [
51386d33ffSBob King             {
52386d33ffSBob King               "pmbus_write_vout_command": {
53386d33ffSBob King                 "format": "linear"
54386d33ffSBob King               }
55386d33ffSBob King             }
56386d33ffSBob King           ]
57b3e48bcaSBob King         },
58b3e48bcaSBob King         {
59b3e48bcaSBob King           "comments": [ "Reads sensors from a PMBus regulator rail" ],
60b3e48bcaSBob King           "id": "read_sensors_rule",
61b3e48bcaSBob King           "actions": [
62b3e48bcaSBob King             {
63b3e48bcaSBob King               "comments": [ "Read output voltage from READ_VOUT." ],
64b3e48bcaSBob King               "pmbus_read_sensor": {
65b3e48bcaSBob King                 "type": "vout",
66b3e48bcaSBob King                 "command": "0x8B",
67b3e48bcaSBob King                 "format": "linear_16"
68b3e48bcaSBob King               }
69b3e48bcaSBob King             }
70b3e48bcaSBob King           ]
71846dde5dSShawn McCarney         },
72846dde5dSShawn McCarney         {
73846dde5dSShawn McCarney           "comments": [ "Detects presence of regulators associated with CPU3" ],
74846dde5dSShawn McCarney           "id": "detect_presence_rule",
75846dde5dSShawn McCarney           "actions": [
76846dde5dSShawn McCarney             {
77846dde5dSShawn McCarney               "compare_presence": {
78846dde5dSShawn McCarney                 "fru": "system/chassis/motherboard/cpu3",
79846dde5dSShawn McCarney                 "value": true
80846dde5dSShawn McCarney               }
81846dde5dSShawn McCarney             }
82846dde5dSShawn McCarney           ]
83846dde5dSShawn McCarney         },
84846dde5dSShawn McCarney         {
85846dde5dSShawn McCarney           "comments": [ "Detects and logs redundant phase faults" ],
86846dde5dSShawn McCarney           "id": "detect_phase_faults_rule",
87846dde5dSShawn McCarney           "actions": [
88846dde5dSShawn McCarney             {
89846dde5dSShawn McCarney               "if": {
90846dde5dSShawn McCarney                 "condition": {
91846dde5dSShawn McCarney                   "i2c_compare_bit": { "register": "0x02", "position": 3, "value": 1 }
92846dde5dSShawn McCarney                 },
93846dde5dSShawn McCarney                 "then": [
94846dde5dSShawn McCarney                   { "log_phase_fault": { "type": "n" } }
95846dde5dSShawn McCarney                 ]
96846dde5dSShawn McCarney               }
97846dde5dSShawn McCarney             }
98846dde5dSShawn McCarney           ]
99386d33ffSBob King         }
100386d33ffSBob King       ],
101386d33ffSBob King 
102386d33ffSBob King       "chassis": [
103386d33ffSBob King         {
104386d33ffSBob King           "comments": [ "Chassis number 1 containing CPUs and memory" ],
105386d33ffSBob King           "number": 1,
106ecbeeea7SShawn McCarney           "inventory_path": "system/chassis",
107386d33ffSBob King           "devices": [
108386d33ffSBob King             {
109386d33ffSBob King               "comments": [ "IR35221 regulator producing the Vdd rail" ],
110386d33ffSBob King               "id": "vdd_regulator",
111386d33ffSBob King               "is_regulator": true,
112a76898f1SBob King               "fru": "system/chassis/motherboard/regulator1",
113386d33ffSBob King               "i2c_interface": {
114386d33ffSBob King                 "bus": 1,
115386d33ffSBob King                 "address": "0x70"
116386d33ffSBob King               },
117386d33ffSBob King               "rails": [
118386d33ffSBob King                 {
119386d33ffSBob King                   "comments": [ "Vdd rail" ],
120386d33ffSBob King                   "id": "vdd",
121386d33ffSBob King                   "configuration": {
122386d33ffSBob King                     "volts": 1.03,
123386d33ffSBob King                     "rule_id": "set_voltage_rule"
124386d33ffSBob King                   },
125386d33ffSBob King                   "sensor_monitoring": {
126386d33ffSBob King                     "rule_id": "read_sensors_rule"
127386d33ffSBob King                   }
128386d33ffSBob King                 }
129386d33ffSBob King               ]
130386d33ffSBob King             }
131386d33ffSBob King           ]
132386d33ffSBob King         }
133386d33ffSBob King       ]
134386d33ffSBob King     }
135386d33ffSBob King )"_json;
136386d33ffSBob King 
getValidationToolCommand(const std::string & configFileName)137386d33ffSBob King std::string getValidationToolCommand(const std::string& configFileName)
138386d33ffSBob King {
139a57e0814SBob King     std::string command =
140a57e0814SBob King         "../phosphor-regulators/tools/validate-regulators-config.py -s \
141a57e0814SBob King          ../phosphor-regulators/schema/config_schema.json -c ";
142386d33ffSBob King     command += configFileName;
143386d33ffSBob King     return command;
144386d33ffSBob King }
145386d33ffSBob King 
runToolForOutputWithCommand(std::string command,std::string & standardOutput,std::string & standardError)146a57e0814SBob King int runToolForOutputWithCommand(std::string command,
147a57e0814SBob King                                 std::string& standardOutput,
148a57e0814SBob King                                 std::string& standardError)
149386d33ffSBob King {
150386d33ffSBob King     // run the validation tool with the temporary file and return the output
151386d33ffSBob King     // of the validation tool.
1520f6ebadeSShawn McCarney     TemporaryFile tmpFile;
1530f6ebadeSShawn McCarney     command += " 2> " + tmpFile.getPath().string();
154386d33ffSBob King     // get the jsonschema print from validation tool.
155386d33ffSBob King     char buffer[256];
156a57e0814SBob King     std::string result;
157386d33ffSBob King     // to get the stdout from the validation tool.
158386d33ffSBob King     FILE* pipe = popen(command.c_str(), "r");
159386d33ffSBob King     if (!pipe)
160386d33ffSBob King     {
161386d33ffSBob King         throw std::runtime_error("popen() failed!");
162386d33ffSBob King     }
163386d33ffSBob King     while (!std::feof(pipe))
164386d33ffSBob King     {
165386d33ffSBob King         if (fgets(buffer, sizeof buffer, pipe) != NULL)
166386d33ffSBob King         {
167386d33ffSBob King             result += buffer;
168386d33ffSBob King         }
169386d33ffSBob King     }
170386d33ffSBob King     int returnValue = pclose(pipe);
171386d33ffSBob King     // Check if pclose() failed
172386d33ffSBob King     if (returnValue == -1)
173386d33ffSBob King     {
174386d33ffSBob King         // unable to close pipe.  Print error and exit function.
175386d33ffSBob King         throw std::runtime_error("pclose() failed!");
176386d33ffSBob King     }
177386d33ffSBob King     std::string firstLine = result.substr(0, result.find('\n'));
178a57e0814SBob King     standardOutput = firstLine;
179386d33ffSBob King     // Get command exit status from return value
180386d33ffSBob King     int exitStatus = WEXITSTATUS(returnValue);
181a57e0814SBob King 
182a57e0814SBob King     // Read the standardError from tmpFile.
1830f6ebadeSShawn McCarney     std::ifstream input(tmpFile.getPath());
184a57e0814SBob King     std::string line;
185a57e0814SBob King 
186a57e0814SBob King     if (std::getline(input, line))
187a57e0814SBob King     {
188a57e0814SBob King         standardError = line;
189a57e0814SBob King     }
190a57e0814SBob King 
191386d33ffSBob King     return exitStatus;
192386d33ffSBob King }
193386d33ffSBob King 
runToolForOutput(const std::string & configFileName,std::string & output,std::string & error)194ed009655SBob King int runToolForOutput(const std::string& configFileName, std::string& output,
195a57e0814SBob King                      std::string& error)
196ed009655SBob King {
197ed009655SBob King     std::string command = getValidationToolCommand(configFileName);
198a57e0814SBob King     return runToolForOutputWithCommand(command, output, error);
199ed009655SBob King }
200ed009655SBob King 
expectFileValid(const std::string & configFileName)201386d33ffSBob King void expectFileValid(const std::string& configFileName)
202386d33ffSBob King {
203ed009655SBob King     std::string errorMessage;
204ed009655SBob King     std::string outputMessage;
205a57e0814SBob King     EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 0);
206386d33ffSBob King     EXPECT_EQ(errorMessage, "");
207386d33ffSBob King     EXPECT_EQ(outputMessage, "");
208386d33ffSBob King }
209386d33ffSBob King 
expectFileInvalid(const std::string & configFileName,const std::string & expectedErrorMessage,const std::string & expectedOutputMessage)210386d33ffSBob King void expectFileInvalid(const std::string& configFileName,
211386d33ffSBob King                        const std::string& expectedErrorMessage,
212386d33ffSBob King                        const std::string& expectedOutputMessage)
213386d33ffSBob King {
214ed009655SBob King     std::string errorMessage;
215ed009655SBob King     std::string outputMessage;
216a57e0814SBob King     EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 1);
217386d33ffSBob King     EXPECT_EQ(errorMessage, expectedErrorMessage);
218846dde5dSShawn McCarney     if (expectedOutputMessage != "")
219846dde5dSShawn McCarney     {
220386d33ffSBob King         EXPECT_EQ(outputMessage, expectedOutputMessage);
221386d33ffSBob King     }
222846dde5dSShawn McCarney }
223386d33ffSBob King 
writeDataToFile(const json configFileJson,std::string fileName)224a57e0814SBob King void writeDataToFile(const json configFileJson, std::string fileName)
225386d33ffSBob King {
226386d33ffSBob King     std::string jsonData = configFileJson.dump();
227386d33ffSBob King     std::ofstream out(fileName);
228386d33ffSBob King     out << jsonData;
229386d33ffSBob King     out.close();
230ed009655SBob King }
231ed009655SBob King 
expectJsonValid(const json configFileJson)232ed009655SBob King void expectJsonValid(const json configFileJson)
233ed009655SBob King {
2340f6ebadeSShawn McCarney     TemporaryFile tmpFile;
2350f6ebadeSShawn McCarney     std::string fileName = tmpFile.getPath().string();
236a57e0814SBob King     writeDataToFile(configFileJson, fileName);
237ed009655SBob King 
238386d33ffSBob King     EXPECT_FILE_VALID(fileName);
239386d33ffSBob King }
240386d33ffSBob King 
expectJsonInvalid(const json configFileJson,const std::string & expectedErrorMessage,const std::string & expectedOutputMessage)241386d33ffSBob King void expectJsonInvalid(const json configFileJson,
242386d33ffSBob King                        const std::string& expectedErrorMessage,
243386d33ffSBob King                        const std::string& expectedOutputMessage)
244386d33ffSBob King {
2450f6ebadeSShawn McCarney     TemporaryFile tmpFile;
2460f6ebadeSShawn McCarney     std::string fileName = tmpFile.getPath().string();
247a57e0814SBob King     writeDataToFile(configFileJson, fileName);
248386d33ffSBob King 
249386d33ffSBob King     EXPECT_FILE_INVALID(fileName, expectedErrorMessage, expectedOutputMessage);
250386d33ffSBob King }
251386d33ffSBob King 
expectCommandLineSyntax(const std::string & expectedErrorMessage,const std::string & expectedOutputMessage,const std::string & command,int status)252ed009655SBob King void expectCommandLineSyntax(const std::string& expectedErrorMessage,
253ed009655SBob King                              const std::string& expectedOutputMessage,
254525e20c9SShawn McCarney                              const std::string& command, int status)
255ed009655SBob King {
256ed009655SBob King     std::string errorMessage;
257ed009655SBob King     std::string outputMessage;
258a57e0814SBob King     EXPECT_EQ(runToolForOutputWithCommand(command, outputMessage, errorMessage),
259a57e0814SBob King               status);
260ed009655SBob King     EXPECT_EQ(errorMessage, expectedErrorMessage);
261ed009655SBob King     EXPECT_EQ(outputMessage, expectedOutputMessage);
262ed009655SBob King }
263ed009655SBob King 
TEST(ValidateRegulatorsConfigTest,Action)2643afa711dSBob King TEST(ValidateRegulatorsConfigTest, Action)
2653afa711dSBob King {
2663afa711dSBob King     // Valid: Comments property not specified
2673afa711dSBob King     {
2683afa711dSBob King         json configFile = validConfigFile;
2693afa711dSBob King         EXPECT_JSON_VALID(configFile);
2703afa711dSBob King     }
2713afa711dSBob King     // Valid: Comments property specified
2723afa711dSBob King     {
2733afa711dSBob King         json configFile = validConfigFile;
2743afa711dSBob King         configFile["rules"][0]["actions"][0]["comments"][0] =
2753afa711dSBob King             "Set VOUT_COMMAND";
2763afa711dSBob King         EXPECT_JSON_VALID(configFile);
2773afa711dSBob King     }
2783afa711dSBob King     // Valid: and action type specified
2793afa711dSBob King     {
2803afa711dSBob King         json configFile = validConfigFile;
2813afa711dSBob King         json andAction =
2823afa711dSBob King             R"(
2833afa711dSBob King                 {
2843afa711dSBob King                  "and": [
2853afa711dSBob King                     { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
2863afa711dSBob King                     { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
2873afa711dSBob King                   ]
2883afa711dSBob King                 }
2893afa711dSBob King             )"_json;
2903afa711dSBob King         configFile["rules"][0]["actions"].push_back(andAction);
2913afa711dSBob King         EXPECT_JSON_VALID(configFile);
2923afa711dSBob King     }
2933afa711dSBob King     // Valid: compare_presence action type specified
2943afa711dSBob King     {
2953afa711dSBob King         json configFile = validConfigFile;
2963afa711dSBob King         configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
297a76898f1SBob King             "system/chassis/motherboard/regulator2";
2983afa711dSBob King         configFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
2993afa711dSBob King             true;
3003afa711dSBob King         EXPECT_JSON_VALID(configFile);
3013afa711dSBob King     }
3023afa711dSBob King     // Valid: compare_vpd action type specified
3033afa711dSBob King     {
3043afa711dSBob King         json configFile = validConfigFile;
3053afa711dSBob King         configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
306a76898f1SBob King             "system/chassis/motherboard/regulator2";
3073afa711dSBob King         configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
3083afa711dSBob King         configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
3093afa711dSBob King         EXPECT_JSON_VALID(configFile);
3103afa711dSBob King     }
311846dde5dSShawn McCarney     // Valid: i2c_capture_bytes action type specified
312846dde5dSShawn McCarney     {
313846dde5dSShawn McCarney         json configFile = validConfigFile;
314846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
315846dde5dSShawn McCarney             "0xA0";
316846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] = 2;
317846dde5dSShawn McCarney         EXPECT_JSON_VALID(configFile);
318846dde5dSShawn McCarney     }
3193afa711dSBob King     // Valid: i2c_compare_bit action type specified
3203afa711dSBob King     {
3213afa711dSBob King         json configFile = validConfigFile;
3223afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
3233afa711dSBob King             "0xA0";
3243afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 3;
3253afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
3263afa711dSBob King         EXPECT_JSON_VALID(configFile);
3273afa711dSBob King     }
3283afa711dSBob King     // Valid: i2c_compare_byte action type specified
3293afa711dSBob King     {
3303afa711dSBob King         json configFile = validConfigFile;
3313afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
3323afa711dSBob King             "0x82";
3333afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
3343afa711dSBob King             "0x40";
3353afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
3363afa711dSBob King             "0x7F";
3373afa711dSBob King         EXPECT_JSON_VALID(configFile);
3383afa711dSBob King     }
3393afa711dSBob King     // Valid: i2c_compare_bytes action type specified
3403afa711dSBob King     {
3413afa711dSBob King         json configFile = validConfigFile;
3423afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
3433afa711dSBob King             "0x82";
3443afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = {
3453afa711dSBob King             "0x02", "0x73"};
3463afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = {
3473afa711dSBob King             "0x7F", "0x7F"};
3483afa711dSBob King         EXPECT_JSON_VALID(configFile);
3493afa711dSBob King     }
3503afa711dSBob King     // Valid: i2c_write_bit action type specified
3513afa711dSBob King     {
3523afa711dSBob King         json configFile = validConfigFile;
3533afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
3543afa711dSBob King             "0xA0";
3553afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3;
3563afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 1;
3573afa711dSBob King         EXPECT_JSON_VALID(configFile);
3583afa711dSBob King     }
3593afa711dSBob King     // Valid: i2c_write_byte action type specified
3603afa711dSBob King     {
3613afa711dSBob King         json configFile = validConfigFile;
3623afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
3633afa711dSBob King             "0x82";
3643afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
3653afa711dSBob King             "0x40";
3663afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0x7F";
3673afa711dSBob King         EXPECT_JSON_VALID(configFile);
3683afa711dSBob King     }
3693afa711dSBob King     // Valid: i2c_write_bytes action type specified
3703afa711dSBob King     {
3713afa711dSBob King         json configFile = validConfigFile;
3723afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
3733afa711dSBob King             "0x82";
3743afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
3753afa711dSBob King             "0x02", "0x73"};
3763afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
3773afa711dSBob King             "0x7F", "0x7F"};
3783afa711dSBob King         EXPECT_JSON_VALID(configFile);
3793afa711dSBob King     }
3803afa711dSBob King     // Valid: if action type specified
3813afa711dSBob King     {
3823afa711dSBob King         json configFile = validConfigFile;
383846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"]["condition"]["run_rule"] =
3843afa711dSBob King             "set_voltage_rule";
385846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"]["then"][0]["run_rule"] =
3863afa711dSBob King             "read_sensors_rule";
387846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"]["else"][0]["run_rule"] =
3883afa711dSBob King             "read_sensors_rule";
389846dde5dSShawn McCarney         configFile["rules"][4]["id"] = "rule_if";
390846dde5dSShawn McCarney         EXPECT_JSON_VALID(configFile);
391846dde5dSShawn McCarney     }
392846dde5dSShawn McCarney     // Valid: log_phase_fault action type specified
393846dde5dSShawn McCarney     {
394846dde5dSShawn McCarney         json configFile = validConfigFile;
395846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = "n+1";
3963afa711dSBob King         EXPECT_JSON_VALID(configFile);
3973afa711dSBob King     }
3983afa711dSBob King     // Valid: not action type specified
3993afa711dSBob King     {
4003afa711dSBob King         json configFile = validConfigFile;
4013afa711dSBob King         configFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]
4023afa711dSBob King                   ["register"] = "0xA0";
4033afa711dSBob King         configFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]
4043afa711dSBob King                   ["value"] = "0xFF";
4053afa711dSBob King         EXPECT_JSON_VALID(configFile);
4063afa711dSBob King     }
4073afa711dSBob King     // Valid: or action type specified
4083afa711dSBob King     {
4093afa711dSBob King         json configFile = validConfigFile;
4103afa711dSBob King         configFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]
4113afa711dSBob King                   ["register"] = "0xA0";
4123afa711dSBob King         configFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]
4133afa711dSBob King                   ["value"] = "0x00";
4143afa711dSBob King         configFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]
4153afa711dSBob King                   ["register"] = "0xA1";
4163afa711dSBob King         configFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]
4173afa711dSBob King                   ["value"] = "0x00";
4183afa711dSBob King         EXPECT_JSON_VALID(configFile);
4193afa711dSBob King     }
4203afa711dSBob King     // Valid: pmbus_read_sensor and pmbus_write_vout_command action type
4213afa711dSBob King     // specified
4223afa711dSBob King     {
4233afa711dSBob King         EXPECT_JSON_VALID(validConfigFile);
4243afa711dSBob King     }
4253afa711dSBob King     // Valid: run_rule action type specified
4263afa711dSBob King     {
4273afa711dSBob King         json configFile = validConfigFile;
4283afa711dSBob King         configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
4293afa711dSBob King         EXPECT_JSON_VALID(configFile);
4303afa711dSBob King     }
4313afa711dSBob King     // Valid: set_device action type specified
4323afa711dSBob King     {
4333afa711dSBob King         json configFile = validConfigFile;
4343afa711dSBob King         configFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator";
4353afa711dSBob King         EXPECT_JSON_VALID(configFile);
4363afa711dSBob King     }
4373afa711dSBob King     // Invalid: Wrong data type for comments (should be array of string)
4383afa711dSBob King     {
4393afa711dSBob King         json configFile = validConfigFile;
4403afa711dSBob King         configFile["rules"][0]["actions"][0]["comments"] = true;
4413afa711dSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
4423afa711dSBob King                             "True is not of type 'array'");
4433afa711dSBob King     }
4443afa711dSBob King     // Invalid: Wrong data type for action type (such as "i2c_write_byte": true)
4453afa711dSBob King     {
4463afa711dSBob King         json configFile = validConfigFile;
4473afa711dSBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"] = true;
4483afa711dSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
4493afa711dSBob King                             "True is not of type 'object'");
4503afa711dSBob King     }
4513afa711dSBob King     // Invalid: Empty comments array
4523afa711dSBob King     {
4533afa711dSBob King         json configFile = validConfigFile;
4543afa711dSBob King         configFile["rules"][0]["actions"][0]["comments"] = json::array();
4553afa711dSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
4563afa711dSBob King                             "[] is too short");
4573afa711dSBob King     }
4583afa711dSBob King     // Invalid: Comments array has wrong element type (should be string)
4593afa711dSBob King     {
4603afa711dSBob King         json configFile = validConfigFile;
4613afa711dSBob King         configFile["rules"][0]["actions"][0]["comments"][0] = true;
4623afa711dSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
4633afa711dSBob King                             "True is not of type 'string'");
4643afa711dSBob King     }
4653afa711dSBob King     // Invalid: No action type specified
4663afa711dSBob King     {
4673afa711dSBob King         json configFile = validConfigFile;
4683afa711dSBob King         configFile["rules"][0]["actions"][1]["comments"][0] =
4693afa711dSBob King             "Check if bit 3 is on";
4700a2b76bcSShawn McCarney         EXPECT_JSON_INVALID(
4710a2b76bcSShawn McCarney             configFile, "Validation failed.",
4720a2b76bcSShawn McCarney             "{'comments': ['Check if bit 3 is on']} is not valid under any of the given schemas");
4733afa711dSBob King     }
4743afa711dSBob King     // Invalid: Multiple action types specified (such as both 'compare_presence'
4753afa711dSBob King     // and 'pmbus_write_vout_command')
4763afa711dSBob King     {
4773afa711dSBob King         json configFile = validConfigFile;
4783afa711dSBob King         configFile["rules"][0]["actions"][0]["compare_presence"]["value"] =
4793afa711dSBob King             true;
4803afa711dSBob King         EXPECT_JSON_INVALID(
4813afa711dSBob King             configFile, "Validation failed.",
4823afa711dSBob King             "{'compare_presence': {'value': True}, 'pmbus_write_vout_command': "
4833afa711dSBob King             "{'format': 'linear'}} is valid under each of {'required': "
4843afa711dSBob King             "['pmbus_write_vout_command']}, {'required': "
4853afa711dSBob King             "['compare_presence']}");
4863afa711dSBob King     }
4873afa711dSBob King     // Invalid: Unexpected property specified (like 'foo')
4883afa711dSBob King     {
4893afa711dSBob King         json configFile = validConfigFile;
4903afa711dSBob King         configFile["rules"][0]["actions"][1]["foo"] = "foo";
4913afa711dSBob King         EXPECT_JSON_INVALID(
4923afa711dSBob King             configFile, "Validation failed.",
4933afa711dSBob King             "Additional properties are not allowed ('foo' was unexpected)");
4943afa711dSBob King     }
4953afa711dSBob King }
496846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,And)497beaf6532SBob King TEST(ValidateRegulatorsConfigTest, And)
498beaf6532SBob King {
499beaf6532SBob King     // Valid.
500beaf6532SBob King     {
501beaf6532SBob King         json configFile = validConfigFile;
502beaf6532SBob King         json andAction =
503beaf6532SBob King             R"(
504beaf6532SBob King                 {
505beaf6532SBob King                  "and": [
506beaf6532SBob King                     { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
507beaf6532SBob King                     { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
508beaf6532SBob King                   ]
509beaf6532SBob King                 }
510beaf6532SBob King             )"_json;
511beaf6532SBob King         configFile["rules"][0]["actions"].push_back(andAction);
512beaf6532SBob King         EXPECT_JSON_VALID(configFile);
513beaf6532SBob King     }
514beaf6532SBob King 
515beaf6532SBob King     // Invalid: actions property value is an empty array.
516beaf6532SBob King     {
517beaf6532SBob King         json configFile = validConfigFile;
518beaf6532SBob King         json andAction =
519beaf6532SBob King             R"(
520beaf6532SBob King                 {
521beaf6532SBob King                  "and": []
522beaf6532SBob King                 }
523beaf6532SBob King             )"_json;
524beaf6532SBob King         configFile["rules"][0]["actions"].push_back(andAction);
525beaf6532SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
526beaf6532SBob King                             "[] is too short");
527beaf6532SBob King     }
528beaf6532SBob King 
529beaf6532SBob King     // Invalid: actions property has incorrect value data type.
530beaf6532SBob King     {
531beaf6532SBob King         json configFile = validConfigFile;
532beaf6532SBob King         json andAction =
533beaf6532SBob King             R"(
534beaf6532SBob King                 {
535beaf6532SBob King                  "and": true
536beaf6532SBob King                 }
537beaf6532SBob King             )"_json;
538beaf6532SBob King         configFile["rules"][0]["actions"].push_back(andAction);
539beaf6532SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
540358c417aSBob King                             "True is not of type 'array'");
541beaf6532SBob King     }
542beaf6532SBob King 
543beaf6532SBob King     // Invalid: actions property value contains wrong element type
544beaf6532SBob King     {
545beaf6532SBob King         json configFile = validConfigFile;
546beaf6532SBob King         json andAction =
547beaf6532SBob King             R"(
548beaf6532SBob King                 {
549beaf6532SBob King                  "and": ["foo"]
550beaf6532SBob King                 }
551beaf6532SBob King             )"_json;
552beaf6532SBob King         configFile["rules"][0]["actions"].push_back(andAction);
553beaf6532SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
554358c417aSBob King                             "'foo' is not of type 'object'");
555beaf6532SBob King     }
556beaf6532SBob King }
557846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,Chassis)5583728f562SBob King TEST(ValidateRegulatorsConfigTest, Chassis)
5593728f562SBob King {
5603728f562SBob King     // Valid: test chassis.
5613728f562SBob King     {
5623728f562SBob King         json configFile = validConfigFile;
5633728f562SBob King         EXPECT_JSON_VALID(configFile);
5643728f562SBob King     }
565ecbeeea7SShawn McCarney     // Valid: test chassis with only required properties.
5663728f562SBob King     {
5673728f562SBob King         json configFile = validConfigFile;
5683728f562SBob King         configFile["chassis"][0].erase("comments");
5693728f562SBob King         configFile["chassis"][0].erase("devices");
5703728f562SBob King         EXPECT_JSON_VALID(configFile);
5713728f562SBob King     }
5723728f562SBob King     // Invalid: test chassis with no number.
5733728f562SBob King     {
5743728f562SBob King         json configFile = validConfigFile;
5753728f562SBob King         configFile["chassis"][0].erase("number");
5763728f562SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
577358c417aSBob King                             "'number' is a required property");
5783728f562SBob King     }
5794c88a4c2SShawn McCarney     // Invalid: test chassis with no inventory_path.
5804c88a4c2SShawn McCarney     {
5814c88a4c2SShawn McCarney         json configFile = validConfigFile;
5824c88a4c2SShawn McCarney         configFile["chassis"][0].erase("inventory_path");
5834c88a4c2SShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
5844c88a4c2SShawn McCarney                             "'inventory_path' is a required property");
5854c88a4c2SShawn McCarney     }
5863728f562SBob King     // Invalid: test chassis with property comments wrong type.
5873728f562SBob King     {
5883728f562SBob King         json configFile = validConfigFile;
5893728f562SBob King         configFile["chassis"][0]["comments"] = true;
5903728f562SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
591358c417aSBob King                             "True is not of type 'array'");
5923728f562SBob King     }
5933728f562SBob King     // Invalid: test chassis with property number wrong type.
5943728f562SBob King     {
5953728f562SBob King         json configFile = validConfigFile;
5963728f562SBob King         configFile["chassis"][0]["number"] = 1.3;
5973728f562SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
598358c417aSBob King                             "1.3 is not of type 'integer'");
5993728f562SBob King     }
600ecbeeea7SShawn McCarney     // Invalid: test chassis with property inventory_path wrong type.
601ecbeeea7SShawn McCarney     {
602ecbeeea7SShawn McCarney         json configFile = validConfigFile;
603ecbeeea7SShawn McCarney         configFile["chassis"][0]["inventory_path"] = 2;
604ecbeeea7SShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
605ecbeeea7SShawn McCarney                             "2 is not of type 'string'");
606ecbeeea7SShawn McCarney     }
6073728f562SBob King     // Invalid: test chassis with property devices wrong type.
6083728f562SBob King     {
6093728f562SBob King         json configFile = validConfigFile;
6103728f562SBob King         configFile["chassis"][0]["devices"] = true;
6113728f562SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
612358c417aSBob King                             "True is not of type 'array'");
6133728f562SBob King     }
6143728f562SBob King     // Invalid: test chassis with property comments empty array.
6153728f562SBob King     {
6163728f562SBob King         json configFile = validConfigFile;
6173728f562SBob King         configFile["chassis"][0]["comments"] = json::array();
6183728f562SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
6193728f562SBob King                             "[] is too short");
6203728f562SBob King     }
6213728f562SBob King     // Invalid: test chassis with property devices empty array.
6223728f562SBob King     {
6233728f562SBob King         json configFile = validConfigFile;
6243728f562SBob King         configFile["chassis"][0]["devices"] = json::array();
6253728f562SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
6263728f562SBob King                             "[] is too short");
6273728f562SBob King     }
6283728f562SBob King     // Invalid: test chassis with property number less than 1.
6293728f562SBob King     {
6303728f562SBob King         json configFile = validConfigFile;
6313728f562SBob King         configFile["chassis"][0]["number"] = 0;
6323728f562SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
6333728f562SBob King                             "0 is less than the minimum of 1");
6343728f562SBob King     }
635ecbeeea7SShawn McCarney     // Invalid: test chassis with property inventory_path empty string.
636ecbeeea7SShawn McCarney     {
637ecbeeea7SShawn McCarney         json configFile = validConfigFile;
638ecbeeea7SShawn McCarney         configFile["chassis"][0]["inventory_path"] = "";
639ecbeeea7SShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
640ecbeeea7SShawn McCarney                             "'' is too short");
641ecbeeea7SShawn McCarney     }
6423728f562SBob King }
643846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,ComparePresence)644bf1cbeaaSBob King TEST(ValidateRegulatorsConfigTest, ComparePresence)
645bf1cbeaaSBob King {
646bf1cbeaaSBob King     json comparePresenceFile = validConfigFile;
647bf1cbeaaSBob King     comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
648a76898f1SBob King         "system/chassis/motherboard/regulator2";
649bf1cbeaaSBob King     comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
650bf1cbeaaSBob King         true;
651bf1cbeaaSBob King     // Valid.
652bf1cbeaaSBob King     {
653bf1cbeaaSBob King         json configFile = comparePresenceFile;
654bf1cbeaaSBob King         EXPECT_JSON_VALID(configFile);
655bf1cbeaaSBob King     }
656bf1cbeaaSBob King 
657bf1cbeaaSBob King     // Invalid: no FRU property.
658bf1cbeaaSBob King     {
659bf1cbeaaSBob King         json configFile = comparePresenceFile;
660bf1cbeaaSBob King         configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru");
661bf1cbeaaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
662358c417aSBob King                             "'fru' is a required property");
663bf1cbeaaSBob King     }
664bf1cbeaaSBob King 
665bf1cbeaaSBob King     // Invalid: FRU property length is string less than 1.
666bf1cbeaaSBob King     {
667bf1cbeaaSBob King         json configFile = comparePresenceFile;
668bf1cbeaaSBob King         configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = "";
669bf1cbeaaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
670358c417aSBob King                             "'' is too short");
671bf1cbeaaSBob King     }
672bf1cbeaaSBob King 
673bf1cbeaaSBob King     // Invalid: no value property.
674bf1cbeaaSBob King     {
675bf1cbeaaSBob King         json configFile = comparePresenceFile;
676bf1cbeaaSBob King         configFile["rules"][0]["actions"][1]["compare_presence"].erase("value");
677bf1cbeaaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
678358c417aSBob King                             "'value' is a required property");
679bf1cbeaaSBob King     }
680bf1cbeaaSBob King 
681bf1cbeaaSBob King     // Invalid: value property type is not boolean.
682bf1cbeaaSBob King     {
683bf1cbeaaSBob King         json configFile = comparePresenceFile;
684bf1cbeaaSBob King         configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1";
685bf1cbeaaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
686358c417aSBob King                             "'1' is not of type 'boolean'");
687bf1cbeaaSBob King     }
688bf1cbeaaSBob King 
689bf1cbeaaSBob King     // Invalid: FRU property type is not string.
690bf1cbeaaSBob King     {
691bf1cbeaaSBob King         json configFile = comparePresenceFile;
692bf1cbeaaSBob King         configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1;
693bf1cbeaaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
694358c417aSBob King                             "1 is not of type 'string'");
695bf1cbeaaSBob King     }
696bf1cbeaaSBob King }
697846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,CompareVpd)698f8b77a02SBob King TEST(ValidateRegulatorsConfigTest, CompareVpd)
699f8b77a02SBob King {
700f8b77a02SBob King     json compareVpdFile = validConfigFile;
701f8b77a02SBob King     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
702a76898f1SBob King         "system/chassis/motherboard/regulator2";
703f8b77a02SBob King     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
704f8b77a02SBob King     compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
705f8b77a02SBob King 
706a2a830b1SShawn McCarney     // Valid: value property: not empty.
707f8b77a02SBob King     {
708f8b77a02SBob King         json configFile = compareVpdFile;
709f8b77a02SBob King         EXPECT_JSON_VALID(configFile);
710f8b77a02SBob King     }
711a2a830b1SShawn McCarney 
712a2a830b1SShawn McCarney     // Valid: value property: empty.
713a2a830b1SShawn McCarney     {
714a2a830b1SShawn McCarney         json configFile = compareVpdFile;
715a2a830b1SShawn McCarney         configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "";
716a2a830b1SShawn McCarney         EXPECT_JSON_VALID(configFile);
717a2a830b1SShawn McCarney     }
718a2a830b1SShawn McCarney 
719a2a830b1SShawn McCarney     // Valid: byte_values property: not empty.
720aacc2aafSMatt Spinler     {
721aacc2aafSMatt Spinler         json configFile = compareVpdFile;
722aacc2aafSMatt Spinler         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
723aacc2aafSMatt Spinler         configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] = {
724aacc2aafSMatt Spinler             "0x01", "0x02"};
725aacc2aafSMatt Spinler         EXPECT_JSON_VALID(configFile);
726aacc2aafSMatt Spinler     }
727f8b77a02SBob King 
728a2a830b1SShawn McCarney     // Valid: byte_values property: empty.
729a2a830b1SShawn McCarney     {
730a2a830b1SShawn McCarney         json configFile = compareVpdFile;
731a2a830b1SShawn McCarney         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
732a2a830b1SShawn McCarney         configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] =
733a2a830b1SShawn McCarney             json::array();
734a2a830b1SShawn McCarney         EXPECT_JSON_VALID(configFile);
735a2a830b1SShawn McCarney     }
736a2a830b1SShawn McCarney 
737f8b77a02SBob King     // Invalid: no FRU property.
738f8b77a02SBob King     {
739f8b77a02SBob King         json configFile = compareVpdFile;
740f8b77a02SBob King         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru");
741f8b77a02SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
742358c417aSBob King                             "'fru' is a required property");
743f8b77a02SBob King     }
744f8b77a02SBob King 
745f8b77a02SBob King     // Invalid: no keyword property.
746f8b77a02SBob King     {
747f8b77a02SBob King         json configFile = compareVpdFile;
748f8b77a02SBob King         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword");
749f8b77a02SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
750358c417aSBob King                             "'keyword' is a required property");
751f8b77a02SBob King     }
752f8b77a02SBob King 
753f8b77a02SBob King     // Invalid: no value property.
754f8b77a02SBob King     {
755f8b77a02SBob King         json configFile = compareVpdFile;
756f8b77a02SBob King         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
7570a2b76bcSShawn McCarney         EXPECT_JSON_INVALID(
7580a2b76bcSShawn McCarney             configFile, "Validation failed.",
7590a2b76bcSShawn McCarney             "{'fru': 'system/chassis/motherboard/regulator2', 'keyword': 'CCIN'} is not valid under any of the given schemas");
760f8b77a02SBob King     }
761f8b77a02SBob King 
762f8b77a02SBob King     // Invalid: property FRU wrong type.
763f8b77a02SBob King     {
764f8b77a02SBob King         json configFile = compareVpdFile;
765f8b77a02SBob King         configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1;
766f8b77a02SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
767358c417aSBob King                             "1 is not of type 'string'");
768f8b77a02SBob King     }
769f8b77a02SBob King 
770f8b77a02SBob King     // Invalid: property FRU is string less than 1.
771f8b77a02SBob King     {
772f8b77a02SBob King         json configFile = compareVpdFile;
773f8b77a02SBob King         configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = "";
774f8b77a02SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
775358c417aSBob King                             "'' is too short");
776f8b77a02SBob King     }
777f8b77a02SBob King 
778f8b77a02SBob King     // Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
779aacc2aafSMatt Spinler     // "PartNumber", "HW"
780f8b77a02SBob King     {
781f8b77a02SBob King         json configFile = compareVpdFile;
782f8b77a02SBob King         configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
783f8b77a02SBob King             "Number";
784f8b77a02SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
785358c417aSBob King                             "'Number' is not one of ['CCIN', "
786aacc2aafSMatt Spinler                             "'Manufacturer', 'Model', 'PartNumber', 'HW']");
787f8b77a02SBob King     }
788f8b77a02SBob King 
789f8b77a02SBob King     // Invalid: property value wrong type.
790f8b77a02SBob King     {
791f8b77a02SBob King         json configFile = compareVpdFile;
792f8b77a02SBob King         configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1;
793f8b77a02SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
794358c417aSBob King                             "1 is not of type 'string'");
795f8b77a02SBob King     }
796aacc2aafSMatt Spinler 
797aacc2aafSMatt Spinler     // Invalid: property byte_values has wrong type
798aacc2aafSMatt Spinler     {
799aacc2aafSMatt Spinler         json configFile = compareVpdFile;
800aacc2aafSMatt Spinler         configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
801aacc2aafSMatt Spinler         configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] =
802aacc2aafSMatt Spinler             "0x50";
803aacc2aafSMatt Spinler         EXPECT_JSON_INVALID(configFile, "Validation failed.",
804aacc2aafSMatt Spinler                             "'0x50' is not of type 'array'");
805aacc2aafSMatt Spinler     }
806aacc2aafSMatt Spinler 
807aacc2aafSMatt Spinler     // Invalid: properties byte_values and value both exist
808aacc2aafSMatt Spinler     {
809aacc2aafSMatt Spinler         json configFile = compareVpdFile;
810aacc2aafSMatt Spinler         configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] = {
811aacc2aafSMatt Spinler             "0x01", "0x02"};
812aacc2aafSMatt Spinler         EXPECT_JSON_INVALID(
813aacc2aafSMatt Spinler             configFile, "Validation failed.",
814aacc2aafSMatt Spinler             "{'byte_values': ['0x01', '0x02'], 'fru': "
815aacc2aafSMatt Spinler             "'system/chassis/motherboard/regulator2', 'keyword': 'CCIN', "
816aacc2aafSMatt Spinler             "'value': '2D35'} is valid under each of {'required': "
817aacc2aafSMatt Spinler             "['byte_values']}, {'required': ['value']}");
818aacc2aafSMatt Spinler     }
819f8b77a02SBob King }
820846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,ConfigFile)82120057416SBob King TEST(ValidateRegulatorsConfigTest, ConfigFile)
82220057416SBob King {
82320057416SBob King     // Valid: Only required properties specified
82420057416SBob King     {
82520057416SBob King         json configFile;
82620057416SBob King         configFile["chassis"][0]["number"] = 1;
8274c88a4c2SShawn McCarney         configFile["chassis"][0]["inventory_path"] = "system/chassis";
82820057416SBob King         EXPECT_JSON_VALID(configFile);
82920057416SBob King     }
83020057416SBob King     // Valid: All properties specified
83120057416SBob King     {
83220057416SBob King         json configFile = validConfigFile;
83320057416SBob King         EXPECT_JSON_VALID(configFile);
83420057416SBob King     }
83520057416SBob King     // Invalid: Required chassis property not specified
83620057416SBob King     {
83720057416SBob King         json configFile = validConfigFile;
83820057416SBob King         configFile.erase("chassis");
83920057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
84020057416SBob King                             "'chassis' is a required property");
84120057416SBob King     }
84220057416SBob King     // Invalid: Wrong data type for comments
84320057416SBob King     {
84420057416SBob King         json configFile = validConfigFile;
84520057416SBob King         configFile["comments"] = true;
84620057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
84720057416SBob King                             "True is not of type 'array'");
84820057416SBob King     }
84920057416SBob King     // Invalid: Wrong data type for rules
85020057416SBob King     {
85120057416SBob King         json configFile = validConfigFile;
85220057416SBob King         configFile["rules"] = true;
85320057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
85420057416SBob King                             "True is not of type 'array'");
85520057416SBob King     }
85620057416SBob King     // Invalid: Wrong data type for chassis
85720057416SBob King     {
85820057416SBob King         json configFile = validConfigFile;
85920057416SBob King         configFile["chassis"] = true;
86020057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
86120057416SBob King                             "True is not of type 'array'");
86220057416SBob King     }
86320057416SBob King     // Invalid: Empty comments array;
86420057416SBob King     {
86520057416SBob King         json configFile = validConfigFile;
86620057416SBob King         configFile["comments"] = json::array();
86720057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
86820057416SBob King                             "[] is too short");
86920057416SBob King     }
87020057416SBob King     // Invalid: Empty rules array
87120057416SBob King     {
87220057416SBob King         json configFile = validConfigFile;
87320057416SBob King         configFile["rules"] = json::array();
87420057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
87520057416SBob King                             "[] is too short");
87620057416SBob King     }
87720057416SBob King     // Invalid: Empty chassis array
87820057416SBob King     {
87920057416SBob King         json configFile = validConfigFile;
88020057416SBob King         configFile["chassis"] = json::array();
88120057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
88220057416SBob King                             "[] is too short");
88320057416SBob King     }
88420057416SBob King     // Invalid: Comments array has wrong element type (should be string)
88520057416SBob King     {
88620057416SBob King         json configFile = validConfigFile;
88720057416SBob King         configFile["comments"][0] = true;
88820057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
88920057416SBob King                             "True is not of type 'string'");
89020057416SBob King     }
89120057416SBob King     // Invalid: Rules array has wrong element type (should be rule)
89220057416SBob King     {
89320057416SBob King         json configFile = validConfigFile;
89420057416SBob King         configFile["rules"][0] = true;
89520057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
89620057416SBob King                             "True is not of type 'object'");
89720057416SBob King     }
89820057416SBob King     // Invalid: Chassis array has wrong element type (should be chassis)
89920057416SBob King     {
90020057416SBob King         json configFile = validConfigFile;
90120057416SBob King         configFile["chassis"][0] = true;
90220057416SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
90320057416SBob King                             "True is not of type 'object'");
90420057416SBob King     }
90520057416SBob King     // Invalid: Unexpected property specified
90620057416SBob King     {
90720057416SBob King         json configFile = validConfigFile;
90820057416SBob King         configFile["foo"] = json::array();
90920057416SBob King         EXPECT_JSON_INVALID(
91020057416SBob King             configFile, "Validation failed.",
91120057416SBob King             "Additional properties are not allowed ('foo' was unexpected)");
91220057416SBob King     }
91320057416SBob King }
914846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,Configuration)9154c67a3a0SBob King TEST(ValidateRegulatorsConfigTest, Configuration)
9164c67a3a0SBob King {
9174c67a3a0SBob King     json configurationFile = validConfigFile;
9184c67a3a0SBob King     configurationFile["chassis"][0]["devices"][0]["configuration"]["comments"]
9194c67a3a0SBob King                      [0] = "Set rail to 1.25V using standard rule";
9204c67a3a0SBob King     configurationFile["chassis"][0]["devices"][0]["configuration"]["volts"] =
9214c67a3a0SBob King         1.25;
9224c67a3a0SBob King     configurationFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
9234c67a3a0SBob King         "set_voltage_rule";
9244c67a3a0SBob King     // Valid: test configuration with property rule_id and with no actions.
9254c67a3a0SBob King     {
9264c67a3a0SBob King         json configFile = configurationFile;
92778793106SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["comments"][1] =
92878793106SBob King             "test multiple array elements in comments.";
9294c67a3a0SBob King         EXPECT_JSON_VALID(configFile);
9304c67a3a0SBob King     }
9314c67a3a0SBob King     // Valid: test configuration with property actions and with no rule_id.
9324c67a3a0SBob King     {
9334c67a3a0SBob King         json configFile = configurationFile;
9344c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"].erase(
9354c67a3a0SBob King             "rule_id");
9364c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
9374c67a3a0SBob King                   ["compare_presence"]["fru"] =
938a76898f1SBob King                       "system/chassis/motherboard/cpu3";
9394c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
9404c67a3a0SBob King                   ["compare_presence"]["value"] = true;
9414c67a3a0SBob King         EXPECT_JSON_VALID(configFile);
9424c67a3a0SBob King     }
9434c67a3a0SBob King     // Valid: comments not specified (optional property).
9444c67a3a0SBob King     {
9454c67a3a0SBob King         json configFile = configurationFile;
9464c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"].erase(
9474c67a3a0SBob King             "comments");
9484c67a3a0SBob King         EXPECT_JSON_VALID(configFile);
9494c67a3a0SBob King     }
9504c67a3a0SBob King     // Valid: volts not specified (optional property).
9514c67a3a0SBob King     {
9524c67a3a0SBob King         json configFile = configurationFile;
9534c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"].erase("volts");
9544c67a3a0SBob King         EXPECT_JSON_VALID(configFile);
9554c67a3a0SBob King     }
9564c67a3a0SBob King     // Valid: configuration is property of a rail (vs. a device).
9574c67a3a0SBob King     {
9584c67a3a0SBob King         json configFile = validConfigFile;
9594c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
9604c67a3a0SBob King                   ["comments"][0] = "Set rail to 1.25V using standard rule";
9614c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
9624c67a3a0SBob King                   ["volts"] = 1.25;
9634c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
9644c67a3a0SBob King                   ["rule_id"] = "set_voltage_rule";
9654c67a3a0SBob King         EXPECT_JSON_VALID(configFile);
9664c67a3a0SBob King     }
9674c67a3a0SBob King     // Invalid: comments property has wrong data type (not an array).
9684c67a3a0SBob King     {
9694c67a3a0SBob King         json configFile = configurationFile;
9704c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["comments"] = 1;
9714c67a3a0SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
972358c417aSBob King                             "1 is not of type 'array'");
9734c67a3a0SBob King     }
9744c67a3a0SBob King     // Invalid: test configuration with both actions and rule_id properties.
9754c67a3a0SBob King     {
9764c67a3a0SBob King         json configFile = configurationFile;
9774c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
9784c67a3a0SBob King                   ["compare_presence"]["fru"] =
979a76898f1SBob King                       "system/chassis/motherboard/cpu3";
9804c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
9814c67a3a0SBob King                   ["compare_presence"]["value"] = true;
982846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
9834c67a3a0SBob King     }
9844c67a3a0SBob King     // Invalid: test configuration with no rule_id and actions.
9854c67a3a0SBob King     {
9864c67a3a0SBob King         json configFile = configurationFile;
9874c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"].erase(
9884c67a3a0SBob King             "rule_id");
9890a2b76bcSShawn McCarney         EXPECT_JSON_INVALID(
9900a2b76bcSShawn McCarney             configFile, "Validation failed.",
9910a2b76bcSShawn McCarney             "{'comments': ['Set rail to 1.25V using standard rule'], 'volts': 1.25} is not valid under any of the given schemas");
9924c67a3a0SBob King     }
9934c67a3a0SBob King     // Invalid: test configuration with property volts wrong type.
9944c67a3a0SBob King     {
9954c67a3a0SBob King         json configFile = configurationFile;
9964c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["volts"] = true;
9974c67a3a0SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
998358c417aSBob King                             "True is not of type 'number'");
9994c67a3a0SBob King     }
10004c67a3a0SBob King     // Invalid: test configuration with property rule_id wrong type.
10014c67a3a0SBob King     {
10024c67a3a0SBob King         json configFile = configurationFile;
10034c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
10044c67a3a0SBob King             true;
10054c67a3a0SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1006358c417aSBob King                             "True is not of type 'string'");
10074c67a3a0SBob King     }
10084c67a3a0SBob King     // Invalid: test configuration with property actions wrong type.
10094c67a3a0SBob King     {
10104c67a3a0SBob King         json configFile = configurationFile;
10114c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"].erase(
10124c67a3a0SBob King             "rule_id");
10134c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
10144c67a3a0SBob King             true;
10154c67a3a0SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1016358c417aSBob King                             "True is not of type 'array'");
10174c67a3a0SBob King     }
10184c67a3a0SBob King     // Invalid: test configuration with property comments empty array.
10194c67a3a0SBob King     {
10204c67a3a0SBob King         json configFile = configurationFile;
10214c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["comments"] =
10224c67a3a0SBob King             json::array();
10234c67a3a0SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
10244c67a3a0SBob King                             "[] is too short");
10254c67a3a0SBob King     }
10264c67a3a0SBob King     // Invalid: test configuration with property rule_id wrong format.
10274c67a3a0SBob King     {
10284c67a3a0SBob King         json configFile = configurationFile;
10294c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
10304c67a3a0SBob King             "id!";
10314c67a3a0SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1032358c417aSBob King                             "'id!' does not match '^[A-Za-z0-9_]+$'");
10334c67a3a0SBob King     }
10344c67a3a0SBob King     // Invalid: test configuration with property actions empty array.
10354c67a3a0SBob King     {
10364c67a3a0SBob King         json configFile = configurationFile;
10374c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"].erase(
10384c67a3a0SBob King             "rule_id");
10394c67a3a0SBob King         configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
10404c67a3a0SBob King             json::array();
10414c67a3a0SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
10424c67a3a0SBob King                             "[] is too short");
10434c67a3a0SBob King     }
10444c67a3a0SBob King }
1045846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,Device)1046a2ba2dfbSBob King TEST(ValidateRegulatorsConfigTest, Device)
1047a2ba2dfbSBob King {
1048a2ba2dfbSBob King     // Valid: test devices.
1049a2ba2dfbSBob King     {
1050a2ba2dfbSBob King         json configFile = validConfigFile;
1051a2ba2dfbSBob King         EXPECT_JSON_VALID(configFile);
1052a2ba2dfbSBob King     }
1053a2ba2dfbSBob King     // Valid: test devices with required properties.
1054a2ba2dfbSBob King     {
1055a2ba2dfbSBob King         json configFile = validConfigFile;
1056a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0].erase("comments");
1057a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0].erase("presence_detection");
1058a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0].erase("configuration");
1059846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0].erase("phase_fault_detection");
1060a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0].erase("rails");
1061a2ba2dfbSBob King         EXPECT_JSON_VALID(configFile);
1062a2ba2dfbSBob King     }
1063a2ba2dfbSBob King     // Invalid: test devices with no id.
1064a2ba2dfbSBob King     {
1065a2ba2dfbSBob King         json configFile = validConfigFile;
1066a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0].erase("id");
1067a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1068358c417aSBob King                             "'id' is a required property");
1069a2ba2dfbSBob King     }
1070a2ba2dfbSBob King     // Invalid: test devices with no is_regulator.
1071a2ba2dfbSBob King     {
1072a2ba2dfbSBob King         json configFile = validConfigFile;
1073a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0].erase("is_regulator");
10740a2b76bcSShawn McCarney         EXPECT_JSON_INVALID(
10750a2b76bcSShawn McCarney             configFile, "Validation failed.",
10760a2b76bcSShawn McCarney             "{'comments': ['IR35221 regulator producing the Vdd rail'], 'fru': 'system/chassis/motherboard/regulator1', 'i2c_interface': {'address': '0x70', 'bus': 1}, 'id': 'vdd_regulator', 'rails': [{'comments': ['Vdd rail'], 'configuration': {'rule_id': 'set_voltage_rule', 'volts': 1.03}, 'id': 'vdd', 'sensor_monitoring': {'rule_id': 'read_sensors_rule'}}]} should not be valid under {'anyOf': [{'required': ['phase_fault_detection']}, {'required': ['rails']}]}");
1077a2ba2dfbSBob King     }
1078a2ba2dfbSBob King     // Invalid: test devices with no fru.
1079a2ba2dfbSBob King     {
1080a2ba2dfbSBob King         json configFile = validConfigFile;
1081a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0].erase("fru");
1082a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1083358c417aSBob King                             "'fru' is a required property");
1084a2ba2dfbSBob King     }
1085a2ba2dfbSBob King     // Invalid: test devices with no i2c_interface.
1086a2ba2dfbSBob King     {
1087a2ba2dfbSBob King         json configFile = validConfigFile;
1088a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0].erase("i2c_interface");
1089a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1090358c417aSBob King                             "'i2c_interface' is a required property");
1091a2ba2dfbSBob King     }
1092846dde5dSShawn McCarney     // Invalid: is_regulator=false: phase_fault_detection specified
1093846dde5dSShawn McCarney     {
1094846dde5dSShawn McCarney         json configFile = validConfigFile;
1095846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["is_regulator"] = false;
1096846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0].erase("rails");
1097846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
1098846dde5dSShawn McCarney                   ["rule_id"] = "detect_phase_faults_rule";
1099846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
1100846dde5dSShawn McCarney     }
1101846dde5dSShawn McCarney     // Invalid: is_regulator=false: rails specified
1102846dde5dSShawn McCarney     {
1103846dde5dSShawn McCarney         json configFile = validConfigFile;
1104846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["is_regulator"] = false;
1105846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
1106846dde5dSShawn McCarney     }
1107846dde5dSShawn McCarney     // Invalid: is_regulator=false: phase_fault_detection and rails specified
1108846dde5dSShawn McCarney     {
1109846dde5dSShawn McCarney         json configFile = validConfigFile;
1110846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["is_regulator"] = false;
1111846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
1112846dde5dSShawn McCarney                   ["rule_id"] = "detect_phase_faults_rule";
1113846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
1114846dde5dSShawn McCarney     }
1115a2ba2dfbSBob King     // Invalid: test devices with property comments wrong type.
1116a2ba2dfbSBob King     {
1117a2ba2dfbSBob King         json configFile = validConfigFile;
1118a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["comments"] = true;
1119a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1120358c417aSBob King                             "True is not of type 'array'");
1121a2ba2dfbSBob King     }
1122a2ba2dfbSBob King     // Invalid: test devices with property id wrong type.
1123a2ba2dfbSBob King     {
1124a2ba2dfbSBob King         json configFile = validConfigFile;
1125a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["id"] = true;
1126a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1127358c417aSBob King                             "True is not of type 'string'");
1128a2ba2dfbSBob King     }
1129a2ba2dfbSBob King     // Invalid: test devices with property is_regulator wrong type.
1130a2ba2dfbSBob King     {
1131a2ba2dfbSBob King         json configFile = validConfigFile;
1132a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["is_regulator"] = 1;
1133a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1134358c417aSBob King                             "1 is not of type 'boolean'");
1135a2ba2dfbSBob King     }
1136a2ba2dfbSBob King     // Invalid: test devices with property fru wrong type.
1137a2ba2dfbSBob King     {
1138a2ba2dfbSBob King         json configFile = validConfigFile;
1139a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["fru"] = true;
1140a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1141358c417aSBob King                             "True is not of type 'string'");
1142a2ba2dfbSBob King     }
1143a2ba2dfbSBob King     // Invalid: test devices with property i2c_interface wrong type.
1144a2ba2dfbSBob King     {
1145a2ba2dfbSBob King         json configFile = validConfigFile;
1146a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["i2c_interface"] = true;
1147a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1148358c417aSBob King                             "True is not of type 'object'");
1149a2ba2dfbSBob King     }
1150a2ba2dfbSBob King     // Invalid: test devices with property presence_detection wrong
1151a2ba2dfbSBob King     // type.
1152a2ba2dfbSBob King     {
1153a2ba2dfbSBob King         json configFile = validConfigFile;
1154a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"] = true;
1155a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1156358c417aSBob King                             "True is not of type 'object'");
1157a2ba2dfbSBob King     }
1158a2ba2dfbSBob King     // Invalid: test devices with property configuration wrong type.
1159a2ba2dfbSBob King     {
1160a2ba2dfbSBob King         json configFile = validConfigFile;
1161a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["configuration"] = true;
1162a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1163358c417aSBob King                             "True is not of type 'object'");
1164a2ba2dfbSBob King     }
1165846dde5dSShawn McCarney     // Invalid: test devices with property phase_fault_detection wrong type.
1166846dde5dSShawn McCarney     {
1167846dde5dSShawn McCarney         json configFile = validConfigFile;
1168846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"] = true;
1169846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1170846dde5dSShawn McCarney                             "True is not of type 'object'");
1171846dde5dSShawn McCarney     }
1172a2ba2dfbSBob King     // Invalid: test devices with property rails wrong type.
1173a2ba2dfbSBob King     {
1174a2ba2dfbSBob King         json configFile = validConfigFile;
1175a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["rails"] = true;
1176a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1177358c417aSBob King                             "True is not of type 'array'");
1178a2ba2dfbSBob King     }
1179a2ba2dfbSBob King     // Invalid: test devices with property comments empty array.
1180a2ba2dfbSBob King     {
1181a2ba2dfbSBob King         json configFile = validConfigFile;
1182a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["comments"] = json::array();
1183a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1184a2ba2dfbSBob King                             "[] is too short");
1185a2ba2dfbSBob King     }
1186a2ba2dfbSBob King     // Invalid: test devices with property fru length less than 1.
1187a2ba2dfbSBob King     {
1188a2ba2dfbSBob King         json configFile = validConfigFile;
1189a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["fru"] = "";
1190a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1191358c417aSBob King                             "'' is too short");
1192a2ba2dfbSBob King     }
1193a2ba2dfbSBob King     // Invalid: test devices with property id wrong format.
1194a2ba2dfbSBob King     {
1195a2ba2dfbSBob King         json configFile = validConfigFile;
1196a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["id"] = "id#";
1197a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1198358c417aSBob King                             "'id#' does not match '^[A-Za-z0-9_]+$'");
1199a2ba2dfbSBob King     }
1200a2ba2dfbSBob King     // Invalid: test devices with property rails empty array.
1201a2ba2dfbSBob King     {
1202a2ba2dfbSBob King         json configFile = validConfigFile;
1203a2ba2dfbSBob King         configFile["chassis"][0]["devices"][0]["rails"] = json::array();
1204a2ba2dfbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1205a2ba2dfbSBob King                             "[] is too short");
1206a2ba2dfbSBob King     }
1207a2ba2dfbSBob King }
1208846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,I2CCaptureBytes)1209846dde5dSShawn McCarney TEST(ValidateRegulatorsConfigTest, I2CCaptureBytes)
1210846dde5dSShawn McCarney {
1211846dde5dSShawn McCarney     json initialFile = validConfigFile;
1212846dde5dSShawn McCarney     initialFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
1213846dde5dSShawn McCarney         "0xA0";
1214846dde5dSShawn McCarney     initialFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] = 2;
1215846dde5dSShawn McCarney 
1216846dde5dSShawn McCarney     // Valid: All required properties
1217846dde5dSShawn McCarney     {
1218846dde5dSShawn McCarney         json configFile = initialFile;
1219846dde5dSShawn McCarney         EXPECT_JSON_VALID(configFile);
1220846dde5dSShawn McCarney     }
1221846dde5dSShawn McCarney 
1222846dde5dSShawn McCarney     // Invalid: register not specified
1223846dde5dSShawn McCarney     {
1224846dde5dSShawn McCarney         json configFile = initialFile;
1225846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["i2c_capture_bytes"].erase(
1226846dde5dSShawn McCarney             "register");
1227846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1228846dde5dSShawn McCarney                             "'register' is a required property");
1229846dde5dSShawn McCarney     }
1230846dde5dSShawn McCarney 
1231846dde5dSShawn McCarney     // Invalid: count not specified
1232846dde5dSShawn McCarney     {
1233846dde5dSShawn McCarney         json configFile = initialFile;
1234846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["i2c_capture_bytes"].erase(
1235846dde5dSShawn McCarney             "count");
1236846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1237846dde5dSShawn McCarney                             "'count' is a required property");
1238846dde5dSShawn McCarney     }
1239846dde5dSShawn McCarney 
1240846dde5dSShawn McCarney     // Invalid: invalid property specified
1241846dde5dSShawn McCarney     {
1242846dde5dSShawn McCarney         json configFile = initialFile;
1243846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["foo"] = true;
1244846dde5dSShawn McCarney         EXPECT_JSON_INVALID(
1245846dde5dSShawn McCarney             configFile, "Validation failed.",
1246846dde5dSShawn McCarney             "Additional properties are not allowed ('foo' was unexpected)");
1247846dde5dSShawn McCarney     }
1248846dde5dSShawn McCarney 
1249846dde5dSShawn McCarney     // Invalid: register has wrong data type
1250846dde5dSShawn McCarney     {
1251846dde5dSShawn McCarney         json configFile = initialFile;
1252846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
1253846dde5dSShawn McCarney             1;
1254846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1255846dde5dSShawn McCarney                             "1 is not of type 'string'");
1256846dde5dSShawn McCarney     }
1257846dde5dSShawn McCarney 
1258846dde5dSShawn McCarney     // Invalid: register has wrong format
1259846dde5dSShawn McCarney     {
1260846dde5dSShawn McCarney         json configFile = initialFile;
1261846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
1262846dde5dSShawn McCarney             "0xA00";
1263846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1264846dde5dSShawn McCarney                             "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
1265846dde5dSShawn McCarney     }
1266846dde5dSShawn McCarney 
1267846dde5dSShawn McCarney     // Invalid: count has wrong data type
1268846dde5dSShawn McCarney     {
1269846dde5dSShawn McCarney         json configFile = initialFile;
1270846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] =
1271846dde5dSShawn McCarney             3.1;
1272846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1273846dde5dSShawn McCarney                             "3.1 is not of type 'integer'");
1274846dde5dSShawn McCarney     }
1275846dde5dSShawn McCarney 
1276846dde5dSShawn McCarney     // Invalid: count < 1
1277846dde5dSShawn McCarney     {
1278846dde5dSShawn McCarney         json configFile = initialFile;
1279846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] = 0;
1280846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1281846dde5dSShawn McCarney                             "0 is less than the minimum of 1");
1282846dde5dSShawn McCarney     }
1283846dde5dSShawn McCarney }
1284846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,I2CCompareBit)12854ab8cbbfSBob King TEST(ValidateRegulatorsConfigTest, I2CCompareBit)
12864ab8cbbfSBob King {
12874ab8cbbfSBob King     json i2cCompareBitFile = validConfigFile;
12884ab8cbbfSBob King     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
12894ab8cbbfSBob King         "0xA0";
12904ab8cbbfSBob King     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
12914ab8cbbfSBob King         3;
12924ab8cbbfSBob King     i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
12934ab8cbbfSBob King     // Valid: test rule actions i2c_compare_bit.
12944ab8cbbfSBob King     {
12954ab8cbbfSBob King         json configFile = i2cCompareBitFile;
12964ab8cbbfSBob King         EXPECT_JSON_VALID(configFile);
12974ab8cbbfSBob King     }
12984ab8cbbfSBob King     // Invalid: test i2c_compare_bit with no register.
12994ab8cbbfSBob King     {
13004ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13014ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
13024ab8cbbfSBob King             "register");
13034ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1304358c417aSBob King                             "'register' is a required property");
13054ab8cbbfSBob King     }
13064ab8cbbfSBob King     // Invalid: test i2c_compare_bit with no position.
13074ab8cbbfSBob King     {
13084ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13094ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
13104ab8cbbfSBob King             "position");
13114ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1312358c417aSBob King                             "'position' is a required property");
13134ab8cbbfSBob King     }
13144ab8cbbfSBob King     // Invalid: test i2c_compare_bit with no value.
13154ab8cbbfSBob King     {
13164ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13174ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value");
13184ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1319358c417aSBob King                             "'value' is a required property");
13204ab8cbbfSBob King     }
13214ab8cbbfSBob King     // Invalid: test i2c_compare_bit with register wrong type.
13224ab8cbbfSBob King     {
13234ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13244ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1;
13254ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1326358c417aSBob King                             "1 is not of type 'string'");
13274ab8cbbfSBob King     }
13284ab8cbbfSBob King     // Invalid: test i2c_compare_bit with register wrong format.
13294ab8cbbfSBob King     {
13304ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13314ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
13324ab8cbbfSBob King             "0xA00";
13334ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1334358c417aSBob King                             "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
13354ab8cbbfSBob King     }
13364ab8cbbfSBob King     // Invalid: test i2c_compare_bit with position wrong type.
13374ab8cbbfSBob King     {
13384ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13394ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
13404ab8cbbfSBob King             3.1;
13414ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1342358c417aSBob King                             "3.1 is not of type 'integer'");
13434ab8cbbfSBob King     }
13444ab8cbbfSBob King     // Invalid: test i2c_compare_bit with position greater than 7.
13454ab8cbbfSBob King     {
13464ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13474ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8;
13484ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
13494ab8cbbfSBob King                             "8 is greater than the maximum of 7");
13504ab8cbbfSBob King     }
13514ab8cbbfSBob King     // Invalid: test i2c_compare_bit with position less than 0.
13524ab8cbbfSBob King     {
13534ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13544ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
13554ab8cbbfSBob King             -1;
13564ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
13574ab8cbbfSBob King                             "-1 is less than the minimum of 0");
13584ab8cbbfSBob King     }
13594ab8cbbfSBob King     // Invalid: test i2c_compare_bit with value wrong type.
13604ab8cbbfSBob King     {
13614ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13624ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1";
13634ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1364358c417aSBob King                             "'1' is not of type 'integer'");
13654ab8cbbfSBob King     }
13664ab8cbbfSBob King     // Invalid: test i2c_compare_bit with value greater than 1.
13674ab8cbbfSBob King     {
13684ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13694ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2;
13704ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
13714ab8cbbfSBob King                             "2 is greater than the maximum of 1");
13724ab8cbbfSBob King     }
13734ab8cbbfSBob King     // Invalid: test i2c_compare_bit with value less than 0.
13744ab8cbbfSBob King     {
13754ab8cbbfSBob King         json configFile = i2cCompareBitFile;
13764ab8cbbfSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1;
13774ab8cbbfSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
13784ab8cbbfSBob King                             "-1 is less than the minimum of 0");
13794ab8cbbfSBob King     }
13804ab8cbbfSBob King }
1381846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,I2CCompareByte)1382514023d5SBob King TEST(ValidateRegulatorsConfigTest, I2CCompareByte)
1383514023d5SBob King {
1384514023d5SBob King     json i2cCompareByteFile = validConfigFile;
1385514023d5SBob King     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]
1386514023d5SBob King                       ["register"] = "0x82";
1387514023d5SBob King     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1388514023d5SBob King         "0x40";
1389514023d5SBob King     i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
1390514023d5SBob King         "0x7F";
1391514023d5SBob King     // Valid: test i2c_compare_byte with all properties.
1392514023d5SBob King     {
1393514023d5SBob King         json configFile = i2cCompareByteFile;
1394514023d5SBob King         EXPECT_JSON_VALID(configFile);
1395514023d5SBob King     }
1396514023d5SBob King     // Valid: test i2c_compare_byte with all required properties.
1397514023d5SBob King     {
1398514023d5SBob King         json configFile = i2cCompareByteFile;
1399514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask");
1400514023d5SBob King         EXPECT_JSON_VALID(configFile);
1401514023d5SBob King     }
1402514023d5SBob King     // Invalid: test i2c_compare_byte with no register.
1403514023d5SBob King     {
1404514023d5SBob King         json configFile = i2cCompareByteFile;
1405514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase(
1406514023d5SBob King             "register");
1407514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1408358c417aSBob King                             "'register' is a required property");
1409514023d5SBob King     }
1410514023d5SBob King     // Invalid: test i2c_compare_byte with no value.
1411514023d5SBob King     {
1412514023d5SBob King         json configFile = i2cCompareByteFile;
1413514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value");
1414514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1415358c417aSBob King                             "'value' is a required property");
1416514023d5SBob King     }
1417514023d5SBob King     // Invalid: test i2c_compare_byte with property register wrong type.
1418514023d5SBob King     {
1419514023d5SBob King         json configFile = i2cCompareByteFile;
1420514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1421514023d5SBob King             1;
1422514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1423358c417aSBob King                             "1 is not of type 'string'");
1424514023d5SBob King     }
1425514023d5SBob King     // Invalid: test i2c_compare_byte with property value wrong type.
1426514023d5SBob King     {
1427514023d5SBob King         json configFile = i2cCompareByteFile;
1428514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1;
1429514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1430358c417aSBob King                             "1 is not of type 'string'");
1431514023d5SBob King     }
1432514023d5SBob King     // Invalid: test i2c_compare_byte with property mask wrong type.
1433514023d5SBob King     {
1434514023d5SBob King         json configFile = i2cCompareByteFile;
1435514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1;
1436514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1437358c417aSBob King                             "1 is not of type 'string'");
1438514023d5SBob King     }
1439514023d5SBob King     // Invalid: test i2c_compare_byte with property register more than 2 hex
1440514023d5SBob King     // digits.
1441514023d5SBob King     {
1442514023d5SBob King         json configFile = i2cCompareByteFile;
1443514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1444514023d5SBob King             "0x820";
1445514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1446358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
1447514023d5SBob King     }
1448514023d5SBob King     // Invalid: test i2c_compare_byte with property value more than 2 hex
1449514023d5SBob King     // digits.
1450514023d5SBob King     {
1451514023d5SBob King         json configFile = i2cCompareByteFile;
1452514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1453514023d5SBob King             "0x820";
1454514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1455358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
1456514023d5SBob King     }
1457514023d5SBob King     // Invalid: test i2c_compare_byte with property mask more than 2 hex digits.
1458514023d5SBob King     {
1459514023d5SBob King         json configFile = i2cCompareByteFile;
1460514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
1461514023d5SBob King             "0x820";
1462514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1463358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
1464514023d5SBob King     }
1465514023d5SBob King     // Invalid: test i2c_compare_byte with property register less than 2 hex
1466514023d5SBob King     // digits.
1467514023d5SBob King     {
1468514023d5SBob King         json configFile = i2cCompareByteFile;
1469514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1470514023d5SBob King             "0x8";
1471514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1472358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
1473514023d5SBob King     }
1474514023d5SBob King     // Invalid: test i2c_compare_byte with property value less than 2 hex
1475514023d5SBob King     // digits.
1476514023d5SBob King     {
1477514023d5SBob King         json configFile = i2cCompareByteFile;
1478514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1479514023d5SBob King             "0x8";
1480514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1481358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
1482514023d5SBob King     }
1483514023d5SBob King     // Invalid: test i2c_compare_byte with property mask less than 2 hex digits.
1484514023d5SBob King     {
1485514023d5SBob King         json configFile = i2cCompareByteFile;
1486514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
1487514023d5SBob King             "0x8";
1488514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1489358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
1490514023d5SBob King     }
1491514023d5SBob King     // Invalid: test i2c_compare_byte with property register no leading prefix.
1492514023d5SBob King     {
1493514023d5SBob King         json configFile = i2cCompareByteFile;
1494514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1495514023d5SBob King             "82";
1496514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1497358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
1498514023d5SBob King     }
1499514023d5SBob King     // Invalid: test i2c_compare_byte with property value no leading prefix.
1500514023d5SBob King     {
1501514023d5SBob King         json configFile = i2cCompareByteFile;
1502514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1503514023d5SBob King             "82";
1504514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1505358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
1506514023d5SBob King     }
1507514023d5SBob King     // Invalid: test i2c_compare_byte with property mask no leading prefix.
1508514023d5SBob King     {
1509514023d5SBob King         json configFile = i2cCompareByteFile;
1510514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82";
1511514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1512358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
1513514023d5SBob King     }
1514514023d5SBob King     // Invalid: test i2c_compare_byte with property register invalid hex digit.
1515514023d5SBob King     {
1516514023d5SBob King         json configFile = i2cCompareByteFile;
1517514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1518514023d5SBob King             "0xG1";
1519514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1520358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
1521514023d5SBob King     }
1522514023d5SBob King     // Invalid: test i2c_compare_byte with property value invalid hex digit.
1523514023d5SBob King     {
1524514023d5SBob King         json configFile = i2cCompareByteFile;
1525514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1526514023d5SBob King             "0xG1";
1527514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1528358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
1529514023d5SBob King     }
1530514023d5SBob King     // Invalid: test i2c_compare_byte with property mask invalid hex digit.
1531514023d5SBob King     {
1532514023d5SBob King         json configFile = i2cCompareByteFile;
1533514023d5SBob King         configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
1534514023d5SBob King             "0xG1";
1535514023d5SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1536358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
1537514023d5SBob King     }
1538514023d5SBob King }
1539846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,I2CCompareBytes)1540fb162bbeSBob King TEST(ValidateRegulatorsConfigTest, I2CCompareBytes)
1541fb162bbeSBob King {
1542fb162bbeSBob King     json i2cCompareBytesFile = validConfigFile;
1543fb162bbeSBob King     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
1544fb162bbeSBob King                        ["register"] = "0x82";
1545fb162bbeSBob King     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
1546fb162bbeSBob King                        ["values"] = {"0x02", "0x73"};
1547fb162bbeSBob King     i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
1548fb162bbeSBob King                        ["masks"] = {"0x7F", "0x7F"};
1549fb162bbeSBob King     // Valid: test i2c_compare_bytes.
1550fb162bbeSBob King     {
1551fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1552fb162bbeSBob King         EXPECT_JSON_VALID(configFile);
1553fb162bbeSBob King     }
1554fb162bbeSBob King     // Valid: test i2c_compare_bytes with all required properties.
1555fb162bbeSBob King     {
1556fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1557fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1558fb162bbeSBob King             "masks");
1559fb162bbeSBob King         EXPECT_JSON_VALID(configFile);
1560fb162bbeSBob King     }
1561fb162bbeSBob King     // Invalid: test i2c_compare_bytes with no register.
1562fb162bbeSBob King     {
1563fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1564fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1565fb162bbeSBob King             "register");
1566fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1567358c417aSBob King                             "'register' is a required property");
1568fb162bbeSBob King     }
1569fb162bbeSBob King     // Invalid: test i2c_compare_bytes with no values.
1570fb162bbeSBob King     {
1571fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1572fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1573fb162bbeSBob King             "values");
1574fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1575358c417aSBob King                             "'values' is a required property");
1576fb162bbeSBob King     }
1577fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property values as empty array.
1578fb162bbeSBob King     {
1579fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1580fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] =
1581fb162bbeSBob King             json::array();
1582fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1583fb162bbeSBob King                             "[] is too short");
1584fb162bbeSBob King     }
1585fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property masks as empty array.
1586fb162bbeSBob King     {
1587fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1588fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] =
1589fb162bbeSBob King             json::array();
1590fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1591fb162bbeSBob King                             "[] is too short");
1592fb162bbeSBob King     }
1593fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property register wrong type.
1594fb162bbeSBob King     {
1595fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1596fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1597fb162bbeSBob King             1;
1598fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1599358c417aSBob King                             "1 is not of type 'string'");
1600fb162bbeSBob King     }
1601fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property values wrong type.
1602fb162bbeSBob King     {
1603fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1604fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1;
1605fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1606358c417aSBob King                             "1 is not of type 'array'");
1607fb162bbeSBob King     }
1608fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property masks wrong type.
1609fb162bbeSBob King     {
1610fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1611fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1;
1612fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1613358c417aSBob King                             "1 is not of type 'array'");
1614fb162bbeSBob King     }
1615fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property register more than 2 hex
1616fb162bbeSBob King     // digits.
1617fb162bbeSBob King     {
1618fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1619fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1620fb162bbeSBob King             "0x820";
1621fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1622358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
1623fb162bbeSBob King     }
1624fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property values more than 2 hex
1625fb162bbeSBob King     // digits.
1626fb162bbeSBob King     {
1627fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1628fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1629fb162bbeSBob King             "0x820";
1630fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1631358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
1632fb162bbeSBob King     }
1633fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property masks more than 2 hex
1634fb162bbeSBob King     // digits.
1635fb162bbeSBob King     {
1636fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1637fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1638fb162bbeSBob King             "0x820";
1639fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1640358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
1641fb162bbeSBob King     }
1642fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property register less than 2 hex
1643fb162bbeSBob King     // digits.
1644fb162bbeSBob King     {
1645fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1646fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1647fb162bbeSBob King             "0x8";
1648fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1649358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
1650fb162bbeSBob King     }
1651fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property values less than 2 hex
1652fb162bbeSBob King     // digits.
1653fb162bbeSBob King     {
1654fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1655fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1656fb162bbeSBob King             "0x8";
1657fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1658358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
1659fb162bbeSBob King     }
1660fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property masks less than 2 hex
1661fb162bbeSBob King     // digits.
1662fb162bbeSBob King     {
1663fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1664fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1665fb162bbeSBob King             "0x8";
1666fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1667358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
1668fb162bbeSBob King     }
1669fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property register no leading prefix.
1670fb162bbeSBob King     {
1671fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1672fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1673fb162bbeSBob King             "82";
1674fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1675358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
1676fb162bbeSBob King     }
1677fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property values no leading prefix.
1678fb162bbeSBob King     {
1679fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1680fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1681fb162bbeSBob King             "82";
1682fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1683358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
1684fb162bbeSBob King     }
1685fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property masks no leading prefix.
1686fb162bbeSBob King     {
1687fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1688fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1689fb162bbeSBob King             "82";
1690fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1691358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
1692fb162bbeSBob King     }
1693fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property register invalid hex digit.
1694fb162bbeSBob King     {
1695fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1696fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1697fb162bbeSBob King             "0xG1";
1698fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1699358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
1700fb162bbeSBob King     }
1701fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property values invalid hex digit.
1702fb162bbeSBob King     {
1703fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1704fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1705fb162bbeSBob King             "0xG1";
1706fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1707358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
1708fb162bbeSBob King     }
1709fb162bbeSBob King     // Invalid: test i2c_compare_bytes with property masks invalid hex digit.
1710fb162bbeSBob King     {
1711fb162bbeSBob King         json configFile = i2cCompareBytesFile;
1712fb162bbeSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1713fb162bbeSBob King             "0xG1";
1714fb162bbeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1715358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
1716fb162bbeSBob King     }
1717fb162bbeSBob King }
1718846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,I2CInterface)1719ca93f1f4SBob King TEST(ValidateRegulatorsConfigTest, I2CInterface)
1720ca93f1f4SBob King {
1721ca93f1f4SBob King     // Valid: test i2c_interface.
1722ca93f1f4SBob King     {
1723ca93f1f4SBob King         json configFile = validConfigFile;
1724ca93f1f4SBob King         EXPECT_JSON_VALID(configFile);
1725ca93f1f4SBob King     }
1726ca93f1f4SBob King     // Invalid: testi2c_interface with no bus.
1727ca93f1f4SBob King     {
1728ca93f1f4SBob King         json configFile = validConfigFile;
1729ca93f1f4SBob King         configFile["chassis"][0]["devices"][0]["i2c_interface"].erase("bus");
1730ca93f1f4SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1731358c417aSBob King                             "'bus' is a required property");
1732ca93f1f4SBob King     }
1733ca93f1f4SBob King     // Invalid: test i2c_interface with no address.
1734ca93f1f4SBob King     {
1735ca93f1f4SBob King         json configFile = validConfigFile;
1736ca93f1f4SBob King         configFile["chassis"][0]["devices"][0]["i2c_interface"].erase(
1737ca93f1f4SBob King             "address");
1738ca93f1f4SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1739358c417aSBob King                             "'address' is a required property");
1740ca93f1f4SBob King     }
1741ca93f1f4SBob King     // Invalid: test i2c_interface with property bus wrong type.
1742ca93f1f4SBob King     {
1743ca93f1f4SBob King         json configFile = validConfigFile;
1744ca93f1f4SBob King         configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = true;
1745ca93f1f4SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1746358c417aSBob King                             "True is not of type 'integer'");
1747ca93f1f4SBob King     }
1748ca93f1f4SBob King     // Invalid: test i2c_interface with property address wrong
1749ca93f1f4SBob King     // type.
1750ca93f1f4SBob King     {
1751ca93f1f4SBob King         json configFile = validConfigFile;
1752ca93f1f4SBob King         configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1753ca93f1f4SBob King             true;
1754ca93f1f4SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1755358c417aSBob King                             "True is not of type 'string'");
1756ca93f1f4SBob King     }
1757ca93f1f4SBob King     // Invalid: test i2c_interface with property bus less than
1758ca93f1f4SBob King     // 0.
1759ca93f1f4SBob King     {
1760ca93f1f4SBob King         json configFile = validConfigFile;
1761ca93f1f4SBob King         configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = -1;
1762ca93f1f4SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1763ca93f1f4SBob King                             "-1 is less than the minimum of 0");
1764ca93f1f4SBob King     }
1765ca93f1f4SBob King     // Invalid: test i2c_interface with property address wrong
1766ca93f1f4SBob King     // format.
1767ca93f1f4SBob King     {
1768ca93f1f4SBob King         json configFile = validConfigFile;
1769ca93f1f4SBob King         configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1770ca93f1f4SBob King             "0x700";
1771ca93f1f4SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1772358c417aSBob King                             "'0x700' does not match '^0x[0-9A-Fa-f]{2}$'");
1773ca93f1f4SBob King     }
1774ca93f1f4SBob King }
1775846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,I2CWriteBit)1776188db7d8SBob King TEST(ValidateRegulatorsConfigTest, I2CWriteBit)
1777188db7d8SBob King {
1778188db7d8SBob King     json i2cWriteBitFile = validConfigFile;
1779188db7d8SBob King     i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
1780188db7d8SBob King         "0xA0";
1781188db7d8SBob King     i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3;
1782188db7d8SBob King     i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 1;
1783188db7d8SBob King     // Valid: test rule actions i2c_write_bit.
1784188db7d8SBob King     {
1785188db7d8SBob King         json configFile = i2cWriteBitFile;
1786188db7d8SBob King         EXPECT_JSON_VALID(configFile);
1787188db7d8SBob King     }
1788188db7d8SBob King     // Invalid: test i2c_write_bit with no register.
1789188db7d8SBob King     {
1790188db7d8SBob King         json configFile = i2cWriteBitFile;
1791188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("register");
1792188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1793358c417aSBob King                             "'register' is a required property");
1794188db7d8SBob King     }
1795188db7d8SBob King     // Invalid: test i2c_write_bit with no position.
1796188db7d8SBob King     {
1797188db7d8SBob King         json configFile = i2cWriteBitFile;
1798188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("position");
1799188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1800358c417aSBob King                             "'position' is a required property");
1801188db7d8SBob King     }
1802188db7d8SBob King     // Invalid: test i2c_write_bit with no value.
1803188db7d8SBob King     {
1804188db7d8SBob King         json configFile = i2cWriteBitFile;
1805188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("value");
1806188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1807358c417aSBob King                             "'value' is a required property");
1808188db7d8SBob King     }
1809188db7d8SBob King     // Invalid: test i2c_write_bit with register wrong type.
1810188db7d8SBob King     {
1811188db7d8SBob King         json configFile = i2cWriteBitFile;
1812188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] = 1;
1813188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1814358c417aSBob King                             "1 is not of type 'string'");
1815188db7d8SBob King     }
1816188db7d8SBob King     // Invalid: test i2c_write_bit with register wrong format.
1817188db7d8SBob King     {
1818188db7d8SBob King         json configFile = i2cWriteBitFile;
1819188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
1820188db7d8SBob King             "0xA00";
1821188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1822358c417aSBob King                             "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
1823188db7d8SBob King     }
1824188db7d8SBob King     // Invalid: test i2c_write_bit with position wrong type.
1825188db7d8SBob King     {
1826188db7d8SBob King         json configFile = i2cWriteBitFile;
1827188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3.1;
1828188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1829358c417aSBob King                             "3.1 is not of type 'integer'");
1830188db7d8SBob King     }
1831188db7d8SBob King     // Invalid: test i2c_write_bit with position greater than 7.
1832188db7d8SBob King     {
1833188db7d8SBob King         json configFile = i2cWriteBitFile;
1834188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 8;
1835188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1836188db7d8SBob King                             "8 is greater than the maximum of 7");
1837188db7d8SBob King     }
1838188db7d8SBob King     // Invalid: test i2c_write_bit with position less than 0.
1839188db7d8SBob King     {
1840188db7d8SBob King         json configFile = i2cWriteBitFile;
1841188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = -1;
1842188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1843188db7d8SBob King                             "-1 is less than the minimum of 0");
1844188db7d8SBob King     }
1845188db7d8SBob King     // Invalid: test i2c_write_bit with value wrong type.
1846188db7d8SBob King     {
1847188db7d8SBob King         json configFile = i2cWriteBitFile;
1848188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = "1";
1849188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1850358c417aSBob King                             "'1' is not of type 'integer'");
1851188db7d8SBob King     }
1852188db7d8SBob King     // Invalid: test i2c_write_bit with value greater than 1.
1853188db7d8SBob King     {
1854188db7d8SBob King         json configFile = i2cWriteBitFile;
1855188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 2;
1856188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1857188db7d8SBob King                             "2 is greater than the maximum of 1");
1858188db7d8SBob King     }
1859188db7d8SBob King     // Invalid: test i2c_write_bit with value less than 0.
1860188db7d8SBob King     {
1861188db7d8SBob King         json configFile = i2cWriteBitFile;
1862188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = -1;
1863188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1864188db7d8SBob King                             "-1 is less than the minimum of 0");
1865188db7d8SBob King     }
1866188db7d8SBob King }
1867846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,I2CWriteByte)1868188db7d8SBob King TEST(ValidateRegulatorsConfigTest, I2CWriteByte)
1869188db7d8SBob King {
1870188db7d8SBob King     json i2cWriteByteFile = validConfigFile;
1871188db7d8SBob King     i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1872188db7d8SBob King         "0x82";
1873188db7d8SBob King     i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1874188db7d8SBob King         "0x40";
1875188db7d8SBob King     i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
1876188db7d8SBob King         "0x7F";
1877188db7d8SBob King     // Valid: test i2c_write_byte with all properties.
1878188db7d8SBob King     {
1879188db7d8SBob King         json configFile = i2cWriteByteFile;
1880188db7d8SBob King         EXPECT_JSON_VALID(configFile);
1881188db7d8SBob King     }
1882188db7d8SBob King     // Valid: test i2c_write_byte with all required properties.
1883188db7d8SBob King     {
1884188db7d8SBob King         json configFile = i2cWriteByteFile;
1885188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("mask");
1886188db7d8SBob King         EXPECT_JSON_VALID(configFile);
1887188db7d8SBob King     }
1888188db7d8SBob King     // Invalid: test i2c_write_byte with no register.
1889188db7d8SBob King     {
1890188db7d8SBob King         json configFile = i2cWriteByteFile;
1891188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase(
1892188db7d8SBob King             "register");
1893188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1894358c417aSBob King                             "'register' is a required property");
1895188db7d8SBob King     }
1896188db7d8SBob King     // Invalid: test i2c_write_byte with no value.
1897188db7d8SBob King     {
1898188db7d8SBob King         json configFile = i2cWriteByteFile;
1899188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("value");
1900188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1901358c417aSBob King                             "'value' is a required property");
1902188db7d8SBob King     }
1903188db7d8SBob King     // Invalid: test i2c_write_byte with property register wrong type.
1904188db7d8SBob King     {
1905188db7d8SBob King         json configFile = i2cWriteByteFile;
1906188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1;
1907188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1908358c417aSBob King                             "1 is not of type 'string'");
1909188db7d8SBob King     }
1910188db7d8SBob King     // Invalid: test i2c_write_byte with property value wrong type.
1911188db7d8SBob King     {
1912188db7d8SBob King         json configFile = i2cWriteByteFile;
1913188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = 1;
1914188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1915358c417aSBob King                             "1 is not of type 'string'");
1916188db7d8SBob King     }
1917188db7d8SBob King     // Invalid: test i2c_write_byte with property mask wrong type.
1918188db7d8SBob King     {
1919188db7d8SBob King         json configFile = i2cWriteByteFile;
1920188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = 1;
1921188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1922358c417aSBob King                             "1 is not of type 'string'");
1923188db7d8SBob King     }
1924188db7d8SBob King     // Invalid: test i2c_write_byte with property register more than 2 hex
1925188db7d8SBob King     // digits.
1926188db7d8SBob King     {
1927188db7d8SBob King         json configFile = i2cWriteByteFile;
1928188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1929188db7d8SBob King             "0x820";
1930188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1931358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
1932188db7d8SBob King     }
1933188db7d8SBob King     // Invalid: test i2c_write_byte with property value more than 2 hex
1934188db7d8SBob King     // digits.
1935188db7d8SBob King     {
1936188db7d8SBob King         json configFile = i2cWriteByteFile;
1937188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1938188db7d8SBob King             "0x820";
1939188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1940358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
1941188db7d8SBob King     }
1942188db7d8SBob King     // Invalid: test i2c_write_byte with property mask more than 2 hex digits.
1943188db7d8SBob King     {
1944188db7d8SBob King         json configFile = i2cWriteByteFile;
1945188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
1946188db7d8SBob King             "0x820";
1947188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1948358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
1949188db7d8SBob King     }
1950188db7d8SBob King     // Invalid: test i2c_write_byte with property register less than 2 hex
1951188db7d8SBob King     // digits.
1952188db7d8SBob King     {
1953188db7d8SBob King         json configFile = i2cWriteByteFile;
1954188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1955188db7d8SBob King             "0x8";
1956188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1957358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
1958188db7d8SBob King     }
1959188db7d8SBob King     // Invalid: test i2c_write_byte with property value less than 2 hex
1960188db7d8SBob King     // digits.
1961188db7d8SBob King     {
1962188db7d8SBob King         json configFile = i2cWriteByteFile;
1963188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "0x8";
1964188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1965358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
1966188db7d8SBob King     }
1967188db7d8SBob King     // Invalid: test i2c_write_byte with property mask less than 2 hex digits.
1968188db7d8SBob King     {
1969188db7d8SBob King         json configFile = i2cWriteByteFile;
1970188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0x8";
1971188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1972358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
1973188db7d8SBob King     }
1974188db7d8SBob King     // Invalid: test i2c_write_byte with property register no leading prefix.
1975188db7d8SBob King     {
1976188db7d8SBob King         json configFile = i2cWriteByteFile;
1977188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1978188db7d8SBob King             "82";
1979188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1980358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
1981188db7d8SBob King     }
1982188db7d8SBob King     // Invalid: test i2c_write_byte with property value no leading prefix.
1983188db7d8SBob King     {
1984188db7d8SBob King         json configFile = i2cWriteByteFile;
1985188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "82";
1986188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1987358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
1988188db7d8SBob King     }
1989188db7d8SBob King     // Invalid: test i2c_write_byte with property mask no leading prefix.
1990188db7d8SBob King     {
1991188db7d8SBob King         json configFile = i2cWriteByteFile;
1992188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "82";
1993188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
1994358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
1995188db7d8SBob King     }
1996188db7d8SBob King     // Invalid: test i2c_write_byte with property register invalid hex digit.
1997188db7d8SBob King     {
1998188db7d8SBob King         json configFile = i2cWriteByteFile;
1999188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
2000188db7d8SBob King             "0xG1";
2001188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2002358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
2003188db7d8SBob King     }
2004188db7d8SBob King     // Invalid: test i2c_write_byte with property value invalid hex digit.
2005188db7d8SBob King     {
2006188db7d8SBob King         json configFile = i2cWriteByteFile;
2007188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
2008188db7d8SBob King             "0xG1";
2009188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2010358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
2011188db7d8SBob King     }
2012188db7d8SBob King     // Invalid: test i2c_write_byte with property mask invalid hex digit.
2013188db7d8SBob King     {
2014188db7d8SBob King         json configFile = i2cWriteByteFile;
2015188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0xG1";
2016188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2017358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
2018188db7d8SBob King     }
2019188db7d8SBob King }
2020846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,I2CWriteBytes)2021188db7d8SBob King TEST(ValidateRegulatorsConfigTest, I2CWriteBytes)
2022188db7d8SBob King {
2023188db7d8SBob King     json i2cWriteBytesFile = validConfigFile;
2024188db7d8SBob King     i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2025188db7d8SBob King         "0x82";
2026188db7d8SBob King     i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
2027188db7d8SBob King         "0x02", "0x73"};
2028188db7d8SBob King     i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
2029188db7d8SBob King         "0x7F", "0x7F"};
2030188db7d8SBob King     // Valid: test i2c_write_bytes.
2031188db7d8SBob King     {
2032188db7d8SBob King         json configFile = i2cWriteBytesFile;
2033188db7d8SBob King         EXPECT_JSON_VALID(configFile);
2034188db7d8SBob King     }
2035188db7d8SBob King     // Valid: test i2c_write_bytes with all required properties.
2036188db7d8SBob King     {
2037188db7d8SBob King         json configFile = i2cWriteBytesFile;
2038188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("masks");
2039188db7d8SBob King         EXPECT_JSON_VALID(configFile);
2040188db7d8SBob King     }
2041188db7d8SBob King     // Invalid: test i2c_write_bytes with no register.
2042188db7d8SBob King     {
2043188db7d8SBob King         json configFile = i2cWriteBytesFile;
2044188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase(
2045188db7d8SBob King             "register");
2046188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2047358c417aSBob King                             "'register' is a required property");
2048188db7d8SBob King     }
2049188db7d8SBob King     // Invalid: test i2c_write_bytes with no values.
2050188db7d8SBob King     {
2051188db7d8SBob King         json configFile = i2cWriteBytesFile;
2052188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("values");
2053188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2054358c417aSBob King                             "'values' is a required property");
2055188db7d8SBob King     }
2056188db7d8SBob King     // Invalid: test i2c_write_bytes with property values as empty array.
2057188db7d8SBob King     {
2058188db7d8SBob King         json configFile = i2cWriteBytesFile;
2059188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] =
2060188db7d8SBob King             json::array();
2061188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2062188db7d8SBob King                             "[] is too short");
2063188db7d8SBob King     }
2064188db7d8SBob King     // Invalid: test i2c_write_bytes with property masks as empty array.
2065188db7d8SBob King     {
2066188db7d8SBob King         json configFile = i2cWriteBytesFile;
2067188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] =
2068188db7d8SBob King             json::array();
2069188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2070188db7d8SBob King                             "[] is too short");
2071188db7d8SBob King     }
2072188db7d8SBob King     // Invalid: test i2c_write_bytes with property register wrong type.
2073188db7d8SBob King     {
2074188db7d8SBob King         json configFile = i2cWriteBytesFile;
2075188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1;
2076188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2077358c417aSBob King                             "1 is not of type 'string'");
2078188db7d8SBob King     }
2079188db7d8SBob King     // Invalid: test i2c_write_bytes with property values wrong type.
2080188db7d8SBob King     {
2081188db7d8SBob King         json configFile = i2cWriteBytesFile;
2082188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = 1;
2083188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2084358c417aSBob King                             "1 is not of type 'array'");
2085188db7d8SBob King     }
2086188db7d8SBob King     // Invalid: test i2c_write_bytes with property masks wrong type.
2087188db7d8SBob King     {
2088188db7d8SBob King         json configFile = i2cWriteBytesFile;
2089188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = 1;
2090188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2091358c417aSBob King                             "1 is not of type 'array'");
2092188db7d8SBob King     }
2093188db7d8SBob King     // Invalid: test i2c_write_bytes with property register more than 2 hex
2094188db7d8SBob King     // digits.
2095188db7d8SBob King     {
2096188db7d8SBob King         json configFile = i2cWriteBytesFile;
2097188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2098188db7d8SBob King             "0x820";
2099188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2100358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
2101188db7d8SBob King     }
2102188db7d8SBob King     // Invalid: test i2c_write_bytes with property values more than 2 hex
2103188db7d8SBob King     // digits.
2104188db7d8SBob King     {
2105188db7d8SBob King         json configFile = i2cWriteBytesFile;
2106188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
2107188db7d8SBob King             "0x820";
2108188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2109358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
2110188db7d8SBob King     }
2111188db7d8SBob King     // Invalid: test i2c_write_bytes with property masks more than 2 hex
2112188db7d8SBob King     // digits.
2113188db7d8SBob King     {
2114188db7d8SBob King         json configFile = i2cWriteBytesFile;
2115188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
2116188db7d8SBob King             "0x820";
2117188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2118358c417aSBob King                             "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
2119188db7d8SBob King     }
2120188db7d8SBob King     // Invalid: test i2c_write_bytes with property register less than 2 hex
2121188db7d8SBob King     // digits.
2122188db7d8SBob King     {
2123188db7d8SBob King         json configFile = i2cWriteBytesFile;
2124188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2125188db7d8SBob King             "0x8";
2126188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2127358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
2128188db7d8SBob King     }
2129188db7d8SBob King     // Invalid: test i2c_write_bytes with property values less than 2 hex
2130188db7d8SBob King     // digits.
2131188db7d8SBob King     {
2132188db7d8SBob King         json configFile = i2cWriteBytesFile;
2133188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
2134188db7d8SBob King             "0x8";
2135188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2136358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
2137188db7d8SBob King     }
2138188db7d8SBob King     // Invalid: test i2c_write_bytes with property masks less than 2 hex
2139188db7d8SBob King     // digits.
2140188db7d8SBob King     {
2141188db7d8SBob King         json configFile = i2cWriteBytesFile;
2142188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
2143188db7d8SBob King             "0x8";
2144188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2145358c417aSBob King                             "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
2146188db7d8SBob King     }
2147188db7d8SBob King     // Invalid: test i2c_write_bytes with property register no leading prefix.
2148188db7d8SBob King     {
2149188db7d8SBob King         json configFile = i2cWriteBytesFile;
2150188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2151188db7d8SBob King             "82";
2152188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2153358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
2154188db7d8SBob King     }
2155188db7d8SBob King     // Invalid: test i2c_write_bytes with property values no leading prefix.
2156188db7d8SBob King     {
2157188db7d8SBob King         json configFile = i2cWriteBytesFile;
2158188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
2159188db7d8SBob King             "82";
2160188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2161358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
2162188db7d8SBob King     }
2163188db7d8SBob King     // Invalid: test i2c_write_bytes with property masks no leading prefix.
2164188db7d8SBob King     {
2165188db7d8SBob King         json configFile = i2cWriteBytesFile;
2166188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
2167188db7d8SBob King             "82";
2168188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2169358c417aSBob King                             "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
2170188db7d8SBob King     }
2171188db7d8SBob King     // Invalid: test i2c_write_bytes with property register invalid hex digit.
2172188db7d8SBob King     {
2173188db7d8SBob King         json configFile = i2cWriteBytesFile;
2174188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2175188db7d8SBob King             "0xG1";
2176188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2177358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
2178188db7d8SBob King     }
2179188db7d8SBob King     // Invalid: test i2c_write_bytes with property values invalid hex digit.
2180188db7d8SBob King     {
2181188db7d8SBob King         json configFile = i2cWriteBytesFile;
2182188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
2183188db7d8SBob King             "0xG1";
2184188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2185358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
2186188db7d8SBob King     }
2187188db7d8SBob King     // Invalid: test i2c_write_bytes with property masks invalid hex digit.
2188188db7d8SBob King     {
2189188db7d8SBob King         json configFile = i2cWriteBytesFile;
2190188db7d8SBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
2191188db7d8SBob King             "0xG1";
2192188db7d8SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2193358c417aSBob King                             "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
2194188db7d8SBob King     }
2195188db7d8SBob King }
2196846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,If)2197ead0b059SBob King TEST(ValidateRegulatorsConfigTest, If)
2198ead0b059SBob King {
2199ead0b059SBob King     json ifFile = validConfigFile;
2200846dde5dSShawn McCarney     ifFile["rules"][4]["actions"][0]["if"]["condition"]["run_rule"] =
22012d27dcfeSBob King         "set_voltage_rule";
2202846dde5dSShawn McCarney     ifFile["rules"][4]["actions"][0]["if"]["then"][0]["run_rule"] =
22032d27dcfeSBob King         "read_sensors_rule";
2204846dde5dSShawn McCarney     ifFile["rules"][4]["actions"][0]["if"]["else"][0]["run_rule"] =
22052d27dcfeSBob King         "read_sensors_rule";
2206846dde5dSShawn McCarney     ifFile["rules"][4]["id"] = "rule_if";
2207ead0b059SBob King     // Valid: test if.
2208ead0b059SBob King     {
2209ead0b059SBob King         json configFile = ifFile;
2210ead0b059SBob King         EXPECT_JSON_VALID(configFile);
2211ead0b059SBob King     }
2212ead0b059SBob King     // Valid: test if with required properties.
2213ead0b059SBob King     {
2214ead0b059SBob King         json configFile = ifFile;
2215846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"].erase("else");
2216ead0b059SBob King         EXPECT_JSON_VALID(configFile);
2217ead0b059SBob King     }
2218ead0b059SBob King     // Invalid: test if with no property condition.
2219ead0b059SBob King     {
2220ead0b059SBob King         json configFile = ifFile;
2221846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"].erase("condition");
2222ead0b059SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2223358c417aSBob King                             "'condition' is a required property");
2224ead0b059SBob King     }
2225ead0b059SBob King     // Invalid: test if with no property then.
2226ead0b059SBob King     {
2227ead0b059SBob King         json configFile = ifFile;
2228846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"].erase("then");
2229ead0b059SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2230358c417aSBob King                             "'then' is a required property");
2231ead0b059SBob King     }
2232ead0b059SBob King     // Invalid: test if with property then empty array.
2233ead0b059SBob King     {
2234ead0b059SBob King         json configFile = ifFile;
2235846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"]["then"] = json::array();
2236ead0b059SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2237ead0b059SBob King                             "[] is too short");
2238ead0b059SBob King     }
2239ead0b059SBob King     // Invalid: test if with property else empty array.
2240ead0b059SBob King     {
2241ead0b059SBob King         json configFile = ifFile;
2242846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"]["else"] = json::array();
2243ead0b059SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2244ead0b059SBob King                             "[] is too short");
2245ead0b059SBob King     }
2246ead0b059SBob King     // Invalid: test if with property condition wrong type.
2247ead0b059SBob King     {
2248ead0b059SBob King         json configFile = ifFile;
2249846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"]["condition"] = 1;
2250ead0b059SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2251358c417aSBob King                             "1 is not of type 'object'");
2252ead0b059SBob King     }
2253ead0b059SBob King     // Invalid: test if with property then wrong type.
2254ead0b059SBob King     {
2255ead0b059SBob King         json configFile = ifFile;
2256846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"]["then"] = 1;
2257ead0b059SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2258358c417aSBob King                             "1 is not of type 'array'");
2259ead0b059SBob King     }
2260ead0b059SBob King     // Invalid: test if with property else wrong type.
2261ead0b059SBob King     {
2262ead0b059SBob King         json configFile = ifFile;
2263846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["if"]["else"] = 1;
2264ead0b059SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2265358c417aSBob King                             "1 is not of type 'array'");
2266ead0b059SBob King     }
2267ead0b059SBob King }
2268846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,LogPhaseFault)2269846dde5dSShawn McCarney TEST(ValidateRegulatorsConfigTest, LogPhaseFault)
2270846dde5dSShawn McCarney {
2271846dde5dSShawn McCarney     json initialFile = validConfigFile;
2272846dde5dSShawn McCarney     initialFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = "n";
2273846dde5dSShawn McCarney 
2274846dde5dSShawn McCarney     // Valid: All required properties
2275846dde5dSShawn McCarney     {
2276846dde5dSShawn McCarney         json configFile = initialFile;
2277846dde5dSShawn McCarney         EXPECT_JSON_VALID(configFile);
2278846dde5dSShawn McCarney     }
2279846dde5dSShawn McCarney 
2280846dde5dSShawn McCarney     // Invalid: type not specified
2281846dde5dSShawn McCarney     {
2282846dde5dSShawn McCarney         json configFile = initialFile;
2283846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["log_phase_fault"].erase("type");
2284846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2285846dde5dSShawn McCarney                             "'type' is a required property");
2286846dde5dSShawn McCarney     }
2287846dde5dSShawn McCarney 
2288846dde5dSShawn McCarney     // Invalid: invalid property specified
2289846dde5dSShawn McCarney     {
2290846dde5dSShawn McCarney         json configFile = initialFile;
2291846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["log_phase_fault"]["foo"] = true;
2292846dde5dSShawn McCarney         EXPECT_JSON_INVALID(
2293846dde5dSShawn McCarney             configFile, "Validation failed.",
2294846dde5dSShawn McCarney             "Additional properties are not allowed ('foo' was unexpected)");
2295846dde5dSShawn McCarney     }
2296846dde5dSShawn McCarney 
2297846dde5dSShawn McCarney     // Invalid: type has wrong data type
2298846dde5dSShawn McCarney     {
2299846dde5dSShawn McCarney         json configFile = initialFile;
2300846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = true;
2301846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2302846dde5dSShawn McCarney                             "True is not of type 'string'");
2303846dde5dSShawn McCarney     }
2304846dde5dSShawn McCarney 
2305846dde5dSShawn McCarney     // Invalid: type has invalid value
2306846dde5dSShawn McCarney     {
2307846dde5dSShawn McCarney         json configFile = initialFile;
2308846dde5dSShawn McCarney         configFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = "n+2";
2309846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2310846dde5dSShawn McCarney                             "'n+2' is not one of ['n+1', 'n']");
2311846dde5dSShawn McCarney     }
2312846dde5dSShawn McCarney }
2313846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,Not)2314bfe9fe7dSBob King TEST(ValidateRegulatorsConfigTest, Not)
2315bfe9fe7dSBob King {
2316bfe9fe7dSBob King     json notFile = validConfigFile;
2317bfe9fe7dSBob King     notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] =
2318bfe9fe7dSBob King         "0xA0";
2319bfe9fe7dSBob King     notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] =
2320bfe9fe7dSBob King         "0xFF";
2321bfe9fe7dSBob King     // Valid: test not.
2322bfe9fe7dSBob King     {
2323bfe9fe7dSBob King         json configFile = notFile;
2324bfe9fe7dSBob King         EXPECT_JSON_VALID(configFile);
2325bfe9fe7dSBob King     }
2326bfe9fe7dSBob King     // Invalid: test not with wrong type.
2327bfe9fe7dSBob King     {
2328bfe9fe7dSBob King         json configFile = notFile;
2329bfe9fe7dSBob King         configFile["rules"][0]["actions"][1]["not"] = 1;
2330bfe9fe7dSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2331358c417aSBob King                             "1 is not of type 'object'");
2332bfe9fe7dSBob King     }
2333bfe9fe7dSBob King }
2334846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,Or)2335cfc29d03SBob King TEST(ValidateRegulatorsConfigTest, Or)
2336cfc29d03SBob King {
2337cfc29d03SBob King     json orFile = validConfigFile;
2338cfc29d03SBob King     orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] =
2339cfc29d03SBob King         "0xA0";
2340cfc29d03SBob King     orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] =
2341cfc29d03SBob King         "0x00";
2342cfc29d03SBob King     orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] =
2343cfc29d03SBob King         "0xA1";
2344cfc29d03SBob King     orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] =
2345cfc29d03SBob King         "0x00";
2346cfc29d03SBob King     // Valid: test or.
2347cfc29d03SBob King     {
2348cfc29d03SBob King         json configFile = orFile;
2349cfc29d03SBob King         EXPECT_JSON_VALID(configFile);
2350cfc29d03SBob King     }
2351cfc29d03SBob King     // Invalid: test or with empty array.
2352cfc29d03SBob King     {
2353cfc29d03SBob King         json configFile = orFile;
2354cfc29d03SBob King         configFile["rules"][0]["actions"][1]["or"] = json::array();
2355cfc29d03SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2356cfc29d03SBob King                             "[] is too short");
2357cfc29d03SBob King     }
2358cfc29d03SBob King     // Invalid: test or with wrong type.
2359cfc29d03SBob King     {
2360cfc29d03SBob King         json configFile = orFile;
2361cfc29d03SBob King         configFile["rules"][0]["actions"][1]["or"] = 1;
2362cfc29d03SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2363358c417aSBob King                             "1 is not of type 'array'");
2364cfc29d03SBob King     }
2365cfc29d03SBob King }
2366846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,PhaseFaultDetection)2367846dde5dSShawn McCarney TEST(ValidateRegulatorsConfigTest, PhaseFaultDetection)
2368846dde5dSShawn McCarney {
2369846dde5dSShawn McCarney     json initialFile = validConfigFile;
2370846dde5dSShawn McCarney     initialFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2371846dde5dSShawn McCarney                ["rule_id"] = "detect_phase_faults_rule";
2372846dde5dSShawn McCarney 
2373846dde5dSShawn McCarney     // Valid: comments specified
2374846dde5dSShawn McCarney     {
2375846dde5dSShawn McCarney         json configFile = initialFile;
2376846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2377846dde5dSShawn McCarney                   ["comments"][0] = "Detect phase faults";
2378846dde5dSShawn McCarney         EXPECT_JSON_VALID(configFile);
2379846dde5dSShawn McCarney     }
2380846dde5dSShawn McCarney 
2381846dde5dSShawn McCarney     // Valid: device_id specified
2382846dde5dSShawn McCarney     {
2383846dde5dSShawn McCarney         json configFile = initialFile;
2384846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2385846dde5dSShawn McCarney                   ["device_id"] = "vdd_regulator";
2386846dde5dSShawn McCarney         EXPECT_JSON_VALID(configFile);
2387846dde5dSShawn McCarney     }
2388846dde5dSShawn McCarney 
2389846dde5dSShawn McCarney     // Valid: rule_id specified
2390846dde5dSShawn McCarney     {
2391846dde5dSShawn McCarney         json configFile = initialFile;
2392846dde5dSShawn McCarney         EXPECT_JSON_VALID(configFile);
2393846dde5dSShawn McCarney     }
2394846dde5dSShawn McCarney 
2395846dde5dSShawn McCarney     // Valid: actions specified
2396846dde5dSShawn McCarney     {
2397846dde5dSShawn McCarney         json configFile = initialFile;
2398846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
2399846dde5dSShawn McCarney             "rule_id");
2400846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2401846dde5dSShawn McCarney                   ["actions"][0]["run_rule"] = "detect_phase_faults_rule";
2402846dde5dSShawn McCarney         EXPECT_JSON_VALID(configFile);
2403846dde5dSShawn McCarney     }
2404846dde5dSShawn McCarney 
2405846dde5dSShawn McCarney     // Invalid: rule_id and actions specified
2406846dde5dSShawn McCarney     {
2407846dde5dSShawn McCarney         json configFile = initialFile;
2408846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2409846dde5dSShawn McCarney                   ["actions"][0]["run_rule"] = "detect_phase_faults_rule";
2410846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
2411846dde5dSShawn McCarney     }
2412846dde5dSShawn McCarney 
2413846dde5dSShawn McCarney     // Invalid: neither rule_id nor actions specified
2414846dde5dSShawn McCarney     {
2415846dde5dSShawn McCarney         json configFile = initialFile;
2416846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
2417846dde5dSShawn McCarney             "rule_id");
2418846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
24190a2b76bcSShawn McCarney                             "{} is not valid under any of the given schemas");
2420846dde5dSShawn McCarney     }
2421846dde5dSShawn McCarney 
2422846dde5dSShawn McCarney     // Invalid: comments has wrong data type
2423846dde5dSShawn McCarney     {
2424846dde5dSShawn McCarney         json configFile = initialFile;
2425846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2426846dde5dSShawn McCarney                   ["comments"] = true;
2427846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2428846dde5dSShawn McCarney                             "True is not of type 'array'");
2429846dde5dSShawn McCarney     }
2430846dde5dSShawn McCarney 
2431846dde5dSShawn McCarney     // Invalid: device_id has wrong data type
2432846dde5dSShawn McCarney     {
2433846dde5dSShawn McCarney         json configFile = initialFile;
2434846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2435846dde5dSShawn McCarney                   ["device_id"] = true;
2436846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2437846dde5dSShawn McCarney                             "True is not of type 'string'");
2438846dde5dSShawn McCarney     }
2439846dde5dSShawn McCarney 
2440846dde5dSShawn McCarney     // Invalid: rule_id has wrong data type
2441846dde5dSShawn McCarney     {
2442846dde5dSShawn McCarney         json configFile = initialFile;
2443846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2444846dde5dSShawn McCarney                   ["rule_id"] = true;
2445846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2446846dde5dSShawn McCarney                             "True is not of type 'string'");
2447846dde5dSShawn McCarney     }
2448846dde5dSShawn McCarney 
2449846dde5dSShawn McCarney     // Invalid: actions has wrong data type
2450846dde5dSShawn McCarney     {
2451846dde5dSShawn McCarney         json configFile = initialFile;
2452846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
2453846dde5dSShawn McCarney             "rule_id");
2454846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2455846dde5dSShawn McCarney                   ["actions"] = true;
2456846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2457846dde5dSShawn McCarney                             "True is not of type 'array'");
2458846dde5dSShawn McCarney     }
2459846dde5dSShawn McCarney 
2460846dde5dSShawn McCarney     // Invalid: device_id has invalid format
2461846dde5dSShawn McCarney     {
2462846dde5dSShawn McCarney         json configFile = initialFile;
2463846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2464846dde5dSShawn McCarney                   ["device_id"] = "id@";
2465846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2466846dde5dSShawn McCarney                             "'id@' does not match '^[A-Za-z0-9_]+$'");
2467846dde5dSShawn McCarney     }
2468846dde5dSShawn McCarney 
2469846dde5dSShawn McCarney     // Invalid: rule_id has invalid format
2470846dde5dSShawn McCarney     {
2471846dde5dSShawn McCarney         json configFile = initialFile;
2472846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2473846dde5dSShawn McCarney                   ["rule_id"] = "id@";
2474846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2475846dde5dSShawn McCarney                             "'id@' does not match '^[A-Za-z0-9_]+$'");
2476846dde5dSShawn McCarney     }
2477846dde5dSShawn McCarney 
2478846dde5dSShawn McCarney     // Invalid: comments array is empty
2479846dde5dSShawn McCarney     {
2480846dde5dSShawn McCarney         json configFile = initialFile;
2481846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2482846dde5dSShawn McCarney                   ["comments"] = json::array();
2483846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2484846dde5dSShawn McCarney                             "[] is too short");
2485846dde5dSShawn McCarney     }
2486846dde5dSShawn McCarney 
2487846dde5dSShawn McCarney     // Invalid: actions array is empty
2488846dde5dSShawn McCarney     {
2489846dde5dSShawn McCarney         json configFile = initialFile;
2490846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
2491846dde5dSShawn McCarney             "rule_id");
2492846dde5dSShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2493846dde5dSShawn McCarney                   ["actions"] = json::array();
2494846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2495846dde5dSShawn McCarney                             "[] is too short");
2496846dde5dSShawn McCarney     }
2497846dde5dSShawn McCarney }
2498846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,PmbusReadSensor)2499d661809bSBob King TEST(ValidateRegulatorsConfigTest, PmbusReadSensor)
2500d661809bSBob King {
2501d661809bSBob King     json pmbusReadSensorFile = validConfigFile;
2502d661809bSBob King     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
2503d661809bSBob King         "vout";
2504d661809bSBob King     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
2505d661809bSBob King                        ["command"] = "0x8B";
2506d661809bSBob King     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
2507d661809bSBob King                        ["format"] = "linear_16";
2508d661809bSBob King     pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
2509d661809bSBob King                        ["exponent"] = -8;
2510d661809bSBob King     // Valid: test pmbus_read_sensor.
2511d661809bSBob King     {
2512d661809bSBob King         json configFile = pmbusReadSensorFile;
2513d661809bSBob King         EXPECT_JSON_VALID(configFile);
2514d661809bSBob King     }
2515d661809bSBob King     // Valid: test pmbus_read_sensor with required properties.
2516d661809bSBob King     {
2517d661809bSBob King         json configFile = pmbusReadSensorFile;
2518d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
2519d661809bSBob King             "exponent");
2520d661809bSBob King         EXPECT_JSON_VALID(configFile);
2521d661809bSBob King     }
2522d661809bSBob King     // Invalid: test pmbus_read_sensor with no type.
2523d661809bSBob King     {
2524d661809bSBob King         json configFile = pmbusReadSensorFile;
2525d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type");
2526d661809bSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2527358c417aSBob King                             "'type' is a required property");
2528d661809bSBob King     }
2529d661809bSBob King     // Invalid: test pmbus_read_sensor with no command.
2530d661809bSBob King     {
2531d661809bSBob King         json configFile = pmbusReadSensorFile;
2532d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
2533d661809bSBob King             "command");
2534d661809bSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2535358c417aSBob King                             "'command' is a required property");
2536d661809bSBob King     }
2537d661809bSBob King     // Invalid: test pmbus_read_sensor with no format.
2538d661809bSBob King     {
2539d661809bSBob King         json configFile = pmbusReadSensorFile;
2540d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
2541d661809bSBob King             "format");
2542d661809bSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2543358c417aSBob King                             "'format' is a required property");
2544d661809bSBob King     }
2545d661809bSBob King     // Invalid: test pmbus_read_sensor with property type wrong type.
2546d661809bSBob King     {
2547d661809bSBob King         json configFile = pmbusReadSensorFile;
2548d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
2549d661809bSBob King             true;
2550358c417aSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2551358c417aSBob King                             "True is not of type 'string'");
2552d661809bSBob King     }
2553d661809bSBob King     // Invalid: test pmbus_read_sensor with property command wrong type.
2554d661809bSBob King     {
2555d661809bSBob King         json configFile = pmbusReadSensorFile;
2556d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
2557d661809bSBob King             true;
2558d661809bSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2559358c417aSBob King                             "True is not of type 'string'");
2560d661809bSBob King     }
2561d661809bSBob King     // Invalid: test pmbus_read_sensor with property format wrong type.
2562d661809bSBob King     {
2563d661809bSBob King         json configFile = pmbusReadSensorFile;
2564d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
2565d661809bSBob King             true;
2566d661809bSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2567358c417aSBob King                             "True is not of type 'string'");
2568d661809bSBob King     }
2569d661809bSBob King     // Invalid: test pmbus_read_sensor with property exponent wrong type.
2570d661809bSBob King     {
2571d661809bSBob King         json configFile = pmbusReadSensorFile;
2572d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] =
2573d661809bSBob King             true;
2574d661809bSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2575358c417aSBob King                             "True is not of type 'integer'");
2576d661809bSBob King     }
2577d661809bSBob King     // Invalid: test pmbus_read_sensor with property type wrong format.
2578d661809bSBob King     {
2579d661809bSBob King         json configFile = pmbusReadSensorFile;
2580d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
2581d661809bSBob King             "foo";
2582d661809bSBob King         EXPECT_JSON_INVALID(
2583d661809bSBob King             configFile, "Validation failed.",
2584358c417aSBob King             "'foo' is not one of ['iout', 'iout_peak', 'iout_valley', "
2585358c417aSBob King             "'pout', 'temperature', 'temperature_peak', 'vout', "
2586358c417aSBob King             "'vout_peak', 'vout_valley']");
2587d661809bSBob King     }
2588d661809bSBob King     // Invalid: test pmbus_read_sensor with property command wrong format.
2589d661809bSBob King     {
2590d661809bSBob King         json configFile = pmbusReadSensorFile;
2591d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
2592d661809bSBob King             "0x8B0";
2593d661809bSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2594358c417aSBob King                             "'0x8B0' does not match '^0x[0-9a-fA-F]{2}$'");
2595d661809bSBob King     }
2596d661809bSBob King     // Invalid: test pmbus_read_sensor with property format wrong format.
2597d661809bSBob King     {
2598d661809bSBob King         json configFile = pmbusReadSensorFile;
2599d661809bSBob King         configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
2600d661809bSBob King             "foo";
2601358c417aSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2602358c417aSBob King                             "'foo' is not one of ['linear_11', 'linear_16']");
2603d661809bSBob King     }
2604d661809bSBob King }
2605846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,PmbusWriteVoutCommand)260602179c63SBob King TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand)
260702179c63SBob King {
260802179c63SBob King     json pmbusWriteVoutCommandFile = validConfigFile;
260902179c63SBob King     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
261002179c63SBob King                              ["pmbus_write_vout_command"]["volts"] = 1.03;
261102179c63SBob King     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
261202179c63SBob King                              ["pmbus_write_vout_command"]["format"] = "linear";
261302179c63SBob King     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
261402179c63SBob King                              ["pmbus_write_vout_command"]["exponent"] = -8;
261502179c63SBob King     pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
261602179c63SBob King                              ["pmbus_write_vout_command"]["is_verified"] = true;
261702179c63SBob King     // Valid: test pmbus_write_vout_command.
261802179c63SBob King     {
261902179c63SBob King         json configFile = pmbusWriteVoutCommandFile;
262002179c63SBob King         EXPECT_JSON_VALID(configFile);
262102179c63SBob King     }
262202179c63SBob King     // Valid: test pmbus_write_vout_command with required properties.
262302179c63SBob King     {
262402179c63SBob King         json configFile = pmbusWriteVoutCommandFile;
262502179c63SBob King         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
262602179c63SBob King             "volts");
262702179c63SBob King         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
262802179c63SBob King             "exponent");
262902179c63SBob King         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
263002179c63SBob King             "is_verified");
263102179c63SBob King         EXPECT_JSON_VALID(configFile);
263202179c63SBob King     }
263302179c63SBob King     // Invalid: test pmbus_write_vout_command with no format.
263402179c63SBob King     {
263502179c63SBob King         json configFile = pmbusWriteVoutCommandFile;
263602179c63SBob King         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
263702179c63SBob King             "format");
263802179c63SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2639358c417aSBob King                             "'format' is a required property");
264002179c63SBob King     }
264102179c63SBob King     // Invalid: test pmbus_write_vout_command with property volts wrong type.
264202179c63SBob King     {
264302179c63SBob King         json configFile = pmbusWriteVoutCommandFile;
264402179c63SBob King         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
264502179c63SBob King                   ["volts"] = true;
264602179c63SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2647358c417aSBob King                             "True is not of type 'number'");
264802179c63SBob King     }
264902179c63SBob King     // Invalid: test pmbus_write_vout_command with property format wrong type.
265002179c63SBob King     {
265102179c63SBob King         json configFile = pmbusWriteVoutCommandFile;
265202179c63SBob King         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
265302179c63SBob King                   ["format"] = true;
265402179c63SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2655358c417aSBob King                             "True is not of type 'string'");
265602179c63SBob King     }
265702179c63SBob King     // Invalid: test pmbus_write_vout_command with property exponent wrong type.
265802179c63SBob King     {
265902179c63SBob King         json configFile = pmbusWriteVoutCommandFile;
266002179c63SBob King         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
266102179c63SBob King                   ["exponent"] = 1.3;
266202179c63SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2663358c417aSBob King                             "1.3 is not of type 'integer'");
266402179c63SBob King     }
266502179c63SBob King     // Invalid: test pmbus_write_vout_command with property is_verified wrong
266602179c63SBob King     // type.
266702179c63SBob King     {
266802179c63SBob King         json configFile = pmbusWriteVoutCommandFile;
266902179c63SBob King         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
267002179c63SBob King                   ["is_verified"] = 1;
267102179c63SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2672358c417aSBob King                             "1 is not of type 'boolean'");
267302179c63SBob King     }
267402179c63SBob King     // Invalid: test pmbus_write_vout_command with property format wrong format.
267502179c63SBob King     {
267602179c63SBob King         json configFile = pmbusWriteVoutCommandFile;
267702179c63SBob King         configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
267802179c63SBob King                   ["format"] = "foo";
267902179c63SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2680358c417aSBob King                             "'foo' is not one of ['linear']");
268102179c63SBob King     }
268202179c63SBob King }
2683846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,PresenceDetection)268499d8fa1aSBob King TEST(ValidateRegulatorsConfigTest, PresenceDetection)
268599d8fa1aSBob King {
268699d8fa1aSBob King     json presenceDetectionFile = validConfigFile;
268799d8fa1aSBob King     presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
2688846dde5dSShawn McCarney                          ["comments"][0] =
2689846dde5dSShawn McCarney                              "Regulator is only present if CPU3 is present";
2690846dde5dSShawn McCarney     presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
2691846dde5dSShawn McCarney                          ["rule_id"] = "detect_presence_rule";
269299d8fa1aSBob King     // Valid: test presence_detection with only property rule_id.
269399d8fa1aSBob King     {
269499d8fa1aSBob King         json configFile = presenceDetectionFile;
269599d8fa1aSBob King         EXPECT_JSON_VALID(configFile);
269699d8fa1aSBob King     }
269799d8fa1aSBob King     // Valid: test presence_detection with only property actions.
269899d8fa1aSBob King     {
269999d8fa1aSBob King         json configFile = presenceDetectionFile;
270099d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
270199d8fa1aSBob King             "rule_id");
270299d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
270399d8fa1aSBob King                   [0]["compare_presence"]["fru"] =
2704a76898f1SBob King                       "system/chassis/motherboard/cpu3";
270599d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
270699d8fa1aSBob King                   [0]["compare_presence"]["value"] = true;
270799d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
270899d8fa1aSBob King             "comments");
270999d8fa1aSBob King         EXPECT_JSON_VALID(configFile);
271099d8fa1aSBob King     }
271199d8fa1aSBob King     // Invalid: test presence_detection with both property rule_id and actions.
271299d8fa1aSBob King     {
271399d8fa1aSBob King         json configFile = presenceDetectionFile;
271499d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
271599d8fa1aSBob King                   [0]["compare_presence"]["fru"] =
2716a76898f1SBob King                       "system/chassis/motherboard/cpu3";
271799d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
271899d8fa1aSBob King                   [0]["compare_presence"]["value"] = true;
2719846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
272099d8fa1aSBob King     }
272199d8fa1aSBob King     // Invalid: test presence_detection with no rule_id and actions.
272299d8fa1aSBob King     {
272399d8fa1aSBob King         json configFile = presenceDetectionFile;
272499d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
272599d8fa1aSBob King             "rule_id");
27260a2b76bcSShawn McCarney         EXPECT_JSON_INVALID(
27270a2b76bcSShawn McCarney             configFile, "Validation failed.",
27280a2b76bcSShawn McCarney             "{'comments': ['Regulator is only present if CPU3 is present']} is not valid under any of the given schemas");
272999d8fa1aSBob King     }
273099d8fa1aSBob King     // Invalid: test presence_detection with property comments wrong type.
273199d8fa1aSBob King     {
273299d8fa1aSBob King         json configFile = presenceDetectionFile;
273399d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]
273499d8fa1aSBob King                   ["comments"] = true;
273599d8fa1aSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2736358c417aSBob King                             "True is not of type 'array'");
273799d8fa1aSBob King     }
273899d8fa1aSBob King     // Invalid: test presence_detection with property rule_id wrong type.
273999d8fa1aSBob King     {
274099d8fa1aSBob King         json configFile = presenceDetectionFile;
274199d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]
274299d8fa1aSBob King                   ["rule_id"] = true;
274399d8fa1aSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2744358c417aSBob King                             "True is not of type 'string'");
274599d8fa1aSBob King     }
274699d8fa1aSBob King     // Invalid: test presence_detection with property actions wrong type.
274799d8fa1aSBob King     {
274899d8fa1aSBob King         json configFile = presenceDetectionFile;
274999d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
275099d8fa1aSBob King             "rule_id");
275199d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]
275299d8fa1aSBob King                   ["actions"] = true;
275399d8fa1aSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2754358c417aSBob King                             "True is not of type 'array'");
275599d8fa1aSBob King     }
275699d8fa1aSBob King     // Invalid: test presence_detection with property rule_id wrong format.
275799d8fa1aSBob King     {
275899d8fa1aSBob King         json configFile = presenceDetectionFile;
275999d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]
276099d8fa1aSBob King                   ["rule_id"] = "id@";
276199d8fa1aSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2762358c417aSBob King                             "'id@' does not match '^[A-Za-z0-9_]+$'");
276399d8fa1aSBob King     }
276499d8fa1aSBob King     // Invalid: test presence_detection with property comments empty array.
276599d8fa1aSBob King     {
276699d8fa1aSBob King         json configFile = presenceDetectionFile;
276799d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]
276899d8fa1aSBob King                   ["comments"] = json::array();
276999d8fa1aSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
277099d8fa1aSBob King                             "[] is too short");
277199d8fa1aSBob King     }
277299d8fa1aSBob King     // Invalid: test presence_detection with property actions empty array.
277399d8fa1aSBob King     {
277499d8fa1aSBob King         json configFile = presenceDetectionFile;
277599d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
277699d8fa1aSBob King             "rule_id");
277799d8fa1aSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]
277899d8fa1aSBob King                   ["actions"] = json::array();
277999d8fa1aSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
278099d8fa1aSBob King                             "[] is too short");
278199d8fa1aSBob King     }
278299d8fa1aSBob King }
2783846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,Rail)2784e9260b57SBob King TEST(ValidateRegulatorsConfigTest, Rail)
2785e9260b57SBob King {
2786e9260b57SBob King     // Valid: test rail.
2787e9260b57SBob King     {
2788e9260b57SBob King         json configFile = validConfigFile;
2789e9260b57SBob King         EXPECT_JSON_VALID(configFile);
2790e9260b57SBob King     }
2791e9260b57SBob King     // Valid: test rail with required properties.
2792e9260b57SBob King     {
2793e9260b57SBob King         json configFile = validConfigFile;
2794e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0].erase("comments");
2795e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0].erase(
2796e9260b57SBob King             "configuration");
2797e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0].erase(
2798e9260b57SBob King             "sensor_monitoring");
2799e9260b57SBob King         EXPECT_JSON_VALID(configFile);
2800e9260b57SBob King     }
2801e9260b57SBob King     // Invalid: test rail with no id.
2802e9260b57SBob King     {
2803e9260b57SBob King         json configFile = validConfigFile;
2804e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0].erase("id");
2805e9260b57SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2806358c417aSBob King                             "'id' is a required property");
2807e9260b57SBob King     }
2808e9260b57SBob King     // Invalid: test rail with comments wrong type.
2809e9260b57SBob King     {
2810e9260b57SBob King         json configFile = validConfigFile;
2811e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = true;
2812e9260b57SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2813358c417aSBob King                             "True is not of type 'array'");
2814e9260b57SBob King     }
2815e9260b57SBob King     // Invalid: test rail with id wrong type.
2816e9260b57SBob King     {
2817e9260b57SBob King         json configFile = validConfigFile;
2818e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = true;
2819e9260b57SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2820358c417aSBob King                             "True is not of type 'string'");
2821e9260b57SBob King     }
2822e9260b57SBob King     // Invalid: test rail with configuration wrong type.
2823e9260b57SBob King     {
2824e9260b57SBob King         json configFile = validConfigFile;
2825e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] =
2826e9260b57SBob King             true;
2827e9260b57SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2828358c417aSBob King                             "True is not of type 'object'");
2829e9260b57SBob King     }
2830e9260b57SBob King     // Invalid: test rail with sensor_monitoring wrong type.
2831e9260b57SBob King     {
2832e9260b57SBob King         json configFile = validConfigFile;
2833e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0]
2834e9260b57SBob King                   ["sensor_monitoring"] = true;
2835e9260b57SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2836358c417aSBob King                             "True is not of type 'object'");
2837e9260b57SBob King     }
2838e9260b57SBob King     // Invalid: test rail with comments empty array.
2839e9260b57SBob King     {
2840e9260b57SBob King         json configFile = validConfigFile;
2841e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] =
2842e9260b57SBob King             json::array();
2843e9260b57SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2844e9260b57SBob King                             "[] is too short");
2845e9260b57SBob King     }
2846e9260b57SBob King     // Invalid: test rail with id wrong format.
2847e9260b57SBob King     {
2848e9260b57SBob King         json configFile = validConfigFile;
2849e9260b57SBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = "id~";
2850e9260b57SBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2851358c417aSBob King                             "'id~' does not match '^[A-Za-z0-9_]+$'");
2852e9260b57SBob King     }
2853e9260b57SBob King }
2854846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,Rule)285564df7daaSBob King TEST(ValidateRegulatorsConfigTest, Rule)
285664df7daaSBob King {
285764df7daaSBob King     // valid test comments property, id property,
285864df7daaSBob King     // action property specified.
285964df7daaSBob King     {
286064df7daaSBob King         json configFile = validConfigFile;
286164df7daaSBob King         EXPECT_JSON_VALID(configFile);
286264df7daaSBob King     }
286364df7daaSBob King 
286464df7daaSBob King     // valid test rule with no comments
286564df7daaSBob King     {
286664df7daaSBob King         json configFile = validConfigFile;
286764df7daaSBob King         configFile["rules"][0].erase("comments");
286864df7daaSBob King         EXPECT_JSON_VALID(configFile);
286964df7daaSBob King     }
287064df7daaSBob King 
287164df7daaSBob King     // invalid test comments property has invalid value type
287264df7daaSBob King     {
287364df7daaSBob King         json configFile = validConfigFile;
287464df7daaSBob King         configFile["rules"][0]["comments"] = {1};
287564df7daaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2876358c417aSBob King                             "1 is not of type 'string'");
287764df7daaSBob King     }
287864df7daaSBob King 
287964df7daaSBob King     // invalid test rule with no ID
288064df7daaSBob King     {
288164df7daaSBob King         json configFile = validConfigFile;
288264df7daaSBob King         configFile["rules"][0].erase("id");
288364df7daaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2884358c417aSBob King                             "'id' is a required property");
288564df7daaSBob King     }
288664df7daaSBob King 
288764df7daaSBob King     // invalid test id property has invalid value type (not string)
288864df7daaSBob King     {
288964df7daaSBob King         json configFile = validConfigFile;
289064df7daaSBob King         configFile["rules"][0]["id"] = true;
289164df7daaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2892358c417aSBob King                             "True is not of type 'string'");
289364df7daaSBob King     }
289464df7daaSBob King 
289564df7daaSBob King     // invalid test id property has invalid value
289664df7daaSBob King     {
289764df7daaSBob King         json configFile = validConfigFile;
289864df7daaSBob King         configFile["rules"][0]["id"] = "foo%";
289964df7daaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2900358c417aSBob King                             "'foo%' does not match '^[A-Za-z0-9_]+$'");
290164df7daaSBob King     }
290264df7daaSBob King 
290364df7daaSBob King     // invalid test rule with no actions property
290464df7daaSBob King     {
290564df7daaSBob King         json configFile = validConfigFile;
290664df7daaSBob King         configFile["rules"][0].erase("actions");
290764df7daaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2908358c417aSBob King                             "'actions' is a required property");
290964df7daaSBob King     }
291064df7daaSBob King 
291164df7daaSBob King     // valid test rule with multiple actions
291264df7daaSBob King     {
291364df7daaSBob King         json configFile = validConfigFile;
291463d795f1SBob King         configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
291564df7daaSBob King         EXPECT_JSON_VALID(configFile);
291664df7daaSBob King     }
291764df7daaSBob King 
291864df7daaSBob King     // invalid test actions property has invalid value type (not an array)
291964df7daaSBob King     {
292064df7daaSBob King         json configFile = validConfigFile;
292164df7daaSBob King         configFile["rules"][0]["actions"] = 1;
292264df7daaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2923358c417aSBob King                             "1 is not of type 'array'");
292464df7daaSBob King     }
292564df7daaSBob King 
292664df7daaSBob King     // invalid test actions property has invalid value of action
292764df7daaSBob King     {
292864df7daaSBob King         json configFile = validConfigFile;
292964df7daaSBob King         configFile["rules"][0]["actions"][0] = "foo";
293064df7daaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2931358c417aSBob King                             "'foo' is not of type 'object'");
293264df7daaSBob King     }
293364df7daaSBob King 
293464df7daaSBob King     // invalid test actions property has empty array
293564df7daaSBob King     {
293664df7daaSBob King         json configFile = validConfigFile;
293764df7daaSBob King         configFile["rules"][0]["actions"] = json::array();
293864df7daaSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
293964df7daaSBob King                             "[] is too short");
294064df7daaSBob King     }
294164df7daaSBob King }
2942846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,RunRule)2943e86c2e5eSBob King TEST(ValidateRegulatorsConfigTest, RunRule)
2944e86c2e5eSBob King {
2945e86c2e5eSBob King     json runRuleFile = validConfigFile;
29467d3a9f1bSBob King     runRuleFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
2947e86c2e5eSBob King     // Valid: test run_rule.
2948e86c2e5eSBob King     {
2949e86c2e5eSBob King         json configFile = runRuleFile;
2950e86c2e5eSBob King         EXPECT_JSON_VALID(configFile);
2951e86c2e5eSBob King     }
2952e86c2e5eSBob King     // Invalid: test run_rule wrong type.
2953e86c2e5eSBob King     {
2954e86c2e5eSBob King         json configFile = runRuleFile;
2955e86c2e5eSBob King         configFile["rules"][0]["actions"][1]["run_rule"] = true;
2956e86c2e5eSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
2957358c417aSBob King                             "True is not of type 'string'");
2958e86c2e5eSBob King     }
2959e86c2e5eSBob King     // Invalid: test run_rule wrong format.
2960e86c2e5eSBob King     {
2961e86c2e5eSBob King         json configFile = runRuleFile;
2962e86c2e5eSBob King         configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%";
2963e86c2e5eSBob King         EXPECT_JSON_INVALID(
2964e86c2e5eSBob King             configFile, "Validation failed.",
2965358c417aSBob King             "'set_voltage_rule%' does not match '^[A-Za-z0-9_]+$'");
2966e86c2e5eSBob King     }
2967e86c2e5eSBob King }
2968846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,SensorMonitoring)2969fcc2a2fbSBob King TEST(ValidateRegulatorsConfigTest, SensorMonitoring)
2970fcc2a2fbSBob King {
2971fcc2a2fbSBob King     // Valid: test rails sensor_monitoring with only property rule id.
2972fcc2a2fbSBob King     {
2973fcc2a2fbSBob King         json configFile = validConfigFile;
2974fcc2a2fbSBob King         EXPECT_JSON_VALID(configFile);
2975fcc2a2fbSBob King     }
2976fcc2a2fbSBob King     // Valid: test rails sensor_monitoring with only property actions.
2977fcc2a2fbSBob King     {
2978fcc2a2fbSBob King         json configFile = validConfigFile;
2979fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2980fcc2a2fbSBob King             .erase("rule_id");
2981fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2982fcc2a2fbSBob King                   ["actions"][0]["compare_presence"]["fru"] =
2983a76898f1SBob King                       "system/chassis/motherboard/cpu3";
2984fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2985fcc2a2fbSBob King                   ["actions"][0]["compare_presence"]["value"] = true;
2986fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2987fcc2a2fbSBob King                   ["comments"][0] = "comments";
2988fcc2a2fbSBob King         EXPECT_JSON_VALID(configFile);
2989fcc2a2fbSBob King     }
2990fcc2a2fbSBob King     // Invalid: test rails sensor_monitoring with both property rule_id and
2991fcc2a2fbSBob King     // actions.
2992fcc2a2fbSBob King     {
2993fcc2a2fbSBob King         json configFile = validConfigFile;
2994fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2995fcc2a2fbSBob King                   ["actions"][0]["compare_presence"]["fru"] =
2996a76898f1SBob King                       "system/chassis/motherboard/cpu3";
2997fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2998fcc2a2fbSBob King                   ["actions"][0]["compare_presence"]["value"] = true;
2999846dde5dSShawn McCarney         EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
3000fcc2a2fbSBob King     }
3001fcc2a2fbSBob King     // Invalid: test rails sensor_monitoring with no rule_id and actions.
3002fcc2a2fbSBob King     {
3003fcc2a2fbSBob King         json configFile = validConfigFile;
3004fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3005fcc2a2fbSBob King             .erase("rule_id");
3006fcc2a2fbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
30070a2b76bcSShawn McCarney                             "{} is not valid under any of the given schemas");
3008fcc2a2fbSBob King     }
3009fcc2a2fbSBob King     // Invalid: test rails sensor_monitoring with property comments wrong type.
3010fcc2a2fbSBob King     {
3011fcc2a2fbSBob King         json configFile = validConfigFile;
3012fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3013fcc2a2fbSBob King                   ["comments"] = true;
3014fcc2a2fbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
3015358c417aSBob King                             "True is not of type 'array'");
3016fcc2a2fbSBob King     }
3017fcc2a2fbSBob King     // Invalid: test rails sensor_monitoring with property rule_id wrong type.
3018fcc2a2fbSBob King     {
3019fcc2a2fbSBob King         json configFile = validConfigFile;
3020fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3021fcc2a2fbSBob King                   ["rule_id"] = true;
3022fcc2a2fbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
3023358c417aSBob King                             "True is not of type 'string'");
3024fcc2a2fbSBob King     }
3025fcc2a2fbSBob King     // Invalid: test rails sensor_monitoring with property actions wrong type.
3026fcc2a2fbSBob King     {
3027fcc2a2fbSBob King         json configFile = validConfigFile;
3028fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3029fcc2a2fbSBob King             .erase("rule_id");
3030fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3031fcc2a2fbSBob King                   ["actions"] = true;
3032fcc2a2fbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
3033358c417aSBob King                             "True is not of type 'array'");
3034fcc2a2fbSBob King     }
3035fcc2a2fbSBob King     // Invalid: test rails sensor_monitoring with property rule_id wrong format.
3036fcc2a2fbSBob King     {
3037fcc2a2fbSBob King         json configFile = validConfigFile;
3038fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3039fcc2a2fbSBob King                   ["rule_id"] = "id@";
3040fcc2a2fbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
3041358c417aSBob King                             "'id@' does not match '^[A-Za-z0-9_]+$'");
3042fcc2a2fbSBob King     }
3043fcc2a2fbSBob King     // Invalid: test rails sensor_monitoring with property comments empty array.
3044fcc2a2fbSBob King     {
3045fcc2a2fbSBob King         json configFile = validConfigFile;
3046fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3047fcc2a2fbSBob King                   ["comments"] = json::array();
3048fcc2a2fbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
3049fcc2a2fbSBob King                             "[] is too short");
3050fcc2a2fbSBob King     }
3051fcc2a2fbSBob King     // Invalid: test rails sensor_monitoring with property actions empty array.
3052fcc2a2fbSBob King     {
3053fcc2a2fbSBob King         json configFile = validConfigFile;
3054fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3055fcc2a2fbSBob King             .erase("rule_id");
3056fcc2a2fbSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3057fcc2a2fbSBob King                   ["actions"] = json::array();
3058fcc2a2fbSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
3059fcc2a2fbSBob King                             "[] is too short");
3060fcc2a2fbSBob King     }
3061fcc2a2fbSBob King }
3062846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,SetDevice)306368230aaeSBob King TEST(ValidateRegulatorsConfigTest, SetDevice)
306468230aaeSBob King {
306568230aaeSBob King     json setDeviceFile = validConfigFile;
30667d3a9f1bSBob King     setDeviceFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator";
306768230aaeSBob King     // Valid: test set_device.
306868230aaeSBob King     {
306968230aaeSBob King         json configFile = setDeviceFile;
307068230aaeSBob King         EXPECT_JSON_VALID(configFile);
307168230aaeSBob King     }
307268230aaeSBob King     // Invalid: test set_device wrong type.
307368230aaeSBob King     {
307468230aaeSBob King         json configFile = setDeviceFile;
307568230aaeSBob King         configFile["rules"][0]["actions"][1]["set_device"] = true;
307668230aaeSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
3077358c417aSBob King                             "True is not of type 'string'");
307868230aaeSBob King     }
307968230aaeSBob King     // Invalid: test set_device wrong format.
308068230aaeSBob King     {
308168230aaeSBob King         json configFile = setDeviceFile;
308268230aaeSBob King         configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%";
3083358c417aSBob King         EXPECT_JSON_INVALID(configFile, "Validation failed.",
3084358c417aSBob King                             "'io_expander2%' does not match '^[A-Za-z0-9_]+$'");
308568230aaeSBob King     }
308668230aaeSBob King }
3087846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,DuplicateRuleID)30883643cc06SBob King TEST(ValidateRegulatorsConfigTest, DuplicateRuleID)
30893643cc06SBob King {
30903643cc06SBob King     // Invalid: test duplicate ID in rule.
30913643cc06SBob King     {
30923643cc06SBob King         json configFile = validConfigFile;
3093846dde5dSShawn McCarney         configFile["rules"][4]["id"] = "set_voltage_rule";
3094846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["pmbus_write_vout_command"]
30953643cc06SBob King                   ["format"] = "linear";
30963643cc06SBob King         EXPECT_JSON_INVALID(configFile, "Error: Duplicate rule ID.", "");
30973643cc06SBob King     }
30983643cc06SBob King }
3099846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,DuplicateChassisNumber)31003643cc06SBob King TEST(ValidateRegulatorsConfigTest, DuplicateChassisNumber)
31013643cc06SBob King {
31023643cc06SBob King     // Invalid: test duplicate number in chassis.
31033643cc06SBob King     {
31043643cc06SBob King         json configFile = validConfigFile;
31053643cc06SBob King         configFile["chassis"][1]["number"] = 1;
31064c88a4c2SShawn McCarney         configFile["chassis"][1]["inventory_path"] = "system/chassis2";
31073643cc06SBob King         EXPECT_JSON_INVALID(configFile, "Error: Duplicate chassis number.", "");
31083643cc06SBob King     }
31093643cc06SBob King }
3110846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,DuplicateDeviceID)31113643cc06SBob King TEST(ValidateRegulatorsConfigTest, DuplicateDeviceID)
31123643cc06SBob King {
31133643cc06SBob King     // Invalid: test duplicate ID in device.
31143643cc06SBob King     {
31153643cc06SBob King         json configFile = validConfigFile;
31163643cc06SBob King         configFile["chassis"][0]["devices"][1]["id"] = "vdd_regulator";
31173643cc06SBob King         configFile["chassis"][0]["devices"][1]["is_regulator"] = true;
31183643cc06SBob King         configFile["chassis"][0]["devices"][1]["fru"] =
3119a76898f1SBob King             "system/chassis/motherboard/regulator1";
31203643cc06SBob King         configFile["chassis"][0]["devices"][1]["i2c_interface"]["bus"] = 2;
31213643cc06SBob King         configFile["chassis"][0]["devices"][1]["i2c_interface"]["address"] =
31223643cc06SBob King             "0x71";
31233643cc06SBob King         EXPECT_JSON_INVALID(configFile, "Error: Duplicate device ID.", "");
31243643cc06SBob King     }
31253643cc06SBob King }
3126846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,DuplicateRailID)31273643cc06SBob King TEST(ValidateRegulatorsConfigTest, DuplicateRailID)
31283643cc06SBob King {
31293643cc06SBob King     // Invalid: test duplicate ID in rail.
31303643cc06SBob King     {
31313643cc06SBob King         json configFile = validConfigFile;
31323643cc06SBob King         configFile["chassis"][0]["devices"][0]["rails"][1]["id"] = "vdd";
31333643cc06SBob King         EXPECT_JSON_INVALID(configFile, "Error: Duplicate rail ID.", "");
31343643cc06SBob King     }
31353643cc06SBob King }
3136846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,DuplicateObjectID)313778793106SBob King TEST(ValidateRegulatorsConfigTest, DuplicateObjectID)
313878793106SBob King {
313978793106SBob King     // Invalid: test duplicate object ID in device and rail.
314078793106SBob King     {
314178793106SBob King         json configFile = validConfigFile;
314278793106SBob King         configFile["chassis"][0]["devices"][0]["rails"][1]["id"] =
314378793106SBob King             "vdd_regulator";
314478793106SBob King         EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
314578793106SBob King     }
314678793106SBob King     // Invalid: test duplicate object ID in device and rule.
314778793106SBob King     {
314878793106SBob King         json configFile = validConfigFile;
3149846dde5dSShawn McCarney         configFile["rules"][4]["id"] = "vdd_regulator";
3150846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["pmbus_write_vout_command"]
315178793106SBob King                   ["format"] = "linear";
315278793106SBob King         EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
315378793106SBob King     }
315478793106SBob King     // Invalid: test duplicate object ID in rule and rail.
315578793106SBob King     {
315678793106SBob King         json configFile = validConfigFile;
315778793106SBob King         configFile["chassis"][0]["devices"][0]["rails"][1]["id"] =
315878793106SBob King             "set_voltage_rule";
315978793106SBob King         EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
316078793106SBob King     }
316178793106SBob King }
3162846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,InfiniteLoops)31633643cc06SBob King TEST(ValidateRegulatorsConfigTest, InfiniteLoops)
31643643cc06SBob King {
31653643cc06SBob King     // Invalid: test run_rule with infinite loop (rules run each other).
31663643cc06SBob King     {
31673643cc06SBob King         json configFile = validConfigFile;
3168846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule2";
3169846dde5dSShawn McCarney         configFile["rules"][4]["id"] = "set_voltage_rule1";
3170846dde5dSShawn McCarney         configFile["rules"][5]["actions"][0]["run_rule"] = "set_voltage_rule1";
3171846dde5dSShawn McCarney         configFile["rules"][5]["id"] = "set_voltage_rule2";
31723643cc06SBob King         EXPECT_JSON_INVALID(configFile,
31733643cc06SBob King                             "Infinite loop caused by run_rule actions.", "");
31743643cc06SBob King     }
31753643cc06SBob King     // Invalid: test run_rule with infinite loop (rule runs itself).
31763643cc06SBob King     {
31773643cc06SBob King         json configFile = validConfigFile;
3178846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule1";
3179846dde5dSShawn McCarney         configFile["rules"][4]["id"] = "set_voltage_rule1";
31803643cc06SBob King         EXPECT_JSON_INVALID(configFile,
31813643cc06SBob King                             "Infinite loop caused by run_rule actions.", "");
31823643cc06SBob King     }
31833643cc06SBob King     // Invalid: test run_rule with infinite loop (indirect loop).
31843643cc06SBob King     {
31853643cc06SBob King         json configFile = validConfigFile;
3186846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule2";
3187846dde5dSShawn McCarney         configFile["rules"][4]["id"] = "set_voltage_rule1";
3188846dde5dSShawn McCarney         configFile["rules"][5]["actions"][0]["run_rule"] = "set_voltage_rule3";
3189846dde5dSShawn McCarney         configFile["rules"][5]["id"] = "set_voltage_rule2";
3190846dde5dSShawn McCarney         configFile["rules"][6]["actions"][0]["run_rule"] = "set_voltage_rule1";
3191846dde5dSShawn McCarney         configFile["rules"][6]["id"] = "set_voltage_rule3";
31923643cc06SBob King         EXPECT_JSON_INVALID(configFile,
31933643cc06SBob King                             "Infinite loop caused by run_rule actions.", "");
31943643cc06SBob King     }
31953643cc06SBob King }
3196846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,RunRuleValueExists)3197f88203a1SBob King TEST(ValidateRegulatorsConfigTest, RunRuleValueExists)
3198f88203a1SBob King {
3199f88203a1SBob King     // Invalid: test run_rule actions specify a rule ID that does not exist.
3200f88203a1SBob King     {
3201f88203a1SBob King         json configFile = validConfigFile;
3202846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule2";
3203846dde5dSShawn McCarney         configFile["rules"][4]["id"] = "set_voltage_rule1";
3204f88203a1SBob King         EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
3205f88203a1SBob King     }
3206f88203a1SBob King }
3207846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,SetDeviceValueExists)320813b2ad9dSBob King TEST(ValidateRegulatorsConfigTest, SetDeviceValueExists)
320913b2ad9dSBob King {
321013b2ad9dSBob King     // Invalid: test set_device actions specify a device ID that does not exist.
321113b2ad9dSBob King     {
321213b2ad9dSBob King         json configFile = validConfigFile;
3213846dde5dSShawn McCarney         configFile["rules"][4]["actions"][0]["set_device"] = "vdd_regulator2";
3214846dde5dSShawn McCarney         configFile["rules"][4]["id"] = "set_voltage_rule1";
321513b2ad9dSBob King         EXPECT_JSON_INVALID(configFile, "Error: Device ID does not exist.", "");
321613b2ad9dSBob King     }
321713b2ad9dSBob King }
3218846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,RuleIDExists)321921b09beaSBob King TEST(ValidateRegulatorsConfigTest, RuleIDExists)
322021b09beaSBob King {
322121b09beaSBob King     // Invalid: test rule_id property in configuration specifies a rule ID that
322221b09beaSBob King     // does not exist.
322321b09beaSBob King     {
322421b09beaSBob King         json configFile = validConfigFile;
322521b09beaSBob King         configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
322621b09beaSBob King             "set_voltage_rule2";
322721b09beaSBob King         EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
322821b09beaSBob King     }
322921b09beaSBob King     // Invalid: test rule_id property in presence_detection specifies a rule ID
323021b09beaSBob King     // that does not exist.
323121b09beaSBob King     {
323221b09beaSBob King         json configFile = validConfigFile;
323321b09beaSBob King         configFile["chassis"][0]["devices"][0]["presence_detection"]
32345d4a9c78SShawn McCarney                   ["rule_id"] = "detect_presence_rule2";
32355d4a9c78SShawn McCarney         EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
32365d4a9c78SShawn McCarney     }
32375d4a9c78SShawn McCarney     // Invalid: test rule_id property in phase_fault_detection specifies a rule
32385d4a9c78SShawn McCarney     // ID that does not exist.
32395d4a9c78SShawn McCarney     {
32405d4a9c78SShawn McCarney         json configFile = validConfigFile;
32415d4a9c78SShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
32425d4a9c78SShawn McCarney                   ["rule_id"] = "detect_phase_faults_rule2";
324321b09beaSBob King         EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
324421b09beaSBob King     }
324521b09beaSBob King     // Invalid: test rule_id property in sensor_monitoring specifies a rule ID
324621b09beaSBob King     // that does not exist.
324721b09beaSBob King     {
324821b09beaSBob King         json configFile = validConfigFile;
324921b09beaSBob King         configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
32505d4a9c78SShawn McCarney                   ["rule_id"] = "read_sensors_rule2";
325121b09beaSBob King         EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
325221b09beaSBob King     }
325321b09beaSBob King }
3254846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,DeviceIDExists)32555d4a9c78SShawn McCarney TEST(ValidateRegulatorsConfigTest, DeviceIDExists)
32565d4a9c78SShawn McCarney {
32575d4a9c78SShawn McCarney     // Invalid: test device_id property in phase_fault_detection specifies a
32585d4a9c78SShawn McCarney     // device ID that does not exist.
32595d4a9c78SShawn McCarney     {
32605d4a9c78SShawn McCarney         json configFile = validConfigFile;
32615d4a9c78SShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
32625d4a9c78SShawn McCarney                   ["device_id"] = "vdd_regulator2";
32635d4a9c78SShawn McCarney         configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
32645d4a9c78SShawn McCarney                   ["rule_id"] = "detect_phase_faults_rule";
32655d4a9c78SShawn McCarney         EXPECT_JSON_INVALID(configFile, "Error: Device ID does not exist.", "");
32665d4a9c78SShawn McCarney     }
32675d4a9c78SShawn McCarney }
32685d4a9c78SShawn McCarney 
TEST(ValidateRegulatorsConfigTest,NumberOfElementsInMasks)3269dc72b62aSBob King TEST(ValidateRegulatorsConfigTest, NumberOfElementsInMasks)
3270dc72b62aSBob King {
3271dc72b62aSBob King     // Invalid: test number of elements in masks not equal to number in values
3272dc72b62aSBob King     // in i2c_compare_bytes.
3273dc72b62aSBob King     {
3274dc72b62aSBob King         json configFile = validConfigFile;
3275dc72b62aSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
3276dc72b62aSBob King             "0x82";
3277dc72b62aSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = {
3278dc72b62aSBob King             "0x02", "0x73"};
3279dc72b62aSBob King         configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = {
3280dc72b62aSBob King             "0x7F"};
3281dc72b62aSBob King         EXPECT_JSON_INVALID(configFile,
3282dc72b62aSBob King                             "Error: Invalid i2c_compare_bytes action.", "");
3283dc72b62aSBob King     }
3284dc72b62aSBob King     // Invalid: test number of elements in masks not equal to number in values
3285dc72b62aSBob King     // in i2c_write_bytes.
3286dc72b62aSBob King     {
3287dc72b62aSBob King         json configFile = validConfigFile;
3288dc72b62aSBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
3289dc72b62aSBob King             "0x82";
3290dc72b62aSBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
3291dc72b62aSBob King             "0x02", "0x73"};
3292dc72b62aSBob King         configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
3293dc72b62aSBob King             "0x7F"};
3294dc72b62aSBob King         EXPECT_JSON_INVALID(configFile,
3295dc72b62aSBob King                             "Error: Invalid i2c_write_bytes action.", "");
3296dc72b62aSBob King     }
3297dc72b62aSBob King }
3298846dde5dSShawn McCarney 
TEST(ValidateRegulatorsConfigTest,CommandLineSyntax)3299ed009655SBob King TEST(ValidateRegulatorsConfigTest, CommandLineSyntax)
3300ed009655SBob King {
3301a57e0814SBob King     std::string validateTool =
3302a57e0814SBob King         " ../phosphor-regulators/tools/validate-regulators-config.py ";
3303ed009655SBob King     std::string schema = " -s ";
3304a57e0814SBob King     std::string schemaFile =
3305a57e0814SBob King         " ../phosphor-regulators/schema/config_schema.json ";
3306ed009655SBob King     std::string configuration = " -c ";
3307ed009655SBob King     std::string command;
3308ed009655SBob King     std::string errorMessage;
3309ed009655SBob King     std::string outputMessage;
3310ed009655SBob King     std::string outputMessageHelp =
3311ed009655SBob King         "usage: validate-regulators-config.py [-h] [-s SCHEMA_FILE]";
3312ed009655SBob King     int valid = 0;
3313ed009655SBob King 
33140f6ebadeSShawn McCarney     TemporaryFile tmpFile;
33150f6ebadeSShawn McCarney     std::string fileName = tmpFile.getPath().string();
3316a57e0814SBob King     writeDataToFile(validConfigFile, fileName);
3317ed009655SBob King     // Valid: -s specified
3318ed009655SBob King     {
3319ed009655SBob King         command = validateTool + "-s " + schemaFile + configuration + fileName;
3320ed009655SBob King         expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
3321ed009655SBob King     }
3322ed009655SBob King     // Valid: --schema-file specified
3323ed009655SBob King     {
3324ed009655SBob King         command = validateTool + "--schema-file " + schemaFile + configuration +
3325ed009655SBob King                   fileName;
3326ed009655SBob King         expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
3327ed009655SBob King     }
3328ed009655SBob King     // Valid: -c specified
3329ed009655SBob King     {
3330ed009655SBob King         command = validateTool + schema + schemaFile + "-c " + fileName;
3331ed009655SBob King         expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
3332ed009655SBob King     }
3333ed009655SBob King     // Valid: --configuration-file specified
3334ed009655SBob King     {
3335ed009655SBob King         command = validateTool + schema + schemaFile + "--configuration-file " +
3336ed009655SBob King                   fileName;
3337ed009655SBob King         expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
3338ed009655SBob King     }
3339ed009655SBob King     // Valid: -h specified
3340ed009655SBob King     {
3341ed009655SBob King         command = validateTool + "-h ";
3342ed009655SBob King         expectCommandLineSyntax(errorMessage, outputMessageHelp, command,
3343ed009655SBob King                                 valid);
3344ed009655SBob King     }
3345ed009655SBob King     // Valid: --help specified
3346ed009655SBob King     {
3347ed009655SBob King         command = validateTool + "--help ";
3348ed009655SBob King         expectCommandLineSyntax(errorMessage, outputMessageHelp, command,
3349ed009655SBob King                                 valid);
3350ed009655SBob King     }
3351ed009655SBob King     // Invalid: -c/--configuration-file not specified
3352ed009655SBob King     {
3353ed009655SBob King         command = validateTool + schema + schemaFile;
3354ed009655SBob King         expectCommandLineSyntax("Error: Configuration file is required.",
3355ed009655SBob King                                 outputMessageHelp, command, 1);
3356ed009655SBob King     }
3357ed009655SBob King     // Invalid: -s/--schema-file not specified
3358ed009655SBob King     {
3359ed009655SBob King         command = validateTool + configuration + fileName;
3360ed009655SBob King         expectCommandLineSyntax("Error: Schema file is required.",
3361ed009655SBob King                                 outputMessageHelp, command, 1);
3362ed009655SBob King     }
3363b7552f0cSBob King     // Invalid: -c specified more than once
3364b7552f0cSBob King     {
3365b7552f0cSBob King         command = validateTool + schema + schemaFile + "-c -c " + fileName;
3366b7552f0cSBob King         expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3367b7552f0cSBob King     }
3368ed009655SBob King     // Invalid: -s specified more than once
3369ed009655SBob King     {
337048781aefSPatrick Williams         command = validateTool + "-s -s " + schemaFile + configuration +
337148781aefSPatrick Williams                   fileName;
3372ed009655SBob King         expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3373ed009655SBob King     }
3374ed009655SBob King     // Invalid: No file name specified after -c
3375ed009655SBob King     {
3376ed009655SBob King         command = validateTool + schema + schemaFile + configuration;
3377ed009655SBob King         expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3378ed009655SBob King     }
3379ed009655SBob King     // Invalid: No file name specified after -s
3380ed009655SBob King     {
3381ed009655SBob King         command = validateTool + schema + configuration + fileName;
3382ed009655SBob King         expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3383ed009655SBob King     }
3384ed009655SBob King     // Invalid: File specified after -c does not exist
3385ed009655SBob King     {
3386ed009655SBob King         command = validateTool + schema + schemaFile + configuration +
3387ed009655SBob King                   "../notExistFile";
3388b7552f0cSBob King         expectCommandLineSyntax("Error: Configuration file does not exist.",
3389b7552f0cSBob King                                 outputMessageHelp, command, 1);
3390ed009655SBob King     }
3391ed009655SBob King     // Invalid: File specified after -s does not exist
3392ed009655SBob King     {
3393ed009655SBob King         command = validateTool + schema + "../notExistFile " + configuration +
3394ed009655SBob King                   fileName;
3395b7552f0cSBob King         expectCommandLineSyntax("Error: Schema file does not exist.",
3396b7552f0cSBob King                                 outputMessageHelp, command, 1);
3397b7552f0cSBob King     }
3398b7552f0cSBob King     // Invalid: File specified after -c is not right data format
3399b7552f0cSBob King     {
3400b7552f0cSBob King         TemporaryFile wrongFormatFile;
3401b7552f0cSBob King         std::string wrongFormatFileName = wrongFormatFile.getPath().string();
3402b7552f0cSBob King         std::ofstream out(wrongFormatFileName);
3403b7552f0cSBob King         out << "foo";
3404b7552f0cSBob King         out.close();
3405b7552f0cSBob King         command = validateTool + schema + schemaFile + configuration +
3406b7552f0cSBob King                   wrongFormatFileName;
3407ed009655SBob King         expectCommandLineSyntax(
3408b7552f0cSBob King             "Error: Configuration file is not in the JSON format.",
3409b7552f0cSBob King             outputMessageHelp, command, 1);
3410ed009655SBob King     }
3411ed009655SBob King     // Invalid: File specified after -s is not right data format
3412ed009655SBob King     {
34130f6ebadeSShawn McCarney         TemporaryFile wrongFormatFile;
34140f6ebadeSShawn McCarney         std::string wrongFormatFileName = wrongFormatFile.getPath().string();
3415a57e0814SBob King         std::ofstream out(wrongFormatFileName);
3416ed009655SBob King         out << "foo";
3417ed009655SBob King         out.close();
3418a57e0814SBob King         command = validateTool + schema + wrongFormatFileName + configuration +
3419a57e0814SBob King                   fileName;
3420b7552f0cSBob King         expectCommandLineSyntax("Error: Schema file is not in the JSON format.",
3421b7552f0cSBob King                                 outputMessageHelp, command, 1);
3422ed009655SBob King     }
3423ed009655SBob King     // Invalid: File specified after -c is not readable
3424ed009655SBob King     {
34250f6ebadeSShawn McCarney         TemporaryFile notReadableFile;
34260f6ebadeSShawn McCarney         std::string notReadableFileName = notReadableFile.getPath().string();
3427a57e0814SBob King         writeDataToFile(validConfigFile, notReadableFileName);
3428ed009655SBob King         command = validateTool + schema + schemaFile + configuration +
3429a57e0814SBob King                   notReadableFileName;
3430a57e0814SBob King         chmod(notReadableFileName.c_str(), 0222);
3431b7552f0cSBob King         expectCommandLineSyntax("Error: Configuration file is not readable.",
3432b7552f0cSBob King                                 outputMessageHelp, command, 1);
3433ed009655SBob King     }
3434ed009655SBob King     // Invalid: File specified after -s is not readable
3435ed009655SBob King     {
34360f6ebadeSShawn McCarney         TemporaryFile notReadableFile;
34370f6ebadeSShawn McCarney         std::string notReadableFileName = notReadableFile.getPath().string();
3438a57e0814SBob King         writeDataToFile(validConfigFile, notReadableFileName);
3439a57e0814SBob King         command = validateTool + schema + notReadableFileName + configuration +
3440a57e0814SBob King                   fileName;
3441a57e0814SBob King         chmod(notReadableFileName.c_str(), 0222);
3442b7552f0cSBob King         expectCommandLineSyntax("Error: Schema file is not readable.",
3443b7552f0cSBob King                                 outputMessageHelp, command, 1);
3444ed009655SBob King     }
3445ed009655SBob King     // Invalid: Unexpected parameter specified (like -g)
3446ed009655SBob King     {
3447ed009655SBob King         command = validateTool + schema + schemaFile + configuration +
3448ed009655SBob King                   fileName + " -g";
3449ed009655SBob King         expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3450ed009655SBob King     }
3451ed009655SBob King }
3452