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