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