From 9996eefc693734adad9d463e46395064a400d88a Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 21 Nov 2019 01:52:54 -0300 Subject: [PATCH] Fixing bidimap and adding more tests --- src/cmc/bidimap.h | 50 ++++++++---- tests/main/unt/bidimap.c | 161 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 188 insertions(+), 23 deletions(-) diff --git a/src/cmc/bidimap.h b/src/cmc/bidimap.h index 960d58d..5d6b51c 100644 --- a/src/cmc/bidimap.h +++ b/src/cmc/bidimap.h @@ -341,7 +341,7 @@ struct cmc_callbacks_bidimap _map_->it_start = PFX##_impl_it_start; \ _map_->it_end = PFX##_impl_it_end; \ \ - _map_->alloc = &cmc_alloc_node_default; \ + _map_->alloc = alloc; \ _map_->callbacks = NULL; \ \ return _map_; \ @@ -404,7 +404,7 @@ struct cmc_callbacks_bidimap { \ struct SNAME##_entry *entry = _map_->key_buffer[i]; \ \ - if (entry != NULL && entry != CMC_ENTRY_DELETED) \ + if (entry && entry != CMC_ENTRY_DELETED) \ { \ if (deallocator) \ deallocator(entry->key, entry->value); \ @@ -597,19 +597,30 @@ struct cmc_callbacks_bidimap if (PFX##_empty(_map_)) \ return false; \ \ - struct SNAME##_entry **entry = PFX##_impl_get_entry_by_key(_map_, key); \ + struct SNAME##_entry **key_entry, **val_entry; \ \ - if (!entry) \ + key_entry = PFX##_impl_get_entry_by_key(_map_, key); \ + \ + if (!key_entry) \ + return false; \ + \ + val_entry = PFX##_impl_get_entry_by_val(_map_, (*key_entry)->value); \ + \ + if (!val_entry) \ + return false; \ + \ + if (*val_entry != *key_entry) \ return false; \ \ if (out_key) \ - *out_key = (*entry)->key; \ + *out_key = (*key_entry)->key; \ if (out_val) \ - *out_val = (*entry)->value; \ + *out_val = (*key_entry)->value; \ \ - _map_->alloc->free(*entry); \ + _map_->alloc->free(*key_entry); \ \ - *entry = CMC_ENTRY_DELETED; \ + *key_entry = CMC_ENTRY_DELETED; \ + *val_entry = CMC_ENTRY_DELETED; \ \ _map_->count--; \ \ @@ -621,19 +632,30 @@ struct cmc_callbacks_bidimap if (PFX##_empty(_map_)) \ return false; \ \ - struct SNAME##_entry **entry = PFX##_impl_get_entry_by_val(_map_, val); \ + struct SNAME##_entry **key_entry, **val_entry; \ \ - if (!entry) \ + val_entry = PFX##_impl_get_entry_by_val(_map_, val); \ + \ + if (!val_entry) \ + return false; \ + \ + key_entry = PFX##_impl_get_entry_by_key(_map_, (*val_entry)->key); \ + \ + if (!key_entry) \ + return false; \ + \ + if (*val_entry != *key_entry) \ return false; \ \ if (out_key) \ - *out_key = (*entry)->key; \ + *out_key = (*val_entry)->key; \ if (out_val) \ - *out_val = (*entry)->value; \ + *out_val = (*val_entry)->value; \ \ - _map_->alloc->free(*entry); \ + _map_->alloc->free(*val_entry); \ \ - *entry = CMC_ENTRY_DELETED; \ + *key_entry = CMC_ENTRY_DELETED; \ + *val_entry = CMC_ENTRY_DELETED; \ \ _map_->count--; \ \ diff --git a/tests/main/unt/bidimap.c b/tests/main/unt/bidimap.c index e04479f..629da56 100644 --- a/tests/main/unt/bidimap.c +++ b/tests/main/unt/bidimap.c @@ -16,17 +16,17 @@ CMC_CREATE_UNIT(bidimap_test, true, { bm_free(map, NULL); }); - CMC_CREATE_TEST(new_custom, { - struct bidimap *map = bm_new_custom(100, 0.6, cmp, hash, cmp, hash, - &(struct cmc_alloc_node){ - .malloc = malloc, - .calloc = calloc, - .realloc = realloc, - .free = free}, - &(struct cmc_callbacks_bidimap){0}); + CMC_CREATE_TEST(new[null buffer], { + struct bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); + for (size_t i = 0; i < map->capacity; i++) + { + cmc_assert_equals(ptr, NULL, map->key_buffer[i]); + cmc_assert_equals(ptr, NULL, map->val_buffer[i]); + } + bm_free(map, NULL); }); @@ -45,7 +45,7 @@ CMC_CREATE_UNIT(bidimap_test, true, { }); CMC_CREATE_TEST(new_custom[insert remove], { - struct bidimap *map = bm_new_custom(100, 0.6, cmp, hash, cmp, hash, + struct bidimap *map = bm_new_custom(500, 0.6, cmp, hash, cmp, hash, &(struct cmc_alloc_node){ .malloc = malloc, .calloc = calloc, @@ -133,6 +133,149 @@ CMC_CREATE_UNIT(bidimap_test, true, { bm_free(map, NULL); }); + CMC_CREATE_TEST(insert[growth remove clear], { + struct bidimap *map = bm_new(100, 0.7, cmp, hash, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 1; i <= 1000; i++) + cmc_assert(bm_insert(map, i, i)); + + cmc_assert_equals(size_t, 1000, bm_count(map)); + + size_t j = 1; + while (!bm_empty(map)) + { + if (bm_count(map) % 2 == 0) + cmc_assert(bm_remove_by_key(map, j++, NULL, NULL)); + else + cmc_assert(bm_remove_by_val(map, j++, NULL, NULL)); + } + + cmc_assert_equals(size_t, 0, bm_count(map)); + + for (size_t i = 1; i <= 1000; i++) + cmc_assert(bm_insert(map, i, i)); + + cmc_assert_equals(size_t, 1000, bm_count(map)); + + bm_clear(map, NULL); + + cmc_assert_equals(size_t, 0, bm_count(map)); + + bm_free(map, NULL); + }); + + CMC_CREATE_TEST(update_key, { + struct bidimap *map = bm_new(100, 0.7, cmp, hash, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(bm_insert(map, i, i)); + + cmc_assert_equals(size_t, 100, bm_count(map)); + + for (size_t i = 100; i > 0; i--) + cmc_assert(bm_update_key(map, i, i + 10)); + + cmc_assert_equals(size_t, 100, bm_count(map)); + + for (size_t i = 1; i <= 100; i++) + cmc_assert_equals(size_t, i + 10, bm_get_key(map, i)); + + cmc_assert_equals(size_t, 100, bm_count(map)); + + bm_free(map, NULL); + }); + + CMC_CREATE_TEST(update_val, { + struct bidimap *map = bm_new(100, 0.7, cmp, hash, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(bm_insert(map, i, i)); + + cmc_assert_equals(size_t, 100, bm_count(map)); + + for (size_t i = 100; i > 0; i--) + cmc_assert(bm_update_val(map, i, i + 10)); + + cmc_assert_equals(size_t, 100, bm_count(map)); + + for (size_t i = 1; i <= 100; i++) + cmc_assert_equals(size_t, i + 10, bm_get_val(map, i)); + + cmc_assert_equals(size_t, 100, bm_count(map)); + + bm_free(map, NULL); + }); + + CMC_CREATE_TEST(remove_by_key[cleanup custom], { + struct bidimap *map = bm_new_custom(10000, 0.6, cmp, hash, cmp, hash, + &(struct cmc_alloc_node){ + .malloc = malloc, + .calloc = calloc, + .realloc = realloc, + .free = free}, + &(struct cmc_callbacks_bidimap){0}); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 10000; i++) + { + cmc_assert(bm_insert(map, i, i)); + } + + for (size_t i = 0; i < 10000; i++) + { + cmc_assert(bm_remove_by_key(map, i, NULL, NULL)); + } + + for (size_t i = 0; i < map->capacity; i++) + { + struct bidimap_entry *k = map->key_buffer[i]; + struct bidimap_entry *v = map->val_buffer[i]; + + cmc_assert((k == NULL || k == CMC_ENTRY_DELETED) && (v == NULL || v == CMC_ENTRY_DELETED)); + } + + bm_free(map, NULL); + }); + + CMC_CREATE_TEST(remove_by_val[cleanup custom], { + struct bidimap *map = bm_new_custom(10000, 0.6, cmp, hash, cmp, hash, + &(struct cmc_alloc_node){ + .malloc = malloc, + .calloc = calloc, + .realloc = realloc, + .free = free}, + &(struct cmc_callbacks_bidimap){0}); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 10000; i++) + { + cmc_assert(bm_insert(map, i, i)); + } + + for (size_t i = 0; i < 10000; i++) + { + cmc_assert(bm_remove_by_val(map, i, NULL, NULL)); + } + + for (size_t i = 0; i < map->capacity; i++) + { + struct bidimap_entry *k = map->key_buffer[i]; + struct bidimap_entry *v = map->val_buffer[i]; + + cmc_assert((k == NULL || k == CMC_ENTRY_DELETED) && (v == NULL || v == CMC_ENTRY_DELETED)); + } + + bm_free(map, NULL); + }); + CMC_CREATE_TEST(copy_of, { struct bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash);