xref: /dpdk/app/test/test_fbarray.c (revision a744665d2149ba8707621c1214c798f807ec398e)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4 
5 #include <stdbool.h>
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <limits.h>
9 
10 #include <rte_common.h>
11 #include <rte_debug.h>
12 #include <rte_errno.h>
13 #include <rte_fbarray.h>
14 
15 #include "test.h"
16 
17 struct fbarray_testsuite_params {
18 	struct rte_fbarray arr;
19 	int start;
20 	int end;
21 };
22 
23 static struct fbarray_testsuite_params param;
24 static struct fbarray_testsuite_params unaligned;
25 
26 #define FBARRAY_TEST_ARR_NAME "fbarray_autotest"
27 #define FBARRAY_TEST_LEN 256
28 #define FBARRAY_UNALIGNED_TEST_ARR_NAME "fbarray_unaligned_autotest"
29 #define FBARRAY_UNALIGNED_TEST_LEN 60
30 #define FBARRAY_TEST_ELT_SZ (sizeof(int))
31 
autotest_setup(void)32 static int autotest_setup(void)
33 {
34 	int ret;
35 
36 	ret = rte_fbarray_init(&param.arr, FBARRAY_TEST_ARR_NAME,
37 			FBARRAY_TEST_LEN, FBARRAY_TEST_ELT_SZ);
38 	if (ret) {
39 		printf("Failed to initialize test array\n");
40 		return -1;
41 	}
42 	ret = rte_fbarray_init(&unaligned.arr, FBARRAY_UNALIGNED_TEST_ARR_NAME,
43 			FBARRAY_UNALIGNED_TEST_LEN, FBARRAY_TEST_ELT_SZ);
44 	if (ret) {
45 		printf("Failed to initialize unaligned test array\n");
46 		rte_fbarray_destroy(&param.arr);
47 		return -1;
48 	}
49 	return 0;
50 }
51 
autotest_teardown(void)52 static void autotest_teardown(void)
53 {
54 	rte_fbarray_destroy(&param.arr);
55 	rte_fbarray_destroy(&unaligned.arr);
56 }
57 
init_aligned(void)58 static int init_aligned(void)
59 {
60 	int i;
61 	for (i = param.start; i <= param.end; i++) {
62 		if (rte_fbarray_set_used(&param.arr, i))
63 			return -1;
64 	}
65 	return 0;
66 }
67 
init_unaligned(void)68 static int init_unaligned(void)
69 {
70 	int i;
71 	for (i = unaligned.start; i <= unaligned.end; i++) {
72 		if (rte_fbarray_set_used(&unaligned.arr, i))
73 			return -1;
74 	}
75 	return 0;
76 }
77 
reset_aligned(void)78 static void reset_aligned(void)
79 {
80 	int i;
81 	for (i = 0; i < FBARRAY_TEST_LEN; i++)
82 		rte_fbarray_set_free(&param.arr, i);
83 	/* reset param as well */
84 	param.start = -1;
85 	param.end = -1;
86 }
87 
reset_unaligned(void)88 static void reset_unaligned(void)
89 {
90 	int i;
91 	for (i = 0; i < FBARRAY_UNALIGNED_TEST_LEN; i++)
92 		rte_fbarray_set_free(&unaligned.arr, i);
93 	/* reset param as well */
94 	unaligned.start = -1;
95 	unaligned.end = -1;
96 
97 }
98 
first_msk_test_setup(void)99 static int first_msk_test_setup(void)
100 {
101 	/* put all within first mask */
102 	param.start = 3;
103 	param.end = 10;
104 	return init_aligned();
105 }
106 
cross_msk_test_setup(void)107 static int cross_msk_test_setup(void)
108 {
109 	/* put all within second and third mask */
110 	param.start = 70;
111 	param.end = 160;
112 	return init_aligned();
113 }
114 
multi_msk_test_setup(void)115 static int multi_msk_test_setup(void)
116 {
117 	/* put all within first and last mask */
118 	param.start = 3;
119 	param.end = FBARRAY_TEST_LEN - 20;
120 	return init_aligned();
121 }
122 
last_msk_test_setup(void)123 static int last_msk_test_setup(void)
124 {
125 	/* put all within last mask */
126 	param.start = FBARRAY_TEST_LEN - 20;
127 	param.end = FBARRAY_TEST_LEN - 1;
128 	return init_aligned();
129 }
130 
full_msk_test_setup(void)131 static int full_msk_test_setup(void)
132 {
133 	/* fill entire mask */
134 	param.start = 0;
135 	param.end = FBARRAY_TEST_LEN - 1;
136 	return init_aligned();
137 }
138 
lookahead_test_setup(void)139 static int lookahead_test_setup(void)
140 {
141 	/* set index 64 as used */
142 	param.start = 64;
143 	param.end = 64;
144 	return init_aligned();
145 }
146 
lookbehind_test_setup(void)147 static int lookbehind_test_setup(void)
148 {
149 	/* set index 63 as used */
150 	param.start = 63;
151 	param.end = 63;
152 	return init_aligned();
153 }
154 
unaligned_test_setup(void)155 static int unaligned_test_setup(void)
156 {
157 	unaligned.start = 0;
158 	/* leave one free bit at the end */
159 	unaligned.end = FBARRAY_UNALIGNED_TEST_LEN - 2;
160 	return init_unaligned();
161 }
162 
test_invalid(void)163 static int test_invalid(void)
164 {
165 	struct rte_fbarray dummy;
166 
167 	/* invalid parameters */
168 	TEST_ASSERT_FAIL(rte_fbarray_attach(NULL),
169 			"Call succeeded with invalid parameters\n");
170 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
171 	TEST_ASSERT_FAIL(rte_fbarray_detach(NULL),
172 			"Call succeeded with invalid parameters\n");
173 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
174 
175 	TEST_ASSERT_FAIL(rte_fbarray_destroy(NULL),
176 			"Call succeeded with invalid parameters\n");
177 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno valuey\n");
178 	TEST_ASSERT_FAIL(rte_fbarray_init(NULL, "fail", 16, 16),
179 			"Call succeeded with invalid parameters\n");
180 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
181 	TEST_ASSERT_FAIL(rte_fbarray_init(&dummy, NULL, 16, 16),
182 			"Call succeeded with invalid parameters\n");
183 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
184 	TEST_ASSERT_FAIL(rte_fbarray_init(&dummy, "fail", 0, 16),
185 			"Call succeeded with invalid parameters\n");
186 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
187 	TEST_ASSERT_FAIL(rte_fbarray_init(&dummy, "fail", 16, 0),
188 			"Call succeeded with invalid parameters\n");
189 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
190 	/* len must not be greater than INT_MAX */
191 	TEST_ASSERT_FAIL(rte_fbarray_init(&dummy, "fail", INT_MAX + 1U, 16),
192 			"Call succeeded with invalid parameters\n");
193 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
194 
195 	TEST_ASSERT_NULL(rte_fbarray_get(NULL, 0),
196 			"Call succeeded with invalid parameters\n");
197 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
198 	TEST_ASSERT(rte_fbarray_find_idx(NULL, 0) < 0,
199 			"Call succeeded with invalid parameters\n");
200 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
201 	TEST_ASSERT(rte_fbarray_set_free(NULL, 0),
202 			"Call succeeded with invalid parameters\n");
203 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
204 	TEST_ASSERT(rte_fbarray_set_used(NULL, 0),
205 			"Call succeeded with invalid parameters\n");
206 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
207 	TEST_ASSERT(rte_fbarray_find_contig_free(NULL, 0) < 0,
208 			"Call succeeded with invalid parameters\n");
209 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
210 	TEST_ASSERT(rte_fbarray_find_contig_used(NULL, 0) < 0,
211 			"Call succeeded with invalid parameters\n");
212 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
213 	TEST_ASSERT(rte_fbarray_find_rev_contig_free(NULL, 0) < 0,
214 			"Call succeeded with invalid parameters\n");
215 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
216 	TEST_ASSERT(rte_fbarray_find_rev_contig_used(NULL, 0) < 0,
217 			"Call succeeded with invalid parameters\n");
218 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
219 	TEST_ASSERT(rte_fbarray_find_next_free(NULL, 0) < 0,
220 			"Call succeeded with invalid parameters\n");
221 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
222 	TEST_ASSERT(rte_fbarray_find_next_used(NULL, 0) < 0,
223 			"Call succeeded with invalid parameters\n");
224 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
225 	TEST_ASSERT(rte_fbarray_find_prev_free(NULL, 0) < 0,
226 			"Call succeeded with invalid parameters\n");
227 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
228 	TEST_ASSERT(rte_fbarray_find_prev_used(NULL, 0) < 0,
229 			"Call succeeded with invalid parameters\n");
230 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
231 	TEST_ASSERT(rte_fbarray_find_next_n_free(NULL, 0, 0) < 0,
232 			"Call succeeded with invalid parameters\n");
233 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
234 	TEST_ASSERT(rte_fbarray_find_next_n_used(NULL, 0, 0) < 0,
235 			"Call succeeded with invalid parameters\n");
236 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
237 	TEST_ASSERT(rte_fbarray_find_prev_n_free(NULL, 0, 0) < 0,
238 			"Call succeeded with invalid parameters\n");
239 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
240 	TEST_ASSERT(rte_fbarray_find_prev_n_used(NULL, 0, 0) < 0,
241 			"Call succeeded with invalid parameters\n");
242 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
243 	TEST_ASSERT(rte_fbarray_is_used(NULL, 0) < 0,
244 			"Call succeeded with invalid parameters\n");
245 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
246 
247 	TEST_ASSERT_SUCCESS(rte_fbarray_init(&dummy, "success",
248 			FBARRAY_TEST_LEN, 8),
249 			"Failed to initialize valid fbarray\n");
250 
251 	/* test API for handling invalid parameters with a valid fbarray */
252 	TEST_ASSERT_NULL(rte_fbarray_get(&dummy, FBARRAY_TEST_LEN),
253 			"Call succeeded with invalid parameters\n");
254 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
255 
256 	TEST_ASSERT(rte_fbarray_find_idx(&dummy, NULL) < 0,
257 			"Call succeeded with invalid parameters\n");
258 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
259 
260 	TEST_ASSERT(rte_fbarray_set_free(&dummy, FBARRAY_TEST_LEN),
261 			"Call succeeded with invalid parameters\n");
262 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
263 
264 	TEST_ASSERT(rte_fbarray_set_used(&dummy, FBARRAY_TEST_LEN),
265 			"Call succeeded with invalid parameters\n");
266 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
267 
268 	TEST_ASSERT(rte_fbarray_find_contig_free(&dummy, FBARRAY_TEST_LEN) < 0,
269 			"Call succeeded with invalid parameters\n");
270 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
271 
272 	TEST_ASSERT(rte_fbarray_find_contig_used(&dummy, FBARRAY_TEST_LEN) < 0,
273 			"Call succeeded with invalid parameters\n");
274 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
275 
276 	TEST_ASSERT(rte_fbarray_find_rev_contig_free(&dummy,
277 			FBARRAY_TEST_LEN) < 0,
278 			"Call succeeded with invalid parameters\n");
279 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
280 
281 	TEST_ASSERT(rte_fbarray_find_rev_contig_used(&dummy,
282 			FBARRAY_TEST_LEN) < 0,
283 			"Call succeeded with invalid parameters\n");
284 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
285 
286 	TEST_ASSERT(rte_fbarray_find_next_free(&dummy, FBARRAY_TEST_LEN) < 0,
287 			"Call succeeded with invalid parameters\n");
288 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
289 
290 	TEST_ASSERT(rte_fbarray_find_next_used(&dummy, FBARRAY_TEST_LEN) < 0,
291 			"Call succeeded with invalid parameters\n");
292 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
293 
294 	TEST_ASSERT(rte_fbarray_find_prev_free(&dummy, FBARRAY_TEST_LEN) < 0,
295 			"Call succeeded with invalid parameters\n");
296 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
297 
298 	TEST_ASSERT(rte_fbarray_find_prev_used(&dummy, FBARRAY_TEST_LEN) < 0,
299 			"Call succeeded with invalid parameters\n");
300 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
301 
302 	TEST_ASSERT(rte_fbarray_find_next_n_free(&dummy,
303 			FBARRAY_TEST_LEN, 1) < 0,
304 			"Call succeeded with invalid parameters\n");
305 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
306 	TEST_ASSERT(rte_fbarray_find_next_n_free(&dummy, 0,
307 			FBARRAY_TEST_LEN + 1) < 0,
308 			"Call succeeded with invalid parameters\n");
309 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
310 	TEST_ASSERT(rte_fbarray_find_next_n_free(&dummy, 0, 0) < 0,
311 			"Call succeeded with invalid parameters\n");
312 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
313 
314 	TEST_ASSERT(rte_fbarray_find_next_n_used(&dummy,
315 			FBARRAY_TEST_LEN, 1) < 0,
316 			"Call succeeded with invalid parameters\n");
317 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
318 	TEST_ASSERT(rte_fbarray_find_next_n_used(&dummy, 0,
319 			FBARRAY_TEST_LEN + 1) < 0,
320 			"Call succeeded with invalid parameters\n");
321 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
322 	TEST_ASSERT(rte_fbarray_find_next_n_used(&dummy, 0, 0) < 0,
323 			"Call succeeded with invalid parameters\n");
324 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
325 
326 	TEST_ASSERT(rte_fbarray_find_prev_n_free(&dummy,
327 			FBARRAY_TEST_LEN, 1) < 0,
328 			"Call succeeded with invalid parameters\n");
329 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
330 	TEST_ASSERT(rte_fbarray_find_prev_n_free(&dummy, 0,
331 			FBARRAY_TEST_LEN + 1) < 0,
332 			"Call succeeded with invalid parameters\n");
333 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
334 	TEST_ASSERT(rte_fbarray_find_prev_n_free(&dummy, 0, 0) < 0,
335 			"Call succeeded with invalid parameters\n");
336 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
337 
338 	TEST_ASSERT(rte_fbarray_find_prev_n_used(&dummy,
339 			FBARRAY_TEST_LEN, 1) < 0,
340 			"Call succeeded with invalid parameters\n");
341 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
342 	TEST_ASSERT(rte_fbarray_find_prev_n_used(&dummy, 0,
343 			FBARRAY_TEST_LEN + 1) < 0,
344 			"Call succeeded with invalid parameters\n");
345 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
346 	TEST_ASSERT(rte_fbarray_find_prev_n_used(&dummy, 0, 0) < 0,
347 			"Call succeeded with invalid parameters\n");
348 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
349 
350 	TEST_ASSERT(rte_fbarray_is_used(&dummy, FBARRAY_TEST_LEN) < 0,
351 			"Call succeeded with invalid parameters\n");
352 	TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
353 
354 	TEST_ASSERT_SUCCESS(rte_fbarray_destroy(&dummy),
355 			"Failed to destroy valid fbarray\n");
356 
357 	return TEST_SUCCESS;
358 }
359 
check_free(void)360 static int check_free(void)
361 {
362 	const int idx = 0;
363 	const int last_idx = FBARRAY_TEST_LEN - 1;
364 
365 	/* ensure we can find a free spot */
366 	TEST_ASSERT_EQUAL(rte_fbarray_find_next_free(&param.arr, idx), idx,
367 			"Free space not found where expected\n");
368 	TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(&param.arr, idx, 1), idx,
369 			"Free space not found where expected\n");
370 	TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(&param.arr, idx),
371 			FBARRAY_TEST_LEN,
372 			"Free space not found where expected\n");
373 
374 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_free(&param.arr, idx), idx,
375 			"Free space not found where expected\n");
376 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(&param.arr, idx, 1), idx,
377 			"Free space not found where expected\n");
378 	TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(&param.arr, idx), 1,
379 			"Free space not found where expected\n");
380 
381 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_free(&param.arr, last_idx),
382 			last_idx, "Free space not found where expected\n");
383 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(&param.arr, last_idx, 1),
384 			last_idx, "Free space not found where expected\n");
385 	TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(&param.arr,
386 			last_idx), FBARRAY_TEST_LEN,
387 			"Free space not found where expected\n");
388 
389 	/* ensure we can't find any used spots */
390 	TEST_ASSERT(rte_fbarray_find_next_used(&param.arr, idx) < 0,
391 			"Used space found where none was expected\n");
392 	TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
393 	TEST_ASSERT(rte_fbarray_find_next_n_used(&param.arr, idx, 1) < 0,
394 			"Used space found where none was expected\n");
395 	TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
396 	TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(&param.arr, idx), 0,
397 			"Used space found where none was expected\n");
398 
399 	TEST_ASSERT(rte_fbarray_find_prev_used(&param.arr, last_idx) < 0,
400 			"Used space found where none was expected\n");
401 	TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
402 	TEST_ASSERT(rte_fbarray_find_prev_n_used(&param.arr, last_idx, 1) < 0,
403 			"Used space found where none was expected\n");
404 	TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
405 	TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(&param.arr,
406 			last_idx), 0,
407 			"Used space found where none was expected\n");
408 
409 	return 0;
410 }
411 
check_used_one(void)412 static int check_used_one(void)
413 {
414 	const int idx = 0;
415 	const int last_idx = FBARRAY_TEST_LEN - 1;
416 
417 	/* check that we can find used spots now */
418 	TEST_ASSERT_EQUAL(rte_fbarray_find_next_used(&param.arr, idx), idx,
419 			"Used space not found where expected\n");
420 	TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_used(&param.arr, idx, 1), idx,
421 			"Used space not found where expected\n");
422 	TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(&param.arr, idx), 1,
423 			"Used space not found where expected\n");
424 
425 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_used(&param.arr, last_idx), idx,
426 			"Used space not found where expected\n");
427 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_used(&param.arr, last_idx, 1),
428 			idx, "Used space not found where expected\n");
429 	TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(&param.arr, idx), 1,
430 			"Used space not found where expected\n");
431 	TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(&param.arr,
432 			last_idx), idx,
433 			"Used space not found where expected\n");
434 
435 	/* check if further indices are still free */
436 	TEST_ASSERT(rte_fbarray_find_next_used(&param.arr, idx + 1) < 0,
437 			"Used space not found where none was expected\n");
438 	TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
439 	TEST_ASSERT(rte_fbarray_find_next_n_used(&param.arr, idx + 1, 1) < 0,
440 			"Used space not found where none was expected\n");
441 	TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
442 	TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(&param.arr, idx + 1), 0,
443 			"Used space not found where none was expected\n");
444 	TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(&param.arr, idx + 1),
445 			FBARRAY_TEST_LEN - 1,
446 			"Used space not found where none was expected\n");
447 
448 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_used(&param.arr, last_idx), 0,
449 			"Used space not found where none was expected\n");
450 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_used(&param.arr, last_idx, 1),
451 			0, "Used space not found where none was expected\n");
452 	TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(&param.arr,
453 			last_idx), 0,
454 			"Used space not found where none was expected\n");
455 	TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(&param.arr,
456 			last_idx), FBARRAY_TEST_LEN - 1,
457 			"Used space not found where none was expected\n");
458 
459 	return 0;
460 }
461 
test_basic(void)462 static int test_basic(void)
463 {
464 	const int idx = 0;
465 	int i;
466 
467 	/* check array count */
468 	TEST_ASSERT_EQUAL(param.arr.count, 0, "Wrong element count\n");
469 
470 	/* ensure we can find a free spot */
471 	if (check_free())
472 		return TEST_FAILED;
473 
474 	/* check if used */
475 	TEST_ASSERT_EQUAL(rte_fbarray_is_used(&param.arr, idx), 0,
476 			"Used space found where not expected\n");
477 
478 	/* mark as used */
479 	TEST_ASSERT_SUCCESS(rte_fbarray_set_used(&param.arr, idx),
480 			"Failed to set as used\n");
481 
482 	/* check if used again */
483 	TEST_ASSERT_NOT_EQUAL(rte_fbarray_is_used(&param.arr, idx), 0,
484 			"Used space not found where expected\n");
485 
486 	if (check_used_one())
487 		return TEST_FAILED;
488 
489 	/* check array count */
490 	TEST_ASSERT_EQUAL(param.arr.count, 1, "Wrong element count\n");
491 
492 	/* check if getting pointers works for every element */
493 	for (i = 0; i < FBARRAY_TEST_LEN; i++) {
494 		void *td = rte_fbarray_get(&param.arr, i);
495 		TEST_ASSERT_NOT_NULL(td, "Invalid pointer returned\n");
496 		TEST_ASSERT_EQUAL(rte_fbarray_find_idx(&param.arr, td), i,
497 				"Wrong index returned\n");
498 	}
499 
500 	/* mark as free */
501 	TEST_ASSERT_SUCCESS(rte_fbarray_set_free(&param.arr, idx),
502 			"Failed to set as free\n");
503 
504 	/* check array count */
505 	TEST_ASSERT_EQUAL(param.arr.count, 0, "Wrong element count\n");
506 
507 	/* check if used */
508 	TEST_ASSERT_EQUAL(rte_fbarray_is_used(&param.arr, idx), 0,
509 			"Used space found where not expected\n");
510 
511 	if (check_free())
512 		return TEST_FAILED;
513 
514 	reset_aligned();
515 
516 	return TEST_SUCCESS;
517 }
518 
test_biggest(struct rte_fbarray * arr,int first,int last)519 static int test_biggest(struct rte_fbarray *arr, int first, int last)
520 {
521 	int lo_free_space_first, lo_free_space_last, lo_free_space_len;
522 	int hi_free_space_first, hi_free_space_last, hi_free_space_len;
523 	int max_free_space_first, max_free_space_last, max_free_space_len;
524 	int len = last - first + 1;
525 
526 	/* first and last must either be both -1, or both not -1 */
527 	TEST_ASSERT((first == -1) == (last == -1),
528 			"Invalid arguments provided\n");
529 
530 	/* figure out what we expect from the low chunk of free space */
531 	if (first == -1) {
532 		/* special case: if there are no occupied elements at all,
533 		 * consider both free spaces to consume the entire array.
534 		 */
535 		lo_free_space_first = 0;
536 		lo_free_space_last = arr->len - 1;
537 		lo_free_space_len = arr->len;
538 		/* if there's no used space, length should be invalid */
539 		len = -1;
540 	} else if (first == 0) {
541 		/* if occupied items start at 0, there's no free space */
542 		lo_free_space_first = -1;
543 		lo_free_space_last = -1;
544 		lo_free_space_len = 0;
545 	} else {
546 		lo_free_space_first = 0;
547 		lo_free_space_last = first - 1;
548 		lo_free_space_len = lo_free_space_last -
549 				lo_free_space_first + 1;
550 	}
551 
552 	/* figure out what we expect from the high chunk of free space */
553 	if (last == -1) {
554 		/* special case: if there are no occupied elements at all,
555 		 * consider both free spaces to consume the entire array.
556 		 */
557 		hi_free_space_first = 0;
558 		hi_free_space_last = arr->len - 1;
559 		hi_free_space_len = arr->len;
560 		/* if there's no used space, length should be invalid */
561 		len = -1;
562 	} else if (last == ((int)arr->len - 1)) {
563 		/* if occupied items end at array len, there's no free space */
564 		hi_free_space_first = -1;
565 		hi_free_space_last = -1;
566 		hi_free_space_len = 0;
567 	} else {
568 		hi_free_space_first = last + 1;
569 		hi_free_space_last = arr->len - 1;
570 		hi_free_space_len = hi_free_space_last -
571 				hi_free_space_first + 1;
572 	}
573 
574 	/* find which one will be biggest */
575 	if (lo_free_space_len > hi_free_space_len) {
576 		max_free_space_first = lo_free_space_first;
577 		max_free_space_last = lo_free_space_last;
578 		max_free_space_len = lo_free_space_len;
579 	} else {
580 		/* if they are equal, we'll just use the high chunk */
581 		max_free_space_first = hi_free_space_first;
582 		max_free_space_last = hi_free_space_last;
583 		max_free_space_len = hi_free_space_len;
584 	}
585 
586 	/* check used regions - these should produce identical results */
587 	TEST_ASSERT_EQUAL(rte_fbarray_find_biggest_used(arr, 0), first,
588 			"Used space index is wrong\n");
589 	TEST_ASSERT_EQUAL(rte_fbarray_find_rev_biggest_used(arr, arr->len - 1),
590 			first,
591 			"Used space index is wrong\n");
592 	/* len may be -1, but function will return error anyway */
593 	TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(arr, first), len,
594 			"Used space length is wrong\n");
595 
596 	/* check if biggest free region is the one we expect to find. It can be
597 	 * -1 if there's no free space - we've made sure we use one or the
598 	 * other, even if both are invalid.
599 	 */
600 	TEST_ASSERT_EQUAL(rte_fbarray_find_biggest_free(arr, 0),
601 			max_free_space_first,
602 			"Biggest free space index is wrong\n");
603 	TEST_ASSERT_EQUAL(rte_fbarray_find_rev_biggest_free(arr, arr->len - 1),
604 			max_free_space_first,
605 			"Biggest free space index is wrong\n");
606 
607 	/* if biggest region exists, check its length */
608 	if (max_free_space_first != -1) {
609 		TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(arr,
610 					max_free_space_first),
611 				max_free_space_len,
612 				"Biggest free space length is wrong\n");
613 		TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
614 					max_free_space_last),
615 				max_free_space_len,
616 				"Biggest free space length is wrong\n");
617 	}
618 
619 	/* find if we see what we expect to see in the low region. if there is
620 	 * no free space, the function should still match expected value, as
621 	 * we've set it to -1. we're scanning backwards to avoid accidentally
622 	 * hitting the high free space region. if there is no occupied space,
623 	 * there's nothing to do.
624 	 */
625 	if (last != -1) {
626 		TEST_ASSERT_EQUAL(rte_fbarray_find_rev_biggest_free(arr, last),
627 				lo_free_space_first,
628 				"Low free space index is wrong\n");
629 	}
630 
631 	if (lo_free_space_first != -1) {
632 		/* if low free region exists, check its length */
633 		TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(arr,
634 					lo_free_space_first),
635 				lo_free_space_len,
636 				"Low free space length is wrong\n");
637 		TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
638 					lo_free_space_last),
639 				lo_free_space_len,
640 				"Low free space length is wrong\n");
641 	}
642 
643 	/* find if we see what we expect to see in the high region. if there is
644 	 * no free space, the function should still match expected value, as
645 	 * we've set it to -1. we're scanning forwards to avoid accidentally
646 	 * hitting the low free space region. if there is no occupied space,
647 	 * there's nothing to do.
648 	 */
649 	if (first != -1) {
650 		TEST_ASSERT_EQUAL(rte_fbarray_find_biggest_free(arr, first),
651 				hi_free_space_first,
652 				"High free space index is wrong\n");
653 	}
654 
655 	/* if high free region exists, check its length */
656 	if (hi_free_space_first != -1) {
657 		TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(arr,
658 					hi_free_space_first),
659 				hi_free_space_len,
660 				"High free space length is wrong\n");
661 		TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
662 					hi_free_space_last),
663 				hi_free_space_len,
664 				"High free space length is wrong\n");
665 	}
666 
667 	return 0;
668 }
669 
ensure_correct(struct rte_fbarray * arr,int first,int last,bool used)670 static int ensure_correct(struct rte_fbarray *arr, int first, int last,
671 		bool used)
672 {
673 	int i, len = last - first + 1;
674 	for (i = 0; i < len; i++) {
675 		int cur = first + i;
676 		int cur_len = len - i;
677 
678 		if (used) {
679 			TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(arr,
680 					cur), cur_len,
681 					"Used space length is wrong\n");
682 			TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(arr,
683 					last), len,
684 					"Used space length is wrong\n");
685 			TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(arr,
686 					cur), i + 1,
687 					"Used space length is wrong\n");
688 
689 			TEST_ASSERT_EQUAL(rte_fbarray_find_next_used(arr, cur),
690 					cur,
691 					"Used space not found where expected\n");
692 			TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_used(arr,
693 					cur, 1), cur,
694 					"Used space not found where expected\n");
695 			TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_used(arr, cur,
696 					cur_len), cur,
697 					"Used space not found where expected\n");
698 
699 			TEST_ASSERT_EQUAL(rte_fbarray_find_prev_used(arr, cur),
700 					cur,
701 					"Used space not found where expected\n");
702 			TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_used(arr,
703 					last, cur_len), cur,
704 					"Used space not found where expected\n");
705 		} else {
706 			TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(arr,
707 					cur), cur_len,
708 					"Free space length is wrong\n");
709 			TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
710 					last), len,
711 					"Free space length is wrong\n");
712 			TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
713 					cur), i + 1,
714 					"Free space length is wrong\n");
715 
716 			TEST_ASSERT_EQUAL(rte_fbarray_find_next_free(arr, cur),
717 					cur,
718 					"Free space not found where expected\n");
719 			TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(arr, cur,
720 					1), cur,
721 					"Free space not found where expected\n");
722 			TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(arr, cur,
723 					cur_len), cur,
724 					"Free space not found where expected\n");
725 
726 			TEST_ASSERT_EQUAL(rte_fbarray_find_prev_free(arr, cur),
727 					cur,
728 					"Free space not found where expected\n");
729 			TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(arr,
730 					last, cur_len), cur,
731 					"Free space not found where expected\n");
732 		}
733 	}
734 	return 0;
735 }
736 
test_find(void)737 static int test_find(void)
738 {
739 	TEST_ASSERT_EQUAL((int)param.arr.count, param.end - param.start + 1,
740 			"Wrong element count\n");
741 	/* ensure space is free before start */
742 	if (ensure_correct(&param.arr, 0, param.start - 1, false))
743 		return TEST_FAILED;
744 	/* ensure space is occupied where it's supposed to be */
745 	if (ensure_correct(&param.arr, param.start, param.end, true))
746 		return TEST_FAILED;
747 	/* ensure space after end is free as well */
748 	if (ensure_correct(&param.arr, param.end + 1, FBARRAY_TEST_LEN - 1,
749 			false))
750 		return TEST_FAILED;
751 	/* test if find_biggest API's work correctly */
752 	if (test_biggest(&param.arr, param.start, param.end))
753 		return TEST_FAILED;
754 	return TEST_SUCCESS;
755 }
756 
test_find_unaligned(void)757 static int test_find_unaligned(void)
758 {
759 	TEST_ASSERT_EQUAL((int)unaligned.arr.count, unaligned.end - unaligned.start + 1,
760 			"Wrong element count\n");
761 	/* ensure space is free before start */
762 	if (ensure_correct(&unaligned.arr, 0, unaligned.start - 1, false))
763 		return TEST_FAILED;
764 	/* ensure space is occupied where it's supposed to be */
765 	if (ensure_correct(&unaligned.arr, unaligned.start, unaligned.end, true))
766 		return TEST_FAILED;
767 	/* ensure space after end is free as well */
768 	if (ensure_correct(&unaligned.arr, unaligned.end + 1, FBARRAY_UNALIGNED_TEST_LEN - 1,
769 			false))
770 		return TEST_FAILED;
771 	/* test if find_biggest API's work correctly */
772 	if (test_biggest(&unaligned.arr, unaligned.start, unaligned.end))
773 		return TEST_FAILED;
774 	return TEST_SUCCESS;
775 }
776 
test_empty(void)777 static int test_empty(void)
778 {
779 	TEST_ASSERT_EQUAL((int)param.arr.count, 0, "Wrong element count\n");
780 	/* ensure space is free */
781 	if (ensure_correct(&param.arr, 0, FBARRAY_TEST_LEN - 1, false))
782 		return TEST_FAILED;
783 	/* test if find_biggest API's work correctly */
784 	if (test_biggest(&param.arr, param.start, param.end))
785 		return TEST_FAILED;
786 	return TEST_SUCCESS;
787 }
788 
test_lookahead(void)789 static int test_lookahead(void)
790 {
791 	int ret;
792 
793 	/* run regular test first */
794 	ret = test_find();
795 	if (ret != TEST_SUCCESS)
796 		return ret;
797 
798 	/* test if we can find free chunk while not starting with 0 */
799 	TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(&param.arr, 1, param.start),
800 			param.start + 1, "Free chunk index is wrong\n");
801 	return TEST_SUCCESS;
802 }
803 
test_lookbehind(void)804 static int test_lookbehind(void)
805 {
806 	int ret, free_len = 2;
807 
808 	/* run regular test first */
809 	ret = test_find();
810 	if (ret != TEST_SUCCESS)
811 		return ret;
812 
813 	/* test if we can find free chunk while crossing mask boundary */
814 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(&param.arr, param.start + 1, free_len),
815 			param.start - free_len, "Free chunk index is wrong\n");
816 	return TEST_SUCCESS;
817 }
818 
test_lookahead_mask(void)819 static int test_lookahead_mask(void)
820 {
821 	/*
822 	 * There is a certain type of lookahead behavior we want to test here,
823 	 * namely masking of bits that were scanned with lookahead but that we
824 	 * know do not match our criteria. This is achieved in following steps:
825 	 *
826 	 *   0. Look for a big enough chunk of free space (say, 62 elements)
827 	 *   1. Trigger lookahead by breaking a run somewhere inside mask 0
828 	 *      (indices 0-63)
829 	 *   2. Fail lookahead by breaking the run somewhere inside mask 1
830 	 *      (indices 64-127)
831 	 *   3. Ensure that we can still find free space in mask 1 afterwards
832 	 */
833 
834 	/* break run on first mask */
835 	rte_fbarray_set_used(&param.arr, 61);
836 	/* break run on second mask */
837 	rte_fbarray_set_used(&param.arr, 70);
838 
839 	/* we expect to find free space at 71 */
840 	TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(&param.arr, 0, 62),
841 			71, "Free chunk index is wrong\n");
842 	return TEST_SUCCESS;
843 }
844 
test_lookbehind_mask(void)845 static int test_lookbehind_mask(void)
846 {
847 	/*
848 	 * There is a certain type of lookbehind behavior we want to test here,
849 	 * namely masking of bits that were scanned with lookbehind but that we
850 	 * know do not match our criteria. This is achieved in two steps:
851 	 *
852 	 *   0. Look for a big enough chunk of free space (say, 62 elements)
853 	 *   1. Trigger lookbehind by breaking a run somewhere inside mask 2
854 	 *      (indices 128-191)
855 	 *   2. Fail lookbehind by breaking the run somewhere inside mask 1
856 	 *      (indices 64-127)
857 	 *   3. Ensure that we can still find free space in mask 1 afterwards
858 	 */
859 
860 	/* break run on mask 2 */
861 	rte_fbarray_set_used(&param.arr, 130);
862 	/* break run on mask 1 */
863 	rte_fbarray_set_used(&param.arr, 70);
864 
865 	/* start from 190, we expect to find free space at 8 */
866 	TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(&param.arr, 190, 62),
867 			8, "Free chunk index is wrong\n");
868 	return TEST_SUCCESS;
869 }
870 
871 static struct unit_test_suite fbarray_test_suite = {
872 	.suite_name = "fbarray autotest",
873 	.setup = autotest_setup,
874 	.teardown = autotest_teardown,
875 	.unit_test_cases = {
876 		TEST_CASE(test_invalid),
877 		TEST_CASE(test_basic),
878 		TEST_CASE_ST(first_msk_test_setup, reset_aligned, test_find),
879 		TEST_CASE_ST(cross_msk_test_setup, reset_aligned, test_find),
880 		TEST_CASE_ST(multi_msk_test_setup, reset_aligned, test_find),
881 		TEST_CASE_ST(last_msk_test_setup, reset_aligned, test_find),
882 		TEST_CASE_ST(full_msk_test_setup, reset_aligned, test_find),
883 		/* empty test does not need setup */
884 		TEST_CASE_ST(NULL, reset_aligned, test_empty),
885 		TEST_CASE_ST(lookahead_test_setup, reset_aligned, test_lookahead),
886 		TEST_CASE_ST(lookbehind_test_setup, reset_aligned, test_lookbehind),
887 		/* setup for these tests is more complex so do it in test func */
888 		TEST_CASE_ST(NULL, reset_aligned, test_lookahead_mask),
889 		TEST_CASE_ST(NULL, reset_aligned, test_lookbehind_mask),
890 		TEST_CASE_ST(unaligned_test_setup, reset_unaligned, test_find_unaligned),
891 		TEST_CASES_END()
892 	}
893 };
894 
895 static int
test_fbarray(void)896 test_fbarray(void)
897 {
898 	return unit_test_suite_runner(&fbarray_test_suite);
899 }
900 
901 REGISTER_FAST_TEST(fbarray_autotest, true, true, test_fbarray);
902