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 #endif 97 char *extra_args; 98 int ret; 99 100 extra_args = getenv("DPDK_TEST_PARAMS"); 101 if (extra_args != NULL && strlen(extra_args) > 0) { 102 char **all_argv; 103 char *eargv[MAX_EXTRA_ARGS]; 104 int all_argc; 105 int eargc; 106 int i; 107 108 RTE_LOG(INFO, APP, "Using additional DPDK_TEST_PARAMS: '%s'\n", 109 extra_args); 110 eargc = rte_strsplit(extra_args, strlen(extra_args), 111 eargv, MAX_EXTRA_ARGS, ' '); 112 113 /* merge argc/argv and the environment args */ 114 all_argc = argc + eargc; 115 all_argv = malloc(sizeof(*all_argv) * (all_argc + 1)); 116 if (all_argv == NULL) { 117 ret = -1; 118 goto out; 119 } 120 121 for (i = 0; i < argc; i++) 122 all_argv[i] = argv[i]; 123 for (i = 0; i < eargc; i++) 124 all_argv[argc + i] = eargv[i]; 125 all_argv[all_argc] = NULL; 126 127 /* call eal_init with combined args */ 128 ret = rte_eal_init(all_argc, all_argv); 129 free(all_argv); 130 } else 131 ret = rte_eal_init(argc, argv); 132 if (ret < 0) { 133 ret = -1; 134 goto out; 135 } 136 137 argv += ret; 138 139 prgname = argv[0]; 140 141 #ifdef RTE_LIB_TIMER 142 ret = rte_timer_subsystem_init(); 143 if (ret < 0 && ret != -EALREADY) { 144 ret = -1; 145 goto out; 146 } 147 #endif 148 149 if (commands_init() < 0) { 150 ret = -1; 151 goto out; 152 } 153 154 recursive_call = getenv(RECURSIVE_ENV_VAR); 155 if (recursive_call != NULL) { 156 ret = do_recursive_call(); 157 goto out; 158 } 159 160 #ifdef RTE_LIBEAL_USE_HPET 161 if (rte_eal_hpet_init(1) < 0) 162 #endif 163 RTE_LOG(INFO, APP, 164 "HPET is not enabled, using TSC as default timer\n"); 165 166 167 #ifdef RTE_LIB_CMDLINE 168 char *dpdk_test = getenv("DPDK_TEST"); 169 if (dpdk_test && strlen(dpdk_test)) { 170 char buf[1024]; 171 172 cl = cmdline_new(main_ctx, "RTE>>", 0, 1); 173 if (cl == NULL) { 174 ret = -1; 175 goto out; 176 } 177 178 snprintf(buf, sizeof(buf), "%s\n", dpdk_test); 179 if (cmdline_in(cl, buf, strlen(buf)) < 0) { 180 printf("error on cmdline input\n"); 181 182 ret = -1; 183 } else { 184 ret = last_test_result; 185 } 186 cmdline_free(cl); 187 goto out; 188 } else { 189 /* if no DPDK_TEST env variable, go interactive */ 190 cl = cmdline_stdin_new(main_ctx, "RTE>>"); 191 if (cl == NULL) { 192 ret = -1; 193 goto out; 194 } 195 196 cmdline_interact(cl); 197 cmdline_stdin_exit(cl); 198 cmdline_free(cl); 199 } 200 #endif 201 ret = 0; 202 203 out: 204 #ifdef RTE_LIB_TIMER 205 rte_timer_subsystem_finalize(); 206 #endif 207 rte_eal_cleanup(); 208 return ret; 209 } 210 211 212 int 213 unit_test_suite_runner(struct unit_test_suite *suite) 214 { 215 int test_success; 216 unsigned int total = 0, executed = 0, skipped = 0; 217 unsigned int succeeded = 0, failed = 0, unsupported = 0; 218 const char *status; 219 220 if (suite->suite_name) { 221 printf(" + ------------------------------------------------------- +\n"); 222 printf(" + Test Suite : %s\n", suite->suite_name); 223 } 224 225 if (suite->setup) { 226 test_success = suite->setup(); 227 if (test_success != 0) { 228 /* 229 * setup did not pass, so count all enabled tests and 230 * mark them as failed/skipped 231 */ 232 while (suite->unit_test_cases[total].testcase) { 233 if (!suite->unit_test_cases[total].enabled || 234 test_success == TEST_SKIPPED) 235 skipped++; 236 else 237 failed++; 238 total++; 239 } 240 goto suite_summary; 241 } 242 } 243 244 printf(" + ------------------------------------------------------- +\n"); 245 246 while (suite->unit_test_cases[total].testcase) { 247 if (!suite->unit_test_cases[total].enabled) { 248 skipped++; 249 total++; 250 continue; 251 } else { 252 executed++; 253 } 254 255 /* run test case setup */ 256 if (suite->unit_test_cases[total].setup) 257 test_success = suite->unit_test_cases[total].setup(); 258 else 259 test_success = TEST_SUCCESS; 260 261 if (test_success == TEST_SUCCESS) { 262 /* run the test case */ 263 test_success = suite->unit_test_cases[total].testcase(); 264 if (test_success == TEST_SUCCESS) 265 succeeded++; 266 else if (test_success == TEST_SKIPPED) 267 skipped++; 268 else if (test_success == -ENOTSUP) 269 unsupported++; 270 else 271 failed++; 272 } else if (test_success == -ENOTSUP) { 273 unsupported++; 274 } else { 275 failed++; 276 } 277 278 /* run the test case teardown */ 279 if (suite->unit_test_cases[total].teardown) 280 suite->unit_test_cases[total].teardown(); 281 282 if (test_success == TEST_SUCCESS) 283 status = "succeeded"; 284 else if (test_success == TEST_SKIPPED) 285 status = "skipped"; 286 else if (test_success == -ENOTSUP) 287 status = "unsupported"; 288 else 289 status = "failed"; 290 291 printf(" + TestCase [%2d] : %s %s\n", total, 292 suite->unit_test_cases[total].name, status); 293 294 total++; 295 } 296 297 /* Run test suite teardown */ 298 if (suite->teardown) 299 suite->teardown(); 300 301 goto suite_summary; 302 303 suite_summary: 304 printf(" + ------------------------------------------------------- +\n"); 305 printf(" + Test Suite Summary \n"); 306 printf(" + Tests Total : %2d\n", total); 307 printf(" + Tests Skipped : %2d\n", skipped); 308 printf(" + Tests Executed : %2d\n", executed); 309 printf(" + Tests Unsupported: %2d\n", unsupported); 310 printf(" + Tests Passed : %2d\n", succeeded); 311 printf(" + Tests Failed : %2d\n", failed); 312 printf(" + ------------------------------------------------------- +\n"); 313 314 last_test_result = failed; 315 316 if (failed) 317 return TEST_FAILED; 318 if (total == skipped) 319 return TEST_SKIPPED; 320 return TEST_SUCCESS; 321 } 322