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