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