blob: d14787e4ebedfb2b6f808158fab686277295ed56 [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 {
Bob Kinga76898f2020-10-13 15:08:33 +0800269 "fru": "system/chassis/motherboard/cpu3",
Bob Kingb267b7e2020-04-22 14:42:39 +0800270 "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 {
Bob Kinga76898f2020-10-13 15:08:33 +0800284 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +0800285 "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,
Bob Kinga76898f2020-10-13 15:08:33 +0800775 "fru": "system/chassis/motherboard/regulator2",
Bob King0e701132020-04-03 21:50:31 +0800776 "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,
Bob Kinga76898f2020-10-13 15:08:33 +0800833 "fru": "system/chassis/motherboard/regulator2",
Bob King0e701132020-04-03 21:50:31 +0800834 "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 {
Bob Kinga76898f2020-10-13 15:08:33 +0800937 "fru": "system/chassis/motherboard/cpu3",
Bob Kingb267b7e2020-04-22 14:42:39 +0800938 "value": true
939 }
940 )"_json;
941 std::unique_ptr<ComparePresenceAction> action =
942 parseComparePresence(element);
Bob Kinga76898f2020-10-13 15:08:33 +0800943 EXPECT_EQ(
944 action->getFRU(),
945 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3");
Bob Kingb267b7e2020-04-22 14:42:39 +0800946 EXPECT_EQ(action->getValue(), true);
947 }
948
949 // Test where fails: Element is not an object
950 try
951 {
952 const json element = R"( [ "0xFF", "0x01" ] )"_json;
953 parseComparePresence(element);
954 ADD_FAILURE() << "Should not have reached this line.";
955 }
956 catch (const std::invalid_argument& e)
957 {
958 EXPECT_STREQ(e.what(), "Element is not an object");
959 }
960
961 // Test where fails: Invalid property specified
962 try
963 {
964 const json element = R"(
965 {
Bob Kinga76898f2020-10-13 15:08:33 +0800966 "fru": "system/chassis/motherboard/cpu3",
Bob Kingb267b7e2020-04-22 14:42:39 +0800967 "value": true,
968 "foo" : true
969 }
970 )"_json;
971 parseComparePresence(element);
972 ADD_FAILURE() << "Should not have reached this line.";
973 }
974 catch (const std::invalid_argument& e)
975 {
976 EXPECT_STREQ(e.what(), "Element contains an invalid property");
977 }
978
979 // Test where fails: Required fru property not specified
980 try
981 {
982 const json element = R"(
983 {
984 "value": true
985 }
986 )"_json;
987 parseComparePresence(element);
988 ADD_FAILURE() << "Should not have reached this line.";
989 }
990 catch (const std::invalid_argument& e)
991 {
992 EXPECT_STREQ(e.what(), "Required property missing: fru");
993 }
994
995 // Test where fails: Required value property not specified
996 try
997 {
998 const json element = R"(
999 {
Bob Kinga76898f2020-10-13 15:08:33 +08001000 "fru": "system/chassis/motherboard/cpu3"
Bob Kingb267b7e2020-04-22 14:42:39 +08001001 }
1002 )"_json;
1003 parseComparePresence(element);
1004 ADD_FAILURE() << "Should not have reached this line.";
1005 }
1006 catch (const std::invalid_argument& e)
1007 {
1008 EXPECT_STREQ(e.what(), "Required property missing: value");
1009 }
1010
1011 // Test where fails: fru value is invalid
1012 try
1013 {
1014 const json element = R"(
1015 {
1016 "fru": 1,
1017 "value": true
1018 }
1019 )"_json;
1020 parseComparePresence(element);
1021 ADD_FAILURE() << "Should not have reached this line.";
1022 }
1023 catch (const std::invalid_argument& e)
1024 {
1025 EXPECT_STREQ(e.what(), "Element is not a string");
1026 }
1027
1028 // Test where fails: value value is invalid
1029 try
1030 {
1031 const json element = R"(
1032 {
Bob Kinga76898f2020-10-13 15:08:33 +08001033 "fru": "system/chassis/motherboard/cpu3",
Bob Kingb267b7e2020-04-22 14:42:39 +08001034 "value": 1
1035 }
1036 )"_json;
1037 parseComparePresence(element);
1038 ADD_FAILURE() << "Should not have reached this line.";
1039 }
1040 catch (const std::invalid_argument& e)
1041 {
1042 EXPECT_STREQ(e.what(), "Element is not a boolean");
1043 }
1044}
1045
Bob Kingf2134322020-04-27 14:14:56 +08001046TEST(ConfigFileParserTests, ParseCompareVPD)
1047{
1048 // Test where works
1049 {
1050 const json element = R"(
1051 {
Bob Kinga76898f2020-10-13 15:08:33 +08001052 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001053 "keyword": "CCIN",
1054 "value": "2D35"
1055 }
1056 )"_json;
1057 std::unique_ptr<CompareVPDAction> action = parseCompareVPD(element);
Bob Kinga76898f2020-10-13 15:08:33 +08001058 EXPECT_EQ(
1059 action->getFRU(),
1060 "/xyz/openbmc_project/inventory/system/chassis/disk_backplane");
Bob Kingf2134322020-04-27 14:14:56 +08001061 EXPECT_EQ(action->getKeyword(), "CCIN");
1062 EXPECT_EQ(action->getValue(), "2D35");
1063 }
1064
1065 // Test where fails: Element is not an object
1066 try
1067 {
1068 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1069 parseCompareVPD(element);
1070 ADD_FAILURE() << "Should not have reached this line.";
1071 }
1072 catch (const std::invalid_argument& e)
1073 {
1074 EXPECT_STREQ(e.what(), "Element is not an object");
1075 }
1076
1077 // Test where fails: Invalid property specified
1078 try
1079 {
1080 const json element = R"(
1081 {
Bob Kinga76898f2020-10-13 15:08:33 +08001082 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001083 "keyword": "CCIN",
1084 "value": "2D35",
1085 "foo" : true
1086 }
1087 )"_json;
1088 parseCompareVPD(element);
1089 ADD_FAILURE() << "Should not have reached this line.";
1090 }
1091 catch (const std::invalid_argument& e)
1092 {
1093 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1094 }
1095
1096 // Test where fails: Required fru property not specified
1097 try
1098 {
1099 const json element = R"(
1100 {
1101 "keyword": "CCIN",
1102 "value": "2D35"
1103 }
1104 )"_json;
1105 parseCompareVPD(element);
1106 ADD_FAILURE() << "Should not have reached this line.";
1107 }
1108 catch (const std::invalid_argument& e)
1109 {
1110 EXPECT_STREQ(e.what(), "Required property missing: fru");
1111 }
1112
1113 // Test where fails: Required keyword property not specified
1114 try
1115 {
1116 const json element = R"(
1117 {
Bob Kinga76898f2020-10-13 15:08:33 +08001118 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001119 "value": "2D35"
1120 }
1121 )"_json;
1122 parseCompareVPD(element);
1123 ADD_FAILURE() << "Should not have reached this line.";
1124 }
1125 catch (const std::invalid_argument& e)
1126 {
1127 EXPECT_STREQ(e.what(), "Required property missing: keyword");
1128 }
1129
1130 // Test where fails: Required value property not specified
1131 try
1132 {
1133 const json element = R"(
1134 {
Bob Kinga76898f2020-10-13 15:08:33 +08001135 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001136 "keyword": "CCIN"
1137 }
1138 )"_json;
1139 parseCompareVPD(element);
1140 ADD_FAILURE() << "Should not have reached this line.";
1141 }
1142 catch (const std::invalid_argument& e)
1143 {
1144 EXPECT_STREQ(e.what(), "Required property missing: value");
1145 }
1146
1147 // Test where fails: fru value is invalid
1148 try
1149 {
1150 const json element = R"(
1151 {
1152 "fru": 1,
1153 "keyword": "CCIN",
1154 "value": "2D35"
1155 }
1156 )"_json;
1157 parseCompareVPD(element);
1158 ADD_FAILURE() << "Should not have reached this line.";
1159 }
1160 catch (const std::invalid_argument& e)
1161 {
1162 EXPECT_STREQ(e.what(), "Element is not a string");
1163 }
1164
1165 // Test where fails: keyword value is invalid
1166 try
1167 {
1168 const json element = R"(
1169 {
Bob Kinga76898f2020-10-13 15:08:33 +08001170 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001171 "keyword": 1,
1172 "value": "2D35"
1173 }
1174 )"_json;
1175 parseCompareVPD(element);
1176 ADD_FAILURE() << "Should not have reached this line.";
1177 }
1178 catch (const std::invalid_argument& e)
1179 {
1180 EXPECT_STREQ(e.what(), "Element is not a string");
1181 }
1182
1183 // Test where fails: value value is invalid
1184 try
1185 {
1186 const json element = R"(
1187 {
Bob Kinga76898f2020-10-13 15:08:33 +08001188 "fru": "system/chassis/disk_backplane",
Bob Kingf2134322020-04-27 14:14:56 +08001189 "keyword": "CCIN",
1190 "value": 1
1191 }
1192 )"_json;
1193 parseCompareVPD(element);
1194 ADD_FAILURE() << "Should not have reached this line.";
1195 }
1196 catch (const std::invalid_argument& e)
1197 {
1198 EXPECT_STREQ(e.what(), "Element is not a string");
1199 }
1200}
1201
Bob King33e7eaa2020-04-01 18:09:34 +08001202TEST(ConfigFileParserTests, ParseConfiguration)
1203{
1204 // Test where works: actions required property specified
1205 {
1206 const json element = R"(
1207 {
1208 "actions": [
1209 {
1210 "pmbus_write_vout_command": {
1211 "format": "linear"
1212 }
1213 }
1214 ]
1215 }
1216 )"_json;
1217 std::unique_ptr<Configuration> configuration =
1218 parseConfiguration(element);
1219 EXPECT_EQ(configuration->getActions().size(), 1);
1220 EXPECT_EQ(configuration->getVolts().has_value(), false);
1221 }
1222
1223 // Test where works: volts and actions properties specified
1224 {
1225 const json element = R"(
1226 {
1227 "comments": [ "comments property" ],
1228 "volts": 1.03,
1229 "actions": [
1230 { "pmbus_write_vout_command": { "format": "linear" } },
1231 { "run_rule": "set_voltage_rule" }
1232 ]
1233 }
1234 )"_json;
1235 std::unique_ptr<Configuration> configuration =
1236 parseConfiguration(element);
1237 EXPECT_EQ(configuration->getVolts().has_value(), true);
1238 EXPECT_EQ(configuration->getVolts().value(), 1.03);
1239 EXPECT_EQ(configuration->getActions().size(), 2);
1240 }
1241
1242 // Test where works: volts and rule_id properties specified
1243 {
1244 const json element = R"(
1245 {
1246 "volts": 1.05,
1247 "rule_id": "set_voltage_rule"
1248 }
1249 )"_json;
1250 std::unique_ptr<Configuration> configuration =
1251 parseConfiguration(element);
1252 EXPECT_EQ(configuration->getVolts().has_value(), true);
1253 EXPECT_EQ(configuration->getVolts().value(), 1.05);
1254 EXPECT_EQ(configuration->getActions().size(), 1);
1255 }
1256
1257 // Test where fails: volts value is invalid
1258 try
1259 {
1260 const json element = R"(
1261 {
1262 "volts": "foo",
1263 "actions": [
1264 {
1265 "pmbus_write_vout_command": {
1266 "format": "linear"
1267 }
1268 }
1269 ]
1270 }
1271 )"_json;
1272 parseConfiguration(element);
1273 ADD_FAILURE() << "Should not have reached this line.";
1274 }
1275 catch (const std::invalid_argument& e)
1276 {
1277 EXPECT_STREQ(e.what(), "Element is not a number");
1278 }
1279
1280 // Test where fails: actions object is invalid
1281 try
1282 {
1283 const json element = R"(
1284 {
1285 "volts": 1.03,
1286 "actions": 1
1287 }
1288 )"_json;
1289 parseConfiguration(element);
1290 ADD_FAILURE() << "Should not have reached this line.";
1291 }
1292 catch (const std::invalid_argument& e)
1293 {
1294 EXPECT_STREQ(e.what(), "Element is not an array");
1295 }
1296
1297 // Test where fails: rule_id value is invalid
1298 try
1299 {
1300 const json element = R"(
1301 {
1302 "volts": 1.05,
1303 "rule_id": 1
1304 }
1305 )"_json;
1306 parseConfiguration(element);
1307 ADD_FAILURE() << "Should not have reached this line.";
1308 }
1309 catch (const std::invalid_argument& e)
1310 {
1311 EXPECT_STREQ(e.what(), "Element is not a string");
1312 }
1313
1314 // Test where fails: Required actions or rule_id property not specified
1315 try
1316 {
1317 const json element = R"(
1318 {
1319 "volts": 1.03
1320 }
1321 )"_json;
1322 parseConfiguration(element);
1323 ADD_FAILURE() << "Should not have reached this line.";
1324 }
1325 catch (const std::invalid_argument& e)
1326 {
1327 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
1328 "either rule_id or actions");
1329 }
1330
1331 // Test where fails: Required actions or rule_id property both specified
1332 try
1333 {
1334 const json element = R"(
1335 {
1336 "volts": 1.03,
1337 "rule_id": "set_voltage_rule",
1338 "actions": [
1339 {
1340 "pmbus_write_vout_command": {
1341 "format": "linear"
1342 }
1343 }
1344 ]
1345 }
1346 )"_json;
1347 parseConfiguration(element);
1348 ADD_FAILURE() << "Should not have reached this line.";
1349 }
1350 catch (const std::invalid_argument& e)
1351 {
1352 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
1353 "either rule_id or actions");
1354 }
1355
1356 // Test where fails: Element is not an object
1357 try
1358 {
1359 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1360 parseConfiguration(element);
1361 ADD_FAILURE() << "Should not have reached this line.";
1362 }
1363 catch (const std::invalid_argument& e)
1364 {
1365 EXPECT_STREQ(e.what(), "Element is not an object");
1366 }
1367
1368 // Test where fails: Invalid property specified
1369 try
1370 {
1371 const json element = R"(
1372 {
1373 "volts": 1.03,
1374 "rule_id": "set_voltage_rule",
1375 "foo": 1
1376 }
1377 )"_json;
1378 parseConfiguration(element);
1379 ADD_FAILURE() << "Should not have reached this line.";
1380 }
1381 catch (const std::invalid_argument& e)
1382 {
1383 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1384 }
1385}
1386
Bob King9c36c5f2020-04-06 11:34:09 +08001387TEST(ConfigFileParserTests, ParseDevice)
1388{
1389 // Test where works: Only required properties specified
1390 {
1391 const json element = R"(
1392 {
1393 "id": "vdd_regulator",
1394 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001395 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001396 "i2c_interface": { "bus": 1, "address": "0x70" }
1397 }
1398 )"_json;
1399 std::unique_ptr<Device> device = parseDevice(element);
1400 EXPECT_EQ(device->getID(), "vdd_regulator");
1401 EXPECT_EQ(device->isRegulator(), true);
Bob Kinga76898f2020-10-13 15:08:33 +08001402 EXPECT_EQ(device->getFRU(), "/xyz/openbmc_project/inventory/system/"
1403 "chassis/motherboard/regulator2");
Bob King9c36c5f2020-04-06 11:34:09 +08001404 EXPECT_NE(&(device->getI2CInterface()), nullptr);
1405 EXPECT_EQ(device->getPresenceDetection(), nullptr);
1406 EXPECT_EQ(device->getConfiguration(), nullptr);
1407 EXPECT_EQ(device->getRails().size(), 0);
1408 }
1409
1410 // Test where works: All properties specified
Bob King33e7eaa2020-04-01 18:09:34 +08001411 {
Bob King33e7eaa2020-04-01 18:09:34 +08001412 const json element = R"(
1413 {
1414 "id": "vdd_regulator",
1415 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001416 "fru": "system/chassis/motherboard/regulator2",
Bob King33e7eaa2020-04-01 18:09:34 +08001417 "i2c_interface":
1418 {
1419 "bus": 1,
1420 "address": "0x70"
1421 },
1422 "configuration":
1423 {
1424 "rule_id": "configure_ir35221_rule"
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001425 },
Bob King2aafb1c2020-04-16 15:24:32 +08001426 "presence_detection":
1427 {
1428 "rule_id": "is_foobar_backplane_installed_rule"
1429 },
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001430 "rails":
1431 [
1432 {
1433 "id": "vdd"
1434 }
1435 ]
Bob King33e7eaa2020-04-01 18:09:34 +08001436 }
1437 )"_json;
1438 std::unique_ptr<Device> device = parseDevice(element);
1439 EXPECT_EQ(device->getID(), "vdd_regulator");
1440 EXPECT_EQ(device->isRegulator(), true);
Bob Kinga76898f2020-10-13 15:08:33 +08001441 EXPECT_EQ(device->getFRU(), "/xyz/openbmc_project/inventory/system/"
1442 "chassis/motherboard/regulator2");
Bob King33e7eaa2020-04-01 18:09:34 +08001443 EXPECT_NE(&(device->getI2CInterface()), nullptr);
Bob King2aafb1c2020-04-16 15:24:32 +08001444 EXPECT_NE(device->getPresenceDetection(), nullptr);
Bob King33e7eaa2020-04-01 18:09:34 +08001445 EXPECT_NE(device->getConfiguration(), nullptr);
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001446 EXPECT_EQ(device->getRails().size(), 1);
1447 }
1448
1449 // Test where fails: rails property exists and is_regulator is false
1450 try
1451 {
1452 const json element = R"(
1453 {
1454 "id": "vdd_regulator",
1455 "is_regulator": false,
Bob Kinga76898f2020-10-13 15:08:33 +08001456 "fru": "system/chassis/motherboard/regulator2",
Bob Kinga2f2a0d2020-04-09 13:32:14 +08001457 "i2c_interface":
1458 {
1459 "bus": 1,
1460 "address": "0x70"
1461 },
1462 "configuration":
1463 {
1464 "rule_id": "configure_ir35221_rule"
1465 },
1466 "rails":
1467 [
1468 {
1469 "id": "vdd"
1470 }
1471 ]
1472 }
1473 )"_json;
1474 parseDevice(element);
1475 ADD_FAILURE() << "Should not have reached this line.";
1476 }
1477 catch (const std::invalid_argument& e)
1478 {
1479 EXPECT_STREQ(e.what(),
1480 "Invalid rails property when is_regulator is false");
Bob King33e7eaa2020-04-01 18:09:34 +08001481 }
Bob King9c36c5f2020-04-06 11:34:09 +08001482
1483 // Test where fails: id value is invalid
1484 try
1485 {
1486 const json element = R"(
1487 {
1488 "id": 3,
1489 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001490 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001491 "i2c_interface":
1492 {
1493 "bus": 1,
1494 "address": "0x70"
1495 }
1496 }
1497 )"_json;
1498 parseDevice(element);
1499 ADD_FAILURE() << "Should not have reached this line.";
1500 }
1501 catch (const std::invalid_argument& e)
1502 {
1503 EXPECT_STREQ(e.what(), "Element is not a string");
1504 }
1505
1506 // Test where fails: is_regulator value is invalid
1507 try
1508 {
1509 const json element = R"(
1510 {
1511 "id": "vdd_regulator",
1512 "is_regulator": 3,
Bob Kinga76898f2020-10-13 15:08:33 +08001513 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001514 "i2c_interface":
1515 {
1516 "bus": 1,
1517 "address": "0x70"
1518 }
1519 }
1520 )"_json;
1521 parseDevice(element);
1522 ADD_FAILURE() << "Should not have reached this line.";
1523 }
1524 catch (const std::invalid_argument& e)
1525 {
1526 EXPECT_STREQ(e.what(), "Element is not a boolean");
1527 }
1528
1529 // Test where fails: fru value is invalid
1530 try
1531 {
1532 const json element = R"(
1533 {
1534 "id": "vdd_regulator",
1535 "is_regulator": true,
1536 "fru": 2,
1537 "i2c_interface":
1538 {
1539 "bus": 1,
1540 "address": "0x70"
1541 }
1542 }
1543 )"_json;
1544 parseDevice(element);
1545 ADD_FAILURE() << "Should not have reached this line.";
1546 }
1547 catch (const std::invalid_argument& e)
1548 {
1549 EXPECT_STREQ(e.what(), "Element is not a string");
1550 }
1551
1552 // Test where fails: i2c_interface value is invalid
1553 try
1554 {
1555 const json element = R"(
1556 {
1557 "id": "vdd_regulator",
1558 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001559 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001560 "i2c_interface": 3
1561 }
1562 )"_json;
1563 parseDevice(element);
1564 ADD_FAILURE() << "Should not have reached this line.";
1565 }
1566 catch (const std::invalid_argument& e)
1567 {
1568 EXPECT_STREQ(e.what(), "Element is not an object");
1569 }
1570
1571 // Test where fails: Required id property not specified
1572 try
1573 {
1574 const json element = R"(
1575 {
1576 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001577 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001578 "i2c_interface":
1579 {
1580 "bus": 1,
1581 "address": "0x70"
1582 }
1583 }
1584 )"_json;
1585 parseDevice(element);
1586 ADD_FAILURE() << "Should not have reached this line.";
1587 }
1588 catch (const std::invalid_argument& e)
1589 {
1590 EXPECT_STREQ(e.what(), "Required property missing: id");
1591 }
1592
1593 // Test where fails: Required is_regulator property not specified
1594 try
1595 {
1596 const json element = R"(
1597 {
1598 "id": "vdd_regulator",
Bob Kinga76898f2020-10-13 15:08:33 +08001599 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001600 "i2c_interface":
1601 {
1602 "bus": 1,
1603 "address": "0x70"
1604 }
1605 }
1606 )"_json;
1607 parseDevice(element);
1608 ADD_FAILURE() << "Should not have reached this line.";
1609 }
1610 catch (const std::invalid_argument& e)
1611 {
1612 EXPECT_STREQ(e.what(), "Required property missing: is_regulator");
1613 }
1614
1615 // Test where fails: Required fru property not specified
1616 try
1617 {
1618 const json element = R"(
1619 {
1620 "id": "vdd_regulator",
1621 "is_regulator": true,
1622 "i2c_interface":
1623 {
1624 "bus": 1,
1625 "address": "0x70"
1626 }
1627 }
1628 )"_json;
1629 parseDevice(element);
1630 ADD_FAILURE() << "Should not have reached this line.";
1631 }
1632 catch (const std::invalid_argument& e)
1633 {
1634 EXPECT_STREQ(e.what(), "Required property missing: fru");
1635 }
1636
1637 // Test where fails: Required i2c_interface property not specified
1638 try
1639 {
1640 const json element = R"(
1641 {
1642 "id": "vdd_regulator",
1643 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001644 "fru": "system/chassis/motherboard/regulator2"
Bob King9c36c5f2020-04-06 11:34:09 +08001645 }
1646 )"_json;
1647 parseDevice(element);
1648 ADD_FAILURE() << "Should not have reached this line.";
1649 }
1650 catch (const std::invalid_argument& e)
1651 {
1652 EXPECT_STREQ(e.what(), "Required property missing: i2c_interface");
1653 }
1654
1655 // Test where fails: Element is not an object
1656 try
1657 {
1658 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1659 parseDevice(element);
1660 ADD_FAILURE() << "Should not have reached this line.";
1661 }
1662 catch (const std::invalid_argument& e)
1663 {
1664 EXPECT_STREQ(e.what(), "Element is not an object");
1665 }
1666
1667 // Test where fails: Invalid property specified
1668 try
1669 {
1670 const json element = R"(
1671 {
1672 "id": "vdd_regulator",
1673 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001674 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001675 "i2c_interface": { "bus": 1, "address": "0x70" },
1676 "foo" : true
1677 }
1678 )"_json;
1679 parseDevice(element);
1680 ADD_FAILURE() << "Should not have reached this line.";
1681 }
1682 catch (const std::invalid_argument& e)
1683 {
1684 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1685 }
1686}
1687
1688TEST(ConfigFileParserTests, ParseDeviceArray)
1689{
1690 // Test where works
1691 {
1692 const json element = R"(
1693 [
1694 {
1695 "id": "vdd_regulator",
1696 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001697 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001698 "i2c_interface": { "bus": 1, "address": "0x70" }
1699 },
1700 {
1701 "id": "vio_regulator",
1702 "is_regulator": true,
Bob Kinga76898f2020-10-13 15:08:33 +08001703 "fru": "system/chassis/motherboard/regulator2",
Bob King9c36c5f2020-04-06 11:34:09 +08001704 "i2c_interface": { "bus": 1, "address": "0x71" }
1705 }
1706 ]
1707 )"_json;
1708 std::vector<std::unique_ptr<Device>> devices =
1709 parseDeviceArray(element);
1710 EXPECT_EQ(devices.size(), 2);
1711 EXPECT_EQ(devices[0]->getID(), "vdd_regulator");
1712 EXPECT_EQ(devices[1]->getID(), "vio_regulator");
1713 }
1714
1715 // Test where fails: Element is not an array
1716 try
1717 {
1718 const json element = R"(
1719 {
1720 "foo": "bar"
1721 }
1722 )"_json;
1723 parseDeviceArray(element);
1724 ADD_FAILURE() << "Should not have reached this line.";
1725 }
1726 catch (const std::invalid_argument& e)
1727 {
1728 EXPECT_STREQ(e.what(), "Element is not an array");
1729 }
1730}
1731
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001732TEST(ConfigFileParserTests, ParseDouble)
1733{
1734 // Test where works: floating point value
1735 {
1736 const json element = R"( 1.03 )"_json;
1737 double value = parseDouble(element);
1738 EXPECT_EQ(value, 1.03);
1739 }
1740
1741 // Test where works: integer value
1742 {
1743 const json element = R"( 24 )"_json;
1744 double value = parseDouble(element);
1745 EXPECT_EQ(value, 24.0);
1746 }
1747
1748 // Test where fails: Element is not a number
1749 try
1750 {
1751 const json element = R"( true )"_json;
1752 parseDouble(element);
1753 ADD_FAILURE() << "Should not have reached this line.";
1754 }
1755 catch (const std::invalid_argument& e)
1756 {
1757 EXPECT_STREQ(e.what(), "Element is not a number");
1758 }
1759}
1760
Bob Kingbafcb862020-03-31 16:39:00 +08001761TEST(ConfigFileParserTests, ParseHexByte)
1762{
1763 // Test where works: "0xFF"
1764 {
1765 const json element = R"( "0xFF" )"_json;
1766 uint8_t value = parseHexByte(element);
1767 EXPECT_EQ(value, 0xFF);
1768 }
1769
1770 // Test where works: "0xff"
1771 {
1772 const json element = R"( "0xff" )"_json;
1773 uint8_t value = parseHexByte(element);
1774 EXPECT_EQ(value, 0xff);
1775 }
1776
1777 // Test where works: "0xf"
1778 {
1779 const json element = R"( "0xf" )"_json;
1780 uint8_t value = parseHexByte(element);
1781 EXPECT_EQ(value, 0xf);
1782 }
1783
1784 // Test where fails: "0xfff"
1785 try
1786 {
1787 const json element = R"( "0xfff" )"_json;
1788 parseHexByte(element);
1789 ADD_FAILURE() << "Should not have reached this line.";
1790 }
1791 catch (const std::invalid_argument& e)
1792 {
1793 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1794 }
1795
1796 // Test where fails: "0xAG"
1797 try
1798 {
1799 const json element = R"( "0xAG" )"_json;
1800 parseHexByte(element);
1801 ADD_FAILURE() << "Should not have reached this line.";
1802 }
1803 catch (const std::invalid_argument& e)
1804 {
1805 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1806 }
1807
1808 // Test where fails: "ff"
1809 try
1810 {
1811 const json element = R"( "ff" )"_json;
1812 parseHexByte(element);
1813 ADD_FAILURE() << "Should not have reached this line.";
1814 }
1815 catch (const std::invalid_argument& e)
1816 {
1817 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1818 }
1819
1820 // Test where fails: ""
1821 try
1822 {
1823 const json element = "";
1824 parseHexByte(element);
1825 ADD_FAILURE() << "Should not have reached this line.";
1826 }
1827 catch (const std::invalid_argument& e)
1828 {
1829 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1830 }
1831
1832 // Test where fails: "f"
1833 try
1834 {
1835 const json element = R"( "f" )"_json;
1836 parseHexByte(element);
1837 ADD_FAILURE() << "Should not have reached this line.";
1838 }
1839 catch (const std::invalid_argument& e)
1840 {
1841 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1842 }
1843
1844 // Test where fails: "0x"
1845 try
1846 {
1847 const json element = R"( "0x" )"_json;
1848 parseHexByte(element);
1849 ADD_FAILURE() << "Should not have reached this line.";
1850 }
1851 catch (const std::invalid_argument& e)
1852 {
1853 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1854 }
1855
1856 // Test where fails: "0Xff"
1857 try
1858 {
1859 const json element = R"( "0XFF" )"_json;
1860 parseHexByte(element);
1861 ADD_FAILURE() << "Should not have reached this line.";
1862 }
1863 catch (const std::invalid_argument& e)
1864 {
1865 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1866 }
1867}
1868
1869TEST(ConfigFileParserTests, ParseHexByteArray)
1870{
1871 // Test where works
1872 {
1873 const json element = R"( [ "0xCC", "0xFF" ] )"_json;
1874 std::vector<uint8_t> hexBytes = parseHexByteArray(element);
1875 std::vector<uint8_t> expected = {0xcc, 0xff};
1876 EXPECT_EQ(hexBytes, expected);
1877 }
1878
1879 // Test where fails: Element is not an array
1880 try
1881 {
1882 const json element = 0;
1883 parseHexByteArray(element);
1884 ADD_FAILURE() << "Should not have reached this line.";
1885 }
1886 catch (const std::invalid_argument& e)
1887 {
1888 EXPECT_STREQ(e.what(), "Element is not an array");
1889 }
1890}
1891
Bob Kingf09bfe02020-04-13 17:21:15 +08001892TEST(ConfigFileParserTests, ParseI2CCompareBit)
1893{
1894 // Test where works
1895 {
1896 const json element = R"(
1897 {
1898 "register": "0xA0",
1899 "position": 3,
1900 "value": 0
1901 }
1902 )"_json;
1903 std::unique_ptr<I2CCompareBitAction> action =
1904 parseI2CCompareBit(element);
1905 EXPECT_EQ(action->getRegister(), 0xA0);
1906 EXPECT_EQ(action->getPosition(), 3);
1907 EXPECT_EQ(action->getValue(), 0);
1908 }
1909
1910 // Test where fails: Invalid property specified
1911 try
1912 {
1913 const json element = R"(
1914 {
1915 "register": "0xA0",
1916 "position": 3,
1917 "value": 0,
1918 "foo": 3
1919 }
1920 )"_json;
1921 parseI2CCompareBit(element);
1922 ADD_FAILURE() << "Should not have reached this line.";
1923 }
1924 catch (const std::invalid_argument& e)
1925 {
1926 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1927 }
1928
1929 // Test where fails: Element is not an object
1930 try
1931 {
1932 const json element = R"( [ "0xFF", "0x01" ] )"_json;
1933 parseI2CCompareBit(element);
1934 ADD_FAILURE() << "Should not have reached this line.";
1935 }
1936 catch (const std::invalid_argument& e)
1937 {
1938 EXPECT_STREQ(e.what(), "Element is not an object");
1939 }
1940
1941 // Test where fails: register value is invalid
1942 try
1943 {
1944 const json element = R"(
1945 {
1946 "register": "0xAG",
1947 "position": 3,
1948 "value": 0
1949 }
1950 )"_json;
1951 parseI2CCompareBit(element);
1952 ADD_FAILURE() << "Should not have reached this line.";
1953 }
1954 catch (const std::invalid_argument& e)
1955 {
1956 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
1957 }
1958
1959 // Test where fails: position value is invalid
1960 try
1961 {
1962 const json element = R"(
1963 {
1964 "register": "0xA0",
1965 "position": 8,
1966 "value": 0
1967 }
1968 )"_json;
1969 parseI2CCompareBit(element);
1970 ADD_FAILURE() << "Should not have reached this line.";
1971 }
1972 catch (const std::invalid_argument& e)
1973 {
1974 EXPECT_STREQ(e.what(), "Element is not a bit position");
1975 }
1976
1977 // Test where fails: value value is invalid
1978 try
1979 {
1980 const json element = R"(
1981 {
1982 "register": "0xA0",
1983 "position": 3,
1984 "value": 2
1985 }
1986 )"_json;
1987 parseI2CCompareBit(element);
1988 ADD_FAILURE() << "Should not have reached this line.";
1989 }
1990 catch (const std::invalid_argument& e)
1991 {
1992 EXPECT_STREQ(e.what(), "Element is not a bit value");
1993 }
1994
1995 // Test where fails: Required register property not specified
1996 try
1997 {
1998 const json element = R"(
1999 {
2000 "position": 3,
2001 "value": 0
2002 }
2003 )"_json;
2004 parseI2CCompareBit(element);
2005 ADD_FAILURE() << "Should not have reached this line.";
2006 }
2007 catch (const std::invalid_argument& e)
2008 {
2009 EXPECT_STREQ(e.what(), "Required property missing: register");
2010 }
2011
2012 // Test where fails: Required position property not specified
2013 try
2014 {
2015 const json element = R"(
2016 {
2017 "register": "0xA0",
2018 "value": 0
2019 }
2020 )"_json;
2021 parseI2CCompareBit(element);
2022 ADD_FAILURE() << "Should not have reached this line.";
2023 }
2024 catch (const std::invalid_argument& e)
2025 {
2026 EXPECT_STREQ(e.what(), "Required property missing: position");
2027 }
2028
2029 // Test where fails: Required value property not specified
2030 try
2031 {
2032 const json element = R"(
2033 {
2034 "register": "0xA0",
2035 "position": 3
2036 }
2037 )"_json;
2038 parseI2CCompareBit(element);
2039 ADD_FAILURE() << "Should not have reached this line.";
2040 }
2041 catch (const std::invalid_argument& e)
2042 {
2043 EXPECT_STREQ(e.what(), "Required property missing: value");
2044 }
2045}
2046
2047TEST(ConfigFileParserTests, ParseI2CCompareByte)
2048{
2049 // Test where works: Only required properties specified
2050 {
2051 const json element = R"(
2052 {
2053 "register": "0x0A",
2054 "value": "0xCC"
2055 }
2056 )"_json;
2057 std::unique_ptr<I2CCompareByteAction> action =
2058 parseI2CCompareByte(element);
2059 EXPECT_EQ(action->getRegister(), 0x0A);
2060 EXPECT_EQ(action->getValue(), 0xCC);
2061 EXPECT_EQ(action->getMask(), 0xFF);
2062 }
2063
2064 // Test where works: All properties specified
2065 {
2066 const json element = R"(
2067 {
2068 "register": "0x0A",
2069 "value": "0xCC",
2070 "mask": "0xF7"
2071 }
2072 )"_json;
2073 std::unique_ptr<I2CCompareByteAction> action =
2074 parseI2CCompareByte(element);
2075 EXPECT_EQ(action->getRegister(), 0x0A);
2076 EXPECT_EQ(action->getValue(), 0xCC);
2077 EXPECT_EQ(action->getMask(), 0xF7);
2078 }
2079
2080 // Test where fails: Element is not an object
2081 try
2082 {
2083 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2084 parseI2CCompareByte(element);
2085 ADD_FAILURE() << "Should not have reached this line.";
2086 }
2087 catch (const std::invalid_argument& e)
2088 {
2089 EXPECT_STREQ(e.what(), "Element is not an object");
2090 }
2091
2092 // Test where fails: Invalid property specified
2093 try
2094 {
2095 const json element = R"(
2096 {
2097 "register": "0x0A",
2098 "value": "0xCC",
2099 "mask": "0xF7",
2100 "foo": 1
2101 }
2102 )"_json;
2103 parseI2CCompareByte(element);
2104 ADD_FAILURE() << "Should not have reached this line.";
2105 }
2106 catch (const std::invalid_argument& e)
2107 {
2108 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2109 }
2110
2111 // Test where fails: register value is invalid
2112 try
2113 {
2114 const json element = R"(
2115 {
2116 "register": "0x0Z",
2117 "value": "0xCC",
2118 "mask": "0xF7"
2119 }
2120 )"_json;
2121 parseI2CCompareByte(element);
2122 ADD_FAILURE() << "Should not have reached this line.";
2123 }
2124 catch (const std::invalid_argument& e)
2125 {
2126 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2127 }
2128
2129 // Test where fails: value value is invalid
2130 try
2131 {
2132 const json element = R"(
2133 {
2134 "register": "0x0A",
2135 "value": "0xCCC",
2136 "mask": "0xF7"
2137 }
2138 )"_json;
2139 parseI2CCompareByte(element);
2140 ADD_FAILURE() << "Should not have reached this line.";
2141 }
2142 catch (const std::invalid_argument& e)
2143 {
2144 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2145 }
2146
2147 // Test where fails: mask value is invalid
2148 try
2149 {
2150 const json element = R"(
2151 {
2152 "register": "0x0A",
2153 "value": "0xCC",
2154 "mask": "F7"
2155 }
2156 )"_json;
2157 parseI2CCompareByte(element);
2158 ADD_FAILURE() << "Should not have reached this line.";
2159 }
2160 catch (const std::invalid_argument& e)
2161 {
2162 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2163 }
2164
2165 // Test where fails: Required register property not specified
2166 try
2167 {
2168 const json element = R"(
2169 {
2170 "value": "0xCC",
2171 "mask": "0xF7"
2172 }
2173 )"_json;
2174 parseI2CCompareByte(element);
2175 ADD_FAILURE() << "Should not have reached this line.";
2176 }
2177 catch (const std::invalid_argument& e)
2178 {
2179 EXPECT_STREQ(e.what(), "Required property missing: register");
2180 }
2181
2182 // Test where fails: Required value property not specified
2183 try
2184 {
2185 const json element = R"(
2186 {
2187 "register": "0x0A",
2188 "mask": "0xF7"
2189 }
2190 )"_json;
2191 parseI2CCompareByte(element);
2192 ADD_FAILURE() << "Should not have reached this line.";
2193 }
2194 catch (const std::invalid_argument& e)
2195 {
2196 EXPECT_STREQ(e.what(), "Required property missing: value");
2197 }
2198}
2199
2200TEST(ConfigFileParserTests, ParseI2CCompareBytes)
2201{
2202 // Test where works: Only required properties specified
2203 {
2204 const json element = R"(
2205 {
2206 "register": "0x0A",
2207 "values": [ "0xCC", "0xFF" ]
2208 }
2209 )"_json;
2210 std::unique_ptr<I2CCompareBytesAction> action =
2211 parseI2CCompareBytes(element);
2212 EXPECT_EQ(action->getRegister(), 0x0A);
2213 EXPECT_EQ(action->getValues().size(), 2);
2214 EXPECT_EQ(action->getValues()[0], 0xCC);
2215 EXPECT_EQ(action->getValues()[1], 0xFF);
2216 EXPECT_EQ(action->getMasks().size(), 2);
2217 EXPECT_EQ(action->getMasks()[0], 0xFF);
2218 EXPECT_EQ(action->getMasks()[1], 0xFF);
2219 }
2220
2221 // Test where works: All properties specified
2222 {
2223 const json element = R"(
2224 {
2225 "register": "0x0A",
2226 "values": [ "0xCC", "0xFF" ],
2227 "masks": [ "0x7F", "0x77" ]
2228 }
2229 )"_json;
2230 std::unique_ptr<I2CCompareBytesAction> action =
2231 parseI2CCompareBytes(element);
2232 EXPECT_EQ(action->getRegister(), 0x0A);
2233 EXPECT_EQ(action->getValues().size(), 2);
2234 EXPECT_EQ(action->getValues()[0], 0xCC);
2235 EXPECT_EQ(action->getValues()[1], 0xFF);
2236 EXPECT_EQ(action->getMasks().size(), 2);
2237 EXPECT_EQ(action->getMasks()[0], 0x7F);
2238 EXPECT_EQ(action->getMasks()[1], 0x77);
2239 }
2240
2241 // Test where fails: Element is not an object
2242 try
2243 {
2244 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2245 parseI2CCompareBytes(element);
2246 ADD_FAILURE() << "Should not have reached this line.";
2247 }
2248 catch (const std::invalid_argument& e)
2249 {
2250 EXPECT_STREQ(e.what(), "Element is not an object");
2251 }
2252
2253 // Test where fails: Invalid property specified
2254 try
2255 {
2256 const json element = R"(
2257 {
2258 "register": "0x0A",
2259 "values": [ "0xCC", "0xFF" ],
2260 "masks": [ "0x7F", "0x7F" ],
2261 "foo": 1
2262 }
2263 )"_json;
2264 parseI2CCompareBytes(element);
2265 ADD_FAILURE() << "Should not have reached this line.";
2266 }
2267 catch (const std::invalid_argument& e)
2268 {
2269 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2270 }
2271
2272 // Test where fails: register value is invalid
2273 try
2274 {
2275 const json element = R"(
2276 {
2277 "register": "0x0Z",
2278 "values": [ "0xCC", "0xFF" ],
2279 "masks": [ "0x7F", "0x7F" ]
2280 }
2281 )"_json;
2282 parseI2CCompareBytes(element);
2283 ADD_FAILURE() << "Should not have reached this line.";
2284 }
2285 catch (const std::invalid_argument& e)
2286 {
2287 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2288 }
2289
2290 // Test where fails: values value is invalid
2291 try
2292 {
2293 const json element = R"(
2294 {
2295 "register": "0x0A",
2296 "values": [ "0xCCC", "0xFF" ],
2297 "masks": [ "0x7F", "0x7F" ]
2298 }
2299 )"_json;
2300 parseI2CCompareBytes(element);
2301 ADD_FAILURE() << "Should not have reached this line.";
2302 }
2303 catch (const std::invalid_argument& e)
2304 {
2305 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2306 }
2307
2308 // Test where fails: masks value is invalid
2309 try
2310 {
2311 const json element = R"(
2312 {
2313 "register": "0x0A",
2314 "values": [ "0xCC", "0xFF" ],
2315 "masks": [ "F", "0x7F" ]
2316 }
2317 )"_json;
2318 parseI2CCompareBytes(element);
2319 ADD_FAILURE() << "Should not have reached this line.";
2320 }
2321 catch (const std::invalid_argument& e)
2322 {
2323 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2324 }
2325
2326 // Test where fails: number of elements in masks is invalid
2327 try
2328 {
2329 const json element = R"(
2330 {
2331 "register": "0x0A",
2332 "values": [ "0xCC", "0xFF" ],
2333 "masks": [ "0x7F" ]
2334 }
2335 )"_json;
2336 parseI2CCompareBytes(element);
2337 ADD_FAILURE() << "Should not have reached this line.";
2338 }
2339 catch (const std::invalid_argument& e)
2340 {
2341 EXPECT_STREQ(e.what(), "Invalid number of elements in masks");
2342 }
2343
2344 // Test where fails: Required register property not specified
2345 try
2346 {
2347 const json element = R"(
2348 {
2349 "values": [ "0xCC", "0xFF" ]
2350 }
2351 )"_json;
2352 parseI2CCompareBytes(element);
2353 ADD_FAILURE() << "Should not have reached this line.";
2354 }
2355 catch (const std::invalid_argument& e)
2356 {
2357 EXPECT_STREQ(e.what(), "Required property missing: register");
2358 }
2359
2360 // Test where fails: Required values property not specified
2361 try
2362 {
2363 const json element = R"(
2364 {
2365 "register": "0x0A"
2366 }
2367 )"_json;
2368 parseI2CCompareBytes(element);
2369 ADD_FAILURE() << "Should not have reached this line.";
2370 }
2371 catch (const std::invalid_argument& e)
2372 {
2373 EXPECT_STREQ(e.what(), "Required property missing: values");
2374 }
2375}
2376
Bob Kingf617f892020-03-30 19:03:35 +08002377TEST(ConfigFileParserTests, ParseI2CWriteBit)
2378{
2379 // Test where works
2380 {
2381 const json element = R"(
2382 {
2383 "register": "0xA0",
2384 "position": 3,
2385 "value": 0
2386 }
2387 )"_json;
2388 std::unique_ptr<I2CWriteBitAction> action = parseI2CWriteBit(element);
2389 EXPECT_EQ(action->getRegister(), 0xA0);
2390 EXPECT_EQ(action->getPosition(), 3);
2391 EXPECT_EQ(action->getValue(), 0);
2392 }
2393
2394 // Test where fails: Invalid property specified
2395 try
2396 {
2397 const json element = R"(
2398 {
2399 "register": "0xA0",
2400 "position": 3,
2401 "value": 0,
2402 "foo": 3
2403 }
2404 )"_json;
2405 parseI2CWriteBit(element);
2406 ADD_FAILURE() << "Should not have reached this line.";
2407 }
2408 catch (const std::invalid_argument& e)
2409 {
2410 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2411 }
2412
2413 // Test where fails: Element is not an object
2414 try
2415 {
2416 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2417 parseI2CWriteBit(element);
2418 ADD_FAILURE() << "Should not have reached this line.";
2419 }
2420 catch (const std::invalid_argument& e)
2421 {
2422 EXPECT_STREQ(e.what(), "Element is not an object");
2423 }
2424
2425 // Test where fails: register value is invalid
2426 try
2427 {
2428 const json element = R"(
2429 {
2430 "register": "0xAG",
2431 "position": 3,
2432 "value": 0
2433 }
2434 )"_json;
2435 parseI2CWriteBit(element);
2436 ADD_FAILURE() << "Should not have reached this line.";
2437 }
2438 catch (const std::invalid_argument& e)
2439 {
2440 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2441 }
2442
2443 // Test where fails: position value is invalid
2444 try
2445 {
2446 const json element = R"(
2447 {
2448 "register": "0xA0",
2449 "position": 8,
2450 "value": 0
2451 }
2452 )"_json;
2453 parseI2CWriteBit(element);
2454 ADD_FAILURE() << "Should not have reached this line.";
2455 }
2456 catch (const std::invalid_argument& e)
2457 {
2458 EXPECT_STREQ(e.what(), "Element is not a bit position");
2459 }
2460
2461 // Test where fails: value value is invalid
2462 try
2463 {
2464 const json element = R"(
2465 {
2466 "register": "0xA0",
2467 "position": 3,
2468 "value": 2
2469 }
2470 )"_json;
2471 parseI2CWriteBit(element);
2472 ADD_FAILURE() << "Should not have reached this line.";
2473 }
2474 catch (const std::invalid_argument& e)
2475 {
2476 EXPECT_STREQ(e.what(), "Element is not a bit value");
2477 }
2478
2479 // Test where fails: Required register property not specified
2480 try
2481 {
2482 const json element = R"(
2483 {
2484 "position": 3,
2485 "value": 0
2486 }
2487 )"_json;
2488 parseI2CWriteBit(element);
2489 ADD_FAILURE() << "Should not have reached this line.";
2490 }
2491 catch (const std::invalid_argument& e)
2492 {
2493 EXPECT_STREQ(e.what(), "Required property missing: register");
2494 }
2495
2496 // Test where fails: Required position property not specified
2497 try
2498 {
2499 const json element = R"(
2500 {
2501 "register": "0xA0",
2502 "value": 0
2503 }
2504 )"_json;
2505 parseI2CWriteBit(element);
2506 ADD_FAILURE() << "Should not have reached this line.";
2507 }
2508 catch (const std::invalid_argument& e)
2509 {
2510 EXPECT_STREQ(e.what(), "Required property missing: position");
2511 }
2512
2513 // Test where fails: Required value property not specified
2514 try
2515 {
2516 const json element = R"(
2517 {
2518 "register": "0xA0",
2519 "position": 3
2520 }
2521 )"_json;
2522 parseI2CWriteBit(element);
2523 ADD_FAILURE() << "Should not have reached this line.";
2524 }
2525 catch (const std::invalid_argument& e)
2526 {
2527 EXPECT_STREQ(e.what(), "Required property missing: value");
2528 }
2529}
2530
Bob King87ff9d72020-03-31 14:02:55 +08002531TEST(ConfigFileParserTests, ParseI2CWriteByte)
2532{
2533 // Test where works: Only required properties specified
2534 {
2535 const json element = R"(
2536 {
2537 "register": "0x0A",
2538 "value": "0xCC"
2539 }
2540 )"_json;
2541 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element);
2542 EXPECT_EQ(action->getRegister(), 0x0A);
2543 EXPECT_EQ(action->getValue(), 0xCC);
2544 EXPECT_EQ(action->getMask(), 0xFF);
2545 }
2546
2547 // Test where works: All properties specified
2548 {
2549 const json element = R"(
2550 {
2551 "register": "0x0A",
2552 "value": "0xCC",
2553 "mask": "0xF7"
2554 }
2555 )"_json;
2556 std::unique_ptr<I2CWriteByteAction> action = parseI2CWriteByte(element);
2557 EXPECT_EQ(action->getRegister(), 0x0A);
2558 EXPECT_EQ(action->getValue(), 0xCC);
2559 EXPECT_EQ(action->getMask(), 0xF7);
2560 }
2561
2562 // Test where fails: Element is not an object
2563 try
2564 {
2565 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2566 parseI2CWriteByte(element);
2567 ADD_FAILURE() << "Should not have reached this line.";
2568 }
2569 catch (const std::invalid_argument& e)
2570 {
2571 EXPECT_STREQ(e.what(), "Element is not an object");
2572 }
2573
2574 // Test where fails: Invalid property specified
2575 try
2576 {
2577 const json element = R"(
2578 {
2579 "register": "0x0A",
2580 "value": "0xCC",
2581 "mask": "0xF7",
2582 "foo": 1
2583 }
2584 )"_json;
2585 parseI2CWriteByte(element);
2586 ADD_FAILURE() << "Should not have reached this line.";
2587 }
2588 catch (const std::invalid_argument& e)
2589 {
2590 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2591 }
2592
2593 // Test where fails: register value is invalid
2594 try
2595 {
2596 const json element = R"(
2597 {
2598 "register": "0x0Z",
2599 "value": "0xCC",
2600 "mask": "0xF7"
2601 }
2602 )"_json;
2603 parseI2CWriteByte(element);
2604 ADD_FAILURE() << "Should not have reached this line.";
2605 }
2606 catch (const std::invalid_argument& e)
2607 {
2608 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2609 }
2610
2611 // Test where fails: value value is invalid
2612 try
2613 {
2614 const json element = R"(
2615 {
2616 "register": "0x0A",
2617 "value": "0xCCC",
2618 "mask": "0xF7"
2619 }
2620 )"_json;
2621 parseI2CWriteByte(element);
2622 ADD_FAILURE() << "Should not have reached this line.";
2623 }
2624 catch (const std::invalid_argument& e)
2625 {
2626 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2627 }
2628
2629 // Test where fails: mask value is invalid
2630 try
2631 {
2632 const json element = R"(
2633 {
2634 "register": "0x0A",
2635 "value": "0xCC",
2636 "mask": "F7"
2637 }
2638 )"_json;
2639 parseI2CWriteByte(element);
2640 ADD_FAILURE() << "Should not have reached this line.";
2641 }
2642 catch (const std::invalid_argument& e)
2643 {
2644 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2645 }
2646
2647 // Test where fails: Required register property not specified
2648 try
2649 {
2650 const json element = R"(
2651 {
2652 "value": "0xCC",
2653 "mask": "0xF7"
2654 }
2655 )"_json;
2656 parseI2CWriteByte(element);
2657 ADD_FAILURE() << "Should not have reached this line.";
2658 }
2659 catch (const std::invalid_argument& e)
2660 {
2661 EXPECT_STREQ(e.what(), "Required property missing: register");
2662 }
2663
2664 // Test where fails: Required value property not specified
2665 try
2666 {
2667 const json element = R"(
2668 {
2669 "register": "0x0A",
2670 "mask": "0xF7"
2671 }
2672 )"_json;
2673 parseI2CWriteByte(element);
2674 ADD_FAILURE() << "Should not have reached this line.";
2675 }
2676 catch (const std::invalid_argument& e)
2677 {
2678 EXPECT_STREQ(e.what(), "Required property missing: value");
2679 }
2680}
2681
Bob Kingbafcb862020-03-31 16:39:00 +08002682TEST(ConfigFileParserTests, ParseI2CWriteBytes)
2683{
2684 // Test where works: Only required properties specified
2685 {
2686 const json element = R"(
2687 {
2688 "register": "0x0A",
2689 "values": [ "0xCC", "0xFF" ]
2690 }
2691 )"_json;
2692 std::unique_ptr<I2CWriteBytesAction> action =
2693 parseI2CWriteBytes(element);
2694 EXPECT_EQ(action->getRegister(), 0x0A);
2695 EXPECT_EQ(action->getValues().size(), 2);
2696 EXPECT_EQ(action->getValues()[0], 0xCC);
2697 EXPECT_EQ(action->getValues()[1], 0xFF);
2698 EXPECT_EQ(action->getMasks().size(), 0);
2699 }
2700
2701 // Test where works: All properties specified
2702 {
2703 const json element = R"(
2704 {
2705 "register": "0x0A",
2706 "values": [ "0xCC", "0xFF" ],
2707 "masks": [ "0x7F", "0x77" ]
2708 }
2709 )"_json;
2710 std::unique_ptr<I2CWriteBytesAction> action =
2711 parseI2CWriteBytes(element);
2712 EXPECT_EQ(action->getRegister(), 0x0A);
2713 EXPECT_EQ(action->getValues().size(), 2);
2714 EXPECT_EQ(action->getValues()[0], 0xCC);
2715 EXPECT_EQ(action->getValues()[1], 0xFF);
2716 EXPECT_EQ(action->getMasks().size(), 2);
2717 EXPECT_EQ(action->getMasks()[0], 0x7F);
2718 EXPECT_EQ(action->getMasks()[1], 0x77);
2719 }
2720
2721 // Test where fails: Element is not an object
2722 try
2723 {
2724 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2725 parseI2CWriteBytes(element);
2726 ADD_FAILURE() << "Should not have reached this line.";
2727 }
2728 catch (const std::invalid_argument& e)
2729 {
2730 EXPECT_STREQ(e.what(), "Element is not an object");
2731 }
2732
2733 // Test where fails: Invalid property specified
2734 try
2735 {
2736 const json element = R"(
2737 {
2738 "register": "0x0A",
2739 "values": [ "0xCC", "0xFF" ],
2740 "masks": [ "0x7F", "0x7F" ],
2741 "foo": 1
2742 }
2743 )"_json;
2744 parseI2CWriteBytes(element);
2745 ADD_FAILURE() << "Should not have reached this line.";
2746 }
2747 catch (const std::invalid_argument& e)
2748 {
2749 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2750 }
2751
2752 // Test where fails: register value is invalid
2753 try
2754 {
2755 const json element = R"(
2756 {
2757 "register": "0x0Z",
2758 "values": [ "0xCC", "0xFF" ],
2759 "masks": [ "0x7F", "0x7F" ]
2760 }
2761 )"_json;
2762 parseI2CWriteBytes(element);
2763 ADD_FAILURE() << "Should not have reached this line.";
2764 }
2765 catch (const std::invalid_argument& e)
2766 {
2767 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2768 }
2769
2770 // Test where fails: values value is invalid
2771 try
2772 {
2773 const json element = R"(
2774 {
2775 "register": "0x0A",
2776 "values": [ "0xCCC", "0xFF" ],
2777 "masks": [ "0x7F", "0x7F" ]
2778 }
2779 )"_json;
2780 parseI2CWriteBytes(element);
2781 ADD_FAILURE() << "Should not have reached this line.";
2782 }
2783 catch (const std::invalid_argument& e)
2784 {
2785 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2786 }
2787
2788 // Test where fails: masks value is invalid
2789 try
2790 {
2791 const json element = R"(
2792 {
2793 "register": "0x0A",
2794 "values": [ "0xCC", "0xFF" ],
2795 "masks": [ "F", "0x7F" ]
2796 }
2797 )"_json;
2798 parseI2CWriteBytes(element);
2799 ADD_FAILURE() << "Should not have reached this line.";
2800 }
2801 catch (const std::invalid_argument& e)
2802 {
2803 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
2804 }
2805
2806 // Test where fails: number of elements in masks is invalid
2807 try
2808 {
2809 const json element = R"(
2810 {
2811 "register": "0x0A",
2812 "values": [ "0xCC", "0xFF" ],
2813 "masks": [ "0x7F" ]
2814 }
2815 )"_json;
2816 parseI2CWriteBytes(element);
2817 ADD_FAILURE() << "Should not have reached this line.";
2818 }
2819 catch (const std::invalid_argument& e)
2820 {
2821 EXPECT_STREQ(e.what(), "Invalid number of elements in masks");
2822 }
2823
2824 // Test where fails: Required register property not specified
2825 try
2826 {
2827 const json element = R"(
2828 {
2829 "values": [ "0xCC", "0xFF" ]
2830 }
2831 )"_json;
2832 parseI2CWriteBytes(element);
2833 ADD_FAILURE() << "Should not have reached this line.";
2834 }
2835 catch (const std::invalid_argument& e)
2836 {
2837 EXPECT_STREQ(e.what(), "Required property missing: register");
2838 }
2839
2840 // Test where fails: Required values property not specified
2841 try
2842 {
2843 const json element = R"(
2844 {
2845 "register": "0x0A"
2846 }
2847 )"_json;
2848 parseI2CWriteBytes(element);
2849 ADD_FAILURE() << "Should not have reached this line.";
2850 }
2851 catch (const std::invalid_argument& e)
2852 {
2853 EXPECT_STREQ(e.what(), "Required property missing: values");
2854 }
2855}
2856
Bob King93a89d72020-04-15 15:11:11 +08002857TEST(ConfigFileParserTests, ParseIf)
2858{
2859 // Test where works: Only required properties specified
2860 {
2861 const json element = R"(
2862 {
2863 "condition": { "run_rule": "is_downlevel_regulator" },
2864 "then": [ { "run_rule": "configure_downlevel_regulator" },
2865 { "run_rule": "configure_standard_regulator" } ]
2866 }
2867 )"_json;
2868 std::unique_ptr<IfAction> action = parseIf(element);
2869 EXPECT_NE(action->getConditionAction().get(), nullptr);
2870 EXPECT_EQ(action->getThenActions().size(), 2);
2871 EXPECT_EQ(action->getElseActions().size(), 0);
2872 }
2873
2874 // Test where works: All properties specified
2875 {
2876 const json element = R"(
2877 {
2878 "condition": { "run_rule": "is_downlevel_regulator" },
2879 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2880 "else": [ { "run_rule": "configure_standard_regulator" } ]
2881 }
2882 )"_json;
2883 std::unique_ptr<IfAction> action = parseIf(element);
2884 EXPECT_NE(action->getConditionAction().get(), nullptr);
2885 EXPECT_EQ(action->getThenActions().size(), 1);
2886 EXPECT_EQ(action->getElseActions().size(), 1);
2887 }
2888
2889 // Test where fails: Required condition property not specified
2890 try
2891 {
2892 const json element = R"(
2893 {
2894 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2895 "else": [ { "run_rule": "configure_standard_regulator" } ]
2896 }
2897 )"_json;
2898 parseIf(element);
2899 ADD_FAILURE() << "Should not have reached this line.";
2900 }
2901 catch (const std::invalid_argument& e)
2902 {
2903 EXPECT_STREQ(e.what(), "Required property missing: condition");
2904 }
2905
2906 // Test where fails: Required then property not specified
2907 try
2908 {
2909 const json element = R"(
2910 {
2911 "condition": { "run_rule": "is_downlevel_regulator" },
2912 "else": [ { "run_rule": "configure_standard_regulator" } ]
2913 }
2914 )"_json;
2915 parseIf(element);
2916 ADD_FAILURE() << "Should not have reached this line.";
2917 }
2918 catch (const std::invalid_argument& e)
2919 {
2920 EXPECT_STREQ(e.what(), "Required property missing: then");
2921 }
2922
2923 // Test where fails: condition value is invalid
2924 try
2925 {
2926 const json element = R"(
2927 {
2928 "condition": 1,
2929 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2930 "else": [ { "run_rule": "configure_standard_regulator" } ]
2931 }
2932 )"_json;
2933 parseIf(element);
2934 ADD_FAILURE() << "Should not have reached this line.";
2935 }
2936 catch (const std::invalid_argument& e)
2937 {
2938 EXPECT_STREQ(e.what(), "Element is not an object");
2939 }
2940
2941 // Test where fails: then value is invalid
2942 try
2943 {
2944 const json element = R"(
2945 {
2946 "condition": { "run_rule": "is_downlevel_regulator" },
2947 "then": "foo",
2948 "else": [ { "run_rule": "configure_standard_regulator" } ]
2949 }
2950 )"_json;
2951 parseIf(element);
2952 ADD_FAILURE() << "Should not have reached this line.";
2953 }
2954 catch (const std::invalid_argument& e)
2955 {
2956 EXPECT_STREQ(e.what(), "Element is not an array");
2957 }
2958
2959 // Test where fails: else value is invalid
2960 try
2961 {
2962 const json element = R"(
2963 {
2964 "condition": { "run_rule": "is_downlevel_regulator" },
2965 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2966 "else": 1
2967 }
2968 )"_json;
2969 parseIf(element);
2970 ADD_FAILURE() << "Should not have reached this line.";
2971 }
2972 catch (const std::invalid_argument& e)
2973 {
2974 EXPECT_STREQ(e.what(), "Element is not an array");
2975 }
2976
2977 // Test where fails: Invalid property specified
2978 try
2979 {
2980 const json element = R"(
2981 {
2982 "condition": { "run_rule": "is_downlevel_regulator" },
2983 "then": [ { "run_rule": "configure_downlevel_regulator" } ],
2984 "foo": "bar"
2985 }
2986 )"_json;
2987 parseIf(element);
2988 ADD_FAILURE() << "Should not have reached this line.";
2989 }
2990 catch (const std::invalid_argument& e)
2991 {
2992 EXPECT_STREQ(e.what(), "Element contains an invalid property");
2993 }
2994
2995 // Test where fails: Element is not an object
2996 try
2997 {
2998 const json element = R"( [ "0xFF", "0x01" ] )"_json;
2999 parseIf(element);
3000 ADD_FAILURE() << "Should not have reached this line.";
3001 }
3002 catch (const std::invalid_argument& e)
3003 {
3004 EXPECT_STREQ(e.what(), "Element is not an object");
3005 }
3006}
3007
Bob King87ff9d72020-03-31 14:02:55 +08003008TEST(ConfigFileParserTests, ParseInt8)
3009{
3010 // Test where works: INT8_MIN
3011 {
3012 const json element = R"( -128 )"_json;
3013 int8_t value = parseInt8(element);
3014 EXPECT_EQ(value, -128);
3015 }
3016
3017 // Test where works: INT8_MAX
3018 {
3019 const json element = R"( 127 )"_json;
3020 int8_t value = parseInt8(element);
3021 EXPECT_EQ(value, 127);
3022 }
3023
3024 // Test where fails: Element is not an integer
3025 try
3026 {
3027 const json element = R"( 1.03 )"_json;
3028 parseInt8(element);
3029 ADD_FAILURE() << "Should not have reached this line.";
3030 }
3031 catch (const std::invalid_argument& e)
3032 {
3033 EXPECT_STREQ(e.what(), "Element is not an integer");
3034 }
3035
3036 // Test where fails: Value < INT8_MIN
3037 try
3038 {
3039 const json element = R"( -129 )"_json;
3040 parseInt8(element);
3041 ADD_FAILURE() << "Should not have reached this line.";
3042 }
3043 catch (const std::invalid_argument& e)
3044 {
3045 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
3046 }
3047
3048 // Test where fails: Value > INT8_MAX
3049 try
3050 {
3051 const json element = R"( 128 )"_json;
3052 parseInt8(element);
3053 ADD_FAILURE() << "Should not have reached this line.";
3054 }
3055 catch (const std::invalid_argument& e)
3056 {
3057 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
3058 }
3059}
3060
Bob Kinga76898f2020-10-13 15:08:33 +08003061TEST(ConfigFileParserTests, ParseInventoryPath)
3062{
3063 // Test where works: Inventory path has a leading '/'
3064 {
3065 const json element = "/system/chassis/motherboard/cpu3";
3066 std::string value = parseInventoryPath(element);
3067 EXPECT_EQ(
3068 value,
3069 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu3");
3070 }
3071
3072 // Test where works: Inventory path does not have a leading '/'
3073 {
3074 const json element = "system/chassis/motherboard/cpu1";
3075 std::string value = parseInventoryPath(element);
3076 EXPECT_EQ(
3077 value,
3078 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1");
3079 }
3080
3081 // Test where fails: JSON element is not a string
3082 try
3083 {
3084 const json element = R"( { "foo": "bar" } )"_json;
3085 parseInventoryPath(element);
3086 ADD_FAILURE() << "Should not have reached this line.";
3087 }
3088 catch (const std::invalid_argument& e)
3089 {
3090 EXPECT_STREQ(e.what(), "Element is not a string");
3091 }
3092
3093 // Test where fails: JSON element contains an empty string
3094 try
3095 {
3096 const json element = "";
3097 parseInventoryPath(element);
3098 ADD_FAILURE() << "Should not have reached this line.";
3099 }
3100 catch (const std::invalid_argument& e)
3101 {
3102 EXPECT_STREQ(e.what(), "Element contains an empty string");
3103 }
3104}
3105
Bob Kingf1b58dc2020-04-14 14:53:10 +08003106TEST(ConfigFileParserTests, ParseNot)
3107{
3108 // Test where works
3109 {
3110 const json element = R"(
3111 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }
3112 )"_json;
3113 std::unique_ptr<NotAction> action = parseNot(element);
3114 EXPECT_NE(action->getAction().get(), nullptr);
3115 }
3116
3117 // Test where fails: Element is not an object
3118 try
3119 {
3120 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3121 parseNot(element);
3122 ADD_FAILURE() << "Should not have reached this line.";
3123 }
3124 catch (const std::invalid_argument& e)
3125 {
3126 EXPECT_STREQ(e.what(), "Element is not an object");
3127 }
3128}
3129
Bob King0b51a9b2020-04-15 13:24:18 +08003130TEST(ConfigFileParserTests, ParseOr)
3131{
3132 // Test where works: Element is an array with 2 actions
3133 {
3134 const json element = R"(
3135 [
3136 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } },
3137 { "i2c_compare_byte": { "register": "0xA1", "value": "0x00" } }
3138 ]
3139 )"_json;
3140 std::unique_ptr<OrAction> action = parseOr(element);
3141 EXPECT_EQ(action->getActions().size(), 2);
3142 }
3143
3144 // Test where fails: Element is an array with 1 action
3145 try
3146 {
3147 const json element = R"(
3148 [
3149 { "i2c_compare_byte": { "register": "0xA0", "value": "0x00" } }
3150 ]
3151 )"_json;
3152 parseOr(element);
3153 ADD_FAILURE() << "Should not have reached this line.";
3154 }
3155 catch (const std::invalid_argument& e)
3156 {
3157 EXPECT_STREQ(e.what(), "Array must contain two or more actions");
3158 }
3159
3160 // Test where fails: Element is not an array
3161 try
3162 {
3163 const json element = R"(
3164 {
3165 "foo": "bar"
3166 }
3167 )"_json;
3168 parseOr(element);
3169 ADD_FAILURE() << "Should not have reached this line.";
3170 }
3171 catch (const std::invalid_argument& e)
3172 {
3173 EXPECT_STREQ(e.what(), "Element is not an array");
3174 }
3175}
3176
Bob King84614882020-04-30 13:13:48 +08003177TEST(ConfigFileParserTests, ParsePMBusReadSensor)
3178{
3179 // Test where works: Only required properties specified
3180 {
3181 const json element = R"(
3182 {
3183 "type": "iout",
3184 "command": "0x8C",
3185 "format": "linear_11"
3186 }
3187 )"_json;
3188 std::unique_ptr<PMBusReadSensorAction> action =
3189 parsePMBusReadSensor(element);
3190 EXPECT_EQ(action->getType(), pmbus_utils::SensorValueType::iout);
3191 EXPECT_EQ(action->getCommand(), 0x8C);
3192 EXPECT_EQ(action->getFormat(),
3193 pmbus_utils::SensorDataFormat::linear_11);
3194 EXPECT_EQ(action->getExponent().has_value(), false);
3195 }
3196
3197 // Test where works: All properties specified
3198 {
3199 const json element = R"(
3200 {
3201 "type": "temperature",
3202 "command": "0x7A",
3203 "format": "linear_16",
3204 "exponent": -8
3205 }
3206 )"_json;
3207 std::unique_ptr<PMBusReadSensorAction> action =
3208 parsePMBusReadSensor(element);
3209 EXPECT_EQ(action->getType(), pmbus_utils::SensorValueType::temperature);
3210 EXPECT_EQ(action->getCommand(), 0x7A);
3211 EXPECT_EQ(action->getFormat(),
3212 pmbus_utils::SensorDataFormat::linear_16);
3213 EXPECT_EQ(action->getExponent().has_value(), true);
3214 EXPECT_EQ(action->getExponent().value(), -8);
3215 }
3216
3217 // Test where fails: Element is not an object
3218 try
3219 {
3220 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3221 parsePMBusReadSensor(element);
3222 ADD_FAILURE() << "Should not have reached this line.";
3223 }
3224 catch (const std::invalid_argument& e)
3225 {
3226 EXPECT_STREQ(e.what(), "Element is not an object");
3227 }
3228
3229 // Test where fails: Invalid property specified
3230 try
3231 {
3232 const json element = R"(
3233 {
3234 "type": "iout",
3235 "command": "0x8C",
3236 "format": "linear_11",
3237 "foo": 1
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(), "Element contains an invalid property");
3246 }
3247
3248 // Test where fails: Required type property not specified
3249 try
3250 {
3251 const json element = R"(
3252 {
3253 "command": "0x8C",
3254 "format": "linear_11"
3255 }
3256 )"_json;
3257 parsePMBusReadSensor(element);
3258 ADD_FAILURE() << "Should not have reached this line.";
3259 }
3260 catch (const std::invalid_argument& e)
3261 {
3262 EXPECT_STREQ(e.what(), "Required property missing: type");
3263 }
3264
3265 // Test where fails: Required command property not specified
3266 try
3267 {
3268 const json element = R"(
3269 {
3270 "type": "iout",
3271 "format": "linear_11"
3272 }
3273 )"_json;
3274 parsePMBusReadSensor(element);
3275 ADD_FAILURE() << "Should not have reached this line.";
3276 }
3277 catch (const std::invalid_argument& e)
3278 {
3279 EXPECT_STREQ(e.what(), "Required property missing: command");
3280 }
3281
3282 // Test where fails: Required format property not specified
3283 try
3284 {
3285 const json element = R"(
3286 {
3287 "type": "iout",
3288 "command": "0x8C"
3289 }
3290 )"_json;
3291 parsePMBusReadSensor(element);
3292 ADD_FAILURE() << "Should not have reached this line.";
3293 }
3294 catch (const std::invalid_argument& e)
3295 {
3296 EXPECT_STREQ(e.what(), "Required property missing: format");
3297 }
3298
3299 // Test where fails: type value is invalid
3300 try
3301 {
3302 const json element = R"(
3303 {
3304 "type": 1,
3305 "command": "0x7A",
3306 "format": "linear_16"
3307 }
3308 )"_json;
3309 parsePMBusReadSensor(element);
3310 ADD_FAILURE() << "Should not have reached this line.";
3311 }
3312 catch (const std::invalid_argument& e)
3313 {
3314 EXPECT_STREQ(e.what(), "Element is not a string");
3315 }
3316
3317 // Test where fails: command value is invalid
3318 try
3319 {
3320 const json element = R"(
3321 {
3322 "type": "temperature",
3323 "command": 0,
3324 "format": "linear_16"
3325 }
3326 )"_json;
3327 parsePMBusReadSensor(element);
3328 ADD_FAILURE() << "Should not have reached this line.";
3329 }
3330 catch (const std::invalid_argument& e)
3331 {
3332 EXPECT_STREQ(e.what(), "Element is not a string");
3333 }
3334
3335 // Test where fails: format value is invalid
3336 try
3337 {
3338 const json element = R"(
3339 {
3340 "type": "temperature",
3341 "command": "0x7A",
3342 "format": 1
3343 }
3344 )"_json;
3345 parsePMBusReadSensor(element);
3346 ADD_FAILURE() << "Should not have reached this line.";
3347 }
3348 catch (const std::invalid_argument& e)
3349 {
3350 EXPECT_STREQ(e.what(), "Element is not a string");
3351 }
3352
3353 // Test where fails: exponent value is invalid
3354 try
3355 {
3356 const json element = R"(
3357 {
3358 "type": "temperature",
3359 "command": "0x7A",
3360 "format": "linear_16",
3361 "exponent": 1.3
3362 }
3363 )"_json;
3364 parsePMBusReadSensor(element);
3365 ADD_FAILURE() << "Should not have reached this line.";
3366 }
3367 catch (const std::invalid_argument& e)
3368 {
3369 EXPECT_STREQ(e.what(), "Element is not an integer");
3370 }
3371}
3372
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003373TEST(ConfigFileParserTests, ParsePMBusWriteVoutCommand)
3374{
3375 // Test where works: Only required properties specified
3376 {
3377 const json element = R"(
3378 {
3379 "format": "linear"
3380 }
3381 )"_json;
3382 std::unique_ptr<PMBusWriteVoutCommandAction> action =
3383 parsePMBusWriteVoutCommand(element);
3384 EXPECT_EQ(action->getVolts().has_value(), false);
3385 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear);
3386 EXPECT_EQ(action->getExponent().has_value(), false);
3387 EXPECT_EQ(action->isVerified(), false);
3388 }
3389
3390 // Test where works: All properties specified
3391 {
3392 const json element = R"(
3393 {
3394 "volts": 1.03,
3395 "format": "linear",
3396 "exponent": -8,
3397 "is_verified": true
3398 }
3399 )"_json;
3400 std::unique_ptr<PMBusWriteVoutCommandAction> action =
3401 parsePMBusWriteVoutCommand(element);
3402 EXPECT_EQ(action->getVolts().has_value(), true);
3403 EXPECT_EQ(action->getVolts().value(), 1.03);
3404 EXPECT_EQ(action->getFormat(), pmbus_utils::VoutDataFormat::linear);
3405 EXPECT_EQ(action->getExponent().has_value(), true);
3406 EXPECT_EQ(action->getExponent().value(), -8);
3407 EXPECT_EQ(action->isVerified(), true);
3408 }
3409
3410 // Test where fails: Element is not an object
3411 try
3412 {
3413 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3414 parsePMBusWriteVoutCommand(element);
3415 ADD_FAILURE() << "Should not have reached this line.";
3416 }
3417 catch (const std::invalid_argument& e)
3418 {
3419 EXPECT_STREQ(e.what(), "Element is not an object");
3420 }
3421
3422 // Test where fails: volts value is invalid
3423 try
3424 {
3425 const json element = R"(
3426 {
3427 "volts": "foo",
3428 "format": "linear"
3429 }
3430 )"_json;
3431 parsePMBusWriteVoutCommand(element);
3432 ADD_FAILURE() << "Should not have reached this line.";
3433 }
3434 catch (const std::invalid_argument& e)
3435 {
3436 EXPECT_STREQ(e.what(), "Element is not a number");
3437 }
3438
3439 // Test where fails: Required format property not specified
3440 try
3441 {
3442 const json element = R"(
3443 {
3444 "volts": 1.03,
3445 "is_verified": true
3446 }
3447 )"_json;
3448 parsePMBusWriteVoutCommand(element);
3449 ADD_FAILURE() << "Should not have reached this line.";
3450 }
3451 catch (const std::invalid_argument& e)
3452 {
3453 EXPECT_STREQ(e.what(), "Required property missing: format");
3454 }
3455
3456 // Test where fails: format value is invalid
3457 try
3458 {
3459 const json element = R"(
3460 {
3461 "format": "linear_11"
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(), "Invalid format value: linear_11");
3470 }
3471
3472 // Test where fails: exponent value is invalid
3473 try
3474 {
3475 const json element = R"(
3476 {
3477 "format": "linear",
3478 "exponent": 1.3
3479 }
3480 )"_json;
3481 parsePMBusWriteVoutCommand(element);
3482 ADD_FAILURE() << "Should not have reached this line.";
3483 }
3484 catch (const std::invalid_argument& e)
3485 {
3486 EXPECT_STREQ(e.what(), "Element is not an integer");
3487 }
3488
3489 // Test where fails: is_verified value is invalid
3490 try
3491 {
3492 const json element = R"(
3493 {
3494 "format": "linear",
3495 "is_verified": "true"
3496 }
3497 )"_json;
3498 parsePMBusWriteVoutCommand(element);
3499 ADD_FAILURE() << "Should not have reached this line.";
3500 }
3501 catch (const std::invalid_argument& e)
3502 {
3503 EXPECT_STREQ(e.what(), "Element is not a boolean");
3504 }
3505
3506 // Test where fails: Invalid property specified
3507 try
3508 {
3509 const json element = R"(
3510 {
3511 "format": "linear",
3512 "foo": "bar"
3513 }
3514 )"_json;
3515 parsePMBusWriteVoutCommand(element);
3516 ADD_FAILURE() << "Should not have reached this line.";
3517 }
3518 catch (const std::invalid_argument& e)
3519 {
3520 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3521 }
3522}
3523
Bob King2aafb1c2020-04-16 15:24:32 +08003524TEST(ConfigFileParserTests, ParsePresenceDetection)
3525{
3526 // Test where works: actions property specified
3527 {
3528 const json element = R"(
3529 {
3530 "actions": [
3531 { "run_rule": "read_sensors_rule" }
3532 ]
3533 }
3534 )"_json;
3535 std::unique_ptr<PresenceDetection> presenceDetection =
3536 parsePresenceDetection(element);
3537 EXPECT_EQ(presenceDetection->getActions().size(), 1);
3538 }
3539
3540 // Test where works: rule_id property specified
3541 {
3542 const json element = R"(
3543 {
3544 "comments": [ "comments property" ],
3545 "rule_id": "set_voltage_rule"
3546 }
3547 )"_json;
3548 std::unique_ptr<PresenceDetection> presenceDetection =
3549 parsePresenceDetection(element);
3550 EXPECT_EQ(presenceDetection->getActions().size(), 1);
3551 }
3552
3553 // Test where fails: actions object is invalid
3554 try
3555 {
3556 const json element = R"(
3557 {
3558 "actions": 1
3559 }
3560 )"_json;
3561 parsePresenceDetection(element);
3562 ADD_FAILURE() << "Should not have reached this line.";
3563 }
3564 catch (const std::invalid_argument& e)
3565 {
3566 EXPECT_STREQ(e.what(), "Element is not an array");
3567 }
3568
3569 // Test where fails: rule_id value is invalid
3570 try
3571 {
3572 const json element = R"(
3573 {
3574 "rule_id": 1
3575 }
3576 )"_json;
3577 parsePresenceDetection(element);
3578 ADD_FAILURE() << "Should not have reached this line.";
3579 }
3580 catch (const std::invalid_argument& e)
3581 {
3582 EXPECT_STREQ(e.what(), "Element is not a string");
3583 }
3584
3585 // Test where fails: Required actions or rule_id property not specified
3586 try
3587 {
3588 const json element = R"(
3589 {
3590 "comments": [ "comments property" ]
3591 }
3592 )"_json;
3593 parsePresenceDetection(element);
3594 ADD_FAILURE() << "Should not have reached this line.";
3595 }
3596 catch (const std::invalid_argument& e)
3597 {
3598 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3599 "either rule_id or actions");
3600 }
3601
3602 // Test where fails: Required actions or rule_id property both specified
3603 try
3604 {
3605 const json element = R"(
3606 {
3607 "rule_id": "set_voltage_rule",
3608 "actions": [
3609 { "run_rule": "read_sensors_rule" }
3610 ]
3611 }
3612 )"_json;
3613 parsePresenceDetection(element);
3614 ADD_FAILURE() << "Should not have reached this line.";
3615 }
3616 catch (const std::invalid_argument& e)
3617 {
3618 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
3619 "either rule_id or actions");
3620 }
3621
3622 // Test where fails: Element is not an object
3623 try
3624 {
3625 const json element = R"( [ "foo", "bar" ] )"_json;
3626 parsePresenceDetection(element);
3627 ADD_FAILURE() << "Should not have reached this line.";
3628 }
3629 catch (const std::invalid_argument& e)
3630 {
3631 EXPECT_STREQ(e.what(), "Element is not an object");
3632 }
3633
3634 // Test where fails: Invalid property specified
3635 try
3636 {
3637 const json element = R"(
3638 {
3639 "foo": "bar",
3640 "actions": [
3641 { "run_rule": "read_sensors_rule" }
3642 ]
3643 }
3644 )"_json;
3645 parsePresenceDetection(element);
3646 ADD_FAILURE() << "Should not have reached this line.";
3647 }
3648 catch (const std::invalid_argument& e)
3649 {
3650 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3651 }
3652}
3653
Bob Kinga2f2a0d2020-04-09 13:32:14 +08003654TEST(ConfigFileParserTests, ParseRail)
3655{
3656 // Test where works: Only required properties specified
3657 {
3658 const json element = R"(
3659 {
3660 "id": "vdd"
3661 }
3662 )"_json;
3663 std::unique_ptr<Rail> rail = parseRail(element);
3664 EXPECT_EQ(rail->getID(), "vdd");
3665 EXPECT_EQ(rail->getConfiguration(), nullptr);
3666 EXPECT_EQ(rail->getSensorMonitoring(), nullptr);
3667 }
3668
3669 // Test where works: All properties specified
3670 {
3671 const json element = R"(
3672 {
3673 "comments": [ "comments property" ],
3674 "id": "vdd",
3675 "configuration": {
3676 "volts": 1.1,
3677 "actions": [
3678 {
3679 "pmbus_write_vout_command": {
3680 "format": "linear"
3681 }
3682 }
3683 ]
3684 },
3685 "sensor_monitoring": {
3686 "actions": [
3687 { "run_rule": "read_sensors_rule" }
3688 ]
3689 }
3690 }
3691 )"_json;
3692 std::unique_ptr<Rail> rail = parseRail(element);
3693 EXPECT_EQ(rail->getID(), "vdd");
3694 EXPECT_NE(rail->getConfiguration(), nullptr);
3695 EXPECT_NE(rail->getSensorMonitoring(), nullptr);
3696 }
3697
3698 // Test where fails: id property not specified
3699 try
3700 {
3701 const json element = R"(
3702 {
3703 "configuration": {
3704 "volts": 1.1,
3705 "actions": [
3706 {
3707 "pmbus_write_vout_command": {
3708 "format": "linear"
3709 }
3710 }
3711 ]
3712 }
3713 }
3714 )"_json;
3715 parseRail(element);
3716 ADD_FAILURE() << "Should not have reached this line.";
3717 }
3718 catch (const std::invalid_argument& e)
3719 {
3720 EXPECT_STREQ(e.what(), "Required property missing: id");
3721 }
3722
3723 // Test where fails: id property is invalid
3724 try
3725 {
3726 const json element = R"(
3727 {
3728 "id": "",
3729 "configuration": {
3730 "volts": 1.1,
3731 "actions": [
3732 {
3733 "pmbus_write_vout_command": {
3734 "format": "linear"
3735 }
3736 }
3737 ]
3738 }
3739 }
3740 )"_json;
3741 parseRail(element);
3742 ADD_FAILURE() << "Should not have reached this line.";
3743 }
3744 catch (const std::invalid_argument& e)
3745 {
3746 EXPECT_STREQ(e.what(), "Element contains an empty string");
3747 }
3748
3749 // Test where fails: Element is not an object
3750 try
3751 {
3752 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3753 parseRail(element);
3754 ADD_FAILURE() << "Should not have reached this line.";
3755 }
3756 catch (const std::invalid_argument& e)
3757 {
3758 EXPECT_STREQ(e.what(), "Element is not an object");
3759 }
3760
3761 // Test where fails: configuration value is invalid
3762 try
3763 {
3764 const json element = R"(
3765 {
3766 "id": "vdd",
3767 "configuration": "config"
3768 }
3769 )"_json;
3770 parseRail(element);
3771 ADD_FAILURE() << "Should not have reached this line.";
3772 }
3773 catch (const std::invalid_argument& e)
3774 {
3775 EXPECT_STREQ(e.what(), "Element is not an object");
3776 }
3777
3778 // Test where fails: sensor_monitoring value is invalid
3779 try
3780 {
3781 const json element = R"(
3782 {
3783 "comments": [ "comments property" ],
3784 "id": "vdd",
3785 "configuration": {
3786 "volts": 1.1,
3787 "actions": [
3788 {
3789 "pmbus_write_vout_command": {
3790 "format": "linear"
3791 }
3792 }
3793 ]
3794 },
3795 "sensor_monitoring": 1
3796 }
3797 )"_json;
3798 parseRail(element);
3799 ADD_FAILURE() << "Should not have reached this line.";
3800 }
3801 catch (const std::invalid_argument& e)
3802 {
3803 EXPECT_STREQ(e.what(), "Element is not an object");
3804 }
3805
3806 // Test where fails: Invalid property specified
3807 try
3808 {
3809 const json element = R"(
3810 {
3811 "id": "vdd",
3812 "foo" : true
3813 }
3814 )"_json;
3815 parseRail(element);
3816 ADD_FAILURE() << "Should not have reached this line.";
3817 }
3818 catch (const std::invalid_argument& e)
3819 {
3820 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3821 }
3822}
3823
3824TEST(ConfigFileParserTests, ParseRailArray)
3825{
3826 // Test where works
3827 {
3828 const json element = R"(
3829 [
3830 { "id": "vdd" },
3831 { "id": "vio" }
3832 ]
3833 )"_json;
3834 std::vector<std::unique_ptr<Rail>> rails = parseRailArray(element);
3835 EXPECT_EQ(rails.size(), 2);
3836 EXPECT_EQ(rails[0]->getID(), "vdd");
3837 EXPECT_EQ(rails[1]->getID(), "vio");
3838 }
3839
3840 // Test where fails: Element is not an array
3841 try
3842 {
3843 const json element = R"(
3844 {
3845 "foo": "bar"
3846 }
3847 )"_json;
3848 parseRailArray(element);
3849 ADD_FAILURE() << "Should not have reached this line.";
3850 }
3851 catch (const std::invalid_argument& e)
3852 {
3853 EXPECT_STREQ(e.what(), "Element is not an array");
3854 }
3855}
3856
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003857TEST(ConfigFileParserTests, ParseRoot)
3858{
3859 // Test where works: Only required properties specified
3860 {
3861 const json element = R"(
3862 {
3863 "chassis": [
3864 { "number": 1 }
3865 ]
3866 }
3867 )"_json;
3868 std::vector<std::unique_ptr<Rule>> rules{};
3869 std::vector<std::unique_ptr<Chassis>> chassis{};
3870 std::tie(rules, chassis) = parseRoot(element);
3871 EXPECT_EQ(rules.size(), 0);
Bob King0e701132020-04-03 21:50:31 +08003872 EXPECT_EQ(chassis.size(), 1);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003873 }
3874
3875 // Test where works: All properties specified
3876 {
3877 const json element = R"(
3878 {
3879 "comments": [ "Config file for a FooBar one-chassis system" ],
3880 "rules": [
3881 {
3882 "id": "set_voltage_rule",
3883 "actions": [
3884 { "pmbus_write_vout_command": { "format": "linear" } }
3885 ]
3886 }
3887 ],
3888 "chassis": [
3889 { "number": 1 },
3890 { "number": 3 }
3891 ]
3892 }
3893 )"_json;
3894 std::vector<std::unique_ptr<Rule>> rules{};
3895 std::vector<std::unique_ptr<Chassis>> chassis{};
3896 std::tie(rules, chassis) = parseRoot(element);
3897 EXPECT_EQ(rules.size(), 1);
Bob King0e701132020-04-03 21:50:31 +08003898 EXPECT_EQ(chassis.size(), 2);
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05003899 }
3900
3901 // Test where fails: Element is not an object
3902 try
3903 {
3904 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3905 parseRoot(element);
3906 ADD_FAILURE() << "Should not have reached this line.";
3907 }
3908 catch (const std::invalid_argument& e)
3909 {
3910 EXPECT_STREQ(e.what(), "Element is not an object");
3911 }
3912
3913 // Test where fails: chassis property not specified
3914 try
3915 {
3916 const json element = R"(
3917 {
3918 "rules": [
3919 {
3920 "id": "set_voltage_rule",
3921 "actions": [
3922 { "pmbus_write_vout_command": { "format": "linear" } }
3923 ]
3924 }
3925 ]
3926 }
3927 )"_json;
3928 parseRoot(element);
3929 ADD_FAILURE() << "Should not have reached this line.";
3930 }
3931 catch (const std::invalid_argument& e)
3932 {
3933 EXPECT_STREQ(e.what(), "Required property missing: chassis");
3934 }
3935
3936 // Test where fails: Invalid property specified
3937 try
3938 {
3939 const json element = R"(
3940 {
3941 "remarks": [ "Config file for a FooBar one-chassis system" ],
3942 "chassis": [
3943 { "number": 1 }
3944 ]
3945 }
3946 )"_json;
3947 parseRoot(element);
3948 ADD_FAILURE() << "Should not have reached this line.";
3949 }
3950 catch (const std::invalid_argument& e)
3951 {
3952 EXPECT_STREQ(e.what(), "Element contains an invalid property");
3953 }
3954}
3955
3956TEST(ConfigFileParserTests, ParseRule)
3957{
3958 // Test where works: comments property specified
3959 {
3960 const json element = R"(
3961 {
3962 "comments": [ "Set voltage rule" ],
3963 "id": "set_voltage_rule",
3964 "actions": [
3965 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
3966 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } }
3967 ]
3968 }
3969 )"_json;
3970 std::unique_ptr<Rule> rule = parseRule(element);
3971 EXPECT_EQ(rule->getID(), "set_voltage_rule");
3972 EXPECT_EQ(rule->getActions().size(), 2);
3973 }
3974
3975 // Test where works: comments property not specified
3976 {
3977 const json element = R"(
3978 {
3979 "id": "set_voltage_rule",
3980 "actions": [
3981 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
3982 { "pmbus_write_vout_command": { "volts": 1.03, "format": "linear" } },
3983 { "pmbus_write_vout_command": { "volts": 1.05, "format": "linear" } }
3984 ]
3985 }
3986 )"_json;
3987 std::unique_ptr<Rule> rule = parseRule(element);
3988 EXPECT_EQ(rule->getID(), "set_voltage_rule");
3989 EXPECT_EQ(rule->getActions().size(), 3);
3990 }
3991
3992 // Test where fails: Element is not an object
3993 try
3994 {
3995 const json element = R"( [ "0xFF", "0x01" ] )"_json;
3996 parseRule(element);
3997 ADD_FAILURE() << "Should not have reached this line.";
3998 }
3999 catch (const std::invalid_argument& e)
4000 {
4001 EXPECT_STREQ(e.what(), "Element is not an object");
4002 }
4003
4004 // Test where fails: id property not specified
4005 try
4006 {
4007 const json element = R"(
4008 {
4009 "actions": [
4010 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
4011 ]
4012 }
4013 )"_json;
4014 parseRule(element);
4015 ADD_FAILURE() << "Should not have reached this line.";
4016 }
4017 catch (const std::invalid_argument& e)
4018 {
4019 EXPECT_STREQ(e.what(), "Required property missing: id");
4020 }
4021
4022 // Test where fails: id property is invalid
4023 try
4024 {
4025 const json element = R"(
4026 {
4027 "id": "",
4028 "actions": [
4029 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
4030 ]
4031 }
4032 )"_json;
4033 parseRule(element);
4034 ADD_FAILURE() << "Should not have reached this line.";
4035 }
4036 catch (const std::invalid_argument& e)
4037 {
4038 EXPECT_STREQ(e.what(), "Element contains an empty string");
4039 }
4040
4041 // Test where fails: actions property not specified
4042 try
4043 {
4044 const json element = R"(
4045 {
4046 "comments": [ "Set voltage rule" ],
4047 "id": "set_voltage_rule"
4048 }
4049 )"_json;
4050 parseRule(element);
4051 ADD_FAILURE() << "Should not have reached this line.";
4052 }
4053 catch (const std::invalid_argument& e)
4054 {
4055 EXPECT_STREQ(e.what(), "Required property missing: actions");
4056 }
4057
4058 // Test where fails: actions property is invalid
4059 try
4060 {
4061 const json element = R"(
4062 {
4063 "id": "set_voltage_rule",
4064 "actions": true
4065 }
4066 )"_json;
4067 parseRule(element);
4068 ADD_FAILURE() << "Should not have reached this line.";
4069 }
4070 catch (const std::invalid_argument& e)
4071 {
4072 EXPECT_STREQ(e.what(), "Element is not an array");
4073 }
4074
4075 // Test where fails: Invalid property specified
4076 try
4077 {
4078 const json element = R"(
4079 {
4080 "remarks": [ "Set voltage rule" ],
4081 "id": "set_voltage_rule",
4082 "actions": [
4083 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
4084 ]
4085 }
4086 )"_json;
4087 parseRule(element);
4088 ADD_FAILURE() << "Should not have reached this line.";
4089 }
4090 catch (const std::invalid_argument& e)
4091 {
4092 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4093 }
4094}
4095
4096TEST(ConfigFileParserTests, ParseRuleArray)
4097{
4098 // Test where works
4099 {
4100 const json element = R"(
4101 [
4102 {
4103 "id": "set_voltage_rule1",
4104 "actions": [
4105 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } }
4106 ]
4107 },
4108 {
4109 "id": "set_voltage_rule2",
4110 "actions": [
4111 { "pmbus_write_vout_command": { "volts": 1.01, "format": "linear" } },
4112 { "pmbus_write_vout_command": { "volts": 1.11, "format": "linear" } }
4113 ]
4114 }
4115 ]
4116 )"_json;
4117 std::vector<std::unique_ptr<Rule>> rules = parseRuleArray(element);
4118 EXPECT_EQ(rules.size(), 2);
4119 EXPECT_EQ(rules[0]->getID(), "set_voltage_rule1");
4120 EXPECT_EQ(rules[0]->getActions().size(), 1);
4121 EXPECT_EQ(rules[1]->getID(), "set_voltage_rule2");
4122 EXPECT_EQ(rules[1]->getActions().size(), 2);
4123 }
4124
4125 // Test where fails: Element is not an array
4126 try
4127 {
4128 const json element = R"( { "id": "set_voltage_rule" } )"_json;
4129 parseRuleArray(element);
4130 ADD_FAILURE() << "Should not have reached this line.";
4131 }
4132 catch (const std::invalid_argument& e)
4133 {
4134 EXPECT_STREQ(e.what(), "Element is not an array");
4135 }
4136}
4137
Bob King33e7eaa2020-04-01 18:09:34 +08004138TEST(ConfigFileParserTests, ParseRuleIDOrActionsProperty)
4139{
4140 // Test where works: actions specified
4141 {
4142 const json element = R"(
4143 {
4144 "actions": [
4145 { "pmbus_write_vout_command": { "format": "linear" } },
4146 { "run_rule": "set_voltage_rule" }
4147 ]
4148 }
4149 )"_json;
4150 std::vector<std::unique_ptr<Action>> actions =
4151 parseRuleIDOrActionsProperty(element);
4152 EXPECT_EQ(actions.size(), 2);
4153 }
4154
4155 // Test where works: rule_id specified
4156 {
4157 const json element = R"(
4158 {
4159 "rule_id": "set_voltage_rule"
4160 }
4161 )"_json;
4162 std::vector<std::unique_ptr<Action>> actions =
4163 parseRuleIDOrActionsProperty(element);
4164 EXPECT_EQ(actions.size(), 1);
4165 }
4166
4167 // Test where fails: Element is not an object
4168 try
4169 {
4170 const json element = R"( [ "foo", "bar" ] )"_json;
4171 parseRuleIDOrActionsProperty(element);
4172 ADD_FAILURE() << "Should not have reached this line.";
4173 }
4174 catch (const std::invalid_argument& e)
4175 {
4176 EXPECT_STREQ(e.what(), "Element is not an object");
4177 }
4178
4179 // Test where fails: rule_id is invalid
4180 try
4181 {
4182 const json element = R"(
4183 { "rule_id": 1 }
4184 )"_json;
4185 parseRuleIDOrActionsProperty(element);
4186 ADD_FAILURE() << "Should not have reached this line.";
4187 }
4188 catch (const std::invalid_argument& e)
4189 {
4190 EXPECT_STREQ(e.what(), "Element is not a string");
4191 }
4192
4193 // Test where fails: actions is invalid
4194 try
4195 {
4196 const json element = R"(
4197 { "actions": 1 }
4198 )"_json;
4199 parseRuleIDOrActionsProperty(element);
4200 ADD_FAILURE() << "Should not have reached this line.";
4201 }
4202 catch (const std::invalid_argument& e)
4203 {
4204 EXPECT_STREQ(e.what(), "Element is not an array");
4205 }
4206
4207 // Test where fails: Neither rule_id nor actions specified
4208 try
4209 {
4210 const json element = R"(
4211 {
4212 "volts": 1.03
4213 }
4214 )"_json;
4215 parseRuleIDOrActionsProperty(element);
4216 ADD_FAILURE() << "Should not have reached this line.";
4217 }
4218 catch (const std::invalid_argument& e)
4219 {
4220 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4221 "either rule_id or actions");
4222 }
4223
4224 // Test where fails: Both rule_id and actions specified
4225 try
4226 {
4227 const json element = R"(
4228 {
4229 "volts": 1.03,
4230 "rule_id": "set_voltage_rule",
4231 "actions": [
4232 {
4233 "pmbus_write_vout_command": {
4234 "format": "linear"
4235 }
4236 }
4237 ]
4238 }
4239 )"_json;
4240 parseRuleIDOrActionsProperty(element);
4241 ADD_FAILURE() << "Should not have reached this line.";
4242 }
4243 catch (const std::invalid_argument& e)
4244 {
4245 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4246 "either rule_id or actions");
4247 }
4248}
4249
Bob King315b0b62020-04-03 21:47:58 +08004250TEST(ConfigFileParserTests, ParseRunRule)
4251{
4252 // Test where works
4253 {
4254 const json element = "vdd_regulator";
4255 std::unique_ptr<RunRuleAction> action = parseRunRule(element);
4256 EXPECT_EQ(action->getRuleID(), "vdd_regulator");
4257 }
4258
4259 // Test where fails: Element is not a string
4260 try
4261 {
4262 const json element = 1;
4263 parseRunRule(element);
4264 ADD_FAILURE() << "Should not have reached this line.";
4265 }
4266 catch (const std::invalid_argument& e)
4267 {
4268 EXPECT_STREQ(e.what(), "Element is not a string");
4269 }
4270
4271 // Test where fails: Empty string
4272 try
4273 {
4274 const json element = "";
4275 parseRunRule(element);
4276 ADD_FAILURE() << "Should not have reached this line.";
4277 }
4278 catch (const std::invalid_argument& e)
4279 {
4280 EXPECT_STREQ(e.what(), "Element contains an empty string");
4281 }
4282}
4283
Bob King84614882020-04-30 13:13:48 +08004284TEST(ConfigFileParserTests, ParseSensorDataFormat)
4285{
4286 // Test where works: linear_11
4287 {
4288 const json element = "linear_11";
4289 pmbus_utils::SensorDataFormat value = parseSensorDataFormat(element);
4290 pmbus_utils::SensorDataFormat format =
4291 pmbus_utils::SensorDataFormat::linear_11;
4292 EXPECT_EQ(value, format);
4293 }
4294
4295 // Test where works: linear_16
4296 {
4297 const json element = "linear_16";
4298 pmbus_utils::SensorDataFormat value = parseSensorDataFormat(element);
4299 pmbus_utils::SensorDataFormat format =
4300 pmbus_utils::SensorDataFormat::linear_16;
4301 EXPECT_EQ(value, format);
4302 }
4303
4304 // Test where fails: Element is not a sensor data format
4305 try
4306 {
4307 const json element = "foo";
4308 parseSensorDataFormat(element);
4309 ADD_FAILURE() << "Should not have reached this line.";
4310 }
4311 catch (const std::invalid_argument& e)
4312 {
4313 EXPECT_STREQ(e.what(), "Element is not a sensor data format");
4314 }
4315
4316 // Test where fails: Element is not a string
4317 try
4318 {
4319 const json element = R"( { "foo": "bar" } )"_json;
4320 parseSensorDataFormat(element);
4321 ADD_FAILURE() << "Should not have reached this line.";
4322 }
4323 catch (const std::invalid_argument& e)
4324 {
4325 EXPECT_STREQ(e.what(), "Element is not a string");
4326 }
4327}
4328
Bob Kinga2f2a0d2020-04-09 13:32:14 +08004329TEST(ConfigFileParserTests, ParseSensorMonitoring)
4330{
4331 // Test where works: actions property specified
4332 {
4333 const json element = R"(
4334 {
4335 "actions": [
4336 { "run_rule": "read_sensors_rule" }
4337 ]
4338 }
4339 )"_json;
4340 std::unique_ptr<SensorMonitoring> sensorMonitoring =
4341 parseSensorMonitoring(element);
4342 EXPECT_EQ(sensorMonitoring->getActions().size(), 1);
4343 }
4344
4345 // Test where works: rule_id property specified
4346 {
4347 const json element = R"(
4348 {
4349 "comments": [ "comments property" ],
4350 "rule_id": "set_voltage_rule"
4351 }
4352 )"_json;
4353 std::unique_ptr<SensorMonitoring> sensorMonitoring =
4354 parseSensorMonitoring(element);
4355 EXPECT_EQ(sensorMonitoring->getActions().size(), 1);
4356 }
4357
4358 // Test where fails: actions object is invalid
4359 try
4360 {
4361 const json element = R"(
4362 {
4363 "actions": 1
4364 }
4365 )"_json;
4366 parseSensorMonitoring(element);
4367 ADD_FAILURE() << "Should not have reached this line.";
4368 }
4369 catch (const std::invalid_argument& e)
4370 {
4371 EXPECT_STREQ(e.what(), "Element is not an array");
4372 }
4373
4374 // Test where fails: rule_id value is invalid
4375 try
4376 {
4377 const json element = R"(
4378 {
4379 "rule_id": 1
4380 }
4381 )"_json;
4382 parseSensorMonitoring(element);
4383 ADD_FAILURE() << "Should not have reached this line.";
4384 }
4385 catch (const std::invalid_argument& e)
4386 {
4387 EXPECT_STREQ(e.what(), "Element is not a string");
4388 }
4389
4390 // Test where fails: Required actions or rule_id property not specified
4391 try
4392 {
4393 const json element = R"(
4394 {
4395 "comments": [ "comments property" ]
4396 }
4397 )"_json;
4398 parseSensorMonitoring(element);
4399 ADD_FAILURE() << "Should not have reached this line.";
4400 }
4401 catch (const std::invalid_argument& e)
4402 {
4403 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4404 "either rule_id or actions");
4405 }
4406
4407 // Test where fails: Required actions or rule_id property both specified
4408 try
4409 {
4410 const json element = R"(
4411 {
4412 "rule_id": "set_voltage_rule",
4413 "actions": [
4414 { "run_rule": "read_sensors_rule" }
4415 ]
4416 }
4417 )"_json;
4418 parseSensorMonitoring(element);
4419 ADD_FAILURE() << "Should not have reached this line.";
4420 }
4421 catch (const std::invalid_argument& e)
4422 {
4423 EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
4424 "either rule_id or actions");
4425 }
4426
4427 // Test where fails: Element is not an object
4428 try
4429 {
4430 const json element = R"( [ "foo", "bar" ] )"_json;
4431 parseSensorMonitoring(element);
4432 ADD_FAILURE() << "Should not have reached this line.";
4433 }
4434 catch (const std::invalid_argument& e)
4435 {
4436 EXPECT_STREQ(e.what(), "Element is not an object");
4437 }
4438
4439 // Test where fails: Invalid property specified
4440 try
4441 {
4442 const json element = R"(
4443 {
4444 "foo": "bar",
4445 "actions": [
4446 { "run_rule": "read_sensors_rule" }
4447 ]
4448 }
4449 )"_json;
4450 parseSensorMonitoring(element);
4451 ADD_FAILURE() << "Should not have reached this line.";
4452 }
4453 catch (const std::invalid_argument& e)
4454 {
4455 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4456 }
4457}
4458
Bob King84614882020-04-30 13:13:48 +08004459TEST(ConfigFileParserTests, ParseSensorValueType)
4460{
4461 // Test where works: iout
4462 {
4463 const json element = "iout";
4464 pmbus_utils::SensorValueType value = parseSensorValueType(element);
4465 pmbus_utils::SensorValueType type = pmbus_utils::SensorValueType::iout;
4466 EXPECT_EQ(value, type);
4467 }
4468
4469 // Test where works: iout_peak
4470 {
4471 const json element = "iout_peak";
4472 pmbus_utils::SensorValueType value = parseSensorValueType(element);
4473 pmbus_utils::SensorValueType type =
4474 pmbus_utils::SensorValueType::iout_peak;
4475 EXPECT_EQ(value, type);
4476 }
4477
4478 // Test where works: iout_valley
4479 {
4480 const json element = "iout_valley";
4481 pmbus_utils::SensorValueType value = parseSensorValueType(element);
4482 pmbus_utils::SensorValueType type =
4483 pmbus_utils::SensorValueType::iout_valley;
4484 EXPECT_EQ(value, type);
4485 }
4486
4487 // Test where works: pout
4488 {
4489 const json element = "pout";
4490 pmbus_utils::SensorValueType value = parseSensorValueType(element);
4491 pmbus_utils::SensorValueType type = pmbus_utils::SensorValueType::pout;
4492 EXPECT_EQ(value, type);
4493 }
4494
4495 // Test where works: temperature
4496 {
4497 const json element = "temperature";
4498 pmbus_utils::SensorValueType value = parseSensorValueType(element);
4499 pmbus_utils::SensorValueType type =
4500 pmbus_utils::SensorValueType::temperature;
4501 EXPECT_EQ(value, type);
4502 }
4503
4504 // Test where works: temperature_peak
4505 {
4506 const json element = "temperature_peak";
4507 pmbus_utils::SensorValueType value = parseSensorValueType(element);
4508 pmbus_utils::SensorValueType type =
4509 pmbus_utils::SensorValueType::temperature_peak;
4510 EXPECT_EQ(value, type);
4511 }
4512
4513 // Test where works: vout
4514 {
4515 const json element = "vout";
4516 pmbus_utils::SensorValueType value = parseSensorValueType(element);
4517 pmbus_utils::SensorValueType type = pmbus_utils::SensorValueType::vout;
4518 EXPECT_EQ(value, type);
4519 }
4520
4521 // Test where works: vout_peak
4522 {
4523 const json element = "vout_peak";
4524 pmbus_utils::SensorValueType value = parseSensorValueType(element);
4525 pmbus_utils::SensorValueType type =
4526 pmbus_utils::SensorValueType::vout_peak;
4527 EXPECT_EQ(value, type);
4528 }
4529
4530 // Test where works: vout_valley
4531 {
4532 const json element = "vout_valley";
4533 pmbus_utils::SensorValueType value = parseSensorValueType(element);
4534 pmbus_utils::SensorValueType type =
4535 pmbus_utils::SensorValueType::vout_valley;
4536 EXPECT_EQ(value, type);
4537 }
4538
4539 // Test where fails: Element is not a sensor value type
4540 try
4541 {
4542 const json element = "foo";
4543 parseSensorValueType(element);
4544 ADD_FAILURE() << "Should not have reached this line.";
4545 }
4546 catch (const std::invalid_argument& e)
4547 {
4548 EXPECT_STREQ(e.what(), "Element is not a sensor value type");
4549 }
4550
4551 // Test where fails: Element is not a string
4552 try
4553 {
4554 const json element = R"( { "foo": "bar" } )"_json;
4555 parseSensorValueType(element);
4556 ADD_FAILURE() << "Should not have reached this line.";
4557 }
4558 catch (const std::invalid_argument& e)
4559 {
4560 EXPECT_STREQ(e.what(), "Element is not a string");
4561 }
4562}
4563
Bob King18a68502020-04-17 14:19:56 +08004564TEST(ConfigFileParserTests, ParseSetDevice)
4565{
4566 // Test where works
4567 {
4568 const json element = "regulator1";
4569 std::unique_ptr<SetDeviceAction> action = parseSetDevice(element);
4570 EXPECT_EQ(action->getDeviceID(), "regulator1");
4571 }
4572
4573 // Test where fails: Element is not a string
4574 try
4575 {
4576 const json element = 1;
4577 parseSetDevice(element);
4578 ADD_FAILURE() << "Should not have reached this line.";
4579 }
4580 catch (const std::invalid_argument& e)
4581 {
4582 EXPECT_STREQ(e.what(), "Element is not a string");
4583 }
4584
4585 // Test where fails: Empty string
4586 try
4587 {
4588 const json element = "";
4589 parseSetDevice(element);
4590 ADD_FAILURE() << "Should not have reached this line.";
4591 }
4592 catch (const std::invalid_argument& e)
4593 {
4594 EXPECT_STREQ(e.what(), "Element contains an empty string");
4595 }
4596}
4597
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004598TEST(ConfigFileParserTests, ParseString)
4599{
4600 // Test where works: Empty string
4601 {
4602 const json element = "";
4603 std::string value = parseString(element, true);
4604 EXPECT_EQ(value, "");
4605 }
4606
4607 // Test where works: Non-empty string
4608 {
4609 const json element = "vdd_regulator";
4610 std::string value = parseString(element, false);
4611 EXPECT_EQ(value, "vdd_regulator");
4612 }
4613
4614 // Test where fails: Element is not a string
4615 try
4616 {
4617 const json element = R"( { "foo": "bar" } )"_json;
4618 parseString(element);
4619 ADD_FAILURE() << "Should not have reached this line.";
4620 }
4621 catch (const std::invalid_argument& e)
4622 {
4623 EXPECT_STREQ(e.what(), "Element is not a string");
4624 }
4625
4626 // Test where fails: Empty string
4627 try
4628 {
4629 const json element = "";
4630 parseString(element);
4631 ADD_FAILURE() << "Should not have reached this line.";
4632 }
4633 catch (const std::invalid_argument& e)
4634 {
4635 EXPECT_STREQ(e.what(), "Element contains an empty string");
4636 }
4637}
4638
Bob Kingf617f892020-03-30 19:03:35 +08004639TEST(ConfigFileParserTests, ParseUint8)
4640{
4641 // Test where works: 0
4642 {
4643 const json element = R"( 0 )"_json;
4644 uint8_t value = parseUint8(element);
4645 EXPECT_EQ(value, 0);
4646 }
4647
4648 // Test where works: UINT8_MAX
4649 {
4650 const json element = R"( 255 )"_json;
4651 uint8_t value = parseUint8(element);
4652 EXPECT_EQ(value, 255);
4653 }
4654
4655 // Test where fails: Element is not an integer
4656 try
4657 {
4658 const json element = R"( 1.03 )"_json;
4659 parseUint8(element);
4660 ADD_FAILURE() << "Should not have reached this line.";
4661 }
4662 catch (const std::invalid_argument& e)
4663 {
4664 EXPECT_STREQ(e.what(), "Element is not an integer");
4665 }
4666
4667 // Test where fails: Value < 0
4668 try
4669 {
4670 const json element = R"( -1 )"_json;
4671 parseUint8(element);
4672 ADD_FAILURE() << "Should not have reached this line.";
4673 }
4674 catch (const std::invalid_argument& e)
4675 {
4676 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
4677 }
4678
4679 // Test where fails: Value > UINT8_MAX
4680 try
4681 {
4682 const json element = R"( 256 )"_json;
4683 parseUint8(element);
4684 ADD_FAILURE() << "Should not have reached this line.";
4685 }
4686 catch (const std::invalid_argument& e)
4687 {
4688 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
4689 }
4690}
4691
Bob King0e701132020-04-03 21:50:31 +08004692TEST(ConfigFileParserTests, ParseUnsignedInteger)
4693{
4694 // Test where works: 1
4695 {
4696 const json element = R"( 1 )"_json;
4697 unsigned int value = parseUnsignedInteger(element);
4698 EXPECT_EQ(value, 1);
4699 }
4700
4701 // Test where fails: Element is not an integer
4702 try
4703 {
4704 const json element = R"( 1.5 )"_json;
4705 parseUnsignedInteger(element);
4706 ADD_FAILURE() << "Should not have reached this line.";
4707 }
4708 catch (const std::invalid_argument& e)
4709 {
4710 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
4711 }
4712
4713 // Test where fails: Value < 0
4714 try
4715 {
4716 const json element = R"( -1 )"_json;
4717 parseUnsignedInteger(element);
4718 ADD_FAILURE() << "Should not have reached this line.";
4719 }
4720 catch (const std::invalid_argument& e)
4721 {
4722 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
4723 }
4724}
4725
Bob King84614882020-04-30 13:13:48 +08004726TEST(ConfigFileParserTests, ParseVoutDataFormat)
4727{
4728 // Test where works: linear
4729 {
4730 const json element = "linear";
4731 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element);
4732 pmbus_utils::VoutDataFormat format =
4733 pmbus_utils::VoutDataFormat::linear;
4734 EXPECT_EQ(value, format);
4735 }
4736
4737 // Test where works: vid
4738 {
4739 const json element = "vid";
4740 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element);
4741 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::vid;
4742 EXPECT_EQ(value, format);
4743 }
4744
4745 // Test where works: direct
4746 {
4747 const json element = "direct";
4748 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element);
4749 pmbus_utils::VoutDataFormat format =
4750 pmbus_utils::VoutDataFormat::direct;
4751 EXPECT_EQ(value, format);
4752 }
4753
4754 // Test where works: ieee
4755 {
4756 const json element = "ieee";
4757 pmbus_utils::VoutDataFormat value = parseVoutDataFormat(element);
4758 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::ieee;
4759 EXPECT_EQ(value, format);
4760 }
4761
4762 // Test where fails: Element is not a vout data format
4763 try
4764 {
4765 const json element = "foo";
4766 parseVoutDataFormat(element);
4767 ADD_FAILURE() << "Should not have reached this line.";
4768 }
4769 catch (const std::invalid_argument& e)
4770 {
4771 EXPECT_STREQ(e.what(), "Element is not a vout data format");
4772 }
4773
4774 // Test where fails: Element is not a string
4775 try
4776 {
4777 const json element = R"( { "foo": "bar" } )"_json;
4778 parseVoutDataFormat(element);
4779 ADD_FAILURE() << "Should not have reached this line.";
4780 }
4781 catch (const std::invalid_argument& e)
4782 {
4783 EXPECT_STREQ(e.what(), "Element is not a string");
4784 }
4785}
4786
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05004787TEST(ConfigFileParserTests, VerifyIsArray)
4788{
4789 // Test where element is an array
4790 try
4791 {
4792 const json element = R"( [ "foo", "bar" ] )"_json;
4793 verifyIsArray(element);
4794 }
4795 catch (const std::exception& e)
4796 {
4797 ADD_FAILURE() << "Should not have caught exception.";
4798 }
4799
4800 // Test where element is not an array
4801 try
4802 {
4803 const json element = R"( { "foo": "bar" } )"_json;
4804 verifyIsArray(element);
4805 ADD_FAILURE() << "Should not have reached this line.";
4806 }
4807 catch (const std::invalid_argument& e)
4808 {
4809 EXPECT_STREQ(e.what(), "Element is not an array");
4810 }
4811}
4812
4813TEST(ConfigFileParserTests, VerifyIsObject)
4814{
4815 // Test where element is an object
4816 try
4817 {
4818 const json element = R"( { "foo": "bar" } )"_json;
4819 verifyIsObject(element);
4820 }
4821 catch (const std::exception& e)
4822 {
4823 ADD_FAILURE() << "Should not have caught exception.";
4824 }
4825
4826 // Test where element is not an object
4827 try
4828 {
4829 const json element = R"( [ "foo", "bar" ] )"_json;
4830 verifyIsObject(element);
4831 ADD_FAILURE() << "Should not have reached this line.";
4832 }
4833 catch (const std::invalid_argument& e)
4834 {
4835 EXPECT_STREQ(e.what(), "Element is not an object");
4836 }
4837}
4838
4839TEST(ConfigFileParserTests, VerifyPropertyCount)
4840{
4841 // Test where element has expected number of properties
4842 try
4843 {
4844 const json element = R"(
4845 {
4846 "comments": [ "Set voltage rule" ],
4847 "id": "set_voltage_rule"
4848 }
4849 )"_json;
4850 verifyPropertyCount(element, 2);
4851 }
4852 catch (const std::exception& e)
4853 {
4854 ADD_FAILURE() << "Should not have caught exception.";
4855 }
4856
4857 // Test where element has unexpected number of properties
4858 try
4859 {
4860 const json element = R"(
4861 {
4862 "comments": [ "Set voltage rule" ],
4863 "id": "set_voltage_rule",
4864 "foo": 1.3
4865 }
4866 )"_json;
4867 verifyPropertyCount(element, 2);
4868 ADD_FAILURE() << "Should not have reached this line.";
4869 }
4870 catch (const std::invalid_argument& e)
4871 {
4872 EXPECT_STREQ(e.what(), "Element contains an invalid property");
4873 }
4874}