diff --git a/lcthw-remnants-2/c-skeleton/.gitignore b/lcthw-remnants-2/c-skeleton/.gitignore index 0c5003d..790f18a 100644 --- a/lcthw-remnants-2/c-skeleton/.gitignore +++ b/lcthw-remnants-2/c-skeleton/.gitignore @@ -1,2 +1,3 @@ tests/runtests -tests/your_library_tests +tests/*_tests +tests/**/*_tests diff --git a/lcthw-remnants-2/c-skeleton/tests/runtests.c b/lcthw-remnants-2/c-skeleton/tests/runtests.c index 9e39d3a..fffa8f7 100644 --- a/lcthw-remnants-2/c-skeleton/tests/runtests.c +++ b/lcthw-remnants-2/c-skeleton/tests/runtests.c @@ -20,17 +20,25 @@ int run_tests_file(char *filename) return -1; } -int main(void) +int main(int argc, char *argv[]) { int entcount = 0; int rc = 0; int i = 0; int ntests = 0; - char *testsdir = getenv("TESTS"); + char *testsdir = NULL; char *valgrind = getenv("VALGRIND"); struct dirent **namelist = NULL; struct dirent *ep = NULL; + if(argc > 1) { + testsdir = argv[1]; + } + + if(!testsdir) { + testsdir = getenv("TESTS"); + } + if(!testsdir) { testsdir = "./tests"; } @@ -70,14 +78,19 @@ int main(void) continue; } - printf("ERROR in test %s: here's tests/tests.log\n", filename); - printf("------\n"); - rc = system("tail tests/tests.log"); + printf("ERROR in test %s", filename); + if(access("tests/tests.log", R_OK) == 0) { + printf(": here's tests/tests.log\n"); + printf("------\n"); + rc = system("tail tests/tests.log"); + } else { + printf("\n"); + } goto error; } printf("------\n"); - printf("Total of %d test files run.\n", ntests); + printf("Total of %d test file%s run.\n", ntests, ntests > 1 ? "s" : ""); if(namelist) { free(namelist); diff --git a/lcthw-remnants-2/liblcthw/.gitignore b/lcthw-remnants-2/liblcthw/.gitignore index 0c5003d..790f18a 100644 --- a/lcthw-remnants-2/liblcthw/.gitignore +++ b/lcthw-remnants-2/liblcthw/.gitignore @@ -1,2 +1,3 @@ tests/runtests -tests/your_library_tests +tests/*_tests +tests/**/*_tests diff --git a/lcthw-remnants-2/liblcthw/Makefile b/lcthw-remnants-2/liblcthw/Makefile index ce425a0..d908dbc 100644 --- a/lcthw-remnants-2/liblcthw/Makefile +++ b/lcthw-remnants-2/liblcthw/Makefile @@ -6,7 +6,7 @@ PREFIX ?= /usr/local SOURCES = $(wildcard src/**/*.c src/*.c) OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) -TEST_SRC = $(wildcard tests/*_tests.c) +TEST_SRC = $(wildcard tests/**/*_tests.c tests/*_tests.c) TESTS = $(patsubst %.c,%,$(TEST_SRC)) LIBNAME = lcthw @@ -35,7 +35,7 @@ build: .PHONY: tests tests: LDLIBS += -static -l$(LIBNAME) tests: ./tests/runtests $(TESTS) - ./tests/runtests + ./tests/runtests ./tests/lcthw valgrind: VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE) diff --git a/lcthw-remnants-2/liblcthw/src/lcthw/list.c b/lcthw-remnants-2/liblcthw/src/lcthw/list.c new file mode 100644 index 0000000..bb7e354 --- /dev/null +++ b/lcthw-remnants-2/liblcthw/src/lcthw/list.c @@ -0,0 +1,124 @@ +#include +#include + +List *List_create() +{ + return calloc(1, sizeof(List)); +} + +void List_destroy(List *list) +{ + LIST_FOREACH(list, first, next, cur) { + if(cur->prev) { + free(cur->prev); + } + } + + free(list->last); + free(list); +} + + +void List_clear(List *list) +{ + LIST_FOREACH(list, first, next, cur) { + free(cur->value); + } +} + + +void List_clear_destroy(List *list) +{ + List_clear(list); + List_destroy(list); +} + + +void List_push(List *list, void *value) +{ + ListNode *node = calloc(1, sizeof(ListNode)); + check_mem(node); + + node->value = value; + + if(list->last == NULL) { + list->first = node; + list->last = node; + } else { + list->last->next = node; + node->prev = list->last; + list->last = node; + } + + list->count++; + +error: + return; +} + +void *List_pop(List *list) +{ + ListNode *node = list->last; + return node != NULL ? List_remove(list, node) : NULL; +} + +void List_unshift(List *list, void *value) +{ + ListNode *node = calloc(1, sizeof(ListNode)); + check_mem(node); + + node->value = value; + + if(list->first == NULL) { + list->first = node; + list->last = node; + } else { + node->next = list->first; + list->first->prev = node; + list->first = node; + } + + list->count++; + +error: + return; +} + +void *List_shift(List *list) +{ + ListNode *node = list->first; + return node != NULL ? List_remove(list, node) : NULL; +} + +void *List_remove(List *list, ListNode *node) +{ + void *result = NULL; + + check(list->first && list->last, "List is empty."); + check(node, "node can't be NULL"); + + if(node == list->first && node == list->last) { + list->first = NULL; + list->last = NULL; + } else if(node == list->first) { + list->first = node->next; + check(list->first != NULL, "Invalid list, somehow got a first that is NULL."); + list->first->prev = NULL; + } else if(node == list->last) { + list->last = node->prev; + check(list->last != NULL, "INvalid list, somehow got a next that is NULL."); + list->last->next = NULL; + } else { + ListNode *after = node->next; + ListNode *before = node->prev; + after->prev = before; + before->next = after; + } + + list->count--; + result = node->value; + free(node); + +error: + return result; +} diff --git a/lcthw-remnants-2/liblcthw/src/lcthw/list.h b/lcthw-remnants-2/liblcthw/src/lcthw/list.h new file mode 100644 index 0000000..83fe51e --- /dev/null +++ b/lcthw-remnants-2/liblcthw/src/lcthw/list.h @@ -0,0 +1,41 @@ +#ifndef lcthw_List_h +#define lcthw_List_h + +#include + +struct ListNode; + +typedef struct ListNode { + struct ListNode *next; + struct ListNode *prev; + void *value; +} ListNode; + +typedef struct List { + int count; + ListNode *first; + ListNode *last; +} List; + +List *List_create(); +void List_destroy(List *list); +void List_clear(List *list); +void List_clear_destroy(List *list); + +#define List_count(A) ((A)->count) +#define List_first(A) ((A)->first != NULL ? (A)->first->value : NULL) +#define List_last(A) ((A)->last != NULL ? (A)->last->value : NULL) + +void List_push(List *list, void *value); +void *List_pop(List *list); + +void List_unshift(List *list, void *value); +void *List_shift(List *list); + +void *List_remove(List *list, ListNode *node); + +#define LIST_FOREACH(L, S, M, V) ListNode *_node = NULL;\ + ListNode *V = NULL;\ + for(V = _node = L->S; _node != NULL; V = _node = _node->M) + +#endif diff --git a/lcthw-remnants-2/liblcthw/tests/lcthw/list_tests.c b/lcthw-remnants-2/liblcthw/tests/lcthw/list_tests.c new file mode 100644 index 0000000..6a4a10c --- /dev/null +++ b/lcthw-remnants-2/liblcthw/tests/lcthw/list_tests.c @@ -0,0 +1,112 @@ +#include "../minunit.h" +#include +#include + +static List *list = NULL; +char *test1 = "test1 data"; +char *test2 = "test2 data"; +char *test3 = "test3 data"; + + +char *test_create() +{ + list = List_create(); + mu_assert(list != NULL, "Failed to create list."); + + return NULL; +} + + +char *test_destroy() +{ + List_clear_destroy(list); + + return NULL; +} + + +char *test_push_pop() +{ + List_push(list, test1); + mu_assert(List_last(list) == test1, "Wrong last value."); + + List_push(list, test2); + mu_assert(List_last(list) == test2, "Wrong last value"); + + List_push(list, test3); + mu_assert(List_last(list) == test3, "Wrong last value"); + mu_assert(List_count(list) == 3, "Wrong count on push."); + + char *val = List_pop(list); + mu_assert(val == test3, "Wrong value on pop."); + + val = List_pop(list); + mu_assert(val == test2, "Wrong value on pop."); + + val = List_pop(list); + mu_assert(val == test1, "Wrong value on pop."); + mu_assert(List_count(list) == 0, "Wrong count after pop."); + + return NULL; +} + +char *test_unshift() +{ + List_unshift(list, test1); + mu_assert(List_first(list) == test1, "Wrong first value."); + + List_unshift(list, test2); + mu_assert(List_first(list) == test2, "Wrong first value."); + + List_unshift(list, test3); + mu_assert(List_first(list) == test3, "Wrong first value."); + mu_assert(List_count(list) == 3, "Wrong count on unshift."); + + return NULL; +} + +char *test_remove() +{ + // we only need to test the middle remove case since push/shift + // already tests the other cases + + char *val = List_remove(list, list->first->next); + mu_assert(val == test2, "Wrong removed element."); + mu_assert(List_count(list) == 2, "Wrong count after remove."); + mu_assert(List_first(list) == test3, "Wrong first after remove."); + mu_assert(List_last(list) == test1, "Wrong last after remove."); + + return NULL; +} + + +char *test_shift() +{ + mu_assert(List_count(list) != 0, "Wrong count before shift."); + + char *val = List_shift(list); + mu_assert(val == test3, "Wrong value on shift."); + + val = List_shift(list); + mu_assert(val == test1, "Wrong value on shift."); + mu_assert(List_count(list) == 0, "Wrong count after shift."); + + return NULL; +} + + + +char *all_tests() { + mu_suite_start(); + + mu_run_test(test_create); + mu_run_test(test_push_pop); + mu_run_test(test_unshift); + mu_run_test(test_remove); + mu_run_test(test_shift); + mu_run_test(test_destroy); + + return NULL; +} + +RUN_TESTS(all_tests); diff --git a/lcthw-remnants-2/liblcthw/tests/minunit.h b/lcthw-remnants-2/liblcthw/tests/minunit.h index 9ed511e..5ffc3e9 100644 --- a/lcthw-remnants-2/liblcthw/tests/minunit.h +++ b/lcthw-remnants-2/liblcthw/tests/minunit.h @@ -13,7 +13,8 @@ message = test(); tests_run++; if (message) return message; #define RUN_TESTS(name) int main(int argc, char *argv[]) {\ - argc = 1; \ + argc = argc; \ + argv = argv; \ debug("----- RUNNING: %s", argv[0]);\ printf("----\nRUNNING: %s\n", argv[0]);\ char *result = name();\ diff --git a/lcthw-remnants-2/liblcthw/tests/runtests.c b/lcthw-remnants-2/liblcthw/tests/runtests.c index 9e39d3a..40585fb 100644 --- a/lcthw-remnants-2/liblcthw/tests/runtests.c +++ b/lcthw-remnants-2/liblcthw/tests/runtests.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include int test_selector(const struct dirent *ep) { @@ -20,17 +20,25 @@ int run_tests_file(char *filename) return -1; } -int main(void) +int main(int argc, char *argv[]) { int entcount = 0; int rc = 0; int i = 0; int ntests = 0; - char *testsdir = getenv("TESTS"); + char *testsdir = NULL; char *valgrind = getenv("VALGRIND"); struct dirent **namelist = NULL; struct dirent *ep = NULL; + if(argc > 1) { + testsdir = argv[1]; + } + + if(!testsdir) { + testsdir = getenv("TESTS"); + } + if(!testsdir) { testsdir = "./tests"; } @@ -70,14 +78,19 @@ int main(void) continue; } - printf("ERROR in test %s: here's tests/tests.log\n", filename); - printf("------\n"); - rc = system("tail tests/tests.log"); + printf("ERROR in test %s", filename); + if(access("tests/tests.log", R_OK) == 0) { + printf(": here's tests/tests.log\n"); + printf("------\n"); + rc = system("tail tests/tests.log"); + } else { + printf("\n"); + } goto error; } printf("------\n"); - printf("Total of %d test files run.\n", ntests); + printf("Total of %d test file%s run.\n", ntests, ntests > 1 ? "s" : ""); if(namelist) { free(namelist);