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