app/bbdev: update for 5GNR
[dpdk.git] / app / test-bbdev / main.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Intel Corporation
3  */
4
5 #include <getopt.h>
6 #include <inttypes.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <stdbool.h>
10
11 #include <rte_eal.h>
12 #include <rte_common.h>
13 #include <rte_string_fns.h>
14 #include <rte_cycles.h>
15 #include <rte_lcore.h>
16
17 #include "main.h"
18
19
20 /* Defines how many testcases can be specified as cmdline args */
21 #define MAX_CMDLINE_TESTCASES 8
22
23 static const char tc_sep = ',';
24
25 /* Declare structure for command line test parameters and options */
26 static struct test_params {
27         struct test_command *test_to_run[MAX_CMDLINE_TESTCASES];
28         unsigned int num_tests;
29         unsigned int num_ops;
30         unsigned int burst_sz;
31         unsigned int num_lcores;
32         char test_vector_filename[PATH_MAX];
33         bool init_device;
34 } test_params;
35
36 static struct test_commands_list commands_list =
37         TAILQ_HEAD_INITIALIZER(commands_list);
38
39 void
40 add_test_command(struct test_command *t)
41 {
42         TAILQ_INSERT_TAIL(&commands_list, t, next);
43 }
44
45 int
46 unit_test_suite_runner(struct unit_test_suite *suite)
47 {
48         int test_result = TEST_SUCCESS;
49         unsigned int total = 0, skipped = 0, succeeded = 0, failed = 0;
50         uint64_t start, end;
51
52         printf("\n===========================================================\n");
53         printf("Starting Test Suite : %s\n", suite->suite_name);
54
55         start = rte_rdtsc_precise();
56
57         if (suite->setup) {
58                 test_result = suite->setup();
59                 if (test_result == TEST_FAILED) {
60                         printf(" + Test suite setup %s failed!\n",
61                                         suite->suite_name);
62                         printf(" + ------------------------------------------------------- +\n");
63                         return 1;
64                 }
65                 if (test_result == TEST_SKIPPED) {
66                         printf(" + Test suite setup %s skipped!\n",
67                                         suite->suite_name);
68                         printf(" + ------------------------------------------------------- +\n");
69                         return 0;
70                 }
71         }
72
73         while (suite->unit_test_cases[total].testcase) {
74                 if (suite->unit_test_cases[total].setup)
75                         test_result = suite->unit_test_cases[total].setup();
76
77                 if (test_result == TEST_SUCCESS)
78                         test_result = suite->unit_test_cases[total].testcase();
79
80                 if (suite->unit_test_cases[total].teardown)
81                         suite->unit_test_cases[total].teardown();
82
83                 if (test_result == TEST_SUCCESS) {
84                         succeeded++;
85                         printf("TestCase [%2d] : %s passed\n", total,
86                                         suite->unit_test_cases[total].name);
87                 } else if (test_result == TEST_SKIPPED) {
88                         skipped++;
89                         printf("TestCase [%2d] : %s skipped\n", total,
90                                         suite->unit_test_cases[total].name);
91                 } else {
92                         failed++;
93                         printf("TestCase [%2d] : %s failed\n", total,
94                                         suite->unit_test_cases[total].name);
95                 }
96
97                 total++;
98         }
99
100         /* Run test suite teardown */
101         if (suite->teardown)
102                 suite->teardown();
103
104         end = rte_rdtsc_precise();
105
106         printf(" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\n");
107         printf(" + Test Suite Summary : %s\n", suite->suite_name);
108         printf(" + Tests Total :       %2d\n", total);
109         printf(" + Tests Skipped :     %2d\n", skipped);
110         printf(" + Tests Passed :      %2d\n", succeeded);
111         printf(" + Tests Failed :      %2d\n", failed);
112         printf(" + Tests Lasted :       %lg ms\n",
113                         ((end - start) * 1000) / (double)rte_get_tsc_hz());
114         printf(" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\n");
115
116         return (failed > 0) ? 1 : 0;
117 }
118
119 const char *
120 get_vector_filename(void)
121 {
122         return test_params.test_vector_filename;
123 }
124
125 unsigned int
126 get_num_ops(void)
127 {
128         return test_params.num_ops;
129 }
130
131 unsigned int
132 get_burst_sz(void)
133 {
134         return test_params.burst_sz;
135 }
136
137 unsigned int
138 get_num_lcores(void)
139 {
140         return test_params.num_lcores;
141 }
142
143 bool
144 get_init_device(void)
145 {
146         return test_params.init_device;
147 }
148
149 static void
150 print_usage(const char *prog_name)
151 {
152         struct test_command *t;
153
154         printf("***Usage: %s [EAL params] [-- [-n/--num-ops NUM_OPS]\n"
155                         "\t[-b/--burst-size BURST_SIZE]\n"
156                         "\t[-v/--test-vector VECTOR_FILE]\n"
157                         "\t[-c/--test-cases TEST_CASE[,TEST_CASE,...]]]\n",
158                         prog_name);
159
160         printf("Available testcases: ");
161         TAILQ_FOREACH(t, &commands_list, next)
162                 printf("%s ", t->command);
163         printf("\n");
164 }
165
166 static int
167 parse_args(int argc, char **argv, struct test_params *tp)
168 {
169         int opt, option_index;
170         unsigned int num_tests = 0;
171         bool test_cases_present = false;
172         bool test_vector_present = false;
173         struct test_command *t;
174         char *tokens[MAX_CMDLINE_TESTCASES];
175         int tc, ret;
176
177         static struct option lgopts[] = {
178                 { "num-ops", 1, 0, 'n' },
179                 { "burst-size", 1, 0, 'b' },
180                 { "test-cases", 1, 0, 'c' },
181                 { "test-vector", 1, 0, 'v' },
182                 { "lcores", 1, 0, 'l' },
183                 { "init-device", 0, 0, 'i'},
184                 { "help", 0, 0, 'h' },
185                 { NULL,  0, 0, 0 }
186         };
187
188         while ((opt = getopt_long(argc, argv, "hin:b:c:v:l:", lgopts,
189                         &option_index)) != EOF)
190                 switch (opt) {
191                 case 'n':
192                         TEST_ASSERT(strlen(optarg) > 0,
193                                         "Num of operations is not provided");
194                         tp->num_ops = strtol(optarg, NULL, 10);
195                         break;
196                 case 'b':
197                         TEST_ASSERT(strlen(optarg) > 0,
198                                         "Burst size is not provided");
199                         tp->burst_sz = strtol(optarg, NULL, 10);
200                         TEST_ASSERT(tp->burst_sz <= MAX_BURST,
201                                         "Burst size mustn't be greater than %u",
202                                         MAX_BURST);
203                         break;
204                 case 'c':
205                         TEST_ASSERT(test_cases_present == false,
206                                         "Test cases provided more than once");
207                         test_cases_present = true;
208
209                         ret = rte_strsplit(optarg, strlen(optarg),
210                                         tokens, MAX_CMDLINE_TESTCASES, tc_sep);
211
212                         TEST_ASSERT(ret <= MAX_CMDLINE_TESTCASES,
213                                         "Too many test cases (max=%d)",
214                                         MAX_CMDLINE_TESTCASES);
215
216                         for (tc = 0; tc < ret; ++tc) {
217                                 /* Find matching test case */
218                                 TAILQ_FOREACH(t, &commands_list, next)
219                                         if (!strcmp(tokens[tc], t->command))
220                                                 tp->test_to_run[num_tests] = t;
221
222                                 TEST_ASSERT(tp->test_to_run[num_tests] != NULL,
223                                                 "Unknown test case: %s",
224                                                 tokens[tc]);
225                                 ++num_tests;
226                         }
227                         break;
228                 case 'v':
229                         TEST_ASSERT(test_vector_present == false,
230                                         "Test vector provided more than once");
231                         test_vector_present = true;
232
233                         TEST_ASSERT(strlen(optarg) > 0,
234                                         "Config file name is null");
235
236                         snprintf(tp->test_vector_filename,
237                                         sizeof(tp->test_vector_filename),
238                                         "%s", optarg);
239                         break;
240                 case 'l':
241                         TEST_ASSERT(strlen(optarg) > 0,
242                                         "Num of lcores is not provided");
243                         tp->num_lcores = strtol(optarg, NULL, 10);
244                         TEST_ASSERT(tp->num_lcores <= RTE_MAX_LCORE,
245                                         "Num of lcores mustn't be greater than %u",
246                                         RTE_MAX_LCORE);
247                         break;
248                 case 'i':
249                         /* indicate fpga fec config required */
250                         tp->init_device = true;
251                         break;
252                 case 'h':
253                         print_usage(argv[0]);
254                         return 0;
255                 default:
256                         printf("ERROR: Unknown option: -%c\n", opt);
257                         return -1;
258                 }
259
260         if (tp->num_ops == 0) {
261                 printf(
262                         "WARNING: Num of operations was not provided or was set 0. Set to default (%u)\n",
263                         DEFAULT_OPS);
264                 tp->num_ops = DEFAULT_OPS;
265         }
266         if (tp->burst_sz == 0) {
267                 printf(
268                         "WARNING: Burst size was not provided or was set 0. Set to default (%u)\n",
269                         DEFAULT_BURST);
270                 tp->burst_sz = DEFAULT_BURST;
271         }
272         if (tp->num_lcores == 0) {
273                 printf(
274                         "WARNING: Num of lcores was not provided or was set 0. Set to value from RTE config (%u)\n",
275                         rte_lcore_count());
276                 tp->num_lcores = rte_lcore_count();
277         }
278
279         TEST_ASSERT(tp->burst_sz <= tp->num_ops,
280                         "Burst size (%u) mustn't be greater than num ops (%u)",
281                         tp->burst_sz, tp->num_ops);
282
283         tp->num_tests = num_tests;
284         return 0;
285 }
286
287 static int
288 run_all_tests(void)
289 {
290         int ret = TEST_SUCCESS;
291         struct test_command *t;
292
293         TAILQ_FOREACH(t, &commands_list, next)
294                 ret |= (int) t->callback();
295
296         return ret;
297 }
298
299 static int
300 run_parsed_tests(struct test_params *tp)
301 {
302         int ret = TEST_SUCCESS;
303         unsigned int i;
304
305         for (i = 0; i < tp->num_tests; ++i)
306                 ret |= (int) tp->test_to_run[i]->callback();
307
308         return ret;
309 }
310
311 int
312 main(int argc, char **argv)
313 {
314         int ret;
315
316         /* Init EAL */
317         ret = rte_eal_init(argc, argv);
318         if (ret < 0)
319                 return 1;
320         argc -= ret;
321         argv += ret;
322
323         /* Parse application arguments (after the EAL ones) */
324         ret = parse_args(argc, argv, &test_params);
325         if (ret < 0) {
326                 print_usage(argv[0]);
327                 return 1;
328         }
329
330         /* If no argument provided - run all tests */
331         if (test_params.num_tests == 0)
332                 return run_all_tests();
333         else
334                 return run_parsed_tests(&test_params);
335 }