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