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