blob: 38bee22096a59863f67c05ccc2e96d0454f198cb [file] [log] [blame]
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001/**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "action.hpp"
Bob King3a787542020-04-14 13:45:01 +080017#include "and_action.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050018#include "chassis.hpp"
Bob Kingb267b7e2020-04-22 14:42:39 +080019#include "compare_presence_action.hpp"
Bob Kingf2134322020-04-27 14:14:56 +080020#include "compare_vpd_action.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050021#include "config_file_parser.hpp"
22#include "config_file_parser_error.hpp"
Bob King9c36c5f2020-04-06 11:34:09 +080023#include "configuration.hpp"
Bob King0e701132020-04-03 21:50:31 +080024#include "device.hpp"
Shawn McCarney91f87a52021-09-07 09:59:57 -050025#include "i2c_capture_bytes_action.hpp"
Bob Kingf09bfe02020-04-13 17:21:15 +080026#include "i2c_compare_bit_action.hpp"
27#include "i2c_compare_byte_action.hpp"
28#include "i2c_compare_bytes_action.hpp"
Bob Kingf617f892020-03-30 19:03:35 +080029#include "i2c_interface.hpp"
30#include "i2c_write_bit_action.hpp"
Bob King87ff9d72020-03-31 14:02:55 +080031#include "i2c_write_byte_action.hpp"
Bob Kingbafcb862020-03-31 16:39:00 +080032#include "i2c_write_bytes_action.hpp"
Shawn McCarney11157852021-09-07 14:04:36 -050033#include "log_phase_fault_action.hpp"
Bob Kingf1b58dc2020-04-14 14:53:10 +080034#include "not_action.hpp"
Bob King0b51a9b2020-04-15 13:24:18 +080035#include "or_action.hpp"
Shawn McCarneyb70370b2021-09-07 12:07:40 -050036#include "phase_fault.hpp"
Shawn McCarney39eb08a2021-09-07 16:34:49 -050037#include "phase_fault_detection.hpp"
Bob King84614882020-04-30 13:13:48 +080038#include "pmbus_read_sensor_action.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050039#include "pmbus_utils.hpp"
40#include "pmbus_write_vout_command_action.hpp"
Bob King9c36c5f2020-04-06 11:34:09 +080041#include "presence_detection.hpp"
42#include "rail.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050043#include "rule.hpp"
Bob King315b0b62020-04-03 21:47:58 +080044#include "run_rule_action.hpp"
Bob Kinga2f2a0d2020-04-09 13:32:14 +080045#include "sensor_monitoring.hpp"
Shawn McCarney2f9e14f2021-04-29 02:45:18 -050046#include "sensors.hpp"
Bob King18a68502020-04-17 14:19:56 +080047#include "set_device_action.hpp"
Shawn McCarney0f6ebad2020-09-04 16:43:00 -050048#include "temporary_file.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050049
Shawn McCarney80c0b042020-03-27 12:08:53 -050050#include <sys/stat.h> // for chmod()
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050051
52#include <nlohmann/json.hpp>
53
54#include <cstdint>
55#include <cstring>
56#include <exception>
57#include <filesystem>
58#include <fstream>
59#include <memory>
60#include <optional>
61#include <stdexcept>
62#include <string>
63#include <tuple>
64#include <vector>
65
66#include <gtest/gtest.h>
67
68using namespace phosphor::power::regulators;
69using namespace phosphor::power::regulators::config_file_parser;
70using namespace phosphor::power::regulators::config_file_parser::internal;
71using json = nlohmann::json;
72
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050073void writeConfigFile(const std::filesystem::path& pathName,
74 const std::string& contents)
75{
76 std::ofstream file{pathName};
77 file << contents;
78}
79
80void writeConfigFile(const std::filesystem::path& pathName,
81 const json& contents)
82{
83 std::ofstream file{pathName};
84 file << contents;
85}
86
87TEST(ConfigFileParserTests, Parse)
88{
89 // Test where works
90 {
91 const json configFileContents = R"(
92 {
93 "rules": [
94 {
95 "id": "set_voltage_rule1",
96 "actions": [
97 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
98 ]
99 },
100 {
101 "id": "set_voltage_rule2",
102 "actions": [
103 { "pmbus_write_vout_command": { "volts": 1.33, "format": "linear" } }
104 ]
105 }
106 ],
107 "chassis": [
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500108 { "number": 1, "inventory_path": "system/chassis1" },
109 { "number": 2, "inventory_path": "system/chassis2" },
110 { "number": 3, "inventory_path": "system/chassis3" }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500111 ]
112 }
113 )"_json;
114
Shawn McCarney0f6ebad2020-09-04 16:43:00 -0500115 TemporaryFile configFile;
116 std::filesystem::path pathName{configFile.getPath()};
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500117 writeConfigFile(pathName, configFileContents);
118
119 std::vector<std::unique_ptr<Rule>> rules{};
120 std::vector<std::unique_ptr<Chassis>> chassis{};
121 std::tie(rules, chassis) = parse(pathName);
122
123 EXPECT_EQ(rules.size(), 2);
124 EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1");
125 EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2");
126
Bob King0e701132020-04-03 21:50:31 +0800127 EXPECT_EQ(chassis.size(), 3);
128 EXPECT_EQ(chassis[0]->getNumber(), 1);
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500129 EXPECT_EQ(chassis[0]->getInventoryPath(),
130 "/xyz/openbmc_project/inventory/system/chassis1");
Bob King0e701132020-04-03 21:50:31 +0800131 EXPECT_EQ(chassis[1]->getNumber(), 2);
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500132 EXPECT_EQ(chassis[1]->getInventoryPath(),
133 "/xyz/openbmc_project/inventory/system/chassis2");
Bob King0e701132020-04-03 21:50:31 +0800134 EXPECT_EQ(chassis[2]->getNumber(), 3);
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500135 EXPECT_EQ(chassis[2]->getInventoryPath(),
136 "/xyz/openbmc_project/inventory/system/chassis3");
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500137 }
138
139 // Test where fails: File does not exist
140 try
141 {
142 std::filesystem::path pathName{"/tmp/non_existent_file"};
143 parse(pathName);
144 ADD_FAILURE() << "Should not have reached this line.";
145 }
146 catch (const ConfigFileParserError& e)
147 {
148 // Expected exception; what() message will vary
149 }
150
151 // Test where fails: File is not readable
152 try
153 {
154 const json configFileContents = R"(
155 {
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500156 "chassis": [
157 { "number": 1, "inventory_path": "system/chassis1" }
158 ]
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500159 }
160 )"_json;
161
Shawn McCarney0f6ebad2020-09-04 16:43:00 -0500162 TemporaryFile configFile;
163 std::filesystem::path pathName{configFile.getPath()};
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500164 writeConfigFile(pathName, configFileContents);
165
166 chmod(pathName.c_str(), 0222);
167
168 parse(pathName);
169 ADD_FAILURE() << "Should not have reached this line.";
170 }
171 catch (const ConfigFileParserError& e)
172 {
173 // Expected exception; what() message will vary
174 }
175
176 // Test where fails: File is not valid JSON
177 try
178 {
179 const std::string configFileContents = "] foo [";
180
Shawn McCarney0f6ebad2020-09-04 16:43:00 -0500181 TemporaryFile configFile;
182 std::filesystem::path pathName{configFile.getPath()};
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500183 writeConfigFile(pathName, configFileContents);
184
185 parse(pathName);
186 ADD_FAILURE() << "Should not have reached this line.";
187 }
188 catch (const ConfigFileParserError& e)
189 {
190 // Expected exception; what() message will vary
191 }
192
193 // Test where fails: Error when parsing JSON elements
194 try
195 {
196 const json configFileContents = R"( { "foo": "bar" } )"_json;
197
Shawn McCarney0f6ebad2020-09-04 16:43:00 -0500198 TemporaryFile configFile;
199 std::filesystem::path pathName{configFile.getPath()};
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500200 writeConfigFile(pathName, configFileContents);
201
202 parse(pathName);
203 ADD_FAILURE() << "Should not have reached this line.";
204 }
205 catch (const ConfigFileParserError& e)
206 {
207 // Expected exception; what() message will vary
208 }
209}
210
211TEST(ConfigFileParserTests, GetRequiredProperty)
212{
213 // Test where property exists
214 {
215 const json element = R"( { "format": "linear" } )"_json;
216 const json& propertyElement = getRequiredProperty(element, "format");
217 EXPECT_EQ(propertyElement.get<std::string>(), "linear");
218 }
219
220 // Test where property does not exist
221 try
222 {
223 const json element = R"( { "volts": 1.03 } )"_json;
224 getRequiredProperty(element, "format");
225 ADD_FAILURE() << "Should not have reached this line.";
226 }
227 catch (const std::invalid_argument& e)
228 {
229 EXPECT_STREQ(e.what(), "Required property missing: format");
230 }
231}
232
233TEST(ConfigFileParserTests, ParseAction)
234{
235 // Test where works: comments property specified
236 {
237 const json element = R"(
238 {
239 "comments": [ "Set output voltage." ],
240 "pmbus_write_vout_command": {
241 "format": "linear"
242 }
243 }
244 )"_json;
245 std::unique_ptr<Action> action = parseAction(element);
246 EXPECT_NE(action.get(), nullptr);
247 }
248
249 // Test where works: comments property not specified
250 {
251 const json element = R"(
252 {
253 "pmbus_write_vout_command": {
254 "format": "linear"
255 }
256 }
257 )"_json;
258 std::unique_ptr<Action> action = parseAction(element);
259 EXPECT_NE(action.get(), nullptr);
260 }
261
262 // Test where works: and action type specified
Bob King3a787542020-04-14 13:45:01 +0800263 {
264 const json element = R"(
265 {
266 "and": [
267 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
268 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
269 ]
270 }
271 )"_json;
272 std::unique_ptr<Action> action = parseAction(element);
273 EXPECT_NE(action.get(), nullptr);
274 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500275
276 // Test where works: compare_presence action type specified
Bob Kingb267b7e2020-04-22 14:42:39 +0800277 {
278 const json element = R"(
279 {
280 "compare_presence":
281 {
Bob Kinga76898f2020-10-13 15:08:33 +0800282 "fru": "system/chassis/motherboard/cpu3",
Bob Kingb267b7e2020-04-22 14:42:39 +0800283 "value": true
284 }
285 }
286 )"_json;
287 std::unique_ptr<Action> action = parseAction(element);
288 EXPECT_NE(action.get(), nullptr);
289 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500290
291 // Test where works: compare_vpd action type specified
Bob Kingf2134322020-04-27 14:14:56 +0800292 {
293 const json element = R"(
294 {
295 "compare_vpd":
296 {
Bob Kinga76898f2020-10-13 15:08:33 +0800297 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +0800298 "keyword": "CCIN",
299 "value": "2D35"
300 }
301 }
302 )"_json;
303 std::unique_ptr<Action> action = parseAction(element);
304 EXPECT_NE(action.get(), nullptr);
305 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500306
Shawn McCarney91f87a52021-09-07 09:59:57 -0500307 // Test where works: i2c_capture_bytes action type specified
308 {
309 const json element = R"(
310 {
311 "i2c_capture_bytes": {
312 "register": "0xA0",
313 "count": 2
314 }
315 }
316 )"_json;
317 std::unique_ptr<Action> action = parseAction(element);
318 EXPECT_NE(action.get(), nullptr);
319 }
320
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500321 // Test where works: i2c_compare_bit action type specified
Bob Kingf09bfe02020-04-13 17:21:15 +0800322 {
323 const json element = R"(
324 {
325 "i2c_compare_bit": {
326 "register": "0xA0",
327 "position": 3,
328 "value": 0
329 }
330 }
331 )"_json;
332 std::unique_ptr<Action> action = parseAction(element);
333 EXPECT_NE(action.get(), nullptr);
334 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500335
336 // Test where works: i2c_compare_byte action type specified
Bob Kingf09bfe02020-04-13 17:21:15 +0800337 {
338 const json element = R"(
339 {
340 "i2c_compare_byte": {
341 "register": "0x0A",
342 "value": "0xCC"
343 }
344 }
345 )"_json;
346 std::unique_ptr<Action> action = parseAction(element);
347 EXPECT_NE(action.get(), nullptr);
348 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500349
350 // Test where works: i2c_compare_bytes action type specified
Bob Kingf09bfe02020-04-13 17:21:15 +0800351 {
352 const json element = R"(
353 {
354 "i2c_compare_bytes": {
355 "register": "0x0A",
356 "values": [ "0xCC", "0xFF" ]
357 }
358 }
359 )"_json;
360 std::unique_ptr<Action> action = parseAction(element);
361 EXPECT_NE(action.get(), nullptr);
362 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500363
364 // Test where works: i2c_write_bit action type specified
Bob Kingf617f892020-03-30 19:03:35 +0800365 {
366 const json element = R"(
367 {
368 "i2c_write_bit": {
369 "register": "0xA0",
370 "position": 3,
371 "value": 0
372 }
373 }
374 )"_json;
375 std::unique_ptr<Action> action = parseAction(element);
376 EXPECT_NE(action.get(), nullptr);
377 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500378
379 // Test where works: i2c_write_byte action type specified
Bob King87ff9d72020-03-31 14:02:55 +0800380 {
381 const json element = R"(
382 {
383 "i2c_write_byte": {
384 "register": "0x0A",
385 "value": "0xCC"
386 }
387 }
388 )"_json;
389 std::unique_ptr<Action> action = parseAction(element);
390 EXPECT_NE(action.get(), nullptr);
391 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500392
393 // Test where works: i2c_write_bytes action type specified
Bob Kingbafcb862020-03-31 16:39:00 +0800394 {
395 const json element = R"(
396 {
397 "i2c_write_bytes": {
398 "register": "0x0A",
399 "values": [ "0xCC", "0xFF" ]
400 }
401 }
402 )"_json;
403 std::unique_ptr<Action> action = parseAction(element);
404 EXPECT_NE(action.get(), nullptr);
405 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500406
407 // Test where works: if action type specified
Bob King93a89d72020-04-15 15:11:11 +0800408 {
409 const json element = R"(
410 {
411 "if":
412 {
413 "condition": { "run_rule": "is_downlevel_regulator" },
414 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
415 "else": [ { "run_rule": "configure_standard_regulator" } ]
416 }
417 }
418 )"_json;
419 std::unique_ptr<Action> action = parseAction(element);
420 EXPECT_NE(action.get(), nullptr);
421 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500422
Shawn McCarney11157852021-09-07 14:04:36 -0500423 // Test where works: log_phase_fault action type specified
424 {
425 const json element = R"(
426 {
427 "log_phase_fault": {
428 "type": "n+1"
429 }
430 }
431 )"_json;
432 std::unique_ptr<Action> action = parseAction(element);
433 EXPECT_NE(action.get(), nullptr);
434 }
435
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500436 // Test where works: not action type specified
Bob Kingf1b58dc2020-04-14 14:53:10 +0800437 {
438 const json element = R"(
439 {
440 "not":
441 { "i2c_compare_byte": { "register": "0xA0", "value": "0xFF" } }
442 }
443 )"_json;
444 std::unique_ptr<Action> action = parseAction(element);
445 EXPECT_NE(action.get(), nullptr);
446 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500447
448 // Test where works: or action type specified
Bob King0b51a9b2020-04-15 13:24:18 +0800449 {
450 const json element = R"(
451 {
452 "or": [
453 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
454 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
455 ]
456 }
457 )"_json;
458 std::unique_ptr<Action> action = parseAction(element);
459 EXPECT_NE(action.get(), nullptr);
460 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500461
462 // Test where works: pmbus_read_sensor action type specified
Bob King84614882020-04-30 13:13:48 +0800463 {
464 const json element = R"(
465 {
466 "pmbus_read_sensor": {
467 "type": "iout",
468 "command": "0x8C",
469 "format": "linear_11"
470 }
471 }
472 )"_json;
473 std::unique_ptr<Action> action = parseAction(element);
474 EXPECT_NE(action.get(), nullptr);
475 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500476
477 // Test where works: pmbus_write_vout_command action type specified
478 {
479 const json element = R"(
480 {
481 "pmbus_write_vout_command": {
482 "format": "linear"
483 }
484 }
485 )"_json;
486 std::unique_ptr<Action> action = parseAction(element);
487 EXPECT_NE(action.get(), nullptr);
488 }
489
490 // Test where works: run_rule action type specified
Bob King315b0b62020-04-03 21:47:58 +0800491 {
492 const json element = R"(
493 {
494 "run_rule": "set_voltage_rule"
495 }
496 )"_json;
497 std::unique_ptr<Action> action = parseAction(element);
498 EXPECT_NE(action.get(), nullptr);
499 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500500
501 // Test where works: set_device action type specified
Bob King18a68502020-04-17 14:19:56 +0800502 {
503 const json element = R"(
504 {
505 "set_device": "io_expander2"
506 }
507 )"_json;
508 std::unique_ptr<Action> action = parseAction(element);
509 EXPECT_NE(action.get(), nullptr);
510 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500511
512 // Test where fails: Element is not an object
513 try
514 {
515 const json element = R"( [ "0xFF", "0x01" ] )"_json;
516 parseAction(element);
517 ADD_FAILURE() << "Should not have reached this line.";
518 }
519 catch (const std::invalid_argument& e)
520 {
521 EXPECT_STREQ(e.what(), "Element is not an object");
522 }
523
524 // Test where fails: No action type specified
525 try
526 {
527 const json element = R"(
528 {
529 "comments": [ "Set output voltage." ]
530 }
531 )"_json;
532 parseAction(element);
533 ADD_FAILURE() << "Should not have reached this line.";
534 }
535 catch (const std::invalid_argument& e)
536 {
537 EXPECT_STREQ(e.what(), "Required action type property missing");
538 }
539
540 // Test where fails: Multiple action types specified
Bob King0e701132020-04-03 21:50:31 +0800541 try
542 {
543 const json element = R"(
544 {
545 "pmbus_write_vout_command": { "format": "linear" },
546 "run_rule": "set_voltage_rule"
547 }
548 )"_json;
549 parseAction(element);
550 ADD_FAILURE() << "Should not have reached this line.";
551 }
552 catch (const std::invalid_argument& e)
553 {
554 EXPECT_STREQ(e.what(), "Element contains an invalid property");
555 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500556
557 // Test where fails: Invalid property specified
558 try
559 {
560 const json element = R"(
561 {
562 "remarks": [ "Set output voltage." ],
563 "pmbus_write_vout_command": {
564 "format": "linear"
565 }
566 }
567 )"_json;
568 parseAction(element);
569 ADD_FAILURE() << "Should not have reached this line.";
570 }
571 catch (const std::invalid_argument& e)
572 {
573 EXPECT_STREQ(e.what(), "Element contains an invalid property");
574 }
575}
576
577TEST(ConfigFileParserTests, ParseActionArray)
578{
579 // Test where works
580 {
581 const json element = R"(
582 [
583 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
584 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
585 ]
586 )"_json;
587 std::vector<std::unique_ptr<Action>> actions =
588 parseActionArray(element);
589 EXPECT_EQ(actions.size(), 2);
590 }
591
592 // Test where fails: Element is not an array
593 try
594 {
595 const json element = R"(
596 {
597 "foo": "bar"
598 }
599 )"_json;
600 parseActionArray(element);
601 ADD_FAILURE() << "Should not have reached this line.";
602 }
603 catch (const std::invalid_argument& e)
604 {
605 EXPECT_STREQ(e.what(), "Element is not an array");
606 }
607}
608
Bob King3a787542020-04-14 13:45:01 +0800609TEST(ConfigFileParserTests, ParseAnd)
610{
611 // Test where works: Element is an array with 2 actions
612 {
613 const json element = R"(
614 [
615 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
616 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
617 ]
618 )"_json;
619 std::unique_ptr<AndAction> action = parseAnd(element);
620 EXPECT_EQ(action->getActions().size(), 2);
621 }
622
623 // Test where fails: Element is an array with 1 action
624 try
625 {
626 const json element = R"(
627 [
628 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }
629 ]
630 )"_json;
631 parseAnd(element);
632 ADD_FAILURE() << "Should not have reached this line.";
633 }
634 catch (const std::invalid_argument& e)
635 {
636 EXPECT_STREQ(e.what(), "Array must contain two or more actions");
637 }
638
639 // Test where fails: Element is not an array
640 try
641 {
642 const json element = R"(
643 {
644 "foo": "bar"
645 }
646 )"_json;
647 parseAnd(element);
648 ADD_FAILURE() << "Should not have reached this line.";
649 }
650 catch (const std::invalid_argument& e)
651 {
652 EXPECT_STREQ(e.what(), "Element is not an array");
653 }
654}
655
Bob Kingf617f892020-03-30 19:03:35 +0800656TEST(ConfigFileParserTests, ParseBitPosition)
657{
658 // Test where works: 0
659 {
660 const json element = R"( 0 )"_json;
661 uint8_t value = parseBitPosition(element);
662 EXPECT_EQ(value, 0);
663 }
664
665 // Test where works: 7
666 {
667 const json element = R"( 7 )"_json;
668 uint8_t value = parseBitPosition(element);
669 EXPECT_EQ(value, 7);
670 }
671
672 // Test where fails: Element is not an integer
673 try
674 {
675 const json element = R"( 1.03 )"_json;
676 parseBitPosition(element);
677 ADD_FAILURE() << "Should not have reached this line.";
678 }
679 catch (const std::invalid_argument& e)
680 {
681 EXPECT_STREQ(e.what(), "Element is not an integer");
682 }
683
684 // Test where fails: Value < 0
685 try
686 {
687 const json element = R"( -1 )"_json;
688 parseBitPosition(element);
689 ADD_FAILURE() << "Should not have reached this line.";
690 }
691 catch (const std::invalid_argument& e)
692 {
693 EXPECT_STREQ(e.what(), "Element is not a bit position");
694 }
695
696 // Test where fails: Value > 7
697 try
698 {
699 const json element = R"( 8 )"_json;
700 parseBitPosition(element);
701 ADD_FAILURE() << "Should not have reached this line.";
702 }
703 catch (const std::invalid_argument& e)
704 {
705 EXPECT_STREQ(e.what(), "Element is not a bit position");
706 }
707}
708
709TEST(ConfigFileParserTests, ParseBitValue)
710{
711 // Test where works: 0
712 {
713 const json element = R"( 0 )"_json;
714 uint8_t value = parseBitValue(element);
715 EXPECT_EQ(value, 0);
716 }
717
718 // Test where works: 1
719 {
720 const json element = R"( 1 )"_json;
721 uint8_t value = parseBitValue(element);
722 EXPECT_EQ(value, 1);
723 }
724
725 // Test where fails: Element is not an integer
726 try
727 {
728 const json element = R"( 0.5 )"_json;
729 parseBitValue(element);
730 ADD_FAILURE() << "Should not have reached this line.";
731 }
732 catch (const std::invalid_argument& e)
733 {
734 EXPECT_STREQ(e.what(), "Element is not an integer");
735 }
736
737 // Test where fails: Value < 0
738 try
739 {
740 const json element = R"( -1 )"_json;
741 parseBitValue(element);
742 ADD_FAILURE() << "Should not have reached this line.";
743 }
744 catch (const std::invalid_argument& e)
745 {
746 EXPECT_STREQ(e.what(), "Element is not a bit value");
747 }
748
749 // Test where fails: Value > 1
750 try
751 {
752 const json element = R"( 2 )"_json;
753 parseBitValue(element);
754 ADD_FAILURE() << "Should not have reached this line.";
755 }
756 catch (const std::invalid_argument& e)
757 {
758 EXPECT_STREQ(e.what(), "Element is not a bit value");
759 }
760}
761
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500762TEST(ConfigFileParserTests, ParseBoolean)
763{
764 // Test where works: true
765 {
766 const json element = R"( true )"_json;
767 bool value = parseBoolean(element);
768 EXPECT_EQ(value, true);
769 }
770
771 // Test where works: false
772 {
773 const json element = R"( false )"_json;
774 bool value = parseBoolean(element);
775 EXPECT_EQ(value, false);
776 }
777
778 // Test where fails: Element is not a boolean
779 try
780 {
781 const json element = R"( 1 )"_json;
782 parseBoolean(element);
783 ADD_FAILURE() << "Should not have reached this line.";
784 }
785 catch (const std::invalid_argument& e)
786 {
787 EXPECT_STREQ(e.what(), "Element is not a boolean");
788 }
789}
790
Bob King0e701132020-04-03 21:50:31 +0800791TEST(ConfigFileParserTests, ParseChassis)
792{
793 // Test where works: Only required properties specified
794 {
795 const json element = R"(
796 {
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500797 "number": 1,
798 "inventory_path": "system/chassis1"
Bob King0e701132020-04-03 21:50:31 +0800799 }
800 )"_json;
801 std::unique_ptr<Chassis> chassis = parseChassis(element);
802 EXPECT_EQ(chassis->getNumber(), 1);
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500803 EXPECT_EQ(chassis->getInventoryPath(),
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500804 "/xyz/openbmc_project/inventory/system/chassis1");
Bob King9c36c5f2020-04-06 11:34:09 +0800805 EXPECT_EQ(chassis->getDevices().size(), 0);
Bob King0e701132020-04-03 21:50:31 +0800806 }
807
808 // Test where works: All properties specified
809 {
810 const json element = R"(
811 {
812 "comments": [ "comments property" ],
813 "number": 2,
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500814 "inventory_path": "system/chassis2",
Bob King0e701132020-04-03 21:50:31 +0800815 "devices": [
816 {
817 "id": "vdd_regulator",
818 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +0800819 "fru": "system/chassis/motherboard/regulator2",
Bob King0e701132020-04-03 21:50:31 +0800820 "i2c_interface":
821 {
822 "bus": 1,
823 "address": "0x70"
824 }
825 }
826 ]
827 }
828 )"_json;
829 std::unique_ptr<Chassis> chassis = parseChassis(element);
830 EXPECT_EQ(chassis->getNumber(), 2);
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500831 EXPECT_EQ(chassis->getInventoryPath(),
832 "/xyz/openbmc_project/inventory/system/chassis2");
Bob King9c36c5f2020-04-06 11:34:09 +0800833 EXPECT_EQ(chassis->getDevices().size(), 1);
834 EXPECT_EQ(chassis->getDevices()[0]->getID(), "vdd_regulator");
Bob King0e701132020-04-03 21:50:31 +0800835 }
836
837 // Test where fails: number value is invalid
838 try
839 {
840 const json element = R"(
841 {
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500842 "number": 0.5,
843 "inventory_path": "system/chassis"
Bob King0e701132020-04-03 21:50:31 +0800844 }
845 )"_json;
846 parseChassis(element);
847 ADD_FAILURE() << "Should not have reached this line.";
848 }
849 catch (const std::invalid_argument& e)
850 {
851 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
852 }
853
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500854 // Test where fails: inventory_path is invalid: Not a string
855 try
856 {
857 const json element = R"(
858 {
859 "number": 2,
860 "inventory_path": true
861 }
862 )"_json;
863 parseChassis(element);
864 ADD_FAILURE() << "Should not have reached this line.";
865 }
866 catch (const std::invalid_argument& e)
867 {
868 EXPECT_STREQ(e.what(), "Element is not a string");
869 }
870
871 // Test where fails: inventory_path is invalid: Empty string
872 try
873 {
874 const json element = R"(
875 {
876 "number": 2,
877 "inventory_path": ""
878 }
879 )"_json;
880 parseChassis(element);
881 ADD_FAILURE() << "Should not have reached this line.";
882 }
883 catch (const std::invalid_argument& e)
884 {
885 EXPECT_STREQ(e.what(), "Element contains an empty string");
886 }
887
Bob King0e701132020-04-03 21:50:31 +0800888 // Test where fails: Invalid property specified
889 try
890 {
891 const json element = R"(
892 {
893 "number": 1,
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500894 "inventory_path": "system/chassis",
Bob King0e701132020-04-03 21:50:31 +0800895 "foo": 2
896 }
897 )"_json;
898 parseChassis(element);
899 ADD_FAILURE() << "Should not have reached this line.";
900 }
901 catch (const std::invalid_argument& e)
902 {
903 EXPECT_STREQ(e.what(), "Element contains an invalid property");
904 }
905
906 // Test where fails: Required number property not specified
907 try
908 {
909 const json element = R"(
910 {
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500911 "inventory_path": "system/chassis"
Bob King0e701132020-04-03 21:50:31 +0800912 }
913 )"_json;
914 parseChassis(element);
915 ADD_FAILURE() << "Should not have reached this line.";
916 }
917 catch (const std::invalid_argument& e)
918 {
919 EXPECT_STREQ(e.what(), "Required property missing: number");
920 }
921
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500922 // Test where fails: Required inventory_path property not specified
923 try
924 {
925 const json element = R"(
926 {
927 "number": 1
928 }
929 )"_json;
930 parseChassis(element);
931 ADD_FAILURE() << "Should not have reached this line.";
932 }
933 catch (const std::invalid_argument& e)
934 {
935 EXPECT_STREQ(e.what(), "Required property missing: inventory_path");
936 }
937
Bob King0e701132020-04-03 21:50:31 +0800938 // Test where fails: Element is not an object
939 try
940 {
941 const json element = R"( [ "0xFF", "0x01" ] )"_json;
942 parseChassis(element);
943 ADD_FAILURE() << "Should not have reached this line.";
944 }
945 catch (const std::invalid_argument& e)
946 {
947 EXPECT_STREQ(e.what(), "Element is not an object");
948 }
949
950 // Test where fails: number value is < 1
951 try
952 {
953 const json element = R"(
954 {
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500955 "number": 0,
956 "inventory_path": "system/chassis"
Bob King0e701132020-04-03 21:50:31 +0800957 }
958 )"_json;
959 parseChassis(element);
960 ADD_FAILURE() << "Should not have reached this line.";
961 }
962 catch (const std::invalid_argument& e)
963 {
964 EXPECT_STREQ(e.what(), "Invalid chassis number: Must be > 0");
965 }
966
967 // Test where fails: devices value is invalid
968 try
969 {
970 const json element = R"(
971 {
972 "number": 1,
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500973 "inventory_path": "system/chassis",
Bob King0e701132020-04-03 21:50:31 +0800974 "devices": 2
975 }
976 )"_json;
977 parseChassis(element);
978 ADD_FAILURE() << "Should not have reached this line.";
979 }
980 catch (const std::invalid_argument& e)
981 {
982 EXPECT_STREQ(e.what(), "Element is not an array");
983 }
984}
985
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500986TEST(ConfigFileParserTests, ParseChassisArray)
987{
Bob King0e701132020-04-03 21:50:31 +0800988 // Test where works
989 {
990 const json element = R"(
991 [
Shawn McCarney4c88a4c2021-09-21 15:29:24 -0500992 { "number": 1, "inventory_path": "system/chassis1" },
993 { "number": 2, "inventory_path": "system/chassis2" }
Bob King0e701132020-04-03 21:50:31 +0800994 ]
995 )"_json;
996 std::vector<std::unique_ptr<Chassis>> chassis =
997 parseChassisArray(element);
998 EXPECT_EQ(chassis.size(), 2);
999 EXPECT_EQ(chassis[0]->getNumber(), 1);
Shawn McCarney4c88a4c2021-09-21 15:29:24 -05001000 EXPECT_EQ(chassis[0]->getInventoryPath(),
1001 "/xyz/openbmc_project/inventory/system/chassis1");
Bob King0e701132020-04-03 21:50:31 +08001002 EXPECT_EQ(chassis[1]->getNumber(), 2);
Shawn McCarney4c88a4c2021-09-21 15:29:24 -05001003 EXPECT_EQ(chassis[1]->getInventoryPath(),
1004 "/xyz/openbmc_project/inventory/system/chassis2");
Bob King0e701132020-04-03 21:50:31 +08001005 }
1006
1007 // Test where fails: Element is not an array
1008 try
1009 {
1010 const json element = R"(
1011 {
1012 "foo": "bar"
1013 }
1014 )"_json;
1015 parseChassisArray(element);
1016 ADD_FAILURE() << "Should not have reached this line.";
1017 }
1018 catch (const std::invalid_argument& e)
1019 {
1020 EXPECT_STREQ(e.what(), "Element is not an array");
1021 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001022}
1023
Bob Kingb267b7e2020-04-22 14:42:39 +08001024TEST(ConfigFileParserTests, ParseComparePresence)
1025{
1026 // Test where works
1027 {
1028 const json element = R"(
1029 {
Bob Kinga76898f2020-10-13 15:08:33 +08001030 "fru": "system/chassis/motherboard/cpu3",
Bob Kingb267b7e2020-04-22 14:42:39 +08001031 "value": true
1032 }
1033 )"_json;
1034 std::unique_ptr<ComparePresenceAction> action =
1035 parseComparePresence(element);
Bob Kinga76898f2020-10-13 15:08:33 +08001036 EXPECT_EQ(
1037 action->getFRU(),
1038 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3");
Bob Kingb267b7e2020-04-22 14:42:39 +08001039 EXPECT_EQ(action->getValue(), true);
1040 }
1041
1042 // Test where fails: Element is not an object
1043 try
1044 {
1045 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1046 parseComparePresence(element);
1047 ADD_FAILURE() << "Should not have reached this line.";
1048 }
1049 catch (const std::invalid_argument& e)
1050 {
1051 EXPECT_STREQ(e.what(), "Element is not an object");
1052 }
1053
1054 // Test where fails: Invalid property specified
1055 try
1056 {
1057 const json element = R"(
1058 {
Bob Kinga76898f2020-10-13 15:08:33 +08001059 "fru": "system/chassis/motherboard/cpu3",
Bob Kingb267b7e2020-04-22 14:42:39 +08001060 "value": true,
1061 "foo" : true
1062 }
1063 )"_json;
1064 parseComparePresence(element);
1065 ADD_FAILURE() << "Should not have reached this line.";
1066 }
1067 catch (const std::invalid_argument& e)
1068 {
1069 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1070 }
1071
1072 // Test where fails: Required fru property not specified
1073 try
1074 {
1075 const json element = R"(
1076 {
1077 "value": true
1078 }
1079 )"_json;
1080 parseComparePresence(element);
1081 ADD_FAILURE() << "Should not have reached this line.";
1082 }
1083 catch (const std::invalid_argument& e)
1084 {
1085 EXPECT_STREQ(e.what(), "Required property missing: fru");
1086 }
1087
1088 // Test where fails: Required value property not specified
1089 try
1090 {
1091 const json element = R"(
1092 {
Bob Kinga76898f2020-10-13 15:08:33 +08001093 "fru": "system/chassis/motherboard/cpu3"
Bob Kingb267b7e2020-04-22 14:42:39 +08001094 }
1095 )"_json;
1096 parseComparePresence(element);
1097 ADD_FAILURE() << "Should not have reached this line.";
1098 }
1099 catch (const std::invalid_argument& e)
1100 {
1101 EXPECT_STREQ(e.what(), "Required property missing: value");
1102 }
1103
1104 // Test where fails: fru value is invalid
1105 try
1106 {
1107 const json element = R"(
1108 {
1109 "fru": 1,
1110 "value": true
1111 }
1112 )"_json;
1113 parseComparePresence(element);
1114 ADD_FAILURE() << "Should not have reached this line.";
1115 }
1116 catch (const std::invalid_argument& e)
1117 {
1118 EXPECT_STREQ(e.what(), "Element is not a string");
1119 }
1120
1121 // Test where fails: value value is invalid
1122 try
1123 {
1124 const json element = R"(
1125 {
Bob Kinga76898f2020-10-13 15:08:33 +08001126 "fru": "system/chassis/motherboard/cpu3",
Bob Kingb267b7e2020-04-22 14:42:39 +08001127 "value": 1
1128 }
1129 )"_json;
1130 parseComparePresence(element);
1131 ADD_FAILURE() << "Should not have reached this line.";
1132 }
1133 catch (const std::invalid_argument& e)
1134 {
1135 EXPECT_STREQ(e.what(), "Element is not a boolean");
1136 }
1137}
1138
Bob Kingf2134322020-04-27 14:14:56 +08001139TEST(ConfigFileParserTests, ParseCompareVPD)
1140{
Matt Spinleraacc2aa2021-05-25 09:31:35 -06001141 // Test where works, using "value"
Bob Kingf2134322020-04-27 14:14:56 +08001142 {
1143 const json element = R"(
1144 {
Bob Kinga76898f2020-10-13 15:08:33 +08001145 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001146 "keyword": "CCIN",
1147 "value": "2D35"
1148 }
1149 )"_json;
1150 std::unique_ptr<CompareVPDAction> action = parseCompareVPD(element);
Bob Kinga76898f2020-10-13 15:08:33 +08001151 EXPECT_EQ(
1152 action->getFRU(),
1153 "/xyz/openbmc_project/inventory/system/chassis/disk_backplane");
Bob Kingf2134322020-04-27 14:14:56 +08001154 EXPECT_EQ(action->getKeyword(), "CCIN");
Matt Spinleraacc2aa2021-05-25 09:31:35 -06001155 EXPECT_EQ(action->getValue(),
1156 (std::vector<uint8_t>{0x32, 0x44, 0x33, 0x35}));
1157 }
1158
1159 // Test where works, using "byte_values"
1160 {
1161 const json element = R"(
1162 {
1163 "fru": "system/chassis/disk_backplane",
1164 "keyword": "CCIN",
1165 "byte_values": ["0x11", "0x22", "0x33"]
1166 }
1167 )"_json;
1168 std::unique_ptr<CompareVPDAction> action = parseCompareVPD(element);
1169 EXPECT_EQ(
1170 action->getFRU(),
1171 "/xyz/openbmc_project/inventory/system/chassis/disk_backplane");
1172 EXPECT_EQ(action->getKeyword(), "CCIN");
1173 EXPECT_EQ(action->getValue(), (std::vector<uint8_t>{0x11, 0x22, 0x33}));
Bob Kingf2134322020-04-27 14:14:56 +08001174 }
1175
1176 // Test where fails: Element is not an object
1177 try
1178 {
1179 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1180 parseCompareVPD(element);
1181 ADD_FAILURE() << "Should not have reached this line.";
1182 }
1183 catch (const std::invalid_argument& e)
1184 {
1185 EXPECT_STREQ(e.what(), "Element is not an object");
1186 }
1187
1188 // Test where fails: Invalid property specified
1189 try
1190 {
1191 const json element = R"(
1192 {
Bob Kinga76898f2020-10-13 15:08:33 +08001193 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001194 "keyword": "CCIN",
1195 "value": "2D35",
1196 "foo" : true
1197 }
1198 )"_json;
1199 parseCompareVPD(element);
1200 ADD_FAILURE() << "Should not have reached this line.";
1201 }
1202 catch (const std::invalid_argument& e)
1203 {
1204 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1205 }
1206
1207 // Test where fails: Required fru property not specified
1208 try
1209 {
1210 const json element = R"(
1211 {
1212 "keyword": "CCIN",
1213 "value": "2D35"
1214 }
1215 )"_json;
1216 parseCompareVPD(element);
1217 ADD_FAILURE() << "Should not have reached this line.";
1218 }
1219 catch (const std::invalid_argument& e)
1220 {
1221 EXPECT_STREQ(e.what(), "Required property missing: fru");
1222 }
1223
1224 // Test where fails: Required keyword property not specified
1225 try
1226 {
1227 const json element = R"(
1228 {
Bob Kinga76898f2020-10-13 15:08:33 +08001229 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001230 "value": "2D35"
1231 }
1232 )"_json;
1233 parseCompareVPD(element);
1234 ADD_FAILURE() << "Should not have reached this line.";
1235 }
1236 catch (const std::invalid_argument& e)
1237 {
1238 EXPECT_STREQ(e.what(), "Required property missing: keyword");
1239 }
1240
1241 // Test where fails: Required value property not specified
1242 try
1243 {
1244 const json element = R"(
1245 {
Bob Kinga76898f2020-10-13 15:08:33 +08001246 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001247 "keyword": "CCIN"
1248 }
1249 )"_json;
1250 parseCompareVPD(element);
1251 ADD_FAILURE() << "Should not have reached this line.";
1252 }
1253 catch (const std::invalid_argument& e)
1254 {
Matt Spinleraacc2aa2021-05-25 09:31:35 -06001255 EXPECT_STREQ(e.what(), "Invalid property: Must contain "
1256 "either value or byte_values");
1257 }
1258
1259 // Test where fails: both value and byte_value specified
1260 try
1261 {
1262 const json element = R"(
1263 {
1264 "fru": "system/chassis/disk_backplane",
1265 "keyword": "CCIN",
1266 "value": "2D35",
1267 "byte_values": [ "0x01", "0x02" ]
1268 }
1269 )"_json;
1270 parseCompareVPD(element);
1271 ADD_FAILURE() << "Should not have reached this line.";
1272 }
1273 catch (const std::invalid_argument& e)
1274 {
1275 EXPECT_STREQ(e.what(), "Invalid property: Must contain "
1276 "either value or byte_values");
Bob Kingf2134322020-04-27 14:14:56 +08001277 }
1278
1279 // Test where fails: fru value is invalid
1280 try
1281 {
1282 const json element = R"(
1283 {
1284 "fru": 1,
1285 "keyword": "CCIN",
1286 "value": "2D35"
1287 }
1288 )"_json;
1289 parseCompareVPD(element);
1290 ADD_FAILURE() << "Should not have reached this line.";
1291 }
1292 catch (const std::invalid_argument& e)
1293 {
1294 EXPECT_STREQ(e.what(), "Element is not a string");
1295 }
1296
1297 // Test where fails: keyword value is invalid
1298 try
1299 {
1300 const json element = R"(
1301 {
Bob Kinga76898f2020-10-13 15:08:33 +08001302 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001303 "keyword": 1,
1304 "value": "2D35"
1305 }
1306 )"_json;
1307 parseCompareVPD(element);
1308 ADD_FAILURE() << "Should not have reached this line.";
1309 }
1310 catch (const std::invalid_argument& e)
1311 {
1312 EXPECT_STREQ(e.what(), "Element is not a string");
1313 }
1314
1315 // Test where fails: value value is invalid
1316 try
1317 {
1318 const json element = R"(
1319 {
Bob Kinga76898f2020-10-13 15:08:33 +08001320 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001321 "keyword": "CCIN",
1322 "value": 1
1323 }
1324 )"_json;
1325 parseCompareVPD(element);
1326 ADD_FAILURE() << "Should not have reached this line.";
1327 }
1328 catch (const std::invalid_argument& e)
1329 {
1330 EXPECT_STREQ(e.what(), "Element is not a string");
1331 }
Matt Spinleraacc2aa2021-05-25 09:31:35 -06001332
1333 // Test where fails: byte_values is wrong format
1334 try
1335 {
1336 const json element = R"(
1337 {
1338 "fru": "system/chassis/disk_backplane",
1339 "keyword": "CCIN",
1340 "byte_values": [1, 2, 3]
1341 }
1342 )"_json;
1343 parseCompareVPD(element);
1344 ADD_FAILURE() << "Should not have reached this line.";
1345 }
1346 catch (const std::invalid_argument& e)
1347 {
1348 EXPECT_STREQ(e.what(), "Element is not a string");
1349 }
Bob Kingf2134322020-04-27 14:14:56 +08001350}
1351
Bob King33e7eaa2020-04-01 18:09:34 +08001352TEST(ConfigFileParserTests, ParseConfiguration)
1353{
1354 // Test where works: actions required property specified
1355 {
1356 const json element = R"(
1357 {
1358 "actions": [
1359 {
1360 "pmbus_write_vout_command": {
1361 "format": "linear"
1362 }
1363 }
1364 ]
1365 }
1366 )"_json;
1367 std::unique_ptr<Configuration> configuration =
1368 parseConfiguration(element);
1369 EXPECT_EQ(configuration->getActions().size(), 1);
1370 EXPECT_EQ(configuration->getVolts().has_value(), false);
1371 }
1372
1373 // Test where works: volts and actions properties specified
1374 {
1375 const json element = R"(
1376 {
1377 "comments": [ "comments property" ],
1378 "volts": 1.03,
1379 "actions": [
1380 { "pmbus_write_vout_command": { "format": "linear" } },
1381 { "run_rule": "set_voltage_rule" }
1382 ]
1383 }
1384 )"_json;
1385 std::unique_ptr<Configuration> configuration =
1386 parseConfiguration(element);
1387 EXPECT_EQ(configuration->getVolts().has_value(), true);
1388 EXPECT_EQ(configuration->getVolts().value(), 1.03);
1389 EXPECT_EQ(configuration->getActions().size(), 2);
1390 }
1391
1392 // Test where works: volts and rule_id properties specified
1393 {
1394 const json element = R"(
1395 {
1396 "volts": 1.05,
1397 "rule_id": "set_voltage_rule"
1398 }
1399 )"_json;
1400 std::unique_ptr<Configuration> configuration =
1401 parseConfiguration(element);
1402 EXPECT_EQ(configuration->getVolts().has_value(), true);
1403 EXPECT_EQ(configuration->getVolts().value(), 1.05);
1404 EXPECT_EQ(configuration->getActions().size(), 1);
1405 }
1406
1407 // Test where fails: volts value is invalid
1408 try
1409 {
1410 const json element = R"(
1411 {
1412 "volts": "foo",
1413 "actions": [
1414 {
1415 "pmbus_write_vout_command": {
1416 "format": "linear"
1417 }
1418 }
1419 ]
1420 }
1421 )"_json;
1422 parseConfiguration(element);
1423 ADD_FAILURE() << "Should not have reached this line.";
1424 }
1425 catch (const std::invalid_argument& e)
1426 {
1427 EXPECT_STREQ(e.what(), "Element is not a number");
1428 }
1429
1430 // Test where fails: actions object is invalid
1431 try
1432 {
1433 const json element = R"(
1434 {
1435 "volts": 1.03,
1436 "actions": 1
1437 }
1438 )"_json;
1439 parseConfiguration(element);
1440 ADD_FAILURE() << "Should not have reached this line.";
1441 }
1442 catch (const std::invalid_argument& e)
1443 {
1444 EXPECT_STREQ(e.what(), "Element is not an array");
1445 }
1446
1447 // Test where fails: rule_id value is invalid
1448 try
1449 {
1450 const json element = R"(
1451 {
1452 "volts": 1.05,
1453 "rule_id": 1
1454 }
1455 )"_json;
1456 parseConfiguration(element);
1457 ADD_FAILURE() << "Should not have reached this line.";
1458 }
1459 catch (const std::invalid_argument& e)
1460 {
1461 EXPECT_STREQ(e.what(), "Element is not a string");
1462 }
1463
1464 // Test where fails: Required actions or rule_id property not specified
1465 try
1466 {
1467 const json element = R"(
1468 {
1469 "volts": 1.03
1470 }
1471 )"_json;
1472 parseConfiguration(element);
1473 ADD_FAILURE() << "Should not have reached this line.";
1474 }
1475 catch (const std::invalid_argument& e)
1476 {
1477 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
1478 "either rule_id or actions");
1479 }
1480
1481 // Test where fails: Required actions or rule_id property both specified
1482 try
1483 {
1484 const json element = R"(
1485 {
1486 "volts": 1.03,
1487 "rule_id": "set_voltage_rule",
1488 "actions": [
1489 {
1490 "pmbus_write_vout_command": {
1491 "format": "linear"
1492 }
1493 }
1494 ]
1495 }
1496 )"_json;
1497 parseConfiguration(element);
1498 ADD_FAILURE() << "Should not have reached this line.";
1499 }
1500 catch (const std::invalid_argument& e)
1501 {
1502 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
1503 "either rule_id or actions");
1504 }
1505
1506 // Test where fails: Element is not an object
1507 try
1508 {
1509 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1510 parseConfiguration(element);
1511 ADD_FAILURE() << "Should not have reached this line.";
1512 }
1513 catch (const std::invalid_argument& e)
1514 {
1515 EXPECT_STREQ(e.what(), "Element is not an object");
1516 }
1517
1518 // Test where fails: Invalid property specified
1519 try
1520 {
1521 const json element = R"(
1522 {
1523 "volts": 1.03,
1524 "rule_id": "set_voltage_rule",
1525 "foo": 1
1526 }
1527 )"_json;
1528 parseConfiguration(element);
1529 ADD_FAILURE() << "Should not have reached this line.";
1530 }
1531 catch (const std::invalid_argument& e)
1532 {
1533 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1534 }
1535}
1536
Bob King9c36c5f2020-04-06 11:34:09 +08001537TEST(ConfigFileParserTests, ParseDevice)
1538{
1539 // Test where works: Only required properties specified
1540 {
1541 const json element = R"(
1542 {
1543 "id": "vdd_regulator",
1544 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001545 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001546 "i2c_interface": { "bus": 1, "address": "0x70" }
1547 }
1548 )"_json;
1549 std::unique_ptr<Device> device = parseDevice(element);
1550 EXPECT_EQ(device->getID(), "vdd_regulator");
1551 EXPECT_EQ(device->isRegulator(), true);
Bob Kinga76898f2020-10-13 15:08:33 +08001552 EXPECT_EQ(device->getFRU(), "/xyz/openbmc_project/inventory/system/"
1553 "chassis/motherboard/regulator2");
Bob King9c36c5f2020-04-06 11:34:09 +08001554 EXPECT_NE(&(device->getI2CInterface()), nullptr);
1555 EXPECT_EQ(device->getPresenceDetection(), nullptr);
1556 EXPECT_EQ(device->getConfiguration(), nullptr);
Shawn McCarney32252592021-09-08 15:29:36 -05001557 EXPECT_EQ(device->getPhaseFaultDetection(), nullptr);
Bob King9c36c5f2020-04-06 11:34:09 +08001558 EXPECT_EQ(device->getRails().size(), 0);
1559 }
1560
1561 // Test where works: All properties specified
Bob King33e7eaa2020-04-01 18:09:34 +08001562 {
Bob King33e7eaa2020-04-01 18:09:34 +08001563 const json element = R"(
1564 {
Shawn McCarney32252592021-09-08 15:29:36 -05001565 "comments": [ "VDD Regulator" ],
Bob King33e7eaa2020-04-01 18:09:34 +08001566 "id": "vdd_regulator",
1567 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001568 "fru": "system/chassis/motherboard/regulator2",
Bob King33e7eaa2020-04-01 18:09:34 +08001569 "i2c_interface":
1570 {
1571 "bus": 1,
1572 "address": "0x70"
1573 },
Shawn McCarney32252592021-09-08 15:29:36 -05001574 "presence_detection":
1575 {
1576 "rule_id": "is_foobar_backplane_installed_rule"
1577 },
Bob King33e7eaa2020-04-01 18:09:34 +08001578 "configuration":
1579 {
1580 "rule_id": "configure_ir35221_rule"
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001581 },
Shawn McCarney32252592021-09-08 15:29:36 -05001582 "phase_fault_detection":
Bob King2aafb1c2020-04-16 15:24:32 +08001583 {
Shawn McCarney32252592021-09-08 15:29:36 -05001584 "rule_id": "detect_phase_fault_rule"
Bob King2aafb1c2020-04-16 15:24:32 +08001585 },
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001586 "rails":
1587 [
1588 {
1589 "id": "vdd"
1590 }
1591 ]
Bob King33e7eaa2020-04-01 18:09:34 +08001592 }
1593 )"_json;
1594 std::unique_ptr<Device> device = parseDevice(element);
1595 EXPECT_EQ(device->getID(), "vdd_regulator");
1596 EXPECT_EQ(device->isRegulator(), true);
Bob Kinga76898f2020-10-13 15:08:33 +08001597 EXPECT_EQ(device->getFRU(), "/xyz/openbmc_project/inventory/system/"
1598 "chassis/motherboard/regulator2");
Bob King33e7eaa2020-04-01 18:09:34 +08001599 EXPECT_NE(&(device->getI2CInterface()), nullptr);
Bob King2aafb1c2020-04-16 15:24:32 +08001600 EXPECT_NE(device->getPresenceDetection(), nullptr);
Bob King33e7eaa2020-04-01 18:09:34 +08001601 EXPECT_NE(device->getConfiguration(), nullptr);
Shawn McCarney32252592021-09-08 15:29:36 -05001602 EXPECT_NE(device->getPhaseFaultDetection(), nullptr);
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001603 EXPECT_EQ(device->getRails().size(), 1);
1604 }
1605
Shawn McCarney32252592021-09-08 15:29:36 -05001606 // Test where fails: phase_fault_detection property exists and is_regulator
1607 // is false
1608 try
1609 {
1610 const json element = R"(
1611 {
1612 "id": "vdd_regulator",
1613 "is_regulator": false,
1614 "fru": "system/chassis/motherboard/regulator2",
1615 "i2c_interface":
1616 {
1617 "bus": 1,
1618 "address": "0x70"
1619 },
1620 "phase_fault_detection":
1621 {
1622 "rule_id": "detect_phase_fault_rule"
1623 }
1624 }
1625 )"_json;
1626 parseDevice(element);
1627 ADD_FAILURE() << "Should not have reached this line.";
1628 }
1629 catch (const std::invalid_argument& e)
1630 {
1631 EXPECT_STREQ(e.what(), "Invalid phase_fault_detection property when "
1632 "is_regulator is false");
1633 }
1634
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001635 // Test where fails: rails property exists and is_regulator is false
1636 try
1637 {
1638 const json element = R"(
1639 {
1640 "id": "vdd_regulator",
1641 "is_regulator": false,
Bob Kinga76898f2020-10-13 15:08:33 +08001642 "fru": "system/chassis/motherboard/regulator2",
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001643 "i2c_interface":
1644 {
1645 "bus": 1,
1646 "address": "0x70"
1647 },
1648 "configuration":
1649 {
1650 "rule_id": "configure_ir35221_rule"
1651 },
1652 "rails":
1653 [
1654 {
1655 "id": "vdd"
1656 }
1657 ]
1658 }
1659 )"_json;
1660 parseDevice(element);
1661 ADD_FAILURE() << "Should not have reached this line.";
1662 }
1663 catch (const std::invalid_argument& e)
1664 {
1665 EXPECT_STREQ(e.what(),
1666 "Invalid rails property when is_regulator is false");
Bob King33e7eaa2020-04-01 18:09:34 +08001667 }
Bob King9c36c5f2020-04-06 11:34:09 +08001668
1669 // Test where fails: id value is invalid
1670 try
1671 {
1672 const json element = R"(
1673 {
1674 "id": 3,
1675 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001676 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001677 "i2c_interface":
1678 {
1679 "bus": 1,
1680 "address": "0x70"
1681 }
1682 }
1683 )"_json;
1684 parseDevice(element);
1685 ADD_FAILURE() << "Should not have reached this line.";
1686 }
1687 catch (const std::invalid_argument& e)
1688 {
1689 EXPECT_STREQ(e.what(), "Element is not a string");
1690 }
1691
1692 // Test where fails: is_regulator value is invalid
1693 try
1694 {
1695 const json element = R"(
1696 {
1697 "id": "vdd_regulator",
1698 "is_regulator": 3,
Bob Kinga76898f2020-10-13 15:08:33 +08001699 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001700 "i2c_interface":
1701 {
1702 "bus": 1,
1703 "address": "0x70"
1704 }
1705 }
1706 )"_json;
1707 parseDevice(element);
1708 ADD_FAILURE() << "Should not have reached this line.";
1709 }
1710 catch (const std::invalid_argument& e)
1711 {
1712 EXPECT_STREQ(e.what(), "Element is not a boolean");
1713 }
1714
1715 // Test where fails: fru value is invalid
1716 try
1717 {
1718 const json element = R"(
1719 {
1720 "id": "vdd_regulator",
1721 "is_regulator": true,
1722 "fru": 2,
1723 "i2c_interface":
1724 {
1725 "bus": 1,
1726 "address": "0x70"
1727 }
1728 }
1729 )"_json;
1730 parseDevice(element);
1731 ADD_FAILURE() << "Should not have reached this line.";
1732 }
1733 catch (const std::invalid_argument& e)
1734 {
1735 EXPECT_STREQ(e.what(), "Element is not a string");
1736 }
1737
1738 // Test where fails: i2c_interface value is invalid
1739 try
1740 {
1741 const json element = R"(
1742 {
1743 "id": "vdd_regulator",
1744 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001745 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001746 "i2c_interface": 3
1747 }
1748 )"_json;
1749 parseDevice(element);
1750 ADD_FAILURE() << "Should not have reached this line.";
1751 }
1752 catch (const std::invalid_argument& e)
1753 {
1754 EXPECT_STREQ(e.what(), "Element is not an object");
1755 }
1756
1757 // Test where fails: Required id property not specified
1758 try
1759 {
1760 const json element = R"(
1761 {
1762 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001763 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001764 "i2c_interface":
1765 {
1766 "bus": 1,
1767 "address": "0x70"
1768 }
1769 }
1770 )"_json;
1771 parseDevice(element);
1772 ADD_FAILURE() << "Should not have reached this line.";
1773 }
1774 catch (const std::invalid_argument& e)
1775 {
1776 EXPECT_STREQ(e.what(), "Required property missing: id");
1777 }
1778
1779 // Test where fails: Required is_regulator property not specified
1780 try
1781 {
1782 const json element = R"(
1783 {
1784 "id": "vdd_regulator",
Bob Kinga76898f2020-10-13 15:08:33 +08001785 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001786 "i2c_interface":
1787 {
1788 "bus": 1,
1789 "address": "0x70"
1790 }
1791 }
1792 )"_json;
1793 parseDevice(element);
1794 ADD_FAILURE() << "Should not have reached this line.";
1795 }
1796 catch (const std::invalid_argument& e)
1797 {
1798 EXPECT_STREQ(e.what(), "Required property missing: is_regulator");
1799 }
1800
1801 // Test where fails: Required fru property not specified
1802 try
1803 {
1804 const json element = R"(
1805 {
1806 "id": "vdd_regulator",
1807 "is_regulator": true,
1808 "i2c_interface":
1809 {
1810 "bus": 1,
1811 "address": "0x70"
1812 }
1813 }
1814 )"_json;
1815 parseDevice(element);
1816 ADD_FAILURE() << "Should not have reached this line.";
1817 }
1818 catch (const std::invalid_argument& e)
1819 {
1820 EXPECT_STREQ(e.what(), "Required property missing: fru");
1821 }
1822
1823 // Test where fails: Required i2c_interface property not specified
1824 try
1825 {
1826 const json element = R"(
1827 {
1828 "id": "vdd_regulator",
1829 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001830 "fru": "system/chassis/motherboard/regulator2"
Bob King9c36c5f2020-04-06 11:34:09 +08001831 }
1832 )"_json;
1833 parseDevice(element);
1834 ADD_FAILURE() << "Should not have reached this line.";
1835 }
1836 catch (const std::invalid_argument& e)
1837 {
1838 EXPECT_STREQ(e.what(), "Required property missing: i2c_interface");
1839 }
1840
1841 // Test where fails: Element is not an object
1842 try
1843 {
1844 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1845 parseDevice(element);
1846 ADD_FAILURE() << "Should not have reached this line.";
1847 }
1848 catch (const std::invalid_argument& e)
1849 {
1850 EXPECT_STREQ(e.what(), "Element is not an object");
1851 }
1852
1853 // Test where fails: Invalid property specified
1854 try
1855 {
1856 const json element = R"(
1857 {
1858 "id": "vdd_regulator",
1859 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001860 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001861 "i2c_interface": { "bus": 1, "address": "0x70" },
1862 "foo" : true
1863 }
1864 )"_json;
1865 parseDevice(element);
1866 ADD_FAILURE() << "Should not have reached this line.";
1867 }
1868 catch (const std::invalid_argument& e)
1869 {
1870 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1871 }
1872}
1873
1874TEST(ConfigFileParserTests, ParseDeviceArray)
1875{
1876 // Test where works
1877 {
1878 const json element = R"(
1879 [
1880 {
1881 "id": "vdd_regulator",
1882 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001883 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001884 "i2c_interface": { "bus": 1, "address": "0x70" }
1885 },
1886 {
1887 "id": "vio_regulator",
1888 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001889 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001890 "i2c_interface": { "bus": 1, "address": "0x71" }
1891 }
1892 ]
1893 )"_json;
1894 std::vector<std::unique_ptr<Device>> devices =
1895 parseDeviceArray(element);
1896 EXPECT_EQ(devices.size(), 2);
1897 EXPECT_EQ(devices[0]->getID(), "vdd_regulator");
1898 EXPECT_EQ(devices[1]->getID(), "vio_regulator");
1899 }
1900
1901 // Test where fails: Element is not an array
1902 try
1903 {
1904 const json element = R"(
1905 {
1906 "foo": "bar"
1907 }
1908 )"_json;
1909 parseDeviceArray(element);
1910 ADD_FAILURE() << "Should not have reached this line.";
1911 }
1912 catch (const std::invalid_argument& e)
1913 {
1914 EXPECT_STREQ(e.what(), "Element is not an array");
1915 }
1916}
1917
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001918TEST(ConfigFileParserTests, ParseDouble)
1919{
1920 // Test where works: floating point value
1921 {
1922 const json element = R"( 1.03 )"_json;
1923 double value = parseDouble(element);
1924 EXPECT_EQ(value, 1.03);
1925 }
1926
1927 // Test where works: integer value
1928 {
1929 const json element = R"( 24 )"_json;
1930 double value = parseDouble(element);
1931 EXPECT_EQ(value, 24.0);
1932 }
1933
1934 // Test where fails: Element is not a number
1935 try
1936 {
1937 const json element = R"( true )"_json;
1938 parseDouble(element);
1939 ADD_FAILURE() << "Should not have reached this line.";
1940 }
1941 catch (const std::invalid_argument& e)
1942 {
1943 EXPECT_STREQ(e.what(), "Element is not a number");
1944 }
1945}
1946
Bob Kingbafcb862020-03-31 16:39:00 +08001947TEST(ConfigFileParserTests, ParseHexByte)
1948{
1949 // Test where works: "0xFF"
1950 {
1951 const json element = R"( "0xFF" )"_json;
1952 uint8_t value = parseHexByte(element);
1953 EXPECT_EQ(value, 0xFF);
1954 }
1955
1956 // Test where works: "0xff"
1957 {
1958 const json element = R"( "0xff" )"_json;
1959 uint8_t value = parseHexByte(element);
1960 EXPECT_EQ(value, 0xff);
1961 }
1962
1963 // Test where works: "0xf"
1964 {
1965 const json element = R"( "0xf" )"_json;
1966 uint8_t value = parseHexByte(element);
1967 EXPECT_EQ(value, 0xf);
1968 }
1969
1970 // Test where fails: "0xfff"
1971 try
1972 {
1973 const json element = R"( "0xfff" )"_json;
1974 parseHexByte(element);
1975 ADD_FAILURE() << "Should not have reached this line.";
1976 }
1977 catch (const std::invalid_argument& e)
1978 {
1979 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1980 }
1981
1982 // Test where fails: "0xAG"
1983 try
1984 {
1985 const json element = R"( "0xAG" )"_json;
1986 parseHexByte(element);
1987 ADD_FAILURE() << "Should not have reached this line.";
1988 }
1989 catch (const std::invalid_argument& e)
1990 {
1991 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1992 }
1993
1994 // Test where fails: "ff"
1995 try
1996 {
1997 const json element = R"( "ff" )"_json;
1998 parseHexByte(element);
1999 ADD_FAILURE() << "Should not have reached this line.";
2000 }
2001 catch (const std::invalid_argument& e)
2002 {
2003 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2004 }
2005
2006 // Test where fails: ""
2007 try
2008 {
2009 const json element = "";
2010 parseHexByte(element);
2011 ADD_FAILURE() << "Should not have reached this line.";
2012 }
2013 catch (const std::invalid_argument& e)
2014 {
2015 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2016 }
2017
2018 // Test where fails: "f"
2019 try
2020 {
2021 const json element = R"( "f" )"_json;
2022 parseHexByte(element);
2023 ADD_FAILURE() << "Should not have reached this line.";
2024 }
2025 catch (const std::invalid_argument& e)
2026 {
2027 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2028 }
2029
2030 // Test where fails: "0x"
2031 try
2032 {
2033 const json element = R"( "0x" )"_json;
2034 parseHexByte(element);
2035 ADD_FAILURE() << "Should not have reached this line.";
2036 }
2037 catch (const std::invalid_argument& e)
2038 {
2039 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2040 }
2041
2042 // Test where fails: "0Xff"
2043 try
2044 {
2045 const json element = R"( "0XFF" )"_json;
2046 parseHexByte(element);
2047 ADD_FAILURE() << "Should not have reached this line.";
2048 }
2049 catch (const std::invalid_argument& e)
2050 {
2051 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2052 }
2053}
2054
2055TEST(ConfigFileParserTests, ParseHexByteArray)
2056{
2057 // Test where works
2058 {
2059 const json element = R"( [ "0xCC", "0xFF" ] )"_json;
2060 std::vector<uint8_t> hexBytes = parseHexByteArray(element);
2061 std::vector<uint8_t> expected = {0xcc, 0xff};
2062 EXPECT_EQ(hexBytes, expected);
2063 }
2064
2065 // Test where fails: Element is not an array
2066 try
2067 {
2068 const json element = 0;
2069 parseHexByteArray(element);
2070 ADD_FAILURE() << "Should not have reached this line.";
2071 }
2072 catch (const std::invalid_argument& e)
2073 {
2074 EXPECT_STREQ(e.what(), "Element is not an array");
2075 }
2076}
2077
Shawn McCarney91f87a52021-09-07 09:59:57 -05002078TEST(ConfigFileParserTests, ParseI2CCaptureBytes)
2079{
2080 // Test where works
2081 {
2082 const json element = R"(
2083 {
2084 "register": "0xA0",
2085 "count": 2
2086 }
2087 )"_json;
2088 std::unique_ptr<I2CCaptureBytesAction> action =
2089 parseI2CCaptureBytes(element);
2090 EXPECT_EQ(action->getRegister(), 0xA0);
2091 EXPECT_EQ(action->getCount(), 2);
2092 }
2093
2094 // Test where fails: Element is not an object
2095 try
2096 {
2097 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2098 parseI2CCaptureBytes(element);
2099 ADD_FAILURE() << "Should not have reached this line.";
2100 }
2101 catch (const std::invalid_argument& e)
2102 {
2103 EXPECT_STREQ(e.what(), "Element is not an object");
2104 }
2105
2106 // Test where fails: register value is invalid
2107 try
2108 {
2109 const json element = R"(
2110 {
2111 "register": "0x0Z",
2112 "count": 2
2113 }
2114 )"_json;
2115 parseI2CCaptureBytes(element);
2116 ADD_FAILURE() << "Should not have reached this line.";
2117 }
2118 catch (const std::invalid_argument& e)
2119 {
2120 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2121 }
2122
2123 // Test where fails: count value is invalid
2124 try
2125 {
2126 const json element = R"(
2127 {
2128 "register": "0xA0",
2129 "count": 0
2130 }
2131 )"_json;
2132 parseI2CCaptureBytes(element);
2133 ADD_FAILURE() << "Should not have reached this line.";
2134 }
2135 catch (const std::invalid_argument& e)
2136 {
2137 EXPECT_STREQ(e.what(), "Invalid byte count: Must be > 0");
2138 }
2139
2140 // Test where fails: Required register property not specified
2141 try
2142 {
2143 const json element = R"(
2144 {
2145 "count": 2
2146 }
2147 )"_json;
2148 parseI2CCaptureBytes(element);
2149 ADD_FAILURE() << "Should not have reached this line.";
2150 }
2151 catch (const std::invalid_argument& e)
2152 {
2153 EXPECT_STREQ(e.what(), "Required property missing: register");
2154 }
2155
2156 // Test where fails: Required count property not specified
2157 try
2158 {
2159 const json element = R"(
2160 {
2161 "register": "0xA0"
2162 }
2163 )"_json;
2164 parseI2CCaptureBytes(element);
2165 ADD_FAILURE() << "Should not have reached this line.";
2166 }
2167 catch (const std::invalid_argument& e)
2168 {
2169 EXPECT_STREQ(e.what(), "Required property missing: count");
2170 }
2171
2172 // Test where fails: Invalid property specified
2173 try
2174 {
2175 const json element = R"(
2176 {
2177 "register": "0xA0",
2178 "count": 2,
2179 "foo": 3
2180 }
2181 )"_json;
2182 parseI2CCaptureBytes(element);
2183 ADD_FAILURE() << "Should not have reached this line.";
2184 }
2185 catch (const std::invalid_argument& e)
2186 {
2187 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2188 }
2189}
2190
Bob Kingf09bfe02020-04-13 17:21:15 +08002191TEST(ConfigFileParserTests, ParseI2CCompareBit)
2192{
2193 // Test where works
2194 {
2195 const json element = R"(
2196 {
2197 "register": "0xA0",
2198 "position": 3,
2199 "value": 0
2200 }
2201 )"_json;
2202 std::unique_ptr<I2CCompareBitAction> action =
2203 parseI2CCompareBit(element);
2204 EXPECT_EQ(action->getRegister(), 0xA0);
2205 EXPECT_EQ(action->getPosition(), 3);
2206 EXPECT_EQ(action->getValue(), 0);
2207 }
2208
2209 // Test where fails: Invalid property specified
2210 try
2211 {
2212 const json element = R"(
2213 {
2214 "register": "0xA0",
2215 "position": 3,
2216 "value": 0,
2217 "foo": 3
2218 }
2219 )"_json;
2220 parseI2CCompareBit(element);
2221 ADD_FAILURE() << "Should not have reached this line.";
2222 }
2223 catch (const std::invalid_argument& e)
2224 {
2225 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2226 }
2227
2228 // Test where fails: Element is not an object
2229 try
2230 {
2231 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2232 parseI2CCompareBit(element);
2233 ADD_FAILURE() << "Should not have reached this line.";
2234 }
2235 catch (const std::invalid_argument& e)
2236 {
2237 EXPECT_STREQ(e.what(), "Element is not an object");
2238 }
2239
2240 // Test where fails: register value is invalid
2241 try
2242 {
2243 const json element = R"(
2244 {
2245 "register": "0xAG",
2246 "position": 3,
2247 "value": 0
2248 }
2249 )"_json;
2250 parseI2CCompareBit(element);
2251 ADD_FAILURE() << "Should not have reached this line.";
2252 }
2253 catch (const std::invalid_argument& e)
2254 {
2255 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2256 }
2257
2258 // Test where fails: position value is invalid
2259 try
2260 {
2261 const json element = R"(
2262 {
2263 "register": "0xA0",
2264 "position": 8,
2265 "value": 0
2266 }
2267 )"_json;
2268 parseI2CCompareBit(element);
2269 ADD_FAILURE() << "Should not have reached this line.";
2270 }
2271 catch (const std::invalid_argument& e)
2272 {
2273 EXPECT_STREQ(e.what(), "Element is not a bit position");
2274 }
2275
2276 // Test where fails: value value is invalid
2277 try
2278 {
2279 const json element = R"(
2280 {
2281 "register": "0xA0",
2282 "position": 3,
2283 "value": 2
2284 }
2285 )"_json;
2286 parseI2CCompareBit(element);
2287 ADD_FAILURE() << "Should not have reached this line.";
2288 }
2289 catch (const std::invalid_argument& e)
2290 {
2291 EXPECT_STREQ(e.what(), "Element is not a bit value");
2292 }
2293
2294 // Test where fails: Required register property not specified
2295 try
2296 {
2297 const json element = R"(
2298 {
2299 "position": 3,
2300 "value": 0
2301 }
2302 )"_json;
2303 parseI2CCompareBit(element);
2304 ADD_FAILURE() << "Should not have reached this line.";
2305 }
2306 catch (const std::invalid_argument& e)
2307 {
2308 EXPECT_STREQ(e.what(), "Required property missing: register");
2309 }
2310
2311 // Test where fails: Required position property not specified
2312 try
2313 {
2314 const json element = R"(
2315 {
2316 "register": "0xA0",
2317 "value": 0
2318 }
2319 )"_json;
2320 parseI2CCompareBit(element);
2321 ADD_FAILURE() << "Should not have reached this line.";
2322 }
2323 catch (const std::invalid_argument& e)
2324 {
2325 EXPECT_STREQ(e.what(), "Required property missing: position");
2326 }
2327
2328 // Test where fails: Required value property not specified
2329 try
2330 {
2331 const json element = R"(
2332 {
2333 "register": "0xA0",
2334 "position": 3
2335 }
2336 )"_json;
2337 parseI2CCompareBit(element);
2338 ADD_FAILURE() << "Should not have reached this line.";
2339 }
2340 catch (const std::invalid_argument& e)
2341 {
2342 EXPECT_STREQ(e.what(), "Required property missing: value");
2343 }
2344}
2345
2346TEST(ConfigFileParserTests, ParseI2CCompareByte)
2347{
2348 // Test where works: Only required properties specified
2349 {
2350 const json element = R"(
2351 {
2352 "register": "0x0A",
2353 "value": "0xCC"
2354 }
2355 )"_json;
2356 std::unique_ptr<I2CCompareByteAction> action =
2357 parseI2CCompareByte(element);
2358 EXPECT_EQ(action->getRegister(), 0x0A);
2359 EXPECT_EQ(action->getValue(), 0xCC);
2360 EXPECT_EQ(action->getMask(), 0xFF);
2361 }
2362
2363 // Test where works: All properties specified
2364 {
2365 const json element = R"(
2366 {
2367 "register": "0x0A",
2368 "value": "0xCC",
2369 "mask": "0xF7"
2370 }
2371 )"_json;
2372 std::unique_ptr<I2CCompareByteAction> action =
2373 parseI2CCompareByte(element);
2374 EXPECT_EQ(action->getRegister(), 0x0A);
2375 EXPECT_EQ(action->getValue(), 0xCC);
2376 EXPECT_EQ(action->getMask(), 0xF7);
2377 }
2378
2379 // Test where fails: Element is not an object
2380 try
2381 {
2382 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2383 parseI2CCompareByte(element);
2384 ADD_FAILURE() << "Should not have reached this line.";
2385 }
2386 catch (const std::invalid_argument& e)
2387 {
2388 EXPECT_STREQ(e.what(), "Element is not an object");
2389 }
2390
2391 // Test where fails: Invalid property specified
2392 try
2393 {
2394 const json element = R"(
2395 {
2396 "register": "0x0A",
2397 "value": "0xCC",
2398 "mask": "0xF7",
2399 "foo": 1
2400 }
2401 )"_json;
2402 parseI2CCompareByte(element);
2403 ADD_FAILURE() << "Should not have reached this line.";
2404 }
2405 catch (const std::invalid_argument& e)
2406 {
2407 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2408 }
2409
2410 // Test where fails: register value is invalid
2411 try
2412 {
2413 const json element = R"(
2414 {
2415 "register": "0x0Z",
2416 "value": "0xCC",
2417 "mask": "0xF7"
2418 }
2419 )"_json;
2420 parseI2CCompareByte(element);
2421 ADD_FAILURE() << "Should not have reached this line.";
2422 }
2423 catch (const std::invalid_argument& e)
2424 {
2425 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2426 }
2427
2428 // Test where fails: value value is invalid
2429 try
2430 {
2431 const json element = R"(
2432 {
2433 "register": "0x0A",
2434 "value": "0xCCC",
2435 "mask": "0xF7"
2436 }
2437 )"_json;
2438 parseI2CCompareByte(element);
2439 ADD_FAILURE() << "Should not have reached this line.";
2440 }
2441 catch (const std::invalid_argument& e)
2442 {
2443 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2444 }
2445
2446 // Test where fails: mask value is invalid
2447 try
2448 {
2449 const json element = R"(
2450 {
2451 "register": "0x0A",
2452 "value": "0xCC",
2453 "mask": "F7"
2454 }
2455 )"_json;
2456 parseI2CCompareByte(element);
2457 ADD_FAILURE() << "Should not have reached this line.";
2458 }
2459 catch (const std::invalid_argument& e)
2460 {
2461 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2462 }
2463
2464 // Test where fails: Required register property not specified
2465 try
2466 {
2467 const json element = R"(
2468 {
2469 "value": "0xCC",
2470 "mask": "0xF7"
2471 }
2472 )"_json;
2473 parseI2CCompareByte(element);
2474 ADD_FAILURE() << "Should not have reached this line.";
2475 }
2476 catch (const std::invalid_argument& e)
2477 {
2478 EXPECT_STREQ(e.what(), "Required property missing: register");
2479 }
2480
2481 // Test where fails: Required value property not specified
2482 try
2483 {
2484 const json element = R"(
2485 {
2486 "register": "0x0A",
2487 "mask": "0xF7"
2488 }
2489 )"_json;
2490 parseI2CCompareByte(element);
2491 ADD_FAILURE() << "Should not have reached this line.";
2492 }
2493 catch (const std::invalid_argument& e)
2494 {
2495 EXPECT_STREQ(e.what(), "Required property missing: value");
2496 }
2497}
2498
2499TEST(ConfigFileParserTests, ParseI2CCompareBytes)
2500{
2501 // Test where works: Only required properties specified
2502 {
2503 const json element = R"(
2504 {
2505 "register": "0x0A",
2506 "values": [ "0xCC", "0xFF" ]
2507 }
2508 )"_json;
2509 std::unique_ptr<I2CCompareBytesAction> action =
2510 parseI2CCompareBytes(element);
2511 EXPECT_EQ(action->getRegister(), 0x0A);
2512 EXPECT_EQ(action->getValues().size(), 2);
2513 EXPECT_EQ(action->getValues()[0], 0xCC);
2514 EXPECT_EQ(action->getValues()[1], 0xFF);
2515 EXPECT_EQ(action->getMasks().size(), 2);
2516 EXPECT_EQ(action->getMasks()[0], 0xFF);
2517 EXPECT_EQ(action->getMasks()[1], 0xFF);
2518 }
2519
2520 // Test where works: All properties specified
2521 {
2522 const json element = R"(
2523 {
2524 "register": "0x0A",
2525 "values": [ "0xCC", "0xFF" ],
2526 "masks": [ "0x7F", "0x77" ]
2527 }
2528 )"_json;
2529 std::unique_ptr<I2CCompareBytesAction> action =
2530 parseI2CCompareBytes(element);
2531 EXPECT_EQ(action->getRegister(), 0x0A);
2532 EXPECT_EQ(action->getValues().size(), 2);
2533 EXPECT_EQ(action->getValues()[0], 0xCC);
2534 EXPECT_EQ(action->getValues()[1], 0xFF);
2535 EXPECT_EQ(action->getMasks().size(), 2);
2536 EXPECT_EQ(action->getMasks()[0], 0x7F);
2537 EXPECT_EQ(action->getMasks()[1], 0x77);
2538 }
2539
2540 // Test where fails: Element is not an object
2541 try
2542 {
2543 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2544 parseI2CCompareBytes(element);
2545 ADD_FAILURE() << "Should not have reached this line.";
2546 }
2547 catch (const std::invalid_argument& e)
2548 {
2549 EXPECT_STREQ(e.what(), "Element is not an object");
2550 }
2551
2552 // Test where fails: Invalid property specified
2553 try
2554 {
2555 const json element = R"(
2556 {
2557 "register": "0x0A",
2558 "values": [ "0xCC", "0xFF" ],
2559 "masks": [ "0x7F", "0x7F" ],
2560 "foo": 1
2561 }
2562 )"_json;
2563 parseI2CCompareBytes(element);
2564 ADD_FAILURE() << "Should not have reached this line.";
2565 }
2566 catch (const std::invalid_argument& e)
2567 {
2568 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2569 }
2570
2571 // Test where fails: register value is invalid
2572 try
2573 {
2574 const json element = R"(
2575 {
2576 "register": "0x0Z",
2577 "values": [ "0xCC", "0xFF" ],
2578 "masks": [ "0x7F", "0x7F" ]
2579 }
2580 )"_json;
2581 parseI2CCompareBytes(element);
2582 ADD_FAILURE() << "Should not have reached this line.";
2583 }
2584 catch (const std::invalid_argument& e)
2585 {
2586 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2587 }
2588
2589 // Test where fails: values value is invalid
2590 try
2591 {
2592 const json element = R"(
2593 {
2594 "register": "0x0A",
2595 "values": [ "0xCCC", "0xFF" ],
2596 "masks": [ "0x7F", "0x7F" ]
2597 }
2598 )"_json;
2599 parseI2CCompareBytes(element);
2600 ADD_FAILURE() << "Should not have reached this line.";
2601 }
2602 catch (const std::invalid_argument& e)
2603 {
2604 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2605 }
2606
2607 // Test where fails: masks value is invalid
2608 try
2609 {
2610 const json element = R"(
2611 {
2612 "register": "0x0A",
2613 "values": [ "0xCC", "0xFF" ],
2614 "masks": [ "F", "0x7F" ]
2615 }
2616 )"_json;
2617 parseI2CCompareBytes(element);
2618 ADD_FAILURE() << "Should not have reached this line.";
2619 }
2620 catch (const std::invalid_argument& e)
2621 {
2622 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2623 }
2624
2625 // Test where fails: number of elements in masks is invalid
2626 try
2627 {
2628 const json element = R"(
2629 {
2630 "register": "0x0A",
2631 "values": [ "0xCC", "0xFF" ],
2632 "masks": [ "0x7F" ]
2633 }
2634 )"_json;
2635 parseI2CCompareBytes(element);
2636 ADD_FAILURE() << "Should not have reached this line.";
2637 }
2638 catch (const std::invalid_argument& e)
2639 {
2640 EXPECT_STREQ(e.what(), "Invalid number of elements in masks");
2641 }
2642
2643 // Test where fails: Required register property not specified
2644 try
2645 {
2646 const json element = R"(
2647 {
2648 "values": [ "0xCC", "0xFF" ]
2649 }
2650 )"_json;
2651 parseI2CCompareBytes(element);
2652 ADD_FAILURE() << "Should not have reached this line.";
2653 }
2654 catch (const std::invalid_argument& e)
2655 {
2656 EXPECT_STREQ(e.what(), "Required property missing: register");
2657 }
2658
2659 // Test where fails: Required values property not specified
2660 try
2661 {
2662 const json element = R"(
2663 {
2664 "register": "0x0A"
2665 }
2666 )"_json;
2667 parseI2CCompareBytes(element);
2668 ADD_FAILURE() << "Should not have reached this line.";
2669 }
2670 catch (const std::invalid_argument& e)
2671 {
2672 EXPECT_STREQ(e.what(), "Required property missing: values");
2673 }
2674}
2675
Bob Kingf617f892020-03-30 19:03:35 +08002676TEST(ConfigFileParserTests, ParseI2CWriteBit)
2677{
2678 // Test where works
2679 {
2680 const json element = R"(
2681 {
2682 "register": "0xA0",
2683 "position": 3,
2684 "value": 0
2685 }
2686 )"_json;
2687 std::unique_ptr<I2CWriteBitAction> action = parseI2CWriteBit(element);
2688 EXPECT_EQ(action->getRegister(), 0xA0);
2689 EXPECT_EQ(action->getPosition(), 3);
2690 EXPECT_EQ(action->getValue(), 0);
2691 }
2692
2693 // Test where fails: Invalid property specified
2694 try
2695 {
2696 const json element = R"(
2697 {
2698 "register": "0xA0",
2699 "position": 3,
2700 "value": 0,
2701 "foo": 3
2702 }
2703 )"_json;
2704 parseI2CWriteBit(element);
2705 ADD_FAILURE() << "Should not have reached this line.";
2706 }
2707 catch (const std::invalid_argument& e)
2708 {
2709 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2710 }
2711
2712 // Test where fails: Element is not an object
2713 try
2714 {
2715 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2716 parseI2CWriteBit(element);
2717 ADD_FAILURE() << "Should not have reached this line.";
2718 }
2719 catch (const std::invalid_argument& e)
2720 {
2721 EXPECT_STREQ(e.what(), "Element is not an object");
2722 }
2723
2724 // Test where fails: register value is invalid
2725 try
2726 {
2727 const json element = R"(
2728 {
2729 "register": "0xAG",
2730 "position": 3,
2731 "value": 0
2732 }
2733 )"_json;
2734 parseI2CWriteBit(element);
2735 ADD_FAILURE() << "Should not have reached this line.";
2736 }
2737 catch (const std::invalid_argument& e)
2738 {
2739 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2740 }
2741
2742 // Test where fails: position value is invalid
2743 try
2744 {
2745 const json element = R"(
2746 {
2747 "register": "0xA0",
2748 "position": 8,
2749 "value": 0
2750 }
2751 )"_json;
2752 parseI2CWriteBit(element);
2753 ADD_FAILURE() << "Should not have reached this line.";
2754 }
2755 catch (const std::invalid_argument& e)
2756 {
2757 EXPECT_STREQ(e.what(), "Element is not a bit position");
2758 }
2759
2760 // Test where fails: value value is invalid
2761 try
2762 {
2763 const json element = R"(
2764 {
2765 "register": "0xA0",
2766 "position": 3,
2767 "value": 2
2768 }
2769 )"_json;
2770 parseI2CWriteBit(element);
2771 ADD_FAILURE() << "Should not have reached this line.";
2772 }
2773 catch (const std::invalid_argument& e)
2774 {
2775 EXPECT_STREQ(e.what(), "Element is not a bit value");
2776 }
2777
2778 // Test where fails: Required register property not specified
2779 try
2780 {
2781 const json element = R"(
2782 {
2783 "position": 3,
2784 "value": 0
2785 }
2786 )"_json;
2787 parseI2CWriteBit(element);
2788 ADD_FAILURE() << "Should not have reached this line.";
2789 }
2790 catch (const std::invalid_argument& e)
2791 {
2792 EXPECT_STREQ(e.what(), "Required property missing: register");
2793 }
2794
2795 // Test where fails: Required position property not specified
2796 try
2797 {
2798 const json element = R"(
2799 {
2800 "register": "0xA0",
2801 "value": 0
2802 }
2803 )"_json;
2804 parseI2CWriteBit(element);
2805 ADD_FAILURE() << "Should not have reached this line.";
2806 }
2807 catch (const std::invalid_argument& e)
2808 {
2809 EXPECT_STREQ(e.what(), "Required property missing: position");
2810 }
2811
2812 // Test where fails: Required value property not specified
2813 try
2814 {
2815 const json element = R"(
2816 {
2817 "register": "0xA0",
2818 "position": 3
2819 }
2820 )"_json;
2821 parseI2CWriteBit(element);
2822 ADD_FAILURE() << "Should not have reached this line.";
2823 }
2824 catch (const std::invalid_argument& e)
2825 {
2826 EXPECT_STREQ(e.what(), "Required property missing: value");
2827 }
2828}
2829
Bob King87ff9d72020-03-31 14:02:55 +08002830TEST(ConfigFileParserTests, ParseI2CWriteByte)
2831{
2832 // Test where works: Only required properties specified
2833 {
2834 const json element = R"(
2835 {
2836 "register": "0x0A",
2837 "value": "0xCC"
2838 }
2839 )"_json;
2840 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element);
2841 EXPECT_EQ(action->getRegister(), 0x0A);
2842 EXPECT_EQ(action->getValue(), 0xCC);
2843 EXPECT_EQ(action->getMask(), 0xFF);
2844 }
2845
2846 // Test where works: All properties specified
2847 {
2848 const json element = R"(
2849 {
2850 "register": "0x0A",
2851 "value": "0xCC",
2852 "mask": "0xF7"
2853 }
2854 )"_json;
2855 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element);
2856 EXPECT_EQ(action->getRegister(), 0x0A);
2857 EXPECT_EQ(action->getValue(), 0xCC);
2858 EXPECT_EQ(action->getMask(), 0xF7);
2859 }
2860
2861 // Test where fails: Element is not an object
2862 try
2863 {
2864 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2865 parseI2CWriteByte(element);
2866 ADD_FAILURE() << "Should not have reached this line.";
2867 }
2868 catch (const std::invalid_argument& e)
2869 {
2870 EXPECT_STREQ(e.what(), "Element is not an object");
2871 }
2872
2873 // Test where fails: Invalid property specified
2874 try
2875 {
2876 const json element = R"(
2877 {
2878 "register": "0x0A",
2879 "value": "0xCC",
2880 "mask": "0xF7",
2881 "foo": 1
2882 }
2883 )"_json;
2884 parseI2CWriteByte(element);
2885 ADD_FAILURE() << "Should not have reached this line.";
2886 }
2887 catch (const std::invalid_argument& e)
2888 {
2889 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2890 }
2891
2892 // Test where fails: register value is invalid
2893 try
2894 {
2895 const json element = R"(
2896 {
2897 "register": "0x0Z",
2898 "value": "0xCC",
2899 "mask": "0xF7"
2900 }
2901 )"_json;
2902 parseI2CWriteByte(element);
2903 ADD_FAILURE() << "Should not have reached this line.";
2904 }
2905 catch (const std::invalid_argument& e)
2906 {
2907 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2908 }
2909
2910 // Test where fails: value value is invalid
2911 try
2912 {
2913 const json element = R"(
2914 {
2915 "register": "0x0A",
2916 "value": "0xCCC",
2917 "mask": "0xF7"
2918 }
2919 )"_json;
2920 parseI2CWriteByte(element);
2921 ADD_FAILURE() << "Should not have reached this line.";
2922 }
2923 catch (const std::invalid_argument& e)
2924 {
2925 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2926 }
2927
2928 // Test where fails: mask value is invalid
2929 try
2930 {
2931 const json element = R"(
2932 {
2933 "register": "0x0A",
2934 "value": "0xCC",
2935 "mask": "F7"
2936 }
2937 )"_json;
2938 parseI2CWriteByte(element);
2939 ADD_FAILURE() << "Should not have reached this line.";
2940 }
2941 catch (const std::invalid_argument& e)
2942 {
2943 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2944 }
2945
2946 // Test where fails: Required register property not specified
2947 try
2948 {
2949 const json element = R"(
2950 {
2951 "value": "0xCC",
2952 "mask": "0xF7"
2953 }
2954 )"_json;
2955 parseI2CWriteByte(element);
2956 ADD_FAILURE() << "Should not have reached this line.";
2957 }
2958 catch (const std::invalid_argument& e)
2959 {
2960 EXPECT_STREQ(e.what(), "Required property missing: register");
2961 }
2962
2963 // Test where fails: Required value property not specified
2964 try
2965 {
2966 const json element = R"(
2967 {
2968 "register": "0x0A",
2969 "mask": "0xF7"
2970 }
2971 )"_json;
2972 parseI2CWriteByte(element);
2973 ADD_FAILURE() << "Should not have reached this line.";
2974 }
2975 catch (const std::invalid_argument& e)
2976 {
2977 EXPECT_STREQ(e.what(), "Required property missing: value");
2978 }
2979}
2980
Bob Kingbafcb862020-03-31 16:39:00 +08002981TEST(ConfigFileParserTests, ParseI2CWriteBytes)
2982{
2983 // Test where works: Only required properties specified
2984 {
2985 const json element = R"(
2986 {
2987 "register": "0x0A",
2988 "values": [ "0xCC", "0xFF" ]
2989 }
2990 )"_json;
2991 std::unique_ptr<I2CWriteBytesAction> action =
2992 parseI2CWriteBytes(element);
2993 EXPECT_EQ(action->getRegister(), 0x0A);
2994 EXPECT_EQ(action->getValues().size(), 2);
2995 EXPECT_EQ(action->getValues()[0], 0xCC);
2996 EXPECT_EQ(action->getValues()[1], 0xFF);
2997 EXPECT_EQ(action->getMasks().size(), 0);
2998 }
2999
3000 // Test where works: All properties specified
3001 {
3002 const json element = R"(
3003 {
3004 "register": "0x0A",
3005 "values": [ "0xCC", "0xFF" ],
3006 "masks": [ "0x7F", "0x77" ]
3007 }
3008 )"_json;
3009 std::unique_ptr<I2CWriteBytesAction> action =
3010 parseI2CWriteBytes(element);
3011 EXPECT_EQ(action->getRegister(), 0x0A);
3012 EXPECT_EQ(action->getValues().size(), 2);
3013 EXPECT_EQ(action->getValues()[0], 0xCC);
3014 EXPECT_EQ(action->getValues()[1], 0xFF);
3015 EXPECT_EQ(action->getMasks().size(), 2);
3016 EXPECT_EQ(action->getMasks()[0], 0x7F);
3017 EXPECT_EQ(action->getMasks()[1], 0x77);
3018 }
3019
3020 // Test where fails: Element is not an object
3021 try
3022 {
3023 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3024 parseI2CWriteBytes(element);
3025 ADD_FAILURE() << "Should not have reached this line.";
3026 }
3027 catch (const std::invalid_argument& e)
3028 {
3029 EXPECT_STREQ(e.what(), "Element is not an object");
3030 }
3031
3032 // Test where fails: Invalid property specified
3033 try
3034 {
3035 const json element = R"(
3036 {
3037 "register": "0x0A",
3038 "values": [ "0xCC", "0xFF" ],
3039 "masks": [ "0x7F", "0x7F" ],
3040 "foo": 1
3041 }
3042 )"_json;
3043 parseI2CWriteBytes(element);
3044 ADD_FAILURE() << "Should not have reached this line.";
3045 }
3046 catch (const std::invalid_argument& e)
3047 {
3048 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3049 }
3050
3051 // Test where fails: register value is invalid
3052 try
3053 {
3054 const json element = R"(
3055 {
3056 "register": "0x0Z",
3057 "values": [ "0xCC", "0xFF" ],
3058 "masks": [ "0x7F", "0x7F" ]
3059 }
3060 )"_json;
3061 parseI2CWriteBytes(element);
3062 ADD_FAILURE() << "Should not have reached this line.";
3063 }
3064 catch (const std::invalid_argument& e)
3065 {
3066 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
3067 }
3068
3069 // Test where fails: values value is invalid
3070 try
3071 {
3072 const json element = R"(
3073 {
3074 "register": "0x0A",
3075 "values": [ "0xCCC", "0xFF" ],
3076 "masks": [ "0x7F", "0x7F" ]
3077 }
3078 )"_json;
3079 parseI2CWriteBytes(element);
3080 ADD_FAILURE() << "Should not have reached this line.";
3081 }
3082 catch (const std::invalid_argument& e)
3083 {
3084 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
3085 }
3086
3087 // Test where fails: masks value is invalid
3088 try
3089 {
3090 const json element = R"(
3091 {
3092 "register": "0x0A",
3093 "values": [ "0xCC", "0xFF" ],
3094 "masks": [ "F", "0x7F" ]
3095 }
3096 )"_json;
3097 parseI2CWriteBytes(element);
3098 ADD_FAILURE() << "Should not have reached this line.";
3099 }
3100 catch (const std::invalid_argument& e)
3101 {
3102 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
3103 }
3104
3105 // Test where fails: number of elements in masks is invalid
3106 try
3107 {
3108 const json element = R"(
3109 {
3110 "register": "0x0A",
3111 "values": [ "0xCC", "0xFF" ],
3112 "masks": [ "0x7F" ]
3113 }
3114 )"_json;
3115 parseI2CWriteBytes(element);
3116 ADD_FAILURE() << "Should not have reached this line.";
3117 }
3118 catch (const std::invalid_argument& e)
3119 {
3120 EXPECT_STREQ(e.what(), "Invalid number of elements in masks");
3121 }
3122
3123 // Test where fails: Required register property not specified
3124 try
3125 {
3126 const json element = R"(
3127 {
3128 "values": [ "0xCC", "0xFF" ]
3129 }
3130 )"_json;
3131 parseI2CWriteBytes(element);
3132 ADD_FAILURE() << "Should not have reached this line.";
3133 }
3134 catch (const std::invalid_argument& e)
3135 {
3136 EXPECT_STREQ(e.what(), "Required property missing: register");
3137 }
3138
3139 // Test where fails: Required values property not specified
3140 try
3141 {
3142 const json element = R"(
3143 {
3144 "register": "0x0A"
3145 }
3146 )"_json;
3147 parseI2CWriteBytes(element);
3148 ADD_FAILURE() << "Should not have reached this line.";
3149 }
3150 catch (const std::invalid_argument& e)
3151 {
3152 EXPECT_STREQ(e.what(), "Required property missing: values");
3153 }
3154}
3155
Bob King93a89d72020-04-15 15:11:11 +08003156TEST(ConfigFileParserTests, ParseIf)
3157{
3158 // Test where works: Only required properties specified
3159 {
3160 const json element = R"(
3161 {
3162 "condition": { "run_rule": "is_downlevel_regulator" },
3163 "then": [ { "run_rule": "configure_downlevel_regulator" },
3164 { "run_rule": "configure_standard_regulator" } ]
3165 }
3166 )"_json;
3167 std::unique_ptr<IfAction> action = parseIf(element);
3168 EXPECT_NE(action->getConditionAction().get(), nullptr);
3169 EXPECT_EQ(action->getThenActions().size(), 2);
3170 EXPECT_EQ(action->getElseActions().size(), 0);
3171 }
3172
3173 // Test where works: All properties specified
3174 {
3175 const json element = R"(
3176 {
3177 "condition": { "run_rule": "is_downlevel_regulator" },
3178 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
3179 "else": [ { "run_rule": "configure_standard_regulator" } ]
3180 }
3181 )"_json;
3182 std::unique_ptr<IfAction> action = parseIf(element);
3183 EXPECT_NE(action->getConditionAction().get(), nullptr);
3184 EXPECT_EQ(action->getThenActions().size(), 1);
3185 EXPECT_EQ(action->getElseActions().size(), 1);
3186 }
3187
3188 // Test where fails: Required condition property not specified
3189 try
3190 {
3191 const json element = R"(
3192 {
3193 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
3194 "else": [ { "run_rule": "configure_standard_regulator" } ]
3195 }
3196 )"_json;
3197 parseIf(element);
3198 ADD_FAILURE() << "Should not have reached this line.";
3199 }
3200 catch (const std::invalid_argument& e)
3201 {
3202 EXPECT_STREQ(e.what(), "Required property missing: condition");
3203 }
3204
3205 // Test where fails: Required then property not specified
3206 try
3207 {
3208 const json element = R"(
3209 {
3210 "condition": { "run_rule": "is_downlevel_regulator" },
3211 "else": [ { "run_rule": "configure_standard_regulator" } ]
3212 }
3213 )"_json;
3214 parseIf(element);
3215 ADD_FAILURE() << "Should not have reached this line.";
3216 }
3217 catch (const std::invalid_argument& e)
3218 {
3219 EXPECT_STREQ(e.what(), "Required property missing: then");
3220 }
3221
3222 // Test where fails: condition value is invalid
3223 try
3224 {
3225 const json element = R"(
3226 {
3227 "condition": 1,
3228 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
3229 "else": [ { "run_rule": "configure_standard_regulator" } ]
3230 }
3231 )"_json;
3232 parseIf(element);
3233 ADD_FAILURE() << "Should not have reached this line.";
3234 }
3235 catch (const std::invalid_argument& e)
3236 {
3237 EXPECT_STREQ(e.what(), "Element is not an object");
3238 }
3239
3240 // Test where fails: then value is invalid
3241 try
3242 {
3243 const json element = R"(
3244 {
3245 "condition": { "run_rule": "is_downlevel_regulator" },
3246 "then": "foo",
3247 "else": [ { "run_rule": "configure_standard_regulator" } ]
3248 }
3249 )"_json;
3250 parseIf(element);
3251 ADD_FAILURE() << "Should not have reached this line.";
3252 }
3253 catch (const std::invalid_argument& e)
3254 {
3255 EXPECT_STREQ(e.what(), "Element is not an array");
3256 }
3257
3258 // Test where fails: else value is invalid
3259 try
3260 {
3261 const json element = R"(
3262 {
3263 "condition": { "run_rule": "is_downlevel_regulator" },
3264 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
3265 "else": 1
3266 }
3267 )"_json;
3268 parseIf(element);
3269 ADD_FAILURE() << "Should not have reached this line.";
3270 }
3271 catch (const std::invalid_argument& e)
3272 {
3273 EXPECT_STREQ(e.what(), "Element is not an array");
3274 }
3275
3276 // Test where fails: Invalid property specified
3277 try
3278 {
3279 const json element = R"(
3280 {
3281 "condition": { "run_rule": "is_downlevel_regulator" },
3282 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
3283 "foo": "bar"
3284 }
3285 )"_json;
3286 parseIf(element);
3287 ADD_FAILURE() << "Should not have reached this line.";
3288 }
3289 catch (const std::invalid_argument& e)
3290 {
3291 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3292 }
3293
3294 // Test where fails: Element is not an object
3295 try
3296 {
3297 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3298 parseIf(element);
3299 ADD_FAILURE() << "Should not have reached this line.";
3300 }
3301 catch (const std::invalid_argument& e)
3302 {
3303 EXPECT_STREQ(e.what(), "Element is not an object");
3304 }
3305}
3306
Bob King87ff9d72020-03-31 14:02:55 +08003307TEST(ConfigFileParserTests, ParseInt8)
3308{
3309 // Test where works: INT8_MIN
3310 {
3311 const json element = R"( -128 )"_json;
3312 int8_t value = parseInt8(element);
3313 EXPECT_EQ(value, -128);
3314 }
3315
3316 // Test where works: INT8_MAX
3317 {
3318 const json element = R"( 127 )"_json;
3319 int8_t value = parseInt8(element);
3320 EXPECT_EQ(value, 127);
3321 }
3322
3323 // Test where fails: Element is not an integer
3324 try
3325 {
3326 const json element = R"( 1.03 )"_json;
3327 parseInt8(element);
3328 ADD_FAILURE() << "Should not have reached this line.";
3329 }
3330 catch (const std::invalid_argument& e)
3331 {
3332 EXPECT_STREQ(e.what(), "Element is not an integer");
3333 }
3334
3335 // Test where fails: Value < INT8_MIN
3336 try
3337 {
3338 const json element = R"( -129 )"_json;
3339 parseInt8(element);
3340 ADD_FAILURE() << "Should not have reached this line.";
3341 }
3342 catch (const std::invalid_argument& e)
3343 {
3344 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
3345 }
3346
3347 // Test where fails: Value > INT8_MAX
3348 try
3349 {
3350 const json element = R"( 128 )"_json;
3351 parseInt8(element);
3352 ADD_FAILURE() << "Should not have reached this line.";
3353 }
3354 catch (const std::invalid_argument& e)
3355 {
3356 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
3357 }
3358}
3359
Bob Kinga76898f2020-10-13 15:08:33 +08003360TEST(ConfigFileParserTests, ParseInventoryPath)
3361{
3362 // Test where works: Inventory path has a leading '/'
3363 {
3364 const json element = "/system/chassis/motherboard/cpu3";
3365 std::string value = parseInventoryPath(element);
3366 EXPECT_EQ(
3367 value,
3368 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3");
3369 }
3370
3371 // Test where works: Inventory path does not have a leading '/'
3372 {
3373 const json element = "system/chassis/motherboard/cpu1";
3374 std::string value = parseInventoryPath(element);
3375 EXPECT_EQ(
3376 value,
3377 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1");
3378 }
3379
3380 // Test where fails: JSON element is not a string
3381 try
3382 {
3383 const json element = R"( { "foo": "bar" } )"_json;
3384 parseInventoryPath(element);
3385 ADD_FAILURE() << "Should not have reached this line.";
3386 }
3387 catch (const std::invalid_argument& e)
3388 {
3389 EXPECT_STREQ(e.what(), "Element is not a string");
3390 }
3391
3392 // Test where fails: JSON element contains an empty string
3393 try
3394 {
3395 const json element = "";
3396 parseInventoryPath(element);
3397 ADD_FAILURE() << "Should not have reached this line.";
3398 }
3399 catch (const std::invalid_argument& e)
3400 {
3401 EXPECT_STREQ(e.what(), "Element contains an empty string");
3402 }
3403}
3404
Shawn McCarney11157852021-09-07 14:04:36 -05003405TEST(ConfigFileParserTests, ParseLogPhaseFault)
3406{
3407 // Test where works
3408 {
3409 const json element = R"(
3410 {
3411 "type": "n+1"
3412 }
3413 )"_json;
3414 std::unique_ptr<LogPhaseFaultAction> action =
3415 parseLogPhaseFault(element);
3416 EXPECT_EQ(action->getType(), PhaseFaultType::n_plus_1);
3417 }
3418
3419 // Test where fails: Element is not an object
3420 try
3421 {
3422 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3423 parseLogPhaseFault(element);
3424 ADD_FAILURE() << "Should not have reached this line.";
3425 }
3426 catch (const std::invalid_argument& e)
3427 {
3428 EXPECT_STREQ(e.what(), "Element is not an object");
3429 }
3430
3431 // Test where fails: Required type property not specified
3432 try
3433 {
3434 const json element = R"(
3435 {
3436 }
3437 )"_json;
3438 parseLogPhaseFault(element);
3439 ADD_FAILURE() << "Should not have reached this line.";
3440 }
3441 catch (const std::invalid_argument& e)
3442 {
3443 EXPECT_STREQ(e.what(), "Required property missing: type");
3444 }
3445
3446 // Test where fails: type value is invalid
3447 try
3448 {
3449 const json element = R"(
3450 {
3451 "type": "n+2"
3452 }
3453 )"_json;
3454 parseLogPhaseFault(element);
3455 ADD_FAILURE() << "Should not have reached this line.";
3456 }
3457 catch (const std::invalid_argument& e)
3458 {
3459 EXPECT_STREQ(e.what(), "Element is not a phase fault type");
3460 }
3461
3462 // Test where fails: Invalid property specified
3463 try
3464 {
3465 const json element = R"(
3466 {
3467 "type": "n+1",
3468 "foo": 1
3469 }
3470 )"_json;
3471 parseLogPhaseFault(element);
3472 ADD_FAILURE() << "Should not have reached this line.";
3473 }
3474 catch (const std::invalid_argument& e)
3475 {
3476 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3477 }
3478}
3479
Bob Kingf1b58dc2020-04-14 14:53:10 +08003480TEST(ConfigFileParserTests, ParseNot)
3481{
3482 // Test where works
3483 {
3484 const json element = R"(
3485 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }
3486 )"_json;
3487 std::unique_ptr<NotAction> action = parseNot(element);
3488 EXPECT_NE(action->getAction().get(), nullptr);
3489 }
3490
3491 // Test where fails: Element is not an object
3492 try
3493 {
3494 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3495 parseNot(element);
3496 ADD_FAILURE() << "Should not have reached this line.";
3497 }
3498 catch (const std::invalid_argument& e)
3499 {
3500 EXPECT_STREQ(e.what(), "Element is not an object");
3501 }
3502}
3503
Bob King0b51a9b2020-04-15 13:24:18 +08003504TEST(ConfigFileParserTests, ParseOr)
3505{
3506 // Test where works: Element is an array with 2 actions
3507 {
3508 const json element = R"(
3509 [
3510 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
3511 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
3512 ]
3513 )"_json;
3514 std::unique_ptr<OrAction> action = parseOr(element);
3515 EXPECT_EQ(action->getActions().size(), 2);
3516 }
3517
3518 // Test where fails: Element is an array with 1 action
3519 try
3520 {
3521 const json element = R"(
3522 [
3523 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }
3524 ]
3525 )"_json;
3526 parseOr(element);
3527 ADD_FAILURE() << "Should not have reached this line.";
3528 }
3529 catch (const std::invalid_argument& e)
3530 {
3531 EXPECT_STREQ(e.what(), "Array must contain two or more actions");
3532 }
3533
3534 // Test where fails: Element is not an array
3535 try
3536 {
3537 const json element = R"(
3538 {
3539 "foo": "bar"
3540 }
3541 )"_json;
3542 parseOr(element);
3543 ADD_FAILURE() << "Should not have reached this line.";
3544 }
3545 catch (const std::invalid_argument& e)
3546 {
3547 EXPECT_STREQ(e.what(), "Element is not an array");
3548 }
3549}
3550
Shawn McCarney39eb08a2021-09-07 16:34:49 -05003551TEST(ConfigFileParserTests, ParsePhaseFaultDetection)
3552{
3553 // Test where works: actions specified: optional properties not specified
3554 {
3555 const json element = R"(
3556 {
3557 "actions": [
3558 { "run_rule": "detect_phase_fault_rule" }
3559 ]
3560 }
3561 )"_json;
3562 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection =
3563 parsePhaseFaultDetection(element);
3564 EXPECT_EQ(phaseFaultDetection->getActions().size(), 1);
3565 EXPECT_EQ(phaseFaultDetection->getDeviceID(), "");
3566 }
3567
3568 // Test where works: rule_id specified: optional properties specified
3569 {
3570 const json element = R"(
3571 {
3572 "comments": [ "Detect phase fault using I/O expander" ],
3573 "device_id": "io_expander",
3574 "rule_id": "detect_phase_fault_rule"
3575 }
3576 )"_json;
3577 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection =
3578 parsePhaseFaultDetection(element);
3579 EXPECT_EQ(phaseFaultDetection->getActions().size(), 1);
3580 EXPECT_EQ(phaseFaultDetection->getDeviceID(), "io_expander");
3581 }
3582
3583 // Test where fails: Element is not an object
3584 try
3585 {
3586 const json element = R"( [ "foo", "bar" ] )"_json;
3587 parsePhaseFaultDetection(element);
3588 ADD_FAILURE() << "Should not have reached this line.";
3589 }
3590 catch (const std::invalid_argument& e)
3591 {
3592 EXPECT_STREQ(e.what(), "Element is not an object");
3593 }
3594
3595 // Test where fails: device_id value is invalid
3596 try
3597 {
3598 const json element = R"(
3599 {
3600 "device_id": 1,
3601 "rule_id": "detect_phase_fault_rule"
3602 }
3603 )"_json;
3604 parsePhaseFaultDetection(element);
3605 ADD_FAILURE() << "Should not have reached this line.";
3606 }
3607 catch (const std::invalid_argument& e)
3608 {
3609 EXPECT_STREQ(e.what(), "Element is not a string");
3610 }
3611
3612 // Test where fails: rule_id value is invalid
3613 try
3614 {
3615 const json element = R"(
3616 {
3617 "rule_id": 1
3618 }
3619 )"_json;
3620 parsePhaseFaultDetection(element);
3621 ADD_FAILURE() << "Should not have reached this line.";
3622 }
3623 catch (const std::invalid_argument& e)
3624 {
3625 EXPECT_STREQ(e.what(), "Element is not a string");
3626 }
3627
3628 // Test where fails: actions object is invalid
3629 try
3630 {
3631 const json element = R"(
3632 {
3633 "actions": 1
3634 }
3635 )"_json;
3636 parsePhaseFaultDetection(element);
3637 ADD_FAILURE() << "Should not have reached this line.";
3638 }
3639 catch (const std::invalid_argument& e)
3640 {
3641 EXPECT_STREQ(e.what(), "Element is not an array");
3642 }
3643
3644 // Test where fails: Required actions or rule_id property not specified
3645 try
3646 {
3647 const json element = R"(
3648 {
3649 "device_id": "io_expander"
3650 }
3651 )"_json;
3652 parsePhaseFaultDetection(element);
3653 ADD_FAILURE() << "Should not have reached this line.";
3654 }
3655 catch (const std::invalid_argument& e)
3656 {
3657 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3658 "either rule_id or actions");
3659 }
3660
3661 // Test where fails: Required actions or rule_id property both specified
3662 try
3663 {
3664 const json element = R"(
3665 {
3666 "rule_id": "detect_phase_fault_rule",
3667 "actions": [
3668 { "run_rule": "detect_phase_fault_rule" }
3669 ]
3670 }
3671 )"_json;
3672 parsePhaseFaultDetection(element);
3673 ADD_FAILURE() << "Should not have reached this line.";
3674 }
3675 catch (const std::invalid_argument& e)
3676 {
3677 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3678 "either rule_id or actions");
3679 }
3680
3681 // Test where fails: Invalid property specified
3682 try
3683 {
3684 const json element = R"(
3685 {
3686 "foo": "bar",
3687 "actions": [
3688 { "run_rule": "detect_phase_fault_rule" }
3689 ]
3690 }
3691 )"_json;
3692 parsePhaseFaultDetection(element);
3693 ADD_FAILURE() << "Should not have reached this line.";
3694 }
3695 catch (const std::invalid_argument& e)
3696 {
3697 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3698 }
3699}
3700
Shawn McCarneyb70370b2021-09-07 12:07:40 -05003701TEST(ConfigFileParserTests, ParsePhaseFaultType)
3702{
3703 // Test where works: n
3704 {
3705 const json element = "n";
3706 PhaseFaultType type = parsePhaseFaultType(element);
3707 EXPECT_EQ(type, PhaseFaultType::n);
3708 }
3709
3710 // Test where works: n+1
3711 {
3712 const json element = "n+1";
3713 PhaseFaultType type = parsePhaseFaultType(element);
3714 EXPECT_EQ(type, PhaseFaultType::n_plus_1);
3715 }
3716
3717 // Test where fails: Element is not a phase fault type
3718 try
3719 {
3720 const json element = "n+2";
3721 parsePhaseFaultType(element);
3722 ADD_FAILURE() << "Should not have reached this line.";
3723 }
3724 catch (const std::invalid_argument& e)
3725 {
3726 EXPECT_STREQ(e.what(), "Element is not a phase fault type");
3727 }
3728
3729 // Test where fails: Element is not a string
3730 try
3731 {
3732 const json element = R"( { "foo": "bar" } )"_json;
3733 parsePhaseFaultType(element);
3734 ADD_FAILURE() << "Should not have reached this line.";
3735 }
3736 catch (const std::invalid_argument& e)
3737 {
3738 EXPECT_STREQ(e.what(), "Element is not a string");
3739 }
3740}
3741
Bob King84614882020-04-30 13:13:48 +08003742TEST(ConfigFileParserTests, ParsePMBusReadSensor)
3743{
3744 // Test where works: Only required properties specified
3745 {
3746 const json element = R"(
3747 {
3748 "type": "iout",
3749 "command": "0x8C",
3750 "format": "linear_11"
3751 }
3752 )"_json;
3753 std::unique_ptr<PMBusReadSensorAction> action =
3754 parsePMBusReadSensor(element);
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05003755 EXPECT_EQ(action->getType(), SensorType::iout);
Bob King84614882020-04-30 13:13:48 +08003756 EXPECT_EQ(action->getCommand(), 0x8C);
3757 EXPECT_EQ(action->getFormat(),
3758 pmbus_utils::SensorDataFormat::linear_11);
3759 EXPECT_EQ(action->getExponent().has_value(), false);
3760 }
3761
3762 // Test where works: All properties specified
3763 {
3764 const json element = R"(
3765 {
3766 "type": "temperature",
3767 "command": "0x7A",
3768 "format": "linear_16",
3769 "exponent": -8
3770 }
3771 )"_json;
3772 std::unique_ptr<PMBusReadSensorAction> action =
3773 parsePMBusReadSensor(element);
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05003774 EXPECT_EQ(action->getType(), SensorType::temperature);
Bob King84614882020-04-30 13:13:48 +08003775 EXPECT_EQ(action->getCommand(), 0x7A);
3776 EXPECT_EQ(action->getFormat(),
3777 pmbus_utils::SensorDataFormat::linear_16);
3778 EXPECT_EQ(action->getExponent().has_value(), true);
3779 EXPECT_EQ(action->getExponent().value(), -8);
3780 }
3781
3782 // Test where fails: Element is not an object
3783 try
3784 {
3785 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3786 parsePMBusReadSensor(element);
3787 ADD_FAILURE() << "Should not have reached this line.";
3788 }
3789 catch (const std::invalid_argument& e)
3790 {
3791 EXPECT_STREQ(e.what(), "Element is not an object");
3792 }
3793
3794 // Test where fails: Invalid property specified
3795 try
3796 {
3797 const json element = R"(
3798 {
3799 "type": "iout",
3800 "command": "0x8C",
3801 "format": "linear_11",
3802 "foo": 1
3803 }
3804 )"_json;
3805 parsePMBusReadSensor(element);
3806 ADD_FAILURE() << "Should not have reached this line.";
3807 }
3808 catch (const std::invalid_argument& e)
3809 {
3810 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3811 }
3812
3813 // Test where fails: Required type property not specified
3814 try
3815 {
3816 const json element = R"(
3817 {
3818 "command": "0x8C",
3819 "format": "linear_11"
3820 }
3821 )"_json;
3822 parsePMBusReadSensor(element);
3823 ADD_FAILURE() << "Should not have reached this line.";
3824 }
3825 catch (const std::invalid_argument& e)
3826 {
3827 EXPECT_STREQ(e.what(), "Required property missing: type");
3828 }
3829
3830 // Test where fails: Required command property not specified
3831 try
3832 {
3833 const json element = R"(
3834 {
3835 "type": "iout",
3836 "format": "linear_11"
3837 }
3838 )"_json;
3839 parsePMBusReadSensor(element);
3840 ADD_FAILURE() << "Should not have reached this line.";
3841 }
3842 catch (const std::invalid_argument& e)
3843 {
3844 EXPECT_STREQ(e.what(), "Required property missing: command");
3845 }
3846
3847 // Test where fails: Required format property not specified
3848 try
3849 {
3850 const json element = R"(
3851 {
3852 "type": "iout",
3853 "command": "0x8C"
3854 }
3855 )"_json;
3856 parsePMBusReadSensor(element);
3857 ADD_FAILURE() << "Should not have reached this line.";
3858 }
3859 catch (const std::invalid_argument& e)
3860 {
3861 EXPECT_STREQ(e.what(), "Required property missing: format");
3862 }
3863
3864 // Test where fails: type value is invalid
3865 try
3866 {
3867 const json element = R"(
3868 {
3869 "type": 1,
3870 "command": "0x7A",
3871 "format": "linear_16"
3872 }
3873 )"_json;
3874 parsePMBusReadSensor(element);
3875 ADD_FAILURE() << "Should not have reached this line.";
3876 }
3877 catch (const std::invalid_argument& e)
3878 {
3879 EXPECT_STREQ(e.what(), "Element is not a string");
3880 }
3881
3882 // Test where fails: command value is invalid
3883 try
3884 {
3885 const json element = R"(
3886 {
3887 "type": "temperature",
3888 "command": 0,
3889 "format": "linear_16"
3890 }
3891 )"_json;
3892 parsePMBusReadSensor(element);
3893 ADD_FAILURE() << "Should not have reached this line.";
3894 }
3895 catch (const std::invalid_argument& e)
3896 {
3897 EXPECT_STREQ(e.what(), "Element is not a string");
3898 }
3899
3900 // Test where fails: format value is invalid
3901 try
3902 {
3903 const json element = R"(
3904 {
3905 "type": "temperature",
3906 "command": "0x7A",
3907 "format": 1
3908 }
3909 )"_json;
3910 parsePMBusReadSensor(element);
3911 ADD_FAILURE() << "Should not have reached this line.";
3912 }
3913 catch (const std::invalid_argument& e)
3914 {
3915 EXPECT_STREQ(e.what(), "Element is not a string");
3916 }
3917
3918 // Test where fails: exponent value is invalid
3919 try
3920 {
3921 const json element = R"(
3922 {
3923 "type": "temperature",
3924 "command": "0x7A",
3925 "format": "linear_16",
3926 "exponent": 1.3
3927 }
3928 )"_json;
3929 parsePMBusReadSensor(element);
3930 ADD_FAILURE() << "Should not have reached this line.";
3931 }
3932 catch (const std::invalid_argument& e)
3933 {
3934 EXPECT_STREQ(e.what(), "Element is not an integer");
3935 }
3936}
3937
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003938TEST(ConfigFileParserTests, ParsePMBusWriteVoutCommand)
3939{
3940 // Test where works: Only required properties specified
3941 {
3942 const json element = R"(
3943 {
3944 "format": "linear"
3945 }
3946 )"_json;
3947 std::unique_ptr<PMBusWriteVoutCommandAction> action =
3948 parsePMBusWriteVoutCommand(element);
3949 EXPECT_EQ(action->getVolts().has_value(), false);
3950 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear);
3951 EXPECT_EQ(action->getExponent().has_value(), false);
3952 EXPECT_EQ(action->isVerified(), false);
3953 }
3954
3955 // Test where works: All properties specified
3956 {
3957 const json element = R"(
3958 {
3959 "volts": 1.03,
3960 "format": "linear",
3961 "exponent": -8,
3962 "is_verified": true
3963 }
3964 )"_json;
3965 std::unique_ptr<PMBusWriteVoutCommandAction> action =
3966 parsePMBusWriteVoutCommand(element);
3967 EXPECT_EQ(action->getVolts().has_value(), true);
3968 EXPECT_EQ(action->getVolts().value(), 1.03);
3969 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear);
3970 EXPECT_EQ(action->getExponent().has_value(), true);
3971 EXPECT_EQ(action->getExponent().value(), -8);
3972 EXPECT_EQ(action->isVerified(), true);
3973 }
3974
3975 // Test where fails: Element is not an object
3976 try
3977 {
3978 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3979 parsePMBusWriteVoutCommand(element);
3980 ADD_FAILURE() << "Should not have reached this line.";
3981 }
3982 catch (const std::invalid_argument& e)
3983 {
3984 EXPECT_STREQ(e.what(), "Element is not an object");
3985 }
3986
3987 // Test where fails: volts value is invalid
3988 try
3989 {
3990 const json element = R"(
3991 {
3992 "volts": "foo",
3993 "format": "linear"
3994 }
3995 )"_json;
3996 parsePMBusWriteVoutCommand(element);
3997 ADD_FAILURE() << "Should not have reached this line.";
3998 }
3999 catch (const std::invalid_argument& e)
4000 {
4001 EXPECT_STREQ(e.what(), "Element is not a number");
4002 }
4003
4004 // Test where fails: Required format property not specified
4005 try
4006 {
4007 const json element = R"(
4008 {
4009 "volts": 1.03,
4010 "is_verified": true
4011 }
4012 )"_json;
4013 parsePMBusWriteVoutCommand(element);
4014 ADD_FAILURE() << "Should not have reached this line.";
4015 }
4016 catch (const std::invalid_argument& e)
4017 {
4018 EXPECT_STREQ(e.what(), "Required property missing: format");
4019 }
4020
4021 // Test where fails: format value is invalid
4022 try
4023 {
4024 const json element = R"(
4025 {
4026 "format": "linear_11"
4027 }
4028 )"_json;
4029 parsePMBusWriteVoutCommand(element);
4030 ADD_FAILURE() << "Should not have reached this line.";
4031 }
4032 catch (const std::invalid_argument& e)
4033 {
4034 EXPECT_STREQ(e.what(), "Invalid format value: linear_11");
4035 }
4036
4037 // Test where fails: exponent value is invalid
4038 try
4039 {
4040 const json element = R"(
4041 {
4042 "format": "linear",
4043 "exponent": 1.3
4044 }
4045 )"_json;
4046 parsePMBusWriteVoutCommand(element);
4047 ADD_FAILURE() << "Should not have reached this line.";
4048 }
4049 catch (const std::invalid_argument& e)
4050 {
4051 EXPECT_STREQ(e.what(), "Element is not an integer");
4052 }
4053
4054 // Test where fails: is_verified value is invalid
4055 try
4056 {
4057 const json element = R"(
4058 {
4059 "format": "linear",
4060 "is_verified": "true"
4061 }
4062 )"_json;
4063 parsePMBusWriteVoutCommand(element);
4064 ADD_FAILURE() << "Should not have reached this line.";
4065 }
4066 catch (const std::invalid_argument& e)
4067 {
4068 EXPECT_STREQ(e.what(), "Element is not a boolean");
4069 }
4070
4071 // Test where fails: Invalid property specified
4072 try
4073 {
4074 const json element = R"(
4075 {
4076 "format": "linear",
4077 "foo": "bar"
4078 }
4079 )"_json;
4080 parsePMBusWriteVoutCommand(element);
4081 ADD_FAILURE() << "Should not have reached this line.";
4082 }
4083 catch (const std::invalid_argument& e)
4084 {
4085 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4086 }
4087}
4088
Bob King2aafb1c2020-04-16 15:24:32 +08004089TEST(ConfigFileParserTests, ParsePresenceDetection)
4090{
4091 // Test where works: actions property specified
4092 {
4093 const json element = R"(
4094 {
4095 "actions": [
4096 { "run_rule": "read_sensors_rule" }
4097 ]
4098 }
4099 )"_json;
4100 std::unique_ptr<PresenceDetection> presenceDetection =
4101 parsePresenceDetection(element);
4102 EXPECT_EQ(presenceDetection->getActions().size(), 1);
4103 }
4104
4105 // Test where works: rule_id property specified
4106 {
4107 const json element = R"(
4108 {
4109 "comments": [ "comments property" ],
4110 "rule_id": "set_voltage_rule"
4111 }
4112 )"_json;
4113 std::unique_ptr<PresenceDetection> presenceDetection =
4114 parsePresenceDetection(element);
4115 EXPECT_EQ(presenceDetection->getActions().size(), 1);
4116 }
4117
4118 // Test where fails: actions object is invalid
4119 try
4120 {
4121 const json element = R"(
4122 {
4123 "actions": 1
4124 }
4125 )"_json;
4126 parsePresenceDetection(element);
4127 ADD_FAILURE() << "Should not have reached this line.";
4128 }
4129 catch (const std::invalid_argument& e)
4130 {
4131 EXPECT_STREQ(e.what(), "Element is not an array");
4132 }
4133
4134 // Test where fails: rule_id value is invalid
4135 try
4136 {
4137 const json element = R"(
4138 {
4139 "rule_id": 1
4140 }
4141 )"_json;
4142 parsePresenceDetection(element);
4143 ADD_FAILURE() << "Should not have reached this line.";
4144 }
4145 catch (const std::invalid_argument& e)
4146 {
4147 EXPECT_STREQ(e.what(), "Element is not a string");
4148 }
4149
4150 // Test where fails: Required actions or rule_id property not specified
4151 try
4152 {
4153 const json element = R"(
4154 {
4155 "comments": [ "comments property" ]
4156 }
4157 )"_json;
4158 parsePresenceDetection(element);
4159 ADD_FAILURE() << "Should not have reached this line.";
4160 }
4161 catch (const std::invalid_argument& e)
4162 {
4163 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4164 "either rule_id or actions");
4165 }
4166
4167 // Test where fails: Required actions or rule_id property both specified
4168 try
4169 {
4170 const json element = R"(
4171 {
4172 "rule_id": "set_voltage_rule",
4173 "actions": [
4174 { "run_rule": "read_sensors_rule" }
4175 ]
4176 }
4177 )"_json;
4178 parsePresenceDetection(element);
4179 ADD_FAILURE() << "Should not have reached this line.";
4180 }
4181 catch (const std::invalid_argument& e)
4182 {
4183 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4184 "either rule_id or actions");
4185 }
4186
4187 // Test where fails: Element is not an object
4188 try
4189 {
4190 const json element = R"( [ "foo", "bar" ] )"_json;
4191 parsePresenceDetection(element);
4192 ADD_FAILURE() << "Should not have reached this line.";
4193 }
4194 catch (const std::invalid_argument& e)
4195 {
4196 EXPECT_STREQ(e.what(), "Element is not an object");
4197 }
4198
4199 // Test where fails: Invalid property specified
4200 try
4201 {
4202 const json element = R"(
4203 {
4204 "foo": "bar",
4205 "actions": [
4206 { "run_rule": "read_sensors_rule" }
4207 ]
4208 }
4209 )"_json;
4210 parsePresenceDetection(element);
4211 ADD_FAILURE() << "Should not have reached this line.";
4212 }
4213 catch (const std::invalid_argument& e)
4214 {
4215 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4216 }
4217}
4218
Bob Kinga2f2a0d2020-04-09 13:32:14 +08004219TEST(ConfigFileParserTests, ParseRail)
4220{
4221 // Test where works: Only required properties specified
4222 {
4223 const json element = R"(
4224 {
4225 "id": "vdd"
4226 }
4227 )"_json;
4228 std::unique_ptr<Rail> rail = parseRail(element);
4229 EXPECT_EQ(rail->getID(), "vdd");
4230 EXPECT_EQ(rail->getConfiguration(), nullptr);
4231 EXPECT_EQ(rail->getSensorMonitoring(), nullptr);
4232 }
4233
4234 // Test where works: All properties specified
4235 {
4236 const json element = R"(
4237 {
4238 "comments": [ "comments property" ],
4239 "id": "vdd",
4240 "configuration": {
4241 "volts": 1.1,
4242 "actions": [
4243 {
4244 "pmbus_write_vout_command": {
4245 "format": "linear"
4246 }
4247 }
4248 ]
4249 },
4250 "sensor_monitoring": {
4251 "actions": [
4252 { "run_rule": "read_sensors_rule" }
4253 ]
4254 }
4255 }
4256 )"_json;
4257 std::unique_ptr<Rail> rail = parseRail(element);
4258 EXPECT_EQ(rail->getID(), "vdd");
4259 EXPECT_NE(rail->getConfiguration(), nullptr);
4260 EXPECT_NE(rail->getSensorMonitoring(), nullptr);
4261 }
4262
4263 // Test where fails: id property not specified
4264 try
4265 {
4266 const json element = R"(
4267 {
4268 "configuration": {
4269 "volts": 1.1,
4270 "actions": [
4271 {
4272 "pmbus_write_vout_command": {
4273 "format": "linear"
4274 }
4275 }
4276 ]
4277 }
4278 }
4279 )"_json;
4280 parseRail(element);
4281 ADD_FAILURE() << "Should not have reached this line.";
4282 }
4283 catch (const std::invalid_argument& e)
4284 {
4285 EXPECT_STREQ(e.what(), "Required property missing: id");
4286 }
4287
4288 // Test where fails: id property is invalid
4289 try
4290 {
4291 const json element = R"(
4292 {
4293 "id": "",
4294 "configuration": {
4295 "volts": 1.1,
4296 "actions": [
4297 {
4298 "pmbus_write_vout_command": {
4299 "format": "linear"
4300 }
4301 }
4302 ]
4303 }
4304 }
4305 )"_json;
4306 parseRail(element);
4307 ADD_FAILURE() << "Should not have reached this line.";
4308 }
4309 catch (const std::invalid_argument& e)
4310 {
4311 EXPECT_STREQ(e.what(), "Element contains an empty string");
4312 }
4313
4314 // Test where fails: Element is not an object
4315 try
4316 {
4317 const json element = R"( [ "0xFF", "0x01" ] )"_json;
4318 parseRail(element);
4319 ADD_FAILURE() << "Should not have reached this line.";
4320 }
4321 catch (const std::invalid_argument& e)
4322 {
4323 EXPECT_STREQ(e.what(), "Element is not an object");
4324 }
4325
4326 // Test where fails: configuration value is invalid
4327 try
4328 {
4329 const json element = R"(
4330 {
4331 "id": "vdd",
4332 "configuration": "config"
4333 }
4334 )"_json;
4335 parseRail(element);
4336 ADD_FAILURE() << "Should not have reached this line.";
4337 }
4338 catch (const std::invalid_argument& e)
4339 {
4340 EXPECT_STREQ(e.what(), "Element is not an object");
4341 }
4342
4343 // Test where fails: sensor_monitoring value is invalid
4344 try
4345 {
4346 const json element = R"(
4347 {
4348 "comments": [ "comments property" ],
4349 "id": "vdd",
4350 "configuration": {
4351 "volts": 1.1,
4352 "actions": [
4353 {
4354 "pmbus_write_vout_command": {
4355 "format": "linear"
4356 }
4357 }
4358 ]
4359 },
4360 "sensor_monitoring": 1
4361 }
4362 )"_json;
4363 parseRail(element);
4364 ADD_FAILURE() << "Should not have reached this line.";
4365 }
4366 catch (const std::invalid_argument& e)
4367 {
4368 EXPECT_STREQ(e.what(), "Element is not an object");
4369 }
4370
4371 // Test where fails: Invalid property specified
4372 try
4373 {
4374 const json element = R"(
4375 {
4376 "id": "vdd",
4377 "foo" : true
4378 }
4379 )"_json;
4380 parseRail(element);
4381 ADD_FAILURE() << "Should not have reached this line.";
4382 }
4383 catch (const std::invalid_argument& e)
4384 {
4385 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4386 }
4387}
4388
4389TEST(ConfigFileParserTests, ParseRailArray)
4390{
4391 // Test where works
4392 {
4393 const json element = R"(
4394 [
4395 { "id": "vdd" },
4396 { "id": "vio" }
4397 ]
4398 )"_json;
4399 std::vector<std::unique_ptr<Rail>> rails = parseRailArray(element);
4400 EXPECT_EQ(rails.size(), 2);
4401 EXPECT_EQ(rails[0]->getID(), "vdd");
4402 EXPECT_EQ(rails[1]->getID(), "vio");
4403 }
4404
4405 // Test where fails: Element is not an array
4406 try
4407 {
4408 const json element = R"(
4409 {
4410 "foo": "bar"
4411 }
4412 )"_json;
4413 parseRailArray(element);
4414 ADD_FAILURE() << "Should not have reached this line.";
4415 }
4416 catch (const std::invalid_argument& e)
4417 {
4418 EXPECT_STREQ(e.what(), "Element is not an array");
4419 }
4420}
4421
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004422TEST(ConfigFileParserTests, ParseRoot)
4423{
4424 // Test where works: Only required properties specified
4425 {
4426 const json element = R"(
4427 {
4428 "chassis": [
Shawn McCarney4c88a4c2021-09-21 15:29:24 -05004429 { "number": 1, "inventory_path": "system/chassis" }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004430 ]
4431 }
4432 )"_json;
4433 std::vector<std::unique_ptr<Rule>> rules{};
4434 std::vector<std::unique_ptr<Chassis>> chassis{};
4435 std::tie(rules, chassis) = parseRoot(element);
4436 EXPECT_EQ(rules.size(), 0);
Bob King0e701132020-04-03 21:50:31 +08004437 EXPECT_EQ(chassis.size(), 1);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004438 }
4439
4440 // Test where works: All properties specified
4441 {
4442 const json element = R"(
4443 {
4444 "comments": [ "Config file for a FooBar one-chassis system" ],
4445 "rules": [
4446 {
4447 "id": "set_voltage_rule",
4448 "actions": [
4449 { "pmbus_write_vout_command": { "format": "linear" } }
4450 ]
4451 }
4452 ],
4453 "chassis": [
Shawn McCarney4c88a4c2021-09-21 15:29:24 -05004454 { "number": 1, "inventory_path": "system/chassis1" },
4455 { "number": 3, "inventory_path": "system/chassis3" }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004456 ]
4457 }
4458 )"_json;
4459 std::vector<std::unique_ptr<Rule>> rules{};
4460 std::vector<std::unique_ptr<Chassis>> chassis{};
4461 std::tie(rules, chassis) = parseRoot(element);
4462 EXPECT_EQ(rules.size(), 1);
Bob King0e701132020-04-03 21:50:31 +08004463 EXPECT_EQ(chassis.size(), 2);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004464 }
4465
4466 // Test where fails: Element is not an object
4467 try
4468 {
4469 const json element = R"( [ "0xFF", "0x01" ] )"_json;
4470 parseRoot(element);
4471 ADD_FAILURE() << "Should not have reached this line.";
4472 }
4473 catch (const std::invalid_argument& e)
4474 {
4475 EXPECT_STREQ(e.what(), "Element is not an object");
4476 }
4477
4478 // Test where fails: chassis property not specified
4479 try
4480 {
4481 const json element = R"(
4482 {
4483 "rules": [
4484 {
4485 "id": "set_voltage_rule",
4486 "actions": [
4487 { "pmbus_write_vout_command": { "format": "linear" } }
4488 ]
4489 }
4490 ]
4491 }
4492 )"_json;
4493 parseRoot(element);
4494 ADD_FAILURE() << "Should not have reached this line.";
4495 }
4496 catch (const std::invalid_argument& e)
4497 {
4498 EXPECT_STREQ(e.what(), "Required property missing: chassis");
4499 }
4500
4501 // Test where fails: Invalid property specified
4502 try
4503 {
4504 const json element = R"(
4505 {
4506 "remarks": [ "Config file for a FooBar one-chassis system" ],
4507 "chassis": [
Shawn McCarney4c88a4c2021-09-21 15:29:24 -05004508 { "number": 1, "inventory_path": "system/chassis" }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004509 ]
4510 }
4511 )"_json;
4512 parseRoot(element);
4513 ADD_FAILURE() << "Should not have reached this line.";
4514 }
4515 catch (const std::invalid_argument& e)
4516 {
4517 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4518 }
4519}
4520
4521TEST(ConfigFileParserTests, ParseRule)
4522{
4523 // Test where works: comments property specified
4524 {
4525 const json element = R"(
4526 {
4527 "comments": [ "Set voltage rule" ],
4528 "id": "set_voltage_rule",
4529 "actions": [
4530 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
4531 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
4532 ]
4533 }
4534 )"_json;
4535 std::unique_ptr<Rule> rule = parseRule(element);
4536 EXPECT_EQ(rule->getID(), "set_voltage_rule");
4537 EXPECT_EQ(rule->getActions().size(), 2);
4538 }
4539
4540 // Test where works: comments property not specified
4541 {
4542 const json element = R"(
4543 {
4544 "id": "set_voltage_rule",
4545 "actions": [
4546 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
4547 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } },
4548 { "pmbus_write_vout_command": { "volts": 1.05, "format": "linear" } }
4549 ]
4550 }
4551 )"_json;
4552 std::unique_ptr<Rule> rule = parseRule(element);
4553 EXPECT_EQ(rule->getID(), "set_voltage_rule");
4554 EXPECT_EQ(rule->getActions().size(), 3);
4555 }
4556
4557 // Test where fails: Element is not an object
4558 try
4559 {
4560 const json element = R"( [ "0xFF", "0x01" ] )"_json;
4561 parseRule(element);
4562 ADD_FAILURE() << "Should not have reached this line.";
4563 }
4564 catch (const std::invalid_argument& e)
4565 {
4566 EXPECT_STREQ(e.what(), "Element is not an object");
4567 }
4568
4569 // Test where fails: id property not specified
4570 try
4571 {
4572 const json element = R"(
4573 {
4574 "actions": [
4575 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
4576 ]
4577 }
4578 )"_json;
4579 parseRule(element);
4580 ADD_FAILURE() << "Should not have reached this line.";
4581 }
4582 catch (const std::invalid_argument& e)
4583 {
4584 EXPECT_STREQ(e.what(), "Required property missing: id");
4585 }
4586
4587 // Test where fails: id property is invalid
4588 try
4589 {
4590 const json element = R"(
4591 {
4592 "id": "",
4593 "actions": [
4594 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
4595 ]
4596 }
4597 )"_json;
4598 parseRule(element);
4599 ADD_FAILURE() << "Should not have reached this line.";
4600 }
4601 catch (const std::invalid_argument& e)
4602 {
4603 EXPECT_STREQ(e.what(), "Element contains an empty string");
4604 }
4605
4606 // Test where fails: actions property not specified
4607 try
4608 {
4609 const json element = R"(
4610 {
4611 "comments": [ "Set voltage rule" ],
4612 "id": "set_voltage_rule"
4613 }
4614 )"_json;
4615 parseRule(element);
4616 ADD_FAILURE() << "Should not have reached this line.";
4617 }
4618 catch (const std::invalid_argument& e)
4619 {
4620 EXPECT_STREQ(e.what(), "Required property missing: actions");
4621 }
4622
4623 // Test where fails: actions property is invalid
4624 try
4625 {
4626 const json element = R"(
4627 {
4628 "id": "set_voltage_rule",
4629 "actions": true
4630 }
4631 )"_json;
4632 parseRule(element);
4633 ADD_FAILURE() << "Should not have reached this line.";
4634 }
4635 catch (const std::invalid_argument& e)
4636 {
4637 EXPECT_STREQ(e.what(), "Element is not an array");
4638 }
4639
4640 // Test where fails: Invalid property specified
4641 try
4642 {
4643 const json element = R"(
4644 {
4645 "remarks": [ "Set voltage rule" ],
4646 "id": "set_voltage_rule",
4647 "actions": [
4648 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
4649 ]
4650 }
4651 )"_json;
4652 parseRule(element);
4653 ADD_FAILURE() << "Should not have reached this line.";
4654 }
4655 catch (const std::invalid_argument& e)
4656 {
4657 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4658 }
4659}
4660
4661TEST(ConfigFileParserTests, ParseRuleArray)
4662{
4663 // Test where works
4664 {
4665 const json element = R"(
4666 [
4667 {
4668 "id": "set_voltage_rule1",
4669 "actions": [
4670 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
4671 ]
4672 },
4673 {
4674 "id": "set_voltage_rule2",
4675 "actions": [
4676 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
4677 { "pmbus_write_vout_command": { "volts": 1.11, "format": "linear" } }
4678 ]
4679 }
4680 ]
4681 )"_json;
4682 std::vector<std::unique_ptr<Rule>> rules = parseRuleArray(element);
4683 EXPECT_EQ(rules.size(), 2);
4684 EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1");
4685 EXPECT_EQ(rules[0]->getActions().size(), 1);
4686 EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2");
4687 EXPECT_EQ(rules[1]->getActions().size(), 2);
4688 }
4689
4690 // Test where fails: Element is not an array
4691 try
4692 {
4693 const json element = R"( { "id": "set_voltage_rule" } )"_json;
4694 parseRuleArray(element);
4695 ADD_FAILURE() << "Should not have reached this line.";
4696 }
4697 catch (const std::invalid_argument& e)
4698 {
4699 EXPECT_STREQ(e.what(), "Element is not an array");
4700 }
4701}
4702
Bob King33e7eaa2020-04-01 18:09:34 +08004703TEST(ConfigFileParserTests, ParseRuleIDOrActionsProperty)
4704{
4705 // Test where works: actions specified
4706 {
4707 const json element = R"(
4708 {
4709 "actions": [
4710 { "pmbus_write_vout_command": { "format": "linear" } },
4711 { "run_rule": "set_voltage_rule" }
4712 ]
4713 }
4714 )"_json;
4715 std::vector<std::unique_ptr<Action>> actions =
4716 parseRuleIDOrActionsProperty(element);
4717 EXPECT_EQ(actions.size(), 2);
4718 }
4719
4720 // Test where works: rule_id specified
4721 {
4722 const json element = R"(
4723 {
4724 "rule_id": "set_voltage_rule"
4725 }
4726 )"_json;
4727 std::vector<std::unique_ptr<Action>> actions =
4728 parseRuleIDOrActionsProperty(element);
4729 EXPECT_EQ(actions.size(), 1);
4730 }
4731
4732 // Test where fails: Element is not an object
4733 try
4734 {
4735 const json element = R"( [ "foo", "bar" ] )"_json;
4736 parseRuleIDOrActionsProperty(element);
4737 ADD_FAILURE() << "Should not have reached this line.";
4738 }
4739 catch (const std::invalid_argument& e)
4740 {
4741 EXPECT_STREQ(e.what(), "Element is not an object");
4742 }
4743
4744 // Test where fails: rule_id is invalid
4745 try
4746 {
4747 const json element = R"(
4748 { "rule_id": 1 }
4749 )"_json;
4750 parseRuleIDOrActionsProperty(element);
4751 ADD_FAILURE() << "Should not have reached this line.";
4752 }
4753 catch (const std::invalid_argument& e)
4754 {
4755 EXPECT_STREQ(e.what(), "Element is not a string");
4756 }
4757
4758 // Test where fails: actions is invalid
4759 try
4760 {
4761 const json element = R"(
4762 { "actions": 1 }
4763 )"_json;
4764 parseRuleIDOrActionsProperty(element);
4765 ADD_FAILURE() << "Should not have reached this line.";
4766 }
4767 catch (const std::invalid_argument& e)
4768 {
4769 EXPECT_STREQ(e.what(), "Element is not an array");
4770 }
4771
4772 // Test where fails: Neither rule_id nor actions specified
4773 try
4774 {
4775 const json element = R"(
4776 {
4777 "volts": 1.03
4778 }
4779 )"_json;
4780 parseRuleIDOrActionsProperty(element);
4781 ADD_FAILURE() << "Should not have reached this line.";
4782 }
4783 catch (const std::invalid_argument& e)
4784 {
4785 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4786 "either rule_id or actions");
4787 }
4788
4789 // Test where fails: Both rule_id and actions specified
4790 try
4791 {
4792 const json element = R"(
4793 {
4794 "volts": 1.03,
4795 "rule_id": "set_voltage_rule",
4796 "actions": [
4797 {
4798 "pmbus_write_vout_command": {
4799 "format": "linear"
4800 }
4801 }
4802 ]
4803 }
4804 )"_json;
4805 parseRuleIDOrActionsProperty(element);
4806 ADD_FAILURE() << "Should not have reached this line.";
4807 }
4808 catch (const std::invalid_argument& e)
4809 {
4810 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4811 "either rule_id or actions");
4812 }
4813}
4814
Bob King315b0b62020-04-03 21:47:58 +08004815TEST(ConfigFileParserTests, ParseRunRule)
4816{
4817 // Test where works
4818 {
4819 const json element = "vdd_regulator";
4820 std::unique_ptr<RunRuleAction> action = parseRunRule(element);
4821 EXPECT_EQ(action->getRuleID(), "vdd_regulator");
4822 }
4823
4824 // Test where fails: Element is not a string
4825 try
4826 {
4827 const json element = 1;
4828 parseRunRule(element);
4829 ADD_FAILURE() << "Should not have reached this line.";
4830 }
4831 catch (const std::invalid_argument& e)
4832 {
4833 EXPECT_STREQ(e.what(), "Element is not a string");
4834 }
4835
4836 // Test where fails: Empty string
4837 try
4838 {
4839 const json element = "";
4840 parseRunRule(element);
4841 ADD_FAILURE() << "Should not have reached this line.";
4842 }
4843 catch (const std::invalid_argument& e)
4844 {
4845 EXPECT_STREQ(e.what(), "Element contains an empty string");
4846 }
4847}
4848
Bob King84614882020-04-30 13:13:48 +08004849TEST(ConfigFileParserTests, ParseSensorDataFormat)
4850{
4851 // Test where works: linear_11
4852 {
4853 const json element = "linear_11";
4854 pmbus_utils::SensorDataFormat value = parseSensorDataFormat(element);
4855 pmbus_utils::SensorDataFormat format =
4856 pmbus_utils::SensorDataFormat::linear_11;
4857 EXPECT_EQ(value, format);
4858 }
4859
4860 // Test where works: linear_16
4861 {
4862 const json element = "linear_16";
4863 pmbus_utils::SensorDataFormat value = parseSensorDataFormat(element);
4864 pmbus_utils::SensorDataFormat format =
4865 pmbus_utils::SensorDataFormat::linear_16;
4866 EXPECT_EQ(value, format);
4867 }
4868
4869 // Test where fails: Element is not a sensor data format
4870 try
4871 {
4872 const json element = "foo";
4873 parseSensorDataFormat(element);
4874 ADD_FAILURE() << "Should not have reached this line.";
4875 }
4876 catch (const std::invalid_argument& e)
4877 {
4878 EXPECT_STREQ(e.what(), "Element is not a sensor data format");
4879 }
4880
4881 // Test where fails: Element is not a string
4882 try
4883 {
4884 const json element = R"( { "foo": "bar" } )"_json;
4885 parseSensorDataFormat(element);
4886 ADD_FAILURE() << "Should not have reached this line.";
4887 }
4888 catch (const std::invalid_argument& e)
4889 {
4890 EXPECT_STREQ(e.what(), "Element is not a string");
4891 }
4892}
4893
Bob Kinga2f2a0d2020-04-09 13:32:14 +08004894TEST(ConfigFileParserTests, ParseSensorMonitoring)
4895{
4896 // Test where works: actions property specified
4897 {
4898 const json element = R"(
4899 {
4900 "actions": [
4901 { "run_rule": "read_sensors_rule" }
4902 ]
4903 }
4904 )"_json;
4905 std::unique_ptr<SensorMonitoring> sensorMonitoring =
4906 parseSensorMonitoring(element);
4907 EXPECT_EQ(sensorMonitoring->getActions().size(), 1);
4908 }
4909
4910 // Test where works: rule_id property specified
4911 {
4912 const json element = R"(
4913 {
4914 "comments": [ "comments property" ],
4915 "rule_id": "set_voltage_rule"
4916 }
4917 )"_json;
4918 std::unique_ptr<SensorMonitoring> sensorMonitoring =
4919 parseSensorMonitoring(element);
4920 EXPECT_EQ(sensorMonitoring->getActions().size(), 1);
4921 }
4922
4923 // Test where fails: actions object is invalid
4924 try
4925 {
4926 const json element = R"(
4927 {
4928 "actions": 1
4929 }
4930 )"_json;
4931 parseSensorMonitoring(element);
4932 ADD_FAILURE() << "Should not have reached this line.";
4933 }
4934 catch (const std::invalid_argument& e)
4935 {
4936 EXPECT_STREQ(e.what(), "Element is not an array");
4937 }
4938
4939 // Test where fails: rule_id value is invalid
4940 try
4941 {
4942 const json element = R"(
4943 {
4944 "rule_id": 1
4945 }
4946 )"_json;
4947 parseSensorMonitoring(element);
4948 ADD_FAILURE() << "Should not have reached this line.";
4949 }
4950 catch (const std::invalid_argument& e)
4951 {
4952 EXPECT_STREQ(e.what(), "Element is not a string");
4953 }
4954
4955 // Test where fails: Required actions or rule_id property not specified
4956 try
4957 {
4958 const json element = R"(
4959 {
4960 "comments": [ "comments property" ]
4961 }
4962 )"_json;
4963 parseSensorMonitoring(element);
4964 ADD_FAILURE() << "Should not have reached this line.";
4965 }
4966 catch (const std::invalid_argument& e)
4967 {
4968 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4969 "either rule_id or actions");
4970 }
4971
4972 // Test where fails: Required actions or rule_id property both specified
4973 try
4974 {
4975 const json element = R"(
4976 {
4977 "rule_id": "set_voltage_rule",
4978 "actions": [
4979 { "run_rule": "read_sensors_rule" }
4980 ]
4981 }
4982 )"_json;
4983 parseSensorMonitoring(element);
4984 ADD_FAILURE() << "Should not have reached this line.";
4985 }
4986 catch (const std::invalid_argument& e)
4987 {
4988 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4989 "either rule_id or actions");
4990 }
4991
4992 // Test where fails: Element is not an object
4993 try
4994 {
4995 const json element = R"( [ "foo", "bar" ] )"_json;
4996 parseSensorMonitoring(element);
4997 ADD_FAILURE() << "Should not have reached this line.";
4998 }
4999 catch (const std::invalid_argument& e)
5000 {
5001 EXPECT_STREQ(e.what(), "Element is not an object");
5002 }
5003
5004 // Test where fails: Invalid property specified
5005 try
5006 {
5007 const json element = R"(
5008 {
5009 "foo": "bar",
5010 "actions": [
5011 { "run_rule": "read_sensors_rule" }
5012 ]
5013 }
5014 )"_json;
5015 parseSensorMonitoring(element);
5016 ADD_FAILURE() << "Should not have reached this line.";
5017 }
5018 catch (const std::invalid_argument& e)
5019 {
5020 EXPECT_STREQ(e.what(), "Element contains an invalid property");
5021 }
5022}
5023
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005024TEST(ConfigFileParserTests, ParseSensorType)
Bob King84614882020-04-30 13:13:48 +08005025{
5026 // Test where works: iout
5027 {
5028 const json element = "iout";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005029 SensorType type = parseSensorType(element);
5030 EXPECT_EQ(type, SensorType::iout);
Bob King84614882020-04-30 13:13:48 +08005031 }
5032
5033 // Test where works: iout_peak
5034 {
5035 const json element = "iout_peak";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005036 SensorType type = parseSensorType(element);
5037 EXPECT_EQ(type, SensorType::iout_peak);
Bob King84614882020-04-30 13:13:48 +08005038 }
5039
5040 // Test where works: iout_valley
5041 {
5042 const json element = "iout_valley";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005043 SensorType type = parseSensorType(element);
5044 EXPECT_EQ(type, SensorType::iout_valley);
Bob King84614882020-04-30 13:13:48 +08005045 }
5046
5047 // Test where works: pout
5048 {
5049 const json element = "pout";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005050 SensorType type = parseSensorType(element);
5051 EXPECT_EQ(type, SensorType::pout);
Bob King84614882020-04-30 13:13:48 +08005052 }
5053
5054 // Test where works: temperature
5055 {
5056 const json element = "temperature";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005057 SensorType type = parseSensorType(element);
5058 EXPECT_EQ(type, SensorType::temperature);
Bob King84614882020-04-30 13:13:48 +08005059 }
5060
5061 // Test where works: temperature_peak
5062 {
5063 const json element = "temperature_peak";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005064 SensorType type = parseSensorType(element);
5065 EXPECT_EQ(type, SensorType::temperature_peak);
Bob King84614882020-04-30 13:13:48 +08005066 }
5067
5068 // Test where works: vout
5069 {
5070 const json element = "vout";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005071 SensorType type = parseSensorType(element);
5072 EXPECT_EQ(type, SensorType::vout);
Bob King84614882020-04-30 13:13:48 +08005073 }
5074
5075 // Test where works: vout_peak
5076 {
5077 const json element = "vout_peak";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005078 SensorType type = parseSensorType(element);
5079 EXPECT_EQ(type, SensorType::vout_peak);
Bob King84614882020-04-30 13:13:48 +08005080 }
5081
5082 // Test where works: vout_valley
5083 {
5084 const json element = "vout_valley";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005085 SensorType type = parseSensorType(element);
5086 EXPECT_EQ(type, SensorType::vout_valley);
Bob King84614882020-04-30 13:13:48 +08005087 }
5088
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005089 // Test where fails: Element is not a sensor type
Bob King84614882020-04-30 13:13:48 +08005090 try
5091 {
5092 const json element = "foo";
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005093 parseSensorType(element);
Bob King84614882020-04-30 13:13:48 +08005094 ADD_FAILURE() << "Should not have reached this line.";
5095 }
5096 catch (const std::invalid_argument& e)
5097 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005098 EXPECT_STREQ(e.what(), "Element is not a sensor type");
Bob King84614882020-04-30 13:13:48 +08005099 }
5100
5101 // Test where fails: Element is not a string
5102 try
5103 {
5104 const json element = R"( { "foo": "bar" } )"_json;
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05005105 parseSensorType(element);
Bob King84614882020-04-30 13:13:48 +08005106 ADD_FAILURE() << "Should not have reached this line.";
5107 }
5108 catch (const std::invalid_argument& e)
5109 {
5110 EXPECT_STREQ(e.what(), "Element is not a string");
5111 }
5112}
5113
Bob King18a68502020-04-17 14:19:56 +08005114TEST(ConfigFileParserTests, ParseSetDevice)
5115{
5116 // Test where works
5117 {
5118 const json element = "regulator1";
5119 std::unique_ptr<SetDeviceAction> action = parseSetDevice(element);
5120 EXPECT_EQ(action->getDeviceID(), "regulator1");
5121 }
5122
5123 // Test where fails: Element is not a string
5124 try
5125 {
5126 const json element = 1;
5127 parseSetDevice(element);
5128 ADD_FAILURE() << "Should not have reached this line.";
5129 }
5130 catch (const std::invalid_argument& e)
5131 {
5132 EXPECT_STREQ(e.what(), "Element is not a string");
5133 }
5134
5135 // Test where fails: Empty string
5136 try
5137 {
5138 const json element = "";
5139 parseSetDevice(element);
5140 ADD_FAILURE() << "Should not have reached this line.";
5141 }
5142 catch (const std::invalid_argument& e)
5143 {
5144 EXPECT_STREQ(e.what(), "Element contains an empty string");
5145 }
5146}
5147
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05005148TEST(ConfigFileParserTests, ParseString)
5149{
5150 // Test where works: Empty string
5151 {
5152 const json element = "";
5153 std::string value = parseString(element, true);
5154 EXPECT_EQ(value, "");
5155 }
5156
5157 // Test where works: Non-empty string
5158 {
5159 const json element = "vdd_regulator";
5160 std::string value = parseString(element, false);
5161 EXPECT_EQ(value, "vdd_regulator");
5162 }
5163
5164 // Test where fails: Element is not a string
5165 try
5166 {
5167 const json element = R"( { "foo": "bar" } )"_json;
5168 parseString(element);
5169 ADD_FAILURE() << "Should not have reached this line.";
5170 }
5171 catch (const std::invalid_argument& e)
5172 {
5173 EXPECT_STREQ(e.what(), "Element is not a string");
5174 }
5175
5176 // Test where fails: Empty string
5177 try
5178 {
5179 const json element = "";
5180 parseString(element);
5181 ADD_FAILURE() << "Should not have reached this line.";
5182 }
5183 catch (const std::invalid_argument& e)
5184 {
5185 EXPECT_STREQ(e.what(), "Element contains an empty string");
5186 }
5187}
5188
Bob Kingf617f892020-03-30 19:03:35 +08005189TEST(ConfigFileParserTests, ParseUint8)
5190{
5191 // Test where works: 0
5192 {
5193 const json element = R"( 0 )"_json;
5194 uint8_t value = parseUint8(element);
5195 EXPECT_EQ(value, 0);
5196 }
5197
5198 // Test where works: UINT8_MAX
5199 {
5200 const json element = R"( 255 )"_json;
5201 uint8_t value = parseUint8(element);
5202 EXPECT_EQ(value, 255);
5203 }
5204
5205 // Test where fails: Element is not an integer
5206 try
5207 {
5208 const json element = R"( 1.03 )"_json;
5209 parseUint8(element);
5210 ADD_FAILURE() << "Should not have reached this line.";
5211 }
5212 catch (const std::invalid_argument& e)
5213 {
5214 EXPECT_STREQ(e.what(), "Element is not an integer");
5215 }
5216
5217 // Test where fails: Value < 0
5218 try
5219 {
5220 const json element = R"( -1 )"_json;
5221 parseUint8(element);
5222 ADD_FAILURE() << "Should not have reached this line.";
5223 }
5224 catch (const std::invalid_argument& e)
5225 {
5226 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
5227 }
5228
5229 // Test where fails: Value > UINT8_MAX
5230 try
5231 {
5232 const json element = R"( 256 )"_json;
5233 parseUint8(element);
5234 ADD_FAILURE() << "Should not have reached this line.";
5235 }
5236 catch (const std::invalid_argument& e)
5237 {
5238 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
5239 }
5240}
5241
Bob King0e701132020-04-03 21:50:31 +08005242TEST(ConfigFileParserTests, ParseUnsignedInteger)
5243{
5244 // Test where works: 1
5245 {
5246 const json element = R"( 1 )"_json;
5247 unsigned int value = parseUnsignedInteger(element);
5248 EXPECT_EQ(value, 1);
5249 }
5250
5251 // Test where fails: Element is not an integer
5252 try
5253 {
5254 const json element = R"( 1.5 )"_json;
5255 parseUnsignedInteger(element);
5256 ADD_FAILURE() << "Should not have reached this line.";
5257 }
5258 catch (const std::invalid_argument& e)
5259 {
5260 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
5261 }
5262
5263 // Test where fails: Value < 0
5264 try
5265 {
5266 const json element = R"( -1 )"_json;
5267 parseUnsignedInteger(element);
5268 ADD_FAILURE() << "Should not have reached this line.";
5269 }
5270 catch (const std::invalid_argument& e)
5271 {
5272 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
5273 }
5274}
5275
Bob King84614882020-04-30 13:13:48 +08005276TEST(ConfigFileParserTests, ParseVoutDataFormat)
5277{
5278 // Test where works: linear
5279 {
5280 const json element = "linear";
5281 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element);
5282 pmbus_utils::VoutDataFormat format =
5283 pmbus_utils::VoutDataFormat::linear;
5284 EXPECT_EQ(value, format);
5285 }
5286
5287 // Test where works: vid
5288 {
5289 const json element = "vid";
5290 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element);
5291 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::vid;
5292 EXPECT_EQ(value, format);
5293 }
5294
5295 // Test where works: direct
5296 {
5297 const json element = "direct";
5298 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element);
5299 pmbus_utils::VoutDataFormat format =
5300 pmbus_utils::VoutDataFormat::direct;
5301 EXPECT_EQ(value, format);
5302 }
5303
5304 // Test where works: ieee
5305 {
5306 const json element = "ieee";
5307 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element);
5308 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::ieee;
5309 EXPECT_EQ(value, format);
5310 }
5311
5312 // Test where fails: Element is not a vout data format
5313 try
5314 {
5315 const json element = "foo";
5316 parseVoutDataFormat(element);
5317 ADD_FAILURE() << "Should not have reached this line.";
5318 }
5319 catch (const std::invalid_argument& e)
5320 {
5321 EXPECT_STREQ(e.what(), "Element is not a vout data format");
5322 }
5323
5324 // Test where fails: Element is not a string
5325 try
5326 {
5327 const json element = R"( { "foo": "bar" } )"_json;
5328 parseVoutDataFormat(element);
5329 ADD_FAILURE() << "Should not have reached this line.";
5330 }
5331 catch (const std::invalid_argument& e)
5332 {
5333 EXPECT_STREQ(e.what(), "Element is not a string");
5334 }
5335}
5336
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05005337TEST(ConfigFileParserTests, VerifyIsArray)
5338{
5339 // Test where element is an array
5340 try
5341 {
5342 const json element = R"( [ "foo", "bar" ] )"_json;
5343 verifyIsArray(element);
5344 }
5345 catch (const std::exception& e)
5346 {
5347 ADD_FAILURE() << "Should not have caught exception.";
5348 }
5349
5350 // Test where element is not an array
5351 try
5352 {
5353 const json element = R"( { "foo": "bar" } )"_json;
5354 verifyIsArray(element);
5355 ADD_FAILURE() << "Should not have reached this line.";
5356 }
5357 catch (const std::invalid_argument& e)
5358 {
5359 EXPECT_STREQ(e.what(), "Element is not an array");
5360 }
5361}
5362
5363TEST(ConfigFileParserTests, VerifyIsObject)
5364{
5365 // Test where element is an object
5366 try
5367 {
5368 const json element = R"( { "foo": "bar" } )"_json;
5369 verifyIsObject(element);
5370 }
5371 catch (const std::exception& e)
5372 {
5373 ADD_FAILURE() << "Should not have caught exception.";
5374 }
5375
5376 // Test where element is not an object
5377 try
5378 {
5379 const json element = R"( [ "foo", "bar" ] )"_json;
5380 verifyIsObject(element);
5381 ADD_FAILURE() << "Should not have reached this line.";
5382 }
5383 catch (const std::invalid_argument& e)
5384 {
5385 EXPECT_STREQ(e.what(), "Element is not an object");
5386 }
5387}
5388
5389TEST(ConfigFileParserTests, VerifyPropertyCount)
5390{
5391 // Test where element has expected number of properties
5392 try
5393 {
5394 const json element = R"(
5395 {
5396 "comments": [ "Set voltage rule" ],
5397 "id": "set_voltage_rule"
5398 }
5399 )"_json;
5400 verifyPropertyCount(element, 2);
5401 }
5402 catch (const std::exception& e)
5403 {
5404 ADD_FAILURE() << "Should not have caught exception.";
5405 }
5406
5407 // Test where element has unexpected number of properties
5408 try
5409 {
5410 const json element = R"(
5411 {
5412 "comments": [ "Set voltage rule" ],
5413 "id": "set_voltage_rule",
5414 "foo": 1.3
5415 }
5416 )"_json;
5417 verifyPropertyCount(element, 2);
5418 ADD_FAILURE() << "Should not have reached this line.";
5419 }
5420 catch (const std::invalid_argument& e)
5421 {
5422 EXPECT_STREQ(e.what(), "Element contains an invalid property");
5423 }
5424}