Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <string.h>
6 : : #include <stdio.h>
7 : : #include <stdint.h>
8 : : #include <stdarg.h>
9 : : #include <stdlib.h>
10 : : #include <errno.h>
11 : : #include <ctype.h>
12 : : #include <sys/queue.h>
13 : :
14 : : #include <cmdline_rdline.h>
15 : : #include <cmdline_parse.h>
16 : : #include <cmdline_socket.h>
17 : : #include <cmdline.h>
18 : : extern cmdline_parse_ctx_t main_ctx[];
19 : :
20 : : #include <rte_memory.h>
21 : : #include <rte_eal.h>
22 : : #include <rte_cycles.h>
23 : : #include <rte_log.h>
24 : : #include <rte_string_fns.h>
25 : : #ifdef RTE_LIB_TIMER
26 : : #include <rte_timer.h>
27 : : #endif
28 : :
29 : : #include "test.h"
30 : : #ifdef RTE_LIB_PDUMP
31 : : #include "test_pdump.h"
32 : : #endif
33 : :
34 : : #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
35 : :
36 : : #define FOR_EACH_SUITE_TESTCASE(iter, suite, case) \
37 : : for (iter = 0, case = suite->unit_test_cases[0]; \
38 : : suite->unit_test_cases[iter].testcase || \
39 : : suite->unit_test_cases[iter].testcase_with_data; \
40 : : iter++, case = suite->unit_test_cases[iter])
41 : :
42 : : #define FOR_EACH_SUITE_TESTSUITE(iter, suite, sub_ts) \
43 : : for (iter = 0, sub_ts = suite->unit_test_suites ? \
44 : : suite->unit_test_suites[0]:NULL; sub_ts && \
45 : : suite->unit_test_suites[iter]->suite_name != NULL; \
46 : : iter++, sub_ts = suite->unit_test_suites[iter])
47 : :
48 : : const char *prgname; /* to be set to argv[0] */
49 : :
50 : : static const char *recursive_call; /* used in linux for MP and other tests */
51 : :
52 : : static int
53 : 52 : no_action(void){ return 0; }
54 : :
55 : : static int
56 : 59 : do_recursive_call(void)
57 : : {
58 : : unsigned i;
59 : : struct {
60 : : const char *env_var;
61 : : int (*action_fn)(void);
62 : 59 : } actions[] = {
63 : : #ifndef RTE_EXEC_ENV_WINDOWS
64 : : { "run_secondary_instances", test_mp_secondary },
65 : : #endif
66 : : #ifdef RTE_LIB_PDUMP
67 : : #ifdef RTE_NET_RING
68 : : { "run_pdump_server_tests", test_pdump },
69 : : #endif
70 : : #endif
71 : : { "test_missing_c_flag", no_action },
72 : : { "test_main_lcore_flag", no_action },
73 : : { "test_invalid_n_flag", no_action },
74 : : { "test_no_hpet_flag", no_action },
75 : : { "test_allow_flag", no_action },
76 : : { "test_invalid_b_flag", no_action },
77 : : { "test_invalid_vdev_flag", no_action },
78 : : { "test_invalid_r_flag", no_action },
79 : : { "test_misc_flags", no_action },
80 : : { "test_memory_flags", no_action },
81 : : { "test_file_prefix", no_action },
82 : : { "test_no_huge_flag", no_action },
83 : : { "test_panic", test_panic },
84 : : { "test_exit", test_exit },
85 : : #ifdef RTE_LIB_TIMER
86 : : #ifndef RTE_EXEC_ENV_WINDOWS
87 : : { "timer_secondary_spawn_wait", test_timer_secondary },
88 : : #endif
89 : : #endif
90 : : };
91 : :
92 [ + - ]: 59 : if (recursive_call == NULL)
93 : : return -1;
94 [ + - ]: 608 : for (i = 0; i < RTE_DIM(actions); i++) {
95 [ + + ]: 608 : if (strcmp(actions[i].env_var, recursive_call) == 0) {
96 : : printf("Calling recursive action for %s\n", recursive_call);
97 : 59 : int ret = actions[i].action_fn();
98 : 54 : printf("Returned from recursive action for %s with %d\n",
99 : : recursive_call, ret);
100 : 54 : return ret;
101 : : }
102 : : }
103 : : printf("ERROR - missing action to take for %s\n", recursive_call);
104 : 0 : return -1;
105 : : }
106 : :
107 : : int last_test_result;
108 : :
109 : : #define MAX_EXTRA_ARGS 32
110 : :
111 : : int
112 : 258 : main(int argc, char **argv)
113 : : {
114 : : struct cmdline *cl;
115 : 258 : char **tests = alloca(sizeof(char *) * argc); /* store an array of tests to run */
116 : : int test_count = 0;
117 : : int i;
118 : : char *extra_args;
119 : : int ret;
120 : :
121 : 258 : extra_args = getenv("DPDK_TEST_PARAMS");
122 [ - + - - ]: 258 : if (extra_args != NULL && strlen(extra_args) > 0) {
123 : : char **all_argv;
124 : : char *eargv[MAX_EXTRA_ARGS];
125 : : int all_argc;
126 : : int eargc;
127 : : int i;
128 : :
129 : 0 : RTE_LOG(INFO, APP, "Using additional DPDK_TEST_PARAMS: '%s'\n",
130 : : extra_args);
131 : 0 : eargc = rte_strsplit(extra_args, strlen(extra_args),
132 : : eargv, MAX_EXTRA_ARGS, ' ');
133 : :
134 : : /* merge argc/argv and the environment args */
135 : 0 : all_argc = argc + eargc;
136 : 0 : all_argv = malloc(sizeof(*all_argv) * (all_argc + 1));
137 [ # # ]: 0 : if (all_argv == NULL) {
138 : : ret = -1;
139 : 0 : goto out;
140 : : }
141 : :
142 [ # # ]: 0 : for (i = 0; i < argc; i++)
143 : 0 : all_argv[i] = argv[i];
144 [ # # ]: 0 : for (i = 0; i < eargc; i++)
145 : 0 : all_argv[argc + i] = eargv[i];
146 : 0 : all_argv[all_argc] = NULL;
147 : :
148 : : /* call eal_init with combined args */
149 : 0 : ret = rte_eal_init(all_argc, all_argv);
150 : 0 : free(all_argv);
151 : : } else
152 : 258 : ret = rte_eal_init(argc, argv);
153 [ + + ]: 251 : if (ret < 0) {
154 : : printf("Error with EAL initialization, ret = %d\n", ret);
155 : : ret = -1;
156 : 65 : goto out;
157 : : }
158 : :
159 : 186 : argv += ret;
160 : 186 : argc -= ret;
161 : :
162 : 186 : prgname = argv[0];
163 : :
164 : : #ifdef RTE_LIB_TIMER
165 : 186 : ret = rte_timer_subsystem_init();
166 [ - + ]: 186 : if (ret < 0 && ret != -EALREADY) {
167 : : ret = -1;
168 : 0 : goto out;
169 : : }
170 : : #endif
171 : :
172 [ - + ]: 186 : if (commands_init() < 0) {
173 : : ret = -1;
174 : 0 : goto out;
175 : : }
176 : :
177 : 186 : recursive_call = getenv(RECURSIVE_ENV_VAR);
178 [ + + ]: 186 : if (recursive_call != NULL) {
179 : 59 : ret = do_recursive_call();
180 : 54 : goto out;
181 : : }
182 : :
183 : : #ifdef RTE_LIBEAL_USE_HPET
184 : : if (rte_eal_hpet_init(1) < 0)
185 : : #endif
186 : 127 : RTE_LOG(INFO, APP,
187 : : "HPET is not enabled, using TSC as default timer\n");
188 : :
189 : :
190 : 127 : char *dpdk_test = getenv("DPDK_TEST");
191 : :
192 [ + + + - ]: 127 : if (dpdk_test && strlen(dpdk_test) > 0)
193 : 126 : tests[test_count++] = dpdk_test;
194 [ - + ]: 127 : for (i = 1; i < argc; i++)
195 : 0 : tests[test_count++] = argv[i];
196 : :
197 [ + + ]: 127 : if (test_count > 0) {
198 : : char buf[1024];
199 : 126 : char *dpdk_test_skip = getenv("DPDK_TEST_SKIP");
200 : 126 : char *skip_tests[128] = {0};
201 : : size_t n_skip_tests = 0;
202 : :
203 [ - + - - ]: 126 : if (dpdk_test_skip != NULL && strlen(dpdk_test_skip) > 0) {
204 : : int split_ret;
205 : 0 : char *dpdk_test_skip_cp = strdup(dpdk_test_skip);
206 [ # # ]: 0 : if (dpdk_test_skip_cp == NULL) {
207 : : ret = -1;
208 : 0 : goto out;
209 : : }
210 : : dpdk_test_skip = dpdk_test_skip_cp;
211 : 0 : split_ret = rte_strsplit(dpdk_test_skip, strlen(dpdk_test_skip),
212 : : skip_tests, RTE_DIM(skip_tests), ',');
213 [ # # ]: 0 : if (split_ret > 0)
214 : 0 : n_skip_tests = split_ret;
215 : : else
216 : 0 : free(dpdk_test_skip);
217 : : }
218 : :
219 : 126 : cl = cmdline_new(main_ctx, "RTE>>", 0, 1);
220 [ - + ]: 126 : if (cl == NULL) {
221 : : ret = -1;
222 : 0 : goto out;
223 : : }
224 : :
225 [ + + ]: 252 : for (i = 0; i < test_count; i++) {
226 : : /* check if test is to be skipped */
227 [ - + ]: 126 : for (size_t j = 0; j < n_skip_tests; j++) {
228 [ # # ]: 0 : if (strcmp(tests[i], skip_tests[j]) == 0) {
229 : 0 : fprintf(stderr, "Skipping %s [DPDK_TEST_SKIP]\n", tests[i]);
230 : : ret = TEST_SKIPPED;
231 : 0 : goto end_of_cmd;
232 : : }
233 : : }
234 : :
235 : 126 : snprintf(buf, sizeof(buf), "%s\n", tests[i]);
236 [ - + ]: 126 : if (cmdline_parse_check(cl, buf) < 0) {
237 : : printf("Error: invalid test command: '%s'\n", tests[i]);
238 : : ret = -1;
239 [ - + ]: 126 : } else if (cmdline_in(cl, buf, strlen(buf)) < 0) {
240 : : printf("error on cmdline input\n");
241 : : ret = -1;
242 : : } else
243 : 126 : ret = last_test_result;
244 : :
245 : 126 : end_of_cmd:
246 [ + - ]: 126 : if (ret != 0 && ret != TEST_SKIPPED)
247 : : break;
248 : : }
249 [ - + ]: 126 : if (n_skip_tests > 0)
250 : 0 : free(dpdk_test_skip);
251 : :
252 : 126 : cmdline_free(cl);
253 : 126 : goto out;
254 : : } else {
255 : : /* if no DPDK_TEST env variable, go interactive */
256 : 1 : cl = cmdline_stdin_new(main_ctx, "RTE>>");
257 [ - + ]: 1 : if (cl == NULL) {
258 : : ret = -1;
259 : 0 : goto out;
260 : : }
261 : :
262 : 1 : cmdline_interact(cl);
263 : 1 : cmdline_stdin_exit(cl);
264 : : }
265 : : ret = 0;
266 : :
267 : 246 : out:
268 [ + + ]: 246 : if (recursive_call != NULL)
269 : 54 : printf("Cleaning up %s recursive instance\n", argv[0]);
270 : : #ifdef RTE_LIB_TIMER
271 : 246 : rte_timer_subsystem_finalize();
272 : : #endif
273 : 246 : rte_eal_cleanup();
274 [ + + ]: 246 : if (recursive_call != NULL)
275 : 54 : printf("%s recursive instance returning %d\n", argv[0], ret);
276 : : return ret;
277 : : }
278 : :
279 : : static void
280 : 24 : unit_test_suite_count_tcs_on_setup_fail(struct unit_test_suite *suite,
281 : : int test_success, unsigned int *sub_ts_failed,
282 : : unsigned int *sub_ts_skipped, unsigned int *sub_ts_total)
283 : : {
284 : : struct unit_test_case tc;
285 : : struct unit_test_suite *ts;
286 : : int i;
287 : :
288 [ + + + + : 54 : FOR_EACH_SUITE_TESTSUITE(i, suite, ts) {
+ - ]
289 : 6 : unit_test_suite_count_tcs_on_setup_fail(
290 : : ts, test_success, sub_ts_failed,
291 : : sub_ts_skipped, sub_ts_total);
292 : 6 : suite->total += ts->total;
293 : 6 : suite->failed += ts->failed;
294 : 6 : suite->skipped += ts->skipped;
295 [ - + ]: 6 : if (ts->failed)
296 : 0 : (*sub_ts_failed)++;
297 : : else
298 : 6 : (*sub_ts_skipped)++;
299 : 6 : (*sub_ts_total)++;
300 : : }
301 [ + + + + ]: 739 : FOR_EACH_SUITE_TESTCASE(i, suite, tc) {
302 : 715 : suite->total++;
303 [ + - + - ]: 715 : if (!tc.enabled || test_success == TEST_SKIPPED)
304 : 715 : suite->skipped++;
305 : : else
306 : 0 : suite->failed++;
307 : : }
308 : 24 : }
309 : :
310 : : static void
311 : 110 : unit_test_suite_reset_counts(struct unit_test_suite *suite)
312 : : {
313 : : struct unit_test_suite *ts;
314 : : int i;
315 : :
316 [ + + + + : 259 : FOR_EACH_SUITE_TESTSUITE(i, suite, ts)
+ + ]
317 : 39 : unit_test_suite_reset_counts(ts);
318 : 110 : suite->total = 0;
319 : 110 : suite->executed = 0;
320 : 110 : suite->succeeded = 0;
321 : 110 : suite->skipped = 0;
322 : 110 : suite->failed = 0;
323 : 110 : suite->unsupported = 0;
324 : 110 : }
325 : :
326 : : int
327 : 71 : unit_test_suite_runner(struct unit_test_suite *suite)
328 : : {
329 : : int test_success, i, ret;
330 : : const char *status;
331 : : struct unit_test_case tc;
332 : : struct unit_test_suite *ts;
333 : 71 : unsigned int sub_ts_succeeded = 0, sub_ts_failed = 0;
334 : 71 : unsigned int sub_ts_skipped = 0, sub_ts_total = 0;
335 : :
336 : 71 : unit_test_suite_reset_counts(suite);
337 : :
338 [ + - ]: 71 : if (suite->suite_name) {
339 : : printf(" + ------------------------------------------------------- +\n");
340 : 71 : printf(" + Test Suite : %s\n", suite->suite_name);
341 : : }
342 : :
343 [ + + ]: 71 : if (suite->setup) {
344 : 52 : test_success = suite->setup();
345 [ + + ]: 52 : if (test_success != 0) {
346 : : /*
347 : : * setup did not pass, so count all enabled tests and
348 : : * mark them as failed/skipped
349 : : */
350 : 18 : unit_test_suite_count_tcs_on_setup_fail(suite,
351 : : test_success, &sub_ts_failed,
352 : : &sub_ts_skipped, &sub_ts_total);
353 : 18 : goto suite_summary;
354 : : }
355 : : }
356 : :
357 : : printf(" + ------------------------------------------------------- +\n");
358 : :
359 [ + + + + ]: 888 : FOR_EACH_SUITE_TESTCASE(suite->total, suite, tc) {
360 [ - + ]: 835 : if (!tc.enabled) {
361 : 0 : suite->skipped++;
362 : 0 : continue;
363 : : } else {
364 : 835 : suite->executed++;
365 : : }
366 : :
367 : : /* run test case setup */
368 [ + + ]: 835 : if (tc.setup)
369 : 579 : test_success = tc.setup();
370 : : else
371 : : test_success = TEST_SUCCESS;
372 : :
373 [ + + ]: 579 : if (test_success == TEST_SUCCESS) {
374 : : /* run the test case */
375 [ + + ]: 831 : if (tc.testcase)
376 : 561 : test_success = tc.testcase();
377 [ + - ]: 270 : else if (tc.testcase_with_data)
378 : 270 : test_success = tc.testcase_with_data(tc.data);
379 : : else
380 : : test_success = -ENOTSUP;
381 : :
382 [ + + ]: 831 : if (test_success == TEST_SUCCESS)
383 : 624 : suite->succeeded++;
384 [ + - ]: 207 : else if (test_success == TEST_SKIPPED) {
385 : 207 : suite->skipped++;
386 : 207 : suite->executed--;
387 [ # # ]: 0 : } else if (test_success == -ENOTSUP) {
388 : 0 : suite->unsupported++;
389 : 0 : suite->executed--;
390 : : } else
391 : 0 : suite->failed++;
392 [ - + ]: 4 : } else if (test_success == -ENOTSUP) {
393 : 0 : suite->unsupported++;
394 [ + - ]: 4 : } else if (test_success == TEST_SKIPPED) {
395 : 4 : suite->skipped++;
396 : : } else {
397 : 0 : suite->failed++;
398 : : }
399 : :
400 : : /* run the test case teardown */
401 [ + + ]: 835 : if (tc.teardown)
402 : 550 : tc.teardown();
403 : :
404 [ + + ]: 835 : if (test_success == TEST_SUCCESS)
405 : : status = "succeeded";
406 [ - + ]: 211 : else if (test_success == TEST_SKIPPED)
407 : : status = "skipped";
408 [ # # ]: 0 : else if (test_success == -ENOTSUP)
409 : : status = "unsupported";
410 : : else
411 : : status = "failed";
412 : :
413 : 835 : printf(" + TestCase [%2d] : %s %s\n", suite->total,
414 : : tc.name, status);
415 : : }
416 [ + + + + : 139 : FOR_EACH_SUITE_TESTSUITE(i, suite, ts) {
+ + ]
417 : 33 : ret = unit_test_suite_runner(ts);
418 [ + + ]: 33 : if (ret == TEST_SUCCESS)
419 : 18 : sub_ts_succeeded++;
420 [ + - ]: 15 : else if (ret == TEST_SKIPPED)
421 : 15 : sub_ts_skipped++;
422 : : else
423 : 0 : sub_ts_failed++;
424 : 33 : sub_ts_total++;
425 : :
426 : 33 : suite->total += ts->total;
427 : 33 : suite->succeeded += ts->succeeded;
428 : 33 : suite->failed += ts->failed;
429 : 33 : suite->skipped += ts->skipped;
430 : 33 : suite->unsupported += ts->unsupported;
431 : 33 : suite->executed += ts->executed;
432 : : }
433 : :
434 : : /* Run test suite teardown */
435 [ + + ]: 53 : if (suite->teardown)
436 : 16 : suite->teardown();
437 : :
438 : 53 : goto suite_summary;
439 : :
440 : 71 : suite_summary:
441 : : printf(" + ------------------------------------------------------- +\n");
442 : 71 : printf(" + Test Suite Summary : %s\n", suite->suite_name);
443 : : printf(" + ------------------------------------------------------- +\n");
444 : :
445 [ + + + + : 181 : FOR_EACH_SUITE_TESTSUITE(i, suite, ts)
+ + ]
446 : 39 : printf(" + %s : %d/%d passed, %d/%d skipped, "
447 : : "%d/%d failed, %d/%d unsupported\n", ts->suite_name,
448 : : ts->succeeded, ts->total, ts->skipped, ts->total,
449 : : ts->failed, ts->total, ts->unsupported, ts->total);
450 : :
451 [ + + ]: 71 : if (suite->unit_test_suites) {
452 : : printf(" + ------------------------------------------------------- +\n");
453 : 2 : printf(" + Sub Testsuites Total : %2d\n", sub_ts_total);
454 : 2 : printf(" + Sub Testsuites Skipped : %2d\n", sub_ts_skipped);
455 : : printf(" + Sub Testsuites Passed : %2d\n", sub_ts_succeeded);
456 : 2 : printf(" + Sub Testsuites Failed : %2d\n", sub_ts_failed);
457 : : printf(" + ------------------------------------------------------- +\n");
458 : : }
459 : :
460 : 71 : printf(" + Tests Total : %2d\n", suite->total);
461 : 71 : printf(" + Tests Skipped : %2d\n", suite->skipped);
462 : 71 : printf(" + Tests Executed : %2d\n", suite->executed);
463 : 71 : printf(" + Tests Unsupported: %2d\n", suite->unsupported);
464 : 71 : printf(" + Tests Passed : %2d\n", suite->succeeded);
465 : 71 : printf(" + Tests Failed : %2d\n", suite->failed);
466 : : printf(" + ------------------------------------------------------- +\n");
467 : :
468 : 71 : last_test_result = suite->failed;
469 : :
470 [ + - ]: 71 : if (suite->failed)
471 : : return TEST_FAILED;
472 [ + + ]: 71 : if (suite->total == suite->skipped)
473 : 19 : return TEST_SKIPPED;
474 : : return TEST_SUCCESS;
475 : : }
|