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 #define SMALL_BUF 8 117 118 /* test invalid parameters */ 119 int 120 test_parse_string_invalid_param(void) 121 { 122 cmdline_parse_token_string_t token; 123 int result; 124 char buf[CMDLINE_TEST_BUFSIZE]; 125 126 memset(&token, 0, sizeof(token)); 127 128 snprintf(buf, sizeof(buf), "buffer"); 129 130 /* test null token */ 131 if (cmdline_get_help_string( 132 NULL, buf, 0) != -1) { 133 printf("Error: function accepted null token!\n"); 134 return -1; 135 } 136 if (cmdline_complete_get_elt_string( 137 NULL, 0, buf, 0) != -1) { 138 printf("Error: function accepted null token!\n"); 139 return -1; 140 } 141 if (cmdline_complete_get_nb_string(NULL) != -1) { 142 printf("Error: function accepted null token!\n"); 143 return -1; 144 } 145 if (cmdline_parse_string(NULL, buf, NULL, 0) != -1) { 146 printf("Error: function accepted null token!\n"); 147 return -1; 148 } 149 /* test null buffer */ 150 if (cmdline_complete_get_elt_string( 151 (cmdline_parse_token_hdr_t*)&token, 0, NULL, 0) != -1) { 152 printf("Error: function accepted null buffer!\n"); 153 return -1; 154 } 155 if (cmdline_parse_string( 156 (cmdline_parse_token_hdr_t*)&token, NULL, 157 (void*)&result, sizeof(result)) != -1) { 158 printf("Error: function accepted null buffer!\n"); 159 return -1; 160 } 161 if (cmdline_get_help_string( 162 (cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) { 163 printf("Error: function accepted null buffer!\n"); 164 return -1; 165 } 166 /* test null result */ 167 if (cmdline_parse_string( 168 (cmdline_parse_token_hdr_t*)&token, buf, NULL, 0) == -1) { 169 printf("Error: function rejected null result!\n"); 170 return -1; 171 } 172 /* test negative index */ 173 if (cmdline_complete_get_elt_string( 174 (cmdline_parse_token_hdr_t*)&token, -1, buf, 0) != -1) { 175 printf("Error: function accepted negative index!\n"); 176 return -1; 177 } 178 return 0; 179 } 180 181 /* test valid parameters but invalid data */ 182 int 183 test_parse_string_invalid_data(void) 184 { 185 cmdline_parse_token_string_t token; 186 cmdline_parse_token_string_t help_token; 187 char buf[CMDLINE_TEST_BUFSIZE]; 188 char help_str[CMDLINE_TEST_BUFSIZE]; 189 char small_buf[SMALL_BUF]; 190 unsigned i; 191 192 /* test parsing invalid strings */ 193 for (i = 0; i < RTE_DIM(string_invalid_strs); i++) { 194 memset(&token, 0, sizeof(token)); 195 memset(buf, 0, sizeof(buf)); 196 197 /* prepare test token data */ 198 token.string_data.str = string_invalid_strs[i].fixed_str; 199 200 if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token, 201 string_invalid_strs[i].str, (void*)buf, 202 sizeof(buf)) != -1) { 203 memset(help_str, 0, sizeof(help_str)); 204 memset(&help_token, 0, sizeof(help_token)); 205 206 help_token.string_data.str = string_invalid_strs[i].fixed_str; 207 208 /* get parse type so we can give a good error message */ 209 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 210 sizeof(help_str)); 211 212 printf("Error: parsing %s as %s succeeded!\n", 213 string_invalid_strs[i].str, help_str); 214 return -1; 215 } 216 } 217 218 /* misc tests (big comments signify test cases) */ 219 memset(&token, 0, sizeof(token)); 220 memset(small_buf, 0, sizeof(small_buf)); 221 222 /* 223 * try to get element from a null token 224 */ 225 token.string_data.str = NULL; 226 if (cmdline_complete_get_elt_string( 227 (cmdline_parse_token_hdr_t*)&token, 1, 228 buf, sizeof(buf)) != -1) { 229 printf("Error: getting token from null token string!\n"); 230 return -1; 231 } 232 233 /* 234 * try to get element into a buffer that is too small 235 */ 236 token.string_data.str = "too_small_buffer"; 237 if (cmdline_complete_get_elt_string( 238 (cmdline_parse_token_hdr_t*)&token, 0, 239 small_buf, sizeof(small_buf)) != -1) { 240 printf("Error: writing token into too small a buffer succeeded!\n"); 241 return -1; 242 } 243 244 /* 245 * get help string written into a buffer smaller than help string 246 * truncation should occur 247 */ 248 token.string_data.str = NULL; 249 if (cmdline_get_help_string( 250 (cmdline_parse_token_hdr_t*)&token, 251 small_buf, sizeof(small_buf)) == -1) { 252 printf("Error: writing help string into too small a buffer failed!\n"); 253 return -1; 254 } 255 /* get help string for "any string" so we can compare it with small_buf */ 256 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 257 sizeof(help_str)); 258 if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) { 259 printf("Error: help string mismatch!\n"); 260 return -1; 261 } 262 /* check null terminator */ 263 if (small_buf[sizeof(small_buf) - 1] != '\0') { 264 printf("Error: small buffer doesn't have a null terminator!\n"); 265 return -1; 266 } 267 268 /* 269 * try to count tokens in a null token 270 */ 271 token.string_data.str = NULL; 272 if (cmdline_complete_get_nb_string( 273 (cmdline_parse_token_hdr_t*)&token) != 0) { 274 printf("Error: getting token count from null token succeeded!\n"); 275 return -1; 276 } 277 278 return 0; 279 } 280 281 /* test valid parameters and data */ 282 int 283 test_parse_string_valid(void) 284 { 285 cmdline_parse_token_string_t token; 286 cmdline_parse_token_string_t help_token; 287 char buf[CMDLINE_TEST_BUFSIZE]; 288 char help_str[CMDLINE_TEST_BUFSIZE]; 289 unsigned i; 290 291 /* test parsing strings */ 292 for (i = 0; i < RTE_DIM(string_parse_strs); i++) { 293 memset(&token, 0, sizeof(token)); 294 memset(buf, 0, sizeof(buf)); 295 296 token.string_data.str = string_parse_strs[i].fixed_str; 297 298 if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token, 299 string_parse_strs[i].str, (void*)buf, 300 sizeof(buf)) < 0) { 301 302 /* clean help data */ 303 memset(&help_token, 0, sizeof(help_token)); 304 memset(help_str, 0, sizeof(help_str)); 305 306 /* prepare help token */ 307 help_token.string_data.str = string_parse_strs[i].fixed_str; 308 309 /* get help string so that we get an informative error message */ 310 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 311 sizeof(help_str)); 312 313 printf("Error: parsing %s as %s failed!\n", 314 string_parse_strs[i].str, help_str); 315 return -1; 316 } 317 if (strcmp(buf, string_parse_strs[i].result) != 0) { 318 printf("Error: result mismatch!\n"); 319 return -1; 320 } 321 } 322 323 /* get number of string tokens and verify it's correct */ 324 for (i = 0; i < RTE_DIM(string_nb_strs); i++) { 325 memset(&token, 0, sizeof(token)); 326 327 token.string_data.str = string_nb_strs[i].str; 328 329 if (cmdline_complete_get_nb_string( 330 (cmdline_parse_token_hdr_t*)&token) < 331 string_nb_strs[i].nb_strs) { 332 printf("Error: strings count mismatch!\n"); 333 return -1; 334 } 335 } 336 337 /* get token at specified position and verify it's correct */ 338 for (i = 0; i < RTE_DIM(string_elt_strs); i++) { 339 memset(&token, 0, sizeof(token)); 340 memset(buf, 0, sizeof(buf)); 341 342 token.string_data.str = string_elt_strs[i].str; 343 344 if (cmdline_complete_get_elt_string( 345 (cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx, 346 buf, sizeof(buf)) < 0) { 347 printf("Error: getting string element failed!\n"); 348 return -1; 349 } 350 if (strncmp(buf, string_elt_strs[i].result, 351 sizeof(buf)) != 0) { 352 printf("Error: result mismatch!\n"); 353 return -1; 354 } 355 } 356 357 /* cover all cases with help strings */ 358 for (i = 0; i < RTE_DIM(string_help_strs); i++) { 359 memset(&help_token, 0, sizeof(help_token)); 360 memset(help_str, 0, sizeof(help_str)); 361 help_token.string_data.str = string_help_strs[i]; 362 if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token, 363 help_str, sizeof(help_str)) < 0) { 364 printf("Error: help operation failed!\n"); 365 return -1; 366 } 367 } 368 369 return 0; 370 } 371