0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00
bird/lib/bitops_test.c

160 lines
3.2 KiB
C

/*
* BIRD Library -- Generic Bit Operations Tests
*
* (c) 2015 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include "test/birdtest.h"
#include "test/bt-utils.h" /* naive_pow() */
#include "lib/bitops.h"
#define MAX_NUM 1000
#define CHECK_BIT(var,pos) ((var) & (u32)(1<<(pos)))
static int
t_mkmask(void)
{
int i;
u32 compute, expect;
bt_assert(u32_mkmask(0) == 0x00000000);
for (i = 1; i <= 32; i++)
{
compute = u32_mkmask(i);
expect = (u32) (0xffffffff << (32-i));
bt_assert_msg(compute == expect, "u32_mkmask(%d) = 0x%08X, expected 0x%08X", i, compute, expect);
}
return 1;
}
static int
u32_masklen_expected(u32 mask)
{
int j, expect = 0;
int valid = 0;
for (j = 0; j <= 32; j++)
if (mask == (j ? (0xffffffff << (32-j)) : 0)) /* Shifting 32-bit value by 32 bits is undefined behavior */
valid = 1;
if (!valid && mask != 0)
expect = 255;
else
for (j = 0; j <= 31; j++)
if (CHECK_BIT(mask, (31-j)))
expect = j+1;
else
break;
return expect;
}
static void
check_mask(u32 mask)
{
int expected, masklen;
expected = u32_masklen_expected(mask);
masklen = u32_masklen(mask);
int ok = (expected == masklen);
bt_debug("u32_masklen(Ox%08x) = %d, expected %d %s\n", mask, masklen, expected, ok ? "OK" : "FAIL!");
bt_assert(ok);
}
static int
t_masklen(void)
{
u32 i;
check_mask(0x82828282);
check_mask(0x00000000);
for (i = 0; i <= 32; i++)
check_mask(((u32) (i ? (0xffffffff << (32-i)) : 0)) & 0xffffffff); /* Shifting 32-bit value by 32 bits is undefined behavior */
for (i = 0; i <= MAX_NUM; i++)
check_mask(bt_random());
return 1;
}
static void
check_log2(u64 n)
{
u64 log = u64_log2(n);
u64 low = bt_naive_pow(2, log);
u64 high = bt_naive_pow(2, log+1);
if (n <= 0xffffffff)
bt_assert(u32_log2(n) == log);
bt_assert_msg(n >= low && n < high,
"u32_log2(%u) = %u, %u should be in the range <%u, %u)",
n, log, n, low, high);
}
static int
t_log2(void)
{
u32 i;
for (i = 0; i < 31; i++)
bt_assert(u32_log2(bt_naive_pow(2, i+1)) == i+1);
for (i = 0; i < 63; i++)
bt_assert(u64_log2(bt_naive_pow(2, i+1)) == i+1);
for (i = 1; i < MAX_NUM; i++)
check_log2(i);
for (i = 1; i < MAX_NUM; i++)
check_log2((unsigned long int) bt_random());
return 1;
}
static void
var_enc_dec(u64 data, uint padlen)
{
uint olen = ~0;
u64 enc = u64_var_encode(data, padlen);
u64 odata = u64_var_decode(enc, &olen);
bt_assert_msg(
(odata == data) && (olen == padlen),
"u64_var_encode(0x%llx, %u) == 0x%llx; u64_var_decode(0x%llx, %u) == 0x%llx",
data, padlen, enc, enc, olen, odata
);
}
static int
t_var(void)
{
for (uint i = 0; i < 63; i++)
for (uint j = 1; j+i < 64; j++) {
var_enc_dec(1ULL << i, j);
var_enc_dec((1ULL << i) - 1, j);
var_enc_dec(((unsigned long int) bt_random()) & ((1ULL << (64-j)) - 1), j);
}
return 1;
}
int
main(int argc, char *argv[])
{
bt_init(argc, argv);
bt_test_suite(t_mkmask, "u32_mkmask()");
bt_test_suite(t_masklen, "u32_masklen()");
bt_test_suite(t_log2, "u32_log2()");
bt_test_suite(t_var, "u64_var_(en|de)code()");
return bt_exit_value();
}