#include #include "malunal/allocators/arena.h" const malunal_size_t page_bytes = 4096; const malunal_size_t init_bytes = sizeof(malunal_int32_t) * 4; const malunal_size_t final_bytes = sizeof(malunal_int32_t) * 8; static allocator_acquire_res_t test_arena_acquires(allocator_mptr_t arena) { allocator_acquire_res_t result = allocator_acquire((allocator_acquire_req_t) { .allocator = arena, .size = init_bytes }); if (result.threw) return result; // Upstream checks. if (arena->upstream->reserved != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->reserved != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->upstream->reserved); return (allocator_acquire_res_t) { .threw = 1, .exception = ALLOCATOR_EXCEPTION_FAILURE }; } if (arena->upstream->allocated != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->allocated != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->upstream->allocated); return (allocator_acquire_res_t) { .threw = 1, .exception = ALLOCATOR_EXCEPTION_FAILURE }; } if (arena->upstream->acquires != 1) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->acquires != 1, actual == %d"; fprintf(stderr, format, arena->upstream->acquires); return (allocator_acquire_res_t) { .threw = 1, .exception = ALLOCATOR_EXCEPTION_FAILURE }; } if (arena->upstream->releases != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->releases != 0, actual == %d"; fprintf(stderr, format, arena->upstream->releases); return (allocator_acquire_res_t) { .threw = 1, .exception = ALLOCATOR_EXCEPTION_FAILURE }; } // Arena checks. if (arena->reserved != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->reserved != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->reserved); return (allocator_acquire_res_t) { .threw = 1, .exception = ALLOCATOR_EXCEPTION_FAILURE }; } if (arena->allocated != init_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->allocated != %d, actual == %d"; fprintf(stderr, format, init_bytes, arena->allocated); return (allocator_acquire_res_t) { .threw = 1, .exception = ALLOCATOR_EXCEPTION_FAILURE }; } if (arena->acquires != 1) { const malunal_cstr_t format = "[arena_allocator]: arena->acquires != 1, actual == %d"; fprintf(stderr, format, arena->acquires); return (allocator_acquire_res_t) { .threw = 1, .exception = ALLOCATOR_EXCEPTION_FAILURE }; } if (arena->releases != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->releases != 0, actual == %d"; fprintf(stderr, format, arena->releases); return (allocator_acquire_res_t) { .threw = 1, .exception = ALLOCATOR_EXCEPTION_FAILURE }; } return result; } static int test_arena_reacquire( allocator_mptr_t arena, malunal_mptr_t address ) { malunal_int32_t index; malunal_int32_t* vector; vector = address; for (index = 0; index < 4; index++) vector[index] = index + 1; allocator_acquire_res_t result = allocator_reacquire((allocator_reacquire_req_t) { .allocator = arena, .prev = result.address, .oldsz = init_bytes, .newsz = final_bytes }); if (result.threw) return result.exception; // Upstream checks. if (arena->upstream->reserved != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->reserved != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->upstream->reserved); return 1; } if (arena->upstream->allocated != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->allocated != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->upstream->allocated); return 1; } if (arena->upstream->acquires != 1) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->acquires != 1, actual == %d"; fprintf(stderr, format, arena->upstream->acquires); return 1; } if (arena->upstream->releases != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->releases != 0, actual == %d"; fprintf(stderr, format, arena->upstream->releases); return 1; } // Arena checks. if (arena->reserved != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->reserved != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->reserved); return 1; } malunal_int32_t all_bytes = init_bytes + final_bytes; if (arena->allocated != all_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->allocated != %d, actual == %d"; fprintf(stderr, format, all_bytes, arena->allocated); return 1; } if (arena->acquires != 2) { const malunal_cstr_t format = "[arena_allocator]: arena->acquires != 2, actual == %d"; fprintf(stderr, format, arena->acquires); return 1; } if (arena->releases != 1) { const malunal_cstr_t format = "[arena_allocator]: arena->releases != 1, actual == %d"; fprintf(stderr, format, arena->releases); return 1; } return ALLOCATOR_EXCEPTION_SUCCESS; } static int test_arena_release( allocator_mptr_t arena, malunal_mptr_t address ) { malunal_int32_t index; malunal_int32_t* vector; vector = address; for (index = 0; index < 4; index++) if (vector[index] != index + 1) return 1; allocator_exception_t relexc = allocator_release((allocator_release_req_t) { .allocator = arena, .address = address, .size = final_bytes }); if (relexc != ALLOCATOR_EXCEPTION_SUCCESS) return relexc; // Upstream checks. if (arena->upstream->reserved != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->reserved != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->upstream->reserved); return 1; } if (arena->upstream->allocated != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->allocated != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->upstream->allocated); return 1; } if (arena->upstream->acquires != 1) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->acquires != 1, actual == %d"; fprintf(stderr, format, arena->upstream->acquires); return 1; } if (arena->upstream->releases != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->releases != 0, actual == %d"; fprintf(stderr, format, arena->upstream->releases); return 1; } // Arena checks. if (arena->reserved != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->reserved != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->reserved); return 1; } malunal_int32_t all_bytes = init_bytes + final_bytes; if (arena->allocated != all_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->allocated != %d, actual == %d"; fprintf(stderr, format, all_bytes, arena->allocated); return 1; } if (arena->acquires != 2) { const malunal_cstr_t format = "[arena_allocator]: arena->acquires != 2, actual == %d"; fprintf(stderr, format, arena->acquires); return 1; } if (arena->releases != 2) { const malunal_cstr_t format = "[arena_allocator]: arena->releases != 2, actual == %d"; fprintf(stderr, format, arena->releases); return 1; } return ALLOCATOR_EXCEPTION_SUCCESS; } static int test_arena_reset(allocator_mptr_t arena) { arena_reset(arena); // Upstream checks. if (arena->upstream->reserved != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->reserved != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->upstream->reserved); return 1; } if (arena->upstream->allocated != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->allocated != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->upstream->allocated); return 1; } if (arena->upstream->acquires != 1) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->acquires != 1, actual == %d"; fprintf(stderr, format, arena->upstream->acquires); return 1; } if (arena->upstream->releases != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->releases != 0, actual == %d"; fprintf(stderr, format, arena->upstream->releases); return 1; } // Arena checks. if (arena->reserved != page_bytes) { const malunal_cstr_t format = "[arena_allocator]: arena->reserved != %d, actual == %d"; fprintf(stderr, format, page_bytes, arena->reserved); return 1; } if (arena->allocated != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->allocated != 0, actual == %d"; fprintf(stderr, format, arena->allocated); return 1; } if (arena->acquires != 2) { const malunal_cstr_t format = "[arena_allocator]: arena->acquires != 2, actual == %d"; fprintf(stderr, format, arena->acquires); return 1; } if (arena->releases != 2) { const malunal_cstr_t format = "[arena_allocator]: arena->releases != 2, actual == %d"; fprintf(stderr, format, arena->releases); return 1; } return ALLOCATOR_EXCEPTION_SUCCESS; } static int test_arena_free(allocator_mptr_t arena) { arena_free(arena); // Upstream checks. if (arena->upstream->reserved != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->reserved != 0, actual == %d"; fprintf(stderr, format, arena->upstream->reserved); return 1; } if (arena->upstream->allocated != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->allocated != %d, actual == %d"; fprintf(stderr, format, arena->upstream->allocated); return 1; } if (arena->upstream->acquires != 1) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->acquires != 1, actual == %d"; fprintf(stderr, format, arena->upstream->acquires); return 1; } if (arena->upstream->releases != 1) { const malunal_cstr_t format = "[arena_allocator]: arena->upstream->releases != 1, actual == %d"; fprintf(stderr, format, arena->upstream->releases); return 1; } // Arena checks. if (arena->reserved != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->reserved != %d, actual == %d"; fprintf(stderr, format, arena->reserved); return 1; } if (arena->allocated != 0) { const malunal_cstr_t format = "[arena_allocator]: arena->allocated != 0, actual == %d"; fprintf(stderr, format, arena->allocated); return 1; } if (arena->acquires != 2) { const malunal_cstr_t format = "[arena_allocator]: arena->acquires != 2, actual == %d"; fprintf(stderr, format, arena->acquires); return 1; } if (arena->releases != 2) { const malunal_cstr_t format = "[arena_allocator]: arena->releases != 2, actual == %d"; fprintf(stderr, format, arena->releases); return 1; } return ALLOCATOR_EXCEPTION_SUCCESS; } int test_arena_allocator() { allocator_t upstream = platform_allocator(); allocator_t arena = arena_allocator(&upstream, page_bytes); allocator_acquire_res_t result = test_arena_acquires(&arena); return !( !result.threw && test_arena_reacquire(result.address, &arena) && test_arena_release(result.address, &arena) && test_arena_reset(&arena) && test_arena_free(&arena) ); }