From 846d0bbba6953bf407d48bf76429aca9fc2866a8 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 4 Jul 2019 02:18:05 -0300 Subject: [PATCH] More tests --- tests/main/Makefile | 2 +- tests/main/main.c | 4 + tests/main/src/deque.c | 128 +++++----- tests/main/src/heap.c | 294 ++++++++++++++++++++++ tests/main/src/linkedlist.c | 479 ++++++++++++++++++++++++++++++++++++ tests/main/unt/hashmap.c | 2 +- tests/main/unt/heap.c | 75 ++++++ tests/main/unt/linkedlist.c | 93 +++++++ tests/main/unt/list.c | 158 ++++++++++-- 9 files changed, 1147 insertions(+), 88 deletions(-) create mode 100644 tests/main/src/heap.c create mode 100644 tests/main/src/linkedlist.c create mode 100644 tests/main/unt/heap.c create mode 100644 tests/main/unt/linkedlist.c diff --git a/tests/main/Makefile b/tests/main/Makefile index 4e9a717..8a8d8fd 100644 --- a/tests/main/Makefile +++ b/tests/main/Makefile @@ -1,6 +1,6 @@ CC = gcc CFLAGS = -std=c11 -Wall -Wextra -CFLAGS += -Wno-unused-function -Wno-unused-paramter -Wno-unused-variable -Wno-unused-label +CFLAGS += -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-unused-label CVFLAGS = --coverage -O0 INCLUDE = ../../src/ diff --git a/tests/main/main.c b/tests/main/main.c index 903bedd..9053716 100644 --- a/tests/main/main.c +++ b/tests/main/main.c @@ -1,6 +1,8 @@ #include "unt/deque.c" #include "unt/hashmap.c" #include "unt/hashset.c" +#include "unt/heap.c" +#include "unt/linkedlist.c" #include "unt/list.c" int main(void) @@ -8,6 +10,8 @@ int main(void) deque_test(); hashmap_test(); hashset_test(); + heap_test(); + linkedlist_test(); list_test(); return 0; diff --git a/tests/main/src/deque.c b/tests/main/src/deque.c index 77e620e..0cf3cf9 100644 --- a/tests/main/src/deque.c +++ b/tests/main/src/deque.c @@ -15,36 +15,36 @@ typedef struct deque_iter_s struct deque_s *target; size_t cursor; size_t index; - _Bool start; - _Bool end; + bool start; + bool end; } deque_iter, *deque_iter_ptr; deque *d_new(size_t capacity); void d_clear(deque *_deque_); void d_free(deque *_deque_); -_Bool d_push_front(deque *_deque_, size_t element); -_Bool d_push_back(deque *_deque_, size_t element); -_Bool d_pop_front(deque *_deque_); -_Bool d_pop_back(deque *_deque_); -_Bool d_push_front_if(deque *_deque_, size_t element, _Bool condition); -_Bool d_push_back_if(deque *_deque_, size_t element, _Bool condition); -_Bool d_pop_front_if(deque *_deque_, _Bool condition); -_Bool d_pop_back_if(deque *_deque_, _Bool condition); +bool d_push_front(deque *_deque_, size_t element); +bool d_push_back(deque *_deque_, size_t element); +bool d_pop_front(deque *_deque_); +bool d_pop_back(deque *_deque_); +bool d_push_front_if(deque *_deque_, size_t element, bool condition); +bool d_push_back_if(deque *_deque_, size_t element, bool condition); +bool d_pop_front_if(deque *_deque_, bool condition); +bool d_pop_back_if(deque *_deque_, bool condition); size_t d_front(deque *_deque_); size_t d_back(deque *_deque_); -_Bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t)); -_Bool d_empty(deque *_deque_); -_Bool d_full(deque *_deque_); +bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t)); +bool d_empty(deque *_deque_); +bool d_full(deque *_deque_); size_t d_count(deque *_deque_); size_t d_capacity(deque *_deque_); deque_iter *d_iter_new(deque *target); void d_iter_free(deque_iter *iter); void d_iter_init(deque_iter *iter, deque *target); -_Bool d_iter_start(deque_iter *iter); -_Bool d_iter_end(deque_iter *iter); +bool d_iter_start(deque_iter *iter); +bool d_iter_end(deque_iter *iter); void d_iter_to_start(deque_iter *iter); void d_iter_to_end(deque_iter *iter); -_Bool d_iter_next(deque_iter *iter); -_Bool d_iter_prev(deque_iter *iter); +bool d_iter_next(deque_iter *iter); +bool d_iter_prev(deque_iter *iter); size_t d_iter_value(deque_iter *iter); size_t *d_iter_rvalue(deque_iter *iter); size_t d_iter_index(deque_iter *iter); @@ -54,21 +54,21 @@ static inline size_t d_impl_default_value(void) memset(&_empty_value_, 0, sizeof(size_t)); return _empty_value_; } -static _Bool d_impl_grow(deque *_deque_); +static bool d_impl_grow(deque *_deque_); static deque_iter d_impl_it_start(deque *_deque_); static deque_iter d_impl_it_end(deque *_deque_); deque *d_new(size_t capacity) { if (capacity < 1) - return ((void *)0); + return NULL; deque *_deque_ = malloc(sizeof(deque)); if (!_deque_) - return ((void *)0); + return NULL; _deque_->buffer = malloc(sizeof(size_t) * capacity); if (!_deque_->buffer) { free(_deque_); - return ((void *)0); + return NULL; } memset(_deque_->buffer, 0, sizeof(size_t) * capacity); _deque_->capacity = capacity; @@ -91,71 +91,71 @@ void d_free(deque *_deque_) free(_deque_->buffer); free(_deque_); } -_Bool d_push_front(deque *_deque_, size_t element) +bool d_push_front(deque *_deque_, size_t element) { if (d_full(_deque_)) { if (!d_impl_grow(_deque_)) - return 0; + return false; } _deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; _deque_->buffer[_deque_->front] = element; _deque_->count++; - return 1; + return true; } -_Bool d_push_back(deque *_deque_, size_t element) +bool d_push_back(deque *_deque_, size_t element) { if (d_full(_deque_)) { if (!d_impl_grow(_deque_)) - return 0; + return false; } _deque_->buffer[_deque_->back] = element; _deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; _deque_->count++; - return 1; + return true; } -_Bool d_pop_front(deque *_deque_) +bool d_pop_front(deque *_deque_) { if (d_empty(_deque_)) - return 0; + return false; _deque_->buffer[_deque_->front] = d_impl_default_value(); _deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; _deque_->count--; - return 1; + return true; } -_Bool d_pop_back(deque *_deque_) +bool d_pop_back(deque *_deque_) { if (d_empty(_deque_)) - return 0; + return false; _deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; _deque_->buffer[_deque_->back] = d_impl_default_value(); _deque_->count--; - return 1; + return true; } -_Bool d_push_front_if(deque *_deque_, size_t element, _Bool condition) +bool d_push_front_if(deque *_deque_, size_t element, bool condition) { if (condition) return d_push_front(_deque_, element); - return 0; + return false; } -_Bool d_push_back_if(deque *_deque_, size_t element, _Bool condition) +bool d_push_back_if(deque *_deque_, size_t element, bool condition) { if (condition) return d_push_back(_deque_, element); - return 0; + return false; } -_Bool d_pop_front_if(deque *_deque_, _Bool condition) +bool d_pop_front_if(deque *_deque_, bool condition) { if (condition) return d_pop_front(_deque_); - return 0; + return false; } -_Bool d_pop_back_if(deque *_deque_, _Bool condition) +bool d_pop_back_if(deque *_deque_, bool condition) { if (condition) return d_pop_back(_deque_); - return 0; + return false; } size_t d_front(deque *_deque_) { @@ -169,24 +169,24 @@ size_t d_back(deque *_deque_) d_impl_default_value(); return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; } -_Bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t)) +bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t)) { for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++) { if (comparator(_deque_->buffer[i], element) == 0) - return 1; + return true; } - return 0; + return false; } -_Bool d_empty(deque *_deque_) { return _deque_->count == 0; } -_Bool d_full(deque *_deque_) { return _deque_->count >= _deque_->capacity; } +bool d_empty(deque *_deque_) { return _deque_->count == 0; } +bool d_full(deque *_deque_) { return _deque_->count >= _deque_->capacity; } size_t d_count(deque *_deque_) { return _deque_->count; } size_t d_capacity(deque *_deque_) { return _deque_->capacity; } deque_iter *d_iter_new(deque *target) { deque_iter *iter = malloc(sizeof(deque_iter)); if (!iter) - return ((void *)0); + return NULL; d_iter_init(iter, target); return iter; } @@ -196,16 +196,16 @@ void d_iter_init(deque_iter *iter, deque *target) iter->target = target; iter->cursor = target->front; iter->index = 0; - iter->start = 1; + iter->start = true; iter->end = d_empty(target); } -_Bool d_iter_start(deque_iter *iter) { return d_empty(iter->target) || iter->start; } -_Bool d_iter_end(deque_iter *iter) { return d_empty(iter->target) || iter->end; } +bool d_iter_start(deque_iter *iter) { return d_empty(iter->target) || iter->start; } +bool d_iter_end(deque_iter *iter) { return d_empty(iter->target) || iter->end; } void d_iter_to_start(deque_iter *iter) { iter->cursor = iter->target->front; iter->index = 0; - iter->start = 1; + iter->start = true; iter->end = d_empty(iter->target); } void d_iter_to_end(deque_iter *iter) @@ -216,35 +216,35 @@ void d_iter_to_end(deque_iter *iter) iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; iter->index = iter->target->count - 1; iter->start = d_empty(iter->target); - iter->end = 1; + iter->end = true; } -_Bool d_iter_next(deque_iter *iter) +bool d_iter_next(deque_iter *iter) { if (iter->end) - return 0; + return false; iter->start = d_empty(iter->target); if (iter->index == iter->target->count - 1) - iter->end = 1; + iter->end = true; else { iter->cursor = (iter->cursor + 1) % (iter->target->capacity); iter->index++; } - return 1; + return true; } -_Bool d_iter_prev(deque_iter *iter) +bool d_iter_prev(deque_iter *iter) { if (iter->start) - return 0; + return false; iter->end = d_empty(iter->target); if (iter->index == 0) - iter->start = 1; + iter->start = true; else { iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; iter->index--; } - return 1; + return true; } size_t d_iter_value(deque_iter *iter) { @@ -255,16 +255,16 @@ size_t d_iter_value(deque_iter *iter) size_t *d_iter_rvalue(deque_iter *iter) { if (d_empty(iter->target)) - return ((void *)0); + return NULL; return &(iter->target->buffer[iter->cursor]); } size_t d_iter_index(deque_iter *iter) { return iter->index; } -static _Bool d_impl_grow(deque *_deque_) +static bool d_impl_grow(deque *_deque_) { size_t new_capacity = _deque_->capacity * 2; size_t *new_buffer = malloc(sizeof(size_t) * new_capacity); if (!new_buffer) - return 0; + return false; for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) { new_buffer[j] = _deque_->buffer[i]; @@ -274,7 +274,7 @@ static _Bool d_impl_grow(deque *_deque_) _deque_->capacity = new_capacity; _deque_->front = 0; _deque_->back = _deque_->count; - return 1; + return true; } static deque_iter d_impl_it_start(deque *_deque_) { diff --git a/tests/main/src/heap.c b/tests/main/src/heap.c new file mode 100644 index 0000000..a9134ec --- /dev/null +++ b/tests/main/src/heap.c @@ -0,0 +1,294 @@ +#include "cmc/heap.h" + +typedef struct heap_s +{ + size_t *buffer; + size_t capacity; + size_t count; + enum HeapOrder HO; + int (*cmp)(size_t, size_t); + struct heap_iter_s (*it_start)(struct heap_s *); + struct heap_iter_s (*it_end)(struct heap_s *); +} heap, *heap_ptr; +typedef struct heap_iter_s +{ + struct heap_s *target; + size_t cursor; + bool start; + bool end; +} heap_iter, *heap_iter_ptr; +heap *h_new(size_t capacity, HeapOrder HO, int (*compare)(size_t, size_t)); +void h_clear(heap *_heap_); +void h_free(heap *_heap_); +bool h_insert(heap *_heap_, size_t element); +bool h_remove(heap *_heap_, size_t *result); +bool h_insert_if(heap *_heap_, size_t element, bool condition); +bool h_remove_if(heap *_heap_, size_t *result, bool condition); +size_t h_peek(heap *_heap_); +size_t *h_peek_ref(heap *_heap_); +bool h_contains(heap *_heap_, size_t element); +bool h_empty(heap *_heap_); +bool h_full(heap *_heap_); +size_t h_count(heap *_heap_); +size_t h_capacity(heap *_heap_); +heap_iter *h_iter_new(heap *target); +void h_iter_free(heap_iter *iter); +void h_iter_init(heap_iter *iter, heap *target); +bool h_iter_start(heap_iter *iter); +bool h_iter_end(heap_iter *iter); +void h_iter_to_start(heap_iter *iter); +void h_iter_to_end(heap_iter *iter); +bool h_iter_next(heap_iter *iter); +bool h_iter_prev(heap_iter *iter); +size_t h_iter_value(heap_iter *iter); +size_t h_iter_index(heap_iter *iter); +static inline size_t h_impl_default_value(void) +{ + size_t _empty_value_; + memset(&_empty_value_, 0, sizeof(size_t)); + return _empty_value_; +} +static bool h_impl_grow(heap *_heap_); +static size_t h_impl_p(size_t index); +static size_t h_impl_l(size_t index); +static size_t h_impl_r(size_t index); +static bool h_impl_float_up(heap *_heap_, size_t index); +static bool h_impl_float_down(heap *_heap_, size_t index); +static heap_iter h_impl_it_start(heap *_heap_); +static heap_iter h_impl_it_end(heap *_heap_); +heap *h_new(size_t capacity, HeapOrder HO, int (*compare)(size_t, size_t)) +{ + if (capacity < 1) + return NULL; + if (HO != MinHeap && HO != MaxHeap) + return NULL; + heap *_heap_ = malloc(sizeof(heap)); + if (!_heap_) + return NULL; + _heap_->buffer = malloc(sizeof(size_t) * capacity); + if (!_heap_->buffer) + { + free(_heap_); + return NULL; + } + memset(_heap_->buffer, 0, sizeof(size_t) * capacity); + _heap_->capacity = capacity; + _heap_->count = 0; + _heap_->HO = HO; + _heap_->cmp = compare; + _heap_->it_start = h_impl_it_start; + _heap_->it_end = h_impl_it_end; + return _heap_; +} +void h_clear(heap *_heap_) +{ + memset(_heap_->buffer, 0, sizeof(size_t) * _heap_->capacity); + _heap_->count = 0; +} +void h_free(heap *_heap_) +{ + free(_heap_->buffer); + free(_heap_); +} +bool h_insert(heap *_heap_, size_t element) +{ + if (h_full(_heap_)) + { + if (!h_impl_grow(_heap_)) + return false; + } + if (_heap_->count == 0) + { + _heap_->buffer[_heap_->count++] = element; + return true; + } + _heap_->buffer[_heap_->count++] = element; + if (!h_impl_float_up(_heap_, _heap_->count - 1)) + return false; + return true; +} +bool h_remove(heap *_heap_, size_t *result) +{ + if (h_empty(_heap_)) + return false; + *result = _heap_->buffer[0]; + _heap_->buffer[0] = _heap_->buffer[_heap_->count - 1]; + _heap_->buffer[_heap_->count - 1] = h_impl_default_value(); + _heap_->count--; + if (!h_impl_float_down(_heap_, 0)) + return false; + return true; +} +bool h_insert_if(heap *_heap_, size_t element, bool condition) +{ + if (condition) + return h_insert(_heap_, element); + return false; +} +bool h_remove_if(heap *_heap_, size_t *result, bool condition) +{ + if (condition) + return h_remove(_heap_, result); + return false; +} +size_t h_peek(heap *_heap_) +{ + if (h_empty(_heap_)) + return h_impl_default_value(); + return _heap_->buffer[0]; +} +size_t *h_peek_ref(heap *_heap_) +{ + if (h_empty(_heap_)) + return NULL; + return &(_heap_->buffer[0]); +} +bool h_contains(heap *_heap_, size_t element) +{ + for (size_t i = 0; i < _heap_->count; i++) + { + if (_heap_->cmp(_heap_->buffer[i], element) == 0) + return true; + } + return false; +} +bool h_empty(heap *_heap_) { return _heap_->count == 0; } +bool h_full(heap *_heap_) { return _heap_->count >= _heap_->capacity; } +size_t h_count(heap *_heap_) { return _heap_->count; } +size_t h_capacity(heap *_heap_) { return _heap_->capacity; } +heap_iter *h_iter_new(heap *target) +{ + heap_iter *iter = malloc(sizeof(heap_iter)); + if (!iter) + return NULL; + h_iter_init(iter, target); + return iter; +} +void h_iter_free(heap_iter *iter) { free(iter); } +void h_iter_init(heap_iter *iter, heap *target) +{ + iter->target = target; + iter->cursor = 0; + iter->start = true; + iter->end = h_empty(target); +} +bool h_iter_start(heap_iter *iter) { return h_empty(iter->target) || iter->start; } +bool h_iter_end(heap_iter *iter) { return h_empty(iter->target) || iter->end; } +void h_iter_to_start(heap_iter *iter) +{ + iter->cursor = 0; + iter->start = true; + iter->end = h_empty(iter->target); +} +void h_iter_to_end(heap_iter *iter) +{ + iter->cursor = iter->target->count - 1; + iter->start = h_empty(iter->target); + iter->end = true; +} +bool h_iter_next(heap_iter *iter) +{ + if (iter->end) + return false; + iter->start = false; + if (iter->cursor == iter->target->count - 1) + iter->end = true; + else + iter->cursor++; + return true; +} +bool h_iter_prev(heap_iter *iter) +{ + if (iter->start) + return false; + iter->end = false; + if (iter->cursor == 0) + iter->start = true; + else + iter->cursor--; + return true; +} +size_t h_iter_value(heap_iter *iter) +{ + if (h_empty(iter->target)) + return h_impl_default_value(); + return iter->target->buffer[iter->cursor]; +} +size_t h_iter_index(heap_iter *iter) { return iter->cursor; } +static bool h_impl_grow(heap *_heap_) +{ + size_t new_capacity = _heap_->capacity * 2; + size_t *new_buffer = realloc(_heap_->buffer, sizeof(size_t) * new_capacity); + if (!new_buffer) + return false; + _heap_->buffer = new_buffer; + _heap_->capacity = new_capacity; + return true; +} +static size_t h_impl_p(size_t index) +{ + if (index == 0) + return 0; + return (index - 1) / 2; +} +static size_t h_impl_l(size_t index) { return 2 * index + 1; } +static size_t h_impl_r(size_t index) { return 2 * index + 2; } +static bool h_impl_float_up(heap *_heap_, size_t index) +{ + size_t C = index; + size_t child = _heap_->buffer[C]; + size_t parent = _heap_->buffer[h_impl_p(C)]; + int mod = _heap_->HO; + while (C > 0 && _heap_->cmp(child, parent) * mod > 0) + { + size_t tmp = _heap_->buffer[C]; + _heap_->buffer[C] = _heap_->buffer[h_impl_p(C)]; + _heap_->buffer[h_impl_p(C)] = tmp; + C = h_impl_p(C); + child = _heap_->buffer[C]; + parent = _heap_->buffer[h_impl_p(C)]; + } + return true; +} +static bool h_impl_float_down(heap *_heap_, size_t index) +{ + int mod = _heap_->HO; + while (index < _heap_->count) + { + size_t L = h_impl_l(index); + size_t R = h_impl_r(index); + size_t C = index; + if (L < _heap_->count && _heap_->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0) + { + C = L; + } + if (R < _heap_->count && _heap_->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0) + { + C = R; + } + if (C != index) + { + size_t tmp = _heap_->buffer[index]; + _heap_->buffer[index] = _heap_->buffer[C]; + _heap_->buffer[C] = tmp; + index = C; + } + else + break; + } + return true; +} +static heap_iter h_impl_it_start(heap *_heap_) +{ + heap_iter iter; + h_iter_init(&iter, _heap_); + h_iter_to_start(&iter); + return iter; +} +static heap_iter h_impl_it_end(heap *_heap_) +{ + heap_iter iter; + h_iter_init(&iter, _heap_); + h_iter_to_end(&iter); + return iter; +} diff --git a/tests/main/src/linkedlist.c b/tests/main/src/linkedlist.c new file mode 100644 index 0000000..1e6d705 --- /dev/null +++ b/tests/main/src/linkedlist.c @@ -0,0 +1,479 @@ +#include "cmc/linkedlist.h" + +typedef struct linkedlist_s +{ + struct linkedlist_node_s *head; + struct linkedlist_node_s *tail; + size_t count; + struct linkedlist_iter_s (*it_start)(struct linkedlist_s *); + struct linkedlist_iter_s (*it_end)(struct linkedlist_s *); +} linkedlist, *linkedlist_ptr; +typedef struct linkedlist_node_s +{ + size_t data; + struct linkedlist_node_s *next; + struct linkedlist_node_s *prev; +} linkedlist_node, *linkedlist_node_ptr; +typedef struct linkedlist_iter_s +{ + struct linkedlist_s *target; + struct linkedlist_node_s *cursor; + size_t index; + bool start; + bool end; +} linkedlist_iter, *linkedlist_iter_ptr; +linkedlist *ll_new(void); +void ll_clear(linkedlist *_list_); +void ll_free(linkedlist *_list_); +bool ll_push_front(linkedlist *_list_, size_t element); +bool ll_push(linkedlist *_list_, size_t element, size_t index); +bool ll_push_back(linkedlist *_list_, size_t element); +bool ll_pop_front(linkedlist *_list_); +bool ll_pop(linkedlist *_list_, size_t index); +bool ll_pop_back(linkedlist *_list_); +bool ll_push_if(linkedlist *_list_, size_t element, size_t index, bool condition); +bool ll_pop_if(linkedlist *_list_, size_t index, bool condition); +size_t ll_front(linkedlist *_list_); +size_t ll_get(linkedlist *_list_, size_t index); +size_t *ll_get_ref(linkedlist *_list_, size_t index); +size_t ll_back(linkedlist *_list_); +bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t)); +bool ll_empty(linkedlist *_list_); +size_t ll_count(linkedlist *_list_); +linkedlist_node *ll_new_node(size_t element); +void ll_free_node(linkedlist_node *_node_); +linkedlist_node *ll_head(linkedlist *_list_); +linkedlist_node *ll_get_node(linkedlist *_list_, size_t index); +linkedlist_node *ll_tail(linkedlist *_list_); +bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element); +bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element); +bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_); +bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_); +bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_); +linkedlist_node *ll_next_node(linkedlist_node *_node_); +linkedlist_node *ll_prev_node(linkedlist_node *_node_); +linkedlist_iter *ll_iter_new(linkedlist *target); +void ll_iter_free(linkedlist_iter *iter); +void ll_iter_init(linkedlist_iter *iter, linkedlist *target); +bool ll_iter_start(linkedlist_iter *iter); +bool ll_iter_end(linkedlist_iter *iter); +void ll_iter_to_start(linkedlist_iter *iter); +void ll_iter_to_end(linkedlist_iter *iter); +bool ll_iter_next(linkedlist_iter *iter); +bool ll_iter_prev(linkedlist_iter *iter); +size_t ll_iter_value(linkedlist_iter *iter); +size_t *ll_iter_rvalue(linkedlist_iter *iter); +size_t ll_iter_index(linkedlist_iter *iter); +linkedlist_node *ll_iter_node(linkedlist_iter *iter); +static inline size_t ll_impl_default_value(void) +{ + size_t _empty_value_; + memset(&_empty_value_, 0, sizeof(size_t)); + return _empty_value_; +} +static linkedlist_iter ll_impl_it_start(linkedlist *_list_); +static linkedlist_iter ll_impl_it_end(linkedlist *_list_); +linkedlist *ll_new(void) +{ + linkedlist *_list_ = malloc(sizeof(linkedlist)); + if (!_list_) + return NULL; + _list_->count = 0; + _list_->head = NULL; + _list_->tail = NULL; + _list_->it_start = ll_impl_it_start; + _list_->it_end = ll_impl_it_end; + return _list_; +} +void ll_clear(linkedlist *_list_) +{ + linkedlist_node *scan = _list_->head; + while (_list_->head != NULL) + { + _list_->head = _list_->head->next; + free(scan); + scan = _list_->head; + } + _list_->count = 0; + _list_->head = NULL; + _list_->tail = NULL; +} +void ll_free(linkedlist *_list_) +{ + ll_clear(_list_); + free(_list_); +} +bool ll_push_front(linkedlist *_list_, size_t element) +{ + linkedlist_node *_node_ = ll_new_node(element); + if (!_node_) + return false; + if (ll_empty(_list_)) + { + _list_->head = _node_; + _list_->tail = _node_; + } + else + { + _node_->next = _list_->head; + _list_->head->prev = _node_; + _list_->head = _node_; + } + _list_->count++; + return true; +} +bool ll_push(linkedlist *_list_, size_t element, size_t index) +{ + if (index > _list_->count) + return false; + if (index == 0) + { + return ll_push_front(_list_, element); + } + else if (index == _list_->count) + { + return ll_push_back(_list_, element); + } + linkedlist_node *_node_ = ll_new_node(element); + if (!_node_) + return false; + linkedlist_node *scan = ll_get_node(_list_, index - 1); + _node_->next = scan->next; + _node_->prev = scan; + _node_->next->prev = _node_; + _node_->prev->next = _node_; + _list_->count++; + return true; +} +bool ll_push_back(linkedlist *_list_, size_t element) +{ + linkedlist_node *_node_ = ll_new_node(element); + if (!_node_) + return false; + if (ll_empty(_list_)) + { + _list_->head = _node_; + _list_->tail = _node_; + } + else + { + _node_->prev = _list_->tail; + _list_->tail->next = _node_; + _list_->tail = _node_; + } + _list_->count++; + return true; +} +bool ll_pop_front(linkedlist *_list_) +{ + if (ll_empty(_list_)) + return false; + linkedlist_node *_node_ = _list_->head; + _list_->head = _list_->head->next; + free(_node_); + if (_list_->head == NULL) + _list_->tail = NULL; + else + _list_->head->prev = NULL; + _list_->count--; + return true; +} +bool ll_pop(linkedlist *_list_, size_t index) +{ + if (ll_empty(_list_)) + return false; + if (index >= _list_->count) + return false; + if (index == 0) + { + return ll_pop_front(_list_); + } + else if (index == _list_->count - 1) + { + return ll_pop_back(_list_); + } + linkedlist_node *_node_ = ll_get_node(_list_, index); + if (!_node_) + return false; + _node_->next->prev = _node_->prev; + _node_->prev->next = _node_->next; + free(_node_); + _list_->count--; + return true; +} +bool ll_pop_back(linkedlist *_list_) +{ + if (ll_empty(_list_)) + return false; + linkedlist_node *_node_ = _list_->tail; + _list_->tail = _list_->tail->prev; + free(_node_); + if (_list_->tail == NULL) + _list_->head = NULL; + else + _list_->tail->next = NULL; + _list_->count--; + return true; +} +bool ll_push_if(linkedlist *_list_, size_t element, size_t index, bool condition) +{ + if (condition) + return ll_push(_list_, element, index); + return false; +} +bool ll_pop_if(linkedlist *_list_, size_t index, bool condition) +{ + if (condition) + return ll_pop(_list_, index); + return false; +} +size_t ll_front(linkedlist *_list_) +{ + if (ll_empty(_list_)) + ll_impl_default_value(); + return _list_->head->data; +} +size_t ll_get(linkedlist *_list_, size_t index) +{ + if (index >= _list_->count || ll_empty(_list_)) + ll_impl_default_value(); + linkedlist_node *scan = ll_get_node(_list_, index); + if (scan == NULL) + return ll_impl_default_value(); + return scan->data; +} +size_t *ll_get_ref(linkedlist *_list_, size_t index) +{ + if (index >= _list_->count) + return NULL; + if (ll_empty(_list_)) + return NULL; + linkedlist_node *scan = ll_get_node(_list_, index); + if (scan == NULL) + return NULL; + return &(scan->data); +} +size_t ll_back(linkedlist *_list_) +{ + if (ll_empty(_list_)) + return ll_impl_default_value(); + return _list_->tail->data; +} +bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t)) +{ + linkedlist_node *scan = _list_->head; + while (scan != NULL) + { + if (comparator(scan->data, element) == 0) + return true; + scan = scan->next; + } + return false; +} +bool ll_empty(linkedlist *_list_) { return _list_->count == 0; } +size_t ll_count(linkedlist *_list_) { return _list_->count; } +linkedlist_node *ll_new_node(size_t element) +{ + linkedlist_node *_node_ = malloc(sizeof(linkedlist_node)); + if (!_node_) + return NULL; + _node_->data = element; + _node_->next = NULL; + _node_->prev = NULL; + return _node_; +} +void ll_free_node(linkedlist_node *_node_) { free(_node_); } +linkedlist_node *ll_head(linkedlist *_list_) { return _list_->head; } +linkedlist_node *ll_get_node(linkedlist *_list_, size_t index) +{ + if (index >= _list_->count) + return NULL; + if (ll_empty(_list_)) + return NULL; + linkedlist_node *_node_ = NULL; + if (index <= _list_->count / 2) + { + _node_ = _list_->head; + for (size_t i = 0; i < index; i++) + { + _node_ = _node_->next; + } + } + else + { + _node_ = _list_->tail; + for (size_t i = _list_->count - 1; i > index; i--) + { + _node_ = _node_->prev; + } + } + return _node_; +} +linkedlist_node *ll_tail(linkedlist *_list_) { return _list_->tail; } +bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element) +{ + linkedlist_node *new_node = ll_new_node(element); + if (!new_node) + return false; + new_node->next = _node_->next; + if (_node_->next != NULL) + _node_->next->prev = new_node; + else + _owner_->tail = new_node; + new_node->prev = _node_; + _node_->next = new_node; + _owner_->count++; + return true; +} +bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element) +{ + linkedlist_node *new_node = ll_new_node(element); + if (!new_node) + return false; + new_node->prev = _node_->prev; + if (_node_->prev != NULL) + _node_->prev->next = new_node; + else + _owner_->head = new_node; + new_node->next = _node_; + _node_->prev = new_node; + _owner_->count++; + return true; +} +bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_) +{ + if (_node_->next == NULL) + return false; + linkedlist_node *tmp = _node_->next; + if (tmp->next != NULL) + { + _node_->next = _node_->next->next; + _node_->next->prev = _node_; + } + else + _owner_->tail = _node_; + free(tmp); + _owner_->count--; + return true; +} +bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_) +{ + if (_node_->prev != NULL) + _node_->prev->next = _node_->next; + else + _owner_->head = _node_->next; + if (_node_->next != NULL) + _node_->next->prev = _node_->prev; + else + _owner_->tail = _node_->prev; + free(_node_); + _owner_->count--; + return true; +} +bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_) +{ + if (_node_->prev == NULL) + return false; + linkedlist_node *tmp = _node_->prev; + if (tmp->prev != NULL) + { + _node_->prev = _node_->prev->prev; + _node_->prev->next = _node_; + } + else + _owner_->head = _node_; + free(tmp); + _owner_->count--; + return true; +} +linkedlist_node *ll_next_node(linkedlist_node *_node_) { return _node_->next; } +linkedlist_node *ll_prev_node(linkedlist_node *_node_) { return _node_->prev; } +linkedlist_iter *ll_iter_new(linkedlist *target) +{ + linkedlist_iter *iter = malloc(sizeof(linkedlist_iter)); + if (!iter) + return NULL; + ll_iter_init(iter, target); + return iter; +} +void ll_iter_free(linkedlist_iter *iter) { free(iter); } +void ll_iter_init(linkedlist_iter *iter, linkedlist *target) +{ + iter->target = target; + iter->cursor = target->head; + iter->index = 0; + iter->start = true; + iter->end = ll_empty(target); +} +bool ll_iter_start(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->start; } +bool ll_iter_end(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->end; } +void ll_iter_to_start(linkedlist_iter *iter) +{ + iter->cursor = iter->target->head; + iter->index = 0; + iter->start = true; + iter->end = ll_empty(iter->target); +} +void ll_iter_to_end(linkedlist_iter *iter) +{ + iter->cursor = iter->target->tail; + iter->index = iter->target->count - 1; + iter->start = ll_empty(iter->target); + iter->end = true; +} +bool ll_iter_next(linkedlist_iter *iter) +{ + if (iter->end) + return false; + iter->start = ll_empty(iter->target); + if (iter->cursor->next == NULL) + iter->end = true; + else + { + iter->cursor = iter->cursor->next; + iter->index++; + } + return true; +} +bool ll_iter_prev(linkedlist_iter *iter) +{ + if (iter->start) + return false; + iter->end = ll_empty(iter->target); + if (iter->cursor->prev == NULL) + iter->start = true; + else + { + iter->cursor = iter->cursor->prev; + iter->index--; + } + return true; +} +size_t ll_iter_value(linkedlist_iter *iter) +{ + if (ll_empty(iter->target)) + return ll_impl_default_value(); + return iter->cursor->data; +} +size_t *ll_iter_rvalue(linkedlist_iter *iter) +{ + if (ll_empty(iter->target)) + return NULL; + return &(iter->cursor->data); +} +size_t ll_iter_index(linkedlist_iter *iter) { return iter->index; } +linkedlist_node *ll_iter_node(linkedlist_iter *iter) { return iter->cursor; } +static linkedlist_iter ll_impl_it_start(linkedlist *_list_) +{ + linkedlist_iter iter; + ll_iter_init(&iter, _list_); + ll_iter_to_start(&iter); + return iter; +} +static linkedlist_iter ll_impl_it_end(linkedlist *_list_) +{ + linkedlist_iter iter; + ll_iter_init(&iter, _list_); + ll_iter_to_end(&iter); + return iter; +} diff --git a/tests/main/unt/hashmap.c b/tests/main/unt/hashmap.c index 88df3d7..e2865ae 100644 --- a/tests/main/unt/hashmap.c +++ b/tests/main/unt/hashmap.c @@ -11,7 +11,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { bool passed = (map->capacity >= (943722 / 0.6)) && map->count == 0 && map->buffer; cmc_assert_not_equals(ptr, NULL, map); - cmc_assert(hm_capacity(map) > (943722 / 0.6)); + cmc_assert_greater_equals(size_t, (943722 / 0.6), hm_capacity(map)); CMC_TEST_PASS_ELSE_FAIL(passed); diff --git a/tests/main/unt/heap.c b/tests/main/unt/heap.c new file mode 100644 index 0000000..f526cc4 --- /dev/null +++ b/tests/main/unt/heap.c @@ -0,0 +1,75 @@ +#include "utl/assert.h" +#include "utl/test.h" +#include "../src/heap.c" + +#include "utl.c" + +CMC_CREATE_UNIT(heap_test, true, { + CMC_CREATE_TEST(new, { + heap *h = h_new(1000000, MaxHeap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + bool passed = h->capacity == 1000000 && h->count == 0 && h->buffer; + + cmc_assert_equals(size_t, 1000000, h->capacity); + cmc_assert_equals(size_t, 0, h_count(h)); + cmc_assert_not_equals(ptr, NULL, h->buffer); + + CMC_TEST_PASS_ELSE_FAIL(passed); + + h_free(h); + }); + + CMC_CREATE_TEST(new[edge_case:capacity = 0], { + heap *h = h_new(0, MaxHeap, cmp); + + cmc_assert_equals(ptr, NULL, h); + + CMC_TEST_PASS_ELSE_FAIL(h == NULL); + }); + + CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], { + heap *h = h_new(UINT64_MAX, MaxHeap, cmp); + + cmc_assert_equals(ptr, NULL, h); + + CMC_TEST_PASS_ELSE_FAIL(h == NULL); + }); + + CMC_CREATE_TEST(clear[count capacity], { + heap *h = h_new(100, MaxHeap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + for (size_t i = 0; i < 50; i++) + h_insert(h, i); + + cmc_assert_equals(size_t, 50, h_count(h)); + + h_clear(h); + + cmc_assert_equals(size_t, 0, h_count(h)); + cmc_assert_equals(size_t, 100, h_capacity(h)); + + CMC_TEST_PASS_ELSE_FAIL(h_count(h) == 0 && h_capacity(h) == 100); + + h_free(h); + }); + + CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], { + heap *h = h_new(1, MaxHeap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + for (size_t i = 0; i < 50; i++) + h_insert(h, i); + + cmc_assert_equals(size_t, 50, h_count(h)); + + CMC_TEST_PASS_ELSE_FAIL(h_count(h) == 50); + + h_free(h); + }); + +}); diff --git a/tests/main/unt/linkedlist.c b/tests/main/unt/linkedlist.c new file mode 100644 index 0000000..0d8125e --- /dev/null +++ b/tests/main/unt/linkedlist.c @@ -0,0 +1,93 @@ +#include "utl/assert.h" +#include "utl/test.h" +#include "../src/linkedlist.c" + +CMC_CREATE_UNIT(linkedlist_test, true, { + CMC_CREATE_TEST(new, { + linkedlist *ll = ll_new(); + + cmc_assert_not_equals(ptr, NULL, ll); + + bool passed = ll->count == 0 && ll->head == NULL && ll->tail == NULL; + + cmc_assert_equals(size_t, 0, ll_count(ll)); + cmc_assert_equals(ptr, NULL, ll->head); + cmc_assert_equals(ptr, NULL, ll->tail); + + CMC_TEST_PASS_ELSE_FAIL(passed); + + ll_free(ll); + }); + + CMC_CREATE_TEST(clear[count capacity], { + linkedlist *ll = ll_new(); + + cmc_assert_not_equals(ptr, NULL, ll); + + for (size_t i = 0; i < 50; i++) + ll_push_back(ll, i); + + cmc_assert_equals(size_t, 50, ll_count(ll)); + + ll_clear(ll); + + cmc_assert_equals(size_t, 0, ll_count(ll)); + + CMC_TEST_PASS_ELSE_FAIL(ll_count(ll) == 0); + + ll_free(ll); + }); + + CMC_CREATE_TEST(clear[edge_case:count = 0], { + linkedlist *ll = ll_new(); + + cmc_assert_not_equals(ptr, NULL, ll); + + ll_clear(ll); + + cmc_assert_equals(size_t, 0, ll_count(ll)); + + CMC_TEST_PASS_ELSE_FAIL(ll_count(ll) == 0); + + ll_free(ll); + }); + + CMC_CREATE_TEST(push_front[count], { + linkedlist *ll = ll_new(); + + cmc_assert_not_equals(ptr, NULL, ll); + + ll_push_front(ll, 1); + + cmc_assert_not_equals(ptr, NULL, ll->head); + cmc_assert_not_equals(ptr, NULL, ll->tail); + cmc_assert_equals(size_t, 1, ll_count(ll)); + + CMC_TEST_PASS_ELSE_FAIL(ll->head && ll->tail && ll_count(ll) == 1); + + ll_free(ll); + }); + + CMC_CREATE_TEST(push_front[item_preservation], { + linkedlist *ll = ll_new(); + + cmc_assert_not_equals(ptr, NULL, ll); + + for (size_t i = 0; i < 200; i++) + ll_push_front(ll, i); + + bool passed = true; + + for (size_t i = 0; i < ll_count(ll); i++) + { + passed = passed && ll_get(ll, i) == (ll_count(ll) - i - 1); + + cmc_assert_equals(size_t, ll_get(ll, i), ll_count(ll) - i - 1); + } + + CMC_TEST_PASS_ELSE_FAIL(passed && ll_count(ll) == 200); + + ll_free(ll); + }); + +}); diff --git a/tests/main/unt/list.c b/tests/main/unt/list.c index be2c08b..2d275d0 100644 --- a/tests/main/unt/list.c +++ b/tests/main/unt/list.c @@ -118,13 +118,43 @@ CMC_CREATE_UNIT(list_test, true, { l_free(l); }); - CMC_CREATE_TEST(push_front[count capacity item_preservation grow], { + CMC_CREATE_TEST(push_front[count], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); - for (size_t i = 0; i < 200; i++) - l_push_front(l, i); + for (size_t i = 0; i < 250; i++) + cmc_assert(l_push_front(l, i)); + + cmc_assert_equals(size_t, 250, l_count(l)); + + CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250); + + l_free(l); + }); + + CMC_CREATE_TEST(push_front[capacity], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + + for (size_t i = 0; i < 250; i++) + cmc_assert(l_push_front(l, i)); + + cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l)); + + CMC_TEST_PASS_ELSE_FAIL(l_count(l) <= l_capacity(l)); + + l_free(l); + }); + + CMC_CREATE_TEST(push_front[item_preservation], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + + for (size_t i = 0; i < 250; i++) + cmc_assert(l_push_front(l, i)); bool passed = true; @@ -135,18 +165,57 @@ CMC_CREATE_UNIT(list_test, true, { cmc_assert_equals(size_t, l_get(l, i), l_count(l) - i - 1); } - CMC_TEST_PASS_ELSE_FAIL(passed && l_count(l) == 200); + CMC_TEST_PASS_ELSE_FAIL(passed); l_free(l); }); - CMC_CREATE_TEST(push[count capacity item_preservation grow], { + CMC_CREATE_TEST(push[count], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); - for (size_t i = 0; i < 200; i++) - l_push(l, i, l_count(l)); + cmc_assert(l_push_back(l, 0)); + cmc_assert(l_push_back(l, 249)); + + for (size_t i = 1; i < 249; i++) + cmc_assert(l_push(l, i, l_count(l) - 1)); + + cmc_assert_equals(size_t, 250, l_count(l)); + + CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250); + + l_free(l); + }); + + CMC_CREATE_TEST(push[capacity], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + + cmc_assert(l_push_back(l, 0)); + cmc_assert(l_push_back(l, 249)); + + for (size_t i = 1; i < 249; i++) + cmc_assert(l_push(l, i, l_count(l) - 1)); + + cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l)); + + CMC_TEST_PASS_ELSE_FAIL(l_count(l) <= l_capacity(l)); + + l_free(l); + }); + + CMC_CREATE_TEST(push[item_preservation], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + + cmc_assert(l_push_back(l, 0)); + cmc_assert(l_push_back(l, 249)); + + for (size_t i = 1; i < 249; i++) + cmc_assert(l_push(l, i, l_count(l) - 1)); bool passed = true; @@ -157,39 +226,84 @@ CMC_CREATE_UNIT(list_test, true, { cmc_assert_equals(size_t, l_get(l, i), i); } - CMC_TEST_PASS_ELSE_FAIL(passed && l_count(l) == 200); + CMC_TEST_PASS_ELSE_FAIL(passed); l_free(l); }); - CMC_CREATE_TEST(push_back[count capacity item_preservation grow], { + CMC_CREATE_TEST(push_back[count], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); - for (size_t i = 0; i < 200; i++) + for (size_t i = 0; i < 250; i++) + cmc_assert(l_push_back(l, i)); + + cmc_assert_equals(size_t, 250, l_count(l)); + + CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250); + + l_free(l); + }); + + CMC_CREATE_TEST(push_back[capacity], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + + for (size_t i = 0; i < 250; i++) + cmc_assert(l_push_back(l, i)); + + cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l)); + + CMC_TEST_PASS_ELSE_FAIL(l_count(l) <= l_capacity(l)); + + l_free(l); + }); + + CMC_CREATE_TEST(push_back[item_preservation], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + + for (size_t i = 0; i < 250; i++) + cmc_assert(l_push_back(l, i)); + + bool passed = true; + + for (size_t i = 0; i < l_count(l); i++) + { + passed = passed && l_get(l, i) == i; + + cmc_assert_equals(size_t, l_get(l, i), i); + } + + CMC_TEST_PASS_ELSE_FAIL(passed); + + l_free(l); + }); + + CMC_CREATE_TEST(pop_front[count], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + + for (size_t i = 0; i < 250; i++) l_push_back(l, i); - bool passed = true; + cmc_assert(l_pop_front(l)); - for (size_t i = 0; i < l_count(l); i++) - { - passed = passed && l_get(l, i) == i; - - cmc_assert_equals(size_t, l_get(l, i), i); - } - - CMC_TEST_PASS_ELSE_FAIL(passed && l_count(l) == 200); + CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250 - 1); l_free(l); }); - CMC_CREATE_TEST(pop_front[count item_preservation], { + CMC_CREATE_TEST(pop_front[item_preservation], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); - for (size_t i = 0; i < 200; i++) + for (size_t i = 0; i < 250; i++) l_push_back(l, i); bool passed = l_pop_front(l); @@ -201,7 +315,7 @@ CMC_CREATE_UNIT(list_test, true, { cmc_assert_equals(size_t, l_get(l, i), i + 1); } - CMC_TEST_PASS_ELSE_FAIL(passed && l_count(l) == 199); + CMC_TEST_PASS_ELSE_FAIL(passed); l_free(l); });