migrate map tests - relates to #342

Sat, 30 Dec 2023 18:48:25 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 30 Dec 2023 18:48:25 +0100
changeset 785
bb18daa62d5f
parent 784
ba5faf85dec6
child 786
b0ebb3d88407

migrate map tests - relates to #342

tests/Makefile file | annotate | diff | comparison | revisions
tests/test_hash_map.c file | annotate | diff | comparison | revisions
tests/test_map.cpp file | annotate | diff | comparison | revisions
tests/test_map_generics.c file | annotate | diff | comparison | revisions
tests/test_map_generics.h file | annotate | diff | comparison | revisions
tests/test_mempool.c file | annotate | diff | comparison | revisions
tests/ucxtest.c file | annotate | diff | comparison | revisions
     1.1 --- a/tests/Makefile	Sat Dec 30 15:21:16 2023 +0100
     1.2 +++ b/tests/Makefile	Sat Dec 30 18:48:25 2023 +0100
     1.3 @@ -28,7 +28,7 @@
     1.4  TEST_DIR=$(build_dir)/tests
     1.5  
     1.6  SRC = util_allocator.c test_utils.c test_hash_key.c test_allocator.c \
     1.7 -	test_string.c test_printf.c test_mempool.c ucxtest.c
     1.8 +	test_string.c test_printf.c test_mempool.c test_hash_map.c ucxtest.c
     1.9  
    1.10  OBJ_EXT=.o
    1.11  OBJ=$(SRC:%.c=$(TEST_DIR)/%$(OBJ_EXT))
    1.12 @@ -57,11 +57,11 @@
    1.13  	@echo "Compiling $<"
    1.14  	$(CC) -o $@ $(CFLAGS) -c $<
    1.15  
    1.16 -$(TEST_DIR)/test_map_generics$(OBJ_EXT): test_map_generics.c \
    1.17 - test_map_generics.h ../src/cx/map.h ../src/cx/common.h \
    1.18 - ../src/cx/collection.h ../src/cx/allocator.h ../src/cx/iterator.h \
    1.19 - ../src/cx/string.h ../src/cx/hash_key.h ../src/cx/hash_map.h \
    1.20 - ../src/cx/map.h
    1.21 +$(TEST_DIR)/test_hash_map$(OBJ_EXT): test_hash_map.c ../src/cx/test.h \
    1.22 + util_allocator.h ../src/cx/allocator.h ../src/cx/common.h \
    1.23 + ../src/cx/hash_map.h ../src/cx/map.h ../src/cx/collection.h \
    1.24 + ../src/cx/allocator.h ../src/cx/iterator.h ../src/cx/string.h \
    1.25 + ../src/cx/hash_key.h
    1.26  	@echo "Compiling $<"
    1.27  	$(CC) -o $@ $(CFLAGS) -c $<
    1.28  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tests/test_hash_map.c	Sat Dec 30 18:48:25 2023 +0100
     2.3 @@ -0,0 +1,669 @@
     2.4 +/*
     2.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     2.6 + *
     2.7 + * Copyright 2023 Mike Becker, Olaf Wintermann All rights reserved.
     2.8 + *
     2.9 + * Redistribution and use in source and binary forms, with or without
    2.10 + * modification, are permitted provided that the following conditions are met:
    2.11 + *
    2.12 + *   1. Redistributions of source code must retain the above copyright
    2.13 + *      notice, this list of conditions and the following disclaimer.
    2.14 + *
    2.15 + *   2. Redistributions in binary form must reproduce the above copyright
    2.16 + *      notice, this list of conditions and the following disclaimer in the
    2.17 + *      documentation and/or other materials provided with the distribution.
    2.18 + *
    2.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    2.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    2.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    2.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    2.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    2.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    2.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    2.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    2.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    2.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    2.29 + * POSSIBILITY OF SUCH DAMAGE.
    2.30 + */
    2.31 +
    2.32 +#include "cx/test.h"
    2.33 +#include "util_allocator.h"
    2.34 +
    2.35 +#include "cx/hash_map.h"
    2.36 +
    2.37 +CX_TEST(test_hash_map_create) {
    2.38 +    CxTestingAllocator talloc;
    2.39 +    cx_testing_allocator_init(&talloc);
    2.40 +    CxAllocator *allocator = &talloc.base;
    2.41 +    CX_TEST_DO {
    2.42 +        CxMap *map = cxHashMapCreate(allocator, 1, 0);
    2.43 +        struct cx_hash_map_s *hmap = (struct cx_hash_map_s *) map;
    2.44 +        CX_TEST_ASSERT(hmap->bucket_count > 0);
    2.45 +        for(size_t i = 0 ; i < hmap->bucket_count ; i++) {
    2.46 +            CX_TEST_ASSERT(hmap->buckets[i] == NULL);
    2.47 +        }
    2.48 +        CX_TEST_ASSERT(map->item_size == 1);
    2.49 +        CX_TEST_ASSERT(map->size == 0);
    2.50 +        CX_TEST_ASSERT(map->allocator == allocator);
    2.51 +        CX_TEST_ASSERT(!map->store_pointer);
    2.52 +        CX_TEST_ASSERT(map->cmpfunc == NULL);
    2.53 +        CX_TEST_ASSERT(map->simple_destructor == NULL);
    2.54 +        CX_TEST_ASSERT(map->advanced_destructor == NULL);
    2.55 +        CX_TEST_ASSERT(map->destructor_data == NULL);
    2.56 +        cxMapStorePointers(map);
    2.57 +        CX_TEST_ASSERT(map->store_pointer);
    2.58 +        CX_TEST_ASSERT(map->item_size == sizeof(void *));
    2.59 +        cxMapStoreObjects(map);
    2.60 +        CX_TEST_ASSERT(!map->store_pointer);
    2.61 +
    2.62 +        cxMapDestroy(map);
    2.63 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
    2.64 +    }
    2.65 +    cx_testing_allocator_destroy(&talloc);
    2.66 +}
    2.67 +
    2.68 +CX_TEST(test_hash_map_create_store_pointers) {
    2.69 +    CxTestingAllocator talloc;
    2.70 +    cx_testing_allocator_init(&talloc);
    2.71 +    CxAllocator *allocator = &talloc.base;
    2.72 +    CX_TEST_DO {
    2.73 +        CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0);
    2.74 +        struct cx_hash_map_s *hmap = (struct cx_hash_map_s *) map;
    2.75 +        CX_TEST_ASSERT(hmap->bucket_count > 0);
    2.76 +        for (size_t i = 0; i < hmap->bucket_count; i++) {
    2.77 +            CX_TEST_ASSERT(hmap->buckets[i] == NULL);
    2.78 +        }
    2.79 +        CX_TEST_ASSERT(map->size == 0);
    2.80 +        CX_TEST_ASSERT(map->allocator == allocator);
    2.81 +        CX_TEST_ASSERT(map->store_pointer);
    2.82 +        CX_TEST_ASSERT(map->item_size == sizeof(void *));
    2.83 +
    2.84 +        cxMapDestroy(map);
    2.85 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
    2.86 +    }
    2.87 +    cx_testing_allocator_destroy(&talloc);
    2.88 +}
    2.89 +
    2.90 +CX_TEST(test_hash_map_rehash) {
    2.91 +    CxTestingAllocator talloc;
    2.92 +    cx_testing_allocator_init(&talloc);
    2.93 +    CxAllocator *allocator = &talloc.base;
    2.94 +    CX_TEST_DO {
    2.95 +        CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 7);
    2.96 +
    2.97 +        cxMapPut(map, "key 1", (void *) "val 1");
    2.98 +        cxMapPut(map, "key 2", (void *) "val 2");
    2.99 +        cxMapPut(map, "key 3", (void *) "val 3");
   2.100 +        cxMapPut(map, "foo 4", (void *) "val 4");
   2.101 +        cxMapPut(map, "key 5", (void *) "val 5");
   2.102 +        cxMapPut(map, "key 6", (void *) "val 6");
   2.103 +        cxMapPut(map, "bar 7", (void *) "val 7");
   2.104 +        cxMapPut(map, "key 8", (void *) "val 8");
   2.105 +        cxMapPut(map, "key 9", (void *) "val 9");
   2.106 +        cxMapPut(map, "key 10", (void *) "val 10");
   2.107 +
   2.108 +        CX_TEST_ASSERT(((struct cx_hash_map_s *)map)->bucket_count == 7);
   2.109 +        int result = cxMapRehash(map);
   2.110 +        CX_TEST_ASSERT(result == 0);
   2.111 +        CX_TEST_ASSERT(((struct cx_hash_map_s *)map)->bucket_count == 25);
   2.112 +        CX_TEST_ASSERT(map->size == 10);
   2.113 +
   2.114 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 1"), "val 1"));
   2.115 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 2"), "val 2"));
   2.116 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 3"), "val 3"));
   2.117 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo 4"), "val 4"));
   2.118 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 5"), "val 5"));
   2.119 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 6"), "val 6"));
   2.120 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "bar 7"), "val 7"));
   2.121 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 8"), "val 8"));
   2.122 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 9"), "val 9"));
   2.123 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 10"), "val 10"));
   2.124 +
   2.125 +        cxMapDestroy(map);
   2.126 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
   2.127 +    }
   2.128 +    cx_testing_allocator_destroy(&talloc);
   2.129 +}
   2.130 +
   2.131 +CX_TEST(test_hash_map_rehash_not_required) {
   2.132 +    CxTestingAllocator talloc;
   2.133 +    cx_testing_allocator_init(&talloc);
   2.134 +    CxAllocator *allocator = &talloc.base;
   2.135 +    CX_TEST_DO {
   2.136 +        CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 8);
   2.137 +
   2.138 +        cxMapPut(map, "key 1", (void *) "val 1");
   2.139 +        cxMapPut(map, "key 2", (void *) "val 2");
   2.140 +        cxMapPut(map, "key 3", (void *) "val 3");
   2.141 +        cxMapPut(map, "key 4", (void *) "val 4");
   2.142 +        cxMapPut(map, "key 5", (void *) "val 5");
   2.143 +        cxMapPut(map, "key 6", (void *) "val 6");
   2.144 +
   2.145 +        // 6/8 does not exceed 0.75, therefore the function should not rehash
   2.146 +        int result = cxMapRehash(map);
   2.147 +        CX_TEST_ASSERT(result == 0);
   2.148 +        CX_TEST_ASSERT(((struct cx_hash_map_s *)map)->bucket_count == 8);
   2.149 +
   2.150 +        cxMapDestroy(map);
   2.151 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
   2.152 +    }
   2.153 +    cx_testing_allocator_destroy(&talloc);
   2.154 +}
   2.155 +
   2.156 +CX_TEST(test_hash_map_clear) {
   2.157 +    CxTestingAllocator talloc;
   2.158 +    cx_testing_allocator_init(&talloc);
   2.159 +    CxAllocator *allocator = &talloc.base;
   2.160 +    CX_TEST_DO {
   2.161 +        CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0);
   2.162 +
   2.163 +        cxMapPut(map, "key 1", (void *) "val 1");
   2.164 +        cxMapPut(map, "key 2", (void *) "val 2");
   2.165 +        cxMapPut(map, "key 3", (void *) "val 3");
   2.166 +
   2.167 +        CX_TEST_ASSERT(map->size == 3);
   2.168 +
   2.169 +        cxMapClear(map);
   2.170 +
   2.171 +        CX_TEST_ASSERT(map->size == 0);
   2.172 +        CX_TEST_ASSERT(cxMapGet(map, "key 1") == NULL);
   2.173 +        CX_TEST_ASSERT(cxMapGet(map, "key 2") == NULL);
   2.174 +        CX_TEST_ASSERT(cxMapGet(map, "key 3") == NULL);
   2.175 +
   2.176 +        cxMapDestroy(map);
   2.177 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
   2.178 +    }
   2.179 +    cx_testing_allocator_destroy(&talloc);
   2.180 +}
   2.181 +
   2.182 +CX_TEST(test_hash_map_store_ucx_strings) {
   2.183 +    CxTestingAllocator talloc;
   2.184 +    cx_testing_allocator_init(&talloc);
   2.185 +    CxAllocator *allocator = &talloc.base;
   2.186 +    CX_TEST_DO {
   2.187 +        // create the map
   2.188 +        CxMap *map = cxHashMapCreate(allocator, sizeof(cxstring), 8);
   2.189 +
   2.190 +        // define some strings
   2.191 +        cxstring s1 = CX_STR("this");
   2.192 +        cxstring s2 = CX_STR("is");
   2.193 +        cxstring s3 = CX_STR("a");
   2.194 +        cxstring s4 = CX_STR("test");
   2.195 +        cxstring s5 = CX_STR("setup");
   2.196 +
   2.197 +        // put them into the map
   2.198 +        cxMapPut(map, "s1", &s1);
   2.199 +        cxMapPut(map, "s2", &s2);
   2.200 +        cxMapPut(map, "s3", &s3);
   2.201 +        cxMapPut(map, "s4", &s4);
   2.202 +
   2.203 +        // overwrite a value
   2.204 +        cxMapPut(map, "s1", &s5);
   2.205 +
   2.206 +        // look up a string
   2.207 +        cxstring * s3p = cxMapGet(map, "s3");
   2.208 +        CX_TEST_ASSERT(s3p->length == s3.length);
   2.209 +        CX_TEST_ASSERT(s3p->ptr == s3.ptr);
   2.210 +        CX_TEST_ASSERT(s3p !=  &s3);
   2.211 +
   2.212 +        // remove a string
   2.213 +        cxMapRemove(map, "s2");
   2.214 +        CX_TEST_ASSERT(map->size == 3);
   2.215 +
   2.216 +        // iterate
   2.217 +        bool s3found = false, s4found = false, s5found = false;
   2.218 +        CxIterator iter = cxMapIteratorValues(map);
   2.219 +        cx_foreach(cxstring*, s, iter) {
   2.220 +            s3found |= s3.ptr == s->ptr;
   2.221 +            s4found |= s4.ptr == s->ptr;
   2.222 +            s5found |= s5.ptr == s->ptr;
   2.223 +        }
   2.224 +        CX_TEST_ASSERT(s3found && s4found && s5found);
   2.225 +
   2.226 +        cxMapDestroy(map);
   2.227 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
   2.228 +    }
   2.229 +    cx_testing_allocator_destroy(&talloc);
   2.230 +}
   2.231 +
   2.232 +CX_TEST(test_hash_map_remove_via_iterator) {
   2.233 +    CxTestingAllocator talloc;
   2.234 +    cx_testing_allocator_init(&talloc);
   2.235 +    CxAllocator *allocator = &talloc.base;
   2.236 +    CX_TEST_DO {
   2.237 +        CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 4);
   2.238 +
   2.239 +        cxMapPut(map, "key 1", (void *) "val 1");
   2.240 +        cxMapPut(map, "key 2", (void *) "val 2");
   2.241 +        cxMapPut(map, "key 3", (void *) "val 3");
   2.242 +        cxMapPut(map, "key 4", (void *) "val 4");
   2.243 +        cxMapPut(map, "key 5", (void *) "val 5");
   2.244 +        cxMapPut(map, "key 6", (void *) "val 6");
   2.245 +
   2.246 +        CxMutIterator iter = cxMapMutIterator(map);
   2.247 +        cx_foreach(CxMapEntry*, entry, iter) {
   2.248 +            if (((char const *)entry->key->data)[4] % 2 == 1) cxIteratorFlagRemoval(iter);
   2.249 +        }
   2.250 +        CX_TEST_ASSERT(map->size == 3);
   2.251 +        CX_TEST_ASSERT(iter.index == map->size);
   2.252 +
   2.253 +        CX_TEST_ASSERT(cxMapGet(map, "key 1") == NULL);
   2.254 +        CX_TEST_ASSERT(cxMapGet(map, "key 2") != NULL);
   2.255 +        CX_TEST_ASSERT(cxMapGet(map, "key 3") == NULL);
   2.256 +        CX_TEST_ASSERT(cxMapGet(map, "key 4") != NULL);
   2.257 +        CX_TEST_ASSERT(cxMapGet(map, "key 5") == NULL);
   2.258 +        CX_TEST_ASSERT(cxMapGet(map, "key 6") != NULL);
   2.259 +
   2.260 +        cxMapDestroy(map);
   2.261 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
   2.262 +    }
   2.263 +    cx_testing_allocator_destroy(&talloc);
   2.264 +}
   2.265 +
   2.266 +static void test_simple_destructor(void *data) {
   2.267 +    strcpy(data, "OK");
   2.268 +}
   2.269 +
   2.270 +static void test_advanced_destructor(
   2.271 +        __attribute__((__unused__)) void *unused,
   2.272 +        void *data
   2.273 +) {
   2.274 +    strcpy(data, "OK");
   2.275 +}
   2.276 +
   2.277 +static CX_TEST_SUBROUTINE(verify_any_destructor, CxMap *map) {
   2.278 +    CxHashKey k1 = cx_hash_key_str("key 1");
   2.279 +    CxHashKey k2 = cx_hash_key_str("key 2");
   2.280 +    CxHashKey k3 = cx_hash_key_str("key 3");
   2.281 +    CxHashKey k4 = cx_hash_key_str("key 4");
   2.282 +    CxHashKey k5 = cx_hash_key_str("key 5");
   2.283 +
   2.284 +    char v1[] = "val 1";
   2.285 +    char v2[] = "val 2";
   2.286 +    char v3[] = "val 3";
   2.287 +    char v4[] = "val 4";
   2.288 +    char v5[] = "val 5";
   2.289 +
   2.290 +    cxMapPut(map, k1, v1);
   2.291 +    cxMapPut(map, k2, v2);
   2.292 +    cxMapPut(map, k3, v3);
   2.293 +    cxMapPut(map, k4, v4);
   2.294 +
   2.295 +    cxMapRemove(map, k2);
   2.296 +    char *r = cxMapRemoveAndGet(map, k3);
   2.297 +    cxMapDetach(map, k1);
   2.298 +
   2.299 +    CX_TEST_ASSERT(0 == strcmp(v1, "val 1"));
   2.300 +    CX_TEST_ASSERT(0 == strcmp(v2, "OK"));
   2.301 +    CX_TEST_ASSERT(0 == strcmp(v3, "val 3"));
   2.302 +    CX_TEST_ASSERT(0 == strcmp(v4, "val 4"));
   2.303 +    CX_TEST_ASSERT(0 == strcmp(v5, "val 5"));
   2.304 +    CX_TEST_ASSERT(r == v3);
   2.305 +
   2.306 +    cxMapClear(map);
   2.307 +
   2.308 +    CX_TEST_ASSERT(0 == strcmp(v1, "val 1"));
   2.309 +    CX_TEST_ASSERT(0 == strcmp(v2, "OK"));
   2.310 +    CX_TEST_ASSERT(0 == strcmp(v3, "val 3"));
   2.311 +    CX_TEST_ASSERT(0 == strcmp(v4, "OK"));
   2.312 +    CX_TEST_ASSERT(0 == strcmp(v5, "val 5"));
   2.313 +
   2.314 +    cxMapPut(map, k1, (void *) v1);
   2.315 +    cxMapPut(map, k3, (void *) v3);
   2.316 +    cxMapPut(map, k5, (void *) v5);
   2.317 +
   2.318 +    {
   2.319 +        CxMutIterator iter = cxMapMutIteratorKeys(map);
   2.320 +        cx_foreach(CxHashKey*, key, iter) {
   2.321 +            if (((char*)key->data)[4] == '1') cxIteratorFlagRemoval(iter);
   2.322 +        }
   2.323 +    }
   2.324 +    {
   2.325 +        CxMutIterator iter = cxMapMutIteratorValues(map);
   2.326 +        cx_foreach(char*, v, iter) {
   2.327 +            if (v[4] == '5') cxIteratorFlagRemoval(iter);
   2.328 +        }
   2.329 +    }
   2.330 +
   2.331 +    CX_TEST_ASSERT(0 == strcmp(v1, "OK"));
   2.332 +    CX_TEST_ASSERT(0 == strcmp(v2, "OK"));
   2.333 +    CX_TEST_ASSERT(0 == strcmp(v3, "val 3"));
   2.334 +    CX_TEST_ASSERT(0 == strcmp(v4, "OK"));
   2.335 +    CX_TEST_ASSERT(0 == strcmp(v5, "OK"));
   2.336 +
   2.337 +    v1[0] = v2[0] = v4[0] = v5[0] = 'c';
   2.338 +
   2.339 +    cxMapDestroy(map);
   2.340 +
   2.341 +    CX_TEST_ASSERT(0 == strcmp(v1, "cK"));
   2.342 +    CX_TEST_ASSERT(0 == strcmp(v2, "cK"));
   2.343 +    CX_TEST_ASSERT(0 == strcmp(v3, "OK"));
   2.344 +    CX_TEST_ASSERT(0 == strcmp(v4, "cK"));
   2.345 +    CX_TEST_ASSERT(0 == strcmp(v5, "cK"));
   2.346 +}
   2.347 +
   2.348 +CX_TEST(test_hash_map_simple_destructor) {
   2.349 +    CxTestingAllocator talloc;
   2.350 +    cx_testing_allocator_init(&talloc);
   2.351 +    CxAllocator *allocator = &talloc.base;
   2.352 +    CX_TEST_DO {
   2.353 +        CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0);
   2.354 +        map->simple_destructor = test_simple_destructor;
   2.355 +        CX_TEST_CALL_SUBROUTINE(verify_any_destructor, map);
   2.356 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
   2.357 +    }
   2.358 +    cx_testing_allocator_destroy(&talloc);
   2.359 +}
   2.360 +
   2.361 +CX_TEST(test_hash_map_advanced_destructor) {
   2.362 +    CxTestingAllocator talloc;
   2.363 +    cx_testing_allocator_init(&talloc);
   2.364 +    CxAllocator *allocator = &talloc.base;
   2.365 +    CX_TEST_DO {
   2.366 +        CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0);
   2.367 +        map->advanced_destructor = test_advanced_destructor;
   2.368 +        CX_TEST_CALL_SUBROUTINE(verify_any_destructor, map);
   2.369 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
   2.370 +    }
   2.371 +    cx_testing_allocator_destroy(&talloc);
   2.372 +}
   2.373 +
   2.374 +CX_TEST(test_empty_map_size) {
   2.375 +    CX_TEST_DO {
   2.376 +        CX_TEST_ASSERT(cxEmptyMap->size == 0);
   2.377 +    }
   2.378 +}
   2.379 +
   2.380 +CX_TEST(test_empty_map_iterator) {
   2.381 +    CxMap *map = cxEmptyMap;
   2.382 +
   2.383 +    CxIterator it1 = cxMapIterator(map);
   2.384 +    CxIterator it2 = cxMapIteratorValues(map);
   2.385 +    CxIterator it3 = cxMapIteratorKeys(map);
   2.386 +    CxMutIterator it4 = cxMapMutIterator(map);
   2.387 +    CxMutIterator it5 = cxMapMutIteratorValues(map);
   2.388 +    CxMutIterator it6 = cxMapMutIteratorKeys(map);
   2.389 +
   2.390 +    CX_TEST_DO {
   2.391 +        CX_TEST_ASSERT(!cxIteratorValid(it1));
   2.392 +        CX_TEST_ASSERT(!cxIteratorValid(it2));
   2.393 +        CX_TEST_ASSERT(!cxIteratorValid(it3));
   2.394 +        CX_TEST_ASSERT(!cxIteratorValid(it4));
   2.395 +        CX_TEST_ASSERT(!cxIteratorValid(it5));
   2.396 +        CX_TEST_ASSERT(!cxIteratorValid(it6));
   2.397 +
   2.398 +        int c = 0;
   2.399 +        cx_foreach(void*, data, it1) c++;
   2.400 +        cx_foreach(void*, data, it2) c++;
   2.401 +        cx_foreach(void*, data, it3) c++;
   2.402 +        cx_foreach(void*, data, it4) c++;
   2.403 +        cx_foreach(void*, data, it5) c++;
   2.404 +        cx_foreach(void*, data, it6) c++;
   2.405 +        CX_TEST_ASSERT(c == 0);
   2.406 +    }
   2.407 +}
   2.408 +
   2.409 +CX_TEST(test_empty_map_no_ops) {
   2.410 +    CX_TEST_DO {
   2.411 +        // assertion not possible
   2.412 +        // test that no segfault happens and valgrind is happy
   2.413 +        cxMapClear(cxEmptyMap);
   2.414 +        cxMapDestroy(cxEmptyMap);
   2.415 +        CX_TEST_ASSERT(true);
   2.416 +    }
   2.417 +}
   2.418 +
   2.419 +CX_TEST(test_empty_map_get) {
   2.420 +    CX_TEST_DO {
   2.421 +        CxHashKey key = cx_hash_key_str("test");
   2.422 +        CX_TEST_ASSERT(cxMapGet(cxEmptyMap, key) == NULL);
   2.423 +    }
   2.424 +}
   2.425 +
   2.426 +CX_TEST(test_hash_map_generics) {
   2.427 +    CxTestingAllocator talloc;
   2.428 +    cx_testing_allocator_init(&talloc);
   2.429 +    CxAllocator *allocator = &talloc.base;
   2.430 +    CX_TEST_DO {
   2.431 +        CxMap *map = cxHashMapCreate(allocator, sizeof(cxstring), 0);
   2.432 +        cxMapPut(map, "test", "test");
   2.433 +        cxMapPut(map, cx_mutstr("foo"), "bar");
   2.434 +        cxMapPut(map, cx_str("hallo"), "welt");
   2.435 +
   2.436 +        CX_TEST_ASSERT(map->size == 3);
   2.437 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "test"), "test"));
   2.438 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar"));
   2.439 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "hallo"), "welt"));
   2.440 +
   2.441 +        // note: we don't have a destructor here, so remove and detach are the same
   2.442 +        cxMapRemove(map, cx_str("test"));
   2.443 +        char const *hallo = "hallo";
   2.444 +        cxMapDetach(map, hallo);
   2.445 +        cxMapPut(map, cx_hash_key_str("key"), "value");
   2.446 +
   2.447 +        CX_TEST_ASSERT(map->size == 2);
   2.448 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key"), "value"));
   2.449 +        CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar"));
   2.450 +
   2.451 +        void *r;
   2.452 +        r = cxMapRemoveAndGet(map, "key");
   2.453 +        r = cxMapRemoveAndGet(map, cx_str("foo"));
   2.454 +        if (r != NULL) map->size = 47;
   2.455 +
   2.456 +        CX_TEST_ASSERT(map->size == 0);
   2.457 +
   2.458 +        cxMapDestroy(map);
   2.459 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
   2.460 +    }
   2.461 +    cx_testing_allocator_destroy(&talloc);
   2.462 +}
   2.463 +
   2.464 +struct test_map_kv {
   2.465 +    char const *key;
   2.466 +    char const *value;
   2.467 +};
   2.468 +
   2.469 +static struct test_map_kv const test_map_operations[] = {
   2.470 +        {"key 1",          "test"},
   2.471 +        {"key 2",          "blub"},
   2.472 +        {"key 3",          "hallo"},
   2.473 +        {"key 2",          "foobar"},
   2.474 +        {"key 4",          "value 4"},
   2.475 +        {"key 5",          "value 5"},
   2.476 +        {"key 6",          "value 6"},
   2.477 +        {"key 4",          NULL},
   2.478 +        {"key 7",          "value 7"},
   2.479 +        {"key 8",          "value 8"},
   2.480 +        {"does not exist", NULL},
   2.481 +        {"key 9",          "value 9"},
   2.482 +        {"key 6",          "other value"},
   2.483 +        {"key 7",          "something else"},
   2.484 +        {"key 8",          NULL},
   2.485 +        {"key 2",          NULL},
   2.486 +        {"key 8",          "new value"},
   2.487 +};
   2.488 +static size_t const test_map_operations_len =
   2.489 +        sizeof(test_map_operations) / sizeof(struct test_map_kv);
   2.490 +static struct test_map_kv test_map_reference[] = {
   2.491 +        {"key 1", NULL},
   2.492 +        {"key 2", NULL},
   2.493 +        {"key 3", NULL},
   2.494 +        {"key 4", NULL},
   2.495 +        {"key 5", NULL},
   2.496 +        {"key 6", NULL},
   2.497 +        {"key 7", NULL},
   2.498 +        {"key 8", NULL},
   2.499 +        {"key 9", NULL},
   2.500 +};
   2.501 +static size_t const test_map_reference_len =
   2.502 +        sizeof(test_map_reference) / sizeof(struct test_map_kv);
   2.503 +
   2.504 +static void test_map_reference_put(char const *key, char const* value) {
   2.505 +    for (size_t i = 0 ; i < test_map_reference_len ; i++) {
   2.506 +        if (0 == strcmp(key, test_map_reference[i].key)) {
   2.507 +            test_map_reference[i].value = value;
   2.508 +            return;
   2.509 +        }
   2.510 +    }
   2.511 +}
   2.512 +
   2.513 +static char const *test_map_reference_get(char const *key) {
   2.514 +    for (size_t i = 0 ; i < test_map_reference_len ; i++) {
   2.515 +        if (0 == strcmp(key, test_map_reference[i].key)) {
   2.516 +            return test_map_reference[i].value;
   2.517 +        }
   2.518 +    }
   2.519 +    return NULL;
   2.520 +}
   2.521 +
   2.522 +static char const *test_map_reference_remove(char const *key) {
   2.523 +    for (size_t i = 0 ; i < test_map_reference_len ; i++) {
   2.524 +        if (0 == strcmp(key, test_map_reference[i].key)) {
   2.525 +            char const *ret = test_map_reference[i].value;
   2.526 +            test_map_reference[i].value = NULL;
   2.527 +            return ret;
   2.528 +        }
   2.529 +    }
   2.530 +    return NULL;
   2.531 +}
   2.532 +
   2.533 +static size_t test_map_reference_size(void) {
   2.534 +    size_t size = 0;
   2.535 +    for (size_t i = 0; i < test_map_reference_len; i++) {
   2.536 +        if (test_map_reference[i].value != NULL) {
   2.537 +            size++;
   2.538 +        }
   2.539 +    }
   2.540 +    return size;
   2.541 +}
   2.542 +
   2.543 +static CX_TEST_SUBROUTINE(verify_map_contents, CxMap *map) {
   2.544 +    // verify that the reference map has same size (i.e. no other keys are mapped)
   2.545 +    CX_TEST_ASSERT(map->size == test_map_reference_size());
   2.546 +
   2.547 +    // verify key iterator
   2.548 +    {
   2.549 +        // collect the keys from the map iterator
   2.550 +        CxIterator keyiter = cxMapIteratorKeys(map);
   2.551 +        CxHashKey *keys = calloc(map->size, sizeof(CxHashKey));
   2.552 +        cx_foreach(CxHashKey*, elem, keyiter) {
   2.553 +            keys[keyiter.index] = *elem;
   2.554 +        }
   2.555 +        CX_TEST_ASSERT(keyiter.index == map->size);
   2.556 +        // verify that all keys are mapped to values in reference map
   2.557 +        for (size_t i = 0 ; i < map->size ; i++) {
   2.558 +            cxmutstr ksz = cx_strdup(cx_strn(keys[i].data, keys[i].len));
   2.559 +            CX_TEST_ASSERT(test_map_reference_get(ksz.ptr) != NULL);
   2.560 +            cx_strfree(&ksz);
   2.561 +        }
   2.562 +        free(keys);
   2.563 +    }
   2.564 +
   2.565 +    // verify value iterator
   2.566 +    {
   2.567 +        // by using that the values in our test data are unique strings
   2.568 +        // we can re-use a similar approach as above
   2.569 +        CxIterator valiter = cxMapIteratorValues(map);
   2.570 +        char const** values = calloc(map->size, sizeof(char const*));
   2.571 +        cx_foreach(char const*, elem, valiter) {
   2.572 +            values[valiter.index] = elem;
   2.573 +        }
   2.574 +        CX_TEST_ASSERT(valiter.index == map->size);
   2.575 +        // verify that all values are present in the reference map
   2.576 +        for (size_t i = 0 ; i < map->size ; i++) {
   2.577 +            bool found = false;
   2.578 +            for (size_t j = 0; j < test_map_reference_len ; j++) {
   2.579 +                if (test_map_reference[j].value == values[i]) {
   2.580 +                    found = true;
   2.581 +                    break;
   2.582 +                }
   2.583 +            }
   2.584 +            CX_TEST_ASSERTM(found, "A value was not found in the reference map");
   2.585 +        }
   2.586 +        free(values);
   2.587 +    }
   2.588 +
   2.589 +    // verify pair iterator
   2.590 +    {
   2.591 +        CxIterator pairiter = cxMapIterator(map);
   2.592 +        struct test_map_kv *pairs = calloc(map->size, sizeof(struct test_map_kv));
   2.593 +        cx_foreach(CxMapEntry*, entry, pairiter) {
   2.594 +            CxHashKey const *key = entry->key;
   2.595 +            pairs[pairiter.index].key = cx_strdup(cx_strn(key->data, key->len)).ptr;
   2.596 +            pairs[pairiter.index].value = entry->value;
   2.597 +        }
   2.598 +        CX_TEST_ASSERT(pairiter.index == map->size);
   2.599 +        // verify that all pairs are present in the reference map
   2.600 +        for (size_t i = 0 ; i < map->size ; i++) {
   2.601 +            CX_TEST_ASSERT(test_map_reference_get(pairs[i].key) == pairs[i].value);
   2.602 +            // this was strdup'ed
   2.603 +            free((void*)pairs[i].key);
   2.604 +        }
   2.605 +        free(pairs);
   2.606 +    }
   2.607 +}
   2.608 +
   2.609 +CX_TEST(test_hash_map_basic_operations) {
   2.610 +    CxTestingAllocator talloc;
   2.611 +    cx_testing_allocator_init(&talloc);
   2.612 +    CxAllocator *allocator = &talloc.base;
   2.613 +    CX_TEST_DO {
   2.614 +        // create the map
   2.615 +        CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 8);
   2.616 +
   2.617 +        // clear the reference map
   2.618 +        for (size_t i = 0 ; i < test_map_reference_len ; i++) {
   2.619 +            test_map_reference[i].value = NULL;
   2.620 +        }
   2.621 +
   2.622 +        // verify iterators for empty map
   2.623 +        CX_TEST_CALL_SUBROUTINE(verify_map_contents, map);
   2.624 +
   2.625 +        // execute operations and verify results
   2.626 +        for (size_t i = 0 ; i < test_map_operations_len ; i++) {
   2.627 +            struct test_map_kv kv = test_map_operations[i];
   2.628 +            CxHashKey key = cx_hash_key_str(kv.key);
   2.629 +            key.hash = 0; // force the hash map to compute the hash
   2.630 +            if (kv.value != NULL) {
   2.631 +                // execute a put operation and verify that the exact value can be read back
   2.632 +                test_map_reference_put(kv.key, kv.value);
   2.633 +                int result = cxMapPut(map, key, (void *) kv.value);
   2.634 +                CX_TEST_ASSERT(result == 0);
   2.635 +                void *added = cxMapGet(map, key);
   2.636 +                CX_TEST_ASSERT(0 == memcmp(kv.value, added, strlen(kv.value)));
   2.637 +            } else {
   2.638 +                // execute a remove and verify that the removed element was returned (or NULL)
   2.639 +                char const *found = test_map_reference_remove(kv.key);
   2.640 +                void *removed = cxMapRemoveAndGet(map, key);
   2.641 +                CX_TEST_ASSERT(found == removed);
   2.642 +            }
   2.643 +            // compare the current map state with the reference map
   2.644 +            CX_TEST_CALL_SUBROUTINE(verify_map_contents, map);
   2.645 +        }
   2.646 +
   2.647 +        // destroy the map and verify the memory (de)allocations
   2.648 +        cxMapDestroy(map);
   2.649 +        CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
   2.650 +    }
   2.651 +    cx_testing_allocator_destroy(&talloc);
   2.652 +}
   2.653 +
   2.654 +CxTestSuite *cx_test_suite_hash_map(void) {
   2.655 +    CxTestSuite *suite = cx_test_suite_new("map");
   2.656 +
   2.657 +    cx_test_register(suite, test_hash_map_create);
   2.658 +    cx_test_register(suite, test_hash_map_create_store_pointers);
   2.659 +    cx_test_register(suite, test_hash_map_basic_operations);
   2.660 +    cx_test_register(suite, test_hash_map_rehash);
   2.661 +    cx_test_register(suite, test_hash_map_rehash_not_required);
   2.662 +    cx_test_register(suite, test_hash_map_clear);
   2.663 +    cx_test_register(suite, test_hash_map_store_ucx_strings);
   2.664 +    cx_test_register(suite, test_hash_map_remove_via_iterator);
   2.665 +    cx_test_register(suite, test_empty_map_no_ops);
   2.666 +    cx_test_register(suite, test_empty_map_size);
   2.667 +    cx_test_register(suite, test_empty_map_get);
   2.668 +    cx_test_register(suite, test_empty_map_iterator);
   2.669 +    cx_test_register(suite, test_hash_map_generics);
   2.670 +
   2.671 +    return suite;
   2.672 +}
     3.1 --- a/tests/test_map.cpp	Sat Dec 30 15:21:16 2023 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,521 +0,0 @@
     3.4 -/*
     3.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3.6 - *
     3.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     3.8 - *
     3.9 - * Redistribution and use in source and binary forms, with or without
    3.10 - * modification, are permitted provided that the following conditions are met:
    3.11 - *
    3.12 - *   1. Redistributions of source code must retain the above copyright
    3.13 - *      notice, this list of conditions and the following disclaimer.
    3.14 - *
    3.15 - *   2. Redistributions in binary form must reproduce the above copyright
    3.16 - *      notice, this list of conditions and the following disclaimer in the
    3.17 - *      documentation and/or other materials provided with the distribution.
    3.18 - *
    3.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    3.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    3.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    3.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    3.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    3.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    3.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    3.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    3.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    3.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    3.29 - * POSSIBILITY OF SUCH DAMAGE.
    3.30 - */
    3.31 -
    3.32 -#include "cx/hash_map.h"
    3.33 -#include "cx/utils.h"
    3.34 -#include "cx/string.h"
    3.35 -#include "util_allocator.h"
    3.36 -#include "test_map_generics.h"
    3.37 -
    3.38 -#include <gtest/gtest.h>
    3.39 -#include <unordered_map>
    3.40 -#include <unordered_set>
    3.41 -
    3.42 -struct map_operation {
    3.43 -    enum {
    3.44 -        put, rm
    3.45 -    } op;
    3.46 -    char const *key;
    3.47 -    char const *value;
    3.48 -};
    3.49 -
    3.50 -auto generate_map_operations() -> std::vector<map_operation> {
    3.51 -    return {
    3.52 -            {map_operation::put, "key 1",          "test"},
    3.53 -            {map_operation::put, "key 2",          "blub"},
    3.54 -            {map_operation::put, "key 3",          "hallo"},
    3.55 -            {map_operation::put, "key 2",          "foobar"},
    3.56 -            {map_operation::put, "key 4",          "value 4"},
    3.57 -            {map_operation::put, "key 5",          "value 5"},
    3.58 -            {map_operation::put, "key 6",          "value 6"},
    3.59 -            {map_operation::rm,  "key 4",          nullptr},
    3.60 -            {map_operation::put, "key 7",          "value 7"},
    3.61 -            {map_operation::put, "key 8",          "value 8"},
    3.62 -            {map_operation::rm,  "does not exist", nullptr},
    3.63 -            {map_operation::put, "key 9",          "value 9"},
    3.64 -            {map_operation::put, "key 6",          "other value"},
    3.65 -            {map_operation::put, "key 7",          "something else"},
    3.66 -            {map_operation::rm,  "key 8",          nullptr},
    3.67 -            {map_operation::rm,  "key 2",          nullptr},
    3.68 -            {map_operation::put, "key 8",          "new value"},
    3.69 -    };
    3.70 -}
    3.71 -
    3.72 -static void verify_map_contents(
    3.73 -        CxMap *map,
    3.74 -        std::unordered_map<std::string, std::string> const &refmap
    3.75 -) {
    3.76 -    // verify key iterator
    3.77 -    {
    3.78 -        auto keyiter = cxMapIteratorKeys(map);
    3.79 -        std::unordered_set<std::string> keys;
    3.80 -        cx_foreach(CxHashKey*, elem, keyiter) {
    3.81 -            keys.insert(std::string(reinterpret_cast<char const *>(elem->data), elem->len));
    3.82 -        }
    3.83 -        EXPECT_EQ(keyiter.index, map->size);
    3.84 -        ASSERT_EQ(keys.size(), map->size);
    3.85 -        for (auto &&k: keys) {
    3.86 -            EXPECT_NE(refmap.find(k), refmap.end());
    3.87 -        }
    3.88 -    }
    3.89 -
    3.90 -    // verify value iterator
    3.91 -    {
    3.92 -        auto valiter = cxMapIteratorValues(map);
    3.93 -        std::unordered_set<std::string> values; // we use that the values in our test data are unique strings
    3.94 -        cx_foreach(char const*, elem, valiter) {
    3.95 -            values.insert(std::string(elem));
    3.96 -        }
    3.97 -        EXPECT_EQ(valiter.index, map->size);
    3.98 -        ASSERT_EQ(values.size(), map->size);
    3.99 -        for (auto &&v: values) {
   3.100 -            EXPECT_NE(std::find_if(refmap.begin(), refmap.end(),
   3.101 -                                   [v](auto const &e) { return e.second == v; }), refmap.end());
   3.102 -        }
   3.103 -    }
   3.104 -
   3.105 -    // verify pair iterator
   3.106 -    {
   3.107 -        auto pairiter = cxMapIterator(map);
   3.108 -        std::unordered_map<std::string, std::string> pairs;
   3.109 -        cx_foreach(CxMapEntry*, entry, pairiter) {
   3.110 -            pairs[std::string(reinterpret_cast<char const *>(entry->key->data), entry->key->len)] = std::string(
   3.111 -                    (char *) entry->value);
   3.112 -        }
   3.113 -        EXPECT_EQ(pairiter.index, map->size);
   3.114 -        ASSERT_EQ(pairs.size(), refmap.size());
   3.115 -        for (auto &&p: pairs) {
   3.116 -            ASSERT_EQ(p.second, refmap.at(p.first));
   3.117 -        }
   3.118 -    }
   3.119 -}
   3.120 -
   3.121 -TEST(CxHashMap, Create) {
   3.122 -    CxTestingAllocator allocator;
   3.123 -    auto map = cxHashMapCreate(&allocator, 1, 0);
   3.124 -    auto hmap = reinterpret_cast<struct cx_hash_map_s *>(map);
   3.125 -    EXPECT_GT(hmap->bucket_count, 0);
   3.126 -    cx_for_n(i, hmap->bucket_count) {
   3.127 -        EXPECT_EQ(hmap->buckets[i], nullptr);
   3.128 -    }
   3.129 -    EXPECT_EQ(map->item_size, 1);
   3.130 -    EXPECT_EQ(map->size, 0);
   3.131 -    EXPECT_EQ(map->allocator, &allocator);
   3.132 -    EXPECT_FALSE(map->store_pointer);
   3.133 -    EXPECT_EQ(map->cmpfunc, nullptr);
   3.134 -    EXPECT_EQ(map->simple_destructor, nullptr);
   3.135 -    EXPECT_EQ(map->advanced_destructor, nullptr);
   3.136 -    EXPECT_EQ(map->destructor_data, nullptr);
   3.137 -    cxMapStorePointers(map);
   3.138 -    EXPECT_TRUE(map->store_pointer);
   3.139 -    EXPECT_EQ(map->item_size, sizeof(void *));
   3.140 -    cxMapStoreObjects(map);
   3.141 -    EXPECT_FALSE(map->store_pointer);
   3.142 -
   3.143 -    cxMapDestroy(map);
   3.144 -    EXPECT_TRUE(allocator.verify());
   3.145 -}
   3.146 -
   3.147 -TEST(CxHashMap, CreateForStoringPointers) {
   3.148 -    CxTestingAllocator allocator;
   3.149 -    auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 0);
   3.150 -    auto hmap = reinterpret_cast<struct cx_hash_map_s *>(map);
   3.151 -    EXPECT_GT(hmap->bucket_count, 0);
   3.152 -    cx_for_n(i, hmap->bucket_count) {
   3.153 -        EXPECT_EQ(hmap->buckets[i], nullptr);
   3.154 -    }
   3.155 -    EXPECT_EQ(map->size, 0);
   3.156 -    EXPECT_EQ(map->allocator, &allocator);
   3.157 -    EXPECT_TRUE(map->store_pointer);
   3.158 -    EXPECT_EQ(map->item_size, sizeof(void *));
   3.159 -
   3.160 -    cxMapDestroy(map);
   3.161 -    EXPECT_TRUE(allocator.verify());
   3.162 -}
   3.163 -
   3.164 -TEST(CxHashMap, BasicOperations) {
   3.165 -    // create the map
   3.166 -    CxTestingAllocator allocator;
   3.167 -    auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 8);
   3.168 -
   3.169 -    // create a reference map
   3.170 -    std::unordered_map<std::string, std::string> refmap;
   3.171 -
   3.172 -    // generate operations
   3.173 -    auto ops = generate_map_operations();
   3.174 -
   3.175 -    // verify iterators for empty map
   3.176 -    verify_map_contents(map, refmap);
   3.177 -
   3.178 -    // execute operations and verify results
   3.179 -    for (auto &&op: ops) {
   3.180 -        CxHashKey key = cx_hash_key_str(op.key);
   3.181 -        key.hash = 0; // force the hash map to compute the hash
   3.182 -        if (op.op == map_operation::put) {
   3.183 -            // execute a put operation and verify that the exact value can be read back
   3.184 -            refmap[std::string(op.key)] = std::string(op.value);
   3.185 -            int result = cxMapPut(map, key, (void *) op.value);
   3.186 -            EXPECT_EQ(result, 0);
   3.187 -            auto added = cxMapGet(map, key);
   3.188 -            EXPECT_EQ(memcmp(op.value, added, strlen(op.value)), 0);
   3.189 -        } else {
   3.190 -            // execute a remove and verify that the removed element was returned (or nullptr)
   3.191 -            auto found = refmap.find(op.key);
   3.192 -            auto removed = cxMapRemoveAndGet(map, key);
   3.193 -            if (found == refmap.end()) {
   3.194 -                EXPECT_EQ(removed, nullptr);
   3.195 -            } else {
   3.196 -                EXPECT_EQ(std::string((char *) removed), found->second);
   3.197 -                refmap.erase(found);
   3.198 -            }
   3.199 -        }
   3.200 -        // compare the current map state with the reference map
   3.201 -        verify_map_contents(map, refmap);
   3.202 -    }
   3.203 -
   3.204 -    // destroy the map and verify the memory (de)allocations
   3.205 -    cxMapDestroy(map);
   3.206 -    EXPECT_TRUE(allocator.verify());
   3.207 -}
   3.208 -
   3.209 -TEST(CxHashMap, RemoveViaIterator) {
   3.210 -    CxTestingAllocator allocator;
   3.211 -    auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 4);
   3.212 -
   3.213 -    cxMapPut(map, "key 1", (void *) "val 1");
   3.214 -    cxMapPut(map, "key 2", (void *) "val 2");
   3.215 -    cxMapPut(map, "key 3", (void *) "val 3");
   3.216 -    cxMapPut(map, "key 4", (void *) "val 4");
   3.217 -    cxMapPut(map, "key 5", (void *) "val 5");
   3.218 -    cxMapPut(map, "key 6", (void *) "val 6");
   3.219 -
   3.220 -    auto iter = cxMapMutIterator(map);
   3.221 -    cx_foreach(CxMapEntry*, entry, iter) {
   3.222 -        if (reinterpret_cast<char const *>(entry->key->data)[4] % 2 == 1) cxIteratorFlagRemoval(iter);
   3.223 -    }
   3.224 -    EXPECT_EQ(map->size, 3);
   3.225 -    EXPECT_EQ(iter.index, map->size);
   3.226 -
   3.227 -    EXPECT_EQ(cxMapGet(map, "key 1"), nullptr);
   3.228 -    EXPECT_NE(cxMapGet(map, "key 2"), nullptr);
   3.229 -    EXPECT_EQ(cxMapGet(map, "key 3"), nullptr);
   3.230 -    EXPECT_NE(cxMapGet(map, "key 4"), nullptr);
   3.231 -    EXPECT_EQ(cxMapGet(map, "key 5"), nullptr);
   3.232 -    EXPECT_NE(cxMapGet(map, "key 6"), nullptr);
   3.233 -
   3.234 -    cxMapDestroy(map);
   3.235 -    EXPECT_TRUE(allocator.verify());
   3.236 -}
   3.237 -
   3.238 -TEST(CxHashMap, RehashNotRequired) {
   3.239 -    CxTestingAllocator allocator;
   3.240 -    auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 8);
   3.241 -
   3.242 -    cxMapPut(map, "key 1", (void *) "val 1");
   3.243 -    cxMapPut(map, "key 2", (void *) "val 2");
   3.244 -    cxMapPut(map, "key 3", (void *) "val 3");
   3.245 -    cxMapPut(map, "key 4", (void *) "val 4");
   3.246 -    cxMapPut(map, "key 5", (void *) "val 5");
   3.247 -    cxMapPut(map, "key 6", (void *) "val 6");
   3.248 -
   3.249 -    // 6/8 does not exceed 0.75, therefore the function should not rehash
   3.250 -    int result = cxMapRehash(map);
   3.251 -    EXPECT_EQ(result, 0);
   3.252 -    EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 8);
   3.253 -
   3.254 -    cxMapDestroy(map);
   3.255 -    EXPECT_TRUE(allocator.verify());
   3.256 -}
   3.257 -
   3.258 -TEST(CxHashMap, Rehash) {
   3.259 -    CxTestingAllocator allocator;
   3.260 -    auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 7);
   3.261 -
   3.262 -    cxMapPut(map, "key 1", (void *) "val 1");
   3.263 -    cxMapPut(map, "key 2", (void *) "val 2");
   3.264 -    cxMapPut(map, "key 3", (void *) "val 3");
   3.265 -    cxMapPut(map, "foo 4", (void *) "val 4");
   3.266 -    cxMapPut(map, "key 5", (void *) "val 5");
   3.267 -    cxMapPut(map, "key 6", (void *) "val 6");
   3.268 -    cxMapPut(map, "bar 7", (void *) "val 7");
   3.269 -    cxMapPut(map, "key 8", (void *) "val 8");
   3.270 -    cxMapPut(map, "key 9", (void *) "val 9");
   3.271 -    cxMapPut(map, "key 10", (void *) "val 10");
   3.272 -
   3.273 -    int result = cxMapRehash(map);
   3.274 -    EXPECT_EQ(result, 0);
   3.275 -    EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 25);
   3.276 -    EXPECT_EQ(map->size, 10);
   3.277 -
   3.278 -    EXPECT_STREQ((char *) cxMapGet(map, "key 1"), "val 1");
   3.279 -    EXPECT_STREQ((char *) cxMapGet(map, "key 2"), "val 2");
   3.280 -    EXPECT_STREQ((char *) cxMapGet(map, "key 3"), "val 3");
   3.281 -    EXPECT_STREQ((char *) cxMapGet(map, "foo 4"), "val 4");
   3.282 -    EXPECT_STREQ((char *) cxMapGet(map, "key 5"), "val 5");
   3.283 -    EXPECT_STREQ((char *) cxMapGet(map, "key 6"), "val 6");
   3.284 -    EXPECT_STREQ((char *) cxMapGet(map, "bar 7"), "val 7");
   3.285 -    EXPECT_STREQ((char *) cxMapGet(map, "key 8"), "val 8");
   3.286 -    EXPECT_STREQ((char *) cxMapGet(map, "key 9"), "val 9");
   3.287 -    EXPECT_STREQ((char *) cxMapGet(map, "key 10"), "val 10");
   3.288 -
   3.289 -    cxMapDestroy(map);
   3.290 -    EXPECT_TRUE(allocator.verify());
   3.291 -}
   3.292 -
   3.293 -TEST(CxHashMap, Clear) {
   3.294 -    CxTestingAllocator allocator;
   3.295 -    auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 0);
   3.296 -
   3.297 -    cxMapPut(map, "key 1", (void *) "val 1");
   3.298 -    cxMapPut(map, "key 2", (void *) "val 2");
   3.299 -    cxMapPut(map, "key 3", (void *) "val 3");
   3.300 -
   3.301 -    EXPECT_EQ(map->size, 3);
   3.302 -
   3.303 -    cxMapClear(map);
   3.304 -
   3.305 -    EXPECT_EQ(map->size, 0);
   3.306 -    EXPECT_EQ(cxMapGet(map, "key 1"), nullptr);
   3.307 -    EXPECT_EQ(cxMapGet(map, "key 2"), nullptr);
   3.308 -    EXPECT_EQ(cxMapGet(map, "key 3"), nullptr);
   3.309 -
   3.310 -    cxMapDestroy(map);
   3.311 -    EXPECT_TRUE(allocator.verify());
   3.312 -}
   3.313 -
   3.314 -TEST(CxHashMap, StoreUcxStrings) {
   3.315 -    // create the map
   3.316 -    CxTestingAllocator allocator;
   3.317 -    auto map = cxHashMapCreate(&allocator, sizeof(cxstring), 8);
   3.318 -
   3.319 -    // define some strings
   3.320 -    auto s1 = CX_STR("this");
   3.321 -    auto s2 = CX_STR("is");
   3.322 -    auto s3 = CX_STR("a");
   3.323 -    auto s4 = CX_STR("test");
   3.324 -    auto s5 = CX_STR("setup");
   3.325 -
   3.326 -    // put them into the map
   3.327 -    cxMapPut(map, "s1", &s1);
   3.328 -    cxMapPut(map, "s2", &s2);
   3.329 -    cxMapPut(map, "s3", &s3);
   3.330 -    cxMapPut(map, "s4", &s4);
   3.331 -
   3.332 -    // overwrite a value
   3.333 -    cxMapPut(map, "s1", &s5);
   3.334 -
   3.335 -    // look up a string
   3.336 -    auto s3p = reinterpret_cast<cxstring *>(cxMapGet(map, "s3"));
   3.337 -    EXPECT_EQ(s3p->length, s3.length);
   3.338 -    EXPECT_EQ(s3p->ptr, s3.ptr);
   3.339 -    EXPECT_NE(s3p, &s3);
   3.340 -
   3.341 -    // remove a string
   3.342 -    cxMapRemove(map, "s2");
   3.343 -
   3.344 -    // iterate
   3.345 -    auto ref = std::vector{s5.ptr, s3.ptr, s4.ptr};
   3.346 -    auto iter = cxMapIteratorValues(map);
   3.347 -    cx_foreach(cxstring*, s, iter) {
   3.348 -        auto found = std::find(ref.begin(), ref.end(), s->ptr);
   3.349 -        ASSERT_NE(found, ref.end());
   3.350 -        ref.erase(found);
   3.351 -    }
   3.352 -    EXPECT_EQ(ref.size(), 0);
   3.353 -
   3.354 -    cxMapDestroy(map);
   3.355 -    EXPECT_TRUE(allocator.verify());
   3.356 -}
   3.357 -
   3.358 -static void test_simple_destructor(void *data) {
   3.359 -    strcpy((char *) data, "OK");
   3.360 -}
   3.361 -
   3.362 -static void test_advanced_destructor(
   3.363 -        [[maybe_unused]] void *unused,
   3.364 -        void *data
   3.365 -) {
   3.366 -    strcpy((char *) data, "OK");
   3.367 -}
   3.368 -
   3.369 -static void verify_any_destructor(CxMap *map) {
   3.370 -    auto k1 = cx_hash_key_str("key 1");
   3.371 -    auto k2 = cx_hash_key_str("key 2");
   3.372 -    auto k3 = cx_hash_key_str("key 3");
   3.373 -    auto k4 = cx_hash_key_str("key 4");
   3.374 -    auto k5 = cx_hash_key_str("key 5");
   3.375 -
   3.376 -    char v1[] = "val 1";
   3.377 -    char v2[] = "val 2";
   3.378 -    char v3[] = "val 3";
   3.379 -    char v4[] = "val 4";
   3.380 -    char v5[] = "val 5";
   3.381 -
   3.382 -    cxMapPut(map, k1, (void *) v1);
   3.383 -    cxMapPut(map, k2, (void *) v2);
   3.384 -    cxMapPut(map, k3, (void *) v3);
   3.385 -    cxMapPut(map, k4, (void *) v4);
   3.386 -
   3.387 -    cxMapRemove(map, k2);
   3.388 -    auto r = cxMapRemoveAndGet(map, k3);
   3.389 -    cxMapDetach(map, k1);
   3.390 -
   3.391 -    EXPECT_STREQ(v1, "val 1");
   3.392 -    EXPECT_STREQ(v2, "OK");
   3.393 -    EXPECT_STREQ(v3, "val 3");
   3.394 -    EXPECT_STREQ(v4, "val 4");
   3.395 -    EXPECT_STREQ(v5, "val 5");
   3.396 -    EXPECT_EQ(r, v3);
   3.397 -
   3.398 -    cxMapClear(map);
   3.399 -
   3.400 -    EXPECT_STREQ(v1, "val 1");
   3.401 -    EXPECT_STREQ(v2, "OK");
   3.402 -    EXPECT_STREQ(v3, "val 3");
   3.403 -    EXPECT_STREQ(v4, "OK");
   3.404 -    EXPECT_STREQ(v5, "val 5");
   3.405 -
   3.406 -    cxMapPut(map, k1, (void *) v1);
   3.407 -    cxMapPut(map, k3, (void *) v3);
   3.408 -    cxMapPut(map, k5, (void *) v5);
   3.409 -
   3.410 -    {
   3.411 -        auto iter = cxMapMutIteratorKeys(map);
   3.412 -        cx_foreach(CxHashKey*, key, iter) {
   3.413 -            if (reinterpret_cast<char const *>(key->data)[4] == '1') cxIteratorFlagRemoval(iter);
   3.414 -        }
   3.415 -    }
   3.416 -    {
   3.417 -        auto iter = cxMapMutIteratorValues(map);
   3.418 -        cx_foreach(char*, v, iter) {
   3.419 -            if (v[4] == '5') cxIteratorFlagRemoval(iter);
   3.420 -        }
   3.421 -    }
   3.422 -
   3.423 -    EXPECT_STREQ(v1, "OK");
   3.424 -    EXPECT_STREQ(v2, "OK");
   3.425 -    EXPECT_STREQ(v3, "val 3");
   3.426 -    EXPECT_STREQ(v4, "OK");
   3.427 -    EXPECT_STREQ(v5, "OK");
   3.428 -
   3.429 -    v1[0] = v2[0] = v4[0] = v5[0] = 'c';
   3.430 -
   3.431 -    cxMapDestroy(map);
   3.432 -
   3.433 -    EXPECT_STREQ(v1, "cK");
   3.434 -    EXPECT_STREQ(v2, "cK");
   3.435 -    EXPECT_STREQ(v3, "OK");
   3.436 -    EXPECT_STREQ(v4, "cK");
   3.437 -    EXPECT_STREQ(v5, "cK");
   3.438 -}
   3.439 -
   3.440 -TEST(CxHashMap, SimpleDestructor) {
   3.441 -    CxTestingAllocator allocator;
   3.442 -    auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 0);
   3.443 -    map->simple_destructor = test_simple_destructor;
   3.444 -    verify_any_destructor(map);
   3.445 -    EXPECT_TRUE(allocator.verify());
   3.446 -}
   3.447 -
   3.448 -TEST(CxHashMap, AdvancedDestructor) {
   3.449 -    CxTestingAllocator allocator;
   3.450 -    auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 0);
   3.451 -    map->advanced_destructor = test_advanced_destructor;
   3.452 -    verify_any_destructor(map);
   3.453 -    EXPECT_TRUE(allocator.verify());
   3.454 -}
   3.455 -
   3.456 -TEST(CxHashMap, Generics) {
   3.457 -    CxTestingAllocator allocator;
   3.458 -    auto map = test_map_generics_step_1(&allocator);
   3.459 -
   3.460 -    EXPECT_EQ(map->size, 3);
   3.461 -    EXPECT_STREQ((char *) cxMapGet(map, "test"), "test");
   3.462 -    EXPECT_STREQ((char *) cxMapGet(map, "foo"), "bar");
   3.463 -    EXPECT_STREQ((char *) cxMapGet(map, "hallo"), "welt");
   3.464 -
   3.465 -    test_map_generics_step_2(map);
   3.466 -
   3.467 -    EXPECT_EQ(map->size, 2);
   3.468 -    EXPECT_STREQ((char *) cxMapGet(map, "key"), "value");
   3.469 -    EXPECT_STREQ((char *) cxMapGet(map, "foo"), "bar");
   3.470 -
   3.471 -    test_map_generics_step_3(map);
   3.472 -
   3.473 -    EXPECT_EQ(map->size, 0);
   3.474 -
   3.475 -    cxMapDestroy(map);
   3.476 -    EXPECT_TRUE(allocator.verify());
   3.477 -}
   3.478 -
   3.479 -TEST(EmptyMap, Size) {
   3.480 -    auto map = cxEmptyMap;
   3.481 -
   3.482 -    EXPECT_EQ(map->size, 0);
   3.483 -}
   3.484 -
   3.485 -TEST(EmptyMap, Iterator) {
   3.486 -    auto map = cxEmptyMap;
   3.487 -
   3.488 -    auto it1 = cxMapIterator(map);
   3.489 -    auto it2 = cxMapIteratorValues(map);
   3.490 -    auto it3 = cxMapIteratorKeys(map);
   3.491 -    auto it4 = cxMapMutIterator(map);
   3.492 -    auto it5 = cxMapMutIteratorValues(map);
   3.493 -    auto it6 = cxMapMutIteratorKeys(map);
   3.494 -
   3.495 -    EXPECT_FALSE(cxIteratorValid(it1));
   3.496 -    EXPECT_FALSE(cxIteratorValid(it2));
   3.497 -    EXPECT_FALSE(cxIteratorValid(it3));
   3.498 -    EXPECT_FALSE(cxIteratorValid(it4));
   3.499 -    EXPECT_FALSE(cxIteratorValid(it5));
   3.500 -    EXPECT_FALSE(cxIteratorValid(it6));
   3.501 -
   3.502 -    int c = 0;
   3.503 -    cx_foreach(void*, data, it1) c++;
   3.504 -    cx_foreach(void*, data, it2) c++;
   3.505 -    cx_foreach(void*, data, it3) c++;
   3.506 -    cx_foreach(void*, data, it4) c++;
   3.507 -    cx_foreach(void*, data, it5) c++;
   3.508 -    cx_foreach(void*, data, it6) c++;
   3.509 -    EXPECT_EQ(c, 0);
   3.510 -}
   3.511 -
   3.512 -TEST(EmptyMap, NoOps) {
   3.513 -    auto map = cxEmptyMap;
   3.514 -
   3.515 -    ASSERT_NO_FATAL_FAILURE(cxMapClear(map));
   3.516 -    ASSERT_NO_FATAL_FAILURE(cxMapDestroy(map));
   3.517 -}
   3.518 -
   3.519 -TEST(EmptyMap, Get) {
   3.520 -    auto map = cxEmptyMap;
   3.521 -
   3.522 -    CxHashKey key = cx_hash_key_str("test");
   3.523 -    EXPECT_EQ(cxMapGet(map, key), nullptr);
   3.524 -}
     4.1 --- a/tests/test_map_generics.c	Sat Dec 30 15:21:16 2023 +0100
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,55 +0,0 @@
     4.4 -/*
     4.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.6 - *
     4.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     4.8 - *
     4.9 - * Redistribution and use in source and binary forms, with or without
    4.10 - * modification, are permitted provided that the following conditions are met:
    4.11 - *
    4.12 - *   1. Redistributions of source code must retain the above copyright
    4.13 - *      notice, this list of conditions and the following disclaimer.
    4.14 - *
    4.15 - *   2. Redistributions in binary form must reproduce the above copyright
    4.16 - *      notice, this list of conditions and the following disclaimer in the
    4.17 - *      documentation and/or other materials provided with the distribution.
    4.18 - *
    4.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    4.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    4.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    4.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    4.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    4.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    4.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    4.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    4.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    4.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    4.29 - * POSSIBILITY OF SUCH DAMAGE.
    4.30 - */
    4.31 -
    4.32 -#include "test_map_generics.h"
    4.33 -#include "cx/hash_map.h"
    4.34 -
    4.35 -CxMap *test_map_generics_step_1(CxAllocator const * allocator) {
    4.36 -    CxMap *map = cxHashMapCreate(allocator, sizeof(cxstring), 0);
    4.37 -
    4.38 -    cxMapPut(map, "test", "test");
    4.39 -    cxMapPut(map, cx_mutstr("foo"), "bar");
    4.40 -    cxMapPut(map, cx_str("hallo"), "welt");
    4.41 -
    4.42 -    return map;
    4.43 -}
    4.44 -
    4.45 -void test_map_generics_step_2(CxMap *map) {
    4.46 -    // note: we don't have a destructor here, so remove and detach are the same
    4.47 -    cxMapRemove(map, cx_str("test"));
    4.48 -    char const* hallo = "hallo";
    4.49 -    cxMapDetach(map, hallo);
    4.50 -    cxMapPut(map, cx_hash_key_str("key"), "value");
    4.51 -}
    4.52 -
    4.53 -void test_map_generics_step_3(CxMap *map) {
    4.54 -    void *r;
    4.55 -    r = cxMapRemoveAndGet(map, "key");
    4.56 -    r = cxMapRemoveAndGet(map, cx_str("foo"));
    4.57 -    if (r != NULL) map->size = 47;
    4.58 -}
     5.1 --- a/tests/test_map_generics.h	Sat Dec 30 15:21:16 2023 +0100
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,48 +0,0 @@
     5.4 -/*
     5.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 - *
     5.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     5.8 - *
     5.9 - * Redistribution and use in source and binary forms, with or without
    5.10 - * modification, are permitted provided that the following conditions are met:
    5.11 - *
    5.12 - *   1. Redistributions of source code must retain the above copyright
    5.13 - *      notice, this list of conditions and the following disclaimer.
    5.14 - *
    5.15 - *   2. Redistributions in binary form must reproduce the above copyright
    5.16 - *      notice, this list of conditions and the following disclaimer in the
    5.17 - *      documentation and/or other materials provided with the distribution.
    5.18 - *
    5.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    5.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    5.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    5.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    5.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    5.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    5.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    5.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    5.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    5.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    5.29 - * POSSIBILITY OF SUCH DAMAGE.
    5.30 - */
    5.31 -
    5.32 -#ifndef UCX_TEST_MAP_GENERICS_H
    5.33 -#define UCX_TEST_MAP_GENERICS_H
    5.34 -
    5.35 -#include "cx/map.h"
    5.36 -
    5.37 -#ifdef __cplusplus
    5.38 -extern "C" {
    5.39 -#endif
    5.40 -
    5.41 -CxMap *test_map_generics_step_1(CxAllocator const *);
    5.42 -
    5.43 -void test_map_generics_step_2(CxMap *);
    5.44 -
    5.45 -void test_map_generics_step_3(CxMap *);
    5.46 -
    5.47 -#ifdef __cplusplus
    5.48 -} // extern "C"
    5.49 -#endif
    5.50 -
    5.51 -#endif //UCX_TEST_MAP_GENERICS_H
     6.1 --- a/tests/test_mempool.c	Sat Dec 30 15:21:16 2023 +0100
     6.2 +++ b/tests/test_mempool.c	Sat Dec 30 18:48:25 2023 +0100
     6.3 @@ -97,7 +97,7 @@
     6.4          while (rdata == data) {
     6.5              n <<= 1;
     6.6              // eventually the memory should be moved elsewhere
     6.7 -            CX_TEST_ASSERTM(n < 65536, "Reallocation attempt failed - test not executable.");
     6.8 +            CX_TEST_ASSERTM(n < 65536, "Reallocation attempt failed - test not executable");
     6.9              rdata = cxRealloc(pool->allocator, data, n * sizeof(intptr_t));
    6.10          }
    6.11  
     7.1 --- a/tests/ucxtest.c	Sat Dec 30 15:21:16 2023 +0100
     7.2 +++ b/tests/ucxtest.c	Sat Dec 30 18:48:25 2023 +0100
     7.3 @@ -35,6 +35,7 @@
     7.4  CxTestSuite *cx_test_suite_string(void);
     7.5  CxTestSuite *cx_test_suite_printf(void);
     7.6  CxTestSuite *cx_test_suite_mempool(void);
     7.7 +CxTestSuite *cx_test_suite_hash_map(void);
     7.8  
     7.9  #define run_tests(suite) cx_test_run_stdout(suite); success += (suite)->success; failure += (suite)->failure
    7.10  #define execute_test_suites(...) unsigned success = 0, failure = 0; CxTestSuite* test_suites[] = {__VA_ARGS__}; \
    7.11 @@ -51,7 +52,8 @@
    7.12              cx_test_suite_allocator(),
    7.13              cx_test_suite_string(),
    7.14              cx_test_suite_printf(),
    7.15 -            cx_test_suite_mempool()
    7.16 +            cx_test_suite_mempool(),
    7.17 +            cx_test_suite_hash_map()
    7.18      );
    7.19      printf("=== OVERALL RESULT ===\n");
    7.20      printf("  Total:   %u\n  Success: %u\n  Failure: %u\n",

mercurial