1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3
4 #include <libcper/cper-utils.h>
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <string.h>
10 #include <json.h>
11
12 // Test vectors: input bytes and expected hex strings
13 static const UINT8 test_bytes_1[] = { 0x00 };
14 static const char *test_hex_1 = "00";
15
16 static const UINT8 test_bytes_2[] = { 0xff };
17 static const char *test_hex_2 = "ff";
18
19 static const UINT8 test_bytes_3[] = { 0xde, 0xad, 0xbe, 0xef };
20 static const char *test_hex_3 = "deadbeef";
21
22 static const UINT8 test_bytes_4[] = { 0x01, 0x23, 0x45, 0x67,
23 0x89, 0xab, 0xcd, 0xef };
24 static const char *test_hex_4 = "0123456789abcdef";
25
26 static const UINT8 test_bytes_5[] = { 0x00, 0x00, 0x00, 0x00 };
27 static const char *test_hex_5 = "00000000";
28
29 // Test encoding: bytes -> hex string
test_hex_encode_good(void)30 void test_hex_encode_good(void)
31 {
32 printf("Testing hex encoding...\n");
33
34 // Test 1: Single zero byte
35 {
36 json_object *obj = json_object_new_object();
37 add_bytes_hex(obj, "data", test_bytes_1, sizeof(test_bytes_1));
38 json_object *field = json_object_object_get(obj, "data");
39 assert(field != NULL);
40 const char *hex = json_object_get_string(field);
41 assert(strcmp(hex, test_hex_1) == 0);
42 json_object_put(obj);
43 }
44
45 // Test 2: Single 0xFF byte
46 {
47 json_object *obj = json_object_new_object();
48 add_bytes_hex(obj, "data", test_bytes_2, sizeof(test_bytes_2));
49 json_object *field = json_object_object_get(obj, "data");
50 assert(field != NULL);
51 const char *hex = json_object_get_string(field);
52 assert(strcmp(hex, test_hex_2) == 0);
53 json_object_put(obj);
54 }
55
56 // Test 3: "deadbeef"
57 {
58 json_object *obj = json_object_new_object();
59 add_bytes_hex(obj, "data", test_bytes_3, sizeof(test_bytes_3));
60 json_object *field = json_object_object_get(obj, "data");
61 assert(field != NULL);
62 const char *hex = json_object_get_string(field);
63 assert(strcmp(hex, test_hex_3) == 0);
64 json_object_put(obj);
65 }
66
67 // Test 4: Full range 0-9, a-f
68 {
69 json_object *obj = json_object_new_object();
70 add_bytes_hex(obj, "data", test_bytes_4, sizeof(test_bytes_4));
71 json_object *field = json_object_object_get(obj, "data");
72 assert(field != NULL);
73 const char *hex = json_object_get_string(field);
74 assert(strcmp(hex, test_hex_4) == 0);
75 json_object_put(obj);
76 }
77
78 // Test 5: All zeros
79 {
80 json_object *obj = json_object_new_object();
81 add_bytes_hex(obj, "data", test_bytes_5, sizeof(test_bytes_5));
82 json_object *field = json_object_object_get(obj, "data");
83 assert(field != NULL);
84 const char *hex = json_object_get_string(field);
85 assert(strcmp(hex, test_hex_5) == 0);
86 json_object_put(obj);
87 }
88
89 printf("Hex encoding tests passed.\n");
90 }
91
92 // Test decoding: hex string -> bytes
test_hex_decode_good(void)93 void test_hex_decode_good(void)
94 {
95 printf("Testing hex decoding...\n");
96
97 // Test 1: Single zero byte
98 {
99 json_object *obj = json_object_new_object();
100 json_object_object_add(obj, "data",
101 json_object_new_string(test_hex_1));
102 size_t out_len = 0;
103 UINT8 *bytes = get_bytes_hex(obj, "data", &out_len);
104 assert(bytes != NULL);
105 assert(out_len == sizeof(test_bytes_1));
106 assert(memcmp(bytes, test_bytes_1, out_len) == 0);
107 free(bytes);
108 json_object_put(obj);
109 }
110
111 // Test 2: Single 0xFF byte
112 {
113 json_object *obj = json_object_new_object();
114 json_object_object_add(obj, "data",
115 json_object_new_string(test_hex_2));
116 size_t out_len = 0;
117 UINT8 *bytes = get_bytes_hex(obj, "data", &out_len);
118 assert(bytes != NULL);
119 assert(out_len == sizeof(test_bytes_2));
120 assert(memcmp(bytes, test_bytes_2, out_len) == 0);
121 free(bytes);
122 json_object_put(obj);
123 }
124
125 // Test 3: "deadbeef"
126 {
127 json_object *obj = json_object_new_object();
128 json_object_object_add(obj, "data",
129 json_object_new_string(test_hex_3));
130 size_t out_len = 0;
131 UINT8 *bytes = get_bytes_hex(obj, "data", &out_len);
132 assert(bytes != NULL);
133 assert(out_len == sizeof(test_bytes_3));
134 assert(memcmp(bytes, test_bytes_3, out_len) == 0);
135 free(bytes);
136 json_object_put(obj);
137 }
138
139 // Test 4: Full range with uppercase hex
140 {
141 json_object *obj = json_object_new_object();
142 json_object_object_add(
143 obj, "data",
144 json_object_new_string("0123456789ABCDEF"));
145 size_t out_len = 0;
146 UINT8 *bytes = get_bytes_hex(obj, "data", &out_len);
147 assert(bytes != NULL);
148 assert(out_len == sizeof(test_bytes_4));
149 assert(memcmp(bytes, test_bytes_4, out_len) == 0);
150 free(bytes);
151 json_object_put(obj);
152 }
153
154 // Test 5: Mixed case hex
155 {
156 json_object *obj = json_object_new_object();
157 json_object_object_add(obj, "data",
158 json_object_new_string("DeAdBeEf"));
159 size_t out_len = 0;
160 UINT8 *bytes = get_bytes_hex(obj, "data", &out_len);
161 assert(bytes != NULL);
162 assert(out_len == sizeof(test_bytes_3));
163 assert(memcmp(bytes, test_bytes_3, out_len) == 0);
164 free(bytes);
165 json_object_put(obj);
166 }
167
168 printf("Hex decoding tests passed.\n");
169 }
170
171 // Test error handling
test_hex_error_cases(void)172 void test_hex_error_cases(void)
173 {
174 printf("Testing hex error handling...\n");
175
176 // Test encode with NULL object
177 {
178 add_bytes_hex(NULL, "data", test_bytes_1, sizeof(test_bytes_1));
179 // Should not crash
180 }
181
182 // Test encode with NULL bytes
183 {
184 json_object *obj = json_object_new_object();
185 add_bytes_hex(obj, "data", NULL, 4);
186 json_object *field = json_object_object_get(obj, "data");
187 assert(field == NULL); // Should not add field
188 json_object_put(obj);
189 }
190
191 // Test encode with zero length
192 {
193 json_object *obj = json_object_new_object();
194 add_bytes_hex(obj, "data", test_bytes_1, 0);
195 json_object *field = json_object_object_get(obj, "data");
196 assert(field == NULL); // Should not add field
197 json_object_put(obj);
198 }
199
200 // Test decode with NULL object
201 {
202 size_t out_len = 0;
203 UINT8 *bytes = get_bytes_hex(NULL, "data", &out_len);
204 assert(bytes == NULL);
205 }
206
207 // Test decode with NULL out_len
208 {
209 json_object *obj = json_object_new_object();
210 json_object_object_add(obj, "data",
211 json_object_new_string("deadbeef"));
212 UINT8 *bytes = get_bytes_hex(obj, "data", NULL);
213 assert(bytes == NULL);
214 json_object_put(obj);
215 }
216
217 // Test decode with missing field
218 {
219 json_object *obj = json_object_new_object();
220 size_t out_len = 0;
221 UINT8 *bytes = get_bytes_hex(obj, "nonexistent", &out_len);
222 assert(bytes == NULL);
223 json_object_put(obj);
224 }
225
226 // Test decode with non-string field
227 {
228 json_object *obj = json_object_new_object();
229 json_object_object_add(obj, "data", json_object_new_int(12345));
230 size_t out_len = 0;
231 UINT8 *bytes = get_bytes_hex(obj, "data", &out_len);
232 assert(bytes == NULL);
233 json_object_put(obj);
234 }
235
236 // Test decode with odd-length hex string
237 {
238 json_object *obj = json_object_new_object();
239 json_object_object_add(obj, "data",
240 json_object_new_string("abc"));
241 size_t out_len = 0;
242 UINT8 *bytes = get_bytes_hex(obj, "data", &out_len);
243 assert(bytes == NULL); // Should fail - odd length
244 json_object_put(obj);
245 }
246
247 // Test decode with invalid hex character
248 {
249 json_object *obj = json_object_new_object();
250 json_object_object_add(obj, "data",
251 json_object_new_string("deadbXef"));
252 size_t out_len = 0;
253 UINT8 *bytes = get_bytes_hex(obj, "data", &out_len);
254 assert(bytes == NULL); // Should fail - 'X' is invalid
255 json_object_put(obj);
256 }
257
258 // Test decode with empty string
259 {
260 json_object *obj = json_object_new_object();
261 json_object_object_add(obj, "data", json_object_new_string(""));
262 size_t out_len = 0;
263 UINT8 *bytes = get_bytes_hex(obj, "data", &out_len);
264 // Empty string has even length (0), so it might succeed with 0 bytes
265 // Or fail - depends on implementation. Current impl should return empty buf
266 if (bytes != NULL) {
267 assert(out_len == 0);
268 free(bytes);
269 }
270 json_object_put(obj);
271 }
272
273 printf("Hex error handling tests passed.\n");
274 }
275
276 // Test round-trip: bytes -> hex -> bytes
test_hex_roundtrip(void)277 void test_hex_roundtrip(void)
278 {
279 printf("Testing hex round-trip...\n");
280
281 // Test with various byte patterns
282 UINT8 test_data[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
283 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
284
285 json_object *obj = json_object_new_object();
286 add_bytes_hex(obj, "roundtrip", test_data, sizeof(test_data));
287
288 size_t out_len = 0;
289 UINT8 *decoded = get_bytes_hex(obj, "roundtrip", &out_len);
290 assert(decoded != NULL);
291 assert(out_len == sizeof(test_data));
292 assert(memcmp(decoded, test_data, out_len) == 0);
293
294 free(decoded);
295 json_object_put(obj);
296
297 printf("Hex round-trip tests passed.\n");
298 }
299