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