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