2026-08-30 02:51:25 +08:00
|
|
|
#include "c_SmartPtr.h"
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
2026-08-30 03:52:23 +08:00
|
|
|
#include "c_Test.h"
|
2026-08-30 02:51:25 +08:00
|
|
|
|
2026-08-30 03:52:23 +08:00
|
|
|
typedef struct {
|
|
|
|
|
int conn_fd;
|
|
|
|
|
} NetSession_t;
|
2026-08-30 02:51:25 +08:00
|
|
|
|
2026-08-30 03:52:23 +08:00
|
|
|
static int g_session_free_call_count = 0;
|
|
|
|
|
static size_t g_buddy_pool_active_chunks = 0; // 審計夥伴系統記憶體池的活躍塊總數
|
|
|
|
|
|
|
|
|
|
// 自定義析構回呼
|
|
|
|
|
static void session_release_handler(void* ptr, void* args) {
|
|
|
|
|
if (ptr) {
|
|
|
|
|
free(ptr); // 釋放業務物件
|
|
|
|
|
g_session_free_call_count++;
|
2026-08-30 02:51:25 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-30 03:52:23 +08:00
|
|
|
// 模擬夥伴系統多態分配器物理開闢
|
|
|
|
|
static void* mock_buddy_alloc(size_t size, void* ctx) {
|
|
|
|
|
(void)ctx; g_buddy_pool_active_chunks++; return malloc(size);
|
|
|
|
|
}
|
|
|
|
|
static void mock_buddy_free(void* ptr, void* ctx) {
|
|
|
|
|
(void)ctx; if (ptr) g_buddy_pool_active_chunks--; free(ptr);
|
2026-08-30 02:51:25 +08:00
|
|
|
}
|
|
|
|
|
|
2026-08-30 03:52:23 +08:00
|
|
|
TEST_CASE(test_fully_closed_smart_pointer_polymorphic_sandbox) {
|
|
|
|
|
g_session_free_call_count = 0;
|
|
|
|
|
g_buddy_pool_active_chunks = 0;
|
|
|
|
|
|
|
|
|
|
// 1. 初始化你的自建多態記憶體池分配器 (夥伴系統物理底座)
|
|
|
|
|
c_Allocator_t buddy_pool = {
|
|
|
|
|
.alloc = mock_buddy_alloc,
|
|
|
|
|
.realloc = NULL,
|
|
|
|
|
.free = mock_buddy_free,
|
|
|
|
|
.dtor = NULL,
|
|
|
|
|
.ud = NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 2. 在堆上構建一個真實的連線工作階段
|
|
|
|
|
NetSession_t* raw_session = (NetSession_t*)malloc(sizeof(NetSession_t));
|
|
|
|
|
raw_session->conn_fd = 8080;
|
|
|
|
|
|
|
|
|
|
// 3. 宣告主智慧指標誕生,並掛載夥伴系統記憶體池
|
|
|
|
|
c_SmartPtr_t sptr_master = c_SmartPtr_Make(raw_session, session_release_handler, NULL, &buddy_pool);
|
|
|
|
|
|
|
|
|
|
// 斷言審判:此時夥伴系統內部的活躍物理塊計數精準等於 1 (即內嵌 allocator 幫我們開闢的 ref_count)
|
|
|
|
|
ASSERT_INT_EQ(1, g_buddy_pool_active_chunks);
|
|
|
|
|
ASSERT_INT_EQ(1, c_SmartPtr_UseCount(&sptr_master));
|
|
|
|
|
|
|
|
|
|
// 4. 驗證共享深度拷貝與分配器血脈克隆繼承 (Copy)
|
|
|
|
|
c_SmartPtr_t sptr_clone = {0};
|
|
|
|
|
ASSERT_INT_EQ(C_ERR_OK, c_SmartPtr_Copy(&sptr_clone, &sptr_master));
|
|
|
|
|
|
|
|
|
|
// 兩者共享原子核,計數精準遞增為 2
|
|
|
|
|
ASSERT_INT_EQ(2, c_SmartPtr_UseCount(&sptr_master));
|
|
|
|
|
ASSERT_INT_EQ(2, c_SmartPtr_UseCount(&sptr_clone));
|
|
|
|
|
|
|
|
|
|
// 5. 【終極高能觀察點】:單體自主銷毀(Destroy)
|
|
|
|
|
// 外部直接呼叫極簡的 c_SmartPtr_Destroy,不需要傳入任何外部分配器!
|
|
|
|
|
c_SmartPtr_Destroy(&sptr_clone); // 克隆體釋放,計數精準回落至 1
|
|
|
|
|
|
|
|
|
|
// 帳目審查:克隆體被銷毀,但主體還活著,實體對象絕不能提前消亡,且夥伴系統計數依然完整保持為 1
|
|
|
|
|
ASSERT_INT_EQ(1, c_SmartPtr_UseCount(&sptr_master));
|
|
|
|
|
ASSERT_INT_EQ(0, g_session_free_call_count);
|
|
|
|
|
ASSERT_INT_EQ(1, g_buddy_pool_active_chunks);
|
|
|
|
|
|
|
|
|
|
// 6. 終致命一擊:銷毀最後持有人 sptr_master
|
|
|
|
|
// 計數歸零,自主觸發託管的 session_release_handler 物理火化,並【自主】利用內嵌的 allocator 退還記憶體
|
|
|
|
|
c_SmartPtr_Destroy(&sptr_master);
|
|
|
|
|
|
|
|
|
|
// 7. 終極一致性雙向審判:
|
|
|
|
|
// A. 實體資源層:業務物件被精準自動火化解體,物理消亡數精準等於 1
|
|
|
|
|
ASSERT_INT_EQ(1, g_session_free_call_count);
|
|
|
|
|
|
|
|
|
|
// B. 多態記憶體池層:分散隨機開闢的原子計數核空間完全由智慧指標內部自主歸還!
|
|
|
|
|
// 夥伴系統記憶體池活躍塊計數 g_buddy_pool_active_chunks 完美且毫無滯留地歸零(0 洩漏,0 跑飛,100% 圓滿!)
|
|
|
|
|
ASSERT_INT_EQ_MSG(0, g_buddy_pool_active_chunks, "CRITICAL: Self-contained Smart Pointer leaked ref_count space inside buddy pool!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(void) {
|
|
|
|
|
printf("\n");
|
|
|
|
|
TEST_START(C_Ultimate_FullyClosed_SmartPtr_Tests);
|
|
|
|
|
RUN_TEST(test_fully_closed_smart_pointer_polymorphic_sandbox);
|
|
|
|
|
TEST_REPORT();
|
|
|
|
|
RETURN_TEST_STATUS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|