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