From 031e5cce385d3f96b1caa1d53495332a7eb03749 Mon Sep 17 00:00:00 2001 From: Steve McIntyre Date: Tue, 23 Mar 2021 23:49:46 +0000 Subject: New upstream version 15.3 --- test-csv.c | 471 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 471 insertions(+) create mode 100644 test-csv.c (limited to 'test-csv.c') diff --git a/test-csv.c b/test-csv.c new file mode 100644 index 00000000..4acf966b --- /dev/null +++ b/test-csv.c @@ -0,0 +1,471 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * test-csv.c - test our csv parser + */ + +#ifndef SHIM_UNIT_TEST +#define SHIM_UNIT_TEST +#endif +#include "shim.h" + +#include + +struct test_entry { + size_t n_columns; + char *columns[7]; +}; + +int +test_parse_csv_line_size_0(void) +{ + char *s0 = ""; + char *columns[] = { "a", "b", "c", "d" }; + char *test_columns[] = { NULL, NULL, NULL, NULL }; + size_t n_columns = 3; + size_t i; + + test_columns[3] = columns[3]; + + parse_csv_line(s0, 0, &n_columns, (const char **)columns); + + assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n"); + assert_equal_return(n_columns, 0, -1, "got %#hhx expected %#hhx\n"); + for (i = 0; i < 4; i++) { + assert_equal_return(test_columns[i], columns[i], -1, + "expected %p got %p for column %d\n", + i); + } + return 0; +} + +int +test_parse_csv_line_size_1(void) +{ + char *s0 = ""; + char *columns[] = { "a", "b", "c", "d" }; + char *test_columns[] = { "", NULL, NULL, NULL }; + size_t n_columns = 3; + size_t max = 1; + size_t i; + + test_columns[3] = columns[3]; + + parse_csv_line(s0, max, &n_columns, (const char **)columns); + + assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n"); + assert_equal_return(n_columns, 1, -1, "got %#hhx expected %#hhx\n"); + for (i = 0; i < 4; i++) { + assert_equal_return(test_columns[i], columns[i], -1, + "expected %p got %p for column %d\n", + i); + } + return 0; +} + +int +test_parse_csv_line_comma_size_1(void) +{ + char *s0; + char *columns[] = { "a", "b", "c", "d" }; + char *test_columns[] = { "", NULL, NULL, "d" }; + size_t n_columns = 3; + size_t max = 1; + size_t i; + + /* + * For reasons unknown, when I do this the normal way with: + * char *s0 = ","; + * gcc is putting it in .rodata, + * *** AND combining it with the "," from delims from parse_csv_line***. + */ + s0 = alloca(2); + s0[0] = ','; + s0[1] = '\0'; + + parse_csv_line(s0, max, &n_columns, (const char **)columns); + + assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n"); + assert_equal_return(n_columns, 1, -1, "got %#hhx expected %#hhx\n"); +// for (i = 0; i < 4; i++) { +// printf("columns[%d]:%p:\"%s\"\n", i, columns[i], columns[i]); +// } + for (i = 0; i < 1; i++) { + assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1, + "expected %d got %d for column %d\n", i); + } + for (i = 1; i < 3; i++) { + assert_equal_return(test_columns[i], columns[i], -1, + "expected %p got %p for column %d\n", + i); + } + for (i = 3; i < 4; i++) { + assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1, + "expected %d got %d for column %d\n", i); + } + + return 0; +} + +int +test_parse_csv_line_comma_size_2(void) +{ + char *s0; + char *columns[] = { "a", "b", "c", "d" }; + char *test_columns[] = { "", "", NULL, "d" }; + size_t n_columns = 3; + size_t max = 2; + size_t i; + + /* + * For reasons unknown, when I do this the normal way with: + * char *s0 = ","; + * gcc is putting it in .rodata, + * *** AND combining it with the "," from delims from parse_csv_line***. + */ + s0 = alloca(2); + s0[0] = ','; + s0[1] = '\0'; + + parse_csv_line(s0, max, &n_columns, (const char **)columns); + + assert_equal_return(s0[0], '\0', -1, "got %#hhx expected %#hhx\n"); + assert_equal_return(n_columns, 2, -1, "got %#hhx expected %#hhx\n"); + for (i = 0; i < 2; i++) { + assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1, + "expected %d got %d for column %d\n", i); + } + for (i = 2; i < 3; i++) { + assert_equal_return(test_columns[i], columns[i], -1, + "expected %p got %p for column %d\n", + i); + } + for (i = 3; i < 4; i++) { + assert_equal_return(strcmp(test_columns[i], columns[i]), 0, -1, + "expected %d got %d for column %d\n", i); + } + + return 0; +} + +int +test_csv_0(void) +{ + char csv[] = + "\000\000\000" + "a,b,c,d,e,f,g,h\n" + "a,b,c\n" + "\n" + "\n" + "a,b,c,d,e,f,g,h\n" + "a,b,c"; + struct test_entry test_entries[]= { + { 7, { "a", "b", "c", "d", "e", "f", "g" } }, + { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } }, + { 7, { "a", "b", "c", "d", "e", "f", "g" } }, + { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } }, + }; + list_t entry_list; + size_t i; + char *current, *end; + list_t *pos = NULL; + EFI_STATUS efi_status; + + INIT_LIST_HEAD(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + + memcpy(csv, (char [])UTF8_BOM, UTF8_BOM_SIZE); + + current = csv; + end = csv + sizeof(csv) - 1; + + efi_status = parse_csv_data(current, end, 7, &entry_list); + assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n"); + + i = 0; + list_for_each(pos, &entry_list) { + struct csv_row *csv_row; + struct test_entry *test_entry = &test_entries[i++]; + size_t j; + + assert_goto(i > 0 && i <= 4, fail, "got %d expected 0 to 4\n", i); + + csv_row = list_entry(pos, struct csv_row, list); + + assert_equal_goto(csv_row->n_columns, test_entry->n_columns, + fail, "got %d expected %d\n"); + for (j = 0; j < csv_row->n_columns; j++) { + assert_equal_goto(strcmp(csv_row->columns[j], + test_entry->columns[j]), 0, + fail, "got %d expected %d\n"); + } + } + + assert_equal_return(list_size(&entry_list), 4, -1, + "got %d expected %d\n"); + free_csv_list(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + return 0; +fail: + free_csv_list(&entry_list); + return -1; +} + +int +test_csv_1(void) +{ + char csv[] = + "a,b,c,d,e,f,g,h\n" + "a,b,c\n" + "\n" + "\n" + "a,b,c,d,e,f,g,h\n" + "a,b,c"; + struct test_entry test_entries[]= { + { 7, { "a", "b", "c", "d", "e", "f", "g" } }, + { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } }, + { 7, { "a", "b", "c", "d", "e", "f", "g" } }, + { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } }, + }; + list_t entry_list; + size_t i; + char *current, *end; + list_t *pos = NULL; + EFI_STATUS efi_status; + + INIT_LIST_HEAD(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + + current = csv; + end = csv + sizeof(csv) - 1; + + efi_status = parse_csv_data(current, end, 7, &entry_list); + assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n"); + + i = 0; + list_for_each(pos, &entry_list) { + struct csv_row *csv_row; + struct test_entry *test_entry = &test_entries[i++]; + size_t j; + + assert_goto(i > 0 && i <= 4, fail, "got %d expected 0 to 4\n", i); + + csv_row = list_entry(pos, struct csv_row, list); + + assert_equal_goto(csv_row->n_columns, test_entry->n_columns, + fail, "got %d expected %d\n"); + for (j = 0; j < csv_row->n_columns; j++) { + assert_equal_goto(strcmp(csv_row->columns[j], + test_entry->columns[j]), 0, + fail, "got %d expected %d\n"); + } + } + + assert_equal_return(list_size(&entry_list), 4, -1, + "got %d expected %d\n"); + free_csv_list(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + return 0; +fail: + free_csv_list(&entry_list); + return -1; +} + +int +test_csv_2(void) +{ + char csv[] = + "\000\000\000" + "a,b,c,d,e,f,g,h\n" + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,c\n" + "\n" + "\n" + "a,b,c,d,e,f,g,h\n" + "a,b,c"; + struct test_entry test_entries[]= { + { 7, { "a", "b", "c", "d", "e", "f", "g" } }, + { 7, { "", "", "", "", "", "", "" } }, + { 7, { "a", "b", "c", "d", "e", "f", "g" } }, + { 3, { "a", "b", "c", NULL, NULL, NULL, NULL } }, + }; + list_t entry_list; + size_t i; + char *current, *end; + list_t *pos = NULL; + EFI_STATUS efi_status; + + INIT_LIST_HEAD(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + + memcpy(csv, (char [])UTF8_BOM, UTF8_BOM_SIZE); + + current = csv; + end = csv + sizeof(csv) - 1; + + efi_status = parse_csv_data(current, end, 7, &entry_list); + assert_equal_return(efi_status, EFI_SUCCESS, -1, "got %x expected %x\n"); + + i = 0; + list_for_each(pos, &entry_list) { + struct csv_row *csv_row; + struct test_entry *test_entry = &test_entries[i++]; + size_t j; + + assert_goto(i > 0 && i <= 7, fail, "got %d expected 0 to 7\n", i); + csv_row = list_entry(pos, struct csv_row, list); + + assert_equal_goto(csv_row->n_columns, test_entry->n_columns, + fail, "got %d expected %d\n"); + for (j = 0; j < csv_row->n_columns; j++) { + assert_equal_goto(strcmp(csv_row->columns[j], + test_entry->columns[j]), 0, + fail, "got %d expected %d\n"); + } + } + + free_csv_list(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + + return 0; +fail: + free_csv_list(&entry_list); + return -1; +} + +int +test_simple_sbat_csv(void) +{ + char csv[] = + "test1,1,SBAT test1,acme1,1,testURL1\n" + "test2,2,SBAT test2,acme2,2,testURL2\n"; + struct test_entry test_entries[]= { + { 6, { "test1", "1", "SBAT test1", "acme1", "1", "testURL1" } }, + { 6, { "test2", "2", "SBAT test2", "acme2", "2", "testURL2" } }, + }; + list_t entry_list; + size_t i; + char *current, *end; + list_t *pos = NULL; + EFI_STATUS efi_status; + + INIT_LIST_HEAD(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + + current = csv; + end = csv + sizeof(csv) - 1; + + efi_status = parse_csv_data(current, end, 6, &entry_list); + assert_equal_return(efi_status, EFI_SUCCESS, -1, + "got %d expected %d\n"); + + i = 0; + list_for_each(pos, &entry_list) { + struct csv_row *csv_row; + struct test_entry *test_entry = &test_entries[i++]; + size_t j; + + csv_row = list_entry(pos, struct csv_row, list); + + assert_equal_goto(csv_row->n_columns, test_entry->n_columns, + fail, "got %d expected %d"); + + for (j = 0; j < csv_row->n_columns; j++) { + assert_equal_goto(strcmp(csv_row->columns[j], + test_entry->columns[j]), 0, + fail, "got %d expected %d\n"); + } + } + + assert_equal_return(list_size(&entry_list), 2, -1, + "got %d expected %d\n"); + free_csv_list(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + + return 0; +fail: + free_csv_list(&entry_list); + return -1; + +} + +int +test_csv_simple_fuzz(char *random_bin, size_t random_bin_len, + bool assert_entries) +{ + list_t entry_list; + size_t i; + char *current, *end; + list_t *pos = NULL; + EFI_STATUS efi_status; + + INIT_LIST_HEAD(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + + current = &random_bin[0]; + current = current + 1 - 1; + end = current + random_bin_len - 1; + *end = '\0'; + + efi_status = parse_csv_data(current, end, 7, &entry_list); + assert_equal_return(efi_status, EFI_SUCCESS, -1, "expected %#x got %#x\n"); + printf("parsed %zd entries\n", list_size(&entry_list)); + if (assert_entries) + assert_goto(list_size(&entry_list) > 0, fail, + "expected >0 entries\n"); + + i = 0; + list_for_each(pos, &entry_list) { + struct csv_row *csv_row; + + csv_row = list_entry(pos, struct csv_row, list); + dprint("row[%zd]: %zd columns\n", i, csv_row->n_columns); + i++; + } + + free_csv_list(&entry_list); + assert_equal_return(list_size(&entry_list), 0, -1, + "got %d expected %d\n"); + + return 0; +fail: + free_csv_list(&entry_list); + return -1; +} + +#include "test-random.h" + +int +main(void) +{ + int status = 0; + size_t i, j; + + setbuf(stdout, NULL); + test(test_parse_csv_line_size_0); + test(test_parse_csv_line_size_1); + test(test_parse_csv_line_comma_size_1); + test(test_parse_csv_line_comma_size_2); + test(test_csv_0); + test(test_csv_1); + test(test_csv_2); + test(test_simple_sbat_csv); + test(test_csv_simple_fuzz, random_bin, random_bin_len, false); + for (i = 0; i < random_bin_len; i++) { + j = i; + while (random_bin[i] == '\0') + random_bin[i] = j++; + } + test(test_csv_simple_fuzz, random_bin, random_bin_len, true); + + return status; +} + +// vim:fenc=utf-8:tw=75:noet -- cgit v1.2.3