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