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