/* * axl_memory_tests.c — Comprehensive unit tests for axl_memory.h */ #include "axl_memory.h" #include "axl_koan.h" #include KOAN(init_called) { void* p = axl_malloc(1); ASSERT_NOT_NULL(p); axl_free(p); } KOAN(malloc_returns_different_pointers) { void* a = axl_malloc(16); void* b = axl_malloc(32); ASSERT_NOT_NULL(a); ASSERT_NOT_NULL(b); ASSERT_TRUE(a != b); axl_free(a); axl_free(b); } KOAN(malloc_exhaustion_returns_null) { void* p = axl_malloc(AXL_HEAP_SIZE + 4096); ASSERT_NULL(p); } KOAN(realloc_null_acts_like_malloc) { void* p = axl_realloc(NULL, 64); ASSERT_NOT_NULL(p); axl_memset(p, 0x55, 64); axl_free(p); } KOAN(realloc_zero_size_frees_and_returns_null_or_valid) { void* p = axl_malloc(100); ASSERT_NOT_NULL(p); void* q = axl_realloc(p, 0); if (q != NULL) axl_free(q); } KOAN(realloc_enlarge_preserves_content) { void* p = axl_malloc(32); axl_memset(p, 0xCD, 32); void* q = axl_realloc(p, 128); ASSERT_NOT_NULL(q); for (int i = 0; i < 32; i++) ASSERT_INT_EQ(0xCD, ((u8*)q)[i]); axl_free(q); } KOAN(realloc_shrink_preserves_prefix) { void* p = axl_malloc(256); axl_memset(p, 0xAB, 256); void* q = axl_realloc(p, 64); ASSERT_NOT_NULL(q); for (int i = 0; i < 64; i++) ASSERT_INT_EQ(0xAB, ((u8*)q)[i]); axl_free(q); } KOAN(realloc_same_size_returns_same_or_equivalent) { void* p = axl_malloc(100); p = axl_realloc(p, 100); ASSERT_NOT_NULL(p); axl_free(p); } KOAN(memset_fills_correctly) { void* p = axl_malloc(64); axl_memset(p, 0x55, 64); for (int i = 0; i < 64; i++) ASSERT_INT_EQ(0x55, ((u8*)p)[i]); axl_free(p); } KOAN(memset_zero_bytes_is_nop) { void* p = axl_malloc(16); axl_memset(p, 0xFF, 16); axl_memset(p, 0x00, 0); for (int i = 0; i < 16; i++) ASSERT_INT_EQ(0xFF, ((u8*)p)[i]); axl_free(p); } KOAN(memcpy_copies_exact_bytes) { u8 src[32]; for (int i = 0; i < 32; i++) src[i] = (u8)i; void* dst = axl_malloc(32); axl_memcpy(dst, src, 32); ASSERT_INT_EQ(0, memcmp(dst, src, 32)); axl_free(dst); } KOAN(memcpy_zero_bytes_is_nop) { u8 data[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; void* p = axl_malloc(16); axl_memcpy(p, data, 16); axl_memcpy(p, "junk", 0); ASSERT_INT_EQ(0, memcmp(p, data, 16)); axl_free(p); } KOAN(memcmp_returns_correct_sign) { u8 a[] = {0, 0, 0, 0}; u8 b[] = {0, 0, 0, 1}; u8 c[] = {0, 0, 1, 0}; ASSERT_INT_EQ(0, axl_memcmp(a, a, 4)); ASSERT_TRUE(axl_memcmp(a, b, 4) < 0); ASSERT_TRUE(axl_memcmp(b, a, 4) > 0); ASSERT_TRUE(axl_memcmp(a, c, 3) < 0 ); ASSERT_TRUE(axl_memcmp(a, b, 2) == 0); ASSERT_TRUE(axl_memcmp(a, c, 2) == 0); ASSERT_TRUE(axl_memcmp(c, b, 2) == 0); ASSERT_TRUE(axl_memcmp(a, c, 4) < 0); } KOAN(memcmp_zero_length_returns_zero) { u8 x = 0xFF, y = 0x00; ASSERT_INT_EQ(0, axl_memcmp(&x, &y, 0)); } KOAN(memchr_finds_character_in_buffer) { u8 buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; void* result = axl_memchr(buffer, 0x03, sizeof(buffer)); ASSERT_NOT_NULL(result); ASSERT_TRUE(result == &buffer[3]); } KOAN(memchr_returns_null_when_not_found) { u8 buffer[] = {0x10, 0x20, 0x30, 0x40, 0x50}; void* result = axl_memchr(buffer, 0x99, sizeof(buffer)); ASSERT_NULL(result); } KOAN(memchr_finds_first_occurrence) { u8 buffer[] = {0xAA, 0xBB, 0xCC, 0xBB, 0xDD}; void* result = axl_memchr(buffer, 0xBB, sizeof(buffer)); ASSERT_NOT_NULL(result); ASSERT_TRUE(result == &buffer[1]); } KOAN(memchr_finds_at_beginning) { u8 buffer[] = {0xFF, 0xFE, 0xFD, 0xFC}; void* result = axl_memchr(buffer, 0xFF, sizeof(buffer)); ASSERT_NOT_NULL(result); ASSERT_TRUE(result == &buffer[0]); } KOAN(memchr_finds_at_end) { u8 buffer[] = {0x11, 0x22, 0x33, 0x44, 0x55}; void* result = axl_memchr(buffer, 0x55, sizeof(buffer)); ASSERT_NOT_NULL(result); ASSERT_TRUE(result == &buffer[4]); } KOAN(memchr_zero_length_returns_null) { u8 buffer[] = {0x01, 0x02, 0x03}; void* result = axl_memchr(buffer, 0x01, 0); ASSERT_NULL(result); } KOAN(memchr_stops_at_specified_length) { u8 buffer[] = {0x10, 0x20, 0x30, 0x40, 0x50}; void* result = axl_memchr(buffer, 0x40, 3); ASSERT_NULL(result); result = axl_memchr(buffer, 0x40, 4); ASSERT_NOT_NULL(result); ASSERT_TRUE(result == &buffer[3]); } KOAN(memchr_handles_all_byte_values) { u8 buffer[256]; for (int i = 0; i < 256; i++) { buffer[i] = (u8)i; } for (int i = 0; i < 256; i++) { void* result = axl_memchr(buffer, (u8)i, sizeof(buffer)); ASSERT_NOT_NULL(result); ASSERT_TRUE(result == &buffer[i]); } } KOAN(memchr_matches_standard_memchr) { u8 buffer[100]; for (int i = 0; i < 100; i++) { buffer[i] = (u8)(i * 3); } for (int val = 0; val < 256; val += 17) { void* axl_result = axl_memchr(buffer, (u8)val, sizeof(buffer)); void* std_result = memchr(buffer, (u8)val, sizeof(buffer)); if (std_result == NULL) { ASSERT_NULL(axl_result); } else { ASSERT_NOT_NULL(axl_result); ASSERT_TRUE(axl_result == std_result); } } } KOAN(memmove_basic_copy) { u8 src[64]; u8 dst[64]; for (int i = 0; i < 64; i++) { src[i] = (u8)(i + 1); } axl_memmove(dst, src, 64); for (int i = 0; i < 64; i++) { ASSERT_INT_EQ(src[i], dst[i]); } } KOAN(memmove_zero_bytes_is_nop) { u8 data[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; u8 copy[16]; axl_memcpy(copy, data, 16); axl_memmove(copy, NULL, 0); for (int i = 0; i < 16; i++) { ASSERT_INT_EQ(data[i], copy[i]); } } KOAN(memmove_overlap_forward) { u8 buffer[32] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; u8 expected[32]; memcpy(expected, buffer, 32); memmove(expected + 8, expected + 4, 16); axl_memmove(buffer + 8, buffer + 4, 16); for (int i = 0; i < 32; i++) { ASSERT_INT_EQ(expected[i], buffer[i]); } } KOAN(memmove_overlap_backward) { u8 buffer[32] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; u8 expected[32]; memcpy(expected, buffer, 32); memmove(expected + 4, expected + 8, 16); axl_memmove(buffer + 4, buffer + 8, 16); for (int i = 0; i < 32; i++) { ASSERT_INT_EQ(expected[i], buffer[i]); } } KOAN(memmove_overlap_same_region) { u8 buffer[32]; for (int i = 0; i < 32; i++) { buffer[i] = (u8)i; } u8 expected[32]; memcpy(expected, buffer, 32); axl_memmove(buffer, buffer, 32); for (int i = 0; i < 32; i++) { ASSERT_INT_EQ(expected[i], buffer[i]); } } KOAN(memmove_overlap_single_byte) { u8 buffer[8] = {0,1,2,3,4,5,6,7}; u8 expected[8]; memcpy(expected, buffer, 8); memmove(expected + 1, expected, 7); axl_memmove(buffer + 1, buffer, 7); for (int i = 0; i < 8; i++) { ASSERT_INT_EQ(expected[i], buffer[i]); } } KOAN(memmove_matches_standard_memmove) { u8 src[128]; u8 dst_axl[128]; u8 dst_std[128]; for (int i = 0; i < 128; i++) { src[i] = (u8)(i * 7); } for (int offset = -16; offset <= 16; offset++) { memcpy(dst_axl, src, 128); memcpy(dst_std, src, 128); int src_offset = 32; int dst_offset = 32 + offset; int copy_size = 64; axl_memmove(dst_axl + dst_offset, dst_axl + src_offset, copy_size); memmove(dst_std + dst_offset, dst_std + src_offset, copy_size); for (int i = 0; i < 128; i++) { ASSERT_INT_EQ(dst_std[i], dst_axl[i]); } } } KOAN(memmove_small_overlap) { u8 buffer[10] = {0,1,2,3,4,5,6,7,8,9}; u8 expected[10]; memcpy(expected, buffer, 10); memmove(expected + 2, expected, 5); axl_memmove(buffer + 2, buffer, 5); for (int i = 0; i < 10; i++) { ASSERT_INT_EQ(expected[i], buffer[i]); } } KOAN(memmove_large_non_overlap) { u8 src[256]; u8 dst[256]; for (int i = 0; i < 256; i++) { src[i] = (u8)(255 - i); } axl_memmove(dst, src, 256); for (int i = 0; i < 256; i++) { ASSERT_INT_EQ(src[i], dst[i]); } } KOAN(double_free_does_not_crash) { void* p = axl_malloc(64); ASSERT_NOT_NULL(p); axl_free(p); axl_free(p); } KOAN(large_allocation_near_heap_limit) { void* p = axl_malloc(AXL_HEAP_SIZE - 1024); ASSERT_NOT_NULL(p); if (p) axl_free(p); } KOAN(allocation_of_max_size_fails) { void* p = axl_malloc(AXL_HEAP_SIZE); ASSERT_NULL(p); } KOAN(many_small_allocations) { #define N 1000 void* ptrs[N]; for (int i = 0; i < N; i++) { ptrs[i] = axl_malloc(16); ASSERT_NOT_NULL(ptrs[i]); *(u32*)ptrs[i] = 0xDEADBEEF; } for (int i = 0; i < N; i++) { ASSERT_INT_EQ(0xDEADBEEF, *(u32*)ptrs[i]); axl_free(ptrs[i]); } } int main(void) { axl_init(); return koan_run_all(); }