graph: remove useless duplicate name check
[dpdk.git] / app / test / test_stack.c
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 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         popped_objs = rte_calloc(NULL, STACK_SIZE, sizeof(void *), 0);
24         if (popped_objs == NULL) {
25                 printf("[%s():%u] failed to calloc %zu bytes\n",
26                        __func__, __LINE__, STACK_SIZE * sizeof(void *));
27                 return -1;
28         }
29
30         for (i = 0; i < STACK_SIZE; i += bulk_sz) {
31                 ret = rte_stack_push(s, &obj_table[i], bulk_sz);
32
33                 if (ret != bulk_sz) {
34                         printf("[%s():%u] push returned: %d (expected %u)\n",
35                                __func__, __LINE__, ret, bulk_sz);
36                         rte_free(popped_objs);
37                         return -1;
38                 }
39
40                 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                         rte_free(popped_objs);
45                         return -1;
46                 }
47
48                 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                         rte_free(popped_objs);
53                         return -1;
54                 }
55         }
56
57         for (i = 0; i < STACK_SIZE; i += bulk_sz) {
58                 ret = rte_stack_pop(s, &popped_objs[i], bulk_sz);
59
60                 if (ret != bulk_sz) {
61                         printf("[%s():%u] pop returned: %d (expected %u)\n",
62                                __func__, __LINE__, ret, bulk_sz);
63                         rte_free(popped_objs);
64                         return -1;
65                 }
66
67                 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                         rte_free(popped_objs);
72                         return -1;
73                 }
74
75                 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                         rte_free(popped_objs);
80                         return -1;
81                 }
82         }
83
84         for (i = 0; i < STACK_SIZE; i++) {
85                 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                         rte_free(popped_objs);
90                         return -1;
91                 }
92         }
93
94         rte_free(popped_objs);
95
96         return 0;
97 }
98
99 static int
100 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         obj_table = rte_calloc(NULL, STACK_SIZE, sizeof(void *), 0);
107         if (obj_table == NULL) {
108                 printf("[%s():%u] failed to calloc %zu bytes\n",
109                        __func__, __LINE__, STACK_SIZE * sizeof(void *));
110                 goto fail_test;
111         }
112
113         for (i = 0; i < STACK_SIZE; i++)
114                 obj_table[i] = (void *)(uintptr_t)i;
115
116         s = rte_stack_create(__func__, STACK_SIZE, rte_socket_id(), flags);
117         if (s == NULL) {
118                 printf("[%s():%u] failed to create a stack\n",
119                        __func__, __LINE__);
120                 goto fail_test;
121         }
122
123         if (rte_stack_lookup(__func__) != s) {
124                 printf("[%s():%u] failed to lookup a stack\n",
125                        __func__, __LINE__);
126                 goto fail_test;
127         }
128
129         if (rte_stack_count(s) != 0) {
130                 printf("[%s():%u] stack count: %u (expected 0)\n",
131                        __func__, __LINE__, rte_stack_count(s));
132                 goto fail_test;
133         }
134
135         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                 goto fail_test;
139         }
140
141         ret = test_stack_push_pop(s, obj_table, 1);
142         if (ret) {
143                 printf("[%s():%u] Single object push/pop failed\n",
144                        __func__, __LINE__);
145                 goto fail_test;
146         }
147
148         ret = test_stack_push_pop(s, obj_table, MAX_BULK);
149         if (ret) {
150                 printf("[%s():%u] Bulk object push/pop failed\n",
151                        __func__, __LINE__);
152                 goto fail_test;
153         }
154
155         ret = rte_stack_push(s, obj_table, 2 * STACK_SIZE);
156         if (ret != 0) {
157                 printf("[%s():%u] Excess objects push succeeded\n",
158                        __func__, __LINE__);
159                 goto fail_test;
160         }
161
162         ret = rte_stack_pop(s, obj_table, 1);
163         if (ret != 0) {
164                 printf("[%s():%u] Empty stack pop succeeded\n",
165                        __func__, __LINE__);
166                 goto fail_test;
167         }
168
169         ret = 0;
170
171 fail_test:
172         rte_stack_free(s);
173
174         rte_free(obj_table);
175
176         return ret;
177 }
178
179 static int
180 test_stack_name_reuse(uint32_t flags)
181 {
182         struct rte_stack *s[2];
183
184         s[0] = rte_stack_create("test", STACK_SIZE, rte_socket_id(), flags);
185         if (s[0] == NULL) {
186                 printf("[%s():%u] Failed to create a stack\n",
187                        __func__, __LINE__);
188                 return -1;
189         }
190
191         s[1] = rte_stack_create("test", STACK_SIZE, rte_socket_id(), flags);
192         if (s[1] != NULL) {
193                 printf("[%s():%u] Failed to detect re-used name\n",
194                        __func__, __LINE__);
195                 return -1;
196         }
197
198         rte_stack_free(s[0]);
199
200         return 0;
201 }
202
203 static int
204 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         name[RTE_STACK_NAMESIZE] = '\0';
211
212         s = rte_stack_create(name, STACK_SIZE, rte_socket_id(), flags);
213         if (s != NULL) {
214                 printf("[%s():%u] Failed to prevent long name\n",
215                        __func__, __LINE__);
216                 return -1;
217         }
218
219         if (rte_errno != ENAMETOOLONG) {
220                 printf("[%s():%u] rte_stack failed to set correct errno on failed lookup\n",
221                        __func__, __LINE__);
222                 return -1;
223         }
224
225         return 0;
226 }
227
228 static int
229 test_lookup_null(void)
230 {
231         struct rte_stack *s = rte_stack_lookup("stack_not_found");
232
233         if (s != NULL) {
234                 printf("[%s():%u] rte_stack found a non-existent stack\n",
235                        __func__, __LINE__);
236                 return -1;
237         }
238
239         if (rte_errno != ENOENT) {
240                 printf("[%s():%u] rte_stack failed to set correct errno on failed lookup\n",
241                        __func__, __LINE__);
242                 return -1;
243         }
244
245         s = rte_stack_lookup(NULL);
246
247         if (s != NULL) {
248                 printf("[%s():%u] rte_stack found a non-existent stack\n",
249                        __func__, __LINE__);
250                 return -1;
251         }
252
253         if (rte_errno != EINVAL) {
254                 printf("[%s():%u] rte_stack failed to set correct errno on failed lookup\n",
255                        __func__, __LINE__);
256                 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         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 stack_thread_push_pop(__rte_unused void *args)
281 {
282         void *obj_table[MAX_BULK];
283         int i;
284
285         for (i = 0; i < NUM_ITERS_PER_THREAD; i++) {
286                 unsigned int num;
287
288                 num = rte_rand() % MAX_BULK;
289
290                 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                         return -1;
294                 }
295
296                 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                         return -1;
300                 }
301         }
302
303         return 0;
304 }
305
306 static int
307 test_stack_multithreaded(uint32_t flags)
308 {
309         unsigned int lcore_id;
310         struct rte_stack *s;
311         int result = 0;
312
313         if (rte_lcore_count() < 2) {
314                 printf("Not enough cores for test_stack_multithreaded, expecting at least 2\n");
315                 return TEST_SKIPPED;
316         }
317
318         printf("[%s():%u] Running with %u lcores\n",
319                __func__, __LINE__, rte_lcore_count());
320
321         s = rte_stack_create("test", MAX_BULK * rte_lcore_count(), rte_socket_id(), flags);
322         if (s == NULL) {
323                 printf("[%s():%u] Failed to create a stack\n",
324                        __func__, __LINE__);
325                 return -1;
326         }
327
328         thread_test_args.s = s;
329
330         if (rte_eal_mp_remote_launch(stack_thread_push_pop, NULL, CALL_MAIN))
331                 rte_panic("Failed to launch tests\n");
332
333         RTE_LCORE_FOREACH(lcore_id) {
334                 if (rte_eal_wait_lcore(lcore_id) < 0)
335                         result = -1;
336         }
337
338         rte_stack_free(s);
339         return result;
340 }
341
342 static int
343 __test_stack(uint32_t flags)
344 {
345         if (test_stack_basic(flags) < 0)
346                 return -1;
347
348         if (test_lookup_null() < 0)
349                 return -1;
350
351         if (test_free_null() < 0)
352                 return -1;
353
354         if (test_stack_name_reuse(flags) < 0)
355                 return -1;
356
357         if (test_stack_name_length(flags) < 0)
358                 return -1;
359
360         if (test_stack_multithreaded(flags) < 0)
361                 return -1;
362
363         return 0;
364 }
365
366 static int
367 test_stack(void)
368 {
369         return __test_stack(0);
370 }
371
372 static int
373 test_lf_stack(void)
374 {
375 #if defined(RTE_STACK_LF_SUPPORTED)
376         return __test_stack(RTE_STACK_F_LF);
377 #else
378         return TEST_SKIPPED;
379 #endif
380 }
381
382 REGISTER_TEST_COMMAND(stack_autotest, test_stack);
383 REGISTER_TEST_COMMAND(stack_lf_autotest, test_lf_stack);