blob: dac017fffcd6f73e2e6c29b518737742f1461ff6 [file] [log] [blame]
Bob King386d33f2019-12-26 17:28:56 +08001/**
Bob King0dcbdf52020-01-20 17:19:39 +08002 * Copyright c 2020 IBM Corporation
Bob King386d33f2019-12-26 17:28:56 +08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <errno.h>
17#include <stdio.h>
18#include <stdlib.h>
Bob Kinged009652020-02-20 14:54:13 +080019#include <sys/stat.h>
Bob King386d33f2019-12-26 17:28:56 +080020#include <sys/wait.h>
21
Bob King386d33f2019-12-26 17:28:56 +080022#include <nlohmann/json.hpp>
23
Bob King0dcbdf52020-01-20 17:19:39 +080024#include <fstream>
25
Bob King386d33f2019-12-26 17:28:56 +080026#include <gtest/gtest.h>
27
28#define EXPECT_FILE_VALID(configFile) expectFileValid(configFile)
29#define EXPECT_FILE_INVALID(configFile, expectedErrorMessage, \
30 expectedOutputMessage) \
31 expectFileInvalid(configFile, expectedErrorMessage, expectedOutputMessage)
32#define EXPECT_JSON_VALID(configFileJson) expectJsonValid(configFileJson)
33#define EXPECT_JSON_INVALID(configFileJson, expectedErrorMessage, \
34 expectedOutputMessage) \
35 expectJsonInvalid(configFileJson, expectedErrorMessage, \
36 expectedOutputMessage)
37
38using json = nlohmann::json;
39
40const json validConfigFile = R"(
41 {
42 "comments": [ "Config file for a FooBar one-chassis system" ],
43
44 "rules": [
45 {
46 "comments": [ "Sets output voltage for a PMBus regulator rail" ],
47 "id": "set_voltage_rule",
48 "actions": [
49 {
50 "pmbus_write_vout_command": {
51 "format": "linear"
52 }
53 }
54 ]
Bob Kingb3e48bc2020-02-18 09:59:09 +080055 },
56 {
57 "comments": [ "Reads sensors from a PMBus regulator rail" ],
58 "id": "read_sensors_rule",
59 "actions": [
60 {
61 "comments": [ "Read output voltage from READ_VOUT." ],
62 "pmbus_read_sensor": {
63 "type": "vout",
64 "command": "0x8B",
65 "format": "linear_16"
66 }
67 }
68 ]
Bob King386d33f2019-12-26 17:28:56 +080069 }
70 ],
71
72 "chassis": [
73 {
74 "comments": [ "Chassis number 1 containing CPUs and memory" ],
75 "number": 1,
76 "devices": [
77 {
78 "comments": [ "IR35221 regulator producing the Vdd rail" ],
79 "id": "vdd_regulator",
80 "is_regulator": true,
81 "fru": "/system/chassis/motherboard/regulator1",
82 "i2c_interface": {
83 "bus": 1,
84 "address": "0x70"
85 },
86 "rails": [
87 {
88 "comments": [ "Vdd rail" ],
89 "id": "vdd",
90 "configuration": {
91 "volts": 1.03,
92 "rule_id": "set_voltage_rule"
93 },
94 "sensor_monitoring": {
95 "rule_id": "read_sensors_rule"
96 }
97 }
98 ]
99 }
100 ]
101 }
102 ]
103 }
104)"_json;
105
Bob Kinga57e0812020-03-12 10:47:42 +0800106class TmpFile
Bob King386d33f2019-12-26 17:28:56 +0800107{
Bob Kinga57e0812020-03-12 10:47:42 +0800108 public:
109 TmpFile()
Bob King386d33f2019-12-26 17:28:56 +0800110 {
Bob Kinga57e0812020-03-12 10:47:42 +0800111 int fd = mkstemp(fileName);
112 if (fd == -1)
113 {
114 perror("Can't create temporary file");
115 }
116 close(fd);
Bob King386d33f2019-12-26 17:28:56 +0800117 }
Bob Kinga57e0812020-03-12 10:47:42 +0800118
119 std::string getName()
120 {
121 return fileName;
122 }
123
124 ~TmpFile()
125 {
126 unlink(fileName);
127 }
128
129 private:
130 char fileName[17] = "/tmp/temp-XXXXXX";
131};
Bob King386d33f2019-12-26 17:28:56 +0800132
133std::string getValidationToolCommand(const std::string& configFileName)
134{
Bob Kinga57e0812020-03-12 10:47:42 +0800135 std::string command =
136 "../phosphor-regulators/tools/validate-regulators-config.py -s \
137 ../phosphor-regulators/schema/config_schema.json -c ";
Bob King386d33f2019-12-26 17:28:56 +0800138 command += configFileName;
139 return command;
140}
141
Bob Kinga57e0812020-03-12 10:47:42 +0800142int runToolForOutputWithCommand(std::string command,
143 std::string& standardOutput,
144 std::string& standardError)
Bob King386d33f2019-12-26 17:28:56 +0800145{
146 // run the validation tool with the temporary file and return the output
147 // of the validation tool.
Bob Kinga57e0812020-03-12 10:47:42 +0800148 TmpFile tmpFile;
149 command += " 2> " + tmpFile.getName();
Bob King386d33f2019-12-26 17:28:56 +0800150 // get the jsonschema print from validation tool.
151 char buffer[256];
Bob Kinga57e0812020-03-12 10:47:42 +0800152 std::string result;
Bob King386d33f2019-12-26 17:28:56 +0800153 // to get the stdout from the validation tool.
154 FILE* pipe = popen(command.c_str(), "r");
155 if (!pipe)
156 {
157 throw std::runtime_error("popen() failed!");
158 }
159 while (!std::feof(pipe))
160 {
161 if (fgets(buffer, sizeof buffer, pipe) != NULL)
162 {
163 result += buffer;
164 }
165 }
166 int returnValue = pclose(pipe);
167 // Check if pclose() failed
168 if (returnValue == -1)
169 {
170 // unable to close pipe. Print error and exit function.
171 throw std::runtime_error("pclose() failed!");
172 }
173 std::string firstLine = result.substr(0, result.find('\n'));
Bob Kinga57e0812020-03-12 10:47:42 +0800174 standardOutput = firstLine;
Bob King386d33f2019-12-26 17:28:56 +0800175 // Get command exit status from return value
176 int exitStatus = WEXITSTATUS(returnValue);
Bob Kinga57e0812020-03-12 10:47:42 +0800177
178 // Read the standardError from tmpFile.
179 std::ifstream input(tmpFile.getName().c_str());
180 std::string line;
181
182 if (std::getline(input, line))
183 {
184 standardError = line;
185 }
186
Bob King386d33f2019-12-26 17:28:56 +0800187 return exitStatus;
188}
189
Bob Kinged009652020-02-20 14:54:13 +0800190int runToolForOutput(const std::string& configFileName, std::string& output,
Bob Kinga57e0812020-03-12 10:47:42 +0800191 std::string& error)
Bob Kinged009652020-02-20 14:54:13 +0800192{
193 std::string command = getValidationToolCommand(configFileName);
Bob Kinga57e0812020-03-12 10:47:42 +0800194 return runToolForOutputWithCommand(command, output, error);
Bob Kinged009652020-02-20 14:54:13 +0800195}
196
Bob King386d33f2019-12-26 17:28:56 +0800197void expectFileValid(const std::string& configFileName)
198{
Bob Kinged009652020-02-20 14:54:13 +0800199 std::string errorMessage;
200 std::string outputMessage;
Bob Kinga57e0812020-03-12 10:47:42 +0800201 EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 0);
Bob King386d33f2019-12-26 17:28:56 +0800202 EXPECT_EQ(errorMessage, "");
203 EXPECT_EQ(outputMessage, "");
204}
205
206void expectFileInvalid(const std::string& configFileName,
207 const std::string& expectedErrorMessage,
208 const std::string& expectedOutputMessage)
209{
Bob Kinged009652020-02-20 14:54:13 +0800210 std::string errorMessage;
211 std::string outputMessage;
Bob Kinga57e0812020-03-12 10:47:42 +0800212 EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 1);
Bob King386d33f2019-12-26 17:28:56 +0800213 EXPECT_EQ(errorMessage, expectedErrorMessage);
214 EXPECT_EQ(outputMessage, expectedOutputMessage);
215}
216
Bob Kinga57e0812020-03-12 10:47:42 +0800217void writeDataToFile(const json configFileJson, std::string fileName)
Bob King386d33f2019-12-26 17:28:56 +0800218{
Bob King386d33f2019-12-26 17:28:56 +0800219 std::string jsonData = configFileJson.dump();
220 std::ofstream out(fileName);
221 out << jsonData;
222 out.close();
Bob Kinged009652020-02-20 14:54:13 +0800223}
224
225void expectJsonValid(const json configFileJson)
226{
227 std::string fileName;
Bob Kinga57e0812020-03-12 10:47:42 +0800228 TmpFile tmpFile;
229 fileName = tmpFile.getName();
230 writeDataToFile(configFileJson, fileName);
Bob Kinged009652020-02-20 14:54:13 +0800231
Bob King386d33f2019-12-26 17:28:56 +0800232 EXPECT_FILE_VALID(fileName);
Bob King386d33f2019-12-26 17:28:56 +0800233}
234
235void expectJsonInvalid(const json configFileJson,
236 const std::string& expectedErrorMessage,
237 const std::string& expectedOutputMessage)
238{
239 std::string fileName;
Bob Kinga57e0812020-03-12 10:47:42 +0800240 TmpFile tmpFile;
241 fileName = tmpFile.getName();
242 writeDataToFile(configFileJson, fileName);
Bob King386d33f2019-12-26 17:28:56 +0800243
244 EXPECT_FILE_INVALID(fileName, expectedErrorMessage, expectedOutputMessage);
Bob King386d33f2019-12-26 17:28:56 +0800245}
246
Bob Kinged009652020-02-20 14:54:13 +0800247void expectCommandLineSyntax(const std::string& expectedErrorMessage,
248 const std::string& expectedOutputMessage,
249 std::string command, int status)
250{
251 std::string errorMessage;
252 std::string outputMessage;
Bob Kinga57e0812020-03-12 10:47:42 +0800253 EXPECT_EQ(runToolForOutputWithCommand(command, outputMessage, errorMessage),
254 status);
Bob Kinged009652020-02-20 14:54:13 +0800255 EXPECT_EQ(errorMessage, expectedErrorMessage);
256 EXPECT_EQ(outputMessage, expectedOutputMessage);
257}
258
Bob Kingbeaf6532020-01-21 11:03:49 +0800259TEST(ValidateRegulatorsConfigTest, And)
260{
261 // Valid.
262 {
263 json configFile = validConfigFile;
264 json andAction =
265 R"(
266 {
267 "and": [
268 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
269 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
270 ]
271 }
272 )"_json;
273 configFile["rules"][0]["actions"].push_back(andAction);
274 EXPECT_JSON_VALID(configFile);
275 }
276
277 // Invalid: actions property value is an empty array.
278 {
279 json configFile = validConfigFile;
280 json andAction =
281 R"(
282 {
283 "and": []
284 }
285 )"_json;
286 configFile["rules"][0]["actions"].push_back(andAction);
287 EXPECT_JSON_INVALID(configFile, "Validation failed.",
288 "[] is too short");
289 }
290
291 // Invalid: actions property has incorrect value data type.
292 {
293 json configFile = validConfigFile;
294 json andAction =
295 R"(
296 {
297 "and": true
298 }
299 )"_json;
300 configFile["rules"][0]["actions"].push_back(andAction);
301 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800302 "True is not of type 'array'");
Bob Kingbeaf6532020-01-21 11:03:49 +0800303 }
304
305 // Invalid: actions property value contains wrong element type
306 {
307 json configFile = validConfigFile;
308 json andAction =
309 R"(
310 {
311 "and": ["foo"]
312 }
313 )"_json;
314 configFile["rules"][0]["actions"].push_back(andAction);
315 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800316 "'foo' is not of type 'object'");
Bob Kingbeaf6532020-01-21 11:03:49 +0800317 }
318}
Bob King3728f562020-01-21 11:35:31 +0800319TEST(ValidateRegulatorsConfigTest, Chassis)
320{
321 // Valid: test chassis.
322 {
323 json configFile = validConfigFile;
324 EXPECT_JSON_VALID(configFile);
325 }
326 // Valid: test chassis with required properties.
327 {
328 json configFile = validConfigFile;
329 configFile["chassis"][0].erase("comments");
330 configFile["chassis"][0].erase("devices");
331 EXPECT_JSON_VALID(configFile);
332 }
333 // Invalid: test chassis with no number.
334 {
335 json configFile = validConfigFile;
336 configFile["chassis"][0].erase("number");
337 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800338 "'number' is a required property");
Bob King3728f562020-01-21 11:35:31 +0800339 }
340 // Invalid: test chassis with property comments wrong type.
341 {
342 json configFile = validConfigFile;
343 configFile["chassis"][0]["comments"] = true;
344 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800345 "True is not of type 'array'");
Bob King3728f562020-01-21 11:35:31 +0800346 }
347 // Invalid: test chassis with property number wrong type.
348 {
349 json configFile = validConfigFile;
350 configFile["chassis"][0]["number"] = 1.3;
351 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800352 "1.3 is not of type 'integer'");
Bob King3728f562020-01-21 11:35:31 +0800353 }
354 // Invalid: test chassis with property devices wrong type.
355 {
356 json configFile = validConfigFile;
357 configFile["chassis"][0]["devices"] = true;
358 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800359 "True is not of type 'array'");
Bob King3728f562020-01-21 11:35:31 +0800360 }
361 // Invalid: test chassis with property comments empty array.
362 {
363 json configFile = validConfigFile;
364 configFile["chassis"][0]["comments"] = json::array();
365 EXPECT_JSON_INVALID(configFile, "Validation failed.",
366 "[] is too short");
367 }
368 // Invalid: test chassis with property devices empty array.
369 {
370 json configFile = validConfigFile;
371 configFile["chassis"][0]["devices"] = json::array();
372 EXPECT_JSON_INVALID(configFile, "Validation failed.",
373 "[] is too short");
374 }
375 // Invalid: test chassis with property number less than 1.
376 {
377 json configFile = validConfigFile;
378 configFile["chassis"][0]["number"] = 0;
379 EXPECT_JSON_INVALID(configFile, "Validation failed.",
380 "0 is less than the minimum of 1");
381 }
382}
Bob Kingbf1cbea2020-01-21 11:08:50 +0800383TEST(ValidateRegulatorsConfigTest, ComparePresence)
384{
385 json comparePresenceFile = validConfigFile;
386 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
387 "/system/chassis/motherboard/regulator2";
388 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
389 true;
390 // Valid.
391 {
392 json configFile = comparePresenceFile;
393 EXPECT_JSON_VALID(configFile);
394 }
395
396 // Invalid: no FRU property.
397 {
398 json configFile = comparePresenceFile;
399 configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru");
400 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800401 "'fru' is a required property");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800402 }
403
404 // Invalid: FRU property length is string less than 1.
405 {
406 json configFile = comparePresenceFile;
407 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = "";
408 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800409 "'' is too short");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800410 }
411
412 // Invalid: no value property.
413 {
414 json configFile = comparePresenceFile;
415 configFile["rules"][0]["actions"][1]["compare_presence"].erase("value");
416 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800417 "'value' is a required property");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800418 }
419
420 // Invalid: value property type is not boolean.
421 {
422 json configFile = comparePresenceFile;
423 configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1";
424 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800425 "'1' is not of type 'boolean'");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800426 }
427
428 // Invalid: FRU property type is not string.
429 {
430 json configFile = comparePresenceFile;
431 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1;
432 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800433 "1 is not of type 'string'");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800434 }
435}
Bob Kingf8b77a02020-01-21 11:09:47 +0800436TEST(ValidateRegulatorsConfigTest, CompareVpd)
437{
438 json compareVpdFile = validConfigFile;
439 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
440 "/system/chassis/motherboard/regulator2";
441 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
442 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
443
444 // Valid.
445 {
446 json configFile = compareVpdFile;
447 EXPECT_JSON_VALID(configFile);
448 }
449
450 // Invalid: no FRU property.
451 {
452 json configFile = compareVpdFile;
453 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru");
454 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800455 "'fru' is a required property");
Bob Kingf8b77a02020-01-21 11:09:47 +0800456 }
457
458 // Invalid: no keyword property.
459 {
460 json configFile = compareVpdFile;
461 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword");
462 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800463 "'keyword' is a required property");
Bob Kingf8b77a02020-01-21 11:09:47 +0800464 }
465
466 // Invalid: no value property.
467 {
468 json configFile = compareVpdFile;
469 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
470 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800471 "'value' is a required property");
Bob Kingf8b77a02020-01-21 11:09:47 +0800472 }
473
474 // Invalid: property FRU wrong type.
475 {
476 json configFile = compareVpdFile;
477 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1;
478 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800479 "1 is not of type 'string'");
Bob Kingf8b77a02020-01-21 11:09:47 +0800480 }
481
482 // Invalid: property FRU is string less than 1.
483 {
484 json configFile = compareVpdFile;
485 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = "";
486 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800487 "'' is too short");
Bob Kingf8b77a02020-01-21 11:09:47 +0800488 }
489
490 // Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
491 // "PartNumber"
492 {
493 json configFile = compareVpdFile;
494 configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
495 "Number";
496 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800497 "'Number' is not one of ['CCIN', "
498 "'Manufacturer', 'Model', 'PartNumber']");
Bob Kingf8b77a02020-01-21 11:09:47 +0800499 }
500
501 // Invalid: property value wrong type.
502 {
503 json configFile = compareVpdFile;
504 configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1;
505 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800506 "1 is not of type 'string'");
Bob Kingf8b77a02020-01-21 11:09:47 +0800507 }
508}
Bob King4c67a3a2020-02-07 09:48:11 +0800509TEST(ValidateRegulatorsConfigTest, Configuration)
510{
511 json configurationFile = validConfigFile;
512 configurationFile["chassis"][0]["devices"][0]["configuration"]["comments"]
513 [0] = "Set rail to 1.25V using standard rule";
514 configurationFile["chassis"][0]["devices"][0]["configuration"]["volts"] =
515 1.25;
516 configurationFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
517 "set_voltage_rule";
518 // Valid: test configuration with property rule_id and with no actions.
519 {
520 json configFile = configurationFile;
Bob King78793102020-03-13 13:16:09 +0800521 configFile["chassis"][0]["devices"][0]["configuration"]["comments"][1] =
522 "test multiple array elements in comments.";
Bob King4c67a3a2020-02-07 09:48:11 +0800523 EXPECT_JSON_VALID(configFile);
524 }
525 // Valid: test configuration with property actions and with no rule_id.
526 {
527 json configFile = configurationFile;
528 configFile["chassis"][0]["devices"][0]["configuration"].erase(
529 "rule_id");
530 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
531 ["compare_presence"]["fru"] =
532 "/system/chassis/motherboard/cpu3";
533 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
534 ["compare_presence"]["value"] = true;
535 EXPECT_JSON_VALID(configFile);
536 }
537 // Valid: comments not specified (optional property).
538 {
539 json configFile = configurationFile;
540 configFile["chassis"][0]["devices"][0]["configuration"].erase(
541 "comments");
542 EXPECT_JSON_VALID(configFile);
543 }
544 // Valid: volts not specified (optional property).
545 {
546 json configFile = configurationFile;
547 configFile["chassis"][0]["devices"][0]["configuration"].erase("volts");
548 EXPECT_JSON_VALID(configFile);
549 }
550 // Valid: configuration is property of a rail (vs. a device).
551 {
552 json configFile = validConfigFile;
553 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
554 ["comments"][0] = "Set rail to 1.25V using standard rule";
555 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
556 ["volts"] = 1.25;
557 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
558 ["rule_id"] = "set_voltage_rule";
559 EXPECT_JSON_VALID(configFile);
560 }
561 // Invalid: comments property has wrong data type (not an array).
562 {
563 json configFile = configurationFile;
564 configFile["chassis"][0]["devices"][0]["configuration"]["comments"] = 1;
565 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800566 "1 is not of type 'array'");
Bob King4c67a3a2020-02-07 09:48:11 +0800567 }
568 // Invalid: test configuration with both actions and rule_id properties.
569 {
570 json configFile = configurationFile;
571 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
572 ["compare_presence"]["fru"] =
573 "/system/chassis/motherboard/cpu3";
574 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
575 ["compare_presence"]["value"] = true;
576 EXPECT_JSON_INVALID(
577 configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800578 "{'actions': [{'compare_presence': {'fru': "
579 "'/system/chassis/motherboard/cpu3', 'value': True}}], 'comments': "
580 "['Set rail to 1.25V using standard rule'], 'rule_id': "
581 "'set_voltage_rule', 'volts': 1.25} is valid under each of "
582 "{'required': ['actions']}, {'required': ['rule_id']}");
Bob King4c67a3a2020-02-07 09:48:11 +0800583 }
584 // Invalid: test configuration with no rule_id and actions.
585 {
586 json configFile = configurationFile;
587 configFile["chassis"][0]["devices"][0]["configuration"].erase(
588 "rule_id");
589 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800590 "'rule_id' is a required property");
Bob King4c67a3a2020-02-07 09:48:11 +0800591 }
592 // Invalid: test configuration with property volts wrong type.
593 {
594 json configFile = configurationFile;
595 configFile["chassis"][0]["devices"][0]["configuration"]["volts"] = true;
596 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800597 "True is not of type 'number'");
Bob King4c67a3a2020-02-07 09:48:11 +0800598 }
599 // Invalid: test configuration with property rule_id wrong type.
600 {
601 json configFile = configurationFile;
602 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
603 true;
604 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800605 "True is not of type 'string'");
Bob King4c67a3a2020-02-07 09:48:11 +0800606 }
607 // Invalid: test configuration with property actions wrong type.
608 {
609 json configFile = configurationFile;
610 configFile["chassis"][0]["devices"][0]["configuration"].erase(
611 "rule_id");
612 configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
613 true;
614 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800615 "True is not of type 'array'");
Bob King4c67a3a2020-02-07 09:48:11 +0800616 }
617 // Invalid: test configuration with property comments empty array.
618 {
619 json configFile = configurationFile;
620 configFile["chassis"][0]["devices"][0]["configuration"]["comments"] =
621 json::array();
622 EXPECT_JSON_INVALID(configFile, "Validation failed.",
623 "[] is too short");
624 }
625 // Invalid: test configuration with property rule_id wrong format.
626 {
627 json configFile = configurationFile;
628 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
629 "id!";
630 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800631 "'id!' does not match '^[A-Za-z0-9_]+$'");
Bob King4c67a3a2020-02-07 09:48:11 +0800632 }
633 // Invalid: test configuration with property actions empty array.
634 {
635 json configFile = configurationFile;
636 configFile["chassis"][0]["devices"][0]["configuration"].erase(
637 "rule_id");
638 configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
639 json::array();
640 EXPECT_JSON_INVALID(configFile, "Validation failed.",
641 "[] is too short");
642 }
643}
Bob Kinga2ba2df2020-02-04 14:38:44 +0800644TEST(ValidateRegulatorsConfigTest, Device)
645{
646
647 // Valid: test devices.
648 {
649 json configFile = validConfigFile;
650 EXPECT_JSON_VALID(configFile);
651 }
652 // Valid: test devices with required properties.
653 {
654 json configFile = validConfigFile;
655 configFile["chassis"][0]["devices"][0].erase("comments");
656 configFile["chassis"][0]["devices"][0].erase("presence_detection");
657 configFile["chassis"][0]["devices"][0].erase("configuration");
658 configFile["chassis"][0]["devices"][0].erase("rails");
659 EXPECT_JSON_VALID(configFile);
660 }
661 // Invalid: test devices with no id.
662 {
663 json configFile = validConfigFile;
664 configFile["chassis"][0]["devices"][0].erase("id");
665 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800666 "'id' is a required property");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800667 }
668 // Invalid: test devices with no is_regulator.
669 {
670 json configFile = validConfigFile;
671 configFile["chassis"][0]["devices"][0].erase("is_regulator");
672 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800673 "'is_regulator' is a required property");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800674 }
675 // Invalid: test devices with no fru.
676 {
677 json configFile = validConfigFile;
678 configFile["chassis"][0]["devices"][0].erase("fru");
679 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800680 "'fru' is a required property");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800681 }
682 // Invalid: test devices with no i2c_interface.
683 {
684 json configFile = validConfigFile;
685 configFile["chassis"][0]["devices"][0].erase("i2c_interface");
686 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800687 "'i2c_interface' is a required property");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800688 }
689 // Invalid: test devices with property comments wrong type.
690 {
691 json configFile = validConfigFile;
692 configFile["chassis"][0]["devices"][0]["comments"] = true;
693 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800694 "True is not of type 'array'");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800695 }
696 // Invalid: test devices with property id wrong type.
697 {
698 json configFile = validConfigFile;
699 configFile["chassis"][0]["devices"][0]["id"] = true;
700 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800701 "True is not of type 'string'");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800702 }
703 // Invalid: test devices with property is_regulator wrong type.
704 {
705 json configFile = validConfigFile;
706 configFile["chassis"][0]["devices"][0]["is_regulator"] = 1;
707 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800708 "1 is not of type 'boolean'");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800709 }
710 // Invalid: test devices with property fru wrong type.
711 {
712 json configFile = validConfigFile;
713 configFile["chassis"][0]["devices"][0]["fru"] = true;
714 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800715 "True is not of type 'string'");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800716 }
717 // Invalid: test devices with property i2c_interface wrong type.
718 {
719 json configFile = validConfigFile;
720 configFile["chassis"][0]["devices"][0]["i2c_interface"] = true;
721 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800722 "True is not of type 'object'");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800723 }
724 // Invalid: test devices with property presence_detection wrong
725 // type.
726 {
727 json configFile = validConfigFile;
728 configFile["chassis"][0]["devices"][0]["presence_detection"] = true;
729 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800730 "True is not of type 'object'");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800731 }
732 // Invalid: test devices with property configuration wrong type.
733 {
734 json configFile = validConfigFile;
735 configFile["chassis"][0]["devices"][0]["configuration"] = true;
736 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800737 "True is not of type 'object'");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800738 }
739 // Invalid: test devices with property rails wrong type.
740 {
741 json configFile = validConfigFile;
742 configFile["chassis"][0]["devices"][0]["rails"] = true;
743 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800744 "True is not of type 'array'");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800745 }
746 // Invalid: test devices with property comments empty array.
747 {
748 json configFile = validConfigFile;
749 configFile["chassis"][0]["devices"][0]["comments"] = json::array();
750 EXPECT_JSON_INVALID(configFile, "Validation failed.",
751 "[] is too short");
752 }
753 // Invalid: test devices with property fru length less than 1.
754 {
755 json configFile = validConfigFile;
756 configFile["chassis"][0]["devices"][0]["fru"] = "";
757 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800758 "'' is too short");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800759 }
760 // Invalid: test devices with property id wrong format.
761 {
762 json configFile = validConfigFile;
763 configFile["chassis"][0]["devices"][0]["id"] = "id#";
764 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800765 "'id#' does not match '^[A-Za-z0-9_]+$'");
Bob Kinga2ba2df2020-02-04 14:38:44 +0800766 }
767 // Invalid: test devices with property rails empty array.
768 {
769 json configFile = validConfigFile;
770 configFile["chassis"][0]["devices"][0]["rails"] = json::array();
771 EXPECT_JSON_INVALID(configFile, "Validation failed.",
772 "[] is too short");
773 }
774}
Bob King4ab8cbb2020-01-21 11:10:48 +0800775TEST(ValidateRegulatorsConfigTest, I2CCompareBit)
776{
777 json i2cCompareBitFile = validConfigFile;
778 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
779 "0xA0";
780 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
781 3;
782 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
783 // Valid: test rule actions i2c_compare_bit.
784 {
785 json configFile = i2cCompareBitFile;
786 EXPECT_JSON_VALID(configFile);
787 }
788 // Invalid: test i2c_compare_bit with no register.
789 {
790 json configFile = i2cCompareBitFile;
791 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
792 "register");
793 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800794 "'register' is a required property");
Bob King4ab8cbb2020-01-21 11:10:48 +0800795 }
796 // Invalid: test i2c_compare_bit with no position.
797 {
798 json configFile = i2cCompareBitFile;
799 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
800 "position");
801 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800802 "'position' is a required property");
Bob King4ab8cbb2020-01-21 11:10:48 +0800803 }
804 // Invalid: test i2c_compare_bit with no value.
805 {
806 json configFile = i2cCompareBitFile;
807 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value");
808 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800809 "'value' is a required property");
Bob King4ab8cbb2020-01-21 11:10:48 +0800810 }
811 // Invalid: test i2c_compare_bit with register wrong type.
812 {
813 json configFile = i2cCompareBitFile;
814 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1;
815 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800816 "1 is not of type 'string'");
Bob King4ab8cbb2020-01-21 11:10:48 +0800817 }
818 // Invalid: test i2c_compare_bit with register wrong format.
819 {
820 json configFile = i2cCompareBitFile;
821 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
822 "0xA00";
823 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800824 "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King4ab8cbb2020-01-21 11:10:48 +0800825 }
826 // Invalid: test i2c_compare_bit with position wrong type.
827 {
828 json configFile = i2cCompareBitFile;
829 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
830 3.1;
831 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800832 "3.1 is not of type 'integer'");
Bob King4ab8cbb2020-01-21 11:10:48 +0800833 }
834 // Invalid: test i2c_compare_bit with position greater than 7.
835 {
836 json configFile = i2cCompareBitFile;
837 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8;
838 EXPECT_JSON_INVALID(configFile, "Validation failed.",
839 "8 is greater than the maximum of 7");
840 }
841 // Invalid: test i2c_compare_bit with position less than 0.
842 {
843 json configFile = i2cCompareBitFile;
844 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
845 -1;
846 EXPECT_JSON_INVALID(configFile, "Validation failed.",
847 "-1 is less than the minimum of 0");
848 }
849 // Invalid: test i2c_compare_bit with value wrong type.
850 {
851 json configFile = i2cCompareBitFile;
852 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1";
853 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800854 "'1' is not of type 'integer'");
Bob King4ab8cbb2020-01-21 11:10:48 +0800855 }
856 // Invalid: test i2c_compare_bit with value greater than 1.
857 {
858 json configFile = i2cCompareBitFile;
859 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2;
860 EXPECT_JSON_INVALID(configFile, "Validation failed.",
861 "2 is greater than the maximum of 1");
862 }
863 // Invalid: test i2c_compare_bit with value less than 0.
864 {
865 json configFile = i2cCompareBitFile;
866 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1;
867 EXPECT_JSON_INVALID(configFile, "Validation failed.",
868 "-1 is less than the minimum of 0");
869 }
870}
Bob King514023d2020-01-21 11:13:05 +0800871TEST(ValidateRegulatorsConfigTest, I2CCompareByte)
872{
873 json i2cCompareByteFile = validConfigFile;
874 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]
875 ["register"] = "0x82";
876 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
877 "0x40";
878 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
879 "0x7F";
880 // Valid: test i2c_compare_byte with all properties.
881 {
882 json configFile = i2cCompareByteFile;
883 EXPECT_JSON_VALID(configFile);
884 }
885 // Valid: test i2c_compare_byte with all required properties.
886 {
887 json configFile = i2cCompareByteFile;
888 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask");
889 EXPECT_JSON_VALID(configFile);
890 }
891 // Invalid: test i2c_compare_byte with no register.
892 {
893 json configFile = i2cCompareByteFile;
894 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase(
895 "register");
896 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800897 "'register' is a required property");
Bob King514023d2020-01-21 11:13:05 +0800898 }
899 // Invalid: test i2c_compare_byte with no value.
900 {
901 json configFile = i2cCompareByteFile;
902 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value");
903 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800904 "'value' is a required property");
Bob King514023d2020-01-21 11:13:05 +0800905 }
906 // Invalid: test i2c_compare_byte with property register wrong type.
907 {
908 json configFile = i2cCompareByteFile;
909 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
910 1;
911 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800912 "1 is not of type 'string'");
Bob King514023d2020-01-21 11:13:05 +0800913 }
914 // Invalid: test i2c_compare_byte with property value wrong type.
915 {
916 json configFile = i2cCompareByteFile;
917 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1;
918 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800919 "1 is not of type 'string'");
Bob King514023d2020-01-21 11:13:05 +0800920 }
921 // Invalid: test i2c_compare_byte with property mask wrong type.
922 {
923 json configFile = i2cCompareByteFile;
924 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1;
925 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800926 "1 is not of type 'string'");
Bob King514023d2020-01-21 11:13:05 +0800927 }
928 // Invalid: test i2c_compare_byte with property register more than 2 hex
929 // digits.
930 {
931 json configFile = i2cCompareByteFile;
932 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
933 "0x820";
934 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800935 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +0800936 }
937 // Invalid: test i2c_compare_byte with property value more than 2 hex
938 // digits.
939 {
940 json configFile = i2cCompareByteFile;
941 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
942 "0x820";
943 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800944 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +0800945 }
946 // Invalid: test i2c_compare_byte with property mask more than 2 hex digits.
947 {
948 json configFile = i2cCompareByteFile;
949 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
950 "0x820";
951 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800952 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +0800953 }
954 // Invalid: test i2c_compare_byte with property register less than 2 hex
955 // digits.
956 {
957 json configFile = i2cCompareByteFile;
958 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
959 "0x8";
960 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800961 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +0800962 }
963 // Invalid: test i2c_compare_byte with property value less than 2 hex
964 // digits.
965 {
966 json configFile = i2cCompareByteFile;
967 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
968 "0x8";
969 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800970 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +0800971 }
972 // Invalid: test i2c_compare_byte with property mask less than 2 hex digits.
973 {
974 json configFile = i2cCompareByteFile;
975 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
976 "0x8";
977 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800978 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +0800979 }
980 // Invalid: test i2c_compare_byte with property register no leading prefix.
981 {
982 json configFile = i2cCompareByteFile;
983 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
984 "82";
985 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800986 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +0800987 }
988 // Invalid: test i2c_compare_byte with property value no leading prefix.
989 {
990 json configFile = i2cCompareByteFile;
991 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
992 "82";
993 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800994 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +0800995 }
996 // Invalid: test i2c_compare_byte with property mask no leading prefix.
997 {
998 json configFile = i2cCompareByteFile;
999 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82";
1000 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001001 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001002 }
1003 // Invalid: test i2c_compare_byte with property register invalid hex digit.
1004 {
1005 json configFile = i2cCompareByteFile;
1006 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1007 "0xG1";
1008 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001009 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001010 }
1011 // Invalid: test i2c_compare_byte with property value invalid hex digit.
1012 {
1013 json configFile = i2cCompareByteFile;
1014 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1015 "0xG1";
1016 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001017 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001018 }
1019 // Invalid: test i2c_compare_byte with property mask invalid hex digit.
1020 {
1021 json configFile = i2cCompareByteFile;
1022 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
1023 "0xG1";
1024 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001025 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001026 }
1027}
Bob Kingfb162bb2020-01-21 11:28:07 +08001028TEST(ValidateRegulatorsConfigTest, I2CCompareBytes)
1029{
1030 json i2cCompareBytesFile = validConfigFile;
1031 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
1032 ["register"] = "0x82";
1033 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
1034 ["values"] = {"0x02", "0x73"};
1035 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
1036 ["masks"] = {"0x7F", "0x7F"};
1037 // Valid: test i2c_compare_bytes.
1038 {
1039 json configFile = i2cCompareBytesFile;
1040 EXPECT_JSON_VALID(configFile);
1041 }
1042 // Valid: test i2c_compare_bytes with all required properties.
1043 {
1044 json configFile = i2cCompareBytesFile;
1045 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1046 "masks");
1047 EXPECT_JSON_VALID(configFile);
1048 }
1049 // Invalid: test i2c_compare_bytes with no register.
1050 {
1051 json configFile = i2cCompareBytesFile;
1052 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1053 "register");
1054 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001055 "'register' is a required property");
Bob Kingfb162bb2020-01-21 11:28:07 +08001056 }
1057 // Invalid: test i2c_compare_bytes with no values.
1058 {
1059 json configFile = i2cCompareBytesFile;
1060 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1061 "values");
1062 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001063 "'values' is a required property");
Bob Kingfb162bb2020-01-21 11:28:07 +08001064 }
1065 // Invalid: test i2c_compare_bytes with property values as empty array.
1066 {
1067 json configFile = i2cCompareBytesFile;
1068 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] =
1069 json::array();
1070 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1071 "[] is too short");
1072 }
1073 // Invalid: test i2c_compare_bytes with property masks as empty array.
1074 {
1075 json configFile = i2cCompareBytesFile;
1076 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] =
1077 json::array();
1078 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1079 "[] is too short");
1080 }
1081 // Invalid: test i2c_compare_bytes with property register wrong type.
1082 {
1083 json configFile = i2cCompareBytesFile;
1084 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1085 1;
1086 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001087 "1 is not of type 'string'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001088 }
1089 // Invalid: test i2c_compare_bytes with property values wrong type.
1090 {
1091 json configFile = i2cCompareBytesFile;
1092 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1;
1093 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001094 "1 is not of type 'array'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001095 }
1096 // Invalid: test i2c_compare_bytes with property masks wrong type.
1097 {
1098 json configFile = i2cCompareBytesFile;
1099 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1;
1100 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001101 "1 is not of type 'array'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001102 }
1103 // Invalid: test i2c_compare_bytes with property register more than 2 hex
1104 // digits.
1105 {
1106 json configFile = i2cCompareBytesFile;
1107 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1108 "0x820";
1109 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001110 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001111 }
1112 // Invalid: test i2c_compare_bytes with property values more than 2 hex
1113 // digits.
1114 {
1115 json configFile = i2cCompareBytesFile;
1116 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1117 "0x820";
1118 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001119 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001120 }
1121 // Invalid: test i2c_compare_bytes with property masks more than 2 hex
1122 // digits.
1123 {
1124 json configFile = i2cCompareBytesFile;
1125 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1126 "0x820";
1127 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001128 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001129 }
1130 // Invalid: test i2c_compare_bytes with property register less than 2 hex
1131 // digits.
1132 {
1133 json configFile = i2cCompareBytesFile;
1134 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1135 "0x8";
1136 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001137 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001138 }
1139 // Invalid: test i2c_compare_bytes with property values less than 2 hex
1140 // digits.
1141 {
1142 json configFile = i2cCompareBytesFile;
1143 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1144 "0x8";
1145 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001146 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001147 }
1148 // Invalid: test i2c_compare_bytes with property masks less than 2 hex
1149 // digits.
1150 {
1151 json configFile = i2cCompareBytesFile;
1152 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1153 "0x8";
1154 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001155 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001156 }
1157 // Invalid: test i2c_compare_bytes with property register no leading prefix.
1158 {
1159 json configFile = i2cCompareBytesFile;
1160 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1161 "82";
1162 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001163 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001164 }
1165 // Invalid: test i2c_compare_bytes with property values no leading prefix.
1166 {
1167 json configFile = i2cCompareBytesFile;
1168 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1169 "82";
1170 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001171 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001172 }
1173 // Invalid: test i2c_compare_bytes with property masks no leading prefix.
1174 {
1175 json configFile = i2cCompareBytesFile;
1176 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1177 "82";
1178 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001179 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001180 }
1181 // Invalid: test i2c_compare_bytes with property register invalid hex digit.
1182 {
1183 json configFile = i2cCompareBytesFile;
1184 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1185 "0xG1";
1186 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001187 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001188 }
1189 // Invalid: test i2c_compare_bytes with property values invalid hex digit.
1190 {
1191 json configFile = i2cCompareBytesFile;
1192 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1193 "0xG1";
1194 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001195 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001196 }
1197 // Invalid: test i2c_compare_bytes with property masks invalid hex digit.
1198 {
1199 json configFile = i2cCompareBytesFile;
1200 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1201 "0xG1";
1202 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001203 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001204 }
1205}
Bob Kingca93f1f2020-01-31 11:21:16 +08001206TEST(ValidateRegulatorsConfigTest, I2CInterface)
1207{
1208 // Valid: test i2c_interface.
1209 {
1210 json configFile = validConfigFile;
1211 EXPECT_JSON_VALID(configFile);
1212 }
1213 // Invalid: testi2c_interface with no bus.
1214 {
1215 json configFile = validConfigFile;
1216 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase("bus");
1217 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001218 "'bus' is a required property");
Bob Kingca93f1f2020-01-31 11:21:16 +08001219 }
1220 // Invalid: test i2c_interface with no address.
1221 {
1222 json configFile = validConfigFile;
1223 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase(
1224 "address");
1225 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001226 "'address' is a required property");
Bob Kingca93f1f2020-01-31 11:21:16 +08001227 }
1228 // Invalid: test i2c_interface with property bus wrong type.
1229 {
1230 json configFile = validConfigFile;
1231 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = true;
1232 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001233 "True is not of type 'integer'");
Bob Kingca93f1f2020-01-31 11:21:16 +08001234 }
1235 // Invalid: test i2c_interface with property address wrong
1236 // type.
1237 {
1238 json configFile = validConfigFile;
1239 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1240 true;
1241 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001242 "True is not of type 'string'");
Bob Kingca93f1f2020-01-31 11:21:16 +08001243 }
1244 // Invalid: test i2c_interface with property bus less than
1245 // 0.
1246 {
1247 json configFile = validConfigFile;
1248 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = -1;
1249 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1250 "-1 is less than the minimum of 0");
1251 }
1252 // Invalid: test i2c_interface with property address wrong
1253 // format.
1254 {
1255 json configFile = validConfigFile;
1256 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1257 "0x700";
1258 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001259 "'0x700' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingca93f1f2020-01-31 11:21:16 +08001260 }
1261}
Bob King188db7d2020-01-31 13:01:01 +08001262TEST(ValidateRegulatorsConfigTest, I2CWriteBit)
1263{
1264 json i2cWriteBitFile = validConfigFile;
1265 i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
1266 "0xA0";
1267 i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3;
1268 i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 1;
1269 // Valid: test rule actions i2c_write_bit.
1270 {
1271 json configFile = i2cWriteBitFile;
1272 EXPECT_JSON_VALID(configFile);
1273 }
1274 // Invalid: test i2c_write_bit with no register.
1275 {
1276 json configFile = i2cWriteBitFile;
1277 configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("register");
1278 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001279 "'register' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001280 }
1281 // Invalid: test i2c_write_bit with no position.
1282 {
1283 json configFile = i2cWriteBitFile;
1284 configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("position");
1285 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001286 "'position' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001287 }
1288 // Invalid: test i2c_write_bit with no value.
1289 {
1290 json configFile = i2cWriteBitFile;
1291 configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("value");
1292 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001293 "'value' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001294 }
1295 // Invalid: test i2c_write_bit with register wrong type.
1296 {
1297 json configFile = i2cWriteBitFile;
1298 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] = 1;
1299 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001300 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08001301 }
1302 // Invalid: test i2c_write_bit with register wrong format.
1303 {
1304 json configFile = i2cWriteBitFile;
1305 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
1306 "0xA00";
1307 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001308 "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001309 }
1310 // Invalid: test i2c_write_bit with position wrong type.
1311 {
1312 json configFile = i2cWriteBitFile;
1313 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3.1;
1314 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001315 "3.1 is not of type 'integer'");
Bob King188db7d2020-01-31 13:01:01 +08001316 }
1317 // Invalid: test i2c_write_bit with position greater than 7.
1318 {
1319 json configFile = i2cWriteBitFile;
1320 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 8;
1321 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1322 "8 is greater than the maximum of 7");
1323 }
1324 // Invalid: test i2c_write_bit with position less than 0.
1325 {
1326 json configFile = i2cWriteBitFile;
1327 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = -1;
1328 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1329 "-1 is less than the minimum of 0");
1330 }
1331 // Invalid: test i2c_write_bit with value wrong type.
1332 {
1333 json configFile = i2cWriteBitFile;
1334 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = "1";
1335 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001336 "'1' is not of type 'integer'");
Bob King188db7d2020-01-31 13:01:01 +08001337 }
1338 // Invalid: test i2c_write_bit with value greater than 1.
1339 {
1340 json configFile = i2cWriteBitFile;
1341 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 2;
1342 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1343 "2 is greater than the maximum of 1");
1344 }
1345 // Invalid: test i2c_write_bit with value less than 0.
1346 {
1347 json configFile = i2cWriteBitFile;
1348 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = -1;
1349 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1350 "-1 is less than the minimum of 0");
1351 }
1352}
1353TEST(ValidateRegulatorsConfigTest, I2CWriteByte)
1354{
1355 json i2cWriteByteFile = validConfigFile;
1356 i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1357 "0x82";
1358 i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1359 "0x40";
1360 i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
1361 "0x7F";
1362 // Valid: test i2c_write_byte with all properties.
1363 {
1364 json configFile = i2cWriteByteFile;
1365 EXPECT_JSON_VALID(configFile);
1366 }
1367 // Valid: test i2c_write_byte with all required properties.
1368 {
1369 json configFile = i2cWriteByteFile;
1370 configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("mask");
1371 EXPECT_JSON_VALID(configFile);
1372 }
1373 // Invalid: test i2c_write_byte with no register.
1374 {
1375 json configFile = i2cWriteByteFile;
1376 configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase(
1377 "register");
1378 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001379 "'register' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001380 }
1381 // Invalid: test i2c_write_byte with no value.
1382 {
1383 json configFile = i2cWriteByteFile;
1384 configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("value");
1385 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001386 "'value' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001387 }
1388 // Invalid: test i2c_write_byte with property register wrong type.
1389 {
1390 json configFile = i2cWriteByteFile;
1391 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1;
1392 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001393 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08001394 }
1395 // Invalid: test i2c_write_byte with property value wrong type.
1396 {
1397 json configFile = i2cWriteByteFile;
1398 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = 1;
1399 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001400 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08001401 }
1402 // Invalid: test i2c_write_byte with property mask wrong type.
1403 {
1404 json configFile = i2cWriteByteFile;
1405 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = 1;
1406 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001407 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08001408 }
1409 // Invalid: test i2c_write_byte with property register more than 2 hex
1410 // digits.
1411 {
1412 json configFile = i2cWriteByteFile;
1413 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1414 "0x820";
1415 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001416 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001417 }
1418 // Invalid: test i2c_write_byte with property value more than 2 hex
1419 // digits.
1420 {
1421 json configFile = i2cWriteByteFile;
1422 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1423 "0x820";
1424 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001425 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001426 }
1427 // Invalid: test i2c_write_byte with property mask more than 2 hex digits.
1428 {
1429 json configFile = i2cWriteByteFile;
1430 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
1431 "0x820";
1432 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001433 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001434 }
1435 // Invalid: test i2c_write_byte with property register less than 2 hex
1436 // digits.
1437 {
1438 json configFile = i2cWriteByteFile;
1439 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1440 "0x8";
1441 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001442 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001443 }
1444 // Invalid: test i2c_write_byte with property value less than 2 hex
1445 // digits.
1446 {
1447 json configFile = i2cWriteByteFile;
1448 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "0x8";
1449 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001450 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001451 }
1452 // Invalid: test i2c_write_byte with property mask less than 2 hex digits.
1453 {
1454 json configFile = i2cWriteByteFile;
1455 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0x8";
1456 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001457 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001458 }
1459 // Invalid: test i2c_write_byte with property register no leading prefix.
1460 {
1461 json configFile = i2cWriteByteFile;
1462 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1463 "82";
1464 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001465 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001466 }
1467 // Invalid: test i2c_write_byte with property value no leading prefix.
1468 {
1469 json configFile = i2cWriteByteFile;
1470 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "82";
1471 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001472 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001473 }
1474 // Invalid: test i2c_write_byte with property mask no leading prefix.
1475 {
1476 json configFile = i2cWriteByteFile;
1477 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "82";
1478 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001479 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001480 }
1481 // Invalid: test i2c_write_byte with property register invalid hex digit.
1482 {
1483 json configFile = i2cWriteByteFile;
1484 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1485 "0xG1";
1486 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001487 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001488 }
1489 // Invalid: test i2c_write_byte with property value invalid hex digit.
1490 {
1491 json configFile = i2cWriteByteFile;
1492 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1493 "0xG1";
1494 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001495 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001496 }
1497 // Invalid: test i2c_write_byte with property mask invalid hex digit.
1498 {
1499 json configFile = i2cWriteByteFile;
1500 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0xG1";
1501 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001502 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001503 }
1504}
1505TEST(ValidateRegulatorsConfigTest, I2CWriteBytes)
1506{
1507 json i2cWriteBytesFile = validConfigFile;
1508 i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1509 "0x82";
1510 i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
1511 "0x02", "0x73"};
1512 i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
1513 "0x7F", "0x7F"};
1514 // Valid: test i2c_write_bytes.
1515 {
1516 json configFile = i2cWriteBytesFile;
1517 EXPECT_JSON_VALID(configFile);
1518 }
1519 // Valid: test i2c_write_bytes with all required properties.
1520 {
1521 json configFile = i2cWriteBytesFile;
1522 configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("masks");
1523 EXPECT_JSON_VALID(configFile);
1524 }
1525 // Invalid: test i2c_write_bytes with no register.
1526 {
1527 json configFile = i2cWriteBytesFile;
1528 configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase(
1529 "register");
1530 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001531 "'register' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001532 }
1533 // Invalid: test i2c_write_bytes with no values.
1534 {
1535 json configFile = i2cWriteBytesFile;
1536 configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("values");
1537 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001538 "'values' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001539 }
1540 // Invalid: test i2c_write_bytes with property values as empty array.
1541 {
1542 json configFile = i2cWriteBytesFile;
1543 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] =
1544 json::array();
1545 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1546 "[] is too short");
1547 }
1548 // Invalid: test i2c_write_bytes with property masks as empty array.
1549 {
1550 json configFile = i2cWriteBytesFile;
1551 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] =
1552 json::array();
1553 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1554 "[] is too short");
1555 }
1556 // Invalid: test i2c_write_bytes with property register wrong type.
1557 {
1558 json configFile = i2cWriteBytesFile;
1559 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1;
1560 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001561 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08001562 }
1563 // Invalid: test i2c_write_bytes with property values wrong type.
1564 {
1565 json configFile = i2cWriteBytesFile;
1566 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = 1;
1567 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001568 "1 is not of type 'array'");
Bob King188db7d2020-01-31 13:01:01 +08001569 }
1570 // Invalid: test i2c_write_bytes with property masks wrong type.
1571 {
1572 json configFile = i2cWriteBytesFile;
1573 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = 1;
1574 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001575 "1 is not of type 'array'");
Bob King188db7d2020-01-31 13:01:01 +08001576 }
1577 // Invalid: test i2c_write_bytes with property register more than 2 hex
1578 // digits.
1579 {
1580 json configFile = i2cWriteBytesFile;
1581 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1582 "0x820";
1583 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001584 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001585 }
1586 // Invalid: test i2c_write_bytes with property values more than 2 hex
1587 // digits.
1588 {
1589 json configFile = i2cWriteBytesFile;
1590 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
1591 "0x820";
1592 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001593 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001594 }
1595 // Invalid: test i2c_write_bytes with property masks more than 2 hex
1596 // digits.
1597 {
1598 json configFile = i2cWriteBytesFile;
1599 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
1600 "0x820";
1601 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001602 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001603 }
1604 // Invalid: test i2c_write_bytes with property register less than 2 hex
1605 // digits.
1606 {
1607 json configFile = i2cWriteBytesFile;
1608 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1609 "0x8";
1610 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001611 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001612 }
1613 // Invalid: test i2c_write_bytes with property values less than 2 hex
1614 // digits.
1615 {
1616 json configFile = i2cWriteBytesFile;
1617 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
1618 "0x8";
1619 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001620 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001621 }
1622 // Invalid: test i2c_write_bytes with property masks less than 2 hex
1623 // digits.
1624 {
1625 json configFile = i2cWriteBytesFile;
1626 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
1627 "0x8";
1628 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001629 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001630 }
1631 // Invalid: test i2c_write_bytes with property register no leading prefix.
1632 {
1633 json configFile = i2cWriteBytesFile;
1634 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1635 "82";
1636 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001637 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001638 }
1639 // Invalid: test i2c_write_bytes with property values no leading prefix.
1640 {
1641 json configFile = i2cWriteBytesFile;
1642 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
1643 "82";
1644 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001645 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001646 }
1647 // Invalid: test i2c_write_bytes with property masks no leading prefix.
1648 {
1649 json configFile = i2cWriteBytesFile;
1650 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
1651 "82";
1652 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001653 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001654 }
1655 // Invalid: test i2c_write_bytes with property register invalid hex digit.
1656 {
1657 json configFile = i2cWriteBytesFile;
1658 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
1659 "0xG1";
1660 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001661 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001662 }
1663 // Invalid: test i2c_write_bytes with property values invalid hex digit.
1664 {
1665 json configFile = i2cWriteBytesFile;
1666 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
1667 "0xG1";
1668 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001669 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001670 }
1671 // Invalid: test i2c_write_bytes with property masks invalid hex digit.
1672 {
1673 json configFile = i2cWriteBytesFile;
1674 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
1675 "0xG1";
1676 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001677 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001678 }
1679}
Bob Kingead0b052020-01-21 11:29:03 +08001680TEST(ValidateRegulatorsConfigTest, If)
1681{
1682 json ifFile = validConfigFile;
Bob King2d27dcf2020-02-11 15:00:50 +08001683 ifFile["rules"][2]["actions"][0]["if"]["condition"]["run_rule"] =
1684 "set_voltage_rule";
1685 ifFile["rules"][2]["actions"][0]["if"]["then"][0]["run_rule"] =
1686 "read_sensors_rule";
1687 ifFile["rules"][2]["actions"][0]["if"]["else"][0]["run_rule"] =
1688 "read_sensors_rule";
1689 ifFile["rules"][2]["id"] = "rule_if";
Bob Kingead0b052020-01-21 11:29:03 +08001690 // Valid: test if.
1691 {
1692 json configFile = ifFile;
1693 EXPECT_JSON_VALID(configFile);
1694 }
1695 // Valid: test if with required properties.
1696 {
1697 json configFile = ifFile;
Bob King2d27dcf2020-02-11 15:00:50 +08001698 configFile["rules"][2]["actions"][0]["if"].erase("else");
Bob Kingead0b052020-01-21 11:29:03 +08001699 EXPECT_JSON_VALID(configFile);
1700 }
1701 // Invalid: test if with no property condition.
1702 {
1703 json configFile = ifFile;
Bob King2d27dcf2020-02-11 15:00:50 +08001704 configFile["rules"][2]["actions"][0]["if"].erase("condition");
Bob Kingead0b052020-01-21 11:29:03 +08001705 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001706 "'condition' is a required property");
Bob Kingead0b052020-01-21 11:29:03 +08001707 }
1708 // Invalid: test if with no property then.
1709 {
1710 json configFile = ifFile;
Bob King2d27dcf2020-02-11 15:00:50 +08001711 configFile["rules"][2]["actions"][0]["if"].erase("then");
Bob Kingead0b052020-01-21 11:29:03 +08001712 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001713 "'then' is a required property");
Bob Kingead0b052020-01-21 11:29:03 +08001714 }
1715 // Invalid: test if with property then empty array.
1716 {
1717 json configFile = ifFile;
Bob King2d27dcf2020-02-11 15:00:50 +08001718 configFile["rules"][2]["actions"][0]["if"]["then"] = json::array();
Bob Kingead0b052020-01-21 11:29:03 +08001719 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1720 "[] is too short");
1721 }
1722 // Invalid: test if with property else empty array.
1723 {
1724 json configFile = ifFile;
Bob King2d27dcf2020-02-11 15:00:50 +08001725 configFile["rules"][2]["actions"][0]["if"]["else"] = json::array();
Bob Kingead0b052020-01-21 11:29:03 +08001726 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1727 "[] is too short");
1728 }
1729 // Invalid: test if with property condition wrong type.
1730 {
1731 json configFile = ifFile;
Bob King2d27dcf2020-02-11 15:00:50 +08001732 configFile["rules"][2]["actions"][0]["if"]["condition"] = 1;
Bob Kingead0b052020-01-21 11:29:03 +08001733 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001734 "1 is not of type 'object'");
Bob Kingead0b052020-01-21 11:29:03 +08001735 }
1736 // Invalid: test if with property then wrong type.
1737 {
1738 json configFile = ifFile;
Bob King2d27dcf2020-02-11 15:00:50 +08001739 configFile["rules"][2]["actions"][0]["if"]["then"] = 1;
Bob Kingead0b052020-01-21 11:29:03 +08001740 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001741 "1 is not of type 'array'");
Bob Kingead0b052020-01-21 11:29:03 +08001742 }
1743 // Invalid: test if with property else wrong type.
1744 {
1745 json configFile = ifFile;
Bob King2d27dcf2020-02-11 15:00:50 +08001746 configFile["rules"][2]["actions"][0]["if"]["else"] = 1;
Bob Kingead0b052020-01-21 11:29:03 +08001747 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001748 "1 is not of type 'array'");
Bob Kingead0b052020-01-21 11:29:03 +08001749 }
1750}
Bob Kingbfe9fe72020-01-21 11:29:57 +08001751TEST(ValidateRegulatorsConfigTest, Not)
1752{
1753 json notFile = validConfigFile;
1754 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] =
1755 "0xA0";
1756 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] =
1757 "0xFF";
1758 // Valid: test not.
1759 {
1760 json configFile = notFile;
1761 EXPECT_JSON_VALID(configFile);
1762 }
1763 // Invalid: test not with wrong type.
1764 {
1765 json configFile = notFile;
1766 configFile["rules"][0]["actions"][1]["not"] = 1;
1767 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001768 "1 is not of type 'object'");
Bob Kingbfe9fe72020-01-21 11:29:57 +08001769 }
1770}
Bob Kingcfc29d02020-01-21 11:30:50 +08001771TEST(ValidateRegulatorsConfigTest, Or)
1772{
1773 json orFile = validConfigFile;
1774 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] =
1775 "0xA0";
1776 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] =
1777 "0x00";
1778 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] =
1779 "0xA1";
1780 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] =
1781 "0x00";
1782 // Valid: test or.
1783 {
1784 json configFile = orFile;
1785 EXPECT_JSON_VALID(configFile);
1786 }
1787 // Invalid: test or with empty array.
1788 {
1789 json configFile = orFile;
1790 configFile["rules"][0]["actions"][1]["or"] = json::array();
1791 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1792 "[] is too short");
1793 }
1794 // Invalid: test or with wrong type.
1795 {
1796 json configFile = orFile;
1797 configFile["rules"][0]["actions"][1]["or"] = 1;
1798 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001799 "1 is not of type 'array'");
Bob Kingcfc29d02020-01-21 11:30:50 +08001800 }
1801}
Bob Kingd6618092020-01-21 11:31:46 +08001802TEST(ValidateRegulatorsConfigTest, PmbusReadSensor)
1803{
1804 json pmbusReadSensorFile = validConfigFile;
1805 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1806 "vout";
1807 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1808 ["command"] = "0x8B";
1809 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1810 ["format"] = "linear_16";
1811 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
1812 ["exponent"] = -8;
1813 // Valid: test pmbus_read_sensor.
1814 {
1815 json configFile = pmbusReadSensorFile;
1816 EXPECT_JSON_VALID(configFile);
1817 }
1818 // Valid: test pmbus_read_sensor with required properties.
1819 {
1820 json configFile = pmbusReadSensorFile;
1821 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1822 "exponent");
1823 EXPECT_JSON_VALID(configFile);
1824 }
1825 // Invalid: test pmbus_read_sensor with no type.
1826 {
1827 json configFile = pmbusReadSensorFile;
1828 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type");
1829 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001830 "'type' is a required property");
Bob Kingd6618092020-01-21 11:31:46 +08001831 }
1832 // Invalid: test pmbus_read_sensor with no command.
1833 {
1834 json configFile = pmbusReadSensorFile;
1835 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1836 "command");
1837 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001838 "'command' is a required property");
Bob Kingd6618092020-01-21 11:31:46 +08001839 }
1840 // Invalid: test pmbus_read_sensor with no format.
1841 {
1842 json configFile = pmbusReadSensorFile;
1843 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
1844 "format");
1845 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001846 "'format' is a required property");
Bob Kingd6618092020-01-21 11:31:46 +08001847 }
1848 // Invalid: test pmbus_read_sensor with property type wrong type.
1849 {
1850 json configFile = pmbusReadSensorFile;
1851 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1852 true;
Bob King358c4172020-03-16 13:57:08 +08001853 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1854 "True is not of type 'string'");
Bob Kingd6618092020-01-21 11:31:46 +08001855 }
1856 // Invalid: test pmbus_read_sensor with property command wrong type.
1857 {
1858 json configFile = pmbusReadSensorFile;
1859 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1860 true;
1861 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001862 "True is not of type 'string'");
Bob Kingd6618092020-01-21 11:31:46 +08001863 }
1864 // Invalid: test pmbus_read_sensor with property format wrong type.
1865 {
1866 json configFile = pmbusReadSensorFile;
1867 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1868 true;
1869 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001870 "True is not of type 'string'");
Bob Kingd6618092020-01-21 11:31:46 +08001871 }
1872 // Invalid: test pmbus_read_sensor with property exponent wrong type.
1873 {
1874 json configFile = pmbusReadSensorFile;
1875 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] =
1876 true;
1877 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001878 "True is not of type 'integer'");
Bob Kingd6618092020-01-21 11:31:46 +08001879 }
1880 // Invalid: test pmbus_read_sensor with property type wrong format.
1881 {
1882 json configFile = pmbusReadSensorFile;
1883 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
1884 "foo";
1885 EXPECT_JSON_INVALID(
1886 configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001887 "'foo' is not one of ['iout', 'iout_peak', 'iout_valley', "
1888 "'pout', 'temperature', 'temperature_peak', 'vout', "
1889 "'vout_peak', 'vout_valley']");
Bob Kingd6618092020-01-21 11:31:46 +08001890 }
1891 // Invalid: test pmbus_read_sensor with property command wrong format.
1892 {
1893 json configFile = pmbusReadSensorFile;
1894 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
1895 "0x8B0";
1896 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001897 "'0x8B0' does not match '^0x[0-9a-fA-F]{2}$'");
Bob Kingd6618092020-01-21 11:31:46 +08001898 }
1899 // Invalid: test pmbus_read_sensor with property format wrong format.
1900 {
1901 json configFile = pmbusReadSensorFile;
1902 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
1903 "foo";
Bob King358c4172020-03-16 13:57:08 +08001904 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1905 "'foo' is not one of ['linear_11', 'linear_16']");
Bob Kingd6618092020-01-21 11:31:46 +08001906 }
1907}
Bob King02179c62020-01-21 11:32:36 +08001908TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand)
1909{
1910 json pmbusWriteVoutCommandFile = validConfigFile;
1911 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1912 ["pmbus_write_vout_command"]["volts"] = 1.03;
1913 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1914 ["pmbus_write_vout_command"]["format"] = "linear";
1915 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1916 ["pmbus_write_vout_command"]["exponent"] = -8;
1917 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
1918 ["pmbus_write_vout_command"]["is_verified"] = true;
1919 // Valid: test pmbus_write_vout_command.
1920 {
1921 json configFile = pmbusWriteVoutCommandFile;
1922 EXPECT_JSON_VALID(configFile);
1923 }
1924 // Valid: test pmbus_write_vout_command with required properties.
1925 {
1926 json configFile = pmbusWriteVoutCommandFile;
1927 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1928 "volts");
1929 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1930 "exponent");
1931 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1932 "is_verified");
1933 EXPECT_JSON_VALID(configFile);
1934 }
1935 // Invalid: test pmbus_write_vout_command with no format.
1936 {
1937 json configFile = pmbusWriteVoutCommandFile;
1938 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
1939 "format");
1940 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001941 "'format' is a required property");
Bob King02179c62020-01-21 11:32:36 +08001942 }
1943 // Invalid: test pmbus_write_vout_command with property volts wrong type.
1944 {
1945 json configFile = pmbusWriteVoutCommandFile;
1946 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1947 ["volts"] = true;
1948 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001949 "True is not of type 'number'");
Bob King02179c62020-01-21 11:32:36 +08001950 }
1951 // Invalid: test pmbus_write_vout_command with property format wrong type.
1952 {
1953 json configFile = pmbusWriteVoutCommandFile;
1954 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1955 ["format"] = true;
1956 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001957 "True is not of type 'string'");
Bob King02179c62020-01-21 11:32:36 +08001958 }
1959 // Invalid: test pmbus_write_vout_command with property exponent wrong type.
1960 {
1961 json configFile = pmbusWriteVoutCommandFile;
1962 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1963 ["exponent"] = 1.3;
1964 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001965 "1.3 is not of type 'integer'");
Bob King02179c62020-01-21 11:32:36 +08001966 }
1967 // Invalid: test pmbus_write_vout_command with property is_verified wrong
1968 // type.
1969 {
1970 json configFile = pmbusWriteVoutCommandFile;
1971 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1972 ["is_verified"] = 1;
1973 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001974 "1 is not of type 'boolean'");
Bob King02179c62020-01-21 11:32:36 +08001975 }
1976 // Invalid: test pmbus_write_vout_command with property format wrong format.
1977 {
1978 json configFile = pmbusWriteVoutCommandFile;
1979 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
1980 ["format"] = "foo";
1981 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001982 "'foo' is not one of ['linear']");
Bob King02179c62020-01-21 11:32:36 +08001983 }
1984}
Bob King99d8fa12020-01-31 11:23:40 +08001985TEST(ValidateRegulatorsConfigTest, PresenceDetection)
1986{
1987 json presenceDetectionFile = validConfigFile;
1988 presenceDetectionFile
1989 ["chassis"][0]["devices"][0]["presence_detection"]["comments"][0] =
1990 "Regulator is only present on the FooBar backplane";
1991 presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
Bob Kingf4ff1162020-02-11 15:13:38 +08001992 ["rule_id"] = "set_voltage_rule";
Bob King99d8fa12020-01-31 11:23:40 +08001993 // Valid: test presence_detection with only property rule_id.
1994 {
1995 json configFile = presenceDetectionFile;
1996 EXPECT_JSON_VALID(configFile);
1997 }
1998 // Valid: test presence_detection with only property actions.
1999 {
2000 json configFile = presenceDetectionFile;
2001 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2002 "rule_id");
2003 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
2004 [0]["compare_presence"]["fru"] =
2005 "/system/chassis/motherboard/cpu3";
2006 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
2007 [0]["compare_presence"]["value"] = true;
2008 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2009 "comments");
2010 EXPECT_JSON_VALID(configFile);
2011 }
2012 // Invalid: test presence_detection with both property rule_id and actions.
2013 {
2014 json configFile = presenceDetectionFile;
2015 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
2016 [0]["compare_presence"]["fru"] =
2017 "/system/chassis/motherboard/cpu3";
2018 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
2019 [0]["compare_presence"]["value"] = true;
2020 EXPECT_JSON_INVALID(
2021 configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002022 "{'actions': [{'compare_presence': {'fru': "
2023 "'/system/chassis/motherboard/cpu3', 'value': True}}], 'comments': "
2024 "['Regulator is only present on the FooBar backplane'], 'rule_id': "
2025 "'set_voltage_rule'} is valid under each of {'required': "
2026 "['actions']}, {'required': ['rule_id']}");
Bob King99d8fa12020-01-31 11:23:40 +08002027 }
2028 // Invalid: test presence_detection with no rule_id and actions.
2029 {
2030 json configFile = presenceDetectionFile;
2031 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2032 "rule_id");
2033 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002034 "'rule_id' is a required property");
Bob King99d8fa12020-01-31 11:23:40 +08002035 }
2036 // Invalid: test presence_detection with property comments wrong type.
2037 {
2038 json configFile = presenceDetectionFile;
2039 configFile["chassis"][0]["devices"][0]["presence_detection"]
2040 ["comments"] = true;
2041 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002042 "True is not of type 'array'");
Bob King99d8fa12020-01-31 11:23:40 +08002043 }
2044 // Invalid: test presence_detection with property rule_id wrong type.
2045 {
2046 json configFile = presenceDetectionFile;
2047 configFile["chassis"][0]["devices"][0]["presence_detection"]
2048 ["rule_id"] = true;
2049 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002050 "True is not of type 'string'");
Bob King99d8fa12020-01-31 11:23:40 +08002051 }
2052 // Invalid: test presence_detection with property actions wrong type.
2053 {
2054 json configFile = presenceDetectionFile;
2055 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2056 "rule_id");
2057 configFile["chassis"][0]["devices"][0]["presence_detection"]
2058 ["actions"] = true;
2059 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002060 "True is not of type 'array'");
Bob King99d8fa12020-01-31 11:23:40 +08002061 }
2062 // Invalid: test presence_detection with property rule_id wrong format.
2063 {
2064 json configFile = presenceDetectionFile;
2065 configFile["chassis"][0]["devices"][0]["presence_detection"]
2066 ["rule_id"] = "id@";
2067 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002068 "'id@' does not match '^[A-Za-z0-9_]+$'");
Bob King99d8fa12020-01-31 11:23:40 +08002069 }
2070 // Invalid: test presence_detection with property comments empty array.
2071 {
2072 json configFile = presenceDetectionFile;
2073 configFile["chassis"][0]["devices"][0]["presence_detection"]
2074 ["comments"] = json::array();
2075 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2076 "[] is too short");
2077 }
2078 // Invalid: test presence_detection with property actions empty array.
2079 {
2080 json configFile = presenceDetectionFile;
2081 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2082 "rule_id");
2083 configFile["chassis"][0]["devices"][0]["presence_detection"]
2084 ["actions"] = json::array();
2085 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2086 "[] is too short");
2087 }
2088}
Bob Kinge9260b52020-01-21 11:46:13 +08002089TEST(ValidateRegulatorsConfigTest, Rail)
2090{
2091 // Valid: test rail.
2092 {
2093 json configFile = validConfigFile;
2094 EXPECT_JSON_VALID(configFile);
2095 }
2096 // Valid: test rail with required properties.
2097 {
2098 json configFile = validConfigFile;
2099 configFile["chassis"][0]["devices"][0]["rails"][0].erase("comments");
2100 configFile["chassis"][0]["devices"][0]["rails"][0].erase(
2101 "configuration");
2102 configFile["chassis"][0]["devices"][0]["rails"][0].erase(
2103 "sensor_monitoring");
2104 EXPECT_JSON_VALID(configFile);
2105 }
2106 // Invalid: test rail with no id.
2107 {
2108 json configFile = validConfigFile;
2109 configFile["chassis"][0]["devices"][0]["rails"][0].erase("id");
2110 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002111 "'id' is a required property");
Bob Kinge9260b52020-01-21 11:46:13 +08002112 }
2113 // Invalid: test rail with comments wrong type.
2114 {
2115 json configFile = validConfigFile;
2116 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = true;
2117 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002118 "True is not of type 'array'");
Bob Kinge9260b52020-01-21 11:46:13 +08002119 }
2120 // Invalid: test rail with id wrong type.
2121 {
2122 json configFile = validConfigFile;
2123 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = true;
2124 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002125 "True is not of type 'string'");
Bob Kinge9260b52020-01-21 11:46:13 +08002126 }
2127 // Invalid: test rail with configuration wrong type.
2128 {
2129 json configFile = validConfigFile;
2130 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] =
2131 true;
2132 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002133 "True is not of type 'object'");
Bob Kinge9260b52020-01-21 11:46:13 +08002134 }
2135 // Invalid: test rail with sensor_monitoring wrong type.
2136 {
2137 json configFile = validConfigFile;
2138 configFile["chassis"][0]["devices"][0]["rails"][0]
2139 ["sensor_monitoring"] = true;
2140 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002141 "True is not of type 'object'");
Bob Kinge9260b52020-01-21 11:46:13 +08002142 }
2143 // Invalid: test rail with comments empty array.
2144 {
2145 json configFile = validConfigFile;
2146 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] =
2147 json::array();
2148 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2149 "[] is too short");
2150 }
2151 // Invalid: test rail with id wrong format.
2152 {
2153 json configFile = validConfigFile;
2154 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = "id~";
2155 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002156 "'id~' does not match '^[A-Za-z0-9_]+$'");
Bob Kinge9260b52020-01-21 11:46:13 +08002157 }
2158}
Bob King64df7da2020-01-31 12:04:12 +08002159TEST(ValidateRegulatorsConfigTest, Rule)
2160{
2161 // valid test comments property, id property,
2162 // action property specified.
2163 {
2164 json configFile = validConfigFile;
2165 EXPECT_JSON_VALID(configFile);
2166 }
2167
2168 // valid test rule with no comments
2169 {
2170 json configFile = validConfigFile;
2171 configFile["rules"][0].erase("comments");
2172 EXPECT_JSON_VALID(configFile);
2173 }
2174
2175 // invalid test comments property has invalid value type
2176 {
2177 json configFile = validConfigFile;
2178 configFile["rules"][0]["comments"] = {1};
2179 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002180 "1 is not of type 'string'");
Bob King64df7da2020-01-31 12:04:12 +08002181 }
2182
2183 // invalid test rule with no ID
2184 {
2185 json configFile = validConfigFile;
2186 configFile["rules"][0].erase("id");
2187 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002188 "'id' is a required property");
Bob King64df7da2020-01-31 12:04:12 +08002189 }
2190
2191 // invalid test id property has invalid value type (not string)
2192 {
2193 json configFile = validConfigFile;
2194 configFile["rules"][0]["id"] = true;
2195 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002196 "True is not of type 'string'");
Bob King64df7da2020-01-31 12:04:12 +08002197 }
2198
2199 // invalid test id property has invalid value
2200 {
2201 json configFile = validConfigFile;
2202 configFile["rules"][0]["id"] = "foo%";
2203 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002204 "'foo%' does not match '^[A-Za-z0-9_]+$'");
Bob King64df7da2020-01-31 12:04:12 +08002205 }
2206
2207 // invalid test rule with no actions property
2208 {
2209 json configFile = validConfigFile;
2210 configFile["rules"][0].erase("actions");
2211 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002212 "'actions' is a required property");
Bob King64df7da2020-01-31 12:04:12 +08002213 }
2214
2215 // valid test rule with multiple actions
2216 {
2217 json configFile = validConfigFile;
Bob King63d795f2020-02-11 15:22:09 +08002218 configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
Bob King64df7da2020-01-31 12:04:12 +08002219 EXPECT_JSON_VALID(configFile);
2220 }
2221
2222 // invalid test actions property has invalid value type (not an array)
2223 {
2224 json configFile = validConfigFile;
2225 configFile["rules"][0]["actions"] = 1;
2226 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002227 "1 is not of type 'array'");
Bob King64df7da2020-01-31 12:04:12 +08002228 }
2229
2230 // invalid test actions property has invalid value of action
2231 {
2232 json configFile = validConfigFile;
2233 configFile["rules"][0]["actions"][0] = "foo";
2234 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002235 "'foo' is not of type 'object'");
Bob King64df7da2020-01-31 12:04:12 +08002236 }
2237
2238 // invalid test actions property has empty array
2239 {
2240 json configFile = validConfigFile;
2241 configFile["rules"][0]["actions"] = json::array();
2242 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2243 "[] is too short");
2244 }
2245}
Bob Kinge86c2e52020-01-21 11:33:32 +08002246TEST(ValidateRegulatorsConfigTest, RunRule)
2247{
2248 json runRuleFile = validConfigFile;
Bob King7d3a9f12020-02-11 15:34:52 +08002249 runRuleFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
Bob Kinge86c2e52020-01-21 11:33:32 +08002250 // Valid: test run_rule.
2251 {
2252 json configFile = runRuleFile;
2253 EXPECT_JSON_VALID(configFile);
2254 }
2255 // Invalid: test run_rule wrong type.
2256 {
2257 json configFile = runRuleFile;
2258 configFile["rules"][0]["actions"][1]["run_rule"] = true;
2259 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002260 "True is not of type 'string'");
Bob Kinge86c2e52020-01-21 11:33:32 +08002261 }
2262 // Invalid: test run_rule wrong format.
2263 {
2264 json configFile = runRuleFile;
2265 configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%";
2266 EXPECT_JSON_INVALID(
2267 configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002268 "'set_voltage_rule%' does not match '^[A-Za-z0-9_]+$'");
Bob Kinge86c2e52020-01-21 11:33:32 +08002269 }
2270}
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002271TEST(ValidateRegulatorsConfigTest, SensorMonitoring)
2272{
2273 // Valid: test rails sensor_monitoring with only property rule id.
2274 {
2275 json configFile = validConfigFile;
2276 EXPECT_JSON_VALID(configFile);
2277 }
2278 // Valid: test rails sensor_monitoring with only property actions.
2279 {
2280 json configFile = validConfigFile;
2281 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2282 .erase("rule_id");
2283 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2284 ["actions"][0]["compare_presence"]["fru"] =
2285 "/system/chassis/motherboard/cpu3";
2286 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2287 ["actions"][0]["compare_presence"]["value"] = true;
2288 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2289 ["comments"][0] = "comments";
2290 EXPECT_JSON_VALID(configFile);
2291 }
2292 // Invalid: test rails sensor_monitoring with both property rule_id and
2293 // actions.
2294 {
2295 json configFile = validConfigFile;
2296 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2297 ["actions"][0]["compare_presence"]["fru"] =
2298 "/system/chassis/motherboard/cpu3";
2299 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2300 ["actions"][0]["compare_presence"]["value"] = true;
2301 EXPECT_JSON_INVALID(
2302 configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002303 "{'actions': [{'compare_presence': {'fru': "
2304 "'/system/chassis/motherboard/cpu3', 'value': True}}], 'rule_id': "
2305 "'read_sensors_rule'} is valid under each of {'required': "
2306 "['actions']}, {'required': ['rule_id']}");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002307 }
2308 // Invalid: test rails sensor_monitoring with no rule_id and actions.
2309 {
2310 json configFile = validConfigFile;
2311 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2312 .erase("rule_id");
2313 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002314 "'rule_id' is a required property");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002315 }
2316 // Invalid: test rails sensor_monitoring with property comments wrong type.
2317 {
2318 json configFile = validConfigFile;
2319 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2320 ["comments"] = true;
2321 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002322 "True is not of type 'array'");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002323 }
2324 // Invalid: test rails sensor_monitoring with property rule_id wrong type.
2325 {
2326 json configFile = validConfigFile;
2327 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2328 ["rule_id"] = true;
2329 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002330 "True is not of type 'string'");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002331 }
2332 // Invalid: test rails sensor_monitoring with property actions wrong type.
2333 {
2334 json configFile = validConfigFile;
2335 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2336 .erase("rule_id");
2337 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2338 ["actions"] = true;
2339 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002340 "True is not of type 'array'");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002341 }
2342 // Invalid: test rails sensor_monitoring with property rule_id wrong format.
2343 {
2344 json configFile = validConfigFile;
2345 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2346 ["rule_id"] = "id@";
2347 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002348 "'id@' does not match '^[A-Za-z0-9_]+$'");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002349 }
2350 // Invalid: test rails sensor_monitoring with property comments empty array.
2351 {
2352 json configFile = validConfigFile;
2353 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2354 ["comments"] = json::array();
2355 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2356 "[] is too short");
2357 }
2358 // Invalid: test rails sensor_monitoring with property actions empty array.
2359 {
2360 json configFile = validConfigFile;
2361 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2362 .erase("rule_id");
2363 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2364 ["actions"] = json::array();
2365 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2366 "[] is too short");
2367 }
2368}
Bob King68230aa2020-01-21 11:34:33 +08002369TEST(ValidateRegulatorsConfigTest, SetDevice)
2370{
2371 json setDeviceFile = validConfigFile;
Bob King7d3a9f12020-02-11 15:34:52 +08002372 setDeviceFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator";
Bob King68230aa2020-01-21 11:34:33 +08002373 // Valid: test set_device.
2374 {
2375 json configFile = setDeviceFile;
2376 EXPECT_JSON_VALID(configFile);
2377 }
2378 // Invalid: test set_device wrong type.
2379 {
2380 json configFile = setDeviceFile;
2381 configFile["rules"][0]["actions"][1]["set_device"] = true;
2382 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002383 "True is not of type 'string'");
Bob King68230aa2020-01-21 11:34:33 +08002384 }
2385 // Invalid: test set_device wrong format.
2386 {
2387 json configFile = setDeviceFile;
2388 configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%";
Bob King358c4172020-03-16 13:57:08 +08002389 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2390 "'io_expander2%' does not match '^[A-Za-z0-9_]+$'");
Bob King68230aa2020-01-21 11:34:33 +08002391 }
2392}
Bob King3643cc02020-01-31 11:32:56 +08002393TEST(ValidateRegulatorsConfigTest, DuplicateRuleID)
2394{
2395 // Invalid: test duplicate ID in rule.
2396 {
2397 json configFile = validConfigFile;
Bob Kingb3e48bc2020-02-18 09:59:09 +08002398 configFile["rules"][2]["id"] = "set_voltage_rule";
2399 configFile["rules"][2]["actions"][0]["pmbus_write_vout_command"]
Bob King3643cc02020-01-31 11:32:56 +08002400 ["format"] = "linear";
2401 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rule ID.", "");
2402 }
2403}
2404TEST(ValidateRegulatorsConfigTest, DuplicateChassisNumber)
2405{
2406 // Invalid: test duplicate number in chassis.
2407 {
2408 json configFile = validConfigFile;
2409 configFile["chassis"][1]["number"] = 1;
2410 EXPECT_JSON_INVALID(configFile, "Error: Duplicate chassis number.", "");
2411 }
2412}
2413TEST(ValidateRegulatorsConfigTest, DuplicateDeviceID)
2414{
2415 // Invalid: test duplicate ID in device.
2416 {
2417 json configFile = validConfigFile;
2418 configFile["chassis"][0]["devices"][1]["id"] = "vdd_regulator";
2419 configFile["chassis"][0]["devices"][1]["is_regulator"] = true;
2420 configFile["chassis"][0]["devices"][1]["fru"] =
2421 "/system/chassis/motherboard/regulator1";
2422 configFile["chassis"][0]["devices"][1]["i2c_interface"]["bus"] = 2;
2423 configFile["chassis"][0]["devices"][1]["i2c_interface"]["address"] =
2424 "0x71";
2425 EXPECT_JSON_INVALID(configFile, "Error: Duplicate device ID.", "");
2426 }
2427}
2428TEST(ValidateRegulatorsConfigTest, DuplicateRailID)
2429{
2430 // Invalid: test duplicate ID in rail.
2431 {
2432 json configFile = validConfigFile;
2433 configFile["chassis"][0]["devices"][0]["rails"][1]["id"] = "vdd";
2434 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rail ID.", "");
2435 }
2436}
Bob King78793102020-03-13 13:16:09 +08002437TEST(ValidateRegulatorsConfigTest, DuplicateObjectID)
2438{
2439 // Invalid: test duplicate object ID in device and rail.
2440 {
2441 json configFile = validConfigFile;
2442 configFile["chassis"][0]["devices"][0]["rails"][1]["id"] =
2443 "vdd_regulator";
2444 EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
2445 }
2446 // Invalid: test duplicate object ID in device and rule.
2447 {
2448 json configFile = validConfigFile;
2449 configFile["rules"][2]["id"] = "vdd_regulator";
2450 configFile["rules"][2]["actions"][0]["pmbus_write_vout_command"]
2451 ["format"] = "linear";
2452 EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
2453 }
2454 // Invalid: test duplicate object ID in rule and rail.
2455 {
2456 json configFile = validConfigFile;
2457 configFile["chassis"][0]["devices"][0]["rails"][1]["id"] =
2458 "set_voltage_rule";
2459 EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
2460 }
2461}
Bob King3643cc02020-01-31 11:32:56 +08002462TEST(ValidateRegulatorsConfigTest, InfiniteLoops)
2463{
2464 // Invalid: test run_rule with infinite loop (rules run each other).
2465 {
2466 json configFile = validConfigFile;
2467 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2";
2468 configFile["rules"][2]["id"] = "set_voltage_rule1";
2469 configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule1";
2470 configFile["rules"][3]["id"] = "set_voltage_rule2";
2471 EXPECT_JSON_INVALID(configFile,
2472 "Infinite loop caused by run_rule actions.", "");
2473 }
2474 // Invalid: test run_rule with infinite loop (rule runs itself).
2475 {
2476 json configFile = validConfigFile;
2477 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule1";
2478 configFile["rules"][2]["id"] = "set_voltage_rule1";
2479 EXPECT_JSON_INVALID(configFile,
2480 "Infinite loop caused by run_rule actions.", "");
2481 }
2482 // Invalid: test run_rule with infinite loop (indirect loop).
2483 {
2484 json configFile = validConfigFile;
2485 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2";
2486 configFile["rules"][2]["id"] = "set_voltage_rule1";
2487 configFile["rules"][3]["actions"][0]["run_rule"] = "set_voltage_rule3";
2488 configFile["rules"][3]["id"] = "set_voltage_rule2";
2489 configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule1";
2490 configFile["rules"][4]["id"] = "set_voltage_rule3";
2491 EXPECT_JSON_INVALID(configFile,
2492 "Infinite loop caused by run_rule actions.", "");
2493 }
2494}
Bob Kingf88203a2020-02-18 13:26:07 +08002495TEST(ValidateRegulatorsConfigTest, RunRuleValueExists)
2496{
2497 // Invalid: test run_rule actions specify a rule ID that does not exist.
2498 {
2499 json configFile = validConfigFile;
2500 configFile["rules"][2]["actions"][0]["run_rule"] = "set_voltage_rule2";
2501 configFile["rules"][2]["id"] = "set_voltage_rule1";
2502 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
2503 }
2504}
Bob King13b2ad92020-02-18 13:31:39 +08002505TEST(ValidateRegulatorsConfigTest, SetDeviceValueExists)
2506{
2507 // Invalid: test set_device actions specify a device ID that does not exist.
2508 {
2509 json configFile = validConfigFile;
2510 configFile["rules"][2]["actions"][0]["set_device"] = "vdd_regulator2";
2511 configFile["rules"][2]["id"] = "set_voltage_rule1";
2512 EXPECT_JSON_INVALID(configFile, "Error: Device ID does not exist.", "");
2513 }
2514}
Bob King21b09be2020-02-18 13:33:09 +08002515TEST(ValidateRegulatorsConfigTest, RuleIDExists)
2516{
2517 // Invalid: test rule_id property in configuration specifies a rule ID that
2518 // does not exist.
2519 {
2520 json configFile = validConfigFile;
2521 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
2522 "set_voltage_rule2";
2523 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
2524 }
2525 // Invalid: test rule_id property in presence_detection specifies a rule ID
2526 // that does not exist.
2527 {
2528 json configFile = validConfigFile;
2529 configFile["chassis"][0]["devices"][0]["presence_detection"]
2530 ["rule_id"] = "set_voltage_rule2";
2531 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
2532 }
2533 // Invalid: test rule_id property in sensor_monitoring specifies a rule ID
2534 // that does not exist.
2535 {
2536 json configFile = validConfigFile;
2537 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2538 ["rule_id"] = "set_voltage_rule2";
2539 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
2540 }
2541}
Bob Kingdc72b622020-02-18 13:36:18 +08002542TEST(ValidateRegulatorsConfigTest, NumberOfElementsInMasks)
2543{
2544 // Invalid: test number of elements in masks not equal to number in values
2545 // in i2c_compare_bytes.
2546 {
2547 json configFile = validConfigFile;
2548 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
2549 "0x82";
2550 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = {
2551 "0x02", "0x73"};
2552 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = {
2553 "0x7F"};
2554 EXPECT_JSON_INVALID(configFile,
2555 "Error: Invalid i2c_compare_bytes action.", "");
2556 }
2557 // Invalid: test number of elements in masks not equal to number in values
2558 // in i2c_write_bytes.
2559 {
2560 json configFile = validConfigFile;
2561 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2562 "0x82";
2563 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
2564 "0x02", "0x73"};
2565 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
2566 "0x7F"};
2567 EXPECT_JSON_INVALID(configFile,
2568 "Error: Invalid i2c_write_bytes action.", "");
2569 }
2570}
Bob Kinged009652020-02-20 14:54:13 +08002571TEST(ValidateRegulatorsConfigTest, CommandLineSyntax)
2572{
Bob Kinga57e0812020-03-12 10:47:42 +08002573 std::string validateTool =
2574 " ../phosphor-regulators/tools/validate-regulators-config.py ";
Bob Kinged009652020-02-20 14:54:13 +08002575 std::string schema = " -s ";
Bob Kinga57e0812020-03-12 10:47:42 +08002576 std::string schemaFile =
2577 " ../phosphor-regulators/schema/config_schema.json ";
Bob Kinged009652020-02-20 14:54:13 +08002578 std::string configuration = " -c ";
2579 std::string command;
2580 std::string errorMessage;
2581 std::string outputMessage;
2582 std::string outputMessageHelp =
2583 "usage: validate-regulators-config.py [-h] [-s SCHEMA_FILE]";
2584 int valid = 0;
2585
2586 std::string fileName;
Bob Kinga57e0812020-03-12 10:47:42 +08002587 TmpFile tmpFile;
2588 fileName = tmpFile.getName();
2589 writeDataToFile(validConfigFile, fileName);
Bob Kinged009652020-02-20 14:54:13 +08002590 // Valid: -s specified
2591 {
2592 command = validateTool + "-s " + schemaFile + configuration + fileName;
2593 expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
2594 }
2595 // Valid: --schema-file specified
2596 {
2597 command = validateTool + "--schema-file " + schemaFile + configuration +
2598 fileName;
2599 expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
2600 }
2601 // Valid: -c specified
2602 {
2603 command = validateTool + schema + schemaFile + "-c " + fileName;
2604 expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
2605 }
2606 // Valid: --configuration-file specified
2607 {
2608 command = validateTool + schema + schemaFile + "--configuration-file " +
2609 fileName;
2610 expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
2611 }
2612 // Valid: -h specified
2613 {
2614 command = validateTool + "-h ";
2615 expectCommandLineSyntax(errorMessage, outputMessageHelp, command,
2616 valid);
2617 }
2618 // Valid: --help specified
2619 {
2620 command = validateTool + "--help ";
2621 expectCommandLineSyntax(errorMessage, outputMessageHelp, command,
2622 valid);
2623 }
2624 // Invalid: -c/--configuration-file not specified
2625 {
2626 command = validateTool + schema + schemaFile;
2627 expectCommandLineSyntax("Error: Configuration file is required.",
2628 outputMessageHelp, command, 1);
2629 }
2630 // Invalid: -s/--schema-file not specified
2631 {
2632 command = validateTool + configuration + fileName;
2633 expectCommandLineSyntax("Error: Schema file is required.",
2634 outputMessageHelp, command, 1);
2635 }
2636 // Invalid: -s specified more than once
2637 {
2638 command =
2639 validateTool + "-s -s " + schemaFile + configuration + fileName;
2640 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
2641 }
2642 // Invalid: -c specified more than once
2643 {
2644 command = validateTool + schema + schemaFile + "-c -c " + fileName;
2645 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
2646 }
2647 // Invalid: No file name specified after -c
2648 {
2649 command = validateTool + schema + schemaFile + configuration;
2650 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
2651 }
2652 // Invalid: No file name specified after -s
2653 {
2654 command = validateTool + schema + configuration + fileName;
2655 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
2656 }
2657 // Invalid: File specified after -c does not exist
2658 {
2659 command = validateTool + schema + schemaFile + configuration +
2660 "../notExistFile";
2661 expectCommandLineSyntax(
2662 "Traceback (most recent call last):", outputMessage, command, 1);
2663 }
2664 // Invalid: File specified after -s does not exist
2665 {
2666 command = validateTool + schema + "../notExistFile " + configuration +
2667 fileName;
2668 expectCommandLineSyntax(
2669 "Traceback (most recent call last):", outputMessage, command, 1);
2670 }
2671 // Invalid: File specified after -s is not right data format
2672 {
Bob Kinga57e0812020-03-12 10:47:42 +08002673 std::string wrongFormatFileName;
2674 TmpFile wrongFormatFile;
2675 wrongFormatFileName = wrongFormatFile.getName();
2676 std::ofstream out(wrongFormatFileName);
Bob Kinged009652020-02-20 14:54:13 +08002677 out << "foo";
2678 out.close();
Bob Kinga57e0812020-03-12 10:47:42 +08002679 command = validateTool + schema + wrongFormatFileName + configuration +
2680 fileName;
Bob Kinged009652020-02-20 14:54:13 +08002681 expectCommandLineSyntax(
2682 "Traceback (most recent call last):", outputMessage, command, 1);
Bob Kinged009652020-02-20 14:54:13 +08002683 }
2684 // Invalid: File specified after -c is not readable
2685 {
Bob Kinga57e0812020-03-12 10:47:42 +08002686 std::string notReadableFileName;
2687 TmpFile notReadableFile;
2688 notReadableFileName = notReadableFile.getName();
2689 writeDataToFile(validConfigFile, notReadableFileName);
Bob Kinged009652020-02-20 14:54:13 +08002690 command = validateTool + schema + schemaFile + configuration +
Bob Kinga57e0812020-03-12 10:47:42 +08002691 notReadableFileName;
2692 chmod(notReadableFileName.c_str(), 0222);
Bob Kinged009652020-02-20 14:54:13 +08002693 expectCommandLineSyntax(
2694 "Traceback (most recent call last):", outputMessage, command, 1);
Bob Kinged009652020-02-20 14:54:13 +08002695 }
2696 // Invalid: File specified after -s is not readable
2697 {
Bob Kinga57e0812020-03-12 10:47:42 +08002698 std::string notReadableFileName;
2699 TmpFile notReadableFile;
2700 notReadableFileName = notReadableFile.getName();
2701 writeDataToFile(validConfigFile, notReadableFileName);
2702 command = validateTool + schema + notReadableFileName + configuration +
2703 fileName;
2704 chmod(notReadableFileName.c_str(), 0222);
Bob Kinged009652020-02-20 14:54:13 +08002705 expectCommandLineSyntax(
2706 "Traceback (most recent call last):", outputMessage, command, 1);
Bob Kinged009652020-02-20 14:54:13 +08002707 }
2708 // Invalid: Unexpected parameter specified (like -g)
2709 {
2710 command = validateTool + schema + schemaFile + configuration +
2711 fileName + " -g";
2712 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
2713 }
Bob Kinged009652020-02-20 14:54:13 +08002714}