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