diff options
Diffstat (limited to 'lib/bitops_test.c')
-rw-r--r-- | lib/bitops_test.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/lib/bitops_test.c b/lib/bitops_test.c new file mode 100644 index 00000000..bd02fccc --- /dev/null +++ b/lib/bitops_test.c @@ -0,0 +1,123 @@ +/* + * 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 BT_SUCCESS; +} + +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 BT_SUCCESS; +} + +static void +check_log2(u32 n) +{ + u32 log = u32_log2(n); + u32 low = bt_naive_pow(2, log); + u32 high = bt_naive_pow(2, log+1); + + 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 = 1; i < MAX_NUM; i++) + check_log2(i); + + for (i = 1; i < MAX_NUM; i++) + check_log2(((u32) bt_random()) % 0x0fffffff); + + return BT_SUCCESS; +} + +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()"); + + return bt_exit_value(); +} |