xref: /dpdk/app/test-bbdev/main.c (revision 089e5ed727a15da2729cfee9b63533dd120bd04c)
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 }
336