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 } 237 #endif 238 ret = 0; 239 240 out: 241 #ifdef RTE_LIB_TIMER 242 rte_timer_subsystem_finalize(); 243 #endif 244 rte_eal_cleanup(); 245 return ret; 246 } 247 248 static void 249 unit_test_suite_count_tcs_on_setup_fail(struct unit_test_suite *suite, 250 int test_success, unsigned int *sub_ts_failed, 251 unsigned int *sub_ts_skipped, unsigned int *sub_ts_total) 252 { 253 struct unit_test_case tc; 254 struct unit_test_suite *ts; 255 int i; 256 257 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) { 258 unit_test_suite_count_tcs_on_setup_fail( 259 ts, test_success, sub_ts_failed, 260 sub_ts_skipped, sub_ts_total); 261 suite->total += ts->total; 262 suite->failed += ts->failed; 263 suite->skipped += ts->skipped; 264 if (ts->failed) 265 (*sub_ts_failed)++; 266 else 267 (*sub_ts_skipped)++; 268 (*sub_ts_total)++; 269 } 270 FOR_EACH_SUITE_TESTCASE(i, suite, tc) { 271 suite->total++; 272 if (!tc.enabled || test_success == TEST_SKIPPED) 273 suite->skipped++; 274 else 275 suite->failed++; 276 } 277 } 278 279 static void 280 unit_test_suite_reset_counts(struct unit_test_suite *suite) 281 { 282 struct unit_test_suite *ts; 283 int i; 284 285 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) 286 unit_test_suite_reset_counts(ts); 287 suite->total = 0; 288 suite->executed = 0; 289 suite->succeeded = 0; 290 suite->skipped = 0; 291 suite->failed = 0; 292 suite->unsupported = 0; 293 } 294 295 int 296 unit_test_suite_runner(struct unit_test_suite *suite) 297 { 298 int test_success, i, ret; 299 const char *status; 300 struct unit_test_case tc; 301 struct unit_test_suite *ts; 302 unsigned int sub_ts_succeeded = 0, sub_ts_failed = 0; 303 unsigned int sub_ts_skipped = 0, sub_ts_total = 0; 304 305 unit_test_suite_reset_counts(suite); 306 307 if (suite->suite_name) { 308 printf(" + ------------------------------------------------------- +\n"); 309 printf(" + Test Suite : %s\n", suite->suite_name); 310 } 311 312 if (suite->setup) { 313 test_success = suite->setup(); 314 if (test_success != 0) { 315 /* 316 * setup did not pass, so count all enabled tests and 317 * mark them as failed/skipped 318 */ 319 unit_test_suite_count_tcs_on_setup_fail(suite, 320 test_success, &sub_ts_failed, 321 &sub_ts_skipped, &sub_ts_total); 322 goto suite_summary; 323 } 324 } 325 326 printf(" + ------------------------------------------------------- +\n"); 327 328 FOR_EACH_SUITE_TESTCASE(suite->total, suite, tc) { 329 if (!tc.enabled) { 330 suite->skipped++; 331 continue; 332 } else { 333 suite->executed++; 334 } 335 336 /* run test case setup */ 337 if (tc.setup) 338 test_success = tc.setup(); 339 else 340 test_success = TEST_SUCCESS; 341 342 if (test_success == TEST_SUCCESS) { 343 /* run the test case */ 344 if (tc.testcase) 345 test_success = tc.testcase(); 346 else if (tc.testcase_with_data) 347 test_success = tc.testcase_with_data(tc.data); 348 else 349 test_success = -ENOTSUP; 350 351 if (test_success == TEST_SUCCESS) 352 suite->succeeded++; 353 else if (test_success == TEST_SKIPPED) 354 suite->skipped++; 355 else if (test_success == -ENOTSUP) 356 suite->unsupported++; 357 else 358 suite->failed++; 359 } else if (test_success == -ENOTSUP) { 360 suite->unsupported++; 361 } else { 362 suite->failed++; 363 } 364 365 /* run the test case teardown */ 366 if (tc.teardown) 367 tc.teardown(); 368 369 if (test_success == TEST_SUCCESS) 370 status = "succeeded"; 371 else if (test_success == TEST_SKIPPED) 372 status = "skipped"; 373 else if (test_success == -ENOTSUP) 374 status = "unsupported"; 375 else 376 status = "failed"; 377 378 printf(" + TestCase [%2d] : %s %s\n", suite->total, 379 tc.name, status); 380 } 381 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) { 382 ret = unit_test_suite_runner(ts); 383 if (ret == TEST_SUCCESS) 384 sub_ts_succeeded++; 385 else if (ret == TEST_SKIPPED) 386 sub_ts_skipped++; 387 else 388 sub_ts_failed++; 389 sub_ts_total++; 390 391 suite->total += ts->total; 392 suite->succeeded += ts->succeeded; 393 suite->failed += ts->failed; 394 suite->skipped += ts->skipped; 395 suite->unsupported += ts->unsupported; 396 suite->executed += ts->executed; 397 } 398 399 /* Run test suite teardown */ 400 if (suite->teardown) 401 suite->teardown(); 402 403 goto suite_summary; 404 405 suite_summary: 406 printf(" + ------------------------------------------------------- +\n"); 407 printf(" + Test Suite Summary : %s\n", suite->suite_name); 408 printf(" + ------------------------------------------------------- +\n"); 409 410 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) 411 printf(" + %s : %d/%d passed, %d/%d skipped, " 412 "%d/%d failed, %d/%d unsupported\n", ts->suite_name, 413 ts->succeeded, ts->total, ts->skipped, ts->total, 414 ts->failed, ts->total, ts->unsupported, ts->total); 415 416 if (suite->unit_test_suites) { 417 printf(" + ------------------------------------------------------- +\n"); 418 printf(" + Sub Testsuites Total : %2d\n", sub_ts_total); 419 printf(" + Sub Testsuites Skipped : %2d\n", sub_ts_skipped); 420 printf(" + Sub Testsuites Passed : %2d\n", sub_ts_succeeded); 421 printf(" + Sub Testsuites Failed : %2d\n", sub_ts_failed); 422 printf(" + ------------------------------------------------------- +\n"); 423 } 424 425 printf(" + Tests Total : %2d\n", suite->total); 426 printf(" + Tests Skipped : %2d\n", suite->skipped); 427 printf(" + Tests Executed : %2d\n", suite->executed); 428 printf(" + Tests Unsupported: %2d\n", suite->unsupported); 429 printf(" + Tests Passed : %2d\n", suite->succeeded); 430 printf(" + Tests Failed : %2d\n", suite->failed); 431 printf(" + ------------------------------------------------------- +\n"); 432 433 last_test_result = suite->failed; 434 435 if (suite->failed) 436 return TEST_FAILED; 437 if (suite->total == suite->skipped) 438 return TEST_SKIPPED; 439 return TEST_SUCCESS; 440 } 441