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