selftests/bpf: libarena: Add bitmap selftests

Add testing for the new arena bitmap data structure.

Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
Acked-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Link: https://lore.kernel.org/bpf/20260706181730.21731-6-emil@etsalapatis.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
Emil Tsalapatis 2026-07-06 14:17:29 -04:00 committed by Kumar Kartikeya Dwivedi
parent 5a93b10f6c
commit 5a903a4f73
No known key found for this signature in database
GPG Key ID: 472D377B63542F83

View File

@ -0,0 +1,394 @@
#include <libarena/common.h>
#include <libarena/asan.h>
#include <libarena/bitmap.h>
#define TEST_BITS (2 * BITS_PER_LONG_LONG)
#define TEST_WORDS BITS_TO_LONG_LONGS(TEST_BITS)
#define MID_BIT (BITS_PER_LONG_LONG + 1)
#define LAST_BIT (TEST_BITS - 1)
static void test_bmp_setall(struct bitmap __arena *bmp)
{
volatile u32 i;
for (i = zero; i < TEST_WORDS && can_loop; i++)
bmp->bits[i] = ~0ULL;
}
SEC("syscall")
__weak int test_bitmap_alloc_free(void)
{
struct bitmap __arena *bmp;
bmp = bmp_alloc(TEST_BITS);
if (!bmp)
return -ENOMEM;
if (!bmp_empty(TEST_BITS, bmp))
goto err;
__bmp_set_bit(LAST_BIT, bmp);
if (!bmp_test_bit(LAST_BIT, bmp))
goto err;
__bmp_clear_bit(LAST_BIT, bmp);
if (bmp_test_bit(LAST_BIT, bmp))
goto err;
bmp_free(bmp);
return 0;
err:
bmp_free(bmp);
return -EINVAL;
}
SEC("syscall")
__weak int test_bitmap_bit_ops(void)
{
struct bitmap __arena *bmp;
bmp = bmp_alloc(TEST_BITS);
if (!bmp)
return -ENOMEM;
__bmp_set_bit(0, bmp);
if (!bmp_test_bit(0, bmp))
goto err;
__bmp_set_bit(MID_BIT, bmp);
if (!bmp_test_bit(MID_BIT, bmp))
goto err;
__bmp_set_bit(LAST_BIT, bmp);
if (!bmp_test_bit(LAST_BIT, bmp))
goto err;
if (bmp_test_bit(MID_BIT - 1, bmp))
goto err;
__bmp_clear_bit(MID_BIT, bmp);
if (bmp_test_bit(MID_BIT, bmp))
goto err;
if (!bmp_test_bit(0, bmp))
goto err;
if (!bmp_test_bit(LAST_BIT, bmp))
goto err;
__bmp_clear_bit(0, bmp);
__bmp_clear_bit(LAST_BIT, bmp);
if (!bmp_empty(TEST_BITS, bmp))
goto err;
if (bmp->bits[0])
goto err;
if (bmp->bits[1])
goto err;
bmp_free(bmp);
return 0;
err:
bmp_free(bmp);
return -EINVAL;
}
static bool test_bitmap_test_and_clear_single(struct bitmap __arena *bmp, size_t ind)
{
if (bmp_test_and_clear_bit(ind, bmp))
return false;
__bmp_set_bit(ind, bmp);
if (!bmp_test_and_clear_bit(ind, bmp))
return false;
if (bmp_test_bit(ind, bmp))
return false;
if (bmp_test_and_clear_bit(ind, bmp))
return false;
return true;
}
static bool test_bitmap_test_and_set_single(struct bitmap __arena *bmp, size_t ind)
{
if (bmp_test_and_set_bit(ind, bmp))
return false;
if (!bmp_test_and_set_bit(ind, bmp))
return false;
if (!bmp_test_bit(ind, bmp))
return false;
__bmp_clear_bit(ind, bmp);
if (bmp_test_and_set_bit(ind, bmp))
return false;
return true;
}
SEC("syscall")
__weak int test_bitmap_test_and_clear_bit(void)
{
struct bitmap __arena *bmp;
bmp = bmp_alloc(TEST_BITS);
if (!bmp)
return -ENOMEM;
if (!test_bitmap_test_and_clear_single(bmp, 0))
goto err;
if (!test_bitmap_test_and_clear_single(bmp, MID_BIT))
goto err;
if (!test_bitmap_test_and_clear_single(bmp, LAST_BIT))
goto err;
if (!bmp_empty(TEST_BITS, bmp))
goto err;
bmp_free(bmp);
return 0;
err:
bmp_free(bmp);
return -EINVAL;
}
SEC("syscall")
__weak int test_bitmap_test_and_set_bit(void)
{
struct bitmap __arena *bmp;
bmp = bmp_alloc(TEST_BITS);
if (!bmp)
return -ENOMEM;
if (!test_bitmap_test_and_set_single(bmp, 0))
goto err;
if (!test_bitmap_test_and_set_single(bmp, MID_BIT))
goto err;
if (!test_bitmap_test_and_set_single(bmp, LAST_BIT))
goto err;
bmp_free(bmp);
return 0;
err:
bmp_free(bmp);
return -EINVAL;
}
SEC("syscall")
__weak int test_bitmap_and(void)
{
struct bitmap __arena *src1 = NULL, *src2 = NULL, *dst = NULL;
src1 = bmp_alloc(TEST_BITS);
src2 = bmp_alloc(TEST_BITS);
dst = bmp_alloc(TEST_BITS);
if (!src1 || !src2 || !dst)
goto err;
test_bmp_setall(dst);
__bmp_set_bit(0, src1);
__bmp_set_bit(MID_BIT, src1);
__bmp_set_bit(LAST_BIT, src1);
__bmp_set_bit(MID_BIT, src2);
__bmp_set_bit(LAST_BIT, src2);
bmp_and(TEST_BITS, dst, src1, src2);
if (bmp_test_bit(0, dst))
goto err;
if (!bmp_test_bit(MID_BIT, dst))
goto err;
if (!bmp_test_bit(LAST_BIT, dst))
goto err;
if (dst->bits[0])
goto err;
if (dst->bits[1] != (BIT_MASK(MID_BIT) | BIT_MASK(LAST_BIT)))
goto err;
bmp_free(src1);
bmp_free(src2);
bmp_free(dst);
return 0;
err:
bmp_free(src1);
bmp_free(src2);
bmp_free(dst);
return -EINVAL;
}
SEC("syscall")
__weak int test_bitmap_or(void)
{
struct bitmap __arena *src1 = NULL, *src2 = NULL, *dst = NULL;
src1 = bmp_alloc(TEST_BITS);
src2 = bmp_alloc(TEST_BITS);
dst = bmp_alloc(TEST_BITS);
if (!src1 || !src2 || !dst)
goto err;
test_bmp_setall(dst);
__bmp_set_bit(0, src1);
__bmp_set_bit(LAST_BIT, src1);
__bmp_set_bit(MID_BIT, src2);
__bmp_set_bit(LAST_BIT, src2);
bmp_or(TEST_BITS, dst, src1, src2);
if (!bmp_test_bit(0, dst))
goto err;
if (!bmp_test_bit(MID_BIT, dst))
goto err;
if (!bmp_test_bit(LAST_BIT, dst))
goto err;
if (dst->bits[0] != BIT_MASK(0))
goto err;
if (dst->bits[1] != (BIT_MASK(MID_BIT) | BIT_MASK(LAST_BIT)))
goto err;
bmp_free(src1);
bmp_free(src2);
bmp_free(dst);
return 0;
err:
bmp_free(src1);
bmp_free(src2);
bmp_free(dst);
return -EINVAL;
}
SEC("syscall")
__weak int test_bitmap_subset(void)
{
struct bitmap __arena *big = NULL, *small = NULL;
big = bmp_alloc(TEST_BITS);
small = bmp_alloc(TEST_BITS);
if (!big || !small)
goto err;
if (!bmp_subset(TEST_BITS, big, small))
goto err;
__bmp_set_bit(0, small);
if (bmp_subset(TEST_BITS, big, small))
goto err;
__bmp_set_bit(0, big);
if (!bmp_subset(TEST_BITS, big, small))
goto err;
__bmp_set_bit(LAST_BIT, small);
if (bmp_subset(TEST_BITS, big, small))
goto err;
__bmp_set_bit(LAST_BIT, big);
__bmp_set_bit(MID_BIT, big);
if (!bmp_subset(TEST_BITS, big, small))
goto err;
if (bmp_subset(TEST_BITS, small, big))
goto err;
bmp_free(big);
bmp_free(small);
return 0;
err:
bmp_free(big);
bmp_free(small);
return -EINVAL;
}
SEC("syscall")
__weak int test_bitmap_intersects(void)
{
struct bitmap __arena *arg1 = NULL, *arg2 = NULL;
arg1 = bmp_alloc(TEST_BITS);
arg2 = bmp_alloc(TEST_BITS);
if (!arg1 || !arg2)
goto err;
if (bmp_intersects(TEST_BITS, arg1, arg2))
goto err;
__bmp_set_bit(0, arg1);
__bmp_set_bit(MID_BIT, arg2);
if (bmp_intersects(TEST_BITS, arg1, arg2))
goto err;
__bmp_set_bit(LAST_BIT, arg1);
__bmp_set_bit(LAST_BIT, arg2);
if (!bmp_intersects(TEST_BITS, arg1, arg2))
goto err;
bmp_free(arg1);
bmp_free(arg2);
return 0;
err:
bmp_free(arg1);
bmp_free(arg2);
return -EINVAL;
}
SEC("syscall")
__weak int test_bitmap_copy(void)
{
struct bitmap __arena *arg1 = NULL, *arg2 = NULL;
arg1 = bmp_alloc(TEST_BITS);
arg2 = bmp_alloc(TEST_BITS);
if (!arg1 || !arg2)
goto err;
__bmp_set_bit(0, arg1);
__bmp_set_bit(MID_BIT, arg1);
/* Make sure those get overwritten. */
__bmp_set_bit(1, arg2);
__bmp_set_bit(MID_BIT + 2, arg2);
bmp_copy(TEST_BITS, arg2, arg1);
/* Bitmaps are equal if a subset of each other. */
if (!bmp_subset(TEST_BITS, arg1, arg2) ||
!bmp_subset(TEST_BITS, arg2, arg1))
goto err;
bmp_free(arg1);
bmp_free(arg2);
return 0;
err:
bmp_free(arg1);
bmp_free(arg2);
return -EINVAL;
}