开始设计
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
#include "c_Arena.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "assert.h"
|
||||
|
||||
static
|
||||
void test_arena_basic_alloc() {
|
||||
printf("[測試] 基礎分配...\n");
|
||||
|
||||
uint8_t backing_buffer[1024];
|
||||
c_Arena_t arena;
|
||||
|
||||
// 初始化
|
||||
c_Arena_Init(&arena, backing_buffer, sizeof(backing_buffer));
|
||||
assert(arena.buf == backing_buffer);
|
||||
assert(arena.buf_len == 1024);
|
||||
assert(arena.curr_offset == 0);
|
||||
|
||||
// 第一次分配
|
||||
void* p1 = c_Arena_Alloc(&arena, 100);
|
||||
assert(p1 != NULL);
|
||||
assert(arena.curr_offset >= 100); // 考慮到對齊,可能大於等於 100
|
||||
|
||||
// 第二次分配
|
||||
void* p2 = c_Arena_Alloc(&arena, 200);
|
||||
assert(p2 != NULL);
|
||||
assert(p2 > p1); // 記憶體地址應是連續向後的
|
||||
|
||||
printf(" => 基礎分配測試成功\n");
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 測試用例 2:記憶體溢出(Out of Memory)
|
||||
// ==========================================
|
||||
static
|
||||
void test_arena_oom() {
|
||||
printf("[測試] 記憶體溢出邊界...\n");
|
||||
|
||||
uint8_t backing_buffer[256];
|
||||
c_Arena_t arena;
|
||||
c_Arena_Init(&arena, backing_buffer, sizeof(backing_buffer));
|
||||
|
||||
// 嘗試分配超出整塊 Arena 大小的記憶體
|
||||
void* p1 = c_Arena_Alloc(&arena, 300);
|
||||
assert(p1 == NULL); // 應返回 NULL
|
||||
|
||||
// 分配剛好極限的記憶體
|
||||
void* p2 = c_Arena_Alloc(&arena, 256);
|
||||
assert(p2 != NULL);
|
||||
|
||||
// 已經滿了,再次分配應失敗
|
||||
void* p3 = c_Arena_Alloc(&arena, 1);
|
||||
assert(p3 == NULL);
|
||||
|
||||
printf(" => OOM 邊界測試成功\n");
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 測試用例 3:Resize 原地擴展(最速路徑)
|
||||
// ==========================================
|
||||
// 說明:若舊記憶體剛好是最後一次分配的區塊(curr_offset 緊鄰它),
|
||||
// Arena 應該直接移動 curr_offset 實現原地擴展,而不需搬移資料。
|
||||
static
|
||||
void test_arena_resize_inplace() {
|
||||
printf("[測試] Resize 原地擴展(最後一個分配物)...\n");
|
||||
|
||||
uint8_t backing_buffer[1024];
|
||||
c_Arena_t arena;
|
||||
c_Arena_Init(&arena, backing_buffer, sizeof(backing_buffer));
|
||||
|
||||
// 分配 p1,並寫入測試資料
|
||||
char* p1 = (char*)c_Arena_Alloc(&arena, 10);
|
||||
strcpy(p1, "Hello");
|
||||
|
||||
c_size_t offset_before_resize = arena.curr_offset;
|
||||
|
||||
// 將 p1 擴大到 50 字節
|
||||
char* p1_new = (char*)c_Arena_Resize(&arena, p1, 10, 50);
|
||||
|
||||
// 驗證:因為 p1 是最後分配的,它的地址不應該改變(原地擴展)
|
||||
assert(p1_new == p1);
|
||||
assert(strcmp(p1_new, "Hello") == 0); // 資料必須完整保留
|
||||
assert(arena.curr_offset > offset_before_resize); // 偏移量正確推移
|
||||
|
||||
printf(" => Resize 原地擴展測試成功\n");
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 測試用例 4:Resize 重新分配(非最後分配物)
|
||||
// ==========================================
|
||||
// 說明:若舊記憶體後面已經有其他分配物(p1 後面有 p2),
|
||||
// 此時對 p1 做 Resize 必須當作全新分配,並拷貝舊資料。
|
||||
static
|
||||
void test_arena_resize_realloc() {
|
||||
printf("[測試] Resize 重新分配(中間的分配物)...\n");
|
||||
|
||||
uint8_t backing_buffer[1024];
|
||||
c_Arena_t arena;
|
||||
c_Arena_Init(&arena, backing_buffer, sizeof(backing_buffer));
|
||||
|
||||
// 連續分配 p1 與 p2
|
||||
char* p1 = (char*)c_Arena_Alloc(&arena, 16);
|
||||
strcpy(p1, "Data1");
|
||||
|
||||
char* p2 = (char*)c_Arena_Alloc(&arena, 16);
|
||||
strcpy(p2, "Data2");
|
||||
|
||||
// 對 p1(此時不是最後一個分配物)進行 Resize
|
||||
char* p1_new = (char*)c_Arena_Resize(&arena, p1, 16, 32);
|
||||
|
||||
// 驗證:
|
||||
assert(p1_new != NULL);
|
||||
assert(p1_new != p1); // 必須分配在 p2 之後的新位置
|
||||
assert(p1_new > p2); // 確保在新地址
|
||||
assert(strcmp(p1_new, "Data1") == 0); // 舊資料必須被 memcpy 過去
|
||||
assert(strcmp(p2, "Data2") == 0); // 隔壁的 p2 資料不能被破壞
|
||||
|
||||
printf(" => Resize 重新分配測試成功\n");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv){
|
||||
printf("--- Test Begin ---\n");
|
||||
|
||||
test_arena_basic_alloc();
|
||||
test_arena_oom();
|
||||
test_arena_resize_inplace();
|
||||
test_arena_resize_realloc();
|
||||
|
||||
printf("--- Test End! ---\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user