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