xref: /f-stack/dpdk/app/test/test_cmdline_string.c (revision 2d9fd380)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright(c) 2010-2014 Intel Corporation
34418919fSjohnjiang  */
44418919fSjohnjiang 
54418919fSjohnjiang #include <stdio.h>
64418919fSjohnjiang #include <string.h>
74418919fSjohnjiang #include <inttypes.h>
84418919fSjohnjiang 
94418919fSjohnjiang #include <rte_common.h>
104418919fSjohnjiang #include <rte_string_fns.h>
114418919fSjohnjiang 
124418919fSjohnjiang #include <cmdline_parse.h>
134418919fSjohnjiang #include <cmdline_parse_string.h>
144418919fSjohnjiang 
154418919fSjohnjiang #include "test_cmdline.h"
164418919fSjohnjiang 
174418919fSjohnjiang /* structures needed to run tests */
184418919fSjohnjiang 
194418919fSjohnjiang struct string_elt_str {
204418919fSjohnjiang 	const char * str;	/* parsed string */
214418919fSjohnjiang 	const char * result;	/* expected string */
224418919fSjohnjiang 	int idx;	/* position at which result is expected to be */
234418919fSjohnjiang };
244418919fSjohnjiang 
254418919fSjohnjiang struct string_elt_str string_elt_strs[] = {
264418919fSjohnjiang 		{"one#two#three", "three", 2},
274418919fSjohnjiang 		{"one#two with spaces#three", "three", 2},
284418919fSjohnjiang 		{"one#two\twith\ttabs#three", "three", 2},
294418919fSjohnjiang 		{"one#two\rwith\rreturns#three", "three", 2},
304418919fSjohnjiang 		{"one#two\nwith\nnewlines#three", "three", 2},
314418919fSjohnjiang 		{"one#two#three", "one", 0},
324418919fSjohnjiang 		{"one#two#three", "two", 1},
334418919fSjohnjiang 		{"one#two\0three", "two", 1},
344418919fSjohnjiang 		{"one#two with spaces#three", "two with spaces", 1},
354418919fSjohnjiang 		{"one#two\twith\ttabs#three", "two\twith\ttabs", 1},
364418919fSjohnjiang 		{"one#two\rwith\rreturns#three", "two\rwith\rreturns", 1},
374418919fSjohnjiang 		{"one#two\nwith\nnewlines#three", "two\nwith\nnewlines", 1},
384418919fSjohnjiang };
394418919fSjohnjiang 
404418919fSjohnjiang #if (CMDLINE_TEST_BUFSIZE < STR_TOKEN_SIZE) \
414418919fSjohnjiang || (CMDLINE_TEST_BUFSIZE < STR_MULTI_TOKEN_SIZE)
424418919fSjohnjiang #undef CMDLINE_TEST_BUFSIZE
434418919fSjohnjiang #define CMDLINE_TEST_BUFSIZE RTE_MAX(STR_TOKEN_SIZE, STR_MULTI_TOKEN_SIZE)
444418919fSjohnjiang #endif
454418919fSjohnjiang 
464418919fSjohnjiang struct string_nb_str {
474418919fSjohnjiang 	const char * str;	/* parsed string */
484418919fSjohnjiang 	int nb_strs;	/* expected number of strings in str */
494418919fSjohnjiang };
504418919fSjohnjiang 
514418919fSjohnjiang struct string_nb_str string_nb_strs[] = {
524418919fSjohnjiang 		{"one#two#three", 3},
534418919fSjohnjiang 		{"one", 1},
544418919fSjohnjiang 		{"one# \t two \r # three \n #four", 4},
554418919fSjohnjiang };
564418919fSjohnjiang 
574418919fSjohnjiang 
584418919fSjohnjiang 
594418919fSjohnjiang struct string_parse_str {
604418919fSjohnjiang 	const char * str;	/* parsed string */
614418919fSjohnjiang 	const char * fixed_str;	/* parsing mode (any, fixed or multi) */
624418919fSjohnjiang 	const char * result;	/* expected result */
634418919fSjohnjiang };
644418919fSjohnjiang 
654418919fSjohnjiang struct string_parse_str string_parse_strs[] = {
664418919fSjohnjiang 		{"one", NULL, "one"},	/* any string */
674418919fSjohnjiang 		{"two", "one#two#three", "two"},	/* multiple choice string */
684418919fSjohnjiang 		{"three", "three", "three"},	/* fixed string */
694418919fSjohnjiang 		{"three", "one#two with\rgarbage\tcharacters\n#three", "three"},
704418919fSjohnjiang 		{"two with\rgarbage\tcharacters\n",
714418919fSjohnjiang 				"one#two with\rgarbage\tcharacters\n#three",
724418919fSjohnjiang 				"two with\rgarbage\tcharacters\n"},
734418919fSjohnjiang 		{"one two", "one", "one"}, /* fixed string */
744418919fSjohnjiang 		{"one two", TOKEN_STRING_MULTI, "one two"}, /* multi string */
754418919fSjohnjiang 		{"one two", NULL, "one"}, /* any string */
764418919fSjohnjiang 		{"one two #three", TOKEN_STRING_MULTI, "one two "},
774418919fSjohnjiang 		/* multi string with comment */
784418919fSjohnjiang };
794418919fSjohnjiang 
804418919fSjohnjiang 
814418919fSjohnjiang 
824418919fSjohnjiang struct string_invalid_str {
834418919fSjohnjiang 	const char * str;	/* parsed string */
844418919fSjohnjiang 	const char * fixed_str;	/* parsing mode (any, fixed or multi) */
854418919fSjohnjiang };
864418919fSjohnjiang 
874418919fSjohnjiang struct string_invalid_str string_invalid_strs[] = {
884418919fSjohnjiang 		{"invalid", "one"},	/* fixed string */
894418919fSjohnjiang 		{"invalid", "one#two#three"},	/* multiple choice string */
904418919fSjohnjiang 		{"invalid", "invalidone"},	/* string that starts the same */
914418919fSjohnjiang 		{"invalidone", "invalid"},	/* string that starts the same */
924418919fSjohnjiang 		{"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
934418919fSjohnjiang 		 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
944418919fSjohnjiang 		 "toolong!!!", NULL },
954418919fSjohnjiang 		{"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
964418919fSjohnjiang 		 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
974418919fSjohnjiang 		 "toolong!!!", "fixed" },
984418919fSjohnjiang 		{"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
994418919fSjohnjiang 		 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
1004418919fSjohnjiang 		 "toolong!!!", "multi#choice#string" },
1014418919fSjohnjiang 		{"invalid",
1024418919fSjohnjiang 		 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
1034418919fSjohnjiang 		 "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
1044418919fSjohnjiang 		 "toolong!!!" },
1054418919fSjohnjiang 		 {"", "invalid"}
1064418919fSjohnjiang };
1074418919fSjohnjiang 
1084418919fSjohnjiang 
1094418919fSjohnjiang 
1104418919fSjohnjiang const char * string_help_strs[] = {
1114418919fSjohnjiang 		NULL,
1124418919fSjohnjiang 		"fixed_str",
1134418919fSjohnjiang 		"multi#str",
1144418919fSjohnjiang };
1154418919fSjohnjiang 
1164418919fSjohnjiang #define SMALL_BUF 8
1174418919fSjohnjiang 
1184418919fSjohnjiang /* test invalid parameters */
1194418919fSjohnjiang int
test_parse_string_invalid_param(void)1204418919fSjohnjiang test_parse_string_invalid_param(void)
1214418919fSjohnjiang {
1224418919fSjohnjiang 	cmdline_parse_token_string_t token;
1234418919fSjohnjiang 	int result;
1244418919fSjohnjiang 	char buf[CMDLINE_TEST_BUFSIZE];
1254418919fSjohnjiang 
1264418919fSjohnjiang 	memset(&token, 0, sizeof(token));
1274418919fSjohnjiang 
1284418919fSjohnjiang 	snprintf(buf, sizeof(buf), "buffer");
1294418919fSjohnjiang 
1304418919fSjohnjiang 	/* test null token */
1314418919fSjohnjiang 	if (cmdline_get_help_string(
1324418919fSjohnjiang 		NULL, buf, 0) != -1) {
1334418919fSjohnjiang 		printf("Error: function accepted null token!\n");
1344418919fSjohnjiang 		return -1;
1354418919fSjohnjiang 	}
1364418919fSjohnjiang 	if (cmdline_complete_get_elt_string(
1374418919fSjohnjiang 			NULL, 0, buf, 0) != -1) {
1384418919fSjohnjiang 		printf("Error: function accepted null token!\n");
1394418919fSjohnjiang 		return -1;
1404418919fSjohnjiang 	}
1414418919fSjohnjiang 	if (cmdline_complete_get_nb_string(NULL) != -1) {
1424418919fSjohnjiang 		printf("Error: function accepted null token!\n");
1434418919fSjohnjiang 		return -1;
1444418919fSjohnjiang 	}
1454418919fSjohnjiang 	if (cmdline_parse_string(NULL, buf, NULL, 0) != -1) {
1464418919fSjohnjiang 		printf("Error: function accepted null token!\n");
1474418919fSjohnjiang 		return -1;
1484418919fSjohnjiang 	}
1494418919fSjohnjiang 	/* test null buffer */
1504418919fSjohnjiang 	if (cmdline_complete_get_elt_string(
1514418919fSjohnjiang 			(cmdline_parse_token_hdr_t*)&token, 0, NULL, 0) != -1) {
1524418919fSjohnjiang 		printf("Error: function accepted null buffer!\n");
1534418919fSjohnjiang 		return -1;
1544418919fSjohnjiang 	}
1554418919fSjohnjiang 	if (cmdline_parse_string(
1564418919fSjohnjiang 			(cmdline_parse_token_hdr_t*)&token, NULL,
1574418919fSjohnjiang 			(void*)&result, sizeof(result)) != -1) {
1584418919fSjohnjiang 		printf("Error: function accepted null buffer!\n");
1594418919fSjohnjiang 		return -1;
1604418919fSjohnjiang 	}
1614418919fSjohnjiang 	if (cmdline_get_help_string(
1624418919fSjohnjiang 			(cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) {
1634418919fSjohnjiang 		printf("Error: function accepted null buffer!\n");
1644418919fSjohnjiang 		return -1;
1654418919fSjohnjiang 	}
1664418919fSjohnjiang 	/* test null result */
1674418919fSjohnjiang 	if (cmdline_parse_string(
1684418919fSjohnjiang 			(cmdline_parse_token_hdr_t*)&token, buf, NULL, 0) == -1) {
1694418919fSjohnjiang 		printf("Error: function rejected null result!\n");
1704418919fSjohnjiang 		return -1;
1714418919fSjohnjiang 	}
1724418919fSjohnjiang 	/* test negative index */
1734418919fSjohnjiang 	if (cmdline_complete_get_elt_string(
1744418919fSjohnjiang 			(cmdline_parse_token_hdr_t*)&token, -1, buf, 0) != -1) {
1754418919fSjohnjiang 		printf("Error: function accepted negative index!\n");
1764418919fSjohnjiang 		return -1;
1774418919fSjohnjiang 	}
1784418919fSjohnjiang 	return 0;
1794418919fSjohnjiang }
1804418919fSjohnjiang 
1814418919fSjohnjiang /* test valid parameters but invalid data */
1824418919fSjohnjiang int
test_parse_string_invalid_data(void)1834418919fSjohnjiang test_parse_string_invalid_data(void)
1844418919fSjohnjiang {
1854418919fSjohnjiang 	cmdline_parse_token_string_t token;
1864418919fSjohnjiang 	cmdline_parse_token_string_t help_token;
1874418919fSjohnjiang 	char buf[CMDLINE_TEST_BUFSIZE];
1884418919fSjohnjiang 	char help_str[CMDLINE_TEST_BUFSIZE];
1894418919fSjohnjiang 	char small_buf[SMALL_BUF];
1904418919fSjohnjiang 	unsigned i;
1914418919fSjohnjiang 
1924418919fSjohnjiang 	/* test parsing invalid strings */
193*2d9fd380Sjfb8856606 	for (i = 0; i < RTE_DIM(string_invalid_strs); i++) {
1944418919fSjohnjiang 		memset(&token, 0, sizeof(token));
1954418919fSjohnjiang 		memset(buf, 0, sizeof(buf));
1964418919fSjohnjiang 
1974418919fSjohnjiang 		/* prepare test token data */
1984418919fSjohnjiang 		token.string_data.str = string_invalid_strs[i].fixed_str;
1994418919fSjohnjiang 
2004418919fSjohnjiang 		if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
2014418919fSjohnjiang 				string_invalid_strs[i].str, (void*)buf,
2024418919fSjohnjiang 				sizeof(buf)) != -1) {
2034418919fSjohnjiang 			memset(help_str, 0, sizeof(help_str));
2044418919fSjohnjiang 			memset(&help_token, 0, sizeof(help_token));
2054418919fSjohnjiang 
2064418919fSjohnjiang 			help_token.string_data.str = string_invalid_strs[i].fixed_str;
2074418919fSjohnjiang 
2084418919fSjohnjiang 			/* get parse type so we can give a good error message */
2094418919fSjohnjiang 			cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
2104418919fSjohnjiang 					sizeof(help_str));
2114418919fSjohnjiang 
2124418919fSjohnjiang 			printf("Error: parsing %s as %s succeeded!\n",
2134418919fSjohnjiang 					string_invalid_strs[i].str, help_str);
2144418919fSjohnjiang 			return -1;
2154418919fSjohnjiang 		}
2164418919fSjohnjiang 	}
2174418919fSjohnjiang 
2184418919fSjohnjiang 	/* misc tests (big comments signify test cases) */
2194418919fSjohnjiang 	memset(&token, 0, sizeof(token));
2204418919fSjohnjiang 	memset(small_buf, 0, sizeof(small_buf));
2214418919fSjohnjiang 
2224418919fSjohnjiang 	/*
2234418919fSjohnjiang 	 * try to get element from a null token
2244418919fSjohnjiang 	 */
2254418919fSjohnjiang 	token.string_data.str = NULL;
2264418919fSjohnjiang 	if (cmdline_complete_get_elt_string(
2274418919fSjohnjiang 			(cmdline_parse_token_hdr_t*)&token, 1,
2284418919fSjohnjiang 			buf, sizeof(buf)) != -1) {
2294418919fSjohnjiang 		printf("Error: getting token from null token string!\n");
2304418919fSjohnjiang 		return -1;
2314418919fSjohnjiang 	}
2324418919fSjohnjiang 
2334418919fSjohnjiang 	/*
2344418919fSjohnjiang 	 * try to get element into a buffer that is too small
2354418919fSjohnjiang 	 */
2364418919fSjohnjiang 	token.string_data.str = "too_small_buffer";
2374418919fSjohnjiang 	if (cmdline_complete_get_elt_string(
2384418919fSjohnjiang 			(cmdline_parse_token_hdr_t*)&token, 0,
2394418919fSjohnjiang 			small_buf, sizeof(small_buf)) != -1) {
2404418919fSjohnjiang 		printf("Error: writing token into too small a buffer succeeded!\n");
2414418919fSjohnjiang 		return -1;
2424418919fSjohnjiang 	}
2434418919fSjohnjiang 
2444418919fSjohnjiang 	/*
2454418919fSjohnjiang 	 * get help string written into a buffer smaller than help string
2464418919fSjohnjiang 	 * truncation should occur
2474418919fSjohnjiang 	 */
2484418919fSjohnjiang 	token.string_data.str = NULL;
2494418919fSjohnjiang 	if (cmdline_get_help_string(
2504418919fSjohnjiang 			(cmdline_parse_token_hdr_t*)&token,
2514418919fSjohnjiang 			small_buf, sizeof(small_buf)) == -1) {
2524418919fSjohnjiang 		printf("Error: writing help string into too small a buffer failed!\n");
2534418919fSjohnjiang 		return -1;
2544418919fSjohnjiang 	}
2554418919fSjohnjiang 	/* get help string for "any string" so we can compare it with small_buf */
2564418919fSjohnjiang 	cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
2574418919fSjohnjiang 			sizeof(help_str));
2584418919fSjohnjiang 	if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) {
2594418919fSjohnjiang 		printf("Error: help string mismatch!\n");
2604418919fSjohnjiang 		return -1;
2614418919fSjohnjiang 	}
2624418919fSjohnjiang 	/* check null terminator */
2634418919fSjohnjiang 	if (small_buf[sizeof(small_buf) - 1] != '\0') {
2644418919fSjohnjiang 		printf("Error: small buffer doesn't have a null terminator!\n");
2654418919fSjohnjiang 		return -1;
2664418919fSjohnjiang 	}
2674418919fSjohnjiang 
2684418919fSjohnjiang 	/*
2694418919fSjohnjiang 	 * try to count tokens in a null token
2704418919fSjohnjiang 	 */
2714418919fSjohnjiang 	token.string_data.str = NULL;
2724418919fSjohnjiang 	if (cmdline_complete_get_nb_string(
2734418919fSjohnjiang 			(cmdline_parse_token_hdr_t*)&token) != 0) {
2744418919fSjohnjiang 		printf("Error: getting token count from null token succeeded!\n");
2754418919fSjohnjiang 		return -1;
2764418919fSjohnjiang 	}
2774418919fSjohnjiang 
2784418919fSjohnjiang 	return 0;
2794418919fSjohnjiang }
2804418919fSjohnjiang 
2814418919fSjohnjiang /* test valid parameters and data */
2824418919fSjohnjiang int
test_parse_string_valid(void)2834418919fSjohnjiang test_parse_string_valid(void)
2844418919fSjohnjiang {
2854418919fSjohnjiang 	cmdline_parse_token_string_t token;
2864418919fSjohnjiang 	cmdline_parse_token_string_t help_token;
2874418919fSjohnjiang 	char buf[CMDLINE_TEST_BUFSIZE];
2884418919fSjohnjiang 	char help_str[CMDLINE_TEST_BUFSIZE];
2894418919fSjohnjiang 	unsigned i;
2904418919fSjohnjiang 
2914418919fSjohnjiang 	/* test parsing strings */
292*2d9fd380Sjfb8856606 	for (i = 0; i < RTE_DIM(string_parse_strs); i++) {
2934418919fSjohnjiang 		memset(&token, 0, sizeof(token));
2944418919fSjohnjiang 		memset(buf, 0, sizeof(buf));
2954418919fSjohnjiang 
2964418919fSjohnjiang 		token.string_data.str = string_parse_strs[i].fixed_str;
2974418919fSjohnjiang 
2984418919fSjohnjiang 		if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
2994418919fSjohnjiang 				string_parse_strs[i].str, (void*)buf,
3004418919fSjohnjiang 				sizeof(buf)) < 0) {
3014418919fSjohnjiang 
3024418919fSjohnjiang 			/* clean help data */
3034418919fSjohnjiang 			memset(&help_token, 0, sizeof(help_token));
3044418919fSjohnjiang 			memset(help_str, 0, sizeof(help_str));
3054418919fSjohnjiang 
3064418919fSjohnjiang 			/* prepare help token */
3074418919fSjohnjiang 			help_token.string_data.str = string_parse_strs[i].fixed_str;
3084418919fSjohnjiang 
3094418919fSjohnjiang 			/* get help string so that we get an informative error message */
3104418919fSjohnjiang 			cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
3114418919fSjohnjiang 					sizeof(help_str));
3124418919fSjohnjiang 
3134418919fSjohnjiang 			printf("Error: parsing %s as %s failed!\n",
3144418919fSjohnjiang 					string_parse_strs[i].str, help_str);
3154418919fSjohnjiang 			return -1;
3164418919fSjohnjiang 		}
3174418919fSjohnjiang 		if (strcmp(buf, string_parse_strs[i].result) != 0) {
3184418919fSjohnjiang 			printf("Error: result mismatch!\n");
3194418919fSjohnjiang 			return -1;
3204418919fSjohnjiang 		}
3214418919fSjohnjiang 	}
3224418919fSjohnjiang 
3234418919fSjohnjiang 	/* get number of string tokens and verify it's correct */
324*2d9fd380Sjfb8856606 	for (i = 0; i < RTE_DIM(string_nb_strs); i++) {
3254418919fSjohnjiang 		memset(&token, 0, sizeof(token));
3264418919fSjohnjiang 
3274418919fSjohnjiang 		token.string_data.str = string_nb_strs[i].str;
3284418919fSjohnjiang 
3294418919fSjohnjiang 		if (cmdline_complete_get_nb_string(
3304418919fSjohnjiang 				(cmdline_parse_token_hdr_t*)&token) <
3314418919fSjohnjiang 				string_nb_strs[i].nb_strs) {
3324418919fSjohnjiang 			printf("Error: strings count mismatch!\n");
3334418919fSjohnjiang 			return -1;
3344418919fSjohnjiang 		}
3354418919fSjohnjiang 	}
3364418919fSjohnjiang 
3374418919fSjohnjiang 	/* get token at specified position and verify it's correct */
338*2d9fd380Sjfb8856606 	for (i = 0; i < RTE_DIM(string_elt_strs); i++) {
3394418919fSjohnjiang 		memset(&token, 0, sizeof(token));
3404418919fSjohnjiang 		memset(buf, 0, sizeof(buf));
3414418919fSjohnjiang 
3424418919fSjohnjiang 		token.string_data.str = string_elt_strs[i].str;
3434418919fSjohnjiang 
3444418919fSjohnjiang 		if (cmdline_complete_get_elt_string(
3454418919fSjohnjiang 				(cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx,
3464418919fSjohnjiang 				buf, sizeof(buf)) < 0) {
3474418919fSjohnjiang 			printf("Error: getting string element failed!\n");
3484418919fSjohnjiang 			return -1;
3494418919fSjohnjiang 		}
3504418919fSjohnjiang 		if (strncmp(buf, string_elt_strs[i].result,
3514418919fSjohnjiang 				sizeof(buf)) != 0) {
3524418919fSjohnjiang 			printf("Error: result mismatch!\n");
3534418919fSjohnjiang 			return -1;
3544418919fSjohnjiang 		}
3554418919fSjohnjiang 	}
3564418919fSjohnjiang 
3574418919fSjohnjiang 	/* cover all cases with help strings */
358*2d9fd380Sjfb8856606 	for (i = 0; i < RTE_DIM(string_help_strs); i++) {
3594418919fSjohnjiang 		memset(&help_token, 0, sizeof(help_token));
3604418919fSjohnjiang 		memset(help_str, 0, sizeof(help_str));
3614418919fSjohnjiang 		help_token.string_data.str = string_help_strs[i];
3624418919fSjohnjiang 		if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token,
3634418919fSjohnjiang 				help_str, sizeof(help_str)) < 0) {
3644418919fSjohnjiang 			printf("Error: help operation failed!\n");
3654418919fSjohnjiang 			return -1;
3664418919fSjohnjiang 		}
3674418919fSjohnjiang 	}
3684418919fSjohnjiang 
3694418919fSjohnjiang 	return 0;
3704418919fSjohnjiang }
371