Move tons of stuff into oldstuff/

This commit is contained in:
2020-06-04 09:54:59 -04:00
parent 49038bb8ef
commit aa1345b6ed
213 changed files with 0 additions and 12 deletions

View File

@@ -0,0 +1,5 @@
tests/runtests
tests/*_tests
tests/**/*_tests
bstrlib.c
bstrlib.h

View File

@@ -0,0 +1,21 @@
Copyright (C) 2016 Dan Buch
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,76 @@
BSTRLIB_BASE_URL ?= https://raw.githubusercontent.com/websnarf/bstrlib/208b1f2a4dfc96b806ed499bd1909e87ec15981d
CFLAGS = -g -O2 -Wall -Wextra -Isrc -Lbuild -rdynamic -DNDEBUG $(OPTFLAGS)
LDLIBS = -ldl $(OPTLIBS)
PREFIX ?= /usr/local
FIND ?= find
CD ?= cd
PATCH ?= patch
INSTALL ?= install
MKDIR ?= mkdir -p
CURL ?= curl -sSL
RANLIB ?= ranlib
RUNTESTS ?= ./tests/runtests
SOURCES = $(wildcard src/**/*.c src/*.c)
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
TEST_SRC = $(wildcard tests/**/*_tests.c tests/*_tests.c)
TESTS = $(patsubst %.c,%,$(TEST_SRC))
LIBNAME = lcthw
TARGET = build/lib$(LIBNAME).a
SO_TARGET = $(patsubst %.a,%.so,$(TARGET))
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS = -g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
$(AR) rcs $@ $(OBJECTS)
$(RANLIB) $@
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
build: bin src/lcthw/bstrlib.c src/lcthw/bstrlib.h
@$(MKDIR) $@
bin:
@$(MKDIR) $@
src/lcthw/bstrlib.c: src/lcthw/bstrlib.h
$(CURL) -o $@ $(BSTRLIB_BASE_URL)/bstrlib.c
$(CD) src/lcthw && $(PATCH) -p1 < bstrlib.patch
src/lcthw/bstrlib.h:
$(CURL) -o $@ $(BSTRLIB_BASE_URL)/bstrlib.h
.PHONY: tests
tests: LDLIBS += -static -l$(LIBNAME) -lbsd
tests: $(RUNTESTS) $(TESTS)
$(RUNTESTS) ./tests/lcthw
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
clean:
$(RM) -r build $(OBJECTS) $(TESTS)
$(RM) tests/tests.log tests/runtests
$(FIND) . -name "*.gc*" -exec rm {} \;
$(RM) -r `find . -name "*.dSYM" -print`
distclean: clean
$(RM) src/lcthw/bstrlib.c src/lcthw/bstrlib.h
install: all
$(INSTALL) -d $(DESTDIR)/$(PREFIX)/lib/
$(INSTALL) $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
@echo Files with potentially dangerous functions
@egrep $(BADFUNCS) $(SOURCES) || true

View File

@@ -0,0 +1,12 @@
--- a/bstrlib.c 2016-04-21 12:26:50.000000000 -0400
+++ b/bstrlib.c 2016-04-21 12:27:59.000000000 -0400
@@ -22,7 +22,8 @@
#include <string.h>
#include <ctype.h>
#include <limits.h>
-#include "bstrlib.h"
+// PATCH to include adjacent bstrlib.h
+#include <lcthw/bstrlib.h>
/* Optionally include a mechanism for debugging memory */

View File

@@ -0,0 +1,116 @@
#include <lcthw/darray.h>
#include <assert.h>
DArray *DArray_create(size_t element_size, size_t initial_max)
{
DArray *array = malloc(sizeof(DArray));
check_mem(array);
array->max = initial_max;
check(array->max > 0, "You must set an initial_max > 0.");
array->contents = calloc(initial_max, sizeof(void *));
check_mem(array->contents);
array->end = 0;
array->element_size = element_size;
array->expand_rate = DEFAULT_EXPAND_RATE;
return array;
error:
if(array) free(array);
return NULL;
}
void DArray_clear(DArray *array)
{
int i = 0;
if(array->element_size > 0) {
for(i = 0; i < array->max; i++) {
if(array->contents[i] != NULL) {
free(array->contents[i]);
}
}
}
}
static inline int DArray_resize(DArray *array, size_t newsize)
{
array->max = newsize;
check(array->max > 0, "The newsize must be > 0.");
void *contents = realloc(array->contents, array->max * sizeof(void *));
check_mem(contents);
array->contents = contents;
return 0;
error:
return -1;
}
int DArray_expand(DArray *array)
{
size_t old_max = array->max;
check(DArray_resize(array, array->max + array->expand_rate) == 0,
"Failed to expand array to new size: %d",
array->max + (int)array->expand_rate);
memset(array->contents + old_max, 0, array->expand_rate + 1);
return 0;
error:
return -1;
}
int DArray_contract(DArray *array)
{
int new_size = array->end < (int)array->expand_rate ? (int)array->expand_rate : array->end;
return DArray_resize(array, new_size + 1);
}
void DArray_destroy(DArray *array)
{
if(array) {
if(array->contents) free(array->contents);
free(array);
}
}
void DArray_clear_destroy(DArray *array)
{
DArray_clear(array);
DArray_destroy(array);
}
int DArray_push(DArray *array, void *el)
{
array->contents[array->end] = el;
array->end++;
if(DArray_end(array) >= DArray_max(array)) {
return DArray_expand(array);
} else {
return 0;
}
}
void *DArray_pop(DArray *array)
{
check(array->end - 1 >= 0, "Attempt to pop from empty array.");
void *el = DArray_remove(array, array->end - 1);
array->end--;
if(DArray_end(array) > (int)array->expand_rate && DArray_end(array) % array->expand_rate) {
DArray_contract(array);
}
return el;
error:
return NULL;
}

View File

@@ -0,0 +1,78 @@
#ifndef lcthw_DArray_h
#define lcthw_DArray_h
#include <stdlib.h>
#include <assert.h>
#include <lcthw/dbg.h>
typedef struct DArray {
int end;
int max;
size_t element_size;
size_t expand_rate;
void **contents;
} DArray;
DArray *DArray_create(size_t element_size, size_t initial_max);
void DArray_destroy(DArray *array);
void DArray_clear(DArray *array);
int DArray_expand(DArray *array);
int DArray_contract(DArray *array);
int DArray_push(DArray *array, void *el);
void *DArray_pop(DArray *array);
void DArray_clear_destroy(DArray *array);
#define DArray_last(A) ((A)->contents[(A)->end - 1])
#define DArray_first(A) ((A)->contents[0])
#define DArray_end(A) ((A)->end)
#define DArray_count(A) DArray_end(A)
#define DArray_max(A) ((A)->max)
#define DEFAULT_EXPAND_RATE 300
static inline void DArray_set(DArray *array, int i, void *el)
{
check(i < array->max, "darray attempt to set past max");
if(i > array->end) array->end = i;
array->contents[i] = el;
error:
return;
}
static inline void *DArray_get(DArray *array, int i)
{
check(i < array->max, "darray attempt to get past max");
return array->contents[i];
error:
return NULL;
}
static inline void *DArray_remove(DArray *array, int i)
{
void *el = array->contents[i];
array->contents[i] = NULL;
return el;
}
static inline void *DArray_new(DArray *array)
{
check(array->element_size > 0, "Can't use DArray_new on 0 size darrays.");
return calloc(1, array->element_size);
error:
return NULL;
}
#define DArray_free(E) free((E))
#endif

View File

@@ -0,0 +1,19 @@
#include <lcthw/darray_algos.h>
#include <stdlib.h>
#include <bsd/stdlib.h>
int DArray_qsort(DArray *array, DArray_compare cmp)
{
qsort(array->contents, DArray_count(array), sizeof(void *), cmp);
return 0;
}
int DArray_heapsort(DArray *array, DArray_compare cmp)
{
return heapsort(array->contents, DArray_count(array), sizeof(void *), cmp);
}
int DArray_mergesort(DArray *array, DArray_compare cmp)
{
return mergesort(array->contents, DArray_count(array), sizeof(void *), cmp);
}

View File

@@ -0,0 +1,14 @@
#ifndef lcthw_DArray_algos_h
#define lcthw_DArray_algos_h
#include <lcthw/darray.h>
typedef int (*DArray_compare)(const void *a, const void *b);
int DArray_qsort(DArray *array, DArray_compare cmp);
int DArray_heapsort(DArray *array, DArray_compare cmp);
int DArray_mergesort(DArray *array, DArray_compare cmp);
#endif

View File

@@ -0,0 +1,30 @@
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:%s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
#endif

View File

@@ -0,0 +1,244 @@
#include <lcthw/list.h>
#include <lcthw/dbg.h>
List *List_create()
{
return calloc(1, sizeof(List));
}
void List_destroy(List *list)
{
List_validate(list);
LIST_FOREACH(list, first, next, cur) {
if(cur->prev) {
free(cur->prev);
}
}
free(list->last);
free(list);
}
void List_clear(List *list)
{
List_validate(list);
LIST_FOREACH(list, first, next, cur) {
free(cur->value);
}
}
void List_clear_destroy(List *list)
{
List_validate(list);
LIST_FOREACH(list, first, next, cur) {
free(cur->value);
if(cur->prev) {
free(cur->prev);
}
}
free(list->last);
free(list);
}
void List_push(List *list, void *value)
{
List_validate(list);
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)
{
List_validate(list);
ListNode *node = list->last;
return node != NULL ? List_remove(list, node) : NULL;
}
void List_unshift(List *list, void *value)
{
List_validate(list);
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)
{
List_validate(list);
ListNode *node = list->first;
return node != NULL ? List_remove(list, node) : NULL;
}
void *List_remove(List *list, ListNode *node)
{
List_validate(list);
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;
}
List *List_copy(List *list)
{
List_validate(list);
List *out = List_create();
LIST_FOREACH(list, first, next, cur) {
List_push(out, cur->value);
}
return out;
}
int List_split(List *list, void *split, List *a, List *b)
{
List_validate(list);
check(list->first && list->last, "List is empty.");
check(split, "split can't be NULL");
if(split == list->last->value || (split == list->first->value && split == list->last->value)) {
(*a) = *List_copy(list);
return 0;
} else if(split == list->first->value) {
(*b) = *List_copy(list);
List_push(a, List_shift(b));
return 0;
} else {
int past_split = 0;
LIST_FOREACH(list, first, next, cur) {
if(past_split) {
List_push(b, cur->value);
continue;
}
if(cur->value == split) {
past_split = 1;
}
List_push(a, cur->value);
}
}
return 0;
error:
return -1;
}
void List_join(List *list, List *b)
{
List_validate(list);
List_validate(b);
List *tail = List_copy(b);
list->last->next = tail->first;
list->count += tail->count;
free(tail);
return;
}
void List_swap(ListNode *a, ListNode *b)
{
ListNode *tmp = a->next;
a->next = b->next;
b->next = tmp;
tmp = a->prev;
a->prev = b->prev;
b->prev = tmp;
}
void List_dump(List *list)
{
List_validate(list);
int i = 0;
int j = 0;
LIST_FOREACH(list, first, next, cur) {
if(i > 0) {
for(j = 0; j < (i*4); j++) {
printf(" ");
}
printf("`");
}
printf("-> [%d] ListNode .value = %p (%s)\n", i, cur->value, (char *)cur->value);
i++;
}
}

View File

@@ -0,0 +1,51 @@
#ifndef lcthw_List_h
#define lcthw_List_h
#include <stdlib.h>
#include <assert.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);
List *List_copy(List *list);
int List_split(List *list, void *split, List *a, List *b);
void List_join(List *list, List *b);
void List_swap(ListNode *a, ListNode *b);
void List_dump(List *list);
#define List_validate(A) (assert(A != NULL && List_count(A) > -1 &&\
(List_count(A) > 0 && List_first(A) != NULL) && "invalid *List"))
#define LIST_FOREACH(L, F, N, C) ListNode *_node = NULL;\
ListNode *C = NULL;\
for(C = _node = L->F; _node != NULL; C = _node = _node->N)
#endif

View File

@@ -0,0 +1,87 @@
#include <lcthw/list_algos.h>
#include <lcthw/dbg.h>
int List_bubble_sort(List *list, List_compare cmp)
{
List_validate(list);
if(List_count(list) <= 1) {
return 0;
}
int swapped = 1;
while(swapped == 1) {
swapped = 0;
LIST_FOREACH(list, first, next, cur) {
if(cur->next == NULL) {
continue;
}
if(cmp(cur->value, cur->next->value) > 0) {
List_swap(cur, cur->next);
swapped = 1;
}
}
}
return 0;
}
List *List_merge(List *left, List *right, List_compare cmp)
{
List *result = List_create();
while(List_count(left) > 0 && List_count(right) > 0) {
if(cmp(List_first(left), List_first(right)) <= 0) {
List_push(result, List_shift(left));
continue;
}
List_push(result, List_shift(right));
}
while(List_count(left) > 0) {
List_push(result, List_shift(left));
}
while(List_count(right) > 0) {
List_push(result, List_shift(right));
}
return result;
}
List *List_merge_sort(List *list, List_compare cmp)
{
if(List_count(list) <= 1) {
return list;;
}
int i = 0;
List *left = List_create();
List *right = List_create();
LIST_FOREACH(list, first, next, cur) {
if(i % 2 == 0) {
List_push(right, cur->value);
} else {
List_push(left, cur->value);
}
i++;
}
List *sort_left = List_merge_sort(left, cmp);
List *sort_right = List_merge_sort(right, cmp);
if(sort_left != left) {
List_destroy(left);
}
if(sort_right != right) {
List_destroy(right);
}
return List_merge(sort_left, sort_right, cmp);
}

View File

@@ -0,0 +1,12 @@
#ifndef lcthw_List_algos_h
#define lcthw_List_algos_h
#include <lcthw/list.h>
typedef int (*List_compare)(const void *a, const void *b);
int List_bubble_sort(List *list, List_compare cmp);
List *List_merge_sort(List *list, List_compare cmp);
#endif

View File

@@ -0,0 +1,140 @@
/*
* Based on code by Andre Reinald then heavily modified by Zed A. Shaw
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdint.h>
#include <lcthw/radixmap.h>
#include <lcthw/dbg.h>
RadixMap *RadixMap_create(size_t max)
{
RadixMap *map = calloc(sizeof(RadixMap), 1);
check_mem(map);
map->contents = calloc(sizeof(RMElement), max + 1);
check_mem(map->contents);
map->temp = calloc(sizeof(RMElement), max + 1);
check_mem(map->temp);
map->max = max;
map->end = 0;
return map;
error:
return NULL;
}
void RadixMap_destroy(RadixMap *map)
{
if(map) {
free(map->contents);
free(map->temp);
free(map);
}
}
#define ByteOf(x,y) (((uint8_t *)x)[y])
static inline void radix_sort(short offset, uint64_t max, uint64_t *source, uint64_t *dest)
{
uint64_t count[256] = {0};
uint64_t *cp = NULL;
uint64_t *sp = NULL;
uint64_t *end = NULL;
uint64_t s = 0;
uint64_t c = 0;
// count occurences of every byte value
for(sp = source, end = source + max; sp < end; sp++) {
count[ByteOf(sp, offset)]++;
}
// transform count into index by summing elements and storing into same array
for(s = 0, cp = count, end = count + 256; cp < end; cp++) {
c = *cp;
*cp = s;
s += c;
}
// fill dest with the right values in the right place
for(sp = source, end = source + max; sp < end; sp++) {
cp = count + ByteOf(sp, offset);
dest[*cp] = *sp;
++(*cp);
}
}
void RadixMap_sort(RadixMap *map)
{
uint64_t *source = &map->contents[0].raw;
uint64_t *temp = &map->temp[0].raw;
radix_sort(0, map->end, source, temp);
radix_sort(1, map->end, temp, source);
radix_sort(2, map->end, source, temp);
radix_sort(3, map->end, temp, source);
}
RMElement *RadixMap_find(RadixMap *map, uint32_t to_find)
{
int low = 0;
int high = map->end - 1;
RMElement *data = map->contents;
while(low <= high) {
int middle = low + (high - low)/2;
uint32_t key = data[middle].data.key;
if(to_find < key) {
high = middle - 1;
} else if(to_find > key) {
low = middle + 1;
} else {
return &data[middle];
}
}
return NULL;
}
int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value)
{
check(key < UINT32_MAX, "Key can't be equal to UINT32_MAX.");
RMElement element = {.data = {.key = key, .value = value}};
check(map->end + 1 < map->max, "RadixMap is full.");
map->contents[map->end++] = element;
RadixMap_sort(map);
return 0;
error:
return -1;
}
int RadixMap_delete(RadixMap *map, RMElement *el)
{
check(map->end > 0, "There is nothing to delete.");
check(el != NULL, "Can't delete a NULL element.");
el->data.key = UINT32_MAX;
if(map->end > 1) {
// don't bother resorting a map of 1 length
RadixMap_sort(map);
}
map->end--;
return 0;
error:
return -1;
}

View File

@@ -0,0 +1,35 @@
#ifndef lcthw_radixmap_h
#define lcthw_radixmap_h
#include <stdint.h>
typedef union RMElement {
uint64_t raw;
struct {
uint32_t key;
uint32_t value;
} data;
} RMElement;
typedef struct RadixMap {
size_t max;
size_t end;
uint32_t counter;
RMElement *contents;
RMElement *temp;
} RadixMap;
RadixMap *RadixMap_create(size_t max);
void RadixMap_destroy(RadixMap *map);
void RadixMap_sort(RadixMap *map);
RMElement *RadixMap_find(RadixMap *map, uint32_t key);
int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value);
int RadixMap_delete(RadixMap *map, RMElement *el);
#endif

View File

@@ -0,0 +1,55 @@
#include "../minunit.h"
#include <lcthw/bstrlib.h>
char *test_bfromcstr()
{
bstring b = bfromcstr("oh hai");
mu_assert(b != NULL, "bstring is NULL.");
return NULL;
}
char *test_blk2bstr()
{
bstring b = blk2bstr("hats", 5);
mu_assert(b != NULL, "bstring is NULL.");
b = blk2bstr(NULL, 42);
mu_assert(b == NULL, "bstring is not NULL.");
b = blk2bstr("bats", -17);
mu_assert(b == NULL, "bstring is not NULL.");
return NULL;
}
char *test_bstrcpy()
{
bstring b = bfromcstr("mats");
mu_assert(bstrcpy(b) != NULL, "bstring is NULL.");
mu_assert(bstrcpy(NULL) == NULL, "bstring is not NULL.");
int orig_len = b->slen;
b->slen = -1;
mu_assert(bstrcpy(b) == NULL, "bstring is not NULL.");
b->slen = orig_len;
b->data = NULL;
mu_assert(bstrcpy(b) == NULL, "bstring is not NULL.");
return NULL;
}
char *all_tests()
{
mu_suite_start();
mu_run_test(test_bfromcstr);
mu_run_test(test_blk2bstr);
mu_run_test(test_bstrcpy);
return NULL;
}
RUN_TESTS(all_tests);

View File

@@ -0,0 +1,78 @@
#include "../minunit.h"
#include <lcthw/darray_algos.h>
int testcmp(char **a, char **b)
{
return strcmp(*a, *b);
}
DArray *create_words()
{
DArray *result = DArray_create(0, 5);
char *words[] = {"asdfasfd", "werwar", "13234", "asdfasfd", "oioj"};
int i = 0;
for(i = 0; i < 5; i++) {
DArray_push(result, words[i]);
}
return result;
}
int is_sorted(DArray *array)
{
int i = 0;
for(i = 0; i < DArray_count(array) - 1; i++) {
if(strcmp(DArray_get(array, i), DArray_get(array, i+1)) > 0) {
return 0;
}
}
return 1;
}
char *run_sort_test(int (*func)(DArray *, DArray_compare), const char *name)
{
DArray *words = create_words();
mu_assert(!is_sorted(words), "Words should start not sorted.");
name = name;
debug("--- Testing %s sorting algorithm", name);
int rc = func(words, (DArray_compare)testcmp);
mu_assert(rc == 0, "sort failed");
mu_assert(is_sorted(words), "didn't sort it");
DArray_destroy(words);
return NULL;
}
char *test_qsort()
{
return run_sort_test(DArray_qsort, "qsort");
}
char *test_heapsort()
{
return run_sort_test(DArray_heapsort, "heapsort");
}
char *test_mergesort()
{
return run_sort_test(DArray_mergesort, "mergesort");
}
char *all_tests()
{
mu_suite_start();
mu_run_test(test_qsort);
mu_run_test(test_heapsort);
mu_run_test(test_mergesort);
return NULL;
}
RUN_TESTS(all_tests);

View File

@@ -0,0 +1,124 @@
#include "../minunit.h"
#include <lcthw/darray.h>
static DArray *array = NULL;
static int *val1 = NULL;
static int *val2 = NULL;
char *test_create()
{
array = DArray_create(sizeof(int), 100);
mu_assert(array != NULL, "DArray_create failed.");
mu_assert(array->contents != NULL, "contents are wrong in darray");
mu_assert(array->end == 0, "end isn't at the right spot");
mu_assert(array->element_size == sizeof(int), "element size is wrong.");
mu_assert(array->max == 100, "wrong max length on initial size");
return NULL;
}
char *test_destroy()
{
DArray_destroy(array);
return NULL;
}
char *test_new()
{
val1 = DArray_new(array);
mu_assert(val1 != NULL, "failed to make a new element");
val2 = DArray_new(array);
mu_assert(val2 != NULL, "failed to make a new element");
return NULL;
}
char *test_set()
{
DArray_set(array, 0, val1);
DArray_set(array, 1, val2);
return NULL;
}
char *test_get()
{
mu_assert(DArray_get(array, 0) == val1, "Wrong first value.");
mu_assert(DArray_get(array, 1) == val2, "Wrong second value.");
return NULL;
}
char *test_remove()
{
int *val_check = DArray_remove(array, 0);
mu_assert(val_check != NULL, "Should not get NULL.");
mu_assert(*val_check == *val1, "Should get the first value.");
mu_assert(DArray_get(array, 0) == NULL, "Should be gone.");
DArray_free(val_check);
val_check = DArray_remove(array, 1);
mu_assert(val_check != NULL, "Should not get NULL.");
mu_assert(*val_check == *val2, "Should get the second value.");
mu_assert(DArray_get(array, 1) == NULL, "Should be gone.");
DArray_free(val_check);
return NULL;
}
char *test_expand_contract()
{
int old_max = array->max;
DArray_expand(array);
mu_assert((unsigned int)array->max == old_max + array->expand_rate, "Wrong size after expand.");
DArray_contract(array);
mu_assert((unsigned int)array->max == array->expand_rate + 1, "Should stay at the expand_rate at least.");
DArray_contract(array);
mu_assert((unsigned int)array->max == array->expand_rate + 1, "Should stay at the expand_rate at least.");
return NULL;
}
char *test_push_pop()
{
int i = 0;
for(i = 0; i < 1000; i++) {
int *val = DArray_new(array);
*val = i * 333;
DArray_push(array, val);;
}
mu_assert(array->max == 1201, "Wrong max size.");
for(i = 999; i >= 0; i--) {
int *val = DArray_pop(array);
mu_assert(val != NULL, "Shouldn't get a NULL.");
mu_assert(*val == i * 333, "Wrong value.");
DArray_free(val);
}
return NULL;
}
char *all_tests()
{
mu_suite_start();
mu_run_test(test_create);
mu_run_test(test_new);
mu_run_test(test_set);
mu_run_test(test_get);
mu_run_test(test_remove);
mu_run_test(test_expand_contract);
mu_run_test(test_push_pop);
mu_run_test(test_destroy);
return NULL;
}
RUN_TESTS(all_tests);

View File

@@ -0,0 +1,91 @@
#include "../minunit.h"
#include <lcthw/list_algos.h>
#include <assert.h>
#include <string.h>
char *values[] = {"XXXX", "1234", "abcd", "xjvef", "NDSS"};
#define NUM_VALUES 5
List *create_words()
{
int i = 0;
List *words = List_create();
for(i = 0; i < NUM_VALUES; i++) {
List_push(words, values[i]);
}
return words;
}
int is_sorted(List *words)
{
LIST_FOREACH(words, first, next, cur) {
if(cur->next && strcmp(cur->value, cur->next->value) > 0) {
debug("%s %s", (char *)cur->value, (char *)cur->next->value);
return 0;
}
}
return 1;
}
char *test_bubble_sort()
{
List *words = create_words();
// should work on a list that needs sorting
int rc = List_bubble_sort(words, (List_compare)strcmp);
mu_assert(rc == 0, "Bubble sort failed.");
mu_assert(is_sorted(words), "Words are not sorted after bubble sort.");
// should work on an already sorted list
rc = List_bubble_sort(words, (List_compare)strcmp);
mu_assert(rc == 0, "Bubble sort of already sorted failed.");
mu_assert(is_sorted(words), "Words should be sorted if already bubble sorted.");
List_destroy(words);
// should work on an empty list
words = List_create();
rc = List_bubble_sort(words, (List_compare)strcmp);
mu_assert(rc == 0, "Bubble sort failed on empty list.");
mu_assert(is_sorted(words), "Words should be sorted if empty.");
List_destroy(words);
return NULL;
}
char *test_merge_sort()
{
List *words = create_words();
// should work on a list that needs sorting
List *res = List_merge_sort(words, (List_compare)strcmp);
mu_assert(List_count(res) == List_count(words), "Sorted list has different count.");
mu_assert(is_sorted(res), "Words are not sorted after merge sort.");
List *res2 = List_merge_sort(res, (List_compare)strcmp);
mu_assert(List_count(res2) == List_count(res), "Sorted list has different count.");
mu_assert(is_sorted(res), "Should still be sorted after merge sort.");
List_destroy(res2);
List_destroy(res);
List_destroy(words);
return NULL;
}
char *all_tests()
{
mu_suite_start();
mu_run_test(test_bubble_sort);
mu_run_test(test_merge_sort);
return NULL;
}
RUN_TESTS(all_tests);

View File

@@ -0,0 +1,205 @@
#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 *test4 = "test4 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 *test_copy()
{
list = List_create();
mu_assert(List_count(list) == 0, "Wrong count before copy.");
List_push(list, test1);
List_push(list, test2);
List_push(list, test3);
List_push(list, test4);
mu_assert(List_count(list) == 4, "Wrong count after push.");
List *copy = List_copy(list);
mu_assert(copy != list, "Copy and list have same address.");
mu_assert(List_count(copy) == 4, "Copy has wrong count.");
return NULL;
}
char *test_split()
{
mu_assert(List_count(list) == 4, "Wrong count before split.");
List *a = List_create();
List *b = List_create();
List *tmp = List_copy(list);
int rc = -1;
rc = List_split(tmp, test2, a, b);
mu_assert(rc == 0, "Failed to split.");
mu_assert(List_count(a) == 2, "List 'a' has wrong count.");
mu_assert(List_count(b) == 2, "List 'b' has wrong count.");
List_destroy(a);
List_destroy(b);
a = List_create();
b = List_create();
tmp = List_copy(list);
rc = List_split(tmp, test1, a, b);
mu_assert(rc == 0, "Failed to split.");
mu_assert(List_count(a) == 1, "List 'a' has wrong count.");
mu_assert(List_count(b) == 3, "List 'b' has wrong count.");
List_destroy(a);
List_destroy(b);
a = List_create();
b = List_create();
tmp = List_copy(list);
rc = List_split(tmp, test3, a, b);
mu_assert(rc == 0, "Failed to split.");
mu_assert(List_count(a) == 3, "List 'a' has wrong count.");
mu_assert(List_count(b) == 1, "List 'b' has wrong count.");
List_destroy(a);
List_destroy(b);
a = List_create();
b = List_create();
tmp = List_copy(list);
rc = List_split(tmp, test4, a, b);
mu_assert(rc == 0, "Failed to split.");
mu_assert(List_count(a) == 4, "List 'a' has wrong count.");
mu_assert(List_count(b) == 0, "List 'b' has wrong count.");
return NULL;
}
char *test_join()
{
mu_assert(List_count(list) == 4, "Wrong count before join.");
List *b = List_create();
List_push(b, test4);
mu_assert(List_count(b) == 1, "List 'b' has wrong count.");
List_join(list, b);
mu_assert(List_count(list) == 5, "Wrong count after join.");
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);
mu_run_test(test_copy);
mu_run_test(test_split);
mu_run_test(test_join);
return NULL;
}
RUN_TESTS(all_tests);

View File

@@ -0,0 +1,105 @@
#include "../minunit.h"
#include <stdint.h>
#include <lcthw/radixmap.h>
#include <stdlib.h>
#include <time.h>
static int make_random(RadixMap *map)
{
size_t i = 0;
for(i = 0; i < map->max - 1; i++) {
uint32_t key = (uint32_t)(rand() | (rand() << 16));
check(RadixMap_add(map, key, i) == 0, "Failed to add key %u", key);
}
return i;
error:
return 0;
}
static int check_order(RadixMap *map)
{
RMElement d1, d2;
unsigned int i = 0;
// only signal errors if any (should not be)
for(i = 0; map->end > 0 && i < map->end-1; i++) {
d1 = map->contents[i];
d2 = map->contents[i+1];
if(d1.data.key > d2.data.key) {
debug("FAIL:i=%u, key: %u, value: %u, equals max? %d\n", i, d1.data.key, d1.data.value,
d2.data.key == UINT32_MAX);
return 0;
}
}
return 1;
}
static int test_search(RadixMap *map)
{
unsigned int i = 0;
RMElement *d = NULL;
RMElement *found = NULL;
for(i = map->end / 2; i < map->end; i++) {
d = &map->contents[i];
found = RadixMap_find(map, d->data.key);
check(found != NULL, "Didn't find %u at %u.", d->data.key, i);
check(found->data.key == d->data.key, "Got the wrong result: %p:%u looking for %u at %u",
found, found->data.key, d->data.key, i);
}
return 1;
error:
return 0;
}
// test for big number of elements
static char *test_operations()
{
size_t N = 200;
RadixMap *map = RadixMap_create(N);
mu_assert(map != NULL, "Failed to make the map.");
mu_assert(make_random(map), "Didn't make a random fake radix map.");
RadixMap_sort(map);
mu_assert(check_order(map), "Failed to properly sort the RadixMap.");
mu_assert(test_search(map), "Failed the search test.");
mu_assert(check_order(map), "RadixMap didn't stay sorted after search.");
while(map->end > 0) {
RMElement *el = RadixMap_find(map, map->contents[map->end / 2].data.key);
mu_assert(el != NULL, "Should get a result.");
size_t old_end = map->end;
mu_assert(RadixMap_delete(map, el) == 0, "Didn't delete it.");
mu_assert(old_end - 1 == map->end, "Wrong size after delete.");
// test that the end is now the old value, but uint32 max so it trails off
mu_assert(check_order(map), "RadixMap didn't stay sorted after delete.");
}
RadixMap_destroy(map);
return NULL;
}
char *all_tests()
{
mu_suite_start();
srand(time(NULL));
mu_run_test(test_operations);
return NULL;
}
RUN_TESTS(all_tests);

View File

@@ -0,0 +1,38 @@
#undef DNDEBUG
#ifndef _minunit_h
#define _minunit_h
#include <stdio.h>
#include <lcthw/dbg.h>
#include <stdlib.h>
#define mu_suite_start() char *message = NULL
#define mu_assert(test, message) if (!(test)) {\
log_err(message); return message;\
}\
assertions_made++;
#define mu_run_test(test) debug("\n-----%s", " " #test); \
message = test(); tests_run++; if (message) return message;
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
argc = argc; \
argv = argv; \
debug("----- RUNNING: %s", argv[0]);\
printf("----\nRUNNING: %s\n", argv[0]);\
char *result = name();\
if (result != 0) {\
printf("FAILED: %s\n", result);\
}\
else {\
printf("ALL TESTS PASSED\n");\
}\
printf("Tests run: %d\n", tests_run);\
printf("Assertions made: %d\n", assertions_made);\
exit(result != 0);\
}
int tests_run;
int assertions_made;
#endif

View File

@@ -0,0 +1,107 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <fnmatch.h>
#include <lcthw/dbg.h>
int test_selector(const struct dirent *ep)
{
return fnmatch("*_tests", ep->d_name, 0) == 0;
}
int run_tests_file(char *filename)
{
if(access(filename, R_OK | X_OK) == 0) {
return system(filename);
}
return -1;
}
int main(int argc, char *argv[])
{
int entcount = 0;
int rc = 0;
int i = 0;
int ntests = 0;
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";
}
entcount = scandir((const char *)testsdir, &namelist, test_selector, alphasort);
check(entcount > -1, "Failed to scan tests dir");
for(i = 0; i < entcount; i++) {
ep = namelist[i];
check(ep, "Dirent is missing.");
char filename[256];
rc = sprintf(filename, "%s/%s", testsdir, ep->d_name);
check(rc > -1, "Failed to build filename.");
debug("Found filename '%s'", filename);
free(ep);
if(valgrind) {
char command[1024];
rc = sprintf(command, "%s %s", valgrind, filename);
check(rc > -1, "Failed to build command with valgrind.");
rc = run_tests_file(command);
} else {
rc = run_tests_file(filename);
}
if(rc > 0) {
debug("Skipping '%s'", filename);
continue;
}
ntests++;
if(rc == 0) {
printf("%s PASS\n", filename);
continue;
}
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 file%s run.\n", ntests, ntests > 1 ? "s" : "");
if(namelist) {
free(namelist);
}
return 0;
error:
if(namelist) {
free(namelist);
}
return rc != 0 ? rc : 1;
}