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