blob: 6953e073c86ec986c99b3477afeb760f5a892b75 [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"
17#include "chassis.hpp"
18#include "config_file_parser.hpp"
19#include "config_file_parser_error.hpp"
Bob King9c36c5f2020-04-06 11:34:09 +080020#include "configuration.hpp"
Bob King0e701132020-04-03 21:50:31 +080021#include "device.hpp"
Bob Kingf09bfe02020-04-13 17:21:15 +080022#include "i2c_compare_bit_action.hpp"
23#include "i2c_compare_byte_action.hpp"
24#include "i2c_compare_bytes_action.hpp"
Bob Kingf617f892020-03-30 19:03:35 +080025#include "i2c_interface.hpp"
26#include "i2c_write_bit_action.hpp"
Bob King87ff9d72020-03-31 14:02:55 +080027#include "i2c_write_byte_action.hpp"
Bob Kingbafcb862020-03-31 16:39:00 +080028#include "i2c_write_bytes_action.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050029#include "pmbus_utils.hpp"
30#include "pmbus_write_vout_command_action.hpp"
Bob King9c36c5f2020-04-06 11:34:09 +080031#include "presence_detection.hpp"
32#include "rail.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050033#include "rule.hpp"
Bob King315b0b62020-04-03 21:47:58 +080034#include "run_rule_action.hpp"
Bob Kinga2f2a0d2020-04-09 13:32:14 +080035#include "sensor_monitoring.hpp"
Shawn McCarney80c0b042020-03-27 12:08:53 -050036#include "tmp_file.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050037
Shawn McCarney80c0b042020-03-27 12:08:53 -050038#include <sys/stat.h> // for chmod()
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050039
40#include <nlohmann/json.hpp>
41
42#include <cstdint>
43#include <cstring>
44#include <exception>
45#include <filesystem>
46#include <fstream>
47#include <memory>
48#include <optional>
49#include <stdexcept>
50#include <string>
51#include <tuple>
52#include <vector>
53
54#include <gtest/gtest.h>
55
56using namespace phosphor::power::regulators;
57using namespace phosphor::power::regulators::config_file_parser;
58using namespace phosphor::power::regulators::config_file_parser::internal;
59using json = nlohmann::json;
60
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050061void writeConfigFile(const std::filesystem::path& pathName,
62 const std::string& contents)
63{
64 std::ofstream file{pathName};
65 file << contents;
66}
67
68void writeConfigFile(const std::filesystem::path& pathName,
69 const json& contents)
70{
71 std::ofstream file{pathName};
72 file << contents;
73}
74
75TEST(ConfigFileParserTests, Parse)
76{
77 // Test where works
78 {
79 const json configFileContents = R"(
80 {
81 "rules": [
82 {
83 "id": "set_voltage_rule1",
84 "actions": [
85 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
86 ]
87 },
88 {
89 "id": "set_voltage_rule2",
90 "actions": [
91 { "pmbus_write_vout_command": { "volts": 1.33, "format": "linear" } }
92 ]
93 }
94 ],
95 "chassis": [
96 { "number": 1 },
97 { "number": 2 },
98 { "number": 3 }
99 ]
100 }
101 )"_json;
102
103 TmpFile configFile;
104 std::filesystem::path pathName{configFile.getName()};
105 writeConfigFile(pathName, configFileContents);
106
107 std::vector<std::unique_ptr<Rule>> rules{};
108 std::vector<std::unique_ptr<Chassis>> chassis{};
109 std::tie(rules, chassis) = parse(pathName);
110
111 EXPECT_EQ(rules.size(), 2);
112 EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1");
113 EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2");
114
Bob King0e701132020-04-03 21:50:31 +0800115 EXPECT_EQ(chassis.size(), 3);
116 EXPECT_EQ(chassis[0]->getNumber(), 1);
117 EXPECT_EQ(chassis[1]->getNumber(), 2);
118 EXPECT_EQ(chassis[2]->getNumber(), 3);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500119 }
120
121 // Test where fails: File does not exist
122 try
123 {
124 std::filesystem::path pathName{"/tmp/non_existent_file"};
125 parse(pathName);
126 ADD_FAILURE() << "Should not have reached this line.";
127 }
128 catch (const ConfigFileParserError& e)
129 {
130 // Expected exception; what() message will vary
131 }
132
133 // Test where fails: File is not readable
134 try
135 {
136 const json configFileContents = R"(
137 {
138 "chassis": [ { "number": 1 } ]
139 }
140 )"_json;
141
142 TmpFile configFile;
143 std::filesystem::path pathName{configFile.getName()};
144 writeConfigFile(pathName, configFileContents);
145
146 chmod(pathName.c_str(), 0222);
147
148 parse(pathName);
149 ADD_FAILURE() << "Should not have reached this line.";
150 }
151 catch (const ConfigFileParserError& e)
152 {
153 // Expected exception; what() message will vary
154 }
155
156 // Test where fails: File is not valid JSON
157 try
158 {
159 const std::string configFileContents = "] foo [";
160
161 TmpFile configFile;
162 std::filesystem::path pathName{configFile.getName()};
163 writeConfigFile(pathName, configFileContents);
164
165 parse(pathName);
166 ADD_FAILURE() << "Should not have reached this line.";
167 }
168 catch (const ConfigFileParserError& e)
169 {
170 // Expected exception; what() message will vary
171 }
172
173 // Test where fails: Error when parsing JSON elements
174 try
175 {
176 const json configFileContents = R"( { "foo": "bar" } )"_json;
177
178 TmpFile configFile;
179 std::filesystem::path pathName{configFile.getName()};
180 writeConfigFile(pathName, configFileContents);
181
182 parse(pathName);
183 ADD_FAILURE() << "Should not have reached this line.";
184 }
185 catch (const ConfigFileParserError& e)
186 {
187 // Expected exception; what() message will vary
188 }
189}
190
191TEST(ConfigFileParserTests, GetRequiredProperty)
192{
193 // Test where property exists
194 {
195 const json element = R"( { "format": "linear" } )"_json;
196 const json& propertyElement = getRequiredProperty(element, "format");
197 EXPECT_EQ(propertyElement.get<std::string>(), "linear");
198 }
199
200 // Test where property does not exist
201 try
202 {
203 const json element = R"( { "volts": 1.03 } )"_json;
204 getRequiredProperty(element, "format");
205 ADD_FAILURE() << "Should not have reached this line.";
206 }
207 catch (const std::invalid_argument& e)
208 {
209 EXPECT_STREQ(e.what(), "Required property missing: format");
210 }
211}
212
213TEST(ConfigFileParserTests, ParseAction)
214{
215 // Test where works: comments property specified
216 {
217 const json element = R"(
218 {
219 "comments": [ "Set output voltage." ],
220 "pmbus_write_vout_command": {
221 "format": "linear"
222 }
223 }
224 )"_json;
225 std::unique_ptr<Action> action = parseAction(element);
226 EXPECT_NE(action.get(), nullptr);
227 }
228
229 // Test where works: comments property not specified
230 {
231 const json element = R"(
232 {
233 "pmbus_write_vout_command": {
234 "format": "linear"
235 }
236 }
237 )"_json;
238 std::unique_ptr<Action> action = parseAction(element);
239 EXPECT_NE(action.get(), nullptr);
240 }
241
242 // Test where works: and action type specified
243 // TODO: Not implemented yet
244
245 // Test where works: compare_presence action type specified
246 // TODO: Not implemented yet
247
248 // Test where works: compare_vpd action type specified
249 // TODO: Not implemented yet
250
251 // Test where works: i2c_compare_bit action type specified
Bob Kingf09bfe02020-04-13 17:21:15 +0800252 {
253 const json element = R"(
254 {
255 "i2c_compare_bit": {
256 "register": "0xA0",
257 "position": 3,
258 "value": 0
259 }
260 }
261 )"_json;
262 std::unique_ptr<Action> action = parseAction(element);
263 EXPECT_NE(action.get(), nullptr);
264 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500265
266 // Test where works: i2c_compare_byte action type specified
Bob Kingf09bfe02020-04-13 17:21:15 +0800267 {
268 const json element = R"(
269 {
270 "i2c_compare_byte": {
271 "register": "0x0A",
272 "value": "0xCC"
273 }
274 }
275 )"_json;
276 std::unique_ptr<Action> action = parseAction(element);
277 EXPECT_NE(action.get(), nullptr);
278 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500279
280 // Test where works: i2c_compare_bytes action type specified
Bob Kingf09bfe02020-04-13 17:21:15 +0800281 {
282 const json element = R"(
283 {
284 "i2c_compare_bytes": {
285 "register": "0x0A",
286 "values": [ "0xCC", "0xFF" ]
287 }
288 }
289 )"_json;
290 std::unique_ptr<Action> action = parseAction(element);
291 EXPECT_NE(action.get(), nullptr);
292 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500293
294 // Test where works: i2c_write_bit action type specified
Bob Kingf617f892020-03-30 19:03:35 +0800295 {
296 const json element = R"(
297 {
298 "i2c_write_bit": {
299 "register": "0xA0",
300 "position": 3,
301 "value": 0
302 }
303 }
304 )"_json;
305 std::unique_ptr<Action> action = parseAction(element);
306 EXPECT_NE(action.get(), nullptr);
307 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500308
309 // Test where works: i2c_write_byte action type specified
Bob King87ff9d72020-03-31 14:02:55 +0800310 {
311 const json element = R"(
312 {
313 "i2c_write_byte": {
314 "register": "0x0A",
315 "value": "0xCC"
316 }
317 }
318 )"_json;
319 std::unique_ptr<Action> action = parseAction(element);
320 EXPECT_NE(action.get(), nullptr);
321 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500322
323 // Test where works: i2c_write_bytes action type specified
Bob Kingbafcb862020-03-31 16:39:00 +0800324 {
325 const json element = R"(
326 {
327 "i2c_write_bytes": {
328 "register": "0x0A",
329 "values": [ "0xCC", "0xFF" ]
330 }
331 }
332 )"_json;
333 std::unique_ptr<Action> action = parseAction(element);
334 EXPECT_NE(action.get(), nullptr);
335 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500336
337 // Test where works: if action type specified
338 // TODO: Not implemented yet
339
340 // Test where works: not action type specified
341 // TODO: Not implemented yet
342
343 // Test where works: or action type specified
344 // TODO: Not implemented yet
345
346 // Test where works: pmbus_read_sensor action type specified
347 // TODO: Not implemented yet
348
349 // Test where works: pmbus_write_vout_command action type specified
350 {
351 const json element = R"(
352 {
353 "pmbus_write_vout_command": {
354 "format": "linear"
355 }
356 }
357 )"_json;
358 std::unique_ptr<Action> action = parseAction(element);
359 EXPECT_NE(action.get(), nullptr);
360 }
361
362 // Test where works: run_rule action type specified
Bob King315b0b62020-04-03 21:47:58 +0800363 {
364 const json element = R"(
365 {
366 "run_rule": "set_voltage_rule"
367 }
368 )"_json;
369 std::unique_ptr<Action> action = parseAction(element);
370 EXPECT_NE(action.get(), nullptr);
371 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500372
373 // Test where works: set_device action type specified
374 // TODO: Not implemented yet
375
376 // Test where fails: Element is not an object
377 try
378 {
379 const json element = R"( [ "0xFF", "0x01" ] )"_json;
380 parseAction(element);
381 ADD_FAILURE() << "Should not have reached this line.";
382 }
383 catch (const std::invalid_argument& e)
384 {
385 EXPECT_STREQ(e.what(), "Element is not an object");
386 }
387
388 // Test where fails: No action type specified
389 try
390 {
391 const json element = R"(
392 {
393 "comments": [ "Set output voltage." ]
394 }
395 )"_json;
396 parseAction(element);
397 ADD_FAILURE() << "Should not have reached this line.";
398 }
399 catch (const std::invalid_argument& e)
400 {
401 EXPECT_STREQ(e.what(), "Required action type property missing");
402 }
403
404 // Test where fails: Multiple action types specified
Bob King0e701132020-04-03 21:50:31 +0800405 try
406 {
407 const json element = R"(
408 {
409 "pmbus_write_vout_command": { "format": "linear" },
410 "run_rule": "set_voltage_rule"
411 }
412 )"_json;
413 parseAction(element);
414 ADD_FAILURE() << "Should not have reached this line.";
415 }
416 catch (const std::invalid_argument& e)
417 {
418 EXPECT_STREQ(e.what(), "Element contains an invalid property");
419 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500420
421 // Test where fails: Invalid property specified
422 try
423 {
424 const json element = R"(
425 {
426 "remarks": [ "Set output voltage." ],
427 "pmbus_write_vout_command": {
428 "format": "linear"
429 }
430 }
431 )"_json;
432 parseAction(element);
433 ADD_FAILURE() << "Should not have reached this line.";
434 }
435 catch (const std::invalid_argument& e)
436 {
437 EXPECT_STREQ(e.what(), "Element contains an invalid property");
438 }
439}
440
441TEST(ConfigFileParserTests, ParseActionArray)
442{
443 // Test where works
444 {
445 const json element = R"(
446 [
447 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
448 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
449 ]
450 )"_json;
451 std::vector<std::unique_ptr<Action>> actions =
452 parseActionArray(element);
453 EXPECT_EQ(actions.size(), 2);
454 }
455
456 // Test where fails: Element is not an array
457 try
458 {
459 const json element = R"(
460 {
461 "foo": "bar"
462 }
463 )"_json;
464 parseActionArray(element);
465 ADD_FAILURE() << "Should not have reached this line.";
466 }
467 catch (const std::invalid_argument& e)
468 {
469 EXPECT_STREQ(e.what(), "Element is not an array");
470 }
471}
472
Bob Kingf617f892020-03-30 19:03:35 +0800473TEST(ConfigFileParserTests, ParseBitPosition)
474{
475 // Test where works: 0
476 {
477 const json element = R"( 0 )"_json;
478 uint8_t value = parseBitPosition(element);
479 EXPECT_EQ(value, 0);
480 }
481
482 // Test where works: 7
483 {
484 const json element = R"( 7 )"_json;
485 uint8_t value = parseBitPosition(element);
486 EXPECT_EQ(value, 7);
487 }
488
489 // Test where fails: Element is not an integer
490 try
491 {
492 const json element = R"( 1.03 )"_json;
493 parseBitPosition(element);
494 ADD_FAILURE() << "Should not have reached this line.";
495 }
496 catch (const std::invalid_argument& e)
497 {
498 EXPECT_STREQ(e.what(), "Element is not an integer");
499 }
500
501 // Test where fails: Value < 0
502 try
503 {
504 const json element = R"( -1 )"_json;
505 parseBitPosition(element);
506 ADD_FAILURE() << "Should not have reached this line.";
507 }
508 catch (const std::invalid_argument& e)
509 {
510 EXPECT_STREQ(e.what(), "Element is not a bit position");
511 }
512
513 // Test where fails: Value > 7
514 try
515 {
516 const json element = R"( 8 )"_json;
517 parseBitPosition(element);
518 ADD_FAILURE() << "Should not have reached this line.";
519 }
520 catch (const std::invalid_argument& e)
521 {
522 EXPECT_STREQ(e.what(), "Element is not a bit position");
523 }
524}
525
526TEST(ConfigFileParserTests, ParseBitValue)
527{
528 // Test where works: 0
529 {
530 const json element = R"( 0 )"_json;
531 uint8_t value = parseBitValue(element);
532 EXPECT_EQ(value, 0);
533 }
534
535 // Test where works: 1
536 {
537 const json element = R"( 1 )"_json;
538 uint8_t value = parseBitValue(element);
539 EXPECT_EQ(value, 1);
540 }
541
542 // Test where fails: Element is not an integer
543 try
544 {
545 const json element = R"( 0.5 )"_json;
546 parseBitValue(element);
547 ADD_FAILURE() << "Should not have reached this line.";
548 }
549 catch (const std::invalid_argument& e)
550 {
551 EXPECT_STREQ(e.what(), "Element is not an integer");
552 }
553
554 // Test where fails: Value < 0
555 try
556 {
557 const json element = R"( -1 )"_json;
558 parseBitValue(element);
559 ADD_FAILURE() << "Should not have reached this line.";
560 }
561 catch (const std::invalid_argument& e)
562 {
563 EXPECT_STREQ(e.what(), "Element is not a bit value");
564 }
565
566 // Test where fails: Value > 1
567 try
568 {
569 const json element = R"( 2 )"_json;
570 parseBitValue(element);
571 ADD_FAILURE() << "Should not have reached this line.";
572 }
573 catch (const std::invalid_argument& e)
574 {
575 EXPECT_STREQ(e.what(), "Element is not a bit value");
576 }
577}
578
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500579TEST(ConfigFileParserTests, ParseBoolean)
580{
581 // Test where works: true
582 {
583 const json element = R"( true )"_json;
584 bool value = parseBoolean(element);
585 EXPECT_EQ(value, true);
586 }
587
588 // Test where works: false
589 {
590 const json element = R"( false )"_json;
591 bool value = parseBoolean(element);
592 EXPECT_EQ(value, false);
593 }
594
595 // Test where fails: Element is not a boolean
596 try
597 {
598 const json element = R"( 1 )"_json;
599 parseBoolean(element);
600 ADD_FAILURE() << "Should not have reached this line.";
601 }
602 catch (const std::invalid_argument& e)
603 {
604 EXPECT_STREQ(e.what(), "Element is not a boolean");
605 }
606}
607
Bob King0e701132020-04-03 21:50:31 +0800608TEST(ConfigFileParserTests, ParseChassis)
609{
610 // Test where works: Only required properties specified
611 {
612 const json element = R"(
613 {
614 "number": 1
615 }
616 )"_json;
617 std::unique_ptr<Chassis> chassis = parseChassis(element);
618 EXPECT_EQ(chassis->getNumber(), 1);
Bob King9c36c5f2020-04-06 11:34:09 +0800619 EXPECT_EQ(chassis->getDevices().size(), 0);
Bob King0e701132020-04-03 21:50:31 +0800620 }
621
622 // Test where works: All properties specified
623 {
624 const json element = R"(
625 {
626 "comments": [ "comments property" ],
627 "number": 2,
628 "devices": [
629 {
630 "id": "vdd_regulator",
631 "is_regulator": true,
632 "fru": "/system/chassis/motherboard/regulator2",
633 "i2c_interface":
634 {
635 "bus": 1,
636 "address": "0x70"
637 }
638 }
639 ]
640 }
641 )"_json;
642 std::unique_ptr<Chassis> chassis = parseChassis(element);
643 EXPECT_EQ(chassis->getNumber(), 2);
Bob King9c36c5f2020-04-06 11:34:09 +0800644 EXPECT_EQ(chassis->getDevices().size(), 1);
645 EXPECT_EQ(chassis->getDevices()[0]->getID(), "vdd_regulator");
Bob King0e701132020-04-03 21:50:31 +0800646 }
647
648 // Test where fails: number value is invalid
649 try
650 {
651 const json element = R"(
652 {
653 "number": 0.5
654 }
655 )"_json;
656 parseChassis(element);
657 ADD_FAILURE() << "Should not have reached this line.";
658 }
659 catch (const std::invalid_argument& e)
660 {
661 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
662 }
663
664 // Test where fails: Invalid property specified
665 try
666 {
667 const json element = R"(
668 {
669 "number": 1,
670 "foo": 2
671 }
672 )"_json;
673 parseChassis(element);
674 ADD_FAILURE() << "Should not have reached this line.";
675 }
676 catch (const std::invalid_argument& e)
677 {
678 EXPECT_STREQ(e.what(), "Element contains an invalid property");
679 }
680
681 // Test where fails: Required number property not specified
682 try
683 {
684 const json element = R"(
685 {
686 "devices": [
687 {
688 "id": "vdd_regulator",
689 "is_regulator": true,
690 "fru": "/system/chassis/motherboard/regulator2",
691 "i2c_interface":
692 {
693 "bus": 1,
694 "address": "0x70"
695 }
696 }
697 ]
698 }
699 )"_json;
700 parseChassis(element);
701 ADD_FAILURE() << "Should not have reached this line.";
702 }
703 catch (const std::invalid_argument& e)
704 {
705 EXPECT_STREQ(e.what(), "Required property missing: number");
706 }
707
708 // Test where fails: Element is not an object
709 try
710 {
711 const json element = R"( [ "0xFF", "0x01" ] )"_json;
712 parseChassis(element);
713 ADD_FAILURE() << "Should not have reached this line.";
714 }
715 catch (const std::invalid_argument& e)
716 {
717 EXPECT_STREQ(e.what(), "Element is not an object");
718 }
719
720 // Test where fails: number value is < 1
721 try
722 {
723 const json element = R"(
724 {
725 "number": 0
726 }
727 )"_json;
728 parseChassis(element);
729 ADD_FAILURE() << "Should not have reached this line.";
730 }
731 catch (const std::invalid_argument& e)
732 {
733 EXPECT_STREQ(e.what(), "Invalid chassis number: Must be > 0");
734 }
735
736 // Test where fails: devices value is invalid
737 try
738 {
739 const json element = R"(
740 {
741 "number": 1,
742 "devices": 2
743 }
744 )"_json;
745 parseChassis(element);
746 ADD_FAILURE() << "Should not have reached this line.";
747 }
748 catch (const std::invalid_argument& e)
749 {
750 EXPECT_STREQ(e.what(), "Element is not an array");
751 }
752}
753
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500754TEST(ConfigFileParserTests, ParseChassisArray)
755{
Bob King0e701132020-04-03 21:50:31 +0800756 // Test where works
757 {
758 const json element = R"(
759 [
760 { "number": 1 },
761 { "number": 2 }
762 ]
763 )"_json;
764 std::vector<std::unique_ptr<Chassis>> chassis =
765 parseChassisArray(element);
766 EXPECT_EQ(chassis.size(), 2);
767 EXPECT_EQ(chassis[0]->getNumber(), 1);
768 EXPECT_EQ(chassis[1]->getNumber(), 2);
769 }
770
771 // Test where fails: Element is not an array
772 try
773 {
774 const json element = R"(
775 {
776 "foo": "bar"
777 }
778 )"_json;
779 parseChassisArray(element);
780 ADD_FAILURE() << "Should not have reached this line.";
781 }
782 catch (const std::invalid_argument& e)
783 {
784 EXPECT_STREQ(e.what(), "Element is not an array");
785 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500786}
787
Bob King33e7eaa2020-04-01 18:09:34 +0800788TEST(ConfigFileParserTests, ParseConfiguration)
789{
790 // Test where works: actions required property specified
791 {
792 const json element = R"(
793 {
794 "actions": [
795 {
796 "pmbus_write_vout_command": {
797 "format": "linear"
798 }
799 }
800 ]
801 }
802 )"_json;
803 std::unique_ptr<Configuration> configuration =
804 parseConfiguration(element);
805 EXPECT_EQ(configuration->getActions().size(), 1);
806 EXPECT_EQ(configuration->getVolts().has_value(), false);
807 }
808
809 // Test where works: volts and actions properties specified
810 {
811 const json element = R"(
812 {
813 "comments": [ "comments property" ],
814 "volts": 1.03,
815 "actions": [
816 { "pmbus_write_vout_command": { "format": "linear" } },
817 { "run_rule": "set_voltage_rule" }
818 ]
819 }
820 )"_json;
821 std::unique_ptr<Configuration> configuration =
822 parseConfiguration(element);
823 EXPECT_EQ(configuration->getVolts().has_value(), true);
824 EXPECT_EQ(configuration->getVolts().value(), 1.03);
825 EXPECT_EQ(configuration->getActions().size(), 2);
826 }
827
828 // Test where works: volts and rule_id properties specified
829 {
830 const json element = R"(
831 {
832 "volts": 1.05,
833 "rule_id": "set_voltage_rule"
834 }
835 )"_json;
836 std::unique_ptr<Configuration> configuration =
837 parseConfiguration(element);
838 EXPECT_EQ(configuration->getVolts().has_value(), true);
839 EXPECT_EQ(configuration->getVolts().value(), 1.05);
840 EXPECT_EQ(configuration->getActions().size(), 1);
841 }
842
843 // Test where fails: volts value is invalid
844 try
845 {
846 const json element = R"(
847 {
848 "volts": "foo",
849 "actions": [
850 {
851 "pmbus_write_vout_command": {
852 "format": "linear"
853 }
854 }
855 ]
856 }
857 )"_json;
858 parseConfiguration(element);
859 ADD_FAILURE() << "Should not have reached this line.";
860 }
861 catch (const std::invalid_argument& e)
862 {
863 EXPECT_STREQ(e.what(), "Element is not a number");
864 }
865
866 // Test where fails: actions object is invalid
867 try
868 {
869 const json element = R"(
870 {
871 "volts": 1.03,
872 "actions": 1
873 }
874 )"_json;
875 parseConfiguration(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 // Test where fails: rule_id value is invalid
884 try
885 {
886 const json element = R"(
887 {
888 "volts": 1.05,
889 "rule_id": 1
890 }
891 )"_json;
892 parseConfiguration(element);
893 ADD_FAILURE() << "Should not have reached this line.";
894 }
895 catch (const std::invalid_argument& e)
896 {
897 EXPECT_STREQ(e.what(), "Element is not a string");
898 }
899
900 // Test where fails: Required actions or rule_id property not specified
901 try
902 {
903 const json element = R"(
904 {
905 "volts": 1.03
906 }
907 )"_json;
908 parseConfiguration(element);
909 ADD_FAILURE() << "Should not have reached this line.";
910 }
911 catch (const std::invalid_argument& e)
912 {
913 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
914 "either rule_id or actions");
915 }
916
917 // Test where fails: Required actions or rule_id property both specified
918 try
919 {
920 const json element = R"(
921 {
922 "volts": 1.03,
923 "rule_id": "set_voltage_rule",
924 "actions": [
925 {
926 "pmbus_write_vout_command": {
927 "format": "linear"
928 }
929 }
930 ]
931 }
932 )"_json;
933 parseConfiguration(element);
934 ADD_FAILURE() << "Should not have reached this line.";
935 }
936 catch (const std::invalid_argument& e)
937 {
938 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
939 "either rule_id or actions");
940 }
941
942 // Test where fails: Element is not an object
943 try
944 {
945 const json element = R"( [ "0xFF", "0x01" ] )"_json;
946 parseConfiguration(element);
947 ADD_FAILURE() << "Should not have reached this line.";
948 }
949 catch (const std::invalid_argument& e)
950 {
951 EXPECT_STREQ(e.what(), "Element is not an object");
952 }
953
954 // Test where fails: Invalid property specified
955 try
956 {
957 const json element = R"(
958 {
959 "volts": 1.03,
960 "rule_id": "set_voltage_rule",
961 "foo": 1
962 }
963 )"_json;
964 parseConfiguration(element);
965 ADD_FAILURE() << "Should not have reached this line.";
966 }
967 catch (const std::invalid_argument& e)
968 {
969 EXPECT_STREQ(e.what(), "Element contains an invalid property");
970 }
971}
972
Bob King9c36c5f2020-04-06 11:34:09 +0800973TEST(ConfigFileParserTests, ParseDevice)
974{
975 // Test where works: Only required properties specified
976 {
977 const json element = R"(
978 {
979 "id": "vdd_regulator",
980 "is_regulator": true,
981 "fru": "/system/chassis/motherboard/regulator2",
982 "i2c_interface": { "bus": 1, "address": "0x70" }
983 }
984 )"_json;
985 std::unique_ptr<Device> device = parseDevice(element);
986 EXPECT_EQ(device->getID(), "vdd_regulator");
987 EXPECT_EQ(device->isRegulator(), true);
988 EXPECT_EQ(device->getFRU(), "/system/chassis/motherboard/regulator2");
989 EXPECT_NE(&(device->getI2CInterface()), nullptr);
990 EXPECT_EQ(device->getPresenceDetection(), nullptr);
991 EXPECT_EQ(device->getConfiguration(), nullptr);
992 EXPECT_EQ(device->getRails().size(), 0);
993 }
994
995 // Test where works: All properties specified
Bob King33e7eaa2020-04-01 18:09:34 +0800996 {
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800997 // TODO : add presence_detection property
Bob King33e7eaa2020-04-01 18:09:34 +0800998 const json element = R"(
999 {
1000 "id": "vdd_regulator",
1001 "is_regulator": true,
1002 "fru": "/system/chassis/motherboard/regulator2",
1003 "i2c_interface":
1004 {
1005 "bus": 1,
1006 "address": "0x70"
1007 },
1008 "configuration":
1009 {
1010 "rule_id": "configure_ir35221_rule"
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001011 },
1012 "rails":
1013 [
1014 {
1015 "id": "vdd"
1016 }
1017 ]
Bob King33e7eaa2020-04-01 18:09:34 +08001018 }
1019 )"_json;
1020 std::unique_ptr<Device> device = parseDevice(element);
1021 EXPECT_EQ(device->getID(), "vdd_regulator");
1022 EXPECT_EQ(device->isRegulator(), true);
1023 EXPECT_EQ(device->getFRU(), "/system/chassis/motherboard/regulator2");
1024 EXPECT_NE(&(device->getI2CInterface()), nullptr);
1025 // EXPECT_NE(device->getPresenceDetection(), nullptr);
1026 EXPECT_NE(device->getConfiguration(), nullptr);
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001027 EXPECT_EQ(device->getRails().size(), 1);
1028 }
1029
1030 // Test where fails: rails property exists and is_regulator is false
1031 try
1032 {
1033 const json element = R"(
1034 {
1035 "id": "vdd_regulator",
1036 "is_regulator": false,
1037 "fru": "/system/chassis/motherboard/regulator2",
1038 "i2c_interface":
1039 {
1040 "bus": 1,
1041 "address": "0x70"
1042 },
1043 "configuration":
1044 {
1045 "rule_id": "configure_ir35221_rule"
1046 },
1047 "rails":
1048 [
1049 {
1050 "id": "vdd"
1051 }
1052 ]
1053 }
1054 )"_json;
1055 parseDevice(element);
1056 ADD_FAILURE() << "Should not have reached this line.";
1057 }
1058 catch (const std::invalid_argument& e)
1059 {
1060 EXPECT_STREQ(e.what(),
1061 "Invalid rails property when is_regulator is false");
Bob King33e7eaa2020-04-01 18:09:34 +08001062 }
Bob King9c36c5f2020-04-06 11:34:09 +08001063
1064 // Test where fails: id value is invalid
1065 try
1066 {
1067 const json element = R"(
1068 {
1069 "id": 3,
1070 "is_regulator": true,
1071 "fru": "/system/chassis/motherboard/regulator2",
1072 "i2c_interface":
1073 {
1074 "bus": 1,
1075 "address": "0x70"
1076 }
1077 }
1078 )"_json;
1079 parseDevice(element);
1080 ADD_FAILURE() << "Should not have reached this line.";
1081 }
1082 catch (const std::invalid_argument& e)
1083 {
1084 EXPECT_STREQ(e.what(), "Element is not a string");
1085 }
1086
1087 // Test where fails: is_regulator value is invalid
1088 try
1089 {
1090 const json element = R"(
1091 {
1092 "id": "vdd_regulator",
1093 "is_regulator": 3,
1094 "fru": "/system/chassis/motherboard/regulator2",
1095 "i2c_interface":
1096 {
1097 "bus": 1,
1098 "address": "0x70"
1099 }
1100 }
1101 )"_json;
1102 parseDevice(element);
1103 ADD_FAILURE() << "Should not have reached this line.";
1104 }
1105 catch (const std::invalid_argument& e)
1106 {
1107 EXPECT_STREQ(e.what(), "Element is not a boolean");
1108 }
1109
1110 // Test where fails: fru value is invalid
1111 try
1112 {
1113 const json element = R"(
1114 {
1115 "id": "vdd_regulator",
1116 "is_regulator": true,
1117 "fru": 2,
1118 "i2c_interface":
1119 {
1120 "bus": 1,
1121 "address": "0x70"
1122 }
1123 }
1124 )"_json;
1125 parseDevice(element);
1126 ADD_FAILURE() << "Should not have reached this line.";
1127 }
1128 catch (const std::invalid_argument& e)
1129 {
1130 EXPECT_STREQ(e.what(), "Element is not a string");
1131 }
1132
1133 // Test where fails: i2c_interface value is invalid
1134 try
1135 {
1136 const json element = R"(
1137 {
1138 "id": "vdd_regulator",
1139 "is_regulator": true,
1140 "fru": "/system/chassis/motherboard/regulator2",
1141 "i2c_interface": 3
1142 }
1143 )"_json;
1144 parseDevice(element);
1145 ADD_FAILURE() << "Should not have reached this line.";
1146 }
1147 catch (const std::invalid_argument& e)
1148 {
1149 EXPECT_STREQ(e.what(), "Element is not an object");
1150 }
1151
1152 // Test where fails: Required id property not specified
1153 try
1154 {
1155 const json element = R"(
1156 {
1157 "is_regulator": true,
1158 "fru": "/system/chassis/motherboard/regulator2",
1159 "i2c_interface":
1160 {
1161 "bus": 1,
1162 "address": "0x70"
1163 }
1164 }
1165 )"_json;
1166 parseDevice(element);
1167 ADD_FAILURE() << "Should not have reached this line.";
1168 }
1169 catch (const std::invalid_argument& e)
1170 {
1171 EXPECT_STREQ(e.what(), "Required property missing: id");
1172 }
1173
1174 // Test where fails: Required is_regulator property not specified
1175 try
1176 {
1177 const json element = R"(
1178 {
1179 "id": "vdd_regulator",
1180 "fru": "/system/chassis/motherboard/regulator2",
1181 "i2c_interface":
1182 {
1183 "bus": 1,
1184 "address": "0x70"
1185 }
1186 }
1187 )"_json;
1188 parseDevice(element);
1189 ADD_FAILURE() << "Should not have reached this line.";
1190 }
1191 catch (const std::invalid_argument& e)
1192 {
1193 EXPECT_STREQ(e.what(), "Required property missing: is_regulator");
1194 }
1195
1196 // Test where fails: Required fru property not specified
1197 try
1198 {
1199 const json element = R"(
1200 {
1201 "id": "vdd_regulator",
1202 "is_regulator": true,
1203 "i2c_interface":
1204 {
1205 "bus": 1,
1206 "address": "0x70"
1207 }
1208 }
1209 )"_json;
1210 parseDevice(element);
1211 ADD_FAILURE() << "Should not have reached this line.";
1212 }
1213 catch (const std::invalid_argument& e)
1214 {
1215 EXPECT_STREQ(e.what(), "Required property missing: fru");
1216 }
1217
1218 // Test where fails: Required i2c_interface property not specified
1219 try
1220 {
1221 const json element = R"(
1222 {
1223 "id": "vdd_regulator",
1224 "is_regulator": true,
1225 "fru": "/system/chassis/motherboard/regulator2"
1226 }
1227 )"_json;
1228 parseDevice(element);
1229 ADD_FAILURE() << "Should not have reached this line.";
1230 }
1231 catch (const std::invalid_argument& e)
1232 {
1233 EXPECT_STREQ(e.what(), "Required property missing: i2c_interface");
1234 }
1235
1236 // Test where fails: Element is not an object
1237 try
1238 {
1239 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1240 parseDevice(element);
1241 ADD_FAILURE() << "Should not have reached this line.";
1242 }
1243 catch (const std::invalid_argument& e)
1244 {
1245 EXPECT_STREQ(e.what(), "Element is not an object");
1246 }
1247
1248 // Test where fails: Invalid property specified
1249 try
1250 {
1251 const json element = R"(
1252 {
1253 "id": "vdd_regulator",
1254 "is_regulator": true,
1255 "fru": "/system/chassis/motherboard/regulator2",
1256 "i2c_interface": { "bus": 1, "address": "0x70" },
1257 "foo" : true
1258 }
1259 )"_json;
1260 parseDevice(element);
1261 ADD_FAILURE() << "Should not have reached this line.";
1262 }
1263 catch (const std::invalid_argument& e)
1264 {
1265 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1266 }
1267}
1268
1269TEST(ConfigFileParserTests, ParseDeviceArray)
1270{
1271 // Test where works
1272 {
1273 const json element = R"(
1274 [
1275 {
1276 "id": "vdd_regulator",
1277 "is_regulator": true,
1278 "fru": "/system/chassis/motherboard/regulator2",
1279 "i2c_interface": { "bus": 1, "address": "0x70" }
1280 },
1281 {
1282 "id": "vio_regulator",
1283 "is_regulator": true,
1284 "fru": "/system/chassis/motherboard/regulator2",
1285 "i2c_interface": { "bus": 1, "address": "0x71" }
1286 }
1287 ]
1288 )"_json;
1289 std::vector<std::unique_ptr<Device>> devices =
1290 parseDeviceArray(element);
1291 EXPECT_EQ(devices.size(), 2);
1292 EXPECT_EQ(devices[0]->getID(), "vdd_regulator");
1293 EXPECT_EQ(devices[1]->getID(), "vio_regulator");
1294 }
1295
1296 // Test where fails: Element is not an array
1297 try
1298 {
1299 const json element = R"(
1300 {
1301 "foo": "bar"
1302 }
1303 )"_json;
1304 parseDeviceArray(element);
1305 ADD_FAILURE() << "Should not have reached this line.";
1306 }
1307 catch (const std::invalid_argument& e)
1308 {
1309 EXPECT_STREQ(e.what(), "Element is not an array");
1310 }
1311}
1312
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001313TEST(ConfigFileParserTests, ParseDouble)
1314{
1315 // Test where works: floating point value
1316 {
1317 const json element = R"( 1.03 )"_json;
1318 double value = parseDouble(element);
1319 EXPECT_EQ(value, 1.03);
1320 }
1321
1322 // Test where works: integer value
1323 {
1324 const json element = R"( 24 )"_json;
1325 double value = parseDouble(element);
1326 EXPECT_EQ(value, 24.0);
1327 }
1328
1329 // Test where fails: Element is not a number
1330 try
1331 {
1332 const json element = R"( true )"_json;
1333 parseDouble(element);
1334 ADD_FAILURE() << "Should not have reached this line.";
1335 }
1336 catch (const std::invalid_argument& e)
1337 {
1338 EXPECT_STREQ(e.what(), "Element is not a number");
1339 }
1340}
1341
Bob Kingbafcb862020-03-31 16:39:00 +08001342TEST(ConfigFileParserTests, ParseHexByte)
1343{
1344 // Test where works: "0xFF"
1345 {
1346 const json element = R"( "0xFF" )"_json;
1347 uint8_t value = parseHexByte(element);
1348 EXPECT_EQ(value, 0xFF);
1349 }
1350
1351 // Test where works: "0xff"
1352 {
1353 const json element = R"( "0xff" )"_json;
1354 uint8_t value = parseHexByte(element);
1355 EXPECT_EQ(value, 0xff);
1356 }
1357
1358 // Test where works: "0xf"
1359 {
1360 const json element = R"( "0xf" )"_json;
1361 uint8_t value = parseHexByte(element);
1362 EXPECT_EQ(value, 0xf);
1363 }
1364
1365 // Test where fails: "0xfff"
1366 try
1367 {
1368 const json element = R"( "0xfff" )"_json;
1369 parseHexByte(element);
1370 ADD_FAILURE() << "Should not have reached this line.";
1371 }
1372 catch (const std::invalid_argument& e)
1373 {
1374 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1375 }
1376
1377 // Test where fails: "0xAG"
1378 try
1379 {
1380 const json element = R"( "0xAG" )"_json;
1381 parseHexByte(element);
1382 ADD_FAILURE() << "Should not have reached this line.";
1383 }
1384 catch (const std::invalid_argument& e)
1385 {
1386 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1387 }
1388
1389 // Test where fails: "ff"
1390 try
1391 {
1392 const json element = R"( "ff" )"_json;
1393 parseHexByte(element);
1394 ADD_FAILURE() << "Should not have reached this line.";
1395 }
1396 catch (const std::invalid_argument& e)
1397 {
1398 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1399 }
1400
1401 // Test where fails: ""
1402 try
1403 {
1404 const json element = "";
1405 parseHexByte(element);
1406 ADD_FAILURE() << "Should not have reached this line.";
1407 }
1408 catch (const std::invalid_argument& e)
1409 {
1410 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1411 }
1412
1413 // Test where fails: "f"
1414 try
1415 {
1416 const json element = R"( "f" )"_json;
1417 parseHexByte(element);
1418 ADD_FAILURE() << "Should not have reached this line.";
1419 }
1420 catch (const std::invalid_argument& e)
1421 {
1422 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1423 }
1424
1425 // Test where fails: "0x"
1426 try
1427 {
1428 const json element = R"( "0x" )"_json;
1429 parseHexByte(element);
1430 ADD_FAILURE() << "Should not have reached this line.";
1431 }
1432 catch (const std::invalid_argument& e)
1433 {
1434 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1435 }
1436
1437 // Test where fails: "0Xff"
1438 try
1439 {
1440 const json element = R"( "0XFF" )"_json;
1441 parseHexByte(element);
1442 ADD_FAILURE() << "Should not have reached this line.";
1443 }
1444 catch (const std::invalid_argument& e)
1445 {
1446 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1447 }
1448}
1449
1450TEST(ConfigFileParserTests, ParseHexByteArray)
1451{
1452 // Test where works
1453 {
1454 const json element = R"( [ "0xCC", "0xFF" ] )"_json;
1455 std::vector<uint8_t> hexBytes = parseHexByteArray(element);
1456 std::vector<uint8_t> expected = {0xcc, 0xff};
1457 EXPECT_EQ(hexBytes, expected);
1458 }
1459
1460 // Test where fails: Element is not an array
1461 try
1462 {
1463 const json element = 0;
1464 parseHexByteArray(element);
1465 ADD_FAILURE() << "Should not have reached this line.";
1466 }
1467 catch (const std::invalid_argument& e)
1468 {
1469 EXPECT_STREQ(e.what(), "Element is not an array");
1470 }
1471}
1472
Bob Kingf09bfe02020-04-13 17:21:15 +08001473TEST(ConfigFileParserTests, ParseI2CCompareBit)
1474{
1475 // Test where works
1476 {
1477 const json element = R"(
1478 {
1479 "register": "0xA0",
1480 "position": 3,
1481 "value": 0
1482 }
1483 )"_json;
1484 std::unique_ptr<I2CCompareBitAction> action =
1485 parseI2CCompareBit(element);
1486 EXPECT_EQ(action->getRegister(), 0xA0);
1487 EXPECT_EQ(action->getPosition(), 3);
1488 EXPECT_EQ(action->getValue(), 0);
1489 }
1490
1491 // Test where fails: Invalid property specified
1492 try
1493 {
1494 const json element = R"(
1495 {
1496 "register": "0xA0",
1497 "position": 3,
1498 "value": 0,
1499 "foo": 3
1500 }
1501 )"_json;
1502 parseI2CCompareBit(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 contains an invalid property");
1508 }
1509
1510 // Test where fails: Element is not an object
1511 try
1512 {
1513 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1514 parseI2CCompareBit(element);
1515 ADD_FAILURE() << "Should not have reached this line.";
1516 }
1517 catch (const std::invalid_argument& e)
1518 {
1519 EXPECT_STREQ(e.what(), "Element is not an object");
1520 }
1521
1522 // Test where fails: register value is invalid
1523 try
1524 {
1525 const json element = R"(
1526 {
1527 "register": "0xAG",
1528 "position": 3,
1529 "value": 0
1530 }
1531 )"_json;
1532 parseI2CCompareBit(element);
1533 ADD_FAILURE() << "Should not have reached this line.";
1534 }
1535 catch (const std::invalid_argument& e)
1536 {
1537 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1538 }
1539
1540 // Test where fails: position value is invalid
1541 try
1542 {
1543 const json element = R"(
1544 {
1545 "register": "0xA0",
1546 "position": 8,
1547 "value": 0
1548 }
1549 )"_json;
1550 parseI2CCompareBit(element);
1551 ADD_FAILURE() << "Should not have reached this line.";
1552 }
1553 catch (const std::invalid_argument& e)
1554 {
1555 EXPECT_STREQ(e.what(), "Element is not a bit position");
1556 }
1557
1558 // Test where fails: value value is invalid
1559 try
1560 {
1561 const json element = R"(
1562 {
1563 "register": "0xA0",
1564 "position": 3,
1565 "value": 2
1566 }
1567 )"_json;
1568 parseI2CCompareBit(element);
1569 ADD_FAILURE() << "Should not have reached this line.";
1570 }
1571 catch (const std::invalid_argument& e)
1572 {
1573 EXPECT_STREQ(e.what(), "Element is not a bit value");
1574 }
1575
1576 // Test where fails: Required register property not specified
1577 try
1578 {
1579 const json element = R"(
1580 {
1581 "position": 3,
1582 "value": 0
1583 }
1584 )"_json;
1585 parseI2CCompareBit(element);
1586 ADD_FAILURE() << "Should not have reached this line.";
1587 }
1588 catch (const std::invalid_argument& e)
1589 {
1590 EXPECT_STREQ(e.what(), "Required property missing: register");
1591 }
1592
1593 // Test where fails: Required position property not specified
1594 try
1595 {
1596 const json element = R"(
1597 {
1598 "register": "0xA0",
1599 "value": 0
1600 }
1601 )"_json;
1602 parseI2CCompareBit(element);
1603 ADD_FAILURE() << "Should not have reached this line.";
1604 }
1605 catch (const std::invalid_argument& e)
1606 {
1607 EXPECT_STREQ(e.what(), "Required property missing: position");
1608 }
1609
1610 // Test where fails: Required value property not specified
1611 try
1612 {
1613 const json element = R"(
1614 {
1615 "register": "0xA0",
1616 "position": 3
1617 }
1618 )"_json;
1619 parseI2CCompareBit(element);
1620 ADD_FAILURE() << "Should not have reached this line.";
1621 }
1622 catch (const std::invalid_argument& e)
1623 {
1624 EXPECT_STREQ(e.what(), "Required property missing: value");
1625 }
1626}
1627
1628TEST(ConfigFileParserTests, ParseI2CCompareByte)
1629{
1630 // Test where works: Only required properties specified
1631 {
1632 const json element = R"(
1633 {
1634 "register": "0x0A",
1635 "value": "0xCC"
1636 }
1637 )"_json;
1638 std::unique_ptr<I2CCompareByteAction> action =
1639 parseI2CCompareByte(element);
1640 EXPECT_EQ(action->getRegister(), 0x0A);
1641 EXPECT_EQ(action->getValue(), 0xCC);
1642 EXPECT_EQ(action->getMask(), 0xFF);
1643 }
1644
1645 // Test where works: All properties specified
1646 {
1647 const json element = R"(
1648 {
1649 "register": "0x0A",
1650 "value": "0xCC",
1651 "mask": "0xF7"
1652 }
1653 )"_json;
1654 std::unique_ptr<I2CCompareByteAction> action =
1655 parseI2CCompareByte(element);
1656 EXPECT_EQ(action->getRegister(), 0x0A);
1657 EXPECT_EQ(action->getValue(), 0xCC);
1658 EXPECT_EQ(action->getMask(), 0xF7);
1659 }
1660
1661 // Test where fails: Element is not an object
1662 try
1663 {
1664 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1665 parseI2CCompareByte(element);
1666 ADD_FAILURE() << "Should not have reached this line.";
1667 }
1668 catch (const std::invalid_argument& e)
1669 {
1670 EXPECT_STREQ(e.what(), "Element is not an object");
1671 }
1672
1673 // Test where fails: Invalid property specified
1674 try
1675 {
1676 const json element = R"(
1677 {
1678 "register": "0x0A",
1679 "value": "0xCC",
1680 "mask": "0xF7",
1681 "foo": 1
1682 }
1683 )"_json;
1684 parseI2CCompareByte(element);
1685 ADD_FAILURE() << "Should not have reached this line.";
1686 }
1687 catch (const std::invalid_argument& e)
1688 {
1689 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1690 }
1691
1692 // Test where fails: register value is invalid
1693 try
1694 {
1695 const json element = R"(
1696 {
1697 "register": "0x0Z",
1698 "value": "0xCC",
1699 "mask": "0xF7"
1700 }
1701 )"_json;
1702 parseI2CCompareByte(element);
1703 ADD_FAILURE() << "Should not have reached this line.";
1704 }
1705 catch (const std::invalid_argument& e)
1706 {
1707 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1708 }
1709
1710 // Test where fails: value value is invalid
1711 try
1712 {
1713 const json element = R"(
1714 {
1715 "register": "0x0A",
1716 "value": "0xCCC",
1717 "mask": "0xF7"
1718 }
1719 )"_json;
1720 parseI2CCompareByte(element);
1721 ADD_FAILURE() << "Should not have reached this line.";
1722 }
1723 catch (const std::invalid_argument& e)
1724 {
1725 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1726 }
1727
1728 // Test where fails: mask value is invalid
1729 try
1730 {
1731 const json element = R"(
1732 {
1733 "register": "0x0A",
1734 "value": "0xCC",
1735 "mask": "F7"
1736 }
1737 )"_json;
1738 parseI2CCompareByte(element);
1739 ADD_FAILURE() << "Should not have reached this line.";
1740 }
1741 catch (const std::invalid_argument& e)
1742 {
1743 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1744 }
1745
1746 // Test where fails: Required register property not specified
1747 try
1748 {
1749 const json element = R"(
1750 {
1751 "value": "0xCC",
1752 "mask": "0xF7"
1753 }
1754 )"_json;
1755 parseI2CCompareByte(element);
1756 ADD_FAILURE() << "Should not have reached this line.";
1757 }
1758 catch (const std::invalid_argument& e)
1759 {
1760 EXPECT_STREQ(e.what(), "Required property missing: register");
1761 }
1762
1763 // Test where fails: Required value property not specified
1764 try
1765 {
1766 const json element = R"(
1767 {
1768 "register": "0x0A",
1769 "mask": "0xF7"
1770 }
1771 )"_json;
1772 parseI2CCompareByte(element);
1773 ADD_FAILURE() << "Should not have reached this line.";
1774 }
1775 catch (const std::invalid_argument& e)
1776 {
1777 EXPECT_STREQ(e.what(), "Required property missing: value");
1778 }
1779}
1780
1781TEST(ConfigFileParserTests, ParseI2CCompareBytes)
1782{
1783 // Test where works: Only required properties specified
1784 {
1785 const json element = R"(
1786 {
1787 "register": "0x0A",
1788 "values": [ "0xCC", "0xFF" ]
1789 }
1790 )"_json;
1791 std::unique_ptr<I2CCompareBytesAction> action =
1792 parseI2CCompareBytes(element);
1793 EXPECT_EQ(action->getRegister(), 0x0A);
1794 EXPECT_EQ(action->getValues().size(), 2);
1795 EXPECT_EQ(action->getValues()[0], 0xCC);
1796 EXPECT_EQ(action->getValues()[1], 0xFF);
1797 EXPECT_EQ(action->getMasks().size(), 2);
1798 EXPECT_EQ(action->getMasks()[0], 0xFF);
1799 EXPECT_EQ(action->getMasks()[1], 0xFF);
1800 }
1801
1802 // Test where works: All properties specified
1803 {
1804 const json element = R"(
1805 {
1806 "register": "0x0A",
1807 "values": [ "0xCC", "0xFF" ],
1808 "masks": [ "0x7F", "0x77" ]
1809 }
1810 )"_json;
1811 std::unique_ptr<I2CCompareBytesAction> action =
1812 parseI2CCompareBytes(element);
1813 EXPECT_EQ(action->getRegister(), 0x0A);
1814 EXPECT_EQ(action->getValues().size(), 2);
1815 EXPECT_EQ(action->getValues()[0], 0xCC);
1816 EXPECT_EQ(action->getValues()[1], 0xFF);
1817 EXPECT_EQ(action->getMasks().size(), 2);
1818 EXPECT_EQ(action->getMasks()[0], 0x7F);
1819 EXPECT_EQ(action->getMasks()[1], 0x77);
1820 }
1821
1822 // Test where fails: Element is not an object
1823 try
1824 {
1825 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1826 parseI2CCompareBytes(element);
1827 ADD_FAILURE() << "Should not have reached this line.";
1828 }
1829 catch (const std::invalid_argument& e)
1830 {
1831 EXPECT_STREQ(e.what(), "Element is not an object");
1832 }
1833
1834 // Test where fails: Invalid property specified
1835 try
1836 {
1837 const json element = R"(
1838 {
1839 "register": "0x0A",
1840 "values": [ "0xCC", "0xFF" ],
1841 "masks": [ "0x7F", "0x7F" ],
1842 "foo": 1
1843 }
1844 )"_json;
1845 parseI2CCompareBytes(element);
1846 ADD_FAILURE() << "Should not have reached this line.";
1847 }
1848 catch (const std::invalid_argument& e)
1849 {
1850 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1851 }
1852
1853 // Test where fails: register value is invalid
1854 try
1855 {
1856 const json element = R"(
1857 {
1858 "register": "0x0Z",
1859 "values": [ "0xCC", "0xFF" ],
1860 "masks": [ "0x7F", "0x7F" ]
1861 }
1862 )"_json;
1863 parseI2CCompareBytes(element);
1864 ADD_FAILURE() << "Should not have reached this line.";
1865 }
1866 catch (const std::invalid_argument& e)
1867 {
1868 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1869 }
1870
1871 // Test where fails: values value is invalid
1872 try
1873 {
1874 const json element = R"(
1875 {
1876 "register": "0x0A",
1877 "values": [ "0xCCC", "0xFF" ],
1878 "masks": [ "0x7F", "0x7F" ]
1879 }
1880 )"_json;
1881 parseI2CCompareBytes(element);
1882 ADD_FAILURE() << "Should not have reached this line.";
1883 }
1884 catch (const std::invalid_argument& e)
1885 {
1886 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1887 }
1888
1889 // Test where fails: masks value is invalid
1890 try
1891 {
1892 const json element = R"(
1893 {
1894 "register": "0x0A",
1895 "values": [ "0xCC", "0xFF" ],
1896 "masks": [ "F", "0x7F" ]
1897 }
1898 )"_json;
1899 parseI2CCompareBytes(element);
1900 ADD_FAILURE() << "Should not have reached this line.";
1901 }
1902 catch (const std::invalid_argument& e)
1903 {
1904 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1905 }
1906
1907 // Test where fails: number of elements in masks is invalid
1908 try
1909 {
1910 const json element = R"(
1911 {
1912 "register": "0x0A",
1913 "values": [ "0xCC", "0xFF" ],
1914 "masks": [ "0x7F" ]
1915 }
1916 )"_json;
1917 parseI2CCompareBytes(element);
1918 ADD_FAILURE() << "Should not have reached this line.";
1919 }
1920 catch (const std::invalid_argument& e)
1921 {
1922 EXPECT_STREQ(e.what(), "Invalid number of elements in masks");
1923 }
1924
1925 // Test where fails: Required register property not specified
1926 try
1927 {
1928 const json element = R"(
1929 {
1930 "values": [ "0xCC", "0xFF" ]
1931 }
1932 )"_json;
1933 parseI2CCompareBytes(element);
1934 ADD_FAILURE() << "Should not have reached this line.";
1935 }
1936 catch (const std::invalid_argument& e)
1937 {
1938 EXPECT_STREQ(e.what(), "Required property missing: register");
1939 }
1940
1941 // Test where fails: Required values property not specified
1942 try
1943 {
1944 const json element = R"(
1945 {
1946 "register": "0x0A"
1947 }
1948 )"_json;
1949 parseI2CCompareBytes(element);
1950 ADD_FAILURE() << "Should not have reached this line.";
1951 }
1952 catch (const std::invalid_argument& e)
1953 {
1954 EXPECT_STREQ(e.what(), "Required property missing: values");
1955 }
1956}
1957
Bob Kingf617f892020-03-30 19:03:35 +08001958TEST(ConfigFileParserTests, ParseI2CWriteBit)
1959{
1960 // Test where works
1961 {
1962 const json element = R"(
1963 {
1964 "register": "0xA0",
1965 "position": 3,
1966 "value": 0
1967 }
1968 )"_json;
1969 std::unique_ptr<I2CWriteBitAction> action = parseI2CWriteBit(element);
1970 EXPECT_EQ(action->getRegister(), 0xA0);
1971 EXPECT_EQ(action->getPosition(), 3);
1972 EXPECT_EQ(action->getValue(), 0);
1973 }
1974
1975 // Test where fails: Invalid property specified
1976 try
1977 {
1978 const json element = R"(
1979 {
1980 "register": "0xA0",
1981 "position": 3,
1982 "value": 0,
1983 "foo": 3
1984 }
1985 )"_json;
1986 parseI2CWriteBit(element);
1987 ADD_FAILURE() << "Should not have reached this line.";
1988 }
1989 catch (const std::invalid_argument& e)
1990 {
1991 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1992 }
1993
1994 // Test where fails: Element is not an object
1995 try
1996 {
1997 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1998 parseI2CWriteBit(element);
1999 ADD_FAILURE() << "Should not have reached this line.";
2000 }
2001 catch (const std::invalid_argument& e)
2002 {
2003 EXPECT_STREQ(e.what(), "Element is not an object");
2004 }
2005
2006 // Test where fails: register value is invalid
2007 try
2008 {
2009 const json element = R"(
2010 {
2011 "register": "0xAG",
2012 "position": 3,
2013 "value": 0
2014 }
2015 )"_json;
2016 parseI2CWriteBit(element);
2017 ADD_FAILURE() << "Should not have reached this line.";
2018 }
2019 catch (const std::invalid_argument& e)
2020 {
2021 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2022 }
2023
2024 // Test where fails: position value is invalid
2025 try
2026 {
2027 const json element = R"(
2028 {
2029 "register": "0xA0",
2030 "position": 8,
2031 "value": 0
2032 }
2033 )"_json;
2034 parseI2CWriteBit(element);
2035 ADD_FAILURE() << "Should not have reached this line.";
2036 }
2037 catch (const std::invalid_argument& e)
2038 {
2039 EXPECT_STREQ(e.what(), "Element is not a bit position");
2040 }
2041
2042 // Test where fails: value value is invalid
2043 try
2044 {
2045 const json element = R"(
2046 {
2047 "register": "0xA0",
2048 "position": 3,
2049 "value": 2
2050 }
2051 )"_json;
2052 parseI2CWriteBit(element);
2053 ADD_FAILURE() << "Should not have reached this line.";
2054 }
2055 catch (const std::invalid_argument& e)
2056 {
2057 EXPECT_STREQ(e.what(), "Element is not a bit value");
2058 }
2059
2060 // Test where fails: Required register property not specified
2061 try
2062 {
2063 const json element = R"(
2064 {
2065 "position": 3,
2066 "value": 0
2067 }
2068 )"_json;
2069 parseI2CWriteBit(element);
2070 ADD_FAILURE() << "Should not have reached this line.";
2071 }
2072 catch (const std::invalid_argument& e)
2073 {
2074 EXPECT_STREQ(e.what(), "Required property missing: register");
2075 }
2076
2077 // Test where fails: Required position property not specified
2078 try
2079 {
2080 const json element = R"(
2081 {
2082 "register": "0xA0",
2083 "value": 0
2084 }
2085 )"_json;
2086 parseI2CWriteBit(element);
2087 ADD_FAILURE() << "Should not have reached this line.";
2088 }
2089 catch (const std::invalid_argument& e)
2090 {
2091 EXPECT_STREQ(e.what(), "Required property missing: position");
2092 }
2093
2094 // Test where fails: Required value property not specified
2095 try
2096 {
2097 const json element = R"(
2098 {
2099 "register": "0xA0",
2100 "position": 3
2101 }
2102 )"_json;
2103 parseI2CWriteBit(element);
2104 ADD_FAILURE() << "Should not have reached this line.";
2105 }
2106 catch (const std::invalid_argument& e)
2107 {
2108 EXPECT_STREQ(e.what(), "Required property missing: value");
2109 }
2110}
2111
Bob King87ff9d72020-03-31 14:02:55 +08002112TEST(ConfigFileParserTests, ParseI2CWriteByte)
2113{
2114 // Test where works: Only required properties specified
2115 {
2116 const json element = R"(
2117 {
2118 "register": "0x0A",
2119 "value": "0xCC"
2120 }
2121 )"_json;
2122 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element);
2123 EXPECT_EQ(action->getRegister(), 0x0A);
2124 EXPECT_EQ(action->getValue(), 0xCC);
2125 EXPECT_EQ(action->getMask(), 0xFF);
2126 }
2127
2128 // Test where works: All properties specified
2129 {
2130 const json element = R"(
2131 {
2132 "register": "0x0A",
2133 "value": "0xCC",
2134 "mask": "0xF7"
2135 }
2136 )"_json;
2137 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element);
2138 EXPECT_EQ(action->getRegister(), 0x0A);
2139 EXPECT_EQ(action->getValue(), 0xCC);
2140 EXPECT_EQ(action->getMask(), 0xF7);
2141 }
2142
2143 // Test where fails: Element is not an object
2144 try
2145 {
2146 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2147 parseI2CWriteByte(element);
2148 ADD_FAILURE() << "Should not have reached this line.";
2149 }
2150 catch (const std::invalid_argument& e)
2151 {
2152 EXPECT_STREQ(e.what(), "Element is not an object");
2153 }
2154
2155 // Test where fails: Invalid property specified
2156 try
2157 {
2158 const json element = R"(
2159 {
2160 "register": "0x0A",
2161 "value": "0xCC",
2162 "mask": "0xF7",
2163 "foo": 1
2164 }
2165 )"_json;
2166 parseI2CWriteByte(element);
2167 ADD_FAILURE() << "Should not have reached this line.";
2168 }
2169 catch (const std::invalid_argument& e)
2170 {
2171 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2172 }
2173
2174 // Test where fails: register value is invalid
2175 try
2176 {
2177 const json element = R"(
2178 {
2179 "register": "0x0Z",
2180 "value": "0xCC",
2181 "mask": "0xF7"
2182 }
2183 )"_json;
2184 parseI2CWriteByte(element);
2185 ADD_FAILURE() << "Should not have reached this line.";
2186 }
2187 catch (const std::invalid_argument& e)
2188 {
2189 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2190 }
2191
2192 // Test where fails: value value is invalid
2193 try
2194 {
2195 const json element = R"(
2196 {
2197 "register": "0x0A",
2198 "value": "0xCCC",
2199 "mask": "0xF7"
2200 }
2201 )"_json;
2202 parseI2CWriteByte(element);
2203 ADD_FAILURE() << "Should not have reached this line.";
2204 }
2205 catch (const std::invalid_argument& e)
2206 {
2207 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2208 }
2209
2210 // Test where fails: mask value is invalid
2211 try
2212 {
2213 const json element = R"(
2214 {
2215 "register": "0x0A",
2216 "value": "0xCC",
2217 "mask": "F7"
2218 }
2219 )"_json;
2220 parseI2CWriteByte(element);
2221 ADD_FAILURE() << "Should not have reached this line.";
2222 }
2223 catch (const std::invalid_argument& e)
2224 {
2225 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2226 }
2227
2228 // Test where fails: Required register property not specified
2229 try
2230 {
2231 const json element = R"(
2232 {
2233 "value": "0xCC",
2234 "mask": "0xF7"
2235 }
2236 )"_json;
2237 parseI2CWriteByte(element);
2238 ADD_FAILURE() << "Should not have reached this line.";
2239 }
2240 catch (const std::invalid_argument& e)
2241 {
2242 EXPECT_STREQ(e.what(), "Required property missing: register");
2243 }
2244
2245 // Test where fails: Required value property not specified
2246 try
2247 {
2248 const json element = R"(
2249 {
2250 "register": "0x0A",
2251 "mask": "0xF7"
2252 }
2253 )"_json;
2254 parseI2CWriteByte(element);
2255 ADD_FAILURE() << "Should not have reached this line.";
2256 }
2257 catch (const std::invalid_argument& e)
2258 {
2259 EXPECT_STREQ(e.what(), "Required property missing: value");
2260 }
2261}
2262
Bob Kingbafcb862020-03-31 16:39:00 +08002263TEST(ConfigFileParserTests, ParseI2CWriteBytes)
2264{
2265 // Test where works: Only required properties specified
2266 {
2267 const json element = R"(
2268 {
2269 "register": "0x0A",
2270 "values": [ "0xCC", "0xFF" ]
2271 }
2272 )"_json;
2273 std::unique_ptr<I2CWriteBytesAction> action =
2274 parseI2CWriteBytes(element);
2275 EXPECT_EQ(action->getRegister(), 0x0A);
2276 EXPECT_EQ(action->getValues().size(), 2);
2277 EXPECT_EQ(action->getValues()[0], 0xCC);
2278 EXPECT_EQ(action->getValues()[1], 0xFF);
2279 EXPECT_EQ(action->getMasks().size(), 0);
2280 }
2281
2282 // Test where works: All properties specified
2283 {
2284 const json element = R"(
2285 {
2286 "register": "0x0A",
2287 "values": [ "0xCC", "0xFF" ],
2288 "masks": [ "0x7F", "0x77" ]
2289 }
2290 )"_json;
2291 std::unique_ptr<I2CWriteBytesAction> action =
2292 parseI2CWriteBytes(element);
2293 EXPECT_EQ(action->getRegister(), 0x0A);
2294 EXPECT_EQ(action->getValues().size(), 2);
2295 EXPECT_EQ(action->getValues()[0], 0xCC);
2296 EXPECT_EQ(action->getValues()[1], 0xFF);
2297 EXPECT_EQ(action->getMasks().size(), 2);
2298 EXPECT_EQ(action->getMasks()[0], 0x7F);
2299 EXPECT_EQ(action->getMasks()[1], 0x77);
2300 }
2301
2302 // Test where fails: Element is not an object
2303 try
2304 {
2305 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2306 parseI2CWriteBytes(element);
2307 ADD_FAILURE() << "Should not have reached this line.";
2308 }
2309 catch (const std::invalid_argument& e)
2310 {
2311 EXPECT_STREQ(e.what(), "Element is not an object");
2312 }
2313
2314 // Test where fails: Invalid property specified
2315 try
2316 {
2317 const json element = R"(
2318 {
2319 "register": "0x0A",
2320 "values": [ "0xCC", "0xFF" ],
2321 "masks": [ "0x7F", "0x7F" ],
2322 "foo": 1
2323 }
2324 )"_json;
2325 parseI2CWriteBytes(element);
2326 ADD_FAILURE() << "Should not have reached this line.";
2327 }
2328 catch (const std::invalid_argument& e)
2329 {
2330 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2331 }
2332
2333 // Test where fails: register value is invalid
2334 try
2335 {
2336 const json element = R"(
2337 {
2338 "register": "0x0Z",
2339 "values": [ "0xCC", "0xFF" ],
2340 "masks": [ "0x7F", "0x7F" ]
2341 }
2342 )"_json;
2343 parseI2CWriteBytes(element);
2344 ADD_FAILURE() << "Should not have reached this line.";
2345 }
2346 catch (const std::invalid_argument& e)
2347 {
2348 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2349 }
2350
2351 // Test where fails: values value is invalid
2352 try
2353 {
2354 const json element = R"(
2355 {
2356 "register": "0x0A",
2357 "values": [ "0xCCC", "0xFF" ],
2358 "masks": [ "0x7F", "0x7F" ]
2359 }
2360 )"_json;
2361 parseI2CWriteBytes(element);
2362 ADD_FAILURE() << "Should not have reached this line.";
2363 }
2364 catch (const std::invalid_argument& e)
2365 {
2366 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2367 }
2368
2369 // Test where fails: masks value is invalid
2370 try
2371 {
2372 const json element = R"(
2373 {
2374 "register": "0x0A",
2375 "values": [ "0xCC", "0xFF" ],
2376 "masks": [ "F", "0x7F" ]
2377 }
2378 )"_json;
2379 parseI2CWriteBytes(element);
2380 ADD_FAILURE() << "Should not have reached this line.";
2381 }
2382 catch (const std::invalid_argument& e)
2383 {
2384 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2385 }
2386
2387 // Test where fails: number of elements in masks is invalid
2388 try
2389 {
2390 const json element = R"(
2391 {
2392 "register": "0x0A",
2393 "values": [ "0xCC", "0xFF" ],
2394 "masks": [ "0x7F" ]
2395 }
2396 )"_json;
2397 parseI2CWriteBytes(element);
2398 ADD_FAILURE() << "Should not have reached this line.";
2399 }
2400 catch (const std::invalid_argument& e)
2401 {
2402 EXPECT_STREQ(e.what(), "Invalid number of elements in masks");
2403 }
2404
2405 // Test where fails: Required register property not specified
2406 try
2407 {
2408 const json element = R"(
2409 {
2410 "values": [ "0xCC", "0xFF" ]
2411 }
2412 )"_json;
2413 parseI2CWriteBytes(element);
2414 ADD_FAILURE() << "Should not have reached this line.";
2415 }
2416 catch (const std::invalid_argument& e)
2417 {
2418 EXPECT_STREQ(e.what(), "Required property missing: register");
2419 }
2420
2421 // Test where fails: Required values property not specified
2422 try
2423 {
2424 const json element = R"(
2425 {
2426 "register": "0x0A"
2427 }
2428 )"_json;
2429 parseI2CWriteBytes(element);
2430 ADD_FAILURE() << "Should not have reached this line.";
2431 }
2432 catch (const std::invalid_argument& e)
2433 {
2434 EXPECT_STREQ(e.what(), "Required property missing: values");
2435 }
2436}
2437
Bob King87ff9d72020-03-31 14:02:55 +08002438TEST(ConfigFileParserTests, ParseInt8)
2439{
2440 // Test where works: INT8_MIN
2441 {
2442 const json element = R"( -128 )"_json;
2443 int8_t value = parseInt8(element);
2444 EXPECT_EQ(value, -128);
2445 }
2446
2447 // Test where works: INT8_MAX
2448 {
2449 const json element = R"( 127 )"_json;
2450 int8_t value = parseInt8(element);
2451 EXPECT_EQ(value, 127);
2452 }
2453
2454 // Test where fails: Element is not an integer
2455 try
2456 {
2457 const json element = R"( 1.03 )"_json;
2458 parseInt8(element);
2459 ADD_FAILURE() << "Should not have reached this line.";
2460 }
2461 catch (const std::invalid_argument& e)
2462 {
2463 EXPECT_STREQ(e.what(), "Element is not an integer");
2464 }
2465
2466 // Test where fails: Value < INT8_MIN
2467 try
2468 {
2469 const json element = R"( -129 )"_json;
2470 parseInt8(element);
2471 ADD_FAILURE() << "Should not have reached this line.";
2472 }
2473 catch (const std::invalid_argument& e)
2474 {
2475 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
2476 }
2477
2478 // Test where fails: Value > INT8_MAX
2479 try
2480 {
2481 const json element = R"( 128 )"_json;
2482 parseInt8(element);
2483 ADD_FAILURE() << "Should not have reached this line.";
2484 }
2485 catch (const std::invalid_argument& e)
2486 {
2487 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
2488 }
2489}
2490
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05002491TEST(ConfigFileParserTests, ParsePMBusWriteVoutCommand)
2492{
2493 // Test where works: Only required properties specified
2494 {
2495 const json element = R"(
2496 {
2497 "format": "linear"
2498 }
2499 )"_json;
2500 std::unique_ptr<PMBusWriteVoutCommandAction> action =
2501 parsePMBusWriteVoutCommand(element);
2502 EXPECT_EQ(action->getVolts().has_value(), false);
2503 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear);
2504 EXPECT_EQ(action->getExponent().has_value(), false);
2505 EXPECT_EQ(action->isVerified(), false);
2506 }
2507
2508 // Test where works: All properties specified
2509 {
2510 const json element = R"(
2511 {
2512 "volts": 1.03,
2513 "format": "linear",
2514 "exponent": -8,
2515 "is_verified": true
2516 }
2517 )"_json;
2518 std::unique_ptr<PMBusWriteVoutCommandAction> action =
2519 parsePMBusWriteVoutCommand(element);
2520 EXPECT_EQ(action->getVolts().has_value(), true);
2521 EXPECT_EQ(action->getVolts().value(), 1.03);
2522 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear);
2523 EXPECT_EQ(action->getExponent().has_value(), true);
2524 EXPECT_EQ(action->getExponent().value(), -8);
2525 EXPECT_EQ(action->isVerified(), true);
2526 }
2527
2528 // Test where fails: Element is not an object
2529 try
2530 {
2531 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2532 parsePMBusWriteVoutCommand(element);
2533 ADD_FAILURE() << "Should not have reached this line.";
2534 }
2535 catch (const std::invalid_argument& e)
2536 {
2537 EXPECT_STREQ(e.what(), "Element is not an object");
2538 }
2539
2540 // Test where fails: volts value is invalid
2541 try
2542 {
2543 const json element = R"(
2544 {
2545 "volts": "foo",
2546 "format": "linear"
2547 }
2548 )"_json;
2549 parsePMBusWriteVoutCommand(element);
2550 ADD_FAILURE() << "Should not have reached this line.";
2551 }
2552 catch (const std::invalid_argument& e)
2553 {
2554 EXPECT_STREQ(e.what(), "Element is not a number");
2555 }
2556
2557 // Test where fails: Required format property not specified
2558 try
2559 {
2560 const json element = R"(
2561 {
2562 "volts": 1.03,
2563 "is_verified": true
2564 }
2565 )"_json;
2566 parsePMBusWriteVoutCommand(element);
2567 ADD_FAILURE() << "Should not have reached this line.";
2568 }
2569 catch (const std::invalid_argument& e)
2570 {
2571 EXPECT_STREQ(e.what(), "Required property missing: format");
2572 }
2573
2574 // Test where fails: format value is invalid
2575 try
2576 {
2577 const json element = R"(
2578 {
2579 "format": "linear_11"
2580 }
2581 )"_json;
2582 parsePMBusWriteVoutCommand(element);
2583 ADD_FAILURE() << "Should not have reached this line.";
2584 }
2585 catch (const std::invalid_argument& e)
2586 {
2587 EXPECT_STREQ(e.what(), "Invalid format value: linear_11");
2588 }
2589
2590 // Test where fails: exponent value is invalid
2591 try
2592 {
2593 const json element = R"(
2594 {
2595 "format": "linear",
2596 "exponent": 1.3
2597 }
2598 )"_json;
2599 parsePMBusWriteVoutCommand(element);
2600 ADD_FAILURE() << "Should not have reached this line.";
2601 }
2602 catch (const std::invalid_argument& e)
2603 {
2604 EXPECT_STREQ(e.what(), "Element is not an integer");
2605 }
2606
2607 // Test where fails: is_verified value is invalid
2608 try
2609 {
2610 const json element = R"(
2611 {
2612 "format": "linear",
2613 "is_verified": "true"
2614 }
2615 )"_json;
2616 parsePMBusWriteVoutCommand(element);
2617 ADD_FAILURE() << "Should not have reached this line.";
2618 }
2619 catch (const std::invalid_argument& e)
2620 {
2621 EXPECT_STREQ(e.what(), "Element is not a boolean");
2622 }
2623
2624 // Test where fails: Invalid property specified
2625 try
2626 {
2627 const json element = R"(
2628 {
2629 "format": "linear",
2630 "foo": "bar"
2631 }
2632 )"_json;
2633 parsePMBusWriteVoutCommand(element);
2634 ADD_FAILURE() << "Should not have reached this line.";
2635 }
2636 catch (const std::invalid_argument& e)
2637 {
2638 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2639 }
2640}
2641
Bob Kinga2f2a0d2020-04-09 13:32:14 +08002642TEST(ConfigFileParserTests, ParseRail)
2643{
2644 // Test where works: Only required properties specified
2645 {
2646 const json element = R"(
2647 {
2648 "id": "vdd"
2649 }
2650 )"_json;
2651 std::unique_ptr<Rail> rail = parseRail(element);
2652 EXPECT_EQ(rail->getID(), "vdd");
2653 EXPECT_EQ(rail->getConfiguration(), nullptr);
2654 EXPECT_EQ(rail->getSensorMonitoring(), nullptr);
2655 }
2656
2657 // Test where works: All properties specified
2658 {
2659 const json element = R"(
2660 {
2661 "comments": [ "comments property" ],
2662 "id": "vdd",
2663 "configuration": {
2664 "volts": 1.1,
2665 "actions": [
2666 {
2667 "pmbus_write_vout_command": {
2668 "format": "linear"
2669 }
2670 }
2671 ]
2672 },
2673 "sensor_monitoring": {
2674 "actions": [
2675 { "run_rule": "read_sensors_rule" }
2676 ]
2677 }
2678 }
2679 )"_json;
2680 std::unique_ptr<Rail> rail = parseRail(element);
2681 EXPECT_EQ(rail->getID(), "vdd");
2682 EXPECT_NE(rail->getConfiguration(), nullptr);
2683 EXPECT_NE(rail->getSensorMonitoring(), nullptr);
2684 }
2685
2686 // Test where fails: id property not specified
2687 try
2688 {
2689 const json element = R"(
2690 {
2691 "configuration": {
2692 "volts": 1.1,
2693 "actions": [
2694 {
2695 "pmbus_write_vout_command": {
2696 "format": "linear"
2697 }
2698 }
2699 ]
2700 }
2701 }
2702 )"_json;
2703 parseRail(element);
2704 ADD_FAILURE() << "Should not have reached this line.";
2705 }
2706 catch (const std::invalid_argument& e)
2707 {
2708 EXPECT_STREQ(e.what(), "Required property missing: id");
2709 }
2710
2711 // Test where fails: id property is invalid
2712 try
2713 {
2714 const json element = R"(
2715 {
2716 "id": "",
2717 "configuration": {
2718 "volts": 1.1,
2719 "actions": [
2720 {
2721 "pmbus_write_vout_command": {
2722 "format": "linear"
2723 }
2724 }
2725 ]
2726 }
2727 }
2728 )"_json;
2729 parseRail(element);
2730 ADD_FAILURE() << "Should not have reached this line.";
2731 }
2732 catch (const std::invalid_argument& e)
2733 {
2734 EXPECT_STREQ(e.what(), "Element contains an empty string");
2735 }
2736
2737 // Test where fails: Element is not an object
2738 try
2739 {
2740 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2741 parseRail(element);
2742 ADD_FAILURE() << "Should not have reached this line.";
2743 }
2744 catch (const std::invalid_argument& e)
2745 {
2746 EXPECT_STREQ(e.what(), "Element is not an object");
2747 }
2748
2749 // Test where fails: configuration value is invalid
2750 try
2751 {
2752 const json element = R"(
2753 {
2754 "id": "vdd",
2755 "configuration": "config"
2756 }
2757 )"_json;
2758 parseRail(element);
2759 ADD_FAILURE() << "Should not have reached this line.";
2760 }
2761 catch (const std::invalid_argument& e)
2762 {
2763 EXPECT_STREQ(e.what(), "Element is not an object");
2764 }
2765
2766 // Test where fails: sensor_monitoring value is invalid
2767 try
2768 {
2769 const json element = R"(
2770 {
2771 "comments": [ "comments property" ],
2772 "id": "vdd",
2773 "configuration": {
2774 "volts": 1.1,
2775 "actions": [
2776 {
2777 "pmbus_write_vout_command": {
2778 "format": "linear"
2779 }
2780 }
2781 ]
2782 },
2783 "sensor_monitoring": 1
2784 }
2785 )"_json;
2786 parseRail(element);
2787 ADD_FAILURE() << "Should not have reached this line.";
2788 }
2789 catch (const std::invalid_argument& e)
2790 {
2791 EXPECT_STREQ(e.what(), "Element is not an object");
2792 }
2793
2794 // Test where fails: Invalid property specified
2795 try
2796 {
2797 const json element = R"(
2798 {
2799 "id": "vdd",
2800 "foo" : true
2801 }
2802 )"_json;
2803 parseRail(element);
2804 ADD_FAILURE() << "Should not have reached this line.";
2805 }
2806 catch (const std::invalid_argument& e)
2807 {
2808 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2809 }
2810}
2811
2812TEST(ConfigFileParserTests, ParseRailArray)
2813{
2814 // Test where works
2815 {
2816 const json element = R"(
2817 [
2818 { "id": "vdd" },
2819 { "id": "vio" }
2820 ]
2821 )"_json;
2822 std::vector<std::unique_ptr<Rail>> rails = parseRailArray(element);
2823 EXPECT_EQ(rails.size(), 2);
2824 EXPECT_EQ(rails[0]->getID(), "vdd");
2825 EXPECT_EQ(rails[1]->getID(), "vio");
2826 }
2827
2828 // Test where fails: Element is not an array
2829 try
2830 {
2831 const json element = R"(
2832 {
2833 "foo": "bar"
2834 }
2835 )"_json;
2836 parseRailArray(element);
2837 ADD_FAILURE() << "Should not have reached this line.";
2838 }
2839 catch (const std::invalid_argument& e)
2840 {
2841 EXPECT_STREQ(e.what(), "Element is not an array");
2842 }
2843}
2844
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05002845TEST(ConfigFileParserTests, ParseRoot)
2846{
2847 // Test where works: Only required properties specified
2848 {
2849 const json element = R"(
2850 {
2851 "chassis": [
2852 { "number": 1 }
2853 ]
2854 }
2855 )"_json;
2856 std::vector<std::unique_ptr<Rule>> rules{};
2857 std::vector<std::unique_ptr<Chassis>> chassis{};
2858 std::tie(rules, chassis) = parseRoot(element);
2859 EXPECT_EQ(rules.size(), 0);
Bob King0e701132020-04-03 21:50:31 +08002860 EXPECT_EQ(chassis.size(), 1);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05002861 }
2862
2863 // Test where works: All properties specified
2864 {
2865 const json element = R"(
2866 {
2867 "comments": [ "Config file for a FooBar one-chassis system" ],
2868 "rules": [
2869 {
2870 "id": "set_voltage_rule",
2871 "actions": [
2872 { "pmbus_write_vout_command": { "format": "linear" } }
2873 ]
2874 }
2875 ],
2876 "chassis": [
2877 { "number": 1 },
2878 { "number": 3 }
2879 ]
2880 }
2881 )"_json;
2882 std::vector<std::unique_ptr<Rule>> rules{};
2883 std::vector<std::unique_ptr<Chassis>> chassis{};
2884 std::tie(rules, chassis) = parseRoot(element);
2885 EXPECT_EQ(rules.size(), 1);
Bob King0e701132020-04-03 21:50:31 +08002886 EXPECT_EQ(chassis.size(), 2);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05002887 }
2888
2889 // Test where fails: Element is not an object
2890 try
2891 {
2892 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2893 parseRoot(element);
2894 ADD_FAILURE() << "Should not have reached this line.";
2895 }
2896 catch (const std::invalid_argument& e)
2897 {
2898 EXPECT_STREQ(e.what(), "Element is not an object");
2899 }
2900
2901 // Test where fails: chassis property not specified
2902 try
2903 {
2904 const json element = R"(
2905 {
2906 "rules": [
2907 {
2908 "id": "set_voltage_rule",
2909 "actions": [
2910 { "pmbus_write_vout_command": { "format": "linear" } }
2911 ]
2912 }
2913 ]
2914 }
2915 )"_json;
2916 parseRoot(element);
2917 ADD_FAILURE() << "Should not have reached this line.";
2918 }
2919 catch (const std::invalid_argument& e)
2920 {
2921 EXPECT_STREQ(e.what(), "Required property missing: chassis");
2922 }
2923
2924 // Test where fails: Invalid property specified
2925 try
2926 {
2927 const json element = R"(
2928 {
2929 "remarks": [ "Config file for a FooBar one-chassis system" ],
2930 "chassis": [
2931 { "number": 1 }
2932 ]
2933 }
2934 )"_json;
2935 parseRoot(element);
2936 ADD_FAILURE() << "Should not have reached this line.";
2937 }
2938 catch (const std::invalid_argument& e)
2939 {
2940 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2941 }
2942}
2943
2944TEST(ConfigFileParserTests, ParseRule)
2945{
2946 // Test where works: comments property specified
2947 {
2948 const json element = R"(
2949 {
2950 "comments": [ "Set voltage rule" ],
2951 "id": "set_voltage_rule",
2952 "actions": [
2953 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
2954 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
2955 ]
2956 }
2957 )"_json;
2958 std::unique_ptr<Rule> rule = parseRule(element);
2959 EXPECT_EQ(rule->getID(), "set_voltage_rule");
2960 EXPECT_EQ(rule->getActions().size(), 2);
2961 }
2962
2963 // Test where works: comments property not specified
2964 {
2965 const json element = R"(
2966 {
2967 "id": "set_voltage_rule",
2968 "actions": [
2969 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
2970 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } },
2971 { "pmbus_write_vout_command": { "volts": 1.05, "format": "linear" } }
2972 ]
2973 }
2974 )"_json;
2975 std::unique_ptr<Rule> rule = parseRule(element);
2976 EXPECT_EQ(rule->getID(), "set_voltage_rule");
2977 EXPECT_EQ(rule->getActions().size(), 3);
2978 }
2979
2980 // Test where fails: Element is not an object
2981 try
2982 {
2983 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2984 parseRule(element);
2985 ADD_FAILURE() << "Should not have reached this line.";
2986 }
2987 catch (const std::invalid_argument& e)
2988 {
2989 EXPECT_STREQ(e.what(), "Element is not an object");
2990 }
2991
2992 // Test where fails: id property not specified
2993 try
2994 {
2995 const json element = R"(
2996 {
2997 "actions": [
2998 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
2999 ]
3000 }
3001 )"_json;
3002 parseRule(element);
3003 ADD_FAILURE() << "Should not have reached this line.";
3004 }
3005 catch (const std::invalid_argument& e)
3006 {
3007 EXPECT_STREQ(e.what(), "Required property missing: id");
3008 }
3009
3010 // Test where fails: id property is invalid
3011 try
3012 {
3013 const json element = R"(
3014 {
3015 "id": "",
3016 "actions": [
3017 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
3018 ]
3019 }
3020 )"_json;
3021 parseRule(element);
3022 ADD_FAILURE() << "Should not have reached this line.";
3023 }
3024 catch (const std::invalid_argument& e)
3025 {
3026 EXPECT_STREQ(e.what(), "Element contains an empty string");
3027 }
3028
3029 // Test where fails: actions property not specified
3030 try
3031 {
3032 const json element = R"(
3033 {
3034 "comments": [ "Set voltage rule" ],
3035 "id": "set_voltage_rule"
3036 }
3037 )"_json;
3038 parseRule(element);
3039 ADD_FAILURE() << "Should not have reached this line.";
3040 }
3041 catch (const std::invalid_argument& e)
3042 {
3043 EXPECT_STREQ(e.what(), "Required property missing: actions");
3044 }
3045
3046 // Test where fails: actions property is invalid
3047 try
3048 {
3049 const json element = R"(
3050 {
3051 "id": "set_voltage_rule",
3052 "actions": true
3053 }
3054 )"_json;
3055 parseRule(element);
3056 ADD_FAILURE() << "Should not have reached this line.";
3057 }
3058 catch (const std::invalid_argument& e)
3059 {
3060 EXPECT_STREQ(e.what(), "Element is not an array");
3061 }
3062
3063 // Test where fails: Invalid property specified
3064 try
3065 {
3066 const json element = R"(
3067 {
3068 "remarks": [ "Set voltage rule" ],
3069 "id": "set_voltage_rule",
3070 "actions": [
3071 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
3072 ]
3073 }
3074 )"_json;
3075 parseRule(element);
3076 ADD_FAILURE() << "Should not have reached this line.";
3077 }
3078 catch (const std::invalid_argument& e)
3079 {
3080 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3081 }
3082}
3083
3084TEST(ConfigFileParserTests, ParseRuleArray)
3085{
3086 // Test where works
3087 {
3088 const json element = R"(
3089 [
3090 {
3091 "id": "set_voltage_rule1",
3092 "actions": [
3093 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
3094 ]
3095 },
3096 {
3097 "id": "set_voltage_rule2",
3098 "actions": [
3099 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
3100 { "pmbus_write_vout_command": { "volts": 1.11, "format": "linear" } }
3101 ]
3102 }
3103 ]
3104 )"_json;
3105 std::vector<std::unique_ptr<Rule>> rules = parseRuleArray(element);
3106 EXPECT_EQ(rules.size(), 2);
3107 EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1");
3108 EXPECT_EQ(rules[0]->getActions().size(), 1);
3109 EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2");
3110 EXPECT_EQ(rules[1]->getActions().size(), 2);
3111 }
3112
3113 // Test where fails: Element is not an array
3114 try
3115 {
3116 const json element = R"( { "id": "set_voltage_rule" } )"_json;
3117 parseRuleArray(element);
3118 ADD_FAILURE() << "Should not have reached this line.";
3119 }
3120 catch (const std::invalid_argument& e)
3121 {
3122 EXPECT_STREQ(e.what(), "Element is not an array");
3123 }
3124}
3125
Bob King33e7eaa2020-04-01 18:09:34 +08003126TEST(ConfigFileParserTests, ParseRuleIDOrActionsProperty)
3127{
3128 // Test where works: actions specified
3129 {
3130 const json element = R"(
3131 {
3132 "actions": [
3133 { "pmbus_write_vout_command": { "format": "linear" } },
3134 { "run_rule": "set_voltage_rule" }
3135 ]
3136 }
3137 )"_json;
3138 std::vector<std::unique_ptr<Action>> actions =
3139 parseRuleIDOrActionsProperty(element);
3140 EXPECT_EQ(actions.size(), 2);
3141 }
3142
3143 // Test where works: rule_id specified
3144 {
3145 const json element = R"(
3146 {
3147 "rule_id": "set_voltage_rule"
3148 }
3149 )"_json;
3150 std::vector<std::unique_ptr<Action>> actions =
3151 parseRuleIDOrActionsProperty(element);
3152 EXPECT_EQ(actions.size(), 1);
3153 }
3154
3155 // Test where fails: Element is not an object
3156 try
3157 {
3158 const json element = R"( [ "foo", "bar" ] )"_json;
3159 parseRuleIDOrActionsProperty(element);
3160 ADD_FAILURE() << "Should not have reached this line.";
3161 }
3162 catch (const std::invalid_argument& e)
3163 {
3164 EXPECT_STREQ(e.what(), "Element is not an object");
3165 }
3166
3167 // Test where fails: rule_id is invalid
3168 try
3169 {
3170 const json element = R"(
3171 { "rule_id": 1 }
3172 )"_json;
3173 parseRuleIDOrActionsProperty(element);
3174 ADD_FAILURE() << "Should not have reached this line.";
3175 }
3176 catch (const std::invalid_argument& e)
3177 {
3178 EXPECT_STREQ(e.what(), "Element is not a string");
3179 }
3180
3181 // Test where fails: actions is invalid
3182 try
3183 {
3184 const json element = R"(
3185 { "actions": 1 }
3186 )"_json;
3187 parseRuleIDOrActionsProperty(element);
3188 ADD_FAILURE() << "Should not have reached this line.";
3189 }
3190 catch (const std::invalid_argument& e)
3191 {
3192 EXPECT_STREQ(e.what(), "Element is not an array");
3193 }
3194
3195 // Test where fails: Neither rule_id nor actions specified
3196 try
3197 {
3198 const json element = R"(
3199 {
3200 "volts": 1.03
3201 }
3202 )"_json;
3203 parseRuleIDOrActionsProperty(element);
3204 ADD_FAILURE() << "Should not have reached this line.";
3205 }
3206 catch (const std::invalid_argument& e)
3207 {
3208 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3209 "either rule_id or actions");
3210 }
3211
3212 // Test where fails: Both rule_id and actions specified
3213 try
3214 {
3215 const json element = R"(
3216 {
3217 "volts": 1.03,
3218 "rule_id": "set_voltage_rule",
3219 "actions": [
3220 {
3221 "pmbus_write_vout_command": {
3222 "format": "linear"
3223 }
3224 }
3225 ]
3226 }
3227 )"_json;
3228 parseRuleIDOrActionsProperty(element);
3229 ADD_FAILURE() << "Should not have reached this line.";
3230 }
3231 catch (const std::invalid_argument& e)
3232 {
3233 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3234 "either rule_id or actions");
3235 }
3236}
3237
Bob King315b0b62020-04-03 21:47:58 +08003238TEST(ConfigFileParserTests, ParseRunRule)
3239{
3240 // Test where works
3241 {
3242 const json element = "vdd_regulator";
3243 std::unique_ptr<RunRuleAction> action = parseRunRule(element);
3244 EXPECT_EQ(action->getRuleID(), "vdd_regulator");
3245 }
3246
3247 // Test where fails: Element is not a string
3248 try
3249 {
3250 const json element = 1;
3251 parseRunRule(element);
3252 ADD_FAILURE() << "Should not have reached this line.";
3253 }
3254 catch (const std::invalid_argument& e)
3255 {
3256 EXPECT_STREQ(e.what(), "Element is not a string");
3257 }
3258
3259 // Test where fails: Empty string
3260 try
3261 {
3262 const json element = "";
3263 parseRunRule(element);
3264 ADD_FAILURE() << "Should not have reached this line.";
3265 }
3266 catch (const std::invalid_argument& e)
3267 {
3268 EXPECT_STREQ(e.what(), "Element contains an empty string");
3269 }
3270}
3271
Bob Kinga2f2a0d2020-04-09 13:32:14 +08003272TEST(ConfigFileParserTests, ParseSensorMonitoring)
3273{
3274 // Test where works: actions property specified
3275 {
3276 const json element = R"(
3277 {
3278 "actions": [
3279 { "run_rule": "read_sensors_rule" }
3280 ]
3281 }
3282 )"_json;
3283 std::unique_ptr<SensorMonitoring> sensorMonitoring =
3284 parseSensorMonitoring(element);
3285 EXPECT_EQ(sensorMonitoring->getActions().size(), 1);
3286 }
3287
3288 // Test where works: rule_id property specified
3289 {
3290 const json element = R"(
3291 {
3292 "comments": [ "comments property" ],
3293 "rule_id": "set_voltage_rule"
3294 }
3295 )"_json;
3296 std::unique_ptr<SensorMonitoring> sensorMonitoring =
3297 parseSensorMonitoring(element);
3298 EXPECT_EQ(sensorMonitoring->getActions().size(), 1);
3299 }
3300
3301 // Test where fails: actions object is invalid
3302 try
3303 {
3304 const json element = R"(
3305 {
3306 "actions": 1
3307 }
3308 )"_json;
3309 parseSensorMonitoring(element);
3310 ADD_FAILURE() << "Should not have reached this line.";
3311 }
3312 catch (const std::invalid_argument& e)
3313 {
3314 EXPECT_STREQ(e.what(), "Element is not an array");
3315 }
3316
3317 // Test where fails: rule_id value is invalid
3318 try
3319 {
3320 const json element = R"(
3321 {
3322 "rule_id": 1
3323 }
3324 )"_json;
3325 parseSensorMonitoring(element);
3326 ADD_FAILURE() << "Should not have reached this line.";
3327 }
3328 catch (const std::invalid_argument& e)
3329 {
3330 EXPECT_STREQ(e.what(), "Element is not a string");
3331 }
3332
3333 // Test where fails: Required actions or rule_id property not specified
3334 try
3335 {
3336 const json element = R"(
3337 {
3338 "comments": [ "comments property" ]
3339 }
3340 )"_json;
3341 parseSensorMonitoring(element);
3342 ADD_FAILURE() << "Should not have reached this line.";
3343 }
3344 catch (const std::invalid_argument& e)
3345 {
3346 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3347 "either rule_id or actions");
3348 }
3349
3350 // Test where fails: Required actions or rule_id property both specified
3351 try
3352 {
3353 const json element = R"(
3354 {
3355 "rule_id": "set_voltage_rule",
3356 "actions": [
3357 { "run_rule": "read_sensors_rule" }
3358 ]
3359 }
3360 )"_json;
3361 parseSensorMonitoring(element);
3362 ADD_FAILURE() << "Should not have reached this line.";
3363 }
3364 catch (const std::invalid_argument& e)
3365 {
3366 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3367 "either rule_id or actions");
3368 }
3369
3370 // Test where fails: Element is not an object
3371 try
3372 {
3373 const json element = R"( [ "foo", "bar" ] )"_json;
3374 parseSensorMonitoring(element);
3375 ADD_FAILURE() << "Should not have reached this line.";
3376 }
3377 catch (const std::invalid_argument& e)
3378 {
3379 EXPECT_STREQ(e.what(), "Element is not an object");
3380 }
3381
3382 // Test where fails: Invalid property specified
3383 try
3384 {
3385 const json element = R"(
3386 {
3387 "foo": "bar",
3388 "actions": [
3389 { "run_rule": "read_sensors_rule" }
3390 ]
3391 }
3392 )"_json;
3393 parseSensorMonitoring(element);
3394 ADD_FAILURE() << "Should not have reached this line.";
3395 }
3396 catch (const std::invalid_argument& e)
3397 {
3398 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3399 }
3400}
3401
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003402TEST(ConfigFileParserTests, ParseString)
3403{
3404 // Test where works: Empty string
3405 {
3406 const json element = "";
3407 std::string value = parseString(element, true);
3408 EXPECT_EQ(value, "");
3409 }
3410
3411 // Test where works: Non-empty string
3412 {
3413 const json element = "vdd_regulator";
3414 std::string value = parseString(element, false);
3415 EXPECT_EQ(value, "vdd_regulator");
3416 }
3417
3418 // Test where fails: Element is not a string
3419 try
3420 {
3421 const json element = R"( { "foo": "bar" } )"_json;
3422 parseString(element);
3423 ADD_FAILURE() << "Should not have reached this line.";
3424 }
3425 catch (const std::invalid_argument& e)
3426 {
3427 EXPECT_STREQ(e.what(), "Element is not a string");
3428 }
3429
3430 // Test where fails: Empty string
3431 try
3432 {
3433 const json element = "";
3434 parseString(element);
3435 ADD_FAILURE() << "Should not have reached this line.";
3436 }
3437 catch (const std::invalid_argument& e)
3438 {
3439 EXPECT_STREQ(e.what(), "Element contains an empty string");
3440 }
3441}
3442
Bob Kingf617f892020-03-30 19:03:35 +08003443TEST(ConfigFileParserTests, ParseUint8)
3444{
3445 // Test where works: 0
3446 {
3447 const json element = R"( 0 )"_json;
3448 uint8_t value = parseUint8(element);
3449 EXPECT_EQ(value, 0);
3450 }
3451
3452 // Test where works: UINT8_MAX
3453 {
3454 const json element = R"( 255 )"_json;
3455 uint8_t value = parseUint8(element);
3456 EXPECT_EQ(value, 255);
3457 }
3458
3459 // Test where fails: Element is not an integer
3460 try
3461 {
3462 const json element = R"( 1.03 )"_json;
3463 parseUint8(element);
3464 ADD_FAILURE() << "Should not have reached this line.";
3465 }
3466 catch (const std::invalid_argument& e)
3467 {
3468 EXPECT_STREQ(e.what(), "Element is not an integer");
3469 }
3470
3471 // Test where fails: Value < 0
3472 try
3473 {
3474 const json element = R"( -1 )"_json;
3475 parseUint8(element);
3476 ADD_FAILURE() << "Should not have reached this line.";
3477 }
3478 catch (const std::invalid_argument& e)
3479 {
3480 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
3481 }
3482
3483 // Test where fails: Value > UINT8_MAX
3484 try
3485 {
3486 const json element = R"( 256 )"_json;
3487 parseUint8(element);
3488 ADD_FAILURE() << "Should not have reached this line.";
3489 }
3490 catch (const std::invalid_argument& e)
3491 {
3492 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
3493 }
3494}
3495
Bob King0e701132020-04-03 21:50:31 +08003496TEST(ConfigFileParserTests, ParseUnsignedInteger)
3497{
3498 // Test where works: 1
3499 {
3500 const json element = R"( 1 )"_json;
3501 unsigned int value = parseUnsignedInteger(element);
3502 EXPECT_EQ(value, 1);
3503 }
3504
3505 // Test where fails: Element is not an integer
3506 try
3507 {
3508 const json element = R"( 1.5 )"_json;
3509 parseUnsignedInteger(element);
3510 ADD_FAILURE() << "Should not have reached this line.";
3511 }
3512 catch (const std::invalid_argument& e)
3513 {
3514 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
3515 }
3516
3517 // Test where fails: Value < 0
3518 try
3519 {
3520 const json element = R"( -1 )"_json;
3521 parseUnsignedInteger(element);
3522 ADD_FAILURE() << "Should not have reached this line.";
3523 }
3524 catch (const std::invalid_argument& e)
3525 {
3526 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
3527 }
3528}
3529
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003530TEST(ConfigFileParserTests, VerifyIsArray)
3531{
3532 // Test where element is an array
3533 try
3534 {
3535 const json element = R"( [ "foo", "bar" ] )"_json;
3536 verifyIsArray(element);
3537 }
3538 catch (const std::exception& e)
3539 {
3540 ADD_FAILURE() << "Should not have caught exception.";
3541 }
3542
3543 // Test where element is not an array
3544 try
3545 {
3546 const json element = R"( { "foo": "bar" } )"_json;
3547 verifyIsArray(element);
3548 ADD_FAILURE() << "Should not have reached this line.";
3549 }
3550 catch (const std::invalid_argument& e)
3551 {
3552 EXPECT_STREQ(e.what(), "Element is not an array");
3553 }
3554}
3555
3556TEST(ConfigFileParserTests, VerifyIsObject)
3557{
3558 // Test where element is an object
3559 try
3560 {
3561 const json element = R"( { "foo": "bar" } )"_json;
3562 verifyIsObject(element);
3563 }
3564 catch (const std::exception& e)
3565 {
3566 ADD_FAILURE() << "Should not have caught exception.";
3567 }
3568
3569 // Test where element is not an object
3570 try
3571 {
3572 const json element = R"( [ "foo", "bar" ] )"_json;
3573 verifyIsObject(element);
3574 ADD_FAILURE() << "Should not have reached this line.";
3575 }
3576 catch (const std::invalid_argument& e)
3577 {
3578 EXPECT_STREQ(e.what(), "Element is not an object");
3579 }
3580}
3581
3582TEST(ConfigFileParserTests, VerifyPropertyCount)
3583{
3584 // Test where element has expected number of properties
3585 try
3586 {
3587 const json element = R"(
3588 {
3589 "comments": [ "Set voltage rule" ],
3590 "id": "set_voltage_rule"
3591 }
3592 )"_json;
3593 verifyPropertyCount(element, 2);
3594 }
3595 catch (const std::exception& e)
3596 {
3597 ADD_FAILURE() << "Should not have caught exception.";
3598 }
3599
3600 // Test where element has unexpected number of properties
3601 try
3602 {
3603 const json element = R"(
3604 {
3605 "comments": [ "Set voltage rule" ],
3606 "id": "set_voltage_rule",
3607 "foo": 1.3
3608 }
3609 )"_json;
3610 verifyPropertyCount(element, 2);
3611 ADD_FAILURE() << "Should not have reached this line.";
3612 }
3613 catch (const std::invalid_argument& e)
3614 {
3615 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3616 }
3617}