xref: /dpdk/app/test/test_bitset.c (revision c889c037f67342d972ef7a24580d3c24b6f33e26)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2023 Ericsson AB
3  */
4 
5 #include <inttypes.h>
6 #include <stdlib.h>
7 
8 #include <rte_bitset.h>
9 #include <rte_random.h>
10 
11 #include "test.h"
12 
13 #define MAGIC UINT64_C(0xdeadbeefdeadbeef)
14 
15 static void
16 rand_buf(void *buf, size_t n)
17 {
18 	size_t i;
19 
20 	for (i = 0; i < n; i++)
21 		((unsigned char *)buf)[i] = rte_rand();
22 }
23 
24 static uint64_t *
25 alloc_bitset(size_t size)
26 {
27 	uint64_t *p;
28 
29 	p = malloc(RTE_BITSET_SIZE(size) + 2 * sizeof(uint64_t));
30 	if (p == NULL)
31 		rte_panic("Unable to allocate memory\n");
32 
33 	rand_buf(&p[0], RTE_BITSET_SIZE(size));
34 
35 	p[0] = MAGIC;
36 	p[RTE_BITSET_NUM_WORDS(size) + 1] = MAGIC;
37 
38 	return p + 1;
39 }
40 
41 
42 static int
43 free_bitset(uint64_t *bitset, size_t size)
44 {
45 	uint64_t *p;
46 
47 	p = bitset - 1;
48 
49 	if (p[0] != MAGIC)
50 		return TEST_FAILED;
51 
52 	if (p[RTE_BITSET_NUM_WORDS(size) + 1] != MAGIC)
53 		return TEST_FAILED;
54 
55 	free(p);
56 
57 	return TEST_SUCCESS;
58 }
59 
60 static bool
61 rand_bool(void)
62 {
63 	return rte_rand_max(2);
64 }
65 
66 static void
67 rand_bool_ary(bool *ary, size_t len)
68 {
69 	size_t i;
70 
71 	for (i = 0; i < len; i++)
72 		ary[i] = rand_bool();
73 }
74 
75 static void
76 rand_unused_bits(uint64_t *bitset, size_t size)
77 {
78 	uint64_t bits = rte_rand() & ~__RTE_BITSET_USED_MASK(size);
79 
80 	bitset[RTE_BITSET_NUM_WORDS(size) - 1] |= bits;
81 }
82 
83 static void
84 rand_bitset(uint64_t *bitset, size_t size)
85 {
86 	size_t i;
87 
88 	rte_bitset_init(bitset, size);
89 
90 	for (i = 0; i < size; i++)
91 		rte_bitset_assign(bitset, i, rand_bool());
92 
93 	rand_unused_bits(bitset, size);
94 }
95 
96 typedef bool test_fun(const uint64_t *bitset, size_t bit_num);
97 typedef void set_fun(uint64_t *bitset, size_t bit_num);
98 typedef void clear_fun(uint64_t *bitset, size_t bit_num);
99 typedef void assign_fun(uint64_t *bitset, size_t bit_num, bool value);
100 typedef void flip_fun(uint64_t *bitset, size_t bit_num);
101 
102 static int
103 test_set_clear_size(test_fun test_fun, set_fun set_fun, clear_fun clear_fun, size_t size)
104 {
105 	size_t i;
106 	bool reference[size];
107 	uint64_t *bitset;
108 
109 	rand_bool_ary(reference, size);
110 
111 	bitset = alloc_bitset(size);
112 
113 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
114 
115 	rte_bitset_init(bitset, size);
116 
117 	for (i = 0; i < size; i++) {
118 		if (reference[i])
119 			set_fun(bitset, i);
120 		else
121 			clear_fun(bitset, i);
122 	}
123 
124 	for (i = 0; i < size; i++)
125 		if (reference[i] != test_fun(bitset, i))
126 			return TEST_FAILED;
127 
128 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
129 		"Buffer over- or underrun detected");
130 
131 	return TEST_SUCCESS;
132 }
133 
134 #define RAND_ITERATIONS (10000)
135 #define RAND_SET_MAX_SIZE (1000)
136 
137 static int
138 test_set_clear_fun(test_fun test_fun, set_fun set_fun, clear_fun clear_fun)
139 {
140 	size_t i;
141 
142 	for (i = 0; i < RAND_ITERATIONS; i++) {
143 		size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
144 
145 		if (test_set_clear_size(test_fun, set_fun, clear_fun, size) != TEST_SUCCESS)
146 			return TEST_FAILED;
147 	}
148 
149 	return TEST_SUCCESS;
150 }
151 
152 static int
153 test_set_clear(void)
154 {
155 	return test_set_clear_fun(rte_bitset_test, rte_bitset_set, rte_bitset_clear);
156 }
157 
158 static int
159 test_flip_size(test_fun test_fun, assign_fun assign_fun, flip_fun flip_fun, size_t size)
160 {
161 	size_t i;
162 	uint64_t *bitset;
163 
164 	bitset = alloc_bitset(size);
165 
166 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
167 
168 	rand_bitset(bitset, size);
169 
170 	for (i = 0; i < size; i++) {
171 		RTE_BITSET_DECLARE(reference, size);
172 
173 		rte_bitset_copy(reference, bitset, size);
174 
175 		bool value = test_fun(bitset, i);
176 
177 		flip_fun(bitset, i);
178 
179 		TEST_ASSERT(test_fun(bitset, i) != value, "Bit %zd was not flipped", i);
180 
181 		assign_fun(reference, i, !value);
182 
183 		TEST_ASSERT(rte_bitset_equal(bitset, reference, size),
184 			"Not only the target bit %zd was flipped", i);
185 
186 
187 	}
188 
189 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
190 		"Buffer over- or underrun detected");
191 
192 	return TEST_SUCCESS;
193 }
194 
195 static int
196 test_flip_fun(test_fun test_fun, assign_fun assign_fun, flip_fun flip_fun)
197 {
198 	size_t i;
199 
200 	for (i = 0; i < RAND_ITERATIONS; i++) {
201 		size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
202 
203 		if (test_flip_size(test_fun, assign_fun, flip_fun, size) != TEST_SUCCESS)
204 			return TEST_FAILED;
205 	}
206 
207 	return TEST_SUCCESS;
208 }
209 
210 static int
211 test_flip(void)
212 {
213 	return test_flip_fun(rte_bitset_test, rte_bitset_assign, rte_bitset_flip);
214 }
215 
216 static bool
217 bitset_atomic_test(const uint64_t *bitset, size_t bit_num)
218 {
219 	return rte_bitset_atomic_test(bitset, bit_num, rte_memory_order_relaxed);
220 }
221 
222 static void
223 bitset_atomic_set(uint64_t *bitset, size_t bit_num)
224 {
225 	rte_bitset_atomic_set(bitset, bit_num, rte_memory_order_relaxed);
226 }
227 
228 static void
229 bitset_atomic_clear(uint64_t *bitset, size_t bit_num)
230 {
231 	rte_bitset_atomic_clear(bitset, bit_num, rte_memory_order_relaxed);
232 }
233 
234 static void
235 bitset_atomic_flip(uint64_t *bitset, size_t bit_num)
236 {
237 	rte_bitset_atomic_flip(bitset, bit_num, rte_memory_order_relaxed);
238 }
239 
240 static void
241 bitset_atomic_assign(uint64_t *bitset, size_t bit_num, bool bit_value)
242 {
243 	rte_bitset_atomic_assign(bitset, bit_num, bit_value, rte_memory_order_relaxed);
244 }
245 
246 static int
247 test_atomic_set_clear(void)
248 {
249 	return test_set_clear_fun(bitset_atomic_test, bitset_atomic_set, bitset_atomic_clear);
250 }
251 
252 static int
253 test_atomic_flip(void)
254 {
255 	return test_flip_fun(bitset_atomic_test, bitset_atomic_assign, bitset_atomic_flip);
256 }
257 
258 static ssize_t
259 find(const bool *ary, size_t num_bools, size_t start, size_t len, bool set)
260 {
261 	size_t i;
262 
263 	for (i = 0; i < len; i++) {
264 		ssize_t idx = (start + i) % num_bools;
265 
266 		if (ary[idx] == set)
267 			return idx;
268 	}
269 
270 	return -1;
271 }
272 
273 static ssize_t
274 find_set(const bool *ary, size_t num_bools, size_t start, size_t len)
275 {
276 	return find(ary, num_bools, start, len, true);
277 }
278 
279 static ssize_t
280 find_clear(const bool *ary, size_t num_bools, size_t start, size_t len)
281 {
282 	return find(ary, num_bools, start, len, false);
283 }
284 
285 #define FFS_ITERATIONS (100)
286 
287 static int
288 test_find_size(size_t size, bool set)
289 {
290 	uint64_t *bitset;
291 	bool reference[size];
292 	size_t i;
293 
294 	bitset = alloc_bitset(size);
295 
296 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
297 
298 	rte_bitset_init(bitset, size);
299 
300 	for (i = 0; i < size; i++) {
301 		bool bit = rand_bool();
302 		reference[i] = bit;
303 
304 		if (bit)
305 			rte_bitset_set(bitset, i);
306 		else /* redundant, still useful for testing */
307 			rte_bitset_clear(bitset, i);
308 	}
309 
310 	for (i = 0; i < FFS_ITERATIONS; i++) {
311 		size_t start_bit = rte_rand_max(size);
312 		size_t len = rte_rand_max(size + 1);
313 		bool full_range = len == size && start_bit == 0;
314 		bool wraps = start_bit + len > size;
315 		ssize_t rc;
316 
317 		if (set) {
318 			if (full_range && rand_bool())
319 				rc = rte_bitset_find_first_set(bitset, size);
320 			else if (wraps || rand_bool())
321 				rc = rte_bitset_find_set_wrap(bitset, size, start_bit, len);
322 			else
323 				rc = rte_bitset_find_set(bitset, size, start_bit, len);
324 
325 			if (rc != find_set(reference, size, start_bit, len))
326 				return TEST_FAILED;
327 		} else {
328 			if (full_range && rand_bool())
329 				rc = rte_bitset_find_first_clear(bitset, size);
330 			else if (wraps || rand_bool())
331 				rc = rte_bitset_find_clear_wrap(bitset, size, start_bit, len);
332 			else
333 				rc = rte_bitset_find_clear(bitset, size, start_bit, len);
334 
335 			if (rc != find_clear(reference, size, start_bit, len))
336 				return TEST_FAILED;
337 		}
338 
339 	}
340 
341 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
342 		"Buffer over- or underrun detected");
343 
344 	return TEST_SUCCESS;
345 }
346 
347 static int
348 test_find_set_size(size_t size)
349 {
350 	return test_find_size(size, true);
351 }
352 
353 static int
354 test_find_clear_size(size_t size)
355 {
356 	return test_find_size(size, false);
357 }
358 
359 static int
360 test_find(void)
361 {
362 	size_t i;
363 
364 	for (i = 0; i < RAND_ITERATIONS; i++) {
365 		size_t size = 2 + rte_rand_max(RAND_SET_MAX_SIZE - 2);
366 
367 		if (test_find_set_size(size) != TEST_SUCCESS)
368 			return TEST_FAILED;
369 
370 		if (test_find_clear_size(size) != TEST_SUCCESS)
371 			return TEST_FAILED;
372 	}
373 
374 	return TEST_SUCCESS;
375 }
376 
377 static int
378 record_match(ssize_t match_idx, size_t size, int *calls)
379 {
380 	if (match_idx < 0 || (size_t)match_idx >= size)
381 		return TEST_FAILED;
382 
383 	calls[match_idx]++;
384 
385 	return TEST_SUCCESS;
386 }
387 
388 static int
389 test_foreach_size(ssize_t size, bool may_wrap, bool set)
390 {
391 	bool reference[size];
392 	int calls[size];
393 	uint64_t *bitset;
394 	ssize_t i;
395 	ssize_t start_bit;
396 	ssize_t len;
397 	bool full_range;
398 	size_t total_calls = 0;
399 
400 	rand_bool_ary(reference, size);
401 
402 	bitset = alloc_bitset(size);
403 
404 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
405 
406 	memset(calls, 0, sizeof(calls));
407 
408 	start_bit = rte_rand_max(size);
409 	len = may_wrap ? rte_rand_max(size + 1) :
410 		rte_rand_max(size - start_bit + 1);
411 
412 	rte_bitset_init(bitset, size);
413 
414 	/* random data in the unused bits should not matter */
415 	rand_buf(bitset, RTE_BITSET_SIZE(size));
416 
417 	for (i = start_bit; i < start_bit + len; i++) {
418 		size_t idx = i % size;
419 
420 		if (reference[idx])
421 			rte_bitset_set(bitset, idx);
422 		else
423 			rte_bitset_clear(bitset, idx);
424 
425 		if (rte_bitset_test(bitset, idx) != reference[idx])
426 			return TEST_FAILED;
427 	}
428 
429 	full_range = (len == size && start_bit == 0);
430 
431 	/* XXX: verify iteration order as well */
432 	if (set) {
433 		if (full_range && rand_bool()) {
434 			RTE_BITSET_FOREACH_SET(i, bitset, size) {
435 				if (record_match(i, size, calls) != TEST_SUCCESS)
436 					return TEST_FAILED;
437 			}
438 		} else if (may_wrap) {
439 			RTE_BITSET_FOREACH_SET_WRAP(i, bitset, size, start_bit, len) {
440 				if (record_match(i, size, calls) != TEST_SUCCESS) {
441 					printf("failed\n");
442 					return TEST_FAILED;
443 				}
444 			}
445 		} else {
446 			RTE_BITSET_FOREACH_SET_RANGE(i, bitset, size, start_bit, len) {
447 				if (record_match(i, size, calls) != TEST_SUCCESS)
448 					return TEST_FAILED;
449 			}
450 		}
451 	} else {
452 		if (full_range && rand_bool()) {
453 			RTE_BITSET_FOREACH_CLEAR(i, bitset, size)
454 				if (record_match(i, size, calls) != TEST_SUCCESS)
455 					return TEST_FAILED;
456 		} else if (may_wrap) {
457 			RTE_BITSET_FOREACH_CLEAR_WRAP(i, bitset, size, start_bit, len) {
458 				if (record_match(i, size, calls) != TEST_SUCCESS)
459 					return TEST_FAILED;
460 			}
461 		} else {
462 			RTE_BITSET_FOREACH_CLEAR_RANGE(i, bitset, size, start_bit, len)
463 				if (record_match(i, size, calls) != TEST_SUCCESS)
464 					return TEST_FAILED;
465 		}
466 	}
467 
468 	for (i = 0; i < len; i++) {
469 		size_t idx = (start_bit + i) % size;
470 
471 		if (reference[idx] == set && calls[idx] != 1) {
472 			printf("bit %zd shouldn't have been found %d times\n", idx, calls[idx]);
473 			return TEST_FAILED;
474 		}
475 
476 		if (reference[idx] != set && calls[idx] != 0) {
477 			puts("bar");
478 			return TEST_FAILED;
479 		}
480 
481 		total_calls += calls[idx];
482 	}
483 
484 	if (full_range) {
485 		size_t count;
486 
487 		count = set ? rte_bitset_count_set(bitset, size) :
488 			rte_bitset_count_clear(bitset, size);
489 
490 		if (count != total_calls)
491 			return TEST_FAILED;
492 	}
493 
494 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
495 		"Buffer over- or underrun detected");
496 
497 	return TEST_SUCCESS;
498 }
499 
500 static int
501 test_foreach(void)
502 {
503 	size_t i;
504 
505 	for (i = 0; i < RAND_ITERATIONS; i++) {
506 		size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
507 
508 		if (test_foreach_size(size, false, true) != TEST_SUCCESS)
509 			return TEST_FAILED;
510 
511 		if (test_foreach_size(size, false, false) != TEST_SUCCESS)
512 			return TEST_FAILED;
513 
514 		if (test_foreach_size(size, true, true) != TEST_SUCCESS)
515 			return TEST_FAILED;
516 
517 		if (test_foreach_size(size, true, false) != TEST_SUCCESS)
518 			return TEST_FAILED;
519 	}
520 
521 	return TEST_SUCCESS;
522 }
523 
524 static int
525 test_count_size(size_t size)
526 {
527 	uint64_t *bitset;
528 
529 	bitset = alloc_bitset(size);
530 
531 	TEST_ASSERT(bitset != NULL, "Failed to allocate memory");
532 
533 	rte_bitset_init(bitset, size);
534 
535 	rand_unused_bits(bitset, size);
536 
537 	if (rte_bitset_count_set(bitset, size) != 0)
538 		return TEST_FAILED;
539 
540 	if (rte_bitset_count_clear(bitset, size) != size)
541 		return TEST_FAILED;
542 
543 	rte_bitset_set_all(bitset, size);
544 
545 	if (rte_bitset_count_set(bitset, size) != size)
546 		return TEST_FAILED;
547 
548 	if (rte_bitset_count_clear(bitset, size) != 0)
549 		return TEST_FAILED;
550 
551 	rte_bitset_clear_all(bitset, size);
552 
553 	if (rte_bitset_count_set(bitset, size) != 0)
554 		return TEST_FAILED;
555 
556 	if (rte_bitset_count_clear(bitset, size) != size)
557 		return TEST_FAILED;
558 
559 	rte_bitset_set(bitset, rte_rand_max(size));
560 
561 	if (rte_bitset_count_set(bitset, size) != 1)
562 		return TEST_FAILED;
563 
564 	if (rte_bitset_count_clear(bitset, size) != (size - 1))
565 		return TEST_FAILED;
566 
567 	rte_bitset_clear_all(bitset, size);
568 	if (rte_bitset_count_set(bitset, size) != 0)
569 		return TEST_FAILED;
570 	if (rte_bitset_count_clear(bitset, size) != size)
571 		return TEST_FAILED;
572 
573 	rte_bitset_set_all(bitset, size);
574 	if (rte_bitset_count_set(bitset, size) != size)
575 		return TEST_FAILED;
576 	if (rte_bitset_count_clear(bitset, size) != 0)
577 		return TEST_FAILED;
578 
579 	TEST_ASSERT_EQUAL(free_bitset(bitset, size), TEST_SUCCESS,
580 		"Buffer over- or underrun detected");
581 
582 	return TEST_SUCCESS;
583 }
584 
585 static int
586 test_count(void)
587 {
588 	size_t i;
589 
590 	if (test_count_size(128) != TEST_SUCCESS)
591 		return TEST_FAILED;
592 	if (test_count_size(1) != TEST_SUCCESS)
593 		return TEST_FAILED;
594 	if (test_count_size(63) != TEST_SUCCESS)
595 		return TEST_FAILED;
596 	if (test_count_size(64) != TEST_SUCCESS)
597 		return TEST_FAILED;
598 	if (test_count_size(65) != TEST_SUCCESS)
599 		return TEST_FAILED;
600 
601 	for (i = 0; i < RAND_ITERATIONS; i++) {
602 		size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
603 
604 		if (test_count_size(size) != TEST_SUCCESS)
605 			return TEST_FAILED;
606 	}
607 
608 	return TEST_SUCCESS;
609 }
610 
611 #define GEN_DECLARE(size) \
612 { \
613 	RTE_BITSET_DECLARE(bitset, size); \
614 	size_t idx = rte_rand_max(size); \
615 	rte_bitset_init(bitset, size); \
616 	rte_bitset_set(bitset, idx); \
617 	if (!rte_bitset_test(bitset, idx)) \
618 		return TEST_FAILED; \
619 	if (rte_bitset_count_set(bitset, size) != 1) \
620 		return TEST_FAILED; \
621 	return TEST_SUCCESS; \
622 }
623 
624 static int
625 test_define(void)
626 {
627 	GEN_DECLARE(1);
628 	GEN_DECLARE(64);
629 	GEN_DECLARE(65);
630 	GEN_DECLARE(4097);
631 }
632 
633 typedef void bitset_op(uint64_t *dst, const uint64_t *a, const uint64_t *b, size_t bit_num);
634 typedef bool bool_op(bool a, bool b);
635 
636 static int
637 test_logic_op(bitset_op bitset_op, bool_op bool_op)
638 {
639 	const size_t size = 1 + rte_rand_max(200);
640 	RTE_BITSET_DECLARE(bitset_a, size);
641 	RTE_BITSET_DECLARE(bitset_b, size);
642 	RTE_BITSET_DECLARE(bitset_d, size);
643 
644 	bool ary_a[size];
645 	bool ary_b[size];
646 	bool ary_d[size];
647 
648 	rand_bool_ary(ary_a, size);
649 	rand_bool_ary(ary_b, size);
650 
651 	size_t i;
652 	for (i = 0; i < size; i++) {
653 		rte_bitset_assign(bitset_a, i, ary_a[i]);
654 		rte_bitset_assign(bitset_b, i, ary_b[i]);
655 		ary_d[i] = bool_op(ary_a[i], ary_b[i]);
656 	}
657 
658 	bitset_op(bitset_d, bitset_a, bitset_b, size);
659 
660 	for (i = 0; i < size; i++)
661 		TEST_ASSERT_EQUAL(rte_bitset_test(bitset_d, i), ary_d[i],
662 			"Unexpected value of bit %zd", i);
663 
664 	return TEST_SUCCESS;
665 }
666 
667 static bool
668 bool_or(bool a, bool b)
669 {
670 	return a || b;
671 }
672 
673 static int
674 test_or(void)
675 {
676 	return test_logic_op(rte_bitset_or, bool_or);
677 }
678 
679 static bool
680 bool_and(bool a, bool b)
681 {
682 	return a && b;
683 }
684 
685 static int
686 test_and(void)
687 {
688 	return test_logic_op(rte_bitset_and, bool_and);
689 }
690 
691 static bool
692 bool_xor(bool a, bool b)
693 {
694 	return a != b;
695 }
696 
697 static int
698 test_xor(void)
699 {
700 	return test_logic_op(rte_bitset_xor, bool_xor);
701 }
702 
703 static int
704 test_complement(void)
705 {
706 	int i;
707 
708 	for (i = 0; i < RAND_ITERATIONS; i++) {
709 		const size_t size = 1 + rte_rand_max(RAND_SET_MAX_SIZE - 1);
710 
711 		RTE_BITSET_DECLARE(src, size);
712 
713 		rand_bitset(src, size);
714 
715 		bool bit_idx = rte_rand_max(size);
716 		bool bit_value = rte_bitset_test(src, bit_idx);
717 
718 		RTE_BITSET_DECLARE(dst, size);
719 
720 		rte_bitset_complement(dst, src, size);
721 
722 		TEST_ASSERT(bit_value != rte_bitset_test(dst, bit_idx),
723 			"Bit %d was not flipped", bit_idx);
724 	}
725 
726 	return TEST_SUCCESS;
727 }
728 
729 static int
730 test_shift(bool right)
731 {
732 	int i;
733 
734 	const char *direction = right ? "right" : "left";
735 
736 	for (i = 0; i < 10000; i++) {
737 		const int size = 1 + (int)rte_rand_max(500);
738 		const int shift_count = (int)rte_rand_max(1.5 * size);
739 		int src_idx;
740 
741 		RTE_BITSET_DECLARE(src, size);
742 		RTE_BITSET_DECLARE(reference, size);
743 
744 		rte_bitset_init(src, size);
745 		rte_bitset_init(reference, size);
746 
747 		rand_unused_bits(src, size);
748 		rand_unused_bits(reference, size);
749 
750 		for (src_idx = 0; src_idx < size; src_idx++) {
751 			bool value = rand_bool();
752 
753 			rte_bitset_assign(src, src_idx, value);
754 
755 			int dst_idx = right ? src_idx - shift_count : src_idx + shift_count;
756 
757 			if (dst_idx >= 0 && dst_idx < size)
758 				rte_bitset_assign(reference, dst_idx, value);
759 		}
760 
761 		uint64_t *dst = alloc_bitset(size);
762 
763 		if (right)
764 			rte_bitset_shift_right(dst, src, size, shift_count);
765 		else
766 			rte_bitset_shift_left(dst, src, size, shift_count);
767 
768 		TEST_ASSERT(rte_bitset_equal(dst, reference, size),
769 			"Unexpected result from shifting bitset of size %d bits %d bits %s",
770 			size, shift_count, direction);
771 
772 		TEST_ASSERT_EQUAL(free_bitset(dst, size), TEST_SUCCESS,
773 			"Shift %s operation overwrote buffer", direction);
774 	}
775 
776 	return TEST_SUCCESS;
777 }
778 
779 static int
780 test_shift_right(void)
781 {
782 	return test_shift(true);
783 }
784 
785 static int
786 test_shift_left(void)
787 {
788 	return test_shift(false);
789 }
790 
791 static int
792 test_equal(void)
793 {
794 	const size_t size = 100;
795 	RTE_BITSET_DECLARE(bitset_a, size);
796 	RTE_BITSET_DECLARE(bitset_b, size);
797 
798 	rand_buf(bitset_a, RTE_BITSET_SIZE(size));
799 	rand_buf(bitset_b, RTE_BITSET_SIZE(size));
800 
801 	rte_bitset_init(bitset_a, size);
802 	rte_bitset_init(bitset_b, size);
803 
804 	rte_bitset_set(bitset_a, 9);
805 	rte_bitset_set(bitset_b, 9);
806 	rte_bitset_set(bitset_a, 90);
807 	rte_bitset_set(bitset_b, 90);
808 
809 	if (!rte_bitset_equal(bitset_a, bitset_b, size))
810 		return TEST_FAILED;
811 
812 	/* set unused bit, which should be ignored */
813 	rte_bitset_set(&bitset_a[1], 60);
814 
815 	if (!rte_bitset_equal(bitset_a, bitset_b, size))
816 		return TEST_FAILED;
817 
818 	return TEST_SUCCESS;
819 }
820 
821 static int
822 test_copy(void)
823 {
824 	const size_t size = 100;
825 	RTE_BITSET_DECLARE(bitset_a, size);
826 	RTE_BITSET_DECLARE(bitset_b, size);
827 
828 	rand_buf(bitset_a, RTE_BITSET_SIZE(size));
829 	rand_buf(bitset_b, RTE_BITSET_SIZE(size));
830 
831 	rte_bitset_copy(bitset_a, bitset_b, size);
832 
833 	if (!rte_bitset_equal(bitset_a, bitset_b, size))
834 		return TEST_FAILED;
835 
836 	return TEST_SUCCESS;
837 }
838 
839 static int
840 test_to_str(void)
841 {
842 	char buf[1024];
843 	RTE_BITSET_DECLARE(bitset, 128);
844 
845 	rte_bitset_init(bitset, 128);
846 	rte_bitset_set(bitset, 1);
847 
848 	if (rte_bitset_to_str(bitset, 2, buf, 3) != 3)
849 		return TEST_FAILED;
850 	if (strcmp(buf, "10") != 0)
851 		return TEST_FAILED;
852 
853 	rte_bitset_set(bitset, 0);
854 
855 	if (rte_bitset_to_str(bitset, 1, buf, sizeof(buf)) != 2)
856 		return TEST_FAILED;
857 	if (strcmp(buf, "1") != 0)
858 		return TEST_FAILED;
859 
860 	rte_bitset_init(bitset, 99);
861 	rte_bitset_set(bitset, 98);
862 
863 	if (rte_bitset_to_str(bitset, 99, buf, sizeof(buf)) != 100)
864 		return TEST_FAILED;
865 
866 	if (buf[0] != '1' || strchr(&buf[1], '1') != NULL)
867 		return TEST_FAILED;
868 
869 	if (rte_bitset_to_str(bitset, 128, buf, 64) != -EINVAL)
870 		return TEST_FAILED;
871 
872 	return TEST_SUCCESS;
873 }
874 
875 static struct unit_test_suite bitset_tests = {
876 	.suite_name = "bitset test suite",
877 	.unit_test_cases = {
878 		TEST_CASE_ST(NULL, NULL, test_set_clear),
879 		TEST_CASE_ST(NULL, NULL, test_flip),
880 		TEST_CASE_ST(NULL, NULL, test_atomic_set_clear),
881 		TEST_CASE_ST(NULL, NULL, test_atomic_flip),
882 		TEST_CASE_ST(NULL, NULL, test_find),
883 		TEST_CASE_ST(NULL, NULL, test_foreach),
884 		TEST_CASE_ST(NULL, NULL, test_count),
885 		TEST_CASE_ST(NULL, NULL, test_define),
886 		TEST_CASE_ST(NULL, NULL, test_or),
887 		TEST_CASE_ST(NULL, NULL, test_and),
888 		TEST_CASE_ST(NULL, NULL, test_xor),
889 		TEST_CASE_ST(NULL, NULL, test_complement),
890 		TEST_CASE_ST(NULL, NULL, test_shift_right),
891 		TEST_CASE_ST(NULL, NULL, test_shift_left),
892 		TEST_CASE_ST(NULL, NULL, test_equal),
893 		TEST_CASE_ST(NULL, NULL, test_copy),
894 		TEST_CASE_ST(NULL, NULL, test_to_str),
895 		TEST_CASES_END()
896 	}
897 };
898 
899 static int
900 test_bitset(void)
901 {
902 	return unit_test_suite_runner(&bitset_tests);
903 }
904 
905 REGISTER_FAST_TEST(bitset_autotest, true, true, test_bitset);
906