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