xref: /dpdk/app/test/test_bitset.c (revision c889c037f67342d972ef7a24580d3c24b6f33e26)
199a11976SMattias Rönnblom /* SPDX-License-Identifier: BSD-3-Clause
299a11976SMattias Rönnblom  * Copyright(c) 2023 Ericsson AB
399a11976SMattias Rönnblom  */
499a11976SMattias Rönnblom 
599a11976SMattias Rönnblom #include <inttypes.h>
699a11976SMattias Rönnblom #include <stdlib.h>
799a11976SMattias Rönnblom 
899a11976SMattias Rönnblom #include <rte_bitset.h>
999a11976SMattias Rönnblom #include <rte_random.h>
1099a11976SMattias Rönnblom 
1199a11976SMattias Rönnblom #include "test.h"
1299a11976SMattias Rönnblom 
1399a11976SMattias Rönnblom #define MAGIC UINT64_C(0xdeadbeefdeadbeef)
1499a11976SMattias Rönnblom 
1599a11976SMattias Rönnblom static void
1699a11976SMattias Rönnblom rand_buf(void *buf, size_t n)
1799a11976SMattias Rönnblom {
1899a11976SMattias Rönnblom 	size_t i;
1999a11976SMattias Rönnblom 
2099a11976SMattias Rönnblom 	for (i = 0; i < n; i++)
2199a11976SMattias Rönnblom 		((unsigned char *)buf)[i] = rte_rand();
2299a11976SMattias Rönnblom }
2399a11976SMattias Rönnblom 
2499a11976SMattias Rönnblom static uint64_t *
2599a11976SMattias Rönnblom alloc_bitset(size_t size)
2699a11976SMattias Rönnblom {
2799a11976SMattias Rönnblom 	uint64_t *p;
2899a11976SMattias Rönnblom 
2999a11976SMattias Rönnblom 	p = malloc(RTE_BITSET_SIZE(size) + 2 * sizeof(uint64_t));
3099a11976SMattias Rönnblom 	if (p == NULL)
3199a11976SMattias Rönnblom 		rte_panic("Unable to allocate memory\n");
3299a11976SMattias Rönnblom 
3399a11976SMattias Rönnblom 	rand_buf(&p[0], RTE_BITSET_SIZE(size));
3499a11976SMattias Rönnblom 
3599a11976SMattias Rönnblom 	p[0] = MAGIC;
3699a11976SMattias Rönnblom 	p[RTE_BITSET_NUM_WORDS(size) + 1] = MAGIC;
3799a11976SMattias Rönnblom 
3899a11976SMattias Rönnblom 	return p + 1;
3999a11976SMattias Rönnblom }
4099a11976SMattias Rönnblom 
4199a11976SMattias Rönnblom 
4299a11976SMattias Rönnblom static int
4399a11976SMattias Rönnblom free_bitset(uint64_t *bitset, size_t size)
4499a11976SMattias Rönnblom {
4599a11976SMattias Rönnblom 	uint64_t *p;
4699a11976SMattias Rönnblom 
4799a11976SMattias Rönnblom 	p = bitset - 1;
4899a11976SMattias Rönnblom 
4999a11976SMattias Rönnblom 	if (p[0] != MAGIC)
5099a11976SMattias Rönnblom 		return TEST_FAILED;
5199a11976SMattias Rönnblom 
5299a11976SMattias Rönnblom 	if (p[RTE_BITSET_NUM_WORDS(size) + 1] != MAGIC)
5399a11976SMattias Rönnblom 		return TEST_FAILED;
5499a11976SMattias Rönnblom 
5599a11976SMattias Rönnblom 	free(p);
5699a11976SMattias Rönnblom 
5799a11976SMattias Rönnblom 	return TEST_SUCCESS;
5899a11976SMattias Rönnblom }
5999a11976SMattias Rönnblom 
6099a11976SMattias Rönnblom static bool
6199a11976SMattias Rönnblom rand_bool(void)
6299a11976SMattias Rönnblom {
6399a11976SMattias Rönnblom 	return rte_rand_max(2);
6499a11976SMattias Rönnblom }
6599a11976SMattias Rönnblom 
6699a11976SMattias Rönnblom static void
6799a11976SMattias Rönnblom rand_bool_ary(bool *ary, size_t len)
6899a11976SMattias Rönnblom {
6999a11976SMattias Rönnblom 	size_t i;
7099a11976SMattias Rönnblom 
7199a11976SMattias Rönnblom 	for (i = 0; i < len; i++)
7299a11976SMattias Rönnblom 		ary[i] = rand_bool();
7399a11976SMattias Rönnblom }
7499a11976SMattias Rönnblom 
7599a11976SMattias Rönnblom static void
7699a11976SMattias Rönnblom rand_unused_bits(uint64_t *bitset, size_t size)
7799a11976SMattias Rönnblom {
7899a11976SMattias Rönnblom 	uint64_t bits = rte_rand() & ~__RTE_BITSET_USED_MASK(size);
7999a11976SMattias Rönnblom 
8099a11976SMattias Rönnblom 	bitset[RTE_BITSET_NUM_WORDS(size) - 1] |= bits;
8199a11976SMattias Rönnblom }
8299a11976SMattias Rönnblom 
8399a11976SMattias Rönnblom static void
8499a11976SMattias Rönnblom rand_bitset(uint64_t *bitset, size_t size)
8599a11976SMattias Rönnblom {
8699a11976SMattias Rönnblom 	size_t i;
8799a11976SMattias Rönnblom 
8899a11976SMattias Rönnblom 	rte_bitset_init(bitset, size);
8999a11976SMattias Rönnblom 
9099a11976SMattias Rönnblom 	for (i = 0; i < size; i++)
9199a11976SMattias Rönnblom 		rte_bitset_assign(bitset, i, rand_bool());
9299a11976SMattias Rönnblom 
9399a11976SMattias Rönnblom 	rand_unused_bits(bitset, size);
9499a11976SMattias Rönnblom }
9599a11976SMattias Rönnblom 
9699a11976SMattias Rönnblom typedef bool test_fun(const uint64_t *bitset, size_t bit_num);
9799a11976SMattias Rönnblom typedef void set_fun(uint64_t *bitset, size_t bit_num);
9899a11976SMattias Rönnblom typedef void clear_fun(uint64_t *bitset, size_t bit_num);
9999a11976SMattias Rönnblom typedef void assign_fun(uint64_t *bitset, size_t bit_num, bool value);
10099a11976SMattias Rönnblom typedef void flip_fun(uint64_t *bitset, size_t bit_num);
10199a11976SMattias Rönnblom 
10299a11976SMattias Rönnblom static int
10399a11976SMattias Rönnblom test_set_clear_size(test_fun test_fun, set_fun set_fun, clear_fun clear_fun, size_t size)
10499a11976SMattias Rönnblom {
10599a11976SMattias Rönnblom 	size_t i;
10699a11976SMattias Rönnblom 	bool reference[size];
10799a11976SMattias Rönnblom 	uint64_t *bitset;
10899a11976SMattias Rönnblom 
10999a11976SMattias Rönnblom 	rand_bool_ary(reference, size);
11099a11976SMattias Rönnblom 
11199a11976SMattias Rönnblom 	bitset = alloc_bitset(size);
11299a11976SMattias Rönnblom 
11399a11976SMattias Rönnblom 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
11499a11976SMattias Rönnblom 
11599a11976SMattias Rönnblom 	rte_bitset_init(bitset, size);
11699a11976SMattias Rönnblom 
11799a11976SMattias Rönnblom 	for (i = 0; i < size; i++) {
11899a11976SMattias Rönnblom 		if (reference[i])
11999a11976SMattias Rönnblom 			set_fun(bitset, i);
12099a11976SMattias Rönnblom 		else
12199a11976SMattias Rönnblom 			clear_fun(bitset, i);
12299a11976SMattias Rönnblom 	}
12399a11976SMattias Rönnblom 
12499a11976SMattias Rönnblom 	for (i = 0; i < size; i++)
12599a11976SMattias Rönnblom 		if (reference[i] != test_fun(bitset, i))
12699a11976SMattias Rönnblom 			return TEST_FAILED;
12799a11976SMattias Rönnblom 
12899a11976SMattias Rönnblom 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
12999a11976SMattias Rönnblom 		"Buffer over- or underrun detected");
13099a11976SMattias Rönnblom 
13199a11976SMattias Rönnblom 	return TEST_SUCCESS;
13299a11976SMattias Rönnblom }
13399a11976SMattias Rönnblom 
13499a11976SMattias Rönnblom #define RAND_ITERATIONS (10000)
13599a11976SMattias Rönnblom #define RAND_SET_MAX_SIZE (1000)
13699a11976SMattias Rönnblom 
13799a11976SMattias Rönnblom static int
13899a11976SMattias Rönnblom test_set_clear_fun(test_fun test_fun, set_fun set_fun, clear_fun clear_fun)
13999a11976SMattias Rönnblom {
14099a11976SMattias Rönnblom 	size_t i;
14199a11976SMattias Rönnblom 
14299a11976SMattias Rönnblom 	for (i = 0; i < RAND_ITERATIONS; i++) {
14399a11976SMattias Rönnblom 		size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
14499a11976SMattias Rönnblom 
14599a11976SMattias Rönnblom 		if (test_set_clear_size(test_fun, set_fun, clear_fun, size) != TEST_SUCCESS)
14699a11976SMattias Rönnblom 			return TEST_FAILED;
14799a11976SMattias Rönnblom 	}
14899a11976SMattias Rönnblom 
14999a11976SMattias Rönnblom 	return TEST_SUCCESS;
15099a11976SMattias Rönnblom }
15199a11976SMattias Rönnblom 
15299a11976SMattias Rönnblom static int
15399a11976SMattias Rönnblom test_set_clear(void)
15499a11976SMattias Rönnblom {
15599a11976SMattias Rönnblom 	return test_set_clear_fun(rte_bitset_test, rte_bitset_set, rte_bitset_clear);
15699a11976SMattias Rönnblom }
15799a11976SMattias Rönnblom 
15899a11976SMattias Rönnblom static int
15999a11976SMattias Rönnblom test_flip_size(test_fun test_fun, assign_fun assign_fun, flip_fun flip_fun, size_t size)
16099a11976SMattias Rönnblom {
16199a11976SMattias Rönnblom 	size_t i;
16299a11976SMattias Rönnblom 	uint64_t *bitset;
16399a11976SMattias Rönnblom 
16499a11976SMattias Rönnblom 	bitset = alloc_bitset(size);
16599a11976SMattias Rönnblom 
16699a11976SMattias Rönnblom 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
16799a11976SMattias Rönnblom 
16899a11976SMattias Rönnblom 	rand_bitset(bitset, size);
16999a11976SMattias Rönnblom 
17099a11976SMattias Rönnblom 	for (i = 0; i < size; i++) {
17199a11976SMattias Rönnblom 		RTE_BITSET_DECLARE(reference, size);
17299a11976SMattias Rönnblom 
17399a11976SMattias Rönnblom 		rte_bitset_copy(reference, bitset, size);
17499a11976SMattias Rönnblom 
17599a11976SMattias Rönnblom 		bool value = test_fun(bitset, i);
17699a11976SMattias Rönnblom 
17799a11976SMattias Rönnblom 		flip_fun(bitset, i);
17899a11976SMattias Rönnblom 
17999a11976SMattias Rönnblom 		TEST_ASSERT(test_fun(bitset, i) != value, "Bit %zd was not flipped", i);
18099a11976SMattias Rönnblom 
18199a11976SMattias Rönnblom 		assign_fun(reference, i, !value);
18299a11976SMattias Rönnblom 
18399a11976SMattias Rönnblom 		TEST_ASSERT(rte_bitset_equal(bitset, reference, size),
18499a11976SMattias Rönnblom 			"Not only the target bit %zd was flipped", i);
18599a11976SMattias Rönnblom 
18699a11976SMattias Rönnblom 
18799a11976SMattias Rönnblom 	}
18899a11976SMattias Rönnblom 
18999a11976SMattias Rönnblom 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
19099a11976SMattias Rönnblom 		"Buffer over- or underrun detected");
19199a11976SMattias Rönnblom 
19299a11976SMattias Rönnblom 	return TEST_SUCCESS;
19399a11976SMattias Rönnblom }
19499a11976SMattias Rönnblom 
19599a11976SMattias Rönnblom static int
19699a11976SMattias Rönnblom test_flip_fun(test_fun test_fun, assign_fun assign_fun, flip_fun flip_fun)
19799a11976SMattias Rönnblom {
19899a11976SMattias Rönnblom 	size_t i;
19999a11976SMattias Rönnblom 
20099a11976SMattias Rönnblom 	for (i = 0; i < RAND_ITERATIONS; i++) {
20199a11976SMattias Rönnblom 		size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
20299a11976SMattias Rönnblom 
20399a11976SMattias Rönnblom 		if (test_flip_size(test_fun, assign_fun, flip_fun, size) != TEST_SUCCESS)
20499a11976SMattias Rönnblom 			return TEST_FAILED;
20599a11976SMattias Rönnblom 	}
20699a11976SMattias Rönnblom 
20799a11976SMattias Rönnblom 	return TEST_SUCCESS;
20899a11976SMattias Rönnblom }
20999a11976SMattias Rönnblom 
21099a11976SMattias Rönnblom static int
21199a11976SMattias Rönnblom test_flip(void)
21299a11976SMattias Rönnblom {
21399a11976SMattias Rönnblom 	return test_flip_fun(rte_bitset_test, rte_bitset_assign, rte_bitset_flip);
21499a11976SMattias Rönnblom }
21599a11976SMattias Rönnblom 
216*c889c037SMattias Rönnblom static bool
217*c889c037SMattias Rönnblom bitset_atomic_test(const uint64_t *bitset, size_t bit_num)
218*c889c037SMattias Rönnblom {
219*c889c037SMattias Rönnblom 	return rte_bitset_atomic_test(bitset, bit_num, rte_memory_order_relaxed);
220*c889c037SMattias Rönnblom }
221*c889c037SMattias Rönnblom 
222*c889c037SMattias Rönnblom static void
223*c889c037SMattias Rönnblom bitset_atomic_set(uint64_t *bitset, size_t bit_num)
224*c889c037SMattias Rönnblom {
225*c889c037SMattias Rönnblom 	rte_bitset_atomic_set(bitset, bit_num, rte_memory_order_relaxed);
226*c889c037SMattias Rönnblom }
227*c889c037SMattias Rönnblom 
228*c889c037SMattias Rönnblom static void
229*c889c037SMattias Rönnblom bitset_atomic_clear(uint64_t *bitset, size_t bit_num)
230*c889c037SMattias Rönnblom {
231*c889c037SMattias Rönnblom 	rte_bitset_atomic_clear(bitset, bit_num, rte_memory_order_relaxed);
232*c889c037SMattias Rönnblom }
233*c889c037SMattias Rönnblom 
234*c889c037SMattias Rönnblom static void
235*c889c037SMattias Rönnblom bitset_atomic_flip(uint64_t *bitset, size_t bit_num)
236*c889c037SMattias Rönnblom {
237*c889c037SMattias Rönnblom 	rte_bitset_atomic_flip(bitset, bit_num, rte_memory_order_relaxed);
238*c889c037SMattias Rönnblom }
239*c889c037SMattias Rönnblom 
240*c889c037SMattias Rönnblom static void
241*c889c037SMattias Rönnblom bitset_atomic_assign(uint64_t *bitset, size_t bit_num, bool bit_value)
242*c889c037SMattias Rönnblom {
243*c889c037SMattias Rönnblom 	rte_bitset_atomic_assign(bitset, bit_num, bit_value, rte_memory_order_relaxed);
244*c889c037SMattias Rönnblom }
245*c889c037SMattias Rönnblom 
246*c889c037SMattias Rönnblom static int
247*c889c037SMattias Rönnblom test_atomic_set_clear(void)
248*c889c037SMattias Rönnblom {
249*c889c037SMattias Rönnblom 	return test_set_clear_fun(bitset_atomic_test, bitset_atomic_set, bitset_atomic_clear);
250*c889c037SMattias Rönnblom }
251*c889c037SMattias Rönnblom 
252*c889c037SMattias Rönnblom static int
253*c889c037SMattias Rönnblom test_atomic_flip(void)
254*c889c037SMattias Rönnblom {
255*c889c037SMattias Rönnblom 	return test_flip_fun(bitset_atomic_test, bitset_atomic_assign, bitset_atomic_flip);
256*c889c037SMattias Rönnblom }
257*c889c037SMattias Rönnblom 
25899a11976SMattias Rönnblom static ssize_t
25999a11976SMattias Rönnblom find(const bool *ary, size_t num_bools, size_t start, size_t len, bool set)
26099a11976SMattias Rönnblom {
26199a11976SMattias Rönnblom 	size_t i;
26299a11976SMattias Rönnblom 
26399a11976SMattias Rönnblom 	for (i = 0; i < len; i++) {
26499a11976SMattias Rönnblom 		ssize_t idx = (start + i) % num_bools;
26599a11976SMattias Rönnblom 
26699a11976SMattias Rönnblom 		if (ary[idx] == set)
26799a11976SMattias Rönnblom 			return idx;
26899a11976SMattias Rönnblom 	}
26999a11976SMattias Rönnblom 
27099a11976SMattias Rönnblom 	return -1;
27199a11976SMattias Rönnblom }
27299a11976SMattias Rönnblom 
27399a11976SMattias Rönnblom static ssize_t
27499a11976SMattias Rönnblom find_set(const bool *ary, size_t num_bools, size_t start, size_t len)
27599a11976SMattias Rönnblom {
27699a11976SMattias Rönnblom 	return find(ary, num_bools, start, len, true);
27799a11976SMattias Rönnblom }
27899a11976SMattias Rönnblom 
27999a11976SMattias Rönnblom static ssize_t
28099a11976SMattias Rönnblom find_clear(const bool *ary, size_t num_bools, size_t start, size_t len)
28199a11976SMattias Rönnblom {
28299a11976SMattias Rönnblom 	return find(ary, num_bools, start, len, false);
28399a11976SMattias Rönnblom }
28499a11976SMattias Rönnblom 
28599a11976SMattias Rönnblom #define FFS_ITERATIONS (100)
28699a11976SMattias Rönnblom 
28799a11976SMattias Rönnblom static int
28899a11976SMattias Rönnblom test_find_size(size_t size, bool set)
28999a11976SMattias Rönnblom {
29099a11976SMattias Rönnblom 	uint64_t *bitset;
29199a11976SMattias Rönnblom 	bool reference[size];
29299a11976SMattias Rönnblom 	size_t i;
29399a11976SMattias Rönnblom 
29499a11976SMattias Rönnblom 	bitset = alloc_bitset(size);
29599a11976SMattias Rönnblom 
29699a11976SMattias Rönnblom 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
29799a11976SMattias Rönnblom 
29899a11976SMattias Rönnblom 	rte_bitset_init(bitset, size);
29999a11976SMattias Rönnblom 
30099a11976SMattias Rönnblom 	for (i = 0; i < size; i++) {
30199a11976SMattias Rönnblom 		bool bit = rand_bool();
30299a11976SMattias Rönnblom 		reference[i] = bit;
30399a11976SMattias Rönnblom 
30499a11976SMattias Rönnblom 		if (bit)
30599a11976SMattias Rönnblom 			rte_bitset_set(bitset, i);
30699a11976SMattias Rönnblom 		else /* redundant, still useful for testing */
30799a11976SMattias Rönnblom 			rte_bitset_clear(bitset, i);
30899a11976SMattias Rönnblom 	}
30999a11976SMattias Rönnblom 
31099a11976SMattias Rönnblom 	for (i = 0; i < FFS_ITERATIONS; i++) {
31199a11976SMattias Rönnblom 		size_t start_bit = rte_rand_max(size);
31299a11976SMattias Rönnblom 		size_t len = rte_rand_max(size + 1);
31399a11976SMattias Rönnblom 		bool full_range = len == size && start_bit == 0;
31499a11976SMattias Rönnblom 		bool wraps = start_bit + len > size;
31599a11976SMattias Rönnblom 		ssize_t rc;
31699a11976SMattias Rönnblom 
31799a11976SMattias Rönnblom 		if (set) {
31899a11976SMattias Rönnblom 			if (full_range && rand_bool())
31999a11976SMattias Rönnblom 				rc = rte_bitset_find_first_set(bitset, size);
32099a11976SMattias Rönnblom 			else if (wraps || rand_bool())
32199a11976SMattias Rönnblom 				rc = rte_bitset_find_set_wrap(bitset, size, start_bit, len);
32299a11976SMattias Rönnblom 			else
32399a11976SMattias Rönnblom 				rc = rte_bitset_find_set(bitset, size, start_bit, len);
32499a11976SMattias Rönnblom 
32599a11976SMattias Rönnblom 			if (rc != find_set(reference, size, start_bit, len))
32699a11976SMattias Rönnblom 				return TEST_FAILED;
32799a11976SMattias Rönnblom 		} else {
32899a11976SMattias Rönnblom 			if (full_range && rand_bool())
32999a11976SMattias Rönnblom 				rc = rte_bitset_find_first_clear(bitset, size);
33099a11976SMattias Rönnblom 			else if (wraps || rand_bool())
33199a11976SMattias Rönnblom 				rc = rte_bitset_find_clear_wrap(bitset, size, start_bit, len);
33299a11976SMattias Rönnblom 			else
33399a11976SMattias Rönnblom 				rc = rte_bitset_find_clear(bitset, size, start_bit, len);
33499a11976SMattias Rönnblom 
33599a11976SMattias Rönnblom 			if (rc != find_clear(reference, size, start_bit, len))
33699a11976SMattias Rönnblom 				return TEST_FAILED;
33799a11976SMattias Rönnblom 		}
33899a11976SMattias Rönnblom 
33999a11976SMattias Rönnblom 	}
34099a11976SMattias Rönnblom 
34199a11976SMattias Rönnblom 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
34299a11976SMattias Rönnblom 		"Buffer over- or underrun detected");
34399a11976SMattias Rönnblom 
34499a11976SMattias Rönnblom 	return TEST_SUCCESS;
34599a11976SMattias Rönnblom }
34699a11976SMattias Rönnblom 
34799a11976SMattias Rönnblom static int
34899a11976SMattias Rönnblom test_find_set_size(size_t size)
34999a11976SMattias Rönnblom {
35099a11976SMattias Rönnblom 	return test_find_size(size, true);
35199a11976SMattias Rönnblom }
35299a11976SMattias Rönnblom 
35399a11976SMattias Rönnblom static int
35499a11976SMattias Rönnblom test_find_clear_size(size_t size)
35599a11976SMattias Rönnblom {
35699a11976SMattias Rönnblom 	return test_find_size(size, false);
35799a11976SMattias Rönnblom }
35899a11976SMattias Rönnblom 
35999a11976SMattias Rönnblom static int
36099a11976SMattias Rönnblom test_find(void)
36199a11976SMattias Rönnblom {
36299a11976SMattias Rönnblom 	size_t i;
36399a11976SMattias Rönnblom 
36499a11976SMattias Rönnblom 	for (i = 0; i < RAND_ITERATIONS; i++) {
36599a11976SMattias Rönnblom 		size_t size = 2 + rte_rand_max(RAND_SET_MAX_SIZE - 2);
36699a11976SMattias Rönnblom 
36799a11976SMattias Rönnblom 		if (test_find_set_size(size) != TEST_SUCCESS)
36899a11976SMattias Rönnblom 			return TEST_FAILED;
36999a11976SMattias Rönnblom 
37099a11976SMattias Rönnblom 		if (test_find_clear_size(size) != TEST_SUCCESS)
37199a11976SMattias Rönnblom 			return TEST_FAILED;
37299a11976SMattias Rönnblom 	}
37399a11976SMattias Rönnblom 
37499a11976SMattias Rönnblom 	return TEST_SUCCESS;
37599a11976SMattias Rönnblom }
37699a11976SMattias Rönnblom 
37799a11976SMattias Rönnblom static int
37899a11976SMattias Rönnblom record_match(ssize_t match_idx, size_t size, int *calls)
37999a11976SMattias Rönnblom {
38099a11976SMattias Rönnblom 	if (match_idx < 0 || (size_t)match_idx >= size)
38199a11976SMattias Rönnblom 		return TEST_FAILED;
38299a11976SMattias Rönnblom 
38399a11976SMattias Rönnblom 	calls[match_idx]++;
38499a11976SMattias Rönnblom 
38599a11976SMattias Rönnblom 	return TEST_SUCCESS;
38699a11976SMattias Rönnblom }
38799a11976SMattias Rönnblom 
38899a11976SMattias Rönnblom static int
38999a11976SMattias Rönnblom test_foreach_size(ssize_t size, bool may_wrap, bool set)
39099a11976SMattias Rönnblom {
39199a11976SMattias Rönnblom 	bool reference[size];
39299a11976SMattias Rönnblom 	int calls[size];
39399a11976SMattias Rönnblom 	uint64_t *bitset;
39499a11976SMattias Rönnblom 	ssize_t i;
39599a11976SMattias Rönnblom 	ssize_t start_bit;
39699a11976SMattias Rönnblom 	ssize_t len;
39799a11976SMattias Rönnblom 	bool full_range;
39899a11976SMattias Rönnblom 	size_t total_calls = 0;
39999a11976SMattias Rönnblom 
40099a11976SMattias Rönnblom 	rand_bool_ary(reference, size);
40199a11976SMattias Rönnblom 
40299a11976SMattias Rönnblom 	bitset = alloc_bitset(size);
40399a11976SMattias Rönnblom 
40499a11976SMattias Rönnblom 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
40599a11976SMattias Rönnblom 
40699a11976SMattias Rönnblom 	memset(calls, 0, sizeof(calls));
40799a11976SMattias Rönnblom 
40899a11976SMattias Rönnblom 	start_bit = rte_rand_max(size);
40999a11976SMattias Rönnblom 	len = may_wrap ? rte_rand_max(size + 1) :
41099a11976SMattias Rönnblom 		rte_rand_max(size - start_bit + 1);
41199a11976SMattias Rönnblom 
41299a11976SMattias Rönnblom 	rte_bitset_init(bitset, size);
41399a11976SMattias Rönnblom 
41499a11976SMattias Rönnblom 	/* random data in the unused bits should not matter */
41599a11976SMattias Rönnblom 	rand_buf(bitset, RTE_BITSET_SIZE(size));
41699a11976SMattias Rönnblom 
41799a11976SMattias Rönnblom 	for (i = start_bit; i < start_bit + len; i++) {
41899a11976SMattias Rönnblom 		size_t idx = i % size;
41999a11976SMattias Rönnblom 
42099a11976SMattias Rönnblom 		if (reference[idx])
42199a11976SMattias Rönnblom 			rte_bitset_set(bitset, idx);
42299a11976SMattias Rönnblom 		else
42399a11976SMattias Rönnblom 			rte_bitset_clear(bitset, idx);
42499a11976SMattias Rönnblom 
42599a11976SMattias Rönnblom 		if (rte_bitset_test(bitset, idx) != reference[idx])
42699a11976SMattias Rönnblom 			return TEST_FAILED;
42799a11976SMattias Rönnblom 	}
42899a11976SMattias Rönnblom 
42999a11976SMattias Rönnblom 	full_range = (len == size && start_bit == 0);
43099a11976SMattias Rönnblom 
43199a11976SMattias Rönnblom 	/* XXX: verify iteration order as well */
43299a11976SMattias Rönnblom 	if (set) {
43399a11976SMattias Rönnblom 		if (full_range && rand_bool()) {
43499a11976SMattias Rönnblom 			RTE_BITSET_FOREACH_SET(i, bitset, size) {
43599a11976SMattias Rönnblom 				if (record_match(i, size, calls) != TEST_SUCCESS)
43699a11976SMattias Rönnblom 					return TEST_FAILED;
43799a11976SMattias Rönnblom 			}
43899a11976SMattias Rönnblom 		} else if (may_wrap) {
43999a11976SMattias Rönnblom 			RTE_BITSET_FOREACH_SET_WRAP(i, bitset, size, start_bit, len) {
44099a11976SMattias Rönnblom 				if (record_match(i, size, calls) != TEST_SUCCESS) {
44199a11976SMattias Rönnblom 					printf("failed\n");
44299a11976SMattias Rönnblom 					return TEST_FAILED;
44399a11976SMattias Rönnblom 				}
44499a11976SMattias Rönnblom 			}
44599a11976SMattias Rönnblom 		} else {
44699a11976SMattias Rönnblom 			RTE_BITSET_FOREACH_SET_RANGE(i, bitset, size, start_bit, len) {
44799a11976SMattias Rönnblom 				if (record_match(i, size, calls) != TEST_SUCCESS)
44899a11976SMattias Rönnblom 					return TEST_FAILED;
44999a11976SMattias Rönnblom 			}
45099a11976SMattias Rönnblom 		}
45199a11976SMattias Rönnblom 	} else {
45299a11976SMattias Rönnblom 		if (full_range && rand_bool()) {
45399a11976SMattias Rönnblom 			RTE_BITSET_FOREACH_CLEAR(i, bitset, size)
45499a11976SMattias Rönnblom 				if (record_match(i, size, calls) != TEST_SUCCESS)
45599a11976SMattias Rönnblom 					return TEST_FAILED;
45699a11976SMattias Rönnblom 		} else if (may_wrap) {
45799a11976SMattias Rönnblom 			RTE_BITSET_FOREACH_CLEAR_WRAP(i, bitset, size, start_bit, len) {
45899a11976SMattias Rönnblom 				if (record_match(i, size, calls) != TEST_SUCCESS)
45999a11976SMattias Rönnblom 					return TEST_FAILED;
46099a11976SMattias Rönnblom 			}
46199a11976SMattias Rönnblom 		} else {
46299a11976SMattias Rönnblom 			RTE_BITSET_FOREACH_CLEAR_RANGE(i, bitset, size, start_bit, len)
46399a11976SMattias Rönnblom 				if (record_match(i, size, calls) != TEST_SUCCESS)
46499a11976SMattias Rönnblom 					return TEST_FAILED;
46599a11976SMattias Rönnblom 		}
46699a11976SMattias Rönnblom 	}
46799a11976SMattias Rönnblom 
46899a11976SMattias Rönnblom 	for (i = 0; i < len; i++) {
46999a11976SMattias Rönnblom 		size_t idx = (start_bit + i) % size;
47099a11976SMattias Rönnblom 
47199a11976SMattias Rönnblom 		if (reference[idx] == set && calls[idx] != 1) {
47299a11976SMattias Rönnblom 			printf("bit %zd shouldn't have been found %d times\n", idx, calls[idx]);
47399a11976SMattias Rönnblom 			return TEST_FAILED;
47499a11976SMattias Rönnblom 		}
47599a11976SMattias Rönnblom 
47699a11976SMattias Rönnblom 		if (reference[idx] != set && calls[idx] != 0) {
47799a11976SMattias Rönnblom 			puts("bar");
47899a11976SMattias Rönnblom 			return TEST_FAILED;
47999a11976SMattias Rönnblom 		}
48099a11976SMattias Rönnblom 
48199a11976SMattias Rönnblom 		total_calls += calls[idx];
48299a11976SMattias Rönnblom 	}
48399a11976SMattias Rönnblom 
48499a11976SMattias Rönnblom 	if (full_range) {
48599a11976SMattias Rönnblom 		size_t count;
48699a11976SMattias Rönnblom 
48799a11976SMattias Rönnblom 		count = set ? rte_bitset_count_set(bitset, size) :
48899a11976SMattias Rönnblom 			rte_bitset_count_clear(bitset, size);
48999a11976SMattias Rönnblom 
49099a11976SMattias Rönnblom 		if (count != total_calls)
49199a11976SMattias Rönnblom 			return TEST_FAILED;
49299a11976SMattias Rönnblom 	}
49399a11976SMattias Rönnblom 
49499a11976SMattias Rönnblom 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
49599a11976SMattias Rönnblom 		"Buffer over- or underrun detected");
49699a11976SMattias Rönnblom 
49799a11976SMattias Rönnblom 	return TEST_SUCCESS;
49899a11976SMattias Rönnblom }
49999a11976SMattias Rönnblom 
50099a11976SMattias Rönnblom static int
50199a11976SMattias Rönnblom test_foreach(void)
50299a11976SMattias Rönnblom {
50399a11976SMattias Rönnblom 	size_t i;
50499a11976SMattias Rönnblom 
50599a11976SMattias Rönnblom 	for (i = 0; i < RAND_ITERATIONS; i++) {
50699a11976SMattias Rönnblom 		size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
50799a11976SMattias Rönnblom 
50899a11976SMattias Rönnblom 		if (test_foreach_size(size, false, true) != TEST_SUCCESS)
50999a11976SMattias Rönnblom 			return TEST_FAILED;
51099a11976SMattias Rönnblom 
51199a11976SMattias Rönnblom 		if (test_foreach_size(size, false, false) != TEST_SUCCESS)
51299a11976SMattias Rönnblom 			return TEST_FAILED;
51399a11976SMattias Rönnblom 
51499a11976SMattias Rönnblom 		if (test_foreach_size(size, true, true) != TEST_SUCCESS)
51599a11976SMattias Rönnblom 			return TEST_FAILED;
51699a11976SMattias Rönnblom 
51799a11976SMattias Rönnblom 		if (test_foreach_size(size, true, false) != TEST_SUCCESS)
51899a11976SMattias Rönnblom 			return TEST_FAILED;
51999a11976SMattias Rönnblom 	}
52099a11976SMattias Rönnblom 
52199a11976SMattias Rönnblom 	return TEST_SUCCESS;
52299a11976SMattias Rönnblom }
52399a11976SMattias Rönnblom 
52499a11976SMattias Rönnblom static int
52599a11976SMattias Rönnblom test_count_size(size_t size)
52699a11976SMattias Rönnblom {
52799a11976SMattias Rönnblom 	uint64_t *bitset;
52899a11976SMattias Rönnblom 
52999a11976SMattias Rönnblom 	bitset = alloc_bitset(size);
53099a11976SMattias Rönnblom 
53199a11976SMattias Rönnblom 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
53299a11976SMattias Rönnblom 
53399a11976SMattias Rönnblom 	rte_bitset_init(bitset, size);
53499a11976SMattias Rönnblom 
53599a11976SMattias Rönnblom 	rand_unused_bits(bitset, size);
53699a11976SMattias Rönnblom 
53799a11976SMattias Rönnblom 	if (rte_bitset_count_set(bitset, size) != 0)
53899a11976SMattias Rönnblom 		return TEST_FAILED;
53999a11976SMattias Rönnblom 
54099a11976SMattias Rönnblom 	if (rte_bitset_count_clear(bitset, size) != size)
54199a11976SMattias Rönnblom 		return TEST_FAILED;
54299a11976SMattias Rönnblom 
54399a11976SMattias Rönnblom 	rte_bitset_set_all(bitset, size);
54499a11976SMattias Rönnblom 
54599a11976SMattias Rönnblom 	if (rte_bitset_count_set(bitset, size) != size)
54699a11976SMattias Rönnblom 		return TEST_FAILED;
54799a11976SMattias Rönnblom 
54899a11976SMattias Rönnblom 	if (rte_bitset_count_clear(bitset, size) != 0)
54999a11976SMattias Rönnblom 		return TEST_FAILED;
55099a11976SMattias Rönnblom 
55199a11976SMattias Rönnblom 	rte_bitset_clear_all(bitset, size);
55299a11976SMattias Rönnblom 
55399a11976SMattias Rönnblom 	if (rte_bitset_count_set(bitset, size) != 0)
55499a11976SMattias Rönnblom 		return TEST_FAILED;
55599a11976SMattias Rönnblom 
55699a11976SMattias Rönnblom 	if (rte_bitset_count_clear(bitset, size) != size)
55799a11976SMattias Rönnblom 		return TEST_FAILED;
55899a11976SMattias Rönnblom 
55999a11976SMattias Rönnblom 	rte_bitset_set(bitset, rte_rand_max(size));
56099a11976SMattias Rönnblom 
56199a11976SMattias Rönnblom 	if (rte_bitset_count_set(bitset, size) != 1)
56299a11976SMattias Rönnblom 		return TEST_FAILED;
56399a11976SMattias Rönnblom 
56499a11976SMattias Rönnblom 	if (rte_bitset_count_clear(bitset, size) != (size - 1))
56599a11976SMattias Rönnblom 		return TEST_FAILED;
56699a11976SMattias Rönnblom 
56799a11976SMattias Rönnblom 	rte_bitset_clear_all(bitset, size);
56899a11976SMattias Rönnblom 	if (rte_bitset_count_set(bitset, size) != 0)
56999a11976SMattias Rönnblom 		return TEST_FAILED;
57099a11976SMattias Rönnblom 	if (rte_bitset_count_clear(bitset, size) != size)
57199a11976SMattias Rönnblom 		return TEST_FAILED;
57299a11976SMattias Rönnblom 
57399a11976SMattias Rönnblom 	rte_bitset_set_all(bitset, size);
57499a11976SMattias Rönnblom 	if (rte_bitset_count_set(bitset, size) != size)
57599a11976SMattias Rönnblom 		return TEST_FAILED;
57699a11976SMattias Rönnblom 	if (rte_bitset_count_clear(bitset, size) != 0)
57799a11976SMattias Rönnblom 		return TEST_FAILED;
57899a11976SMattias Rönnblom 
57999a11976SMattias Rönnblom 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
58099a11976SMattias Rönnblom 		"Buffer over- or underrun detected");
58199a11976SMattias Rönnblom 
58299a11976SMattias Rönnblom 	return TEST_SUCCESS;
58399a11976SMattias Rönnblom }
58499a11976SMattias Rönnblom 
58599a11976SMattias Rönnblom static int
58699a11976SMattias Rönnblom test_count(void)
58799a11976SMattias Rönnblom {
58899a11976SMattias Rönnblom 	size_t i;
58999a11976SMattias Rönnblom 
59099a11976SMattias Rönnblom 	if (test_count_size(128) != TEST_SUCCESS)
59199a11976SMattias Rönnblom 		return TEST_FAILED;
59299a11976SMattias Rönnblom 	if (test_count_size(1) != TEST_SUCCESS)
59399a11976SMattias Rönnblom 		return TEST_FAILED;
59499a11976SMattias Rönnblom 	if (test_count_size(63) != TEST_SUCCESS)
59599a11976SMattias Rönnblom 		return TEST_FAILED;
59699a11976SMattias Rönnblom 	if (test_count_size(64) != TEST_SUCCESS)
59799a11976SMattias Rönnblom 		return TEST_FAILED;
59899a11976SMattias Rönnblom 	if (test_count_size(65) != TEST_SUCCESS)
59999a11976SMattias Rönnblom 		return TEST_FAILED;
60099a11976SMattias Rönnblom 
60199a11976SMattias Rönnblom 	for (i = 0; i < RAND_ITERATIONS; i++) {
60299a11976SMattias Rönnblom 		size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
60399a11976SMattias Rönnblom 
60499a11976SMattias Rönnblom 		if (test_count_size(size) != TEST_SUCCESS)
60599a11976SMattias Rönnblom 			return TEST_FAILED;
60699a11976SMattias Rönnblom 	}
60799a11976SMattias Rönnblom 
60899a11976SMattias Rönnblom 	return TEST_SUCCESS;
60999a11976SMattias Rönnblom }
61099a11976SMattias Rönnblom 
61199a11976SMattias Rönnblom #define GEN_DECLARE(size) \
61299a11976SMattias Rönnblom { \
61399a11976SMattias Rönnblom 	RTE_BITSET_DECLARE(bitset, size); \
61499a11976SMattias Rönnblom 	size_t idx = rte_rand_max(size); \
61599a11976SMattias Rönnblom 	rte_bitset_init(bitset, size); \
61699a11976SMattias Rönnblom 	rte_bitset_set(bitset, idx); \
61799a11976SMattias Rönnblom 	if (!rte_bitset_test(bitset, idx)) \
61899a11976SMattias Rönnblom 		return TEST_FAILED; \
61999a11976SMattias Rönnblom 	if (rte_bitset_count_set(bitset, size) != 1) \
62099a11976SMattias Rönnblom 		return TEST_FAILED; \
62199a11976SMattias Rönnblom 	return TEST_SUCCESS; \
62299a11976SMattias Rönnblom }
62399a11976SMattias Rönnblom 
62499a11976SMattias Rönnblom static int
62599a11976SMattias Rönnblom test_define(void)
62699a11976SMattias Rönnblom {
62799a11976SMattias Rönnblom 	GEN_DECLARE(1);
62899a11976SMattias Rönnblom 	GEN_DECLARE(64);
62999a11976SMattias Rönnblom 	GEN_DECLARE(65);
63099a11976SMattias Rönnblom 	GEN_DECLARE(4097);
63199a11976SMattias Rönnblom }
63299a11976SMattias Rönnblom 
63399a11976SMattias Rönnblom typedef void bitset_op(uint64_t *dst, const uint64_t *a, const uint64_t *b, size_t bit_num);
63499a11976SMattias Rönnblom typedef bool bool_op(bool a, bool b);
63599a11976SMattias Rönnblom 
63699a11976SMattias Rönnblom static int
63799a11976SMattias Rönnblom test_logic_op(bitset_op bitset_op, bool_op bool_op)
63899a11976SMattias Rönnblom {
63999a11976SMattias Rönnblom 	const size_t size = 1 + rte_rand_max(200);
64099a11976SMattias Rönnblom 	RTE_BITSET_DECLARE(bitset_a, size);
64199a11976SMattias Rönnblom 	RTE_BITSET_DECLARE(bitset_b, size);
64299a11976SMattias Rönnblom 	RTE_BITSET_DECLARE(bitset_d, size);
64399a11976SMattias Rönnblom 
64499a11976SMattias Rönnblom 	bool ary_a[size];
64599a11976SMattias Rönnblom 	bool ary_b[size];
64699a11976SMattias Rönnblom 	bool ary_d[size];
64799a11976SMattias Rönnblom 
64899a11976SMattias Rönnblom 	rand_bool_ary(ary_a, size);
64999a11976SMattias Rönnblom 	rand_bool_ary(ary_b, size);
65099a11976SMattias Rönnblom 
65199a11976SMattias Rönnblom 	size_t i;
65299a11976SMattias Rönnblom 	for (i = 0; i < size; i++) {
65399a11976SMattias Rönnblom 		rte_bitset_assign(bitset_a, i, ary_a[i]);
65499a11976SMattias Rönnblom 		rte_bitset_assign(bitset_b, i, ary_b[i]);
65599a11976SMattias Rönnblom 		ary_d[i] = bool_op(ary_a[i], ary_b[i]);
65699a11976SMattias Rönnblom 	}
65799a11976SMattias Rönnblom 
65899a11976SMattias Rönnblom 	bitset_op(bitset_d, bitset_a, bitset_b, size);
65999a11976SMattias Rönnblom 
66099a11976SMattias Rönnblom 	for (i = 0; i < size; i++)
66199a11976SMattias Rönnblom 		TEST_ASSERT_EQUAL(rte_bitset_test(bitset_d, i), ary_d[i],
66299a11976SMattias Rönnblom 			"Unexpected value of bit %zd", i);
66399a11976SMattias Rönnblom 
66499a11976SMattias Rönnblom 	return TEST_SUCCESS;
66599a11976SMattias Rönnblom }
66699a11976SMattias Rönnblom 
66799a11976SMattias Rönnblom static bool
66899a11976SMattias Rönnblom bool_or(bool a, bool b)
66999a11976SMattias Rönnblom {
67099a11976SMattias Rönnblom 	return a || b;
67199a11976SMattias Rönnblom }
67299a11976SMattias Rönnblom 
67399a11976SMattias Rönnblom static int
67499a11976SMattias Rönnblom test_or(void)
67599a11976SMattias Rönnblom {
67699a11976SMattias Rönnblom 	return test_logic_op(rte_bitset_or, bool_or);
67799a11976SMattias Rönnblom }
67899a11976SMattias Rönnblom 
67999a11976SMattias Rönnblom static bool
68099a11976SMattias Rönnblom bool_and(bool a, bool b)
68199a11976SMattias Rönnblom {
68299a11976SMattias Rönnblom 	return a && b;
68399a11976SMattias Rönnblom }
68499a11976SMattias Rönnblom 
68599a11976SMattias Rönnblom static int
68699a11976SMattias Rönnblom test_and(void)
68799a11976SMattias Rönnblom {
68899a11976SMattias Rönnblom 	return test_logic_op(rte_bitset_and, bool_and);
68999a11976SMattias Rönnblom }
69099a11976SMattias Rönnblom 
69199a11976SMattias Rönnblom static bool
69299a11976SMattias Rönnblom bool_xor(bool a, bool b)
69399a11976SMattias Rönnblom {
69499a11976SMattias Rönnblom 	return a != b;
69599a11976SMattias Rönnblom }
69699a11976SMattias Rönnblom 
69799a11976SMattias Rönnblom static int
69899a11976SMattias Rönnblom test_xor(void)
69999a11976SMattias Rönnblom {
70099a11976SMattias Rönnblom 	return test_logic_op(rte_bitset_xor, bool_xor);
70199a11976SMattias Rönnblom }
70299a11976SMattias Rönnblom 
70399a11976SMattias Rönnblom static int
70499a11976SMattias Rönnblom test_complement(void)
70599a11976SMattias Rönnblom {
70699a11976SMattias Rönnblom 	int i;
70799a11976SMattias Rönnblom 
70899a11976SMattias Rönnblom 	for (i = 0; i < RAND_ITERATIONS; i++) {
70999a11976SMattias Rönnblom 		const size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
71099a11976SMattias Rönnblom 
71199a11976SMattias Rönnblom 		RTE_BITSET_DECLARE(src, size);
71299a11976SMattias Rönnblom 
71399a11976SMattias Rönnblom 		rand_bitset(src, size);
71499a11976SMattias Rönnblom 
71599a11976SMattias Rönnblom 		bool bit_idx = rte_rand_max(size);
71699a11976SMattias Rönnblom 		bool bit_value = rte_bitset_test(src, bit_idx);
71799a11976SMattias Rönnblom 
71899a11976SMattias Rönnblom 		RTE_BITSET_DECLARE(dst, size);
71999a11976SMattias Rönnblom 
72099a11976SMattias Rönnblom 		rte_bitset_complement(dst, src, size);
72199a11976SMattias Rönnblom 
72299a11976SMattias Rönnblom 		TEST_ASSERT(bit_value != rte_bitset_test(dst, bit_idx),
72399a11976SMattias Rönnblom 			"Bit %d was not flipped", bit_idx);
72499a11976SMattias Rönnblom 	}
72599a11976SMattias Rönnblom 
72699a11976SMattias Rönnblom 	return TEST_SUCCESS;
72799a11976SMattias Rönnblom }
72899a11976SMattias Rönnblom 
72999a11976SMattias Rönnblom static int
73099a11976SMattias Rönnblom test_shift(bool right)
73199a11976SMattias Rönnblom {
73299a11976SMattias Rönnblom 	int i;
73399a11976SMattias Rönnblom 
73499a11976SMattias Rönnblom 	const char *direction = right ? "right" : "left";
73599a11976SMattias Rönnblom 
73699a11976SMattias Rönnblom 	for (i = 0; i < 10000; i++) {
73799a11976SMattias Rönnblom 		const int size = 1 + (int)rte_rand_max(500);
73899a11976SMattias Rönnblom 		const int shift_count = (int)rte_rand_max(1.5 * size);
73999a11976SMattias Rönnblom 		int src_idx;
74099a11976SMattias Rönnblom 
74199a11976SMattias Rönnblom 		RTE_BITSET_DECLARE(src, size);
74299a11976SMattias Rönnblom 		RTE_BITSET_DECLARE(reference, size);
74399a11976SMattias Rönnblom 
74499a11976SMattias Rönnblom 		rte_bitset_init(src, size);
74599a11976SMattias Rönnblom 		rte_bitset_init(reference, size);
74699a11976SMattias Rönnblom 
74799a11976SMattias Rönnblom 		rand_unused_bits(src, size);
74899a11976SMattias Rönnblom 		rand_unused_bits(reference, size);
74999a11976SMattias Rönnblom 
75099a11976SMattias Rönnblom 		for (src_idx = 0; src_idx < size; src_idx++) {
75199a11976SMattias Rönnblom 			bool value = rand_bool();
75299a11976SMattias Rönnblom 
75399a11976SMattias Rönnblom 			rte_bitset_assign(src, src_idx, value);
75499a11976SMattias Rönnblom 
75599a11976SMattias Rönnblom 			int dst_idx = right ? src_idx - shift_count : src_idx + shift_count;
75699a11976SMattias Rönnblom 
75799a11976SMattias Rönnblom 			if (dst_idx >= 0 && dst_idx < size)
75899a11976SMattias Rönnblom 				rte_bitset_assign(reference, dst_idx, value);
75999a11976SMattias Rönnblom 		}
76099a11976SMattias Rönnblom 
76199a11976SMattias Rönnblom 		uint64_t *dst = alloc_bitset(size);
76299a11976SMattias Rönnblom 
76399a11976SMattias Rönnblom 		if (right)
76499a11976SMattias Rönnblom 			rte_bitset_shift_right(dst, src, size, shift_count);
76599a11976SMattias Rönnblom 		else
76699a11976SMattias Rönnblom 			rte_bitset_shift_left(dst, src, size, shift_count);
76799a11976SMattias Rönnblom 
76899a11976SMattias Rönnblom 		TEST_ASSERT(rte_bitset_equal(dst, reference, size),
76999a11976SMattias Rönnblom 			"Unexpected result from shifting bitset of size %d bits %d bits %s",
77099a11976SMattias Rönnblom 			size, shift_count, direction);
77199a11976SMattias Rönnblom 
77299a11976SMattias Rönnblom 		TEST_ASSERT_EQUAL(free_bitset(dst, size), TEST_SUCCESS,
77399a11976SMattias Rönnblom 			"Shift %s operation overwrote buffer", direction);
77499a11976SMattias Rönnblom 	}
77599a11976SMattias Rönnblom 
77699a11976SMattias Rönnblom 	return TEST_SUCCESS;
77799a11976SMattias Rönnblom }
77899a11976SMattias Rönnblom 
77999a11976SMattias Rönnblom static int
78099a11976SMattias Rönnblom test_shift_right(void)
78199a11976SMattias Rönnblom {
78299a11976SMattias Rönnblom 	return test_shift(true);
78399a11976SMattias Rönnblom }
78499a11976SMattias Rönnblom 
78599a11976SMattias Rönnblom static int
78699a11976SMattias Rönnblom test_shift_left(void)
78799a11976SMattias Rönnblom {
78899a11976SMattias Rönnblom 	return test_shift(false);
78999a11976SMattias Rönnblom }
79099a11976SMattias Rönnblom 
79199a11976SMattias Rönnblom static int
79299a11976SMattias Rönnblom test_equal(void)
79399a11976SMattias Rönnblom {
79499a11976SMattias Rönnblom 	const size_t size = 100;
79599a11976SMattias Rönnblom 	RTE_BITSET_DECLARE(bitset_a, size);
79699a11976SMattias Rönnblom 	RTE_BITSET_DECLARE(bitset_b, size);
79799a11976SMattias Rönnblom 
79899a11976SMattias Rönnblom 	rand_buf(bitset_a, RTE_BITSET_SIZE(size));
79999a11976SMattias Rönnblom 	rand_buf(bitset_b, RTE_BITSET_SIZE(size));
80099a11976SMattias Rönnblom 
80199a11976SMattias Rönnblom 	rte_bitset_init(bitset_a, size);
80299a11976SMattias Rönnblom 	rte_bitset_init(bitset_b, size);
80399a11976SMattias Rönnblom 
80499a11976SMattias Rönnblom 	rte_bitset_set(bitset_a, 9);
80599a11976SMattias Rönnblom 	rte_bitset_set(bitset_b, 9);
80699a11976SMattias Rönnblom 	rte_bitset_set(bitset_a, 90);
80799a11976SMattias Rönnblom 	rte_bitset_set(bitset_b, 90);
80899a11976SMattias Rönnblom 
80999a11976SMattias Rönnblom 	if (!rte_bitset_equal(bitset_a, bitset_b, size))
81099a11976SMattias Rönnblom 		return TEST_FAILED;
81199a11976SMattias Rönnblom 
81299a11976SMattias Rönnblom 	/* set unused bit, which should be ignored */
81399a11976SMattias Rönnblom 	rte_bitset_set(&bitset_a[1], 60);
81499a11976SMattias Rönnblom 
81599a11976SMattias Rönnblom 	if (!rte_bitset_equal(bitset_a, bitset_b, size))
81699a11976SMattias Rönnblom 		return TEST_FAILED;
81799a11976SMattias Rönnblom 
81899a11976SMattias Rönnblom 	return TEST_SUCCESS;
81999a11976SMattias Rönnblom }
82099a11976SMattias Rönnblom 
82199a11976SMattias Rönnblom static int
82299a11976SMattias Rönnblom test_copy(void)
82399a11976SMattias Rönnblom {
82499a11976SMattias Rönnblom 	const size_t size = 100;
82599a11976SMattias Rönnblom 	RTE_BITSET_DECLARE(bitset_a, size);
82699a11976SMattias Rönnblom 	RTE_BITSET_DECLARE(bitset_b, size);
82799a11976SMattias Rönnblom 
82899a11976SMattias Rönnblom 	rand_buf(bitset_a, RTE_BITSET_SIZE(size));
82999a11976SMattias Rönnblom 	rand_buf(bitset_b, RTE_BITSET_SIZE(size));
83099a11976SMattias Rönnblom 
83199a11976SMattias Rönnblom 	rte_bitset_copy(bitset_a, bitset_b, size);
83299a11976SMattias Rönnblom 
83399a11976SMattias Rönnblom 	if (!rte_bitset_equal(bitset_a, bitset_b, size))
83499a11976SMattias Rönnblom 		return TEST_FAILED;
83599a11976SMattias Rönnblom 
83699a11976SMattias Rönnblom 	return TEST_SUCCESS;
83799a11976SMattias Rönnblom }
83899a11976SMattias Rönnblom 
83999a11976SMattias Rönnblom static int
84099a11976SMattias Rönnblom test_to_str(void)
84199a11976SMattias Rönnblom {
84299a11976SMattias Rönnblom 	char buf[1024];
84399a11976SMattias Rönnblom 	RTE_BITSET_DECLARE(bitset, 128);
84499a11976SMattias Rönnblom 
84599a11976SMattias Rönnblom 	rte_bitset_init(bitset, 128);
84699a11976SMattias Rönnblom 	rte_bitset_set(bitset, 1);
84799a11976SMattias Rönnblom 
84899a11976SMattias Rönnblom 	if (rte_bitset_to_str(bitset, 2, buf, 3) != 3)
84999a11976SMattias Rönnblom 		return TEST_FAILED;
85099a11976SMattias Rönnblom 	if (strcmp(buf, "10") != 0)
85199a11976SMattias Rönnblom 		return TEST_FAILED;
85299a11976SMattias Rönnblom 
85399a11976SMattias Rönnblom 	rte_bitset_set(bitset, 0);
85499a11976SMattias Rönnblom 
85599a11976SMattias Rönnblom 	if (rte_bitset_to_str(bitset, 1, buf, sizeof(buf)) != 2)
85699a11976SMattias Rönnblom 		return TEST_FAILED;
85799a11976SMattias Rönnblom 	if (strcmp(buf, "1") != 0)
85899a11976SMattias Rönnblom 		return TEST_FAILED;
85999a11976SMattias Rönnblom 
86099a11976SMattias Rönnblom 	rte_bitset_init(bitset, 99);
86199a11976SMattias Rönnblom 	rte_bitset_set(bitset, 98);
86299a11976SMattias Rönnblom 
86399a11976SMattias Rönnblom 	if (rte_bitset_to_str(bitset, 99, buf, sizeof(buf)) != 100)
86499a11976SMattias Rönnblom 		return TEST_FAILED;
86599a11976SMattias Rönnblom 
86699a11976SMattias Rönnblom 	if (buf[0] != '1' || strchr(&buf[1], '1') != NULL)
86799a11976SMattias Rönnblom 		return TEST_FAILED;
86899a11976SMattias Rönnblom 
86999a11976SMattias Rönnblom 	if (rte_bitset_to_str(bitset, 128, buf, 64) != -EINVAL)
87099a11976SMattias Rönnblom 		return TEST_FAILED;
87199a11976SMattias Rönnblom 
87299a11976SMattias Rönnblom 	return TEST_SUCCESS;
87399a11976SMattias Rönnblom }
87499a11976SMattias Rönnblom 
87599a11976SMattias Rönnblom static struct unit_test_suite bitset_tests = {
87699a11976SMattias Rönnblom 	.suite_name = "bitset test suite",
87799a11976SMattias Rönnblom 	.unit_test_cases = {
87899a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_set_clear),
87999a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_flip),
880*c889c037SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_atomic_set_clear),
881*c889c037SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_atomic_flip),
88299a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_find),
88399a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_foreach),
88499a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_count),
88599a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_define),
88699a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_or),
88799a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_and),
88899a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_xor),
88999a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_complement),
89099a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_shift_right),
89199a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_shift_left),
89299a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_equal),
89399a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_copy),
89499a11976SMattias Rönnblom 		TEST_CASE_ST(NULL, NULL, test_to_str),
89599a11976SMattias Rönnblom 		TEST_CASES_END()
89699a11976SMattias Rönnblom 	}
89799a11976SMattias Rönnblom };
89899a11976SMattias Rönnblom 
89999a11976SMattias Rönnblom static int
90099a11976SMattias Rönnblom test_bitset(void)
90199a11976SMattias Rönnblom {
90299a11976SMattias Rönnblom 	return unit_test_suite_runner(&bitset_tests);
90399a11976SMattias Rönnblom }
90499a11976SMattias Rönnblom 
90599a11976SMattias Rönnblom REGISTER_FAST_TEST(bitset_autotest, true, true, test_bitset);
906