mirror of
https://github.com/bkthomps/Containers.git
synced 2025-11-16 12:34:47 +00:00
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.
405 lines
12 KiB
C
405 lines
12 KiB
C
#include <limits.h>
|
|
#include "test.h"
|
|
#include "../src/include/unordered_multiset.h"
|
|
|
|
static int compare_int(const void *const one, const void *const two)
|
|
{
|
|
const int a = *(int *) one;
|
|
const int b = *(int *) two;
|
|
return a - b;
|
|
}
|
|
|
|
static int hash_count;
|
|
|
|
static unsigned long hash_int(const void *const key)
|
|
{
|
|
unsigned long hash = 17;
|
|
hash_count++;
|
|
hash = 31 * hash + *(int *) key;
|
|
return hash;
|
|
}
|
|
|
|
static unsigned long bad_hash_int()
|
|
{
|
|
return 5;
|
|
}
|
|
|
|
static void test_invalid_init(void)
|
|
{
|
|
assert(!unordered_multiset_init(0, hash_int, compare_int));
|
|
assert(!unordered_multiset_init(sizeof(int), NULL, compare_int));
|
|
assert(!unordered_multiset_init(sizeof(int), hash_int, NULL));
|
|
}
|
|
|
|
static void test_put(unordered_multiset me)
|
|
{
|
|
int val_arr[10] = {5, 9, 4, -5, 0, 6, 1, 5, 7, 2};
|
|
int key;
|
|
int i;
|
|
int j;
|
|
assert(unordered_multiset_size(me) == 0);
|
|
assert(unordered_multiset_is_empty(me));
|
|
key = 4;
|
|
unordered_multiset_put(me, &key);
|
|
assert(unordered_multiset_size(me) == 1);
|
|
unordered_multiset_put(me, &key);
|
|
assert(unordered_multiset_size(me) == 2);
|
|
assert(!unordered_multiset_is_empty(me));
|
|
assert(unordered_multiset_contains(me, &key));
|
|
key = 7;
|
|
assert(!unordered_multiset_contains(me, &key));
|
|
unordered_multiset_put(me, &key);
|
|
assert(unordered_multiset_size(me) == 3);
|
|
assert(unordered_multiset_contains(me, &key));
|
|
unordered_multiset_remove(me, &key);
|
|
assert(unordered_multiset_size(me) == 2);
|
|
assert(!unordered_multiset_contains(me, &key));
|
|
key = 4;
|
|
unordered_multiset_remove(me, &key);
|
|
assert(unordered_multiset_size(me) == 1);
|
|
unordered_multiset_remove(me, &key);
|
|
assert(unordered_multiset_size(me) == 0);
|
|
for (i = 0; i < 10; i++) {
|
|
unordered_multiset_put(me, &val_arr[i]);
|
|
assert(unordered_multiset_contains(me, &val_arr[i]));
|
|
}
|
|
assert(unordered_multiset_size(me) == 10);
|
|
for (i = 0; i < 10; i++) {
|
|
assert(unordered_multiset_contains(me, &val_arr[i]));
|
|
}
|
|
for (i = -100; i < 100; i++) {
|
|
int contains = 0;
|
|
for (j = 0; j < 10; j++) {
|
|
if (val_arr[j] == i) {
|
|
contains = 1;
|
|
}
|
|
}
|
|
assert(unordered_multiset_contains(me, &i) == contains);
|
|
}
|
|
}
|
|
|
|
static void test_remove(unordered_multiset me)
|
|
{
|
|
int num = -3;
|
|
assert(!unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 10);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
num = 6;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 9);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
num = 4;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 8);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
num = 7;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 7);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
num = 9;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 6);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
num = -5;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 5);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
num = 0;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 4);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
num = 1;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 3);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
num = 5;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 2);
|
|
assert(unordered_multiset_contains(me, &num));
|
|
num = 2;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 1);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
num = 5;
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 0);
|
|
assert(!unordered_multiset_contains(me, &num));
|
|
}
|
|
|
|
static void test_stress_remove(unordered_multiset me)
|
|
{
|
|
int i;
|
|
for (i = 4000; i < 6000; i++) {
|
|
unordered_multiset_put(me, &i);
|
|
assert(unordered_multiset_contains(me, &i));
|
|
}
|
|
assert(unordered_multiset_size(me) == 2000);
|
|
for (i = 4000; i < 6000; i++) {
|
|
unordered_multiset_remove(me, &i);
|
|
assert(!unordered_multiset_contains(me, &i));
|
|
}
|
|
assert(unordered_multiset_size(me) == 0);
|
|
assert(unordered_multiset_is_empty(me));
|
|
unordered_multiset_clear(me);
|
|
assert(unordered_multiset_size(me) == 0);
|
|
assert(unordered_multiset_is_empty(me));
|
|
}
|
|
|
|
static void test_stress_clear(unordered_multiset me)
|
|
{
|
|
int key;
|
|
int i;
|
|
for (i = 5000; i < 6000; i++) {
|
|
unordered_multiset_put(me, &i);
|
|
assert(unordered_multiset_contains(me, &i));
|
|
}
|
|
assert(unordered_multiset_size(me) == 1000);
|
|
hash_count = 0;
|
|
unordered_multiset_rehash(me);
|
|
assert(hash_count == 1000);
|
|
unordered_multiset_clear(me);
|
|
key = 0xfacade;
|
|
assert(!unordered_multiset_remove(me, &key));
|
|
assert(unordered_multiset_size(me) == 0);
|
|
assert(unordered_multiset_is_empty(me));
|
|
key = 5;
|
|
unordered_multiset_put(me, &key);
|
|
assert(unordered_multiset_size(me) == 1);
|
|
key = 7;
|
|
for (i = 0; i < 10; i++) {
|
|
unordered_multiset_put(me, &key);
|
|
}
|
|
assert(unordered_multiset_size(me) == 11);
|
|
unordered_multiset_remove_all(me, &key);
|
|
assert(unordered_multiset_size(me) == 1);
|
|
}
|
|
|
|
static void test_basic(void)
|
|
{
|
|
unordered_multiset me = unordered_multiset_init(sizeof(int), hash_int,
|
|
compare_int);
|
|
assert(me);
|
|
test_put(me);
|
|
test_remove(me);
|
|
test_stress_remove(me);
|
|
test_stress_clear(me);
|
|
assert(!unordered_multiset_destroy(me));
|
|
}
|
|
|
|
static void test_bad_hash(void)
|
|
{
|
|
int i;
|
|
int num;
|
|
unordered_multiset me = unordered_multiset_init(sizeof(int), bad_hash_int,
|
|
compare_int);
|
|
assert(me);
|
|
num = 1;
|
|
unordered_multiset_put(me, &num);
|
|
num = 2;
|
|
unordered_multiset_put(me, &num);
|
|
num = 3;
|
|
unordered_multiset_put(me, &num);
|
|
assert(unordered_multiset_size(me) == 3);
|
|
unordered_multiset_put(me, &num);
|
|
assert(unordered_multiset_size(me) == 4);
|
|
num = 4;
|
|
unordered_multiset_put(me, &num);
|
|
assert(unordered_multiset_size(me) == 5);
|
|
assert(unordered_multiset_remove(me, &num));
|
|
assert(!unordered_multiset_remove(me, &num));
|
|
assert(unordered_multiset_size(me) == 4);
|
|
unordered_multiset_rehash(me);
|
|
assert(unordered_multiset_size(me) == 4);
|
|
for (i = 3; i > 0; i--) {
|
|
assert(unordered_multiset_remove(me, &i));
|
|
}
|
|
assert(!unordered_multiset_destroy(me));
|
|
}
|
|
|
|
static void test_collision(void)
|
|
{
|
|
int num;
|
|
unordered_multiset me = unordered_multiset_init(sizeof(int), bad_hash_int,
|
|
compare_int);
|
|
assert(me);
|
|
num = 1;
|
|
unordered_multiset_put(me, &num);
|
|
num = 2;
|
|
unordered_multiset_put(me, &num);
|
|
num = 3;
|
|
unordered_multiset_put(me, &num);
|
|
assert(unordered_multiset_size(me) == 3);
|
|
unordered_multiset_put(me, &num);
|
|
assert(unordered_multiset_size(me) == 4);
|
|
num = 4;
|
|
unordered_multiset_put(me, &num);
|
|
assert(unordered_multiset_size(me) == 5);
|
|
assert(unordered_multiset_remove_all(me, &num));
|
|
assert(!unordered_multiset_remove_all(me, &num));
|
|
assert(unordered_multiset_size(me) == 4);
|
|
unordered_multiset_rehash(me);
|
|
assert(unordered_multiset_size(me) == 4);
|
|
unordered_multiset_clear(me);
|
|
assert(unordered_multiset_size(me) == 0);
|
|
assert(!unordered_multiset_remove_all(me, &num));
|
|
assert(unordered_multiset_size(me) == 0);
|
|
assert(!unordered_multiset_destroy(me));
|
|
}
|
|
|
|
#if STUB_MALLOC
|
|
static void test_init_out_of_memory(void)
|
|
{
|
|
fail_malloc = 1;
|
|
assert(!unordered_multiset_init(sizeof(int), hash_int, compare_int));
|
|
fail_calloc = 1;
|
|
assert(!unordered_multiset_init(sizeof(int), hash_int, compare_int));
|
|
}
|
|
#endif
|
|
|
|
#if STUB_MALLOC
|
|
static void test_rehash_out_of_memory(void)
|
|
{
|
|
int key = 5;
|
|
unordered_multiset me = unordered_multiset_init(sizeof(int), hash_int,
|
|
compare_int);
|
|
assert(me);
|
|
unordered_multiset_put(me, &key);
|
|
assert(unordered_multiset_size(me) == 1);
|
|
assert(unordered_multiset_contains(me, &key));
|
|
fail_calloc = 1;
|
|
assert(unordered_multiset_rehash(me) == -ENOMEM);
|
|
assert(unordered_multiset_size(me) == 1);
|
|
assert(unordered_multiset_contains(me, &key));
|
|
assert(!unordered_multiset_destroy(me));
|
|
}
|
|
#endif
|
|
|
|
#if STUB_MALLOC
|
|
static void test_put_out_of_memory(void)
|
|
{
|
|
int key = 5;
|
|
unordered_multiset me = unordered_multiset_init(sizeof(int), bad_hash_int,
|
|
compare_int);
|
|
assert(me);
|
|
fail_malloc = 1;
|
|
assert(unordered_multiset_put(me, &key) == -ENOMEM);
|
|
fail_malloc = 1;
|
|
assert(unordered_multiset_put(me, &key) == -ENOMEM);
|
|
assert(unordered_multiset_put(me, &key) == 0);
|
|
key = 7;
|
|
fail_malloc = 1;
|
|
assert(unordered_multiset_put(me, &key) == -ENOMEM);
|
|
fail_malloc = 1;
|
|
assert(unordered_multiset_put(me, &key) == -ENOMEM);
|
|
assert(!unordered_multiset_destroy(me));
|
|
}
|
|
#endif
|
|
|
|
#if STUB_MALLOC
|
|
static void test_resize_out_of_memory(void)
|
|
{
|
|
int i;
|
|
unordered_multiset me = unordered_multiset_init(sizeof(int), hash_int,
|
|
compare_int);
|
|
for (i = 0; i < 11; i++) {
|
|
assert(unordered_multiset_put(me, &i) == 0);
|
|
}
|
|
assert(unordered_multiset_size(me) == 11);
|
|
i++;
|
|
fail_calloc = 1;
|
|
assert(unordered_multiset_put(me, &i) == -ENOMEM);
|
|
assert(unordered_multiset_size(me) == 11);
|
|
for (i = 0; i < 11; i++) {
|
|
assert(unordered_multiset_contains(me, &i));
|
|
}
|
|
assert(!unordered_multiset_destroy(me));
|
|
}
|
|
#endif
|
|
|
|
#if STUB_MALLOC
|
|
static void test_clear_out_of_memory(void)
|
|
{
|
|
int key = 5;
|
|
unordered_multiset me = unordered_multiset_init(sizeof(int), hash_int,
|
|
compare_int);
|
|
assert(me);
|
|
assert(unordered_multiset_put(me, &key) == 0);
|
|
assert(unordered_multiset_size(me) == 1);
|
|
assert(unordered_multiset_contains(me, &key));
|
|
fail_calloc = 1;
|
|
assert(unordered_multiset_clear(me) == -ENOMEM);
|
|
assert(unordered_multiset_size(me) == 1);
|
|
assert(unordered_multiset_contains(me, &key));
|
|
assert(!unordered_multiset_destroy(me));
|
|
}
|
|
#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();
|
|
test_basic();
|
|
test_bad_hash();
|
|
test_collision();
|
|
#if STUB_MALLOC
|
|
test_init_out_of_memory();
|
|
test_rehash_out_of_memory();
|
|
test_put_out_of_memory();
|
|
test_resize_out_of_memory();
|
|
test_clear_out_of_memory();
|
|
#endif
|
|
test_big_object();
|
|
}
|