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