Wed, 27 Dec 2023 16:04:38 +0100
migrates self-test for testing allocator - relates to #342
CHANGELOG | file | annotate | diff | comparison | revisions | |
tests/Makefile | file | annotate | diff | comparison | revisions | |
tests/ucxtest.c | file | annotate | diff | comparison | revisions | |
tests/util_allocator.c | file | annotate | diff | comparison | revisions | |
tests/util_allocator.cpp | file | annotate | diff | comparison | revisions | |
tests/util_allocator.h | file | annotate | diff | comparison | revisions |
1.1 --- a/CHANGELOG Wed Dec 27 14:54:04 2023 +0100 1.2 +++ b/CHANGELOG Wed Dec 27 16:04:38 2023 +0100 1.3 @@ -4,8 +4,10 @@ 1.4 * adds cxListFindRemove() 1.5 * adds cxBufferReset() 1.6 * adds cx_cmp_ptr() 1.7 + * adds improved version of UCX 2 Test framework (now a self-contained header) 1.8 * fixes wrong link from UCX 2 documentation to UCX 3 documentation 1.9 - * removes CMake, except for tests at the moment, in favor of uwproj 1.10 + * removes CMake 1.11 + * removes GTest dependency 1.12 1.13 Version 3.0 - 2023-07-09 1.14 ------------------------
2.1 --- a/tests/Makefile Wed Dec 27 14:54:04 2023 +0100 2.2 +++ b/tests/Makefile Wed Dec 27 16:04:38 2023 +0100 2.3 @@ -27,7 +27,7 @@ 2.4 2.5 TEST_DIR=$(build_dir)/tests 2.6 2.7 -SRC = test_utils.c test_hash_key.c ucxtest.c 2.8 +SRC = util_allocator.c test_utils.c test_hash_key.c ucxtest.c 2.9 2.10 OBJ_EXT=.o 2.11 OBJ=$(SRC:%.c=$(TEST_DIR)/%$(OBJ_EXT)) 2.12 @@ -69,3 +69,8 @@ 2.13 @echo "Compiling $<" 2.14 $(CC) -o $@ $(CFLAGS) -c $< 2.15 2.16 +$(TEST_DIR)/util_allocator$(OBJ_EXT): util_allocator.c util_allocator.h \ 2.17 + ../src/cx/allocator.h ../src/cx/common.h ../src/cx/test.h 2.18 + @echo "Compiling $<" 2.19 + $(CC) -o $@ $(CFLAGS) -c $< 2.20 +
3.1 --- a/tests/ucxtest.c Wed Dec 27 14:54:04 2023 +0100 3.2 +++ b/tests/ucxtest.c Wed Dec 27 16:04:38 2023 +0100 3.3 @@ -28,32 +28,27 @@ 3.4 3.5 #include "cx/test.h" 3.6 3.7 +CxTestSuite *cx_test_suite_testing_allocator(void); 3.8 CxTestSuite *cx_test_suite_utils(void); 3.9 CxTestSuite *cx_test_suite_hash_key(void); 3.10 3.11 #define run_tests(suite) cx_test_run_stdout(suite); success += (suite)->success; failure += (suite)->failure 3.12 +#define execute_test_suites(...) unsigned success = 0, failure = 0; CxTestSuite* test_suites[] = {__VA_ARGS__}; \ 3.13 + for (size_t i = 0; i < sizeof(test_suites)/sizeof(void*) ; i++) {run_tests(test_suites[i]);} (void)0 3.14 +#define free_test_suites for (size_t i = 0 ; i < sizeof(test_suites)/sizeof(void*) ; i++) {cx_test_suite_free(test_suites[i]);} (void)0 3.15 3.16 int main(void) { 3.17 printf("UCX Tests\n---------\n"); 3.18 3.19 - unsigned success = 0, failure = 0; 3.20 - 3.21 - // create test suites 3.22 - CxTestSuite 3.23 - *utils = cx_test_suite_utils(), 3.24 - *hash_key = cx_test_suite_hash_key(); 3.25 - 3.26 - // run tests 3.27 - run_tests(utils); 3.28 - run_tests(hash_key); 3.29 - 3.30 - // print overall result 3.31 + execute_test_suites( 3.32 + cx_test_suite_testing_allocator(), 3.33 + cx_test_suite_utils(), 3.34 + cx_test_suite_hash_key() 3.35 + ); 3.36 printf("=== OVERALL RESULT ===\n"); 3.37 printf(" Total: %u\n Success: %u\n Failure: %u\n", 3.38 success + failure, success, failure); 3.39 - 3.40 - cx_test_suite_free(utils); 3.41 - cx_test_suite_free(hash_key); 3.42 + free_test_suites; 3.43 3.44 return failure > 0 ? 1 : 0; 3.45 }
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/tests/util_allocator.c Wed Dec 27 16:04:38 2023 +0100 4.3 @@ -0,0 +1,253 @@ 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 "util_allocator.h" 4.33 +#include "cx/test.h" 4.34 + 4.35 +static void cx_testing_allocator_track(CxTestingAllocator *alloc, void *ptr) { 4.36 + for (size_t i = 0; i < alloc->tracked_count; i++) { 4.37 + if (alloc->tracked[i] == ptr) return; // is already tracked 4.38 + } 4.39 + 4.40 + if (alloc->tracked_count == alloc->tracked_capacity) { 4.41 + size_t newcapa = alloc->tracked_capacity + 64; 4.42 + void *newarr = realloc(alloc->tracked, newcapa * sizeof(void *)); 4.43 + if (newarr == NULL) abort(); 4.44 + alloc->tracked = newarr; 4.45 + alloc->tracked_capacity = newcapa; 4.46 + } 4.47 + 4.48 + alloc->tracked[alloc->tracked_count] = ptr; 4.49 + alloc->tracked_count++; 4.50 +} 4.51 + 4.52 +static bool cx_testing_allocator_untrack(CxTestingAllocator *alloc, void *ptr) { 4.53 + for (size_t i = 0; i < alloc->tracked_count; i++) { 4.54 + if (alloc->tracked[i] == ptr) { 4.55 + size_t last = alloc->tracked_count - 1; 4.56 + if (i < last) { 4.57 + alloc->tracked[i] = alloc->tracked[last]; 4.58 + } 4.59 + alloc->tracked_count--; 4.60 + return true; 4.61 + } 4.62 + } 4.63 + return false; 4.64 +} 4.65 + 4.66 +static void *cx_malloc_testing(void *d, size_t n) { 4.67 + CxTestingAllocator *data = d; 4.68 + void *ptr = malloc(n); 4.69 + data->alloc_total++; 4.70 + if (ptr == NULL) { 4.71 + data->alloc_failed++; 4.72 + } else { 4.73 + cx_testing_allocator_track(data, ptr); 4.74 + } 4.75 + return ptr; 4.76 +} 4.77 + 4.78 +static void *cx_realloc_testing(void *d, void *mem, size_t n) { 4.79 + CxTestingAllocator *data = d; 4.80 + void *ptr = realloc(mem, n); 4.81 + if (ptr == mem) { 4.82 + return ptr; 4.83 + } else { 4.84 + data->alloc_total++; 4.85 + if (ptr == NULL) { 4.86 + data->alloc_failed++; 4.87 + } else { 4.88 + data->free_total++; 4.89 + if (!cx_testing_allocator_untrack(data, mem)) { 4.90 + data->free_failed++; 4.91 + } 4.92 + cx_testing_allocator_track(data, ptr); 4.93 + } 4.94 + return ptr; 4.95 + } 4.96 +} 4.97 + 4.98 +static void *cx_calloc_testing(void *d, size_t nelem, size_t n) { 4.99 + CxTestingAllocator *data = d; 4.100 + void *ptr = calloc(nelem, n); 4.101 + data->alloc_total++; 4.102 + if (ptr == NULL) { 4.103 + data->alloc_failed++; 4.104 + } else { 4.105 + cx_testing_allocator_track(data, ptr); 4.106 + } 4.107 + return ptr; 4.108 +} 4.109 + 4.110 +static void cx_free_testing(void *d, void *mem) { 4.111 + CxTestingAllocator *data = d; 4.112 + data->free_total++; 4.113 + if (cx_testing_allocator_untrack(data, mem)) { 4.114 + free(mem); 4.115 + } else { 4.116 + data->free_failed++; 4.117 + // do not even attempt to free mem, because it is likely to segfault 4.118 + } 4.119 +} 4.120 + 4.121 +cx_allocator_class cx_testing_allocator_class = { 4.122 + cx_malloc_testing, 4.123 + cx_realloc_testing, 4.124 + cx_calloc_testing, 4.125 + cx_free_testing 4.126 +}; 4.127 + 4.128 + 4.129 +void cx_testing_allocator_init(CxTestingAllocator *alloc) { 4.130 + alloc->base.cl = &cx_testing_allocator_class; 4.131 + alloc->base.data = alloc; 4.132 + alloc->alloc_failed = 0; 4.133 + alloc->alloc_total = 0; 4.134 + alloc->free_failed = 0; 4.135 + alloc->free_total = 0; 4.136 + size_t initial_capa = 16; 4.137 + alloc->tracked_capacity = initial_capa; 4.138 + alloc->tracked_count = 0; 4.139 + alloc->tracked = calloc(sizeof(void *), initial_capa); 4.140 +} 4.141 + 4.142 +void cx_testing_allocator_destroy(CxTestingAllocator *alloc) { 4.143 + free(alloc->tracked); 4.144 +} 4.145 + 4.146 +bool cx_testing_allocator_used(CxTestingAllocator const *alloc) { 4.147 + return alloc->alloc_total > 0; 4.148 +} 4.149 + 4.150 +bool cx_testing_allocator_verify(CxTestingAllocator const *alloc) { 4.151 + return alloc->tracked_count == 0 && alloc->alloc_failed == 0 && alloc->free_failed == 0 4.152 + && alloc->alloc_total == alloc->free_total; 4.153 +} 4.154 + 4.155 +// SELF-TEST 4.156 + 4.157 +CX_TEST(test_util_allocator_expect_free) { 4.158 + CxTestingAllocator talloc; 4.159 + cx_testing_allocator_init(&talloc); 4.160 + CxAllocator *alloc = &talloc.base; 4.161 + CX_TEST_DO { 4.162 + CX_TEST_ASSERTM(cx_testing_allocator_verify(&talloc), 4.163 + "Fresh testing allocator fails to verify."); 4.164 + CX_TEST_ASSERTM(!cx_testing_allocator_used(&talloc), 4.165 + "Fresh testing allocator already used."); 4.166 + void *ptr = cxMalloc(alloc, 16); 4.167 + CX_TEST_ASSERTM(!cx_testing_allocator_verify(&talloc), 4.168 + "Testing allocator verifies with unfreed memory."); 4.169 + CX_TEST_ASSERT(cx_testing_allocator_used(&talloc)); 4.170 + CX_TEST_ASSERT(ptr != NULL); 4.171 + 4.172 + cxFree(alloc, ptr); 4.173 + CX_TEST_ASSERTM(cx_testing_allocator_verify(&talloc), 4.174 + "Testing allocator fails to verify after everything freed."); 4.175 + } 4.176 + cx_testing_allocator_destroy(&talloc); 4.177 +} 4.178 + 4.179 +CX_TEST(test_util_allocator_detect_double_free) { 4.180 + CxTestingAllocator talloc; 4.181 + cx_testing_allocator_init(&talloc); 4.182 + CxAllocator *alloc = &talloc.base; 4.183 + CX_TEST_DO { 4.184 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 4.185 + void *ptr = cxMalloc(alloc, 16); 4.186 + CX_TEST_ASSERT(ptr != NULL); 4.187 + cxFree(alloc, ptr); 4.188 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 4.189 + cxFree(alloc, ptr); 4.190 + CX_TEST_ASSERTM(!cx_testing_allocator_verify(&talloc), 4.191 + "Testing allocator does not detect double-free."); 4.192 + } 4.193 + cx_testing_allocator_destroy(&talloc); 4.194 +} 4.195 + 4.196 +CX_TEST(test_util_allocator_free_untracked) { 4.197 + CxTestingAllocator talloc; 4.198 + cx_testing_allocator_init(&talloc); 4.199 + CxAllocator *alloc = &talloc.base; 4.200 + void *ptr = malloc(16); 4.201 + CX_TEST_DO { 4.202 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 4.203 + cxFree(alloc, ptr); 4.204 + CX_TEST_ASSERTM(!cx_testing_allocator_verify(&talloc), 4.205 + "Testing allocator does not detect free of untracked memory."); 4.206 + } 4.207 + free(ptr); 4.208 + cx_testing_allocator_destroy(&talloc); 4.209 +} 4.210 + 4.211 +CX_TEST(test_util_allocator_full_lifecycle_with_realloc) { 4.212 + CxTestingAllocator talloc; 4.213 + cx_testing_allocator_init(&talloc); 4.214 + CxAllocator *alloc = &talloc.base; 4.215 + CX_TEST_DO { 4.216 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 4.217 + void *ptr = cxMalloc(alloc, 16); 4.218 + CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc)); 4.219 + CX_TEST_ASSERT(ptr != NULL); 4.220 + CX_TEST_ASSERT(talloc.tracked_count == 1); 4.221 + ptr = cxRealloc(alloc, ptr, 256); 4.222 + CX_TEST_ASSERT(!cx_testing_allocator_verify(&talloc)); 4.223 + CX_TEST_ASSERT(ptr != NULL); 4.224 + CX_TEST_ASSERT(talloc.tracked_count == 1); 4.225 + cxFree(alloc, ptr); 4.226 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 4.227 + } 4.228 + cx_testing_allocator_destroy(&talloc); 4.229 +} 4.230 + 4.231 +CX_TEST(test_util_allocator_calloc_initializes) { 4.232 + CxTestingAllocator talloc; 4.233 + cx_testing_allocator_init(&talloc); 4.234 + CxAllocator *alloc = &talloc.base; 4.235 + CX_TEST_DO { 4.236 + const char zeros[16] = {0}; 4.237 + void *ptr = cxCalloc(alloc, 16, 1); 4.238 + CX_TEST_ASSERT(memcmp(ptr, zeros, 16) == 0); 4.239 + cxFree(alloc, ptr); 4.240 + CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 4.241 + } 4.242 + cx_testing_allocator_destroy(&talloc); 4.243 +} 4.244 + 4.245 +CxTestSuite *cx_test_suite_testing_allocator(void) { 4.246 + CxTestSuite *suite = cx_test_suite_new("testing allocator self-test"); 4.247 + 4.248 + cx_test_register(suite, test_util_allocator_expect_free); 4.249 + cx_test_register(suite, test_util_allocator_detect_double_free); 4.250 + cx_test_register(suite, test_util_allocator_free_untracked); 4.251 + cx_test_register(suite, test_util_allocator_full_lifecycle_with_realloc); 4.252 + cx_test_register(suite, test_util_allocator_calloc_initializes); 4.253 + 4.254 + return suite; 4.255 +} 4.256 +
5.1 --- a/tests/util_allocator.cpp Wed Dec 27 14:54:04 2023 +0100 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,167 +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 -#include "util_allocator.h" 5.33 - 5.34 -void *cx_malloc_testing(void *d, size_t n) { 5.35 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 5.36 - void *ptr = malloc(n); 5.37 - data->alloc_total++; 5.38 - if (ptr == nullptr) { 5.39 - data->alloc_failed++; 5.40 - } else { 5.41 - data->tracked.insert(ptr); 5.42 - } 5.43 - return ptr; 5.44 -} 5.45 - 5.46 -void *cx_realloc_testing(void *d, void *mem, size_t n) { 5.47 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 5.48 - void *ptr = realloc(mem, n); 5.49 - if (ptr == mem) { 5.50 - return ptr; 5.51 - } else { 5.52 - data->alloc_total++; 5.53 - if (ptr == nullptr) { 5.54 - data->alloc_failed++; 5.55 - } else { 5.56 - data->free_total++; 5.57 - if (data->tracked.erase(mem) == 0) { 5.58 - data->free_failed++; 5.59 - } 5.60 - data->tracked.insert(ptr); 5.61 - } 5.62 - return ptr; 5.63 - } 5.64 -} 5.65 - 5.66 -void *cx_calloc_testing(void *d, size_t nelem, size_t n) { 5.67 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 5.68 - void *ptr = calloc(nelem, n); 5.69 - data->alloc_total++; 5.70 - if (ptr == nullptr) { 5.71 - data->alloc_failed++; 5.72 - } else { 5.73 - data->tracked.insert(ptr); 5.74 - } 5.75 - return ptr; 5.76 -} 5.77 - 5.78 -void cx_free_testing(void *d, void *mem) { 5.79 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 5.80 - data->free_total++; 5.81 - if (data->tracked.erase(mem) == 0) { 5.82 - data->free_failed++; 5.83 - // do not even attempt to free mem, because it is likely to segfault 5.84 - } else { 5.85 - free(mem); 5.86 - } 5.87 -} 5.88 - 5.89 -cx_allocator_class cx_testing_allocator_class = { 5.90 - cx_malloc_testing, 5.91 - cx_realloc_testing, 5.92 - cx_calloc_testing, 5.93 - cx_free_testing 5.94 -}; 5.95 - 5.96 -CxTestingAllocator::CxTestingAllocator() : CxAllocator() { 5.97 - cl = &cx_testing_allocator_class; 5.98 - data = this; 5.99 -} 5.100 - 5.101 -bool CxTestingAllocator::used() const { 5.102 - return alloc_total > 0; 5.103 -} 5.104 - 5.105 -bool CxTestingAllocator::verify() const { 5.106 - return tracked.empty() && alloc_failed == 0 && free_failed == 0 && alloc_total == free_total; 5.107 -} 5.108 - 5.109 -// SELF-TEST 5.110 - 5.111 -#include <gtest/gtest.h> 5.112 - 5.113 -TEST(TestingAllocator, ExpectFree) { 5.114 - CxTestingAllocator allocator; 5.115 - 5.116 - ASSERT_TRUE(allocator.verify()); 5.117 - EXPECT_FALSE(allocator.used()); 5.118 - auto ptr = cxMalloc(&allocator, 16); 5.119 - EXPECT_TRUE(allocator.used()); 5.120 - ASSERT_NE(ptr, nullptr); 5.121 - EXPECT_FALSE(allocator.verify()); 5.122 - 5.123 - cxFree(&allocator, ptr); 5.124 - EXPECT_TRUE(allocator.verify()); 5.125 -} 5.126 - 5.127 -TEST(TestingAllocator, DetectDoubleFree) { 5.128 - CxTestingAllocator allocator; 5.129 - 5.130 - ASSERT_TRUE(allocator.verify()); 5.131 - auto ptr = cxMalloc(&allocator, 16); 5.132 - ASSERT_NE(ptr, nullptr); 5.133 - 5.134 - cxFree(&allocator, ptr); 5.135 - EXPECT_TRUE(allocator.verify()); 5.136 - ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 5.137 - EXPECT_FALSE(allocator.verify()); 5.138 -} 5.139 - 5.140 -TEST(TestingAllocator, FreeUntracked) { 5.141 - CxTestingAllocator allocator; 5.142 - 5.143 - auto ptr = malloc(16); 5.144 - ASSERT_TRUE(allocator.verify()); 5.145 - ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 5.146 - EXPECT_FALSE(allocator.verify()); 5.147 - ASSERT_NO_FATAL_FAILURE(free(ptr)); 5.148 -} 5.149 - 5.150 -TEST(TestingAllocator, FullLifecycleWithRealloc) { 5.151 - CxTestingAllocator allocator; 5.152 - ASSERT_TRUE(allocator.verify()); 5.153 - auto ptr = cxMalloc(&allocator, 16); 5.154 - ASSERT_NE(ptr, nullptr); 5.155 - EXPECT_EQ(allocator.tracked.size(), 1); 5.156 - ptr = cxRealloc(&allocator, ptr, 256); 5.157 - ASSERT_NE(ptr, nullptr); 5.158 - EXPECT_EQ(allocator.tracked.size(), 1); 5.159 - cxFree(&allocator, ptr); 5.160 - EXPECT_TRUE(allocator.verify()); 5.161 -} 5.162 - 5.163 -TEST(TestingAllocator, CallocInitializes) { 5.164 - CxTestingAllocator allocator; 5.165 - const char zeros[16] = {0}; 5.166 - auto ptr = cxCalloc(&allocator, 16, 1); 5.167 - EXPECT_EQ(memcmp(ptr, zeros, 16), 0); 5.168 - cxFree(&allocator, ptr); 5.169 - EXPECT_TRUE(allocator.verify()); 5.170 -}
6.1 --- a/tests/util_allocator.h Wed Dec 27 14:54:04 2023 +0100 6.2 +++ b/tests/util_allocator.h Wed Dec 27 16:04:38 2023 +0100 6.3 @@ -26,56 +26,77 @@ 6.4 * POSSIBILITY OF SUCH DAMAGE. 6.5 */ 6.6 6.7 -#ifndef UCX_UTIL_ALLOCATOR_H 6.8 -#define UCX_UTIL_ALLOCATOR_H 6.9 +#ifndef UCX_TEST_UTIL_ALLOCATOR_H 6.10 +#define UCX_TEST_UTIL_ALLOCATOR_H 6.11 6.12 #include "cx/allocator.h" 6.13 6.14 -#include <set> 6.15 +#ifdef __cplusplus 6.16 +#extern "C" { 6.17 +#endif 6.18 6.19 -struct CxTestingAllocator : public CxAllocator { 6.20 +typedef struct CxTestingAllocator { 6.21 + CxAllocator base; 6.22 /** 6.23 * Total number of all allocations (malloc, calloc, realloc). 6.24 * A realloc() does only count when the memory has to be moved. 6.25 */ 6.26 - unsigned alloc_total = 0; 6.27 + unsigned alloc_total; 6.28 /** 6.29 * Number of failed allocations (malloc, calloc, realloc). 6.30 */ 6.31 - unsigned alloc_failed = 0; 6.32 + unsigned alloc_failed; 6.33 /** 6.34 * Total number of freed pointers. 6.35 * A reallocation also counts as a free when the memory has to be moved. 6.36 */ 6.37 - unsigned free_total = 0; 6.38 + unsigned free_total; 6.39 /** 6.40 * Number of failed free invocations. 6.41 * A free() is considered failed, if it has not been performed on tracked memory. 6.42 */ 6.43 - unsigned free_failed = 0; 6.44 + unsigned free_failed; 6.45 + /** 6.46 + * The number of currently tracked memory blocks. 6.47 + */ 6.48 + size_t tracked_count; 6.49 + /** 6.50 + * The capaciyty of the \c tracked array. 6.51 + */ 6.52 + size_t tracked_capacity; 6.53 /** 6.54 * The set of tracked memory blocks. 6.55 */ 6.56 - std::set<void *> tracked; 6.57 + void **tracked; 6.58 +} CxTestingAllocator; 6.59 6.60 - /** 6.61 - * Constructs a new testing allocator. 6.62 - */ 6.63 - CxTestingAllocator(); 6.64 6.65 - /** 6.66 - * Verifies that this allocator has been used. 6.67 - * 6.68 - * @return true if any allocation was attempted using this allocator 6.69 - */ 6.70 - [[nodiscard]] bool used() const; 6.71 +/** 6.72 + * Initializes a new testing allocator. 6.73 + */ 6.74 +void cx_testing_allocator_init(CxTestingAllocator *alloc); 6.75 6.76 - /** 6.77 - * Verifies that all allocated memory blocks are freed and no free occurred twice. 6.78 - * 6.79 - * @return true iff all tracked allocations / deallocations were valid 6.80 - */ 6.81 - [[nodiscard]] bool verify() const; 6.82 -}; 6.83 +/** 6.84 + * Destroys a testing allocator. 6.85 + */ 6.86 +void cx_testing_allocator_destroy(CxTestingAllocator *alloc); 6.87 6.88 -#endif // UCX_UTIL_ALLOCATOR_H 6.89 +/** 6.90 + * Verifies that this allocator has been used. 6.91 + * 6.92 + * @return true if any allocation was attempted using this allocator 6.93 + */ 6.94 +bool cx_testing_allocator_used(CxTestingAllocator const *alloc); 6.95 + 6.96 +/** 6.97 + * Verifies that all allocated memory blocks are freed and no free occurred twice. 6.98 + * 6.99 + * @return true iff all tracked allocations / deallocations were valid 6.100 + */ 6.101 +bool cx_testing_allocator_verify(CxTestingAllocator const *alloc); 6.102 + 6.103 +#ifdef __cplusplus 6.104 +} // extern "C" 6.105 +#endif 6.106 + 6.107 +#endif // UCX_TEST_UTIL_ALLOCATOR_H