| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789 |
- /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include <stdint.h>
- #include <string.h>
- #include <cmocka.h>
- #if WAMR_BUILD_TEST != 1
- #error "WAMR_BUILD_TEST must be defined as 1"
- #endif
- #include "mem_alloc.h"
- #include "ems_gc_internal.h"
- #include "wasm_export.h"
- /* Test helper: Check if pointer is aligned */
- static inline bool
- is_aligned(void *ptr, size_t alignment)
- {
- return ((uintptr_t)ptr % alignment) == 0;
- }
- /* Test helper: Check if allocation is aligned (has magic value) */
- static inline bool
- is_aligned_allocation(gc_object_t obj)
- {
- uint32_t *magic_ptr = (uint32_t *)((char *)obj - 4);
- return ((*magic_ptr & ALIGNED_ALLOC_MAGIC_MASK)
- == ALIGNED_ALLOC_MAGIC_VALUE);
- }
- /* Test: Normal allocation still works (regression) */
- static void
- test_normal_alloc_basic(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[64 * 1024];
- void *ptr;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Normal allocation should still work */
- ptr = mem_allocator_malloc(allocator, 128);
- assert_non_null(ptr);
- /* Should be 8-byte aligned */
- assert_true(is_aligned(ptr, 8));
- /* Should NOT be marked as aligned allocation */
- assert_false(is_aligned_allocation(ptr));
- /* Free should work */
- mem_allocator_free(allocator, ptr);
- mem_allocator_destroy(allocator);
- }
- /* Test: Valid alignment powers of 2 */
- static void
- test_aligned_alloc_valid_alignments(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[128 * 1024];
- void *ptr;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Test each valid alignment */
- int alignments[] = { 8, 16, 32, 64, 128, 256, 512, 1024 };
- int num_alignments = sizeof(alignments) / sizeof(alignments[0]);
- for (int i = 0; i < num_alignments; i++) {
- int align = alignments[i];
- /* Allocate with size = multiple of alignment */
- ptr = mem_allocator_malloc_aligned(allocator, align * 2, align);
- assert_non_null(ptr);
- /* Verify alignment */
- assert_true(is_aligned(ptr, align));
- /* Verify marked as aligned */
- assert_true(is_aligned_allocation(ptr));
- /* Free */
- mem_allocator_free(allocator, ptr);
- }
- mem_allocator_destroy(allocator);
- }
- /* Test: Realloc rejects aligned allocations */
- static void
- test_realloc_rejects_aligned(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[64 * 1024];
- void *ptr, *new_ptr;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Allocate aligned */
- ptr = mem_allocator_malloc_aligned(allocator, 128, 64);
- assert_non_null(ptr);
- assert_true(is_aligned_allocation(ptr));
- /* Realloc should reject aligned allocation */
- new_ptr = mem_allocator_realloc(allocator, ptr, 256);
- assert_null(new_ptr);
- /* Original pointer should still be valid - free it */
- mem_allocator_free(allocator, ptr);
- mem_allocator_destroy(allocator);
- }
- /* Test: Realloc still works for normal allocations */
- static void
- test_normal_realloc_works(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[64 * 1024];
- void *ptr, *new_ptr;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Allocate normal */
- ptr = mem_allocator_malloc(allocator, 128);
- assert_non_null(ptr);
- /* Write some data */
- memset(ptr, 0xAB, 128);
- /* Realloc should work */
- new_ptr = mem_allocator_realloc(allocator, ptr, 256);
- assert_non_null(new_ptr);
- /* Data should be preserved */
- for (int i = 0; i < 128; i++) {
- assert_int_equal(((unsigned char *)new_ptr)[i], 0xAB);
- }
- mem_allocator_free(allocator, new_ptr);
- mem_allocator_destroy(allocator);
- }
- /* Test: Invalid alignments (not power of 2 or zero) */
- static void
- test_aligned_alloc_invalid_not_power_of_2(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[64 * 1024];
- void *ptr;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* These should all fail (zero or not power of 2) */
- int invalid_alignments[] = { 0, 3, 5, 7, 9, 15, 17, 100 };
- int num_invalid =
- sizeof(invalid_alignments) / sizeof(invalid_alignments[0]);
- for (int i = 0; i < num_invalid; i++) {
- ptr =
- mem_allocator_malloc_aligned(allocator, 128, invalid_alignments[i]);
- assert_null(ptr);
- }
- /* Small powers of 2 should succeed (adjusted to GC_MIN_ALIGNMENT) */
- ptr = mem_allocator_malloc_aligned(allocator, 8, 1);
- assert_non_null(ptr);
- mem_allocator_free(allocator, ptr);
- ptr = mem_allocator_malloc_aligned(allocator, 8, 2);
- assert_non_null(ptr);
- mem_allocator_free(allocator, ptr);
- ptr = mem_allocator_malloc_aligned(allocator, 8, 4);
- assert_non_null(ptr);
- mem_allocator_free(allocator, ptr);
- mem_allocator_destroy(allocator);
- }
- /* Test: Size must be multiple of alignment */
- static void
- test_aligned_alloc_size_not_multiple(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[64 * 1024];
- void *ptr;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Size not multiple of alignment - should fail */
- ptr = mem_allocator_malloc_aligned(allocator, 100, 64);
- assert_null(ptr);
- ptr = mem_allocator_malloc_aligned(allocator, 65, 64);
- assert_null(ptr);
- /* Size is multiple - should succeed */
- ptr = mem_allocator_malloc_aligned(allocator, 128, 64);
- assert_non_null(ptr);
- mem_allocator_free(allocator, ptr);
- mem_allocator_destroy(allocator);
- }
- /* Test: Mixed normal and aligned allocations */
- static void
- test_mixed_alloc_interleaved(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[128 * 1024];
- void *normal1, *aligned1, *normal2, *aligned2;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Allocate: normal -> aligned -> normal -> aligned */
- normal1 = mem_allocator_malloc(allocator, 64);
- assert_non_null(normal1);
- assert_false(is_aligned_allocation(normal1));
- aligned1 = mem_allocator_malloc_aligned(allocator, 128, 64);
- assert_non_null(aligned1);
- assert_true(is_aligned_allocation(aligned1));
- assert_true(is_aligned(aligned1, 64));
- normal2 = mem_allocator_malloc(allocator, 96);
- assert_non_null(normal2);
- assert_false(is_aligned_allocation(normal2));
- aligned2 = mem_allocator_malloc_aligned(allocator, 256, 128);
- assert_non_null(aligned2);
- assert_true(is_aligned_allocation(aligned2));
- assert_true(is_aligned(aligned2, 128));
- /* Free in mixed order */
- mem_allocator_free(allocator, normal1);
- mem_allocator_free(allocator, aligned2);
- mem_allocator_free(allocator, normal2);
- mem_allocator_free(allocator, aligned1);
- mem_allocator_destroy(allocator);
- }
- /* Test: obj_to_hmu works correctly for both types */
- static void
- test_mixed_obj_to_hmu(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[64 * 1024];
- void *normal, *aligned;
- hmu_t *hmu_normal, *hmu_aligned;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Allocate both types */
- normal = mem_allocator_malloc(allocator, 128);
- assert_non_null(normal);
- aligned = mem_allocator_malloc_aligned(allocator, 128, 64);
- assert_non_null(aligned);
- /* Get HMU pointers */
- hmu_normal = obj_to_hmu(normal);
- hmu_aligned = obj_to_hmu(aligned);
- assert_non_null(hmu_normal);
- assert_non_null(hmu_aligned);
- /* Both should have HMU_VO type */
- assert_int_equal(hmu_get_ut(hmu_normal), HMU_VO);
- assert_int_equal(hmu_get_ut(hmu_aligned), HMU_VO);
- /* Sizes should be reasonable */
- assert_true(hmu_get_size(hmu_normal) >= 128);
- assert_true(hmu_get_size(hmu_aligned) >= 128);
- /* Free both */
- mem_allocator_free(allocator, normal);
- mem_allocator_free(allocator, aligned);
- mem_allocator_destroy(allocator);
- }
- /* Test: Many aligned allocations */
- static void
- test_aligned_alloc_many(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[512 * 1024];
- void *ptrs[100];
- int count = 0;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Allocate as many as possible */
- for (int i = 0; i < 100; i++) {
- int align = (i % 4 == 0) ? 64 : 32;
- ptrs[i] = mem_allocator_malloc_aligned(allocator, align * 2, align);
- if (ptrs[i]) {
- assert_true(is_aligned(ptrs[i], align));
- count++;
- }
- else {
- break;
- }
- }
- assert_true(count > 10); /* At least some should succeed */
- /* Free all */
- for (int i = 0; i < count; i++) {
- mem_allocator_free(allocator, ptrs[i]);
- }
- mem_allocator_destroy(allocator);
- }
- /* Test: Many mixed allocations */
- static void
- test_mixed_alloc_many(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[512 * 1024];
- void *ptrs[200];
- int count = 0;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Alternate normal and aligned */
- for (int i = 0; i < 200; i++) {
- if (i % 2 == 0) {
- /* Normal allocation */
- ptrs[i] = mem_allocator_malloc(allocator, 64);
- }
- else {
- /* Aligned allocation */
- ptrs[i] = mem_allocator_malloc_aligned(allocator, 64, 32);
- }
- if (ptrs[i]) {
- count++;
- }
- else {
- break;
- }
- }
- assert_true(count > 20);
- /* Free in reverse order */
- for (int i = count - 1; i >= 0; i--) {
- mem_allocator_free(allocator, ptrs[i]);
- }
- mem_allocator_destroy(allocator);
- }
- /* Test: free a .ro data */
- static void
- test_free_ro_data(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[64 * 1024];
- void *ptr;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Freeing a .ro data pointer should not crash */
- const char *ro_str = "This is a read-only string.";
- // FIXME: This case should trigger an exception because the pointer is not
- // allocated by the allocator, but currently it just does nothing. We should
- // add a check in mem_allocator_free to detect this case and return an
- // error. mem_allocator_free(allocator, (void *)ro_str);
- mem_allocator_destroy(allocator);
- }
- /* Test: free a freed pointer */
- static void
- test_free_freed_pointer(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[64 * 1024];
- void *ptr;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- ptr = mem_allocator_malloc(allocator, 64);
- assert_non_null(ptr);
- mem_allocator_free(allocator, ptr);
- /* Freeing the same pointer again should not crash */
- mem_allocator_free(allocator, ptr);
- mem_allocator_free(allocator, ptr);
- mem_allocator_destroy(allocator);
- }
- /* Test: free a freed pointer from aligned-alloc */
- static void
- test_free_freed_pointer_aligned(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[64 * 1024];
- void *ptr;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- ptr = mem_allocator_malloc_aligned(allocator, 128, 64);
- assert_non_null(ptr);
- mem_allocator_free(allocator, ptr);
- /* Freeing the same pointer again should not crash */
- mem_allocator_free(allocator, ptr);
- mem_allocator_free(allocator, ptr);
- mem_allocator_free(allocator, ptr);
- mem_allocator_destroy(allocator);
- }
- /* Test: wasm_runtime_aligned_alloc with valid inputs in POOL mode */
- static void
- test_wasm_runtime_aligned_alloc_valid(void **state)
- {
- RuntimeInitArgs init_args;
- void *ptr;
- memset(&init_args, 0, sizeof(RuntimeInitArgs));
- init_args.mem_alloc_type = Alloc_With_Pool;
- init_args.mem_alloc_option.pool.heap_buf = malloc(256 * 1024);
- init_args.mem_alloc_option.pool.heap_size = 256 * 1024;
- assert_true(wasm_runtime_full_init(&init_args));
- /* Test valid aligned allocation */
- ptr = wasm_runtime_aligned_alloc(128, 64);
- assert_non_null(ptr);
- assert_true(is_aligned(ptr, 64));
- /* Free should work */
- wasm_runtime_free(ptr);
- wasm_runtime_destroy();
- free(init_args.mem_alloc_option.pool.heap_buf);
- }
- /* Test: wasm_runtime_aligned_alloc with zero size */
- static void
- test_wasm_runtime_aligned_alloc_zero_size(void **state)
- {
- RuntimeInitArgs init_args;
- void *ptr;
- memset(&init_args, 0, sizeof(RuntimeInitArgs));
- init_args.mem_alloc_type = Alloc_With_Pool;
- init_args.mem_alloc_option.pool.heap_buf = malloc(256 * 1024);
- init_args.mem_alloc_option.pool.heap_size = 256 * 1024;
- assert_true(wasm_runtime_full_init(&init_args));
- /* Zero size should allocate alignment bytes (like malloc(0) behavior) */
- ptr = wasm_runtime_aligned_alloc(0, 64);
- assert_non_null(ptr);
- assert_true(is_aligned(ptr, 64));
- wasm_runtime_free(ptr);
- wasm_runtime_destroy();
- free(init_args.mem_alloc_option.pool.heap_buf);
- }
- /* Test: wasm_runtime_aligned_alloc with zero alignment */
- static void
- test_wasm_runtime_aligned_alloc_zero_alignment(void **state)
- {
- RuntimeInitArgs init_args;
- void *ptr;
- memset(&init_args, 0, sizeof(RuntimeInitArgs));
- init_args.mem_alloc_type = Alloc_With_Pool;
- init_args.mem_alloc_option.pool.heap_buf = malloc(256 * 1024);
- init_args.mem_alloc_option.pool.heap_size = 256 * 1024;
- assert_true(wasm_runtime_full_init(&init_args));
- /* Zero alignment should return NULL */
- ptr = wasm_runtime_aligned_alloc(128, 0);
- assert_null(ptr);
- wasm_runtime_destroy();
- free(init_args.mem_alloc_option.pool.heap_buf);
- }
- /* Test: wasm_runtime_aligned_alloc in SYSTEM_ALLOCATOR mode returns NULL */
- static void
- test_wasm_runtime_aligned_alloc_system_mode(void **state)
- {
- RuntimeInitArgs init_args;
- void *ptr;
- memset(&init_args, 0, sizeof(RuntimeInitArgs));
- init_args.mem_alloc_type = Alloc_With_System_Allocator;
- assert_true(wasm_runtime_full_init(&init_args));
- /* Should return NULL in non-POOL mode */
- ptr = wasm_runtime_aligned_alloc(128, 64);
- assert_null(ptr);
- wasm_runtime_destroy();
- }
- /* Test: wasm_runtime_realloc rejects aligned allocations */
- static void
- test_wasm_runtime_realloc_rejects_aligned(void **state)
- {
- RuntimeInitArgs init_args;
- void *ptr, *new_ptr;
- memset(&init_args, 0, sizeof(RuntimeInitArgs));
- init_args.mem_alloc_type = Alloc_With_Pool;
- init_args.mem_alloc_option.pool.heap_buf = malloc(256 * 1024);
- init_args.mem_alloc_option.pool.heap_size = 256 * 1024;
- assert_true(wasm_runtime_full_init(&init_args));
- /* Allocate with alignment */
- ptr = wasm_runtime_aligned_alloc(128, 64);
- assert_non_null(ptr);
- /* Realloc should return NULL */
- new_ptr = wasm_runtime_realloc(ptr, 256);
- assert_null(new_ptr);
- /* Original pointer still valid */
- wasm_runtime_free(ptr);
- wasm_runtime_destroy();
- free(init_args.mem_alloc_option.pool.heap_buf);
- }
- /* Test: wasm_runtime_aligned_alloc with various alignments */
- static void
- test_wasm_runtime_aligned_alloc_multiple_alignments(void **state)
- {
- RuntimeInitArgs init_args;
- int alignments[] = { 8, 16, 32, 64, 128, 256 };
- int num_alignments = sizeof(alignments) / sizeof(alignments[0]);
- memset(&init_args, 0, sizeof(RuntimeInitArgs));
- init_args.mem_alloc_type = Alloc_With_Pool;
- init_args.mem_alloc_option.pool.heap_buf = malloc(512 * 1024);
- init_args.mem_alloc_option.pool.heap_size = 512 * 1024;
- assert_true(wasm_runtime_full_init(&init_args));
- for (int i = 0; i < num_alignments; i++) {
- int align = alignments[i];
- void *ptr = wasm_runtime_aligned_alloc(align * 2, align);
- assert_non_null(ptr);
- assert_true(is_aligned(ptr, align));
- wasm_runtime_free(ptr);
- }
- wasm_runtime_destroy();
- free(init_args.mem_alloc_option.pool.heap_buf);
- }
- /* Test: Normal allocation with huge size (near upper limit) */
- static void
- test_normal_alloc_huge_size(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[1024 * 1024]; /* 1MB heap */
- void *ptr;
- size_t huge_size;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Try to allocate most of the heap */
- huge_size = sizeof(heap_buf) - 4096; /* Leave some overhead */
- ptr = mem_allocator_malloc(allocator, huge_size);
- /* May succeed or fail depending on internal fragmentation */
- if (ptr) {
- /* If it succeeds, verify it's properly allocated */
- assert_true(is_aligned(ptr, 8));
- mem_allocator_free(allocator, ptr);
- }
- /* Try allocation at exact upper limit - should handle gracefully */
- huge_size = SIZE_MAX - 1024;
- ptr = mem_allocator_malloc(allocator, huge_size);
- assert_null(ptr); /* Should fail gracefully, not crash */
- mem_allocator_destroy(allocator);
- }
- /* Test: Aligned allocation with huge size (near upper limit) */
- static void
- test_aligned_alloc_huge_size(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[1024 * 1024]; /* 1MB heap */
- void *ptr;
- size_t huge_size;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Try to allocate most of the heap with alignment */
- huge_size = 512 * 1024; /* Size must be multiple of alignment */
- ptr = mem_allocator_malloc_aligned(allocator, huge_size, 512);
- /* May succeed or fail depending on alignment overhead */
- if (ptr) {
- assert_true(is_aligned(ptr, 512));
- mem_allocator_free(allocator, ptr);
- }
- /* Try allocation at extreme size - should fail gracefully */
- huge_size = (SIZE_MAX / 2) & ~(size_t)4095; /* Aligned to 4096 */
- ptr = mem_allocator_malloc_aligned(allocator, huge_size, 4096);
- assert_null(ptr); /* Should fail gracefully, not crash */
- mem_allocator_destroy(allocator);
- }
- /* Test: Normal allocations until OOM */
- static void
- test_normal_alloc_until_oom(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[256 * 1024];
- void *ptrs[1000];
- int count = 0;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Allocate until we run out of memory */
- for (int i = 0; i < 1000; i++) {
- ptrs[i] = mem_allocator_malloc(allocator, 1024);
- if (ptrs[i]) {
- count++;
- }
- else {
- /* OOM reached - this is expected */
- break;
- }
- }
- /* Should have allocated at least some blocks */
- assert_true(count > 10);
- assert_true(count < 1000); /* Should not have allocated all */
- /* Should still be able to free what we allocated */
- for (int i = 0; i < count; i++) {
- mem_allocator_free(allocator, ptrs[i]);
- }
- /* After freeing, should be able to allocate again */
- void *ptr = mem_allocator_malloc(allocator, 1024);
- assert_non_null(ptr);
- mem_allocator_free(allocator, ptr);
- mem_allocator_destroy(allocator);
- }
- /* Test: Aligned allocations until OOM */
- static void
- test_aligned_alloc_until_oom(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[512 * 1024];
- void *ptrs[500];
- int count = 0;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Allocate with alignment until we run out of memory */
- for (int i = 0; i < 500; i++) {
- /* Alternate between different alignments */
- int align = (i % 2 == 0) ? 64 : 128;
- ptrs[i] = mem_allocator_malloc_aligned(allocator, align * 20, align);
- if (ptrs[i]) {
- assert_true(is_aligned(ptrs[i], align));
- count++;
- }
- else {
- /* OOM reached - this is expected */
- break;
- }
- }
- /* Should have allocated at least some blocks */
- assert_true(count > 5);
- assert_true(count < 500); /* Should not have allocated all */
- /* Free all allocated blocks */
- for (int i = 0; i < count; i++) {
- mem_allocator_free(allocator, ptrs[i]);
- }
- /* After freeing, should be able to allocate again */
- void *ptr = mem_allocator_malloc_aligned(allocator, 256, 64);
- assert_non_null(ptr);
- mem_allocator_free(allocator, ptr);
- mem_allocator_destroy(allocator);
- }
- /* Test: Mixed normal and aligned allocations until OOM */
- static void
- test_mixed_alloc_until_oom(void **state)
- {
- mem_allocator_t allocator;
- char heap_buf[128 * 1024];
- void *ptrs[1000];
- bool is_aligned_alloc[1000];
- int count = 0;
- allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
- assert_non_null(allocator);
- /* Alternate between normal and aligned allocations until OOM */
- for (int i = 0; i < 1000; i++) {
- if (i % 3 == 0) {
- /* Aligned allocation */
- ptrs[i] = mem_allocator_malloc_aligned(allocator, 128, 64);
- is_aligned_alloc[i] = true;
- }
- else {
- /* Normal allocation */
- ptrs[i] = mem_allocator_malloc(allocator, 512);
- is_aligned_alloc[i] = false;
- }
- if (ptrs[i]) {
- if (is_aligned_alloc[i]) {
- assert_true(is_aligned(ptrs[i], 64));
- }
- count++;
- }
- else {
- /* OOM reached */
- break;
- }
- }
- /* Should have allocated a reasonable number of blocks */
- assert_true(count > 20);
- assert_true(count < 1000); /* Should not have allocated all */
- /* Free in random order (every other block first) */
- for (int i = 0; i < count; i += 2) {
- mem_allocator_free(allocator, ptrs[i]);
- }
- for (int i = 1; i < count; i += 2) {
- mem_allocator_free(allocator, ptrs[i]);
- }
- /* Verify allocator still works after OOM and free */
- void *ptr1 = mem_allocator_malloc(allocator, 1024);
- void *ptr2 = mem_allocator_malloc_aligned(allocator, 128, 64);
- assert_non_null(ptr1);
- assert_non_null(ptr2);
- mem_allocator_free(allocator, ptr1);
- mem_allocator_free(allocator, ptr2);
- mem_allocator_destroy(allocator);
- }
|