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