cmdline: tests
[dpdk.git] / app / test / test_cmdline_string.c
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 }