From eade6e458693e1a8ae0becf716e413b32fb32bd0 Mon Sep 17 00:00:00 2001 From: Bailey Thompson Date: Sun, 16 Aug 2020 19:17:59 -0400 Subject: [PATCH] Bug bash (#105) Valgrind previously did not fail the test suite when there were memory leaks or invalid accesses. Due to this, a few bugs slipped in. These bugs have been fixed, and now every container has more test cases. Furthermore, the test suite has been updated to fail if Valgrind reports any errors. --- .github/workflows/build.yml | 3 +- Makefile | 3 +- src/multimap.c | 9 +++--- src/unordered_map.c | 3 +- src/unordered_multimap.c | 5 +-- src/unordered_multiset.c | 1 + src/unordered_set.c | 1 + tst/test_array.c | 41 ++++++++++++++++++++++++ tst/test_deque.c | 41 ++++++++++++++++++++++++ tst/test_forward_list.c | 42 +++++++++++++++++++++++++ tst/test_list.c | 42 +++++++++++++++++++++++++ tst/test_map.c | 49 +++++++++++++++++++++++++++++ tst/test_multimap.c | 56 +++++++++++++++++++++++++++++++++ tst/test_multiset.c | 53 +++++++++++++++++++++++++++++++ tst/test_priority_queue.c | 50 +++++++++++++++++++++++++++++ tst/test_queue.c | 41 ++++++++++++++++++++++++ tst/test_set.c | 53 +++++++++++++++++++++++++++++++ tst/test_stack.c | 41 ++++++++++++++++++++++++ tst/test_unordered_map.c | 50 +++++++++++++++++++++++++++++ tst/test_unordered_multimap.c | 59 +++++++++++++++++++++++++++++++++++ tst/test_unordered_multiset.c | 55 ++++++++++++++++++++++++++++++++ tst/test_unordered_set.c | 54 ++++++++++++++++++++++++++++++++ tst/test_vector.c | 42 +++++++++++++++++++++++++ 23 files changed, 783 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ff68483..89e97bc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,4 +25,5 @@ jobs: steps: - uses: actions/checkout@v2 - run: sudo apt install -y valgrind - - run: make valgrind + - run: make test_valgrind + - run: valgrind --leak-check=full --error-exitcode=1 ./ContainersTestValgrind diff --git a/Makefile b/Makefile index bcb032a..4afaa4f 100644 --- a/Makefile +++ b/Makefile @@ -31,8 +31,7 @@ test_optimized: test_coverage: @gcc src/*.c tst/*.c -Wall -Wextra -Wpedantic -Werror -std=c89 -O0 -ldl -g -coverage -o ContainersTestCoverage -valgrind: +test_valgrind: @sed -i 's/STUB_MALLOC 1/STUB_MALLOC 0/g' tst/test.h @gcc src/*.c tst/*.c -Wall -Wextra -Wpedantic -Werror -std=c89 -O0 -o ContainersTestValgrind @sed -i 's/STUB_MALLOC 0/STUB_MALLOC 1/g' tst/test.h - @valgrind --leak-check=full ./ContainersTestValgrind diff --git a/src/multimap.c b/src/multimap.c index 0c13a31..0334a95 100644 --- a/src/multimap.c +++ b/src/multimap.c @@ -306,7 +306,7 @@ static void multimap_insert_balance(multimap me, char *const item) */ static char *multimap_create_value_node(multimap me, const void *const value) { - char *const add = malloc(sizeof(char *) + me->value_size); + char *const add = malloc(ptr_size + me->value_size); if (!add) { return NULL; } @@ -321,8 +321,7 @@ static char *multimap_create_value_node(multimap me, const void *const value) static char *multimap_create_node(multimap me, const void *const key, const void *const value, char *const parent) { - const size_t size = 1 + sizeof(size_t) + 4 * sizeof(char *) + me->key_size; - char *const insert = malloc(size); + char *const insert = malloc(1 + count_size + 4 * ptr_size + me->key_size); const size_t one = 1; char *value_node; if (!insert) { @@ -495,7 +494,7 @@ void multimap_get_start(multimap me, void *const key) * @param value the value to be copied to from iteration * @param me the multi-map to iterate over * - * @return 1 if there exist no more values for the key which is being iterated + * @return 1 if there exist more values for the key which is being iterated * over, otherwise 0 */ int multimap_get_next(void *const value, multimap me) @@ -836,7 +835,7 @@ int multimap_remove(multimap me, void *const key, void *const value) if (me->value_comparator(current_value_node + value_node_value_offset, value) == 0) { memcpy(traverse + node_value_head_offset, - current_value_node + node_value_head_offset, ptr_size); + current_value_node + value_node_next_offset, ptr_size); } else { char *previous_value_node = current_value_node; memcpy(¤t_value_node, current_value_node + value_node_next_offset, diff --git a/src/unordered_map.c b/src/unordered_map.c index 684d694..c9b23ac 100644 --- a/src/unordered_map.c +++ b/src/unordered_map.c @@ -234,7 +234,7 @@ static char *unordered_map_create_element(unordered_map me, const void *const key, const void *const value) { - char *init = malloc(ptr_size + hash_size + me->key_size); + char *init = malloc(ptr_size + hash_size + me->key_size + me->value_size); if (!init) { return NULL; } @@ -425,6 +425,7 @@ int unordered_map_clear(unordered_map me) free(backup); } } + free(me->buckets); me->size = 0; me->capacity = STARTING_BUCKETS; me->buckets = updated_buckets; diff --git a/src/unordered_multimap.c b/src/unordered_multimap.c index 951c431..bde3047 100644 --- a/src/unordered_multimap.c +++ b/src/unordered_multimap.c @@ -253,7 +253,7 @@ static char *unordered_multimap_create_element(unordered_multimap me, const void *const key, const void *const value) { - char *init = malloc(ptr_size + hash_size + me->key_size); + char *init = malloc(ptr_size + hash_size + me->key_size + me->value_size); if (!init) { return NULL; } @@ -356,7 +356,7 @@ void unordered_multimap_get_start(unordered_multimap me, void *const key) * @param value the value to be copied to from iteration * @param me the unordered multi-map to iterate over * - * @return 1 if there exist no more values for the key which is being iterated + * @return 1 if there exist more values for the key which is being iterated * over, otherwise 0 */ int unordered_multimap_get_next(void *const value, unordered_multimap me) @@ -559,6 +559,7 @@ int unordered_multimap_clear(unordered_multimap me) free(backup); } } + free(me->buckets); me->size = 0; me->capacity = STARTING_BUCKETS; me->buckets = updated_buckets; diff --git a/src/unordered_multiset.c b/src/unordered_multiset.c index d9e4bd2..052317b 100644 --- a/src/unordered_multiset.c +++ b/src/unordered_multiset.c @@ -483,6 +483,7 @@ int unordered_multiset_clear(unordered_multiset me) free(backup); } } + free(me->buckets); me->size = 0; me->capacity = STARTING_BUCKETS; me->used = 0; diff --git a/src/unordered_set.c b/src/unordered_set.c index aa8da93..50a2276 100644 --- a/src/unordered_set.c +++ b/src/unordered_set.c @@ -381,6 +381,7 @@ int unordered_set_clear(unordered_set me) free(backup); } } + free(me->buckets); me->size = 0; me->capacity = STARTING_BUCKETS; me->buckets = updated_buckets; diff --git a/tst/test_array.c b/tst/test_array.c index 5f4c317..0de7cab 100644 --- a/tst/test_array.c +++ b/tst/test_array.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/array.h" @@ -85,6 +86,45 @@ static void test_init_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static void test_big_object(void) +{ + int i; + array me = array_init(16, sizeof(struct big_object)); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(array_set(me, i, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + assert(array_get(&b, me, i) == 0); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!array_destroy(me)); +} + void test_array(void) { test_invalid_init(); @@ -93,4 +133,5 @@ void test_array(void) #if STUB_MALLOC test_init_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_deque.c b/tst/test_deque.c index 5110b4a..8f1dc0c 100644 --- a/tst/test_deque.c +++ b/tst/test_deque.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/deque.h" @@ -420,6 +421,45 @@ static int test_puzzle(int start_node, int dest_node) return -1; } +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static void test_big_object(void) +{ + int i; + deque me = deque_init(sizeof(struct big_object)); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(deque_push_front(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + assert(deque_pop_back(&b, me) == 0); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!deque_destroy(me)); +} + void test_deque(void) { test_invalid_init(); @@ -440,4 +480,5 @@ void test_deque(void) test_single_full_block(); assert(test_puzzle(2, 5) == 4); assert(test_puzzle(2, 10) == 5); + test_big_object(); } diff --git a/tst/test_forward_list.c b/tst/test_forward_list.c index f0dedeb..e572c71 100644 --- a/tst/test_forward_list.c +++ b/tst/test_forward_list.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/forward_list.h" @@ -342,6 +343,46 @@ static int test_puzzle_backwards(int start_node, int dest_node) return -1; } +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static void test_big_object(void) +{ + int i; + forward_list me = forward_list_init(sizeof(struct big_object)); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(forward_list_add_first(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + assert(forward_list_get_last(&b, me) == 0); + assert(forward_list_remove_last(me) == 0); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!forward_list_destroy(me)); +} + void test_forward_list(void) { test_invalid_init(); @@ -357,4 +398,5 @@ void test_forward_list(void) assert(test_puzzle_forwards(2, 10) == 5); assert(test_puzzle_backwards(2, 5) == 4); assert(test_puzzle_backwards(2, 10) == 5); + test_big_object(); } diff --git a/tst/test_list.c b/tst/test_list.c index 762d9b6..a2867c1 100644 --- a/tst/test_list.c +++ b/tst/test_list.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/list.h" @@ -335,6 +336,46 @@ static int test_puzzle_backwards(int start_node, int dest_node) return -1; } +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static void test_big_object(void) +{ + int i; + list me = list_init(sizeof(struct big_object)); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(list_add_first(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + assert(list_get_last(&b, me) == 0); + assert(list_remove_last(me) == 0); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!list_destroy(me)); +} + void test_list(void) { test_invalid_init(); @@ -350,4 +391,5 @@ void test_list(void) assert(test_puzzle_forwards(2, 10) == 5); assert(test_puzzle_backwards(2, 5) == 4); assert(test_puzzle_backwards(2, 10) == 5); + test_big_object(); } diff --git a/tst/test_map.c b/tst/test_map.c index 483494c..3a9b424 100644 --- a/tst/test_map.c +++ b/tst/test_map.c @@ -1,3 +1,4 @@ +#include #include #include "test.h" #include "../src/include/map.h" @@ -552,6 +553,53 @@ static void test_put_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static int compare_big_object(const void *const one, const void *const two) +{ + const struct big_object *const a = one; + const struct big_object *const b = two; + return a->n - b->n; +} + +static void test_big_object(void) +{ + int i; + map me = map_init(sizeof(int), sizeof(struct big_object), + compare_big_object); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(map_put(me, &i, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + assert(map_get(&b, me, &i) == 1); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!map_destroy(me)); +} + void test_map(void) { test_invalid_init(); @@ -567,4 +615,5 @@ void test_map(void) test_init_out_of_memory(); test_put_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_multimap.c b/tst/test_multimap.c index 2fd1332..85b0503 100644 --- a/tst/test_multimap.c +++ b/tst/test_multimap.c @@ -1,3 +1,4 @@ +#include #include #include "test.h" #include "../src/include/multimap.h" @@ -617,6 +618,60 @@ static void test_put_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static int compare_big_object(const void *const one, const void *const two) +{ + const struct big_object *const a = one; + const struct big_object *const b = two; + return a->n - b->n; +} + +static int compare_dummy() +{ + assert(0); +} + +static void test_big_object(void) +{ + int i; + multimap me = multimap_init(sizeof(int), sizeof(struct big_object), + compare_big_object, compare_dummy); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(multimap_put(me, &i, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + multimap_get_start(me, &i); + assert(multimap_get_next(&b, me) == 1); + assert(multimap_get_next(&b, me) == 0); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!multimap_destroy(me)); +} + void test_multimap(void) { test_invalid_init(); @@ -633,4 +688,5 @@ void test_multimap(void) test_init_out_of_memory(); test_put_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_multiset.c b/tst/test_multiset.c index 0436497..7993c78 100644 --- a/tst/test_multiset.c +++ b/tst/test_multiset.c @@ -1,3 +1,4 @@ +#include #include #include "test.h" #include "../src/include/multiset.h" @@ -553,6 +554,57 @@ static void test_put_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static int compare_big_object(const void *const one, const void *const two) +{ + const struct big_object *const a = one; + const struct big_object *const b = two; + return a->n - b->n; +} + +static void test_big_object(void) +{ + int i; + multiset me = multiset_init(sizeof(struct big_object), compare_big_object); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(multiset_put(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(multiset_contains(me, &b) == 1); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!multiset_destroy(me)); +} + void test_multiset(void) { test_invalid_init(); @@ -568,4 +620,5 @@ void test_multiset(void) test_init_out_of_memory(); test_put_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_priority_queue.c b/tst/test_priority_queue.c index ae64a30..3a8e117 100644 --- a/tst/test_priority_queue.c +++ b/tst/test_priority_queue.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/vector.h" #include "../src/include/priority_queue.h" @@ -182,6 +183,54 @@ static void test_push_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static int compare_big_object(const void *const one, const void *const two) +{ + const struct big_object *const a = one; + const struct big_object *const b = two; + /* Bigger number = lower priority */ + return b->n - a->n; +} + +static void test_big_object(void) +{ + int i; + priority_queue me = priority_queue_init(sizeof(struct big_object), + compare_big_object); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(priority_queue_push(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + assert(priority_queue_pop(&b, me) == 1); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!priority_queue_destroy(me)); +} + void test_priority_queue(void) { test_invalid_init(); @@ -190,4 +239,5 @@ void test_priority_queue(void) test_init_out_of_memory(); test_push_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_queue.c b/tst/test_queue.c index d30cf85..df196c7 100644 --- a/tst/test_queue.c +++ b/tst/test_queue.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/queue.h" @@ -140,6 +141,45 @@ static int test_puzzle(int start_node, int dest_node) return -1; } +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static void test_big_object(void) +{ + int i; + queue me = queue_init(sizeof(struct big_object)); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(queue_push(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + assert(queue_pop(&b, me) == 1); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!queue_destroy(me)); +} + void test_queue(void) { test_invalid_init(); @@ -148,4 +188,5 @@ void test_queue(void) test_automated_trim(); assert(test_puzzle(2, 5) == 4); assert(test_puzzle(2, 10) == 5); + test_big_object(); } diff --git a/tst/test_set.c b/tst/test_set.c index 6bdc830..87df060 100644 --- a/tst/test_set.c +++ b/tst/test_set.c @@ -1,3 +1,4 @@ +#include #include #include "test.h" #include "../src/include/set.h" @@ -522,6 +523,57 @@ static void test_put_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static int compare_big_object(const void *const one, const void *const two) +{ + const struct big_object *const a = one; + const struct big_object *const b = two; + return a->n - b->n; +} + +static void test_big_object(void) +{ + int i; + set me = set_init(sizeof(struct big_object), compare_big_object); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(set_put(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(set_contains(me, &b) == 1); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!set_destroy(me)); +} + void test_set(void) { test_invalid_init(); @@ -536,4 +588,5 @@ void test_set(void) test_init_out_of_memory(); test_put_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_stack.c b/tst/test_stack.c index f0c37b6..804058e 100644 --- a/tst/test_stack.c +++ b/tst/test_stack.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/stack.h" @@ -67,9 +68,49 @@ static void test_automated_trim(void) assert(!stack_destroy(me)); } +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static void test_big_object(void) +{ + int i; + stack me = stack_init(sizeof(struct big_object)); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(stack_push(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 15; i >= 0; i--) { + int j; + struct big_object b; + assert(stack_pop(&b, me) == 1); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!stack_destroy(me)); +} + void test_stack(void) { test_invalid_init(); test_basic(); test_automated_trim(); + test_big_object(); } diff --git a/tst/test_unordered_map.c b/tst/test_unordered_map.c index aca644a..7b1ab24 100644 --- a/tst/test_unordered_map.c +++ b/tst/test_unordered_map.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/unordered_map.h" @@ -291,6 +292,54 @@ static void test_clear_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static int compare_big_object(const void *const one, const void *const two) +{ + const struct big_object *const a = one; + const struct big_object *const b = two; + return a->n - b->n; +} + +static void test_big_object(void) +{ + int i; + unordered_map me = unordered_map_init(sizeof(int), + sizeof(struct big_object), + bad_hash_int, compare_big_object); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(unordered_map_put(me, &i, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + assert(unordered_map_get(&b, me, &i) == 1); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!unordered_map_destroy(me)); +} + void test_unordered_map(void) { test_invalid_init(); @@ -303,4 +352,5 @@ void test_unordered_map(void) test_resize_out_of_memory(); test_clear_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_unordered_multimap.c b/tst/test_unordered_multimap.c index 222457d..483233f 100644 --- a/tst/test_unordered_multimap.c +++ b/tst/test_unordered_multimap.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/unordered_multimap.h" @@ -401,6 +402,63 @@ static void test_clear_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static int compare_big_object(const void *const one, const void *const two) +{ + const struct big_object *const a = one; + const struct big_object *const b = two; + return a->n - b->n; +} + +static int compare_dummy() +{ + assert(0); +} + +static void test_big_object(void) +{ + int i; + unordered_multimap me = unordered_multimap_init(sizeof(int), + sizeof(struct big_object), + bad_hash_int, + compare_big_object, + compare_dummy); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(unordered_multimap_put(me, &i, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + unordered_multimap_get_start(me, &i); + assert(unordered_multimap_get_next(&b, me) == 1); + assert(unordered_multimap_get_next(&b, me) == 0); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!unordered_multimap_destroy(me)); +} + void test_unordered_multimap(void) { test_invalid_init(); @@ -415,4 +473,5 @@ void test_unordered_multimap(void) test_resize_out_of_memory(); test_clear_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_unordered_multiset.c b/tst/test_unordered_multiset.c index 8c4bb62..3016d0b 100644 --- a/tst/test_unordered_multiset.c +++ b/tst/test_unordered_multiset.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/unordered_multiset.h" @@ -333,6 +334,59 @@ static void test_clear_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static int compare_big_object(const void *const one, const void *const two) +{ + const struct big_object *const a = one; + const struct big_object *const b = two; + return a->n - b->n; +} + +static void test_big_object(void) +{ + int i; + unordered_multiset me = unordered_multiset_init(sizeof(struct big_object), + bad_hash_int, + compare_big_object); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(unordered_multiset_put(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(unordered_multiset_contains(me, &b) == 1); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!unordered_multiset_destroy(me)); +} + void test_unordered_multiset(void) { test_invalid_init(); @@ -346,4 +400,5 @@ void test_unordered_multiset(void) test_resize_out_of_memory(); test_clear_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_unordered_set.c b/tst/test_unordered_set.c index f8d88cc..1049ff1 100644 --- a/tst/test_unordered_set.c +++ b/tst/test_unordered_set.c @@ -1,3 +1,4 @@ +#include #include "test.h" #include "../src/include/unordered_set.h" @@ -275,6 +276,58 @@ static void test_clear_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static int compare_big_object(const void *const one, const void *const two) +{ + const struct big_object *const a = one; + const struct big_object *const b = two; + return a->n - b->n; +} + +static void test_big_object(void) +{ + int i; + unordered_set me = unordered_set_init(sizeof(struct big_object), + bad_hash_int, compare_big_object); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(unordered_set_put(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(unordered_set_contains(me, &b) == 1); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!unordered_set_destroy(me)); +} + void test_unordered_set(void) { test_invalid_init(); @@ -287,4 +340,5 @@ void test_unordered_set(void) test_resize_out_of_memory(); test_clear_out_of_memory(); #endif + test_big_object(); } diff --git a/tst/test_vector.c b/tst/test_vector.c index 185c73c..309babd 100644 --- a/tst/test_vector.c +++ b/tst/test_vector.c @@ -1,3 +1,4 @@ +#include #include #include "test.h" #include "../src/include/vector.h" @@ -272,6 +273,46 @@ static void test_add_out_of_memory(void) } #endif +struct big_object { + int n; + double d; + signed char c[8]; +}; + +static void test_big_object(void) +{ + int i; + vector me = vector_init(sizeof(struct big_object)); + assert(me); + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + b.n = INT_MIN + i; + b.d = i + 0.5; + for (j = 0; j < 8; j++) { + b.c[j] = (signed char) (SCHAR_MIN + i + j); + } + assert(vector_add_first(me, &b) == 0); + b.n = -1; + b.d = -1; + for (j = 0; j < 8; j++) { + b.c[j] = -1; + } + } + for (i = 0; i < 16; i++) { + int j; + struct big_object b; + assert(vector_get_last(&b, me) == 0); + assert(vector_remove_last(me) == 0); + assert(b.n == INT_MIN + i); + assert(b.d == i + 0.5); + for (j = 0; j < 8; j++) { + assert(b.c[j] == SCHAR_MIN + i + j); + } + } + assert(!vector_destroy(me)); +} + void test_vector(void) { test_invalid_init(); @@ -283,4 +324,5 @@ void test_vector(void) test_set_space_out_of_memory(); test_add_out_of_memory(); #endif + test_big_object(); }