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