1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson * Copyright(c) 2010-2014 Intel Corporation
3a9de470cSBruce Richardson */
4a9de470cSBruce Richardson
5a9de470cSBruce Richardson #include <stdio.h>
6a9de470cSBruce Richardson #include <string.h>
7a9de470cSBruce Richardson #include <inttypes.h>
8a9de470cSBruce Richardson
9a9de470cSBruce Richardson #include <rte_string_fns.h>
10a9de470cSBruce Richardson
11a9de470cSBruce Richardson #include <cmdline_parse.h>
12a9de470cSBruce Richardson #include <cmdline_parse_num.h>
13a9de470cSBruce Richardson
14a9de470cSBruce Richardson #include "test_cmdline.h"
15a9de470cSBruce Richardson
16a9de470cSBruce Richardson struct num_unsigned_str {
17a9de470cSBruce Richardson const char * str;
18a9de470cSBruce Richardson uint64_t result;
19a9de470cSBruce Richardson };
20a9de470cSBruce Richardson
21a9de470cSBruce Richardson struct num_signed_str {
22a9de470cSBruce Richardson const char * str;
23a9de470cSBruce Richardson int64_t result;
24a9de470cSBruce Richardson };
25a9de470cSBruce Richardson
26a9de470cSBruce Richardson const struct num_unsigned_str num_valid_positive_strs[] = {
27a9de470cSBruce Richardson /* decimal positive */
28a9de470cSBruce Richardson {"0", 0 },
29a9de470cSBruce Richardson {"127", INT8_MAX },
30a9de470cSBruce Richardson {"128", INT8_MAX + 1 },
31a9de470cSBruce Richardson {"255", UINT8_MAX },
32a9de470cSBruce Richardson {"256", UINT8_MAX + 1 },
33a9de470cSBruce Richardson {"32767", INT16_MAX },
34a9de470cSBruce Richardson {"32768", INT16_MAX + 1 },
35a9de470cSBruce Richardson {"65535", UINT16_MAX },
36a9de470cSBruce Richardson {"65536", UINT16_MAX + 1 },
37a9de470cSBruce Richardson {"2147483647", INT32_MAX },
38a9de470cSBruce Richardson {"2147483648", INT32_MAX + 1U },
39a9de470cSBruce Richardson {"4294967295", UINT32_MAX },
40a9de470cSBruce Richardson {"4294967296", UINT32_MAX + 1ULL },
41a9de470cSBruce Richardson {"9223372036854775807", INT64_MAX },
42a9de470cSBruce Richardson {"9223372036854775808", INT64_MAX + 1ULL},
43a9de470cSBruce Richardson {"18446744073709551615", UINT64_MAX },
44a9de470cSBruce Richardson /* hexadecimal (no leading zeroes) */
45a9de470cSBruce Richardson {"0x0", 0 },
46a9de470cSBruce Richardson {"0x7F", INT8_MAX },
47a9de470cSBruce Richardson {"0x80", INT8_MAX + 1 },
48a9de470cSBruce Richardson {"0xFF", UINT8_MAX },
49a9de470cSBruce Richardson {"0x100", UINT8_MAX + 1 },
50a9de470cSBruce Richardson {"0x7FFF", INT16_MAX },
51a9de470cSBruce Richardson {"0x8000", INT16_MAX + 1 },
52a9de470cSBruce Richardson {"0xFFFF", UINT16_MAX },
53a9de470cSBruce Richardson {"0x10000", UINT16_MAX + 1 },
54a9de470cSBruce Richardson {"0x7FFFFFFF", INT32_MAX },
55a9de470cSBruce Richardson {"0x80000000", INT32_MAX + 1U },
56a9de470cSBruce Richardson {"0xFFFFFFFF", UINT32_MAX },
57a9de470cSBruce Richardson {"0x100000000", UINT32_MAX + 1ULL },
58a9de470cSBruce Richardson {"0x7FFFFFFFFFFFFFFF", INT64_MAX },
59a9de470cSBruce Richardson {"0x8000000000000000", INT64_MAX + 1ULL},
60a9de470cSBruce Richardson {"0xFFFFFFFFFFFFFFFF", UINT64_MAX },
61a9de470cSBruce Richardson /* hexadecimal (with leading zeroes) */
62a9de470cSBruce Richardson {"0x00", 0 },
63a9de470cSBruce Richardson {"0x7F", INT8_MAX },
64a9de470cSBruce Richardson {"0x80", INT8_MAX + 1 },
65a9de470cSBruce Richardson {"0xFF", UINT8_MAX },
66a9de470cSBruce Richardson {"0x0100", UINT8_MAX + 1 },
67a9de470cSBruce Richardson {"0x7FFF", INT16_MAX },
68a9de470cSBruce Richardson {"0x8000", INT16_MAX + 1 },
69a9de470cSBruce Richardson {"0xFFFF", UINT16_MAX },
70a9de470cSBruce Richardson {"0x00010000", UINT16_MAX + 1 },
71a9de470cSBruce Richardson {"0x7FFFFFFF", INT32_MAX },
72a9de470cSBruce Richardson {"0x80000000", INT32_MAX + 1U },
73a9de470cSBruce Richardson {"0xFFFFFFFF", UINT32_MAX },
74a9de470cSBruce Richardson {"0x0000000100000000", UINT32_MAX + 1ULL },
75a9de470cSBruce Richardson {"0x7FFFFFFFFFFFFFFF", INT64_MAX },
76a9de470cSBruce Richardson {"0x8000000000000000", INT64_MAX + 1ULL},
77a9de470cSBruce Richardson {"0xFFFFFFFFFFFFFFFF", UINT64_MAX },
78a9de470cSBruce Richardson /* check all characters */
79a9de470cSBruce Richardson {"0x1234567890ABCDEF", 0x1234567890ABCDEFULL },
80a9de470cSBruce Richardson {"0x1234567890abcdef", 0x1234567890ABCDEFULL },
81a9de470cSBruce Richardson /* binary (no leading zeroes) */
82a9de470cSBruce Richardson {"0b0", 0 },
83a9de470cSBruce Richardson {"0b1111111", INT8_MAX },
84a9de470cSBruce Richardson {"0b10000000", INT8_MAX + 1 },
85a9de470cSBruce Richardson {"0b11111111", UINT8_MAX },
86a9de470cSBruce Richardson {"0b100000000", UINT8_MAX + 1 },
87a9de470cSBruce Richardson {"0b111111111111111", INT16_MAX },
88a9de470cSBruce Richardson {"0b1000000000000000", INT16_MAX + 1 },
89a9de470cSBruce Richardson {"0b1111111111111111", UINT16_MAX },
90a9de470cSBruce Richardson {"0b10000000000000000", UINT16_MAX + 1 },
91a9de470cSBruce Richardson {"0b1111111111111111111111111111111", INT32_MAX },
92a9de470cSBruce Richardson {"0b10000000000000000000000000000000", INT32_MAX + 1U },
93a9de470cSBruce Richardson {"0b11111111111111111111111111111111", UINT32_MAX },
94a9de470cSBruce Richardson {"0b100000000000000000000000000000000", UINT32_MAX + 1ULL },
95a9de470cSBruce Richardson {"0b111111111111111111111111111111111111111111111111111111111111111",
96a9de470cSBruce Richardson INT64_MAX },
97a9de470cSBruce Richardson {"0b1000000000000000000000000000000000000000000000000000000000000000",
98a9de470cSBruce Richardson INT64_MAX + 1ULL},
99a9de470cSBruce Richardson {"0b1111111111111111111111111111111111111111111111111111111111111111",
100a9de470cSBruce Richardson UINT64_MAX },
101a9de470cSBruce Richardson /* binary (with leading zeroes) */
102a9de470cSBruce Richardson {"0b01111111", INT8_MAX },
103a9de470cSBruce Richardson {"0b0000000100000000", UINT8_MAX + 1 },
104a9de470cSBruce Richardson {"0b0111111111111111", INT16_MAX },
105a9de470cSBruce Richardson {"0b00000000000000010000000000000000", UINT16_MAX + 1 },
106a9de470cSBruce Richardson {"0b01111111111111111111111111111111", INT32_MAX },
107a9de470cSBruce Richardson {"0b0000000000000000000000000000000100000000000000000000000000000000",
108a9de470cSBruce Richardson UINT32_MAX + 1ULL },
109a9de470cSBruce Richardson {"0b0111111111111111111111111111111111111111111111111111111111111111",
110a9de470cSBruce Richardson INT64_MAX },
111a9de470cSBruce Richardson /* octal */
112a9de470cSBruce Richardson {"00", 0 },
113a9de470cSBruce Richardson {"0177", INT8_MAX },
114a9de470cSBruce Richardson {"0200", INT8_MAX + 1 },
115a9de470cSBruce Richardson {"0377", UINT8_MAX },
116a9de470cSBruce Richardson {"0400", UINT8_MAX + 1 },
117a9de470cSBruce Richardson {"077777", INT16_MAX },
118a9de470cSBruce Richardson {"0100000", INT16_MAX + 1 },
119a9de470cSBruce Richardson {"0177777", UINT16_MAX },
120a9de470cSBruce Richardson {"0200000", UINT16_MAX + 1 },
121a9de470cSBruce Richardson {"017777777777", INT32_MAX },
122a9de470cSBruce Richardson {"020000000000", INT32_MAX + 1U },
123a9de470cSBruce Richardson {"037777777777", UINT32_MAX },
124a9de470cSBruce Richardson {"040000000000", UINT32_MAX + 1ULL },
125a9de470cSBruce Richardson {"0777777777777777777777", INT64_MAX },
126a9de470cSBruce Richardson {"01000000000000000000000", INT64_MAX + 1ULL},
127a9de470cSBruce Richardson {"01777777777777777777777", UINT64_MAX },
128a9de470cSBruce Richardson /* check all numbers */
129a9de470cSBruce Richardson {"012345670", 012345670 },
130a9de470cSBruce Richardson {"076543210", 076543210 },
131a9de470cSBruce Richardson };
132a9de470cSBruce Richardson
133a9de470cSBruce Richardson const struct num_signed_str num_valid_negative_strs[] = {
134a9de470cSBruce Richardson /* deciman negative */
135a9de470cSBruce Richardson {"-128", INT8_MIN },
136a9de470cSBruce Richardson {"-129", INT8_MIN - 1 },
137a9de470cSBruce Richardson {"-32768", INT16_MIN },
138a9de470cSBruce Richardson {"-32769", INT16_MIN - 1 },
139a9de470cSBruce Richardson {"-2147483648", INT32_MIN },
140a9de470cSBruce Richardson {"-2147483649", INT32_MIN - 1LL },
141a9de470cSBruce Richardson {"-9223372036854775808", INT64_MIN },
142a9de470cSBruce Richardson };
143a9de470cSBruce Richardson
144a9de470cSBruce Richardson const struct num_unsigned_str num_garbage_positive_strs[] = {
145a9de470cSBruce Richardson /* valid strings with garbage on the end, should still be valid */
146a9de470cSBruce Richardson /* decimal */
147a9de470cSBruce Richardson {"9223372036854775807\0garbage", INT64_MAX },
148a9de470cSBruce Richardson {"9223372036854775807\tgarbage", INT64_MAX },
149a9de470cSBruce Richardson {"9223372036854775807\rgarbage", INT64_MAX },
150a9de470cSBruce Richardson {"9223372036854775807\ngarbage", INT64_MAX },
151a9de470cSBruce Richardson {"9223372036854775807#garbage", INT64_MAX },
152a9de470cSBruce Richardson {"9223372036854775807 garbage", INT64_MAX },
153a9de470cSBruce Richardson /* hex */
154a9de470cSBruce Richardson {"0x7FFFFFFFFFFFFFFF\0garbage", INT64_MAX },
155a9de470cSBruce Richardson {"0x7FFFFFFFFFFFFFFF\tgarbage", INT64_MAX },
156a9de470cSBruce Richardson {"0x7FFFFFFFFFFFFFFF\rgarbage", INT64_MAX },
157a9de470cSBruce Richardson {"0x7FFFFFFFFFFFFFFF\ngarbage", INT64_MAX },
158a9de470cSBruce Richardson {"0x7FFFFFFFFFFFFFFF#garbage", INT64_MAX },
159a9de470cSBruce Richardson {"0x7FFFFFFFFFFFFFFF garbage", INT64_MAX },
160a9de470cSBruce Richardson /* binary */
161a9de470cSBruce Richardson {"0b1111111111111111111111111111111\0garbage", INT32_MAX },
162a9de470cSBruce Richardson {"0b1111111111111111111111111111111\rgarbage", INT32_MAX },
163a9de470cSBruce Richardson {"0b1111111111111111111111111111111\tgarbage", INT32_MAX },
164a9de470cSBruce Richardson {"0b1111111111111111111111111111111\ngarbage", INT32_MAX },
165a9de470cSBruce Richardson {"0b1111111111111111111111111111111#garbage", INT32_MAX },
166a9de470cSBruce Richardson {"0b1111111111111111111111111111111 garbage", INT32_MAX },
167a9de470cSBruce Richardson /* octal */
168a9de470cSBruce Richardson {"01777777777777777777777\0garbage", UINT64_MAX },
169a9de470cSBruce Richardson {"01777777777777777777777\rgarbage", UINT64_MAX },
170a9de470cSBruce Richardson {"01777777777777777777777\tgarbage", UINT64_MAX },
171a9de470cSBruce Richardson {"01777777777777777777777\ngarbage", UINT64_MAX },
172a9de470cSBruce Richardson {"01777777777777777777777#garbage", UINT64_MAX },
173a9de470cSBruce Richardson {"01777777777777777777777 garbage", UINT64_MAX },
174a9de470cSBruce Richardson };
175a9de470cSBruce Richardson
176a9de470cSBruce Richardson const struct num_signed_str num_garbage_negative_strs[] = {
177a9de470cSBruce Richardson /* valid strings with garbage on the end, should still be valid */
178a9de470cSBruce Richardson {"-9223372036854775808\0garbage", INT64_MIN },
179a9de470cSBruce Richardson {"-9223372036854775808\rgarbage", INT64_MIN },
180a9de470cSBruce Richardson {"-9223372036854775808\tgarbage", INT64_MIN },
181a9de470cSBruce Richardson {"-9223372036854775808\ngarbage", INT64_MIN },
182a9de470cSBruce Richardson {"-9223372036854775808#garbage", INT64_MIN },
183a9de470cSBruce Richardson {"-9223372036854775808 garbage", INT64_MIN },
184a9de470cSBruce Richardson };
185a9de470cSBruce Richardson
186a9de470cSBruce Richardson const char * num_invalid_strs[] = {
187a9de470cSBruce Richardson "18446744073709551616", /* out of range unsigned */
188a9de470cSBruce Richardson "-9223372036854775809", /* out of range negative signed */
189a9de470cSBruce Richardson "0x10000000000000000", /* out of range hex */
190a9de470cSBruce Richardson /* out of range binary */
191a9de470cSBruce Richardson "0b10000000000000000000000000000000000000000000000000000000000000000",
192a9de470cSBruce Richardson "020000000000000000000000", /* out of range octal */
193a9de470cSBruce Richardson /* wrong chars */
194a9de470cSBruce Richardson "0123456239",
195a9de470cSBruce Richardson "0x1234580AGE",
196a9de470cSBruce Richardson "0b0111010101g001",
197a9de470cSBruce Richardson "0b01110101017001",
198a9de470cSBruce Richardson /* false negative numbers */
199a9de470cSBruce Richardson "-12345F623",
200a9de470cSBruce Richardson "-0x1234580A",
201a9de470cSBruce Richardson "-0b0111010101",
202a9de470cSBruce Richardson /* too long (128+ chars) */
203*5ac070cfSKevin Traynor ("0b1111000011110000111100001111000011110000111100001111000011110000"
204*5ac070cfSKevin Traynor "1111000011110000111100001111000011110000111100001111000011110000"),
205a9de470cSBruce Richardson "1E3",
206a9de470cSBruce Richardson "0A",
207a9de470cSBruce Richardson "-B",
208a9de470cSBruce Richardson "+4",
209a9de470cSBruce Richardson "1.23G",
210a9de470cSBruce Richardson "",
211a9de470cSBruce Richardson " ",
212a9de470cSBruce Richardson "#",
213a9de470cSBruce Richardson "\r",
214a9de470cSBruce Richardson "\t",
215a9de470cSBruce Richardson "\n",
216a9de470cSBruce Richardson "\0",
217a9de470cSBruce Richardson };
218a9de470cSBruce Richardson
219a9de470cSBruce Richardson static int
can_parse_unsigned(uint64_t expected_result,enum cmdline_numtype type)220a9de470cSBruce Richardson can_parse_unsigned(uint64_t expected_result, enum cmdline_numtype type)
221a9de470cSBruce Richardson {
222a9de470cSBruce Richardson switch (type) {
223c2341bb6SDmitry Kozlyuk case RTE_UINT8:
224a9de470cSBruce Richardson if (expected_result > UINT8_MAX)
225a9de470cSBruce Richardson return 0;
226a9de470cSBruce Richardson break;
227c2341bb6SDmitry Kozlyuk case RTE_UINT16:
228a9de470cSBruce Richardson if (expected_result > UINT16_MAX)
229a9de470cSBruce Richardson return 0;
230a9de470cSBruce Richardson break;
231c2341bb6SDmitry Kozlyuk case RTE_UINT32:
232a9de470cSBruce Richardson if (expected_result > UINT32_MAX)
233a9de470cSBruce Richardson return 0;
234a9de470cSBruce Richardson break;
235c2341bb6SDmitry Kozlyuk case RTE_INT8:
236a9de470cSBruce Richardson if (expected_result > INT8_MAX)
237a9de470cSBruce Richardson return 0;
238a9de470cSBruce Richardson break;
239c2341bb6SDmitry Kozlyuk case RTE_INT16:
240a9de470cSBruce Richardson if (expected_result > INT16_MAX)
241a9de470cSBruce Richardson return 0;
242a9de470cSBruce Richardson break;
243c2341bb6SDmitry Kozlyuk case RTE_INT32:
244a9de470cSBruce Richardson if (expected_result > INT32_MAX)
245a9de470cSBruce Richardson return 0;
246a9de470cSBruce Richardson break;
247c2341bb6SDmitry Kozlyuk case RTE_INT64:
248a9de470cSBruce Richardson if (expected_result > INT64_MAX)
249a9de470cSBruce Richardson return 0;
250a9de470cSBruce Richardson break;
251a9de470cSBruce Richardson default:
252a9de470cSBruce Richardson return 1;
253a9de470cSBruce Richardson }
254a9de470cSBruce Richardson return 1;
255a9de470cSBruce Richardson }
256a9de470cSBruce Richardson
257a9de470cSBruce Richardson static int
can_parse_signed(int64_t expected_result,enum cmdline_numtype type)258a9de470cSBruce Richardson can_parse_signed(int64_t expected_result, enum cmdline_numtype type)
259a9de470cSBruce Richardson {
260a9de470cSBruce Richardson switch (type) {
261c2341bb6SDmitry Kozlyuk case RTE_UINT8:
262a9de470cSBruce Richardson if (expected_result > UINT8_MAX || expected_result < 0)
263a9de470cSBruce Richardson return 0;
264a9de470cSBruce Richardson break;
265c2341bb6SDmitry Kozlyuk case RTE_UINT16:
266a9de470cSBruce Richardson if (expected_result > UINT16_MAX || expected_result < 0)
267a9de470cSBruce Richardson return 0;
268a9de470cSBruce Richardson break;
269c2341bb6SDmitry Kozlyuk case RTE_UINT32:
270a9de470cSBruce Richardson if (expected_result > UINT32_MAX || expected_result < 0)
271a9de470cSBruce Richardson return 0;
272a9de470cSBruce Richardson break;
273c2341bb6SDmitry Kozlyuk case RTE_UINT64:
274a9de470cSBruce Richardson if (expected_result < 0)
275a9de470cSBruce Richardson return 0;
276a9de470cSBruce Richardson break;
277c2341bb6SDmitry Kozlyuk case RTE_INT8:
278a9de470cSBruce Richardson if (expected_result > INT8_MAX || expected_result < INT8_MIN)
279a9de470cSBruce Richardson return 0;
280a9de470cSBruce Richardson break;
281c2341bb6SDmitry Kozlyuk case RTE_INT16:
282a9de470cSBruce Richardson if (expected_result > INT16_MAX || expected_result < INT16_MIN)
283a9de470cSBruce Richardson return 0;
284a9de470cSBruce Richardson break;
285c2341bb6SDmitry Kozlyuk case RTE_INT32:
286a9de470cSBruce Richardson if (expected_result > INT32_MAX || expected_result < INT32_MIN)
287a9de470cSBruce Richardson return 0;
288a9de470cSBruce Richardson break;
289a9de470cSBruce Richardson default:
290a9de470cSBruce Richardson return 1;
291a9de470cSBruce Richardson }
292a9de470cSBruce Richardson return 1;
293a9de470cSBruce Richardson }
294a9de470cSBruce Richardson
295a9de470cSBruce Richardson /* test invalid parameters */
296a9de470cSBruce Richardson int
test_parse_num_invalid_param(void)297a9de470cSBruce Richardson test_parse_num_invalid_param(void)
298a9de470cSBruce Richardson {
299a9de470cSBruce Richardson char buf[CMDLINE_TEST_BUFSIZE];
300a9de470cSBruce Richardson uint32_t result;
301a9de470cSBruce Richardson cmdline_parse_token_num_t token;
302a9de470cSBruce Richardson int ret = 0;
303a9de470cSBruce Richardson
304a9de470cSBruce Richardson /* set up a token */
305c2341bb6SDmitry Kozlyuk token.num_data.type = RTE_UINT32;
306a9de470cSBruce Richardson
307a9de470cSBruce Richardson /* copy string to buffer */
308f9acaf84SBruce Richardson strlcpy(buf, num_valid_positive_strs[0].str, sizeof(buf));
309a9de470cSBruce Richardson
310a9de470cSBruce Richardson /* try all null */
311a9de470cSBruce Richardson ret = cmdline_parse_num(NULL, NULL, NULL, 0);
312a9de470cSBruce Richardson if (ret != -1) {
313a9de470cSBruce Richardson printf("Error: parser accepted null parameters!\n");
314a9de470cSBruce Richardson return -1;
315a9de470cSBruce Richardson }
316a9de470cSBruce Richardson
317a9de470cSBruce Richardson /* try null token */
318a9de470cSBruce Richardson ret = cmdline_parse_num(NULL, buf, (void*)&result, sizeof(result));
319a9de470cSBruce Richardson if (ret != -1) {
320a9de470cSBruce Richardson printf("Error: parser accepted null token!\n");
321a9de470cSBruce Richardson return -1;
322a9de470cSBruce Richardson }
323a9de470cSBruce Richardson
324a9de470cSBruce Richardson /* try null buf */
325a9de470cSBruce Richardson ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, NULL,
326a9de470cSBruce Richardson (void*)&result, sizeof(result));
327a9de470cSBruce Richardson if (ret != -1) {
328a9de470cSBruce Richardson printf("Error: parser accepted null string!\n");
329a9de470cSBruce Richardson return -1;
330a9de470cSBruce Richardson }
331a9de470cSBruce Richardson
332a9de470cSBruce Richardson /* try null result */
333a9de470cSBruce Richardson ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, buf,
334a9de470cSBruce Richardson NULL, 0);
335a9de470cSBruce Richardson if (ret == -1) {
336a9de470cSBruce Richardson printf("Error: parser rejected null result!\n");
337a9de470cSBruce Richardson return -1;
338a9de470cSBruce Richardson }
339a9de470cSBruce Richardson
340a9de470cSBruce Richardson /* test help function */
341a9de470cSBruce Richardson memset(&buf, 0, sizeof(buf));
342a9de470cSBruce Richardson
343a9de470cSBruce Richardson /* try all null */
344a9de470cSBruce Richardson ret = cmdline_get_help_num(NULL, NULL, 0);
345a9de470cSBruce Richardson if (ret != -1) {
346a9de470cSBruce Richardson printf("Error: help function accepted null parameters!\n");
347a9de470cSBruce Richardson return -1;
348a9de470cSBruce Richardson }
349a9de470cSBruce Richardson
350a9de470cSBruce Richardson /* try null token */
351a9de470cSBruce Richardson ret = cmdline_get_help_num(NULL, buf, sizeof(buf));
352a9de470cSBruce Richardson if (ret != -1) {
353a9de470cSBruce Richardson printf("Error: help function accepted null token!\n");
354a9de470cSBruce Richardson return -1;
355a9de470cSBruce Richardson }
356a9de470cSBruce Richardson
357a9de470cSBruce Richardson /* coverage! */
358a9de470cSBruce Richardson ret = cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf));
359a9de470cSBruce Richardson if (ret < 0) {
360a9de470cSBruce Richardson printf("Error: help function failed with valid parameters!\n");
361a9de470cSBruce Richardson return -1;
362a9de470cSBruce Richardson }
363a9de470cSBruce Richardson
364a9de470cSBruce Richardson return 0;
365a9de470cSBruce Richardson }
366a9de470cSBruce Richardson /* test valid parameters but invalid data */
367a9de470cSBruce Richardson int
test_parse_num_invalid_data(void)368a9de470cSBruce Richardson test_parse_num_invalid_data(void)
369a9de470cSBruce Richardson {
370a9de470cSBruce Richardson enum cmdline_numtype type;
371a9de470cSBruce Richardson int ret = 0;
372a9de470cSBruce Richardson unsigned i;
373a9de470cSBruce Richardson char buf[CMDLINE_TEST_BUFSIZE];
374a9de470cSBruce Richardson uint64_t result; /* pick largest buffer */
375a9de470cSBruce Richardson cmdline_parse_token_num_t token;
376a9de470cSBruce Richardson
377a9de470cSBruce Richardson /* cycle through all possible parsed types */
378c2341bb6SDmitry Kozlyuk for (type = RTE_UINT8; type <= RTE_INT64; type++) {
379a9de470cSBruce Richardson token.num_data.type = type;
380a9de470cSBruce Richardson
381a9de470cSBruce Richardson /* test full strings */
38271bdd8a1SPavan Nikhilesh for (i = 0; i < RTE_DIM(num_invalid_strs); i++) {
383a9de470cSBruce Richardson
384a9de470cSBruce Richardson memset(&result, 0, sizeof(uint64_t));
385a9de470cSBruce Richardson memset(&buf, 0, sizeof(buf));
386a9de470cSBruce Richardson
387a9de470cSBruce Richardson ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token,
388a9de470cSBruce Richardson num_invalid_strs[i], (void*)&result, sizeof(result));
389a9de470cSBruce Richardson if (ret != -1) {
390a9de470cSBruce Richardson /* get some info about what we are trying to parse */
391a9de470cSBruce Richardson cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
392a9de470cSBruce Richardson buf, sizeof(buf));
393a9de470cSBruce Richardson
394a9de470cSBruce Richardson printf("Error: parsing %s as %s succeeded!\n",
395a9de470cSBruce Richardson num_invalid_strs[i], buf);
396a9de470cSBruce Richardson return -1;
397a9de470cSBruce Richardson }
398a9de470cSBruce Richardson }
399a9de470cSBruce Richardson }
400a9de470cSBruce Richardson return 0;
401a9de470cSBruce Richardson }
402a9de470cSBruce Richardson
403a9de470cSBruce Richardson /* test valid parameters and data */
404a9de470cSBruce Richardson int
test_parse_num_valid(void)405a9de470cSBruce Richardson test_parse_num_valid(void)
406a9de470cSBruce Richardson {
407a9de470cSBruce Richardson int ret = 0;
408a9de470cSBruce Richardson enum cmdline_numtype type;
409a9de470cSBruce Richardson unsigned i;
410a9de470cSBruce Richardson char buf[CMDLINE_TEST_BUFSIZE];
411a9de470cSBruce Richardson uint64_t result;
412a9de470cSBruce Richardson cmdline_parse_token_num_t token;
413a9de470cSBruce Richardson
414a9de470cSBruce Richardson /** valid strings **/
415a9de470cSBruce Richardson
416a9de470cSBruce Richardson /* cycle through all possible parsed types */
417c2341bb6SDmitry Kozlyuk for (type = RTE_UINT8; type <= RTE_INT64; type++) {
418a9de470cSBruce Richardson token.num_data.type = type;
419a9de470cSBruce Richardson
420a9de470cSBruce Richardson /* test positive strings */
42171bdd8a1SPavan Nikhilesh for (i = 0; i < RTE_DIM(num_valid_positive_strs); i++) {
422a9de470cSBruce Richardson result = 0;
423a9de470cSBruce Richardson memset(&buf, 0, sizeof(buf));
424a9de470cSBruce Richardson
425a9de470cSBruce Richardson cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
426a9de470cSBruce Richardson buf, sizeof(buf));
427a9de470cSBruce Richardson
428a9de470cSBruce Richardson ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
429a9de470cSBruce Richardson num_valid_positive_strs[i].str,
430a9de470cSBruce Richardson (void*)&result, sizeof(result));
431a9de470cSBruce Richardson
432a9de470cSBruce Richardson /* if it should have passed but didn't, or if it should have failed but didn't */
433a9de470cSBruce Richardson if ((ret < 0) == (can_parse_unsigned(num_valid_positive_strs[i].result, type) > 0)) {
434a9de470cSBruce Richardson printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
435a9de470cSBruce Richardson num_valid_positive_strs[i].str, buf);
436a9de470cSBruce Richardson return -1;
437a9de470cSBruce Richardson }
438a9de470cSBruce Richardson /* check if result matches what it should have matched
439a9de470cSBruce Richardson * since unsigned numbers don't care about number of bits, we can just convert
440a9de470cSBruce Richardson * everything to uint64_t without any worries. */
441a9de470cSBruce Richardson if (ret > 0 && num_valid_positive_strs[i].result != result) {
442a9de470cSBruce Richardson printf("Error: parsing %s as %s failed: result mismatch!\n",
443a9de470cSBruce Richardson num_valid_positive_strs[i].str, buf);
444a9de470cSBruce Richardson return -1;
445a9de470cSBruce Richardson }
446a9de470cSBruce Richardson }
447a9de470cSBruce Richardson
448a9de470cSBruce Richardson /* test negative strings */
44971bdd8a1SPavan Nikhilesh for (i = 0; i < RTE_DIM(num_valid_negative_strs); i++) {
450a9de470cSBruce Richardson result = 0;
451a9de470cSBruce Richardson memset(&buf, 0, sizeof(buf));
452a9de470cSBruce Richardson
453a9de470cSBruce Richardson cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
454a9de470cSBruce Richardson buf, sizeof(buf));
455a9de470cSBruce Richardson
456a9de470cSBruce Richardson ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
457a9de470cSBruce Richardson num_valid_negative_strs[i].str,
458a9de470cSBruce Richardson (void*)&result, sizeof(result));
459a9de470cSBruce Richardson
460a9de470cSBruce Richardson /* if it should have passed but didn't, or if it should have failed but didn't */
461a9de470cSBruce Richardson if ((ret < 0) == (can_parse_signed(num_valid_negative_strs[i].result, type) > 0)) {
462a9de470cSBruce Richardson printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
463a9de470cSBruce Richardson num_valid_negative_strs[i].str, buf);
464a9de470cSBruce Richardson return -1;
465a9de470cSBruce Richardson }
466a9de470cSBruce Richardson /* check if result matches what it should have matched
467a9de470cSBruce Richardson * the result is signed in this case, so we have to account for that */
468a9de470cSBruce Richardson if (ret > 0) {
469a9de470cSBruce Richardson /* detect negative */
470a9de470cSBruce Richardson switch (type) {
471c2341bb6SDmitry Kozlyuk case RTE_INT8:
472a9de470cSBruce Richardson result = (int8_t) result;
473a9de470cSBruce Richardson break;
474c2341bb6SDmitry Kozlyuk case RTE_INT16:
475a9de470cSBruce Richardson result = (int16_t) result;
476a9de470cSBruce Richardson break;
477c2341bb6SDmitry Kozlyuk case RTE_INT32:
478a9de470cSBruce Richardson result = (int32_t) result;
479a9de470cSBruce Richardson break;
480a9de470cSBruce Richardson default:
481a9de470cSBruce Richardson break;
482a9de470cSBruce Richardson }
483a9de470cSBruce Richardson if (num_valid_negative_strs[i].result == (int64_t) result)
484a9de470cSBruce Richardson continue;
485a9de470cSBruce Richardson printf("Error: parsing %s as %s failed: result mismatch!\n",
486a9de470cSBruce Richardson num_valid_negative_strs[i].str, buf);
487a9de470cSBruce Richardson return -1;
488a9de470cSBruce Richardson }
489a9de470cSBruce Richardson }
490a9de470cSBruce Richardson }
491a9de470cSBruce Richardson
492a9de470cSBruce Richardson /** garbage strings **/
493a9de470cSBruce Richardson
494a9de470cSBruce Richardson /* cycle through all possible parsed types */
495c2341bb6SDmitry Kozlyuk for (type = RTE_UINT8; type <= RTE_INT64; type++) {
496a9de470cSBruce Richardson token.num_data.type = type;
497a9de470cSBruce Richardson
498a9de470cSBruce Richardson /* test positive garbage strings */
49971bdd8a1SPavan Nikhilesh for (i = 0; i < RTE_DIM(num_garbage_positive_strs); i++) {
500a9de470cSBruce Richardson result = 0;
501a9de470cSBruce Richardson memset(&buf, 0, sizeof(buf));
502a9de470cSBruce Richardson
503a9de470cSBruce Richardson cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
504a9de470cSBruce Richardson buf, sizeof(buf));
505a9de470cSBruce Richardson
506a9de470cSBruce Richardson ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
507a9de470cSBruce Richardson num_garbage_positive_strs[i].str,
508a9de470cSBruce Richardson (void*)&result, sizeof(result));
509a9de470cSBruce Richardson
510a9de470cSBruce Richardson /* if it should have passed but didn't, or if it should have failed but didn't */
511a9de470cSBruce Richardson if ((ret < 0) == (can_parse_unsigned(num_garbage_positive_strs[i].result, type) > 0)) {
512a9de470cSBruce Richardson printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
513a9de470cSBruce Richardson num_garbage_positive_strs[i].str, buf);
514a9de470cSBruce Richardson return -1;
515a9de470cSBruce Richardson }
516a9de470cSBruce Richardson /* check if result matches what it should have matched
517a9de470cSBruce Richardson * since unsigned numbers don't care about number of bits, we can just convert
518a9de470cSBruce Richardson * everything to uint64_t without any worries. */
519a9de470cSBruce Richardson if (ret > 0 && num_garbage_positive_strs[i].result != result) {
520a9de470cSBruce Richardson printf("Error: parsing %s as %s failed: result mismatch!\n",
521a9de470cSBruce Richardson num_garbage_positive_strs[i].str, buf);
522a9de470cSBruce Richardson return -1;
523a9de470cSBruce Richardson }
524a9de470cSBruce Richardson }
525a9de470cSBruce Richardson
526a9de470cSBruce Richardson /* test negative strings */
52771bdd8a1SPavan Nikhilesh for (i = 0; i < RTE_DIM(num_garbage_negative_strs); i++) {
528a9de470cSBruce Richardson result = 0;
529a9de470cSBruce Richardson memset(&buf, 0, sizeof(buf));
530a9de470cSBruce Richardson
531a9de470cSBruce Richardson cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
532a9de470cSBruce Richardson buf, sizeof(buf));
533a9de470cSBruce Richardson
534a9de470cSBruce Richardson ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
535a9de470cSBruce Richardson num_garbage_negative_strs[i].str,
536a9de470cSBruce Richardson (void*)&result, sizeof(result));
537a9de470cSBruce Richardson
538a9de470cSBruce Richardson /* if it should have passed but didn't, or if it should have failed but didn't */
539a9de470cSBruce Richardson if ((ret < 0) == (can_parse_signed(num_garbage_negative_strs[i].result, type) > 0)) {
540a9de470cSBruce Richardson printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
541a9de470cSBruce Richardson num_garbage_negative_strs[i].str, buf);
542a9de470cSBruce Richardson return -1;
543a9de470cSBruce Richardson }
544a9de470cSBruce Richardson /* check if result matches what it should have matched
545a9de470cSBruce Richardson * the result is signed in this case, so we have to account for that */
546a9de470cSBruce Richardson if (ret > 0) {
547a9de470cSBruce Richardson /* detect negative */
548a9de470cSBruce Richardson switch (type) {
549c2341bb6SDmitry Kozlyuk case RTE_INT8:
550a9de470cSBruce Richardson if (result & (INT8_MAX + 1))
551a9de470cSBruce Richardson result |= 0xFFFFFFFFFFFFFF00ULL;
552a9de470cSBruce Richardson break;
553c2341bb6SDmitry Kozlyuk case RTE_INT16:
554a9de470cSBruce Richardson if (result & (INT16_MAX + 1))
555a9de470cSBruce Richardson result |= 0xFFFFFFFFFFFF0000ULL;
556a9de470cSBruce Richardson break;
557c2341bb6SDmitry Kozlyuk case RTE_INT32:
558a9de470cSBruce Richardson if (result & (INT32_MAX + 1ULL))
559a9de470cSBruce Richardson result |= 0xFFFFFFFF00000000ULL;
560a9de470cSBruce Richardson break;
561a9de470cSBruce Richardson default:
562a9de470cSBruce Richardson break;
563a9de470cSBruce Richardson }
564a9de470cSBruce Richardson if (num_garbage_negative_strs[i].result == (int64_t) result)
565a9de470cSBruce Richardson continue;
566a9de470cSBruce Richardson printf("Error: parsing %s as %s failed: result mismatch!\n",
567a9de470cSBruce Richardson num_garbage_negative_strs[i].str, buf);
568a9de470cSBruce Richardson return -1;
569a9de470cSBruce Richardson }
570a9de470cSBruce Richardson }
571a9de470cSBruce Richardson }
572a9de470cSBruce Richardson
573a9de470cSBruce Richardson memset(&buf, 0, sizeof(buf));
574a9de470cSBruce Richardson
575a9de470cSBruce Richardson /* coverage! */
576a9de470cSBruce Richardson cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
577a9de470cSBruce Richardson buf, sizeof(buf));
578a9de470cSBruce Richardson
579a9de470cSBruce Richardson return 0;
580a9de470cSBruce Richardson }
581