diff --git a/README.md b/README.md
index 3fc17e4..668a488 100644
--- a/README.md
+++ b/README.md
@@ -30,8 +30,6 @@
* [Available Collections](#available-collections)
* [Other Features](#other-features)
* [Design Decisions](#design-decisions)
-* [What to use](#what-to-use)
-* [Code Review](#code-review)
## Installation
@@ -158,13 +156,10 @@ Every macro is suffixed by `CMC` and each section is separated by an underscore
* __documentation__ - The markdowns used by [mdBook](https://github.com/rust-lang/mdBook) to generate the website
* __examples__ - Examples using the C Macro Collections Library
* __src__ - All headers part of the C Macro Collections Library
- * __macro\_collections.h__ - Master header containing all collections and utilities
* __tests__ - Where all tests are hosted
## Available Collections
-Check out the STATUS file at the root of the project for more information.
-
__The following table is an overview of all the currently available or upcoming data structures__:
| Collection
| Abstract Data Type
| Data Structure
| Details |
@@ -194,21 +189,21 @@ __The following table is an overview of all the currently available or upcoming
These are some features within the library that are implemented by all collections.
-### Two-way iterators
+## Two-way iterators
All collections come with a two-way iterator. You can go back and forwards in constant time and access elements in constant time.
-### Custom Allocation
+## Custom Allocation
All collections have a `cmc_alloc_node` which provides pointers to the four dynamic memory allocation functions in C: `malloc`, `calloc`, `realloc` and `free`. These pointers can be customized for each individual collection created or a default can be used, as specified in `cmc_alloc_node_default`.
-### Callbacks
+## Callbacks
Every function that operates on a collection can be separated in 5 different types. Create, Read, Update, Delete and (an extra one besides CRUD) Resize. You can define one callback function for each operation. Check out the documentation to see when each callback function is called.
-### Functions Table
+## Functions Table
-Functions table is a `struct` of function pointers containing 'methods' for a custom data type. Some methods are optional and others are needed in order to a collection to operate. They are:
+Functions table is a `struct` of function pointers containing 'methods' for a custom data type. Some methods are optional and others are needed in order for a collection to operate. They are:
#### CMP
@@ -293,31 +288,3 @@ You can use them as Stacks, Queues and Deques, but with modern memory hierarchy
### You can't structurally modify a collection when iterating over it
Modifying a collection will possibly invalidate all iterators currently initialized by it. Currently, the only collection that allows this is the LinkedList (using the node-based functions, not the iterator).
-
-## What to use
-
-(Outdated)
-
-The following table shows how each collection is implemented and how well they do when using as common [abstract data types](https://en.wikipedia.org/wiki/Abstract_data_type).
-
-* **Ideal** - The collection implements correctly the abstract data type;
-* **Not Ideal** - The implementation is fulfilled but some functionalities are either not part of the ADT or not present;
-* **Bad** - It can be done, but its a bad idea.
-
-
-
-
-
-
-
-## Code Review
-
-Check out some code reviews that covers some parts the project. Most of them were posted a long time ago and are probably outdated.
-
-| About | Link |
-| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
-| Unit Test *./utl/test.h* | [](http://codereview.stackexchange.com/q/222954/178948) |
-| Interval Heap *./cmc/intervalheap.h* | [](http://codereview.stackexchange.com/q/223595/178948) |
-| Hash Set *./cmc/hashset.h* | [](http://codereview.stackexchange.com/q/217333/178948) |
-| Linked List *./cmc/linkedlist.h* | [](http://codereview.stackexchange.com/q/216737/178948) |
-| Others | [](http://codereview.stackexchange.com/q/213553/178948) |
diff --git a/src/cmc/cmc/list/ext/struct.h b/src/cmc/cmc/list/ext/struct.h
index 88eba84..bbebe63 100644
--- a/src/cmc/cmc/list/ext/struct.h
+++ b/src/cmc/cmc/list/ext/struct.h
@@ -27,7 +27,7 @@
*
* List bi-directional iterator.
*/
-#ifdef CMC_EXT_DEQUE_ITER
+#ifdef CMC_EXT_LIST_ITER
/* List Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -45,4 +45,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_DEQUE_ITER */
+#endif /* CMC_EXT_LIST_ITER */
diff --git a/src/cmc/cmc_deque.h b/src/cmc/deque.h
similarity index 100%
rename from src/cmc/cmc_deque.h
rename to src/cmc/deque.h
diff --git a/src/cmc/cmc_list.h b/src/cmc/list.h
similarity index 100%
rename from src/cmc/cmc_list.h
rename to src/cmc/list.h
diff --git a/src/cmc/cmc_stack.h b/src/cmc/stack.h
similarity index 100%
rename from src/cmc/cmc_stack.h
rename to src/cmc/stack.h
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..11957a5
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,11 @@
+CC=gcc
+CFLAGS=-Wall -fprofile-arcs -ftest-coverage -g -O0
+INCLUDE=-I ../src
+
+main:
+ $(CC) ./main.c $(INCLUDE) $(CFLAGS) -o $@.exe
+ valgrind --leak-check=yes ./$@.exe
+ gcov -p main.gcda
+
+clean:
+ rm ./*.gcov ./*.gcda ./*.gcno ./*.exe -f
diff --git a/tests/main.c b/tests/main.c
new file mode 100644
index 0000000..8d954bf
--- /dev/null
+++ b/tests/main.c
@@ -0,0 +1,102 @@
+#include
+#include
+
+// #include "unt_bitset.h"
+#include "unt_deque.h"
+// #include "unt_hashbidimap.h"
+// #include "unt_hashmap.h"
+// #include "unt_hashmultimap.h"
+// #include "unt_hashmultiset.h"
+// #include "unt_hashset.h"
+// #include "unt_heap.h"
+// #include "unt_intervalheap.h"
+// #include "unt_linkedlist.h"
+#include "unt_list.h"
+// #include "unt_queue.h"
+// #include "unt_sortedlist.h"
+#include "unt_stack.h"
+// #include "unt_treemap.h"
+// #include "unt_treeset.h"
+
+// #include "unt_foreach.h"
+
+#include "cmc/utl/assert.h"
+#include "cmc/utl/timer.h"
+
+#include "utl.h"
+
+#define cmc_run(unit, unit_fails, test_fails) \
+ do \
+ { \
+ uintmax_t f = unit(); \
+ if (f != 0) \
+ unit_fails += 1; \
+ test_fails += f; \
+ } while (0)
+
+int main(void)
+{
+ // clang-format off
+ printf(" +---------------------------------------------------------------+\n");
+ printf(" | C Macro Collections Library |\n");
+ printf(" | |\n");
+ printf(" | Test Suite |\n");
+ printf(" | |\n");
+ printf(" | https://github.com/LeoVen/C-Macro-Collections |\n");
+ printf(" | Leonardo Vencovsky (leonardo.vencovsky@gmail.com) |\n");
+ printf(" +---------------------------------------------------------------+\n\n");
+ // clang-format on
+
+ struct cmc_timer timer;
+
+ cmc_timer_start(timer);
+ uintmax_t tests = 0, units = 0;
+
+ // cmc_run(CMCBitSet, units, tests);
+ // cmc_run(CMCBitSetIter, units, tests);
+ cmc_run(CMCDeque, units, tests);
+ cmc_run(CMCDequeIter, units, tests);
+ // cmc_run(CMCHashBidiMap, units, tests);
+ // cmc_run(CMCHashBidiMapIter, units, tests);
+ // cmc_run(CMCHashMap, units, tests);
+ // cmc_run(CMCHashMapIter, units, tests);
+ // cmc_run(CMCHashMultiMap, units, tests);
+ // cmc_run(CMCHashMultiMapIter, units, tests);
+ // cmc_run(CMCHashMultiSet, units, tests);
+ // cmc_run(CMCHashMultiSetIter, units, tests);
+ // cmc_run(CMCHashSet, units, tests);
+ // cmc_run(CMCHashSetIter, units, tests);
+ // cmc_run(CMCHeap, units, tests);
+ // cmc_run(CMCHeapIter, units, tests);
+ // cmc_run(CMCIntervalHeap, units, tests);
+ // cmc_run(CMCIntervalHeapIter, units, tests);
+ // cmc_run(CMCLinkedList, units, tests);
+ // cmc_run(CMCLinkedListIter, units, tests);
+ cmc_run(CMCList, units, tests);
+ cmc_run(CMCListIter, units, tests);
+ // cmc_run(CMCQueue, units, tests);
+ // cmc_run(CMCQueueIter, units, tests);
+ // cmc_run(CMCSortedList, units, tests);
+ // cmc_run(CMCSortedListIter, units, tests);
+ cmc_run(CMCStack, units, tests);
+ cmc_run(CMCStackIter, units, tests);
+ // cmc_run(CMCTreeMap, units, tests);
+ // cmc_run(CMCTreeMapIter, units, tests);
+ // cmc_run(CMCTreeSet, units, tests);
+ // cmc_run(CMCTreeSetIter, units, tests);
+
+ // cmc_run(ForEach, units, tests);
+
+ cmc_timer_stop(timer);
+
+ printf(" +---------------------------------------------------------------+\n");
+ printf(" | SUMMARY |\n");
+ printf(" +---------------------------------------------------------------+\n");
+ printf(" | Total Units Failed : %25" PRIuMAX " units |\n", units);
+ printf(" | Total Tests Failed : %25" PRIuMAX " tests |\n", tests);
+ printf(" | Total Asserts Failed : %25" PRIuMAX " asserts |\n", cmc_assert_failed);
+ printf(" | Total Runtime : %25.0lf milliseconds |\n", timer.result);
+ printf(" +---------------------------------------------------------------+\n");
+
+ return tests;
+}
diff --git a/tests/unt_deque.h b/tests/unt_deque.h
new file mode 100644
index 0000000..244b4a1
--- /dev/null
+++ b/tests/unt_deque.h
@@ -0,0 +1,1725 @@
+#ifndef CMC_TESTS_UNT_DEQUE_H
+#define CMC_TESTS_UNT_DEQUE_H
+
+#include "utl.h"
+
+#define V size_t
+#define PFX d
+#define SNAME deque
+#define CMC_EXT_DEQUE_INIT
+#define CMC_EXT_DEQUE_ITER
+#include "cmc/deque.h"
+
+struct deque_fval *d_fval = &(struct deque_fval){
+ .cmp = cmc_size_cmp, .cpy = NULL, .str = cmc_size_str, .free = NULL, .hash = cmc_size_hash, .pri = cmc_size_cmp
+};
+
+struct deque_fval *d_fval_counter = &(struct deque_fval){
+ .cmp = v_c_cmp, .cpy = v_c_cpy, .str = v_c_str, .free = v_c_free, .hash = v_c_hash, .pri = v_c_pri
+};
+
+struct cmc_alloc_node *d_alloc_node =
+ &(struct cmc_alloc_node){ .malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free };
+
+CMC_CREATE_UNIT(CMCDeque, true, {
+ CMC_CREATE_TEST(PFX##_new(), {
+ struct deque *d = d_new(1000000, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+ cmc_assert_not_equals(ptr, NULL, d->buffer);
+ cmc_assert_equals(size_t, 1000000, d->capacity);
+ cmc_assert_equals(size_t, 0, d->count);
+ cmc_assert_equals(size_t, 0, d->front);
+ cmc_assert_equals(size_t, 0, d->back);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d->flag);
+ cmc_assert_equals(ptr, d_fval, d->f_val);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.malloc, d->alloc->malloc);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.calloc, d->alloc->calloc);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.realloc, d->alloc->realloc);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.free, d->alloc->free);
+ cmc_assert_equals(ptr, NULL, d->callbacks);
+
+ d_free(d);
+
+ d = d_new(0, d_fval);
+ cmc_assert_equals(ptr, NULL, d);
+
+ d = d_new(1000, NULL);
+ cmc_assert_equals(ptr, NULL, d);
+
+ d = d_new(UINT64_MAX, d_fval);
+ cmc_assert_equals(ptr, NULL, d);
+ });
+
+ CMC_CREATE_TEST(PFX##_new_custom(), {
+ struct deque *d = d_new_custom(1000000, d_fval, d_alloc_node, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+ cmc_assert_not_equals(ptr, NULL, d->buffer);
+ cmc_assert_equals(size_t, 1000000, d->capacity);
+ cmc_assert_equals(size_t, 0, d->count);
+ cmc_assert_equals(size_t, 0, d->front);
+ cmc_assert_equals(size_t, 0, d->back);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d->flag);
+ cmc_assert_equals(ptr, d_fval, d->f_val);
+ cmc_assert_equals(ptr, d_alloc_node, d->alloc);
+ cmc_assert_equals(ptr, callbacks, d->callbacks);
+
+ d_free(d);
+
+ d = d_new_custom(0, d_fval, d_alloc_node, callbacks);
+ cmc_assert_equals(ptr, NULL, d);
+
+ d = d_new_custom(1000, NULL, d_alloc_node, callbacks);
+ cmc_assert_equals(ptr, NULL, d);
+
+ d = d_new_custom(UINT64_MAX, d_fval, d_alloc_node, callbacks);
+ cmc_assert_equals(ptr, NULL, d);
+ });
+
+ CMC_CREATE_TEST(PFX##_init(), {
+ struct deque d = d_init(1000000, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d.buffer);
+ cmc_assert_equals(size_t, 1000000, d.capacity);
+ cmc_assert_equals(size_t, 0, d.count);
+ cmc_assert_equals(size_t, 0, d.front);
+ cmc_assert_equals(size_t, 0, d.back);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d.flag);
+ cmc_assert_equals(ptr, d_fval, d.f_val);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.malloc, d.alloc->malloc);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.calloc, d.alloc->calloc);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.realloc, d.alloc->realloc);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.free, d.alloc->free);
+ cmc_assert_equals(ptr, NULL, d.callbacks);
+
+ d_release(d);
+
+ d = d_init(0, d_fval);
+
+ cmc_assert_equals(size_t, 0, d.capacity);
+ cmc_assert_equals(ptr, NULL, d.buffer);
+
+ d = d_init(1000, NULL);
+
+ cmc_assert_equals(size_t, 0, d.capacity);
+ cmc_assert_equals(ptr, NULL, d.buffer);
+
+ d = d_init(UINT64_MAX, d_fval);
+
+ cmc_assert_equals(size_t, 0, d.capacity);
+ cmc_assert_equals(ptr, NULL, d.buffer);
+
+ if (d.buffer)
+ d_release(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_init_custom(), {
+ struct deque d = d_init_custom(1000000, d_fval, d_alloc_node, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, d.buffer);
+ cmc_assert_equals(size_t, 1000000, d.capacity);
+ cmc_assert_equals(size_t, 0, d.count);
+ cmc_assert_equals(size_t, 0, d.front);
+ cmc_assert_equals(size_t, 0, d.back);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d.flag);
+ cmc_assert_equals(ptr, d_fval, d.f_val);
+ cmc_assert_equals(ptr, d_alloc_node, d.alloc);
+ cmc_assert_equals(ptr, callbacks, d.callbacks);
+
+ d_release(d);
+
+ d = d_init_custom(0, d_fval, d_alloc_node, callbacks);
+
+ cmc_assert_equals(size_t, 0, d.capacity);
+ cmc_assert_equals(ptr, NULL, d.buffer);
+
+ d = d_init_custom(1000, NULL, d_alloc_node, callbacks);
+
+ cmc_assert_equals(size_t, 0, d.capacity);
+ cmc_assert_equals(ptr, NULL, d.buffer);
+
+ d = d_init_custom(UINT64_MAX, d_fval, d_alloc_node, callbacks);
+
+ cmc_assert_equals(size_t, 0, d.capacity);
+ cmc_assert_equals(ptr, NULL, d.buffer);
+
+ if (d.buffer)
+ d_release(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_clear(), {
+ v_total_free = 0;
+ struct deque *d = d_new(100, d_fval_counter);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 0; i < 50; i++)
+ d_push_back(d, i);
+
+ cmc_assert_equals(size_t, 50, d_count(d));
+
+ d->flag = CMC_FLAG_ERROR;
+ d_clear(d);
+
+ cmc_assert_equals(size_t, 50, v_total_free);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+ cmc_assert_equals(size_t, 100, d_capacity(d));
+
+ for (size_t i = 1; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ d_push_front(d, i);
+ else
+ d_push_back(d, i);
+ }
+
+ cmc_assert_equals(size_t, 1000, d_count(d));
+
+ size_t sum = 0;
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ sum += d->buffer[i];
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ d->flag = CMC_FLAG_ERROR;
+ d_clear(d);
+
+ cmc_assert_equals(size_t, 1050, v_total_free);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ sum = 0;
+ for (size_t i = 0; i < d->capacity; i++)
+ sum += d->buffer[i];
+
+ cmc_assert_equals(size_t, 0, sum);
+
+ d_free(d);
+
+ cmc_assert_equals(size_t, 1050, v_total_free);
+
+ v_total_free = 0;
+ });
+
+ CMC_CREATE_TEST(PFX##_free(), {
+ v_total_free = 0;
+
+ struct deque *d = d_new(100, d_fval_counter);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 1; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ d_push_front(d, i);
+ else
+ d_push_back(d, i);
+ }
+
+ cmc_assert_equals(size_t, 1000, d_count(d));
+
+ size_t sum = 0;
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ sum += d->buffer[i];
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ d_free(d);
+
+ cmc_assert_equals(size_t, 1000, v_total_free);
+
+ v_total_free = 0;
+ });
+
+ CMC_CREATE_TEST(PFX##_release(), {
+ v_total_free = 0;
+
+ struct deque d = d_init(100, d_fval_counter);
+
+ cmc_assert_not_equals(ptr, NULL, d.buffer);
+
+ for (size_t i = 1; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ d_push_front(&d, i);
+ else
+ d_push_back(&d, i);
+ }
+
+ cmc_assert_equals(size_t, 1000, d_count(&d));
+
+ size_t sum = 0;
+ for (size_t i = d.front, j = 0; j < d.count; i = (i + 1) % d.capacity, j++)
+ sum += d.buffer[i];
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ d_release(d);
+
+ cmc_assert_equals(size_t, 1000, v_total_free);
+
+ v_total_free = 0;
+ });
+
+ CMC_CREATE_TEST(PFX##_customize(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ d->flag = CMC_FLAG_ERROR;
+ d_customize(d, d_alloc_node, callbacks);
+
+ cmc_assert_equals(ptr, d_alloc_node, d->alloc);
+ cmc_assert_equals(ptr, callbacks, d->callbacks);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ d->flag = CMC_FLAG_ERROR;
+ d_customize(d, NULL, NULL);
+
+ cmc_assert_equals(ptr, cmc_alloc_node_default.malloc, d->alloc->malloc);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.calloc, d->alloc->calloc);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.realloc, d->alloc->realloc);
+ cmc_assert_equals(ptr, cmc_alloc_node_default.free, d->alloc->free);
+ cmc_assert_equals(ptr, NULL, d->callbacks);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_push_front(), {
+ total_create = 0;
+ struct deque *d = d_new_custom(100, d_fval, NULL, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_push_front(d, 10));
+
+ cmc_assert_equals(size_t, 1, d_count(d));
+ cmc_assert_equals(int32_t, 1, total_create);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ d_customize(d, NULL, NULL);
+
+ d_clear(d);
+
+ for (size_t i = 0; i < 150; i++)
+ d_push_front(d, i);
+
+ cmc_assert_equals(size_t, 150, d_count(d));
+ cmc_assert_greater(size_t, 100, d_capacity(d));
+
+ d_free(d);
+
+ d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 1; i <= 10000; i++)
+ d_push_front(d, i);
+
+ size_t sum = 0;
+
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ {
+ sum += d->buffer[i];
+ }
+
+ cmc_assert_equals(size_t, 50005000, sum);
+
+ d_free(d);
+
+ cmc_assert_equals(int32_t, 1, total_create);
+ total_create = 0;
+ });
+
+ CMC_CREATE_TEST(PFX##_push_back(), {
+ total_create = 0;
+ struct deque *d = d_new_custom(100, d_fval, NULL, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_push_front(d, 10));
+
+ cmc_assert_equals(size_t, 1, d_count(d));
+ cmc_assert_equals(int32_t, 1, total_create);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ d_customize(d, NULL, NULL);
+
+ d_clear(d);
+
+ for (size_t i = 0; i < 150; i++)
+ d_push_back(d, i);
+
+ cmc_assert_equals(size_t, 150, d_count(d));
+ cmc_assert_greater(size_t, 100, d_capacity(d));
+
+ d_free(d);
+
+ d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 1; i <= 10000; i++)
+ d_push_back(d, i);
+
+ size_t sum = 0;
+
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ {
+ sum += d->buffer[i];
+ }
+
+ cmc_assert_equals(size_t, 50005000, sum);
+
+ d_free(d);
+
+ cmc_assert_equals(int32_t, 1, total_create);
+ total_create = 0;
+ });
+
+ CMC_CREATE_TEST(PFX##_pop_front(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert(!d_pop_front(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d));
+
+ cmc_assert(d_push_front(d, 10));
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_pop_front(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_pop_front(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ d_free(d);
+
+ d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 1; i <= 20000; i++)
+ d_push_front(d, i);
+
+ cmc_assert_equals(size_t, 20000, d_count(d));
+
+ for (size_t i = 0; i < 10000; i++)
+ d_pop_front(d);
+
+ size_t sum = 0;
+
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ {
+ sum += d->buffer[i];
+ }
+
+ cmc_assert_equals(size_t, 50005000, sum);
+
+ d_clear(d);
+
+ for (size_t i = 1; i <= 20000; i++)
+ d_push_front(d, i);
+
+ cmc_assert_equals(size_t, 20000, d_count(d));
+
+ for (size_t i = 0; i < 10000; i++)
+ d_pop_front(d);
+
+ sum = 0;
+
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ {
+ sum += d->buffer[i];
+ }
+
+ cmc_assert_equals(size_t, 50005000, sum);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_pop_back(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert(!d_pop_back(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d));
+
+ cmc_assert(d_push_front(d, 10));
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_pop_back(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_pop_back(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ d_free(d);
+
+ d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 1; i <= 20000; i++)
+ d_push_back(d, i);
+
+ for (size_t i = 0; i < 10000; i++)
+ d_pop_back(d);
+
+ size_t sum = 0;
+
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ {
+ sum += d->buffer[i];
+ }
+
+ cmc_assert_equals(size_t, 50005000, sum);
+
+ d_clear(d);
+
+ for (size_t i = 1; i <= 20000; i++)
+ d_push_back(d, i);
+
+ cmc_assert_equals(size_t, 20000, d_count(d));
+
+ for (size_t i = 0; i < 10000; i++)
+ d_pop_back(d);
+
+ sum = 0;
+
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ {
+ sum += d->buffer[i];
+ }
+
+ cmc_assert_equals(size_t, 50005000, sum);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_front(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ d_front(d);
+
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d));
+
+ cmc_assert(d_push_front(d, 99));
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert_equals(size_t, 99, d_front(d));
+
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ cmc_assert(d_push_back(d, 98));
+ cmc_assert_equals(size_t, 99, d_front(d));
+ cmc_assert(d_pop_front(d));
+ cmc_assert_equals(size_t, 98, d_front(d));
+
+ d_clear(d);
+
+ cmc_assert(d_push_back(d, 99));
+ cmc_assert_equals(size_t, 99, d_front(d));
+
+ d_clear(d);
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ for (size_t i = 1; i <= 10000; i++)
+ {
+ if (i % 2 == 0)
+ d_push_front(d, i);
+ else
+ d_push_back(d, i);
+ }
+
+ size_t sum = 0;
+ for (size_t i = 0; i < 5000; i++)
+ {
+ sum += d_front(d);
+ cmc_assert_equals(int32_t, 0, d_front(d) % 2);
+ d_pop_front(d);
+ }
+
+ cmc_assert_equals(size_t, 5000, d_count(d));
+ cmc_assert_equals(size_t, 25005000, sum);
+
+ d_clear(d);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_back(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ d_back(d);
+
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d));
+
+ cmc_assert(d_push_back(d, 99));
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert_equals(size_t, 99, d_back(d));
+
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ cmc_assert(d_push_front(d, 98));
+ cmc_assert_equals(size_t, 99, d_back(d));
+ cmc_assert(d_pop_back(d));
+ cmc_assert_equals(size_t, 98, d_back(d));
+
+ d_clear(d);
+
+ cmc_assert(d_push_front(d, 99));
+ cmc_assert_equals(size_t, 99, d_back(d));
+
+ d_clear(d);
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ for (size_t i = 1; i <= 10000; i++)
+ {
+ if (i % 2 == 0)
+ d_push_back(d, i);
+ else
+ d_push_front(d, i);
+ }
+
+ size_t sum = 0;
+ for (size_t i = 0; i < 5000; i++)
+ {
+ sum += d_back(d);
+ cmc_assert_equals(int32_t, 0, d_back(d) % 2);
+ d_pop_back(d);
+ }
+
+ cmc_assert_equals(size_t, 5000, d_count(d));
+ cmc_assert_equals(size_t, 25005000, sum);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_contains(), {
+ struct deque *d = d_new(100, d_fval);
+
+ for (size_t i = 0; i < 100; i++)
+ {
+ if (i % 2 == 0)
+ d_push_back(d, i);
+ else
+ d_push_front(d, i);
+ }
+
+ for (size_t i = 0; i < 100; i++)
+ cmc_assert(d_contains(d, i));
+
+ d_free(d);
+
+ d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 1; i <= 20; i++)
+ d_push_back(d, i);
+
+ for (size_t i = 1; i <= 20; i++)
+ cmc_assert(d_contains(d, i));
+
+ d_clear(d);
+
+ for (size_t i = 1; i <= 20; i++)
+ d_push_front(d, i);
+
+ for (size_t i = 1; i <= 20; i++)
+ cmc_assert(d_contains(d, i));
+
+ d_free(d);
+
+ d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert(!d_contains(d, 10));
+
+ d_free(d);
+
+ d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert(!d_contains(d, 10));
+
+ cmc_assert(d_push_back(d, 100));
+
+ cmc_assert(d_contains(d, 100));
+ cmc_assert(!d_contains(d, 101));
+
+ cmc_assert(d_pop_front(d));
+ cmc_assert(d_push_front(d, 100));
+
+ cmc_assert(d_contains(d, 100));
+ cmc_assert(!d_contains(d, 101));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_empty(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert(d_empty(d));
+
+ cmc_assert(d_push_back(d, 1));
+
+ cmc_assert(!d_empty(d));
+
+ cmc_assert(d_pop_front(d));
+
+ cmc_assert(d_empty(d));
+
+ cmc_assert(d_push_front(d, 1));
+
+ cmc_assert(!d_empty(d));
+
+ cmc_assert(d_pop_back(d));
+
+ cmc_assert(d_empty(d));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_full(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert(!d_full(d));
+
+ for (size_t i = 0; i != d_capacity(d); i++)
+ d_push_front(d, i);
+
+ cmc_assert(d_full(d));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_count(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ for (size_t i = 0; i < 100; i++)
+ d_push_back(d, i);
+
+ cmc_assert_equals(size_t, 100, d_count(d));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_capacity(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert_equals(size_t, 100, d_capacity(d));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_resize(), {
+ total_resize = 0;
+ struct deque *d = d_new_custom(100, d_fval, NULL, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert_equals(size_t, 100, d_capacity(d));
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_resize(d, 100));
+ cmc_assert_equals(size_t, 100, d_capacity(d));
+
+ cmc_assert_equals(int32_t, 1, total_resize);
+
+ cmc_assert(d_resize(d, 200));
+ cmc_assert_equals(size_t, 200, d_capacity(d));
+
+ cmc_assert(d_resize(d, 100));
+ cmc_assert_equals(size_t, 100, d_capacity(d));
+
+ cmc_assert_equals(int32_t, 3, total_resize);
+
+ for (size_t i = 0; i < 150; i++)
+ {
+ if (i % 2 == 0)
+ cmc_assert(d_push_back(d, i));
+ else
+ cmc_assert(d_push_front(d, i));
+ }
+
+ cmc_assert_equals(size_t, 150, d_count(d));
+ cmc_assert(d_resize(d, d_count(d)));
+ cmc_assert_equals(size_t, 150, d_capacity(d));
+
+ cmc_assert(!d_resize(d, d_count(d) - 10));
+ cmc_assert_equals(int32_t, CMC_FLAG_INVALID, d_flag(d));
+
+ d_free(d);
+
+ // item preservation
+ d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 1; i <= 150; i++)
+ {
+ if (i % 2 != 0)
+ cmc_assert(d_push_back(d, i));
+ else
+ cmc_assert(d_push_front(d, i));
+ }
+
+ cmc_assert(d_resize(d, d_count(d)));
+
+ size_t sum = 0;
+
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ {
+ sum += d->buffer[i];
+ }
+
+ cmc_assert_equals(size_t, 11325, sum);
+
+ d_free(d);
+ total_resize = 0;
+ });
+
+ CMC_CREATE_TEST(PFX##_copy_of(), {
+ v_total_cpy = 0;
+ struct deque *d1 = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d1);
+
+ for (size_t i = 1; i <= 150; i++)
+ {
+ if (i % 2 != 0)
+ d_push_back(d1, i);
+ else
+ d_push_front(d1, i);
+ }
+
+ struct deque *d2 = d_copy_of(d1);
+
+ cmc_assert_not_equals(ptr, NULL, d2);
+ cmc_assert_equals(size_t, d_count(d1), d_count(d2));
+
+ for (size_t i1 = d1->front, i2 = d2->front, j = 0; j < d1->count; j++)
+ {
+ cmc_assert_equals(size_t, d1->buffer[i1], d2->buffer[i2]);
+
+ i1 = (i1 + 1) % d1->capacity;
+ i2 = (i2 + 1) % d2->capacity;
+ }
+
+ cmc_assert(d_push_front(d1, 10));
+ cmc_assert(d_push_front(d2, 10));
+ cmc_assert(d_push_back(d1, 11));
+ cmc_assert(d_push_back(d2, 11));
+
+ cmc_assert(d_equals(d1, d2));
+
+ d_free(d1);
+ d_free(d2);
+
+ // v_total_cpy
+ d1 = d_new_custom(100, d_fval_counter, d_alloc_node, NULL);
+
+ cmc_assert_not_equals(ptr, NULL, d1);
+
+ d2 = d_copy_of(d1);
+
+ cmc_assert_not_equals(ptr, NULL, d1);
+
+ cmc_assert_equals(int32_t, 0, v_total_cpy);
+
+ d_free(d2);
+
+ for (size_t i = 0; i < 1000; i++)
+ {
+ if (i % 2 != 0)
+ d_push_back(d1, i);
+ else
+ d_push_front(d1, i);
+ }
+
+ cmc_assert_equals(size_t, 1000, d1->count);
+
+ d2 = d_copy_of(d1);
+
+ cmc_assert_equals(int32_t, 1000, v_total_cpy);
+
+ d_free(d1);
+ d_free(d2);
+ v_total_cpy = 0;
+ });
+
+ CMC_CREATE_TEST(PFX##_equals(), {
+ v_total_cmp = 0;
+ struct deque *d1 = d_new(100, d_fval);
+ struct deque *d2 = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d1);
+ cmc_assert_not_equals(ptr, NULL, d2);
+
+ for (size_t i = 1; i <= 150; i++)
+ {
+ if (i % 2 != 0)
+ {
+ d_push_back(d1, i);
+ d_push_back(d2, i);
+ }
+ else
+ {
+ d_push_front(d1, i);
+ d_push_front(d2, i);
+ }
+ }
+
+ cmc_assert(d_equals(d1, d2));
+
+ d_free(d1);
+ d_free(d2);
+
+ // from copy
+ d1 = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d1);
+
+ for (size_t i = 1; i <= 150; i++)
+ {
+ if (i % 2 != 0)
+ cmc_assert(d_push_back(d1, i));
+ else
+ cmc_assert(d_push_front(d1, i));
+ }
+
+ d2 = d_copy_of(d1);
+
+ cmc_assert_not_equals(ptr, NULL, d2);
+
+ cmc_assert(d_equals(d1, d2));
+
+ d_free(d1);
+ d_free(d2);
+
+ // count = 0
+ d1 = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d1);
+
+ d2 = d_copy_of(d1);
+
+ cmc_assert_not_equals(ptr, NULL, d2);
+
+ cmc_assert(d_equals(d1, d2));
+
+ d_free(d1);
+ d_free(d2);
+
+ // false eq
+ d1 = d_new(100, d_fval);
+ d2 = d_new_custom(100, d_fval_counter, d_alloc_node, NULL);
+
+ cmc_assert(d_equals(d1, d2));
+
+ cmc_assert_equals(int32_t, 0, v_total_cmp);
+
+ d_push_back(d1, 100);
+
+ cmc_assert(!d_equals(d1, d2));
+
+ d_push_back(d2, 100);
+
+ cmc_assert(d_equals(d1, d2));
+
+ d_push_front(d1, 10);
+ d_push_front(d2, 10);
+
+ cmc_assert(d_equals(d1, d2));
+
+ d_push_back(d1, 40);
+ d_push_back(d2, 41);
+
+ cmc_assert(!d_equals(d1, d2));
+
+ v_total_cmp = 0;
+
+ d_clear(d1);
+ d_clear(d2);
+
+ for (size_t i = 0; i < 1000; i++)
+ {
+ if (i % 2 == 0)
+ {
+ d_push_back(d1, i);
+ d_push_back(d2, i);
+ }
+ else
+ {
+ d_push_front(d1, i);
+ d_push_front(d2, i);
+ }
+ }
+
+ // d2's cmp is used and v_total_cmp is incremented each time
+ cmc_assert(d_equals(d2, d1));
+
+ cmc_assert_equals(int32_t, 1000, v_total_cmp);
+
+ d_free(d1);
+ d_free(d2);
+ v_total_cmp = 0;
+ });
+
+ CMC_CREATE_TEST(Mixed IO, {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_pop_back(d));
+ cmc_assert(d_pop_back(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_pop_back(d));
+ cmc_assert(d_pop_back(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_pop_front(d));
+ cmc_assert(d_pop_front(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_pop_front(d));
+ cmc_assert(d_pop_front(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+ // ----------
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_pop_back(d));
+ cmc_assert(d_pop_front(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_pop_front(d));
+ cmc_assert(d_pop_back(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_pop_back(d));
+ cmc_assert(d_pop_front(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_pop_front(d));
+ cmc_assert(d_pop_back(d));
+
+ cmc_assert_equals(size_t, 0, d_count(d));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(buffer_growth[capacity = 1], {
+ struct deque *d = d_new(1, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 0; i < 50; i++)
+ d_push_back(d, i);
+
+ cmc_assert_equals(size_t, 50, d_count(d));
+ cmc_assert_lesser_equals(size_t, d_capacity(d), d_count(d));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(buffer_growth[item preservation], {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 1; i <= 1200; i++)
+ {
+ if (i % 2 == 0)
+ d_push_front(d, i);
+ else
+ d_push_back(d, i);
+ }
+
+ size_t sum = 0;
+ for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
+ sum += d->buffer[i];
+
+ cmc_assert_equals(size_t, 1200, d_count(d));
+ cmc_assert_equals(size_t, 720600, sum);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(flags, {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ // customize
+ d->flag = CMC_FLAG_ERROR;
+ d_customize(d, &cmc_alloc_node_default, &(struct cmc_callbacks){ 0 });
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ // push_front
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_push_front(d, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ // pop_front
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_pop_front(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+ cmc_assert(!d_pop_front(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d));
+
+ // push_back
+ cmc_assert(d_push_back(d, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ // pop_back
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_pop_back(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+ cmc_assert(!d_pop_back(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d));
+
+ // front
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_front(d) == 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d));
+
+ cmc_assert(d_push_back(d, 1));
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_front(d) == 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ // clear
+ d->flag = CMC_FLAG_ERROR;
+ d_clear(d);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ // back
+ cmc_assert(d_back(d) == 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d));
+
+ cmc_assert(d_push_front(d, 1));
+ cmc_assert(d_back(d) == 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ // contains
+ d->flag = CMC_FLAG_ERROR;
+ cmc_assert(d_contains(d, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+
+ // copy_of
+ d->flag = CMC_FLAG_ERROR;
+ struct deque *d2 = d_copy_of(d);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d2));
+
+ // equals
+ cmc_assert(d_pop_back(d));
+ cmc_assert(d_pop_back(d2));
+ d->flag = CMC_FLAG_ERROR;
+ d2->flag = CMC_FLAG_ERROR;
+ d_front(d);
+ d_front(d2);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, d_flag(d2));
+ cmc_assert(d_equals(d, d2));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, d_flag(d2));
+
+ d_free(d);
+ d_free(d2);
+ });
+
+ CMC_CREATE_TEST(callbacks, {
+ struct deque *d = d_new_custom(100, d_fval, NULL, callbacks);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert_equals(int32_t, 1, total_create);
+
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert_equals(int32_t, 2, total_create);
+
+ cmc_assert(d_pop_front(d));
+ cmc_assert_equals(int32_t, 1, total_delete);
+
+ cmc_assert(d_pop_back(d));
+ cmc_assert_equals(int32_t, 2, total_delete);
+
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_push_front(d, 5));
+ cmc_assert_equals(int32_t, 4, total_create);
+
+ cmc_assert_equals(size_t, 5, d_front(d));
+ cmc_assert_equals(int32_t, 1, total_read);
+
+ cmc_assert_equals(size_t, 10, d_back(d));
+ cmc_assert_equals(int32_t, 2, total_read);
+
+ cmc_assert(d_contains(d, 10));
+ cmc_assert(!d_contains(d, 1));
+ cmc_assert_equals(int32_t, 4, total_read);
+
+ cmc_assert(d_resize(d, 1000));
+ cmc_assert_equals(int32_t, 1, total_resize);
+
+ cmc_assert(d_resize(d, 10));
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ cmc_assert_equals(int32_t, 4, total_create);
+ cmc_assert_equals(int32_t, 4, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 2, total_delete);
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ d_customize(d, NULL, NULL);
+
+ cmc_assert_equals(ptr, NULL, d->callbacks);
+
+ d_clear(d);
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_push_back(d, 10));
+ cmc_assert(d_pop_front(d));
+ cmc_assert(d_pop_back(d));
+ cmc_assert(d_push_front(d, 10));
+ cmc_assert(d_push_front(d, 5));
+ cmc_assert_equals(size_t, 5, d_front(d));
+ cmc_assert_equals(size_t, 10, d_back(d));
+ cmc_assert(d_contains(d, 10));
+ cmc_assert(!d_contains(d, 1));
+ cmc_assert(d_resize(d, 1000));
+ cmc_assert(d_resize(d, 10));
+
+ cmc_assert_equals(int32_t, 4, total_create);
+ cmc_assert_equals(int32_t, 4, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 2, total_delete);
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ cmc_assert_equals(ptr, NULL, d->callbacks);
+
+ d_free(d);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+ });
+});
+
+CMC_CREATE_UNIT(CMCDequeIter, true, {
+ CMC_CREATE_TEST(PFX##_iter_start(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_start(d);
+
+ cmc_assert_equals(ptr, d, it.target);
+ cmc_assert_equals(size_t, d->front, it.cursor);
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(d_iter_at_start(&it));
+ cmc_assert(d_iter_at_end(&it));
+
+ cmc_assert(d_push_front(d, 1));
+ cmc_assert(d_push_front(d, 2));
+
+ it = d_iter_start(d);
+
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, false, it.end);
+ cmc_assert_equals(size_t, d->front, it.cursor);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_end(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_end(d);
+
+ cmc_assert_equals(ptr, d, it.target);
+ cmc_assert_equals(size_t, d->back, it.cursor);
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(d_iter_at_start(&it));
+ cmc_assert(d_iter_at_end(&it));
+
+ cmc_assert(d_push_back(d, 1));
+ cmc_assert(d_push_back(d, 2));
+ cmc_assert(d_push_back(d, 3));
+
+ it = d_iter_end(d);
+
+ cmc_assert_equals(size_t, d->count - 1, it.index);
+ cmc_assert_equals(size_t, d->back - 1, it.cursor);
+ cmc_assert_equals(bool, false, it.start);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_start(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_start(d);
+
+ // Empty checks
+ cmc_assert(d_iter_at_start(&it));
+ it = d_iter_end(d);
+ cmc_assert(d_iter_at_start(&it));
+
+ // Non-empty checks
+ cmc_assert(d_push_back(d, 1));
+ it = d_iter_end(d);
+ cmc_assert(!d_iter_at_start(&it));
+ it = d_iter_start(d);
+ cmc_assert(d_iter_at_start(&it));
+
+ d_clear(d);
+
+ cmc_assert(d_push_front(d, 1));
+ it = d_iter_end(d);
+ cmc_assert(!d_iter_at_start(&it));
+ it = d_iter_start(d);
+ cmc_assert(d_iter_at_start(&it));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_end(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_start(d);
+
+ // Empty check
+ cmc_assert(d_iter_at_end(&it));
+ it = d_iter_end(d);
+ cmc_assert(d_iter_at_end(&it));
+
+ // Non-empty checks
+ cmc_assert(d_push_back(d, 1));
+ it = d_iter_end(d);
+ cmc_assert(d_iter_at_end(&it));
+ it = d_iter_start(d);
+ cmc_assert(!d_iter_at_end(&it));
+
+ d_clear(d);
+
+ cmc_assert(d_push_front(d, 1));
+ it = d_iter_end(d);
+ cmc_assert(d_iter_at_end(&it));
+ it = d_iter_start(d);
+ cmc_assert(!d_iter_at_end(&it));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_start(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_start(d);
+
+ cmc_assert(!d_iter_to_start(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ {
+ if (i % 2 == 0)
+ d_push_back(d, i);
+ else
+ d_push_front(d, i);
+ }
+
+ cmc_assert_equals(size_t, 100, d->count);
+
+ it = d_iter_end(d);
+
+ cmc_assert(!d_iter_at_start(&it));
+ cmc_assert(d_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, d_iter_value(&it));
+
+ cmc_assert(d_iter_to_start(&it));
+
+ cmc_assert(d_iter_at_start(&it));
+ cmc_assert(!d_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 99, d_iter_value(&it));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_end(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_end(d);
+
+ cmc_assert(!d_iter_to_end(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ {
+ if (i % 2 == 0)
+ d_push_back(d, i);
+ else
+ d_push_front(d, i);
+ }
+
+ it = d_iter_start(d);
+
+ cmc_assert(d_iter_at_start(&it));
+ cmc_assert(!d_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 99, d_iter_value(&it));
+
+ cmc_assert(d_iter_to_end(&it));
+
+ cmc_assert(!d_iter_at_start(&it));
+ cmc_assert(d_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, d_iter_value(&it));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_next(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_start(d);
+
+ cmc_assert(!d_iter_next(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ d_push_back(d, i);
+ else
+ d_push_front(d, i);
+ }
+
+ size_t sum = 0;
+ for (it = d_iter_start(d); !d_iter_at_end(&it); d_iter_next(&it))
+ {
+ sum += d_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ d_iter_to_start(&it);
+ do
+ {
+ sum += d_iter_value(&it);
+ } while (d_iter_next(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_prev(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_end(d);
+
+ cmc_assert(!d_iter_prev(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ d_push_back(d, i);
+ else
+ d_push_front(d, i);
+ }
+
+ size_t sum = 0;
+ for (it = d_iter_end(d); !d_iter_at_start(&it); d_iter_prev(&it))
+ {
+ sum += d_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ d_iter_to_end(&it);
+ do
+ {
+ sum += d_iter_value(&it);
+ } while (d_iter_prev(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_advance(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_start(d);
+
+ cmc_assert(!d_iter_advance(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ d_push_back(d, i); // will sum all even numbers
+ else
+ d_push_back(d, 0);
+ }
+
+ it = d_iter_start(d);
+
+ cmc_assert(!d_iter_advance(&it, 0));
+ cmc_assert(!d_iter_advance(&it, d->count));
+
+ size_t sum = 0;
+ for (it = d_iter_start(d);;)
+ {
+ sum += d_iter_value(&it);
+
+ if (!d_iter_advance(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ d_iter_to_start(&it);
+ cmc_assert(d_iter_advance(&it, d->count - 1));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rewind(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_end(d);
+
+ cmc_assert(!d_iter_rewind(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ d_push_front(d, i); // will sum all even numbers
+ else
+ d_push_front(d, 0);
+ }
+
+ it = d_iter_end(d);
+
+ cmc_assert(!d_iter_rewind(&it, 0));
+ cmc_assert(!d_iter_rewind(&it, d->count));
+
+ size_t sum = 0;
+ for (it = d_iter_end(d);;)
+ {
+ sum += d_iter_value(&it);
+
+ if (!d_iter_rewind(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ d_iter_to_end(&it);
+ cmc_assert(d_iter_rewind(&it, d->count - 1));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_go_to(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_end(d);
+ cmc_assert(!d_iter_go_to(&it, 0));
+
+ it = d_iter_start(d);
+ cmc_assert(!d_iter_go_to(&it, 0));
+
+ for (size_t i = 0; i <= 1000; i++)
+ d_push_back(d, i);
+
+ it = d_iter_start(d);
+
+ size_t sum = 0;
+ for (size_t i = 0; i < 1001; i++)
+ {
+ d_iter_go_to(&it, i);
+
+ sum += d_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert(d_iter_go_to(&it, i - 1));
+
+ sum += d_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 0; i < 1001; i += 100)
+ {
+ cmc_assert(d_iter_go_to(&it, i));
+ cmc_assert_equals(size_t, i, d_iter_index(&it));
+
+ sum += d_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 5500, sum);
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_value(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_end(d);
+
+ cmc_assert_equals(size_t, (size_t){ 0 }, d_iter_value(&it));
+
+ cmc_assert(d_push_back(d, 10));
+
+ it = d_iter_start(d);
+
+ cmc_assert_equals(size_t, 10, d_iter_value(&it));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rvalue(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ struct deque_iter it = d_iter_end(d);
+
+ cmc_assert_equals(ptr, NULL, d_iter_rvalue(&it));
+
+ cmc_assert(d_push_back(d, 10));
+
+ it = d_iter_start(d);
+
+ cmc_assert_not_equals(ptr, NULL, d_iter_rvalue(&it));
+ cmc_assert_equals(size_t, 10, *d_iter_rvalue(&it));
+
+ d_free(d);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_index(), {
+ struct deque *d = d_new(100, d_fval);
+
+ cmc_assert_not_equals(ptr, NULL, d);
+
+ for (size_t i = 0; i <= 1000; i++)
+ d_push_back(d, i);
+
+ struct deque_iter it = d_iter_start(d);
+
+ for (size_t i = 0; i < 1001; i++)
+ {
+ cmc_assert_equals(size_t, i, d_iter_index(&it));
+ d_iter_next(&it);
+ }
+
+ it = d_iter_end(d);
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert_equals(size_t, i - 1, d_iter_index(&it));
+ d_iter_prev(&it);
+ }
+
+ d_free(d);
+ });
+});
+
+#endif /* CMC_TESTS_UNT_DEQUE_H */
diff --git a/tests/unt_list.h b/tests/unt_list.h
new file mode 100644
index 0000000..38993fb
--- /dev/null
+++ b/tests/unt_list.h
@@ -0,0 +1,1072 @@
+#ifndef CMC_TESTS_UNT_LIST_H
+#define CMC_TESTS_UNT_LIST_H
+
+#include "utl.h"
+
+#define V size_t
+#define PFX l
+#define SNAME list
+#define CMC_EXT_LIST_INIT
+#define CMC_EXT_LIST_ITER
+#define CMC_EXT_LIST_SEQ
+#include "cmc/list.h"
+
+struct list_fval *l_fval = &(struct list_fval){
+ .cmp = cmc_size_cmp, .cpy = NULL, .str = cmc_size_str, .free = NULL, .hash = cmc_size_hash, .pri = cmc_size_cmp
+};
+
+CMC_CREATE_UNIT(CMCList, true, {
+ CMC_CREATE_TEST(new, {
+ struct list *l = l_new(1000000, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+ cmc_assert_not_equals(ptr, NULL, l->buffer);
+ cmc_assert_equals(size_t, 1000000, l_capacity(l));
+ cmc_assert_equals(size_t, 0, l_count(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(new[capacity = 0], {
+ struct list *l = l_new(0, l_fval);
+
+ cmc_assert_equals(ptr, NULL, l);
+ });
+
+ CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
+ struct list *l = l_new(UINT64_MAX, l_fval);
+
+ cmc_assert_equals(ptr, NULL, l);
+ });
+
+ CMC_CREATE_TEST(clear[count capacity], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ for (size_t i = 0; i < 50; i++)
+ l_push_back(l, i);
+
+ cmc_assert_equals(size_t, 50, l_count(l));
+
+ l_clear(l);
+
+ cmc_assert_equals(size_t, 0, l_count(l));
+ cmc_assert_equals(size_t, 100, l_capacity(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(buffer_growth[capacity = 1], {
+ struct list *l = l_new(1, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ for (size_t i = 0; i < 100; i++)
+ l_push_back(l, i);
+
+ cmc_assert_equals(size_t, 100, l_count(l));
+
+ for (size_t i = 0; i < 100; i++)
+ cmc_assert_equals(size_t, i, l_get(l, i));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(push_front[count], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(l_push_front(l, i));
+
+ cmc_assert_equals(size_t, 250, l_count(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(push_front[capacity], {
+ struct list *l = l_new(100, l_fval);
+
+ 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));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(push_front[item preservation], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(l_push_front(l, i));
+
+ for (size_t i = 0; i < l_count(l); i++)
+ cmc_assert_equals(size_t, l_get(l, i), l_count(l) - i - 1);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(push_at[count], {
+ struct list *l = l_new(100, l_fval);
+
+ 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_at(l, i, l_count(l) - 1));
+
+ cmc_assert_equals(size_t, 250, l_count(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(push_at[capacity], {
+ struct list *l = l_new(100, l_fval);
+
+ 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_at(l, i, l_count(l) - 1));
+
+ cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(push_at[item preservation], {
+ struct list *l = l_new(100, l_fval);
+
+ 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_at(l, i, l_count(l) - 1));
+
+ for (size_t i = 0; i < l_count(l); i++)
+ cmc_assert_equals(size_t, l_get(l, i), i);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(push_back[count], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(l_push_back(l, i));
+
+ cmc_assert_equals(size_t, 250, l_count(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(push_back[capacity], {
+ struct list *l = l_new(100, l_fval);
+
+ 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));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(push_back[item preservation], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(l_push_back(l, i));
+
+ for (size_t i = 0; i < l_count(l); i++)
+ cmc_assert_equals(size_t, l_get(l, i), i);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_front[count], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ for (size_t i = 0; i < 250; i++)
+ l_push_back(l, i);
+
+ cmc_assert(l_pop_front(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_front[item preservation], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ for (size_t i = 0; i < 250; i++)
+ l_push_back(l, i);
+
+ cmc_assert(l_pop_front(l));
+
+ for (size_t i = 0; i < l_count(l); i++)
+ cmc_assert_equals(size_t, l_get(l, i), i + 1);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_front[count = 0], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+ cmc_assert(!l_pop_front(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_front[count = 1], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+ cmc_assert(l_push_back(l, 10));
+ cmc_assert(l_pop_front(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_front[buffer_clear], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+ cmc_assert(l_push_back(l, 1));
+ cmc_assert(l_push_front(l, 2));
+
+ cmc_assert(l_pop_front(l));
+
+ cmc_assert_equals(size_t, 0, l->buffer[1]);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_at[count = 0], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+ cmc_assert(!l_pop_at(l, 1));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_at[count = 1], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+ cmc_assert(l_push_back(l, 1));
+ cmc_assert(l_pop_at(l, 0));
+
+ cmc_assert_equals(size_t, 0, l->buffer[0]);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_at[buffer_clear], {
+ struct list *l = l_new(100, l_fval);
+
+ 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_at(l, 1));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_back[count = 0], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+ cmc_assert(!l_pop_back(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(pop_back[count = 1], {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+ cmc_assert(l_push_back(l, 10));
+ cmc_assert(l_pop_back(l));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(flags, {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // clear
+ l->flag = CMC_FLAG_ERROR;
+ l_clear(l);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // customize
+ l->flag = CMC_FLAG_ERROR;
+ l_customize(l, NULL, NULL);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // push_front
+ l->flag = CMC_FLAG_ERROR;
+ cmc_assert(l_push_front(l, 10));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // push_at
+ cmc_assert(!l_push_at(l, 5, 2));
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, l_flag(l));
+ cmc_assert(l_push_at(l, 5, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // push_back
+ l->flag = CMC_FLAG_ERROR;
+ cmc_assert(l_push_back(l, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // pop_front
+ l->flag = CMC_FLAG_ERROR;
+ cmc_assert(l_pop_front(l));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ l_clear(l);
+ cmc_assert(!l_pop_front(l));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, l_flag(l));
+
+ // pop_back
+ cmc_assert(l_push_front(l, 10));
+ l->flag = CMC_FLAG_ERROR;
+ cmc_assert(l_pop_back(l));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ cmc_assert(!l_pop_front(l));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, l_flag(l));
+
+ // pop_at
+ l->flag = CMC_FLAG_ERROR;
+ cmc_assert(!l_pop_at(l, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, l_flag(l));
+
+ cmc_assert(l_push_back(l, 10));
+ cmc_assert(!l_pop_at(l, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, l_flag(l));
+
+ cmc_assert(l_pop_at(l, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // seq_push_front
+ cmc_assert(!l_seq_push_front(l, NULL, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_INVALID, l_flag(l));
+
+ cmc_assert(l_seq_push_front(l, (size_t[2]){ 1, 2 }, 2));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // seq_push_at
+ cmc_assert(!l_seq_push_at(l, NULL, 0, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_INVALID, l_flag(l));
+
+ cmc_assert(!l_seq_push_at(l, (size_t[2]){ 1, 2 }, 2, 10));
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, l_flag(l));
+
+ cmc_assert(l_seq_push_at(l, (size_t[2]){ 1, 2 }, 2, l_count(l) - 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // seq_push_back
+ cmc_assert(!l_seq_push_back(l, NULL, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_INVALID, l_flag(l));
+
+ cmc_assert(l_seq_push_back(l, (size_t[2]){ 1, 2 }, 2));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // seq_pop_at
+ cmc_assert(!l_seq_pop_at(l, 10, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_INVALID, l_flag(l));
+
+ cmc_assert(!l_seq_pop_at(l, 100, 200));
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, l_flag(l));
+
+ cmc_assert(l_seq_pop_at(l, 1, l_count(l) - 2));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // seq_sublist
+ struct list *l2 = l_seq_sublist(l, 10, 1);
+ cmc_assert_equals(ptr, NULL, l2);
+ cmc_assert_equals(int32_t, CMC_FLAG_INVALID, l_flag(l));
+
+ l2 = l_seq_sublist(l, 100, 200);
+ cmc_assert_equals(ptr, NULL, l2);
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, l_flag(l));
+
+ l2 = l_seq_sublist(l, 0, l_count(l) - 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l2));
+
+ l_clear(l);
+
+ // l_front
+ l_front(l);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, l_flag(l));
+
+ cmc_assert(l_push_back(l, 10));
+ l->flag = CMC_FLAG_ERROR;
+ l_front(l);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ l_clear(l);
+
+ // l_back
+ l_back(l);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, l_flag(l));
+
+ cmc_assert(l_push_back(l, 10));
+ l->flag = CMC_FLAG_ERROR;
+ l_back(l);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ l_clear(l);
+
+ // get, get_ref
+ l_get(l, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, l_flag(l));
+ l->flag = CMC_FLAG_ERROR;
+ l_get_ref(l, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, l_flag(l));
+
+ cmc_assert(l_push_back(l, 10));
+
+ l_get(l, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, l_flag(l));
+ l->flag = CMC_FLAG_ERROR;
+ l_get_ref(l, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, l_flag(l));
+
+ l_get(l, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+ l->flag = CMC_FLAG_ERROR;
+ l_get_ref(l, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // index_of
+ l->flag = CMC_FLAG_ERROR;
+ l_index_of(l, 10, false);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // contains
+ l->flag = CMC_FLAG_ERROR;
+ cmc_assert(l_contains(l, 10));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+
+ // copy_of
+ l->flag = CMC_FLAG_ERROR;
+ struct list *l3 = l_copy_of(l);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l3));
+
+ // equals
+ l->flag = CMC_FLAG_ERROR;
+ l3->flag = CMC_FLAG_ERROR;
+ cmc_assert(l_equals(l, l3));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l3));
+
+ l_free(l);
+ l_free(l2);
+ l_free(l3);
+ });
+
+ CMC_CREATE_TEST(callbacks, {
+ struct list *l = l_new_custom(100, l_fval, NULL, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+
+ cmc_assert(l_push_front(l, 10));
+ cmc_assert_equals(int32_t, 1, total_create);
+
+ cmc_assert(l_push_back(l, 10));
+ cmc_assert_equals(int32_t, 2, total_create);
+
+ cmc_assert(l_push_at(l, 10, 1));
+ cmc_assert_equals(int32_t, 3, total_create);
+
+ cmc_assert(l_pop_at(l, 1));
+ cmc_assert_equals(int32_t, 1, total_delete);
+
+ cmc_assert(l_pop_front(l));
+ cmc_assert_equals(int32_t, 2, total_delete);
+
+ cmc_assert(l_pop_back(l));
+ cmc_assert_equals(int32_t, 3, total_delete);
+
+ cmc_assert(l_push_back(l, 10));
+ cmc_assert_equals(int32_t, 4, total_create);
+
+ cmc_assert_equals(size_t, 10, l_front(l));
+ cmc_assert_equals(int32_t, 1, total_read);
+
+ cmc_assert_equals(size_t, 10, l_back(l));
+ cmc_assert_equals(int32_t, 2, total_read);
+
+ cmc_assert_equals(size_t, 10, l_get(l, 0));
+ cmc_assert_equals(int32_t, 3, total_read);
+
+ cmc_assert_not_equals(ptr, NULL, l_get_ref(l, 0));
+ cmc_assert_equals(int32_t, 4, total_read);
+
+ cmc_assert(l_contains(l, 10));
+ cmc_assert_equals(int32_t, 5, total_read);
+
+ cmc_assert(l_seq_push_front(l, (size_t[]){ 7, 8, 9 }, 3));
+ cmc_assert_equals(int32_t, 5, total_create);
+
+ cmc_assert(l_seq_push_back(l, (size_t[]){ 14, 15, 16 }, 3));
+ cmc_assert_equals(int32_t, 6, total_create);
+
+ cmc_assert(l_seq_push_at(l, (size_t[]){ 11, 12, 13 }, 3, 4));
+ cmc_assert_equals(int32_t, 7, total_create);
+
+ cmc_assert(l_seq_pop_at(l, 1, 4));
+ cmc_assert_equals(int32_t, 4, total_delete);
+
+ struct list *l2 = l_seq_sublist(l, 0, 4);
+ cmc_assert_equals(int32_t, 5, total_delete);
+
+ cmc_assert(l_resize(l, 1000));
+ cmc_assert_equals(int32_t, 1, total_resize);
+
+ cmc_assert(l_resize(l2, 1000));
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ cmc_assert_equals(int32_t, 7, total_create);
+ cmc_assert_equals(int32_t, 5, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 5, total_delete);
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ l_customize(l, NULL, NULL);
+
+ cmc_assert_equals(ptr, NULL, l->callbacks);
+
+ l_clear(l);
+ cmc_assert(l_push_front(l, 10));
+ cmc_assert(l_push_back(l, 10));
+ cmc_assert(l_push_at(l, 10, 1));
+ cmc_assert(l_pop_at(l, 1));
+ cmc_assert(l_pop_front(l));
+ cmc_assert(l_pop_back(l));
+ cmc_assert(l_push_back(l, 10));
+ cmc_assert_equals(size_t, 10, l_front(l));
+ cmc_assert_equals(size_t, 10, l_back(l));
+ cmc_assert_equals(size_t, 10, l_get(l, 0));
+ cmc_assert_not_equals(ptr, NULL, l_get_ref(l, 0));
+ cmc_assert(l_contains(l, 10));
+ cmc_assert(l_seq_push_front(l, (size_t[]){ 7, 8, 9 }, 3));
+ cmc_assert(l_seq_push_back(l, (size_t[]){ 14, 15, 16 }, 3));
+ cmc_assert(l_seq_push_at(l, (size_t[]){ 11, 12, 13 }, 3, 4));
+ cmc_assert(l_seq_pop_at(l, 1, 4));
+ struct list *l3 = l_seq_sublist(l, 0, 4);
+ cmc_assert(l_resize(l, 1000));
+ cmc_assert(l_resize(l3, 1000));
+
+ cmc_assert_equals(int32_t, 7, total_create);
+ cmc_assert_equals(int32_t, 5, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 5, total_delete);
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ cmc_assert_equals(ptr, NULL, l->callbacks);
+
+ l_free(l);
+ l_free(l2);
+ l_free(l3);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+ });
+})
+
+CMC_CREATE_UNIT(CMCListIter, true, {
+ CMC_CREATE_TEST(PFX##_iter_start(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_start(l);
+
+ cmc_assert_equals(ptr, l, it.target);
+ cmc_assert_equals(size_t, 0, it.cursor);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(l_iter_at_start(&it));
+ cmc_assert(l_iter_at_end(&it));
+
+ cmc_assert(l_push_front(l, 1));
+ cmc_assert(l_push_front(l, 2));
+
+ it = l_iter_start(l);
+
+ cmc_assert_equals(size_t, 0, it.cursor);
+ cmc_assert_equals(bool, false, it.end);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_end(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_end(l);
+
+ cmc_assert_equals(ptr, l, it.target);
+ cmc_assert_equals(size_t, 0, it.cursor);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(l_iter_at_start(&it));
+ cmc_assert(l_iter_at_end(&it));
+
+ cmc_assert(l_push_back(l, 1));
+ cmc_assert(l_push_back(l, 2));
+ cmc_assert(l_push_back(l, 3));
+
+ it = l_iter_end(l);
+
+ cmc_assert_equals(size_t, l->count - 1, it.cursor);
+ cmc_assert_equals(bool, false, it.start);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_start(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_start(l);
+
+ // Empty checks
+ cmc_assert(l_iter_at_start(&it));
+ it = l_iter_end(l);
+ cmc_assert(l_iter_at_start(&it));
+
+ // Non-empty checks
+ cmc_assert(l_push_back(l, 1));
+ it = l_iter_end(l);
+ cmc_assert(!l_iter_at_start(&it));
+ it = l_iter_start(l);
+ cmc_assert(l_iter_at_start(&it));
+
+ l_clear(l);
+
+ cmc_assert(l_push_front(l, 1));
+ it = l_iter_end(l);
+ cmc_assert(!l_iter_at_start(&it));
+ it = l_iter_start(l);
+ cmc_assert(l_iter_at_start(&it));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_end(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_start(l);
+
+ // Empty check
+ cmc_assert(l_iter_at_end(&it));
+ it = l_iter_end(l);
+ cmc_assert(l_iter_at_end(&it));
+
+ // Non-empty checks
+ cmc_assert(l_push_back(l, 1));
+ it = l_iter_end(l);
+ cmc_assert(l_iter_at_end(&it));
+ it = l_iter_start(l);
+ cmc_assert(!l_iter_at_end(&it));
+
+ l_clear(l);
+
+ cmc_assert(l_push_front(l, 1));
+ it = l_iter_end(l);
+ cmc_assert(l_iter_at_end(&it));
+ it = l_iter_start(l);
+ cmc_assert(!l_iter_at_end(&it));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_start(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_start(l);
+
+ cmc_assert(!l_iter_to_start(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ {
+ if (i % 2 == 0)
+ l_push_back(l, i);
+ else
+ l_push_front(l, i);
+ }
+
+ cmc_assert_equals(size_t, 100, l->count);
+
+ it = l_iter_end(l);
+
+ cmc_assert(!l_iter_at_start(&it));
+ cmc_assert(l_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, l_iter_value(&it));
+
+ cmc_assert(l_iter_to_start(&it));
+
+ cmc_assert(l_iter_at_start(&it));
+ cmc_assert(!l_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 99, l_iter_value(&it));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_end(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_end(l);
+
+ cmc_assert(!l_iter_to_end(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ {
+ if (i % 2 == 0)
+ l_push_back(l, i);
+ else
+ l_push_front(l, i);
+ }
+
+ it = l_iter_start(l);
+
+ cmc_assert(l_iter_at_start(&it));
+ cmc_assert(!l_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 99, l_iter_value(&it));
+
+ cmc_assert(l_iter_to_end(&it));
+
+ cmc_assert(!l_iter_at_start(&it));
+ cmc_assert(l_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, l_iter_value(&it));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_next(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_start(l);
+
+ cmc_assert(!l_iter_next(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ l_push_back(l, i);
+ else
+ l_push_front(l, i);
+ }
+
+ size_t sum = 0;
+ for (it = l_iter_start(l); !l_iter_at_end(&it); l_iter_next(&it))
+ {
+ sum += l_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ l_iter_to_start(&it);
+ do
+ {
+ sum += l_iter_value(&it);
+ } while (l_iter_next(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_prev(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_end(l);
+
+ cmc_assert(!l_iter_prev(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ l_push_back(l, i);
+ else
+ l_push_front(l, i);
+ }
+
+ size_t sum = 0;
+ for (it = l_iter_end(l); !l_iter_at_start(&it); l_iter_prev(&it))
+ {
+ sum += l_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ l_iter_to_end(&it);
+ do
+ {
+ sum += l_iter_value(&it);
+ } while (l_iter_prev(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_advance(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_start(l);
+
+ cmc_assert(!l_iter_advance(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ l_push_back(l, i); // will sum all even numbers
+ else
+ l_push_back(l, 0);
+ }
+
+ it = l_iter_start(l);
+
+ cmc_assert(!l_iter_advance(&it, 0));
+ cmc_assert(!l_iter_advance(&it, l->count));
+
+ size_t sum = 0;
+ for (it = l_iter_start(l);;)
+ {
+ sum += l_iter_value(&it);
+
+ if (!l_iter_advance(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ l_iter_to_start(&it);
+ cmc_assert(l_iter_advance(&it, l->count - 1));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rewind(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_end(l);
+
+ cmc_assert(!l_iter_rewind(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ l_push_front(l, i); // will sum all even numbers
+ else
+ l_push_front(l, 0);
+ }
+
+ it = l_iter_end(l);
+
+ cmc_assert(!l_iter_rewind(&it, 0));
+ cmc_assert(!l_iter_rewind(&it, l->count));
+
+ size_t sum = 0;
+ for (it = l_iter_end(l);;)
+ {
+ sum += l_iter_value(&it);
+
+ if (!l_iter_rewind(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ l_iter_to_end(&it);
+ cmc_assert(l_iter_rewind(&it, l->count - 1));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_go_to(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_end(l);
+ cmc_assert(!l_iter_go_to(&it, 0));
+
+ it = l_iter_start(l);
+ cmc_assert(!l_iter_go_to(&it, 0));
+
+ for (size_t i = 0; i <= 1000; i++)
+ l_push_back(l, i);
+
+ it = l_iter_start(l);
+
+ size_t sum = 0;
+ for (size_t i = 0; i < 1001; i++)
+ {
+ l_iter_go_to(&it, i);
+
+ sum += l_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert(l_iter_go_to(&it, i - 1));
+
+ sum += l_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 0; i < 1001; i += 100)
+ {
+ cmc_assert(l_iter_go_to(&it, i));
+ cmc_assert_equals(size_t, i, l_iter_index(&it));
+
+ sum += l_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 5500, sum);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_value(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_end(l);
+
+ cmc_assert_equals(size_t, (size_t){ 0 }, l_iter_value(&it));
+
+ cmc_assert(l_push_back(l, 10));
+
+ it = l_iter_start(l);
+
+ cmc_assert_equals(size_t, 10, l_iter_value(&it));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rvalue(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ struct list_iter it = l_iter_end(l);
+
+ cmc_assert_equals(ptr, NULL, l_iter_rvalue(&it));
+
+ cmc_assert(l_push_back(l, 10));
+
+ it = l_iter_start(l);
+
+ cmc_assert_not_equals(ptr, NULL, l_iter_rvalue(&it));
+ cmc_assert_equals(size_t, 10, *l_iter_rvalue(&it));
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_index(), {
+ struct list *l = l_new(100, l_fval);
+
+ cmc_assert_not_equals(ptr, NULL, l);
+
+ for (size_t i = 0; i <= 1000; i++)
+ l_push_back(l, i);
+
+ struct list_iter it = l_iter_start(l);
+
+ for (size_t i = 0; i < 1001; i++)
+ {
+ cmc_assert_equals(size_t, i, l_iter_index(&it));
+ l_iter_next(&it);
+ }
+
+ it = l_iter_end(l);
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert_equals(size_t, i - 1, l_iter_index(&it));
+ l_iter_prev(&it);
+ }
+
+ l_free(l);
+ });
+});
+
+#endif /* CMC_TESTS_UNT_LIST_H */
diff --git a/tests/unt_stack.h b/tests/unt_stack.h
new file mode 100644
index 0000000..6e365c9
--- /dev/null
+++ b/tests/unt_stack.h
@@ -0,0 +1,854 @@
+#ifndef CMC_TESTS_UNT_STACK_H
+#define CMC_TESTS_UNT_STACK_H
+
+#include "utl.h"
+
+#define V size_t
+#define PFX s
+#define SNAME stack
+#define CMC_EXT_STACK_INIT
+#define CMC_EXT_STACK_ITER
+#include "cmc/stack.h"
+
+struct stack_fval *s_fval = &(struct stack_fval){
+ .cmp = cmc_size_cmp, .cpy = NULL, .str = cmc_size_str, .free = NULL, .hash = cmc_size_hash, .pri = cmc_size_cmp
+};
+
+CMC_CREATE_UNIT(CMCStack, true, {
+ CMC_CREATE_TEST(new, {
+ struct stack *s = s_new(1000000, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+ cmc_assert_not_equals(ptr, NULL, s->buffer);
+ cmc_assert_equals(size_t, 1000000, s_capacity(s));
+ cmc_assert_equals(size_t, 0, s_count(s));
+ cmc_assert_not_equals(ptr, NULL, s->buffer);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(new[capacity = 0], {
+ struct stack *s = s_new(0, s_fval);
+
+ cmc_assert_equals(ptr, NULL, s);
+ });
+
+ CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
+ struct stack *s = s_new(UINT64_MAX, s_fval);
+
+ cmc_assert_equals(ptr, NULL, s);
+ });
+
+ CMC_CREATE_TEST(clear[count capacity], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 50; i++)
+ cmc_assert(s_push(s, i));
+
+ cmc_assert_equals(size_t, 50, s_count(s));
+
+ s_clear(s);
+
+ cmc_assert_equals(size_t, 0, s_count(s));
+ cmc_assert_equals(size_t, 100, s_capacity(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(buffer_growth[capacity = 1], {
+ struct stack *s = s_new(1, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 50; i++)
+ cmc_assert(s_push(s, i));
+
+ cmc_assert_equals(size_t, 50, s_count(s));
+ cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(push[count], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(s_push(s, i));
+
+ cmc_assert_equals(size_t, 250, s_count(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(push[capacity], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(s_push(s, i));
+
+ cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(push[item preservation], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(s_push(s, i));
+
+ for (size_t i = 0; i < s_count(s); i++)
+ cmc_assert_equals(size_t, i, s->buffer[i]);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(pop[count], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(s_push(s, i));
+
+ cmc_assert(s_pop(s));
+
+ cmc_assert_equals(size_t, 249, s_count(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(pop[capacity], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(s_push(s, i));
+
+ cmc_assert(s_pop(s));
+
+ cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(pop[item preservation], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(s_push(s, i));
+
+ cmc_assert(s_pop(s));
+ cmc_assert(s_pop(s));
+
+ for (size_t i = 0; i < s_count(s); i++)
+ cmc_assert_equals(size_t, i, s->buffer[i]);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(pop[count = 0], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ cmc_assert_equals(bool, false, s_pop(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(top, {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 250; i++)
+ cmc_assert(s_push(s, i));
+
+ cmc_assert(s_pop(s));
+ cmc_assert(s_pop(s));
+
+ cmc_assert_equals(size_t, 247, s_top(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(top[count = 0], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ cmc_assert(s_push(s, 1));
+
+ cmc_assert(s_pop(s));
+
+ cmc_assert_equals(size_t, (size_t){ 0 }, s_top(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(top[count = 1], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ cmc_assert(s_push(s, 10));
+ cmc_assert_equals(size_t, 1, s_count(s));
+ cmc_assert_equals(size_t, 10, s_top(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(contains, {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < 150; i++)
+ cmc_assert(s_push(s, i));
+
+ for (size_t i = 0; i < 150; i++)
+ cmc_assert(s_contains(s, i));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(contains[count = 0], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ cmc_assert_equals(bool, false, s_contains(s, 10));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(empty, {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ cmc_assert(s_empty(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(empty[after_io], {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ cmc_assert(s_push(s, 10));
+ cmc_assert(s_pop(s));
+ cmc_assert(s_empty(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(full, {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i < s_capacity(s); i++)
+ cmc_assert(s_push(s, i));
+
+ cmc_assert(s_full(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(full[capacity = 1], {
+ struct stack *s = s_new(1, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ cmc_assert(s_push(s, 10));
+
+ cmc_assert(s_full(s));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(flags, {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s));
+
+ // clear
+ s->flag = CMC_FLAG_ERROR;
+ s_clear(s);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s));
+
+ // customize
+ s->flag = CMC_FLAG_ERROR;
+ s_customize(s, NULL, NULL);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s));
+
+ // push
+ s->flag = CMC_FLAG_ERROR;
+ cmc_assert(s_push(s, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s));
+
+ // pop
+ s->flag = CMC_FLAG_ERROR;
+ cmc_assert(s_pop(s));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s));
+
+ cmc_assert(!s_pop(s));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, s_flag(s));
+
+ // top
+ s->flag = CMC_FLAG_ERROR;
+ s_top(s);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, s_flag(s));
+
+ cmc_assert(s_push(s, 1));
+ s_top(s);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s));
+
+ // contains
+ s->flag = CMC_FLAG_ERROR;
+ cmc_assert(s_contains(s, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s));
+
+ // copy_of
+ s->flag = CMC_FLAG_ERROR;
+ struct stack *s2 = s_copy_of(s);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s2));
+
+ // equals
+ s->flag = CMC_FLAG_ERROR;
+ s2->flag = CMC_FLAG_ERROR;
+ cmc_assert(s_equals(s, s2));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, s_flag(s2));
+
+ s_free(s);
+ s_free(s2);
+ });
+
+ CMC_CREATE_TEST(callbacks, {
+ struct stack *s = s_new_custom(100, s_fval, NULL, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+
+ cmc_assert(s_push(s, 10));
+ cmc_assert_equals(int32_t, 1, total_create);
+
+ cmc_assert(s_pop(s));
+ cmc_assert_equals(int32_t, 1, total_delete);
+
+ cmc_assert(s_push(s, 1));
+ cmc_assert_equals(int32_t, 2, total_create);
+
+ cmc_assert_equals(size_t, 1, s_top(s));
+ cmc_assert_equals(int32_t, 1, total_read);
+
+ cmc_assert(s_contains(s, 1));
+ cmc_assert_equals(int32_t, 2, total_read);
+
+ cmc_assert(s_resize(s, 1000));
+ cmc_assert_equals(int32_t, 1, total_resize);
+
+ cmc_assert(s_resize(s, 10));
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ cmc_assert_equals(int32_t, 2, total_create);
+ cmc_assert_equals(int32_t, 2, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 1, total_delete);
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ s_customize(s, NULL, NULL);
+
+ s_clear(s);
+ cmc_assert(s_push(s, 10));
+ cmc_assert(s_pop(s));
+ cmc_assert(s_push(s, 1));
+ cmc_assert_equals(size_t, 1, s_top(s));
+ cmc_assert(s_contains(s, 1));
+ cmc_assert(s_resize(s, 1000));
+ cmc_assert(s_resize(s, 10));
+
+ cmc_assert_equals(int32_t, 2, total_create);
+ cmc_assert_equals(int32_t, 2, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 1, total_delete);
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ cmc_assert_equals(ptr, NULL, s->callbacks);
+
+ s_free(s);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+ });
+});
+
+CMC_CREATE_UNIT(CMCStackIter, true, {
+ CMC_CREATE_TEST(PFX##_iter_start(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_start(s);
+
+ cmc_assert_equals(ptr, s, it.target);
+ cmc_assert_equals(size_t, 0, it.cursor);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(s_iter_at_start(&it));
+ cmc_assert(s_iter_at_end(&it));
+
+ cmc_assert(s_push(s, 1));
+ cmc_assert(s_push(s, 2));
+
+ it = s_iter_start(s);
+
+ cmc_assert_equals(size_t, s->count - 1, it.cursor);
+ cmc_assert_equals(bool, false, it.end);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_end(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_end(s);
+
+ cmc_assert_equals(ptr, s, it.target);
+ cmc_assert_equals(size_t, 0, it.cursor);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(s_iter_at_start(&it));
+ cmc_assert(s_iter_at_end(&it));
+
+ cmc_assert(s_push(s, 1));
+ cmc_assert(s_push(s, 2));
+ cmc_assert(s_push(s, 3));
+
+ it = s_iter_end(s);
+
+ cmc_assert_equals(size_t, 0, it.cursor);
+ cmc_assert_equals(bool, false, it.start);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_start(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_start(s);
+
+ // Empty checks
+ cmc_assert(s_iter_at_start(&it));
+ it = s_iter_end(s);
+ cmc_assert(s_iter_at_start(&it));
+
+ // Non-empty checks
+ cmc_assert(s_push(s, 1));
+ it = s_iter_end(s);
+ cmc_assert(!s_iter_at_start(&it));
+ it = s_iter_start(s);
+ cmc_assert(s_iter_at_start(&it));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_end(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_start(s);
+
+ // Empty check
+ cmc_assert(s_iter_at_end(&it));
+ it = s_iter_end(s);
+ cmc_assert(s_iter_at_end(&it));
+
+ // Non-empty checks
+ cmc_assert(s_push(s, 1));
+ it = s_iter_end(s);
+ cmc_assert(s_iter_at_end(&it));
+ it = s_iter_start(s);
+ cmc_assert(!s_iter_at_end(&it));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_start(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_start(s);
+
+ cmc_assert(!s_iter_to_start(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ s_push(s, i);
+
+ cmc_assert_equals(size_t, 100, s->count);
+
+ it = s_iter_end(s);
+
+ cmc_assert(!s_iter_at_start(&it));
+ cmc_assert(s_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 1, s_iter_value(&it));
+
+ cmc_assert(s_iter_to_start(&it));
+
+ cmc_assert(s_iter_at_start(&it));
+ cmc_assert(!s_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, s_iter_value(&it));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_end(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_end(s);
+
+ cmc_assert(!s_iter_to_end(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ s_push(s, i);
+
+ it = s_iter_start(s);
+
+ cmc_assert(s_iter_at_start(&it));
+ cmc_assert(!s_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, s_iter_value(&it));
+
+ cmc_assert(s_iter_to_end(&it));
+
+ cmc_assert(!s_iter_at_start(&it));
+ cmc_assert(s_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 1, s_iter_value(&it));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_next(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_start(s);
+
+ cmc_assert(!s_iter_next(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ s_push(s, i);
+
+ size_t sum = 0;
+ for (it = s_iter_start(s); !s_iter_at_end(&it); s_iter_next(&it))
+ {
+ sum += s_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ s_iter_to_start(&it);
+ do
+ {
+ sum += s_iter_value(&it);
+ } while (s_iter_next(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_prev(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_end(s);
+
+ cmc_assert(!s_iter_prev(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ s_push(s, i);
+
+ size_t sum = 0;
+ for (it = s_iter_end(s); !s_iter_at_start(&it); s_iter_prev(&it))
+ {
+ sum += s_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ s_iter_to_end(&it);
+ do
+ {
+ sum += s_iter_value(&it);
+ } while (s_iter_prev(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_advance(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_start(s);
+
+ cmc_assert(!s_iter_advance(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ s_push(s, i);
+
+ it = s_iter_start(s);
+
+ cmc_assert(!s_iter_advance(&it, 0));
+ cmc_assert(!s_iter_advance(&it, s->count));
+
+ size_t sum = 0;
+ for (it = s_iter_start(s);;)
+ {
+ sum += s_iter_value(&it);
+
+ if (!s_iter_advance(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ s_iter_to_start(&it);
+ cmc_assert(s_iter_advance(&it, s->count - 1));
+
+ // sum (1000, 990, 980, 970, ..., 910, 900)
+ sum = 0;
+ it = s_iter_start(s);
+ for (size_t val = s_iter_value(&it); val > 900; s_iter_advance(&it, 10))
+ {
+ val = s_iter_value(&it);
+ sum += val;
+ }
+
+ cmc_assert_equals(size_t, 10450, sum);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rewind(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_end(s);
+
+ cmc_assert(!s_iter_rewind(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ s_push(s, i);
+
+ it = s_iter_end(s);
+
+ cmc_assert(!s_iter_rewind(&it, 0));
+ cmc_assert(!s_iter_rewind(&it, s->count));
+
+ size_t sum = 0;
+ for (it = s_iter_end(s);;)
+ {
+ sum += s_iter_value(&it);
+
+ if (!s_iter_rewind(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ s_iter_to_end(&it);
+ cmc_assert(s_iter_rewind(&it, s->count - 1));
+
+ // sum (0, 10, 20, ..., 90, 100)
+ sum = 0;
+ it = s_iter_end(s);
+ for (size_t val = s_iter_value(&it); val < 100; s_iter_rewind(&it, 10))
+ {
+ val = s_iter_value(&it);
+ sum += val;
+ }
+
+ cmc_assert_equals(size_t, 550, sum);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_go_to(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_end(s);
+ cmc_assert(!s_iter_go_to(&it, 0));
+
+ it = s_iter_start(s);
+ cmc_assert(!s_iter_go_to(&it, 0));
+
+ for (size_t i = 1001; i > 0; i--)
+ s_push(s, i - 1);
+
+ it = s_iter_start(s);
+
+ size_t sum = 0;
+ for (size_t i = 0; i < 1001; i++)
+ {
+ s_iter_go_to(&it, i);
+
+ sum += s_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert(s_iter_go_to(&it, i - 1));
+
+ sum += s_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 1000; i > 0; i -= 100)
+ {
+ cmc_assert(s_iter_go_to(&it, 1000 - i));
+ cmc_assert_equals(size_t, i, s_iter_index(&it));
+
+ sum += s_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 5500, sum);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_value(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_end(s);
+
+ cmc_assert_equals(size_t, (size_t){ 0 }, s_iter_value(&it));
+
+ cmc_assert(s_push(s, 10));
+
+ it = s_iter_start(s);
+
+ cmc_assert_equals(size_t, 10, s_iter_value(&it));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rvalue(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ struct stack_iter it = s_iter_end(s);
+
+ cmc_assert_equals(ptr, NULL, s_iter_rvalue(&it));
+
+ cmc_assert(s_push(s, 10));
+
+ it = s_iter_start(s);
+
+ cmc_assert_not_equals(ptr, NULL, s_iter_rvalue(&it));
+ cmc_assert_equals(size_t, 10, *s_iter_rvalue(&it));
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_index(), {
+ struct stack *s = s_new(100, s_fval);
+
+ cmc_assert_not_equals(ptr, NULL, s);
+
+ for (size_t i = 0; i <= 1000; i++)
+ s_push(s, i);
+
+ struct stack_iter it = s_iter_start(s);
+
+ for (size_t i = 0; i < 1001; i++)
+ {
+ cmc_assert_equals(size_t, i, s_iter_index(&it));
+ s_iter_next(&it);
+ }
+
+ it = s_iter_end(s);
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert_equals(size_t, i - 1, s_iter_index(&it));
+ s_iter_prev(&it);
+ }
+
+ s_free(s);
+ });
+});
+
+#ifdef CMC_TEST_MAIN
+int main(void)
+{
+ int result = CMCStack() + CMCStackIter();
+
+ printf(" +---------------------------------------------------------------+");
+ printf("\n");
+ printf(" | CMCStack Suit : %-48s |\n", result == 0 ? "PASSED" : "FAILED");
+ printf(" +---------------------------------------------------------------+");
+ printf("\n\n\n");
+
+ return result;
+}
+#endif
+
+#endif /* CMC_TESTS_UNT_STACK_H */
diff --git a/tests/utl.h b/tests/utl.h
new file mode 100644
index 0000000..2645acd
--- /dev/null
+++ b/tests/utl.h
@@ -0,0 +1,171 @@
+/* Utility file to be included in the unit tests */
+#ifndef CMC_TESTS_UTL
+#define CMC_TESTS_UTL
+
+#include
+#include
+#include
+
+#include "cmc/cor/hashtable.h"
+#include "cmc/utl/assert.h"
+#include "cmc/utl/foreach.h"
+#include "cmc/utl/futils.h"
+#include "cmc/utl/test.h"
+
+size_t numhash(size_t a)
+{
+ return a;
+}
+
+size_t hashcapminus1(size_t a)
+{
+ (void)a;
+ return cmc_hashtable_primes[0] - 1;
+}
+
+size_t hashcapminus4(size_t a)
+{
+ (void)a;
+ return cmc_hashtable_primes[0] - 1;
+}
+
+size_t hash0(size_t a)
+{
+ (void)a;
+ return 0;
+}
+
+// counter ftab functions
+
+int32_t k_total_cmp = 0;
+int32_t k_total_cpy = 0;
+int32_t k_total_str = 0;
+int32_t k_total_free = 0;
+int32_t k_total_hash = 0;
+int32_t k_total_pri = 0;
+
+int32_t v_total_cmp = 0;
+int32_t v_total_cpy = 0;
+int32_t v_total_str = 0;
+int32_t v_total_free = 0;
+int32_t v_total_hash = 0;
+int32_t v_total_pri = 0;
+
+int k_c_cmp(size_t a, size_t b)
+{
+ k_total_cmp++;
+ return (a > b) - (a < b);
+}
+
+size_t k_c_cpy(size_t a)
+{
+ k_total_cpy++;
+ return a;
+}
+
+bool k_c_str(FILE *fptr, size_t a)
+{
+ k_total_str++;
+ return fprintf(fptr, "%" PRIuMAX " ", a) > 0;
+}
+
+void k_c_free(size_t a)
+{
+ (void)a;
+ k_total_free++;
+}
+
+size_t k_c_hash(size_t x)
+{
+ k_total_hash++;
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = (x >> 16) ^ x;
+ return x;
+}
+
+int k_c_pri(size_t a, size_t b)
+{
+ k_total_pri++;
+ return (a > b) - (a < b);
+}
+
+int v_c_cmp(size_t a, size_t b)
+{
+ v_total_cmp++;
+ return (a > b) - (a < b);
+}
+
+size_t v_c_cpy(size_t a)
+{
+ v_total_cpy++;
+ return a;
+}
+
+bool v_c_str(FILE *fptr, size_t a)
+{
+ v_total_str++;
+ return fprintf(fptr, "%" PRIuMAX " ", a) > 0;
+}
+
+void v_c_free(size_t a)
+{
+ (void)a;
+ v_total_free++;
+}
+
+size_t v_c_hash(size_t x)
+{
+ v_total_hash++;
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = (x >> 16) ^ x;
+ return x;
+}
+
+int v_c_pri(size_t a, size_t b)
+{
+ v_total_pri++;
+ return (a > b) - (a < b);
+}
+
+// callbacks
+
+int total_create = 0;
+int total_read = 0;
+int total_update = 0;
+int total_delete = 0;
+int total_resize = 0;
+
+void callback_create(void)
+{
+ total_create++;
+}
+
+void callback_read(void)
+{
+ total_read++;
+}
+
+void callback_update(void)
+{
+ total_update++;
+}
+
+void callback_delete(void)
+{
+ total_delete++;
+}
+
+void callback_resize(void)
+{
+ total_resize++;
+}
+
+struct cmc_callbacks *callbacks = &(struct cmc_callbacks){ .create = callback_create,
+ .read = callback_read,
+ .update = callback_update,
+ .delete = callback_delete,
+ .resize = callback_resize };
+
+#endif /* CMC_TESTS_UTL */