500 lines
12 KiB
C
500 lines
12 KiB
C
#include <collections.h>
|
|
#include <stdlib.h>
|
|
|
|
static
|
|
uint64_t* generate_keys(
|
|
int count)
|
|
{
|
|
uint64_t *keys = ecs_os_malloc_n(uint64_t, count);
|
|
for (int i = 0; i < count; i ++) {
|
|
keys[i] = i + 1;
|
|
}
|
|
return keys;
|
|
}
|
|
|
|
static
|
|
uint64_t* generate_random_keys(
|
|
int count)
|
|
{
|
|
uint64_t *keys = ecs_os_malloc_n(uint64_t, count);
|
|
for (int i = 0; i < count; i ++) {
|
|
uint64_t key;
|
|
int j = 0;
|
|
do {
|
|
key = rand() % RAND_MAX;
|
|
if (rand() % 2) {
|
|
key = ecs_pair(key, rand() % RAND_MAX);
|
|
}
|
|
|
|
for (j = 0; j < i; j ++) {
|
|
if (keys[j] == key) {
|
|
break;
|
|
}
|
|
}
|
|
} while (j != i); /* no duplicate keys */
|
|
keys[i] = key;
|
|
}
|
|
|
|
return keys;
|
|
}
|
|
|
|
static
|
|
void insert_map(
|
|
ecs_map_t *map,
|
|
uint64_t *keys,
|
|
int count)
|
|
{
|
|
for (int i = 0; i < count; i ++) {
|
|
for (int j = 0; j < i; j ++) {
|
|
uint64_t *v = ecs_map_get(map, keys[j]);
|
|
test_assert(v != NULL);
|
|
test_assert(v[0] == keys[j]);
|
|
}
|
|
|
|
test_assert(ecs_map_count(map) == i);
|
|
test_assert(ecs_map_get(map, keys[i]) == NULL);
|
|
ecs_map_insert(map, keys[i], keys[i]);
|
|
test_assert(ecs_map_get(map, keys[i])[0] == keys[i]);
|
|
test_assert(ecs_map_count(map) == (i + 1));
|
|
}
|
|
}
|
|
|
|
static
|
|
ecs_map_t populate_map(
|
|
uint64_t *keys,
|
|
int count)
|
|
{
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
insert_map(&map, keys, count);
|
|
return map;
|
|
}
|
|
|
|
static
|
|
void free_map(
|
|
ecs_map_t *map,
|
|
uint64_t *keys,
|
|
int count)
|
|
{
|
|
for (int i = 0; i < count; i ++) {
|
|
for (int j = i; j < count; j ++) {
|
|
uint64_t *v = ecs_map_get(map, keys[j]);
|
|
test_assert(v != NULL);
|
|
test_assert(v[0] == keys[j]);
|
|
}
|
|
|
|
test_assert(ecs_map_count(map) == (count - i));
|
|
test_assert(ecs_map_get(map, keys[i]) != NULL);
|
|
ecs_map_remove(map, keys[i]);
|
|
test_assert(ecs_map_count(map) == ((count - i) - 1));
|
|
test_assert(ecs_map_get(map, keys[i]) == NULL);
|
|
}
|
|
}
|
|
|
|
static int32_t malloc_count;
|
|
|
|
static
|
|
void *test_malloc(ecs_size_t size) {
|
|
malloc_count ++;
|
|
return malloc(size);
|
|
}
|
|
|
|
static
|
|
void *test_calloc(ecs_size_t size) {
|
|
malloc_count ++;
|
|
return calloc(1, size);
|
|
}
|
|
|
|
static
|
|
void *test_realloc(void *old_ptr, ecs_size_t size) {
|
|
malloc_count ++;
|
|
return realloc(old_ptr, size);
|
|
}
|
|
|
|
|
|
void Map_setup(void) {
|
|
ecs_os_set_api_defaults();
|
|
ecs_os_api_t os_api = ecs_os_api;
|
|
os_api.malloc_ = test_malloc;
|
|
os_api.calloc_ = test_calloc;
|
|
os_api.realloc_ = test_realloc;
|
|
ecs_os_set_api(&os_api);
|
|
}
|
|
|
|
void Map_count(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
test_int(ecs_map_count(&map), 4);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_count_empty(void) {
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
test_int(ecs_map_count(&map), 0);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_set_overwrite(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
uint64_t *val = ecs_map_get(&map, 1);
|
|
test_int(*val, 1);
|
|
|
|
uint64_t *el = ecs_map_ensure(&map, 1);
|
|
test_assert(val == el);
|
|
test_int(ecs_map_count(&map), 4);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_set_rehash(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
test_int(map.bucket_count, 4);
|
|
|
|
int i;
|
|
for (i = 5; i < 16; i ++) {
|
|
uint64_t *ptr = ecs_map_ensure(&map, i);
|
|
*ptr = i;
|
|
}
|
|
|
|
test_int(map.bucket_count, 32);
|
|
for (i = 1; i < 16; i ++) {
|
|
test_int(ecs_map_get(&map, i)[0], i);
|
|
}
|
|
|
|
for (i = 1; i < 8; i ++) {
|
|
uint64_t *ptr = ecs_map_ensure(&map, i + 1000000);
|
|
*ptr = i + 1000000;
|
|
}
|
|
|
|
test_int(map.bucket_count, 32);
|
|
for (i = 1; i < 16; i ++) {
|
|
test_int(ecs_map_get(&map, i)[0], i);
|
|
}
|
|
for (i = 1; i < 8; i ++) {
|
|
test_int(ecs_map_get(&map, i + 1000000)[0], i + 1000000);
|
|
}
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_get(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
uint64_t *value = ecs_map_get(&map, 1);
|
|
test_assert(value != NULL);
|
|
test_int(value[0], 1);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_get_all(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
uint64_t *value = ecs_map_get(&map, 1);
|
|
test_assert(value != NULL);
|
|
test_int(*value, 1);
|
|
|
|
value = ecs_map_get(&map, 2);
|
|
test_assert(value != NULL);
|
|
test_int(*value, 2);
|
|
|
|
value = ecs_map_get(&map, 3);
|
|
test_assert(value != NULL);
|
|
test_int(*value, 3);
|
|
|
|
value = ecs_map_get(&map, 4);
|
|
test_assert(value != NULL);
|
|
test_int(*value, 4);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_get_empty(void) {
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
uint64_t *value = ecs_map_get(&map, 1);
|
|
test_assert(value == NULL);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_get_unknown(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
uint64_t *value = ecs_map_get(&map, 5);
|
|
test_assert(value == NULL);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_get_0_from_empty(void) {
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
uint64_t *value = ecs_map_get(&map, 0);
|
|
test_assert(value == NULL);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_get_0_from_populated(void) {
|
|
uint64_t *keys = generate_keys(32);
|
|
ecs_map_t map = populate_map(keys, 32);
|
|
|
|
uint64_t *value = ecs_map_get(&map, 0);
|
|
test_assert(value == NULL);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_get_0_after_insert(void) {
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
ecs_map_insert(&map, 0, 10);
|
|
uint64_t *value = ecs_map_get(&map, 0);
|
|
test_assert(value != NULL);
|
|
test_int(value[0], 10);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_get_0_after_ensure(void) {
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
ecs_map_ensure(&map, 0)[0] = 10;
|
|
uint64_t *value = ecs_map_get(&map, 0);
|
|
test_assert(value != NULL);
|
|
test_int(value[0], 10);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_iter(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
int i = 0;
|
|
ecs_map_iter_t it = ecs_map_iter(&map);
|
|
while (ecs_map_next(&it)) {
|
|
ecs_map_key_t key = ecs_map_key(&it);
|
|
uint64_t val = ecs_map_value(&it);
|
|
test_assert(key == val);
|
|
i ++;
|
|
}
|
|
|
|
test_int(i, 4);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_iter_empty(void) {
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
ecs_map_iter_t it = ecs_map_iter(&map);
|
|
test_assert(!ecs_map_next(&it));
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_iter_null(void) {
|
|
ecs_map_iter_t it = ecs_map_iter(NULL);
|
|
test_assert(!ecs_map_next(&it));
|
|
}
|
|
|
|
void Map_remove(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
test_assert(ecs_map_get(&map, 3) != NULL);
|
|
test_int(ecs_map_count(&map), 4);
|
|
ecs_map_remove(&map, 3);
|
|
test_assert(ecs_map_get(&map, 3) == NULL);
|
|
test_int(ecs_map_count(&map), 3);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_remove_empty(void) {
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
ecs_map_remove(&map, 3);
|
|
test_int(ecs_map_count(&map), 0);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_remove_unknown(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
test_assert(ecs_map_get(&map, 5) == NULL);
|
|
test_int(ecs_map_count(&map), 4);
|
|
ecs_map_remove(&map, 5);
|
|
test_int(ecs_map_get(&map, 1)[0], 1);
|
|
test_int(ecs_map_get(&map, 2)[0], 2);
|
|
test_int(ecs_map_get(&map, 3)[0], 3);
|
|
test_int(ecs_map_get(&map, 4)[0], 4);
|
|
test_int(ecs_map_count(&map), 4);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_remove_twice(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
test_assert(ecs_map_get(&map, 3) != NULL);
|
|
test_int(ecs_map_count(&map), 4);
|
|
ecs_map_remove(&map, 3);
|
|
test_assert(ecs_map_get(&map, 3) == NULL);
|
|
test_int(ecs_map_count(&map), 3);
|
|
ecs_map_remove(&map, 3);
|
|
test_assert(ecs_map_get(&map, 3) == NULL);
|
|
test_int(ecs_map_count(&map), 3);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_clear_empty(void) {
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
ecs_map_clear(&map);
|
|
test_int(ecs_map_count(&map), 0);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_clear_populated(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
test_int(ecs_map_count(&map), 4);
|
|
ecs_map_clear(&map);
|
|
test_int(ecs_map_count(&map), 0);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_clear_empty_twice(void) {
|
|
ecs_map_t map;
|
|
ecs_map_init(&map, NULL);
|
|
ecs_map_clear(&map);
|
|
test_int(ecs_map_count(&map), 0);
|
|
ecs_map_clear(&map);
|
|
test_int(ecs_map_count(&map), 0);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_clear_populated_twice(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
test_int(ecs_map_count(&map), 4);
|
|
ecs_map_clear(&map);
|
|
test_int(ecs_map_count(&map), 0);
|
|
ecs_map_clear(&map);
|
|
test_int(ecs_map_count(&map), 0);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_populate_after_clear(void) {
|
|
uint64_t *keys = generate_keys(4);
|
|
ecs_map_t map = populate_map(keys, 4);
|
|
|
|
test_int(ecs_map_count(&map), 4);
|
|
ecs_map_clear(&map);
|
|
test_int(ecs_map_count(&map), 0);
|
|
|
|
insert_map(&map, keys, 4);
|
|
test_int(ecs_map_count(&map), 4);
|
|
ecs_map_clear(&map);
|
|
test_int(ecs_map_count(&map), 0);
|
|
|
|
ecs_os_free(keys);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
void Map_randomized_insert(void) {
|
|
uint64_t *keys = generate_random_keys(100);
|
|
|
|
for (int count = 0; count < 100; count ++) {
|
|
ecs_map_t map = populate_map(keys, count);
|
|
test_int(ecs_map_count(&map), count);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
ecs_os_free(keys);
|
|
}
|
|
|
|
void Map_randomized_remove(void) {
|
|
uint64_t *keys = generate_random_keys(100);
|
|
|
|
for (int count = 0; count < 100; count ++) {
|
|
ecs_map_t map = populate_map(keys, count);
|
|
test_int(ecs_map_count(&map), count);
|
|
free_map(&map, keys, count);
|
|
test_int(ecs_map_count(&map), 0);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
ecs_os_free(keys);
|
|
}
|
|
|
|
void Map_randomized_insert_large(void) {
|
|
uint64_t *keys = generate_random_keys(1000);
|
|
|
|
for (int count = 0; count < 1000; count += 27) {
|
|
ecs_map_t map = populate_map(keys, count);
|
|
test_int(ecs_map_count(&map), count);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
ecs_os_free(keys);
|
|
}
|
|
|
|
void Map_randomized_remove_large(void) {
|
|
uint64_t *keys = generate_random_keys(1000);
|
|
|
|
for (int count = 0; count < 1000; count += 50) {
|
|
ecs_map_t map = populate_map(keys, count);
|
|
test_int(ecs_map_count(&map), count);
|
|
free_map(&map, keys, count);
|
|
test_int(ecs_map_count(&map), 0);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
ecs_os_free(keys);
|
|
}
|
|
|
|
void Map_randomized_after_clear(void) {
|
|
uint64_t *keys = generate_random_keys(1000);
|
|
|
|
for (int count = 0; count < 1000; count += 50) {
|
|
ecs_map_t map = populate_map(keys, count);
|
|
test_int(ecs_map_count(&map), count);
|
|
ecs_map_clear(&map);
|
|
test_int(ecs_map_count(&map), 0);
|
|
insert_map(&map, keys, count);
|
|
test_int(ecs_map_count(&map), count);
|
|
ecs_map_fini(&map);
|
|
}
|
|
|
|
ecs_os_free(keys);
|
|
}
|