1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <inttypes.h> 8 9 #include <rte_common.h> 10 #include <rte_string_fns.h> 11 12 #include <cmdline_parse.h> 13 #include <cmdline_parse_string.h> 14 15 #include "test_cmdline.h" 16 17 /* structures needed to run tests */ 18 19 struct string_elt_str { 20 const char * str; /* parsed string */ 21 const char * result; /* expected string */ 22 int idx; /* position at which result is expected to be */ 23 }; 24 25 struct string_elt_str string_elt_strs[] = { 26 {"one#two#three", "three", 2}, 27 {"one#two with spaces#three", "three", 2}, 28 {"one#two\twith\ttabs#three", "three", 2}, 29 {"one#two\rwith\rreturns#three", "three", 2}, 30 {"one#two\nwith\nnewlines#three", "three", 2}, 31 {"one#two#three", "one", 0}, 32 {"one#two#three", "two", 1}, 33 {"one#two\0three", "two", 1}, 34 {"one#two with spaces#three", "two with spaces", 1}, 35 {"one#two\twith\ttabs#three", "two\twith\ttabs", 1}, 36 {"one#two\rwith\rreturns#three", "two\rwith\rreturns", 1}, 37 {"one#two\nwith\nnewlines#three", "two\nwith\nnewlines", 1}, 38 }; 39 40 #if (CMDLINE_TEST_BUFSIZE < STR_TOKEN_SIZE) \ 41 || (CMDLINE_TEST_BUFSIZE < STR_MULTI_TOKEN_SIZE) 42 #undef CMDLINE_TEST_BUFSIZE 43 #define CMDLINE_TEST_BUFSIZE RTE_MAX(STR_TOKEN_SIZE, STR_MULTI_TOKEN_SIZE) 44 #endif 45 46 struct string_nb_str { 47 const char * str; /* parsed string */ 48 int nb_strs; /* expected number of strings in str */ 49 }; 50 51 struct string_nb_str string_nb_strs[] = { 52 {"one#two#three", 3}, 53 {"one", 1}, 54 {"one# \t two \r # three \n #four", 4}, 55 }; 56 57 58 59 struct string_parse_str { 60 const char * str; /* parsed string */ 61 const char * fixed_str; /* parsing mode (any, fixed or multi) */ 62 const char * result; /* expected result */ 63 }; 64 65 struct string_parse_str string_parse_strs[] = { 66 {"one", NULL, "one"}, /* any string */ 67 {"two", "one#two#three", "two"}, /* multiple choice string */ 68 {"three", "three", "three"}, /* fixed string */ 69 {"three", "one#two with\rgarbage\tcharacters\n#three", "three"}, 70 {"two with\rgarbage\tcharacters\n", 71 "one#two with\rgarbage\tcharacters\n#three", 72 "two with\rgarbage\tcharacters\n"}, 73 {"one two", "one", "one"}, /* fixed string */ 74 {"one two", TOKEN_STRING_MULTI, "one two"}, /* multi string */ 75 {"one two", NULL, "one"}, /* any string */ 76 {"one two #three", TOKEN_STRING_MULTI, "one two "}, 77 /* multi string with comment */ 78 }; 79 80 81 82 struct string_invalid_str { 83 const char * str; /* parsed string */ 84 const char * fixed_str; /* parsing mode (any, fixed or multi) */ 85 }; 86 87 struct string_invalid_str string_invalid_strs[] = { 88 {"invalid", "one"}, /* fixed string */ 89 {"invalid", "one#two#three"}, /* multiple choice string */ 90 {"invalid", "invalidone"}, /* string that starts the same */ 91 {"invalidone", "invalid"}, /* string that starts the same */ 92 {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 93 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 94 "toolong!!!", NULL }, 95 {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 96 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 97 "toolong!!!", "fixed" }, 98 {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 99 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 100 "toolong!!!", "multi#choice#string" }, 101 {"invalid", 102 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 103 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 104 "toolong!!!" }, 105 {"", "invalid"} 106 }; 107 108 109 110 const char * string_help_strs[] = { 111 NULL, 112 "fixed_str", 113 "multi#str", 114 }; 115 116 117 118 #define STRING_PARSE_STRS_SIZE \ 119 (sizeof(string_parse_strs) / sizeof(string_parse_strs[0])) 120 #define STRING_HELP_STRS_SIZE \ 121 (sizeof(string_help_strs) / sizeof(string_help_strs[0])) 122 #define STRING_ELT_STRS_SIZE \ 123 (sizeof(string_elt_strs) / sizeof(string_elt_strs[0])) 124 #define STRING_NB_STRS_SIZE \ 125 (sizeof(string_nb_strs) / sizeof(string_nb_strs[0])) 126 #define STRING_INVALID_STRS_SIZE \ 127 (sizeof(string_invalid_strs) / sizeof(string_invalid_strs[0])) 128 129 #define SMALL_BUF 8 130 131 /* test invalid parameters */ 132 int 133 test_parse_string_invalid_param(void) 134 { 135 cmdline_parse_token_string_t token; 136 int result; 137 char buf[CMDLINE_TEST_BUFSIZE]; 138 139 memset(&token, 0, sizeof(token)); 140 141 snprintf(buf, sizeof(buf), "buffer"); 142 143 /* test null token */ 144 if (cmdline_get_help_string( 145 NULL, buf, 0) != -1) { 146 printf("Error: function accepted null token!\n"); 147 return -1; 148 } 149 if (cmdline_complete_get_elt_string( 150 NULL, 0, buf, 0) != -1) { 151 printf("Error: function accepted null token!\n"); 152 return -1; 153 } 154 if (cmdline_complete_get_nb_string(NULL) != -1) { 155 printf("Error: function accepted null token!\n"); 156 return -1; 157 } 158 if (cmdline_parse_string(NULL, buf, NULL, 0) != -1) { 159 printf("Error: function accepted null token!\n"); 160 return -1; 161 } 162 /* test null buffer */ 163 if (cmdline_complete_get_elt_string( 164 (cmdline_parse_token_hdr_t*)&token, 0, NULL, 0) != -1) { 165 printf("Error: function accepted null buffer!\n"); 166 return -1; 167 } 168 if (cmdline_parse_string( 169 (cmdline_parse_token_hdr_t*)&token, NULL, 170 (void*)&result, sizeof(result)) != -1) { 171 printf("Error: function accepted null buffer!\n"); 172 return -1; 173 } 174 if (cmdline_get_help_string( 175 (cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) { 176 printf("Error: function accepted null buffer!\n"); 177 return -1; 178 } 179 /* test null result */ 180 if (cmdline_parse_string( 181 (cmdline_parse_token_hdr_t*)&token, buf, NULL, 0) == -1) { 182 printf("Error: function rejected null result!\n"); 183 return -1; 184 } 185 /* test negative index */ 186 if (cmdline_complete_get_elt_string( 187 (cmdline_parse_token_hdr_t*)&token, -1, buf, 0) != -1) { 188 printf("Error: function accepted negative index!\n"); 189 return -1; 190 } 191 return 0; 192 } 193 194 /* test valid parameters but invalid data */ 195 int 196 test_parse_string_invalid_data(void) 197 { 198 cmdline_parse_token_string_t token; 199 cmdline_parse_token_string_t help_token; 200 char buf[CMDLINE_TEST_BUFSIZE]; 201 char help_str[CMDLINE_TEST_BUFSIZE]; 202 char small_buf[SMALL_BUF]; 203 unsigned i; 204 205 /* test parsing invalid strings */ 206 for (i = 0; i < STRING_INVALID_STRS_SIZE; i++) { 207 memset(&token, 0, sizeof(token)); 208 memset(buf, 0, sizeof(buf)); 209 210 /* prepare test token data */ 211 token.string_data.str = string_invalid_strs[i].fixed_str; 212 213 if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token, 214 string_invalid_strs[i].str, (void*)buf, 215 sizeof(buf)) != -1) { 216 memset(help_str, 0, sizeof(help_str)); 217 memset(&help_token, 0, sizeof(help_token)); 218 219 help_token.string_data.str = string_invalid_strs[i].fixed_str; 220 221 /* get parse type so we can give a good error message */ 222 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 223 sizeof(help_str)); 224 225 printf("Error: parsing %s as %s succeeded!\n", 226 string_invalid_strs[i].str, help_str); 227 return -1; 228 } 229 } 230 231 /* misc tests (big comments signify test cases) */ 232 memset(&token, 0, sizeof(token)); 233 memset(small_buf, 0, sizeof(small_buf)); 234 235 /* 236 * try to get element from a null token 237 */ 238 token.string_data.str = NULL; 239 if (cmdline_complete_get_elt_string( 240 (cmdline_parse_token_hdr_t*)&token, 1, 241 buf, sizeof(buf)) != -1) { 242 printf("Error: getting token from null token string!\n"); 243 return -1; 244 } 245 246 /* 247 * try to get element into a buffer that is too small 248 */ 249 token.string_data.str = "too_small_buffer"; 250 if (cmdline_complete_get_elt_string( 251 (cmdline_parse_token_hdr_t*)&token, 0, 252 small_buf, sizeof(small_buf)) != -1) { 253 printf("Error: writing token into too small a buffer succeeded!\n"); 254 return -1; 255 } 256 257 /* 258 * get help string written into a buffer smaller than help string 259 * truncation should occur 260 */ 261 token.string_data.str = NULL; 262 if (cmdline_get_help_string( 263 (cmdline_parse_token_hdr_t*)&token, 264 small_buf, sizeof(small_buf)) == -1) { 265 printf("Error: writing help string into too small a buffer failed!\n"); 266 return -1; 267 } 268 /* get help string for "any string" so we can compare it with small_buf */ 269 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 270 sizeof(help_str)); 271 if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) { 272 printf("Error: help string mismatch!\n"); 273 return -1; 274 } 275 /* check null terminator */ 276 if (small_buf[sizeof(small_buf) - 1] != '\0') { 277 printf("Error: small buffer doesn't have a null terminator!\n"); 278 return -1; 279 } 280 281 /* 282 * try to count tokens in a null token 283 */ 284 token.string_data.str = NULL; 285 if (cmdline_complete_get_nb_string( 286 (cmdline_parse_token_hdr_t*)&token) != 0) { 287 printf("Error: getting token count from null token succeeded!\n"); 288 return -1; 289 } 290 291 return 0; 292 } 293 294 /* test valid parameters and data */ 295 int 296 test_parse_string_valid(void) 297 { 298 cmdline_parse_token_string_t token; 299 cmdline_parse_token_string_t help_token; 300 char buf[CMDLINE_TEST_BUFSIZE]; 301 char help_str[CMDLINE_TEST_BUFSIZE]; 302 unsigned i; 303 304 /* test parsing strings */ 305 for (i = 0; i < STRING_PARSE_STRS_SIZE; i++) { 306 memset(&token, 0, sizeof(token)); 307 memset(buf, 0, sizeof(buf)); 308 309 token.string_data.str = string_parse_strs[i].fixed_str; 310 311 if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token, 312 string_parse_strs[i].str, (void*)buf, 313 sizeof(buf)) < 0) { 314 315 /* clean help data */ 316 memset(&help_token, 0, sizeof(help_token)); 317 memset(help_str, 0, sizeof(help_str)); 318 319 /* prepare help token */ 320 help_token.string_data.str = string_parse_strs[i].fixed_str; 321 322 /* get help string so that we get an informative error message */ 323 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 324 sizeof(help_str)); 325 326 printf("Error: parsing %s as %s failed!\n", 327 string_parse_strs[i].str, help_str); 328 return -1; 329 } 330 if (strcmp(buf, string_parse_strs[i].result) != 0) { 331 printf("Error: result mismatch!\n"); 332 return -1; 333 } 334 } 335 336 /* get number of string tokens and verify it's correct */ 337 for (i = 0; i < STRING_NB_STRS_SIZE; i++) { 338 memset(&token, 0, sizeof(token)); 339 340 token.string_data.str = string_nb_strs[i].str; 341 342 if (cmdline_complete_get_nb_string( 343 (cmdline_parse_token_hdr_t*)&token) < 344 string_nb_strs[i].nb_strs) { 345 printf("Error: strings count mismatch!\n"); 346 return -1; 347 } 348 } 349 350 /* get token at specified position and verify it's correct */ 351 for (i = 0; i < STRING_ELT_STRS_SIZE; i++) { 352 memset(&token, 0, sizeof(token)); 353 memset(buf, 0, sizeof(buf)); 354 355 token.string_data.str = string_elt_strs[i].str; 356 357 if (cmdline_complete_get_elt_string( 358 (cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx, 359 buf, sizeof(buf)) < 0) { 360 printf("Error: getting string element failed!\n"); 361 return -1; 362 } 363 if (strncmp(buf, string_elt_strs[i].result, 364 sizeof(buf)) != 0) { 365 printf("Error: result mismatch!\n"); 366 return -1; 367 } 368 } 369 370 /* cover all cases with help strings */ 371 for (i = 0; i < STRING_HELP_STRS_SIZE; i++) { 372 memset(&help_token, 0, sizeof(help_token)); 373 memset(help_str, 0, sizeof(help_str)); 374 help_token.string_data.str = string_help_strs[i]; 375 if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token, 376 help_str, sizeof(help_str)) < 0) { 377 printf("Error: help operation failed!\n"); 378 return -1; 379 } 380 } 381 382 return 0; 383 } 384