Files
2026-08-29 00:53:40 +08:00

88 lines
3.9 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_Pool.h"
#include <stdlib.h>
#include <stdio.h>
#include "c_Test.h"
#include "c_Memory.h"
#define C_ASSERT_ALIGNED_TO(ptr, align) \
C_ASSERT(((uintptr_t)(ptr) % (align)) == 0, "Pool分配出的块地址不符合对齐边界")
/* ==============================================================================
* 🧪 1. 测试全自动“无感自愈扩容”核心行为流 (c_Pool_Alloc)
* ============================================================================== */
C_TEST_CASE(test_pool_auto_healing_expansion)
{
c_Pool_t pool;
/* 初始化:每个块 24 字节,每页(ChunkSize)只装载极小的 2 个块 */
c_err_t err = c_Pool_Init(&pool, 24, 2);
C_ASSERT_INT_EQ(err, C_ERR_OK, "弹性自愈内存池初始化必须返回 C_OK");
C_ASSERT_INT_EQ(pool.instanceCount, 0, "初始活跃贷出对象数必须为 0");
/* 1. 连续掏空第一页的 2 个默认格子 */
void* block_1 = c_Pool_Alloc(&pool);
void* block_2 = c_Pool_Alloc(&pool);
C_ASSERT(block_1 != NULL && block_2 != NULL, "第一页的额度分配顺利通过");
C_ASSERT_INT_EQ(pool.instanceCount, 2, "此时贷出计数必须动态变更为 2");
/* 2. 🎯 核心高能看点:在上一版设计中,此时再 Alloc 会直接返回 NULL。
但在这一代高级设计下,池子会在内部发现 freelist 为空,从而自动追加串联一个新 Page! */
void* block_3_auto_healed = c_Pool_Alloc(&pool);
/* 断言:分配绝对不能为 NULL,上层代码完全没有感知到任何耗尽异常! */
C_ASSERT(block_3_auto_healed != NULL, "耗尽时追加申请,分配器必须完成全自动无感自愈扩容!");
C_ASSERT_INT_EQ(pool.instanceCount, 3, "贷出计数动态累加为 3");
/* 规范回收其中两个 */
c_Pool_Free(&pool, block_2);
c_Pool_Free(&pool, block_3_auto_healed);
C_ASSERT_INT_EQ(pool.instanceCount, 1, "主动还回 2 个对象后,instanceCount 必须平滑退回 1");
c_Pool_DryUp(&pool);
c_Pool_Destroy(&pool);
}
/* ==============================================================================
* 🧪 2. 测试 `c_Pool_DryUp` 强制全量洗净一键清零机制
* ============================================================================== */
C_TEST_CASE(test_pool_dry_up_force_reset)
{
c_Pool_t pool;
c_Pool_Init(&pool, sizeof(double), 5); /* 每页 5 个对象 */
/* 连续狂点分配 12 次,这会迫使池子在内部自动开辟 3 个 Page 页(5 + 5 + 5 = 15 */
for (int i = 0; i < 12; ++i) {
void* ptr = c_Pool_Alloc(&pool);
C_UNUSED(ptr);
}
C_ASSERT_INT_EQ(pool.instanceCount, 12, "12 个活跃对象驻留在外");
/* 🛠️ 执行高能一键强制回收 */
c_Pool_DryUp(&pool);
/* 断言:执行一键 DryUp 后,无论刚才贷出了多少,活跃计数瞬间全量归零! */
C_ASSERT_INT_EQ(pool.instanceCount, 0, "执行 DryUp 后,活跃贷出计数必须强行全量斩断复位为 0");
/* 此时,池子内部历史上申请的 3 个物理大页并没有被销毁(不释放传统堆,防止高频申请时的性能抖动),
但所有的 15 个空闲格子已经被全部强行重新串联回 freelist,可以直接重新欢快地发牌复用! */
void* fresh_ptr = c_Pool_Alloc(&pool);
C_ASSERT(fresh_ptr != NULL, "DryUp 后,内存池可以在零传统堆开销下立刻无缝重新投入使用");
c_Pool_Free(&pool, fresh_ptr);
c_Pool_Destroy(&pool);
}
/* ==============================================================================
* 🚀 测试套件统一注册调度主函数
* ============================================================================== */
int main(int argc, char** argv){
C_TEST_SUITE_BEGIN(MemoryPoolAutoHealingTestSuite)
C_RUN_TEST_CASE(test_pool_auto_healing_expansion);
C_RUN_TEST_CASE(test_pool_dry_up_force_reset);
C_TEST_SUITE_END()
return 0;
}