1 /**
2 * Copyright © 2025 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 "json_parser_utils.hpp"
17
18 #include <nlohmann/json.hpp>
19
20 #include <cstdint>
21 #include <exception>
22 #include <stdexcept>
23 #include <string>
24 #include <vector>
25
26 #include <gtest/gtest.h>
27
28 using namespace phosphor::power::json_parser_utils;
29 using namespace phosphor::power::json_parser_utils::internal;
30 using json = nlohmann::json;
31
TEST(JSONParserUtilsTests,GetRequiredProperty)32 TEST(JSONParserUtilsTests, GetRequiredProperty)
33 {
34 // Test where property exists
35 {
36 const json element = R"( { "format": "linear" } )"_json;
37 const json& propertyElement = getRequiredProperty(element, "format");
38 EXPECT_EQ(propertyElement.get<std::string>(), "linear");
39 }
40
41 // Test where property does not exist
42 try
43 {
44 const json element = R"( { "volts": 1.03 } )"_json;
45 getRequiredProperty(element, "format");
46 ADD_FAILURE() << "Should not have reached this line.";
47 }
48 catch (const std::invalid_argument& e)
49 {
50 EXPECT_STREQ(e.what(), "Required property missing: format");
51 }
52 }
53
TEST(JSONParserUtilsTests,ParseBitPosition)54 TEST(JSONParserUtilsTests, ParseBitPosition)
55 {
56 // Test where works: 0
57 {
58 const json element = R"( 0 )"_json;
59 uint8_t value = parseBitPosition(element);
60 EXPECT_EQ(value, 0);
61 }
62
63 // Test where works: 7
64 {
65 const json element = R"( 7 )"_json;
66 uint8_t value = parseBitPosition(element);
67 EXPECT_EQ(value, 7);
68 }
69
70 // Test where works: Variable specified
71 {
72 std::map<std::string, std::string> variables{{"bit_pos", "3"}};
73 const json element = R"( "${bit_pos}" )"_json;
74 uint8_t value = parseBitPosition(element, variables);
75 EXPECT_EQ(value, 3);
76 }
77
78 // Test where fails: Element is not an integer
79 try
80 {
81 const json element = R"( 1.03 )"_json;
82 parseBitPosition(element);
83 ADD_FAILURE() << "Should not have reached this line.";
84 }
85 catch (const std::invalid_argument& e)
86 {
87 EXPECT_STREQ(e.what(), "Element is not an integer");
88 }
89
90 // Test where fails: Value < 0
91 try
92 {
93 const json element = R"( -1 )"_json;
94 parseBitPosition(element);
95 ADD_FAILURE() << "Should not have reached this line.";
96 }
97 catch (const std::invalid_argument& e)
98 {
99 EXPECT_STREQ(e.what(), "Element is not a bit position");
100 }
101
102 // Test where fails: Value > 7
103 try
104 {
105 const json element = R"( 8 )"_json;
106 parseBitPosition(element);
107 ADD_FAILURE() << "Should not have reached this line.";
108 }
109 catch (const std::invalid_argument& e)
110 {
111 EXPECT_STREQ(e.what(), "Element is not a bit position");
112 }
113
114 // Test where fails: Variable specified: Value < 0
115 try
116 {
117 std::map<std::string, std::string> variables{{"bit_pos", "-1"}};
118 const json element = R"( "${bit_pos}" )"_json;
119 parseBitPosition(element, variables);
120 ADD_FAILURE() << "Should not have reached this line.";
121 }
122 catch (const std::invalid_argument& e)
123 {
124 EXPECT_STREQ(e.what(), "Element is not a bit position");
125 }
126 }
127
TEST(JSONParserUtilsTests,ParseBitValue)128 TEST(JSONParserUtilsTests, ParseBitValue)
129 {
130 // Test where works: 0
131 {
132 const json element = R"( 0 )"_json;
133 uint8_t value = parseBitValue(element);
134 EXPECT_EQ(value, 0);
135 }
136
137 // Test where works: 1
138 {
139 const json element = R"( 1 )"_json;
140 uint8_t value = parseBitValue(element);
141 EXPECT_EQ(value, 1);
142 }
143
144 // Test where works: Variable specified
145 {
146 std::map<std::string, std::string> variables{{"bit_val", "1"}};
147 const json element = R"( "${bit_val}" )"_json;
148 uint8_t value = parseBitValue(element, variables);
149 EXPECT_EQ(value, 1);
150 }
151
152 // Test where fails: Element is not an integer
153 try
154 {
155 const json element = R"( 0.5 )"_json;
156 parseBitValue(element);
157 ADD_FAILURE() << "Should not have reached this line.";
158 }
159 catch (const std::invalid_argument& e)
160 {
161 EXPECT_STREQ(e.what(), "Element is not an integer");
162 }
163
164 // Test where fails: Value < 0
165 try
166 {
167 const json element = R"( -1 )"_json;
168 parseBitValue(element);
169 ADD_FAILURE() << "Should not have reached this line.";
170 }
171 catch (const std::invalid_argument& e)
172 {
173 EXPECT_STREQ(e.what(), "Element is not a bit value");
174 }
175
176 // Test where fails: Value > 1
177 try
178 {
179 const json element = R"( 2 )"_json;
180 parseBitValue(element);
181 ADD_FAILURE() << "Should not have reached this line.";
182 }
183 catch (const std::invalid_argument& e)
184 {
185 EXPECT_STREQ(e.what(), "Element is not a bit value");
186 }
187
188 // Test where fails: Variable specified: Not an integer
189 try
190 {
191 std::map<std::string, std::string> variables{{"bit_val", "one"}};
192 const json element = R"( "${bit_val}" )"_json;
193 parseBitValue(element, variables);
194 ADD_FAILURE() << "Should not have reached this line.";
195 }
196 catch (const std::invalid_argument& e)
197 {
198 EXPECT_STREQ(e.what(), "Element is not an integer");
199 }
200 }
201
TEST(JSONParserUtilsTests,ParseBoolean)202 TEST(JSONParserUtilsTests, ParseBoolean)
203 {
204 // Test where works: true
205 {
206 const json element = R"( true )"_json;
207 bool value = parseBoolean(element);
208 EXPECT_EQ(value, true);
209 }
210
211 // Test where works: false
212 {
213 const json element = R"( false )"_json;
214 bool value = parseBoolean(element);
215 EXPECT_EQ(value, false);
216 }
217
218 // Test where works: Variable specified: true
219 {
220 std::map<std::string, std::string> variables{{"bool_val", "true"}};
221 const json element = R"( "${bool_val}" )"_json;
222 bool value = parseBoolean(element, variables);
223 EXPECT_EQ(value, true);
224 }
225
226 // Test where works: Variable specified: false
227 {
228 std::map<std::string, std::string> variables{{"bool_val", "false"}};
229 const json element = R"( "${bool_val}" )"_json;
230 bool value = parseBoolean(element, variables);
231 EXPECT_EQ(value, false);
232 }
233
234 // Test where fails: Element is not a boolean
235 try
236 {
237 const json element = R"( 1 )"_json;
238 parseBoolean(element);
239 ADD_FAILURE() << "Should not have reached this line.";
240 }
241 catch (const std::invalid_argument& e)
242 {
243 EXPECT_STREQ(e.what(), "Element is not a boolean");
244 }
245
246 // Test where fails: Variable specified: Variables map not specified
247 try
248 {
249 const json element = R"( "${bool_val}" )"_json;
250 parseBoolean(element);
251 ADD_FAILURE() << "Should not have reached this line.";
252 }
253 catch (const std::invalid_argument& e)
254 {
255 EXPECT_STREQ(e.what(), "Element is not a boolean");
256 }
257
258 // Test where fails: Variable specified: Value is not a boolean
259 try
260 {
261 std::map<std::string, std::string> variables{{"bool_val", "3.2"}};
262 const json element = R"( "${bool_val}" )"_json;
263 parseBoolean(element, variables);
264 ADD_FAILURE() << "Should not have reached this line.";
265 }
266 catch (const std::invalid_argument& e)
267 {
268 EXPECT_STREQ(e.what(), "Element is not a boolean");
269 }
270 }
271
TEST(JSONParserUtilsTests,ParseDouble)272 TEST(JSONParserUtilsTests, ParseDouble)
273 {
274 // Test where works: Floating point value
275 {
276 const json element = R"( 1.03 )"_json;
277 double value = parseDouble(element);
278 EXPECT_EQ(value, 1.03);
279 }
280
281 // Test where works: Integer value
282 {
283 const json element = R"( -24 )"_json;
284 double value = parseDouble(element);
285 EXPECT_EQ(value, -24.0);
286 }
287
288 // Test where works: Variable specified: Floating point value
289 {
290 std::map<std::string, std::string> variables{{"var", "-1.03"}};
291 const json element = R"( "${var}" )"_json;
292 double value = parseDouble(element, variables);
293 EXPECT_EQ(value, -1.03);
294 }
295
296 // Test where works: Variable specified: Integer value
297 {
298 std::map<std::string, std::string> variables{{"var", "24"}};
299 const json element = R"( "${var}" )"_json;
300 double value = parseDouble(element, variables);
301 EXPECT_EQ(value, 24.0);
302 }
303
304 // Test where fails: Element is not a double
305 try
306 {
307 const json element = R"( true )"_json;
308 parseDouble(element);
309 ADD_FAILURE() << "Should not have reached this line.";
310 }
311 catch (const std::invalid_argument& e)
312 {
313 EXPECT_STREQ(e.what(), "Element is not a double");
314 }
315
316 // Test where fails: Variable specified: Variables map not specified
317 try
318 {
319 const json element = R"( "${var}" )"_json;
320 parseDouble(element);
321 ADD_FAILURE() << "Should not have reached this line.";
322 }
323 catch (const std::invalid_argument& e)
324 {
325 EXPECT_STREQ(e.what(), "Element is not a double");
326 }
327
328 // Test where fails: Variable specified: Leading whitespace
329 try
330 {
331 std::map<std::string, std::string> variables{{"var", " -1.03"}};
332 const json element = R"( "${var}" )"_json;
333 parseDouble(element, variables);
334 ADD_FAILURE() << "Should not have reached this line.";
335 }
336 catch (const std::invalid_argument& e)
337 {
338 EXPECT_STREQ(e.what(), "Element is not a double");
339 }
340
341 // Test where fails: Variable specified: Trailing whitespace
342 try
343 {
344 std::map<std::string, std::string> variables{{"var", "-1.03 "}};
345 const json element = R"( "${var}" )"_json;
346 parseDouble(element, variables);
347 ADD_FAILURE() << "Should not have reached this line.";
348 }
349 catch (const std::invalid_argument& e)
350 {
351 EXPECT_STREQ(e.what(), "Element is not a double");
352 }
353
354 // Test where fails: Variable specified: Starts with non-number character
355 try
356 {
357 std::map<std::string, std::string> variables{{"var", "x-1.03"}};
358 const json element = R"( "${var}" )"_json;
359 parseDouble(element, variables);
360 ADD_FAILURE() << "Should not have reached this line.";
361 }
362 catch (const std::invalid_argument& e)
363 {
364 EXPECT_STREQ(e.what(), "Element is not a double");
365 }
366
367 // Test where fails: Variable specified: Ends with non-number character
368 try
369 {
370 std::map<std::string, std::string> variables{{"var", "-1.03x"}};
371 const json element = R"( "${var}" )"_json;
372 parseDouble(element, variables);
373 ADD_FAILURE() << "Should not have reached this line.";
374 }
375 catch (const std::invalid_argument& e)
376 {
377 EXPECT_STREQ(e.what(), "Element is not a double");
378 }
379
380 // Test where fails: Variable specified: Not a double
381 try
382 {
383 std::map<std::string, std::string> variables{{"var", "foo"}};
384 const json element = R"( "${var}" )"_json;
385 parseDouble(element, variables);
386 ADD_FAILURE() << "Should not have reached this line.";
387 }
388 catch (const std::invalid_argument& e)
389 {
390 EXPECT_STREQ(e.what(), "Element is not a double");
391 }
392 }
393
TEST(JSONParserUtilsTests,ParseHexByte)394 TEST(JSONParserUtilsTests, ParseHexByte)
395 {
396 // Test where works: "0xFF"
397 {
398 const json element = R"( "0xFF" )"_json;
399 uint8_t value = parseHexByte(element);
400 EXPECT_EQ(value, 0xFF);
401 }
402
403 // Test where works: "0xff"
404 {
405 const json element = R"( "0xff" )"_json;
406 uint8_t value = parseHexByte(element);
407 EXPECT_EQ(value, 0xff);
408 }
409
410 // Test where works: "0xf"
411 {
412 const json element = R"( "0xf" )"_json;
413 uint8_t value = parseHexByte(element);
414 EXPECT_EQ(value, 0xf);
415 }
416
417 // Test where works: Variable specified
418 {
419 std::map<std::string, std::string> variables{{"var", "ed"}};
420 const json element = R"( "0x${var}" )"_json;
421 uint8_t value = parseHexByte(element, variables);
422 EXPECT_EQ(value, 0xed);
423 }
424
425 // Test where fails: "0xfff"
426 try
427 {
428 const json element = R"( "0xfff" )"_json;
429 parseHexByte(element);
430 ADD_FAILURE() << "Should not have reached this line.";
431 }
432 catch (const std::invalid_argument& e)
433 {
434 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
435 }
436
437 // Test where fails: "0xAG"
438 try
439 {
440 const json element = R"( "0xAG" )"_json;
441 parseHexByte(element);
442 ADD_FAILURE() << "Should not have reached this line.";
443 }
444 catch (const std::invalid_argument& e)
445 {
446 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
447 }
448
449 // Test where fails: "ff"
450 try
451 {
452 const json element = R"( "ff" )"_json;
453 parseHexByte(element);
454 ADD_FAILURE() << "Should not have reached this line.";
455 }
456 catch (const std::invalid_argument& e)
457 {
458 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
459 }
460
461 // Test where fails: ""
462 try
463 {
464 const json element = "";
465 parseHexByte(element);
466 ADD_FAILURE() << "Should not have reached this line.";
467 }
468 catch (const std::invalid_argument& e)
469 {
470 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
471 }
472
473 // Test where fails: "f"
474 try
475 {
476 const json element = R"( "f" )"_json;
477 parseHexByte(element);
478 ADD_FAILURE() << "Should not have reached this line.";
479 }
480 catch (const std::invalid_argument& e)
481 {
482 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
483 }
484
485 // Test where fails: "0x"
486 try
487 {
488 const json element = R"( "0x" )"_json;
489 parseHexByte(element);
490 ADD_FAILURE() << "Should not have reached this line.";
491 }
492 catch (const std::invalid_argument& e)
493 {
494 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
495 }
496
497 // Test where fails: "0Xff"
498 try
499 {
500 const json element = R"( "0XFF" )"_json;
501 parseHexByte(element);
502 ADD_FAILURE() << "Should not have reached this line.";
503 }
504 catch (const std::invalid_argument& e)
505 {
506 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
507 }
508
509 // Test where fails: Variable specified: Not a hex string
510 try
511 {
512 std::map<std::string, std::string> variables{{"var", "0xsz"}};
513 const json element = R"( "${var}" )"_json;
514 parseHexByte(element, variables);
515 ADD_FAILURE() << "Should not have reached this line.";
516 }
517 catch (const std::invalid_argument& e)
518 {
519 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
520 }
521 }
522
TEST(JSONParserUtilsTests,ParseHexByteArray)523 TEST(JSONParserUtilsTests, ParseHexByteArray)
524 {
525 // Test where works
526 {
527 const json element = R"( [ "0xCC", "0xFF" ] )"_json;
528 std::vector<uint8_t> hexBytes = parseHexByteArray(element);
529 std::vector<uint8_t> expected = {0xcc, 0xff};
530 EXPECT_EQ(hexBytes, expected);
531 }
532
533 // Test where works: Variables specified
534 {
535 std::map<std::string, std::string> variables{{"var1", "0xCC"},
536 {"var2", "0xFF"}};
537 const json element = R"( [ "${var1}", "${var2}" ] )"_json;
538 std::vector<uint8_t> hexBytes = parseHexByteArray(element, variables);
539 std::vector<uint8_t> expected = {0xcc, 0xff};
540 EXPECT_EQ(hexBytes, expected);
541 }
542
543 // Test where fails: Element is not an array
544 try
545 {
546 const json element = 0;
547 parseHexByteArray(element);
548 ADD_FAILURE() << "Should not have reached this line.";
549 }
550 catch (const std::invalid_argument& e)
551 {
552 EXPECT_STREQ(e.what(), "Element is not an array");
553 }
554
555 // Test where fails: Variables specified: Invalid byte value
556 try
557 {
558 std::map<std::string, std::string> variables{{"var1", "0xCC"},
559 {"var2", "99"}};
560 const json element = R"( [ "${var1}", "${var2}" ] )"_json;
561 parseHexByteArray(element, variables);
562 ADD_FAILURE() << "Should not have reached this line.";
563 }
564 catch (const std::invalid_argument& e)
565 {
566 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
567 }
568 }
569
TEST(JSONParserUtilsTests,ParseInt8)570 TEST(JSONParserUtilsTests, ParseInt8)
571 {
572 // Test where works: INT8_MIN
573 {
574 const json element = R"( -128 )"_json;
575 int8_t value = parseInt8(element);
576 EXPECT_EQ(value, -128);
577 }
578
579 // Test where works: INT8_MAX
580 {
581 const json element = R"( 127 )"_json;
582 int8_t value = parseInt8(element);
583 EXPECT_EQ(value, 127);
584 }
585
586 // Test where works: Variable specified
587 {
588 std::map<std::string, std::string> variables{{"var", "-23"}};
589 const json element = R"( "${var}" )"_json;
590 int8_t value = parseInt8(element, variables);
591 EXPECT_EQ(value, -23);
592 }
593
594 // Test where fails: Element is not an integer
595 try
596 {
597 const json element = R"( 1.03 )"_json;
598 parseInt8(element);
599 ADD_FAILURE() << "Should not have reached this line.";
600 }
601 catch (const std::invalid_argument& e)
602 {
603 EXPECT_STREQ(e.what(), "Element is not an integer");
604 }
605
606 // Test where fails: Value < INT8_MIN
607 try
608 {
609 const json element = R"( -129 )"_json;
610 parseInt8(element);
611 ADD_FAILURE() << "Should not have reached this line.";
612 }
613 catch (const std::invalid_argument& e)
614 {
615 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
616 }
617
618 // Test where fails: Value > INT8_MAX
619 try
620 {
621 const json element = R"( 128 )"_json;
622 parseInt8(element);
623 ADD_FAILURE() << "Should not have reached this line.";
624 }
625 catch (const std::invalid_argument& e)
626 {
627 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
628 }
629
630 // Test where fails: Variable specified: Value > INT8_MAX
631 try
632 {
633 std::map<std::string, std::string> variables{{"var", "128"}};
634 const json element = R"( "${var}" )"_json;
635 parseInt8(element, variables);
636 ADD_FAILURE() << "Should not have reached this line.";
637 }
638 catch (const std::invalid_argument& e)
639 {
640 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
641 }
642 }
643
TEST(JSONParserUtilsTests,ParseInteger)644 TEST(JSONParserUtilsTests, ParseInteger)
645 {
646 // Test where works: Zero
647 {
648 const json element = R"( 0 )"_json;
649 int value = parseInteger(element);
650 EXPECT_EQ(value, 0);
651 }
652
653 // Test where works: Positive value
654 {
655 const json element = R"( 103 )"_json;
656 int value = parseInteger(element);
657 EXPECT_EQ(value, 103);
658 }
659
660 // Test where works: Negative value
661 {
662 const json element = R"( -24 )"_json;
663 int value = parseInteger(element);
664 EXPECT_EQ(value, -24);
665 }
666
667 // Test where works: Variable specified: Positive value
668 {
669 std::map<std::string, std::string> variables{{"var", "1024"}};
670 const json element = R"( "${var}" )"_json;
671 int value = parseInteger(element, variables);
672 EXPECT_EQ(value, 1024);
673 }
674
675 // Test where works: Variable specified: Negative value
676 {
677 std::map<std::string, std::string> variables{{"var", "-9924"}};
678 const json element = R"( "${var}" )"_json;
679 int value = parseInteger(element, variables);
680 EXPECT_EQ(value, -9924);
681 }
682
683 // Test where fails: Element is not a integer
684 try
685 {
686 const json element = R"( true )"_json;
687 parseInteger(element);
688 ADD_FAILURE() << "Should not have reached this line.";
689 }
690 catch (const std::invalid_argument& e)
691 {
692 EXPECT_STREQ(e.what(), "Element is not an integer");
693 }
694
695 // Test where fails: Variable specified: Variables map not specified
696 try
697 {
698 const json element = R"( "${var}" )"_json;
699 parseInteger(element);
700 ADD_FAILURE() << "Should not have reached this line.";
701 }
702 catch (const std::invalid_argument& e)
703 {
704 EXPECT_STREQ(e.what(), "Element is not an integer");
705 }
706
707 // Test where fails: Variable specified: Leading whitespace
708 try
709 {
710 std::map<std::string, std::string> variables{{"var", " -13"}};
711 const json element = R"( "${var}" )"_json;
712 parseInteger(element, variables);
713 ADD_FAILURE() << "Should not have reached this line.";
714 }
715 catch (const std::invalid_argument& e)
716 {
717 EXPECT_STREQ(e.what(), "Element is not an integer");
718 }
719
720 // Test where fails: Variable specified: Trailing whitespace
721 try
722 {
723 std::map<std::string, std::string> variables{{"var", "-13 "}};
724 const json element = R"( "${var}" )"_json;
725 parseInteger(element, variables);
726 ADD_FAILURE() << "Should not have reached this line.";
727 }
728 catch (const std::invalid_argument& e)
729 {
730 EXPECT_STREQ(e.what(), "Element is not an integer");
731 }
732
733 // Test where fails: Variable specified: Starts with non-number character
734 try
735 {
736 std::map<std::string, std::string> variables{{"var", "x-13"}};
737 const json element = R"( "${var}" )"_json;
738 parseInteger(element, variables);
739 ADD_FAILURE() << "Should not have reached this line.";
740 }
741 catch (const std::invalid_argument& e)
742 {
743 EXPECT_STREQ(e.what(), "Element is not an integer");
744 }
745
746 // Test where fails: Variable specified: Ends with non-number character
747 try
748 {
749 std::map<std::string, std::string> variables{{"var", "-13x"}};
750 const json element = R"( "${var}" )"_json;
751 parseInteger(element, variables);
752 ADD_FAILURE() << "Should not have reached this line.";
753 }
754 catch (const std::invalid_argument& e)
755 {
756 EXPECT_STREQ(e.what(), "Element is not an integer");
757 }
758
759 // Test where fails: Variable specified: Not an integer
760 try
761 {
762 std::map<std::string, std::string> variables{{"var", "foo"}};
763 const json element = R"( "${var}" )"_json;
764 parseInteger(element, variables);
765 ADD_FAILURE() << "Should not have reached this line.";
766 }
767 catch (const std::invalid_argument& e)
768 {
769 EXPECT_STREQ(e.what(), "Element is not an integer");
770 }
771 }
772
TEST(JSONParserUtilsTests,ParseString)773 TEST(JSONParserUtilsTests, ParseString)
774 {
775 // Test where works: Empty string
776 {
777 const json element = "";
778 std::string value = parseString(element, true);
779 EXPECT_EQ(value, "");
780 }
781
782 // Test where works: Non-empty string
783 {
784 const json element = "vdd_regulator";
785 std::string value = parseString(element, false);
786 EXPECT_EQ(value, "vdd_regulator");
787 }
788
789 // Test where works: Variable specified: Empty string
790 {
791 std::map<std::string, std::string> variables{{"var", ""}};
792 const json element = R"( "${var}" )"_json;
793 std::string value = parseString(element, true, variables);
794 EXPECT_EQ(value, "");
795 }
796
797 // Test where works: Variable specified: Non-empty string
798 {
799 std::map<std::string, std::string> variables{{"var", "vio_regulator"}};
800 const json element = R"( "${var}" )"_json;
801 std::string value = parseString(element, false, variables);
802 EXPECT_EQ(value, "vio_regulator");
803 }
804
805 // Test where fails: Element is not a string
806 try
807 {
808 const json element = R"( { "foo": "bar" } )"_json;
809 parseString(element);
810 ADD_FAILURE() << "Should not have reached this line.";
811 }
812 catch (const std::invalid_argument& e)
813 {
814 EXPECT_STREQ(e.what(), "Element is not a string");
815 }
816
817 // Test where fails: Empty string
818 try
819 {
820 const json element = "";
821 parseString(element);
822 ADD_FAILURE() << "Should not have reached this line.";
823 }
824 catch (const std::invalid_argument& e)
825 {
826 EXPECT_STREQ(e.what(), "Element contains an empty string");
827 }
828
829 // Test where fails: Variable specified: Empty string
830 try
831 {
832 std::map<std::string, std::string> variables{{"var", ""}};
833 const json element = R"( "${var}" )"_json;
834 parseString(element, false, variables);
835 ADD_FAILURE() << "Should not have reached this line.";
836 }
837 catch (const std::invalid_argument& e)
838 {
839 EXPECT_STREQ(e.what(), "Element contains an empty string");
840 }
841
842 // Test where fails: Variable specified: Variable not defined
843 try
844 {
845 std::map<std::string, std::string> variables{{"var1", "foo"}};
846 const json element = R"( "${var2}" )"_json;
847 parseString(element, false, variables);
848 ADD_FAILURE() << "Should not have reached this line.";
849 }
850 catch (const std::invalid_argument& e)
851 {
852 EXPECT_STREQ(e.what(), "Undefined variable: var2");
853 }
854 }
855
TEST(JSONParserUtilsTests,ParseUint8)856 TEST(JSONParserUtilsTests, ParseUint8)
857 {
858 // Test where works: 0
859 {
860 const json element = R"( 0 )"_json;
861 uint8_t value = parseUint8(element);
862 EXPECT_EQ(value, 0);
863 }
864
865 // Test where works: UINT8_MAX
866 {
867 const json element = R"( 255 )"_json;
868 uint8_t value = parseUint8(element);
869 EXPECT_EQ(value, 255);
870 }
871
872 // Test where works: Variable specified
873 {
874 std::map<std::string, std::string> variables{{"var", "19"}};
875 const json element = R"( "${var}" )"_json;
876 uint8_t value = parseUint8(element, variables);
877 EXPECT_EQ(value, 19);
878 }
879
880 // Test where fails: Element is not an integer
881 try
882 {
883 const json element = R"( 1.03 )"_json;
884 parseUint8(element);
885 ADD_FAILURE() << "Should not have reached this line.";
886 }
887 catch (const std::invalid_argument& e)
888 {
889 EXPECT_STREQ(e.what(), "Element is not an integer");
890 }
891
892 // Test where fails: Value < 0
893 try
894 {
895 const json element = R"( -1 )"_json;
896 parseUint8(element);
897 ADD_FAILURE() << "Should not have reached this line.";
898 }
899 catch (const std::invalid_argument& e)
900 {
901 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
902 }
903
904 // Test where fails: Value > UINT8_MAX
905 try
906 {
907 const json element = R"( 256 )"_json;
908 parseUint8(element);
909 ADD_FAILURE() << "Should not have reached this line.";
910 }
911 catch (const std::invalid_argument& e)
912 {
913 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
914 }
915
916 // Test where fails: Variable specified: Value > UINT8_MAX
917 try
918 {
919 std::map<std::string, std::string> variables{{"var", "256"}};
920 const json element = R"( "${var}" )"_json;
921 parseUint8(element, variables);
922 ADD_FAILURE() << "Should not have reached this line.";
923 }
924 catch (const std::invalid_argument& e)
925 {
926 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
927 }
928 }
929
TEST(JSONParserUtilsTests,ParseUint16)930 TEST(JSONParserUtilsTests, ParseUint16)
931 {
932 // Test where works: 0
933 {
934 const json element = R"( 0 )"_json;
935 uint16_t value = parseUint16(element);
936 EXPECT_EQ(value, 0);
937 }
938
939 // Test where works: UINT16_MAX
940 {
941 const json element = R"( 65535 )"_json;
942 uint16_t value = parseUint16(element);
943 EXPECT_EQ(value, 65535);
944 }
945
946 // Test where works: Variable specified
947 {
948 std::map<std::string, std::string> variables{{"var", "24699"}};
949 const json element = R"( "${var}" )"_json;
950 uint16_t value = parseUint16(element, variables);
951 EXPECT_EQ(value, 24699);
952 }
953
954 // Test where fails: Element is not an integer
955 try
956 {
957 const json element = R"( 1.03 )"_json;
958 parseUint16(element);
959 ADD_FAILURE() << "Should not have reached this line.";
960 }
961 catch (const std::invalid_argument& e)
962 {
963 EXPECT_STREQ(e.what(), "Element is not an integer");
964 }
965
966 // Test where fails: Value < 0
967 try
968 {
969 const json element = R"( -1 )"_json;
970 parseUint16(element);
971 ADD_FAILURE() << "Should not have reached this line.";
972 }
973 catch (const std::invalid_argument& e)
974 {
975 EXPECT_STREQ(e.what(), "Element is not a 16-bit unsigned integer");
976 }
977
978 // Test where fails: Value > UINT16_MAX
979 try
980 {
981 const json element = R"( 65536 )"_json;
982 parseUint16(element);
983 ADD_FAILURE() << "Should not have reached this line.";
984 }
985 catch (const std::invalid_argument& e)
986 {
987 EXPECT_STREQ(e.what(), "Element is not a 16-bit unsigned integer");
988 }
989
990 // Test where fails: Variable specified: Value > UINT16_MAX
991 try
992 {
993 std::map<std::string, std::string> variables{{"var", "65536"}};
994 const json element = R"( "${var}" )"_json;
995 parseUint16(element, variables);
996 ADD_FAILURE() << "Should not have reached this line.";
997 }
998 catch (const std::invalid_argument& e)
999 {
1000 EXPECT_STREQ(e.what(), "Element is not a 16-bit unsigned integer");
1001 }
1002 }
1003
TEST(JSONParserUtilsTests,ParseUnsignedInteger)1004 TEST(JSONParserUtilsTests, ParseUnsignedInteger)
1005 {
1006 // Test where works: 1
1007 {
1008 const json element = R"( 1 )"_json;
1009 unsigned int value = parseUnsignedInteger(element);
1010 EXPECT_EQ(value, 1);
1011 }
1012
1013 // Test where works: Variable specified
1014 {
1015 std::map<std::string, std::string> variables{{"var", "25678"}};
1016 const json element = R"( "${var}" )"_json;
1017 unsigned int value = parseUnsignedInteger(element, variables);
1018 EXPECT_EQ(value, 25678);
1019 }
1020
1021 // Test where fails: Element is not an integer
1022 try
1023 {
1024 const json element = R"( 1.5 )"_json;
1025 parseUnsignedInteger(element);
1026 ADD_FAILURE() << "Should not have reached this line.";
1027 }
1028 catch (const std::invalid_argument& e)
1029 {
1030 EXPECT_STREQ(e.what(), "Element is not an integer");
1031 }
1032
1033 // Test where fails: Value < 0
1034 try
1035 {
1036 const json element = R"( -1 )"_json;
1037 parseUnsignedInteger(element);
1038 ADD_FAILURE() << "Should not have reached this line.";
1039 }
1040 catch (const std::invalid_argument& e)
1041 {
1042 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
1043 }
1044
1045 // Test where fails: Variable specified: Value < 0
1046 try
1047 {
1048 std::map<std::string, std::string> variables{{"var", "-23"}};
1049 const json element = R"( "${var}" )"_json;
1050 parseUnsignedInteger(element, variables);
1051 ADD_FAILURE() << "Should not have reached this line.";
1052 }
1053 catch (const std::invalid_argument& e)
1054 {
1055 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
1056 }
1057 }
1058
TEST(JSONParserUtilsTests,VerifyIsArray)1059 TEST(JSONParserUtilsTests, VerifyIsArray)
1060 {
1061 // Test where element is an array
1062 {
1063 const json element = R"( [ "foo", "bar" ] )"_json;
1064 verifyIsArray(element);
1065 }
1066
1067 // Test where element is not an array
1068 try
1069 {
1070 const json element = R"( { "foo": "bar" } )"_json;
1071 verifyIsArray(element);
1072 ADD_FAILURE() << "Should not have reached this line.";
1073 }
1074 catch (const std::invalid_argument& e)
1075 {
1076 EXPECT_STREQ(e.what(), "Element is not an array");
1077 }
1078 }
1079
TEST(JSONParserUtilsTests,VerifyIsObject)1080 TEST(JSONParserUtilsTests, VerifyIsObject)
1081 {
1082 // Test where element is an object
1083 {
1084 const json element = R"( { "foo": "bar" } )"_json;
1085 verifyIsObject(element);
1086 }
1087
1088 // Test where element is not an object
1089 try
1090 {
1091 const json element = R"( [ "foo", "bar" ] )"_json;
1092 verifyIsObject(element);
1093 ADD_FAILURE() << "Should not have reached this line.";
1094 }
1095 catch (const std::invalid_argument& e)
1096 {
1097 EXPECT_STREQ(e.what(), "Element is not an object");
1098 }
1099 }
1100
TEST(JSONParserUtilsTests,VerifyPropertyCount)1101 TEST(JSONParserUtilsTests, VerifyPropertyCount)
1102 {
1103 // Test where element has expected number of properties
1104 {
1105 const json element = R"(
1106 {
1107 "comments": [ "Set voltage rule" ],
1108 "id": "set_voltage_rule"
1109 }
1110 )"_json;
1111 verifyPropertyCount(element, 2);
1112 }
1113
1114 // Test where element has unexpected number of properties
1115 try
1116 {
1117 const json element = R"(
1118 {
1119 "comments": [ "Set voltage rule" ],
1120 "id": "set_voltage_rule",
1121 "foo": 1.3
1122 }
1123 )"_json;
1124 verifyPropertyCount(element, 2);
1125 ADD_FAILURE() << "Should not have reached this line.";
1126 }
1127 catch (const std::invalid_argument& e)
1128 {
1129 EXPECT_STREQ(e.what(), "Element contains an invalid property");
1130 }
1131 }
1132
TEST(JSONParserUtilsTests,ExpandVariables)1133 TEST(JSONParserUtilsTests, ExpandVariables)
1134 {
1135 // Test where works: Single variable: Variable is entire value: Lower case
1136 // in variable name
1137 {
1138 std::map<std::string, std::string> variables{{"var", "vio_regulator"}};
1139 std::string value{"${var}"};
1140 expandVariables(value, variables);
1141 EXPECT_EQ(value, "vio_regulator");
1142 }
1143
1144 // Test where works: Multiple variables: Variables are part of value: Upper
1145 // case and underscore in variable name
1146 {
1147 std::map<std::string, std::string> variables{
1148 {"CHASSIS_NUMBER", "1"}, {"REGULATOR", "vcs_vio"}, {"RAIL", "vio"}};
1149 std::string value{
1150 "chassis${CHASSIS_NUMBER}_${REGULATOR}_regulator_${RAIL}_rail"};
1151 expandVariables(value, variables);
1152 EXPECT_EQ(value, "chassis1_vcs_vio_regulator_vio_rail");
1153 }
1154
1155 // Test where works: Variable at start of value: Number in variable name
1156 {
1157 std::map<std::string, std::string> variables{{"var1", "vio_regulator"}};
1158 std::string value{"${var1}_rail"};
1159 expandVariables(value, variables);
1160 EXPECT_EQ(value, "vio_regulator_rail");
1161 }
1162
1163 // Test where works: Variable at end of value
1164 {
1165 std::map<std::string, std::string> variables{{"chassis_number", "3"}};
1166 std::string value{
1167 "/xyz/openbmc_project/inventory/system/chassis${chassis_number}"};
1168 expandVariables(value, variables);
1169 EXPECT_EQ(value, "/xyz/openbmc_project/inventory/system/chassis3");
1170 }
1171
1172 // Test where works: Variable has empty value: Start of value
1173 {
1174 std::map<std::string, std::string> variables{{"chassis_prefix", ""}};
1175 std::string value{"${chassis_prefix}vio_regulator"};
1176 expandVariables(value, variables);
1177 EXPECT_EQ(value, "vio_regulator");
1178 }
1179
1180 // Test where works: Variable has empty value: Middle of value
1181 {
1182 std::map<std::string, std::string> variables{{"chassis_number", ""}};
1183 std::string value{"c${chassis_number}_vio_regulator"};
1184 expandVariables(value, variables);
1185 EXPECT_EQ(value, "c_vio_regulator");
1186 }
1187
1188 // Test where works: Variable has empty value: End of value
1189 {
1190 std::map<std::string, std::string> variables{{"chassis_number", ""}};
1191 std::string value{
1192 "/xyz/openbmc_project/inventory/system/chassis${chassis_number}"};
1193 expandVariables(value, variables);
1194 EXPECT_EQ(value, "/xyz/openbmc_project/inventory/system/chassis");
1195 }
1196
1197 // Test where works: No variables specified
1198 {
1199 std::map<std::string, std::string> variables{{"var", "vio_regulator"}};
1200 std::string value{"vcs_rail"};
1201 expandVariables(value, variables);
1202 EXPECT_EQ(value, "vcs_rail");
1203 }
1204
1205 // Test where works: Nested variable expansion
1206 {
1207 std::map<std::string, std::string> variables{{"var1", "${var2}"},
1208 {"var2", "vio_reg"}};
1209 std::string value{"${var1}_rail"};
1210 expandVariables(value, variables);
1211 EXPECT_EQ(value, "vio_reg_rail");
1212 }
1213
1214 // Test where fails: Variables map is empty
1215 {
1216 std::map<std::string, std::string> variables{};
1217 std::string value{"${var}_rail"};
1218 expandVariables(value, variables);
1219 EXPECT_EQ(value, "${var}_rail");
1220 }
1221
1222 // Test where fails: Variable missing $
1223 {
1224 std::map<std::string, std::string> variables{{"var", "vio_reg"}};
1225 std::string value{"{var}_rail"};
1226 expandVariables(value, variables);
1227 EXPECT_EQ(value, "{var}_rail");
1228 }
1229
1230 // Test where fails: Variable missing {
1231 {
1232 std::map<std::string, std::string> variables{{"var", "vio_reg"}};
1233 std::string value{"$var}_rail"};
1234 expandVariables(value, variables);
1235 EXPECT_EQ(value, "$var}_rail");
1236 }
1237
1238 // Test where fails: Variable missing }
1239 {
1240 std::map<std::string, std::string> variables{{"var", "vio_reg"}};
1241 std::string value{"${var_rail"};
1242 expandVariables(value, variables);
1243 EXPECT_EQ(value, "${var_rail");
1244 }
1245
1246 // Test where fails: Variable missing name
1247 {
1248 std::map<std::string, std::string> variables{{"var", "vio_reg"}};
1249 std::string value{"${}_rail"};
1250 expandVariables(value, variables);
1251 EXPECT_EQ(value, "${}_rail");
1252 }
1253
1254 // Test where fails: Variable name has invalid characters
1255 {
1256 std::map<std::string, std::string> variables{{"var-2", "vio_reg"}};
1257 std::string value{"${var-2}_rail"};
1258 expandVariables(value, variables);
1259 EXPECT_EQ(value, "${var-2}_rail");
1260 }
1261
1262 // Test where fails: Variable has unexpected whitespace
1263 {
1264 std::map<std::string, std::string> variables{{"var", "vio_reg"}};
1265 std::string value{"${ var }_rail"};
1266 expandVariables(value, variables);
1267 EXPECT_EQ(value, "${ var }_rail");
1268 }
1269
1270 // Test where fails: Undefined variable
1271 try
1272 {
1273 std::map<std::string, std::string> variables{{"var", "vio_reg"}};
1274 std::string value{"${foo}_rail"};
1275 expandVariables(value, variables);
1276 ADD_FAILURE() << "Should not have reached this line.";
1277 }
1278 catch (const std::invalid_argument& e)
1279 {
1280 EXPECT_STREQ(e.what(), "Undefined variable: foo");
1281 }
1282 }
1283