UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2023 Mike Becker, Olaf Wintermann All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "cx/test.h" 30 31 #if __GNUC__ 32 // we want to perform overflow tests, but we don't want warnings about them 33 #define __alloc_size__(...) // NOLINT(*-reserved-identifier) 34 #endif 35 36 #include "cx/allocator.h" 37 #include <errno.h> 38 39 CX_TEST(test_allocator_stdlib_malloc) { 40 void *test = cxMalloc(cxStdlibAllocator, 16); 41 CX_TEST_DO { 42 CX_TEST_ASSERT(test != NULL); 43 // we cannot assert sth. but valgrind will detect an error 44 memcpy(test, "0123456789ABCDEF", 16); 45 } 46 cxFree(cxStdlibAllocator, test); 47 } 48 49 CX_TEST(test_allocator_stdlib_zalloc) { 50 void *test = cxZalloc(cxStdlibAllocator, 16); 51 CX_TEST_DO { 52 CX_TEST_ASSERT(test != NULL); 53 CX_TEST_ASSERT(0 == memcmp(test, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)); 54 } 55 cxFree(cxStdlibAllocator, test); 56 } 57 58 CX_TEST(test_allocator_stdlib_calloc) { 59 char *test = cxCalloc(cxStdlibAllocator, 8, 2); 60 CX_TEST_DO { 61 CX_TEST_ASSERT(test != NULL); 62 for (int i = 0; i < 16; i++) { 63 CX_TEST_ASSERT(test[i] == 0); 64 } 65 } 66 cxFree(cxStdlibAllocator, test); 67 } 68 69 CX_TEST(test_allocator_stdlib_realloc) { 70 char *test = cxCalloc(cxStdlibAllocator, 8, 1); 71 memcpy(test, "Test", 5); 72 CX_TEST_DO { 73 test = cxRealloc(cxStdlibAllocator, test, 16); 74 CX_TEST_ASSERT(test != NULL); 75 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 76 } 77 cxFree(cxStdlibAllocator, test); 78 } 79 80 CX_TEST(test_allocator_stdlib_reallocarray) { 81 char *test = cxCalloc(cxStdlibAllocator, 8, 1); 82 memcpy(test, "Test", 5); 83 CX_TEST_DO { 84 test = cxReallocArray(cxStdlibAllocator, test, 16, 2); 85 CX_TEST_ASSERT(test != NULL); 86 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 87 } 88 cxFree(cxStdlibAllocator, test); 89 } 90 91 CX_TEST(test_allocator_stdlib_reallocarray_overflow) { 92 char *test = cxCalloc(cxStdlibAllocator, 8, 1); 93 memcpy(test, "Test", 5); 94 CX_TEST_DO { 95 void *fail = cxReallocArray(cxStdlibAllocator, test, SIZE_MAX/2, 4); 96 CX_TEST_ASSERT(errno == EOVERFLOW); 97 CX_TEST_ASSERT(fail == NULL); 98 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 99 } 100 cxFree(cxStdlibAllocator, test); 101 } 102 103 CX_TEST(test_allocator_stdlib_free) { 104 void *test = cxMalloc(cxStdlibAllocator, 16); 105 CX_TEST_DO { 106 // we cannot assert sth. but valgrind will detect an error 107 cxFree(cxStdlibAllocator, test); 108 CX_TEST_ASSERT(true); 109 } 110 } 111 112 CX_TEST(test_allocator_default_malloc) { 113 void *test = cxMallocDefault(16); 114 CX_TEST_DO { 115 CX_TEST_ASSERT(test != NULL); 116 // we cannot assert sth. but valgrind will detect an error 117 memcpy(test, "0123456789ABCDEF", 16); 118 } 119 cxFreeDefault(test); 120 } 121 122 CX_TEST(test_allocator_default_zalloc) { 123 void *test = cxZallocDefault(16); 124 CX_TEST_DO { 125 CX_TEST_ASSERT(test != NULL); 126 CX_TEST_ASSERT(0 == memcmp(test, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)); 127 } 128 cxFreeDefault(test); 129 } 130 131 CX_TEST(test_allocator_default_calloc) { 132 char *test = cxCallocDefault(8, 2); 133 CX_TEST_DO { 134 CX_TEST_ASSERT(test != NULL); 135 for (int i = 0; i < 16; i++) { 136 CX_TEST_ASSERT(test[i] == 0); 137 } 138 } 139 cxFreeDefault(test); 140 } 141 142 CX_TEST(test_allocator_default_realloc) { 143 char *test = cxCallocDefault(8, 1); 144 memcpy(test, "Test", 5); 145 CX_TEST_DO { 146 test = cxReallocDefault(test, 16); 147 CX_TEST_ASSERT(test != NULL); 148 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 149 } 150 cxFreeDefault(test); 151 } 152 153 CX_TEST(test_allocator_default_reallocarray) { 154 char *test = cxCallocDefault(8, 1); 155 memcpy(test, "Test", 5); 156 CX_TEST_DO { 157 test = cxReallocArrayDefault(test, 16, 2); 158 CX_TEST_ASSERT(test != NULL); 159 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 160 } 161 cxFreeDefault(test); 162 } 163 164 CX_TEST(test_allocator_default_reallocarray_overflow) { 165 char *test = cxCallocDefault(8, 1); 166 memcpy(test, "Test", 5); 167 CX_TEST_DO { 168 void *fail = cxReallocArrayDefault(test, SIZE_MAX/2, 4); 169 CX_TEST_ASSERT(errno == EOVERFLOW); 170 CX_TEST_ASSERT(fail == NULL); 171 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 172 } 173 cxFreeDefault(test); 174 } 175 176 CX_TEST(test_allocator_default_free) { 177 void *test = cxMallocDefault(16); 178 CX_TEST_DO { 179 // we cannot assert sth. but valgrind will detect an error 180 cxFreeDefault(test); 181 CX_TEST_ASSERT(true); 182 } 183 } 184 185 CX_TEST(test_allocator_reallocate) { 186 char *test = cxCallocDefault(8, 1); 187 memcpy(test, "Test", 5); 188 CX_TEST_DO { 189 int ret = cxReallocateDefault(&test, 16); 190 CX_TEST_ASSERT(ret == 0); 191 CX_TEST_ASSERT(test != NULL); 192 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 193 } 194 cxFreeDefault(test); 195 } 196 197 CX_TEST(test_allocator_reallocate_low_level) { 198 void *test = calloc(8, 1); 199 memcpy(test, "Test", 5); 200 CX_TEST_DO { 201 int ret = cx_reallocate(&test, 16); 202 CX_TEST_ASSERT(ret == 0); 203 CX_TEST_ASSERT(test != NULL); 204 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 205 } 206 free(test); 207 } 208 209 CX_TEST(test_allocator_reallocatearray) { 210 char *test = cxCallocDefault(8, 1); 211 memcpy(test, "Test", 5); 212 CX_TEST_DO { 213 int ret = cxReallocateArrayDefault(&test, 16, 2); 214 CX_TEST_ASSERT(ret == 0); 215 CX_TEST_ASSERT(test != NULL); 216 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 217 } 218 cxFreeDefault(test); 219 } 220 221 CX_TEST(test_allocator_reallocatearray_overflow) { 222 char *test = cxCallocDefault(8, 1); 223 memcpy(test, "Test", 5); 224 CX_TEST_DO { 225 int ret = cxReallocateArrayDefault(&test, SIZE_MAX/2, 4); 226 CX_TEST_ASSERT(ret != 0); 227 CX_TEST_ASSERT(errno == EOVERFLOW); 228 CX_TEST_ASSERT(test != NULL); 229 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 230 } 231 cxFreeDefault(test); 232 } 233 234 CX_TEST(test_allocator_reallocatearray_low_level) { 235 char *test = calloc(8, 1); 236 memcpy(test, "Test", 5); 237 CX_TEST_DO { 238 int ret = cx_reallocatearray(&test, 16, 2); 239 CX_TEST_ASSERT(ret == 0); 240 CX_TEST_ASSERT(test != NULL); 241 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 242 } 243 free(test); 244 } 245 246 CX_TEST(test_allocator_reallocatearray_low_level_overflow) { 247 char *test = calloc(8, 1); 248 memcpy(test, "Test", 5); 249 CX_TEST_DO { 250 int ret = cx_reallocatearray(&test, SIZE_MAX/2, 4); 251 CX_TEST_ASSERT(ret != 0); 252 CX_TEST_ASSERT(errno == EOVERFLOW); 253 CX_TEST_ASSERT(test != NULL); 254 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 255 } 256 free(test); 257 } 258 259 static void *test_allocator_mock_failing_realloc( 260 cx_attr_unused void *p, 261 cx_attr_unused void *d, 262 cx_attr_unused size_t n 263 ) { 264 return NULL; 265 } 266 267 CX_TEST(test_allocator_reallocate_fails) { 268 // Mock an allocator that always returns NULL on realloc 269 cx_allocator_class mock_cl; 270 mock_cl.realloc = test_allocator_mock_failing_realloc; 271 CxAllocator mock = {&mock_cl, NULL}; 272 273 void *test = calloc(8, 1); 274 memcpy(test, "Test", 5); 275 void *original = test; 276 CX_TEST_DO { 277 int ret = cxReallocate(&mock, &test, 16); 278 // non-zero return code because of the failure 279 CX_TEST_ASSERT(ret != 0); 280 // the test pointer was not changed and still points to the same memory 281 CX_TEST_ASSERT(test == original); 282 CX_TEST_ASSERT(0 == strcmp(test, "Test")); 283 } 284 free(test); 285 } 286 287 CxTestSuite *cx_test_suite_allocator(void) { 288 CxTestSuite *suite = cx_test_suite_new("allocator"); 289 290 cx_test_register(suite, test_allocator_stdlib_malloc); 291 cx_test_register(suite, test_allocator_stdlib_zalloc); 292 cx_test_register(suite, test_allocator_stdlib_calloc); 293 cx_test_register(suite, test_allocator_stdlib_realloc); 294 cx_test_register(suite, test_allocator_stdlib_reallocarray); 295 cx_test_register(suite, test_allocator_stdlib_reallocarray_overflow); 296 cx_test_register(suite, test_allocator_stdlib_free); 297 cx_test_register(suite, test_allocator_default_malloc); 298 cx_test_register(suite, test_allocator_default_zalloc); 299 cx_test_register(suite, test_allocator_default_calloc); 300 cx_test_register(suite, test_allocator_default_realloc); 301 cx_test_register(suite, test_allocator_default_reallocarray); 302 cx_test_register(suite, test_allocator_default_reallocarray_overflow); 303 cx_test_register(suite, test_allocator_default_free); 304 cx_test_register(suite, test_allocator_reallocate); 305 cx_test_register(suite, test_allocator_reallocate_fails); 306 cx_test_register(suite, test_allocator_reallocate_low_level); 307 cx_test_register(suite, test_allocator_reallocatearray); 308 cx_test_register(suite, test_allocator_reallocatearray_overflow); 309 cx_test_register(suite, test_allocator_reallocatearray_low_level); 310 cx_test_register(suite, test_allocator_reallocatearray_low_level_overflow); 311 312 return suite; 313 } 314