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