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