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(¶m.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(¶m.arr);
47 return -1;
48 }
49 return 0;
50 }
51
autotest_teardown(void)52 static void autotest_teardown(void)
53 {
54 rte_fbarray_destroy(¶m.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(¶m.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(¶m.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(¶m.arr, idx), idx,
367 "Free space not found where expected\n");
368 TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(¶m.arr, idx, 1), idx,
369 "Free space not found where expected\n");
370 TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(¶m.arr, idx),
371 FBARRAY_TEST_LEN,
372 "Free space not found where expected\n");
373
374 TEST_ASSERT_EQUAL(rte_fbarray_find_prev_free(¶m.arr, idx), idx,
375 "Free space not found where expected\n");
376 TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(¶m.arr, idx, 1), idx,
377 "Free space not found where expected\n");
378 TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(¶m.arr, idx), 1,
379 "Free space not found where expected\n");
380
381 TEST_ASSERT_EQUAL(rte_fbarray_find_prev_free(¶m.arr, last_idx),
382 last_idx, "Free space not found where expected\n");
383 TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(¶m.arr, last_idx, 1),
384 last_idx, "Free space not found where expected\n");
385 TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(¶m.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(¶m.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(¶m.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(¶m.arr, idx), 0,
397 "Used space found where none was expected\n");
398
399 TEST_ASSERT(rte_fbarray_find_prev_used(¶m.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(¶m.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(¶m.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(¶m.arr, idx), idx,
419 "Used space not found where expected\n");
420 TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_used(¶m.arr, idx, 1), idx,
421 "Used space not found where expected\n");
422 TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(¶m.arr, idx), 1,
423 "Used space not found where expected\n");
424
425 TEST_ASSERT_EQUAL(rte_fbarray_find_prev_used(¶m.arr, last_idx), idx,
426 "Used space not found where expected\n");
427 TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_used(¶m.arr, last_idx, 1),
428 idx, "Used space not found where expected\n");
429 TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(¶m.arr, idx), 1,
430 "Used space not found where expected\n");
431 TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(¶m.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(¶m.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(¶m.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(¶m.arr, idx + 1), 0,
443 "Used space not found where none was expected\n");
444 TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(¶m.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(¶m.arr, last_idx), 0,
449 "Used space not found where none was expected\n");
450 TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_used(¶m.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(¶m.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(¶m.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(¶m.arr, idx), 0,
476 "Used space found where not expected\n");
477
478 /* mark as used */
479 TEST_ASSERT_SUCCESS(rte_fbarray_set_used(¶m.arr, idx),
480 "Failed to set as used\n");
481
482 /* check if used again */
483 TEST_ASSERT_NOT_EQUAL(rte_fbarray_is_used(¶m.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(¶m.arr, i);
495 TEST_ASSERT_NOT_NULL(td, "Invalid pointer returned\n");
496 TEST_ASSERT_EQUAL(rte_fbarray_find_idx(¶m.arr, td), i,
497 "Wrong index returned\n");
498 }
499
500 /* mark as free */
501 TEST_ASSERT_SUCCESS(rte_fbarray_set_free(¶m.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(¶m.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(¶m.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(¶m.arr, param.start, param.end, true))
746 return TEST_FAILED;
747 /* ensure space after end is free as well */
748 if (ensure_correct(¶m.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(¶m.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(¶m.arr, 0, FBARRAY_TEST_LEN - 1, false))
782 return TEST_FAILED;
783 /* test if find_biggest API's work correctly */
784 if (test_biggest(¶m.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(¶m.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(¶m.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(¶m.arr, 61);
836 /* break run on second mask */
837 rte_fbarray_set_used(¶m.arr, 70);
838
839 /* we expect to find free space at 71 */
840 TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(¶m.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(¶m.arr, 130);
862 /* break run on mask 1 */
863 rte_fbarray_set_used(¶m.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(¶m.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