#include #include "list.h" #include "util.h" #include "macro.h" #include "munit/munit.h" #define NAMELEN 128 typedef struct num_node { list_node l; int n; } num_node; static num_node * new_num_node(int n) { num_node *res; res = xmalloc(sizeof(*res)); res->n = n; return res; } //#define NEW_ITEM(tp) xmalloc(sizeof(tp)) /* list l; list_init(&l); list_clear(&l, NULL); */ int n_hardfrees = 0; static void hardmode_free(list_node *n) { n_hardfrees++; memset(n, 0, sizeof(*n)); free(n); } void list_num_print(list *l) { struct list_node *iter; const char *hdrfmt = "%16.10s|%16.10s|%16.10s|%5.5s\n"; const char *itemfmt = "%16.10p|%16.10p|%16.10p|%5d\n"; printf("head = %p tail = %p\n", l->head, l->tail); printf(hdrfmt, "ptr", "next", "prev", "n"); printf(" -------------------------------------------\n"); list_for_each(iter, l) { num_node *ni; ni = (num_node *)iter; printf(itemfmt, ni, ni->l.next, ni->l.prev, ni->n); } } static MunitResult test_list_stage1(const MunitParameter params[], void * data) { //Tests for: list_init, list_clear, list_push_front, list_first, list_last int num_arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int reverse_arr[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; num_node *ni; int i; list l; munit_logf(MUNIT_LOG_INFO, "Tests for %s", "list_init, list_clear, list_push_front, list_first, list_last"); munit_log(MUNIT_LOG_INFO, "Intializing num_node list..."); list_init(&l); list_clear(&l, NULL); munit_assert_null(l.head); munit_assert_null(l.tail); munit_log(MUNIT_LOG_INFO, "Checking list_push_front..."); // Insert first element, check list sanity ni = new_num_node(num_arr[0]); list_push_front(&l, (list_node *)ni); munit_assert_null(ni->l.next); munit_assert_null(ni->l.prev); munit_assert_ptr(l.head, ==, ni); munit_assert_ptr(l.tail, ==, ni); // Insert second element, check list sanity ni = new_num_node(num_arr[1]); list_push_front(&l, (list_node *)ni); munit_assert_not_null(ni->l.next); munit_assert_null(ni->l.prev); munit_assert_ptr(l.head, ==, ni); munit_assert_ptr(l.tail, !=, ni); for (i = 2; i < ARRSZ(num_arr); i++) { munit_logf(MUNIT_LOG_DEBUG, "list_push_front i = %d", i); ni = new_num_node(num_arr[i]); list_push_front(&l, (list_node *)ni); } //list_num_print(&l); munit_log(MUNIT_LOG_INFO, "Checking list contents after list_push_front calls"); // Manually traverse list and check it for (i = 0, ni = (num_node *) l.head; ni != NULL; i++, ni = (num_node *) (ni->l.next)) { munit_assert_int(ni->n, ==, reverse_arr[i]); } ni = (num_node *) list_first(&l); munit_assert_not_null(ni); munit_assert_int(ni->n, ==, reverse_arr[0]); ni = (num_node *) list_last(&l); munit_assert_not_null(ni); munit_assert_int(ni->n, ==, num_arr[0]); munit_assert_size(list_len(&l), ==, ARRSZ(num_arr)); list_clear(&l, (list_free_cb) free); munit_assert_size(list_len(&l), ==, 0); munit_log(MUNIT_LOG_INFO, "try to free every node and zero it memory"); for (i = 0; i < ARRSZ(num_arr); i++) { ni = xmalloc(sizeof(*ni)); ni->n = num_arr[i]; list_push_front(&l, (list_node *)ni); } size_t lsz = list_len(&l); list_clear(&l, hardmode_free); if (lsz != n_hardfrees) { munit_log(MUNIT_LOG_WARNING, "not all objects are freed. Bug in list_clear??"); } munit_assert_int(lsz, ==, n_hardfrees); munit_assert_size(list_len(&l), ==, 0); return MUNIT_OK; } static MunitResult test_list_stage2(const MunitParameter params[], void * data) { //tests for list_push_back list_get list_insert list_pop_front list_pop_back int num_arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int res_arr[] = {42, 43, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, 10}; num_node *n1, *n2; num_node *ni; int i; int idx; list l; list_init(&l); munit_log(MUNIT_LOG_INFO, "Checking list_push_back"); for (i = 2; i < ARRSZ(num_arr); i++) { ni = new_num_node(num_arr[i]); list_push_back(&l, (list_node *)ni); } munit_log(MUNIT_LOG_INFO, "Checking list_get"); for (i = 0; i < ARRSZ(num_arr) - 2; i++) { ni = (num_node *) list_get(&l, i); munit_assert_int(ni->n, ==, num_arr[i + 2]); } list_insert(&l, (list_node *) new_num_node(num_arr[0]), 0); list_insert(&l, (list_node *) new_num_node(num_arr[1]), 1); // manually traverse list and check it for (i = 0, ni = (num_node *) l.head; ni != NULL; i++, ni = (num_node *) (ni->l.next)) { munit_assert_int(ni->n, ==, num_arr[i]); } list_insert(&l, (list_node *) new_num_node(42), 0); list_insert(&l, (list_node *) new_num_node(43), 1); list_insert(&l, (list_node *) new_num_node(44), list_len(&l) - 1); // manually traverse list and check it for (i = 0, ni = (num_node *) l.head; ni != NULL; i++, ni = (num_node *) (ni->l.next)) { munit_assert_int(ni->n, ==, res_arr[i]); } n2 = (num_node *) list_pop_front(&l); munit_assert_not_null(n2); munit_assert_int(n2->n, ==, 42); n1 = (num_node *) list_pop_back(&l); munit_assert_not_null(n1); munit_assert_int(n1->n, ==, 10); idx = list_index(&l, (list_node *) n2); munit_assert_int(idx, ==, -1); for (i = 0; i < 5; i++) { munit_assert_int( i, ==, list_index(&l, list_get(&l, i)) ); } list_clear(&l, (list_free_cb) free); list_push_front(&l, (list_node *) n1); list_push_front(&l, (list_node *) n2); ni = (num_node *) list_pop_front(&l); munit_assert_ptr(ni, ==, n2); ni = (num_node *) list_pop_front(&l); munit_assert_ptr(ni, ==, n1); munit_assert_size(list_len(&l), ==, 0); list_clear(&l, (list_free_cb) free); munit_assert_null(list_pop_front(&l)); munit_assert_null(list_pop_back(&l)); return MUNIT_OK; } /* static MunitResult test_list_tmp(const MunitParameter params[], void * data) { //Tests for: list_remove list_reverse int num_arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int reverse_arr[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; num_node *ni; int i; list l; list_init(&l); list_clear(&l, (list_free_cb) free); return MUNIT_OK; } */ static MunitResult test_list_remove(const MunitParameter params[], void * data) { //Tests for: list_remove list_reverse int num_arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; num_node *ni; int i; list l; list_init(&l); for (i = 0; i < ARRSZ(num_arr); i++) { ni = new_num_node(num_arr[i]); list_push_back(&l, (list_node *)ni); } ni = (num_node *) list_remove(&l, 122); munit_assert_null(ni); ni = (num_node *) list_remove(&l, 0); munit_assert_not_null(ni); munit_assert_int(ni->n, ==, num_arr[0]); ni = (num_node *) list_remove(&l, list_len(&l) - 1); munit_assert_not_null(ni); munit_assert_int(ni->n, ==, num_arr[ARRSZ(num_arr) - 1]); size_t sz = list_len(&l); for (i = 0; i < sz; i++) { ni = (num_node *) list_remove(&l, 0); munit_assert_not_null(ni); } list_clear(&l, (list_free_cb) free); return MUNIT_OK; } static MunitResult test_list_reverse(const MunitParameter params[], void * data) { int num_arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int reverse_arr[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; num_node *ni; int i; list l; list_init(&l); list_reverse(&l); munit_assert_size(0, ==, list_len(&l)); for (i = 0; i < ARRSZ(num_arr); i++) { ni = new_num_node(num_arr[i]); list_push_back(&l, (list_node *)ni); } list_reverse(&l); munit_assert_size(list_len(&l), ==, ARRSZ(reverse_arr)); //manually traverse list and check it for (i = 0, ni = (num_node *) l.head; ni != NULL; i++, ni = (num_node *) (ni->l.next)) { munit_assert_int(ni->n, ==, reverse_arr[i]); } return MUNIT_OK; } #define TEST_ITEM(func) {#func, func, NULL, NULL, MUNIT_TEST_OPTION_NONE } static MunitTest test_suite_tests[] = { TEST_ITEM(test_list_stage1), TEST_ITEM(test_list_stage2), TEST_ITEM(test_list_remove), TEST_ITEM(test_list_reverse), { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } }; static const MunitSuite test_suite = { (char *) "", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE }; int main(int argc, const char *argv[]) { munit_suite_main(&test_suite, (void *) "vector_test", argc, (char * const*) argv); return 0; }