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