blob: e4f591c73a0a536bbcc45d4ba792de572456b83c [file] [log] [blame]
Shawn McCarney38f85002025-10-31 17:59:36 -05001/**
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
28using namespace phosphor::power::json_parser_utils;
29using json = nlohmann::json;
30
31TEST(JSONParserUtilsTests, GetRequiredProperty)
32{
33 // Test where property exists
34 {
35 const json element = R"( { "format": "linear" } )"_json;
36 const json& propertyElement = getRequiredProperty(element, "format");
37 EXPECT_EQ(propertyElement.get<std::string>(), "linear");
38 }
39
40 // Test where property does not exist
41 try
42 {
43 const json element = R"( { "volts": 1.03 } )"_json;
44 getRequiredProperty(element, "format");
45 ADD_FAILURE() << "Should not have reached this line.";
46 }
47 catch (const std::invalid_argument& e)
48 {
49 EXPECT_STREQ(e.what(), "Required property missing: format");
50 }
51}
52
53TEST(JSONParserUtilsTests, ParseBitPosition)
54{
55 // Test where works: 0
56 {
57 const json element = R"( 0 )"_json;
58 uint8_t value = parseBitPosition(element);
59 EXPECT_EQ(value, 0);
60 }
61
62 // Test where works: 7
63 {
64 const json element = R"( 7 )"_json;
65 uint8_t value = parseBitPosition(element);
66 EXPECT_EQ(value, 7);
67 }
68
69 // Test where fails: Element is not an integer
70 try
71 {
72 const json element = R"( 1.03 )"_json;
73 parseBitPosition(element);
74 ADD_FAILURE() << "Should not have reached this line.";
75 }
76 catch (const std::invalid_argument& e)
77 {
78 EXPECT_STREQ(e.what(), "Element is not an integer");
79 }
80
81 // Test where fails: Value < 0
82 try
83 {
84 const json element = R"( -1 )"_json;
85 parseBitPosition(element);
86 ADD_FAILURE() << "Should not have reached this line.";
87 }
88 catch (const std::invalid_argument& e)
89 {
90 EXPECT_STREQ(e.what(), "Element is not a bit position");
91 }
92
93 // Test where fails: Value > 7
94 try
95 {
96 const json element = R"( 8 )"_json;
97 parseBitPosition(element);
98 ADD_FAILURE() << "Should not have reached this line.";
99 }
100 catch (const std::invalid_argument& e)
101 {
102 EXPECT_STREQ(e.what(), "Element is not a bit position");
103 }
104}
105
106TEST(JSONParserUtilsTests, ParseBitValue)
107{
108 // Test where works: 0
109 {
110 const json element = R"( 0 )"_json;
111 uint8_t value = parseBitValue(element);
112 EXPECT_EQ(value, 0);
113 }
114
115 // Test where works: 1
116 {
117 const json element = R"( 1 )"_json;
118 uint8_t value = parseBitValue(element);
119 EXPECT_EQ(value, 1);
120 }
121
122 // Test where fails: Element is not an integer
123 try
124 {
125 const json element = R"( 0.5 )"_json;
126 parseBitValue(element);
127 ADD_FAILURE() << "Should not have reached this line.";
128 }
129 catch (const std::invalid_argument& e)
130 {
131 EXPECT_STREQ(e.what(), "Element is not an integer");
132 }
133
134 // Test where fails: Value < 0
135 try
136 {
137 const json element = R"( -1 )"_json;
138 parseBitValue(element);
139 ADD_FAILURE() << "Should not have reached this line.";
140 }
141 catch (const std::invalid_argument& e)
142 {
143 EXPECT_STREQ(e.what(), "Element is not a bit value");
144 }
145
146 // Test where fails: Value > 1
147 try
148 {
149 const json element = R"( 2 )"_json;
150 parseBitValue(element);
151 ADD_FAILURE() << "Should not have reached this line.";
152 }
153 catch (const std::invalid_argument& e)
154 {
155 EXPECT_STREQ(e.what(), "Element is not a bit value");
156 }
157}
158
159TEST(JSONParserUtilsTests, ParseBoolean)
160{
161 // Test where works: true
162 {
163 const json element = R"( true )"_json;
164 bool value = parseBoolean(element);
165 EXPECT_EQ(value, true);
166 }
167
168 // Test where works: false
169 {
170 const json element = R"( false )"_json;
171 bool value = parseBoolean(element);
172 EXPECT_EQ(value, false);
173 }
174
175 // Test where fails: Element is not a boolean
176 try
177 {
178 const json element = R"( 1 )"_json;
179 parseBoolean(element);
180 ADD_FAILURE() << "Should not have reached this line.";
181 }
182 catch (const std::invalid_argument& e)
183 {
184 EXPECT_STREQ(e.what(), "Element is not a boolean");
185 }
186}
187
188TEST(JSONParserUtilsTests, ParseDouble)
189{
190 // Test where works: floating point value
191 {
192 const json element = R"( 1.03 )"_json;
193 double value = parseDouble(element);
194 EXPECT_EQ(value, 1.03);
195 }
196
197 // Test where works: integer value
198 {
199 const json element = R"( 24 )"_json;
200 double value = parseDouble(element);
201 EXPECT_EQ(value, 24.0);
202 }
203
204 // Test where fails: Element is not a number
205 try
206 {
207 const json element = R"( true )"_json;
208 parseDouble(element);
209 ADD_FAILURE() << "Should not have reached this line.";
210 }
211 catch (const std::invalid_argument& e)
212 {
213 EXPECT_STREQ(e.what(), "Element is not a number");
214 }
215}
216
217TEST(JSONParserUtilsTests, ParseHexByte)
218{
219 // Test where works: "0xFF"
220 {
221 const json element = R"( "0xFF" )"_json;
222 uint8_t value = parseHexByte(element);
223 EXPECT_EQ(value, 0xFF);
224 }
225
226 // Test where works: "0xff"
227 {
228 const json element = R"( "0xff" )"_json;
229 uint8_t value = parseHexByte(element);
230 EXPECT_EQ(value, 0xff);
231 }
232
233 // Test where works: "0xf"
234 {
235 const json element = R"( "0xf" )"_json;
236 uint8_t value = parseHexByte(element);
237 EXPECT_EQ(value, 0xf);
238 }
239
240 // Test where fails: "0xfff"
241 try
242 {
243 const json element = R"( "0xfff" )"_json;
244 parseHexByte(element);
245 ADD_FAILURE() << "Should not have reached this line.";
246 }
247 catch (const std::invalid_argument& e)
248 {
249 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
250 }
251
252 // Test where fails: "0xAG"
253 try
254 {
255 const json element = R"( "0xAG" )"_json;
256 parseHexByte(element);
257 ADD_FAILURE() << "Should not have reached this line.";
258 }
259 catch (const std::invalid_argument& e)
260 {
261 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
262 }
263
264 // Test where fails: "ff"
265 try
266 {
267 const json element = R"( "ff" )"_json;
268 parseHexByte(element);
269 ADD_FAILURE() << "Should not have reached this line.";
270 }
271 catch (const std::invalid_argument& e)
272 {
273 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
274 }
275
276 // Test where fails: ""
277 try
278 {
279 const json element = "";
280 parseHexByte(element);
281 ADD_FAILURE() << "Should not have reached this line.";
282 }
283 catch (const std::invalid_argument& e)
284 {
285 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
286 }
287
288 // Test where fails: "f"
289 try
290 {
291 const json element = R"( "f" )"_json;
292 parseHexByte(element);
293 ADD_FAILURE() << "Should not have reached this line.";
294 }
295 catch (const std::invalid_argument& e)
296 {
297 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
298 }
299
300 // Test where fails: "0x"
301 try
302 {
303 const json element = R"( "0x" )"_json;
304 parseHexByte(element);
305 ADD_FAILURE() << "Should not have reached this line.";
306 }
307 catch (const std::invalid_argument& e)
308 {
309 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
310 }
311
312 // Test where fails: "0Xff"
313 try
314 {
315 const json element = R"( "0XFF" )"_json;
316 parseHexByte(element);
317 ADD_FAILURE() << "Should not have reached this line.";
318 }
319 catch (const std::invalid_argument& e)
320 {
321 EXPECT_STREQ(e.what(), "Element is not hexadecimal string");
322 }
323}
324
325TEST(JSONParserUtilsTests, ParseHexByteArray)
326{
327 // Test where works
328 {
329 const json element = R"( [ "0xCC", "0xFF" ] )"_json;
330 std::vector<uint8_t> hexBytes = parseHexByteArray(element);
331 std::vector<uint8_t> expected = {0xcc, 0xff};
332 EXPECT_EQ(hexBytes, expected);
333 }
334
335 // Test where fails: Element is not an array
336 try
337 {
338 const json element = 0;
339 parseHexByteArray(element);
340 ADD_FAILURE() << "Should not have reached this line.";
341 }
342 catch (const std::invalid_argument& e)
343 {
344 EXPECT_STREQ(e.what(), "Element is not an array");
345 }
346}
347
348TEST(JSONParserUtilsTests, ParseInt8)
349{
350 // Test where works: INT8_MIN
351 {
352 const json element = R"( -128 )"_json;
353 int8_t value = parseInt8(element);
354 EXPECT_EQ(value, -128);
355 }
356
357 // Test where works: INT8_MAX
358 {
359 const json element = R"( 127 )"_json;
360 int8_t value = parseInt8(element);
361 EXPECT_EQ(value, 127);
362 }
363
364 // Test where fails: Element is not an integer
365 try
366 {
367 const json element = R"( 1.03 )"_json;
368 parseInt8(element);
369 ADD_FAILURE() << "Should not have reached this line.";
370 }
371 catch (const std::invalid_argument& e)
372 {
373 EXPECT_STREQ(e.what(), "Element is not an integer");
374 }
375
376 // Test where fails: Value < INT8_MIN
377 try
378 {
379 const json element = R"( -129 )"_json;
380 parseInt8(element);
381 ADD_FAILURE() << "Should not have reached this line.";
382 }
383 catch (const std::invalid_argument& e)
384 {
385 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
386 }
387
388 // Test where fails: Value > INT8_MAX
389 try
390 {
391 const json element = R"( 128 )"_json;
392 parseInt8(element);
393 ADD_FAILURE() << "Should not have reached this line.";
394 }
395 catch (const std::invalid_argument& e)
396 {
397 EXPECT_STREQ(e.what(), "Element is not an 8-bit signed integer");
398 }
399}
400
401TEST(JSONParserUtilsTests, ParseString)
402{
403 // Test where works: Empty string
404 {
405 const json element = "";
406 std::string value = parseString(element, true);
407 EXPECT_EQ(value, "");
408 }
409
410 // Test where works: Non-empty string
411 {
412 const json element = "vdd_regulator";
413 std::string value = parseString(element, false);
414 EXPECT_EQ(value, "vdd_regulator");
415 }
416
417 // Test where fails: Element is not a string
418 try
419 {
420 const json element = R"( { "foo": "bar" } )"_json;
421 parseString(element);
422 ADD_FAILURE() << "Should not have reached this line.";
423 }
424 catch (const std::invalid_argument& e)
425 {
426 EXPECT_STREQ(e.what(), "Element is not a string");
427 }
428
429 // Test where fails: Empty string
430 try
431 {
432 const json element = "";
433 parseString(element);
434 ADD_FAILURE() << "Should not have reached this line.";
435 }
436 catch (const std::invalid_argument& e)
437 {
438 EXPECT_STREQ(e.what(), "Element contains an empty string");
439 }
440}
441
442TEST(JSONParserUtilsTests, ParseUint8)
443{
444 // Test where works: 0
445 {
446 const json element = R"( 0 )"_json;
447 uint8_t value = parseUint8(element);
448 EXPECT_EQ(value, 0);
449 }
450
451 // Test where works: UINT8_MAX
452 {
453 const json element = R"( 255 )"_json;
454 uint8_t value = parseUint8(element);
455 EXPECT_EQ(value, 255);
456 }
457
458 // Test where fails: Element is not an integer
459 try
460 {
461 const json element = R"( 1.03 )"_json;
462 parseUint8(element);
463 ADD_FAILURE() << "Should not have reached this line.";
464 }
465 catch (const std::invalid_argument& e)
466 {
467 EXPECT_STREQ(e.what(), "Element is not an integer");
468 }
469
470 // Test where fails: Value < 0
471 try
472 {
473 const json element = R"( -1 )"_json;
474 parseUint8(element);
475 ADD_FAILURE() << "Should not have reached this line.";
476 }
477 catch (const std::invalid_argument& e)
478 {
479 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
480 }
481
482 // Test where fails: Value > UINT8_MAX
483 try
484 {
485 const json element = R"( 256 )"_json;
486 parseUint8(element);
487 ADD_FAILURE() << "Should not have reached this line.";
488 }
489 catch (const std::invalid_argument& e)
490 {
491 EXPECT_STREQ(e.what(), "Element is not an 8-bit unsigned integer");
492 }
493}
494
495TEST(JSONParserUtilsTests, ParseUnsignedInteger)
496{
497 // Test where works: 1
498 {
499 const json element = R"( 1 )"_json;
500 unsigned int value = parseUnsignedInteger(element);
501 EXPECT_EQ(value, 1);
502 }
503
504 // Test where fails: Element is not an integer
505 try
506 {
507 const json element = R"( 1.5 )"_json;
508 parseUnsignedInteger(element);
509 ADD_FAILURE() << "Should not have reached this line.";
510 }
511 catch (const std::invalid_argument& e)
512 {
513 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
514 }
515
516 // Test where fails: Value < 0
517 try
518 {
519 const json element = R"( -1 )"_json;
520 parseUnsignedInteger(element);
521 ADD_FAILURE() << "Should not have reached this line.";
522 }
523 catch (const std::invalid_argument& e)
524 {
525 EXPECT_STREQ(e.what(), "Element is not an unsigned integer");
526 }
527}
528
529TEST(JSONParserUtilsTests, VerifyIsArray)
530{
531 // Test where element is an array
532 {
533 const json element = R"( [ "foo", "bar" ] )"_json;
534 verifyIsArray(element);
535 }
536
537 // Test where element is not an array
538 try
539 {
540 const json element = R"( { "foo": "bar" } )"_json;
541 verifyIsArray(element);
542 ADD_FAILURE() << "Should not have reached this line.";
543 }
544 catch (const std::invalid_argument& e)
545 {
546 EXPECT_STREQ(e.what(), "Element is not an array");
547 }
548}
549
550TEST(JSONParserUtilsTests, VerifyIsObject)
551{
552 // Test where element is an object
553 {
554 const json element = R"( { "foo": "bar" } )"_json;
555 verifyIsObject(element);
556 }
557
558 // Test where element is not an object
559 try
560 {
561 const json element = R"( [ "foo", "bar" ] )"_json;
562 verifyIsObject(element);
563 ADD_FAILURE() << "Should not have reached this line.";
564 }
565 catch (const std::invalid_argument& e)
566 {
567 EXPECT_STREQ(e.what(), "Element is not an object");
568 }
569}
570
571TEST(JSONParserUtilsTests, VerifyPropertyCount)
572{
573 // Test where element has expected number of properties
574 {
575 const json element = R"(
576 {
577 "comments": [ "Set voltage rule" ],
578 "id": "set_voltage_rule"
579 }
580 )"_json;
581 verifyPropertyCount(element, 2);
582 }
583
584 // Test where element has unexpected number of properties
585 try
586 {
587 const json element = R"(
588 {
589 "comments": [ "Set voltage rule" ],
590 "id": "set_voltage_rule",
591 "foo": 1.3
592 }
593 )"_json;
594 verifyPropertyCount(element, 2);
595 ADD_FAILURE() << "Should not have reached this line.";
596 }
597 catch (const std::invalid_argument& e)
598 {
599 EXPECT_STREQ(e.what(), "Element contains an invalid property");
600 }
601}