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