blob: 3bc52da31d99912eb31b81ff621a2cb0250a2bdf [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 */
Shawn McCarney0f6ebad2020-09-04 16:43:00 -050016#include "temporary_file.hpp"
Shawn McCarney80c0b042020-03-27 12:08:53 -050017
18#include <stdio.h> // for popen(), pclose(), fgets()
19#include <sys/stat.h> // for chmod()
20#include <sys/wait.h> // for WEXITSTATUS
Bob King386d33f2019-12-26 17:28:56 +080021
Bob King386d33f2019-12-26 17:28:56 +080022#include <nlohmann/json.hpp>
23
Shawn McCarney80c0b042020-03-27 12:08:53 -050024#include <cstdio>
Bob King0dcbdf52020-01-20 17:19:39 +080025#include <fstream>
26
Bob King386d33f2019-12-26 17:28:56 +080027#include <gtest/gtest.h>
28
29#define EXPECT_FILE_VALID(configFile) expectFileValid(configFile)
30#define EXPECT_FILE_INVALID(configFile, expectedErrorMessage, \
31 expectedOutputMessage) \
32 expectFileInvalid(configFile, expectedErrorMessage, expectedOutputMessage)
33#define EXPECT_JSON_VALID(configFileJson) expectJsonValid(configFileJson)
34#define EXPECT_JSON_INVALID(configFileJson, expectedErrorMessage, \
35 expectedOutputMessage) \
36 expectJsonInvalid(configFileJson, expectedErrorMessage, \
37 expectedOutputMessage)
38
39using json = nlohmann::json;
Shawn McCarney5f514442024-01-04 14:03:24 -060040using TemporaryFile = phosphor::power::util::TemporaryFile;
Bob King386d33f2019-12-26 17:28:56 +080041
42const json validConfigFile = R"(
43 {
44 "comments": [ "Config file for a FooBar one-chassis system" ],
45
46 "rules": [
47 {
48 "comments": [ "Sets output voltage for a PMBus regulator rail" ],
49 "id": "set_voltage_rule",
50 "actions": [
51 {
52 "pmbus_write_vout_command": {
53 "format": "linear"
54 }
55 }
56 ]
Bob Kingb3e48bc2020-02-18 09:59:09 +080057 },
58 {
59 "comments": [ "Reads sensors from a PMBus regulator rail" ],
60 "id": "read_sensors_rule",
61 "actions": [
62 {
63 "comments": [ "Read output voltage from READ_VOUT." ],
64 "pmbus_read_sensor": {
65 "type": "vout",
66 "command": "0x8B",
67 "format": "linear_16"
68 }
69 }
70 ]
Shawn McCarney846dde52021-08-14 12:47:44 -050071 },
72 {
73 "comments": [ "Detects presence of regulators associated with CPU3" ],
74 "id": "detect_presence_rule",
75 "actions": [
76 {
77 "compare_presence": {
78 "fru": "system/chassis/motherboard/cpu3",
79 "value": true
80 }
81 }
82 ]
83 },
84 {
85 "comments": [ "Detects and logs redundant phase faults" ],
86 "id": "detect_phase_faults_rule",
87 "actions": [
88 {
89 "if": {
90 "condition": {
91 "i2c_compare_bit": { "register": "0x02", "position": 3, "value": 1 }
92 },
93 "then": [
94 { "log_phase_fault": { "type": "n" } }
95 ]
96 }
97 }
98 ]
Bob King386d33f2019-12-26 17:28:56 +080099 }
100 ],
101
102 "chassis": [
103 {
104 "comments": [ "Chassis number 1 containing CPUs and memory" ],
105 "number": 1,
Shawn McCarneyecbeeea2021-04-29 21:08:18 -0500106 "inventory_path": "system/chassis",
Bob King386d33f2019-12-26 17:28:56 +0800107 "devices": [
108 {
109 "comments": [ "IR35221 regulator producing the Vdd rail" ],
110 "id": "vdd_regulator",
111 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +0800112 "fru": "system/chassis/motherboard/regulator1",
Bob King386d33f2019-12-26 17:28:56 +0800113 "i2c_interface": {
114 "bus": 1,
115 "address": "0x70"
116 },
117 "rails": [
118 {
119 "comments": [ "Vdd rail" ],
120 "id": "vdd",
121 "configuration": {
122 "volts": 1.03,
123 "rule_id": "set_voltage_rule"
124 },
125 "sensor_monitoring": {
126 "rule_id": "read_sensors_rule"
127 }
128 }
129 ]
130 }
131 ]
132 }
133 ]
134 }
135)"_json;
136
Bob King386d33f2019-12-26 17:28:56 +0800137std::string getValidationToolCommand(const std::string& configFileName)
138{
Bob Kinga57e0812020-03-12 10:47:42 +0800139 std::string command =
140 "../phosphor-regulators/tools/validate-regulators-config.py -s \
141 ../phosphor-regulators/schema/config_schema.json -c ";
Bob King386d33f2019-12-26 17:28:56 +0800142 command += configFileName;
143 return command;
144}
145
Bob Kinga57e0812020-03-12 10:47:42 +0800146int runToolForOutputWithCommand(std::string command,
147 std::string& standardOutput,
148 std::string& standardError)
Bob King386d33f2019-12-26 17:28:56 +0800149{
150 // run the validation tool with the temporary file and return the output
151 // of the validation tool.
Shawn McCarney0f6ebad2020-09-04 16:43:00 -0500152 TemporaryFile tmpFile;
153 command += " 2> " + tmpFile.getPath().string();
Bob King386d33f2019-12-26 17:28:56 +0800154 // get the jsonschema print from validation tool.
155 char buffer[256];
Bob Kinga57e0812020-03-12 10:47:42 +0800156 std::string result;
Bob King386d33f2019-12-26 17:28:56 +0800157 // to get the stdout from the validation tool.
158 FILE* pipe = popen(command.c_str(), "r");
159 if (!pipe)
160 {
161 throw std::runtime_error("popen() failed!");
162 }
163 while (!std::feof(pipe))
164 {
165 if (fgets(buffer, sizeof buffer, pipe) != NULL)
166 {
167 result += buffer;
168 }
169 }
170 int returnValue = pclose(pipe);
171 // Check if pclose() failed
172 if (returnValue == -1)
173 {
174 // unable to close pipe. Print error and exit function.
175 throw std::runtime_error("pclose() failed!");
176 }
177 std::string firstLine = result.substr(0, result.find('\n'));
Bob Kinga57e0812020-03-12 10:47:42 +0800178 standardOutput = firstLine;
Bob King386d33f2019-12-26 17:28:56 +0800179 // Get command exit status from return value
180 int exitStatus = WEXITSTATUS(returnValue);
Bob Kinga57e0812020-03-12 10:47:42 +0800181
182 // Read the standardError from tmpFile.
Shawn McCarney0f6ebad2020-09-04 16:43:00 -0500183 std::ifstream input(tmpFile.getPath());
Bob Kinga57e0812020-03-12 10:47:42 +0800184 std::string line;
185
186 if (std::getline(input, line))
187 {
188 standardError = line;
189 }
190
Bob King386d33f2019-12-26 17:28:56 +0800191 return exitStatus;
192}
193
Bob Kinged009652020-02-20 14:54:13 +0800194int runToolForOutput(const std::string& configFileName, std::string& output,
Bob Kinga57e0812020-03-12 10:47:42 +0800195 std::string& error)
Bob Kinged009652020-02-20 14:54:13 +0800196{
197 std::string command = getValidationToolCommand(configFileName);
Bob Kinga57e0812020-03-12 10:47:42 +0800198 return runToolForOutputWithCommand(command, output, error);
Bob Kinged009652020-02-20 14:54:13 +0800199}
200
Bob King386d33f2019-12-26 17:28:56 +0800201void expectFileValid(const std::string& configFileName)
202{
Bob Kinged009652020-02-20 14:54:13 +0800203 std::string errorMessage;
204 std::string outputMessage;
Bob Kinga57e0812020-03-12 10:47:42 +0800205 EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 0);
Bob King386d33f2019-12-26 17:28:56 +0800206 EXPECT_EQ(errorMessage, "");
207 EXPECT_EQ(outputMessage, "");
208}
209
210void expectFileInvalid(const std::string& configFileName,
211 const std::string& expectedErrorMessage,
212 const std::string& expectedOutputMessage)
213{
Bob Kinged009652020-02-20 14:54:13 +0800214 std::string errorMessage;
215 std::string outputMessage;
Bob Kinga57e0812020-03-12 10:47:42 +0800216 EXPECT_EQ(runToolForOutput(configFileName, outputMessage, errorMessage), 1);
Bob King386d33f2019-12-26 17:28:56 +0800217 EXPECT_EQ(errorMessage, expectedErrorMessage);
Shawn McCarney846dde52021-08-14 12:47:44 -0500218 if (expectedOutputMessage != "")
219 {
220 EXPECT_EQ(outputMessage, expectedOutputMessage);
221 }
Bob King386d33f2019-12-26 17:28:56 +0800222}
223
Bob Kinga57e0812020-03-12 10:47:42 +0800224void writeDataToFile(const json configFileJson, std::string fileName)
Bob King386d33f2019-12-26 17:28:56 +0800225{
Bob King386d33f2019-12-26 17:28:56 +0800226 std::string jsonData = configFileJson.dump();
227 std::ofstream out(fileName);
228 out << jsonData;
229 out.close();
Bob Kinged009652020-02-20 14:54:13 +0800230}
231
232void expectJsonValid(const json configFileJson)
233{
Shawn McCarney0f6ebad2020-09-04 16:43:00 -0500234 TemporaryFile tmpFile;
235 std::string fileName = tmpFile.getPath().string();
Bob Kinga57e0812020-03-12 10:47:42 +0800236 writeDataToFile(configFileJson, fileName);
Bob Kinged009652020-02-20 14:54:13 +0800237
Bob King386d33f2019-12-26 17:28:56 +0800238 EXPECT_FILE_VALID(fileName);
Bob King386d33f2019-12-26 17:28:56 +0800239}
240
241void expectJsonInvalid(const json configFileJson,
242 const std::string& expectedErrorMessage,
243 const std::string& expectedOutputMessage)
244{
Shawn McCarney0f6ebad2020-09-04 16:43:00 -0500245 TemporaryFile tmpFile;
246 std::string fileName = tmpFile.getPath().string();
Bob Kinga57e0812020-03-12 10:47:42 +0800247 writeDataToFile(configFileJson, fileName);
Bob King386d33f2019-12-26 17:28:56 +0800248
249 EXPECT_FILE_INVALID(fileName, expectedErrorMessage, expectedOutputMessage);
Bob King386d33f2019-12-26 17:28:56 +0800250}
251
Bob Kinged009652020-02-20 14:54:13 +0800252void expectCommandLineSyntax(const std::string& expectedErrorMessage,
253 const std::string& expectedOutputMessage,
Shawn McCarney525e20c2020-04-14 11:05:39 -0500254 const std::string& command, int status)
Bob Kinged009652020-02-20 14:54:13 +0800255{
256 std::string errorMessage;
257 std::string outputMessage;
Bob Kinga57e0812020-03-12 10:47:42 +0800258 EXPECT_EQ(runToolForOutputWithCommand(command, outputMessage, errorMessage),
259 status);
Bob Kinged009652020-02-20 14:54:13 +0800260 EXPECT_EQ(errorMessage, expectedErrorMessage);
261 EXPECT_EQ(outputMessage, expectedOutputMessage);
262}
263
Bob King3afa7112020-03-19 09:35:31 +0800264TEST(ValidateRegulatorsConfigTest, Action)
265{
266 // Valid: Comments property not specified
267 {
268 json configFile = validConfigFile;
269 EXPECT_JSON_VALID(configFile);
270 }
271 // Valid: Comments property specified
272 {
273 json configFile = validConfigFile;
274 configFile["rules"][0]["actions"][0]["comments"][0] =
275 "Set VOUT_COMMAND";
276 EXPECT_JSON_VALID(configFile);
277 }
278 // Valid: and action type specified
279 {
280 json configFile = validConfigFile;
281 json andAction =
282 R"(
283 {
284 "and": [
285 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
286 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
287 ]
288 }
289 )"_json;
290 configFile["rules"][0]["actions"].push_back(andAction);
291 EXPECT_JSON_VALID(configFile);
292 }
293 // Valid: compare_presence action type specified
294 {
295 json configFile = validConfigFile;
296 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +0800297 "system/chassis/motherboard/regulator2";
Bob King3afa7112020-03-19 09:35:31 +0800298 configFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
299 true;
300 EXPECT_JSON_VALID(configFile);
301 }
302 // Valid: compare_vpd action type specified
303 {
304 json configFile = validConfigFile;
305 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +0800306 "system/chassis/motherboard/regulator2";
Bob King3afa7112020-03-19 09:35:31 +0800307 configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
308 configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
309 EXPECT_JSON_VALID(configFile);
310 }
Shawn McCarney846dde52021-08-14 12:47:44 -0500311 // Valid: i2c_capture_bytes action type specified
312 {
313 json configFile = validConfigFile;
314 configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
315 "0xA0";
316 configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] = 2;
317 EXPECT_JSON_VALID(configFile);
318 }
Bob King3afa7112020-03-19 09:35:31 +0800319 // Valid: i2c_compare_bit action type specified
320 {
321 json configFile = validConfigFile;
322 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
323 "0xA0";
324 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 3;
325 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
326 EXPECT_JSON_VALID(configFile);
327 }
328 // Valid: i2c_compare_byte action type specified
329 {
330 json configFile = validConfigFile;
331 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
332 "0x82";
333 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
334 "0x40";
335 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
336 "0x7F";
337 EXPECT_JSON_VALID(configFile);
338 }
339 // Valid: i2c_compare_bytes action type specified
340 {
341 json configFile = validConfigFile;
342 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
343 "0x82";
344 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = {
345 "0x02", "0x73"};
346 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = {
347 "0x7F", "0x7F"};
348 EXPECT_JSON_VALID(configFile);
349 }
350 // Valid: i2c_write_bit action type specified
351 {
352 json configFile = validConfigFile;
353 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
354 "0xA0";
355 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3;
356 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 1;
357 EXPECT_JSON_VALID(configFile);
358 }
359 // Valid: i2c_write_byte action type specified
360 {
361 json configFile = validConfigFile;
362 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
363 "0x82";
364 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
365 "0x40";
366 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0x7F";
367 EXPECT_JSON_VALID(configFile);
368 }
369 // Valid: i2c_write_bytes action type specified
370 {
371 json configFile = validConfigFile;
372 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
373 "0x82";
374 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
375 "0x02", "0x73"};
376 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
377 "0x7F", "0x7F"};
378 EXPECT_JSON_VALID(configFile);
379 }
380 // Valid: if action type specified
381 {
382 json configFile = validConfigFile;
Shawn McCarney846dde52021-08-14 12:47:44 -0500383 configFile["rules"][4]["actions"][0]["if"]["condition"]["run_rule"] =
Bob King3afa7112020-03-19 09:35:31 +0800384 "set_voltage_rule";
Shawn McCarney846dde52021-08-14 12:47:44 -0500385 configFile["rules"][4]["actions"][0]["if"]["then"][0]["run_rule"] =
Bob King3afa7112020-03-19 09:35:31 +0800386 "read_sensors_rule";
Shawn McCarney846dde52021-08-14 12:47:44 -0500387 configFile["rules"][4]["actions"][0]["if"]["else"][0]["run_rule"] =
Bob King3afa7112020-03-19 09:35:31 +0800388 "read_sensors_rule";
Shawn McCarney846dde52021-08-14 12:47:44 -0500389 configFile["rules"][4]["id"] = "rule_if";
390 EXPECT_JSON_VALID(configFile);
391 }
392 // Valid: log_phase_fault action type specified
393 {
394 json configFile = validConfigFile;
395 configFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = "n+1";
Bob King3afa7112020-03-19 09:35:31 +0800396 EXPECT_JSON_VALID(configFile);
397 }
398 // Valid: not action type specified
399 {
400 json configFile = validConfigFile;
401 configFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]
402 ["register"] = "0xA0";
403 configFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]
404 ["value"] = "0xFF";
405 EXPECT_JSON_VALID(configFile);
406 }
407 // Valid: or action type specified
408 {
409 json configFile = validConfigFile;
410 configFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]
411 ["register"] = "0xA0";
412 configFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]
413 ["value"] = "0x00";
414 configFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]
415 ["register"] = "0xA1";
416 configFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]
417 ["value"] = "0x00";
418 EXPECT_JSON_VALID(configFile);
419 }
420 // Valid: pmbus_read_sensor and pmbus_write_vout_command action type
421 // specified
422 {
423 EXPECT_JSON_VALID(validConfigFile);
424 }
425 // Valid: run_rule action type specified
426 {
427 json configFile = validConfigFile;
428 configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
429 EXPECT_JSON_VALID(configFile);
430 }
431 // Valid: set_device action type specified
432 {
433 json configFile = validConfigFile;
434 configFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator";
435 EXPECT_JSON_VALID(configFile);
436 }
437 // Invalid: Wrong data type for comments (should be array of string)
438 {
439 json configFile = validConfigFile;
440 configFile["rules"][0]["actions"][0]["comments"] = true;
441 EXPECT_JSON_INVALID(configFile, "Validation failed.",
442 "True is not of type 'array'");
443 }
444 // Invalid: Wrong data type for action type (such as "i2c_write_byte": true)
445 {
446 json configFile = validConfigFile;
447 configFile["rules"][0]["actions"][1]["i2c_write_byte"] = true;
448 EXPECT_JSON_INVALID(configFile, "Validation failed.",
449 "True is not of type 'object'");
450 }
451 // Invalid: Empty comments array
452 {
453 json configFile = validConfigFile;
454 configFile["rules"][0]["actions"][0]["comments"] = json::array();
455 EXPECT_JSON_INVALID(configFile, "Validation failed.",
456 "[] is too short");
457 }
458 // Invalid: Comments array has wrong element type (should be string)
459 {
460 json configFile = validConfigFile;
461 configFile["rules"][0]["actions"][0]["comments"][0] = true;
462 EXPECT_JSON_INVALID(configFile, "Validation failed.",
463 "True is not of type 'string'");
464 }
465 // Invalid: No action type specified
466 {
467 json configFile = validConfigFile;
468 configFile["rules"][0]["actions"][1]["comments"][0] =
469 "Check if bit 3 is on";
Shawn McCarney0a2b76b2022-12-06 12:52:31 -0600470 EXPECT_JSON_INVALID(
471 configFile, "Validation failed.",
472 "{'comments': ['Check if bit 3 is on']} is not valid under any of the given schemas");
Bob King3afa7112020-03-19 09:35:31 +0800473 }
474 // Invalid: Multiple action types specified (such as both 'compare_presence'
475 // and 'pmbus_write_vout_command')
476 {
477 json configFile = validConfigFile;
478 configFile["rules"][0]["actions"][0]["compare_presence"]["value"] =
479 true;
480 EXPECT_JSON_INVALID(
481 configFile, "Validation failed.",
482 "{'compare_presence': {'value': True}, 'pmbus_write_vout_command': "
483 "{'format': 'linear'}} is valid under each of {'required': "
484 "['pmbus_write_vout_command']}, {'required': "
485 "['compare_presence']}");
486 }
487 // Invalid: Unexpected property specified (like 'foo')
488 {
489 json configFile = validConfigFile;
490 configFile["rules"][0]["actions"][1]["foo"] = "foo";
491 EXPECT_JSON_INVALID(
492 configFile, "Validation failed.",
493 "Additional properties are not allowed ('foo' was unexpected)");
494 }
495}
Shawn McCarney846dde52021-08-14 12:47:44 -0500496
Bob Kingbeaf6532020-01-21 11:03:49 +0800497TEST(ValidateRegulatorsConfigTest, And)
498{
499 // Valid.
500 {
501 json configFile = validConfigFile;
502 json andAction =
503 R"(
504 {
505 "and": [
506 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
507 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
508 ]
509 }
510 )"_json;
511 configFile["rules"][0]["actions"].push_back(andAction);
512 EXPECT_JSON_VALID(configFile);
513 }
514
515 // Invalid: actions property value is an empty array.
516 {
517 json configFile = validConfigFile;
518 json andAction =
519 R"(
520 {
521 "and": []
522 }
523 )"_json;
524 configFile["rules"][0]["actions"].push_back(andAction);
525 EXPECT_JSON_INVALID(configFile, "Validation failed.",
526 "[] is too short");
527 }
528
529 // Invalid: actions property has incorrect value data type.
530 {
531 json configFile = validConfigFile;
532 json andAction =
533 R"(
534 {
535 "and": true
536 }
537 )"_json;
538 configFile["rules"][0]["actions"].push_back(andAction);
539 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800540 "True is not of type 'array'");
Bob Kingbeaf6532020-01-21 11:03:49 +0800541 }
542
543 // Invalid: actions property value contains wrong element type
544 {
545 json configFile = validConfigFile;
546 json andAction =
547 R"(
548 {
549 "and": ["foo"]
550 }
551 )"_json;
552 configFile["rules"][0]["actions"].push_back(andAction);
553 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800554 "'foo' is not of type 'object'");
Bob Kingbeaf6532020-01-21 11:03:49 +0800555 }
556}
Shawn McCarney846dde52021-08-14 12:47:44 -0500557
Bob King3728f562020-01-21 11:35:31 +0800558TEST(ValidateRegulatorsConfigTest, Chassis)
559{
560 // Valid: test chassis.
561 {
562 json configFile = validConfigFile;
563 EXPECT_JSON_VALID(configFile);
564 }
Shawn McCarneyecbeeea2021-04-29 21:08:18 -0500565 // Valid: test chassis with only required properties.
Bob King3728f562020-01-21 11:35:31 +0800566 {
567 json configFile = validConfigFile;
568 configFile["chassis"][0].erase("comments");
569 configFile["chassis"][0].erase("devices");
570 EXPECT_JSON_VALID(configFile);
571 }
572 // Invalid: test chassis with no number.
573 {
574 json configFile = validConfigFile;
575 configFile["chassis"][0].erase("number");
576 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800577 "'number' is a required property");
Bob King3728f562020-01-21 11:35:31 +0800578 }
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500579 // Invalid: test chassis with no inventory_path.
580 {
581 json configFile = validConfigFile;
582 configFile["chassis"][0].erase("inventory_path");
583 EXPECT_JSON_INVALID(configFile, "Validation failed.",
584 "'inventory_path' is a required property");
585 }
Bob King3728f562020-01-21 11:35:31 +0800586 // Invalid: test chassis with property comments wrong type.
587 {
588 json configFile = validConfigFile;
589 configFile["chassis"][0]["comments"] = true;
590 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800591 "True is not of type 'array'");
Bob King3728f562020-01-21 11:35:31 +0800592 }
593 // Invalid: test chassis with property number wrong type.
594 {
595 json configFile = validConfigFile;
596 configFile["chassis"][0]["number"] = 1.3;
597 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800598 "1.3 is not of type 'integer'");
Bob King3728f562020-01-21 11:35:31 +0800599 }
Shawn McCarneyecbeeea2021-04-29 21:08:18 -0500600 // Invalid: test chassis with property inventory_path wrong type.
601 {
602 json configFile = validConfigFile;
603 configFile["chassis"][0]["inventory_path"] = 2;
604 EXPECT_JSON_INVALID(configFile, "Validation failed.",
605 "2 is not of type 'string'");
606 }
Bob King3728f562020-01-21 11:35:31 +0800607 // Invalid: test chassis with property devices wrong type.
608 {
609 json configFile = validConfigFile;
610 configFile["chassis"][0]["devices"] = true;
611 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800612 "True is not of type 'array'");
Bob King3728f562020-01-21 11:35:31 +0800613 }
614 // Invalid: test chassis with property comments empty array.
615 {
616 json configFile = validConfigFile;
617 configFile["chassis"][0]["comments"] = json::array();
618 EXPECT_JSON_INVALID(configFile, "Validation failed.",
619 "[] is too short");
620 }
621 // Invalid: test chassis with property devices empty array.
622 {
623 json configFile = validConfigFile;
624 configFile["chassis"][0]["devices"] = json::array();
625 EXPECT_JSON_INVALID(configFile, "Validation failed.",
626 "[] is too short");
627 }
628 // Invalid: test chassis with property number less than 1.
629 {
630 json configFile = validConfigFile;
631 configFile["chassis"][0]["number"] = 0;
632 EXPECT_JSON_INVALID(configFile, "Validation failed.",
633 "0 is less than the minimum of 1");
634 }
Shawn McCarneyecbeeea2021-04-29 21:08:18 -0500635 // Invalid: test chassis with property inventory_path empty string.
636 {
637 json configFile = validConfigFile;
638 configFile["chassis"][0]["inventory_path"] = "";
639 EXPECT_JSON_INVALID(configFile, "Validation failed.",
640 "'' is too short");
641 }
Bob King3728f562020-01-21 11:35:31 +0800642}
Shawn McCarney846dde52021-08-14 12:47:44 -0500643
Bob Kingbf1cbea2020-01-21 11:08:50 +0800644TEST(ValidateRegulatorsConfigTest, ComparePresence)
645{
646 json comparePresenceFile = validConfigFile;
647 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +0800648 "system/chassis/motherboard/regulator2";
Bob Kingbf1cbea2020-01-21 11:08:50 +0800649 comparePresenceFile["rules"][0]["actions"][1]["compare_presence"]["value"] =
650 true;
651 // Valid.
652 {
653 json configFile = comparePresenceFile;
654 EXPECT_JSON_VALID(configFile);
655 }
656
657 // Invalid: no FRU property.
658 {
659 json configFile = comparePresenceFile;
660 configFile["rules"][0]["actions"][1]["compare_presence"].erase("fru");
661 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800662 "'fru' is a required property");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800663 }
664
665 // Invalid: FRU property length is string less than 1.
666 {
667 json configFile = comparePresenceFile;
668 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = "";
669 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800670 "'' is too short");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800671 }
672
673 // Invalid: no value property.
674 {
675 json configFile = comparePresenceFile;
676 configFile["rules"][0]["actions"][1]["compare_presence"].erase("value");
677 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800678 "'value' is a required property");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800679 }
680
681 // Invalid: value property type is not boolean.
682 {
683 json configFile = comparePresenceFile;
684 configFile["rules"][0]["actions"][1]["compare_presence"]["value"] = "1";
685 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800686 "'1' is not of type 'boolean'");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800687 }
688
689 // Invalid: FRU property type is not string.
690 {
691 json configFile = comparePresenceFile;
692 configFile["rules"][0]["actions"][1]["compare_presence"]["fru"] = 1;
693 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800694 "1 is not of type 'string'");
Bob Kingbf1cbea2020-01-21 11:08:50 +0800695 }
696}
Shawn McCarney846dde52021-08-14 12:47:44 -0500697
Bob Kingf8b77a02020-01-21 11:09:47 +0800698TEST(ValidateRegulatorsConfigTest, CompareVpd)
699{
700 json compareVpdFile = validConfigFile;
701 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +0800702 "system/chassis/motherboard/regulator2";
Bob Kingf8b77a02020-01-21 11:09:47 +0800703 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] = "CCIN";
704 compareVpdFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "2D35";
705
Shawn McCarneya2a830b2021-10-30 14:24:31 -0500706 // Valid: value property: not empty.
Bob Kingf8b77a02020-01-21 11:09:47 +0800707 {
708 json configFile = compareVpdFile;
709 EXPECT_JSON_VALID(configFile);
710 }
Shawn McCarneya2a830b2021-10-30 14:24:31 -0500711
712 // Valid: value property: empty.
713 {
714 json configFile = compareVpdFile;
715 configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = "";
716 EXPECT_JSON_VALID(configFile);
717 }
718
719 // Valid: byte_values property: not empty.
Matt Spinleraacc2aa2021-05-25 09:31:35 -0600720 {
721 json configFile = compareVpdFile;
722 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
723 configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] = {
724 "0x01", "0x02"};
725 EXPECT_JSON_VALID(configFile);
726 }
Bob Kingf8b77a02020-01-21 11:09:47 +0800727
Shawn McCarneya2a830b2021-10-30 14:24:31 -0500728 // Valid: byte_values property: empty.
729 {
730 json configFile = compareVpdFile;
731 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
732 configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] =
733 json::array();
734 EXPECT_JSON_VALID(configFile);
735 }
736
Bob Kingf8b77a02020-01-21 11:09:47 +0800737 // Invalid: no FRU property.
738 {
739 json configFile = compareVpdFile;
740 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("fru");
741 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800742 "'fru' is a required property");
Bob Kingf8b77a02020-01-21 11:09:47 +0800743 }
744
745 // Invalid: no keyword property.
746 {
747 json configFile = compareVpdFile;
748 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("keyword");
749 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800750 "'keyword' is a required property");
Bob Kingf8b77a02020-01-21 11:09:47 +0800751 }
752
753 // Invalid: no value property.
754 {
755 json configFile = compareVpdFile;
756 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
Shawn McCarney0a2b76b2022-12-06 12:52:31 -0600757 EXPECT_JSON_INVALID(
758 configFile, "Validation failed.",
759 "{'fru': 'system/chassis/motherboard/regulator2', 'keyword': 'CCIN'} is not valid under any of the given schemas");
Bob Kingf8b77a02020-01-21 11:09:47 +0800760 }
761
762 // Invalid: property FRU wrong type.
763 {
764 json configFile = compareVpdFile;
765 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = 1;
766 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800767 "1 is not of type 'string'");
Bob Kingf8b77a02020-01-21 11:09:47 +0800768 }
769
770 // Invalid: property FRU is string less than 1.
771 {
772 json configFile = compareVpdFile;
773 configFile["rules"][0]["actions"][1]["compare_vpd"]["fru"] = "";
774 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800775 "'' is too short");
Bob Kingf8b77a02020-01-21 11:09:47 +0800776 }
777
778 // Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
Matt Spinleraacc2aa2021-05-25 09:31:35 -0600779 // "PartNumber", "HW"
Bob Kingf8b77a02020-01-21 11:09:47 +0800780 {
781 json configFile = compareVpdFile;
782 configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
783 "Number";
784 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800785 "'Number' is not one of ['CCIN', "
Matt Spinleraacc2aa2021-05-25 09:31:35 -0600786 "'Manufacturer', 'Model', 'PartNumber', 'HW']");
Bob Kingf8b77a02020-01-21 11:09:47 +0800787 }
788
789 // Invalid: property value wrong type.
790 {
791 json configFile = compareVpdFile;
792 configFile["rules"][0]["actions"][1]["compare_vpd"]["value"] = 1;
793 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800794 "1 is not of type 'string'");
Bob Kingf8b77a02020-01-21 11:09:47 +0800795 }
Matt Spinleraacc2aa2021-05-25 09:31:35 -0600796
797 // Invalid: property byte_values has wrong type
798 {
799 json configFile = compareVpdFile;
800 configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
801 configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] =
802 "0x50";
803 EXPECT_JSON_INVALID(configFile, "Validation failed.",
804 "'0x50' is not of type 'array'");
805 }
806
Matt Spinleraacc2aa2021-05-25 09:31:35 -0600807 // Invalid: properties byte_values and value both exist
808 {
809 json configFile = compareVpdFile;
810 configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] = {
811 "0x01", "0x02"};
812 EXPECT_JSON_INVALID(
813 configFile, "Validation failed.",
814 "{'byte_values': ['0x01', '0x02'], 'fru': "
815 "'system/chassis/motherboard/regulator2', 'keyword': 'CCIN', "
816 "'value': '2D35'} is valid under each of {'required': "
817 "['byte_values']}, {'required': ['value']}");
818 }
Bob Kingf8b77a02020-01-21 11:09:47 +0800819}
Shawn McCarney846dde52021-08-14 12:47:44 -0500820
Bob King20057412020-03-16 16:50:17 +0800821TEST(ValidateRegulatorsConfigTest, ConfigFile)
822{
823 // Valid: Only required properties specified
824 {
825 json configFile;
826 configFile["chassis"][0]["number"] = 1;
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500827 configFile["chassis"][0]["inventory_path"] = "system/chassis";
Bob King20057412020-03-16 16:50:17 +0800828 EXPECT_JSON_VALID(configFile);
829 }
830 // Valid: All properties specified
831 {
832 json configFile = validConfigFile;
833 EXPECT_JSON_VALID(configFile);
834 }
835 // Invalid: Required chassis property not specified
836 {
837 json configFile = validConfigFile;
838 configFile.erase("chassis");
839 EXPECT_JSON_INVALID(configFile, "Validation failed.",
840 "'chassis' is a required property");
841 }
842 // Invalid: Wrong data type for comments
843 {
844 json configFile = validConfigFile;
845 configFile["comments"] = true;
846 EXPECT_JSON_INVALID(configFile, "Validation failed.",
847 "True is not of type 'array'");
848 }
849 // Invalid: Wrong data type for rules
850 {
851 json configFile = validConfigFile;
852 configFile["rules"] = true;
853 EXPECT_JSON_INVALID(configFile, "Validation failed.",
854 "True is not of type 'array'");
855 }
856 // Invalid: Wrong data type for chassis
857 {
858 json configFile = validConfigFile;
859 configFile["chassis"] = true;
860 EXPECT_JSON_INVALID(configFile, "Validation failed.",
861 "True is not of type 'array'");
862 }
863 // Invalid: Empty comments array;
864 {
865 json configFile = validConfigFile;
866 configFile["comments"] = json::array();
867 EXPECT_JSON_INVALID(configFile, "Validation failed.",
868 "[] is too short");
869 }
870 // Invalid: Empty rules array
871 {
872 json configFile = validConfigFile;
873 configFile["rules"] = json::array();
874 EXPECT_JSON_INVALID(configFile, "Validation failed.",
875 "[] is too short");
876 }
877 // Invalid: Empty chassis array
878 {
879 json configFile = validConfigFile;
880 configFile["chassis"] = json::array();
881 EXPECT_JSON_INVALID(configFile, "Validation failed.",
882 "[] is too short");
883 }
884 // Invalid: Comments array has wrong element type (should be string)
885 {
886 json configFile = validConfigFile;
887 configFile["comments"][0] = true;
888 EXPECT_JSON_INVALID(configFile, "Validation failed.",
889 "True is not of type 'string'");
890 }
891 // Invalid: Rules array has wrong element type (should be rule)
892 {
893 json configFile = validConfigFile;
894 configFile["rules"][0] = true;
895 EXPECT_JSON_INVALID(configFile, "Validation failed.",
896 "True is not of type 'object'");
897 }
898 // Invalid: Chassis array has wrong element type (should be chassis)
899 {
900 json configFile = validConfigFile;
901 configFile["chassis"][0] = true;
902 EXPECT_JSON_INVALID(configFile, "Validation failed.",
903 "True is not of type 'object'");
904 }
905 // Invalid: Unexpected property specified
906 {
907 json configFile = validConfigFile;
908 configFile["foo"] = json::array();
909 EXPECT_JSON_INVALID(
910 configFile, "Validation failed.",
911 "Additional properties are not allowed ('foo' was unexpected)");
912 }
913}
Shawn McCarney846dde52021-08-14 12:47:44 -0500914
Bob King4c67a3a2020-02-07 09:48:11 +0800915TEST(ValidateRegulatorsConfigTest, Configuration)
916{
917 json configurationFile = validConfigFile;
918 configurationFile["chassis"][0]["devices"][0]["configuration"]["comments"]
919 [0] = "Set rail to 1.25V using standard rule";
920 configurationFile["chassis"][0]["devices"][0]["configuration"]["volts"] =
921 1.25;
922 configurationFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
923 "set_voltage_rule";
924 // Valid: test configuration with property rule_id and with no actions.
925 {
926 json configFile = configurationFile;
Bob King78793102020-03-13 13:16:09 +0800927 configFile["chassis"][0]["devices"][0]["configuration"]["comments"][1] =
928 "test multiple array elements in comments.";
Bob King4c67a3a2020-02-07 09:48:11 +0800929 EXPECT_JSON_VALID(configFile);
930 }
931 // Valid: test configuration with property actions and with no rule_id.
932 {
933 json configFile = configurationFile;
934 configFile["chassis"][0]["devices"][0]["configuration"].erase(
935 "rule_id");
936 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
937 ["compare_presence"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +0800938 "system/chassis/motherboard/cpu3";
Bob King4c67a3a2020-02-07 09:48:11 +0800939 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
940 ["compare_presence"]["value"] = true;
941 EXPECT_JSON_VALID(configFile);
942 }
943 // Valid: comments not specified (optional property).
944 {
945 json configFile = configurationFile;
946 configFile["chassis"][0]["devices"][0]["configuration"].erase(
947 "comments");
948 EXPECT_JSON_VALID(configFile);
949 }
950 // Valid: volts not specified (optional property).
951 {
952 json configFile = configurationFile;
953 configFile["chassis"][0]["devices"][0]["configuration"].erase("volts");
954 EXPECT_JSON_VALID(configFile);
955 }
956 // Valid: configuration is property of a rail (vs. a device).
957 {
958 json configFile = validConfigFile;
959 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
960 ["comments"][0] = "Set rail to 1.25V using standard rule";
961 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
962 ["volts"] = 1.25;
963 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"]
964 ["rule_id"] = "set_voltage_rule";
965 EXPECT_JSON_VALID(configFile);
966 }
967 // Invalid: comments property has wrong data type (not an array).
968 {
969 json configFile = configurationFile;
970 configFile["chassis"][0]["devices"][0]["configuration"]["comments"] = 1;
971 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800972 "1 is not of type 'array'");
Bob King4c67a3a2020-02-07 09:48:11 +0800973 }
974 // Invalid: test configuration with both actions and rule_id properties.
975 {
976 json configFile = configurationFile;
977 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
978 ["compare_presence"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +0800979 "system/chassis/motherboard/cpu3";
Bob King4c67a3a2020-02-07 09:48:11 +0800980 configFile["chassis"][0]["devices"][0]["configuration"]["actions"][0]
981 ["compare_presence"]["value"] = true;
Shawn McCarney846dde52021-08-14 12:47:44 -0500982 EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
Bob King4c67a3a2020-02-07 09:48:11 +0800983 }
984 // Invalid: test configuration with no rule_id and actions.
985 {
986 json configFile = configurationFile;
987 configFile["chassis"][0]["devices"][0]["configuration"].erase(
988 "rule_id");
Shawn McCarney0a2b76b2022-12-06 12:52:31 -0600989 EXPECT_JSON_INVALID(
990 configFile, "Validation failed.",
991 "{'comments': ['Set rail to 1.25V using standard rule'], 'volts': 1.25} is not valid under any of the given schemas");
Bob King4c67a3a2020-02-07 09:48:11 +0800992 }
993 // Invalid: test configuration with property volts wrong type.
994 {
995 json configFile = configurationFile;
996 configFile["chassis"][0]["devices"][0]["configuration"]["volts"] = true;
997 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +0800998 "True is not of type 'number'");
Bob King4c67a3a2020-02-07 09:48:11 +0800999 }
1000 // Invalid: test configuration with property rule_id wrong type.
1001 {
1002 json configFile = configurationFile;
1003 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
1004 true;
1005 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001006 "True is not of type 'string'");
Bob King4c67a3a2020-02-07 09:48:11 +08001007 }
1008 // Invalid: test configuration with property actions wrong type.
1009 {
1010 json configFile = configurationFile;
1011 configFile["chassis"][0]["devices"][0]["configuration"].erase(
1012 "rule_id");
1013 configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
1014 true;
1015 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001016 "True is not of type 'array'");
Bob King4c67a3a2020-02-07 09:48:11 +08001017 }
1018 // Invalid: test configuration with property comments empty array.
1019 {
1020 json configFile = configurationFile;
1021 configFile["chassis"][0]["devices"][0]["configuration"]["comments"] =
1022 json::array();
1023 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1024 "[] is too short");
1025 }
1026 // Invalid: test configuration with property rule_id wrong format.
1027 {
1028 json configFile = configurationFile;
1029 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
1030 "id!";
1031 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001032 "'id!' does not match '^[A-Za-z0-9_]+$'");
Bob King4c67a3a2020-02-07 09:48:11 +08001033 }
1034 // Invalid: test configuration with property actions empty array.
1035 {
1036 json configFile = configurationFile;
1037 configFile["chassis"][0]["devices"][0]["configuration"].erase(
1038 "rule_id");
1039 configFile["chassis"][0]["devices"][0]["configuration"]["actions"] =
1040 json::array();
1041 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1042 "[] is too short");
1043 }
1044}
Shawn McCarney846dde52021-08-14 12:47:44 -05001045
Bob Kinga2ba2df2020-02-04 14:38:44 +08001046TEST(ValidateRegulatorsConfigTest, Device)
1047{
Bob Kinga2ba2df2020-02-04 14:38:44 +08001048 // Valid: test devices.
1049 {
1050 json configFile = validConfigFile;
1051 EXPECT_JSON_VALID(configFile);
1052 }
1053 // Valid: test devices with required properties.
1054 {
1055 json configFile = validConfigFile;
1056 configFile["chassis"][0]["devices"][0].erase("comments");
1057 configFile["chassis"][0]["devices"][0].erase("presence_detection");
1058 configFile["chassis"][0]["devices"][0].erase("configuration");
Shawn McCarney846dde52021-08-14 12:47:44 -05001059 configFile["chassis"][0]["devices"][0].erase("phase_fault_detection");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001060 configFile["chassis"][0]["devices"][0].erase("rails");
1061 EXPECT_JSON_VALID(configFile);
1062 }
1063 // Invalid: test devices with no id.
1064 {
1065 json configFile = validConfigFile;
1066 configFile["chassis"][0]["devices"][0].erase("id");
1067 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001068 "'id' is a required property");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001069 }
1070 // Invalid: test devices with no is_regulator.
1071 {
1072 json configFile = validConfigFile;
1073 configFile["chassis"][0]["devices"][0].erase("is_regulator");
Shawn McCarney0a2b76b2022-12-06 12:52:31 -06001074 EXPECT_JSON_INVALID(
1075 configFile, "Validation failed.",
1076 "{'comments': ['IR35221 regulator producing the Vdd rail'], 'fru': 'system/chassis/motherboard/regulator1', 'i2c_interface': {'address': '0x70', 'bus': 1}, 'id': 'vdd_regulator', 'rails': [{'comments': ['Vdd rail'], 'configuration': {'rule_id': 'set_voltage_rule', 'volts': 1.03}, 'id': 'vdd', 'sensor_monitoring': {'rule_id': 'read_sensors_rule'}}]} should not be valid under {'anyOf': [{'required': ['phase_fault_detection']}, {'required': ['rails']}]}");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001077 }
1078 // Invalid: test devices with no fru.
1079 {
1080 json configFile = validConfigFile;
1081 configFile["chassis"][0]["devices"][0].erase("fru");
1082 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001083 "'fru' is a required property");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001084 }
1085 // Invalid: test devices with no i2c_interface.
1086 {
1087 json configFile = validConfigFile;
1088 configFile["chassis"][0]["devices"][0].erase("i2c_interface");
1089 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001090 "'i2c_interface' is a required property");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001091 }
Shawn McCarney846dde52021-08-14 12:47:44 -05001092 // Invalid: is_regulator=false: phase_fault_detection specified
1093 {
1094 json configFile = validConfigFile;
1095 configFile["chassis"][0]["devices"][0]["is_regulator"] = false;
1096 configFile["chassis"][0]["devices"][0].erase("rails");
1097 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
1098 ["rule_id"] = "detect_phase_faults_rule";
1099 EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
1100 }
1101 // Invalid: is_regulator=false: rails specified
1102 {
1103 json configFile = validConfigFile;
1104 configFile["chassis"][0]["devices"][0]["is_regulator"] = false;
1105 EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
1106 }
1107 // Invalid: is_regulator=false: phase_fault_detection and rails specified
1108 {
1109 json configFile = validConfigFile;
1110 configFile["chassis"][0]["devices"][0]["is_regulator"] = false;
1111 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
1112 ["rule_id"] = "detect_phase_faults_rule";
1113 EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
1114 }
Bob Kinga2ba2df2020-02-04 14:38:44 +08001115 // Invalid: test devices with property comments wrong type.
1116 {
1117 json configFile = validConfigFile;
1118 configFile["chassis"][0]["devices"][0]["comments"] = true;
1119 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001120 "True is not of type 'array'");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001121 }
1122 // Invalid: test devices with property id wrong type.
1123 {
1124 json configFile = validConfigFile;
1125 configFile["chassis"][0]["devices"][0]["id"] = true;
1126 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001127 "True is not of type 'string'");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001128 }
1129 // Invalid: test devices with property is_regulator wrong type.
1130 {
1131 json configFile = validConfigFile;
1132 configFile["chassis"][0]["devices"][0]["is_regulator"] = 1;
1133 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001134 "1 is not of type 'boolean'");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001135 }
1136 // Invalid: test devices with property fru wrong type.
1137 {
1138 json configFile = validConfigFile;
1139 configFile["chassis"][0]["devices"][0]["fru"] = true;
1140 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001141 "True is not of type 'string'");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001142 }
1143 // Invalid: test devices with property i2c_interface wrong type.
1144 {
1145 json configFile = validConfigFile;
1146 configFile["chassis"][0]["devices"][0]["i2c_interface"] = true;
1147 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001148 "True is not of type 'object'");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001149 }
1150 // Invalid: test devices with property presence_detection wrong
1151 // type.
1152 {
1153 json configFile = validConfigFile;
1154 configFile["chassis"][0]["devices"][0]["presence_detection"] = true;
1155 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001156 "True is not of type 'object'");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001157 }
1158 // Invalid: test devices with property configuration wrong type.
1159 {
1160 json configFile = validConfigFile;
1161 configFile["chassis"][0]["devices"][0]["configuration"] = true;
1162 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001163 "True is not of type 'object'");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001164 }
Shawn McCarney846dde52021-08-14 12:47:44 -05001165 // Invalid: test devices with property phase_fault_detection wrong type.
1166 {
1167 json configFile = validConfigFile;
1168 configFile["chassis"][0]["devices"][0]["phase_fault_detection"] = true;
1169 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1170 "True is not of type 'object'");
1171 }
Bob Kinga2ba2df2020-02-04 14:38:44 +08001172 // Invalid: test devices with property rails wrong type.
1173 {
1174 json configFile = validConfigFile;
1175 configFile["chassis"][0]["devices"][0]["rails"] = true;
1176 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001177 "True is not of type 'array'");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001178 }
1179 // Invalid: test devices with property comments empty array.
1180 {
1181 json configFile = validConfigFile;
1182 configFile["chassis"][0]["devices"][0]["comments"] = json::array();
1183 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1184 "[] is too short");
1185 }
1186 // Invalid: test devices with property fru length less than 1.
1187 {
1188 json configFile = validConfigFile;
1189 configFile["chassis"][0]["devices"][0]["fru"] = "";
1190 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001191 "'' is too short");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001192 }
1193 // Invalid: test devices with property id wrong format.
1194 {
1195 json configFile = validConfigFile;
1196 configFile["chassis"][0]["devices"][0]["id"] = "id#";
1197 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001198 "'id#' does not match '^[A-Za-z0-9_]+$'");
Bob Kinga2ba2df2020-02-04 14:38:44 +08001199 }
1200 // Invalid: test devices with property rails empty array.
1201 {
1202 json configFile = validConfigFile;
1203 configFile["chassis"][0]["devices"][0]["rails"] = json::array();
1204 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1205 "[] is too short");
1206 }
1207}
Shawn McCarney846dde52021-08-14 12:47:44 -05001208
1209TEST(ValidateRegulatorsConfigTest, I2CCaptureBytes)
1210{
1211 json initialFile = validConfigFile;
1212 initialFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
1213 "0xA0";
1214 initialFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] = 2;
1215
1216 // Valid: All required properties
1217 {
1218 json configFile = initialFile;
1219 EXPECT_JSON_VALID(configFile);
1220 }
1221
1222 // Invalid: register not specified
1223 {
1224 json configFile = initialFile;
1225 configFile["rules"][0]["actions"][1]["i2c_capture_bytes"].erase(
1226 "register");
1227 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1228 "'register' is a required property");
1229 }
1230
1231 // Invalid: count not specified
1232 {
1233 json configFile = initialFile;
1234 configFile["rules"][0]["actions"][1]["i2c_capture_bytes"].erase(
1235 "count");
1236 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1237 "'count' is a required property");
1238 }
1239
1240 // Invalid: invalid property specified
1241 {
1242 json configFile = initialFile;
1243 configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["foo"] = true;
1244 EXPECT_JSON_INVALID(
1245 configFile, "Validation failed.",
1246 "Additional properties are not allowed ('foo' was unexpected)");
1247 }
1248
1249 // Invalid: register has wrong data type
1250 {
1251 json configFile = initialFile;
1252 configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
1253 1;
1254 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1255 "1 is not of type 'string'");
1256 }
1257
1258 // Invalid: register has wrong format
1259 {
1260 json configFile = initialFile;
1261 configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["register"] =
1262 "0xA00";
1263 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1264 "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
1265 }
1266
1267 // Invalid: count has wrong data type
1268 {
1269 json configFile = initialFile;
1270 configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] =
1271 3.1;
1272 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1273 "3.1 is not of type 'integer'");
1274 }
1275
1276 // Invalid: count < 1
1277 {
1278 json configFile = initialFile;
1279 configFile["rules"][0]["actions"][1]["i2c_capture_bytes"]["count"] = 0;
1280 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1281 "0 is less than the minimum of 1");
1282 }
1283}
1284
Bob King4ab8cbb2020-01-21 11:10:48 +08001285TEST(ValidateRegulatorsConfigTest, I2CCompareBit)
1286{
1287 json i2cCompareBitFile = validConfigFile;
1288 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
1289 "0xA0";
1290 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
1291 3;
1292 i2cCompareBitFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 1;
1293 // Valid: test rule actions i2c_compare_bit.
1294 {
1295 json configFile = i2cCompareBitFile;
1296 EXPECT_JSON_VALID(configFile);
1297 }
1298 // Invalid: test i2c_compare_bit with no register.
1299 {
1300 json configFile = i2cCompareBitFile;
1301 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
1302 "register");
1303 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001304 "'register' is a required property");
Bob King4ab8cbb2020-01-21 11:10:48 +08001305 }
1306 // Invalid: test i2c_compare_bit with no position.
1307 {
1308 json configFile = i2cCompareBitFile;
1309 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase(
1310 "position");
1311 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001312 "'position' is a required property");
Bob King4ab8cbb2020-01-21 11:10:48 +08001313 }
1314 // Invalid: test i2c_compare_bit with no value.
1315 {
1316 json configFile = i2cCompareBitFile;
1317 configFile["rules"][0]["actions"][1]["i2c_compare_bit"].erase("value");
1318 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001319 "'value' is a required property");
Bob King4ab8cbb2020-01-21 11:10:48 +08001320 }
1321 // Invalid: test i2c_compare_bit with register wrong type.
1322 {
1323 json configFile = i2cCompareBitFile;
1324 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] = 1;
1325 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001326 "1 is not of type 'string'");
Bob King4ab8cbb2020-01-21 11:10:48 +08001327 }
1328 // Invalid: test i2c_compare_bit with register wrong format.
1329 {
1330 json configFile = i2cCompareBitFile;
1331 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["register"] =
1332 "0xA00";
1333 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001334 "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King4ab8cbb2020-01-21 11:10:48 +08001335 }
1336 // Invalid: test i2c_compare_bit with position wrong type.
1337 {
1338 json configFile = i2cCompareBitFile;
1339 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
1340 3.1;
1341 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001342 "3.1 is not of type 'integer'");
Bob King4ab8cbb2020-01-21 11:10:48 +08001343 }
1344 // Invalid: test i2c_compare_bit with position greater than 7.
1345 {
1346 json configFile = i2cCompareBitFile;
1347 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] = 8;
1348 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1349 "8 is greater than the maximum of 7");
1350 }
1351 // Invalid: test i2c_compare_bit with position less than 0.
1352 {
1353 json configFile = i2cCompareBitFile;
1354 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["position"] =
1355 -1;
1356 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1357 "-1 is less than the minimum of 0");
1358 }
1359 // Invalid: test i2c_compare_bit with value wrong type.
1360 {
1361 json configFile = i2cCompareBitFile;
1362 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = "1";
1363 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001364 "'1' is not of type 'integer'");
Bob King4ab8cbb2020-01-21 11:10:48 +08001365 }
1366 // Invalid: test i2c_compare_bit with value greater than 1.
1367 {
1368 json configFile = i2cCompareBitFile;
1369 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = 2;
1370 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1371 "2 is greater than the maximum of 1");
1372 }
1373 // Invalid: test i2c_compare_bit with value less than 0.
1374 {
1375 json configFile = i2cCompareBitFile;
1376 configFile["rules"][0]["actions"][1]["i2c_compare_bit"]["value"] = -1;
1377 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1378 "-1 is less than the minimum of 0");
1379 }
1380}
Shawn McCarney846dde52021-08-14 12:47:44 -05001381
Bob King514023d2020-01-21 11:13:05 +08001382TEST(ValidateRegulatorsConfigTest, I2CCompareByte)
1383{
1384 json i2cCompareByteFile = validConfigFile;
1385 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]
1386 ["register"] = "0x82";
1387 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1388 "0x40";
1389 i2cCompareByteFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
1390 "0x7F";
1391 // Valid: test i2c_compare_byte with all properties.
1392 {
1393 json configFile = i2cCompareByteFile;
1394 EXPECT_JSON_VALID(configFile);
1395 }
1396 // Valid: test i2c_compare_byte with all required properties.
1397 {
1398 json configFile = i2cCompareByteFile;
1399 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("mask");
1400 EXPECT_JSON_VALID(configFile);
1401 }
1402 // Invalid: test i2c_compare_byte with no register.
1403 {
1404 json configFile = i2cCompareByteFile;
1405 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase(
1406 "register");
1407 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001408 "'register' is a required property");
Bob King514023d2020-01-21 11:13:05 +08001409 }
1410 // Invalid: test i2c_compare_byte with no value.
1411 {
1412 json configFile = i2cCompareByteFile;
1413 configFile["rules"][0]["actions"][1]["i2c_compare_byte"].erase("value");
1414 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001415 "'value' is a required property");
Bob King514023d2020-01-21 11:13:05 +08001416 }
1417 // Invalid: test i2c_compare_byte with property register wrong type.
1418 {
1419 json configFile = i2cCompareByteFile;
1420 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1421 1;
1422 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001423 "1 is not of type 'string'");
Bob King514023d2020-01-21 11:13:05 +08001424 }
1425 // Invalid: test i2c_compare_byte with property value wrong type.
1426 {
1427 json configFile = i2cCompareByteFile;
1428 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] = 1;
1429 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001430 "1 is not of type 'string'");
Bob King514023d2020-01-21 11:13:05 +08001431 }
1432 // Invalid: test i2c_compare_byte with property mask wrong type.
1433 {
1434 json configFile = i2cCompareByteFile;
1435 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = 1;
1436 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001437 "1 is not of type 'string'");
Bob King514023d2020-01-21 11:13:05 +08001438 }
1439 // Invalid: test i2c_compare_byte with property register more than 2 hex
1440 // digits.
1441 {
1442 json configFile = i2cCompareByteFile;
1443 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1444 "0x820";
1445 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001446 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001447 }
1448 // Invalid: test i2c_compare_byte with property value more than 2 hex
1449 // digits.
1450 {
1451 json configFile = i2cCompareByteFile;
1452 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1453 "0x820";
1454 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001455 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001456 }
1457 // Invalid: test i2c_compare_byte with property mask more than 2 hex digits.
1458 {
1459 json configFile = i2cCompareByteFile;
1460 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
1461 "0x820";
1462 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001463 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001464 }
1465 // Invalid: test i2c_compare_byte with property register less than 2 hex
1466 // digits.
1467 {
1468 json configFile = i2cCompareByteFile;
1469 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1470 "0x8";
1471 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001472 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001473 }
1474 // Invalid: test i2c_compare_byte with property value less than 2 hex
1475 // digits.
1476 {
1477 json configFile = i2cCompareByteFile;
1478 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1479 "0x8";
1480 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001481 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001482 }
1483 // Invalid: test i2c_compare_byte with property mask less than 2 hex digits.
1484 {
1485 json configFile = i2cCompareByteFile;
1486 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
1487 "0x8";
1488 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001489 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001490 }
1491 // Invalid: test i2c_compare_byte with property register no leading prefix.
1492 {
1493 json configFile = i2cCompareByteFile;
1494 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1495 "82";
1496 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001497 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001498 }
1499 // Invalid: test i2c_compare_byte with property value no leading prefix.
1500 {
1501 json configFile = i2cCompareByteFile;
1502 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1503 "82";
1504 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001505 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001506 }
1507 // Invalid: test i2c_compare_byte with property mask no leading prefix.
1508 {
1509 json configFile = i2cCompareByteFile;
1510 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] = "82";
1511 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001512 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001513 }
1514 // Invalid: test i2c_compare_byte with property register invalid hex digit.
1515 {
1516 json configFile = i2cCompareByteFile;
1517 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["register"] =
1518 "0xG1";
1519 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001520 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001521 }
1522 // Invalid: test i2c_compare_byte with property value invalid hex digit.
1523 {
1524 json configFile = i2cCompareByteFile;
1525 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["value"] =
1526 "0xG1";
1527 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001528 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001529 }
1530 // Invalid: test i2c_compare_byte with property mask invalid hex digit.
1531 {
1532 json configFile = i2cCompareByteFile;
1533 configFile["rules"][0]["actions"][1]["i2c_compare_byte"]["mask"] =
1534 "0xG1";
1535 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001536 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King514023d2020-01-21 11:13:05 +08001537 }
1538}
Shawn McCarney846dde52021-08-14 12:47:44 -05001539
Bob Kingfb162bb2020-01-21 11:28:07 +08001540TEST(ValidateRegulatorsConfigTest, I2CCompareBytes)
1541{
1542 json i2cCompareBytesFile = validConfigFile;
1543 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
1544 ["register"] = "0x82";
1545 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
1546 ["values"] = {"0x02", "0x73"};
1547 i2cCompareBytesFile["rules"][0]["actions"][1]["i2c_compare_bytes"]
1548 ["masks"] = {"0x7F", "0x7F"};
1549 // Valid: test i2c_compare_bytes.
1550 {
1551 json configFile = i2cCompareBytesFile;
1552 EXPECT_JSON_VALID(configFile);
1553 }
1554 // Valid: test i2c_compare_bytes with all required properties.
1555 {
1556 json configFile = i2cCompareBytesFile;
1557 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1558 "masks");
1559 EXPECT_JSON_VALID(configFile);
1560 }
1561 // Invalid: test i2c_compare_bytes with no register.
1562 {
1563 json configFile = i2cCompareBytesFile;
1564 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1565 "register");
1566 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001567 "'register' is a required property");
Bob Kingfb162bb2020-01-21 11:28:07 +08001568 }
1569 // Invalid: test i2c_compare_bytes with no values.
1570 {
1571 json configFile = i2cCompareBytesFile;
1572 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"].erase(
1573 "values");
1574 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001575 "'values' is a required property");
Bob Kingfb162bb2020-01-21 11:28:07 +08001576 }
1577 // Invalid: test i2c_compare_bytes with property values as empty array.
1578 {
1579 json configFile = i2cCompareBytesFile;
1580 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] =
1581 json::array();
1582 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1583 "[] is too short");
1584 }
1585 // Invalid: test i2c_compare_bytes with property masks as empty array.
1586 {
1587 json configFile = i2cCompareBytesFile;
1588 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] =
1589 json::array();
1590 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1591 "[] is too short");
1592 }
1593 // Invalid: test i2c_compare_bytes with property register wrong type.
1594 {
1595 json configFile = i2cCompareBytesFile;
1596 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1597 1;
1598 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001599 "1 is not of type 'string'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001600 }
1601 // Invalid: test i2c_compare_bytes with property values wrong type.
1602 {
1603 json configFile = i2cCompareBytesFile;
1604 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = 1;
1605 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001606 "1 is not of type 'array'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001607 }
1608 // Invalid: test i2c_compare_bytes with property masks wrong type.
1609 {
1610 json configFile = i2cCompareBytesFile;
1611 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = 1;
1612 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001613 "1 is not of type 'array'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001614 }
1615 // Invalid: test i2c_compare_bytes with property register more than 2 hex
1616 // digits.
1617 {
1618 json configFile = i2cCompareBytesFile;
1619 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1620 "0x820";
1621 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001622 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001623 }
1624 // Invalid: test i2c_compare_bytes with property values more than 2 hex
1625 // digits.
1626 {
1627 json configFile = i2cCompareBytesFile;
1628 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1629 "0x820";
1630 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001631 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001632 }
1633 // Invalid: test i2c_compare_bytes with property masks more than 2 hex
1634 // digits.
1635 {
1636 json configFile = i2cCompareBytesFile;
1637 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1638 "0x820";
1639 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001640 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001641 }
1642 // Invalid: test i2c_compare_bytes with property register less than 2 hex
1643 // digits.
1644 {
1645 json configFile = i2cCompareBytesFile;
1646 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1647 "0x8";
1648 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001649 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001650 }
1651 // Invalid: test i2c_compare_bytes with property values less than 2 hex
1652 // digits.
1653 {
1654 json configFile = i2cCompareBytesFile;
1655 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1656 "0x8";
1657 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001658 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001659 }
1660 // Invalid: test i2c_compare_bytes with property masks less than 2 hex
1661 // digits.
1662 {
1663 json configFile = i2cCompareBytesFile;
1664 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1665 "0x8";
1666 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001667 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001668 }
1669 // Invalid: test i2c_compare_bytes with property register no leading prefix.
1670 {
1671 json configFile = i2cCompareBytesFile;
1672 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1673 "82";
1674 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001675 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001676 }
1677 // Invalid: test i2c_compare_bytes with property values no leading prefix.
1678 {
1679 json configFile = i2cCompareBytesFile;
1680 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1681 "82";
1682 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001683 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001684 }
1685 // Invalid: test i2c_compare_bytes with property masks no leading prefix.
1686 {
1687 json configFile = i2cCompareBytesFile;
1688 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1689 "82";
1690 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001691 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001692 }
1693 // Invalid: test i2c_compare_bytes with property register invalid hex digit.
1694 {
1695 json configFile = i2cCompareBytesFile;
1696 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
1697 "0xG1";
1698 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001699 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001700 }
1701 // Invalid: test i2c_compare_bytes with property values invalid hex digit.
1702 {
1703 json configFile = i2cCompareBytesFile;
1704 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"][0] =
1705 "0xG1";
1706 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001707 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001708 }
1709 // Invalid: test i2c_compare_bytes with property masks invalid hex digit.
1710 {
1711 json configFile = i2cCompareBytesFile;
1712 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"][0] =
1713 "0xG1";
1714 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001715 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingfb162bb2020-01-21 11:28:07 +08001716 }
1717}
Shawn McCarney846dde52021-08-14 12:47:44 -05001718
Bob Kingca93f1f2020-01-31 11:21:16 +08001719TEST(ValidateRegulatorsConfigTest, I2CInterface)
1720{
1721 // Valid: test i2c_interface.
1722 {
1723 json configFile = validConfigFile;
1724 EXPECT_JSON_VALID(configFile);
1725 }
1726 // Invalid: testi2c_interface with no bus.
1727 {
1728 json configFile = validConfigFile;
1729 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase("bus");
1730 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001731 "'bus' is a required property");
Bob Kingca93f1f2020-01-31 11:21:16 +08001732 }
1733 // Invalid: test i2c_interface with no address.
1734 {
1735 json configFile = validConfigFile;
1736 configFile["chassis"][0]["devices"][0]["i2c_interface"].erase(
1737 "address");
1738 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001739 "'address' is a required property");
Bob Kingca93f1f2020-01-31 11:21:16 +08001740 }
1741 // Invalid: test i2c_interface with property bus wrong type.
1742 {
1743 json configFile = validConfigFile;
1744 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = true;
1745 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001746 "True is not of type 'integer'");
Bob Kingca93f1f2020-01-31 11:21:16 +08001747 }
1748 // Invalid: test i2c_interface with property address wrong
1749 // type.
1750 {
1751 json configFile = validConfigFile;
1752 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1753 true;
1754 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001755 "True is not of type 'string'");
Bob Kingca93f1f2020-01-31 11:21:16 +08001756 }
1757 // Invalid: test i2c_interface with property bus less than
1758 // 0.
1759 {
1760 json configFile = validConfigFile;
1761 configFile["chassis"][0]["devices"][0]["i2c_interface"]["bus"] = -1;
1762 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1763 "-1 is less than the minimum of 0");
1764 }
1765 // Invalid: test i2c_interface with property address wrong
1766 // format.
1767 {
1768 json configFile = validConfigFile;
1769 configFile["chassis"][0]["devices"][0]["i2c_interface"]["address"] =
1770 "0x700";
1771 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001772 "'0x700' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob Kingca93f1f2020-01-31 11:21:16 +08001773 }
1774}
Shawn McCarney846dde52021-08-14 12:47:44 -05001775
Bob King188db7d2020-01-31 13:01:01 +08001776TEST(ValidateRegulatorsConfigTest, I2CWriteBit)
1777{
1778 json i2cWriteBitFile = validConfigFile;
1779 i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
1780 "0xA0";
1781 i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3;
1782 i2cWriteBitFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 1;
1783 // Valid: test rule actions i2c_write_bit.
1784 {
1785 json configFile = i2cWriteBitFile;
1786 EXPECT_JSON_VALID(configFile);
1787 }
1788 // Invalid: test i2c_write_bit with no register.
1789 {
1790 json configFile = i2cWriteBitFile;
1791 configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("register");
1792 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001793 "'register' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001794 }
1795 // Invalid: test i2c_write_bit with no position.
1796 {
1797 json configFile = i2cWriteBitFile;
1798 configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("position");
1799 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001800 "'position' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001801 }
1802 // Invalid: test i2c_write_bit with no value.
1803 {
1804 json configFile = i2cWriteBitFile;
1805 configFile["rules"][0]["actions"][1]["i2c_write_bit"].erase("value");
1806 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001807 "'value' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001808 }
1809 // Invalid: test i2c_write_bit with register wrong type.
1810 {
1811 json configFile = i2cWriteBitFile;
1812 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] = 1;
1813 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001814 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08001815 }
1816 // Invalid: test i2c_write_bit with register wrong format.
1817 {
1818 json configFile = i2cWriteBitFile;
1819 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["register"] =
1820 "0xA00";
1821 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001822 "'0xA00' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001823 }
1824 // Invalid: test i2c_write_bit with position wrong type.
1825 {
1826 json configFile = i2cWriteBitFile;
1827 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 3.1;
1828 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001829 "3.1 is not of type 'integer'");
Bob King188db7d2020-01-31 13:01:01 +08001830 }
1831 // Invalid: test i2c_write_bit with position greater than 7.
1832 {
1833 json configFile = i2cWriteBitFile;
1834 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = 8;
1835 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1836 "8 is greater than the maximum of 7");
1837 }
1838 // Invalid: test i2c_write_bit with position less than 0.
1839 {
1840 json configFile = i2cWriteBitFile;
1841 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["position"] = -1;
1842 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1843 "-1 is less than the minimum of 0");
1844 }
1845 // Invalid: test i2c_write_bit with value wrong type.
1846 {
1847 json configFile = i2cWriteBitFile;
1848 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = "1";
1849 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001850 "'1' is not of type 'integer'");
Bob King188db7d2020-01-31 13:01:01 +08001851 }
1852 // Invalid: test i2c_write_bit with value greater than 1.
1853 {
1854 json configFile = i2cWriteBitFile;
1855 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = 2;
1856 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1857 "2 is greater than the maximum of 1");
1858 }
1859 // Invalid: test i2c_write_bit with value less than 0.
1860 {
1861 json configFile = i2cWriteBitFile;
1862 configFile["rules"][0]["actions"][1]["i2c_write_bit"]["value"] = -1;
1863 EXPECT_JSON_INVALID(configFile, "Validation failed.",
1864 "-1 is less than the minimum of 0");
1865 }
1866}
Shawn McCarney846dde52021-08-14 12:47:44 -05001867
Bob King188db7d2020-01-31 13:01:01 +08001868TEST(ValidateRegulatorsConfigTest, I2CWriteByte)
1869{
1870 json i2cWriteByteFile = validConfigFile;
1871 i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1872 "0x82";
1873 i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1874 "0x40";
1875 i2cWriteByteFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
1876 "0x7F";
1877 // Valid: test i2c_write_byte with all properties.
1878 {
1879 json configFile = i2cWriteByteFile;
1880 EXPECT_JSON_VALID(configFile);
1881 }
1882 // Valid: test i2c_write_byte with all required properties.
1883 {
1884 json configFile = i2cWriteByteFile;
1885 configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("mask");
1886 EXPECT_JSON_VALID(configFile);
1887 }
1888 // Invalid: test i2c_write_byte with no register.
1889 {
1890 json configFile = i2cWriteByteFile;
1891 configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase(
1892 "register");
1893 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001894 "'register' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001895 }
1896 // Invalid: test i2c_write_byte with no value.
1897 {
1898 json configFile = i2cWriteByteFile;
1899 configFile["rules"][0]["actions"][1]["i2c_write_byte"].erase("value");
1900 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001901 "'value' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08001902 }
1903 // Invalid: test i2c_write_byte with property register wrong type.
1904 {
1905 json configFile = i2cWriteByteFile;
1906 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] = 1;
1907 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001908 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08001909 }
1910 // Invalid: test i2c_write_byte with property value wrong type.
1911 {
1912 json configFile = i2cWriteByteFile;
1913 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = 1;
1914 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001915 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08001916 }
1917 // Invalid: test i2c_write_byte with property mask wrong type.
1918 {
1919 json configFile = i2cWriteByteFile;
1920 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = 1;
1921 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001922 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08001923 }
1924 // Invalid: test i2c_write_byte with property register more than 2 hex
1925 // digits.
1926 {
1927 json configFile = i2cWriteByteFile;
1928 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1929 "0x820";
1930 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001931 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001932 }
1933 // Invalid: test i2c_write_byte with property value more than 2 hex
1934 // digits.
1935 {
1936 json configFile = i2cWriteByteFile;
1937 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
1938 "0x820";
1939 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001940 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001941 }
1942 // Invalid: test i2c_write_byte with property mask more than 2 hex digits.
1943 {
1944 json configFile = i2cWriteByteFile;
1945 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] =
1946 "0x820";
1947 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001948 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001949 }
1950 // Invalid: test i2c_write_byte with property register less than 2 hex
1951 // digits.
1952 {
1953 json configFile = i2cWriteByteFile;
1954 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1955 "0x8";
1956 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001957 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001958 }
1959 // Invalid: test i2c_write_byte with property value less than 2 hex
1960 // digits.
1961 {
1962 json configFile = i2cWriteByteFile;
1963 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "0x8";
1964 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001965 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001966 }
1967 // Invalid: test i2c_write_byte with property mask less than 2 hex digits.
1968 {
1969 json configFile = i2cWriteByteFile;
1970 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0x8";
1971 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001972 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001973 }
1974 // Invalid: test i2c_write_byte with property register no leading prefix.
1975 {
1976 json configFile = i2cWriteByteFile;
1977 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
1978 "82";
1979 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001980 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001981 }
1982 // Invalid: test i2c_write_byte with property value no leading prefix.
1983 {
1984 json configFile = i2cWriteByteFile;
1985 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] = "82";
1986 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001987 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001988 }
1989 // Invalid: test i2c_write_byte with property mask no leading prefix.
1990 {
1991 json configFile = i2cWriteByteFile;
1992 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "82";
1993 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08001994 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08001995 }
1996 // Invalid: test i2c_write_byte with property register invalid hex digit.
1997 {
1998 json configFile = i2cWriteByteFile;
1999 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["register"] =
2000 "0xG1";
2001 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002002 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002003 }
2004 // Invalid: test i2c_write_byte with property value invalid hex digit.
2005 {
2006 json configFile = i2cWriteByteFile;
2007 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["value"] =
2008 "0xG1";
2009 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002010 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002011 }
2012 // Invalid: test i2c_write_byte with property mask invalid hex digit.
2013 {
2014 json configFile = i2cWriteByteFile;
2015 configFile["rules"][0]["actions"][1]["i2c_write_byte"]["mask"] = "0xG1";
2016 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002017 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002018 }
2019}
Shawn McCarney846dde52021-08-14 12:47:44 -05002020
Bob King188db7d2020-01-31 13:01:01 +08002021TEST(ValidateRegulatorsConfigTest, I2CWriteBytes)
2022{
2023 json i2cWriteBytesFile = validConfigFile;
2024 i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2025 "0x82";
2026 i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
2027 "0x02", "0x73"};
2028 i2cWriteBytesFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
2029 "0x7F", "0x7F"};
2030 // Valid: test i2c_write_bytes.
2031 {
2032 json configFile = i2cWriteBytesFile;
2033 EXPECT_JSON_VALID(configFile);
2034 }
2035 // Valid: test i2c_write_bytes with all required properties.
2036 {
2037 json configFile = i2cWriteBytesFile;
2038 configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("masks");
2039 EXPECT_JSON_VALID(configFile);
2040 }
2041 // Invalid: test i2c_write_bytes with no register.
2042 {
2043 json configFile = i2cWriteBytesFile;
2044 configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase(
2045 "register");
2046 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002047 "'register' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08002048 }
2049 // Invalid: test i2c_write_bytes with no values.
2050 {
2051 json configFile = i2cWriteBytesFile;
2052 configFile["rules"][0]["actions"][1]["i2c_write_bytes"].erase("values");
2053 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002054 "'values' is a required property");
Bob King188db7d2020-01-31 13:01:01 +08002055 }
2056 // Invalid: test i2c_write_bytes with property values as empty array.
2057 {
2058 json configFile = i2cWriteBytesFile;
2059 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] =
2060 json::array();
2061 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2062 "[] is too short");
2063 }
2064 // Invalid: test i2c_write_bytes with property masks as empty array.
2065 {
2066 json configFile = i2cWriteBytesFile;
2067 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] =
2068 json::array();
2069 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2070 "[] is too short");
2071 }
2072 // Invalid: test i2c_write_bytes with property register wrong type.
2073 {
2074 json configFile = i2cWriteBytesFile;
2075 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] = 1;
2076 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002077 "1 is not of type 'string'");
Bob King188db7d2020-01-31 13:01:01 +08002078 }
2079 // Invalid: test i2c_write_bytes with property values wrong type.
2080 {
2081 json configFile = i2cWriteBytesFile;
2082 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = 1;
2083 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002084 "1 is not of type 'array'");
Bob King188db7d2020-01-31 13:01:01 +08002085 }
2086 // Invalid: test i2c_write_bytes with property masks wrong type.
2087 {
2088 json configFile = i2cWriteBytesFile;
2089 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = 1;
2090 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002091 "1 is not of type 'array'");
Bob King188db7d2020-01-31 13:01:01 +08002092 }
2093 // Invalid: test i2c_write_bytes with property register more than 2 hex
2094 // digits.
2095 {
2096 json configFile = i2cWriteBytesFile;
2097 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2098 "0x820";
2099 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002100 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002101 }
2102 // Invalid: test i2c_write_bytes with property values more than 2 hex
2103 // digits.
2104 {
2105 json configFile = i2cWriteBytesFile;
2106 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
2107 "0x820";
2108 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002109 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002110 }
2111 // Invalid: test i2c_write_bytes with property masks more than 2 hex
2112 // digits.
2113 {
2114 json configFile = i2cWriteBytesFile;
2115 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
2116 "0x820";
2117 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002118 "'0x820' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002119 }
2120 // Invalid: test i2c_write_bytes with property register less than 2 hex
2121 // digits.
2122 {
2123 json configFile = i2cWriteBytesFile;
2124 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2125 "0x8";
2126 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002127 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002128 }
2129 // Invalid: test i2c_write_bytes with property values less than 2 hex
2130 // digits.
2131 {
2132 json configFile = i2cWriteBytesFile;
2133 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
2134 "0x8";
2135 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002136 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002137 }
2138 // Invalid: test i2c_write_bytes with property masks less than 2 hex
2139 // digits.
2140 {
2141 json configFile = i2cWriteBytesFile;
2142 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
2143 "0x8";
2144 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002145 "'0x8' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002146 }
2147 // Invalid: test i2c_write_bytes with property register no leading prefix.
2148 {
2149 json configFile = i2cWriteBytesFile;
2150 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2151 "82";
2152 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002153 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002154 }
2155 // Invalid: test i2c_write_bytes with property values no leading prefix.
2156 {
2157 json configFile = i2cWriteBytesFile;
2158 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
2159 "82";
2160 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002161 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002162 }
2163 // Invalid: test i2c_write_bytes with property masks no leading prefix.
2164 {
2165 json configFile = i2cWriteBytesFile;
2166 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
2167 "82";
2168 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002169 "'82' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002170 }
2171 // Invalid: test i2c_write_bytes with property register invalid hex digit.
2172 {
2173 json configFile = i2cWriteBytesFile;
2174 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
2175 "0xG1";
2176 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002177 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002178 }
2179 // Invalid: test i2c_write_bytes with property values invalid hex digit.
2180 {
2181 json configFile = i2cWriteBytesFile;
2182 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"][0] =
2183 "0xG1";
2184 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002185 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002186 }
2187 // Invalid: test i2c_write_bytes with property masks invalid hex digit.
2188 {
2189 json configFile = i2cWriteBytesFile;
2190 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"][0] =
2191 "0xG1";
2192 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002193 "'0xG1' does not match '^0x[0-9A-Fa-f]{2}$'");
Bob King188db7d2020-01-31 13:01:01 +08002194 }
2195}
Shawn McCarney846dde52021-08-14 12:47:44 -05002196
Bob Kingead0b052020-01-21 11:29:03 +08002197TEST(ValidateRegulatorsConfigTest, If)
2198{
2199 json ifFile = validConfigFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05002200 ifFile["rules"][4]["actions"][0]["if"]["condition"]["run_rule"] =
Bob King2d27dcf2020-02-11 15:00:50 +08002201 "set_voltage_rule";
Shawn McCarney846dde52021-08-14 12:47:44 -05002202 ifFile["rules"][4]["actions"][0]["if"]["then"][0]["run_rule"] =
Bob King2d27dcf2020-02-11 15:00:50 +08002203 "read_sensors_rule";
Shawn McCarney846dde52021-08-14 12:47:44 -05002204 ifFile["rules"][4]["actions"][0]["if"]["else"][0]["run_rule"] =
Bob King2d27dcf2020-02-11 15:00:50 +08002205 "read_sensors_rule";
Shawn McCarney846dde52021-08-14 12:47:44 -05002206 ifFile["rules"][4]["id"] = "rule_if";
Bob Kingead0b052020-01-21 11:29:03 +08002207 // Valid: test if.
2208 {
2209 json configFile = ifFile;
2210 EXPECT_JSON_VALID(configFile);
2211 }
2212 // Valid: test if with required properties.
2213 {
2214 json configFile = ifFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05002215 configFile["rules"][4]["actions"][0]["if"].erase("else");
Bob Kingead0b052020-01-21 11:29:03 +08002216 EXPECT_JSON_VALID(configFile);
2217 }
2218 // Invalid: test if with no property condition.
2219 {
2220 json configFile = ifFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05002221 configFile["rules"][4]["actions"][0]["if"].erase("condition");
Bob Kingead0b052020-01-21 11:29:03 +08002222 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002223 "'condition' is a required property");
Bob Kingead0b052020-01-21 11:29:03 +08002224 }
2225 // Invalid: test if with no property then.
2226 {
2227 json configFile = ifFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05002228 configFile["rules"][4]["actions"][0]["if"].erase("then");
Bob Kingead0b052020-01-21 11:29:03 +08002229 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002230 "'then' is a required property");
Bob Kingead0b052020-01-21 11:29:03 +08002231 }
2232 // Invalid: test if with property then empty array.
2233 {
2234 json configFile = ifFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05002235 configFile["rules"][4]["actions"][0]["if"]["then"] = json::array();
Bob Kingead0b052020-01-21 11:29:03 +08002236 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2237 "[] is too short");
2238 }
2239 // Invalid: test if with property else empty array.
2240 {
2241 json configFile = ifFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05002242 configFile["rules"][4]["actions"][0]["if"]["else"] = json::array();
Bob Kingead0b052020-01-21 11:29:03 +08002243 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2244 "[] is too short");
2245 }
2246 // Invalid: test if with property condition wrong type.
2247 {
2248 json configFile = ifFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05002249 configFile["rules"][4]["actions"][0]["if"]["condition"] = 1;
Bob Kingead0b052020-01-21 11:29:03 +08002250 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002251 "1 is not of type 'object'");
Bob Kingead0b052020-01-21 11:29:03 +08002252 }
2253 // Invalid: test if with property then wrong type.
2254 {
2255 json configFile = ifFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05002256 configFile["rules"][4]["actions"][0]["if"]["then"] = 1;
Bob Kingead0b052020-01-21 11:29:03 +08002257 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002258 "1 is not of type 'array'");
Bob Kingead0b052020-01-21 11:29:03 +08002259 }
2260 // Invalid: test if with property else wrong type.
2261 {
2262 json configFile = ifFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05002263 configFile["rules"][4]["actions"][0]["if"]["else"] = 1;
Bob Kingead0b052020-01-21 11:29:03 +08002264 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002265 "1 is not of type 'array'");
Bob Kingead0b052020-01-21 11:29:03 +08002266 }
2267}
Shawn McCarney846dde52021-08-14 12:47:44 -05002268
2269TEST(ValidateRegulatorsConfigTest, LogPhaseFault)
2270{
2271 json initialFile = validConfigFile;
2272 initialFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = "n";
2273
2274 // Valid: All required properties
2275 {
2276 json configFile = initialFile;
2277 EXPECT_JSON_VALID(configFile);
2278 }
2279
2280 // Invalid: type not specified
2281 {
2282 json configFile = initialFile;
2283 configFile["rules"][0]["actions"][1]["log_phase_fault"].erase("type");
2284 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2285 "'type' is a required property");
2286 }
2287
2288 // Invalid: invalid property specified
2289 {
2290 json configFile = initialFile;
2291 configFile["rules"][0]["actions"][1]["log_phase_fault"]["foo"] = true;
2292 EXPECT_JSON_INVALID(
2293 configFile, "Validation failed.",
2294 "Additional properties are not allowed ('foo' was unexpected)");
2295 }
2296
2297 // Invalid: type has wrong data type
2298 {
2299 json configFile = initialFile;
2300 configFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = true;
2301 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2302 "True is not of type 'string'");
2303 }
2304
2305 // Invalid: type has invalid value
2306 {
2307 json configFile = initialFile;
2308 configFile["rules"][0]["actions"][1]["log_phase_fault"]["type"] = "n+2";
2309 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2310 "'n+2' is not one of ['n+1', 'n']");
2311 }
2312}
2313
Bob Kingbfe9fe72020-01-21 11:29:57 +08002314TEST(ValidateRegulatorsConfigTest, Not)
2315{
2316 json notFile = validConfigFile;
2317 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["register"] =
2318 "0xA0";
2319 notFile["rules"][0]["actions"][1]["not"]["i2c_compare_byte"]["value"] =
2320 "0xFF";
2321 // Valid: test not.
2322 {
2323 json configFile = notFile;
2324 EXPECT_JSON_VALID(configFile);
2325 }
2326 // Invalid: test not with wrong type.
2327 {
2328 json configFile = notFile;
2329 configFile["rules"][0]["actions"][1]["not"] = 1;
2330 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002331 "1 is not of type 'object'");
Bob Kingbfe9fe72020-01-21 11:29:57 +08002332 }
2333}
Shawn McCarney846dde52021-08-14 12:47:44 -05002334
Bob Kingcfc29d02020-01-21 11:30:50 +08002335TEST(ValidateRegulatorsConfigTest, Or)
2336{
2337 json orFile = validConfigFile;
2338 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["register"] =
2339 "0xA0";
2340 orFile["rules"][0]["actions"][1]["or"][0]["i2c_compare_byte"]["value"] =
2341 "0x00";
2342 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["register"] =
2343 "0xA1";
2344 orFile["rules"][0]["actions"][1]["or"][1]["i2c_compare_byte"]["value"] =
2345 "0x00";
2346 // Valid: test or.
2347 {
2348 json configFile = orFile;
2349 EXPECT_JSON_VALID(configFile);
2350 }
2351 // Invalid: test or with empty array.
2352 {
2353 json configFile = orFile;
2354 configFile["rules"][0]["actions"][1]["or"] = json::array();
2355 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2356 "[] is too short");
2357 }
2358 // Invalid: test or with wrong type.
2359 {
2360 json configFile = orFile;
2361 configFile["rules"][0]["actions"][1]["or"] = 1;
2362 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002363 "1 is not of type 'array'");
Bob Kingcfc29d02020-01-21 11:30:50 +08002364 }
2365}
Shawn McCarney846dde52021-08-14 12:47:44 -05002366
2367TEST(ValidateRegulatorsConfigTest, PhaseFaultDetection)
2368{
2369 json initialFile = validConfigFile;
2370 initialFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2371 ["rule_id"] = "detect_phase_faults_rule";
2372
2373 // Valid: comments specified
2374 {
2375 json configFile = initialFile;
2376 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2377 ["comments"][0] = "Detect phase faults";
2378 EXPECT_JSON_VALID(configFile);
2379 }
2380
2381 // Valid: device_id specified
2382 {
2383 json configFile = initialFile;
2384 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2385 ["device_id"] = "vdd_regulator";
2386 EXPECT_JSON_VALID(configFile);
2387 }
2388
2389 // Valid: rule_id specified
2390 {
2391 json configFile = initialFile;
2392 EXPECT_JSON_VALID(configFile);
2393 }
2394
2395 // Valid: actions specified
2396 {
2397 json configFile = initialFile;
2398 configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
2399 "rule_id");
2400 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2401 ["actions"][0]["run_rule"] = "detect_phase_faults_rule";
2402 EXPECT_JSON_VALID(configFile);
2403 }
2404
2405 // Invalid: rule_id and actions specified
2406 {
2407 json configFile = initialFile;
2408 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2409 ["actions"][0]["run_rule"] = "detect_phase_faults_rule";
2410 EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
2411 }
2412
2413 // Invalid: neither rule_id nor actions specified
2414 {
2415 json configFile = initialFile;
2416 configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
2417 "rule_id");
2418 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Shawn McCarney0a2b76b2022-12-06 12:52:31 -06002419 "{} is not valid under any of the given schemas");
Shawn McCarney846dde52021-08-14 12:47:44 -05002420 }
2421
2422 // Invalid: comments has wrong data type
2423 {
2424 json configFile = initialFile;
2425 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2426 ["comments"] = true;
2427 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2428 "True is not of type 'array'");
2429 }
2430
2431 // Invalid: device_id has wrong data type
2432 {
2433 json configFile = initialFile;
2434 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2435 ["device_id"] = true;
2436 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2437 "True is not of type 'string'");
2438 }
2439
2440 // Invalid: rule_id has wrong data type
2441 {
2442 json configFile = initialFile;
2443 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2444 ["rule_id"] = true;
2445 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2446 "True is not of type 'string'");
2447 }
2448
2449 // Invalid: actions has wrong data type
2450 {
2451 json configFile = initialFile;
2452 configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
2453 "rule_id");
2454 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2455 ["actions"] = true;
2456 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2457 "True is not of type 'array'");
2458 }
2459
2460 // Invalid: device_id has invalid format
2461 {
2462 json configFile = initialFile;
2463 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2464 ["device_id"] = "id@";
2465 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2466 "'id@' does not match '^[A-Za-z0-9_]+$'");
2467 }
2468
2469 // Invalid: rule_id has invalid format
2470 {
2471 json configFile = initialFile;
2472 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2473 ["rule_id"] = "id@";
2474 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2475 "'id@' does not match '^[A-Za-z0-9_]+$'");
2476 }
2477
2478 // Invalid: comments array is empty
2479 {
2480 json configFile = initialFile;
2481 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2482 ["comments"] = json::array();
2483 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2484 "[] is too short");
2485 }
2486
2487 // Invalid: actions array is empty
2488 {
2489 json configFile = initialFile;
2490 configFile["chassis"][0]["devices"][0]["phase_fault_detection"].erase(
2491 "rule_id");
2492 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
2493 ["actions"] = json::array();
2494 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2495 "[] is too short");
2496 }
2497}
2498
Bob Kingd6618092020-01-21 11:31:46 +08002499TEST(ValidateRegulatorsConfigTest, PmbusReadSensor)
2500{
2501 json pmbusReadSensorFile = validConfigFile;
2502 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
2503 "vout";
2504 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
2505 ["command"] = "0x8B";
2506 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
2507 ["format"] = "linear_16";
2508 pmbusReadSensorFile["rules"][0]["actions"][1]["pmbus_read_sensor"]
2509 ["exponent"] = -8;
2510 // Valid: test pmbus_read_sensor.
2511 {
2512 json configFile = pmbusReadSensorFile;
2513 EXPECT_JSON_VALID(configFile);
2514 }
2515 // Valid: test pmbus_read_sensor with required properties.
2516 {
2517 json configFile = pmbusReadSensorFile;
2518 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
2519 "exponent");
2520 EXPECT_JSON_VALID(configFile);
2521 }
2522 // Invalid: test pmbus_read_sensor with no type.
2523 {
2524 json configFile = pmbusReadSensorFile;
2525 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase("type");
2526 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002527 "'type' is a required property");
Bob Kingd6618092020-01-21 11:31:46 +08002528 }
2529 // Invalid: test pmbus_read_sensor with no command.
2530 {
2531 json configFile = pmbusReadSensorFile;
2532 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
2533 "command");
2534 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002535 "'command' is a required property");
Bob Kingd6618092020-01-21 11:31:46 +08002536 }
2537 // Invalid: test pmbus_read_sensor with no format.
2538 {
2539 json configFile = pmbusReadSensorFile;
2540 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"].erase(
2541 "format");
2542 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002543 "'format' is a required property");
Bob Kingd6618092020-01-21 11:31:46 +08002544 }
2545 // Invalid: test pmbus_read_sensor with property type wrong type.
2546 {
2547 json configFile = pmbusReadSensorFile;
2548 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
2549 true;
Bob King358c4172020-03-16 13:57:08 +08002550 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2551 "True is not of type 'string'");
Bob Kingd6618092020-01-21 11:31:46 +08002552 }
2553 // Invalid: test pmbus_read_sensor with property command wrong type.
2554 {
2555 json configFile = pmbusReadSensorFile;
2556 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
2557 true;
2558 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002559 "True is not of type 'string'");
Bob Kingd6618092020-01-21 11:31:46 +08002560 }
2561 // Invalid: test pmbus_read_sensor with property format wrong type.
2562 {
2563 json configFile = pmbusReadSensorFile;
2564 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
2565 true;
2566 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002567 "True is not of type 'string'");
Bob Kingd6618092020-01-21 11:31:46 +08002568 }
2569 // Invalid: test pmbus_read_sensor with property exponent wrong type.
2570 {
2571 json configFile = pmbusReadSensorFile;
2572 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["exponent"] =
2573 true;
2574 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002575 "True is not of type 'integer'");
Bob Kingd6618092020-01-21 11:31:46 +08002576 }
2577 // Invalid: test pmbus_read_sensor with property type wrong format.
2578 {
2579 json configFile = pmbusReadSensorFile;
2580 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["type"] =
2581 "foo";
2582 EXPECT_JSON_INVALID(
2583 configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002584 "'foo' is not one of ['iout', 'iout_peak', 'iout_valley', "
2585 "'pout', 'temperature', 'temperature_peak', 'vout', "
2586 "'vout_peak', 'vout_valley']");
Bob Kingd6618092020-01-21 11:31:46 +08002587 }
2588 // Invalid: test pmbus_read_sensor with property command wrong format.
2589 {
2590 json configFile = pmbusReadSensorFile;
2591 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["command"] =
2592 "0x8B0";
2593 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002594 "'0x8B0' does not match '^0x[0-9a-fA-F]{2}$'");
Bob Kingd6618092020-01-21 11:31:46 +08002595 }
2596 // Invalid: test pmbus_read_sensor with property format wrong format.
2597 {
2598 json configFile = pmbusReadSensorFile;
2599 configFile["rules"][0]["actions"][1]["pmbus_read_sensor"]["format"] =
2600 "foo";
Bob King358c4172020-03-16 13:57:08 +08002601 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2602 "'foo' is not one of ['linear_11', 'linear_16']");
Bob Kingd6618092020-01-21 11:31:46 +08002603 }
2604}
Shawn McCarney846dde52021-08-14 12:47:44 -05002605
Bob King02179c62020-01-21 11:32:36 +08002606TEST(ValidateRegulatorsConfigTest, PmbusWriteVoutCommand)
2607{
2608 json pmbusWriteVoutCommandFile = validConfigFile;
2609 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
2610 ["pmbus_write_vout_command"]["volts"] = 1.03;
2611 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
2612 ["pmbus_write_vout_command"]["format"] = "linear";
2613 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
2614 ["pmbus_write_vout_command"]["exponent"] = -8;
2615 pmbusWriteVoutCommandFile["rules"][0]["actions"][1]
2616 ["pmbus_write_vout_command"]["is_verified"] = true;
2617 // Valid: test pmbus_write_vout_command.
2618 {
2619 json configFile = pmbusWriteVoutCommandFile;
2620 EXPECT_JSON_VALID(configFile);
2621 }
2622 // Valid: test pmbus_write_vout_command with required properties.
2623 {
2624 json configFile = pmbusWriteVoutCommandFile;
2625 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
2626 "volts");
2627 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
2628 "exponent");
2629 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
2630 "is_verified");
2631 EXPECT_JSON_VALID(configFile);
2632 }
2633 // Invalid: test pmbus_write_vout_command with no format.
2634 {
2635 json configFile = pmbusWriteVoutCommandFile;
2636 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"].erase(
2637 "format");
2638 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002639 "'format' is a required property");
Bob King02179c62020-01-21 11:32:36 +08002640 }
2641 // Invalid: test pmbus_write_vout_command with property volts wrong type.
2642 {
2643 json configFile = pmbusWriteVoutCommandFile;
2644 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
2645 ["volts"] = true;
2646 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002647 "True is not of type 'number'");
Bob King02179c62020-01-21 11:32:36 +08002648 }
2649 // Invalid: test pmbus_write_vout_command with property format wrong type.
2650 {
2651 json configFile = pmbusWriteVoutCommandFile;
2652 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
2653 ["format"] = true;
2654 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002655 "True is not of type 'string'");
Bob King02179c62020-01-21 11:32:36 +08002656 }
2657 // Invalid: test pmbus_write_vout_command with property exponent wrong type.
2658 {
2659 json configFile = pmbusWriteVoutCommandFile;
2660 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
2661 ["exponent"] = 1.3;
2662 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002663 "1.3 is not of type 'integer'");
Bob King02179c62020-01-21 11:32:36 +08002664 }
2665 // Invalid: test pmbus_write_vout_command with property is_verified wrong
2666 // type.
2667 {
2668 json configFile = pmbusWriteVoutCommandFile;
2669 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
2670 ["is_verified"] = 1;
2671 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002672 "1 is not of type 'boolean'");
Bob King02179c62020-01-21 11:32:36 +08002673 }
2674 // Invalid: test pmbus_write_vout_command with property format wrong format.
2675 {
2676 json configFile = pmbusWriteVoutCommandFile;
2677 configFile["rules"][0]["actions"][1]["pmbus_write_vout_command"]
2678 ["format"] = "foo";
2679 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002680 "'foo' is not one of ['linear']");
Bob King02179c62020-01-21 11:32:36 +08002681 }
2682}
Shawn McCarney846dde52021-08-14 12:47:44 -05002683
Bob King99d8fa12020-01-31 11:23:40 +08002684TEST(ValidateRegulatorsConfigTest, PresenceDetection)
2685{
2686 json presenceDetectionFile = validConfigFile;
Bob King99d8fa12020-01-31 11:23:40 +08002687 presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
Shawn McCarney846dde52021-08-14 12:47:44 -05002688 ["comments"][0] =
2689 "Regulator is only present if CPU3 is present";
2690 presenceDetectionFile["chassis"][0]["devices"][0]["presence_detection"]
2691 ["rule_id"] = "detect_presence_rule";
Bob King99d8fa12020-01-31 11:23:40 +08002692 // Valid: test presence_detection with only property rule_id.
2693 {
2694 json configFile = presenceDetectionFile;
2695 EXPECT_JSON_VALID(configFile);
2696 }
2697 // Valid: test presence_detection with only property actions.
2698 {
2699 json configFile = presenceDetectionFile;
2700 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2701 "rule_id");
2702 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
2703 [0]["compare_presence"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +08002704 "system/chassis/motherboard/cpu3";
Bob King99d8fa12020-01-31 11:23:40 +08002705 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
2706 [0]["compare_presence"]["value"] = true;
2707 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2708 "comments");
2709 EXPECT_JSON_VALID(configFile);
2710 }
2711 // Invalid: test presence_detection with both property rule_id and actions.
2712 {
2713 json configFile = presenceDetectionFile;
2714 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
2715 [0]["compare_presence"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +08002716 "system/chassis/motherboard/cpu3";
Bob King99d8fa12020-01-31 11:23:40 +08002717 configFile["chassis"][0]["devices"][0]["presence_detection"]["actions"]
2718 [0]["compare_presence"]["value"] = true;
Shawn McCarney846dde52021-08-14 12:47:44 -05002719 EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
Bob King99d8fa12020-01-31 11:23:40 +08002720 }
2721 // Invalid: test presence_detection with no rule_id and actions.
2722 {
2723 json configFile = presenceDetectionFile;
2724 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2725 "rule_id");
Shawn McCarney0a2b76b2022-12-06 12:52:31 -06002726 EXPECT_JSON_INVALID(
2727 configFile, "Validation failed.",
2728 "{'comments': ['Regulator is only present if CPU3 is present']} is not valid under any of the given schemas");
Bob King99d8fa12020-01-31 11:23:40 +08002729 }
2730 // Invalid: test presence_detection with property comments wrong type.
2731 {
2732 json configFile = presenceDetectionFile;
2733 configFile["chassis"][0]["devices"][0]["presence_detection"]
2734 ["comments"] = true;
2735 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002736 "True is not of type 'array'");
Bob King99d8fa12020-01-31 11:23:40 +08002737 }
2738 // Invalid: test presence_detection with property rule_id wrong type.
2739 {
2740 json configFile = presenceDetectionFile;
2741 configFile["chassis"][0]["devices"][0]["presence_detection"]
2742 ["rule_id"] = true;
2743 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002744 "True is not of type 'string'");
Bob King99d8fa12020-01-31 11:23:40 +08002745 }
2746 // Invalid: test presence_detection with property actions wrong type.
2747 {
2748 json configFile = presenceDetectionFile;
2749 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2750 "rule_id");
2751 configFile["chassis"][0]["devices"][0]["presence_detection"]
2752 ["actions"] = true;
2753 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002754 "True is not of type 'array'");
Bob King99d8fa12020-01-31 11:23:40 +08002755 }
2756 // Invalid: test presence_detection with property rule_id wrong format.
2757 {
2758 json configFile = presenceDetectionFile;
2759 configFile["chassis"][0]["devices"][0]["presence_detection"]
2760 ["rule_id"] = "id@";
2761 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002762 "'id@' does not match '^[A-Za-z0-9_]+$'");
Bob King99d8fa12020-01-31 11:23:40 +08002763 }
2764 // Invalid: test presence_detection with property comments empty array.
2765 {
2766 json configFile = presenceDetectionFile;
2767 configFile["chassis"][0]["devices"][0]["presence_detection"]
2768 ["comments"] = json::array();
2769 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2770 "[] is too short");
2771 }
2772 // Invalid: test presence_detection with property actions empty array.
2773 {
2774 json configFile = presenceDetectionFile;
2775 configFile["chassis"][0]["devices"][0]["presence_detection"].erase(
2776 "rule_id");
2777 configFile["chassis"][0]["devices"][0]["presence_detection"]
2778 ["actions"] = json::array();
2779 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2780 "[] is too short");
2781 }
2782}
Shawn McCarney846dde52021-08-14 12:47:44 -05002783
Bob Kinge9260b52020-01-21 11:46:13 +08002784TEST(ValidateRegulatorsConfigTest, Rail)
2785{
2786 // Valid: test rail.
2787 {
2788 json configFile = validConfigFile;
2789 EXPECT_JSON_VALID(configFile);
2790 }
2791 // Valid: test rail with required properties.
2792 {
2793 json configFile = validConfigFile;
2794 configFile["chassis"][0]["devices"][0]["rails"][0].erase("comments");
2795 configFile["chassis"][0]["devices"][0]["rails"][0].erase(
2796 "configuration");
2797 configFile["chassis"][0]["devices"][0]["rails"][0].erase(
2798 "sensor_monitoring");
2799 EXPECT_JSON_VALID(configFile);
2800 }
2801 // Invalid: test rail with no id.
2802 {
2803 json configFile = validConfigFile;
2804 configFile["chassis"][0]["devices"][0]["rails"][0].erase("id");
2805 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002806 "'id' is a required property");
Bob Kinge9260b52020-01-21 11:46:13 +08002807 }
2808 // Invalid: test rail with comments wrong type.
2809 {
2810 json configFile = validConfigFile;
2811 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] = true;
2812 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002813 "True is not of type 'array'");
Bob Kinge9260b52020-01-21 11:46:13 +08002814 }
2815 // Invalid: test rail with id wrong type.
2816 {
2817 json configFile = validConfigFile;
2818 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = true;
2819 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002820 "True is not of type 'string'");
Bob Kinge9260b52020-01-21 11:46:13 +08002821 }
2822 // Invalid: test rail with configuration wrong type.
2823 {
2824 json configFile = validConfigFile;
2825 configFile["chassis"][0]["devices"][0]["rails"][0]["configuration"] =
2826 true;
2827 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002828 "True is not of type 'object'");
Bob Kinge9260b52020-01-21 11:46:13 +08002829 }
2830 // Invalid: test rail with sensor_monitoring wrong type.
2831 {
2832 json configFile = validConfigFile;
2833 configFile["chassis"][0]["devices"][0]["rails"][0]
2834 ["sensor_monitoring"] = true;
2835 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002836 "True is not of type 'object'");
Bob Kinge9260b52020-01-21 11:46:13 +08002837 }
2838 // Invalid: test rail with comments empty array.
2839 {
2840 json configFile = validConfigFile;
2841 configFile["chassis"][0]["devices"][0]["rails"][0]["comments"] =
2842 json::array();
2843 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2844 "[] is too short");
2845 }
2846 // Invalid: test rail with id wrong format.
2847 {
2848 json configFile = validConfigFile;
2849 configFile["chassis"][0]["devices"][0]["rails"][0]["id"] = "id~";
2850 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002851 "'id~' does not match '^[A-Za-z0-9_]+$'");
Bob Kinge9260b52020-01-21 11:46:13 +08002852 }
2853}
Shawn McCarney846dde52021-08-14 12:47:44 -05002854
Bob King64df7da2020-01-31 12:04:12 +08002855TEST(ValidateRegulatorsConfigTest, Rule)
2856{
2857 // valid test comments property, id property,
2858 // action property specified.
2859 {
2860 json configFile = validConfigFile;
2861 EXPECT_JSON_VALID(configFile);
2862 }
2863
2864 // valid test rule with no comments
2865 {
2866 json configFile = validConfigFile;
2867 configFile["rules"][0].erase("comments");
2868 EXPECT_JSON_VALID(configFile);
2869 }
2870
2871 // invalid test comments property has invalid value type
2872 {
2873 json configFile = validConfigFile;
2874 configFile["rules"][0]["comments"] = {1};
2875 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002876 "1 is not of type 'string'");
Bob King64df7da2020-01-31 12:04:12 +08002877 }
2878
2879 // invalid test rule with no ID
2880 {
2881 json configFile = validConfigFile;
2882 configFile["rules"][0].erase("id");
2883 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002884 "'id' is a required property");
Bob King64df7da2020-01-31 12:04:12 +08002885 }
2886
2887 // invalid test id property has invalid value type (not string)
2888 {
2889 json configFile = validConfigFile;
2890 configFile["rules"][0]["id"] = true;
2891 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002892 "True is not of type 'string'");
Bob King64df7da2020-01-31 12:04:12 +08002893 }
2894
2895 // invalid test id property has invalid value
2896 {
2897 json configFile = validConfigFile;
2898 configFile["rules"][0]["id"] = "foo%";
2899 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002900 "'foo%' does not match '^[A-Za-z0-9_]+$'");
Bob King64df7da2020-01-31 12:04:12 +08002901 }
2902
2903 // invalid test rule with no actions property
2904 {
2905 json configFile = validConfigFile;
2906 configFile["rules"][0].erase("actions");
2907 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002908 "'actions' is a required property");
Bob King64df7da2020-01-31 12:04:12 +08002909 }
2910
2911 // valid test rule with multiple actions
2912 {
2913 json configFile = validConfigFile;
Bob King63d795f2020-02-11 15:22:09 +08002914 configFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
Bob King64df7da2020-01-31 12:04:12 +08002915 EXPECT_JSON_VALID(configFile);
2916 }
2917
2918 // invalid test actions property has invalid value type (not an array)
2919 {
2920 json configFile = validConfigFile;
2921 configFile["rules"][0]["actions"] = 1;
2922 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002923 "1 is not of type 'array'");
Bob King64df7da2020-01-31 12:04:12 +08002924 }
2925
2926 // invalid test actions property has invalid value of action
2927 {
2928 json configFile = validConfigFile;
2929 configFile["rules"][0]["actions"][0] = "foo";
2930 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002931 "'foo' is not of type 'object'");
Bob King64df7da2020-01-31 12:04:12 +08002932 }
2933
2934 // invalid test actions property has empty array
2935 {
2936 json configFile = validConfigFile;
2937 configFile["rules"][0]["actions"] = json::array();
2938 EXPECT_JSON_INVALID(configFile, "Validation failed.",
2939 "[] is too short");
2940 }
2941}
Shawn McCarney846dde52021-08-14 12:47:44 -05002942
Bob Kinge86c2e52020-01-21 11:33:32 +08002943TEST(ValidateRegulatorsConfigTest, RunRule)
2944{
2945 json runRuleFile = validConfigFile;
Bob King7d3a9f12020-02-11 15:34:52 +08002946 runRuleFile["rules"][0]["actions"][1]["run_rule"] = "read_sensors_rule";
Bob Kinge86c2e52020-01-21 11:33:32 +08002947 // Valid: test run_rule.
2948 {
2949 json configFile = runRuleFile;
2950 EXPECT_JSON_VALID(configFile);
2951 }
2952 // Invalid: test run_rule wrong type.
2953 {
2954 json configFile = runRuleFile;
2955 configFile["rules"][0]["actions"][1]["run_rule"] = true;
2956 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002957 "True is not of type 'string'");
Bob Kinge86c2e52020-01-21 11:33:32 +08002958 }
2959 // Invalid: test run_rule wrong format.
2960 {
2961 json configFile = runRuleFile;
2962 configFile["rules"][0]["actions"][1]["run_rule"] = "set_voltage_rule%";
2963 EXPECT_JSON_INVALID(
2964 configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08002965 "'set_voltage_rule%' does not match '^[A-Za-z0-9_]+$'");
Bob Kinge86c2e52020-01-21 11:33:32 +08002966 }
2967}
Shawn McCarney846dde52021-08-14 12:47:44 -05002968
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002969TEST(ValidateRegulatorsConfigTest, SensorMonitoring)
2970{
2971 // Valid: test rails sensor_monitoring with only property rule id.
2972 {
2973 json configFile = validConfigFile;
2974 EXPECT_JSON_VALID(configFile);
2975 }
2976 // Valid: test rails sensor_monitoring with only property actions.
2977 {
2978 json configFile = validConfigFile;
2979 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2980 .erase("rule_id");
2981 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2982 ["actions"][0]["compare_presence"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +08002983 "system/chassis/motherboard/cpu3";
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002984 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2985 ["actions"][0]["compare_presence"]["value"] = true;
2986 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2987 ["comments"][0] = "comments";
2988 EXPECT_JSON_VALID(configFile);
2989 }
2990 // Invalid: test rails sensor_monitoring with both property rule_id and
2991 // actions.
2992 {
2993 json configFile = validConfigFile;
2994 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2995 ["actions"][0]["compare_presence"]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +08002996 "system/chassis/motherboard/cpu3";
Bob Kingfcc2a2f2020-01-31 11:29:45 +08002997 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
2998 ["actions"][0]["compare_presence"]["value"] = true;
Shawn McCarney846dde52021-08-14 12:47:44 -05002999 EXPECT_JSON_INVALID(configFile, "Validation failed.", "");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08003000 }
3001 // Invalid: test rails sensor_monitoring with no rule_id and actions.
3002 {
3003 json configFile = validConfigFile;
3004 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3005 .erase("rule_id");
3006 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Shawn McCarney0a2b76b2022-12-06 12:52:31 -06003007 "{} is not valid under any of the given schemas");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08003008 }
3009 // Invalid: test rails sensor_monitoring with property comments wrong type.
3010 {
3011 json configFile = validConfigFile;
3012 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3013 ["comments"] = true;
3014 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08003015 "True is not of type 'array'");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08003016 }
3017 // Invalid: test rails sensor_monitoring with property rule_id wrong type.
3018 {
3019 json configFile = validConfigFile;
3020 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3021 ["rule_id"] = true;
3022 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08003023 "True is not of type 'string'");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08003024 }
3025 // Invalid: test rails sensor_monitoring with property actions wrong type.
3026 {
3027 json configFile = validConfigFile;
3028 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3029 .erase("rule_id");
3030 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3031 ["actions"] = true;
3032 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08003033 "True is not of type 'array'");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08003034 }
3035 // Invalid: test rails sensor_monitoring with property rule_id wrong format.
3036 {
3037 json configFile = validConfigFile;
3038 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3039 ["rule_id"] = "id@";
3040 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08003041 "'id@' does not match '^[A-Za-z0-9_]+$'");
Bob Kingfcc2a2f2020-01-31 11:29:45 +08003042 }
3043 // Invalid: test rails sensor_monitoring with property comments empty array.
3044 {
3045 json configFile = validConfigFile;
3046 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3047 ["comments"] = json::array();
3048 EXPECT_JSON_INVALID(configFile, "Validation failed.",
3049 "[] is too short");
3050 }
3051 // Invalid: test rails sensor_monitoring with property actions empty array.
3052 {
3053 json configFile = validConfigFile;
3054 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3055 .erase("rule_id");
3056 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
3057 ["actions"] = json::array();
3058 EXPECT_JSON_INVALID(configFile, "Validation failed.",
3059 "[] is too short");
3060 }
3061}
Shawn McCarney846dde52021-08-14 12:47:44 -05003062
Bob King68230aa2020-01-21 11:34:33 +08003063TEST(ValidateRegulatorsConfigTest, SetDevice)
3064{
3065 json setDeviceFile = validConfigFile;
Bob King7d3a9f12020-02-11 15:34:52 +08003066 setDeviceFile["rules"][0]["actions"][1]["set_device"] = "vdd_regulator";
Bob King68230aa2020-01-21 11:34:33 +08003067 // Valid: test set_device.
3068 {
3069 json configFile = setDeviceFile;
3070 EXPECT_JSON_VALID(configFile);
3071 }
3072 // Invalid: test set_device wrong type.
3073 {
3074 json configFile = setDeviceFile;
3075 configFile["rules"][0]["actions"][1]["set_device"] = true;
3076 EXPECT_JSON_INVALID(configFile, "Validation failed.",
Bob King358c4172020-03-16 13:57:08 +08003077 "True is not of type 'string'");
Bob King68230aa2020-01-21 11:34:33 +08003078 }
3079 // Invalid: test set_device wrong format.
3080 {
3081 json configFile = setDeviceFile;
3082 configFile["rules"][0]["actions"][1]["set_device"] = "io_expander2%";
Bob King358c4172020-03-16 13:57:08 +08003083 EXPECT_JSON_INVALID(configFile, "Validation failed.",
3084 "'io_expander2%' does not match '^[A-Za-z0-9_]+$'");
Bob King68230aa2020-01-21 11:34:33 +08003085 }
3086}
Shawn McCarney846dde52021-08-14 12:47:44 -05003087
Bob King3643cc02020-01-31 11:32:56 +08003088TEST(ValidateRegulatorsConfigTest, DuplicateRuleID)
3089{
3090 // Invalid: test duplicate ID in rule.
3091 {
3092 json configFile = validConfigFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05003093 configFile["rules"][4]["id"] = "set_voltage_rule";
3094 configFile["rules"][4]["actions"][0]["pmbus_write_vout_command"]
Bob King3643cc02020-01-31 11:32:56 +08003095 ["format"] = "linear";
3096 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rule ID.", "");
3097 }
3098}
Shawn McCarney846dde52021-08-14 12:47:44 -05003099
Bob King3643cc02020-01-31 11:32:56 +08003100TEST(ValidateRegulatorsConfigTest, DuplicateChassisNumber)
3101{
3102 // Invalid: test duplicate number in chassis.
3103 {
3104 json configFile = validConfigFile;
3105 configFile["chassis"][1]["number"] = 1;
Shawn McCarney4c88a4c2021-09-21 15:29:24 -05003106 configFile["chassis"][1]["inventory_path"] = "system/chassis2";
Bob King3643cc02020-01-31 11:32:56 +08003107 EXPECT_JSON_INVALID(configFile, "Error: Duplicate chassis number.", "");
3108 }
3109}
Shawn McCarney846dde52021-08-14 12:47:44 -05003110
Bob King3643cc02020-01-31 11:32:56 +08003111TEST(ValidateRegulatorsConfigTest, DuplicateDeviceID)
3112{
3113 // Invalid: test duplicate ID in device.
3114 {
3115 json configFile = validConfigFile;
3116 configFile["chassis"][0]["devices"][1]["id"] = "vdd_regulator";
3117 configFile["chassis"][0]["devices"][1]["is_regulator"] = true;
3118 configFile["chassis"][0]["devices"][1]["fru"] =
Bob Kinga76898f2020-10-13 15:08:33 +08003119 "system/chassis/motherboard/regulator1";
Bob King3643cc02020-01-31 11:32:56 +08003120 configFile["chassis"][0]["devices"][1]["i2c_interface"]["bus"] = 2;
3121 configFile["chassis"][0]["devices"][1]["i2c_interface"]["address"] =
3122 "0x71";
3123 EXPECT_JSON_INVALID(configFile, "Error: Duplicate device ID.", "");
3124 }
3125}
Shawn McCarney846dde52021-08-14 12:47:44 -05003126
Bob King3643cc02020-01-31 11:32:56 +08003127TEST(ValidateRegulatorsConfigTest, DuplicateRailID)
3128{
3129 // Invalid: test duplicate ID in rail.
3130 {
3131 json configFile = validConfigFile;
3132 configFile["chassis"][0]["devices"][0]["rails"][1]["id"] = "vdd";
3133 EXPECT_JSON_INVALID(configFile, "Error: Duplicate rail ID.", "");
3134 }
3135}
Shawn McCarney846dde52021-08-14 12:47:44 -05003136
Bob King78793102020-03-13 13:16:09 +08003137TEST(ValidateRegulatorsConfigTest, DuplicateObjectID)
3138{
3139 // Invalid: test duplicate object ID in device and rail.
3140 {
3141 json configFile = validConfigFile;
3142 configFile["chassis"][0]["devices"][0]["rails"][1]["id"] =
3143 "vdd_regulator";
3144 EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
3145 }
3146 // Invalid: test duplicate object ID in device and rule.
3147 {
3148 json configFile = validConfigFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05003149 configFile["rules"][4]["id"] = "vdd_regulator";
3150 configFile["rules"][4]["actions"][0]["pmbus_write_vout_command"]
Bob King78793102020-03-13 13:16:09 +08003151 ["format"] = "linear";
3152 EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
3153 }
3154 // Invalid: test duplicate object ID in rule and rail.
3155 {
3156 json configFile = validConfigFile;
3157 configFile["chassis"][0]["devices"][0]["rails"][1]["id"] =
3158 "set_voltage_rule";
3159 EXPECT_JSON_INVALID(configFile, "Error: Duplicate ID.", "");
3160 }
3161}
Shawn McCarney846dde52021-08-14 12:47:44 -05003162
Bob King3643cc02020-01-31 11:32:56 +08003163TEST(ValidateRegulatorsConfigTest, InfiniteLoops)
3164{
3165 // Invalid: test run_rule with infinite loop (rules run each other).
3166 {
3167 json configFile = validConfigFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05003168 configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule2";
3169 configFile["rules"][4]["id"] = "set_voltage_rule1";
3170 configFile["rules"][5]["actions"][0]["run_rule"] = "set_voltage_rule1";
3171 configFile["rules"][5]["id"] = "set_voltage_rule2";
Bob King3643cc02020-01-31 11:32:56 +08003172 EXPECT_JSON_INVALID(configFile,
3173 "Infinite loop caused by run_rule actions.", "");
3174 }
3175 // Invalid: test run_rule with infinite loop (rule runs itself).
3176 {
3177 json configFile = validConfigFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05003178 configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule1";
3179 configFile["rules"][4]["id"] = "set_voltage_rule1";
Bob King3643cc02020-01-31 11:32:56 +08003180 EXPECT_JSON_INVALID(configFile,
3181 "Infinite loop caused by run_rule actions.", "");
3182 }
3183 // Invalid: test run_rule with infinite loop (indirect loop).
3184 {
3185 json configFile = validConfigFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05003186 configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule2";
3187 configFile["rules"][4]["id"] = "set_voltage_rule1";
3188 configFile["rules"][5]["actions"][0]["run_rule"] = "set_voltage_rule3";
3189 configFile["rules"][5]["id"] = "set_voltage_rule2";
3190 configFile["rules"][6]["actions"][0]["run_rule"] = "set_voltage_rule1";
3191 configFile["rules"][6]["id"] = "set_voltage_rule3";
Bob King3643cc02020-01-31 11:32:56 +08003192 EXPECT_JSON_INVALID(configFile,
3193 "Infinite loop caused by run_rule actions.", "");
3194 }
3195}
Shawn McCarney846dde52021-08-14 12:47:44 -05003196
Bob Kingf88203a2020-02-18 13:26:07 +08003197TEST(ValidateRegulatorsConfigTest, RunRuleValueExists)
3198{
3199 // Invalid: test run_rule actions specify a rule ID that does not exist.
3200 {
3201 json configFile = validConfigFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05003202 configFile["rules"][4]["actions"][0]["run_rule"] = "set_voltage_rule2";
3203 configFile["rules"][4]["id"] = "set_voltage_rule1";
Bob Kingf88203a2020-02-18 13:26:07 +08003204 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
3205 }
3206}
Shawn McCarney846dde52021-08-14 12:47:44 -05003207
Bob King13b2ad92020-02-18 13:31:39 +08003208TEST(ValidateRegulatorsConfigTest, SetDeviceValueExists)
3209{
3210 // Invalid: test set_device actions specify a device ID that does not exist.
3211 {
3212 json configFile = validConfigFile;
Shawn McCarney846dde52021-08-14 12:47:44 -05003213 configFile["rules"][4]["actions"][0]["set_device"] = "vdd_regulator2";
3214 configFile["rules"][4]["id"] = "set_voltage_rule1";
Bob King13b2ad92020-02-18 13:31:39 +08003215 EXPECT_JSON_INVALID(configFile, "Error: Device ID does not exist.", "");
3216 }
3217}
Shawn McCarney846dde52021-08-14 12:47:44 -05003218
Bob King21b09be2020-02-18 13:33:09 +08003219TEST(ValidateRegulatorsConfigTest, RuleIDExists)
3220{
3221 // Invalid: test rule_id property in configuration specifies a rule ID that
3222 // does not exist.
3223 {
3224 json configFile = validConfigFile;
3225 configFile["chassis"][0]["devices"][0]["configuration"]["rule_id"] =
3226 "set_voltage_rule2";
3227 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
3228 }
3229 // Invalid: test rule_id property in presence_detection specifies a rule ID
3230 // that does not exist.
3231 {
3232 json configFile = validConfigFile;
3233 configFile["chassis"][0]["devices"][0]["presence_detection"]
Shawn McCarney5d4a9c72021-08-19 18:45:59 -05003234 ["rule_id"] = "detect_presence_rule2";
3235 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
3236 }
3237 // Invalid: test rule_id property in phase_fault_detection specifies a rule
3238 // ID that does not exist.
3239 {
3240 json configFile = validConfigFile;
3241 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
3242 ["rule_id"] = "detect_phase_faults_rule2";
Bob King21b09be2020-02-18 13:33:09 +08003243 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
3244 }
3245 // Invalid: test rule_id property in sensor_monitoring specifies a rule ID
3246 // that does not exist.
3247 {
3248 json configFile = validConfigFile;
3249 configFile["chassis"][0]["devices"][0]["rails"][0]["sensor_monitoring"]
Shawn McCarney5d4a9c72021-08-19 18:45:59 -05003250 ["rule_id"] = "read_sensors_rule2";
Bob King21b09be2020-02-18 13:33:09 +08003251 EXPECT_JSON_INVALID(configFile, "Error: Rule ID does not exist.", "");
3252 }
3253}
Shawn McCarney846dde52021-08-14 12:47:44 -05003254
Shawn McCarney5d4a9c72021-08-19 18:45:59 -05003255TEST(ValidateRegulatorsConfigTest, DeviceIDExists)
3256{
3257 // Invalid: test device_id property in phase_fault_detection specifies a
3258 // device ID that does not exist.
3259 {
3260 json configFile = validConfigFile;
3261 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
3262 ["device_id"] = "vdd_regulator2";
3263 configFile["chassis"][0]["devices"][0]["phase_fault_detection"]
3264 ["rule_id"] = "detect_phase_faults_rule";
3265 EXPECT_JSON_INVALID(configFile, "Error: Device ID does not exist.", "");
3266 }
3267}
3268
Bob Kingdc72b622020-02-18 13:36:18 +08003269TEST(ValidateRegulatorsConfigTest, NumberOfElementsInMasks)
3270{
3271 // Invalid: test number of elements in masks not equal to number in values
3272 // in i2c_compare_bytes.
3273 {
3274 json configFile = validConfigFile;
3275 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["register"] =
3276 "0x82";
3277 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["values"] = {
3278 "0x02", "0x73"};
3279 configFile["rules"][0]["actions"][1]["i2c_compare_bytes"]["masks"] = {
3280 "0x7F"};
3281 EXPECT_JSON_INVALID(configFile,
3282 "Error: Invalid i2c_compare_bytes action.", "");
3283 }
3284 // Invalid: test number of elements in masks not equal to number in values
3285 // in i2c_write_bytes.
3286 {
3287 json configFile = validConfigFile;
3288 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["register"] =
3289 "0x82";
3290 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["values"] = {
3291 "0x02", "0x73"};
3292 configFile["rules"][0]["actions"][1]["i2c_write_bytes"]["masks"] = {
3293 "0x7F"};
3294 EXPECT_JSON_INVALID(configFile,
3295 "Error: Invalid i2c_write_bytes action.", "");
3296 }
3297}
Shawn McCarney846dde52021-08-14 12:47:44 -05003298
Bob Kinged009652020-02-20 14:54:13 +08003299TEST(ValidateRegulatorsConfigTest, CommandLineSyntax)
3300{
Bob Kinga57e0812020-03-12 10:47:42 +08003301 std::string validateTool =
3302 " ../phosphor-regulators/tools/validate-regulators-config.py ";
Bob Kinged009652020-02-20 14:54:13 +08003303 std::string schema = " -s ";
Bob Kinga57e0812020-03-12 10:47:42 +08003304 std::string schemaFile =
3305 " ../phosphor-regulators/schema/config_schema.json ";
Bob Kinged009652020-02-20 14:54:13 +08003306 std::string configuration = " -c ";
3307 std::string command;
3308 std::string errorMessage;
3309 std::string outputMessage;
3310 std::string outputMessageHelp =
3311 "usage: validate-regulators-config.py [-h] [-s SCHEMA_FILE]";
3312 int valid = 0;
3313
Shawn McCarney0f6ebad2020-09-04 16:43:00 -05003314 TemporaryFile tmpFile;
3315 std::string fileName = tmpFile.getPath().string();
Bob Kinga57e0812020-03-12 10:47:42 +08003316 writeDataToFile(validConfigFile, fileName);
Bob Kinged009652020-02-20 14:54:13 +08003317 // Valid: -s specified
3318 {
3319 command = validateTool + "-s " + schemaFile + configuration + fileName;
3320 expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
3321 }
3322 // Valid: --schema-file specified
3323 {
3324 command = validateTool + "--schema-file " + schemaFile + configuration +
3325 fileName;
3326 expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
3327 }
3328 // Valid: -c specified
3329 {
3330 command = validateTool + schema + schemaFile + "-c " + fileName;
3331 expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
3332 }
3333 // Valid: --configuration-file specified
3334 {
3335 command = validateTool + schema + schemaFile + "--configuration-file " +
3336 fileName;
3337 expectCommandLineSyntax(errorMessage, outputMessage, command, valid);
3338 }
3339 // Valid: -h specified
3340 {
3341 command = validateTool + "-h ";
3342 expectCommandLineSyntax(errorMessage, outputMessageHelp, command,
3343 valid);
3344 }
3345 // Valid: --help specified
3346 {
3347 command = validateTool + "--help ";
3348 expectCommandLineSyntax(errorMessage, outputMessageHelp, command,
3349 valid);
3350 }
3351 // Invalid: -c/--configuration-file not specified
3352 {
3353 command = validateTool + schema + schemaFile;
3354 expectCommandLineSyntax("Error: Configuration file is required.",
3355 outputMessageHelp, command, 1);
3356 }
3357 // Invalid: -s/--schema-file not specified
3358 {
3359 command = validateTool + configuration + fileName;
3360 expectCommandLineSyntax("Error: Schema file is required.",
3361 outputMessageHelp, command, 1);
3362 }
Bob Kingb7552f02020-10-15 14:34:17 +08003363 // Invalid: -c specified more than once
3364 {
3365 command = validateTool + schema + schemaFile + "-c -c " + fileName;
3366 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3367 }
Bob Kinged009652020-02-20 14:54:13 +08003368 // Invalid: -s specified more than once
3369 {
Patrick Williams48781ae2023-05-10 07:50:50 -05003370 command = validateTool + "-s -s " + schemaFile + configuration +
3371 fileName;
Bob Kinged009652020-02-20 14:54:13 +08003372 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3373 }
Bob Kinged009652020-02-20 14:54:13 +08003374 // Invalid: No file name specified after -c
3375 {
3376 command = validateTool + schema + schemaFile + configuration;
3377 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3378 }
3379 // Invalid: No file name specified after -s
3380 {
3381 command = validateTool + schema + configuration + fileName;
3382 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3383 }
3384 // Invalid: File specified after -c does not exist
3385 {
3386 command = validateTool + schema + schemaFile + configuration +
3387 "../notExistFile";
Bob Kingb7552f02020-10-15 14:34:17 +08003388 expectCommandLineSyntax("Error: Configuration file does not exist.",
3389 outputMessageHelp, command, 1);
Bob Kinged009652020-02-20 14:54:13 +08003390 }
3391 // Invalid: File specified after -s does not exist
3392 {
3393 command = validateTool + schema + "../notExistFile " + configuration +
3394 fileName;
Bob Kingb7552f02020-10-15 14:34:17 +08003395 expectCommandLineSyntax("Error: Schema file does not exist.",
3396 outputMessageHelp, command, 1);
3397 }
3398 // Invalid: File specified after -c is not right data format
3399 {
3400 TemporaryFile wrongFormatFile;
3401 std::string wrongFormatFileName = wrongFormatFile.getPath().string();
3402 std::ofstream out(wrongFormatFileName);
3403 out << "foo";
3404 out.close();
3405 command = validateTool + schema + schemaFile + configuration +
3406 wrongFormatFileName;
Bob Kinged009652020-02-20 14:54:13 +08003407 expectCommandLineSyntax(
Bob Kingb7552f02020-10-15 14:34:17 +08003408 "Error: Configuration file is not in the JSON format.",
3409 outputMessageHelp, command, 1);
Bob Kinged009652020-02-20 14:54:13 +08003410 }
3411 // Invalid: File specified after -s is not right data format
3412 {
Shawn McCarney0f6ebad2020-09-04 16:43:00 -05003413 TemporaryFile wrongFormatFile;
3414 std::string wrongFormatFileName = wrongFormatFile.getPath().string();
Bob Kinga57e0812020-03-12 10:47:42 +08003415 std::ofstream out(wrongFormatFileName);
Bob Kinged009652020-02-20 14:54:13 +08003416 out << "foo";
3417 out.close();
Bob Kinga57e0812020-03-12 10:47:42 +08003418 command = validateTool + schema + wrongFormatFileName + configuration +
3419 fileName;
Bob Kingb7552f02020-10-15 14:34:17 +08003420 expectCommandLineSyntax("Error: Schema file is not in the JSON format.",
3421 outputMessageHelp, command, 1);
Bob Kinged009652020-02-20 14:54:13 +08003422 }
3423 // Invalid: File specified after -c is not readable
3424 {
Shawn McCarney0f6ebad2020-09-04 16:43:00 -05003425 TemporaryFile notReadableFile;
3426 std::string notReadableFileName = notReadableFile.getPath().string();
Bob Kinga57e0812020-03-12 10:47:42 +08003427 writeDataToFile(validConfigFile, notReadableFileName);
Bob Kinged009652020-02-20 14:54:13 +08003428 command = validateTool + schema + schemaFile + configuration +
Bob Kinga57e0812020-03-12 10:47:42 +08003429 notReadableFileName;
3430 chmod(notReadableFileName.c_str(), 0222);
Bob Kingb7552f02020-10-15 14:34:17 +08003431 expectCommandLineSyntax("Error: Configuration file is not readable.",
3432 outputMessageHelp, command, 1);
Bob Kinged009652020-02-20 14:54:13 +08003433 }
3434 // Invalid: File specified after -s is not readable
3435 {
Shawn McCarney0f6ebad2020-09-04 16:43:00 -05003436 TemporaryFile notReadableFile;
3437 std::string notReadableFileName = notReadableFile.getPath().string();
Bob Kinga57e0812020-03-12 10:47:42 +08003438 writeDataToFile(validConfigFile, notReadableFileName);
3439 command = validateTool + schema + notReadableFileName + configuration +
3440 fileName;
3441 chmod(notReadableFileName.c_str(), 0222);
Bob Kingb7552f02020-10-15 14:34:17 +08003442 expectCommandLineSyntax("Error: Schema file is not readable.",
3443 outputMessageHelp, command, 1);
Bob Kinged009652020-02-20 14:54:13 +08003444 }
3445 // Invalid: Unexpected parameter specified (like -g)
3446 {
3447 command = validateTool + schema + schemaFile + configuration +
3448 fileName + " -g";
3449 expectCommandLineSyntax(outputMessageHelp, outputMessage, command, 2);
3450 }
Bob Kinged009652020-02-20 14:54:13 +08003451}