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 const char *prgname; /* to be set to argv[0] */ 40 41 static const char *recursive_call; /* used in linux for MP and other tests */ 42 43 static int 44 no_action(void){ return 0; } 45 46 static int 47 do_recursive_call(void) 48 { 49 unsigned i; 50 struct { 51 const char *env_var; 52 int (*action_fn)(void); 53 } actions[] = { 54 { "run_secondary_instances", test_mp_secondary }, 55 #ifdef RTE_LIB_PDUMP 56 #ifdef RTE_NET_RING 57 { "run_pdump_server_tests", test_pdump }, 58 #endif 59 #endif 60 { "test_missing_c_flag", no_action }, 61 { "test_main_lcore_flag", no_action }, 62 { "test_invalid_n_flag", no_action }, 63 { "test_no_hpet_flag", no_action }, 64 { "test_allow_flag", no_action }, 65 { "test_invalid_b_flag", no_action }, 66 { "test_invalid_vdev_flag", no_action }, 67 { "test_invalid_r_flag", no_action }, 68 { "test_misc_flags", no_action }, 69 { "test_memory_flags", no_action }, 70 { "test_file_prefix", no_action }, 71 { "test_no_huge_flag", no_action }, 72 #ifdef RTE_LIB_TIMER 73 { "timer_secondary_spawn_wait", test_timer_secondary }, 74 #endif 75 }; 76 77 if (recursive_call == NULL) 78 return -1; 79 for (i = 0; i < RTE_DIM(actions); i++) { 80 if (strcmp(actions[i].env_var, recursive_call) == 0) 81 return (actions[i].action_fn)(); 82 } 83 printf("ERROR - missing action to take for %s\n", recursive_call); 84 return -1; 85 } 86 87 int last_test_result; 88 89 #define MAX_EXTRA_ARGS 32 90 91 int 92 main(int argc, char **argv) 93 { 94 #ifdef RTE_LIB_CMDLINE 95 struct cmdline *cl; 96 char *tests[argc]; /* store an array of tests to run */ 97 int test_count = 0; 98 int i; 99 #endif 100 char *extra_args; 101 int ret; 102 103 extra_args = getenv("DPDK_TEST_PARAMS"); 104 if (extra_args != NULL && strlen(extra_args) > 0) { 105 char **all_argv; 106 char *eargv[MAX_EXTRA_ARGS]; 107 int all_argc; 108 int eargc; 109 int i; 110 111 RTE_LOG(INFO, APP, "Using additional DPDK_TEST_PARAMS: '%s'\n", 112 extra_args); 113 eargc = rte_strsplit(extra_args, strlen(extra_args), 114 eargv, MAX_EXTRA_ARGS, ' '); 115 116 /* merge argc/argv and the environment args */ 117 all_argc = argc + eargc; 118 all_argv = malloc(sizeof(*all_argv) * (all_argc + 1)); 119 if (all_argv == NULL) { 120 ret = -1; 121 goto out; 122 } 123 124 for (i = 0; i < argc; i++) 125 all_argv[i] = argv[i]; 126 for (i = 0; i < eargc; i++) 127 all_argv[argc + i] = eargv[i]; 128 all_argv[all_argc] = NULL; 129 130 /* call eal_init with combined args */ 131 ret = rte_eal_init(all_argc, all_argv); 132 free(all_argv); 133 } else 134 ret = rte_eal_init(argc, argv); 135 if (ret < 0) { 136 ret = -1; 137 goto out; 138 } 139 140 argv += ret; 141 argc -= ret; 142 143 prgname = argv[0]; 144 145 #ifdef RTE_LIB_TIMER 146 ret = rte_timer_subsystem_init(); 147 if (ret < 0 && ret != -EALREADY) { 148 ret = -1; 149 goto out; 150 } 151 #endif 152 153 if (commands_init() < 0) { 154 ret = -1; 155 goto out; 156 } 157 158 recursive_call = getenv(RECURSIVE_ENV_VAR); 159 if (recursive_call != NULL) { 160 ret = do_recursive_call(); 161 goto out; 162 } 163 164 #ifdef RTE_LIBEAL_USE_HPET 165 if (rte_eal_hpet_init(1) < 0) 166 #endif 167 RTE_LOG(INFO, APP, 168 "HPET is not enabled, using TSC as default timer\n"); 169 170 171 #ifdef RTE_LIB_CMDLINE 172 char *dpdk_test = getenv("DPDK_TEST"); 173 174 if (dpdk_test && strlen(dpdk_test) == 0) 175 dpdk_test = NULL; 176 177 if (dpdk_test && !command_valid(dpdk_test)) { 178 RTE_LOG(WARNING, APP, "Invalid DPDK_TEST value '%s'\n", dpdk_test); 179 dpdk_test = NULL; 180 } 181 182 if (dpdk_test) 183 tests[test_count++] = dpdk_test; 184 for (i = 1; i < argc; i++) { 185 if (!command_valid(argv[i])) 186 RTE_LOG(WARNING, APP, "Invalid test requested: '%s'\n", argv[i]); 187 else 188 tests[test_count++] = argv[i]; 189 } 190 191 if (test_count > 0) { 192 char buf[1024]; 193 194 cl = cmdline_new(main_ctx, "RTE>>", 0, 1); 195 if (cl == NULL) { 196 ret = -1; 197 goto out; 198 } 199 200 for (i = 0; i < test_count; i++) { 201 snprintf(buf, sizeof(buf), "%s\n", tests[i]); 202 if (cmdline_in(cl, buf, strlen(buf)) < 0) { 203 printf("error on cmdline input\n"); 204 205 ret = -1; 206 } else 207 ret = last_test_result; 208 209 if (ret != 0) 210 break; 211 } 212 cmdline_free(cl); 213 goto out; 214 } else { 215 /* if no DPDK_TEST env variable, go interactive */ 216 cl = cmdline_stdin_new(main_ctx, "RTE>>"); 217 if (cl == NULL) { 218 ret = -1; 219 goto out; 220 } 221 222 cmdline_interact(cl); 223 cmdline_stdin_exit(cl); 224 cmdline_free(cl); 225 } 226 #endif 227 ret = 0; 228 229 out: 230 #ifdef RTE_LIB_TIMER 231 rte_timer_subsystem_finalize(); 232 #endif 233 rte_eal_cleanup(); 234 return ret; 235 } 236 237 238 int 239 unit_test_suite_runner(struct unit_test_suite *suite) 240 { 241 int test_success; 242 unsigned int total = 0, executed = 0, skipped = 0; 243 unsigned int succeeded = 0, failed = 0, unsupported = 0; 244 const char *status; 245 246 if (suite->suite_name) { 247 printf(" + ------------------------------------------------------- +\n"); 248 printf(" + Test Suite : %s\n", suite->suite_name); 249 } 250 251 if (suite->setup) { 252 test_success = suite->setup(); 253 if (test_success != 0) { 254 /* 255 * setup did not pass, so count all enabled tests and 256 * mark them as failed/skipped 257 */ 258 while (suite->unit_test_cases[total].testcase) { 259 if (!suite->unit_test_cases[total].enabled || 260 test_success == TEST_SKIPPED) 261 skipped++; 262 else 263 failed++; 264 total++; 265 } 266 goto suite_summary; 267 } 268 } 269 270 printf(" + ------------------------------------------------------- +\n"); 271 272 while (suite->unit_test_cases[total].testcase) { 273 if (!suite->unit_test_cases[total].enabled) { 274 skipped++; 275 total++; 276 continue; 277 } else { 278 executed++; 279 } 280 281 /* run test case setup */ 282 if (suite->unit_test_cases[total].setup) 283 test_success = suite->unit_test_cases[total].setup(); 284 else 285 test_success = TEST_SUCCESS; 286 287 if (test_success == TEST_SUCCESS) { 288 /* run the test case */ 289 test_success = suite->unit_test_cases[total].testcase(); 290 if (test_success == TEST_SUCCESS) 291 succeeded++; 292 else if (test_success == TEST_SKIPPED) 293 skipped++; 294 else if (test_success == -ENOTSUP) 295 unsupported++; 296 else 297 failed++; 298 } else if (test_success == -ENOTSUP) { 299 unsupported++; 300 } else { 301 failed++; 302 } 303 304 /* run the test case teardown */ 305 if (suite->unit_test_cases[total].teardown) 306 suite->unit_test_cases[total].teardown(); 307 308 if (test_success == TEST_SUCCESS) 309 status = "succeeded"; 310 else if (test_success == TEST_SKIPPED) 311 status = "skipped"; 312 else if (test_success == -ENOTSUP) 313 status = "unsupported"; 314 else 315 status = "failed"; 316 317 printf(" + TestCase [%2d] : %s %s\n", total, 318 suite->unit_test_cases[total].name, status); 319 320 total++; 321 } 322 323 /* Run test suite teardown */ 324 if (suite->teardown) 325 suite->teardown(); 326 327 goto suite_summary; 328 329 suite_summary: 330 printf(" + ------------------------------------------------------- +\n"); 331 printf(" + Test Suite Summary \n"); 332 printf(" + Tests Total : %2d\n", total); 333 printf(" + Tests Skipped : %2d\n", skipped); 334 printf(" + Tests Executed : %2d\n", executed); 335 printf(" + Tests Unsupported: %2d\n", unsupported); 336 printf(" + Tests Passed : %2d\n", succeeded); 337 printf(" + Tests Failed : %2d\n", failed); 338 printf(" + ------------------------------------------------------- +\n"); 339 340 last_test_result = failed; 341 342 if (failed) 343 return TEST_FAILED; 344 if (total == skipped) 345 return TEST_SKIPPED; 346 return TEST_SUCCESS; 347 } 348