diff --git a/.travis.yml b/.travis.yml index 3a74055..cf7632d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,5 +14,7 @@ script: - export CC=gcc-7 - cd ./tests - make + - cd main + - make after_success: - bash <(curl -s https://codecov.io/bash) diff --git a/tests/Makefile b/tests/Makefile index fe6f135..65dc46e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,7 +1,6 @@ CC = gcc CFLAGS = -std=c11 -Wall -Wextra CFLAGS += -Wno-unused-function -Wno-unused-paramter -Wno-unused-variable -Wno-unused-label -CVFLAGS = --coverage -O0 main: $(CC) foreach.c -o foreach $(CFLAGS) @@ -16,6 +15,3 @@ main: $(CC) -c ./sep/main.c -o ./sep/main.o $(CFLAGS) $(CC) ./sep/sep.o ./sep/main.o -o ./sep/sep ./sep/sep - $(CC) list.c -o list $(CFLAGS) $(CVFLAGS) - ./list - gcov ./list.c diff --git a/tests/README.md b/tests/README.md index 4547ec1..4a4692d 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,5 +1,6 @@ # Tests +* `main` - Unit tests for the main C Macro Collections library with code coverage; * `sep/main.c`, `sep/sep.c` and `sep/sep.h` - Tests separate header and source compilation; * `contains.c` - Tests the `contains` function for all collections; * `foreach.c` - Tests the ForEach macros for all collections; diff --git a/tests/main/Makefile b/tests/main/Makefile new file mode 100644 index 0000000..b7dca90 --- /dev/null +++ b/tests/main/Makefile @@ -0,0 +1,10 @@ +CC = gcc +CFLAGS = -std=c11 -Wall -Wextra +CFLAGS += -Wno-unused-function -Wno-unused-paramter -Wno-unused-variable -Wno-unused-label +CVFLAGS = --coverage -O0 +INCLUDE = ../../src/ + +main: + $(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE) + ./main + gcov ./main.c diff --git a/tests/main/README.md b/tests/main/README.md new file mode 100644 index 0000000..24f0a9b --- /dev/null +++ b/tests/main/README.md @@ -0,0 +1,7 @@ +# main + +Tests for the main C Macro Collections library. In order to provide a good code coverage, all macros have been expanded and added to `src/*.c`. + +* `src` - Since gcov fails to detect code that was expanded by macro, all collections where manually expanded and dumped into their respective source files; +* `unt` - Unit Tests; +* `main.c` - Where all tests are compiled together and called by main(). diff --git a/tests/main/main.c b/tests/main/main.c new file mode 100644 index 0000000..0876148 --- /dev/null +++ b/tests/main/main.c @@ -0,0 +1,10 @@ +#include "unt/list.c" +#include "unt/deque.c" + +int main(void) +{ + deque_test(); + list_test(); + + return 0; +} diff --git a/tests/main/src/deque.c b/tests/main/src/deque.c new file mode 100644 index 0000000..d581617 --- /dev/null +++ b/tests/main/src/deque.c @@ -0,0 +1,291 @@ +#include "macro_collections.h" + +typedef struct deque_s +{ + size_t *buffer; + size_t capacity; + size_t count; + size_t front; + size_t back; + struct deque_iter_s (*it_start)(struct deque_s *); + struct deque_iter_s (*it_end)(struct deque_s *); +} deque, *deque_ptr; +typedef struct deque_iter_s +{ + struct deque_s *target; + size_t cursor; + size_t index; + _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); +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_); +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); +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); +size_t d_iter_value(deque_iter *iter); +size_t *d_iter_rvalue(deque_iter *iter); +size_t d_iter_index(deque_iter *iter); +static inline size_t d_impl_default_value(void) +{ + size_t _empty_value_; + memset(&_empty_value_, 0, sizeof(size_t)); + return _empty_value_; +} +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); + deque *_deque_ = malloc(sizeof(deque)); + if (!_deque_) + return ((void *)0); + _deque_->buffer = malloc(sizeof(size_t) * capacity); + if (!_deque_->buffer) + { + free(_deque_); + return ((void *)0); + } + memset(_deque_->buffer, 0, sizeof(size_t) * capacity); + _deque_->capacity = capacity; + _deque_->count = 0; + _deque_->front = 0; + _deque_->back = 0; + _deque_->it_start = d_impl_it_start; + _deque_->it_end = d_impl_it_end; + return _deque_; +} +void d_clear(deque *_deque_) +{ + memset(_deque_->buffer, 0, sizeof(size_t) * _deque_->capacity); + _deque_->count = 0; + _deque_->front = 0; + _deque_->back = 0; +} +void d_free(deque *_deque_) +{ + free(_deque_->buffer); + free(_deque_); +} +_Bool d_push_front(deque *_deque_, size_t element) +{ + if (d_full(_deque_)) + { + if (!d_impl_grow(_deque_)) + return 0; + } + _deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; + _deque_->buffer[_deque_->front] = element; + _deque_->count++; + return 1; +} +_Bool d_push_back(deque *_deque_, size_t element) +{ + if (d_full(_deque_)) + { + if (!d_impl_grow(_deque_)) + return 0; + } + _deque_->buffer[_deque_->back] = element; + _deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; + _deque_->count++; + return 1; +} +_Bool d_pop_front(deque *_deque_) +{ + if (d_empty(_deque_)) + return 0; + _deque_->buffer[_deque_->front] = d_impl_default_value(); + _deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; + _deque_->count--; + return 1; +} +_Bool d_pop_back(deque *_deque_) +{ + if (d_empty(_deque_)) + return 0; + _deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; + _deque_->buffer[_deque_->back] = d_impl_default_value(); + _deque_->count--; + return 1; +} +_Bool d_push_front_if(deque *_deque_, size_t element, _Bool condition) +{ + if (condition) + return d_push_front(_deque_, element); + return 0; +} +_Bool d_push_back_if(deque *_deque_, size_t element, _Bool condition) +{ + if (condition) + return d_push_back(_deque_, element); + return 0; +} +_Bool d_pop_front_if(deque *_deque_, _Bool condition) +{ + if (condition) + return d_pop_front(_deque_); + return 0; +} +_Bool d_pop_back_if(deque *_deque_, _Bool condition) +{ + if (condition) + return d_pop_back(_deque_); + return 0; +} +size_t d_front(deque *_deque_) +{ + if (d_empty(_deque_)) + d_impl_default_value(); + return _deque_->buffer[_deque_->front]; +} +size_t d_back(deque *_deque_) +{ + if (d_empty(_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)) +{ + 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 0; +} +_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); + d_iter_init(iter, target); + return iter; +} +void d_iter_free(deque_iter *iter) { free(iter); } +void d_iter_init(deque_iter *iter, deque *target) +{ + iter->target = target; + iter->cursor = target->front; + iter->index = 0; + iter->start = 1; + 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; } +void d_iter_to_start(deque_iter *iter) +{ + iter->cursor = iter->target->front; + iter->index = 0; + iter->start = 1; + iter->end = d_empty(iter->target); +} +void d_iter_to_end(deque_iter *iter) +{ + if (d_empty(iter->target)) + iter->cursor = 0; + else + 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; +} +_Bool d_iter_next(deque_iter *iter) +{ + if (iter->end) + return 0; + iter->start = d_empty(iter->target); + if (iter->index == iter->target->count - 1) + iter->end = 1; + else + { + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); + iter->index++; + } + return 1; +} +_Bool d_iter_prev(deque_iter *iter) +{ + if (iter->start) + return 0; + iter->end = d_empty(iter->target); + if (iter->index == 0) + iter->start = 1; + else + { + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; + iter->index--; + } + return 1; +} +size_t d_iter_value(deque_iter *iter) +{ + if (d_empty(iter->target)) + d_impl_default_value(); + return iter->target->buffer[iter->cursor]; +} +size_t *d_iter_rvalue(deque_iter *iter) +{ + if (d_empty(iter->target)) + return ((void *)0); + return &(iter->target->buffer[iter->cursor]); +} +size_t d_iter_index(deque_iter *iter) { return iter->index; } +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; + for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) + { + new_buffer[j] = _deque_->buffer[i]; + } + free(_deque_->buffer); + _deque_->buffer = new_buffer; + _deque_->capacity = new_capacity; + _deque_->front = 0; + _deque_->back = _deque_->count; + return 1; +} +static deque_iter d_impl_it_start(deque *_deque_) +{ + deque_iter iter; + d_iter_init(&iter, _deque_); + return iter; +} +static deque_iter d_impl_it_end(deque *_deque_) +{ + deque_iter iter; + d_iter_init(&iter, _deque_); + d_iter_to_end(&iter); + return iter; +} diff --git a/tests/main/src/list.c b/tests/main/src/list.c new file mode 100644 index 0000000..c848d01 --- /dev/null +++ b/tests/main/src/list.c @@ -0,0 +1,422 @@ +#include "macro_collections.h" + +typedef struct list_s +{ + size_t *buffer; + size_t capacity; + size_t count; + struct list_iter_s (*it_start)(struct list_s *); + struct list_iter_s (*it_end)(struct list_s *); +} list, *list_ptr; +typedef struct list_iter_s +{ + struct list_s *target; + size_t cursor; + bool start; + bool end; +} list_iter, *list_iter_ptr; +list *l_new(size_t capacity); +list *l_new_from(size_t *elements, size_t size); +void l_clear(list *_list_); +void l_free(list *_list_); +bool l_push_front(list *_list_, size_t element); +bool l_push(list *_list_, size_t element, size_t index); +bool l_push_back(list *_list_, size_t element); +bool l_pop_front(list *_list_); +bool l_pop(list *_list_, size_t index); +bool l_pop_back(list *_list_); +bool l_push_if(list *_list_, size_t element, size_t index, bool condition); +bool l_pop_if(list *_list_, size_t index, bool condition); +bool l_prepend(list *_list_, size_t *elements, size_t size); +bool l_insert(list *_list_, size_t *elements, size_t size, size_t index); +bool l_append(list *_list_, size_t *elements, size_t size); +bool l_remove(list *_list_, size_t from, size_t to); +list *l_extract(list *_list_, size_t from, size_t to); +size_t l_front(list *_list_); +size_t l_get(list *_list_, size_t index); +size_t *l_get_ref(list *_list_, size_t index); +size_t l_back(list *_list_); +size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), bool from_start); +bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t)); +bool l_empty(list *_list_); +bool l_full(list *_list_); +size_t l_count(list *_list_); +bool l_fits(list *_list_, size_t size); +size_t l_capacity(list *_list_); +list_iter *l_iter_new(list *target); +void l_iter_free(list_iter *iter); +void l_iter_init(list_iter *iter, list *target); +bool l_iter_start(list_iter *iter); +bool l_iter_end(list_iter *iter); +void l_iter_to_start(list_iter *iter); +void l_iter_to_end(list_iter *iter); +bool l_iter_next(list_iter *iter); +bool l_iter_prev(list_iter *iter); +size_t l_iter_value(list_iter *iter); +size_t *l_iter_rvalue(list_iter *iter); +size_t l_iter_index(list_iter *iter); +static inline size_t l_impl_default_value(void) +{ + size_t _empty_value_; + memset(&_empty_value_, 0, sizeof(size_t)); + return _empty_value_; +} + +static bool l_impl_grow(list *_list_, size_t required); +static list_iter l_impl_it_start(list *_list_); +static list_iter l_impl_it_end(list *_list_); +list *l_new(size_t capacity) +{ + if (capacity < 1) + return NULL; + list *_list_ = malloc(sizeof(list)); + if (!_list_) + return NULL; + _list_->buffer = malloc(capacity * sizeof(size_t)); + if (!_list_->buffer) + { + free(_list_); + return NULL; + } + memset(_list_->buffer, 0, capacity * sizeof(size_t)); + _list_->capacity = capacity; + _list_->count = 0; + _list_->it_start = l_impl_it_start; + _list_->it_end = l_impl_it_end; + return _list_; +} +list *l_new_from(size_t *elements, size_t size) +{ + if (size == 0) + return NULL; + list *_list_ = l_new(size + size / 2); + if (!_list_) + return NULL; + memcpy(_list_->buffer, elements, size * sizeof(size_t)); + _list_->count = size; + return _list_; +} +void l_clear(list *_list_) +{ + memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity); + _list_->count = 0; +} +void l_free(list *_list_) +{ + free(_list_->buffer); + free(_list_); +} +bool l_push_front(list *_list_, size_t element) +{ + if (l_full(_list_)) + { + if (!l_impl_grow(_list_, _list_->count + 1)) + return false; + } + if (!l_empty(_list_)) + { + memmove(_list_->buffer + 1, _list_->buffer, _list_->count * sizeof(size_t)); + } + _list_->buffer[0] = element; + _list_->count++; + return true; +} +bool l_push(list *_list_, size_t element, size_t index) +{ + if (index > _list_->count) + return false; + if (index == 0) + { + return l_push_front(_list_, element); + } + else if (index == _list_->count) + { + return l_push_back(_list_, element); + } + if (l_full(_list_)) + { + if (!l_impl_grow(_list_, _list_->count + 1)) + return false; + } + memmove(_list_->buffer + index + 1, _list_->buffer + index, (_list_->count - index) * sizeof(size_t)); + _list_->buffer[index] = element; + _list_->count++; + return true; +} +bool l_push_back(list *_list_, size_t element) +{ + if (l_full(_list_)) + { + if (!l_impl_grow(_list_, _list_->count + 1)) + return false; + } + _list_->buffer[_list_->count++] = element; + return true; +} +bool l_pop_front(list *_list_) +{ + if (l_empty(_list_)) + return false; + memmove(_list_->buffer, _list_->buffer + 1, _list_->count * sizeof(size_t)); + _list_->buffer[--_list_->count] = l_impl_default_value(); + return true; +} +bool l_pop(list *_list_, size_t index) +{ + if (l_empty(_list_)) + return false; + if (index >= _list_->count) + return false; + if (index == 0) + { + return l_pop_front(_list_); + } + else if (index == _list_->count - 1) + { + return l_pop_back(_list_); + } + memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(size_t)); + _list_->buffer[--_list_->count] = l_impl_default_value(); + return true; +} +bool l_pop_back(list *_list_) +{ + if (l_empty(_list_)) + return false; + _list_->buffer[--_list_->count] = l_impl_default_value(); + return true; +} +bool l_push_if(list *_list_, size_t element, size_t index, bool condition) +{ + if (condition) + return l_push(_list_, element, index); + return false; +} +bool l_pop_if(list *_list_, size_t index, bool condition) +{ + if (condition) + return l_pop(_list_, index); + return false; +} +bool l_prepend(list *_list_, size_t *elements, size_t size) +{ + if (size == 0) + return false; + if (!l_fits(_list_, size)) + { + if (!l_impl_grow(_list_, _list_->count + size)) + return false; + } + memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(size_t)); + memcpy(_list_->buffer, elements, size * sizeof(size_t)); + _list_->count += size; + return true; +} +bool l_insert(list *_list_, size_t *elements, size_t size, size_t index) +{ + if (size == 0 || index > _list_->count) + return false; + if (index == 0) + return l_prepend(_list_, elements, size); + else if (index == _list_->count) + return l_append(_list_, elements, size); + else + { + if (!l_fits(_list_, size)) + { + if (!l_impl_grow(_list_, _list_->count + size)) + return false; + } + memmove(_list_->buffer + index + size, _list_->buffer + index, (_list_->count - index) * sizeof(size_t)); + memcpy(_list_->buffer + index, elements, size * sizeof(size_t)); + _list_->count += size; + } + return true; +} +bool l_append(list *_list_, size_t *elements, size_t size) +{ + if (size == 0) + return false; + if (!l_fits(_list_, size)) + { + if (!l_impl_grow(_list_, _list_->count + size)) + return false; + } + memcpy(_list_->buffer + _list_->count, elements, size * sizeof(size_t)); + _list_->count += size; + return true; +} +bool l_remove(list *_list_, size_t from, size_t to) +{ + if (from > to || to >= _list_->count) + return false; + size_t length = (to - from + 1); + memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t)); + memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t)); + _list_->count -= to - from + 1; + return true; +} +list *l_extract(list *_list_, size_t from, size_t to) +{ + if (from > to || to >= _list_->count) + return false; + size_t length = to - from + 1; + list *result = l_new_from(_list_->buffer + from, length); + if (!result) + return NULL; + memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t)); + memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t)); + _list_->count -= length; + return result; +} +size_t l_front(list *_list_) +{ + if (l_empty(_list_)) + return l_impl_default_value(); + return _list_->buffer[0]; +} +size_t l_get(list *_list_, size_t index) +{ + if (index >= _list_->count || l_empty(_list_)) + return l_impl_default_value(); + return _list_->buffer[index]; +} +size_t *l_get_ref(list *_list_, size_t index) +{ + if (index >= _list_->count) + return NULL; + if (l_empty(_list_)) + return NULL; + return &(_list_->buffer[index]); +} +size_t l_back(list *_list_) +{ + if (l_empty(_list_)) + return l_impl_default_value(); + return _list_->buffer[_list_->count - 1]; +} +size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), bool from_start) +{ + if (from_start) + { + for (size_t i = 0; i < _list_->count; i++) + { + if (comparator(_list_->buffer[i], element) == 0) + return i; + } + } + else + { + for (size_t i = _list_->count; i > 0; i--) + { + if (comparator(_list_->buffer[i - 1], element) == 0) + return i - 1; + } + } + return _list_->count; +} +bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t)) +{ + for (size_t i = 0; i < _list_->count; i++) + { + if (comparator(_list_->buffer[i], element) == 0) + return true; + } + return false; +} +bool l_empty(list *_list_) { return _list_->count == 0; } +bool l_full(list *_list_) { return _list_->count >= _list_->capacity; } +size_t l_count(list *_list_) { return _list_->count; } +bool l_fits(list *_list_, size_t size) { return _list_->count + size <= _list_->capacity; } +size_t l_capacity(list *_list_) { return _list_->capacity; } +list_iter *l_iter_new(list *target) +{ + list_iter *iter = malloc(sizeof(list_iter)); + if (!iter) + return NULL; + l_iter_init(iter, target); + return iter; +} +void l_iter_free(list_iter *iter) { free(iter); } +void l_iter_init(list_iter *iter, list *target) +{ + iter->target = target; + iter->cursor = 0; + iter->start = true; + iter->end = l_empty(target); +} +bool l_iter_start(list_iter *iter) { return l_empty(iter->target) || iter->start; } +bool l_iter_end(list_iter *iter) { return l_empty(iter->target) || iter->end; } +void l_iter_to_start(list_iter *iter) +{ + iter->cursor = 0; + iter->start = true; + iter->end = l_empty(iter->target); +} +void l_iter_to_end(list_iter *iter) +{ + iter->start = l_empty(iter->target); + iter->cursor = l_empty(iter->target) ? 0 : iter->target->count - 1; + iter->end = true; +} +bool l_iter_next(list_iter *iter) +{ + if (iter->end) + return false; + iter->start = l_empty(iter->target); + if (iter->cursor == iter->target->count - 1) + iter->end = true; + else + iter->cursor++; + return true; +} +bool l_iter_prev(list_iter *iter) +{ + if (iter->start) + return false; + iter->end = l_empty(iter->target); + if (iter->cursor == 0) + iter->start = true; + else + iter->cursor--; + return true; +} +size_t l_iter_value(list_iter *iter) +{ + if (l_empty(iter->target)) + return l_impl_default_value(); + return iter->target->buffer[iter->cursor]; +} +size_t *l_iter_rvalue(list_iter *iter) +{ + if (l_empty(iter->target)) + return NULL; + return &(iter->target->buffer[iter->cursor]); +} +size_t l_iter_index(list_iter *iter) { return iter->cursor; } +static bool l_impl_grow(list *_list_, size_t required) +{ + size_t new_capacity = _list_->capacity * 2; + if (new_capacity < required) + new_capacity = required; + size_t *new_buffer = realloc(_list_->buffer, sizeof(size_t) * new_capacity); + if (!new_buffer) + return false; + _list_->buffer = new_buffer; + _list_->capacity = new_capacity; + return true; +} +static list_iter l_impl_it_start(list *_list_) +{ + list_iter iter; + l_iter_init(&iter, _list_); + l_iter_to_start(&iter); + return iter; +} +static list_iter l_impl_it_end(list *_list_) +{ + list_iter iter; + l_iter_init(&iter, _list_); + l_iter_to_end(&iter); + return iter; +} diff --git a/tests/main/unt/deque.c b/tests/main/unt/deque.c new file mode 100644 index 0000000..6a2bca5 --- /dev/null +++ b/tests/main/unt/deque.c @@ -0,0 +1,28 @@ +#include "../src/deque.c" + +CMC_CREATE_UNIT(deque_test, true, { + CMC_CREATE_TEST(new, { + deque *d = d_new(1000000); + + cmc_assert_not_equals(ptr, NULL, d); + + bool passed = d->capacity == 1000000 && d->count == 0 && d->buffer; + + cmc_assert_equals(size_t, 1000000, d->capacity); + cmc_assert_equals(size_t, 0, d_count(d)); + cmc_assert_not_equals(ptr, NULL, d->buffer); + + CMC_TEST_PASS_ELSE_FAIL(passed); + + d_free(d); + }); + + CMC_CREATE_TEST(new[edge_case:capacity = 0], { + deque *d = d_new(0); + + cmc_assert_equals(ptr, NULL, d); + + CMC_TEST_PASS_ELSE_FAIL(d == NULL); + }); + +}); diff --git a/tests/list.c b/tests/main/unt/list.c similarity index 70% rename from tests/list.c rename to tests/main/unt/list.c index 315497e..7cf1dea 100644 --- a/tests/list.c +++ b/tests/main/unt/list.c @@ -1,6 +1,4 @@ -#include "../src/macro_collections.h" - -LIST_GENERATE(l, list, , size_t) +#include "../src/list.c" CMC_CREATE_UNIT(list_test, true, { CMC_CREATE_TEST(new, { @@ -22,7 +20,7 @@ CMC_CREATE_UNIT(list_test, true, { l_free(l); }); - CMC_CREATE_TEST(new [edge_case:capacity = 0], { + CMC_CREATE_TEST(new[edge_case:capacity = 0], { list *l = l_new(0); cmc_assert_equals(ptr, NULL, l); @@ -56,7 +54,7 @@ CMC_CREATE_UNIT(list_test, true, { l_free(l); }); - CMC_CREATE_TEST(new_from [edge_case:size = 1], { + CMC_CREATE_TEST(new_from[edge_case:size = 1], { size_t a = 10; size_t *values = &a; @@ -173,7 +171,17 @@ CMC_CREATE_UNIT(list_test, true, { l_free(l); }); - CMC_CREATE_TEST(pop_front [edge_case:count = 1], { + CMC_CREATE_TEST(pop_front[edge_case:count = 0], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + cmc_assert(!l_pop_front(l)); + CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0); + + l_free(l); + }); + + CMC_CREATE_TEST(pop_front[edge_case:count = 1], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -185,24 +193,13 @@ CMC_CREATE_UNIT(list_test, true, { l_free(l); }); - CMC_CREATE_TEST(pop_front [edge_case:count = 2], { - list *l = l_new(100); - - cmc_assert(l_push_back(l, 10)); - cmc_assert(l_push_front(l, 10)); - - CMC_TEST_PASS_ELSE_FAIL(l_pop_front(l) && l_count(l) == 1); - - l_free(l); - }); - CMC_CREATE_TEST(pop_front[buffer_clear], { list *l = l_new(100); - cmc_assert(l_push_back(l, 10)); - cmc_assert(l_push_front(l, 10)); + cmc_assert_not_equals(ptr, NULL, l); + cmc_assert(l_push_back(l, 1)); + cmc_assert(l_push_front(l, 2)); - // Default value is all bytes are 0 bool passed = l_pop_front(l) && l->buffer[1] == 0; cmc_assert_equals(size_t, 0, l->buffer[1]); @@ -211,11 +208,64 @@ CMC_CREATE_UNIT(list_test, true, { l_free(l); }); + + CMC_CREATE_TEST(pop[edge_case:count = 0], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + cmc_assert(!l_pop(l, 1)); + + CMC_TEST_PASS_ELSE_FAIL(!l_pop(l, 1)); + + l_free(l); + }); + + CMC_CREATE_TEST(pop[edge_case:count = 1], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + cmc_assert(l_push_back(l, 1)); + + CMC_TEST_PASS_ELSE_FAIL(l_pop(l, 0)); + + cmc_assert_equals(size_t, 0, l->buffer[0]); + + l_free(l); + }); + + CMC_CREATE_TEST(pop[buffer_clear], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + cmc_assert(l_push_back(l, 1)); + cmc_assert(l_push_back(l, 2)); + cmc_assert(l_push_back(l, 3)); + cmc_assert(l_pop(l, 1)); + + CMC_TEST_PASS_ELSE_FAIL(0 == l->buffer[2]); + + l_free(l); + }); + + CMC_CREATE_TEST(pop_back[edge_case:count = 0], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + cmc_assert(!l_pop_back(l)); + CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0); + + l_free(l); + }); + + CMC_CREATE_TEST(pop_back[edge_case:count = 1], { + list *l = l_new(100); + + cmc_assert_not_equals(ptr, NULL, l); + cmc_assert(l_push_back(l, 10)); + cmc_assert(l_pop_back(l)); + + CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0); + + l_free(l); + }); }) - -int main(void) -{ - list_test(); - - return 0; -}