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