Files
Containers/tst/test_unordered_multiset.c
Bailey Thompson eade6e4586 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.
2020-08-16 19:17:59 -04:00

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();
}