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