DragonOS/kernel/ktest/test-idr.c

593 lines
13 KiB
C
Raw 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.

#pragma GCC push_options
#pragma GCC optimize("O1")
#include "ktest.h"
#include "ktest_utils.h"
#include <common/idr.h>
/**
* @brief 测试idr的构建,预获取空间是否成功
*
* 以下函数将被测试:
* 1. idr_preload
* 2. DECLARE_IDR
* 3. idr_init
* 4. idr_destroy
*
* 同时还会(间接)测试一些内部函数:
* 1. move_to_free_list
*
* @param arg0
* @param arg1
*/
static long ktest_idr_case0(uint64_t arg0, uint64_t arg1)
{
unsigned long bitmap = -1;
assert((int)(bitmap == IDR_FULL));
DECLARE_IDR(k_idr);
assert(k_idr.top == NULL); // 刚被创建,必须是NULL
assert(k_idr.id_free_cnt == 0); // 必须是0
assert(k_idr.free_list == NULL);
k_idr.id_free_cnt = arg1;
idr_init(&k_idr);
assert(k_idr.id_free_cnt == 0);
assert(idr_preload(&k_idr, 0) == 0);
assert(k_idr.id_free_cnt == IDR_FREE_MAX);
for (uint64_t i = 1; i < 64; i++)
{
int id = __lowbit_id(i), chk_id = -1;
for (int j = 0; j < 64; j++)
if ((i >> j) & 1)
{
chk_id = j;
break;
}
assert(id == chk_id);
}
// 销毁
idr_destroy(&k_idr);
assert(k_idr.id_free_cnt == 0);
assert(k_idr.free_list == NULL);
assert(k_idr.top == NULL);
return 0;
}
/**
* @brief 测试id的获取id的删除id的全体删除, idr的find函数
*
* @param arg0
* @param arg1
*/
static long ktest_idr_case1(uint64_t arg0, uint64_t arg1)
{
DECLARE_IDR(k_idr);
int a[128];
// 获取128个id
for (int i = 0; i < 128; i++)
{
assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
assert(a[i] == i);
}
// 查询128个ptr
for (int i = 0; i < 128; i++)
{
int *ptr = idr_find(&k_idr, a[i]);
assert(ptr == &a[i]);
assert(ptr != NULL);
assert(*ptr == a[i]);
}
// 倒序删除64个id
for (int i = 127; i >= 64; i--)
{
int *id = idr_remove(&k_idr, a[i]);
assert(id != NULL);
assert(*id == i);
assert(idr_find(&k_idr, a[i]) == NULL);
}
// 正序删除64个id
for (int i = 0; i <= 63; i++)
{
int *id = idr_remove(&k_idr, a[i]);
assert(id != NULL);
assert(*id == i);
assert(idr_find(&k_idr, a[i]) == NULL);
}
for (int i = 0; i < 128; i++)
{
assert(idr_count(&k_idr, i) == 0);
}
// 重新申请128个id, 值域范围应该仍然是[0,127]
for (int i = 0; i < 128; i++)
{
assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
assert(a[i] == i);
}
for (int i = 0; i < 128; i++)
{
assert(idr_count(&k_idr, i));
}
// 正序删除32个id
for (int i = 0; i <= 31; i++)
{
int *id = idr_remove(&k_idr, a[i]);
assert(id != NULL);
assert(*id == i);
assert(idr_find(&k_idr, a[i]) == NULL);
}
// 倒序删除32个id
for (int i = 127; i >= 96; i--)
{
int *id = idr_remove(&k_idr, a[i]);
assert(id != NULL);
assert(*id == i);
assert(idr_find(&k_idr, a[i]) == NULL);
}
// 整体删除
idr_remove_all(&k_idr);
assert(k_idr.top == NULL);
// 获取128个id
for (int i = 0; i < 128; i++)
{
assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
assert(a[i] == i);
}
// 查询128个ptr
for (int i = 0; i < 128; i++)
{
int *ptr = idr_find(&k_idr, a[i]);
assert(ptr == &a[i]);
assert(*ptr == a[i]);
}
// 正序删除64个id
for (int i = 0; i <= 63; i++)
{
idr_remove(&k_idr, a[i]);
assert(idr_find(&k_idr, a[i]) == NULL);
}
// 倒序删除64个id
for (int i = 127; i >= 64; i--)
{
idr_remove(&k_idr, a[i]);
assert(idr_find(&k_idr, a[i]) == NULL);
}
// 销毁
idr_destroy(&k_idr);
assert(k_idr.id_free_cnt == 0);
assert(k_idr.free_list == NULL);
return 0;
}
/**
* @brief case1 的大数据测试
*
* @param arg0
* @param arg1
*/
static long ktest_idr_case2(uint64_t arg0, uint64_t arg1)
{
DECLARE_IDR(k_idr);
// 获取 1000000 个ID
const int N = 1e6;
// const int N = 1048576;
const int M = 2e5;
int tmp = 0;
for (int i = 0; i < N; i++)
{
barrier();
assert(idr_alloc(&k_idr, &tmp, &tmp) == 0);
barrier();
assert(tmp == i);
barrier();
int *ptr = idr_find(&k_idr, i);
barrier();
assert(ptr != NULL);
assert(*ptr == i);
barrier();
// if (i >= 7255) kdebug("1e6 !!!!!!! : %d", i);
assert(idr_count(&k_idr, i));
barrier();
}
// kdebug("111111");
// 正向: M 个ID
for (int i = 0; i < M; i++)
{
int *ptr = idr_find(&k_idr, i);
assert(ptr != NULL);
assert(*ptr == N - 1);
idr_remove(&k_idr, i);
assert(idr_find(&k_idr, i) == NULL);
}
// kdebug("22222");
// 倒序: N-M 个ID
for (int i = (N)-1; i >= M; i--)
{
int *ptr = idr_find(&k_idr, i);
assert(*ptr == N - 1);
idr_remove(&k_idr, i);
assert(idr_find(&k_idr, i) == NULL);
}
// kdebug("3333333");
// 重新插入数据
for (int i = 0; i < N; i++)
{
assert(idr_alloc(&k_idr, &tmp, &tmp) == 0);
assert(tmp == i);
assert(k_idr.top != NULL);
int *ptr = idr_find(&k_idr, i);
assert(ptr != NULL);
assert(*ptr == i);
}
// kdebug("4444444444");
assert(k_idr.top != NULL);
for (int i = 0; i < M; i++)
{
assert(idr_replace(&k_idr, NULL, i) == 0);
}
// kdebug("555555555555555555");
// 销毁
idr_destroy(&k_idr);
assert(k_idr.id_free_cnt == 0);
assert(k_idr.free_list == NULL);
// kdebug("666666666666");
return 0;
}
/**
* @brief case1 的大数据测试
*
* @param arg0
* @param arg1
*/
static long ktest_idr_case3(uint64_t arg0, uint64_t arg1)
{
DECLARE_IDR(k_idr);
const int N = 1949;
int tmp;
// 获取ID
for (int i = 0; i < N; i++)
{
assert(idr_alloc(&k_idr, &tmp, &tmp) == 0);
assert(tmp == i);
int *ptr = idr_find(&k_idr, i);
assert(ptr != NULL);
assert(*ptr == i);
}
// 查询 nextid
for (int i = 1; i <= N; i++)
{
int nextid;
int *ptr = idr_find_next_getid(&k_idr, i - 1, &nextid);
if (likely(i < N))
{
assert(ptr != NULL);
assert(*ptr == N - 1);
assert(nextid == i);
}
else
{
assert(ptr == NULL);
assert(nextid == -1);
}
}
int sz = N;
// 删掉某一段
for (int i = N / 3, j = 2 * (N / 3), k = 0; i <= j; k++, i++)
{
int *ptr = idr_find(&k_idr, i);
assert(ptr != NULL);
assert(*ptr == N - 1);
idr_remove(&k_idr, i);
assert(idr_find(&k_idr, i) == NULL);
sz--;
assert(k_idr.top != NULL);
}
// 查询 nextid
for (int i = 1; i <= N; i++)
{
int nextid;
int *ptr = idr_find_next_getid(&k_idr, i - 1, &nextid);
if (likely(i < N))
{
int target = i < N / 3 ? i : max(i, 2 * (N / 3) + 1);
assert(ptr != NULL);
assert(*ptr == N - 1);
assert(nextid == target);
}
else
{
assert(ptr == NULL);
assert(nextid == -1);
}
}
// 销毁
idr_destroy(&k_idr);
assert(k_idr.id_free_cnt == 0);
assert(k_idr.free_list == NULL);
return 0;
}
/**
* @brief 更加全面覆盖所有函数 - 小数据测试
*
* @param arg0
* @param arg1
*/
static long ktest_idr_case4(uint64_t arg0, uint64_t arg1)
{
DECLARE_IDR(k_idr);
idr_init(&k_idr);
const int N = 91173;
static uint32_t tmp;
for (int i = 1; i <= 20; i++)
{
int M = N / i, T = M / 3, b = 2 * T;
for (int j = 0; j < M; j++)
{
assert(idr_alloc(&k_idr, &tmp, &tmp) == 0);
assert(tmp == j);
}
for (int j = b; j >= T; j--)
{
int *ptr = idr_find(&k_idr, j);
assert(ptr != NULL);
assert(*ptr == M - 1);
idr_remove(&k_idr, j);
}
for (int j = b + 1; j < M; j++)
{
int *ptr = idr_find(&k_idr, j);
assert(ptr != NULL);
assert(*ptr == M - 1);
idr_remove(&k_idr, j);
}
for (int j = T - 1; j >= 0; j--)
{
int *ptr = idr_find(&k_idr, j);
assert(ptr != NULL);
assert(*ptr == M - 1);
idr_remove(&k_idr, j);
}
assert(k_idr.top == NULL);
assert(idr_empty(&k_idr));
}
// 销毁
idr_destroy(&k_idr);
assert(k_idr.id_free_cnt == 0);
assert(k_idr.free_list == NULL);
assert(idr_empty(&k_idr));
return 0;
}
/**
* @brief 测试id的获取id的删除id的全体删除, idr的find函数
*
* @param arg0
* @param arg1
*/
static long ktest_idr_case5(uint64_t arg0, uint64_t arg1)
{
DECLARE_IDR(k_idr);
const int N = 128;
int a[N];
// 获取128个id
for (int i = 0; i < N; i++)
{
assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
assert(a[i] == i);
}
// 把id指向的指针向后移动一个单位
for (int i = 0; i < N; i++)
{
int *ptr;
int flags = idr_replace_get_old(&k_idr, &a[(i + 1) % N], i, (void *)&ptr);
assert(flags == 0); // 0 是成功
assert(ptr != NULL);
assert(*ptr == i);
// 测试是否替换成功
ptr = idr_find(&k_idr, i);
assert(ptr != NULL);
assert(*ptr == (i + 1) % N);
}
// 销毁
idr_destroy(&k_idr);
assert(k_idr.id_free_cnt == 0);
assert(k_idr.free_list == NULL);
// destroy之后再获取128个id
for (int i = 0; i < N; i++)
{
assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
assert(a[i] == i);
}
// 销毁
idr_destroy(&k_idr);
assert(idr_empty(&k_idr));
assert(k_idr.id_free_cnt == 0);
assert(k_idr.free_list == NULL);
return 0;
}
/**
* @brief 测试ida的插入/删除
*
* @param arg0
* @param arg1
* @return long
*/
static long ktest_idr_case6(uint64_t arg0, uint64_t arg1)
{
assert(IDA_BITMAP_LONGS != 0);
assert(IDA_BMP_SIZE != 0);
assert(IDA_FULL != 0);
assert(IDA_BITMAP_BITS != 0);
DECLARE_IDA(k_ida);
ida_init(&k_ida);
io_sfence();
const int N = IDA_FULL * IDR_SIZE + 1;
for (int i = 0; i < N; i++)
{
int p_id;
io_sfence();
assert(ida_alloc(&k_ida, &p_id) == 0);
io_sfence();
assert(p_id == i);
io_sfence();
}
for (int i = 0; i < N; i++)
{
assert(ida_count(&k_ida, i) == 1);
io_sfence();
}
for (int i = N - 1; i >= 0; i--)
{
ida_remove(&k_ida, i);
io_sfence();
assert(ida_count(&k_ida, i) == 0);
io_sfence();
}
assert(k_ida.idr.top == NULL);
for (int i = 0; i < N; i++)
{
int p_id;
io_sfence();
assert(ida_alloc(&k_ida, &p_id) == 0);
io_sfence();
assert(p_id == i);
io_sfence();
}
assert(k_ida.idr.top != NULL);
io_sfence();
ida_destroy(&k_ida);
io_sfence();
assert(k_ida.idr.top == NULL);
io_sfence();
assert(k_ida.free_list == NULL);
io_sfence();
assert(ida_empty(&k_ida));
io_sfence();
// 测试destroy之后能否重新获取ID
for (int i = 0; i < N; i++)
{
int p_id;
io_sfence();
assert(ida_alloc(&k_ida, &p_id) == 0);
io_sfence();
assert(p_id == i);
io_sfence();
}
for (int i = 0; i < N / 3; i++)
{
ida_remove(&k_ida, i);
io_sfence();
assert(ida_count(&k_ida, i) == 0);
io_sfence();
}
for (int i = 2 * N / 3; i < N; i++)
{
ida_remove(&k_ida, i);
io_sfence();
assert(ida_count(&k_ida, i) == 0);
io_sfence();
}
assert(k_ida.idr.top != NULL);
io_sfence();
ida_destroy(&k_ida);
io_sfence();
assert(k_ida.idr.top == NULL);
io_sfence();
assert(k_ida.free_list == NULL);
io_sfence();
assert(ida_empty(&k_ida));
io_sfence();
return 0;
}
static ktest_case_table kt_idr_func_table[] = {
ktest_idr_case0,
ktest_idr_case1,
// ktest_idr_case2, // 为了加快启动速度, 暂时注释掉这个测试
ktest_idr_case3,
ktest_idr_case4,
ktest_idr_case5,
ktest_idr_case6,
};
int ktest_test_idr(void *arg)
{
kTEST("Testing idr...");
unsigned int sz = sizeof(kt_idr_func_table) / sizeof(ktest_case_table);
for (int i = 0; i < sz; ++i)
{
kTEST("Testing case %d", i);
kt_idr_func_table[i](i, i + 1);
}
kTEST("idr Test done.");
return 0;
}
#pragma GCC pop_options