test: move unit tests to separate directory
[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         case INT8:
319                 if (expected_result > INT8_MAX || expected_result < INT8_MIN)
320                         return 0;
321                 break;
322         case INT16:
323                 if (expected_result > INT16_MAX || expected_result < INT16_MIN)
324                         return 0;
325                 break;
326         case INT32:
327                 if (expected_result > INT32_MAX || expected_result < INT32_MIN)
328                         return 0;
329                 break;
330         default:
331                 return 1;
332         }
333         return 1;
334 }
335
336 /* test invalid parameters */
337 int
338 test_parse_num_invalid_param(void)
339 {
340         char buf[CMDLINE_TEST_BUFSIZE];
341         uint32_t result;
342         cmdline_parse_token_num_t token;
343         int ret = 0;
344
345         /* set up a token */
346         token.num_data.type = UINT32;
347
348         /* copy string to buffer */
349         snprintf(buf, sizeof(buf), "%s",
350                         num_valid_positive_strs[0].str);
351
352         /* try all null */
353         ret = cmdline_parse_num(NULL, NULL, NULL, 0);
354         if (ret != -1) {
355                 printf("Error: parser accepted null parameters!\n");
356                 return -1;
357         }
358
359         /* try null token */
360         ret = cmdline_parse_num(NULL, buf, (void*)&result, sizeof(result));
361         if (ret != -1) {
362                 printf("Error: parser accepted null token!\n");
363                 return -1;
364         }
365
366         /* try null buf */
367         ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, NULL,
368                 (void*)&result, sizeof(result));
369         if (ret != -1) {
370                 printf("Error: parser accepted null string!\n");
371                 return -1;
372         }
373
374         /* try null result */
375         ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, buf,
376                 NULL, 0);
377         if (ret == -1) {
378                 printf("Error: parser rejected null result!\n");
379                 return -1;
380         }
381
382         /* test help function */
383         memset(&buf, 0, sizeof(buf));
384
385         /* try all null */
386         ret = cmdline_get_help_num(NULL, NULL, 0);
387         if (ret != -1) {
388                 printf("Error: help function accepted null parameters!\n");
389                 return -1;
390         }
391
392         /* try null token */
393         ret = cmdline_get_help_num(NULL, buf, sizeof(buf));
394         if (ret != -1) {
395                 printf("Error: help function accepted null token!\n");
396                 return -1;
397         }
398
399         /* coverage! */
400         ret = cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf));
401         if (ret < 0) {
402                 printf("Error: help function failed with valid parameters!\n");
403                 return -1;
404         }
405
406         return 0;
407 }
408 /* test valid parameters but invalid data */
409 int
410 test_parse_num_invalid_data(void)
411 {
412         enum cmdline_numtype type;
413         int ret = 0;
414         unsigned i;
415         char buf[CMDLINE_TEST_BUFSIZE];
416         uint64_t result; /* pick largest buffer */
417         cmdline_parse_token_num_t token;
418
419         /* cycle through all possible parsed types */
420         for (type = UINT8; type <= INT64; type++) {
421                 token.num_data.type = type;
422
423                 /* test full strings */
424                 for (i = 0; i < NUM_INVALID_STRS_SIZE; i++) {
425
426                         memset(&result, 0, sizeof(uint64_t));
427                         memset(&buf, 0, sizeof(buf));
428
429                         ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token,
430                                 num_invalid_strs[i], (void*)&result, sizeof(result));
431                         if (ret != -1) {
432                                 /* get some info about what we are trying to parse */
433                                 cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
434                                                 buf, sizeof(buf));
435
436                                 printf("Error: parsing %s as %s succeeded!\n",
437                                                 num_invalid_strs[i], buf);
438                                 return -1;
439                         }
440                 }
441         }
442         return 0;
443 }
444
445 /* test valid parameters and data */
446 int
447 test_parse_num_valid(void)
448 {
449         int ret = 0;
450         enum cmdline_numtype type;
451         unsigned i;
452         char buf[CMDLINE_TEST_BUFSIZE];
453         uint64_t result;
454         cmdline_parse_token_num_t token;
455
456         /** valid strings **/
457
458         /* cycle through all possible parsed types */
459         for (type = UINT8; type <= INT64; type++) {
460                 token.num_data.type = type;
461
462                 /* test positive strings */
463                 for (i = 0; i < NUM_POSITIVE_STRS_SIZE; i++) {
464                         result = 0;
465                         memset(&buf, 0, sizeof(buf));
466
467                         cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
468                                         buf, sizeof(buf));
469
470                         ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
471                                 num_valid_positive_strs[i].str,
472                                 (void*)&result, sizeof(result));
473
474                         /* if it should have passed but didn't, or if it should have failed but didn't */
475                         if ((ret < 0) == (can_parse_unsigned(num_valid_positive_strs[i].result, type) > 0)) {
476                                 printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
477                                                 num_valid_positive_strs[i].str, buf);
478                                 return -1;
479                         }
480                         /* check if result matches what it should have matched
481                          * since unsigned numbers don't care about number of bits, we can just convert
482                          * everything to uint64_t without any worries. */
483                         if (ret > 0 && num_valid_positive_strs[i].result != result) {
484                                 printf("Error: parsing %s as %s failed: result mismatch!\n",
485                                                 num_valid_positive_strs[i].str, buf);
486                                 return -1;
487                         }
488                 }
489
490                 /* test negative strings */
491                 for (i = 0; i < NUM_NEGATIVE_STRS_SIZE; i++) {
492                         result = 0;
493                         memset(&buf, 0, sizeof(buf));
494
495                         cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
496                                         buf, sizeof(buf));
497
498                         ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
499                                 num_valid_negative_strs[i].str,
500                                 (void*)&result, sizeof(result));
501
502                         /* if it should have passed but didn't, or if it should have failed but didn't */
503                         if ((ret < 0) == (can_parse_signed(num_valid_negative_strs[i].result, type) > 0)) {
504                                 printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
505                                                 num_valid_negative_strs[i].str, buf);
506                                 return -1;
507                         }
508                         /* check if result matches what it should have matched
509                          * the result is signed in this case, so we have to account for that */
510                         if (ret > 0) {
511                                 /* detect negative */
512                                 switch (type) {
513                                 case INT8:
514                                         result = (int8_t) result;
515                                         break;
516                                 case INT16:
517                                         result = (int16_t) result;
518                                         break;
519                                 case INT32:
520                                         result = (int32_t) result;
521                                         break;
522                                 default:
523                                         break;
524                                 }
525                                 if (num_valid_negative_strs[i].result == (int64_t) result)
526                                         continue;
527                                 printf("Error: parsing %s as %s failed: result mismatch!\n",
528                                                 num_valid_negative_strs[i].str, buf);
529                                 return -1;
530                         }
531                 }
532         }
533
534         /** garbage strings **/
535
536         /* cycle through all possible parsed types */
537         for (type = UINT8; type <= INT64; type++) {
538                 token.num_data.type = type;
539
540                 /* test positive garbage strings */
541                 for (i = 0; i < NUM_POSITIVE_GARBAGE_STRS_SIZE; i++) {
542                         result = 0;
543                         memset(&buf, 0, sizeof(buf));
544
545                         cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
546                                         buf, sizeof(buf));
547
548                         ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
549                                 num_garbage_positive_strs[i].str,
550                                 (void*)&result, sizeof(result));
551
552                         /* if it should have passed but didn't, or if it should have failed but didn't */
553                         if ((ret < 0) == (can_parse_unsigned(num_garbage_positive_strs[i].result, type) > 0)) {
554                                 printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
555                                                 num_garbage_positive_strs[i].str, buf);
556                                 return -1;
557                         }
558                         /* check if result matches what it should have matched
559                          * since unsigned numbers don't care about number of bits, we can just convert
560                          * everything to uint64_t without any worries. */
561                         if (ret > 0 && num_garbage_positive_strs[i].result != result) {
562                                 printf("Error: parsing %s as %s failed: result mismatch!\n",
563                                                 num_garbage_positive_strs[i].str, buf);
564                                 return -1;
565                         }
566                 }
567
568                 /* test negative strings */
569                 for (i = 0; i < NUM_NEGATIVE_GARBAGE_STRS_SIZE; i++) {
570                         result = 0;
571                         memset(&buf, 0, sizeof(buf));
572
573                         cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
574                                         buf, sizeof(buf));
575
576                         ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
577                                 num_garbage_negative_strs[i].str,
578                                 (void*)&result, sizeof(result));
579
580                         /* if it should have passed but didn't, or if it should have failed but didn't */
581                         if ((ret < 0) == (can_parse_signed(num_garbage_negative_strs[i].result, type) > 0)) {
582                                 printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
583                                                 num_garbage_negative_strs[i].str, buf);
584                                 return -1;
585                         }
586                         /* check if result matches what it should have matched
587                          * the result is signed in this case, so we have to account for that */
588                         if (ret > 0) {
589                                 /* detect negative */
590                                 switch (type) {
591                                 case INT8:
592                                         if (result & (INT8_MAX + 1))
593                                                 result |= 0xFFFFFFFFFFFFFF00ULL;
594                                         break;
595                                 case INT16:
596                                         if (result & (INT16_MAX + 1))
597                                                 result |= 0xFFFFFFFFFFFF0000ULL;
598                                         break;
599                                 case INT32:
600                                         if (result & (INT32_MAX + 1ULL))
601                                                 result |= 0xFFFFFFFF00000000ULL;
602                                         break;
603                                 default:
604                                         break;
605                                 }
606                                 if (num_garbage_negative_strs[i].result == (int64_t) result)
607                                         continue;
608                                 printf("Error: parsing %s as %s failed: result mismatch!\n",
609                                                 num_garbage_negative_strs[i].str, buf);
610                                 return -1;
611                         }
612                 }
613         }
614
615         memset(&buf, 0, sizeof(buf));
616
617         /* coverage! */
618         cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
619                         buf, sizeof(buf));
620
621         return 0;
622 }