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