xref: /dpdk/app/test/test_cmdline_string.c (revision 14ad4f01845331a0ae98c681efa3086eeed3343a)
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 
117 
118 #define STRING_PARSE_STRS_SIZE \
119 	(sizeof(string_parse_strs) / sizeof(string_parse_strs[0]))
120 #define STRING_HELP_STRS_SIZE \
121 	(sizeof(string_help_strs) / sizeof(string_help_strs[0]))
122 #define STRING_ELT_STRS_SIZE \
123 	(sizeof(string_elt_strs) / sizeof(string_elt_strs[0]))
124 #define STRING_NB_STRS_SIZE \
125 	(sizeof(string_nb_strs) / sizeof(string_nb_strs[0]))
126 #define STRING_INVALID_STRS_SIZE \
127 	(sizeof(string_invalid_strs) / sizeof(string_invalid_strs[0]))
128 
129 #define SMALL_BUF 8
130 
131 /* test invalid parameters */
132 int
133 test_parse_string_invalid_param(void)
134 {
135 	cmdline_parse_token_string_t token;
136 	int result;
137 	char buf[CMDLINE_TEST_BUFSIZE];
138 
139 	memset(&token, 0, sizeof(token));
140 
141 	snprintf(buf, sizeof(buf), "buffer");
142 
143 	/* test null token */
144 	if (cmdline_get_help_string(
145 		NULL, buf, 0) != -1) {
146 		printf("Error: function accepted null token!\n");
147 		return -1;
148 	}
149 	if (cmdline_complete_get_elt_string(
150 			NULL, 0, buf, 0) != -1) {
151 		printf("Error: function accepted null token!\n");
152 		return -1;
153 	}
154 	if (cmdline_complete_get_nb_string(NULL) != -1) {
155 		printf("Error: function accepted null token!\n");
156 		return -1;
157 	}
158 	if (cmdline_parse_string(NULL, buf, NULL, 0) != -1) {
159 		printf("Error: function accepted null token!\n");
160 		return -1;
161 	}
162 	/* test null buffer */
163 	if (cmdline_complete_get_elt_string(
164 			(cmdline_parse_token_hdr_t*)&token, 0, NULL, 0) != -1) {
165 		printf("Error: function accepted null buffer!\n");
166 		return -1;
167 	}
168 	if (cmdline_parse_string(
169 			(cmdline_parse_token_hdr_t*)&token, NULL,
170 			(void*)&result, sizeof(result)) != -1) {
171 		printf("Error: function accepted null buffer!\n");
172 		return -1;
173 	}
174 	if (cmdline_get_help_string(
175 			(cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) {
176 		printf("Error: function accepted null buffer!\n");
177 		return -1;
178 	}
179 	/* test null result */
180 	if (cmdline_parse_string(
181 			(cmdline_parse_token_hdr_t*)&token, buf, NULL, 0) == -1) {
182 		printf("Error: function rejected null result!\n");
183 		return -1;
184 	}
185 	/* test negative index */
186 	if (cmdline_complete_get_elt_string(
187 			(cmdline_parse_token_hdr_t*)&token, -1, buf, 0) != -1) {
188 		printf("Error: function accepted negative index!\n");
189 		return -1;
190 	}
191 	return 0;
192 }
193 
194 /* test valid parameters but invalid data */
195 int
196 test_parse_string_invalid_data(void)
197 {
198 	cmdline_parse_token_string_t token;
199 	cmdline_parse_token_string_t help_token;
200 	char buf[CMDLINE_TEST_BUFSIZE];
201 	char help_str[CMDLINE_TEST_BUFSIZE];
202 	char small_buf[SMALL_BUF];
203 	unsigned i;
204 
205 	/* test parsing invalid strings */
206 	for (i = 0; i < STRING_INVALID_STRS_SIZE; i++) {
207 		memset(&token, 0, sizeof(token));
208 		memset(buf, 0, sizeof(buf));
209 
210 		/* prepare test token data */
211 		token.string_data.str = string_invalid_strs[i].fixed_str;
212 
213 		if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
214 				string_invalid_strs[i].str, (void*)buf,
215 				sizeof(buf)) != -1) {
216 			memset(help_str, 0, sizeof(help_str));
217 			memset(&help_token, 0, sizeof(help_token));
218 
219 			help_token.string_data.str = string_invalid_strs[i].fixed_str;
220 
221 			/* get parse type so we can give a good error message */
222 			cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
223 					sizeof(help_str));
224 
225 			printf("Error: parsing %s as %s succeeded!\n",
226 					string_invalid_strs[i].str, help_str);
227 			return -1;
228 		}
229 	}
230 
231 	/* misc tests (big comments signify test cases) */
232 	memset(&token, 0, sizeof(token));
233 	memset(small_buf, 0, sizeof(small_buf));
234 
235 	/*
236 	 * try to get element from a null token
237 	 */
238 	token.string_data.str = NULL;
239 	if (cmdline_complete_get_elt_string(
240 			(cmdline_parse_token_hdr_t*)&token, 1,
241 			buf, sizeof(buf)) != -1) {
242 		printf("Error: getting token from null token string!\n");
243 		return -1;
244 	}
245 
246 	/*
247 	 * try to get element into a buffer that is too small
248 	 */
249 	token.string_data.str = "too_small_buffer";
250 	if (cmdline_complete_get_elt_string(
251 			(cmdline_parse_token_hdr_t*)&token, 0,
252 			small_buf, sizeof(small_buf)) != -1) {
253 		printf("Error: writing token into too small a buffer succeeded!\n");
254 		return -1;
255 	}
256 
257 	/*
258 	 * get help string written into a buffer smaller than help string
259 	 * truncation should occur
260 	 */
261 	token.string_data.str = NULL;
262 	if (cmdline_get_help_string(
263 			(cmdline_parse_token_hdr_t*)&token,
264 			small_buf, sizeof(small_buf)) == -1) {
265 		printf("Error: writing help string into too small a buffer failed!\n");
266 		return -1;
267 	}
268 	/* get help string for "any string" so we can compare it with small_buf */
269 	cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
270 			sizeof(help_str));
271 	if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) {
272 		printf("Error: help string mismatch!\n");
273 		return -1;
274 	}
275 	/* check null terminator */
276 	if (small_buf[sizeof(small_buf) - 1] != '\0') {
277 		printf("Error: small buffer doesn't have a null terminator!\n");
278 		return -1;
279 	}
280 
281 	/*
282 	 * try to count tokens in a null token
283 	 */
284 	token.string_data.str = NULL;
285 	if (cmdline_complete_get_nb_string(
286 			(cmdline_parse_token_hdr_t*)&token) != 0) {
287 		printf("Error: getting token count from null token succeeded!\n");
288 		return -1;
289 	}
290 
291 	return 0;
292 }
293 
294 /* test valid parameters and data */
295 int
296 test_parse_string_valid(void)
297 {
298 	cmdline_parse_token_string_t token;
299 	cmdline_parse_token_string_t help_token;
300 	char buf[CMDLINE_TEST_BUFSIZE];
301 	char help_str[CMDLINE_TEST_BUFSIZE];
302 	unsigned i;
303 
304 	/* test parsing strings */
305 	for (i = 0; i < STRING_PARSE_STRS_SIZE; i++) {
306 		memset(&token, 0, sizeof(token));
307 		memset(buf, 0, sizeof(buf));
308 
309 		token.string_data.str = string_parse_strs[i].fixed_str;
310 
311 		if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
312 				string_parse_strs[i].str, (void*)buf,
313 				sizeof(buf)) < 0) {
314 
315 			/* clean help data */
316 			memset(&help_token, 0, sizeof(help_token));
317 			memset(help_str, 0, sizeof(help_str));
318 
319 			/* prepare help token */
320 			help_token.string_data.str = string_parse_strs[i].fixed_str;
321 
322 			/* get help string so that we get an informative error message */
323 			cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
324 					sizeof(help_str));
325 
326 			printf("Error: parsing %s as %s failed!\n",
327 					string_parse_strs[i].str, help_str);
328 			return -1;
329 		}
330 		if (strcmp(buf, string_parse_strs[i].result) != 0) {
331 			printf("Error: result mismatch!\n");
332 			return -1;
333 		}
334 	}
335 
336 	/* get number of string tokens and verify it's correct */
337 	for (i = 0; i < STRING_NB_STRS_SIZE; i++) {
338 		memset(&token, 0, sizeof(token));
339 
340 		token.string_data.str = string_nb_strs[i].str;
341 
342 		if (cmdline_complete_get_nb_string(
343 				(cmdline_parse_token_hdr_t*)&token) <
344 				string_nb_strs[i].nb_strs) {
345 			printf("Error: strings count mismatch!\n");
346 			return -1;
347 		}
348 	}
349 
350 	/* get token at specified position and verify it's correct */
351 	for (i = 0; i < STRING_ELT_STRS_SIZE; i++) {
352 		memset(&token, 0, sizeof(token));
353 		memset(buf, 0, sizeof(buf));
354 
355 		token.string_data.str = string_elt_strs[i].str;
356 
357 		if (cmdline_complete_get_elt_string(
358 				(cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx,
359 				buf, sizeof(buf)) < 0) {
360 			printf("Error: getting string element failed!\n");
361 			return -1;
362 		}
363 		if (strncmp(buf, string_elt_strs[i].result,
364 				sizeof(buf)) != 0) {
365 			printf("Error: result mismatch!\n");
366 			return -1;
367 		}
368 	}
369 
370 	/* cover all cases with help strings */
371 	for (i = 0; i < STRING_HELP_STRS_SIZE; i++) {
372 		memset(&help_token, 0, sizeof(help_token));
373 		memset(help_str, 0, sizeof(help_str));
374 		help_token.string_data.str = string_help_strs[i];
375 		if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token,
376 				help_str, sizeof(help_str)) < 0) {
377 			printf("Error: help operation failed!\n");
378 			return -1;
379 		}
380 	}
381 
382 	return 0;
383 }
384