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