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