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 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 { "run_secondary_instances", test_mp_secondary }, 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 { "timer_secondary_spawn_wait", test_timer_secondary }, 85 #endif 86 }; 87 88 if (recursive_call == NULL) 89 return -1; 90 for (i = 0; i < RTE_DIM(actions); i++) { 91 if (strcmp(actions[i].env_var, recursive_call) == 0) 92 return (actions[i].action_fn)(); 93 } 94 printf("ERROR - missing action to take for %s\n", recursive_call); 95 return -1; 96 } 97 98 int last_test_result; 99 100 #define MAX_EXTRA_ARGS 32 101 102 int 103 main(int argc, char **argv) 104 { 105 #ifdef RTE_LIB_CMDLINE 106 struct cmdline *cl; 107 char *tests[argc]; /* store an array of tests to run */ 108 int test_count = 0; 109 int i; 110 #endif 111 char *extra_args; 112 int ret; 113 114 extra_args = getenv("DPDK_TEST_PARAMS"); 115 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 RTE_LOG(INFO, APP, "Using additional DPDK_TEST_PARAMS: '%s'\n", 123 extra_args); 124 eargc = rte_strsplit(extra_args, strlen(extra_args), 125 eargv, MAX_EXTRA_ARGS, ' '); 126 127 /* merge argc/argv and the environment args */ 128 all_argc = argc + eargc; 129 all_argv = malloc(sizeof(*all_argv) * (all_argc + 1)); 130 if (all_argv == NULL) { 131 ret = -1; 132 goto out; 133 } 134 135 for (i = 0; i < argc; i++) 136 all_argv[i] = argv[i]; 137 for (i = 0; i < eargc; i++) 138 all_argv[argc + i] = eargv[i]; 139 all_argv[all_argc] = NULL; 140 141 /* call eal_init with combined args */ 142 ret = rte_eal_init(all_argc, all_argv); 143 free(all_argv); 144 } else 145 ret = rte_eal_init(argc, argv); 146 if (ret < 0) { 147 ret = -1; 148 goto out; 149 } 150 151 argv += ret; 152 argc -= ret; 153 154 prgname = argv[0]; 155 156 #ifdef RTE_LIB_TIMER 157 ret = rte_timer_subsystem_init(); 158 if (ret < 0 && ret != -EALREADY) { 159 ret = -1; 160 goto out; 161 } 162 #endif 163 164 if (commands_init() < 0) { 165 ret = -1; 166 goto out; 167 } 168 169 recursive_call = getenv(RECURSIVE_ENV_VAR); 170 if (recursive_call != NULL) { 171 ret = do_recursive_call(); 172 goto out; 173 } 174 175 #ifdef RTE_LIBEAL_USE_HPET 176 if (rte_eal_hpet_init(1) < 0) 177 #endif 178 RTE_LOG(INFO, APP, 179 "HPET is not enabled, using TSC as default timer\n"); 180 181 182 #ifdef RTE_LIB_CMDLINE 183 char *dpdk_test = getenv("DPDK_TEST"); 184 185 if (dpdk_test && strlen(dpdk_test) == 0) 186 dpdk_test = NULL; 187 188 if (dpdk_test && !command_valid(dpdk_test)) { 189 RTE_LOG(WARNING, APP, "Invalid DPDK_TEST value '%s'\n", dpdk_test); 190 dpdk_test = NULL; 191 } 192 193 if (dpdk_test) 194 tests[test_count++] = dpdk_test; 195 for (i = 1; i < argc; i++) { 196 if (!command_valid(argv[i])) 197 RTE_LOG(WARNING, APP, "Invalid test requested: '%s'\n", argv[i]); 198 else 199 tests[test_count++] = argv[i]; 200 } 201 202 if (test_count > 0) { 203 char buf[1024]; 204 205 cl = cmdline_new(main_ctx, "RTE>>", 0, 1); 206 if (cl == NULL) { 207 ret = -1; 208 goto out; 209 } 210 211 for (i = 0; i < test_count; i++) { 212 snprintf(buf, sizeof(buf), "%s\n", tests[i]); 213 if (cmdline_in(cl, buf, strlen(buf)) < 0) { 214 printf("error on cmdline input\n"); 215 216 ret = -1; 217 } else 218 ret = last_test_result; 219 220 if (ret != 0) 221 break; 222 } 223 cmdline_free(cl); 224 goto out; 225 } else { 226 /* if no DPDK_TEST env variable, go interactive */ 227 cl = cmdline_stdin_new(main_ctx, "RTE>>"); 228 if (cl == NULL) { 229 ret = -1; 230 goto out; 231 } 232 233 cmdline_interact(cl); 234 cmdline_stdin_exit(cl); 235 cmdline_free(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 test_success = tc.testcase(); 345 if (test_success == TEST_SUCCESS) 346 suite->succeeded++; 347 else if (test_success == TEST_SKIPPED) 348 suite->skipped++; 349 else if (test_success == -ENOTSUP) 350 suite->unsupported++; 351 else 352 suite->failed++; 353 } else if (test_success == -ENOTSUP) { 354 suite->unsupported++; 355 } else { 356 suite->failed++; 357 } 358 359 /* run the test case teardown */ 360 if (tc.teardown) 361 tc.teardown(); 362 363 if (test_success == TEST_SUCCESS) 364 status = "succeeded"; 365 else if (test_success == TEST_SKIPPED) 366 status = "skipped"; 367 else if (test_success == -ENOTSUP) 368 status = "unsupported"; 369 else 370 status = "failed"; 371 372 printf(" + TestCase [%2d] : %s %s\n", suite->total, 373 tc.name, status); 374 } 375 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) { 376 ret = unit_test_suite_runner(ts); 377 if (ret == TEST_SUCCESS) 378 sub_ts_succeeded++; 379 else if (ret == TEST_SKIPPED) 380 sub_ts_skipped++; 381 else 382 sub_ts_failed++; 383 sub_ts_total++; 384 385 suite->total += ts->total; 386 suite->succeeded += ts->succeeded; 387 suite->failed += ts->failed; 388 suite->skipped += ts->skipped; 389 suite->unsupported += ts->unsupported; 390 suite->executed += ts->executed; 391 } 392 393 /* Run test suite teardown */ 394 if (suite->teardown) 395 suite->teardown(); 396 397 goto suite_summary; 398 399 suite_summary: 400 printf(" + ------------------------------------------------------- +\n"); 401 printf(" + Test Suite Summary : %s\n", suite->suite_name); 402 printf(" + ------------------------------------------------------- +\n"); 403 404 FOR_EACH_SUITE_TESTSUITE(i, suite, ts) 405 printf(" + %s : %d/%d passed, %d/%d skipped, " 406 "%d/%d failed, %d/%d unsupported\n", ts->suite_name, 407 ts->succeeded, ts->total, ts->skipped, ts->total, 408 ts->failed, ts->total, ts->unsupported, ts->total); 409 410 if (suite->unit_test_suites) { 411 printf(" + ------------------------------------------------------- +\n"); 412 printf(" + Sub Testsuites Total : %2d\n", sub_ts_total); 413 printf(" + Sub Testsuites Skipped : %2d\n", sub_ts_skipped); 414 printf(" + Sub Testsuites Passed : %2d\n", sub_ts_succeeded); 415 printf(" + Sub Testsuites Failed : %2d\n", sub_ts_failed); 416 printf(" + ------------------------------------------------------- +\n"); 417 } 418 419 printf(" + Tests Total : %2d\n", suite->total); 420 printf(" + Tests Skipped : %2d\n", suite->skipped); 421 printf(" + Tests Executed : %2d\n", suite->executed); 422 printf(" + Tests Unsupported: %2d\n", suite->unsupported); 423 printf(" + Tests Passed : %2d\n", suite->succeeded); 424 printf(" + Tests Failed : %2d\n", suite->failed); 425 printf(" + ------------------------------------------------------- +\n"); 426 427 last_test_result = suite->failed; 428 429 if (suite->failed) 430 return TEST_FAILED; 431 if (suite->total == suite->skipped) 432 return TEST_SKIPPED; 433 return TEST_SUCCESS; 434 } 435