xref: /f-stack/dpdk/app/test/test_cmdline_num.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_string_fns.h>
104418919fSjohnjiang 
114418919fSjohnjiang #include <cmdline_parse.h>
124418919fSjohnjiang #include <cmdline_parse_num.h>
134418919fSjohnjiang 
144418919fSjohnjiang #include "test_cmdline.h"
154418919fSjohnjiang 
164418919fSjohnjiang struct num_unsigned_str {
174418919fSjohnjiang 	const char * str;
184418919fSjohnjiang 	uint64_t result;
194418919fSjohnjiang };
204418919fSjohnjiang 
214418919fSjohnjiang struct num_signed_str {
224418919fSjohnjiang 	const char * str;
234418919fSjohnjiang 	int64_t result;
244418919fSjohnjiang };
254418919fSjohnjiang 
264418919fSjohnjiang const struct num_unsigned_str num_valid_positive_strs[] = {
274418919fSjohnjiang 		/* decimal positive */
284418919fSjohnjiang 		{"0", 0 },
294418919fSjohnjiang 		{"127", INT8_MAX },
304418919fSjohnjiang 		{"128", INT8_MAX + 1 },
314418919fSjohnjiang 		{"255", UINT8_MAX },
324418919fSjohnjiang 		{"256", UINT8_MAX + 1 },
334418919fSjohnjiang 		{"32767", INT16_MAX },
344418919fSjohnjiang 		{"32768", INT16_MAX + 1 },
354418919fSjohnjiang 		{"65535", UINT16_MAX },
364418919fSjohnjiang 		{"65536", UINT16_MAX + 1 },
374418919fSjohnjiang 		{"2147483647", INT32_MAX },
384418919fSjohnjiang 		{"2147483648", INT32_MAX + 1U },
394418919fSjohnjiang 		{"4294967295", UINT32_MAX },
404418919fSjohnjiang 		{"4294967296", UINT32_MAX + 1ULL },
414418919fSjohnjiang 		{"9223372036854775807", INT64_MAX },
424418919fSjohnjiang 		{"9223372036854775808", INT64_MAX + 1ULL},
434418919fSjohnjiang 		{"18446744073709551615", UINT64_MAX },
444418919fSjohnjiang 		/* hexadecimal (no leading zeroes) */
454418919fSjohnjiang 		{"0x0", 0 },
464418919fSjohnjiang 		{"0x7F", INT8_MAX },
474418919fSjohnjiang 		{"0x80", INT8_MAX + 1 },
484418919fSjohnjiang 		{"0xFF", UINT8_MAX },
494418919fSjohnjiang 		{"0x100", UINT8_MAX + 1 },
504418919fSjohnjiang 		{"0x7FFF", INT16_MAX },
514418919fSjohnjiang 		{"0x8000", INT16_MAX + 1 },
524418919fSjohnjiang 		{"0xFFFF", UINT16_MAX },
534418919fSjohnjiang 		{"0x10000", UINT16_MAX + 1 },
544418919fSjohnjiang 		{"0x7FFFFFFF", INT32_MAX },
554418919fSjohnjiang 		{"0x80000000", INT32_MAX + 1U },
564418919fSjohnjiang 		{"0xFFFFFFFF", UINT32_MAX },
574418919fSjohnjiang 		{"0x100000000", UINT32_MAX + 1ULL },
584418919fSjohnjiang 		{"0x7FFFFFFFFFFFFFFF", INT64_MAX },
594418919fSjohnjiang 		{"0x8000000000000000", INT64_MAX + 1ULL},
604418919fSjohnjiang 		{"0xFFFFFFFFFFFFFFFF", UINT64_MAX },
614418919fSjohnjiang 		/* hexadecimal (with leading zeroes) */
624418919fSjohnjiang 		{"0x00", 0 },
634418919fSjohnjiang 		{"0x7F", INT8_MAX },
644418919fSjohnjiang 		{"0x80", INT8_MAX + 1 },
654418919fSjohnjiang 		{"0xFF", UINT8_MAX },
664418919fSjohnjiang 		{"0x0100", UINT8_MAX + 1 },
674418919fSjohnjiang 		{"0x7FFF", INT16_MAX },
684418919fSjohnjiang 		{"0x8000", INT16_MAX + 1 },
694418919fSjohnjiang 		{"0xFFFF", UINT16_MAX },
704418919fSjohnjiang 		{"0x00010000", UINT16_MAX + 1 },
714418919fSjohnjiang 		{"0x7FFFFFFF", INT32_MAX },
724418919fSjohnjiang 		{"0x80000000", INT32_MAX + 1U },
734418919fSjohnjiang 		{"0xFFFFFFFF", UINT32_MAX },
744418919fSjohnjiang 		{"0x0000000100000000", UINT32_MAX + 1ULL },
754418919fSjohnjiang 		{"0x7FFFFFFFFFFFFFFF", INT64_MAX },
764418919fSjohnjiang 		{"0x8000000000000000", INT64_MAX + 1ULL},
774418919fSjohnjiang 		{"0xFFFFFFFFFFFFFFFF", UINT64_MAX },
784418919fSjohnjiang 		/* check all characters */
794418919fSjohnjiang 		{"0x1234567890ABCDEF", 0x1234567890ABCDEFULL },
804418919fSjohnjiang 		{"0x1234567890abcdef", 0x1234567890ABCDEFULL },
814418919fSjohnjiang 		/* binary (no leading zeroes) */
824418919fSjohnjiang 		{"0b0", 0 },
834418919fSjohnjiang 		{"0b1111111", INT8_MAX },
844418919fSjohnjiang 		{"0b10000000", INT8_MAX + 1 },
854418919fSjohnjiang 		{"0b11111111", UINT8_MAX },
864418919fSjohnjiang 		{"0b100000000", UINT8_MAX + 1 },
874418919fSjohnjiang 		{"0b111111111111111", INT16_MAX },
884418919fSjohnjiang 		{"0b1000000000000000", INT16_MAX + 1 },
894418919fSjohnjiang 		{"0b1111111111111111", UINT16_MAX },
904418919fSjohnjiang 		{"0b10000000000000000", UINT16_MAX + 1 },
914418919fSjohnjiang 		{"0b1111111111111111111111111111111", INT32_MAX },
924418919fSjohnjiang 		{"0b10000000000000000000000000000000", INT32_MAX + 1U },
934418919fSjohnjiang 		{"0b11111111111111111111111111111111", UINT32_MAX },
944418919fSjohnjiang 		{"0b100000000000000000000000000000000", UINT32_MAX + 1ULL },
954418919fSjohnjiang 		{"0b111111111111111111111111111111111111111111111111111111111111111",
964418919fSjohnjiang 				INT64_MAX },
974418919fSjohnjiang 		{"0b1000000000000000000000000000000000000000000000000000000000000000",
984418919fSjohnjiang 				INT64_MAX + 1ULL},
994418919fSjohnjiang 		{"0b1111111111111111111111111111111111111111111111111111111111111111",
1004418919fSjohnjiang 				UINT64_MAX },
1014418919fSjohnjiang 		/* binary (with leading zeroes) */
1024418919fSjohnjiang 		{"0b01111111", INT8_MAX },
1034418919fSjohnjiang 		{"0b0000000100000000", UINT8_MAX + 1 },
1044418919fSjohnjiang 		{"0b0111111111111111", INT16_MAX },
1054418919fSjohnjiang 		{"0b00000000000000010000000000000000", UINT16_MAX + 1 },
1064418919fSjohnjiang 		{"0b01111111111111111111111111111111", INT32_MAX },
1074418919fSjohnjiang 		{"0b0000000000000000000000000000000100000000000000000000000000000000",
1084418919fSjohnjiang 				UINT32_MAX + 1ULL },
1094418919fSjohnjiang 		{"0b0111111111111111111111111111111111111111111111111111111111111111",
1104418919fSjohnjiang 				INT64_MAX },
1114418919fSjohnjiang 		/* octal */
1124418919fSjohnjiang 		{"00", 0 },
1134418919fSjohnjiang 		{"0177", INT8_MAX },
1144418919fSjohnjiang 		{"0200", INT8_MAX + 1 },
1154418919fSjohnjiang 		{"0377", UINT8_MAX },
1164418919fSjohnjiang 		{"0400", UINT8_MAX + 1 },
1174418919fSjohnjiang 		{"077777", INT16_MAX },
1184418919fSjohnjiang 		{"0100000", INT16_MAX + 1 },
1194418919fSjohnjiang 		{"0177777", UINT16_MAX },
1204418919fSjohnjiang 		{"0200000", UINT16_MAX + 1 },
1214418919fSjohnjiang 		{"017777777777", INT32_MAX },
1224418919fSjohnjiang 		{"020000000000", INT32_MAX + 1U },
1234418919fSjohnjiang 		{"037777777777", UINT32_MAX },
1244418919fSjohnjiang 		{"040000000000", UINT32_MAX + 1ULL },
1254418919fSjohnjiang 		{"0777777777777777777777", INT64_MAX },
1264418919fSjohnjiang 		{"01000000000000000000000", INT64_MAX + 1ULL},
1274418919fSjohnjiang 		{"01777777777777777777777", UINT64_MAX },
1284418919fSjohnjiang 		/* check all numbers */
1294418919fSjohnjiang 		{"012345670", 012345670 },
1304418919fSjohnjiang 		{"076543210", 076543210 },
1314418919fSjohnjiang };
1324418919fSjohnjiang 
1334418919fSjohnjiang const struct num_signed_str num_valid_negative_strs[] = {
1344418919fSjohnjiang 		/* deciman negative */
1354418919fSjohnjiang 		{"-128", INT8_MIN },
1364418919fSjohnjiang 		{"-129", INT8_MIN - 1 },
1374418919fSjohnjiang 		{"-32768", INT16_MIN },
1384418919fSjohnjiang 		{"-32769", INT16_MIN - 1 },
1394418919fSjohnjiang 		{"-2147483648", INT32_MIN },
1404418919fSjohnjiang 		{"-2147483649", INT32_MIN - 1LL },
1414418919fSjohnjiang 		{"-9223372036854775808", INT64_MIN },
1424418919fSjohnjiang };
1434418919fSjohnjiang 
1444418919fSjohnjiang const struct num_unsigned_str num_garbage_positive_strs[] = {
1454418919fSjohnjiang 		/* valid strings with garbage on the end, should still be valid */
1464418919fSjohnjiang 		/* decimal */
1474418919fSjohnjiang 		{"9223372036854775807\0garbage", INT64_MAX },
1484418919fSjohnjiang 		{"9223372036854775807\tgarbage", INT64_MAX },
1494418919fSjohnjiang 		{"9223372036854775807\rgarbage", INT64_MAX },
1504418919fSjohnjiang 		{"9223372036854775807\ngarbage", INT64_MAX },
1514418919fSjohnjiang 		{"9223372036854775807#garbage", INT64_MAX },
1524418919fSjohnjiang 		{"9223372036854775807 garbage", INT64_MAX },
1534418919fSjohnjiang 		/* hex */
1544418919fSjohnjiang 		{"0x7FFFFFFFFFFFFFFF\0garbage", INT64_MAX },
1554418919fSjohnjiang 		{"0x7FFFFFFFFFFFFFFF\tgarbage", INT64_MAX },
1564418919fSjohnjiang 		{"0x7FFFFFFFFFFFFFFF\rgarbage", INT64_MAX },
1574418919fSjohnjiang 		{"0x7FFFFFFFFFFFFFFF\ngarbage", INT64_MAX },
1584418919fSjohnjiang 		{"0x7FFFFFFFFFFFFFFF#garbage", INT64_MAX },
1594418919fSjohnjiang 		{"0x7FFFFFFFFFFFFFFF garbage", INT64_MAX },
1604418919fSjohnjiang 		/* binary */
1614418919fSjohnjiang 		{"0b1111111111111111111111111111111\0garbage", INT32_MAX },
1624418919fSjohnjiang 		{"0b1111111111111111111111111111111\rgarbage", INT32_MAX },
1634418919fSjohnjiang 		{"0b1111111111111111111111111111111\tgarbage", INT32_MAX },
1644418919fSjohnjiang 		{"0b1111111111111111111111111111111\ngarbage", INT32_MAX },
1654418919fSjohnjiang 		{"0b1111111111111111111111111111111#garbage", INT32_MAX },
1664418919fSjohnjiang 		{"0b1111111111111111111111111111111 garbage", INT32_MAX },
1674418919fSjohnjiang 		/* octal */
1684418919fSjohnjiang 		{"01777777777777777777777\0garbage", UINT64_MAX },
1694418919fSjohnjiang 		{"01777777777777777777777\rgarbage", UINT64_MAX },
1704418919fSjohnjiang 		{"01777777777777777777777\tgarbage", UINT64_MAX },
1714418919fSjohnjiang 		{"01777777777777777777777\ngarbage", UINT64_MAX },
1724418919fSjohnjiang 		{"01777777777777777777777#garbage", UINT64_MAX },
1734418919fSjohnjiang 		{"01777777777777777777777 garbage", UINT64_MAX },
1744418919fSjohnjiang };
1754418919fSjohnjiang 
1764418919fSjohnjiang const struct num_signed_str num_garbage_negative_strs[] = {
1774418919fSjohnjiang 		/* valid strings with garbage on the end, should still be valid */
1784418919fSjohnjiang 		{"-9223372036854775808\0garbage", INT64_MIN },
1794418919fSjohnjiang 		{"-9223372036854775808\rgarbage", INT64_MIN },
1804418919fSjohnjiang 		{"-9223372036854775808\tgarbage", INT64_MIN },
1814418919fSjohnjiang 		{"-9223372036854775808\ngarbage", INT64_MIN },
1824418919fSjohnjiang 		{"-9223372036854775808#garbage", INT64_MIN },
1834418919fSjohnjiang 		{"-9223372036854775808 garbage", INT64_MIN },
1844418919fSjohnjiang };
1854418919fSjohnjiang 
1864418919fSjohnjiang const char * num_invalid_strs[] = {
1874418919fSjohnjiang 		"18446744073709551616", /* out of range unsigned */
1884418919fSjohnjiang 		"-9223372036854775809", /* out of range negative signed */
1894418919fSjohnjiang 		"0x10000000000000000", /* out of range hex */
1904418919fSjohnjiang 		/* out of range binary */
1914418919fSjohnjiang 		"0b10000000000000000000000000000000000000000000000000000000000000000",
1924418919fSjohnjiang 		"020000000000000000000000", /* out of range octal */
1934418919fSjohnjiang 		/* wrong chars */
1944418919fSjohnjiang 		"0123456239",
1954418919fSjohnjiang 		"0x1234580AGE",
1964418919fSjohnjiang 		"0b0111010101g001",
1974418919fSjohnjiang 		"0b01110101017001",
1984418919fSjohnjiang 		/* false negative numbers */
1994418919fSjohnjiang 		"-12345F623",
2004418919fSjohnjiang 		"-0x1234580A",
2014418919fSjohnjiang 		"-0b0111010101",
2024418919fSjohnjiang 		/* too long (128+ chars) */
2034418919fSjohnjiang 		"0b1111000011110000111100001111000011110000111100001111000011110000"
2044418919fSjohnjiang 		  "1111000011110000111100001111000011110000111100001111000011110000",
2054418919fSjohnjiang 		"1E3",
2064418919fSjohnjiang 		"0A",
2074418919fSjohnjiang 		"-B",
2084418919fSjohnjiang 		"+4",
2094418919fSjohnjiang 		"1.23G",
2104418919fSjohnjiang 		"",
2114418919fSjohnjiang 		" ",
2124418919fSjohnjiang 		"#",
2134418919fSjohnjiang 		"\r",
2144418919fSjohnjiang 		"\t",
2154418919fSjohnjiang 		"\n",
2164418919fSjohnjiang 		"\0",
2174418919fSjohnjiang };
2184418919fSjohnjiang 
2194418919fSjohnjiang static int
can_parse_unsigned(uint64_t expected_result,enum cmdline_numtype type)2204418919fSjohnjiang can_parse_unsigned(uint64_t expected_result, enum cmdline_numtype type)
2214418919fSjohnjiang {
2224418919fSjohnjiang 	switch (type) {
223*2d9fd380Sjfb8856606 	case RTE_UINT8:
2244418919fSjohnjiang 		if (expected_result > UINT8_MAX)
2254418919fSjohnjiang 			return 0;
2264418919fSjohnjiang 		break;
227*2d9fd380Sjfb8856606 	case RTE_UINT16:
2284418919fSjohnjiang 		if (expected_result > UINT16_MAX)
2294418919fSjohnjiang 			return 0;
2304418919fSjohnjiang 		break;
231*2d9fd380Sjfb8856606 	case RTE_UINT32:
2324418919fSjohnjiang 		if (expected_result > UINT32_MAX)
2334418919fSjohnjiang 			return 0;
2344418919fSjohnjiang 		break;
235*2d9fd380Sjfb8856606 	case RTE_INT8:
2364418919fSjohnjiang 		if (expected_result > INT8_MAX)
2374418919fSjohnjiang 			return 0;
2384418919fSjohnjiang 		break;
239*2d9fd380Sjfb8856606 	case RTE_INT16:
2404418919fSjohnjiang 		if (expected_result > INT16_MAX)
2414418919fSjohnjiang 			return 0;
2424418919fSjohnjiang 		break;
243*2d9fd380Sjfb8856606 	case RTE_INT32:
2444418919fSjohnjiang 		if (expected_result > INT32_MAX)
2454418919fSjohnjiang 			return 0;
2464418919fSjohnjiang 		break;
247*2d9fd380Sjfb8856606 	case RTE_INT64:
2484418919fSjohnjiang 		if (expected_result > INT64_MAX)
2494418919fSjohnjiang 			return 0;
2504418919fSjohnjiang 		break;
2514418919fSjohnjiang 	default:
2524418919fSjohnjiang 		return 1;
2534418919fSjohnjiang 	}
2544418919fSjohnjiang 	return 1;
2554418919fSjohnjiang }
2564418919fSjohnjiang 
2574418919fSjohnjiang static int
can_parse_signed(int64_t expected_result,enum cmdline_numtype type)2584418919fSjohnjiang can_parse_signed(int64_t expected_result, enum cmdline_numtype type)
2594418919fSjohnjiang {
2604418919fSjohnjiang 	switch (type) {
261*2d9fd380Sjfb8856606 	case RTE_UINT8:
2624418919fSjohnjiang 		if (expected_result > UINT8_MAX || expected_result < 0)
2634418919fSjohnjiang 			return 0;
2644418919fSjohnjiang 		break;
265*2d9fd380Sjfb8856606 	case RTE_UINT16:
2664418919fSjohnjiang 		if (expected_result > UINT16_MAX || expected_result < 0)
2674418919fSjohnjiang 			return 0;
2684418919fSjohnjiang 		break;
269*2d9fd380Sjfb8856606 	case RTE_UINT32:
2704418919fSjohnjiang 		if (expected_result > UINT32_MAX || expected_result < 0)
2714418919fSjohnjiang 			return 0;
2724418919fSjohnjiang 		break;
273*2d9fd380Sjfb8856606 	case RTE_UINT64:
2744418919fSjohnjiang 		if (expected_result < 0)
2754418919fSjohnjiang 			return 0;
2764418919fSjohnjiang 		break;
277*2d9fd380Sjfb8856606 	case RTE_INT8:
2784418919fSjohnjiang 		if (expected_result > INT8_MAX || expected_result < INT8_MIN)
2794418919fSjohnjiang 			return 0;
2804418919fSjohnjiang 		break;
281*2d9fd380Sjfb8856606 	case RTE_INT16:
2824418919fSjohnjiang 		if (expected_result > INT16_MAX || expected_result < INT16_MIN)
2834418919fSjohnjiang 			return 0;
2844418919fSjohnjiang 		break;
285*2d9fd380Sjfb8856606 	case RTE_INT32:
2864418919fSjohnjiang 		if (expected_result > INT32_MAX || expected_result < INT32_MIN)
2874418919fSjohnjiang 			return 0;
2884418919fSjohnjiang 		break;
2894418919fSjohnjiang 	default:
2904418919fSjohnjiang 		return 1;
2914418919fSjohnjiang 	}
2924418919fSjohnjiang 	return 1;
2934418919fSjohnjiang }
2944418919fSjohnjiang 
2954418919fSjohnjiang /* test invalid parameters */
2964418919fSjohnjiang int
test_parse_num_invalid_param(void)2974418919fSjohnjiang test_parse_num_invalid_param(void)
2984418919fSjohnjiang {
2994418919fSjohnjiang 	char buf[CMDLINE_TEST_BUFSIZE];
3004418919fSjohnjiang 	uint32_t result;
3014418919fSjohnjiang 	cmdline_parse_token_num_t token;
3024418919fSjohnjiang 	int ret = 0;
3034418919fSjohnjiang 
3044418919fSjohnjiang 	/* set up a token */
305*2d9fd380Sjfb8856606 	token.num_data.type = RTE_UINT32;
3064418919fSjohnjiang 
3074418919fSjohnjiang 	/* copy string to buffer */
3084418919fSjohnjiang 	strlcpy(buf, num_valid_positive_strs[0].str, sizeof(buf));
3094418919fSjohnjiang 
3104418919fSjohnjiang 	/* try all null */
3114418919fSjohnjiang 	ret = cmdline_parse_num(NULL, NULL, NULL, 0);
3124418919fSjohnjiang 	if (ret != -1) {
3134418919fSjohnjiang 		printf("Error: parser accepted null parameters!\n");
3144418919fSjohnjiang 		return -1;
3154418919fSjohnjiang 	}
3164418919fSjohnjiang 
3174418919fSjohnjiang 	/* try null token */
3184418919fSjohnjiang 	ret = cmdline_parse_num(NULL, buf, (void*)&result, sizeof(result));
3194418919fSjohnjiang 	if (ret != -1) {
3204418919fSjohnjiang 		printf("Error: parser accepted null token!\n");
3214418919fSjohnjiang 		return -1;
3224418919fSjohnjiang 	}
3234418919fSjohnjiang 
3244418919fSjohnjiang 	/* try null buf */
3254418919fSjohnjiang 	ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, NULL,
3264418919fSjohnjiang 		(void*)&result, sizeof(result));
3274418919fSjohnjiang 	if (ret != -1) {
3284418919fSjohnjiang 		printf("Error: parser accepted null string!\n");
3294418919fSjohnjiang 		return -1;
3304418919fSjohnjiang 	}
3314418919fSjohnjiang 
3324418919fSjohnjiang 	/* try null result */
3334418919fSjohnjiang 	ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, buf,
3344418919fSjohnjiang 		NULL, 0);
3354418919fSjohnjiang 	if (ret == -1) {
3364418919fSjohnjiang 		printf("Error: parser rejected null result!\n");
3374418919fSjohnjiang 		return -1;
3384418919fSjohnjiang 	}
3394418919fSjohnjiang 
3404418919fSjohnjiang 	/* test help function */
3414418919fSjohnjiang 	memset(&buf, 0, sizeof(buf));
3424418919fSjohnjiang 
3434418919fSjohnjiang 	/* try all null */
3444418919fSjohnjiang 	ret = cmdline_get_help_num(NULL, NULL, 0);
3454418919fSjohnjiang 	if (ret != -1) {
3464418919fSjohnjiang 		printf("Error: help function accepted null parameters!\n");
3474418919fSjohnjiang 		return -1;
3484418919fSjohnjiang 	}
3494418919fSjohnjiang 
3504418919fSjohnjiang 	/* try null token */
3514418919fSjohnjiang 	ret = cmdline_get_help_num(NULL, buf, sizeof(buf));
3524418919fSjohnjiang 	if (ret != -1) {
3534418919fSjohnjiang 		printf("Error: help function accepted null token!\n");
3544418919fSjohnjiang 		return -1;
3554418919fSjohnjiang 	}
3564418919fSjohnjiang 
3574418919fSjohnjiang 	/* coverage! */
3584418919fSjohnjiang 	ret = cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf));
3594418919fSjohnjiang 	if (ret < 0) {
3604418919fSjohnjiang 		printf("Error: help function failed with valid parameters!\n");
3614418919fSjohnjiang 		return -1;
3624418919fSjohnjiang 	}
3634418919fSjohnjiang 
3644418919fSjohnjiang 	return 0;
3654418919fSjohnjiang }
3664418919fSjohnjiang /* test valid parameters but invalid data */
3674418919fSjohnjiang int
test_parse_num_invalid_data(void)3684418919fSjohnjiang test_parse_num_invalid_data(void)
3694418919fSjohnjiang {
3704418919fSjohnjiang 	enum cmdline_numtype type;
3714418919fSjohnjiang 	int ret = 0;
3724418919fSjohnjiang 	unsigned i;
3734418919fSjohnjiang 	char buf[CMDLINE_TEST_BUFSIZE];
3744418919fSjohnjiang 	uint64_t result; /* pick largest buffer */
3754418919fSjohnjiang 	cmdline_parse_token_num_t token;
3764418919fSjohnjiang 
3774418919fSjohnjiang 	/* cycle through all possible parsed types */
378*2d9fd380Sjfb8856606 	for (type = RTE_UINT8; type <= RTE_INT64; type++) {
3794418919fSjohnjiang 		token.num_data.type = type;
3804418919fSjohnjiang 
3814418919fSjohnjiang 		/* test full strings */
382*2d9fd380Sjfb8856606 		for (i = 0; i < RTE_DIM(num_invalid_strs); i++) {
3834418919fSjohnjiang 
3844418919fSjohnjiang 			memset(&result, 0, sizeof(uint64_t));
3854418919fSjohnjiang 			memset(&buf, 0, sizeof(buf));
3864418919fSjohnjiang 
3874418919fSjohnjiang 			ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token,
3884418919fSjohnjiang 				num_invalid_strs[i], (void*)&result, sizeof(result));
3894418919fSjohnjiang 			if (ret != -1) {
3904418919fSjohnjiang 				/* get some info about what we are trying to parse */
3914418919fSjohnjiang 				cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
3924418919fSjohnjiang 						buf, sizeof(buf));
3934418919fSjohnjiang 
3944418919fSjohnjiang 				printf("Error: parsing %s as %s succeeded!\n",
3954418919fSjohnjiang 						num_invalid_strs[i], buf);
3964418919fSjohnjiang 				return -1;
3974418919fSjohnjiang 			}
3984418919fSjohnjiang 		}
3994418919fSjohnjiang 	}
4004418919fSjohnjiang 	return 0;
4014418919fSjohnjiang }
4024418919fSjohnjiang 
4034418919fSjohnjiang /* test valid parameters and data */
4044418919fSjohnjiang int
test_parse_num_valid(void)4054418919fSjohnjiang test_parse_num_valid(void)
4064418919fSjohnjiang {
4074418919fSjohnjiang 	int ret = 0;
4084418919fSjohnjiang 	enum cmdline_numtype type;
4094418919fSjohnjiang 	unsigned i;
4104418919fSjohnjiang 	char buf[CMDLINE_TEST_BUFSIZE];
4114418919fSjohnjiang 	uint64_t result;
4124418919fSjohnjiang 	cmdline_parse_token_num_t token;
4134418919fSjohnjiang 
4144418919fSjohnjiang 	/** valid strings **/
4154418919fSjohnjiang 
4164418919fSjohnjiang 	/* cycle through all possible parsed types */
417*2d9fd380Sjfb8856606 	for (type = RTE_UINT8; type <= RTE_INT64; type++) {
4184418919fSjohnjiang 		token.num_data.type = type;
4194418919fSjohnjiang 
4204418919fSjohnjiang 		/* test positive strings */
421*2d9fd380Sjfb8856606 		for (i = 0; i < RTE_DIM(num_valid_positive_strs); i++) {
4224418919fSjohnjiang 			result = 0;
4234418919fSjohnjiang 			memset(&buf, 0, sizeof(buf));
4244418919fSjohnjiang 
4254418919fSjohnjiang 			cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
4264418919fSjohnjiang 					buf, sizeof(buf));
4274418919fSjohnjiang 
4284418919fSjohnjiang 			ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
4294418919fSjohnjiang 				num_valid_positive_strs[i].str,
4304418919fSjohnjiang 				(void*)&result, sizeof(result));
4314418919fSjohnjiang 
4324418919fSjohnjiang 			/* if it should have passed but didn't, or if it should have failed but didn't */
4334418919fSjohnjiang 			if ((ret < 0) == (can_parse_unsigned(num_valid_positive_strs[i].result, type) > 0)) {
4344418919fSjohnjiang 				printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
4354418919fSjohnjiang 						num_valid_positive_strs[i].str, buf);
4364418919fSjohnjiang 				return -1;
4374418919fSjohnjiang 			}
4384418919fSjohnjiang 			/* check if result matches what it should have matched
4394418919fSjohnjiang 			 * since unsigned numbers don't care about number of bits, we can just convert
4404418919fSjohnjiang 			 * everything to uint64_t without any worries. */
4414418919fSjohnjiang 			if (ret > 0 && num_valid_positive_strs[i].result != result) {
4424418919fSjohnjiang 				printf("Error: parsing %s as %s failed: result mismatch!\n",
4434418919fSjohnjiang 						num_valid_positive_strs[i].str, buf);
4444418919fSjohnjiang 				return -1;
4454418919fSjohnjiang 			}
4464418919fSjohnjiang 		}
4474418919fSjohnjiang 
4484418919fSjohnjiang 		/* test negative strings */
449*2d9fd380Sjfb8856606 		for (i = 0; i < RTE_DIM(num_valid_negative_strs); i++) {
4504418919fSjohnjiang 			result = 0;
4514418919fSjohnjiang 			memset(&buf, 0, sizeof(buf));
4524418919fSjohnjiang 
4534418919fSjohnjiang 			cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
4544418919fSjohnjiang 					buf, sizeof(buf));
4554418919fSjohnjiang 
4564418919fSjohnjiang 			ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
4574418919fSjohnjiang 				num_valid_negative_strs[i].str,
4584418919fSjohnjiang 				(void*)&result, sizeof(result));
4594418919fSjohnjiang 
4604418919fSjohnjiang 			/* if it should have passed but didn't, or if it should have failed but didn't */
4614418919fSjohnjiang 			if ((ret < 0) == (can_parse_signed(num_valid_negative_strs[i].result, type) > 0)) {
4624418919fSjohnjiang 				printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
4634418919fSjohnjiang 						num_valid_negative_strs[i].str, buf);
4644418919fSjohnjiang 				return -1;
4654418919fSjohnjiang 			}
4664418919fSjohnjiang 			/* check if result matches what it should have matched
4674418919fSjohnjiang 			 * the result is signed in this case, so we have to account for that */
4684418919fSjohnjiang 			if (ret > 0) {
4694418919fSjohnjiang 				/* detect negative */
4704418919fSjohnjiang 				switch (type) {
471*2d9fd380Sjfb8856606 				case RTE_INT8:
4724418919fSjohnjiang 					result = (int8_t) result;
4734418919fSjohnjiang 					break;
474*2d9fd380Sjfb8856606 				case RTE_INT16:
4754418919fSjohnjiang 					result = (int16_t) result;
4764418919fSjohnjiang 					break;
477*2d9fd380Sjfb8856606 				case RTE_INT32:
4784418919fSjohnjiang 					result = (int32_t) result;
4794418919fSjohnjiang 					break;
4804418919fSjohnjiang 				default:
4814418919fSjohnjiang 					break;
4824418919fSjohnjiang 				}
4834418919fSjohnjiang 				if (num_valid_negative_strs[i].result == (int64_t) result)
4844418919fSjohnjiang 					continue;
4854418919fSjohnjiang 				printf("Error: parsing %s as %s failed: result mismatch!\n",
4864418919fSjohnjiang 						num_valid_negative_strs[i].str, buf);
4874418919fSjohnjiang 				return -1;
4884418919fSjohnjiang 			}
4894418919fSjohnjiang 		}
4904418919fSjohnjiang 	}
4914418919fSjohnjiang 
4924418919fSjohnjiang 	/** garbage strings **/
4934418919fSjohnjiang 
4944418919fSjohnjiang 	/* cycle through all possible parsed types */
495*2d9fd380Sjfb8856606 	for (type = RTE_UINT8; type <= RTE_INT64; type++) {
4964418919fSjohnjiang 		token.num_data.type = type;
4974418919fSjohnjiang 
4984418919fSjohnjiang 		/* test positive garbage strings */
499*2d9fd380Sjfb8856606 		for (i = 0; i < RTE_DIM(num_garbage_positive_strs); i++) {
5004418919fSjohnjiang 			result = 0;
5014418919fSjohnjiang 			memset(&buf, 0, sizeof(buf));
5024418919fSjohnjiang 
5034418919fSjohnjiang 			cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
5044418919fSjohnjiang 					buf, sizeof(buf));
5054418919fSjohnjiang 
5064418919fSjohnjiang 			ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
5074418919fSjohnjiang 				num_garbage_positive_strs[i].str,
5084418919fSjohnjiang 				(void*)&result, sizeof(result));
5094418919fSjohnjiang 
5104418919fSjohnjiang 			/* if it should have passed but didn't, or if it should have failed but didn't */
5114418919fSjohnjiang 			if ((ret < 0) == (can_parse_unsigned(num_garbage_positive_strs[i].result, type) > 0)) {
5124418919fSjohnjiang 				printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
5134418919fSjohnjiang 						num_garbage_positive_strs[i].str, buf);
5144418919fSjohnjiang 				return -1;
5154418919fSjohnjiang 			}
5164418919fSjohnjiang 			/* check if result matches what it should have matched
5174418919fSjohnjiang 			 * since unsigned numbers don't care about number of bits, we can just convert
5184418919fSjohnjiang 			 * everything to uint64_t without any worries. */
5194418919fSjohnjiang 			if (ret > 0 && num_garbage_positive_strs[i].result != result) {
5204418919fSjohnjiang 				printf("Error: parsing %s as %s failed: result mismatch!\n",
5214418919fSjohnjiang 						num_garbage_positive_strs[i].str, buf);
5224418919fSjohnjiang 				return -1;
5234418919fSjohnjiang 			}
5244418919fSjohnjiang 		}
5254418919fSjohnjiang 
5264418919fSjohnjiang 		/* test negative strings */
527*2d9fd380Sjfb8856606 		for (i = 0; i < RTE_DIM(num_garbage_negative_strs); i++) {
5284418919fSjohnjiang 			result = 0;
5294418919fSjohnjiang 			memset(&buf, 0, sizeof(buf));
5304418919fSjohnjiang 
5314418919fSjohnjiang 			cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
5324418919fSjohnjiang 					buf, sizeof(buf));
5334418919fSjohnjiang 
5344418919fSjohnjiang 			ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
5354418919fSjohnjiang 				num_garbage_negative_strs[i].str,
5364418919fSjohnjiang 				(void*)&result, sizeof(result));
5374418919fSjohnjiang 
5384418919fSjohnjiang 			/* if it should have passed but didn't, or if it should have failed but didn't */
5394418919fSjohnjiang 			if ((ret < 0) == (can_parse_signed(num_garbage_negative_strs[i].result, type) > 0)) {
5404418919fSjohnjiang 				printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
5414418919fSjohnjiang 						num_garbage_negative_strs[i].str, buf);
5424418919fSjohnjiang 				return -1;
5434418919fSjohnjiang 			}
5444418919fSjohnjiang 			/* check if result matches what it should have matched
5454418919fSjohnjiang 			 * the result is signed in this case, so we have to account for that */
5464418919fSjohnjiang 			if (ret > 0) {
5474418919fSjohnjiang 				/* detect negative */
5484418919fSjohnjiang 				switch (type) {
549*2d9fd380Sjfb8856606 				case RTE_INT8:
5504418919fSjohnjiang 					if (result & (INT8_MAX + 1))
5514418919fSjohnjiang 						result |= 0xFFFFFFFFFFFFFF00ULL;
5524418919fSjohnjiang 					break;
553*2d9fd380Sjfb8856606 				case RTE_INT16:
5544418919fSjohnjiang 					if (result & (INT16_MAX + 1))
5554418919fSjohnjiang 						result |= 0xFFFFFFFFFFFF0000ULL;
5564418919fSjohnjiang 					break;
557*2d9fd380Sjfb8856606 				case RTE_INT32:
5584418919fSjohnjiang 					if (result & (INT32_MAX + 1ULL))
5594418919fSjohnjiang 						result |= 0xFFFFFFFF00000000ULL;
5604418919fSjohnjiang 					break;
5614418919fSjohnjiang 				default:
5624418919fSjohnjiang 					break;
5634418919fSjohnjiang 				}
5644418919fSjohnjiang 				if (num_garbage_negative_strs[i].result == (int64_t) result)
5654418919fSjohnjiang 					continue;
5664418919fSjohnjiang 				printf("Error: parsing %s as %s failed: result mismatch!\n",
5674418919fSjohnjiang 						num_garbage_negative_strs[i].str, buf);
5684418919fSjohnjiang 				return -1;
5694418919fSjohnjiang 			}
5704418919fSjohnjiang 		}
5714418919fSjohnjiang 	}
5724418919fSjohnjiang 
5734418919fSjohnjiang 	memset(&buf, 0, sizeof(buf));
5744418919fSjohnjiang 
5754418919fSjohnjiang 	/* coverage! */
5764418919fSjohnjiang 	cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
5774418919fSjohnjiang 			buf, sizeof(buf));
5784418919fSjohnjiang 
5794418919fSjohnjiang 	return 0;
5804418919fSjohnjiang }
581