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