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