#include "malunal/allocators/arena.h" #include "malunal/microtest.h" MICROTEST(arena_allocator, can_init_and_free) { error_t result = {}; arena_allocator_t allocator = {}; malunal_uint32_t temporary = 0; result = arena_allocator_init(500, &allocator); MICROTEST_EXPECT_NULL(result.domain); result = arena_allocator_size(&allocator, &temporary); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_EXPECT_EQ(temporary, platform_page_size()); result = arena_allocator_used(&allocator, &temporary); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_EXPECT_EQ(temporary, 16); result = arena_allocator_free(&allocator); MICROTEST_EXPECT_NULL(result.domain); result = arena_allocator_size(&allocator, &temporary); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_EXPECT_EQ(temporary, 0); result = arena_allocator_used(&allocator, &temporary); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_EXPECT_EQ(temporary, 0); } MICROTEST(arena_allocator, can_acquire_and_dispose) { error_t result = {}; arena_allocator_t allocator = {}; malunal_mptr_t address = null; malunal_uint32_t temporary = 0; arena_allocator_init(500, &allocator); result = arena_allocator_acquire(&allocator, 64, &address); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_ASSERT_NOT_NULL(address); result = arena_allocator_used(&allocator, &temporary); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_EXPECT_EQ(temporary, 80); result = arena_allocator_dispose(&allocator, address, 64); MICROTEST_EXPECT_NULL(result.domain); result = arena_allocator_used(&allocator, &temporary); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_EXPECT_EQ(temporary, 80); arena_allocator_free(&allocator); } MICROTEST(arena_allocator, can_reset_allocator) { error_t result = {}; arena_allocator_t allocator = {}; malunal_mptr_t address = null; malunal_uint32_t temporary = 0; arena_allocator_init(500, &allocator); result = arena_allocator_acquire(&allocator, 64, &address); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_ASSERT_NOT_NULL(address); result = arena_allocator_used(&allocator, &temporary); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_EXPECT_EQ(temporary, 80); result = arena_allocator_reset(&allocator); MICROTEST_EXPECT_NULL(result.domain); result = arena_allocator_used(&allocator, &temporary); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_EXPECT_EQ(temporary, 16); arena_allocator_free(&allocator); } MICROTEST(arena_allocator, can_acquire_beyond_first_region) { arena_allocator_t allocator = {}; malunal_mptr_t addresses[256]; malunal_uint32_t temporary = 0; arena_allocator_init(500, &allocator); for (malunal_size_t index = 0; index < 256; index++) { error_t result = arena_allocator_acquire(&allocator, 64, &addresses[index]); MICROTEST_ASSERT_NULL(result.domain); memset(addresses[index], (int)index, 64); } for (malunal_size_t index = 0; index < 256; index++) { malunal_uint8_t* bytes = addresses[index]; MICROTEST_EXPECT_EQ(bytes[63], (malunal_uint8_t)index); } arena_allocator_size(&allocator, &temporary); MICROTEST_EXPECT_GT(temporary, platform_page_size()); arena_allocator_free(&allocator); } MICROTEST(arena_allocator, can_acquire_larger_than_region) { arena_allocator_t allocator = {}; malunal_mptr_t address = null; malunal_size_t size = platform_page_size() * 3; arena_allocator_init(500, &allocator); error_t result = arena_allocator_acquire(&allocator, size, &address); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_ASSERT_NOT_NULL(address); memset(address, 0xAB, size); arena_allocator_free(&allocator); } MICROTEST(arena_allocator, oversized_request_reports_out_of_memory) { arena_allocator_t allocator = {}; malunal_mptr_t address = null; arena_allocator_init(500, &allocator); error_t result = arena_allocator_acquire(&allocator, (malunal_size_t)-1, &address); MICROTEST_EXPECT_NOT_NULL(result.domain); MICROTEST_EXPECT_EQ(result.code, (malunal_int32_t)ALLOCATOR_ERROR_OUT_OF_MEMORY); arena_allocator_free(&allocator); } MICROTEST(arena_allocator, acquisitions_are_aligned) { arena_allocator_t allocator = {}; arena_allocator_init(500, &allocator); for (malunal_size_t size = 1; size <= 33; size += 3) { malunal_mptr_t address = null; arena_allocator_acquire(&allocator, size, &address); MICROTEST_EXPECT_EQ((malunal_uintptr_t)address % 16, (malunal_uintptr_t)0); } arena_allocator_free(&allocator); } MICROTEST(arena_allocator, can_dispose_from_later_region) { arena_allocator_t allocator = {}; malunal_mptr_t address = null; arena_allocator_init(500, &allocator); for (malunal_size_t index = 0; index < 128; index++) arena_allocator_acquire(&allocator, 64, &address); error_t result = arena_allocator_dispose(&allocator, address, 64); MICROTEST_EXPECT_NULL(result.domain); arena_allocator_free(&allocator); } MICROTEST(arena_allocator, dispose_rejects_foreign_address) { arena_allocator_t allocator = {}; malunal_uint8_t foreign[64]; arena_allocator_init(500, &allocator); error_t result = arena_allocator_dispose(&allocator, foreign, sizeof(foreign)); MICROTEST_EXPECT_NOT_NULL(result.domain); MICROTEST_EXPECT_EQ(result.code, (malunal_int32_t)ALLOCATOR_ERROR_NOT_MY_ADDRESS); arena_allocator_free(&allocator); } MICROTEST(arena_allocator, can_acquire_after_free) { arena_allocator_t allocator = {}; malunal_mptr_t address = null; arena_allocator_init(500, &allocator); arena_allocator_free(&allocator); error_t result = arena_allocator_acquire(&allocator, 64, &address); MICROTEST_EXPECT_NULL(result.domain); MICROTEST_ASSERT_NOT_NULL(address); arena_allocator_free(&allocator); }