summaryrefslogtreecommitdiff
path: root/test-csv.c
diff options
context:
space:
mode:
Diffstat (limited to 'test-csv.c')
-rw-r--r--test-csv.c471
1 files changed, 471 insertions, 0 deletions
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 <stdio.h>
+
+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