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