11eaf0ac3Slogwang /*-
21eaf0ac3Slogwang  * Copyright 2012 Clifton Royston
31eaf0ac3Slogwang  * Copyright 2013 John-Mark Gurney
41eaf0ac3Slogwang  * All rights reserved.
51eaf0ac3Slogwang  *
61eaf0ac3Slogwang  * Redistribution and use in source and binary forms, with or without
71eaf0ac3Slogwang  * modification, are permitted provided that the following conditions
81eaf0ac3Slogwang  * are met:
91eaf0ac3Slogwang  * 1. Redistributions of source code must retain the above copyright
101eaf0ac3Slogwang  *    notice, this list of conditions and the following disclaimer.
111eaf0ac3Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
121eaf0ac3Slogwang  *    notice, this list of conditions and the following disclaimer in the
131eaf0ac3Slogwang  *    documentation and/or other materials provided with the distribution.
141eaf0ac3Slogwang  *
151eaf0ac3Slogwang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
161eaf0ac3Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
171eaf0ac3Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
181eaf0ac3Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
191eaf0ac3Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
201eaf0ac3Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
211eaf0ac3Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
221eaf0ac3Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
231eaf0ac3Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
241eaf0ac3Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
251eaf0ac3Slogwang  * SUCH DAMAGE.
261eaf0ac3Slogwang  *
271eaf0ac3Slogwang  * $FreeBSD$
281eaf0ac3Slogwang  *
291eaf0ac3Slogwang  */
301eaf0ac3Slogwang 
311eaf0ac3Slogwang #include <sys/param.h>
321eaf0ac3Slogwang #include <inttypes.h>
331eaf0ac3Slogwang #include <libutil.h>
341eaf0ac3Slogwang #include <limits.h>
351eaf0ac3Slogwang #include <math.h>
361eaf0ac3Slogwang #include <stdio.h>
371eaf0ac3Slogwang #include <stdlib.h>
381eaf0ac3Slogwang #include <string.h>
391eaf0ac3Slogwang #include <unistd.h>
401eaf0ac3Slogwang 
411eaf0ac3Slogwang #define	MAX_STR_FLAGS_RESULT	80
421eaf0ac3Slogwang #define MAX_INT_STR_DIGITS	12
431eaf0ac3Slogwang 
441eaf0ac3Slogwang static const int64_t halfExabyte = (int64_t)500*1000*1000*1000*1000*1000L;
451eaf0ac3Slogwang 
461eaf0ac3Slogwang static struct {
471eaf0ac3Slogwang 	int retval;
481eaf0ac3Slogwang 	const char *res;
491eaf0ac3Slogwang 	int64_t num;
501eaf0ac3Slogwang 	int flags;
511eaf0ac3Slogwang 	int scale;
52*22ce4affSfengbojiang 	size_t buflen;
531eaf0ac3Slogwang } test_args[] = {
541eaf0ac3Slogwang 	/* tests 0-13 test 1000 suffixes */
55*22ce4affSfengbojiang 	{ 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
56*22ce4affSfengbojiang 	{ 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
57*22ce4affSfengbojiang 	{ 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
58*22ce4affSfengbojiang 	{ 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
59*22ce4affSfengbojiang 	{ 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
60*22ce4affSfengbojiang 	{ 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
61*22ce4affSfengbojiang 	{ 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
62*22ce4affSfengbojiang 	{ 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
63*22ce4affSfengbojiang 	{ 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
64*22ce4affSfengbojiang 	{ 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
65*22ce4affSfengbojiang 	{ 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
66*22ce4affSfengbojiang 	{ 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
67*22ce4affSfengbojiang 	{ 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
68*22ce4affSfengbojiang 	{ 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
691eaf0ac3Slogwang 
701eaf0ac3Slogwang 	/* tests 14-27 test 1024 suffixes */
71*22ce4affSfengbojiang 	{ 2, "0 ", (int64_t)0L, 0, HN_AUTOSCALE, 4 },
72*22ce4affSfengbojiang 	{ 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE, 4 },
73*22ce4affSfengbojiang 	{ 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE, 4 },
74*22ce4affSfengbojiang 	{ 3, "1 G", (int64_t)512*1024*1024L, 0, HN_AUTOSCALE, 4 },
75*22ce4affSfengbojiang 	{ 3, "1 T", (int64_t)512*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
76*22ce4affSfengbojiang 	{ 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
77*22ce4affSfengbojiang 	{ 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
78*22ce4affSfengbojiang 	{ 2, "1 ", (int64_t)1L, 0, HN_AUTOSCALE, 4 },
79*22ce4affSfengbojiang 	{ 3, "2 K", (int64_t)1536L, 0, HN_AUTOSCALE, 4 },
80*22ce4affSfengbojiang 	{ 3, "2 M", (int64_t)1536*1024L, 0, HN_AUTOSCALE, 4 },
81*22ce4affSfengbojiang 	{ 3, "2 G", (int64_t)1536*1024*1024L, 0, HN_AUTOSCALE, 4 },
82*22ce4affSfengbojiang 	{ 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
83*22ce4affSfengbojiang 	{ 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
84*22ce4affSfengbojiang 	{ 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
851eaf0ac3Slogwang 
861eaf0ac3Slogwang 	/* tests 28-37 test rounding */
87*22ce4affSfengbojiang 	{ 3, "0 M", (int64_t)500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
88*22ce4affSfengbojiang 	{ 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
89*22ce4affSfengbojiang 	{ 3, "1 M", (int64_t)1000*1000L + 500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
90*22ce4affSfengbojiang 	{ 3, "2 M", (int64_t)1000*1000L + 500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
91*22ce4affSfengbojiang 	{ 3, "0 K", (int64_t)512L-1, 0, HN_AUTOSCALE, 4 },
92*22ce4affSfengbojiang 	{ 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE, 4 },
93*22ce4affSfengbojiang 	{ 3, "0 M", (int64_t)512*1024L-1, 0, HN_AUTOSCALE, 4 },
94*22ce4affSfengbojiang 	{ 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE, 4 },
95*22ce4affSfengbojiang 	{ 3, "1 M", (int64_t)1024*1024L + 512*1024L-1, 0, HN_AUTOSCALE, 4 },
96*22ce4affSfengbojiang 	{ 3, "2 M", (int64_t)1024*1024L + 512*1024L, 0, HN_AUTOSCALE, 4 },
971eaf0ac3Slogwang 
981eaf0ac3Slogwang 	/* tests 38-61 test specific scale factors with 1000 divisor */
99*22ce4affSfengbojiang 	{ 3, "0 k", (int64_t)0L, HN_DIVISOR_1000, 1, 4 },
100*22ce4affSfengbojiang 	{ 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, 1, 4 },
101*22ce4affSfengbojiang 	{ 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, 2, 4 },
102*22ce4affSfengbojiang 	{ 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, 2, 4 },
103*22ce4affSfengbojiang 	{ 3, "0 G", (int64_t)500*1000L, HN_DIVISOR_1000, 3, 4 },
104*22ce4affSfengbojiang 	{ 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 3, 4 },
105*22ce4affSfengbojiang 	{ 3, "0 T", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 4, 4 },
106*22ce4affSfengbojiang 	{ 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 4, 4 },
107*22ce4affSfengbojiang 	{ 3, "0 P", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 5, 4 },
108*22ce4affSfengbojiang 	{ 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5, 4 },
109*22ce4affSfengbojiang 	{ 3, "0 E", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 4 },
110*22ce4affSfengbojiang 	{ 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 4 },
111*22ce4affSfengbojiang 	{ 3, "0 k", (int64_t)1L, HN_DIVISOR_1000, 1, 4 },
112*22ce4affSfengbojiang 	{ 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, 1, 4 },
113*22ce4affSfengbojiang 	{ 3, "0 M", (int64_t)1500L, HN_DIVISOR_1000, 2, 4 },
114*22ce4affSfengbojiang 	{ 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, 2, 4 },
115*22ce4affSfengbojiang 	{ 3, "0 G", (int64_t)1500*1000L, HN_DIVISOR_1000, 3, 4 },
116*22ce4affSfengbojiang 	{ 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 3, 4 },
117*22ce4affSfengbojiang 	{ 3, "0 T", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 4, 4 },
118*22ce4affSfengbojiang 	{ 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 4, 4 },
119*22ce4affSfengbojiang 	{ 3, "0 P", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 5, 4 },
120*22ce4affSfengbojiang 	{ 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5, 4 },
121*22ce4affSfengbojiang 	{ 3, "0 E", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 4 },
122*22ce4affSfengbojiang 	{ 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 4 },
1231eaf0ac3Slogwang 
1241eaf0ac3Slogwang 	/* tests 62-85 test specific scale factors with 1024 divisor */
125*22ce4affSfengbojiang 	{ 3, "0 K", (int64_t)0L, 0, 1, 4 },
126*22ce4affSfengbojiang 	{ 3, "1 K", (int64_t)512L, 0, 1, 4 },
127*22ce4affSfengbojiang 	{ 3, "0 M", (int64_t)512L, 0, 2, 4 },
128*22ce4affSfengbojiang 	{ 3, "1 M", (int64_t)512*1024L, 0, 2, 4 },
129*22ce4affSfengbojiang 	{ 3, "0 G", (int64_t)512*1024L, 0, 3, 4 },
130*22ce4affSfengbojiang 	{ 3, "1 G", (int64_t)512*1024*1024L, 0, 3, 4 },
131*22ce4affSfengbojiang 	{ 3, "0 T", (int64_t)512*1024*1024L, 0, 4, 4 },
132*22ce4affSfengbojiang 	{ 3, "1 T", (int64_t)512*1024*1024*1024L, 0, 4, 4 },
133*22ce4affSfengbojiang 	{ 3, "0 P", (int64_t)512*1024*1024*1024L, 0, 5, 4 },
134*22ce4affSfengbojiang 	{ 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, 5, 4 },
135*22ce4affSfengbojiang 	{ 3, "0 E", (int64_t)512*1024*1024*1024*1024L, 0, 6, 4 },
136*22ce4affSfengbojiang 	{ 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, 6, 4 },
137*22ce4affSfengbojiang 	{ 3, "0 K", (int64_t)1L, 0, 1, 4 },
138*22ce4affSfengbojiang 	{ 3, "2 K", (int64_t)1536L, 0, 1, 4 },
139*22ce4affSfengbojiang 	{ 3, "0 M", (int64_t)1536L, 0, 2, 4 },
140*22ce4affSfengbojiang 	{ 3, "2 M", (int64_t)1536*1024L, 0, 2, 4 },
141*22ce4affSfengbojiang 	{ 3, "0 G", (int64_t)1536*1024L, 0, 3, 4 },
142*22ce4affSfengbojiang 	{ 3, "2 G", (int64_t)1536*1024*1024L, 0, 3, 4 },
143*22ce4affSfengbojiang 	{ 3, "0 T", (int64_t)1536*1024*1024L, 0, 4, 4 },
144*22ce4affSfengbojiang 	{ 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, 4, 4 },
145*22ce4affSfengbojiang 	{ 3, "0 P", (int64_t)1536*1024*1024*1024L, 0, 5, 4 },
146*22ce4affSfengbojiang 	{ 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, 5, 4 },
147*22ce4affSfengbojiang 	{ 3, "0 E", (int64_t)1536*1024*1024*1024*1024L, 0, 6, 4 },
148*22ce4affSfengbojiang 	{ 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, 6, 4 },
1491eaf0ac3Slogwang 
1501eaf0ac3Slogwang 	/* tests 86-99 test invalid specific scale values of < 0 or >= 7 with
1511eaf0ac3Slogwang 	and without HN_DIVISOR_1000 set */
1521eaf0ac3Slogwang 	/*  all should return errors with new code; with old, the latter 3
1531eaf0ac3Slogwang 	are instead processed as if having AUTOSCALE and/or GETSCALE set */
154*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, 0, 7, 4 },
155*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, 7, 4 },
156*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, 0, 1000, 4 },
157*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, 1000, 4 },
158*22ce4affSfengbojiang 	{ -1, "", (int64_t)0L, 0, 1000*1000, 4 },
159*22ce4affSfengbojiang 	{ -1, "", (int64_t)0L, HN_DIVISOR_1000, 1000*1000, 4 },
160*22ce4affSfengbojiang 	{ -1, "", (int64_t)0L, 0, INT_MAX, 4 },
161*22ce4affSfengbojiang 	{ -1, "", (int64_t)0L, HN_DIVISOR_1000, INT_MAX, 4 },
1621eaf0ac3Slogwang 
1631eaf0ac3Slogwang 	/* Negative scale values are not handled well
1641eaf0ac3Slogwang 	 by the existing library routine - should report as error */
1651eaf0ac3Slogwang 	/*  all should return errors with new code, fail assertion with old */
1661eaf0ac3Slogwang 
167*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, 0, -1, 4 },
168*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, -1, 4 },
169*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, 0, -1000, 4 },
170*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, -1000, 4 },
1711eaf0ac3Slogwang 
1721eaf0ac3Slogwang 	/* __INT_MIN doesn't print properly, skipped. */
1731eaf0ac3Slogwang 
174*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, 0, -__INT_MAX, 4 },
175*22ce4affSfengbojiang 	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, -__INT_MAX, 4 },
1761eaf0ac3Slogwang 
1771eaf0ac3Slogwang 
1781eaf0ac3Slogwang 	/* tests for scale == 0, without autoscale */
1791eaf0ac3Slogwang 	/* tests 100-114 test scale 0 with 1000 divisor - print first N digits */
180*22ce4affSfengbojiang 	{ 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, 0, 4 },
181*22ce4affSfengbojiang 	{ 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, 0, 4 },
182*22ce4affSfengbojiang 	{ 3, "10 ", (int64_t)10L, HN_DIVISOR_1000, 0, 4 },
183*22ce4affSfengbojiang 	{ 3, "0 M", (int64_t)150L, HN_DIVISOR_1000, HN_NOSPACE, 4 },
184*22ce4affSfengbojiang 	{ 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, HN_NOSPACE, 4 },
185*22ce4affSfengbojiang 	{ 3, "0 M", (int64_t)999L, HN_DIVISOR_1000, HN_NOSPACE, 4 },
186*22ce4affSfengbojiang 	{ 4, "150", (int64_t)150L, HN_DIVISOR_1000, 0, 4 },
187*22ce4affSfengbojiang 	{ 4, "500", (int64_t)500L, HN_DIVISOR_1000, 0, 4 },
188*22ce4affSfengbojiang 	{ 4, "999", (int64_t)999L, HN_DIVISOR_1000, 0, 4 },
189*22ce4affSfengbojiang 	{ 5, "100", (int64_t)1000L, HN_DIVISOR_1000, 0, 4 },
190*22ce4affSfengbojiang 	{ 5, "150", (int64_t)1500L, HN_DIVISOR_1000, 0, 4 },
191*22ce4affSfengbojiang 	{ 7, "500", (int64_t)500*1000L, HN_DIVISOR_1000, 0, 4 },
192*22ce4affSfengbojiang 	{ 8, "150", (int64_t)1500*1000L, HN_DIVISOR_1000, 0, 4 },
193*22ce4affSfengbojiang 	{ 10, "500", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 0, 4 },
194*22ce4affSfengbojiang 	{ 11, "150", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 0, 4 },
1951eaf0ac3Slogwang 
1961eaf0ac3Slogwang 	/* tests 115-126 test scale 0 with 1024 divisor - print first N digits */
197*22ce4affSfengbojiang 	{ 2, "0 ", (int64_t)0L, 0, 0, 4 },
198*22ce4affSfengbojiang 	{ 2, "1 ", (int64_t)1L, 0, 0, 4 },
199*22ce4affSfengbojiang 	{ 3, "10 ", (int64_t)10L, 0, 0, 4 },
200*22ce4affSfengbojiang 	{ 4, "150", (int64_t)150L, 0, 0, 4 },
201*22ce4affSfengbojiang 	{ 4, "500", (int64_t)500L, 0, 0, 4 },
202*22ce4affSfengbojiang 	{ 4, "999", (int64_t)999L, 0, 0, 4 },
203*22ce4affSfengbojiang 	{ 5, "100", (int64_t)1000L, 0, 0, 4 },
204*22ce4affSfengbojiang 	{ 5, "150", (int64_t)1500L, 0, 0, 4 },
205*22ce4affSfengbojiang 	{ 7, "500", (int64_t)500*1000L, 0, 0, 4 },
206*22ce4affSfengbojiang 	{ 8, "150", (int64_t)1500*1000L, 0, 0, 4 },
207*22ce4affSfengbojiang 	{ 10, "500", (int64_t)500*1000*1000L, 0, 0, 4 },
208*22ce4affSfengbojiang 	{ 11, "150", (int64_t)1500*1000*1000L, 0, 0, 4 },
209*22ce4affSfengbojiang 
210*22ce4affSfengbojiang 	/* Test case for rounding of edge numbers around 999.5+, see PR224498.
211*22ce4affSfengbojiang 	 * Require buflen >= 5 */
212*22ce4affSfengbojiang 	{ 4, "1.0M", (int64_t)1023500, HN_DECIMAL|HN_B|HN_NOSPACE, HN_AUTOSCALE, 5 },
2131eaf0ac3Slogwang 
2141eaf0ac3Slogwang 	/* Test boundary cases for very large positive/negative number formatting */
2151eaf0ac3Slogwang 	/* Explicit scale, divisor 1024 */
2161eaf0ac3Slogwang 
217*22ce4affSfengbojiang 	/* Requires buflen >= 6 */
218*22ce4affSfengbojiang 	{ 3, "8 E",   INT64_MAX, 0, 6, 6 },
219*22ce4affSfengbojiang 	{ 4, "-8 E", -INT64_MAX, 0, 6, 6 },
220*22ce4affSfengbojiang 	{ 3, "0 E", (int64_t)92*1024*1024*1024*1024*1024L, 0, 6, 6 },
221*22ce4affSfengbojiang 	{ 3, "0 E", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 6, 6 },
222*22ce4affSfengbojiang 	{ 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, 0, 6, 6 },
223*22ce4affSfengbojiang 	{ 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 6, 6 },
224*22ce4affSfengbojiang 	{ 3, "0 E", (int64_t)81*1024*1024*1024*1024*1024L, 0, 6, 6 },
225*22ce4affSfengbojiang 	{ 3, "0 E", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 6, 6 },
226*22ce4affSfengbojiang 	{ 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, 5, 6 },
227*22ce4affSfengbojiang 	{ 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 5, 6 },
228*22ce4affSfengbojiang 	{ 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, 5, 6 },
229*22ce4affSfengbojiang 	{ 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 5, 6 },
230*22ce4affSfengbojiang 	{ 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, 5, 6 },
231*22ce4affSfengbojiang 	{ 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 5, 6 },
2321eaf0ac3Slogwang 
2331eaf0ac3Slogwang 	/* Explicit scale, divisor 1000 */
234*22ce4affSfengbojiang 	{ 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, 6, 6 },
235*22ce4affSfengbojiang 	{ 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000,  6, 6 },
236*22ce4affSfengbojiang 	{ 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6, 6 },
237*22ce4affSfengbojiang 	{ 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6, 6 },
238*22ce4affSfengbojiang 	{ 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6, 6 },
239*22ce4affSfengbojiang 	{ 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6, 6 },
240*22ce4affSfengbojiang 	{ 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5, 6 },
241*22ce4affSfengbojiang 	{ 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5, 6 },
242*22ce4affSfengbojiang 	{ 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5, 6 },
243*22ce4affSfengbojiang 	{ 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5, 6 },
2441eaf0ac3Slogwang 
2451eaf0ac3Slogwang 	/* Autoscale, divisor 1024 */
246*22ce4affSfengbojiang 	{ 3, "8 E",   INT64_MAX, 0, HN_AUTOSCALE, 6 },
247*22ce4affSfengbojiang 	{ 4, "-8 E", -INT64_MAX, 0, HN_AUTOSCALE, 6 },
248*22ce4affSfengbojiang 	{ 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 6 },
249*22ce4affSfengbojiang 	{ 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 6 },
250*22ce4affSfengbojiang 	{ 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 6 },
251*22ce4affSfengbojiang 	{ 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 6 },
252*22ce4affSfengbojiang 	{ 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 6 },
253*22ce4affSfengbojiang 	{ 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 6 },
2541eaf0ac3Slogwang 	/* Autoscale, divisor 1000 */
255*22ce4affSfengbojiang 	{ 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
256*22ce4affSfengbojiang 	{ 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
257*22ce4affSfengbojiang 	{ 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
258*22ce4affSfengbojiang 	{ 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
259*22ce4affSfengbojiang 	{ 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
260*22ce4affSfengbojiang 	{ 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
2611eaf0ac3Slogwang 
2621eaf0ac3Slogwang 	/* 0 scale, divisor 1024 */
263*22ce4affSfengbojiang 	{ 12, "skdj",  INT64_MAX, 0, 0, 6 },
264*22ce4affSfengbojiang 	{ 21, "-9223", -INT64_MAX, 0, 0, 6 },
265*22ce4affSfengbojiang 	{ 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, 0, 0, 6 },
266*22ce4affSfengbojiang 	{ 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 0, 6 },
267*22ce4affSfengbojiang 	{ 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, 0, 0, 6 },
268*22ce4affSfengbojiang 	{ 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 0, 6 },
269*22ce4affSfengbojiang 	{ 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, 0, 0, 6 },
270*22ce4affSfengbojiang 	{ 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 0, 6 },
2711eaf0ac3Slogwang 
2721eaf0ac3Slogwang 	/* 0 scale, divisor 1000 */
2731eaf0ac3Slogwang 	/* XXX - why does this fail? */
274*22ce4affSfengbojiang 	{ -1, "", INT64_MAX, HN_DIVISOR_1000, 0, 6 },
275*22ce4affSfengbojiang 	{ 21, "-9223", -INT64_MAX, HN_DIVISOR_1000,  0, 6 },
276*22ce4affSfengbojiang 	{ 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0, 6 },
277*22ce4affSfengbojiang 	{ 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0, 6 },
278*22ce4affSfengbojiang 	{ 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0, 6 },
279*22ce4affSfengbojiang 	{ 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0, 6 },
2801eaf0ac3Slogwang 	/* Expected to pass */
281*22ce4affSfengbojiang 	{ 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0, 6 },
282*22ce4affSfengbojiang 	{ 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0, 6 },
2831eaf0ac3Slogwang 
2841eaf0ac3Slogwang 
2851eaf0ac3Slogwang 
2861eaf0ac3Slogwang 	/* Need to implement tests for GETSCALE */
287*22ce4affSfengbojiang /*	{ ?, "", (int64_t)0L, HN_DIVISOR_1000, HN_GETSCALE, 6 },
2881eaf0ac3Slogwang 	...
2891eaf0ac3Slogwang */
2901eaf0ac3Slogwang         /* Tests for HN_DECIMAL */
2911eaf0ac3Slogwang         /* Positive, Autoscale */
292*22ce4affSfengbojiang 	{ 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
293*22ce4affSfengbojiang 	{ 5, "994 k", (int64_t)994*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
294*22ce4affSfengbojiang 	{ 5, "995 k", (int64_t)995*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
295*22ce4affSfengbojiang 	{ 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
296*22ce4affSfengbojiang 	{ 5, "1.0 M", (int64_t)1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
297*22ce4affSfengbojiang 	{ 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
298*22ce4affSfengbojiang 	{ 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
299*22ce4affSfengbojiang 	{ 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
300*22ce4affSfengbojiang 	{ 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
301*22ce4affSfengbojiang 	{ 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
302*22ce4affSfengbojiang 	{ 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
303*22ce4affSfengbojiang 	{ 5, "994 M", (int64_t)994*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
304*22ce4affSfengbojiang 	{ 5, "995 M", (int64_t)995*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
305*22ce4affSfengbojiang 	{ 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
3061eaf0ac3Slogwang 
307*22ce4affSfengbojiang 	{ 5, "500 K", (int64_t)500*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
308*22ce4affSfengbojiang 	{ 5, "994 K", (int64_t)994*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
309*22ce4affSfengbojiang 	{ 5, "995 K", (int64_t)995*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
310*22ce4affSfengbojiang 	{ 5, "999 K", (int64_t)999*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
311*22ce4affSfengbojiang 	{ 5, "1.0 M", (int64_t)1000*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
312*22ce4affSfengbojiang 	{ 5, "1.0 M", (int64_t)1018*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
313*22ce4affSfengbojiang 	{ 5, "1.0 M", (int64_t)1019*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
314*22ce4affSfengbojiang 	{ 5, "1.5 M", (int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
315*22ce4affSfengbojiang 	{ 5, "1.9 M", (int64_t)1996*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
316*22ce4affSfengbojiang 	{ 5, "2.0 M", (int64_t)1997*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
317*22ce4affSfengbojiang 	{ 5, "2.0 M", (int64_t)2047*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
318*22ce4affSfengbojiang 	{ 5, "2.0 M", (int64_t)2048*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
319*22ce4affSfengbojiang 	{ 5, "2.0 M", (int64_t)2099*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
320*22ce4affSfengbojiang 	{ 5, "2.1 M", (int64_t)2100*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
321*22ce4affSfengbojiang 	{ 5, "9.9 M", (int64_t)10188*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
3221eaf0ac3Slogwang 	/* XXX - shouldn't the following two be "10. M"? */
323*22ce4affSfengbojiang 	{ 4, "10 M", (int64_t)10189*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
324*22ce4affSfengbojiang 	{ 4, "10 M", (int64_t)10240*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
325*22ce4affSfengbojiang 	{ 5, "500 M", (int64_t)500*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
326*22ce4affSfengbojiang 	{ 5, "994 M", (int64_t)994*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
327*22ce4affSfengbojiang 	{ 5, "995 M", (int64_t)995*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
328*22ce4affSfengbojiang 	{ 5, "999 M", (int64_t)999*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
329*22ce4affSfengbojiang 	{ 5, "1.0 G", (int64_t)1000*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
330*22ce4affSfengbojiang 	{ 5, "1.0 G", (int64_t)1023*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
3311eaf0ac3Slogwang 
3321eaf0ac3Slogwang         /* Negative, Autoscale - should pass */
333*22ce4affSfengbojiang 	{ 6, "-1.5 ", -(int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
334*22ce4affSfengbojiang 	{ 6, "-1.9 ", -(int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
335*22ce4affSfengbojiang 	{ 6, "-9.9 ", -(int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
3361eaf0ac3Slogwang 
337*22ce4affSfengbojiang 	{ 6, "-1.5 ", -(int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
338*22ce4affSfengbojiang 	{ 6, "-1.9 ", -(int64_t)1949*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
339*22ce4affSfengbojiang 	{ 6, "-9.7 ", -(int64_t)9949*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
3401eaf0ac3Slogwang 
3411eaf0ac3Slogwang 	/* Positive/negative, at maximum scale */
342*22ce4affSfengbojiang 	{ 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
343*22ce4affSfengbojiang 	{ 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
344*22ce4affSfengbojiang 	{ 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
345*22ce4affSfengbojiang 	{ 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
3461eaf0ac3Slogwang         /* Negatives work with latest rev only: */
347*22ce4affSfengbojiang 	{ 6, "-9.2 ", -INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
348*22ce4affSfengbojiang 	{ 6, "-8.9 ", -(int64_t)8949*1000*1000*1000*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
3491eaf0ac3Slogwang 
350*22ce4affSfengbojiang 	{ 5, "8.0 E",   INT64_MAX, HN_DECIMAL, HN_AUTOSCALE, 6 },
351*22ce4affSfengbojiang 	{ 5, "7.9 E",   INT64_MAX-(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL, HN_AUTOSCALE, 6 },
352*22ce4affSfengbojiang 	{ 6, "-8.0 ", -INT64_MAX, HN_DECIMAL, HN_AUTOSCALE, 6 },
353*22ce4affSfengbojiang 	{ 6, "-7.9 ",   -INT64_MAX+(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL, HN_AUTOSCALE, 6 },
3541eaf0ac3Slogwang 
3551eaf0ac3Slogwang 	/* Positive, Fixed scales */
356*22ce4affSfengbojiang 	{ 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1, 6 },
357*22ce4affSfengbojiang 	{ 5, "0.5 M", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
358*22ce4affSfengbojiang 	{ 5, "949 k", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1, 6 },
359*22ce4affSfengbojiang 	{ 5, "0.9 M", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
360*22ce4affSfengbojiang 	{ 5, "950 k", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1, 6 },
361*22ce4affSfengbojiang 	{ 5, "1.0 M", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
362*22ce4affSfengbojiang 	{ 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1, 6 },
363*22ce4affSfengbojiang 	{ 5, "1.0 M", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
364*22ce4affSfengbojiang 	{ 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
365*22ce4affSfengbojiang 	{ 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
366*22ce4affSfengbojiang 	{ 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
367*22ce4affSfengbojiang 	{ 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
368*22ce4affSfengbojiang 	{ 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
369*22ce4affSfengbojiang 	{ 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
370*22ce4affSfengbojiang 	{ 5, "0.5 G", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3, 6 },
371*22ce4affSfengbojiang 	{ 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
372*22ce4affSfengbojiang 	{ 5, "1.0 G", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3, 6 },
3731eaf0ac3Slogwang 	/* Positive/negative, at maximum scale */
374*22ce4affSfengbojiang 	{ 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 5, 6 },
375*22ce4affSfengbojiang 	{ 5, "1.0 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 6 },
376*22ce4affSfengbojiang 	{ 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 6 },
377*22ce4affSfengbojiang 	{ 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 6 },
378*22ce4affSfengbojiang 	{ 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, 6, 6 },
3791eaf0ac3Slogwang 
3801eaf0ac3Slogwang 	/* HN_DECIMAL + binary + fixed scale cases not completed */
381*22ce4affSfengbojiang 	{ 5, "512 K", (int64_t)512*1024L, HN_DECIMAL, 1, 6 },
382*22ce4affSfengbojiang 	{ 5, "0.5 M", (int64_t)512*1024L, HN_DECIMAL, 2, 6 },
3831eaf0ac3Slogwang 
3841eaf0ac3Slogwang 	/* Negative, Fixed scales */
3851eaf0ac3Slogwang         /* Not yet added, but should work with latest rev */
3861eaf0ac3Slogwang 
3871eaf0ac3Slogwang };
3881eaf0ac3Slogwang 
3891eaf0ac3Slogwang 
3901eaf0ac3Slogwang /* Command line options usage */
3911eaf0ac3Slogwang static void
usage(char * progname)3921eaf0ac3Slogwang usage(char * progname) {
3931eaf0ac3Slogwang 	printf("%s: tests libutil humanize_number function\n", progname);
3941eaf0ac3Slogwang 	printf("Usage: %s [-nE] [-l num] [-v]\n\n", progname);
3951eaf0ac3Slogwang 	printf("Options:\n");
3961eaf0ac3Slogwang 	printf("\t-l num\tSet max length for result; buflen = num + 1\n");
3971eaf0ac3Slogwang 	printf("\t\t  (NOTE: does not change expected result strings.)\n");
3981eaf0ac3Slogwang 	printf("\t-n\tInclude negative scale tests, which cause older libutil\n");
3991eaf0ac3Slogwang 	printf("\t\t  version of function to coredump with assertion failure\n");
4001eaf0ac3Slogwang 	printf("\t-E\tInclude numbers > 1/2 Exa[byte] which currently fail\n");
4011eaf0ac3Slogwang 	printf("\t-v\tVerbose - always print summary results\n");
4021eaf0ac3Slogwang 	printf("\t-h, -?\tShow options\n");
4031eaf0ac3Slogwang }
4041eaf0ac3Slogwang 
4051eaf0ac3Slogwang /* Parse command line options */
4061eaf0ac3Slogwang static void
read_options(int argc,char * const argv[],size_t * bufLength,int * includeNegativeScale,int * includeExabytes,int * verbose)4071eaf0ac3Slogwang read_options(int argc, char * const argv[], size_t *bufLength,
4081eaf0ac3Slogwang     int *includeNegativeScale, int *includeExabytes, int *verbose) {
4091eaf0ac3Slogwang 	int ch;
4101eaf0ac3Slogwang 	size_t temp;
4111eaf0ac3Slogwang 
4121eaf0ac3Slogwang 	while ((ch = getopt(argc, argv, "nEh?vl:")) != -1) {
4131eaf0ac3Slogwang 		switch (ch) {
4141eaf0ac3Slogwang 			default:
4151eaf0ac3Slogwang 				usage(argv[0]);
4161eaf0ac3Slogwang 				exit(1);
4171eaf0ac3Slogwang 				break;	/* UNREACHABLE */
4181eaf0ac3Slogwang 			case 'h' :
4191eaf0ac3Slogwang 			case '?' :
4201eaf0ac3Slogwang 				usage(argv[0]);
4211eaf0ac3Slogwang 				exit(0);
4221eaf0ac3Slogwang 				break;	/* UNREACHABLE */
4231eaf0ac3Slogwang 			case 'l' :
4241eaf0ac3Slogwang 				sscanf(optarg, "%zu", &temp);
4251eaf0ac3Slogwang 				*bufLength = temp + 1;
4261eaf0ac3Slogwang 				break;
4271eaf0ac3Slogwang 			case 'n' :
4281eaf0ac3Slogwang 				*includeNegativeScale = 1;
4291eaf0ac3Slogwang 				break;
4301eaf0ac3Slogwang 			case 'E' :
4311eaf0ac3Slogwang 				*includeExabytes = 1;
4321eaf0ac3Slogwang 				break;
4331eaf0ac3Slogwang 			case 'v' :
4341eaf0ac3Slogwang 				*verbose = 1;
4351eaf0ac3Slogwang 				break;
4361eaf0ac3Slogwang 		}
4371eaf0ac3Slogwang 	}
4381eaf0ac3Slogwang }
4391eaf0ac3Slogwang 
4401eaf0ac3Slogwang static struct {
4411eaf0ac3Slogwang 	int value;
4421eaf0ac3Slogwang 	const char *name;
4431eaf0ac3Slogwang  } flags[] = {
4441eaf0ac3Slogwang 	{ HN_AUTOSCALE, "HN_AUTOSCALE" },
4451eaf0ac3Slogwang 	{ HN_GETSCALE, "HN_GETSCALE" },
4461eaf0ac3Slogwang 	{ HN_DIVISOR_1000, "HN_DIVISOR_1000" },
4471eaf0ac3Slogwang 	{ HN_B, "HN_B" },
4481eaf0ac3Slogwang 	{ HN_DECIMAL, "HN_DECIMAL" },
4491eaf0ac3Slogwang };
4501eaf0ac3Slogwang 
4511eaf0ac3Slogwang static const char *separator = "|";
4521eaf0ac3Slogwang 
4531eaf0ac3Slogwang /* Format flags parameter for meaningful display */
4541eaf0ac3Slogwang static char *
str_flags(int hn_flags,char * noFlags)4551eaf0ac3Slogwang str_flags(int hn_flags, char *noFlags) {
4561eaf0ac3Slogwang 	size_t i;
4571eaf0ac3Slogwang 	char * result;
4581eaf0ac3Slogwang 
4591eaf0ac3Slogwang 	result = malloc(MAX_STR_FLAGS_RESULT);
4601eaf0ac3Slogwang 	result[0] = '\0';
4611eaf0ac3Slogwang 
4621eaf0ac3Slogwang 	for (i = 0; i < sizeof flags / sizeof *flags; i++) {
4631eaf0ac3Slogwang 		if (hn_flags & flags[i].value) {
4641eaf0ac3Slogwang 			if (*result != 0)
4651eaf0ac3Slogwang 				strlcat(result, separator,
4661eaf0ac3Slogwang 				    MAX_STR_FLAGS_RESULT);
4671eaf0ac3Slogwang 			strlcat(result, flags[i].name, MAX_STR_FLAGS_RESULT);
4681eaf0ac3Slogwang 		}
4691eaf0ac3Slogwang 	}
4701eaf0ac3Slogwang 
4711eaf0ac3Slogwang 	if (strlen(result) == 0)
4721eaf0ac3Slogwang 		strlcat(result, noFlags, MAX_STR_FLAGS_RESULT);
4731eaf0ac3Slogwang 	return result;
4741eaf0ac3Slogwang }
4751eaf0ac3Slogwang 
4761eaf0ac3Slogwang 
4771eaf0ac3Slogwang /* Format scale parameter for meaningful display */
4781eaf0ac3Slogwang static char *
str_scale(int scale)4791eaf0ac3Slogwang str_scale(int scale) {
4801eaf0ac3Slogwang 	char *result;
4811eaf0ac3Slogwang 
4821eaf0ac3Slogwang 	if (scale == HN_AUTOSCALE || scale == HN_GETSCALE)
4831eaf0ac3Slogwang 		return str_flags(scale, "");
4841eaf0ac3Slogwang 
4851eaf0ac3Slogwang 	result = malloc(MAX_INT_STR_DIGITS);
4861eaf0ac3Slogwang 	result[0] = '\0';
4871eaf0ac3Slogwang 	snprintf(result, MAX_INT_STR_DIGITS, "%d", scale);
4881eaf0ac3Slogwang 	return result;
4891eaf0ac3Slogwang }
4901eaf0ac3Slogwang 
4911eaf0ac3Slogwang static void
testskipped(size_t i)4921eaf0ac3Slogwang testskipped(size_t i)
4931eaf0ac3Slogwang {
4941eaf0ac3Slogwang 
4951eaf0ac3Slogwang 	printf("ok %zu # skip - not turned on\n", i);
4961eaf0ac3Slogwang }
4971eaf0ac3Slogwang 
4981eaf0ac3Slogwang int
main(int argc,char * const argv[])4991eaf0ac3Slogwang main(int argc, char * const argv[])
5001eaf0ac3Slogwang {
5011eaf0ac3Slogwang 	char *buf;
5021eaf0ac3Slogwang 	char *flag_str, *scale_str;
503*22ce4affSfengbojiang 	size_t blen, buflen, errcnt, i, skipped, tested;
5041eaf0ac3Slogwang 	int r;
5051eaf0ac3Slogwang 	int includeNegScale;
5061eaf0ac3Slogwang 	int includeExabyteTests;
5071eaf0ac3Slogwang 	int verbose;
5081eaf0ac3Slogwang 
509*22ce4affSfengbojiang 	buf = NULL;
510*22ce4affSfengbojiang 	buflen = 0;
5111eaf0ac3Slogwang 	includeNegScale = 0;
5121eaf0ac3Slogwang 	includeExabyteTests = 0;
5131eaf0ac3Slogwang 	verbose = 0;
5141eaf0ac3Slogwang 
5151eaf0ac3Slogwang 	read_options(argc, argv, &buflen, &includeNegScale,
5161eaf0ac3Slogwang 	    &includeExabyteTests, &verbose);
5171eaf0ac3Slogwang 
5181eaf0ac3Slogwang 	errcnt = 0;
5191eaf0ac3Slogwang 	tested = 0;
5201eaf0ac3Slogwang 	skipped = 0;
5211eaf0ac3Slogwang 
5221eaf0ac3Slogwang 	if (buflen != 4)
5231eaf0ac3Slogwang 		printf("Warning: buffer size %zu != 4, expect some results to differ.\n", buflen);
5241eaf0ac3Slogwang 
5251eaf0ac3Slogwang 	printf("1..%zu\n", nitems(test_args));
5261eaf0ac3Slogwang 	for (i = 0; i < nitems(test_args); i++) {
527*22ce4affSfengbojiang 		blen = (buflen > 0) ? buflen : test_args[i].buflen;
528*22ce4affSfengbojiang 		buf = realloc(buf, blen);
5291eaf0ac3Slogwang 
5301eaf0ac3Slogwang 		if (test_args[i].scale < 0 && ! includeNegScale) {
5311eaf0ac3Slogwang 			skipped++;
5321eaf0ac3Slogwang 			testskipped(i + 1);
5331eaf0ac3Slogwang 			continue;
5341eaf0ac3Slogwang 		}
5351eaf0ac3Slogwang 		if (test_args[i].num >= halfExabyte && ! includeExabyteTests) {
5361eaf0ac3Slogwang 			skipped++;
5371eaf0ac3Slogwang 			testskipped(i + 1);
5381eaf0ac3Slogwang 			continue;
5391eaf0ac3Slogwang 		}
5401eaf0ac3Slogwang 
541*22ce4affSfengbojiang 		r = humanize_number(buf, blen, test_args[i].num, "",
5421eaf0ac3Slogwang 		    test_args[i].scale, test_args[i].flags);
5431eaf0ac3Slogwang 		flag_str = str_flags(test_args[i].flags, "[no flags]");
5441eaf0ac3Slogwang 		scale_str = str_scale(test_args[i].scale);
5451eaf0ac3Slogwang 
5461eaf0ac3Slogwang 		if (r != test_args[i].retval) {
5471eaf0ac3Slogwang 			if (verbose)
5481eaf0ac3Slogwang 				printf("wrong return value on index %zu, "
5491eaf0ac3Slogwang 				    "buflen: %zu, got: %d + \"%s\", "
5501eaf0ac3Slogwang 				    "expected %d + \"%s\"; num = %jd, "
5511eaf0ac3Slogwang 				    "scale = %s, flags= %s.\n",
552*22ce4affSfengbojiang 				    i, blen, r, buf, test_args[i].retval,
5531eaf0ac3Slogwang 				    test_args[i].res,
5541eaf0ac3Slogwang 				    (intmax_t)test_args[i].num,
5551eaf0ac3Slogwang 				    scale_str, flag_str);
5561eaf0ac3Slogwang 			else
5571eaf0ac3Slogwang 				printf("not ok %zu # return %d != %d\n",
5581eaf0ac3Slogwang 				    i + 1, r, test_args[i].retval);
5591eaf0ac3Slogwang 			errcnt++;
5601eaf0ac3Slogwang 		} else if (strcmp(buf, test_args[i].res) != 0) {
5611eaf0ac3Slogwang 			if (verbose)
5621eaf0ac3Slogwang 				printf("result mismatch on index %zu, got: "
5631eaf0ac3Slogwang 				    "\"%s\", expected \"%s\"; num = %jd, "
564*22ce4affSfengbojiang 				    "buflen: %zu, scale = %s, flags= %s.\n",
5651eaf0ac3Slogwang 				    i, buf, test_args[i].res,
5661eaf0ac3Slogwang 				    (intmax_t)test_args[i].num,
567*22ce4affSfengbojiang 				    blen, scale_str, flag_str);
5681eaf0ac3Slogwang 			else
5691eaf0ac3Slogwang 				printf("not ok %zu # buf \"%s\" != \"%s\"\n",
5701eaf0ac3Slogwang 				    i + 1, buf, test_args[i].res);
5711eaf0ac3Slogwang 			errcnt++;
5721eaf0ac3Slogwang 		} else {
5731eaf0ac3Slogwang 			if (verbose)
5741eaf0ac3Slogwang 				printf("successful result on index %zu, "
5751eaf0ac3Slogwang 				    "returned %d, got: \"%s\"; num = %jd, "
576*22ce4affSfengbojiang 				    "buflen = %zd, scale = %s, flags= %s.\n",
577*22ce4affSfengbojiang 				    i, r, buf, (intmax_t)test_args[i].num,
578*22ce4affSfengbojiang 				    blen, scale_str, flag_str);
5791eaf0ac3Slogwang 			else
5801eaf0ac3Slogwang 				printf("ok %zu\n", i + 1);
5811eaf0ac3Slogwang 		}
5821eaf0ac3Slogwang 		tested++;
5831eaf0ac3Slogwang 	}
584*22ce4affSfengbojiang 	free(buf);
5851eaf0ac3Slogwang 
5861eaf0ac3Slogwang 	if (verbose)
5871eaf0ac3Slogwang 		printf("total errors: %zu/%zu tests, %zu skipped\n", errcnt,
5881eaf0ac3Slogwang 		    tested, skipped);
5891eaf0ac3Slogwang 
5901eaf0ac3Slogwang 	if (errcnt)
5911eaf0ac3Slogwang 		return 1;
5921eaf0ac3Slogwang 
5931eaf0ac3Slogwang 	return 0;
5941eaf0ac3Slogwang }
595