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