mbuf: fix performance with 128-byte cache line
[dpdk.git] / app / test / test_cmdline_string.c
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 }