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 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, 0) != -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, 193 (void*)&result, sizeof(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, 0) == -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, 238 sizeof(buf)) != -1) { 239 memset(help_str, 0, sizeof(help_str)); 240 memset(&help_token, 0, sizeof(help_token)); 241 242 help_token.string_data.str = string_invalid_strs[i].fixed_str; 243 244 /* get parse type so we can give a good error message */ 245 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 246 sizeof(help_str)); 247 248 printf("Error: parsing %s as %s succeeded!\n", 249 string_invalid_strs[i].str, help_str); 250 return -1; 251 } 252 } 253 254 /* misc tests (big comments signify test cases) */ 255 memset(&token, 0, sizeof(token)); 256 memset(small_buf, 0, sizeof(small_buf)); 257 258 /* 259 * try to get element from a null token 260 */ 261 token.string_data.str = NULL; 262 if (cmdline_complete_get_elt_string( 263 (cmdline_parse_token_hdr_t*)&token, 1, 264 buf, sizeof(buf)) != -1) { 265 printf("Error: getting token from null token string!\n"); 266 return -1; 267 } 268 269 /* 270 * try to get element into a buffer that is too small 271 */ 272 token.string_data.str = "too_small_buffer"; 273 if (cmdline_complete_get_elt_string( 274 (cmdline_parse_token_hdr_t*)&token, 0, 275 small_buf, sizeof(small_buf)) != -1) { 276 printf("Error: writing token into too small a buffer succeeded!\n"); 277 return -1; 278 } 279 280 /* 281 * get help string written into a buffer smaller than help string 282 * truncation should occur 283 */ 284 token.string_data.str = NULL; 285 if (cmdline_get_help_string( 286 (cmdline_parse_token_hdr_t*)&token, 287 small_buf, sizeof(small_buf)) == -1) { 288 printf("Error: writing help string into too small a buffer failed!\n"); 289 return -1; 290 } 291 /* get help string for "any string" so we can compare it with small_buf */ 292 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 293 sizeof(help_str)); 294 if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) { 295 printf("Error: help string mismatch!\n"); 296 return -1; 297 } 298 /* check null terminator */ 299 if (small_buf[sizeof(small_buf) - 1] != '\0') { 300 printf("Error: small buffer doesn't have a null terminator!\n"); 301 return -1; 302 } 303 304 /* 305 * try to count tokens in a null token 306 */ 307 token.string_data.str = NULL; 308 if (cmdline_complete_get_nb_string( 309 (cmdline_parse_token_hdr_t*)&token) != 0) { 310 printf("Error: getting token count from null token succeeded!\n"); 311 return -1; 312 } 313 314 return 0; 315 } 316 317 /* test valid parameters and data */ 318 int 319 test_parse_string_valid(void) 320 { 321 cmdline_parse_token_string_t token; 322 cmdline_parse_token_string_t help_token; 323 char buf[CMDLINE_TEST_BUFSIZE]; 324 char help_str[CMDLINE_TEST_BUFSIZE]; 325 unsigned i; 326 327 /* test parsing strings */ 328 for (i = 0; i < STRING_PARSE_STRS_SIZE; i++) { 329 memset(&token, 0, sizeof(token)); 330 memset(buf, 0, sizeof(buf)); 331 332 token.string_data.str = string_parse_strs[i].fixed_str; 333 334 if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token, 335 string_parse_strs[i].str, (void*)buf, 336 sizeof(buf)) < 0) { 337 338 /* clean help data */ 339 memset(&help_token, 0, sizeof(help_token)); 340 memset(help_str, 0, sizeof(help_str)); 341 342 /* prepare help token */ 343 help_token.string_data.str = string_parse_strs[i].fixed_str; 344 345 /* get help string so that we get an informative error message */ 346 cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, 347 sizeof(help_str)); 348 349 printf("Error: parsing %s as %s failed!\n", 350 string_parse_strs[i].str, help_str); 351 return -1; 352 } 353 if (strncmp(buf, string_parse_strs[i].result, 354 sizeof(string_parse_strs[i].result) - 1) != 0) { 355 printf("Error: result mismatch!\n"); 356 return -1; 357 } 358 } 359 360 /* get number of string tokens and verify it's correct */ 361 for (i = 0; i < STRING_NB_STRS_SIZE; i++) { 362 memset(&token, 0, sizeof(token)); 363 364 token.string_data.str = string_nb_strs[i].str; 365 366 if (cmdline_complete_get_nb_string( 367 (cmdline_parse_token_hdr_t*)&token) < 368 string_nb_strs[i].nb_strs) { 369 printf("Error: strings count mismatch!\n"); 370 return -1; 371 } 372 } 373 374 /* get token at specified position and verify it's correct */ 375 for (i = 0; i < STRING_ELT_STRS_SIZE; i++) { 376 memset(&token, 0, sizeof(token)); 377 memset(buf, 0, sizeof(buf)); 378 379 token.string_data.str = string_elt_strs[i].str; 380 381 if (cmdline_complete_get_elt_string( 382 (cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx, 383 buf, sizeof(buf)) < 0) { 384 printf("Error: getting string element failed!\n"); 385 return -1; 386 } 387 if (strncmp(buf, string_elt_strs[i].result, 388 sizeof(buf)) != 0) { 389 printf("Error: result mismatch!\n"); 390 return -1; 391 } 392 } 393 394 /* cover all cases with help strings */ 395 for (i = 0; i < STRING_HELP_STRS_SIZE; i++) { 396 memset(&help_token, 0, sizeof(help_token)); 397 memset(help_str, 0, sizeof(help_str)); 398 help_token.string_data.str = string_help_strs[i]; 399 if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token, 400 help_str, sizeof(help_str)) < 0) { 401 printf("Error: help operation failed!\n"); 402 return -1; 403 } 404 } 405 406 return 0; 407 } 408