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