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 #include "util_allocator.h" 31 32 #include "cx/mempool.h" 33 34 #include <errno.h> 35 36 static unsigned test_mempool_destructor_called; 37 38 static void test_mempool_destructor(cx_attr_unused void *mem) { 39 test_mempool_destructor_called++; 40 } 41 42 static void test_mempool_destructor2(void *data, cx_attr_unused void *mem) { 43 int *ctr = data; 44 *ctr = *ctr + 1; 45 } 46 47 CX_TEST(test_mempool_create) { 48 CxMempool *pool = cxMempoolCreateSimple(16); 49 CX_TEST_DO { 50 CX_TEST_ASSERT(pool->destr == NULL); 51 CX_TEST_ASSERT(pool->destr2 == NULL); 52 CX_TEST_ASSERT(pool->destr2_data == NULL); 53 CX_TEST_ASSERT(pool->allocator != NULL); 54 CX_TEST_ASSERT(pool->allocator->cl != NULL); 55 CX_TEST_ASSERT(pool->allocator->data == pool); 56 CX_TEST_ASSERT(pool->allocator->cl->malloc != NULL); 57 CX_TEST_ASSERT(pool->allocator->cl->calloc != NULL); 58 CX_TEST_ASSERT(pool->allocator->cl->realloc != NULL); 59 CX_TEST_ASSERT(pool->allocator->cl->free != NULL); 60 CX_TEST_ASSERT(pool->capacity == 16); 61 CX_TEST_ASSERT(pool->size == 0); 62 CX_TEST_ASSERT(pool->data != NULL); 63 } 64 cxMempoolFree(pool); 65 } 66 67 static CX_TEST_SUBROUTINE(test_mempool_malloc_verify, CxMempool *pool) { 68 CX_TEST_ASSERT(cxMalloc(pool->allocator, sizeof(int)) != NULL); 69 CX_TEST_ASSERT(cxMalloc(pool->allocator, sizeof(int)) != NULL); 70 CX_TEST_ASSERT(pool->size == 2); 71 CX_TEST_ASSERT(pool->capacity == 4); 72 CX_TEST_ASSERT(cxMalloc(pool->allocator, sizeof(int)) != NULL); 73 CX_TEST_ASSERT(cxMalloc(pool->allocator, sizeof(int)) != NULL); 74 CX_TEST_ASSERT(pool->size == 4); 75 CX_TEST_ASSERT(pool->capacity == 4); 76 CX_TEST_ASSERT(cxMalloc(pool->allocator, sizeof(int)) != NULL); 77 int *i = cxMalloc(pool->allocator, sizeof(int)); 78 CX_TEST_ASSERT(i != NULL); 79 *i = 4083914; // let asan / valgrind check 80 CX_TEST_ASSERT(pool->size == 6); 81 CX_TEST_ASSERT(pool->capacity >= 6); 82 } 83 84 CX_TEST(test_mempool_malloc0) { 85 CxMempool *pool = cxMempoolCreatePure(4); 86 CX_TEST_DO { 87 CX_TEST_CALL_SUBROUTINE(test_mempool_malloc_verify, pool); 88 } 89 cxMempoolFree(pool); 90 } 91 92 CX_TEST(test_mempool_malloc) { 93 CxMempool *pool = cxMempoolCreateSimple(4); 94 CX_TEST_DO { 95 CX_TEST_CALL_SUBROUTINE(test_mempool_malloc_verify, pool); 96 } 97 cxMempoolFree(pool); 98 } 99 100 CX_TEST(test_mempool_malloc2) { 101 CxMempool *pool = cxMempoolCreateAdvanced(4); 102 CX_TEST_DO { 103 CX_TEST_CALL_SUBROUTINE(test_mempool_malloc_verify, pool); 104 } 105 cxMempoolFree(pool); 106 } 107 108 static CX_TEST_SUBROUTINE(test_mempool_calloc_verify, CxMempool *pool) { 109 int *test = cxCalloc(pool->allocator, 2, sizeof(int)); 110 CX_TEST_ASSERT(test != NULL); 111 CX_TEST_ASSERT(test[0] == 0); 112 CX_TEST_ASSERT(test[1] == 0); 113 #if __GNUC__ > 11 114 // we want to explicitly test the overflow 115 #pragma GCC diagnostic push 116 #pragma GCC diagnostic ignored "-Walloc-size-larger-than=" 117 #endif 118 errno = 0; 119 CX_TEST_ASSERT(NULL == cxCalloc(pool->allocator, SIZE_MAX / 2, sizeof(int))); 120 CX_TEST_ASSERT(errno == EOVERFLOW); 121 #if __GNUC__ > 11 122 #pragma GCC diagnostic pop 123 #endif 124 } 125 126 CX_TEST(test_mempool_calloc0) { 127 CxMempool *pool = cxMempoolCreatePure(4); 128 CX_TEST_DO { 129 CX_TEST_CALL_SUBROUTINE(test_mempool_calloc_verify, pool); 130 } 131 cxMempoolFree(pool); 132 } 133 134 CX_TEST(test_mempool_calloc) { 135 CxMempool *pool = cxMempoolCreateSimple(4); 136 CX_TEST_DO { 137 CX_TEST_CALL_SUBROUTINE(test_mempool_calloc_verify, pool); 138 } 139 cxMempoolFree(pool); 140 } 141 142 CX_TEST(test_mempool_calloc2) { 143 CxMempool *pool = cxMempoolCreateAdvanced(4); 144 CX_TEST_DO { 145 CX_TEST_CALL_SUBROUTINE(test_mempool_calloc_verify, pool); 146 } 147 cxMempoolFree(pool); 148 } 149 150 static CX_TEST_SUBROUTINE(test_mempool_realloc_verify, CxMempool *pool, enum cx_mempool_type type) { 151 // use realloc with NULL which shall behave as a malloc 152 int *data = cxRealloc(pool->allocator, NULL, 2*sizeof(int)); 153 if (type == CX_MEMPOOL_TYPE_SIMPLE) { 154 cxMempoolSetDestructor(data, test_mempool_destructor); 155 } else if (type == CX_MEMPOOL_TYPE_ADVANCED) { 156 cxMempoolSetDestructor2(data, test_mempool_destructor2, &test_mempool_destructor_called); 157 } 158 *data = 13; 159 160 // shrink to actual sizeof(int) 161 data = cxRealloc(pool->allocator, data, sizeof(int)); 162 CX_TEST_ASSERT(*data == 13); 163 164 // realloc with the same size (should not do anything) 165 data = cxRealloc(pool->allocator, data, sizeof(int)); 166 CX_TEST_ASSERT(*data == 13); 167 168 // now try hard to trigger a memmove 169 int *rdata = data; 170 unsigned n = 1; 171 while (rdata == data) { 172 n <<= 1; 173 // eventually the memory should be moved elsewhere 174 CX_TEST_ASSERTM(n < 65536, "Reallocation attempt failed - test not executable"); 175 rdata = cxRealloc(pool->allocator, data, n * sizeof(intptr_t)); 176 } 177 178 CX_TEST_ASSERT(*rdata == 13); 179 // test if destructor is still intact 180 if (type != CX_MEMPOOL_TYPE_PURE) { 181 test_mempool_destructor_called = 0; 182 cxFree(pool->allocator, rdata); 183 CX_TEST_ASSERT(test_mempool_destructor_called == 1); 184 } 185 } 186 187 CX_TEST(test_mempool_realloc0) { 188 CxMempool *pool = cxMempoolCreatePure(4); 189 CX_TEST_DO { 190 CX_TEST_CALL_SUBROUTINE(test_mempool_realloc_verify, pool, CX_MEMPOOL_TYPE_PURE); 191 } 192 cxMempoolFree(pool); 193 } 194 195 CX_TEST(test_mempool_realloc) { 196 CxMempool *pool = cxMempoolCreateSimple(4); 197 CX_TEST_DO { 198 CX_TEST_CALL_SUBROUTINE(test_mempool_realloc_verify, pool, CX_MEMPOOL_TYPE_SIMPLE); 199 } 200 cxMempoolFree(pool); 201 } 202 203 CX_TEST(test_mempool_realloc2) { 204 CxMempool *pool = cxMempoolCreateAdvanced(4); 205 CX_TEST_DO { 206 CX_TEST_CALL_SUBROUTINE(test_mempool_realloc_verify, pool, CX_MEMPOOL_TYPE_ADVANCED); 207 } 208 cxMempoolFree(pool); 209 } 210 211 static CX_TEST_SUBROUTINE(test_mempool_free_verify, CxMempool *pool) { 212 void *mem1, *mem2; 213 mem1 = cxMalloc(pool->allocator, 16); 214 cxFree(pool->allocator, mem1); 215 CX_TEST_ASSERT(pool->size == 0); 216 217 mem1 = cxMalloc(pool->allocator, 16); 218 mem1 = cxMalloc(pool->allocator, 16); 219 mem1 = cxMalloc(pool->allocator, 16); 220 mem2 = cxMalloc(pool->allocator, 16); 221 mem2 = cxMalloc(pool->allocator, 16); 222 223 CX_TEST_ASSERT(pool->size == 5); 224 // a realloc with size zero shall behave like a free 225 void *freed = cxRealloc(pool->allocator, mem1, 0); 226 CX_TEST_ASSERT(freed == NULL); 227 CX_TEST_ASSERT(pool->size == 4); 228 cxFree(pool->allocator, mem2); 229 CX_TEST_ASSERT(pool->size == 3); 230 } 231 232 CX_TEST(test_mempool_free0) { 233 CxMempool *pool = cxMempoolCreatePure(4); 234 CX_TEST_DO { 235 CX_TEST_CALL_SUBROUTINE(test_mempool_free_verify, pool); 236 } 237 cxMempoolFree(pool); 238 } 239 240 CX_TEST(test_mempool_free) { 241 CxMempool *pool = cxMempoolCreateSimple(4); 242 CX_TEST_DO { 243 CX_TEST_CALL_SUBROUTINE(test_mempool_free_verify, pool); 244 } 245 cxMempoolFree(pool); 246 } 247 248 CX_TEST(test_mempool_free2) { 249 CxMempool *pool = cxMempoolCreateAdvanced(4); 250 CX_TEST_DO { 251 CX_TEST_CALL_SUBROUTINE(test_mempool_free_verify, pool); 252 } 253 cxMempoolFree(pool); 254 } 255 256 CX_TEST(test_mempool_destroy) { 257 CxMempool *pool = cxMempoolCreateSimple(4); 258 CX_TEST_DO { 259 int *data = cxMalloc(pool->allocator, sizeof(int)); 260 *data = 13; 261 cxMempoolSetDestructor(data, test_mempool_destructor); 262 CX_TEST_ASSERT(*data == 13); 263 test_mempool_destructor_called = 0; 264 cxFree(pool->allocator, data); 265 CX_TEST_ASSERT(test_mempool_destructor_called == 1); 266 data = cxMalloc(pool->allocator, sizeof(int)); 267 cxMempoolSetDestructor(data, test_mempool_destructor); 268 cxMempoolFree(pool); 269 CX_TEST_ASSERT(test_mempool_destructor_called == 2); 270 } 271 } 272 273 CX_TEST(test_mempool_destroy2) { 274 CxMempool *pool = cxMempoolCreateAdvanced(4); 275 CX_TEST_DO { 276 int *data = cxMalloc(pool->allocator, sizeof(int)); 277 int ctr = 0; 278 *data = 47; 279 cxMempoolSetDestructor2(data, test_mempool_destructor2, &ctr); 280 CX_TEST_ASSERT(*data == 47); 281 cxFree(pool->allocator, data); 282 CX_TEST_ASSERT(ctr == 1); 283 data = cxMalloc(pool->allocator, sizeof(int)); 284 cxMempoolSetDestructor2(data, test_mempool_destructor2, &ctr); 285 cxMempoolFree(pool); 286 CX_TEST_ASSERT(ctr == 2); 287 } 288 } 289 290 CX_TEST(test_mempool_remove_destructor) { 291 CxMempool *pool = cxMempoolCreateSimple(4); 292 CX_TEST_DO { 293 int *data = cxMalloc(pool->allocator, sizeof(int)); 294 *data = 13; 295 cxMempoolSetDestructor(data, test_mempool_destructor); 296 CX_TEST_ASSERT(*data == 13); 297 cxMempoolRemoveDestructor(data); 298 CX_TEST_ASSERT(*data == 13); 299 test_mempool_destructor_called = 0; 300 cxFree(pool->allocator, data); 301 CX_TEST_ASSERT(test_mempool_destructor_called == 0); 302 data = cxMalloc(pool->allocator, sizeof(int)); 303 *data = 99; 304 cxMempoolSetDestructor(data, test_mempool_destructor); 305 cxMempoolRemoveDestructor(data); 306 CX_TEST_ASSERT(*data == 99); 307 cxMempoolFree(pool); 308 CX_TEST_ASSERT(test_mempool_destructor_called == 0); 309 } 310 } 311 312 CX_TEST(test_mempool_remove_destructor2) { 313 CxMempool *pool = cxMempoolCreateAdvanced(4); 314 CX_TEST_DO { 315 int *data = cxMalloc(pool->allocator, sizeof(int)); 316 int ctr = 0; 317 *data = 47; 318 cxMempoolSetDestructor2(data, test_mempool_destructor2, &ctr); 319 CX_TEST_ASSERT(*data == 47); 320 cxMempoolRemoveDestructor2(data); 321 CX_TEST_ASSERT(*data == 47); 322 cxFree(pool->allocator, data); 323 CX_TEST_ASSERT(ctr == 0); 324 data = cxMalloc(pool->allocator, sizeof(int)); 325 *data = 99; 326 cxMempoolSetDestructor2(data, test_mempool_destructor2, &ctr); 327 cxMempoolRemoveDestructor2(data); 328 CX_TEST_ASSERT(*data == 99); 329 cxMempoolFree(pool); 330 CX_TEST_ASSERT(ctr == 0); 331 } 332 } 333 334 static CX_TEST_SUBROUTINE(test_mempool_global_destructors_verify, CxMempool *pool) { 335 int *data = cxMalloc(pool->allocator, sizeof(int)); 336 int ctr = 0; 337 cxMempoolGlobalDestructor(pool, test_mempool_destructor); 338 cxMempoolGlobalDestructor2(pool, test_mempool_destructor2, &ctr); 339 test_mempool_destructor_called = 0; 340 cxFree(pool->allocator, data); 341 CX_TEST_ASSERT(ctr == 1); 342 CX_TEST_ASSERT(test_mempool_destructor_called == 1); 343 data = cxMalloc(pool->allocator, sizeof(int)); 344 cxMempoolFree(pool); 345 CX_TEST_ASSERT(ctr == 2); 346 CX_TEST_ASSERT(test_mempool_destructor_called == 2); 347 } 348 349 CX_TEST(test_mempool_global_destructors0) { 350 CxMempool *pool = cxMempoolCreatePure(4); 351 CX_TEST_DO { 352 CX_TEST_CALL_SUBROUTINE(test_mempool_global_destructors_verify, pool); 353 } 354 } 355 356 CX_TEST(test_mempool_global_destructors) { 357 CxMempool *pool = cxMempoolCreateSimple(4); 358 CX_TEST_DO { 359 CX_TEST_CALL_SUBROUTINE(test_mempool_global_destructors_verify, pool); 360 } 361 } 362 363 CX_TEST(test_mempool_global_destructors2) { 364 CxMempool *pool = cxMempoolCreateAdvanced(4); 365 CX_TEST_DO { 366 CX_TEST_CALL_SUBROUTINE(test_mempool_global_destructors_verify, pool); 367 } 368 } 369 370 CX_TEST(test_mempool_register) { 371 CxMempool *pool = cxMempoolCreateAdvanced(4); 372 CX_TEST_DO { 373 int *data = cxMalloc(pool->allocator, sizeof(int)); 374 test_mempool_destructor_called = 0; 375 cxMempoolSetDestructor2(data, test_mempool_destructor2, &test_mempool_destructor_called); 376 int donotfree = 0; 377 cxMempoolRegister(pool, &donotfree, test_mempool_destructor); 378 cxMempoolFree(pool); 379 CX_TEST_ASSERT(test_mempool_destructor_called == 2); 380 } 381 } 382 383 CX_TEST(test_mempool_register2) { 384 CxMempool *pool = cxMempoolCreateSimple(4); 385 CX_TEST_DO { 386 int *data = cxMalloc(pool->allocator, sizeof(int)); 387 test_mempool_destructor_called = 0; 388 cxMempoolSetDestructor(data, test_mempool_destructor); 389 int donotfree = 0; 390 cxMempoolRegister2(pool, &donotfree, test_mempool_destructor2, &test_mempool_destructor_called); 391 cxMempoolFree(pool); 392 CX_TEST_ASSERT(test_mempool_destructor_called == 2); 393 } 394 } 395 396 CX_TEST(test_mempool_transfer) { 397 CxMempool *src = cxMempoolCreateSimple(4); 398 CxMempool *dest = cxMempoolCreateSimple(4); 399 CX_TEST_DO { 400 // allocate the first object 401 int *c = cxMalloc(src->allocator, sizeof(int)); 402 // check that the destructor functions are also transferred 403 cxMempoolSetDestructor(c, test_mempool_destructor); 404 // allocate the second object 405 c = cxMalloc(src->allocator, sizeof(int)); 406 cxMempoolSetDestructor(c, test_mempool_destructor); 407 408 409 // check source pool 410 CX_TEST_ASSERT(src->size == 2); 411 CX_TEST_ASSERT(src->registered_size == 0); 412 const CxAllocator *old_allocator = src->allocator; 413 CX_TEST_ASSERT(old_allocator->data == src); 414 415 // perform transfer 416 int result = cxMempoolTransfer(src, dest); 417 CX_TEST_ASSERT(result == 0); 418 419 // check transfer 420 CX_TEST_ASSERT(src->size == 0); 421 CX_TEST_ASSERT(dest->size == 2); 422 CX_TEST_ASSERT(src->registered_size == 0); 423 CX_TEST_ASSERT(dest->registered_size == 1); // the old allocator 424 CX_TEST_ASSERT(src->allocator != old_allocator); 425 CX_TEST_ASSERT(old_allocator->data == dest); 426 427 // verify that destroying old pool does nothing 428 test_mempool_destructor_called = 0; 429 cxMempoolFree(src); 430 CX_TEST_ASSERT(test_mempool_destructor_called == 0); 431 432 // cover illegal arguments 433 result = cxMempoolTransfer(dest, dest); 434 CX_TEST_ASSERT(result != 0); 435 436 // verify that destroying new pool calls the destructors 437 // but only two times (the old allocator has a different destructor) 438 cxMempoolFree(dest); 439 CX_TEST_ASSERT(test_mempool_destructor_called == 2); 440 } 441 } 442 443 CX_TEST(test_mempool_transfer_with_foreign_memory) { 444 CxMempool *src = cxMempoolCreateSimple(4); 445 CxMempool *dest = cxMempoolCreateSimple(4); 446 CX_TEST_DO { 447 // allocate the first object 448 int *c = cxMalloc(src->allocator, sizeof(int)); 449 // allocate the second object 450 c = cxMalloc(src->allocator, sizeof(int)); 451 // check that the destructor functions are also transferred 452 cxMempoolSetDestructor(c, test_mempool_destructor); 453 // register foreign object 454 c = malloc(sizeof(int)); 455 cxMempoolRegister(src, c, test_mempool_destructor); 456 457 // check source pool 458 CX_TEST_ASSERT(src->size == 2); 459 CX_TEST_ASSERT(src->registered_size == 1); 460 const CxAllocator *old_allocator = src->allocator; 461 CX_TEST_ASSERT(old_allocator->data == src); 462 463 // perform transfer 464 int result = cxMempoolTransfer(src, dest); 465 CX_TEST_ASSERT(result == 0); 466 467 // check transfer 468 CX_TEST_ASSERT(src->size == 0); 469 CX_TEST_ASSERT(dest->size == 2); 470 CX_TEST_ASSERT(src->registered_size == 0); 471 CX_TEST_ASSERT(dest->registered_size == 2); // 1 object + old allocator 472 CX_TEST_ASSERT(src->allocator != old_allocator); 473 CX_TEST_ASSERT(old_allocator->data == dest); 474 475 // verify that destroying old pool does nothing 476 test_mempool_destructor_called = 0; 477 cxMempoolFree(src); 478 CX_TEST_ASSERT(test_mempool_destructor_called == 0); 479 480 // verify that destroying new pool calls the destructors 481 // but only two times (the old allocator has a different destructor) 482 cxMempoolFree(dest); 483 CX_TEST_ASSERT(test_mempool_destructor_called == 2); 484 485 // free the foreign object 486 free(c); 487 } 488 } 489 490 CX_TEST(test_mempool_transfer_foreign_memory_only) { 491 CxMempool *src = cxMempoolCreateSimple(4); 492 CxMempool *dest = cxMempoolCreateSimple(4); 493 int *a = malloc(sizeof(int)); 494 int *b = malloc(sizeof(int)); 495 CX_TEST_DO { 496 // register foreign objects 497 cxMempoolRegister(src, a, test_mempool_destructor); 498 cxMempoolRegister(src, b, test_mempool_destructor); 499 500 // check source pool 501 CX_TEST_ASSERT(src->size == 0); 502 CX_TEST_ASSERT(src->registered_size == 2); 503 const CxAllocator *old_allocator = src->allocator; 504 CX_TEST_ASSERT(old_allocator->data == src); 505 506 // perform transfer 507 int result = cxMempoolTransfer(src, dest); 508 CX_TEST_ASSERT(result == 0); 509 510 // check transfer 511 CX_TEST_ASSERT(src->size == 0); 512 CX_TEST_ASSERT(dest->size == 0); 513 CX_TEST_ASSERT(src->registered_size == 0); 514 CX_TEST_ASSERT(dest->registered_size == 3); // 2 objects + old allocator 515 CX_TEST_ASSERT(src->allocator != old_allocator); 516 CX_TEST_ASSERT(old_allocator->data == dest); 517 518 // verify that destroying old pool does nothing 519 test_mempool_destructor_called = 0; 520 cxMempoolFree(src); 521 CX_TEST_ASSERT(test_mempool_destructor_called == 0); 522 523 // verify that destroying new pool calls the destructors 524 // but only two times (the old allocator has a different destructor) 525 cxMempoolFree(dest); 526 CX_TEST_ASSERT(test_mempool_destructor_called == 2); 527 } 528 free(a); 529 free(b); 530 } 531 532 CX_TEST(test_mempool_transfer_object) { 533 CxMempool *src = cxMempoolCreateSimple(4); 534 CxMempool *dest = cxMempoolCreateSimple(4); 535 CX_TEST_DO { 536 int *a = cxMalloc(src->allocator, sizeof(int)); 537 int *b = cxMalloc(src->allocator, sizeof(int)); 538 int *c = malloc(sizeof(int)); 539 cxMempoolRegister(src, c, free); 540 int *d = malloc(sizeof(int)); 541 cxMempoolRegister(src, d, free); 542 CX_TEST_ASSERT(src->size == 2); 543 CX_TEST_ASSERT(src->registered_size == 2); 544 545 int result = cxMempoolTransferObject(src, dest, a); 546 CX_TEST_ASSERT(result == 0); 547 CX_TEST_ASSERT(src->size == 1); 548 CX_TEST_ASSERT(src->registered_size == 2); 549 CX_TEST_ASSERT(dest->size == 1); 550 CX_TEST_ASSERT(dest->registered_size == 0); 551 result = cxMempoolTransferObject(src, dest, a); 552 CX_TEST_ASSERT(result != 0); 553 CX_TEST_ASSERT(src->size == 1); 554 CX_TEST_ASSERT(src->registered_size == 2); 555 CX_TEST_ASSERT(dest->size == 1); 556 CX_TEST_ASSERT(dest->registered_size == 0); 557 558 // can also transfer foreign memory this way 559 result = cxMempoolTransferObject(src, dest, c); 560 CX_TEST_ASSERT(result == 0); 561 CX_TEST_ASSERT(src->size == 1); 562 CX_TEST_ASSERT(src->registered_size == 1); 563 CX_TEST_ASSERT(dest->size == 1); 564 CX_TEST_ASSERT(dest->registered_size == 1); 565 566 // src==dest is an error 567 result = cxMempoolTransferObject(dest, dest, b); 568 CX_TEST_ASSERT(result != 0); 569 CX_TEST_ASSERT(src->size == 1); 570 CX_TEST_ASSERT(dest->size == 1); 571 572 // check that we don't die when we free memory that's still in the source pool 573 cxFree(src->allocator, b); 574 } 575 cxMempoolFree(src); 576 cxMempoolFree(dest); 577 // let valgrind check that everything else worked 578 } 579 580 CxTestSuite *cx_test_suite_mempool(void) { 581 CxTestSuite *suite = cx_test_suite_new("mempool"); 582 583 cx_test_register(suite, test_mempool_create); 584 cx_test_register(suite, test_mempool_malloc0); 585 cx_test_register(suite, test_mempool_calloc0); 586 cx_test_register(suite, test_mempool_realloc0); 587 cx_test_register(suite, test_mempool_free0); 588 cx_test_register(suite, test_mempool_malloc); 589 cx_test_register(suite, test_mempool_calloc); 590 cx_test_register(suite, test_mempool_realloc); 591 cx_test_register(suite, test_mempool_free); 592 cx_test_register(suite, test_mempool_destroy); 593 cx_test_register(suite, test_mempool_malloc2); 594 cx_test_register(suite, test_mempool_calloc2); 595 cx_test_register(suite, test_mempool_realloc2); 596 cx_test_register(suite, test_mempool_free2); 597 cx_test_register(suite, test_mempool_destroy2); 598 cx_test_register(suite, test_mempool_remove_destructor); 599 cx_test_register(suite, test_mempool_remove_destructor2); 600 cx_test_register(suite, test_mempool_global_destructors0); 601 cx_test_register(suite, test_mempool_global_destructors); 602 cx_test_register(suite, test_mempool_global_destructors2); 603 cx_test_register(suite, test_mempool_register); 604 cx_test_register(suite, test_mempool_register2); 605 cx_test_register(suite, test_mempool_transfer); 606 cx_test_register(suite, test_mempool_transfer_with_foreign_memory); 607 cx_test_register(suite, test_mempool_transfer_foreign_memory_only); 608 cx_test_register(suite, test_mempool_transfer_object); 609 610 return suite; 611 } 612