blob: c6db12dfeae78142cd88076778ff8a44d2615aee [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"
Bob Kingf09bfe02020-04-13 17:21:15 +080025#include "i2c_compare_bit_action.hpp"
26#include "i2c_compare_byte_action.hpp"
27#include "i2c_compare_bytes_action.hpp"
Bob Kingf617f892020-03-30 19:03:35 +080028#include "i2c_interface.hpp"
29#include "i2c_write_bit_action.hpp"
Bob King87ff9d72020-03-31 14:02:55 +080030#include "i2c_write_byte_action.hpp"
Bob Kingbafcb862020-03-31 16:39:00 +080031#include "i2c_write_bytes_action.hpp"
Bob Kingf1b58dc2020-04-14 14:53:10 +080032#include "not_action.hpp"
Bob King0b51a9b2020-04-15 13:24:18 +080033#include "or_action.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050034#include "pmbus_utils.hpp"
35#include "pmbus_write_vout_command_action.hpp"
Bob King9c36c5f2020-04-06 11:34:09 +080036#include "presence_detection.hpp"
37#include "rail.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050038#include "rule.hpp"
Bob King315b0b62020-04-03 21:47:58 +080039#include "run_rule_action.hpp"
Bob Kinga2f2a0d2020-04-09 13:32:14 +080040#include "sensor_monitoring.hpp"
Bob King18a68502020-04-17 14:19:56 +080041#include "set_device_action.hpp"
Shawn McCarney80c0b042020-03-27 12:08:53 -050042#include "tmp_file.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050043
Shawn McCarney80c0b042020-03-27 12:08:53 -050044#include <sys/stat.h> // for chmod()
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050045
46#include <nlohmann/json.hpp>
47
48#include <cstdint>
49#include <cstring>
50#include <exception>
51#include <filesystem>
52#include <fstream>
53#include <memory>
54#include <optional>
55#include <stdexcept>
56#include <string>
57#include <tuple>
58#include <vector>
59
60#include <gtest/gtest.h>
61
62using namespace phosphor::power::regulators;
63using namespace phosphor::power::regulators::config_file_parser;
64using namespace phosphor::power::regulators::config_file_parser::internal;
65using json = nlohmann::json;
66
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050067void writeConfigFile(const std::filesystem::path& pathName,
68 const std::string& contents)
69{
70 std::ofstream file{pathName};
71 file << contents;
72}
73
74void writeConfigFile(const std::filesystem::path& pathName,
75 const json& contents)
76{
77 std::ofstream file{pathName};
78 file << contents;
79}
80
81TEST(ConfigFileParserTests, Parse)
82{
83 // Test where works
84 {
85 const json configFileContents = R"(
86 {
87 "rules": [
88 {
89 "id": "set_voltage_rule1",
90 "actions": [
91 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
92 ]
93 },
94 {
95 "id": "set_voltage_rule2",
96 "actions": [
97 { "pmbus_write_vout_command": { "volts": 1.33, "format": "linear" } }
98 ]
99 }
100 ],
101 "chassis": [
102 { "number": 1 },
103 { "number": 2 },
104 { "number": 3 }
105 ]
106 }
107 )"_json;
108
109 TmpFile configFile;
110 std::filesystem::path pathName{configFile.getName()};
111 writeConfigFile(pathName, configFileContents);
112
113 std::vector<std::unique_ptr<Rule>> rules{};
114 std::vector<std::unique_ptr<Chassis>> chassis{};
115 std::tie(rules, chassis) = parse(pathName);
116
117 EXPECT_EQ(rules.size(), 2);
118 EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1");
119 EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2");
120
Bob King0e701132020-04-03 21:50:31 +0800121 EXPECT_EQ(chassis.size(), 3);
122 EXPECT_EQ(chassis[0]->getNumber(), 1);
123 EXPECT_EQ(chassis[1]->getNumber(), 2);
124 EXPECT_EQ(chassis[2]->getNumber(), 3);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500125 }
126
127 // Test where fails: File does not exist
128 try
129 {
130 std::filesystem::path pathName{"/tmp/non_existent_file"};
131 parse(pathName);
132 ADD_FAILURE() << "Should not have reached this line.";
133 }
134 catch (const ConfigFileParserError& e)
135 {
136 // Expected exception; what() message will vary
137 }
138
139 // Test where fails: File is not readable
140 try
141 {
142 const json configFileContents = R"(
143 {
144 "chassis": [ { "number": 1 } ]
145 }
146 )"_json;
147
148 TmpFile configFile;
149 std::filesystem::path pathName{configFile.getName()};
150 writeConfigFile(pathName, configFileContents);
151
152 chmod(pathName.c_str(), 0222);
153
154 parse(pathName);
155 ADD_FAILURE() << "Should not have reached this line.";
156 }
157 catch (const ConfigFileParserError& e)
158 {
159 // Expected exception; what() message will vary
160 }
161
162 // Test where fails: File is not valid JSON
163 try
164 {
165 const std::string configFileContents = "] foo [";
166
167 TmpFile configFile;
168 std::filesystem::path pathName{configFile.getName()};
169 writeConfigFile(pathName, configFileContents);
170
171 parse(pathName);
172 ADD_FAILURE() << "Should not have reached this line.";
173 }
174 catch (const ConfigFileParserError& e)
175 {
176 // Expected exception; what() message will vary
177 }
178
179 // Test where fails: Error when parsing JSON elements
180 try
181 {
182 const json configFileContents = R"( { "foo": "bar" } )"_json;
183
184 TmpFile configFile;
185 std::filesystem::path pathName{configFile.getName()};
186 writeConfigFile(pathName, configFileContents);
187
188 parse(pathName);
189 ADD_FAILURE() << "Should not have reached this line.";
190 }
191 catch (const ConfigFileParserError& e)
192 {
193 // Expected exception; what() message will vary
194 }
195}
196
197TEST(ConfigFileParserTests, GetRequiredProperty)
198{
199 // Test where property exists
200 {
201 const json element = R"( { "format": "linear" } )"_json;
202 const json& propertyElement = getRequiredProperty(element, "format");
203 EXPECT_EQ(propertyElement.get<std::string>(), "linear");
204 }
205
206 // Test where property does not exist
207 try
208 {
209 const json element = R"( { "volts": 1.03 } )"_json;
210 getRequiredProperty(element, "format");
211 ADD_FAILURE() << "Should not have reached this line.";
212 }
213 catch (const std::invalid_argument& e)
214 {
215 EXPECT_STREQ(e.what(), "Required property missing: format");
216 }
217}
218
219TEST(ConfigFileParserTests, ParseAction)
220{
221 // Test where works: comments property specified
222 {
223 const json element = R"(
224 {
225 "comments": [ "Set output voltage." ],
226 "pmbus_write_vout_command": {
227 "format": "linear"
228 }
229 }
230 )"_json;
231 std::unique_ptr<Action> action = parseAction(element);
232 EXPECT_NE(action.get(), nullptr);
233 }
234
235 // Test where works: comments property not specified
236 {
237 const json element = R"(
238 {
239 "pmbus_write_vout_command": {
240 "format": "linear"
241 }
242 }
243 )"_json;
244 std::unique_ptr<Action> action = parseAction(element);
245 EXPECT_NE(action.get(), nullptr);
246 }
247
248 // Test where works: and action type specified
Bob King3a787542020-04-14 13:45:01 +0800249 {
250 const json element = R"(
251 {
252 "and": [
253 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
254 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
255 ]
256 }
257 )"_json;
258 std::unique_ptr<Action> action = parseAction(element);
259 EXPECT_NE(action.get(), nullptr);
260 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500261
262 // Test where works: compare_presence action type specified
Bob Kingb267b7e2020-04-22 14:42:39 +0800263 {
264 const json element = R"(
265 {
266 "compare_presence":
267 {
268 "fru": "/system/chassis/motherboard/cpu3",
269 "value": true
270 }
271 }
272 )"_json;
273 std::unique_ptr<Action> action = parseAction(element);
274 EXPECT_NE(action.get(), nullptr);
275 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500276
277 // Test where works: compare_vpd action type specified
Bob Kingf2134322020-04-27 14:14:56 +0800278 {
279 const json element = R"(
280 {
281 "compare_vpd":
282 {
283 "fru": "/system/chassis/disk_backplane",
284 "keyword": "CCIN",
285 "value": "2D35"
286 }
287 }
288 )"_json;
289 std::unique_ptr<Action> action = parseAction(element);
290 EXPECT_NE(action.get(), nullptr);
291 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500292
293 // Test where works: i2c_compare_bit action type specified
Bob Kingf09bfe02020-04-13 17:21:15 +0800294 {
295 const json element = R"(
296 {
297 "i2c_compare_bit": {
298 "register": "0xA0",
299 "position": 3,
300 "value": 0
301 }
302 }
303 )"_json;
304 std::unique_ptr<Action> action = parseAction(element);
305 EXPECT_NE(action.get(), nullptr);
306 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500307
308 // Test where works: i2c_compare_byte action type specified
Bob Kingf09bfe02020-04-13 17:21:15 +0800309 {
310 const json element = R"(
311 {
312 "i2c_compare_byte": {
313 "register": "0x0A",
314 "value": "0xCC"
315 }
316 }
317 )"_json;
318 std::unique_ptr<Action> action = parseAction(element);
319 EXPECT_NE(action.get(), nullptr);
320 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500321
322 // Test where works: i2c_compare_bytes action type specified
Bob Kingf09bfe02020-04-13 17:21:15 +0800323 {
324 const json element = R"(
325 {
326 "i2c_compare_bytes": {
327 "register": "0x0A",
328 "values": [ "0xCC", "0xFF" ]
329 }
330 }
331 )"_json;
332 std::unique_ptr<Action> action = parseAction(element);
333 EXPECT_NE(action.get(), nullptr);
334 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500335
336 // Test where works: i2c_write_bit action type specified
Bob Kingf617f892020-03-30 19:03:35 +0800337 {
338 const json element = R"(
339 {
340 "i2c_write_bit": {
341 "register": "0xA0",
342 "position": 3,
343 "value": 0
344 }
345 }
346 )"_json;
347 std::unique_ptr<Action> action = parseAction(element);
348 EXPECT_NE(action.get(), nullptr);
349 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500350
351 // Test where works: i2c_write_byte action type specified
Bob King87ff9d72020-03-31 14:02:55 +0800352 {
353 const json element = R"(
354 {
355 "i2c_write_byte": {
356 "register": "0x0A",
357 "value": "0xCC"
358 }
359 }
360 )"_json;
361 std::unique_ptr<Action> action = parseAction(element);
362 EXPECT_NE(action.get(), nullptr);
363 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500364
365 // Test where works: i2c_write_bytes action type specified
Bob Kingbafcb862020-03-31 16:39:00 +0800366 {
367 const json element = R"(
368 {
369 "i2c_write_bytes": {
370 "register": "0x0A",
371 "values": [ "0xCC", "0xFF" ]
372 }
373 }
374 )"_json;
375 std::unique_ptr<Action> action = parseAction(element);
376 EXPECT_NE(action.get(), nullptr);
377 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500378
379 // Test where works: if action type specified
Bob King93a89d72020-04-15 15:11:11 +0800380 {
381 const json element = R"(
382 {
383 "if":
384 {
385 "condition": { "run_rule": "is_downlevel_regulator" },
386 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
387 "else": [ { "run_rule": "configure_standard_regulator" } ]
388 }
389 }
390 )"_json;
391 std::unique_ptr<Action> action = parseAction(element);
392 EXPECT_NE(action.get(), nullptr);
393 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500394
395 // Test where works: not action type specified
Bob Kingf1b58dc2020-04-14 14:53:10 +0800396 {
397 const json element = R"(
398 {
399 "not":
400 { "i2c_compare_byte": { "register": "0xA0", "value": "0xFF" } }
401 }
402 )"_json;
403 std::unique_ptr<Action> action = parseAction(element);
404 EXPECT_NE(action.get(), nullptr);
405 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500406
407 // Test where works: or action type specified
Bob King0b51a9b2020-04-15 13:24:18 +0800408 {
409 const json element = R"(
410 {
411 "or": [
412 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
413 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
414 ]
415 }
416 )"_json;
417 std::unique_ptr<Action> action = parseAction(element);
418 EXPECT_NE(action.get(), nullptr);
419 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500420
421 // Test where works: pmbus_read_sensor action type specified
422 // TODO: Not implemented yet
423
424 // Test where works: pmbus_write_vout_command action type specified
425 {
426 const json element = R"(
427 {
428 "pmbus_write_vout_command": {
429 "format": "linear"
430 }
431 }
432 )"_json;
433 std::unique_ptr<Action> action = parseAction(element);
434 EXPECT_NE(action.get(), nullptr);
435 }
436
437 // Test where works: run_rule action type specified
Bob King315b0b62020-04-03 21:47:58 +0800438 {
439 const json element = R"(
440 {
441 "run_rule": "set_voltage_rule"
442 }
443 )"_json;
444 std::unique_ptr<Action> action = parseAction(element);
445 EXPECT_NE(action.get(), nullptr);
446 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500447
448 // Test where works: set_device action type specified
Bob King18a68502020-04-17 14:19:56 +0800449 {
450 const json element = R"(
451 {
452 "set_device": "io_expander2"
453 }
454 )"_json;
455 std::unique_ptr<Action> action = parseAction(element);
456 EXPECT_NE(action.get(), nullptr);
457 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500458
459 // Test where fails: Element is not an object
460 try
461 {
462 const json element = R"( [ "0xFF", "0x01" ] )"_json;
463 parseAction(element);
464 ADD_FAILURE() << "Should not have reached this line.";
465 }
466 catch (const std::invalid_argument& e)
467 {
468 EXPECT_STREQ(e.what(), "Element is not an object");
469 }
470
471 // Test where fails: No action type specified
472 try
473 {
474 const json element = R"(
475 {
476 "comments": [ "Set output voltage." ]
477 }
478 )"_json;
479 parseAction(element);
480 ADD_FAILURE() << "Should not have reached this line.";
481 }
482 catch (const std::invalid_argument& e)
483 {
484 EXPECT_STREQ(e.what(), "Required action type property missing");
485 }
486
487 // Test where fails: Multiple action types specified
Bob King0e701132020-04-03 21:50:31 +0800488 try
489 {
490 const json element = R"(
491 {
492 "pmbus_write_vout_command": { "format": "linear" },
493 "run_rule": "set_voltage_rule"
494 }
495 )"_json;
496 parseAction(element);
497 ADD_FAILURE() << "Should not have reached this line.";
498 }
499 catch (const std::invalid_argument& e)
500 {
501 EXPECT_STREQ(e.what(), "Element contains an invalid property");
502 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500503
504 // Test where fails: Invalid property specified
505 try
506 {
507 const json element = R"(
508 {
509 "remarks": [ "Set output voltage." ],
510 "pmbus_write_vout_command": {
511 "format": "linear"
512 }
513 }
514 )"_json;
515 parseAction(element);
516 ADD_FAILURE() << "Should not have reached this line.";
517 }
518 catch (const std::invalid_argument& e)
519 {
520 EXPECT_STREQ(e.what(), "Element contains an invalid property");
521 }
522}
523
524TEST(ConfigFileParserTests, ParseActionArray)
525{
526 // Test where works
527 {
528 const json element = R"(
529 [
530 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
531 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
532 ]
533 )"_json;
534 std::vector<std::unique_ptr<Action>> actions =
535 parseActionArray(element);
536 EXPECT_EQ(actions.size(), 2);
537 }
538
539 // Test where fails: Element is not an array
540 try
541 {
542 const json element = R"(
543 {
544 "foo": "bar"
545 }
546 )"_json;
547 parseActionArray(element);
548 ADD_FAILURE() << "Should not have reached this line.";
549 }
550 catch (const std::invalid_argument& e)
551 {
552 EXPECT_STREQ(e.what(), "Element is not an array");
553 }
554}
555
Bob King3a787542020-04-14 13:45:01 +0800556TEST(ConfigFileParserTests, ParseAnd)
557{
558 // Test where works: Element is an array with 2 actions
559 {
560 const json element = R"(
561 [
562 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
563 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
564 ]
565 )"_json;
566 std::unique_ptr<AndAction> action = parseAnd(element);
567 EXPECT_EQ(action->getActions().size(), 2);
568 }
569
570 // Test where fails: Element is an array with 1 action
571 try
572 {
573 const json element = R"(
574 [
575 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }
576 ]
577 )"_json;
578 parseAnd(element);
579 ADD_FAILURE() << "Should not have reached this line.";
580 }
581 catch (const std::invalid_argument& e)
582 {
583 EXPECT_STREQ(e.what(), "Array must contain two or more actions");
584 }
585
586 // Test where fails: Element is not an array
587 try
588 {
589 const json element = R"(
590 {
591 "foo": "bar"
592 }
593 )"_json;
594 parseAnd(element);
595 ADD_FAILURE() << "Should not have reached this line.";
596 }
597 catch (const std::invalid_argument& e)
598 {
599 EXPECT_STREQ(e.what(), "Element is not an array");
600 }
601}
602
Bob Kingf617f892020-03-30 19:03:35 +0800603TEST(ConfigFileParserTests, ParseBitPosition)
604{
605 // Test where works: 0
606 {
607 const json element = R"( 0 )"_json;
608 uint8_t value = parseBitPosition(element);
609 EXPECT_EQ(value, 0);
610 }
611
612 // Test where works: 7
613 {
614 const json element = R"( 7 )"_json;
615 uint8_t value = parseBitPosition(element);
616 EXPECT_EQ(value, 7);
617 }
618
619 // Test where fails: Element is not an integer
620 try
621 {
622 const json element = R"( 1.03 )"_json;
623 parseBitPosition(element);
624 ADD_FAILURE() << "Should not have reached this line.";
625 }
626 catch (const std::invalid_argument& e)
627 {
628 EXPECT_STREQ(e.what(), "Element is not an integer");
629 }
630
631 // Test where fails: Value < 0
632 try
633 {
634 const json element = R"( -1 )"_json;
635 parseBitPosition(element);
636 ADD_FAILURE() << "Should not have reached this line.";
637 }
638 catch (const std::invalid_argument& e)
639 {
640 EXPECT_STREQ(e.what(), "Element is not a bit position");
641 }
642
643 // Test where fails: Value > 7
644 try
645 {
646 const json element = R"( 8 )"_json;
647 parseBitPosition(element);
648 ADD_FAILURE() << "Should not have reached this line.";
649 }
650 catch (const std::invalid_argument& e)
651 {
652 EXPECT_STREQ(e.what(), "Element is not a bit position");
653 }
654}
655
656TEST(ConfigFileParserTests, ParseBitValue)
657{
658 // Test where works: 0
659 {
660 const json element = R"( 0 )"_json;
661 uint8_t value = parseBitValue(element);
662 EXPECT_EQ(value, 0);
663 }
664
665 // Test where works: 1
666 {
667 const json element = R"( 1 )"_json;
668 uint8_t value = parseBitValue(element);
669 EXPECT_EQ(value, 1);
670 }
671
672 // Test where fails: Element is not an integer
673 try
674 {
675 const json element = R"( 0.5 )"_json;
676 parseBitValue(element);
677 ADD_FAILURE() << "Should not have reached this line.";
678 }
679 catch (const std::invalid_argument& e)
680 {
681 EXPECT_STREQ(e.what(), "Element is not an integer");
682 }
683
684 // Test where fails: Value < 0
685 try
686 {
687 const json element = R"( -1 )"_json;
688 parseBitValue(element);
689 ADD_FAILURE() << "Should not have reached this line.";
690 }
691 catch (const std::invalid_argument& e)
692 {
693 EXPECT_STREQ(e.what(), "Element is not a bit value");
694 }
695
696 // Test where fails: Value > 1
697 try
698 {
699 const json element = R"( 2 )"_json;
700 parseBitValue(element);
701 ADD_FAILURE() << "Should not have reached this line.";
702 }
703 catch (const std::invalid_argument& e)
704 {
705 EXPECT_STREQ(e.what(), "Element is not a bit value");
706 }
707}
708
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500709TEST(ConfigFileParserTests, ParseBoolean)
710{
711 // Test where works: true
712 {
713 const json element = R"( true )"_json;
714 bool value = parseBoolean(element);
715 EXPECT_EQ(value, true);
716 }
717
718 // Test where works: false
719 {
720 const json element = R"( false )"_json;
721 bool value = parseBoolean(element);
722 EXPECT_EQ(value, false);
723 }
724
725 // Test where fails: Element is not a boolean
726 try
727 {
728 const json element = R"( 1 )"_json;
729 parseBoolean(element);
730 ADD_FAILURE() << "Should not have reached this line.";
731 }
732 catch (const std::invalid_argument& e)
733 {
734 EXPECT_STREQ(e.what(), "Element is not a boolean");
735 }
736}
737
Bob King0e701132020-04-03 21:50:31 +0800738TEST(ConfigFileParserTests, ParseChassis)
739{
740 // Test where works: Only required properties specified
741 {
742 const json element = R"(
743 {
744 "number": 1
745 }
746 )"_json;
747 std::unique_ptr<Chassis> chassis = parseChassis(element);
748 EXPECT_EQ(chassis->getNumber(), 1);
Bob King9c36c5f2020-04-06 11:34:09 +0800749 EXPECT_EQ(chassis->getDevices().size(), 0);
Bob King0e701132020-04-03 21:50:31 +0800750 }
751
752 // Test where works: All properties specified
753 {
754 const json element = R"(
755 {
756 "comments": [ "comments property" ],
757 "number": 2,
758 "devices": [
759 {
760 "id": "vdd_regulator",
761 "is_regulator": true,
762 "fru": "/system/chassis/motherboard/regulator2",
763 "i2c_interface":
764 {
765 "bus": 1,
766 "address": "0x70"
767 }
768 }
769 ]
770 }
771 )"_json;
772 std::unique_ptr<Chassis> chassis = parseChassis(element);
773 EXPECT_EQ(chassis->getNumber(), 2);
Bob King9c36c5f2020-04-06 11:34:09 +0800774 EXPECT_EQ(chassis->getDevices().size(), 1);
775 EXPECT_EQ(chassis->getDevices()[0]->getID(), "vdd_regulator");
Bob King0e701132020-04-03 21:50:31 +0800776 }
777
778 // Test where fails: number value is invalid
779 try
780 {
781 const json element = R"(
782 {
783 "number": 0.5
784 }
785 )"_json;
786 parseChassis(element);
787 ADD_FAILURE() << "Should not have reached this line.";
788 }
789 catch (const std::invalid_argument& e)
790 {
791 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
792 }
793
794 // Test where fails: Invalid property specified
795 try
796 {
797 const json element = R"(
798 {
799 "number": 1,
800 "foo": 2
801 }
802 )"_json;
803 parseChassis(element);
804 ADD_FAILURE() << "Should not have reached this line.";
805 }
806 catch (const std::invalid_argument& e)
807 {
808 EXPECT_STREQ(e.what(), "Element contains an invalid property");
809 }
810
811 // Test where fails: Required number property not specified
812 try
813 {
814 const json element = R"(
815 {
816 "devices": [
817 {
818 "id": "vdd_regulator",
819 "is_regulator": true,
820 "fru": "/system/chassis/motherboard/regulator2",
821 "i2c_interface":
822 {
823 "bus": 1,
824 "address": "0x70"
825 }
826 }
827 ]
828 }
829 )"_json;
830 parseChassis(element);
831 ADD_FAILURE() << "Should not have reached this line.";
832 }
833 catch (const std::invalid_argument& e)
834 {
835 EXPECT_STREQ(e.what(), "Required property missing: number");
836 }
837
838 // Test where fails: Element is not an object
839 try
840 {
841 const json element = R"( [ "0xFF", "0x01" ] )"_json;
842 parseChassis(element);
843 ADD_FAILURE() << "Should not have reached this line.";
844 }
845 catch (const std::invalid_argument& e)
846 {
847 EXPECT_STREQ(e.what(), "Element is not an object");
848 }
849
850 // Test where fails: number value is < 1
851 try
852 {
853 const json element = R"(
854 {
855 "number": 0
856 }
857 )"_json;
858 parseChassis(element);
859 ADD_FAILURE() << "Should not have reached this line.";
860 }
861 catch (const std::invalid_argument& e)
862 {
863 EXPECT_STREQ(e.what(), "Invalid chassis number: Must be > 0");
864 }
865
866 // Test where fails: devices value is invalid
867 try
868 {
869 const json element = R"(
870 {
871 "number": 1,
872 "devices": 2
873 }
874 )"_json;
875 parseChassis(element);
876 ADD_FAILURE() << "Should not have reached this line.";
877 }
878 catch (const std::invalid_argument& e)
879 {
880 EXPECT_STREQ(e.what(), "Element is not an array");
881 }
882}
883
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500884TEST(ConfigFileParserTests, ParseChassisArray)
885{
Bob King0e701132020-04-03 21:50:31 +0800886 // Test where works
887 {
888 const json element = R"(
889 [
890 { "number": 1 },
891 { "number": 2 }
892 ]
893 )"_json;
894 std::vector<std::unique_ptr<Chassis>> chassis =
895 parseChassisArray(element);
896 EXPECT_EQ(chassis.size(), 2);
897 EXPECT_EQ(chassis[0]->getNumber(), 1);
898 EXPECT_EQ(chassis[1]->getNumber(), 2);
899 }
900
901 // Test where fails: Element is not an array
902 try
903 {
904 const json element = R"(
905 {
906 "foo": "bar"
907 }
908 )"_json;
909 parseChassisArray(element);
910 ADD_FAILURE() << "Should not have reached this line.";
911 }
912 catch (const std::invalid_argument& e)
913 {
914 EXPECT_STREQ(e.what(), "Element is not an array");
915 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500916}
917
Bob Kingb267b7e2020-04-22 14:42:39 +0800918TEST(ConfigFileParserTests, ParseComparePresence)
919{
920 // Test where works
921 {
922 const json element = R"(
923 {
924 "fru": "/system/chassis/motherboard/cpu3",
925 "value": true
926 }
927 )"_json;
928 std::unique_ptr<ComparePresenceAction> action =
929 parseComparePresence(element);
930 EXPECT_EQ(action->getFRU(), "/system/chassis/motherboard/cpu3");
931 EXPECT_EQ(action->getValue(), true);
932 }
933
934 // Test where fails: Element is not an object
935 try
936 {
937 const json element = R"( [ "0xFF", "0x01" ] )"_json;
938 parseComparePresence(element);
939 ADD_FAILURE() << "Should not have reached this line.";
940 }
941 catch (const std::invalid_argument& e)
942 {
943 EXPECT_STREQ(e.what(), "Element is not an object");
944 }
945
946 // Test where fails: Invalid property specified
947 try
948 {
949 const json element = R"(
950 {
951 "fru": "/system/chassis/motherboard/cpu3",
952 "value": true,
953 "foo" : true
954 }
955 )"_json;
956 parseComparePresence(element);
957 ADD_FAILURE() << "Should not have reached this line.";
958 }
959 catch (const std::invalid_argument& e)
960 {
961 EXPECT_STREQ(e.what(), "Element contains an invalid property");
962 }
963
964 // Test where fails: Required fru property not specified
965 try
966 {
967 const json element = R"(
968 {
969 "value": true
970 }
971 )"_json;
972 parseComparePresence(element);
973 ADD_FAILURE() << "Should not have reached this line.";
974 }
975 catch (const std::invalid_argument& e)
976 {
977 EXPECT_STREQ(e.what(), "Required property missing: fru");
978 }
979
980 // Test where fails: Required value property not specified
981 try
982 {
983 const json element = R"(
984 {
985 "fru": "/system/chassis/motherboard/cpu3"
986 }
987 )"_json;
988 parseComparePresence(element);
989 ADD_FAILURE() << "Should not have reached this line.";
990 }
991 catch (const std::invalid_argument& e)
992 {
993 EXPECT_STREQ(e.what(), "Required property missing: value");
994 }
995
996 // Test where fails: fru value is invalid
997 try
998 {
999 const json element = R"(
1000 {
1001 "fru": 1,
1002 "value": true
1003 }
1004 )"_json;
1005 parseComparePresence(element);
1006 ADD_FAILURE() << "Should not have reached this line.";
1007 }
1008 catch (const std::invalid_argument& e)
1009 {
1010 EXPECT_STREQ(e.what(), "Element is not a string");
1011 }
1012
1013 // Test where fails: value value is invalid
1014 try
1015 {
1016 const json element = R"(
1017 {
1018 "fru": "/system/chassis/motherboard/cpu3",
1019 "value": 1
1020 }
1021 )"_json;
1022 parseComparePresence(element);
1023 ADD_FAILURE() << "Should not have reached this line.";
1024 }
1025 catch (const std::invalid_argument& e)
1026 {
1027 EXPECT_STREQ(e.what(), "Element is not a boolean");
1028 }
1029}
1030
Bob Kingf2134322020-04-27 14:14:56 +08001031TEST(ConfigFileParserTests, ParseCompareVPD)
1032{
1033 // Test where works
1034 {
1035 const json element = R"(
1036 {
1037 "fru": "/system/chassis/disk_backplane",
1038 "keyword": "CCIN",
1039 "value": "2D35"
1040 }
1041 )"_json;
1042 std::unique_ptr<CompareVPDAction> action = parseCompareVPD(element);
1043 EXPECT_EQ(action->getFRU(), "/system/chassis/disk_backplane");
1044 EXPECT_EQ(action->getKeyword(), "CCIN");
1045 EXPECT_EQ(action->getValue(), "2D35");
1046 }
1047
1048 // Test where fails: Element is not an object
1049 try
1050 {
1051 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1052 parseCompareVPD(element);
1053 ADD_FAILURE() << "Should not have reached this line.";
1054 }
1055 catch (const std::invalid_argument& e)
1056 {
1057 EXPECT_STREQ(e.what(), "Element is not an object");
1058 }
1059
1060 // Test where fails: Invalid property specified
1061 try
1062 {
1063 const json element = R"(
1064 {
1065 "fru": "/system/chassis/disk_backplane",
1066 "keyword": "CCIN",
1067 "value": "2D35",
1068 "foo" : true
1069 }
1070 )"_json;
1071 parseCompareVPD(element);
1072 ADD_FAILURE() << "Should not have reached this line.";
1073 }
1074 catch (const std::invalid_argument& e)
1075 {
1076 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1077 }
1078
1079 // Test where fails: Required fru property not specified
1080 try
1081 {
1082 const json element = R"(
1083 {
1084 "keyword": "CCIN",
1085 "value": "2D35"
1086 }
1087 )"_json;
1088 parseCompareVPD(element);
1089 ADD_FAILURE() << "Should not have reached this line.";
1090 }
1091 catch (const std::invalid_argument& e)
1092 {
1093 EXPECT_STREQ(e.what(), "Required property missing: fru");
1094 }
1095
1096 // Test where fails: Required keyword property not specified
1097 try
1098 {
1099 const json element = R"(
1100 {
1101 "fru": "/system/chassis/disk_backplane",
1102 "value": "2D35"
1103 }
1104 )"_json;
1105 parseCompareVPD(element);
1106 ADD_FAILURE() << "Should not have reached this line.";
1107 }
1108 catch (const std::invalid_argument& e)
1109 {
1110 EXPECT_STREQ(e.what(), "Required property missing: keyword");
1111 }
1112
1113 // Test where fails: Required value property not specified
1114 try
1115 {
1116 const json element = R"(
1117 {
1118 "fru": "/system/chassis/disk_backplane",
1119 "keyword": "CCIN"
1120 }
1121 )"_json;
1122 parseCompareVPD(element);
1123 ADD_FAILURE() << "Should not have reached this line.";
1124 }
1125 catch (const std::invalid_argument& e)
1126 {
1127 EXPECT_STREQ(e.what(), "Required property missing: value");
1128 }
1129
1130 // Test where fails: fru value is invalid
1131 try
1132 {
1133 const json element = R"(
1134 {
1135 "fru": 1,
1136 "keyword": "CCIN",
1137 "value": "2D35"
1138 }
1139 )"_json;
1140 parseCompareVPD(element);
1141 ADD_FAILURE() << "Should not have reached this line.";
1142 }
1143 catch (const std::invalid_argument& e)
1144 {
1145 EXPECT_STREQ(e.what(), "Element is not a string");
1146 }
1147
1148 // Test where fails: keyword value is invalid
1149 try
1150 {
1151 const json element = R"(
1152 {
1153 "fru": "/system/chassis/disk_backplane",
1154 "keyword": 1,
1155 "value": "2D35"
1156 }
1157 )"_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 a string");
1164 }
1165
1166 // Test where fails: value value is invalid
1167 try
1168 {
1169 const json element = R"(
1170 {
1171 "fru": "/system/chassis/disk_backplane",
1172 "keyword": "CCIN",
1173 "value": 1
1174 }
1175 )"_json;
1176 parseCompareVPD(element);
1177 ADD_FAILURE() << "Should not have reached this line.";
1178 }
1179 catch (const std::invalid_argument& e)
1180 {
1181 EXPECT_STREQ(e.what(), "Element is not a string");
1182 }
1183}
1184
Bob King33e7eaa2020-04-01 18:09:34 +08001185TEST(ConfigFileParserTests, ParseConfiguration)
1186{
1187 // Test where works: actions required property specified
1188 {
1189 const json element = R"(
1190 {
1191 "actions": [
1192 {
1193 "pmbus_write_vout_command": {
1194 "format": "linear"
1195 }
1196 }
1197 ]
1198 }
1199 )"_json;
1200 std::unique_ptr<Configuration> configuration =
1201 parseConfiguration(element);
1202 EXPECT_EQ(configuration->getActions().size(), 1);
1203 EXPECT_EQ(configuration->getVolts().has_value(), false);
1204 }
1205
1206 // Test where works: volts and actions properties specified
1207 {
1208 const json element = R"(
1209 {
1210 "comments": [ "comments property" ],
1211 "volts": 1.03,
1212 "actions": [
1213 { "pmbus_write_vout_command": { "format": "linear" } },
1214 { "run_rule": "set_voltage_rule" }
1215 ]
1216 }
1217 )"_json;
1218 std::unique_ptr<Configuration> configuration =
1219 parseConfiguration(element);
1220 EXPECT_EQ(configuration->getVolts().has_value(), true);
1221 EXPECT_EQ(configuration->getVolts().value(), 1.03);
1222 EXPECT_EQ(configuration->getActions().size(), 2);
1223 }
1224
1225 // Test where works: volts and rule_id properties specified
1226 {
1227 const json element = R"(
1228 {
1229 "volts": 1.05,
1230 "rule_id": "set_voltage_rule"
1231 }
1232 )"_json;
1233 std::unique_ptr<Configuration> configuration =
1234 parseConfiguration(element);
1235 EXPECT_EQ(configuration->getVolts().has_value(), true);
1236 EXPECT_EQ(configuration->getVolts().value(), 1.05);
1237 EXPECT_EQ(configuration->getActions().size(), 1);
1238 }
1239
1240 // Test where fails: volts value is invalid
1241 try
1242 {
1243 const json element = R"(
1244 {
1245 "volts": "foo",
1246 "actions": [
1247 {
1248 "pmbus_write_vout_command": {
1249 "format": "linear"
1250 }
1251 }
1252 ]
1253 }
1254 )"_json;
1255 parseConfiguration(element);
1256 ADD_FAILURE() << "Should not have reached this line.";
1257 }
1258 catch (const std::invalid_argument& e)
1259 {
1260 EXPECT_STREQ(e.what(), "Element is not a number");
1261 }
1262
1263 // Test where fails: actions object is invalid
1264 try
1265 {
1266 const json element = R"(
1267 {
1268 "volts": 1.03,
1269 "actions": 1
1270 }
1271 )"_json;
1272 parseConfiguration(element);
1273 ADD_FAILURE() << "Should not have reached this line.";
1274 }
1275 catch (const std::invalid_argument& e)
1276 {
1277 EXPECT_STREQ(e.what(), "Element is not an array");
1278 }
1279
1280 // Test where fails: rule_id value is invalid
1281 try
1282 {
1283 const json element = R"(
1284 {
1285 "volts": 1.05,
1286 "rule_id": 1
1287 }
1288 )"_json;
1289 parseConfiguration(element);
1290 ADD_FAILURE() << "Should not have reached this line.";
1291 }
1292 catch (const std::invalid_argument& e)
1293 {
1294 EXPECT_STREQ(e.what(), "Element is not a string");
1295 }
1296
1297 // Test where fails: Required actions or rule_id property not specified
1298 try
1299 {
1300 const json element = R"(
1301 {
1302 "volts": 1.03
1303 }
1304 )"_json;
1305 parseConfiguration(element);
1306 ADD_FAILURE() << "Should not have reached this line.";
1307 }
1308 catch (const std::invalid_argument& e)
1309 {
1310 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
1311 "either rule_id or actions");
1312 }
1313
1314 // Test where fails: Required actions or rule_id property both specified
1315 try
1316 {
1317 const json element = R"(
1318 {
1319 "volts": 1.03,
1320 "rule_id": "set_voltage_rule",
1321 "actions": [
1322 {
1323 "pmbus_write_vout_command": {
1324 "format": "linear"
1325 }
1326 }
1327 ]
1328 }
1329 )"_json;
1330 parseConfiguration(element);
1331 ADD_FAILURE() << "Should not have reached this line.";
1332 }
1333 catch (const std::invalid_argument& e)
1334 {
1335 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
1336 "either rule_id or actions");
1337 }
1338
1339 // Test where fails: Element is not an object
1340 try
1341 {
1342 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1343 parseConfiguration(element);
1344 ADD_FAILURE() << "Should not have reached this line.";
1345 }
1346 catch (const std::invalid_argument& e)
1347 {
1348 EXPECT_STREQ(e.what(), "Element is not an object");
1349 }
1350
1351 // Test where fails: Invalid property specified
1352 try
1353 {
1354 const json element = R"(
1355 {
1356 "volts": 1.03,
1357 "rule_id": "set_voltage_rule",
1358 "foo": 1
1359 }
1360 )"_json;
1361 parseConfiguration(element);
1362 ADD_FAILURE() << "Should not have reached this line.";
1363 }
1364 catch (const std::invalid_argument& e)
1365 {
1366 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1367 }
1368}
1369
Bob King9c36c5f2020-04-06 11:34:09 +08001370TEST(ConfigFileParserTests, ParseDevice)
1371{
1372 // Test where works: Only required properties specified
1373 {
1374 const json element = R"(
1375 {
1376 "id": "vdd_regulator",
1377 "is_regulator": true,
1378 "fru": "/system/chassis/motherboard/regulator2",
1379 "i2c_interface": { "bus": 1, "address": "0x70" }
1380 }
1381 )"_json;
1382 std::unique_ptr<Device> device = parseDevice(element);
1383 EXPECT_EQ(device->getID(), "vdd_regulator");
1384 EXPECT_EQ(device->isRegulator(), true);
1385 EXPECT_EQ(device->getFRU(), "/system/chassis/motherboard/regulator2");
1386 EXPECT_NE(&(device->getI2CInterface()), nullptr);
1387 EXPECT_EQ(device->getPresenceDetection(), nullptr);
1388 EXPECT_EQ(device->getConfiguration(), nullptr);
1389 EXPECT_EQ(device->getRails().size(), 0);
1390 }
1391
1392 // Test where works: All properties specified
Bob King33e7eaa2020-04-01 18:09:34 +08001393 {
Bob King33e7eaa2020-04-01 18:09:34 +08001394 const json element = R"(
1395 {
1396 "id": "vdd_regulator",
1397 "is_regulator": true,
1398 "fru": "/system/chassis/motherboard/regulator2",
1399 "i2c_interface":
1400 {
1401 "bus": 1,
1402 "address": "0x70"
1403 },
1404 "configuration":
1405 {
1406 "rule_id": "configure_ir35221_rule"
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001407 },
Bob King2aafb1c2020-04-16 15:24:32 +08001408 "presence_detection":
1409 {
1410 "rule_id": "is_foobar_backplane_installed_rule"
1411 },
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001412 "rails":
1413 [
1414 {
1415 "id": "vdd"
1416 }
1417 ]
Bob King33e7eaa2020-04-01 18:09:34 +08001418 }
1419 )"_json;
1420 std::unique_ptr<Device> device = parseDevice(element);
1421 EXPECT_EQ(device->getID(), "vdd_regulator");
1422 EXPECT_EQ(device->isRegulator(), true);
1423 EXPECT_EQ(device->getFRU(), "/system/chassis/motherboard/regulator2");
1424 EXPECT_NE(&(device->getI2CInterface()), nullptr);
Bob King2aafb1c2020-04-16 15:24:32 +08001425 EXPECT_NE(device->getPresenceDetection(), nullptr);
Bob King33e7eaa2020-04-01 18:09:34 +08001426 EXPECT_NE(device->getConfiguration(), nullptr);
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001427 EXPECT_EQ(device->getRails().size(), 1);
1428 }
1429
1430 // Test where fails: rails property exists and is_regulator is false
1431 try
1432 {
1433 const json element = R"(
1434 {
1435 "id": "vdd_regulator",
1436 "is_regulator": false,
1437 "fru": "/system/chassis/motherboard/regulator2",
1438 "i2c_interface":
1439 {
1440 "bus": 1,
1441 "address": "0x70"
1442 },
1443 "configuration":
1444 {
1445 "rule_id": "configure_ir35221_rule"
1446 },
1447 "rails":
1448 [
1449 {
1450 "id": "vdd"
1451 }
1452 ]
1453 }
1454 )"_json;
1455 parseDevice(element);
1456 ADD_FAILURE() << "Should not have reached this line.";
1457 }
1458 catch (const std::invalid_argument& e)
1459 {
1460 EXPECT_STREQ(e.what(),
1461 "Invalid rails property when is_regulator is false");
Bob King33e7eaa2020-04-01 18:09:34 +08001462 }
Bob King9c36c5f2020-04-06 11:34:09 +08001463
1464 // Test where fails: id value is invalid
1465 try
1466 {
1467 const json element = R"(
1468 {
1469 "id": 3,
1470 "is_regulator": true,
1471 "fru": "/system/chassis/motherboard/regulator2",
1472 "i2c_interface":
1473 {
1474 "bus": 1,
1475 "address": "0x70"
1476 }
1477 }
1478 )"_json;
1479 parseDevice(element);
1480 ADD_FAILURE() << "Should not have reached this line.";
1481 }
1482 catch (const std::invalid_argument& e)
1483 {
1484 EXPECT_STREQ(e.what(), "Element is not a string");
1485 }
1486
1487 // Test where fails: is_regulator value is invalid
1488 try
1489 {
1490 const json element = R"(
1491 {
1492 "id": "vdd_regulator",
1493 "is_regulator": 3,
1494 "fru": "/system/chassis/motherboard/regulator2",
1495 "i2c_interface":
1496 {
1497 "bus": 1,
1498 "address": "0x70"
1499 }
1500 }
1501 )"_json;
1502 parseDevice(element);
1503 ADD_FAILURE() << "Should not have reached this line.";
1504 }
1505 catch (const std::invalid_argument& e)
1506 {
1507 EXPECT_STREQ(e.what(), "Element is not a boolean");
1508 }
1509
1510 // Test where fails: fru value is invalid
1511 try
1512 {
1513 const json element = R"(
1514 {
1515 "id": "vdd_regulator",
1516 "is_regulator": true,
1517 "fru": 2,
1518 "i2c_interface":
1519 {
1520 "bus": 1,
1521 "address": "0x70"
1522 }
1523 }
1524 )"_json;
1525 parseDevice(element);
1526 ADD_FAILURE() << "Should not have reached this line.";
1527 }
1528 catch (const std::invalid_argument& e)
1529 {
1530 EXPECT_STREQ(e.what(), "Element is not a string");
1531 }
1532
1533 // Test where fails: i2c_interface value is invalid
1534 try
1535 {
1536 const json element = R"(
1537 {
1538 "id": "vdd_regulator",
1539 "is_regulator": true,
1540 "fru": "/system/chassis/motherboard/regulator2",
1541 "i2c_interface": 3
1542 }
1543 )"_json;
1544 parseDevice(element);
1545 ADD_FAILURE() << "Should not have reached this line.";
1546 }
1547 catch (const std::invalid_argument& e)
1548 {
1549 EXPECT_STREQ(e.what(), "Element is not an object");
1550 }
1551
1552 // Test where fails: Required id property not specified
1553 try
1554 {
1555 const json element = R"(
1556 {
1557 "is_regulator": true,
1558 "fru": "/system/chassis/motherboard/regulator2",
1559 "i2c_interface":
1560 {
1561 "bus": 1,
1562 "address": "0x70"
1563 }
1564 }
1565 )"_json;
1566 parseDevice(element);
1567 ADD_FAILURE() << "Should not have reached this line.";
1568 }
1569 catch (const std::invalid_argument& e)
1570 {
1571 EXPECT_STREQ(e.what(), "Required property missing: id");
1572 }
1573
1574 // Test where fails: Required is_regulator property not specified
1575 try
1576 {
1577 const json element = R"(
1578 {
1579 "id": "vdd_regulator",
1580 "fru": "/system/chassis/motherboard/regulator2",
1581 "i2c_interface":
1582 {
1583 "bus": 1,
1584 "address": "0x70"
1585 }
1586 }
1587 )"_json;
1588 parseDevice(element);
1589 ADD_FAILURE() << "Should not have reached this line.";
1590 }
1591 catch (const std::invalid_argument& e)
1592 {
1593 EXPECT_STREQ(e.what(), "Required property missing: is_regulator");
1594 }
1595
1596 // Test where fails: Required fru property not specified
1597 try
1598 {
1599 const json element = R"(
1600 {
1601 "id": "vdd_regulator",
1602 "is_regulator": true,
1603 "i2c_interface":
1604 {
1605 "bus": 1,
1606 "address": "0x70"
1607 }
1608 }
1609 )"_json;
1610 parseDevice(element);
1611 ADD_FAILURE() << "Should not have reached this line.";
1612 }
1613 catch (const std::invalid_argument& e)
1614 {
1615 EXPECT_STREQ(e.what(), "Required property missing: fru");
1616 }
1617
1618 // Test where fails: Required i2c_interface property not specified
1619 try
1620 {
1621 const json element = R"(
1622 {
1623 "id": "vdd_regulator",
1624 "is_regulator": true,
1625 "fru": "/system/chassis/motherboard/regulator2"
1626 }
1627 )"_json;
1628 parseDevice(element);
1629 ADD_FAILURE() << "Should not have reached this line.";
1630 }
1631 catch (const std::invalid_argument& e)
1632 {
1633 EXPECT_STREQ(e.what(), "Required property missing: i2c_interface");
1634 }
1635
1636 // Test where fails: Element is not an object
1637 try
1638 {
1639 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1640 parseDevice(element);
1641 ADD_FAILURE() << "Should not have reached this line.";
1642 }
1643 catch (const std::invalid_argument& e)
1644 {
1645 EXPECT_STREQ(e.what(), "Element is not an object");
1646 }
1647
1648 // Test where fails: Invalid property specified
1649 try
1650 {
1651 const json element = R"(
1652 {
1653 "id": "vdd_regulator",
1654 "is_regulator": true,
1655 "fru": "/system/chassis/motherboard/regulator2",
1656 "i2c_interface": { "bus": 1, "address": "0x70" },
1657 "foo" : true
1658 }
1659 )"_json;
1660 parseDevice(element);
1661 ADD_FAILURE() << "Should not have reached this line.";
1662 }
1663 catch (const std::invalid_argument& e)
1664 {
1665 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1666 }
1667}
1668
1669TEST(ConfigFileParserTests, ParseDeviceArray)
1670{
1671 // Test where works
1672 {
1673 const json element = R"(
1674 [
1675 {
1676 "id": "vdd_regulator",
1677 "is_regulator": true,
1678 "fru": "/system/chassis/motherboard/regulator2",
1679 "i2c_interface": { "bus": 1, "address": "0x70" }
1680 },
1681 {
1682 "id": "vio_regulator",
1683 "is_regulator": true,
1684 "fru": "/system/chassis/motherboard/regulator2",
1685 "i2c_interface": { "bus": 1, "address": "0x71" }
1686 }
1687 ]
1688 )"_json;
1689 std::vector<std::unique_ptr<Device>> devices =
1690 parseDeviceArray(element);
1691 EXPECT_EQ(devices.size(), 2);
1692 EXPECT_EQ(devices[0]->getID(), "vdd_regulator");
1693 EXPECT_EQ(devices[1]->getID(), "vio_regulator");
1694 }
1695
1696 // Test where fails: Element is not an array
1697 try
1698 {
1699 const json element = R"(
1700 {
1701 "foo": "bar"
1702 }
1703 )"_json;
1704 parseDeviceArray(element);
1705 ADD_FAILURE() << "Should not have reached this line.";
1706 }
1707 catch (const std::invalid_argument& e)
1708 {
1709 EXPECT_STREQ(e.what(), "Element is not an array");
1710 }
1711}
1712
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001713TEST(ConfigFileParserTests, ParseDouble)
1714{
1715 // Test where works: floating point value
1716 {
1717 const json element = R"( 1.03 )"_json;
1718 double value = parseDouble(element);
1719 EXPECT_EQ(value, 1.03);
1720 }
1721
1722 // Test where works: integer value
1723 {
1724 const json element = R"( 24 )"_json;
1725 double value = parseDouble(element);
1726 EXPECT_EQ(value, 24.0);
1727 }
1728
1729 // Test where fails: Element is not a number
1730 try
1731 {
1732 const json element = R"( true )"_json;
1733 parseDouble(element);
1734 ADD_FAILURE() << "Should not have reached this line.";
1735 }
1736 catch (const std::invalid_argument& e)
1737 {
1738 EXPECT_STREQ(e.what(), "Element is not a number");
1739 }
1740}
1741
Bob Kingbafcb862020-03-31 16:39:00 +08001742TEST(ConfigFileParserTests, ParseHexByte)
1743{
1744 // Test where works: "0xFF"
1745 {
1746 const json element = R"( "0xFF" )"_json;
1747 uint8_t value = parseHexByte(element);
1748 EXPECT_EQ(value, 0xFF);
1749 }
1750
1751 // Test where works: "0xff"
1752 {
1753 const json element = R"( "0xff" )"_json;
1754 uint8_t value = parseHexByte(element);
1755 EXPECT_EQ(value, 0xff);
1756 }
1757
1758 // Test where works: "0xf"
1759 {
1760 const json element = R"( "0xf" )"_json;
1761 uint8_t value = parseHexByte(element);
1762 EXPECT_EQ(value, 0xf);
1763 }
1764
1765 // Test where fails: "0xfff"
1766 try
1767 {
1768 const json element = R"( "0xfff" )"_json;
1769 parseHexByte(element);
1770 ADD_FAILURE() << "Should not have reached this line.";
1771 }
1772 catch (const std::invalid_argument& e)
1773 {
1774 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1775 }
1776
1777 // Test where fails: "0xAG"
1778 try
1779 {
1780 const json element = R"( "0xAG" )"_json;
1781 parseHexByte(element);
1782 ADD_FAILURE() << "Should not have reached this line.";
1783 }
1784 catch (const std::invalid_argument& e)
1785 {
1786 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1787 }
1788
1789 // Test where fails: "ff"
1790 try
1791 {
1792 const json element = R"( "ff" )"_json;
1793 parseHexByte(element);
1794 ADD_FAILURE() << "Should not have reached this line.";
1795 }
1796 catch (const std::invalid_argument& e)
1797 {
1798 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1799 }
1800
1801 // Test where fails: ""
1802 try
1803 {
1804 const json element = "";
1805 parseHexByte(element);
1806 ADD_FAILURE() << "Should not have reached this line.";
1807 }
1808 catch (const std::invalid_argument& e)
1809 {
1810 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1811 }
1812
1813 // Test where fails: "f"
1814 try
1815 {
1816 const json element = R"( "f" )"_json;
1817 parseHexByte(element);
1818 ADD_FAILURE() << "Should not have reached this line.";
1819 }
1820 catch (const std::invalid_argument& e)
1821 {
1822 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1823 }
1824
1825 // Test where fails: "0x"
1826 try
1827 {
1828 const json element = R"( "0x" )"_json;
1829 parseHexByte(element);
1830 ADD_FAILURE() << "Should not have reached this line.";
1831 }
1832 catch (const std::invalid_argument& e)
1833 {
1834 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1835 }
1836
1837 // Test where fails: "0Xff"
1838 try
1839 {
1840 const json element = R"( "0XFF" )"_json;
1841 parseHexByte(element);
1842 ADD_FAILURE() << "Should not have reached this line.";
1843 }
1844 catch (const std::invalid_argument& e)
1845 {
1846 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1847 }
1848}
1849
1850TEST(ConfigFileParserTests, ParseHexByteArray)
1851{
1852 // Test where works
1853 {
1854 const json element = R"( [ "0xCC", "0xFF" ] )"_json;
1855 std::vector<uint8_t> hexBytes = parseHexByteArray(element);
1856 std::vector<uint8_t> expected = {0xcc, 0xff};
1857 EXPECT_EQ(hexBytes, expected);
1858 }
1859
1860 // Test where fails: Element is not an array
1861 try
1862 {
1863 const json element = 0;
1864 parseHexByteArray(element);
1865 ADD_FAILURE() << "Should not have reached this line.";
1866 }
1867 catch (const std::invalid_argument& e)
1868 {
1869 EXPECT_STREQ(e.what(), "Element is not an array");
1870 }
1871}
1872
Bob Kingf09bfe02020-04-13 17:21:15 +08001873TEST(ConfigFileParserTests, ParseI2CCompareBit)
1874{
1875 // Test where works
1876 {
1877 const json element = R"(
1878 {
1879 "register": "0xA0",
1880 "position": 3,
1881 "value": 0
1882 }
1883 )"_json;
1884 std::unique_ptr<I2CCompareBitAction> action =
1885 parseI2CCompareBit(element);
1886 EXPECT_EQ(action->getRegister(), 0xA0);
1887 EXPECT_EQ(action->getPosition(), 3);
1888 EXPECT_EQ(action->getValue(), 0);
1889 }
1890
1891 // Test where fails: Invalid property specified
1892 try
1893 {
1894 const json element = R"(
1895 {
1896 "register": "0xA0",
1897 "position": 3,
1898 "value": 0,
1899 "foo": 3
1900 }
1901 )"_json;
1902 parseI2CCompareBit(element);
1903 ADD_FAILURE() << "Should not have reached this line.";
1904 }
1905 catch (const std::invalid_argument& e)
1906 {
1907 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1908 }
1909
1910 // Test where fails: Element is not an object
1911 try
1912 {
1913 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1914 parseI2CCompareBit(element);
1915 ADD_FAILURE() << "Should not have reached this line.";
1916 }
1917 catch (const std::invalid_argument& e)
1918 {
1919 EXPECT_STREQ(e.what(), "Element is not an object");
1920 }
1921
1922 // Test where fails: register value is invalid
1923 try
1924 {
1925 const json element = R"(
1926 {
1927 "register": "0xAG",
1928 "position": 3,
1929 "value": 0
1930 }
1931 )"_json;
1932 parseI2CCompareBit(element);
1933 ADD_FAILURE() << "Should not have reached this line.";
1934 }
1935 catch (const std::invalid_argument& e)
1936 {
1937 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1938 }
1939
1940 // Test where fails: position value is invalid
1941 try
1942 {
1943 const json element = R"(
1944 {
1945 "register": "0xA0",
1946 "position": 8,
1947 "value": 0
1948 }
1949 )"_json;
1950 parseI2CCompareBit(element);
1951 ADD_FAILURE() << "Should not have reached this line.";
1952 }
1953 catch (const std::invalid_argument& e)
1954 {
1955 EXPECT_STREQ(e.what(), "Element is not a bit position");
1956 }
1957
1958 // Test where fails: value value is invalid
1959 try
1960 {
1961 const json element = R"(
1962 {
1963 "register": "0xA0",
1964 "position": 3,
1965 "value": 2
1966 }
1967 )"_json;
1968 parseI2CCompareBit(element);
1969 ADD_FAILURE() << "Should not have reached this line.";
1970 }
1971 catch (const std::invalid_argument& e)
1972 {
1973 EXPECT_STREQ(e.what(), "Element is not a bit value");
1974 }
1975
1976 // Test where fails: Required register property not specified
1977 try
1978 {
1979 const json element = R"(
1980 {
1981 "position": 3,
1982 "value": 0
1983 }
1984 )"_json;
1985 parseI2CCompareBit(element);
1986 ADD_FAILURE() << "Should not have reached this line.";
1987 }
1988 catch (const std::invalid_argument& e)
1989 {
1990 EXPECT_STREQ(e.what(), "Required property missing: register");
1991 }
1992
1993 // Test where fails: Required position property not specified
1994 try
1995 {
1996 const json element = R"(
1997 {
1998 "register": "0xA0",
1999 "value": 0
2000 }
2001 )"_json;
2002 parseI2CCompareBit(element);
2003 ADD_FAILURE() << "Should not have reached this line.";
2004 }
2005 catch (const std::invalid_argument& e)
2006 {
2007 EXPECT_STREQ(e.what(), "Required property missing: position");
2008 }
2009
2010 // Test where fails: Required value property not specified
2011 try
2012 {
2013 const json element = R"(
2014 {
2015 "register": "0xA0",
2016 "position": 3
2017 }
2018 )"_json;
2019 parseI2CCompareBit(element);
2020 ADD_FAILURE() << "Should not have reached this line.";
2021 }
2022 catch (const std::invalid_argument& e)
2023 {
2024 EXPECT_STREQ(e.what(), "Required property missing: value");
2025 }
2026}
2027
2028TEST(ConfigFileParserTests, ParseI2CCompareByte)
2029{
2030 // Test where works: Only required properties specified
2031 {
2032 const json element = R"(
2033 {
2034 "register": "0x0A",
2035 "value": "0xCC"
2036 }
2037 )"_json;
2038 std::unique_ptr<I2CCompareByteAction> action =
2039 parseI2CCompareByte(element);
2040 EXPECT_EQ(action->getRegister(), 0x0A);
2041 EXPECT_EQ(action->getValue(), 0xCC);
2042 EXPECT_EQ(action->getMask(), 0xFF);
2043 }
2044
2045 // Test where works: All properties specified
2046 {
2047 const json element = R"(
2048 {
2049 "register": "0x0A",
2050 "value": "0xCC",
2051 "mask": "0xF7"
2052 }
2053 )"_json;
2054 std::unique_ptr<I2CCompareByteAction> action =
2055 parseI2CCompareByte(element);
2056 EXPECT_EQ(action->getRegister(), 0x0A);
2057 EXPECT_EQ(action->getValue(), 0xCC);
2058 EXPECT_EQ(action->getMask(), 0xF7);
2059 }
2060
2061 // Test where fails: Element is not an object
2062 try
2063 {
2064 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2065 parseI2CCompareByte(element);
2066 ADD_FAILURE() << "Should not have reached this line.";
2067 }
2068 catch (const std::invalid_argument& e)
2069 {
2070 EXPECT_STREQ(e.what(), "Element is not an object");
2071 }
2072
2073 // Test where fails: Invalid property specified
2074 try
2075 {
2076 const json element = R"(
2077 {
2078 "register": "0x0A",
2079 "value": "0xCC",
2080 "mask": "0xF7",
2081 "foo": 1
2082 }
2083 )"_json;
2084 parseI2CCompareByte(element);
2085 ADD_FAILURE() << "Should not have reached this line.";
2086 }
2087 catch (const std::invalid_argument& e)
2088 {
2089 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2090 }
2091
2092 // Test where fails: register value is invalid
2093 try
2094 {
2095 const json element = R"(
2096 {
2097 "register": "0x0Z",
2098 "value": "0xCC",
2099 "mask": "0xF7"
2100 }
2101 )"_json;
2102 parseI2CCompareByte(element);
2103 ADD_FAILURE() << "Should not have reached this line.";
2104 }
2105 catch (const std::invalid_argument& e)
2106 {
2107 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2108 }
2109
2110 // Test where fails: value value is invalid
2111 try
2112 {
2113 const json element = R"(
2114 {
2115 "register": "0x0A",
2116 "value": "0xCCC",
2117 "mask": "0xF7"
2118 }
2119 )"_json;
2120 parseI2CCompareByte(element);
2121 ADD_FAILURE() << "Should not have reached this line.";
2122 }
2123 catch (const std::invalid_argument& e)
2124 {
2125 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2126 }
2127
2128 // Test where fails: mask value is invalid
2129 try
2130 {
2131 const json element = R"(
2132 {
2133 "register": "0x0A",
2134 "value": "0xCC",
2135 "mask": "F7"
2136 }
2137 )"_json;
2138 parseI2CCompareByte(element);
2139 ADD_FAILURE() << "Should not have reached this line.";
2140 }
2141 catch (const std::invalid_argument& e)
2142 {
2143 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2144 }
2145
2146 // Test where fails: Required register property not specified
2147 try
2148 {
2149 const json element = R"(
2150 {
2151 "value": "0xCC",
2152 "mask": "0xF7"
2153 }
2154 )"_json;
2155 parseI2CCompareByte(element);
2156 ADD_FAILURE() << "Should not have reached this line.";
2157 }
2158 catch (const std::invalid_argument& e)
2159 {
2160 EXPECT_STREQ(e.what(), "Required property missing: register");
2161 }
2162
2163 // Test where fails: Required value property not specified
2164 try
2165 {
2166 const json element = R"(
2167 {
2168 "register": "0x0A",
2169 "mask": "0xF7"
2170 }
2171 )"_json;
2172 parseI2CCompareByte(element);
2173 ADD_FAILURE() << "Should not have reached this line.";
2174 }
2175 catch (const std::invalid_argument& e)
2176 {
2177 EXPECT_STREQ(e.what(), "Required property missing: value");
2178 }
2179}
2180
2181TEST(ConfigFileParserTests, ParseI2CCompareBytes)
2182{
2183 // Test where works: Only required properties specified
2184 {
2185 const json element = R"(
2186 {
2187 "register": "0x0A",
2188 "values": [ "0xCC", "0xFF" ]
2189 }
2190 )"_json;
2191 std::unique_ptr<I2CCompareBytesAction> action =
2192 parseI2CCompareBytes(element);
2193 EXPECT_EQ(action->getRegister(), 0x0A);
2194 EXPECT_EQ(action->getValues().size(), 2);
2195 EXPECT_EQ(action->getValues()[0], 0xCC);
2196 EXPECT_EQ(action->getValues()[1], 0xFF);
2197 EXPECT_EQ(action->getMasks().size(), 2);
2198 EXPECT_EQ(action->getMasks()[0], 0xFF);
2199 EXPECT_EQ(action->getMasks()[1], 0xFF);
2200 }
2201
2202 // Test where works: All properties specified
2203 {
2204 const json element = R"(
2205 {
2206 "register": "0x0A",
2207 "values": [ "0xCC", "0xFF" ],
2208 "masks": [ "0x7F", "0x77" ]
2209 }
2210 )"_json;
2211 std::unique_ptr<I2CCompareBytesAction> action =
2212 parseI2CCompareBytes(element);
2213 EXPECT_EQ(action->getRegister(), 0x0A);
2214 EXPECT_EQ(action->getValues().size(), 2);
2215 EXPECT_EQ(action->getValues()[0], 0xCC);
2216 EXPECT_EQ(action->getValues()[1], 0xFF);
2217 EXPECT_EQ(action->getMasks().size(), 2);
2218 EXPECT_EQ(action->getMasks()[0], 0x7F);
2219 EXPECT_EQ(action->getMasks()[1], 0x77);
2220 }
2221
2222 // Test where fails: Element is not an object
2223 try
2224 {
2225 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2226 parseI2CCompareBytes(element);
2227 ADD_FAILURE() << "Should not have reached this line.";
2228 }
2229 catch (const std::invalid_argument& e)
2230 {
2231 EXPECT_STREQ(e.what(), "Element is not an object");
2232 }
2233
2234 // Test where fails: Invalid property specified
2235 try
2236 {
2237 const json element = R"(
2238 {
2239 "register": "0x0A",
2240 "values": [ "0xCC", "0xFF" ],
2241 "masks": [ "0x7F", "0x7F" ],
2242 "foo": 1
2243 }
2244 )"_json;
2245 parseI2CCompareBytes(element);
2246 ADD_FAILURE() << "Should not have reached this line.";
2247 }
2248 catch (const std::invalid_argument& e)
2249 {
2250 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2251 }
2252
2253 // Test where fails: register value is invalid
2254 try
2255 {
2256 const json element = R"(
2257 {
2258 "register": "0x0Z",
2259 "values": [ "0xCC", "0xFF" ],
2260 "masks": [ "0x7F", "0x7F" ]
2261 }
2262 )"_json;
2263 parseI2CCompareBytes(element);
2264 ADD_FAILURE() << "Should not have reached this line.";
2265 }
2266 catch (const std::invalid_argument& e)
2267 {
2268 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2269 }
2270
2271 // Test where fails: values value is invalid
2272 try
2273 {
2274 const json element = R"(
2275 {
2276 "register": "0x0A",
2277 "values": [ "0xCCC", "0xFF" ],
2278 "masks": [ "0x7F", "0x7F" ]
2279 }
2280 )"_json;
2281 parseI2CCompareBytes(element);
2282 ADD_FAILURE() << "Should not have reached this line.";
2283 }
2284 catch (const std::invalid_argument& e)
2285 {
2286 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2287 }
2288
2289 // Test where fails: masks value is invalid
2290 try
2291 {
2292 const json element = R"(
2293 {
2294 "register": "0x0A",
2295 "values": [ "0xCC", "0xFF" ],
2296 "masks": [ "F", "0x7F" ]
2297 }
2298 )"_json;
2299 parseI2CCompareBytes(element);
2300 ADD_FAILURE() << "Should not have reached this line.";
2301 }
2302 catch (const std::invalid_argument& e)
2303 {
2304 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2305 }
2306
2307 // Test where fails: number of elements in masks is invalid
2308 try
2309 {
2310 const json element = R"(
2311 {
2312 "register": "0x0A",
2313 "values": [ "0xCC", "0xFF" ],
2314 "masks": [ "0x7F" ]
2315 }
2316 )"_json;
2317 parseI2CCompareBytes(element);
2318 ADD_FAILURE() << "Should not have reached this line.";
2319 }
2320 catch (const std::invalid_argument& e)
2321 {
2322 EXPECT_STREQ(e.what(), "Invalid number of elements in masks");
2323 }
2324
2325 // Test where fails: Required register property not specified
2326 try
2327 {
2328 const json element = R"(
2329 {
2330 "values": [ "0xCC", "0xFF" ]
2331 }
2332 )"_json;
2333 parseI2CCompareBytes(element);
2334 ADD_FAILURE() << "Should not have reached this line.";
2335 }
2336 catch (const std::invalid_argument& e)
2337 {
2338 EXPECT_STREQ(e.what(), "Required property missing: register");
2339 }
2340
2341 // Test where fails: Required values property not specified
2342 try
2343 {
2344 const json element = R"(
2345 {
2346 "register": "0x0A"
2347 }
2348 )"_json;
2349 parseI2CCompareBytes(element);
2350 ADD_FAILURE() << "Should not have reached this line.";
2351 }
2352 catch (const std::invalid_argument& e)
2353 {
2354 EXPECT_STREQ(e.what(), "Required property missing: values");
2355 }
2356}
2357
Bob Kingf617f892020-03-30 19:03:35 +08002358TEST(ConfigFileParserTests, ParseI2CWriteBit)
2359{
2360 // Test where works
2361 {
2362 const json element = R"(
2363 {
2364 "register": "0xA0",
2365 "position": 3,
2366 "value": 0
2367 }
2368 )"_json;
2369 std::unique_ptr<I2CWriteBitAction> action = parseI2CWriteBit(element);
2370 EXPECT_EQ(action->getRegister(), 0xA0);
2371 EXPECT_EQ(action->getPosition(), 3);
2372 EXPECT_EQ(action->getValue(), 0);
2373 }
2374
2375 // Test where fails: Invalid property specified
2376 try
2377 {
2378 const json element = R"(
2379 {
2380 "register": "0xA0",
2381 "position": 3,
2382 "value": 0,
2383 "foo": 3
2384 }
2385 )"_json;
2386 parseI2CWriteBit(element);
2387 ADD_FAILURE() << "Should not have reached this line.";
2388 }
2389 catch (const std::invalid_argument& e)
2390 {
2391 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2392 }
2393
2394 // Test where fails: Element is not an object
2395 try
2396 {
2397 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2398 parseI2CWriteBit(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 an object");
2404 }
2405
2406 // Test where fails: register value is invalid
2407 try
2408 {
2409 const json element = R"(
2410 {
2411 "register": "0xAG",
2412 "position": 3,
2413 "value": 0
2414 }
2415 )"_json;
2416 parseI2CWriteBit(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: position value is invalid
2425 try
2426 {
2427 const json element = R"(
2428 {
2429 "register": "0xA0",
2430 "position": 8,
2431 "value": 0
2432 }
2433 )"_json;
2434 parseI2CWriteBit(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 a bit position");
2440 }
2441
2442 // Test where fails: value value is invalid
2443 try
2444 {
2445 const json element = R"(
2446 {
2447 "register": "0xA0",
2448 "position": 3,
2449 "value": 2
2450 }
2451 )"_json;
2452 parseI2CWriteBit(element);
2453 ADD_FAILURE() << "Should not have reached this line.";
2454 }
2455 catch (const std::invalid_argument& e)
2456 {
2457 EXPECT_STREQ(e.what(), "Element is not a bit value");
2458 }
2459
2460 // Test where fails: Required register property not specified
2461 try
2462 {
2463 const json element = R"(
2464 {
2465 "position": 3,
2466 "value": 0
2467 }
2468 )"_json;
2469 parseI2CWriteBit(element);
2470 ADD_FAILURE() << "Should not have reached this line.";
2471 }
2472 catch (const std::invalid_argument& e)
2473 {
2474 EXPECT_STREQ(e.what(), "Required property missing: register");
2475 }
2476
2477 // Test where fails: Required position property not specified
2478 try
2479 {
2480 const json element = R"(
2481 {
2482 "register": "0xA0",
2483 "value": 0
2484 }
2485 )"_json;
2486 parseI2CWriteBit(element);
2487 ADD_FAILURE() << "Should not have reached this line.";
2488 }
2489 catch (const std::invalid_argument& e)
2490 {
2491 EXPECT_STREQ(e.what(), "Required property missing: position");
2492 }
2493
2494 // Test where fails: Required value property not specified
2495 try
2496 {
2497 const json element = R"(
2498 {
2499 "register": "0xA0",
2500 "position": 3
2501 }
2502 )"_json;
2503 parseI2CWriteBit(element);
2504 ADD_FAILURE() << "Should not have reached this line.";
2505 }
2506 catch (const std::invalid_argument& e)
2507 {
2508 EXPECT_STREQ(e.what(), "Required property missing: value");
2509 }
2510}
2511
Bob King87ff9d72020-03-31 14:02:55 +08002512TEST(ConfigFileParserTests, ParseI2CWriteByte)
2513{
2514 // Test where works: Only required properties specified
2515 {
2516 const json element = R"(
2517 {
2518 "register": "0x0A",
2519 "value": "0xCC"
2520 }
2521 )"_json;
2522 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element);
2523 EXPECT_EQ(action->getRegister(), 0x0A);
2524 EXPECT_EQ(action->getValue(), 0xCC);
2525 EXPECT_EQ(action->getMask(), 0xFF);
2526 }
2527
2528 // Test where works: All properties specified
2529 {
2530 const json element = R"(
2531 {
2532 "register": "0x0A",
2533 "value": "0xCC",
2534 "mask": "0xF7"
2535 }
2536 )"_json;
2537 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element);
2538 EXPECT_EQ(action->getRegister(), 0x0A);
2539 EXPECT_EQ(action->getValue(), 0xCC);
2540 EXPECT_EQ(action->getMask(), 0xF7);
2541 }
2542
2543 // Test where fails: Element is not an object
2544 try
2545 {
2546 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2547 parseI2CWriteByte(element);
2548 ADD_FAILURE() << "Should not have reached this line.";
2549 }
2550 catch (const std::invalid_argument& e)
2551 {
2552 EXPECT_STREQ(e.what(), "Element is not an object");
2553 }
2554
2555 // Test where fails: Invalid property specified
2556 try
2557 {
2558 const json element = R"(
2559 {
2560 "register": "0x0A",
2561 "value": "0xCC",
2562 "mask": "0xF7",
2563 "foo": 1
2564 }
2565 )"_json;
2566 parseI2CWriteByte(element);
2567 ADD_FAILURE() << "Should not have reached this line.";
2568 }
2569 catch (const std::invalid_argument& e)
2570 {
2571 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2572 }
2573
2574 // Test where fails: register value is invalid
2575 try
2576 {
2577 const json element = R"(
2578 {
2579 "register": "0x0Z",
2580 "value": "0xCC",
2581 "mask": "0xF7"
2582 }
2583 )"_json;
2584 parseI2CWriteByte(element);
2585 ADD_FAILURE() << "Should not have reached this line.";
2586 }
2587 catch (const std::invalid_argument& e)
2588 {
2589 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2590 }
2591
2592 // Test where fails: value value is invalid
2593 try
2594 {
2595 const json element = R"(
2596 {
2597 "register": "0x0A",
2598 "value": "0xCCC",
2599 "mask": "0xF7"
2600 }
2601 )"_json;
2602 parseI2CWriteByte(element);
2603 ADD_FAILURE() << "Should not have reached this line.";
2604 }
2605 catch (const std::invalid_argument& e)
2606 {
2607 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2608 }
2609
2610 // Test where fails: mask value is invalid
2611 try
2612 {
2613 const json element = R"(
2614 {
2615 "register": "0x0A",
2616 "value": "0xCC",
2617 "mask": "F7"
2618 }
2619 )"_json;
2620 parseI2CWriteByte(element);
2621 ADD_FAILURE() << "Should not have reached this line.";
2622 }
2623 catch (const std::invalid_argument& e)
2624 {
2625 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2626 }
2627
2628 // Test where fails: Required register property not specified
2629 try
2630 {
2631 const json element = R"(
2632 {
2633 "value": "0xCC",
2634 "mask": "0xF7"
2635 }
2636 )"_json;
2637 parseI2CWriteByte(element);
2638 ADD_FAILURE() << "Should not have reached this line.";
2639 }
2640 catch (const std::invalid_argument& e)
2641 {
2642 EXPECT_STREQ(e.what(), "Required property missing: register");
2643 }
2644
2645 // Test where fails: Required value property not specified
2646 try
2647 {
2648 const json element = R"(
2649 {
2650 "register": "0x0A",
2651 "mask": "0xF7"
2652 }
2653 )"_json;
2654 parseI2CWriteByte(element);
2655 ADD_FAILURE() << "Should not have reached this line.";
2656 }
2657 catch (const std::invalid_argument& e)
2658 {
2659 EXPECT_STREQ(e.what(), "Required property missing: value");
2660 }
2661}
2662
Bob Kingbafcb862020-03-31 16:39:00 +08002663TEST(ConfigFileParserTests, ParseI2CWriteBytes)
2664{
2665 // Test where works: Only required properties specified
2666 {
2667 const json element = R"(
2668 {
2669 "register": "0x0A",
2670 "values": [ "0xCC", "0xFF" ]
2671 }
2672 )"_json;
2673 std::unique_ptr<I2CWriteBytesAction> action =
2674 parseI2CWriteBytes(element);
2675 EXPECT_EQ(action->getRegister(), 0x0A);
2676 EXPECT_EQ(action->getValues().size(), 2);
2677 EXPECT_EQ(action->getValues()[0], 0xCC);
2678 EXPECT_EQ(action->getValues()[1], 0xFF);
2679 EXPECT_EQ(action->getMasks().size(), 0);
2680 }
2681
2682 // Test where works: All properties specified
2683 {
2684 const json element = R"(
2685 {
2686 "register": "0x0A",
2687 "values": [ "0xCC", "0xFF" ],
2688 "masks": [ "0x7F", "0x77" ]
2689 }
2690 )"_json;
2691 std::unique_ptr<I2CWriteBytesAction> action =
2692 parseI2CWriteBytes(element);
2693 EXPECT_EQ(action->getRegister(), 0x0A);
2694 EXPECT_EQ(action->getValues().size(), 2);
2695 EXPECT_EQ(action->getValues()[0], 0xCC);
2696 EXPECT_EQ(action->getValues()[1], 0xFF);
2697 EXPECT_EQ(action->getMasks().size(), 2);
2698 EXPECT_EQ(action->getMasks()[0], 0x7F);
2699 EXPECT_EQ(action->getMasks()[1], 0x77);
2700 }
2701
2702 // Test where fails: Element is not an object
2703 try
2704 {
2705 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2706 parseI2CWriteBytes(element);
2707 ADD_FAILURE() << "Should not have reached this line.";
2708 }
2709 catch (const std::invalid_argument& e)
2710 {
2711 EXPECT_STREQ(e.what(), "Element is not an object");
2712 }
2713
2714 // Test where fails: Invalid property specified
2715 try
2716 {
2717 const json element = R"(
2718 {
2719 "register": "0x0A",
2720 "values": [ "0xCC", "0xFF" ],
2721 "masks": [ "0x7F", "0x7F" ],
2722 "foo": 1
2723 }
2724 )"_json;
2725 parseI2CWriteBytes(element);
2726 ADD_FAILURE() << "Should not have reached this line.";
2727 }
2728 catch (const std::invalid_argument& e)
2729 {
2730 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2731 }
2732
2733 // Test where fails: register value is invalid
2734 try
2735 {
2736 const json element = R"(
2737 {
2738 "register": "0x0Z",
2739 "values": [ "0xCC", "0xFF" ],
2740 "masks": [ "0x7F", "0x7F" ]
2741 }
2742 )"_json;
2743 parseI2CWriteBytes(element);
2744 ADD_FAILURE() << "Should not have reached this line.";
2745 }
2746 catch (const std::invalid_argument& e)
2747 {
2748 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2749 }
2750
2751 // Test where fails: values value is invalid
2752 try
2753 {
2754 const json element = R"(
2755 {
2756 "register": "0x0A",
2757 "values": [ "0xCCC", "0xFF" ],
2758 "masks": [ "0x7F", "0x7F" ]
2759 }
2760 )"_json;
2761 parseI2CWriteBytes(element);
2762 ADD_FAILURE() << "Should not have reached this line.";
2763 }
2764 catch (const std::invalid_argument& e)
2765 {
2766 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2767 }
2768
2769 // Test where fails: masks value is invalid
2770 try
2771 {
2772 const json element = R"(
2773 {
2774 "register": "0x0A",
2775 "values": [ "0xCC", "0xFF" ],
2776 "masks": [ "F", "0x7F" ]
2777 }
2778 )"_json;
2779 parseI2CWriteBytes(element);
2780 ADD_FAILURE() << "Should not have reached this line.";
2781 }
2782 catch (const std::invalid_argument& e)
2783 {
2784 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2785 }
2786
2787 // Test where fails: number of elements in masks is invalid
2788 try
2789 {
2790 const json element = R"(
2791 {
2792 "register": "0x0A",
2793 "values": [ "0xCC", "0xFF" ],
2794 "masks": [ "0x7F" ]
2795 }
2796 )"_json;
2797 parseI2CWriteBytes(element);
2798 ADD_FAILURE() << "Should not have reached this line.";
2799 }
2800 catch (const std::invalid_argument& e)
2801 {
2802 EXPECT_STREQ(e.what(), "Invalid number of elements in masks");
2803 }
2804
2805 // Test where fails: Required register property not specified
2806 try
2807 {
2808 const json element = R"(
2809 {
2810 "values": [ "0xCC", "0xFF" ]
2811 }
2812 )"_json;
2813 parseI2CWriteBytes(element);
2814 ADD_FAILURE() << "Should not have reached this line.";
2815 }
2816 catch (const std::invalid_argument& e)
2817 {
2818 EXPECT_STREQ(e.what(), "Required property missing: register");
2819 }
2820
2821 // Test where fails: Required values property not specified
2822 try
2823 {
2824 const json element = R"(
2825 {
2826 "register": "0x0A"
2827 }
2828 )"_json;
2829 parseI2CWriteBytes(element);
2830 ADD_FAILURE() << "Should not have reached this line.";
2831 }
2832 catch (const std::invalid_argument& e)
2833 {
2834 EXPECT_STREQ(e.what(), "Required property missing: values");
2835 }
2836}
2837
Bob King93a89d72020-04-15 15:11:11 +08002838TEST(ConfigFileParserTests, ParseIf)
2839{
2840 // Test where works: Only required properties specified
2841 {
2842 const json element = R"(
2843 {
2844 "condition": { "run_rule": "is_downlevel_regulator" },
2845 "then": [ { "run_rule": "configure_downlevel_regulator" },
2846 { "run_rule": "configure_standard_regulator" } ]
2847 }
2848 )"_json;
2849 std::unique_ptr<IfAction> action = parseIf(element);
2850 EXPECT_NE(action->getConditionAction().get(), nullptr);
2851 EXPECT_EQ(action->getThenActions().size(), 2);
2852 EXPECT_EQ(action->getElseActions().size(), 0);
2853 }
2854
2855 // Test where works: All properties specified
2856 {
2857 const json element = R"(
2858 {
2859 "condition": { "run_rule": "is_downlevel_regulator" },
2860 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2861 "else": [ { "run_rule": "configure_standard_regulator" } ]
2862 }
2863 )"_json;
2864 std::unique_ptr<IfAction> action = parseIf(element);
2865 EXPECT_NE(action->getConditionAction().get(), nullptr);
2866 EXPECT_EQ(action->getThenActions().size(), 1);
2867 EXPECT_EQ(action->getElseActions().size(), 1);
2868 }
2869
2870 // Test where fails: Required condition property not specified
2871 try
2872 {
2873 const json element = R"(
2874 {
2875 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2876 "else": [ { "run_rule": "configure_standard_regulator" } ]
2877 }
2878 )"_json;
2879 parseIf(element);
2880 ADD_FAILURE() << "Should not have reached this line.";
2881 }
2882 catch (const std::invalid_argument& e)
2883 {
2884 EXPECT_STREQ(e.what(), "Required property missing: condition");
2885 }
2886
2887 // Test where fails: Required then property not specified
2888 try
2889 {
2890 const json element = R"(
2891 {
2892 "condition": { "run_rule": "is_downlevel_regulator" },
2893 "else": [ { "run_rule": "configure_standard_regulator" } ]
2894 }
2895 )"_json;
2896 parseIf(element);
2897 ADD_FAILURE() << "Should not have reached this line.";
2898 }
2899 catch (const std::invalid_argument& e)
2900 {
2901 EXPECT_STREQ(e.what(), "Required property missing: then");
2902 }
2903
2904 // Test where fails: condition value is invalid
2905 try
2906 {
2907 const json element = R"(
2908 {
2909 "condition": 1,
2910 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2911 "else": [ { "run_rule": "configure_standard_regulator" } ]
2912 }
2913 )"_json;
2914 parseIf(element);
2915 ADD_FAILURE() << "Should not have reached this line.";
2916 }
2917 catch (const std::invalid_argument& e)
2918 {
2919 EXPECT_STREQ(e.what(), "Element is not an object");
2920 }
2921
2922 // Test where fails: then value is invalid
2923 try
2924 {
2925 const json element = R"(
2926 {
2927 "condition": { "run_rule": "is_downlevel_regulator" },
2928 "then": "foo",
2929 "else": [ { "run_rule": "configure_standard_regulator" } ]
2930 }
2931 )"_json;
2932 parseIf(element);
2933 ADD_FAILURE() << "Should not have reached this line.";
2934 }
2935 catch (const std::invalid_argument& e)
2936 {
2937 EXPECT_STREQ(e.what(), "Element is not an array");
2938 }
2939
2940 // Test where fails: else value is invalid
2941 try
2942 {
2943 const json element = R"(
2944 {
2945 "condition": { "run_rule": "is_downlevel_regulator" },
2946 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2947 "else": 1
2948 }
2949 )"_json;
2950 parseIf(element);
2951 ADD_FAILURE() << "Should not have reached this line.";
2952 }
2953 catch (const std::invalid_argument& e)
2954 {
2955 EXPECT_STREQ(e.what(), "Element is not an array");
2956 }
2957
2958 // Test where fails: Invalid property specified
2959 try
2960 {
2961 const json element = R"(
2962 {
2963 "condition": { "run_rule": "is_downlevel_regulator" },
2964 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2965 "foo": "bar"
2966 }
2967 )"_json;
2968 parseIf(element);
2969 ADD_FAILURE() << "Should not have reached this line.";
2970 }
2971 catch (const std::invalid_argument& e)
2972 {
2973 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2974 }
2975
2976 // Test where fails: Element is not an object
2977 try
2978 {
2979 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2980 parseIf(element);
2981 ADD_FAILURE() << "Should not have reached this line.";
2982 }
2983 catch (const std::invalid_argument& e)
2984 {
2985 EXPECT_STREQ(e.what(), "Element is not an object");
2986 }
2987}
2988
Bob King87ff9d72020-03-31 14:02:55 +08002989TEST(ConfigFileParserTests, ParseInt8)
2990{
2991 // Test where works: INT8_MIN
2992 {
2993 const json element = R"( -128 )"_json;
2994 int8_t value = parseInt8(element);
2995 EXPECT_EQ(value, -128);
2996 }
2997
2998 // Test where works: INT8_MAX
2999 {
3000 const json element = R"( 127 )"_json;
3001 int8_t value = parseInt8(element);
3002 EXPECT_EQ(value, 127);
3003 }
3004
3005 // Test where fails: Element is not an integer
3006 try
3007 {
3008 const json element = R"( 1.03 )"_json;
3009 parseInt8(element);
3010 ADD_FAILURE() << "Should not have reached this line.";
3011 }
3012 catch (const std::invalid_argument& e)
3013 {
3014 EXPECT_STREQ(e.what(), "Element is not an integer");
3015 }
3016
3017 // Test where fails: Value < INT8_MIN
3018 try
3019 {
3020 const json element = R"( -129 )"_json;
3021 parseInt8(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 is not an 8-bit signed integer");
3027 }
3028
3029 // Test where fails: Value > INT8_MAX
3030 try
3031 {
3032 const json element = R"( 128 )"_json;
3033 parseInt8(element);
3034 ADD_FAILURE() << "Should not have reached this line.";
3035 }
3036 catch (const std::invalid_argument& e)
3037 {
3038 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
3039 }
3040}
3041
Bob Kingf1b58dc2020-04-14 14:53:10 +08003042TEST(ConfigFileParserTests, ParseNot)
3043{
3044 // Test where works
3045 {
3046 const json element = R"(
3047 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }
3048 )"_json;
3049 std::unique_ptr<NotAction> action = parseNot(element);
3050 EXPECT_NE(action->getAction().get(), nullptr);
3051 }
3052
3053 // Test where fails: Element is not an object
3054 try
3055 {
3056 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3057 parseNot(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 an object");
3063 }
3064}
3065
Bob King0b51a9b2020-04-15 13:24:18 +08003066TEST(ConfigFileParserTests, ParseOr)
3067{
3068 // Test where works: Element is an array with 2 actions
3069 {
3070 const json element = R"(
3071 [
3072 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
3073 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
3074 ]
3075 )"_json;
3076 std::unique_ptr<OrAction> action = parseOr(element);
3077 EXPECT_EQ(action->getActions().size(), 2);
3078 }
3079
3080 // Test where fails: Element is an array with 1 action
3081 try
3082 {
3083 const json element = R"(
3084 [
3085 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }
3086 ]
3087 )"_json;
3088 parseOr(element);
3089 ADD_FAILURE() << "Should not have reached this line.";
3090 }
3091 catch (const std::invalid_argument& e)
3092 {
3093 EXPECT_STREQ(e.what(), "Array must contain two or more actions");
3094 }
3095
3096 // Test where fails: Element is not an array
3097 try
3098 {
3099 const json element = R"(
3100 {
3101 "foo": "bar"
3102 }
3103 )"_json;
3104 parseOr(element);
3105 ADD_FAILURE() << "Should not have reached this line.";
3106 }
3107 catch (const std::invalid_argument& e)
3108 {
3109 EXPECT_STREQ(e.what(), "Element is not an array");
3110 }
3111}
3112
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003113TEST(ConfigFileParserTests, ParsePMBusWriteVoutCommand)
3114{
3115 // Test where works: Only required properties specified
3116 {
3117 const json element = R"(
3118 {
3119 "format": "linear"
3120 }
3121 )"_json;
3122 std::unique_ptr<PMBusWriteVoutCommandAction> action =
3123 parsePMBusWriteVoutCommand(element);
3124 EXPECT_EQ(action->getVolts().has_value(), false);
3125 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear);
3126 EXPECT_EQ(action->getExponent().has_value(), false);
3127 EXPECT_EQ(action->isVerified(), false);
3128 }
3129
3130 // Test where works: All properties specified
3131 {
3132 const json element = R"(
3133 {
3134 "volts": 1.03,
3135 "format": "linear",
3136 "exponent": -8,
3137 "is_verified": true
3138 }
3139 )"_json;
3140 std::unique_ptr<PMBusWriteVoutCommandAction> action =
3141 parsePMBusWriteVoutCommand(element);
3142 EXPECT_EQ(action->getVolts().has_value(), true);
3143 EXPECT_EQ(action->getVolts().value(), 1.03);
3144 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear);
3145 EXPECT_EQ(action->getExponent().has_value(), true);
3146 EXPECT_EQ(action->getExponent().value(), -8);
3147 EXPECT_EQ(action->isVerified(), true);
3148 }
3149
3150 // Test where fails: Element is not an object
3151 try
3152 {
3153 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3154 parsePMBusWriteVoutCommand(element);
3155 ADD_FAILURE() << "Should not have reached this line.";
3156 }
3157 catch (const std::invalid_argument& e)
3158 {
3159 EXPECT_STREQ(e.what(), "Element is not an object");
3160 }
3161
3162 // Test where fails: volts value is invalid
3163 try
3164 {
3165 const json element = R"(
3166 {
3167 "volts": "foo",
3168 "format": "linear"
3169 }
3170 )"_json;
3171 parsePMBusWriteVoutCommand(element);
3172 ADD_FAILURE() << "Should not have reached this line.";
3173 }
3174 catch (const std::invalid_argument& e)
3175 {
3176 EXPECT_STREQ(e.what(), "Element is not a number");
3177 }
3178
3179 // Test where fails: Required format property not specified
3180 try
3181 {
3182 const json element = R"(
3183 {
3184 "volts": 1.03,
3185 "is_verified": true
3186 }
3187 )"_json;
3188 parsePMBusWriteVoutCommand(element);
3189 ADD_FAILURE() << "Should not have reached this line.";
3190 }
3191 catch (const std::invalid_argument& e)
3192 {
3193 EXPECT_STREQ(e.what(), "Required property missing: format");
3194 }
3195
3196 // Test where fails: format value is invalid
3197 try
3198 {
3199 const json element = R"(
3200 {
3201 "format": "linear_11"
3202 }
3203 )"_json;
3204 parsePMBusWriteVoutCommand(element);
3205 ADD_FAILURE() << "Should not have reached this line.";
3206 }
3207 catch (const std::invalid_argument& e)
3208 {
3209 EXPECT_STREQ(e.what(), "Invalid format value: linear_11");
3210 }
3211
3212 // Test where fails: exponent value is invalid
3213 try
3214 {
3215 const json element = R"(
3216 {
3217 "format": "linear",
3218 "exponent": 1.3
3219 }
3220 )"_json;
3221 parsePMBusWriteVoutCommand(element);
3222 ADD_FAILURE() << "Should not have reached this line.";
3223 }
3224 catch (const std::invalid_argument& e)
3225 {
3226 EXPECT_STREQ(e.what(), "Element is not an integer");
3227 }
3228
3229 // Test where fails: is_verified value is invalid
3230 try
3231 {
3232 const json element = R"(
3233 {
3234 "format": "linear",
3235 "is_verified": "true"
3236 }
3237 )"_json;
3238 parsePMBusWriteVoutCommand(element);
3239 ADD_FAILURE() << "Should not have reached this line.";
3240 }
3241 catch (const std::invalid_argument& e)
3242 {
3243 EXPECT_STREQ(e.what(), "Element is not a boolean");
3244 }
3245
3246 // Test where fails: Invalid property specified
3247 try
3248 {
3249 const json element = R"(
3250 {
3251 "format": "linear",
3252 "foo": "bar"
3253 }
3254 )"_json;
3255 parsePMBusWriteVoutCommand(element);
3256 ADD_FAILURE() << "Should not have reached this line.";
3257 }
3258 catch (const std::invalid_argument& e)
3259 {
3260 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3261 }
3262}
3263
Bob King2aafb1c2020-04-16 15:24:32 +08003264TEST(ConfigFileParserTests, ParsePresenceDetection)
3265{
3266 // Test where works: actions property specified
3267 {
3268 const json element = R"(
3269 {
3270 "actions": [
3271 { "run_rule": "read_sensors_rule" }
3272 ]
3273 }
3274 )"_json;
3275 std::unique_ptr<PresenceDetection> presenceDetection =
3276 parsePresenceDetection(element);
3277 EXPECT_EQ(presenceDetection->getActions().size(), 1);
3278 }
3279
3280 // Test where works: rule_id property specified
3281 {
3282 const json element = R"(
3283 {
3284 "comments": [ "comments property" ],
3285 "rule_id": "set_voltage_rule"
3286 }
3287 )"_json;
3288 std::unique_ptr<PresenceDetection> presenceDetection =
3289 parsePresenceDetection(element);
3290 EXPECT_EQ(presenceDetection->getActions().size(), 1);
3291 }
3292
3293 // Test where fails: actions object is invalid
3294 try
3295 {
3296 const json element = R"(
3297 {
3298 "actions": 1
3299 }
3300 )"_json;
3301 parsePresenceDetection(element);
3302 ADD_FAILURE() << "Should not have reached this line.";
3303 }
3304 catch (const std::invalid_argument& e)
3305 {
3306 EXPECT_STREQ(e.what(), "Element is not an array");
3307 }
3308
3309 // Test where fails: rule_id value is invalid
3310 try
3311 {
3312 const json element = R"(
3313 {
3314 "rule_id": 1
3315 }
3316 )"_json;
3317 parsePresenceDetection(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 a string");
3323 }
3324
3325 // Test where fails: Required actions or rule_id property not specified
3326 try
3327 {
3328 const json element = R"(
3329 {
3330 "comments": [ "comments property" ]
3331 }
3332 )"_json;
3333 parsePresenceDetection(element);
3334 ADD_FAILURE() << "Should not have reached this line.";
3335 }
3336 catch (const std::invalid_argument& e)
3337 {
3338 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3339 "either rule_id or actions");
3340 }
3341
3342 // Test where fails: Required actions or rule_id property both specified
3343 try
3344 {
3345 const json element = R"(
3346 {
3347 "rule_id": "set_voltage_rule",
3348 "actions": [
3349 { "run_rule": "read_sensors_rule" }
3350 ]
3351 }
3352 )"_json;
3353 parsePresenceDetection(element);
3354 ADD_FAILURE() << "Should not have reached this line.";
3355 }
3356 catch (const std::invalid_argument& e)
3357 {
3358 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3359 "either rule_id or actions");
3360 }
3361
3362 // Test where fails: Element is not an object
3363 try
3364 {
3365 const json element = R"( [ "foo", "bar" ] )"_json;
3366 parsePresenceDetection(element);
3367 ADD_FAILURE() << "Should not have reached this line.";
3368 }
3369 catch (const std::invalid_argument& e)
3370 {
3371 EXPECT_STREQ(e.what(), "Element is not an object");
3372 }
3373
3374 // Test where fails: Invalid property specified
3375 try
3376 {
3377 const json element = R"(
3378 {
3379 "foo": "bar",
3380 "actions": [
3381 { "run_rule": "read_sensors_rule" }
3382 ]
3383 }
3384 )"_json;
3385 parsePresenceDetection(element);
3386 ADD_FAILURE() << "Should not have reached this line.";
3387 }
3388 catch (const std::invalid_argument& e)
3389 {
3390 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3391 }
3392}
3393
Bob Kinga2f2a0d2020-04-09 13:32:14 +08003394TEST(ConfigFileParserTests, ParseRail)
3395{
3396 // Test where works: Only required properties specified
3397 {
3398 const json element = R"(
3399 {
3400 "id": "vdd"
3401 }
3402 )"_json;
3403 std::unique_ptr<Rail> rail = parseRail(element);
3404 EXPECT_EQ(rail->getID(), "vdd");
3405 EXPECT_EQ(rail->getConfiguration(), nullptr);
3406 EXPECT_EQ(rail->getSensorMonitoring(), nullptr);
3407 }
3408
3409 // Test where works: All properties specified
3410 {
3411 const json element = R"(
3412 {
3413 "comments": [ "comments property" ],
3414 "id": "vdd",
3415 "configuration": {
3416 "volts": 1.1,
3417 "actions": [
3418 {
3419 "pmbus_write_vout_command": {
3420 "format": "linear"
3421 }
3422 }
3423 ]
3424 },
3425 "sensor_monitoring": {
3426 "actions": [
3427 { "run_rule": "read_sensors_rule" }
3428 ]
3429 }
3430 }
3431 )"_json;
3432 std::unique_ptr<Rail> rail = parseRail(element);
3433 EXPECT_EQ(rail->getID(), "vdd");
3434 EXPECT_NE(rail->getConfiguration(), nullptr);
3435 EXPECT_NE(rail->getSensorMonitoring(), nullptr);
3436 }
3437
3438 // Test where fails: id property not specified
3439 try
3440 {
3441 const json element = R"(
3442 {
3443 "configuration": {
3444 "volts": 1.1,
3445 "actions": [
3446 {
3447 "pmbus_write_vout_command": {
3448 "format": "linear"
3449 }
3450 }
3451 ]
3452 }
3453 }
3454 )"_json;
3455 parseRail(element);
3456 ADD_FAILURE() << "Should not have reached this line.";
3457 }
3458 catch (const std::invalid_argument& e)
3459 {
3460 EXPECT_STREQ(e.what(), "Required property missing: id");
3461 }
3462
3463 // Test where fails: id property is invalid
3464 try
3465 {
3466 const json element = R"(
3467 {
3468 "id": "",
3469 "configuration": {
3470 "volts": 1.1,
3471 "actions": [
3472 {
3473 "pmbus_write_vout_command": {
3474 "format": "linear"
3475 }
3476 }
3477 ]
3478 }
3479 }
3480 )"_json;
3481 parseRail(element);
3482 ADD_FAILURE() << "Should not have reached this line.";
3483 }
3484 catch (const std::invalid_argument& e)
3485 {
3486 EXPECT_STREQ(e.what(), "Element contains an empty string");
3487 }
3488
3489 // Test where fails: Element is not an object
3490 try
3491 {
3492 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3493 parseRail(element);
3494 ADD_FAILURE() << "Should not have reached this line.";
3495 }
3496 catch (const std::invalid_argument& e)
3497 {
3498 EXPECT_STREQ(e.what(), "Element is not an object");
3499 }
3500
3501 // Test where fails: configuration value is invalid
3502 try
3503 {
3504 const json element = R"(
3505 {
3506 "id": "vdd",
3507 "configuration": "config"
3508 }
3509 )"_json;
3510 parseRail(element);
3511 ADD_FAILURE() << "Should not have reached this line.";
3512 }
3513 catch (const std::invalid_argument& e)
3514 {
3515 EXPECT_STREQ(e.what(), "Element is not an object");
3516 }
3517
3518 // Test where fails: sensor_monitoring value is invalid
3519 try
3520 {
3521 const json element = R"(
3522 {
3523 "comments": [ "comments property" ],
3524 "id": "vdd",
3525 "configuration": {
3526 "volts": 1.1,
3527 "actions": [
3528 {
3529 "pmbus_write_vout_command": {
3530 "format": "linear"
3531 }
3532 }
3533 ]
3534 },
3535 "sensor_monitoring": 1
3536 }
3537 )"_json;
3538 parseRail(element);
3539 ADD_FAILURE() << "Should not have reached this line.";
3540 }
3541 catch (const std::invalid_argument& e)
3542 {
3543 EXPECT_STREQ(e.what(), "Element is not an object");
3544 }
3545
3546 // Test where fails: Invalid property specified
3547 try
3548 {
3549 const json element = R"(
3550 {
3551 "id": "vdd",
3552 "foo" : true
3553 }
3554 )"_json;
3555 parseRail(element);
3556 ADD_FAILURE() << "Should not have reached this line.";
3557 }
3558 catch (const std::invalid_argument& e)
3559 {
3560 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3561 }
3562}
3563
3564TEST(ConfigFileParserTests, ParseRailArray)
3565{
3566 // Test where works
3567 {
3568 const json element = R"(
3569 [
3570 { "id": "vdd" },
3571 { "id": "vio" }
3572 ]
3573 )"_json;
3574 std::vector<std::unique_ptr<Rail>> rails = parseRailArray(element);
3575 EXPECT_EQ(rails.size(), 2);
3576 EXPECT_EQ(rails[0]->getID(), "vdd");
3577 EXPECT_EQ(rails[1]->getID(), "vio");
3578 }
3579
3580 // Test where fails: Element is not an array
3581 try
3582 {
3583 const json element = R"(
3584 {
3585 "foo": "bar"
3586 }
3587 )"_json;
3588 parseRailArray(element);
3589 ADD_FAILURE() << "Should not have reached this line.";
3590 }
3591 catch (const std::invalid_argument& e)
3592 {
3593 EXPECT_STREQ(e.what(), "Element is not an array");
3594 }
3595}
3596
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003597TEST(ConfigFileParserTests, ParseRoot)
3598{
3599 // Test where works: Only required properties specified
3600 {
3601 const json element = R"(
3602 {
3603 "chassis": [
3604 { "number": 1 }
3605 ]
3606 }
3607 )"_json;
3608 std::vector<std::unique_ptr<Rule>> rules{};
3609 std::vector<std::unique_ptr<Chassis>> chassis{};
3610 std::tie(rules, chassis) = parseRoot(element);
3611 EXPECT_EQ(rules.size(), 0);
Bob King0e701132020-04-03 21:50:31 +08003612 EXPECT_EQ(chassis.size(), 1);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003613 }
3614
3615 // Test where works: All properties specified
3616 {
3617 const json element = R"(
3618 {
3619 "comments": [ "Config file for a FooBar one-chassis system" ],
3620 "rules": [
3621 {
3622 "id": "set_voltage_rule",
3623 "actions": [
3624 { "pmbus_write_vout_command": { "format": "linear" } }
3625 ]
3626 }
3627 ],
3628 "chassis": [
3629 { "number": 1 },
3630 { "number": 3 }
3631 ]
3632 }
3633 )"_json;
3634 std::vector<std::unique_ptr<Rule>> rules{};
3635 std::vector<std::unique_ptr<Chassis>> chassis{};
3636 std::tie(rules, chassis) = parseRoot(element);
3637 EXPECT_EQ(rules.size(), 1);
Bob King0e701132020-04-03 21:50:31 +08003638 EXPECT_EQ(chassis.size(), 2);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003639 }
3640
3641 // Test where fails: Element is not an object
3642 try
3643 {
3644 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3645 parseRoot(element);
3646 ADD_FAILURE() << "Should not have reached this line.";
3647 }
3648 catch (const std::invalid_argument& e)
3649 {
3650 EXPECT_STREQ(e.what(), "Element is not an object");
3651 }
3652
3653 // Test where fails: chassis property not specified
3654 try
3655 {
3656 const json element = R"(
3657 {
3658 "rules": [
3659 {
3660 "id": "set_voltage_rule",
3661 "actions": [
3662 { "pmbus_write_vout_command": { "format": "linear" } }
3663 ]
3664 }
3665 ]
3666 }
3667 )"_json;
3668 parseRoot(element);
3669 ADD_FAILURE() << "Should not have reached this line.";
3670 }
3671 catch (const std::invalid_argument& e)
3672 {
3673 EXPECT_STREQ(e.what(), "Required property missing: chassis");
3674 }
3675
3676 // Test where fails: Invalid property specified
3677 try
3678 {
3679 const json element = R"(
3680 {
3681 "remarks": [ "Config file for a FooBar one-chassis system" ],
3682 "chassis": [
3683 { "number": 1 }
3684 ]
3685 }
3686 )"_json;
3687 parseRoot(element);
3688 ADD_FAILURE() << "Should not have reached this line.";
3689 }
3690 catch (const std::invalid_argument& e)
3691 {
3692 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3693 }
3694}
3695
3696TEST(ConfigFileParserTests, ParseRule)
3697{
3698 // Test where works: comments property specified
3699 {
3700 const json element = R"(
3701 {
3702 "comments": [ "Set voltage rule" ],
3703 "id": "set_voltage_rule",
3704 "actions": [
3705 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
3706 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
3707 ]
3708 }
3709 )"_json;
3710 std::unique_ptr<Rule> rule = parseRule(element);
3711 EXPECT_EQ(rule->getID(), "set_voltage_rule");
3712 EXPECT_EQ(rule->getActions().size(), 2);
3713 }
3714
3715 // Test where works: comments property not specified
3716 {
3717 const json element = R"(
3718 {
3719 "id": "set_voltage_rule",
3720 "actions": [
3721 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
3722 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } },
3723 { "pmbus_write_vout_command": { "volts": 1.05, "format": "linear" } }
3724 ]
3725 }
3726 )"_json;
3727 std::unique_ptr<Rule> rule = parseRule(element);
3728 EXPECT_EQ(rule->getID(), "set_voltage_rule");
3729 EXPECT_EQ(rule->getActions().size(), 3);
3730 }
3731
3732 // Test where fails: Element is not an object
3733 try
3734 {
3735 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3736 parseRule(element);
3737 ADD_FAILURE() << "Should not have reached this line.";
3738 }
3739 catch (const std::invalid_argument& e)
3740 {
3741 EXPECT_STREQ(e.what(), "Element is not an object");
3742 }
3743
3744 // Test where fails: id property not specified
3745 try
3746 {
3747 const json element = R"(
3748 {
3749 "actions": [
3750 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
3751 ]
3752 }
3753 )"_json;
3754 parseRule(element);
3755 ADD_FAILURE() << "Should not have reached this line.";
3756 }
3757 catch (const std::invalid_argument& e)
3758 {
3759 EXPECT_STREQ(e.what(), "Required property missing: id");
3760 }
3761
3762 // Test where fails: id property is invalid
3763 try
3764 {
3765 const json element = R"(
3766 {
3767 "id": "",
3768 "actions": [
3769 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
3770 ]
3771 }
3772 )"_json;
3773 parseRule(element);
3774 ADD_FAILURE() << "Should not have reached this line.";
3775 }
3776 catch (const std::invalid_argument& e)
3777 {
3778 EXPECT_STREQ(e.what(), "Element contains an empty string");
3779 }
3780
3781 // Test where fails: actions property not specified
3782 try
3783 {
3784 const json element = R"(
3785 {
3786 "comments": [ "Set voltage rule" ],
3787 "id": "set_voltage_rule"
3788 }
3789 )"_json;
3790 parseRule(element);
3791 ADD_FAILURE() << "Should not have reached this line.";
3792 }
3793 catch (const std::invalid_argument& e)
3794 {
3795 EXPECT_STREQ(e.what(), "Required property missing: actions");
3796 }
3797
3798 // Test where fails: actions property is invalid
3799 try
3800 {
3801 const json element = R"(
3802 {
3803 "id": "set_voltage_rule",
3804 "actions": true
3805 }
3806 )"_json;
3807 parseRule(element);
3808 ADD_FAILURE() << "Should not have reached this line.";
3809 }
3810 catch (const std::invalid_argument& e)
3811 {
3812 EXPECT_STREQ(e.what(), "Element is not an array");
3813 }
3814
3815 // Test where fails: Invalid property specified
3816 try
3817 {
3818 const json element = R"(
3819 {
3820 "remarks": [ "Set voltage rule" ],
3821 "id": "set_voltage_rule",
3822 "actions": [
3823 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
3824 ]
3825 }
3826 )"_json;
3827 parseRule(element);
3828 ADD_FAILURE() << "Should not have reached this line.";
3829 }
3830 catch (const std::invalid_argument& e)
3831 {
3832 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3833 }
3834}
3835
3836TEST(ConfigFileParserTests, ParseRuleArray)
3837{
3838 // Test where works
3839 {
3840 const json element = R"(
3841 [
3842 {
3843 "id": "set_voltage_rule1",
3844 "actions": [
3845 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
3846 ]
3847 },
3848 {
3849 "id": "set_voltage_rule2",
3850 "actions": [
3851 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
3852 { "pmbus_write_vout_command": { "volts": 1.11, "format": "linear" } }
3853 ]
3854 }
3855 ]
3856 )"_json;
3857 std::vector<std::unique_ptr<Rule>> rules = parseRuleArray(element);
3858 EXPECT_EQ(rules.size(), 2);
3859 EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1");
3860 EXPECT_EQ(rules[0]->getActions().size(), 1);
3861 EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2");
3862 EXPECT_EQ(rules[1]->getActions().size(), 2);
3863 }
3864
3865 // Test where fails: Element is not an array
3866 try
3867 {
3868 const json element = R"( { "id": "set_voltage_rule" } )"_json;
3869 parseRuleArray(element);
3870 ADD_FAILURE() << "Should not have reached this line.";
3871 }
3872 catch (const std::invalid_argument& e)
3873 {
3874 EXPECT_STREQ(e.what(), "Element is not an array");
3875 }
3876}
3877
Bob King33e7eaa2020-04-01 18:09:34 +08003878TEST(ConfigFileParserTests, ParseRuleIDOrActionsProperty)
3879{
3880 // Test where works: actions specified
3881 {
3882 const json element = R"(
3883 {
3884 "actions": [
3885 { "pmbus_write_vout_command": { "format": "linear" } },
3886 { "run_rule": "set_voltage_rule" }
3887 ]
3888 }
3889 )"_json;
3890 std::vector<std::unique_ptr<Action>> actions =
3891 parseRuleIDOrActionsProperty(element);
3892 EXPECT_EQ(actions.size(), 2);
3893 }
3894
3895 // Test where works: rule_id specified
3896 {
3897 const json element = R"(
3898 {
3899 "rule_id": "set_voltage_rule"
3900 }
3901 )"_json;
3902 std::vector<std::unique_ptr<Action>> actions =
3903 parseRuleIDOrActionsProperty(element);
3904 EXPECT_EQ(actions.size(), 1);
3905 }
3906
3907 // Test where fails: Element is not an object
3908 try
3909 {
3910 const json element = R"( [ "foo", "bar" ] )"_json;
3911 parseRuleIDOrActionsProperty(element);
3912 ADD_FAILURE() << "Should not have reached this line.";
3913 }
3914 catch (const std::invalid_argument& e)
3915 {
3916 EXPECT_STREQ(e.what(), "Element is not an object");
3917 }
3918
3919 // Test where fails: rule_id is invalid
3920 try
3921 {
3922 const json element = R"(
3923 { "rule_id": 1 }
3924 )"_json;
3925 parseRuleIDOrActionsProperty(element);
3926 ADD_FAILURE() << "Should not have reached this line.";
3927 }
3928 catch (const std::invalid_argument& e)
3929 {
3930 EXPECT_STREQ(e.what(), "Element is not a string");
3931 }
3932
3933 // Test where fails: actions is invalid
3934 try
3935 {
3936 const json element = R"(
3937 { "actions": 1 }
3938 )"_json;
3939 parseRuleIDOrActionsProperty(element);
3940 ADD_FAILURE() << "Should not have reached this line.";
3941 }
3942 catch (const std::invalid_argument& e)
3943 {
3944 EXPECT_STREQ(e.what(), "Element is not an array");
3945 }
3946
3947 // Test where fails: Neither rule_id nor actions specified
3948 try
3949 {
3950 const json element = R"(
3951 {
3952 "volts": 1.03
3953 }
3954 )"_json;
3955 parseRuleIDOrActionsProperty(element);
3956 ADD_FAILURE() << "Should not have reached this line.";
3957 }
3958 catch (const std::invalid_argument& e)
3959 {
3960 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3961 "either rule_id or actions");
3962 }
3963
3964 // Test where fails: Both rule_id and actions specified
3965 try
3966 {
3967 const json element = R"(
3968 {
3969 "volts": 1.03,
3970 "rule_id": "set_voltage_rule",
3971 "actions": [
3972 {
3973 "pmbus_write_vout_command": {
3974 "format": "linear"
3975 }
3976 }
3977 ]
3978 }
3979 )"_json;
3980 parseRuleIDOrActionsProperty(element);
3981 ADD_FAILURE() << "Should not have reached this line.";
3982 }
3983 catch (const std::invalid_argument& e)
3984 {
3985 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3986 "either rule_id or actions");
3987 }
3988}
3989
Bob King315b0b62020-04-03 21:47:58 +08003990TEST(ConfigFileParserTests, ParseRunRule)
3991{
3992 // Test where works
3993 {
3994 const json element = "vdd_regulator";
3995 std::unique_ptr<RunRuleAction> action = parseRunRule(element);
3996 EXPECT_EQ(action->getRuleID(), "vdd_regulator");
3997 }
3998
3999 // Test where fails: Element is not a string
4000 try
4001 {
4002 const json element = 1;
4003 parseRunRule(element);
4004 ADD_FAILURE() << "Should not have reached this line.";
4005 }
4006 catch (const std::invalid_argument& e)
4007 {
4008 EXPECT_STREQ(e.what(), "Element is not a string");
4009 }
4010
4011 // Test where fails: Empty string
4012 try
4013 {
4014 const json element = "";
4015 parseRunRule(element);
4016 ADD_FAILURE() << "Should not have reached this line.";
4017 }
4018 catch (const std::invalid_argument& e)
4019 {
4020 EXPECT_STREQ(e.what(), "Element contains an empty string");
4021 }
4022}
4023
Bob Kinga2f2a0d2020-04-09 13:32:14 +08004024TEST(ConfigFileParserTests, ParseSensorMonitoring)
4025{
4026 // Test where works: actions property specified
4027 {
4028 const json element = R"(
4029 {
4030 "actions": [
4031 { "run_rule": "read_sensors_rule" }
4032 ]
4033 }
4034 )"_json;
4035 std::unique_ptr<SensorMonitoring> sensorMonitoring =
4036 parseSensorMonitoring(element);
4037 EXPECT_EQ(sensorMonitoring->getActions().size(), 1);
4038 }
4039
4040 // Test where works: rule_id property specified
4041 {
4042 const json element = R"(
4043 {
4044 "comments": [ "comments property" ],
4045 "rule_id": "set_voltage_rule"
4046 }
4047 )"_json;
4048 std::unique_ptr<SensorMonitoring> sensorMonitoring =
4049 parseSensorMonitoring(element);
4050 EXPECT_EQ(sensorMonitoring->getActions().size(), 1);
4051 }
4052
4053 // Test where fails: actions object is invalid
4054 try
4055 {
4056 const json element = R"(
4057 {
4058 "actions": 1
4059 }
4060 )"_json;
4061 parseSensorMonitoring(element);
4062 ADD_FAILURE() << "Should not have reached this line.";
4063 }
4064 catch (const std::invalid_argument& e)
4065 {
4066 EXPECT_STREQ(e.what(), "Element is not an array");
4067 }
4068
4069 // Test where fails: rule_id value is invalid
4070 try
4071 {
4072 const json element = R"(
4073 {
4074 "rule_id": 1
4075 }
4076 )"_json;
4077 parseSensorMonitoring(element);
4078 ADD_FAILURE() << "Should not have reached this line.";
4079 }
4080 catch (const std::invalid_argument& e)
4081 {
4082 EXPECT_STREQ(e.what(), "Element is not a string");
4083 }
4084
4085 // Test where fails: Required actions or rule_id property not specified
4086 try
4087 {
4088 const json element = R"(
4089 {
4090 "comments": [ "comments property" ]
4091 }
4092 )"_json;
4093 parseSensorMonitoring(element);
4094 ADD_FAILURE() << "Should not have reached this line.";
4095 }
4096 catch (const std::invalid_argument& e)
4097 {
4098 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4099 "either rule_id or actions");
4100 }
4101
4102 // Test where fails: Required actions or rule_id property both specified
4103 try
4104 {
4105 const json element = R"(
4106 {
4107 "rule_id": "set_voltage_rule",
4108 "actions": [
4109 { "run_rule": "read_sensors_rule" }
4110 ]
4111 }
4112 )"_json;
4113 parseSensorMonitoring(element);
4114 ADD_FAILURE() << "Should not have reached this line.";
4115 }
4116 catch (const std::invalid_argument& e)
4117 {
4118 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4119 "either rule_id or actions");
4120 }
4121
4122 // Test where fails: Element is not an object
4123 try
4124 {
4125 const json element = R"( [ "foo", "bar" ] )"_json;
4126 parseSensorMonitoring(element);
4127 ADD_FAILURE() << "Should not have reached this line.";
4128 }
4129 catch (const std::invalid_argument& e)
4130 {
4131 EXPECT_STREQ(e.what(), "Element is not an object");
4132 }
4133
4134 // Test where fails: Invalid property specified
4135 try
4136 {
4137 const json element = R"(
4138 {
4139 "foo": "bar",
4140 "actions": [
4141 { "run_rule": "read_sensors_rule" }
4142 ]
4143 }
4144 )"_json;
4145 parseSensorMonitoring(element);
4146 ADD_FAILURE() << "Should not have reached this line.";
4147 }
4148 catch (const std::invalid_argument& e)
4149 {
4150 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4151 }
4152}
4153
Bob King18a68502020-04-17 14:19:56 +08004154TEST(ConfigFileParserTests, ParseSetDevice)
4155{
4156 // Test where works
4157 {
4158 const json element = "regulator1";
4159 std::unique_ptr<SetDeviceAction> action = parseSetDevice(element);
4160 EXPECT_EQ(action->getDeviceID(), "regulator1");
4161 }
4162
4163 // Test where fails: Element is not a string
4164 try
4165 {
4166 const json element = 1;
4167 parseSetDevice(element);
4168 ADD_FAILURE() << "Should not have reached this line.";
4169 }
4170 catch (const std::invalid_argument& e)
4171 {
4172 EXPECT_STREQ(e.what(), "Element is not a string");
4173 }
4174
4175 // Test where fails: Empty string
4176 try
4177 {
4178 const json element = "";
4179 parseSetDevice(element);
4180 ADD_FAILURE() << "Should not have reached this line.";
4181 }
4182 catch (const std::invalid_argument& e)
4183 {
4184 EXPECT_STREQ(e.what(), "Element contains an empty string");
4185 }
4186}
4187
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004188TEST(ConfigFileParserTests, ParseString)
4189{
4190 // Test where works: Empty string
4191 {
4192 const json element = "";
4193 std::string value = parseString(element, true);
4194 EXPECT_EQ(value, "");
4195 }
4196
4197 // Test where works: Non-empty string
4198 {
4199 const json element = "vdd_regulator";
4200 std::string value = parseString(element, false);
4201 EXPECT_EQ(value, "vdd_regulator");
4202 }
4203
4204 // Test where fails: Element is not a string
4205 try
4206 {
4207 const json element = R"( { "foo": "bar" } )"_json;
4208 parseString(element);
4209 ADD_FAILURE() << "Should not have reached this line.";
4210 }
4211 catch (const std::invalid_argument& e)
4212 {
4213 EXPECT_STREQ(e.what(), "Element is not a string");
4214 }
4215
4216 // Test where fails: Empty string
4217 try
4218 {
4219 const json element = "";
4220 parseString(element);
4221 ADD_FAILURE() << "Should not have reached this line.";
4222 }
4223 catch (const std::invalid_argument& e)
4224 {
4225 EXPECT_STREQ(e.what(), "Element contains an empty string");
4226 }
4227}
4228
Bob Kingf617f892020-03-30 19:03:35 +08004229TEST(ConfigFileParserTests, ParseUint8)
4230{
4231 // Test where works: 0
4232 {
4233 const json element = R"( 0 )"_json;
4234 uint8_t value = parseUint8(element);
4235 EXPECT_EQ(value, 0);
4236 }
4237
4238 // Test where works: UINT8_MAX
4239 {
4240 const json element = R"( 255 )"_json;
4241 uint8_t value = parseUint8(element);
4242 EXPECT_EQ(value, 255);
4243 }
4244
4245 // Test where fails: Element is not an integer
4246 try
4247 {
4248 const json element = R"( 1.03 )"_json;
4249 parseUint8(element);
4250 ADD_FAILURE() << "Should not have reached this line.";
4251 }
4252 catch (const std::invalid_argument& e)
4253 {
4254 EXPECT_STREQ(e.what(), "Element is not an integer");
4255 }
4256
4257 // Test where fails: Value < 0
4258 try
4259 {
4260 const json element = R"( -1 )"_json;
4261 parseUint8(element);
4262 ADD_FAILURE() << "Should not have reached this line.";
4263 }
4264 catch (const std::invalid_argument& e)
4265 {
4266 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
4267 }
4268
4269 // Test where fails: Value > UINT8_MAX
4270 try
4271 {
4272 const json element = R"( 256 )"_json;
4273 parseUint8(element);
4274 ADD_FAILURE() << "Should not have reached this line.";
4275 }
4276 catch (const std::invalid_argument& e)
4277 {
4278 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
4279 }
4280}
4281
Bob King0e701132020-04-03 21:50:31 +08004282TEST(ConfigFileParserTests, ParseUnsignedInteger)
4283{
4284 // Test where works: 1
4285 {
4286 const json element = R"( 1 )"_json;
4287 unsigned int value = parseUnsignedInteger(element);
4288 EXPECT_EQ(value, 1);
4289 }
4290
4291 // Test where fails: Element is not an integer
4292 try
4293 {
4294 const json element = R"( 1.5 )"_json;
4295 parseUnsignedInteger(element);
4296 ADD_FAILURE() << "Should not have reached this line.";
4297 }
4298 catch (const std::invalid_argument& e)
4299 {
4300 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
4301 }
4302
4303 // Test where fails: Value < 0
4304 try
4305 {
4306 const json element = R"( -1 )"_json;
4307 parseUnsignedInteger(element);
4308 ADD_FAILURE() << "Should not have reached this line.";
4309 }
4310 catch (const std::invalid_argument& e)
4311 {
4312 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
4313 }
4314}
4315
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004316TEST(ConfigFileParserTests, VerifyIsArray)
4317{
4318 // Test where element is an array
4319 try
4320 {
4321 const json element = R"( [ "foo", "bar" ] )"_json;
4322 verifyIsArray(element);
4323 }
4324 catch (const std::exception& e)
4325 {
4326 ADD_FAILURE() << "Should not have caught exception.";
4327 }
4328
4329 // Test where element is not an array
4330 try
4331 {
4332 const json element = R"( { "foo": "bar" } )"_json;
4333 verifyIsArray(element);
4334 ADD_FAILURE() << "Should not have reached this line.";
4335 }
4336 catch (const std::invalid_argument& e)
4337 {
4338 EXPECT_STREQ(e.what(), "Element is not an array");
4339 }
4340}
4341
4342TEST(ConfigFileParserTests, VerifyIsObject)
4343{
4344 // Test where element is an object
4345 try
4346 {
4347 const json element = R"( { "foo": "bar" } )"_json;
4348 verifyIsObject(element);
4349 }
4350 catch (const std::exception& e)
4351 {
4352 ADD_FAILURE() << "Should not have caught exception.";
4353 }
4354
4355 // Test where element is not an object
4356 try
4357 {
4358 const json element = R"( [ "foo", "bar" ] )"_json;
4359 verifyIsObject(element);
4360 ADD_FAILURE() << "Should not have reached this line.";
4361 }
4362 catch (const std::invalid_argument& e)
4363 {
4364 EXPECT_STREQ(e.what(), "Element is not an object");
4365 }
4366}
4367
4368TEST(ConfigFileParserTests, VerifyPropertyCount)
4369{
4370 // Test where element has expected number of properties
4371 try
4372 {
4373 const json element = R"(
4374 {
4375 "comments": [ "Set voltage rule" ],
4376 "id": "set_voltage_rule"
4377 }
4378 )"_json;
4379 verifyPropertyCount(element, 2);
4380 }
4381 catch (const std::exception& e)
4382 {
4383 ADD_FAILURE() << "Should not have caught exception.";
4384 }
4385
4386 // Test where element has unexpected number of properties
4387 try
4388 {
4389 const json element = R"(
4390 {
4391 "comments": [ "Set voltage rule" ],
4392 "id": "set_voltage_rule",
4393 "foo": 1.3
4394 }
4395 )"_json;
4396 verifyPropertyCount(element, 2);
4397 ADD_FAILURE() << "Should not have reached this line.";
4398 }
4399 catch (const std::invalid_argument& e)
4400 {
4401 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4402 }
4403}