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