xref: /dpdk/app/test/test_cmdline_string.c (revision dbb860e0)
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 }
403