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 dpdk_test = NULL; 191 192 if (dpdk_test && !command_valid(dpdk_test)) { 193 RTE_LOG(WARNING, APP, "Invalid DPDK_TEST value '%s'\n", dpdk_test); 194 dpdk_test = NULL; 195 } 196 197 if (dpdk_test) 198 tests[test_count++] = dpdk_test; 199 for (i = 1; i < argc; i++) { 200 if (!command_valid(argv[i])) 201 RTE_LOG(WARNING, APP, "Invalid test requested: '%s'\n", argv[i]); 202 else 203 tests[test_count++] = argv[i]; 204 } 205 206 if (test_count > 0) { 207 char buf[1024]; 208 209 cl = cmdline_new(main_ctx, "RTE>>", 0, 1); 210 if (cl == NULL) { 211 ret = -1; 212 goto out; 213 } 214 215 for (i = 0; i < test_count; i++) { 216 snprintf(buf, sizeof(buf), "%s\n", tests[i]); 217 if (cmdline_in(cl, buf, strlen(buf)) < 0) { 218 printf("error on cmdline input\n"); 219 220 ret = -1; 221 } else 222 ret = last_test_result; 223 224 if (ret != 0) 225 break; 226 } 227 cmdline_free(cl); 228 goto out; 229 } else { 230 /* if no DPDK_TEST env variable, go interactive */ 231 cl = cmdline_stdin_new(main_ctx, "RTE>>"); 232 if (cl == NULL) { 233 ret = -1; 234 goto out; 235 } 236 237 cmdline_interact(cl); 238 cmdline_stdin_exit(cl); 239 } 240 #endif 241 ret = 0; 242 243 out: 244 #ifdef RTE_LIB_TIMER 245 rte_timer_subsystem_finalize(); 246 #endif 247 rte_eal_cleanup(); 248 return ret; 249 } 250 251 static void 252 unit_test_suite_count_tcs_on_setup_fail(struct unit_test_suite *suite, 253 int test_success, unsigned int *sub_ts_failed, 254 unsigned int *sub_ts_skipped, unsigned int *sub_ts_total) 255 { 256 struct unit_test_case tc; 257 struct unit_test_suite *ts; 258 int i; 259 260 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) { 261 unit_test_suite_count_tcs_on_setup_fail( 262 ts, test_success, sub_ts_failed, 263 sub_ts_skipped, sub_ts_total); 264 suite->total += ts->total; 265 suite->failed += ts->failed; 266 suite->skipped += ts->skipped; 267 if (ts->failed) 268 (*sub_ts_failed)++; 269 else 270 (*sub_ts_skipped)++; 271 (*sub_ts_total)++; 272 } 273 FOR_EACH_SUITE_TESTCASE(i, suite, tc) { 274 suite->total++; 275 if (!tc.enabled || test_success == TEST_SKIPPED) 276 suite->skipped++; 277 else 278 suite->failed++; 279 } 280 } 281 282 static void 283 unit_test_suite_reset_counts(struct unit_test_suite *suite) 284 { 285 struct unit_test_suite *ts; 286 int i; 287 288 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) 289 unit_test_suite_reset_counts(ts); 290 suite->total = 0; 291 suite->executed = 0; 292 suite->succeeded = 0; 293 suite->skipped = 0; 294 suite->failed = 0; 295 suite->unsupported = 0; 296 } 297 298 int 299 unit_test_suite_runner(struct unit_test_suite *suite) 300 { 301 int test_success, i, ret; 302 const char *status; 303 struct unit_test_case tc; 304 struct unit_test_suite *ts; 305 unsigned int sub_ts_succeeded = 0, sub_ts_failed = 0; 306 unsigned int sub_ts_skipped = 0, sub_ts_total = 0; 307 308 unit_test_suite_reset_counts(suite); 309 310 if (suite->suite_name) { 311 printf(" + ------------------------------------------------------- +\n"); 312 printf(" + Test Suite : %s\n", suite->suite_name); 313 } 314 315 if (suite->setup) { 316 test_success = suite->setup(); 317 if (test_success != 0) { 318 /* 319 * setup did not pass, so count all enabled tests and 320 * mark them as failed/skipped 321 */ 322 unit_test_suite_count_tcs_on_setup_fail(suite, 323 test_success, &sub_ts_failed, 324 &sub_ts_skipped, &sub_ts_total); 325 goto suite_summary; 326 } 327 } 328 329 printf(" + ------------------------------------------------------- +\n"); 330 331 FOR_EACH_SUITE_TESTCASE(suite->total, suite, tc) { 332 if (!tc.enabled) { 333 suite->skipped++; 334 continue; 335 } else { 336 suite->executed++; 337 } 338 339 /* run test case setup */ 340 if (tc.setup) 341 test_success = tc.setup(); 342 else 343 test_success = TEST_SUCCESS; 344 345 if (test_success == TEST_SUCCESS) { 346 /* run the test case */ 347 if (tc.testcase) 348 test_success = tc.testcase(); 349 else if (tc.testcase_with_data) 350 test_success = tc.testcase_with_data(tc.data); 351 else 352 test_success = -ENOTSUP; 353 354 if (test_success == TEST_SUCCESS) 355 suite->succeeded++; 356 else if (test_success == TEST_SKIPPED) 357 suite->skipped++; 358 else if (test_success == -ENOTSUP) 359 suite->unsupported++; 360 else 361 suite->failed++; 362 } else if (test_success == -ENOTSUP) { 363 suite->unsupported++; 364 } else { 365 suite->failed++; 366 } 367 368 /* run the test case teardown */ 369 if (tc.teardown) 370 tc.teardown(); 371 372 if (test_success == TEST_SUCCESS) 373 status = "succeeded"; 374 else if (test_success == TEST_SKIPPED) 375 status = "skipped"; 376 else if (test_success == -ENOTSUP) 377 status = "unsupported"; 378 else 379 status = "failed"; 380 381 printf(" + TestCase [%2d] : %s %s\n", suite->total, 382 tc.name, status); 383 } 384 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) { 385 ret = unit_test_suite_runner(ts); 386 if (ret == TEST_SUCCESS) 387 sub_ts_succeeded++; 388 else if (ret == TEST_SKIPPED) 389 sub_ts_skipped++; 390 else 391 sub_ts_failed++; 392 sub_ts_total++; 393 394 suite->total += ts->total; 395 suite->succeeded += ts->succeeded; 396 suite->failed += ts->failed; 397 suite->skipped += ts->skipped; 398 suite->unsupported += ts->unsupported; 399 suite->executed += ts->executed; 400 } 401 402 /* Run test suite teardown */ 403 if (suite->teardown) 404 suite->teardown(); 405 406 goto suite_summary; 407 408 suite_summary: 409 printf(" + ------------------------------------------------------- +\n"); 410 printf(" + Test Suite Summary : %s\n", suite->suite_name); 411 printf(" + ------------------------------------------------------- +\n"); 412 413 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) 414 printf(" + %s : %d/%d passed, %d/%d skipped, " 415 "%d/%d failed, %d/%d unsupported\n", ts->suite_name, 416 ts->succeeded, ts->total, ts->skipped, ts->total, 417 ts->failed, ts->total, ts->unsupported, ts->total); 418 419 if (suite->unit_test_suites) { 420 printf(" + ------------------------------------------------------- +\n"); 421 printf(" + Sub Testsuites Total : %2d\n", sub_ts_total); 422 printf(" + Sub Testsuites Skipped : %2d\n", sub_ts_skipped); 423 printf(" + Sub Testsuites Passed : %2d\n", sub_ts_succeeded); 424 printf(" + Sub Testsuites Failed : %2d\n", sub_ts_failed); 425 printf(" + ------------------------------------------------------- +\n"); 426 } 427 428 printf(" + Tests Total : %2d\n", suite->total); 429 printf(" + Tests Skipped : %2d\n", suite->skipped); 430 printf(" + Tests Executed : %2d\n", suite->executed); 431 printf(" + Tests Unsupported: %2d\n", suite->unsupported); 432 printf(" + Tests Passed : %2d\n", suite->succeeded); 433 printf(" + Tests Failed : %2d\n", suite->failed); 434 printf(" + ------------------------------------------------------- +\n"); 435 436 last_test_result = suite->failed; 437 438 if (suite->failed) 439 return TEST_FAILED; 440 if (suite->total == suite->skipped) 441 return TEST_SKIPPED; 442 return TEST_SUCCESS; 443 } 444