app: use common macro RTE_DIM
[dpdk.git] / app / test / test_cmdline_string.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <inttypes.h>
8
9 #include <rte_common.h>
10 #include <rte_string_fns.h>
11
12 #include <cmdline_parse.h>
13 #include <cmdline_parse_string.h>
14
15 #include "test_cmdline.h"
16
17 /* structures needed to run tests */
18
19 struct string_elt_str {
20         const char * str;       /* parsed string */
21         const char * result;    /* expected string */
22         int idx;        /* position at which result is expected to be */
23 };
24
25 struct string_elt_str string_elt_strs[] = {
26                 {"one#two#three", "three", 2},
27                 {"one#two with spaces#three", "three", 2},
28                 {"one#two\twith\ttabs#three", "three", 2},
29                 {"one#two\rwith\rreturns#three", "three", 2},
30                 {"one#two\nwith\nnewlines#three", "three", 2},
31                 {"one#two#three", "one", 0},
32                 {"one#two#three", "two", 1},
33                 {"one#two\0three", "two", 1},
34                 {"one#two with spaces#three", "two with spaces", 1},
35                 {"one#two\twith\ttabs#three", "two\twith\ttabs", 1},
36                 {"one#two\rwith\rreturns#three", "two\rwith\rreturns", 1},
37                 {"one#two\nwith\nnewlines#three", "two\nwith\nnewlines", 1},
38 };
39
40 #if (CMDLINE_TEST_BUFSIZE < STR_TOKEN_SIZE) \
41 || (CMDLINE_TEST_BUFSIZE < STR_MULTI_TOKEN_SIZE)
42 #undef CMDLINE_TEST_BUFSIZE
43 #define CMDLINE_TEST_BUFSIZE RTE_MAX(STR_TOKEN_SIZE, STR_MULTI_TOKEN_SIZE)
44 #endif
45
46 struct string_nb_str {
47         const char * str;       /* parsed string */
48         int nb_strs;    /* expected number of strings in str */
49 };
50
51 struct string_nb_str string_nb_strs[] = {
52                 {"one#two#three", 3},
53                 {"one", 1},
54                 {"one# \t two \r # three \n #four", 4},
55 };
56
57
58
59 struct string_parse_str {
60         const char * str;       /* parsed string */
61         const char * fixed_str; /* parsing mode (any, fixed or multi) */
62         const char * result;    /* expected result */
63 };
64
65 struct string_parse_str string_parse_strs[] = {
66                 {"one", NULL, "one"},   /* any string */
67                 {"two", "one#two#three", "two"},        /* multiple choice string */
68                 {"three", "three", "three"},    /* fixed string */
69                 {"three", "one#two with\rgarbage\tcharacters\n#three", "three"},
70                 {"two with\rgarbage\tcharacters\n",
71                                 "one#two with\rgarbage\tcharacters\n#three",
72                                 "two with\rgarbage\tcharacters\n"},
73                 {"one two", "one", "one"}, /* fixed string */
74                 {"one two", TOKEN_STRING_MULTI, "one two"}, /* multi string */
75                 {"one two", NULL, "one"}, /* any string */
76                 {"one two #three", TOKEN_STRING_MULTI, "one two "},
77                 /* multi string with comment */
78 };
79
80
81
82 struct string_invalid_str {
83         const char * str;       /* parsed string */
84         const char * fixed_str; /* parsing mode (any, fixed or multi) */
85 };
86
87 struct string_invalid_str string_invalid_strs[] = {
88                 {"invalid", "one"},     /* fixed string */
89                 {"invalid", "one#two#three"},   /* multiple choice string */
90                 {"invalid", "invalidone"},      /* string that starts the same */
91                 {"invalidone", "invalid"},      /* string that starts the same */
92                 {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
93                  "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
94                  "toolong!!!", NULL },
95                 {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
96                  "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
97                  "toolong!!!", "fixed" },
98                 {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
99                  "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
100                  "toolong!!!", "multi#choice#string" },
101                 {"invalid",
102                  "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
103                  "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
104                  "toolong!!!" },
105                  {"", "invalid"}
106 };
107
108
109
110 const char * string_help_strs[] = {
111                 NULL,
112                 "fixed_str",
113                 "multi#str",
114 };
115
116 #define SMALL_BUF 8
117
118 /* test invalid parameters */
119 int
120 test_parse_string_invalid_param(void)
121 {
122         cmdline_parse_token_string_t token;
123         int result;
124         char buf[CMDLINE_TEST_BUFSIZE];
125
126         memset(&token, 0, sizeof(token));
127
128         snprintf(buf, sizeof(buf), "buffer");
129
130         /* test null token */
131         if (cmdline_get_help_string(
132                 NULL, buf, 0) != -1) {
133                 printf("Error: function accepted null token!\n");
134                 return -1;
135         }
136         if (cmdline_complete_get_elt_string(
137                         NULL, 0, buf, 0) != -1) {
138                 printf("Error: function accepted null token!\n");
139                 return -1;
140         }
141         if (cmdline_complete_get_nb_string(NULL) != -1) {
142                 printf("Error: function accepted null token!\n");
143                 return -1;
144         }
145         if (cmdline_parse_string(NULL, buf, NULL, 0) != -1) {
146                 printf("Error: function accepted null token!\n");
147                 return -1;
148         }
149         /* test null buffer */
150         if (cmdline_complete_get_elt_string(
151                         (cmdline_parse_token_hdr_t*)&token, 0, NULL, 0) != -1) {
152                 printf("Error: function accepted null buffer!\n");
153                 return -1;
154         }
155         if (cmdline_parse_string(
156                         (cmdline_parse_token_hdr_t*)&token, NULL,
157                         (void*)&result, sizeof(result)) != -1) {
158                 printf("Error: function accepted null buffer!\n");
159                 return -1;
160         }
161         if (cmdline_get_help_string(
162                         (cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) {
163                 printf("Error: function accepted null buffer!\n");
164                 return -1;
165         }
166         /* test null result */
167         if (cmdline_parse_string(
168                         (cmdline_parse_token_hdr_t*)&token, buf, NULL, 0) == -1) {
169                 printf("Error: function rejected null result!\n");
170                 return -1;
171         }
172         /* test negative index */
173         if (cmdline_complete_get_elt_string(
174                         (cmdline_parse_token_hdr_t*)&token, -1, buf, 0) != -1) {
175                 printf("Error: function accepted negative index!\n");
176                 return -1;
177         }
178         return 0;
179 }
180
181 /* test valid parameters but invalid data */
182 int
183 test_parse_string_invalid_data(void)
184 {
185         cmdline_parse_token_string_t token;
186         cmdline_parse_token_string_t help_token;
187         char buf[CMDLINE_TEST_BUFSIZE];
188         char help_str[CMDLINE_TEST_BUFSIZE];
189         char small_buf[SMALL_BUF];
190         unsigned i;
191
192         /* test parsing invalid strings */
193         for (i = 0; i < RTE_DIM(string_invalid_strs); i++) {
194                 memset(&token, 0, sizeof(token));
195                 memset(buf, 0, sizeof(buf));
196
197                 /* prepare test token data */
198                 token.string_data.str = string_invalid_strs[i].fixed_str;
199
200                 if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
201                                 string_invalid_strs[i].str, (void*)buf,
202                                 sizeof(buf)) != -1) {
203                         memset(help_str, 0, sizeof(help_str));
204                         memset(&help_token, 0, sizeof(help_token));
205
206                         help_token.string_data.str = string_invalid_strs[i].fixed_str;
207
208                         /* get parse type so we can give a good error message */
209                         cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
210                                         sizeof(help_str));
211
212                         printf("Error: parsing %s as %s succeeded!\n",
213                                         string_invalid_strs[i].str, help_str);
214                         return -1;
215                 }
216         }
217
218         /* misc tests (big comments signify test cases) */
219         memset(&token, 0, sizeof(token));
220         memset(small_buf, 0, sizeof(small_buf));
221
222         /*
223          * try to get element from a null token
224          */
225         token.string_data.str = NULL;
226         if (cmdline_complete_get_elt_string(
227                         (cmdline_parse_token_hdr_t*)&token, 1,
228                         buf, sizeof(buf)) != -1) {
229                 printf("Error: getting token from null token string!\n");
230                 return -1;
231         }
232
233         /*
234          * try to get element into a buffer that is too small
235          */
236         token.string_data.str = "too_small_buffer";
237         if (cmdline_complete_get_elt_string(
238                         (cmdline_parse_token_hdr_t*)&token, 0,
239                         small_buf, sizeof(small_buf)) != -1) {
240                 printf("Error: writing token into too small a buffer succeeded!\n");
241                 return -1;
242         }
243
244         /*
245          * get help string written into a buffer smaller than help string
246          * truncation should occur
247          */
248         token.string_data.str = NULL;
249         if (cmdline_get_help_string(
250                         (cmdline_parse_token_hdr_t*)&token,
251                         small_buf, sizeof(small_buf)) == -1) {
252                 printf("Error: writing help string into too small a buffer failed!\n");
253                 return -1;
254         }
255         /* get help string for "any string" so we can compare it with small_buf */
256         cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
257                         sizeof(help_str));
258         if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) {
259                 printf("Error: help string mismatch!\n");
260                 return -1;
261         }
262         /* check null terminator */
263         if (small_buf[sizeof(small_buf) - 1] != '\0') {
264                 printf("Error: small buffer doesn't have a null terminator!\n");
265                 return -1;
266         }
267
268         /*
269          * try to count tokens in a null token
270          */
271         token.string_data.str = NULL;
272         if (cmdline_complete_get_nb_string(
273                         (cmdline_parse_token_hdr_t*)&token) != 0) {
274                 printf("Error: getting token count from null token succeeded!\n");
275                 return -1;
276         }
277
278         return 0;
279 }
280
281 /* test valid parameters and data */
282 int
283 test_parse_string_valid(void)
284 {
285         cmdline_parse_token_string_t token;
286         cmdline_parse_token_string_t help_token;
287         char buf[CMDLINE_TEST_BUFSIZE];
288         char help_str[CMDLINE_TEST_BUFSIZE];
289         unsigned i;
290
291         /* test parsing strings */
292         for (i = 0; i < RTE_DIM(string_parse_strs); i++) {
293                 memset(&token, 0, sizeof(token));
294                 memset(buf, 0, sizeof(buf));
295
296                 token.string_data.str = string_parse_strs[i].fixed_str;
297
298                 if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
299                                 string_parse_strs[i].str, (void*)buf,
300                                 sizeof(buf)) < 0) {
301
302                         /* clean help data */
303                         memset(&help_token, 0, sizeof(help_token));
304                         memset(help_str, 0, sizeof(help_str));
305
306                         /* prepare help token */
307                         help_token.string_data.str = string_parse_strs[i].fixed_str;
308
309                         /* get help string so that we get an informative error message */
310                         cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
311                                         sizeof(help_str));
312
313                         printf("Error: parsing %s as %s failed!\n",
314                                         string_parse_strs[i].str, help_str);
315                         return -1;
316                 }
317                 if (strcmp(buf, string_parse_strs[i].result) != 0) {
318                         printf("Error: result mismatch!\n");
319                         return -1;
320                 }
321         }
322
323         /* get number of string tokens and verify it's correct */
324         for (i = 0; i < RTE_DIM(string_nb_strs); i++) {
325                 memset(&token, 0, sizeof(token));
326
327                 token.string_data.str = string_nb_strs[i].str;
328
329                 if (cmdline_complete_get_nb_string(
330                                 (cmdline_parse_token_hdr_t*)&token) <
331                                 string_nb_strs[i].nb_strs) {
332                         printf("Error: strings count mismatch!\n");
333                         return -1;
334                 }
335         }
336
337         /* get token at specified position and verify it's correct */
338         for (i = 0; i < RTE_DIM(string_elt_strs); i++) {
339                 memset(&token, 0, sizeof(token));
340                 memset(buf, 0, sizeof(buf));
341
342                 token.string_data.str = string_elt_strs[i].str;
343
344                 if (cmdline_complete_get_elt_string(
345                                 (cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx,
346                                 buf, sizeof(buf)) < 0) {
347                         printf("Error: getting string element failed!\n");
348                         return -1;
349                 }
350                 if (strncmp(buf, string_elt_strs[i].result,
351                                 sizeof(buf)) != 0) {
352                         printf("Error: result mismatch!\n");
353                         return -1;
354                 }
355         }
356
357         /* cover all cases with help strings */
358         for (i = 0; i < RTE_DIM(string_help_strs); i++) {
359                 memset(&help_token, 0, sizeof(help_token));
360                 memset(help_str, 0, sizeof(help_str));
361                 help_token.string_data.str = string_help_strs[i];
362                 if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token,
363                                 help_str, sizeof(help_str)) < 0) {
364                         printf("Error: help operation failed!\n");
365                         return -1;
366                 }
367         }
368
369         return 0;
370 }