diff --git a/.gitignore b/.gitignore index ad7502c..cf50ee5 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,9 @@ m4/lt~obsolete.m4 .libs *.la *.lo + +# Nica tests +check_array +check_hashmap +check_inifile +check_list diff --git a/Makefile.am b/Makefile.am index 481a62c..16b568a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,6 +11,13 @@ EXTRA_DIST = ${top_srcdir}/README.md \ ${top_srcdir}/tests/data/match1 \ ${top_srcdir}/tests/data/nomatch1 \ ${top_srcdir}/tests/data/nomatch2 \ + ${top_srcdir}/tests/data/ini/wellformed.ini \ + ${top_srcdir}/tests/data/ini/valid_padding.ini \ + ${top_srcdir}/tests/data/ini/sectionless.ini \ + ${top_srcdir}/tests/data/ini/empty_key.ini \ + ${top_srcdir}/tests/data/ini/just_assign.ini \ + ${top_srcdir}/tests/data/ini/broken_section_start.ini \ + ${top_srcdir}/tests/data/ini/broken_section_end.ini \ ${top_srcdir}/sgcheck.suppressions \ ${top_srcdir}/data/clr-boot-manager-booted.service \ ${top_srcdir}/compat/kernel_updater.sh \ @@ -158,7 +165,11 @@ distclean-local: TESTS = \ check_core \ check_files \ - check_updates + check_updates \ + check_array \ + check_list \ + check_hashmap \ + check_inifile check_PROGRAMS = $(TESTS) @@ -208,6 +219,51 @@ check_updates_LDADD = \ $(BLKID_LIBS) \ $(CHECK_LIBS) +# Nica tests +# Test array +check_array_SOURCES = \ + tests/check-array.c + +check_array_CFLAGS = \ + $(CHECK_CFLAGS) \ + $(AM_CFLAGS) + +check_array_LDADD = \ + $(CHECK_LIBS) + +# Test hashmap +check_hashmap_SOURCES = \ + tests/check-hashmap.c + +check_hashmap_CFLAGS = \ + $(CHECK_CFLAGS) \ + $(AM_CFLAGS) + +check_hashmap_LDADD = \ + $(CHECK_LIBS) + +# Test inifile +check_inifile_SOURCES = \ + tests/check-inifile.c + +check_inifile_CFLAGS = \ + $(CHECK_CFLAGS) \ + $(AM_CFLAGS) + +check_inifile_LDADD = \ + $(CHECK_LIBS) + +# Test list +check_list_SOURCES = \ + tests/check-list.c + +check_list_CFLAGS = \ + $(CHECK_CFLAGS) \ + $(AM_CFLAGS) + +check_list_LDADD = \ + $(CHECK_LIBS) + @VALGRIND_CHECK_RULES@ diff --git a/tests/check-array.c b/tests/check-array.c new file mode 100644 index 0000000..70d0273 --- /dev/null +++ b/tests/check-array.c @@ -0,0 +1,228 @@ +/* + * This file is part of libnica. + * + * Copyright (C) 2016 Intel Corporation + * + * libnica is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + */ + +#define _GNU_SOURCE +#include +#include +#include + +#include "nica/array.c" +#include "nica/util.c" + +START_TEST(nc_array_new_check) +{ + NcArray *array = NULL; + + array = nc_array_new(); + fail_if(!array, "Failed to allocate new array"); + fail_if(array->data, "array->data is not NULL after new"); + fail_if(array->len != 0, "array->len is not 0 after new"); + nc_array_free(&array, NULL); +} +END_TEST + +START_TEST(nc_array_free_check) +{ + NcArray *array = NULL; + + nc_array_free(&array, NULL); + fail_if(array, "Free changed NULL array to non NULL"); + /* Check to see if array free on NULL segfaults */ + nc_array_free(NULL, NULL); + array = nc_array_new(); + fail_if(!array, "Failed to allocate new array"); + nc_array_free(&array, NULL); + fail_if(array, "Failed to set array to NULL"); +} +END_TEST + +static inline void nc_array_free_fun(void *p) +{ + free(p); +} + +START_TEST(nc_array_add_check) +{ + NcArray *array = NULL; + int data1 = 1; + int data2 = 2; + int *data3 = NULL; + + fail_if(nc_array_add(NULL, &data1), "Added data to NULL array"); + array = nc_array_new(); + fail_if(!array, "Failed to allocate new array"); + fail_if(nc_array_add(array, NULL), "Added NULL data to array"); + fail_if(!nc_array_add(array, &data1), "Failed to add data1 to array"); + fail_if(!array->data, "Failed to allocate array->data"); + fail_if(array->len != 1, "Failed to update array->len with the size of the array"); + fail_if(*((int *)array->data[0]) != 1, "Failed to store correct data value to array"); + array->len = (uint16_t)(0 - 1); + fail_if(nc_array_add(array, &data1), "Able to add more than max number of elements"); + array->len = 1; + /* Test resize */ + fail_if(!nc_array_add(array, &data2), "Failed to add second element to array"); + fail_if(!array->data, "Failed to keep array->data"); + fail_if(array->len != 2, "Failed to update array->len with new size"); + fail_if(*((int *)array->data[0]) != 1, "Changed the first array element"); + fail_if(*((int *)array->data[1]) != 2, "Failed to set the second array element"); + nc_array_free(&array, NULL); + fail_if(array, "Failed to set array to NULL 1"); + data3 = malloc(sizeof(int)); + fail_if(!data3, "Failed to allocate data"); + *data3 = 3; + array = nc_array_new(); + fail_if(!array, "Failed to allocate new array"); + fail_if(!nc_array_add(array, data3), "Failed to add pointer data"); + fail_if(*((int *)array->data[0]) != 3, + "Failed to store correct pointer data value to array"); + nc_array_free(&array, nc_array_free_fun); + fail_if(array, "Failed to set array to NULL 2"); +} +END_TEST + +START_TEST(nc_array_get_check) +{ + NcArray *array = NULL; + int data1 = 1; + + array = nc_array_new(); + fail_if(!array, "Failed to allocate new array"); + fail_if(nc_array_get(NULL, 0), "Got data from NULL array"); + fail_if(nc_array_get(array, 0), "Got data from empty array"); + fail_if(!nc_array_add(array, &data1), "Failed to add data1 to array"); + fail_if(*((int *)nc_array_get(array, 0)) != 1, "Failed to get correct value for element 0"); + fail_if(nc_array_get(array, 1), "Got data past end of array"); + nc_array_free(&array, NULL); + fail_if(array, "Failed to set array to NULL"); +} +END_TEST + +START_TEST(nc_array_check) +{ + NcArray *array = NULL; + char *value; + char *element; + void *f; + bool r; + + array = nc_array_new(); + fail_if(array == NULL, "Failed to allocate memory for NcArray"); + element = strdup("test"); + fail_if(!element, "Failed to allocate memory for array item"); + r = nc_array_add(NULL, element); + fail_if(r, "Added element to NULL array"); + r = nc_array_add(array, NULL); + fail_if(r, "Added NULL element to array"); + r = nc_array_add(array, element); + fail_if(r == false, "Failed to add element to NcArray"); + fail_if(array->len != 1, "Failed to get correct value for number of elements in array"); + + f = nc_array_get(NULL, 0); + fail_if(f, "Got value from NULL array"); + f = nc_array_get(array, (uint16_t)(array->len + 1)); + fail_if(f, "Got value from index bigger than maximum index"); + value = (char *)nc_array_get(array, 0); + + fail_if(value == NULL, "Failed to get value from NcArray"); + + fail_if(strcmp(value, "test") != 0, "Failed to retrieve the stored value"); + + nc_array_free(&array, nc_array_free_fun); + fail_if(array != NULL, "Failed to free NcArray"); +} +END_TEST + +static int sort_strings(const void *a, const void *b) +{ + return strcmp(*(char **)a, *(char **)b); +} + +static int sort_strings_reverse(const void *a, const void *b) +{ + return strcmp(*(char **)b, *(char **)a); +} + +START_TEST(nc_array_sort_check) +{ + NcArray *array = NULL; + + array = nc_array_new(); + fail_if(!array, "Failed to allocate memory for NcArray"); + + fail_if(!nc_array_add(array, "gamma"), "Failed to add to array"); + fail_if(!nc_array_add(array, "delta"), "Failed to add to array"); + fail_if(!nc_array_add(array, "beta"), "Failed to add to array"); + fail_if(!nc_array_add(array, "alpha"), "Failed to add to array"); + + fail_if(array->len != 4, "Array length invalid"); + + fail_if(!streq(nc_array_get(array, 0), "gamma"), "Invalid ordering in array #1"); + fail_if(!streq(nc_array_get(array, 1), "delta"), "Invalid ordering in array #2"); + fail_if(!streq(nc_array_get(array, 2), "beta"), "Invalid ordering in array #3"); + fail_if(!streq(nc_array_get(array, 3), "alpha"), "Invalid ordering in array #4"); + + /* Alpha sort them */ + nc_array_qsort(array, sort_strings); + + fail_if(!streq(nc_array_get(array, 0), "alpha"), "Invalid sort ordering in array #1"); + fail_if(!streq(nc_array_get(array, 1), "beta"), "Invalid sort ordering in array #2"); + fail_if(!streq(nc_array_get(array, 2), "delta"), "Invalid sort ordering in array #3"); + fail_if(!streq(nc_array_get(array, 3), "gamma"), "Invalid sort ordering in array #4"); + + /* Flip them back now */ + nc_array_qsort(array, sort_strings_reverse); + fail_if(!streq(nc_array_get(array, 0), "gamma"), "Invalid reverse ordering in array #1"); + fail_if(!streq(nc_array_get(array, 1), "delta"), "Invalid reverse ordering in array #2"); + fail_if(!streq(nc_array_get(array, 2), "beta"), "Invalid reverse ordering in array #3"); + fail_if(!streq(nc_array_get(array, 3), "alpha"), "Invalid reverse ordering in array #4"); + + nc_array_free(&array, NULL); + fail_if(array != NULL, "Failed to free NcArray"); +} +END_TEST + +int main(void) +{ + int number_failed; + Suite *s; + SRunner *sr; + TCase *tc; + + s = suite_create("nc_array"); + tc = tcase_create("nc_array_functions"); + tcase_add_test(tc, nc_array_new_check); + tcase_add_test(tc, nc_array_free_check); + tcase_add_test(tc, nc_array_add_check); + tcase_add_test(tc, nc_array_get_check); + tcase_add_test(tc, nc_array_check); + tcase_add_test(tc, nc_array_sort_check); + suite_add_tcase(s, tc); + + sr = srunner_create(s); + srunner_run_all(sr, CK_VERBOSE); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=8 tabstop=8 expandtab: + * :indentSize=8:tabSize=8:noTabs=true: + */ diff --git a/tests/check-hashmap.c b/tests/check-hashmap.c new file mode 100644 index 0000000..5fc8e34 --- /dev/null +++ b/tests/check-hashmap.c @@ -0,0 +1,284 @@ +/* + * This file is part of libnica. + * + * Copyright (C) 2016 Intel Corporation + * + * libnica is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + */ + +#define _GNU_SOURCE +#include "nica/hashmap.c" +#include +#include + +START_TEST(nc_hashmap_new_check) +{ + NcHashmap *map = NULL; + + map = nc_hashmap_new(NULL, NULL); + fail_if(!map, "Failed to allocate new hashmap"); + fail_if(nc_hashmap_size(map) != 0, "Hashmap size is not 0 after new"); + nc_hashmap_free(map); +} +END_TEST + +START_TEST(nc_hashmap_simple_check) +{ + NcHashmap *map = NULL; + bool b; + void *val = NULL; + + map = nc_hashmap_new(nc_simple_hash, nc_simple_compare); + fail_if(!map, "Failed to allocate new hashmap"); + + for (int i = 0; i < 1000; i++) { + b = nc_hashmap_put(map, NC_HASH_KEY(i), NC_HASH_VALUE(i)); + fail_if(!b, "Failed to add integer to hashmap"); + } + fail_if(nc_hashmap_size(map) != 1000, "Hashmap size invalid after 1000 elements"); + + for (int i = 300; i < 700; i++) { + b = nc_hashmap_remove(map, NC_HASH_KEY(i)); + fail_if(!b, "Failed to remove known integer from from hashmap"); + } + + fail_if(nc_hashmap_size(map) != 600, "Hashmap size invalid after 400 removals"); + + val = nc_hashmap_get(map, NC_HASH_KEY(302)); + fail_if(val, "Value should not be returned from hashmap after removal"); + + val = nc_hashmap_get(map, NC_HASH_KEY(802)); + fail_if(!val, "Value should be returned from hashmap for known key"); + fail_if(NC_UNHASH_VALUE(val) != 802, "Value returned from hashmap was incorrect"); + + fail_if(!nc_hashmap_steal(map, NC_HASH_KEY(802)), "Failed to steal key/value"); + fail_if(nc_hashmap_contains(map, NC_HASH_KEY(802)), "Stolen key still exists"); + + nc_hashmap_free(map); + map = NULL; + + fail_if(nc_hashmap_size(map) >= 0, "Incorrect size returned for NULL hashmap"); +} +END_TEST + +START_TEST(nc_hashmap_dupe_check) +{ + NcHashmap *map = NULL; + void *val = NULL; + + map = nc_hashmap_new(nc_simple_hash, nc_simple_compare); + + fail_if(!nc_hashmap_put(map, "name", "not important"), + "Failed to put to hashmap first time!"); + val = nc_hashmap_get(map, "name"); + fail_if(!val, "Failed to get name!"); + fail_if(!streq(val, "not important"), "Returned value does not match"); + val = NULL; + + fail_if(!nc_hashmap_put(map, "name", "ikey"), "Failed to replace with second value"); + val = nc_hashmap_get(map, "name"); + fail_if(!streq(val, "ikey"), "Second return doesn't match expectation"); + nc_hashmap_free(map); +} +END_TEST + +START_TEST(nc_hashmap_dupe_alloc_check) +{ + NcHashmap *map = NULL; + void *val = NULL; + void *val2 = NULL; + + map = nc_hashmap_new_full(nc_string_hash, nc_string_compare, free, free); + + fail_if(!nc_hashmap_put(map, strdup("name"), strdup("not important")), + "Failed to put to hashmap first time!"); + val = nc_hashmap_get(map, "name"); + fail_if(!val, "Failed to get name!"); + fail_if(!streq(val, "not important"), "Returned value does not match"); + + fail_if(!nc_hashmap_put(map, strdup("name"), strdup("ikey")), + "Failed to replace with second value"); + val2 = nc_hashmap_get(map, "name"); + fail_if(!streq(val2, "ikey"), "Second return doesn't match expectation"); + nc_hashmap_free(map); +} +END_TEST + +START_TEST(nc_hashmap_string_check) +{ + NcHashmap *map = NULL; + bool b; + void *val = NULL; + + map = nc_hashmap_new(nc_string_hash, nc_string_compare); + fail_if(!map, "Failed to allocate new hashmap"); + + b = nc_hashmap_put(map, "John", NC_HASH_VALUE(12)); + fail_if(!b, "Failed to put entry into map"); + b = nc_hashmap_put(map, "Lucy", NC_HASH_VALUE(42)); + fail_if(!b, "Failed to put entry into map"); + b = nc_hashmap_put(map, "Bob", NC_HASH_VALUE(19012)); + fail_if(!b, "Failed to put entry into map"); + b = nc_hashmap_put(map, "Sarah", NC_HASH_VALUE(83)); + fail_if(!b, "Failed to put entry into map"); + + val = nc_hashmap_get(map, "John"); + fail_if(!val, "Failed to get known key from hashmap"); + fail_if(NC_UNHASH_VALUE(val) != 12, "Failed to get correct value from hashmap"); + + val = nc_hashmap_get(map, "Lucy"); + fail_if(!val, "Failed to get known key from hashmap"); + fail_if(NC_UNHASH_VALUE(val) != 42, "Failed to get correct value from hashmap"); + + val = nc_hashmap_get(map, "Bob"); + fail_if(!val, "Failed to get known key from hashmap"); + fail_if(NC_UNHASH_VALUE(val) != 19012, "Failed to get correct value from hashmap"); + + val = nc_hashmap_get(map, "Sarah"); + fail_if(!val, "Failed to get known key from hashmap"); + fail_if(NC_UNHASH_VALUE(val) != 83, "Failed to get correct value from hashmap"); + + nc_hashmap_free(map); +} +END_TEST + +START_TEST(nc_hashmap_iter_check) +{ + NcHashmap *map = NULL; + NcHashmapIter iter; + bool b; + int count = 0; + void *key = NULL; + void *value = NULL; + + map = nc_hashmap_new(NULL, NULL); + fail_if(!map, "Failed to allocate new hashmap"); + + for (int i = 0; i < 5000; i++) { + b = nc_hashmap_put(map, NC_HASH_KEY(i), NC_HASH_KEY(i)); + fail_if(!b, "Failed to insert key into hashmap"); + } + + fail_if(nc_hashmap_size(map) != 5000, "Invalid hashmap size after 5000 elements"); + + nc_hashmap_iter_init(map, &iter); + while (nc_hashmap_iter_next(&iter, (void **)&key, (void **)&value)) { + fail_if(NC_UNHASH_KEY(key) != NC_UNHASH_VALUE(value), + "Mismatched key/value pair in iteration"); + ++count; + } + fail_if(count != 5000, "Did not iterate all hashmap elements"); + + count = 0; + for (int i = 2000; i < 4000; i++) { + b = nc_hashmap_remove(map, NC_HASH_KEY(i)); + fail_if(!b, "Failed to remove known integer key from hashmap"); + } + + nc_hashmap_iter_init(map, &iter); + key = value = NULL; + while (nc_hashmap_iter_next(&iter, &key, &value)) { + unsigned int k = NC_UNHASH_KEY(key); + fail_if(NC_UNHASH_VALUE(value) != k, + "Mismatched post-removal key/value pair in iteration"); + fail_if(k >= 2000 && k < 4000, "Key/value not removed from hashtable"); + ++count; + } + fail_if(count != 3000, "Did not iterate all 2000 elements"); + fail_if(nc_hashmap_size(map) != 3000, "Invalid hashmap size after removals"); + + nc_hashmap_free(map); +} +END_TEST + +static int free_count = 0; + +static inline void free_helper(void *p) +{ + free((void *)p); + ++free_count; +} + +START_TEST(nc_hashmap_alloc_check) +{ + NcHashmap *map = NULL; + char *str = NULL; + void *val = NULL; + bool b; + + map = nc_hashmap_new_full(nc_string_hash, nc_string_compare, free_helper, NULL); + fail_if(!map, "Failed to allocate new hashmap"); + + fail_if(!(str = strdup("Key 1"), "Allocation problem")); + fail_if(!nc_hashmap_put(map, str, str), "Failed to insert into hashmap"); + + fail_if(!(str = strdup("Key 2"), "Allocation problem")); + fail_if(!nc_hashmap_put(map, str, str), "Failed to insert into hashmap"); + + val = nc_hashmap_get(map, "Key 1"); + fail_if(!val, "Failed to get known value from hashmap"); + fail_if(strcmp(val, "Key 1") != 0, "Key 1 does not match"); + val = NULL; + + val = nc_hashmap_get(map, "Key 2"); + fail_if(!val, "Failed to get known value from hashmap"); + fail_if(strcmp(val, "Key 2") != 0, "Key 2 does not match"); + + b = nc_hashmap_remove(map, "Key 2"); + fail_if(!b, "Failed to remove known key from hashmap"); + fail_if(free_count != 1, "Failed to free element from hashmap"); + + nc_hashmap_free(map); + fail_if(free_count != 2, "Failed to free last element from hashmap"); +} +END_TEST + +static Suite *nc_hashmap_suite(void) +{ + Suite *s = NULL; + TCase *tc = NULL; + + s = suite_create("nc_hashmap"); + tc = tcase_create("nc_hashmap_functions"); + tcase_add_test(tc, nc_hashmap_new_check); + tcase_add_test(tc, nc_hashmap_simple_check); + tcase_add_test(tc, nc_hashmap_string_check); + tcase_add_test(tc, nc_hashmap_iter_check); + tcase_add_test(tc, nc_hashmap_alloc_check); + tcase_add_test(tc, nc_hashmap_dupe_check); + tcase_add_test(tc, nc_hashmap_dupe_alloc_check); + suite_add_tcase(s, tc); + + return s; +} + +int main(void) +{ + int number_failed; + Suite *s; + SRunner *sr; + + s = nc_hashmap_suite(); + sr = srunner_create(s); + srunner_run_all(sr, CK_VERBOSE); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=8 tabstop=8 expandtab: + * :indentSize=8:tabSize=8:noTabs=true: + */ diff --git a/tests/check-inifile.c b/tests/check-inifile.c new file mode 100644 index 0000000..990a1e1 --- /dev/null +++ b/tests/check-inifile.c @@ -0,0 +1,134 @@ +/* + * This file is part of libnica. + * + * Copyright (C) 2016 Intel Corporation + * + * libnica is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include + +#include "nica/hashmap.c" +#include "nica/inifile.c" + +START_TEST(nc_inifile_open_test) +{ + autofree(NcHashmap) *f = NULL; + const char *t_path = TOP_DIR "/tests/data/ini/wellformed.ini"; + + f = nc_ini_file_parse(t_path); + fail_if(f == NULL, "Failed to parse wellformed.ini"); +} +END_TEST + +START_TEST(nc_inifile_good_test) +{ + const char *wellformed[] = { TOP_DIR "/tests/data/ini/wellformed.ini", + TOP_DIR "/tests/data/ini/valid_padding.ini" }; + + for (size_t i = 0; i < sizeof(wellformed) / sizeof(wellformed[0]); i++) { + autofree(NcHashmap) *f = NULL; + char *ret = NULL; + + f = nc_ini_file_parse(wellformed[i]); + fail_if(f == NULL, "Failed to parse wellformed.ini"); + + fail_if(!nc_hashmap_contains(f, "John"), "INI File missing \"John\" section"); + + ret = nc_hashmap_get(nc_hashmap_get(f, "John"), "alive"); + fail_if(!ret, "Failed to get known value from INI file"); + fail_if(!streq(ret, "true"), "Incorrect value in INI file"); + + fail_if(!nc_hashmap_contains(f, "Alice"), "INI File missing \"Alice\" section"); + ret = nc_hashmap_get(nc_hashmap_get(f, "Alice"), "alive"); + fail_if(!ret, "Failed to get known value from INI file"); + fail_if(!streq(ret, "false"), "Incorrect value in INI file #2"); + + ret = nc_hashmap_get(nc_hashmap_get(f, "John"), "Random"); + fail_if(ret, "Got unexpected key in section"); + + ret = nc_hashmap_get(nc_hashmap_get(f, "Bob"), "Random"); + fail_if(ret, "Got unexpected section"); + } +} +END_TEST + +START_TEST(nc_inifile_bad_test) +{ + const char *t_path = TOP_DIR "/tests/data/ini/sectionless.ini"; + autofree(NcHashmap) *f = NULL; + + f = nc_ini_file_parse(t_path); + fail_if(f != NULL, "Parsed illegal sectionless INI file"); + + t_path = TOP_DIR "/tests/data/ini/empty_key.ini"; + f = nc_ini_file_parse(t_path); + fail_if(f != NULL, "Parsed illegal INI file with empty keys"); + + t_path = TOP_DIR "/tests/data/ini/just_assign.ini"; + f = nc_ini_file_parse(t_path); + fail_if(f != NULL, "Parsed illegal assign-only INI file"); + + t_path = TOP_DIR "/tests/data/ini/broken_section_start.ini"; + f = nc_ini_file_parse(t_path); + fail_if(f != NULL, "Parsed illegal broken-section-start INI File"); + + t_path = TOP_DIR "/tests/data/ini/broken_section_end.ini"; + f = nc_ini_file_parse(t_path); + fail_if(f != NULL, "Parsed illegal broken-section-end INI File"); +} +END_TEST + +static Suite *core_suite(void) +{ + Suite *s = NULL; + TCase *tc = NULL; + + s = suite_create("nc_inifile"); + tc = tcase_create("nc_inifile_functions"); + tcase_add_test(tc, nc_inifile_open_test); + tcase_add_test(tc, nc_inifile_good_test); + tcase_add_test(tc, nc_inifile_bad_test); + suite_add_tcase(s, tc); + + return s; +} + +int main(void) +{ + Suite *s; + SRunner *sr; + int fail; + + s = core_suite(); + sr = srunner_create(s); + srunner_run_all(sr, CK_VERBOSE); + fail = srunner_ntests_failed(sr); + srunner_free(sr); + + if (fail > 0) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=8 tabstop=8 expandtab: + * :indentSize=8:tabSize=8:noTabs=true: + */ diff --git a/tests/check-list.c b/tests/check-list.c new file mode 100644 index 0000000..33d9dff --- /dev/null +++ b/tests/check-list.c @@ -0,0 +1,307 @@ +/* + * This file is part of libnica. + * + * Copyright (C) 2016 Intel Corporation + * + * libnica is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nica/list.c" + +START_TEST(nc_list_append_check) +{ + NcList *list = NULL; + NcList *head = NULL; + int data1 = 1; + int data2 = 2; + + fail_if(!nc_list_append(&list, &data1), "Append for new list failed"); + head = list; + fail_if(list->tail != list, "list and list->tail do not match after new list append"); + fail_if(list->next, "list->next is not NULL after new list append"); + fail_if(*((int *)(list->data)) != 1, "list->data is incorrect after new list append"); + fail_if(list->size != 1, "list->size not 1 after new list append"); + + fail_if(!nc_list_append(&list, &data2), "Append for existing list failed"); + fail_if(head != list, "Append switched list head"); + fail_if(list->tail != list->next, + "list->next and list->tail do not match after two appends"); + fail_if(list->next->next, "list->next->next is not NULL after two appends"); + fail_if(*((int *)(list->data)) != 1, "list->data is incorrect after two list appends"); + fail_if(*((int *)(list->next->data)) != 2, + "list->next->data is incorrect after two list appends"); + fail_if(list->size != 2, "list->size not 2 after two list appends"); + + nc_list_free(&list); +} +END_TEST + +START_TEST(nc_list_prepend_check) +{ + NcList *list = NULL; + NcList *tail = NULL; + int data1 = 1; + int data2 = 2; + + fail_if(!nc_list_prepend(&list, &data1), "Prepend for new list failed"); + tail = list; + fail_if(list->tail != list, "list and list->tail do not match after new list prepend"); + fail_if(list->next, "list->next is not NULL after new list prepend"); + fail_if(*((int *)(list->data)) != 1, "list->data is incorrect after new list prepend"); + fail_if(list->size != 1, "list->size not 1 after new list prepend"); + + fail_if(!nc_list_prepend(&list, &data2), "Prepend for existing list failed"); + fail_if(tail != list->next, "Prepend switched list next"); + fail_if(tail != list->tail, "Prepend switched list tail"); + fail_if(list->tail != list->next, + "list->next and list->tail do not match after two prepends"); + fail_if(list->next->next, "list->next->next is not NULL after two prepends"); + fail_if(*((int *)(list->data)) != 2, "list->data is incorrect after two list prepends"); + fail_if(*((int *)(list->next->data)) != 1, + "list->next->data is incorrect after two list prepends"); + fail_if(list->size != 2, "list->size not 2 after two list prepends"); + + nc_list_free(&list); +} +END_TEST + +START_TEST(nc_list_remove_check) +{ + NcList *list = NULL; + int data1 = 1; + int data2 = 2; + int data3 = 3; + int *data4 = NULL; + int *data5 = NULL; + + fail_if(nc_list_remove(&list, &data1, false), "Removed from non existing list"); + fail_if(!nc_list_prepend(&list, &data1), "Prepend for new list failed"); + fail_if(nc_list_remove(&list, &data2, false), "Removed non existing element from list"); + fail_if(list->tail != list, "list and list->tail do not match after new list prepend"); + fail_if(list->next, "list->next is not NULL after new list prepend"); + fail_if(*((int *)(list->data)) != 1, "list->data is incorrect after new list prepend"); + fail_if(list->size != 1, "list->size not 1 after new list prepend"); + fail_if(!nc_list_remove(&list, &data1, false), "Unable to remove existing item from list"); + fail_if(list, "List not NULL after removal of only element"); + + data4 = malloc(sizeof(int)); + data5 = malloc(sizeof(int)); + fail_if(!data4 || !data5, "Failed to allocate"); + *data4 = 4; + *data5 = 5; + fail_if(!nc_list_prepend(&list, &data1), "Prepend 1 for list failed"); + fail_if(!nc_list_append(&list, &data2), "Append 1 for list failed"); + fail_if(!nc_list_prepend(&list, &data3), "Prepend 2 for list failed"); + fail_if(!nc_list_append(&list, data4), "Append 2 for list failed"); + fail_if(!nc_list_prepend(&list, data5), "Prepend 3 for list failed"); + /* the list is = (*5, 3, 1, 2, *4) */ + fail_if(!nc_list_remove(&list, &data1, false), "Unable to remove data1 from list"); + fail_if(nc_list_remove(&list, &data1, false), "Able to remove data1 from list again"); + /* the list is = (*5, 3, 2, *4) */ + fail_if(*((int *)(list->data)) != 5, "list->data value incorrect"); + fail_if(list->size != 4, "list->size incorrect"); + fail_if(*((int *)(list->next->next->data)) != 2, "list->next->next->data value incorrect"); + fail_if(*((int *)(list->tail->data)) != 4, "list->tail->data value incorrect"); + fail_if(list->tail != list->next->next->next, "list->tail is incorrect"); + fail_if(!nc_list_remove(&list, data4, true), "Failed to remove data4 from list"); + /* the list is = (*5, 3, 2) */ + fail_if(*((int *)(list->data)) != 5, "list->data value incorrect"); + fail_if(list->size != 3, "list->size incorrect"); + fail_if(*((int *)(list->tail->data)) != 2, "list->tail->data value incorrect"); + fail_if(list->tail != list->next->next, "list->tail is incorrect"); + fail_if(!nc_list_remove(&list, data5, true), "Failed to remove data5 from list"); + /* the list is = (3, 2) */ + fail_if(*((int *)(list->data)) != 3, "list->data value incorrect"); + fail_if(list->size != 2, "list->size incorrect"); + fail_if(*((int *)(list->tail->data)) != 2, "list->tail->data value incorrect"); + fail_if(list->tail != list->next, "list->tail is incorrect"); + fail_if(!nc_list_remove(&list, &data3, false), "Failed to remove data3 from list"); + /* the list is = (2) */ + fail_if(*((int *)(list->data)) != 2, "list->data value incorrect"); + fail_if(list->size != 1, "list->size incorrect"); + fail_if(*((int *)(list->tail->data)) != 2, "list->tail->data value incorrect"); + fail_if(list->tail != list, "list->tail is incorrect"); + fail_if(!nc_list_remove(&list, &data2, false), "Failed to remove data2 from list"); + /* the list is = () */ + fail_if(list, "list is not NULL"); +} +END_TEST + +START_TEST(nc_list_foreach_check) +{ + NcList *list = NULL; + NcList *i; + int data1 = 1; + int data2 = 2; + int data3 = 3; + int c = 1; + + fail_if(!nc_list_append(&list, &data1), "Append 1 for list failed"); + fail_if(!nc_list_append(&list, &data2), "Append 2 for list failed"); + fail_if(!nc_list_append(&list, &data3), "Append 3 for list failed"); + NC_LIST_FOREACH (list, i) { + fail_if(*((int *)(i->data)) != c, "Failed to iterate list"); + c++; + } + + nc_list_free(&list); +} +END_TEST + +START_TEST(nc_list_free_check) +{ + NcList *list = NULL; + int data1 = 1; + int data2 = 2; + int data3 = 3; + + nc_list_free(&list); + fail_if(list, "null list returned non null after free"); + fail_if(!nc_list_append(&list, &data1), "Append 1 for list failed"); + fail_if(!nc_list_append(&list, &data2), "Append 2 for list failed"); + fail_if(!nc_list_append(&list, &data3), "Append 3 for list failed"); + nc_list_free(&list); + fail_if(list, "non null list returned non null after free"); +} +END_TEST + +START_TEST(nc_list_free_all_check) +{ + NcList *list = NULL; + int *data1 = NULL; + int *data2 = NULL; + int *data3 = NULL; + + nc_list_free(&list); + fail_if(list, "null list returned non null after free"); + data1 = malloc(sizeof(int)); + data2 = malloc(sizeof(int)); + data3 = malloc(sizeof(int)); + fail_if(!data1 || !data2 || !data3, "malloc failed"); + fail_if(!nc_list_append(&list, data1), "Append 1 for list failed"); + fail_if(!nc_list_append(&list, data2), "Append 2 for list failed"); + fail_if(!nc_list_append(&list, data3), "Append 3 for list failed"); + nc_list_free_all(&list); + fail_if(list, "non null list returned non null after free"); +} +END_TEST + +START_TEST(nc_list_check) +{ + NcList *list = NULL; + uint i; + char *tmp = NULL; + char *head = ""; + char *head2 = ""; + char *data = ""; + + /* Append 10k strings. */ + uint DEFAULT_SIZE = (10 * 1000); + for (i = 0; i <= DEFAULT_SIZE; i++) { + if (i == 5) { + fail_if(nc_list_append(&list, data) == false, "Failed to append to NcList"); + } else { + int j = asprintf(&tmp, "i #%d", i); + fail_if(j < 0, "Failed to pass test due to allocation error"); + fail_if(nc_list_prepend(&list, tmp) == false, + "Failed to prepend to NcList"); + } + } + + fail_if(list->size != DEFAULT_SIZE + 1, "List size invalid"); + + /* Prepend head */ + fail_if(nc_list_prepend(&list, head) != true, "Prepend head failed"); + fail_if(list->size != DEFAULT_SIZE + 2, "Prepended head size invalid"); + + /* Prepend head2 */ + fail_if(nc_list_prepend(&list, head2) != true, "Prepend head2 failed"); + fail_if(list->size != DEFAULT_SIZE + 3, "Prepended head2 size invalid"); + + /* Remove from middle */ + fail_if(nc_list_remove(&list, data, false) != true, "List removal from middle failed"); + fail_if(list->size != DEFAULT_SIZE + 2, "List middle removal size invalid"); + + /* Remove from end */ + fail_if(nc_list_remove(&list, tmp, true) != true, "List tail removal failed"); + fail_if(list->size != DEFAULT_SIZE + 1, "List tail removal size invalid"); + + fail_if(nc_list_append(&list, "newend") != true, "List new tail append failed"); + fail_if(list->size != DEFAULT_SIZE + 2, "List new tail size invalid"); + fail_if(nc_list_remove(&list, "newend", false) != true, "List new tail removal failed"); + fail_if(list->size != DEFAULT_SIZE + 1, "List new tail size invalid (post removal)"); + + /* Fake remove */ + fail_if(nc_list_remove(&list, "nonexistent", false) == true, + "List non existent removal should fail"); + fail_if(list->size != DEFAULT_SIZE + 1, "List size invalid after no change"); + + /* Remove head */ + fail_if(nc_list_remove(&list, head, false) == false, "List remove head failed"); + fail_if(nc_list_remove(&list, head2, false) == false, "List remove head2 failed"); + fail_if(list->size != DEFAULT_SIZE - 1, "List post heads removal size invalid"); + + nc_list_free_all(&list); +} +END_TEST + +static Suite *nc_list_suite(void) +{ + Suite *s; + TCase *tc; + + s = suite_create("nc_list"); + tc = tcase_create("nc_list_functions"); + tcase_add_test(tc, nc_list_append_check); + tcase_add_test(tc, nc_list_prepend_check); + tcase_add_test(tc, nc_list_remove_check); + tcase_add_test(tc, nc_list_foreach_check); + tcase_add_test(tc, nc_list_free_check); + tcase_add_test(tc, nc_list_free_all_check); + tcase_add_test(tc, nc_list_check); + suite_add_tcase(s, tc); + + return s; +} + +int main(void) +{ + int number_failed; + Suite *s; + SRunner *sr; + + s = nc_list_suite(); + sr = srunner_create(s); + srunner_run_all(sr, CK_VERBOSE); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=8 tabstop=8 expandtab: + * :indentSize=8:tabSize=8:noTabs=true: + */ diff --git a/tests/data/ini/broken_section_end.ini b/tests/data/ini/broken_section_end.ini new file mode 100644 index 0000000..0723a8e --- /dev/null +++ b/tests/data/ini/broken_section_end.ini @@ -0,0 +1,7 @@ +[John +alive=true + +[Alice] +# Various comment types +; Sorry, Alice! +alive = false diff --git a/tests/data/ini/broken_section_start.ini b/tests/data/ini/broken_section_start.ini new file mode 100644 index 0000000..4e4a83c --- /dev/null +++ b/tests/data/ini/broken_section_start.ini @@ -0,0 +1,7 @@ +John] +alive=true + +[Alice] +# Various comment types +; Sorry, Alice! +alive = false diff --git a/tests/data/ini/empty_key.ini b/tests/data/ini/empty_key.ini new file mode 100644 index 0000000..2ae7111 --- /dev/null +++ b/tests/data/ini/empty_key.ini @@ -0,0 +1,7 @@ +[John] +=true + +[Alice] +# Various comment types +; Sorry, Alice! + = false diff --git a/tests/data/ini/just_assign.ini b/tests/data/ini/just_assign.ini new file mode 100644 index 0000000..7f12517 --- /dev/null +++ b/tests/data/ini/just_assign.ini @@ -0,0 +1,7 @@ +[John] += + +[Alice] +# Various comment types +; Sorry, Alice! + = diff --git a/tests/data/ini/sectionless.ini b/tests/data/ini/sectionless.ini new file mode 100644 index 0000000..9122d0a --- /dev/null +++ b/tests/data/ini/sectionless.ini @@ -0,0 +1,2 @@ +alive=true +alive = false diff --git a/tests/data/ini/valid_padding.ini b/tests/data/ini/valid_padding.ini new file mode 100644 index 0000000..4ac24ca --- /dev/null +++ b/tests/data/ini/valid_padding.ini @@ -0,0 +1,10 @@ +; This file is ugly but still valid INI as far as the parser +; is concerned. + +[John] + alive=true + + [Alice] + # Various comment types + ; Sorry, Alice! + alive = false diff --git a/tests/data/ini/wellformed.ini b/tests/data/ini/wellformed.ini new file mode 100644 index 0000000..565e430 --- /dev/null +++ b/tests/data/ini/wellformed.ini @@ -0,0 +1,7 @@ +[John] +alive=true + +[Alice] +# Various comment types +; Sorry, Alice! +alive = false