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