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