xref: /openbmc/libcper/tests/hex_test.c (revision 51c1813200b42fa35d49eb0c214339ac479f090d)
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