Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2019 Intel Corporation
3 : : */
4 : :
5 : : #include <string.h>
6 : :
7 : : #include <rte_lcore.h>
8 : : #include <rte_malloc.h>
9 : : #include <rte_random.h>
10 : : #include <rte_stack.h>
11 : :
12 : : #include "test.h"
13 : :
14 : : #define STACK_SIZE 4096
15 : : #define MAX_BULK 32
16 : :
17 : : static int
18 : 4 : test_stack_push_pop(struct rte_stack *s, void **obj_table, unsigned int bulk_sz)
19 : : {
20 : : unsigned int i, ret;
21 : : void **popped_objs;
22 : :
23 : 4 : popped_objs = rte_calloc(NULL, STACK_SIZE, sizeof(void *), 0);
24 [ - + ]: 4 : if (popped_objs == NULL) {
25 : : printf("[%s():%u] failed to calloc %zu bytes\n",
26 : : __func__, __LINE__, STACK_SIZE * sizeof(void *));
27 : 0 : return -1;
28 : : }
29 : :
30 [ + + ]: 8452 : for (i = 0; i < STACK_SIZE; i += bulk_sz) {
31 [ + + ]: 8448 : ret = rte_stack_push(s, &obj_table[i], bulk_sz);
32 : :
33 [ - + ]: 8448 : if (ret != bulk_sz) {
34 : : printf("[%s():%u] push returned: %d (expected %u)\n",
35 : : __func__, __LINE__, ret, bulk_sz);
36 : 0 : rte_free(popped_objs);
37 : 0 : return -1;
38 : : }
39 : :
40 [ - + ]: 8448 : if (rte_stack_count(s) != i + bulk_sz) {
41 : : printf("[%s():%u] stack count: %u (expected %u)\n",
42 : : __func__, __LINE__, rte_stack_count(s),
43 : : i + bulk_sz);
44 : 0 : rte_free(popped_objs);
45 : 0 : return -1;
46 : : }
47 : :
48 [ - + ]: 8448 : if (rte_stack_free_count(s) != STACK_SIZE - i - bulk_sz) {
49 : : printf("[%s():%u] stack free count: %u (expected %u)\n",
50 : : __func__, __LINE__, rte_stack_count(s),
51 : : STACK_SIZE - i - bulk_sz);
52 : 0 : rte_free(popped_objs);
53 : 0 : return -1;
54 : : }
55 : : }
56 : :
57 [ + + ]: 8452 : for (i = 0; i < STACK_SIZE; i += bulk_sz) {
58 [ + + ]: 8448 : ret = rte_stack_pop(s, &popped_objs[i], bulk_sz);
59 : :
60 [ - + ]: 8448 : if (ret != bulk_sz) {
61 : : printf("[%s():%u] pop returned: %d (expected %u)\n",
62 : : __func__, __LINE__, ret, bulk_sz);
63 : 0 : rte_free(popped_objs);
64 : 0 : return -1;
65 : : }
66 : :
67 [ - + ]: 8448 : if (rte_stack_count(s) != STACK_SIZE - i - bulk_sz) {
68 : : printf("[%s():%u] stack count: %u (expected %u)\n",
69 : : __func__, __LINE__, rte_stack_count(s),
70 : : STACK_SIZE - i - bulk_sz);
71 : 0 : rte_free(popped_objs);
72 : 0 : return -1;
73 : : }
74 : :
75 [ - + ]: 8448 : if (rte_stack_free_count(s) != i + bulk_sz) {
76 : : printf("[%s():%u] stack free count: %u (expected %u)\n",
77 : : __func__, __LINE__, rte_stack_count(s),
78 : : i + bulk_sz);
79 : 0 : rte_free(popped_objs);
80 : 0 : return -1;
81 : : }
82 : : }
83 : :
84 [ + + ]: 16388 : for (i = 0; i < STACK_SIZE; i++) {
85 [ - + ]: 16384 : if (obj_table[i] != popped_objs[STACK_SIZE - i - 1]) {
86 : : printf("[%s():%u] Incorrect value %p at index 0x%x\n",
87 : : __func__, __LINE__,
88 : : popped_objs[STACK_SIZE - i - 1], i);
89 : 0 : rte_free(popped_objs);
90 : 0 : return -1;
91 : : }
92 : : }
93 : :
94 : 4 : rte_free(popped_objs);
95 : :
96 : 4 : return 0;
97 : : }
98 : :
99 : : static int
100 : 2 : test_stack_basic(uint32_t flags)
101 : : {
102 : : struct rte_stack *s = NULL;
103 : : void **obj_table = NULL;
104 : : int i, ret = -1;
105 : :
106 : 2 : obj_table = rte_calloc(NULL, STACK_SIZE, sizeof(void *), 0);
107 [ - + ]: 2 : if (obj_table == NULL) {
108 : : printf("[%s():%u] failed to calloc %zu bytes\n",
109 : : __func__, __LINE__, STACK_SIZE * sizeof(void *));
110 : 0 : goto fail_test;
111 : : }
112 : :
113 [ + + ]: 8194 : for (i = 0; i < STACK_SIZE; i++)
114 : 8192 : obj_table[i] = (void *)(uintptr_t)i;
115 : :
116 : 2 : s = rte_stack_create(__func__, STACK_SIZE, rte_socket_id(), flags);
117 [ - + ]: 2 : if (s == NULL) {
118 : : printf("[%s():%u] failed to create a stack\n",
119 : : __func__, __LINE__);
120 : 0 : goto fail_test;
121 : : }
122 : :
123 [ - + ]: 2 : if (rte_stack_lookup(__func__) != s) {
124 : : printf("[%s():%u] failed to lookup a stack\n",
125 : : __func__, __LINE__);
126 : 0 : goto fail_test;
127 : : }
128 : :
129 [ - + ]: 2 : if (rte_stack_count(s) != 0) {
130 : : printf("[%s():%u] stack count: %u (expected 0)\n",
131 : : __func__, __LINE__, rte_stack_count(s));
132 : 0 : goto fail_test;
133 : : }
134 : :
135 [ - + ]: 2 : if (rte_stack_free_count(s) != STACK_SIZE) {
136 : : printf("[%s():%u] stack free count: %u (expected %u)\n",
137 : : __func__, __LINE__, rte_stack_count(s), STACK_SIZE);
138 : 0 : goto fail_test;
139 : : }
140 : :
141 : 2 : ret = test_stack_push_pop(s, obj_table, 1);
142 [ - + ]: 2 : if (ret) {
143 : : printf("[%s():%u] Single object push/pop failed\n",
144 : : __func__, __LINE__);
145 : 0 : goto fail_test;
146 : : }
147 : :
148 : 2 : ret = test_stack_push_pop(s, obj_table, MAX_BULK);
149 [ - + ]: 2 : if (ret) {
150 : : printf("[%s():%u] Bulk object push/pop failed\n",
151 : : __func__, __LINE__);
152 : 0 : goto fail_test;
153 : : }
154 : :
155 : 2 : ret = rte_stack_push(s, obj_table, 2 * STACK_SIZE);
156 [ - + ]: 2 : if (ret != 0) {
157 : : printf("[%s():%u] Excess objects push succeeded\n",
158 : : __func__, __LINE__);
159 : 0 : goto fail_test;
160 : : }
161 : :
162 : 2 : ret = rte_stack_pop(s, obj_table, 1);
163 [ - + ]: 2 : if (ret != 0) {
164 : : printf("[%s():%u] Empty stack pop succeeded\n",
165 : : __func__, __LINE__);
166 : 0 : goto fail_test;
167 : : }
168 : :
169 : : ret = 0;
170 : :
171 : 2 : fail_test:
172 : 2 : rte_stack_free(s);
173 : :
174 : 2 : rte_free(obj_table);
175 : :
176 : 2 : return ret;
177 : : }
178 : :
179 : : static int
180 : 2 : test_stack_name_reuse(uint32_t flags)
181 : : {
182 : : struct rte_stack *s[2];
183 : :
184 : 2 : s[0] = rte_stack_create("test", STACK_SIZE, rte_socket_id(), flags);
185 [ - + ]: 2 : if (s[0] == NULL) {
186 : : printf("[%s():%u] Failed to create a stack\n",
187 : : __func__, __LINE__);
188 : 0 : return -1;
189 : : }
190 : :
191 : 2 : s[1] = rte_stack_create("test", STACK_SIZE, rte_socket_id(), flags);
192 [ - + ]: 2 : if (s[1] != NULL) {
193 : : printf("[%s():%u] Failed to detect re-used name\n",
194 : : __func__, __LINE__);
195 : 0 : return -1;
196 : : }
197 : :
198 : 2 : rte_stack_free(s[0]);
199 : :
200 : 2 : return 0;
201 : : }
202 : :
203 : : static int
204 : 2 : test_stack_name_length(uint32_t flags)
205 : : {
206 : : char name[RTE_STACK_NAMESIZE + 1];
207 : : struct rte_stack *s;
208 : :
209 : : memset(name, 's', sizeof(name));
210 : 2 : name[RTE_STACK_NAMESIZE] = '\0';
211 : :
212 : 2 : s = rte_stack_create(name, STACK_SIZE, rte_socket_id(), flags);
213 [ - + ]: 2 : if (s != NULL) {
214 : : printf("[%s():%u] Failed to prevent long name\n",
215 : : __func__, __LINE__);
216 : 0 : return -1;
217 : : }
218 : :
219 [ - + ]: 2 : if (rte_errno != ENAMETOOLONG) {
220 : : printf("[%s():%u] rte_stack failed to set correct errno on failed lookup\n",
221 : : __func__, __LINE__);
222 : 0 : return -1;
223 : : }
224 : :
225 : : return 0;
226 : : }
227 : :
228 : : static int
229 : 2 : test_lookup_null(void)
230 : : {
231 : 2 : struct rte_stack *s = rte_stack_lookup("stack_not_found");
232 : :
233 [ - + ]: 2 : if (s != NULL) {
234 : : printf("[%s():%u] rte_stack found a non-existent stack\n",
235 : : __func__, __LINE__);
236 : 0 : return -1;
237 : : }
238 : :
239 [ - + ]: 2 : if (rte_errno != ENOENT) {
240 : : printf("[%s():%u] rte_stack failed to set correct errno on failed lookup\n",
241 : : __func__, __LINE__);
242 : 0 : return -1;
243 : : }
244 : :
245 : 2 : s = rte_stack_lookup(NULL);
246 : :
247 [ - + ]: 2 : if (s != NULL) {
248 : : printf("[%s():%u] rte_stack found a non-existent stack\n",
249 : : __func__, __LINE__);
250 : 0 : return -1;
251 : : }
252 : :
253 [ - + ]: 2 : if (rte_errno != EINVAL) {
254 : : printf("[%s():%u] rte_stack failed to set correct errno on failed lookup\n",
255 : : __func__, __LINE__);
256 : 0 : return -1;
257 : : }
258 : :
259 : : return 0;
260 : : }
261 : :
262 : : static int
263 : : test_free_null(void)
264 : : {
265 : : /* Check whether the library proper handles a NULL pointer */
266 : 2 : rte_stack_free(NULL);
267 : :
268 : : return 0;
269 : : }
270 : :
271 : : #define NUM_ITERS_PER_THREAD 100000
272 : :
273 : : struct test_args {
274 : : struct rte_stack *s;
275 : : };
276 : :
277 : : static struct test_args thread_test_args;
278 : :
279 : : static int
280 : 4 : stack_thread_push_pop(__rte_unused void *args)
281 : : {
282 : : void *obj_table[MAX_BULK];
283 : : int i;
284 : :
285 [ + + ]: 399203 : for (i = 0; i < NUM_ITERS_PER_THREAD; i++) {
286 : : unsigned int num;
287 : :
288 : 399199 : num = rte_rand() % MAX_BULK;
289 : :
290 [ + + - + ]: 796394 : if (rte_stack_push(thread_test_args.s, obj_table, num) != num) {
291 : : printf("[%s():%u] Failed to push %u pointers\n",
292 : : __func__, __LINE__, num);
293 : 0 : return -1;
294 : : }
295 : :
296 [ + + - + ]: 797430 : if (rte_stack_pop(thread_test_args.s, obj_table, num) != num) {
297 : : printf("[%s():%u] Failed to pop %u pointers\n",
298 : : __func__, __LINE__, num);
299 : 0 : return -1;
300 : : }
301 : : }
302 : :
303 : : return 0;
304 : : }
305 : :
306 : : static int
307 : 2 : test_stack_multithreaded(uint32_t flags)
308 : : {
309 : : unsigned int lcore_id;
310 : : struct rte_stack *s;
311 : : int result = 0;
312 : :
313 [ - + ]: 2 : if (rte_lcore_count() < 2) {
314 : : printf("Not enough cores for test_stack_multithreaded, expecting at least 2\n");
315 : 0 : return TEST_SKIPPED;
316 : : }
317 : :
318 : 2 : printf("[%s():%u] Running with %u lcores\n",
319 : : __func__, __LINE__, rte_lcore_count());
320 : :
321 : 2 : s = rte_stack_create("test", MAX_BULK * rte_lcore_count(), rte_socket_id(), flags);
322 [ - + ]: 2 : if (s == NULL) {
323 : : printf("[%s():%u] Failed to create a stack\n",
324 : : __func__, __LINE__);
325 : 0 : return -1;
326 : : }
327 : :
328 : 2 : thread_test_args.s = s;
329 : :
330 [ - + ]: 2 : if (rte_eal_mp_remote_launch(stack_thread_push_pop, NULL, CALL_MAIN))
331 : 0 : rte_panic("Failed to launch tests\n");
332 : :
333 [ + + ]: 6 : RTE_LCORE_FOREACH(lcore_id) {
334 [ - + ]: 4 : if (rte_eal_wait_lcore(lcore_id) < 0)
335 : : result = -1;
336 : : }
337 : :
338 : 2 : rte_stack_free(s);
339 : 2 : return result;
340 : : }
341 : :
342 : : static int
343 : 2 : __test_stack(uint32_t flags)
344 : : {
345 [ + - ]: 2 : if (test_stack_basic(flags) < 0)
346 : : return -1;
347 : :
348 [ + - ]: 2 : if (test_lookup_null() < 0)
349 : : return -1;
350 : :
351 : : if (test_free_null() < 0)
352 : : return -1;
353 : :
354 [ + - ]: 2 : if (test_stack_name_reuse(flags) < 0)
355 : : return -1;
356 : :
357 [ + - ]: 2 : if (test_stack_name_length(flags) < 0)
358 : : return -1;
359 : :
360 [ - + ]: 2 : if (test_stack_multithreaded(flags) < 0)
361 : 0 : return -1;
362 : :
363 : : return 0;
364 : : }
365 : :
366 : : static int
367 : 1 : test_stack(void)
368 : : {
369 : 1 : return __test_stack(0);
370 : : }
371 : :
372 : : static int
373 : 1 : test_lf_stack(void)
374 : : {
375 : : #if defined(RTE_STACK_LF_SUPPORTED)
376 : 1 : return __test_stack(RTE_STACK_F_LF);
377 : : #else
378 : : return TEST_SKIPPED;
379 : : #endif
380 : : }
381 : :
382 : 251 : REGISTER_FAST_TEST(stack_autotest, false, true, test_stack);
383 : 251 : REGISTER_FAST_TEST(stack_lf_autotest, false, true, test_lf_stack);
|