ex32 plus runtests improvements

This commit is contained in:
Dan Buch 2016-04-17 12:16:00 -04:00
parent 23bb2b1eed
commit 508ac1a5d1
No known key found for this signature in database
GPG Key ID: FAEF12936DD3E3EC
9 changed files with 324 additions and 18 deletions

View File

@ -1,2 +1,3 @@
tests/runtests tests/runtests
tests/your_library_tests tests/*_tests
tests/**/*_tests

View File

@ -20,17 +20,25 @@ int run_tests_file(char *filename)
return -1; return -1;
} }
int main(void) int main(int argc, char *argv[])
{ {
int entcount = 0; int entcount = 0;
int rc = 0; int rc = 0;
int i = 0; int i = 0;
int ntests = 0; int ntests = 0;
char *testsdir = getenv("TESTS"); char *testsdir = NULL;
char *valgrind = getenv("VALGRIND"); char *valgrind = getenv("VALGRIND");
struct dirent **namelist = NULL; struct dirent **namelist = NULL;
struct dirent *ep = NULL; struct dirent *ep = NULL;
if(argc > 1) {
testsdir = argv[1];
}
if(!testsdir) {
testsdir = getenv("TESTS");
}
if(!testsdir) { if(!testsdir) {
testsdir = "./tests"; testsdir = "./tests";
} }
@ -70,14 +78,19 @@ int main(void)
continue; continue;
} }
printf("ERROR in test %s: here's tests/tests.log\n", filename); printf("ERROR in test %s", filename);
printf("------\n"); if(access("tests/tests.log", R_OK) == 0) {
rc = system("tail tests/tests.log"); printf(": here's tests/tests.log\n");
printf("------\n");
rc = system("tail tests/tests.log");
} else {
printf("\n");
}
goto error; goto error;
} }
printf("------\n"); 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) { if(namelist) {
free(namelist); free(namelist);

View File

@ -1,2 +1,3 @@
tests/runtests tests/runtests
tests/your_library_tests tests/*_tests
tests/**/*_tests

View File

@ -6,7 +6,7 @@ PREFIX ?= /usr/local
SOURCES = $(wildcard src/**/*.c src/*.c) SOURCES = $(wildcard src/**/*.c src/*.c)
OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) 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)) TESTS = $(patsubst %.c,%,$(TEST_SRC))
LIBNAME = lcthw LIBNAME = lcthw
@ -35,7 +35,7 @@ build:
.PHONY: tests .PHONY: tests
tests: LDLIBS += -static -l$(LIBNAME) tests: LDLIBS += -static -l$(LIBNAME)
tests: ./tests/runtests $(TESTS) tests: ./tests/runtests $(TESTS)
./tests/runtests ./tests/runtests ./tests/lcthw
valgrind: valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE) VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)

View File

@ -0,0 +1,124 @@
#include <lcthw/list.h>
#include <lcthw/dbg.h>
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;
}

View File

@ -0,0 +1,41 @@
#ifndef lcthw_List_h
#define lcthw_List_h
#include <stdlib.h>
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

View File

@ -0,0 +1,112 @@
#include "../minunit.h"
#include <lcthw/list.h>
#include <assert.h>
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);

View File

@ -13,7 +13,8 @@
message = test(); tests_run++; if (message) return message; message = test(); tests_run++; if (message) return message;
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\ #define RUN_TESTS(name) int main(int argc, char *argv[]) {\
argc = 1; \ argc = argc; \
argv = argv; \
debug("----- RUNNING: %s", argv[0]);\ debug("----- RUNNING: %s", argv[0]);\
printf("----\nRUNNING: %s\n", argv[0]);\ printf("----\nRUNNING: %s\n", argv[0]);\
char *result = name();\ char *result = name();\

View File

@ -4,7 +4,7 @@
#include <dirent.h> #include <dirent.h>
#include <unistd.h> #include <unistd.h>
#include <fnmatch.h> #include <fnmatch.h>
#include <dbg.h> #include <lcthw/dbg.h>
int test_selector(const struct dirent *ep) int test_selector(const struct dirent *ep)
{ {
@ -20,17 +20,25 @@ int run_tests_file(char *filename)
return -1; return -1;
} }
int main(void) int main(int argc, char *argv[])
{ {
int entcount = 0; int entcount = 0;
int rc = 0; int rc = 0;
int i = 0; int i = 0;
int ntests = 0; int ntests = 0;
char *testsdir = getenv("TESTS"); char *testsdir = NULL;
char *valgrind = getenv("VALGRIND"); char *valgrind = getenv("VALGRIND");
struct dirent **namelist = NULL; struct dirent **namelist = NULL;
struct dirent *ep = NULL; struct dirent *ep = NULL;
if(argc > 1) {
testsdir = argv[1];
}
if(!testsdir) {
testsdir = getenv("TESTS");
}
if(!testsdir) { if(!testsdir) {
testsdir = "./tests"; testsdir = "./tests";
} }
@ -70,14 +78,19 @@ int main(void)
continue; continue;
} }
printf("ERROR in test %s: here's tests/tests.log\n", filename); printf("ERROR in test %s", filename);
printf("------\n"); if(access("tests/tests.log", R_OK) == 0) {
rc = system("tail tests/tests.log"); printf(": here's tests/tests.log\n");
printf("------\n");
rc = system("tail tests/tests.log");
} else {
printf("\n");
}
goto error; goto error;
} }
printf("------\n"); 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) { if(namelist) {
free(namelist); free(namelist);