]> git.proxmox.com Git - efi-boot-shim.git/blob - test-csv.c
Prep for releasing based on 15.4
[efi-boot-shim.git] / test-csv.c
1 // SPDX-License-Identifier: BSD-2-Clause-Patent
2 /*
3 * test-csv.c - test our csv parser
4 */
5
6 #ifndef SHIM_UNIT_TEST
7 #define SHIM_UNIT_TEST
8 #endif
9 #include "shim.h"
10
11 #include <stdio.h>
12
13 struct test_entry {
14 size_t n_columns;
15 char *columns[7];
16 };
17
18 int
19 test_parse_csv_line_size_0(void)
20 {
21 char *s0 = "";
22 char *columns[] = { "a", "b", "c", "d" };
23 char *test_columns[] = { NULL, NULL, NULL, NULL };
24 size_t n_columns = 3;
25 size_t i;
26
27 test_columns[3] = columns[3];
28
29 parse_csv_line(s0, 0, &n_columns, (const char **)columns);
30
31 assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n");
32 assert_equal_return(n_columns, 0, -1, "got %#hhx expected %#hhx\n");
33 for (i = 0; i < 4; i++) {
34 assert_equal_return(test_columns[i], columns[i], -1,
35 "expected %p got %p for column %d\n",
36 i);
37 }
38 return 0;
39 }
40
41 int
42 test_parse_csv_line_size_1(void)
43 {
44 char *s0 = "";
45 char *columns[] = { "a", "b", "c", "d" };
46 char *test_columns[] = { "", NULL, NULL, NULL };
47 size_t n_columns = 3;
48 size_t max = 1;
49 size_t i;
50
51 test_columns[3] = columns[3];
52
53 parse_csv_line(s0, max, &n_columns, (const char **)columns);
54
55 assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n");
56 assert_equal_return(n_columns, 1, -1, "got %#hhx expected %#hhx\n");
57 for (i = 0; i < 4; i++) {
58 assert_equal_return(test_columns[i], columns[i], -1,
59 "expected %p got %p for column %d\n",
60 i);
61 }
62 return 0;
63 }
64
65 int
66 test_parse_csv_line_comma_size_1(void)
67 {
68 char *s0;
69 char *columns[] = { "a", "b", "c", "d" };
70 char *test_columns[] = { "", NULL, NULL, "d" };
71 size_t n_columns = 3;
72 size_t max = 1;
73 size_t i;
74
75 /*
76 * For reasons unknown, when I do this the normal way with:
77 * char *s0 = ",";
78 * gcc is putting it in .rodata,
79 * *** AND combining it with the "," from delims from parse_csv_line***.
80 */
81 s0 = alloca(2);
82 s0[0] = ',';
83 s0[1] = '\0';
84
85 parse_csv_line(s0, max, &n_columns, (const char **)columns);
86
87 assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n");
88 assert_equal_return(n_columns, 1, -1, "got %#hhx expected %#hhx\n");
89 // for (i = 0; i < 4; i++) {
90 // printf("columns[%d]:%p:\"%s\"\n", i, columns[i], columns[i]);
91 // }
92 for (i = 0; i < 1; i++) {
93 assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1,
94 "expected %d got %d for column %d\n", i);
95 }
96 for (i = 1; i < 3; i++) {
97 assert_equal_return(test_columns[i], columns[i], -1,
98 "expected %p got %p for column %d\n",
99 i);
100 }
101 for (i = 3; i < 4; i++) {
102 assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1,
103 "expected %d got %d for column %d\n", i);
104 }
105
106 return 0;
107 }
108
109 int
110 test_parse_csv_line_comma_size_2(void)
111 {
112 char *s0;
113 char *columns[] = { "a", "b", "c", "d" };
114 char *test_columns[] = { "", "", NULL, "d" };
115 size_t n_columns = 3;
116 size_t max = 2;
117 size_t i;
118
119 /*
120 * For reasons unknown, when I do this the normal way with:
121 * char *s0 = ",";
122 * gcc is putting it in .rodata,
123 * *** AND combining it with the "," from delims from parse_csv_line***.
124 */
125 s0 = alloca(2);
126 s0[0] = ',';
127 s0[1] = '\0';
128
129 parse_csv_line(s0, max, &n_columns, (const char **)columns);
130
131 assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n");
132 assert_equal_return(n_columns, 2, -1, "got %#hhx expected %#hhx\n");
133 for (i = 0; i < 2; i++) {
134 assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1,
135 "expected %d got %d for column %d\n", i);
136 }
137 for (i = 2; i < 3; i++) {
138 assert_equal_return(test_columns[i], columns[i], -1,
139 "expected %p got %p for column %d\n",
140 i);
141 }
142 for (i = 3; i < 4; i++) {
143 assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1,
144 "expected %d got %d for column %d\n", i);
145 }
146
147 return 0;
148 }
149
150 int
151 test_csv_0(void)
152 {
153 char csv[] =
154 "\000\000\000"
155 "a,b,c,d,e,f,g,h\n"
156 "a,b,c\n"
157 "\n"
158 "\n"
159 "a,b,c,d,e,f,g,h\n"
160 "a,b,c";
161 struct test_entry test_entries[]= {
162 { 7, { "a", "b", "c", "d", "e", "f", "g" } },
163 { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
164 { 7, { "a", "b", "c", "d", "e", "f", "g" } },
165 { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
166 };
167 list_t entry_list;
168 size_t i;
169 char *current, *end;
170 list_t *pos = NULL;
171 EFI_STATUS efi_status;
172
173 INIT_LIST_HEAD(&entry_list);
174 assert_equal_return(list_size(&entry_list), 0, -1,
175 "got %d expected %d\n");
176
177 memcpy(csv, (char [])UTF8_BOM, UTF8_BOM_SIZE);
178
179 current = csv;
180 end = csv + sizeof(csv) - 1;
181
182 efi_status = parse_csv_data(current, end, 7, &entry_list);
183 assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n");
184
185 i = 0;
186 list_for_each(pos, &entry_list) {
187 struct csv_row *csv_row;
188 struct test_entry *test_entry = &test_entries[i++];
189 size_t j;
190
191 assert_goto(i > 0 && i <= 4, fail, "got %d expected 0 to 4\n", i);
192
193 csv_row = list_entry(pos, struct csv_row, list);
194
195 assert_equal_goto(csv_row->n_columns, test_entry->n_columns,
196 fail, "got %d expected %d\n");
197 for (j = 0; j < csv_row->n_columns; j++) {
198 assert_equal_goto(strcmp(csv_row->columns[j],
199 test_entry->columns[j]), 0,
200 fail, "got %d expected %d\n");
201 }
202 }
203
204 assert_equal_return(list_size(&entry_list), 4, -1,
205 "got %d expected %d\n");
206 free_csv_list(&entry_list);
207 assert_equal_return(list_size(&entry_list), 0, -1,
208 "got %d expected %d\n");
209 return 0;
210 fail:
211 free_csv_list(&entry_list);
212 return -1;
213 }
214
215 int
216 test_csv_1(void)
217 {
218 char csv[] =
219 "a,b,c,d,e,f,g,h\n"
220 "a,b,c\n"
221 "\n"
222 "\n"
223 "a,b,c,d,e,f,g,h\n"
224 "a,b,c";
225 struct test_entry test_entries[]= {
226 { 7, { "a", "b", "c", "d", "e", "f", "g" } },
227 { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
228 { 7, { "a", "b", "c", "d", "e", "f", "g" } },
229 { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
230 };
231 list_t entry_list;
232 size_t i;
233 char *current, *end;
234 list_t *pos = NULL;
235 EFI_STATUS efi_status;
236
237 INIT_LIST_HEAD(&entry_list);
238 assert_equal_return(list_size(&entry_list), 0, -1,
239 "got %d expected %d\n");
240
241 current = csv;
242 end = csv + sizeof(csv) - 1;
243
244 efi_status = parse_csv_data(current, end, 7, &entry_list);
245 assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n");
246
247 i = 0;
248 list_for_each(pos, &entry_list) {
249 struct csv_row *csv_row;
250 struct test_entry *test_entry = &test_entries[i++];
251 size_t j;
252
253 assert_goto(i > 0 && i <= 4, fail, "got %d expected 0 to 4\n", i);
254
255 csv_row = list_entry(pos, struct csv_row, list);
256
257 assert_equal_goto(csv_row->n_columns, test_entry->n_columns,
258 fail, "got %d expected %d\n");
259 for (j = 0; j < csv_row->n_columns; j++) {
260 assert_equal_goto(strcmp(csv_row->columns[j],
261 test_entry->columns[j]), 0,
262 fail, "got %d expected %d\n");
263 }
264 }
265
266 assert_equal_return(list_size(&entry_list), 4, -1,
267 "got %d expected %d\n");
268 free_csv_list(&entry_list);
269 assert_equal_return(list_size(&entry_list), 0, -1,
270 "got %d expected %d\n");
271 return 0;
272 fail:
273 free_csv_list(&entry_list);
274 return -1;
275 }
276
277 int
278 test_csv_2(void)
279 {
280 char csv[] =
281 "\000\000\000"
282 "a,b,c,d,e,f,g,h\n"
283 ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,c\n"
284 "\n"
285 "\n"
286 "a,b,c,d,e,f,g,h\n"
287 "a,b,c";
288 struct test_entry test_entries[]= {
289 { 7, { "a", "b", "c", "d", "e", "f", "g" } },
290 { 7, { "", "", "", "", "", "", "" } },
291 { 7, { "a", "b", "c", "d", "e", "f", "g" } },
292 { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } },
293 };
294 list_t entry_list;
295 size_t i;
296 char *current, *end;
297 list_t *pos = NULL;
298 EFI_STATUS efi_status;
299
300 INIT_LIST_HEAD(&entry_list);
301 assert_equal_return(list_size(&entry_list), 0, -1,
302 "got %d expected %d\n");
303
304 memcpy(csv, (char [])UTF8_BOM, UTF8_BOM_SIZE);
305
306 current = csv;
307 end = csv + sizeof(csv) - 1;
308
309 efi_status = parse_csv_data(current, end, 7, &entry_list);
310 assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n");
311
312 i = 0;
313 list_for_each(pos, &entry_list) {
314 struct csv_row *csv_row;
315 struct test_entry *test_entry = &test_entries[i++];
316 size_t j;
317
318 assert_goto(i > 0 && i <= 7, fail, "got %d expected 0 to 7\n", i);
319 csv_row = list_entry(pos, struct csv_row, list);
320
321 assert_equal_goto(csv_row->n_columns, test_entry->n_columns,
322 fail, "got %d expected %d\n");
323 for (j = 0; j < csv_row->n_columns; j++) {
324 assert_equal_goto(strcmp(csv_row->columns[j],
325 test_entry->columns[j]), 0,
326 fail, "got %d expected %d\n");
327 }
328 }
329
330 free_csv_list(&entry_list);
331 assert_equal_return(list_size(&entry_list), 0, -1,
332 "got %d expected %d\n");
333
334 return 0;
335 fail:
336 free_csv_list(&entry_list);
337 return -1;
338 }
339
340 int
341 test_simple_sbat_csv(void)
342 {
343 char csv[] =
344 "test1,1,SBAT test1,acme1,1,testURL1\n"
345 "test2,2,SBAT test2,acme2,2,testURL2\n";
346 struct test_entry test_entries[]= {
347 { 6, { "test1", "1", "SBAT test1", "acme1", "1", "testURL1" } },
348 { 6, { "test2", "2", "SBAT test2", "acme2", "2", "testURL2" } },
349 };
350 list_t entry_list;
351 size_t i;
352 char *current, *end;
353 list_t *pos = NULL;
354 EFI_STATUS efi_status;
355
356 INIT_LIST_HEAD(&entry_list);
357 assert_equal_return(list_size(&entry_list), 0, -1,
358 "got %d expected %d\n");
359
360 current = csv;
361 end = csv + sizeof(csv) - 1;
362
363 efi_status = parse_csv_data(current, end, 6, &entry_list);
364 assert_equal_return(efi_status, EFI_SUCCESS, -1,
365 "got %d expected %d\n");
366
367 i = 0;
368 list_for_each(pos, &entry_list) {
369 struct csv_row *csv_row;
370 struct test_entry *test_entry = &test_entries[i++];
371 size_t j;
372
373 csv_row = list_entry(pos, struct csv_row, list);
374
375 assert_equal_goto(csv_row->n_columns, test_entry->n_columns,
376 fail, "got %d expected %d");
377
378 for (j = 0; j < csv_row->n_columns; j++) {
379 assert_equal_goto(strcmp(csv_row->columns[j],
380 test_entry->columns[j]), 0,
381 fail, "got %d expected %d\n");
382 }
383 }
384
385 assert_equal_return(list_size(&entry_list), 2, -1,
386 "got %d expected %d\n");
387 free_csv_list(&entry_list);
388 assert_equal_return(list_size(&entry_list), 0, -1,
389 "got %d expected %d\n");
390
391 return 0;
392 fail:
393 free_csv_list(&entry_list);
394 return -1;
395
396 }
397
398 int
399 test_csv_simple_fuzz(char *random_bin, size_t random_bin_len,
400 bool assert_entries)
401 {
402 list_t entry_list;
403 size_t i;
404 char *current, *end;
405 list_t *pos = NULL;
406 EFI_STATUS efi_status;
407
408 INIT_LIST_HEAD(&entry_list);
409 assert_equal_return(list_size(&entry_list), 0, -1,
410 "got %d expected %d\n");
411
412 current = &random_bin[0];
413 current = current + 1 - 1;
414 end = current + random_bin_len - 1;
415 *end = '\0';
416
417 efi_status = parse_csv_data(current, end, 7, &entry_list);
418 assert_equal_return(efi_status, EFI_SUCCESS, -1, "expected %#x got %#x\n");
419 printf("parsed %zd entries\n", list_size(&entry_list));
420 if (assert_entries)
421 assert_goto(list_size(&entry_list) > 0, fail,
422 "expected >0 entries\n");
423
424 i = 0;
425 list_for_each(pos, &entry_list) {
426 struct csv_row *csv_row;
427
428 csv_row = list_entry(pos, struct csv_row, list);
429 dprint("row[%zd]: %zd columns\n", i, csv_row->n_columns);
430 i++;
431 }
432
433 free_csv_list(&entry_list);
434 assert_equal_return(list_size(&entry_list), 0, -1,
435 "got %d expected %d\n");
436
437 return 0;
438 fail:
439 free_csv_list(&entry_list);
440 return -1;
441 }
442
443 #include "test-random.h"
444
445 int
446 main(void)
447 {
448 int status = 0;
449 size_t i, j;
450
451 setbuf(stdout, NULL);
452 test(test_parse_csv_line_size_0);
453 test(test_parse_csv_line_size_1);
454 test(test_parse_csv_line_comma_size_1);
455 test(test_parse_csv_line_comma_size_2);
456 test(test_csv_0);
457 test(test_csv_1);
458 test(test_csv_2);
459 test(test_simple_sbat_csv);
460 test(test_csv_simple_fuzz, random_bin, random_bin_len, false);
461 for (i = 0; i < random_bin_len; i++) {
462 j = i;
463 while (random_bin[i] == '\0')
464 random_bin[i] = j++;
465 }
466 test(test_csv_simple_fuzz, random_bin, random_bin_len, true);
467
468 return status;
469 }
470
471 // vim:fenc=utf-8:tw=75:noet