1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <inttypes.h> 37 38 #include <rte_common.h> 39 #include <rte_string_fns.h> 40 41 #include <cmdline_parse.h> 42 #include <cmdline_parse_string.h> 43 44 #include "test_cmdline.h" 45 46 /* structures needed to run tests */ 47 48 struct string_elt_str { 49 const char * str; /* parsed string */ 50 const char * result; /* expected string */ 51 int idx; /* position at which result is expected to be */ 52 }; 53 54 struct string_elt_str string_elt_strs[] = { 55 {"one#two#three", "three", 2}, 56 {"one#two with spaces#three", "three", 2}, 57 {"one#two\twith\ttabs#three", "three", 2}, 58 {"one#two\rwith\rreturns#three", "three", 2}, 59 {"one#two\nwith\nnewlines#three", "three", 2}, 60 {"one#two#three", "one", 0}, 61 {"one#two#three", "two", 1}, 62 {"one#two\0three", "two", 1}, 63 {"one#two with spaces#three", "two with spaces", 1}, 64 {"one#two\twith\ttabs#three", "two\twith\ttabs", 1}, 65 {"one#two\rwith\rreturns#three", "two\rwith\rreturns", 1}, 66 {"one#two\nwith\nnewlines#three", "two\nwith\nnewlines", 1}, 67 }; 68 69 #if (CMDLINE_TEST_BUFSIZE < STR_TOKEN_SIZE) \ 70 || (CMDLINE_TEST_BUFSIZE < STR_MULTI_TOKEN_SIZE) 71 #undef CMDLINE_TEST_BUFSIZE 72 #define CMDLINE_TEST_BUFSIZE RTE_MAX(STR_TOKEN_SIZE, STR_MULTI_TOKEN_SIZE) 73 #endif 74 75 struct string_nb_str { 76 const char * str; /* parsed string */ 77 int nb_strs; /* expected number of strings in str */ 78 }; 79 80 struct string_nb_str string_nb_strs[] = { 81 {"one#two#three", 3}, 82 {"one", 1}, 83 {"one# \t two \r # three \n #four", 4}, 84 }; 85 86 87 88 struct string_parse_str { 89 const char * str; /* parsed string */ 90 const char * fixed_str; /* parsing mode (any, fixed or multi) */ 91 const char * result; /* expected result */ 92 }; 93 94 struct string_parse_str string_parse_strs[] = { 95 {"one", NULL, "one"}, /* any string */ 96 {"two", "one#two#three", "two"}, /* multiple choice string */ 97 {"three", "three", "three"}, /* fixed string */ 98 {"three", "one#two with\rgarbage\tcharacters\n#three", "three"}, 99 {"two with\rgarbage\tcharacters\n", 100 "one#two with\rgarbage\tcharacters\n#three", 101 "two with\rgarbage\tcharacters\n"}, 102 {"one two", "one", "one"}, /* fixed string */ 103 {"one two", TOKEN_STRING_MULTI, "one two"}, /* multi string */ 104 {"one two", NULL, "one"}, /* any string */ 105 {"one two #three", TOKEN_STRING_MULTI, "one two "}, 106 /* multi string with comment */ 107 }; 108 109 110 111 struct string_invalid_str { 112 const char * str; /* parsed string */ 113 const char * fixed_str; /* parsing mode (any, fixed or multi) */ 114 }; 115 116 struct string_invalid_str string_invalid_strs[] = { 117 {"invalid", "one"}, /* fixed string */ 118 {"invalid", "one#two#three"}, /* multiple choice string */ 119 {"invalid", "invalidone"}, /* string that starts the same */ 120 {"invalidone", "invalid"}, /* string that starts the same */ 121 {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 122 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 123 "toolong!!!", NULL }, 124 {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 125 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 126 "toolong!!!", "fixed" }, 127 {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 128 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 129 "toolong!!!", "multi#choice#string" }, 130 {"invalid", 131 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 132 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" 133 "toolong!!!" }, 134 {"", "invalid"} 135 }; 136 137 138 139 const char * string_help_strs[] = { 140 NULL, 141 "fixed_str", 142 "multi#str", 143 }; 144 145 146 147 #define STRING_PARSE_STRS_SIZE \ 148 (sizeof(string_parse_strs) / sizeof(string_parse_strs[0])) 149 #define STRING_HELP_STRS_SIZE \ 150 (sizeof(string_help_strs) / sizeof(string_help_strs[0])) 151 #define STRING_ELT_STRS_SIZE \ 152 (sizeof(string_elt_strs) / sizeof(string_elt_strs[0])) 153 #define STRING_NB_STRS_SIZE \ 154 (sizeof(string_nb_strs) / sizeof(string_nb_strs[0])) 155 #define STRING_INVALID_STRS_SIZE \ 156 (sizeof(string_invalid_strs) / sizeof(string_invalid_strs[0])) 157 158 #define SMALL_BUF 8 159 160 /* test invalid parameters */ 161 int 162 test_parse_string_invalid_param(void) 163 { 164 cmdline_parse_token_string_t token; 165 int result; 166 char buf[CMDLINE_TEST_BUFSIZE]; 167 168 memset(&token, 0, sizeof(token)); 169 170 snprintf(buf, sizeof(buf), "buffer"); 171 172 /* test null token */ 173 if (cmdline_get_help_string( 174 NULL, buf, 0) != -1) { 175 printf("Error: function accepted null token!\n"); 176 return -1; 177 } 178 if (cmdline_complete_get_elt_string( 179 NULL, 0, buf, 0) != -1) { 180 printf("Error: function accepted null token!\n"); 181 return -1; 182 } 183 if (cmdline_complete_get_nb_string(NULL) != -1) { 184 printf("Error: function accepted null token!\n"); 185 return -1; 186 } 187 if (cmdline_parse_string(NULL, buf, NULL, 0) != -1) { 188 printf("Error: function accepted null token!\n"); 189 return -1; 190 } 191 /* test null buffer */ 192 if (cmdline_complete_get_elt_string( 193 (cmdline_parse_token_hdr_t*)&token, 0, NULL, 0) != -1) { 194 printf("Error: function accepted null buffer!\n"); 195 return -1; 196 } 197 if (cmdline_parse_string( 198 (cmdline_parse_token_hdr_t*)&token, NULL, 199 (void*)&result, sizeof(result)) != -1) { 200 printf("Error: function accepted null buffer!\n"); 201 return -1; 202 } 203 if (cmdline_get_help_string( 204 (cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) { 205 printf("Error: function accepted null buffer!\n"); 206 return -1; 207 } 208 /* test null result */ 209 if (cmdline_parse_string( 210 (cmdline_parse_token_hdr_t*)&token, buf, NULL, 0) == -1) { 211 printf("Error: function rejected null result!\n"); 212 return -1; 213 } 214 /* test negative index */ 215 if (cmdline_complete_get_elt_string( 216 (cmdline_parse_token_hdr_t*)&token, -1, buf, 0) != -1) { 217 printf("Error: function accepted negative index!\n"); 218 return -1; 219 } 220 return 0; 221 } 222 223 /* test valid parameters but invalid data */ 224 int 225 test_parse_string_invalid_data(void) 226 { 227 cmdline_parse_token_string_t token; 228 cmdline_parse_token_string_t help_token; 229 char buf[CMDLINE_TEST_BUFSIZE]; 230 char help_str[CMDLINE_TEST_BUFSIZE]; 231 char small_buf[SMALL_BUF]; 232 unsigned i; 233 234 /* test parsing invalid strings */ 235 for (i = 0; i < STRING_INVALID_STRS_SIZE; i++) { 236 memset(&token, 0, sizeof(token)); 237 memset(buf, 0, sizeof(buf)); 238 239 /* prepare test token data */ 240 token.string_data.str = string_invalid_strs[i].fixed_str; 241 242 if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token, 243 string_invalid_strs[i].str, (void*)buf, 244 sizeof(buf)) != -1) { 245 memset(help_str, 0, sizeof(help_str)); 246 memset(&help_token, 0, sizeof(help_token)); 247 248 help_token.string_data.str = string_invalid_strs[i].fixed_str; 249 250 /* get parse type so we can give a good error message */ 251 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 252 sizeof(help_str)); 253 254 printf("Error: parsing %s as %s succeeded!\n", 255 string_invalid_strs[i].str, help_str); 256 return -1; 257 } 258 } 259 260 /* misc tests (big comments signify test cases) */ 261 memset(&token, 0, sizeof(token)); 262 memset(small_buf, 0, sizeof(small_buf)); 263 264 /* 265 * try to get element from a null token 266 */ 267 token.string_data.str = NULL; 268 if (cmdline_complete_get_elt_string( 269 (cmdline_parse_token_hdr_t*)&token, 1, 270 buf, sizeof(buf)) != -1) { 271 printf("Error: getting token from null token string!\n"); 272 return -1; 273 } 274 275 /* 276 * try to get element into a buffer that is too small 277 */ 278 token.string_data.str = "too_small_buffer"; 279 if (cmdline_complete_get_elt_string( 280 (cmdline_parse_token_hdr_t*)&token, 0, 281 small_buf, sizeof(small_buf)) != -1) { 282 printf("Error: writing token into too small a buffer succeeded!\n"); 283 return -1; 284 } 285 286 /* 287 * get help string written into a buffer smaller than help string 288 * truncation should occur 289 */ 290 token.string_data.str = NULL; 291 if (cmdline_get_help_string( 292 (cmdline_parse_token_hdr_t*)&token, 293 small_buf, sizeof(small_buf)) == -1) { 294 printf("Error: writing help string into too small a buffer failed!\n"); 295 return -1; 296 } 297 /* get help string for "any string" so we can compare it with small_buf */ 298 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 299 sizeof(help_str)); 300 if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) { 301 printf("Error: help string mismatch!\n"); 302 return -1; 303 } 304 /* check null terminator */ 305 if (small_buf[sizeof(small_buf) - 1] != '\0') { 306 printf("Error: small buffer doesn't have a null terminator!\n"); 307 return -1; 308 } 309 310 /* 311 * try to count tokens in a null token 312 */ 313 token.string_data.str = NULL; 314 if (cmdline_complete_get_nb_string( 315 (cmdline_parse_token_hdr_t*)&token) != 0) { 316 printf("Error: getting token count from null token succeeded!\n"); 317 return -1; 318 } 319 320 return 0; 321 } 322 323 /* test valid parameters and data */ 324 int 325 test_parse_string_valid(void) 326 { 327 cmdline_parse_token_string_t token; 328 cmdline_parse_token_string_t help_token; 329 char buf[CMDLINE_TEST_BUFSIZE]; 330 char help_str[CMDLINE_TEST_BUFSIZE]; 331 unsigned i; 332 333 /* test parsing strings */ 334 for (i = 0; i < STRING_PARSE_STRS_SIZE; i++) { 335 memset(&token, 0, sizeof(token)); 336 memset(buf, 0, sizeof(buf)); 337 338 token.string_data.str = string_parse_strs[i].fixed_str; 339 340 if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token, 341 string_parse_strs[i].str, (void*)buf, 342 sizeof(buf)) < 0) { 343 344 /* clean help data */ 345 memset(&help_token, 0, sizeof(help_token)); 346 memset(help_str, 0, sizeof(help_str)); 347 348 /* prepare help token */ 349 help_token.string_data.str = string_parse_strs[i].fixed_str; 350 351 /* get help string so that we get an informative error message */ 352 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 353 sizeof(help_str)); 354 355 printf("Error: parsing %s as %s failed!\n", 356 string_parse_strs[i].str, help_str); 357 return -1; 358 } 359 if (strcmp(buf, string_parse_strs[i].result) != 0) { 360 printf("Error: result mismatch!\n"); 361 return -1; 362 } 363 } 364 365 /* get number of string tokens and verify it's correct */ 366 for (i = 0; i < STRING_NB_STRS_SIZE; i++) { 367 memset(&token, 0, sizeof(token)); 368 369 token.string_data.str = string_nb_strs[i].str; 370 371 if (cmdline_complete_get_nb_string( 372 (cmdline_parse_token_hdr_t*)&token) < 373 string_nb_strs[i].nb_strs) { 374 printf("Error: strings count mismatch!\n"); 375 return -1; 376 } 377 } 378 379 /* get token at specified position and verify it's correct */ 380 for (i = 0; i < STRING_ELT_STRS_SIZE; i++) { 381 memset(&token, 0, sizeof(token)); 382 memset(buf, 0, sizeof(buf)); 383 384 token.string_data.str = string_elt_strs[i].str; 385 386 if (cmdline_complete_get_elt_string( 387 (cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx, 388 buf, sizeof(buf)) < 0) { 389 printf("Error: getting string element failed!\n"); 390 return -1; 391 } 392 if (strncmp(buf, string_elt_strs[i].result, 393 sizeof(buf)) != 0) { 394 printf("Error: result mismatch!\n"); 395 return -1; 396 } 397 } 398 399 /* cover all cases with help strings */ 400 for (i = 0; i < STRING_HELP_STRS_SIZE; i++) { 401 memset(&help_token, 0, sizeof(help_token)); 402 memset(help_str, 0, sizeof(help_str)); 403 help_token.string_data.str = string_help_strs[i]; 404 if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token, 405 help_str, sizeof(help_str)) < 0) { 406 printf("Error: help operation failed!\n"); 407 return -1; 408 } 409 } 410 411 return 0; 412 } 413