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