Files
cKit/Foundation/c_SmartPtrVector.t.c
2026-08-30 03:52:23 +08:00

127 lines
5.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "c_SmartPtrVector.h"
#include "c_Test.h"
// 模擬業務層的實體資源
typedef struct {
int resource_id;
int payload;
} TestObject_t;
static int g_resource_destroy_count = 0; // 全局計數器:監控實體被真正 free 的次數
// 匹配你定義的 c_SmartPtrFreeFn_t 簽名
static void test_resource_free(void* ptr, void* args) {
if (ptr) {
TestObject_t* obj = (TestObject_t*)ptr;
int custom_flag = *(int*)args;
printf("[FreeFn Triggered] Object ID: %d, Args Flag: %d\n", obj->resource_id, custom_flag);
free(obj); // 釋放真實業務對象
g_resource_destroy_count++; // 被物理火化銷毀次數遞增
}
}
// 模擬分配器的樁實現(用於驅動 Vector 的內置多態分配鏈)
static size_t g_tracker_active_allocs = 0;
static void* mock_vector_alloc(size_t size, void* ctx) {
(void)ctx; g_tracker_active_allocs++; return malloc(size);
}
static void mock_vector_free(void* ptr, void* ctx) {
(void)ctx; if (ptr) g_tracker_active_allocs--; free(ptr);
}
TEST_CASE(test_real_smart_ptr_vector_atomic_closure) {
g_resource_destroy_count = 0;
g_tracker_active_allocs = 0;
// 1. 初始化多態記憶體管理器底座
c_Allocator_t pool_allocator = {
.alloc = mock_vector_alloc,
.realloc = NULL,
.free = mock_vector_free,
.dtor = NULL,
.ud = NULL
};
c_SmartPtrVector_t vector;
// 初始化容量為 2 的向量,並綁定專屬分配器
ASSERT_INT_EQ(C_ERR_OK, c_SmartPtrVector_Init(&vector, 2, &pool_allocator));
ASSERT_INT_EQ(1, g_tracker_active_allocs); // 內置分配器成功申請了大底座
// 2. 建立一具真實的智慧指標(指向在堆上動態開闢的 TestObject_t
TestObject_t* raw_obj = (TestObject_t*)malloc(sizeof(TestObject_t));
raw_obj->resource_id = 8899;
raw_obj->payload = 100;
int free_args = 2026; // 自定義銷毀引數
// 使用你編寫的 c_SmartPtr_Make / Init 進行生命周期宣告
c_SmartPtr_t master_sptr = c_SmartPtr_Make(raw_obj, test_resource_free, &free_args, 0);
// 剛出生,使用計數必須精準等於 1
ASSERT_INT_EQ(1, c_SmartPtr_UseCount(&master_sptr));
// 3. 測試 PushBack 自動引用計數增長
// 將智慧指標塞入 Vector 槽位 0 中,內部呼叫 c_SmartPtr_Copy,計數應原子遞增至 2
ASSERT_INT_EQ(C_ERR_OK, c_SmartPtrVector_PushBack(&vector, &master_sptr));
ASSERT_INT_EQ(2, c_SmartPtr_UseCount(&master_sptr));
ASSERT_INT_EQ(2, c_SmartPtr_UseCount(c_SmartPtrVector_Get(&vector, 0)));
// 4. 建立第二具獨立智慧指標,迫使 Vector 翻倍自動擴容(2 -> 4
TestObject_t* raw_obj2 = (TestObject_t*)malloc(sizeof(TestObject_t));
raw_obj2->resource_id = 1122;
c_SmartPtr_t master_sptr2 = c_SmartPtr_Make(raw_obj2, test_resource_free, &free_args, 0);
c_SmartPtrVector_PushBack(&vector, &master_sptr2); // 槽位 1
// 核心觀察點:塞入第三個元素,強行觸展 EnsureCapacity 翻倍搬迁!
// 搬遷時內部使用 c_SmartPtr_Move 做轉移,所有權安全平移,兩具老智慧指標的引用計數絕不應發生任何變化!
ASSERT_INT_EQ(C_ERR_OK, c_SmartPtrVector_PushBack(&vector, &master_sptr2)); // 槽位 2 重複掛接 sptr2
ASSERT_INT_EQ(3, vector.size);
ASSERT_INT_EQ(4, vector.capacity);
ASSERT_INT_EQ(1, g_tracker_active_allocs); // 搬遷成功後,老緩衝區被內置分配器乾淨 Free 釋放
// 驗證搬遷後,sptr1 的計數依然穩健維持在 2,完全沒有受到內存重組的交叉干擾
ASSERT_INT_EQ(2, c_SmartPtr_UseCount(&master_sptr));
// 5. 測試中段任意位置定点裁剪(Remove 靜默抹殺)
// 移除槽位 0 的 sptr1,這會扣減其引用計數(2 降到 1)。此時資源依然活在外部持有的 master_sptr 中
ASSERT_INT_EQ(C_ERR_OK, c_SmartPtrVector_Remove(&vector, 0));
ASSERT_INT_EQ(1, c_SmartPtr_UseCount(&master_sptr));
ASSERT_INT_EQ(0, g_resource_destroy_count); // 資源依然安全存活,尚未觸發真正的物理 free_fn
// 6. 測試 RemoveAndTake 控制權完全接管倒騰
c_SmartPtr_t external_receiver = {0};
// 將槽位 0 (因前移,此時存放的是 sptr2 的重複項) 自主剝离倒騰給 external_receiver
// 由於是 Move 倒騰,sptr2 的計數和所有權無痛轉交,完全符合直覺
ASSERT_INT_EQ(C_ERR_OK, c_SmartPtrVector_RemoveAndTake(&vector, 0, &external_receiver));
ASSERT_TRUE(external_receiver.ptr == raw_obj2);
// 7. 外部主動銷毀釋放所有本地變數,將計數往物理火化終點推進
c_SmartPtr_Destroy(&external_receiver);
c_SmartPtr_Destroy(&master_sptr2);
// 8. 終極解體:摧毀 Vector
c_SmartPtrVector_Destroy(&vector);
// 槽位 0 之前剩下一具 sptr2。Vector 銷毀時會將其釋放,此時 raw_obj2 的引用計數徹底歸 0,自動觸發物理銷毀!
ASSERT_INT_EQ(1, g_resource_destroy_count); // raw_obj2 已經在 Vector 解體時被閉環火化
// 9. 外部最後銷毀外部唯一的 master_sptr
c_SmartPtr_Destroy(&master_sptr); // 引用計數歸 0,raw_obj1 自動物理火化!
// 10. 終極一致性雙向審判断言:
// 所有變數與容器全部解體後,兩具堆實體資源必須無一遺漏、百分之百被自動物理銷毀歸還!
ASSERT_INT_EQ_MSG(2, g_resource_destroy_count, "CRITICAL: Smart Pointer Vector Caused Reference Counting Mismatch or Memory Leak!");
// 分配器活躍塊重歸於 0,物理堆記憶體 0 滯留
ASSERT_INT_EQ_MSG(0, g_tracker_active_allocs, "Vector internal allocator leaked heap space!");
}
int main(void) {
TEST_START(C_Real_SmartPtrVector_System_Tests);
RUN_TEST(test_real_smart_ptr_vector_atomic_closure);
TEST_REPORT();
RETURN_TEST_STATUS;
}