]>
git.saurik.com Git - apple/libutil.git/blob - tests/humanize_number_test.c
2 * Copyright 2012 Clifton Royston
3 * Copyright 2013 John-Mark Gurney
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/param.h>
41 #define MAX_STR_FLAGS_RESULT 80
42 #define MAX_INT_STR_DIGITS 12
44 #define nitems(x) (sizeof((x)) / sizeof((x)[0]))
45 #define __INT_MAX INT_MAX
46 #endif /* __APPLE__ */
48 static const int64_t halfExabyte
= (int64_t)500*1000*1000*1000*1000*1000L;
57 /* tests 0-13 test 1000 suffixes */
58 { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
59 { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
60 { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
61 { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
62 { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
63 { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
64 { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
65 { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
66 { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
67 { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
68 { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
69 { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
70 { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
71 { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
73 /* tests 14-27 test 1024 suffixes */
74 { 2, "0 ", (int64_t)0L, 0, HN_AUTOSCALE
},
75 { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE
},
76 { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE
},
77 { 3, "1 G", (int64_t)512*1024*1024L, 0, HN_AUTOSCALE
},
78 { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, HN_AUTOSCALE
},
79 { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
80 { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
81 { 2, "1 ", (int64_t)1L, 0, HN_AUTOSCALE
},
82 { 3, "2 K", (int64_t)1536L, 0, HN_AUTOSCALE
},
83 { 3, "2 M", (int64_t)1536*1024L, 0, HN_AUTOSCALE
},
84 { 3, "2 G", (int64_t)1536*1024*1024L, 0, HN_AUTOSCALE
},
85 { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, HN_AUTOSCALE
},
86 { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
87 { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
89 /* tests 28-37 test rounding */
90 { 3, "0 M", (int64_t)500*1000L-1, HN_DIVISOR_1000
, HN_AUTOSCALE
},
91 { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
92 { 3, "1 M", (int64_t)1000*1000L + 500*1000L-1, HN_DIVISOR_1000
, HN_AUTOSCALE
},
93 { 3, "2 M", (int64_t)1000*1000L + 500*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
94 { 3, "0 K", (int64_t)512L-1, 0, HN_AUTOSCALE
},
95 { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE
},
96 { 3, "0 M", (int64_t)512*1024L-1, 0, HN_AUTOSCALE
},
97 { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE
},
98 { 3, "1 M", (int64_t)1024*1024L + 512*1024L-1, 0, HN_AUTOSCALE
},
99 { 3, "2 M", (int64_t)1024*1024L + 512*1024L, 0, HN_AUTOSCALE
},
101 /* tests 38-61 test specific scale factors with 1000 divisor */
102 { 3, "0 k", (int64_t)0L, HN_DIVISOR_1000
, 1 },
103 { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000
, 1 },
104 { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000
, 2 },
105 { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000
, 2 },
106 { 3, "0 G", (int64_t)500*1000L, HN_DIVISOR_1000
, 3 },
107 { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000
, 3 },
108 { 3, "0 T", (int64_t)500*1000*1000L, HN_DIVISOR_1000
, 4 },
109 { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000
, 4 },
110 { 3, "0 P", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000
, 5 },
111 { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000
, 5 },
112 { 3, "0 E", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000
, 6 },
113 { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, 6 },
114 { 3, "0 k", (int64_t)1L, HN_DIVISOR_1000
, 1 },
115 { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000
, 1 },
116 { 3, "0 M", (int64_t)1500L, HN_DIVISOR_1000
, 2 },
117 { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000
, 2 },
118 { 3, "0 G", (int64_t)1500*1000L, HN_DIVISOR_1000
, 3 },
119 { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000
, 3 },
120 { 3, "0 T", (int64_t)1500*1000*1000L, HN_DIVISOR_1000
, 4 },
121 { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000
, 4 },
122 { 3, "0 P", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000
, 5 },
123 { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000
, 5 },
124 { 3, "0 E", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000
, 6 },
125 { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, 6 },
127 /* tests 62-85 test specific scale factors with 1024 divisor */
128 { 3, "0 K", (int64_t)0L, 0, 1 },
129 { 3, "1 K", (int64_t)512L, 0, 1 },
130 { 3, "0 M", (int64_t)512L, 0, 2 },
131 { 3, "1 M", (int64_t)512*1024L, 0, 2 },
132 { 3, "0 G", (int64_t)512*1024L, 0, 3 },
133 { 3, "1 G", (int64_t)512*1024*1024L, 0, 3 },
134 { 3, "0 T", (int64_t)512*1024*1024L, 0, 4 },
135 { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, 4 },
136 { 3, "0 P", (int64_t)512*1024*1024*1024L, 0, 5 },
137 { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, 5 },
138 { 3, "0 E", (int64_t)512*1024*1024*1024*1024L, 0, 6 },
139 { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, 6 },
140 { 3, "0 K", (int64_t)1L, 0, 1 },
141 { 3, "2 K", (int64_t)1536L, 0, 1 },
142 { 3, "0 M", (int64_t)1536L, 0, 2 },
143 { 3, "2 M", (int64_t)1536*1024L, 0, 2 },
144 { 3, "0 G", (int64_t)1536*1024L, 0, 3 },
145 { 3, "2 G", (int64_t)1536*1024*1024L, 0, 3 },
146 { 3, "0 T", (int64_t)1536*1024*1024L, 0, 4 },
147 { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, 4 },
148 { 3, "0 P", (int64_t)1536*1024*1024*1024L, 0, 5 },
149 { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, 5 },
150 { 3, "0 E", (int64_t)1536*1024*1024*1024*1024L, 0, 6 },
151 { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, 6 },
153 /* tests 86-99 test invalid specific scale values of < 0 or >= 7 with
154 and without HN_DIVISOR_1000 set */
155 /* all should return errors with new code; with old, the latter 3
156 are instead processed as if having AUTOSCALE and/or GETSCALE set */
157 { -1, "", (int64_t)1L, 0, 7 },
158 { -1, "", (int64_t)1L, HN_DIVISOR_1000
, 7 },
159 { -1, "", (int64_t)1L, 0, 1000 },
160 { -1, "", (int64_t)1L, HN_DIVISOR_1000
, 1000 },
161 { -1, "", (int64_t)0L, 0, 1000*1000 },
162 { -1, "", (int64_t)0L, HN_DIVISOR_1000
, 1000*1000 },
163 { -1, "", (int64_t)0L, 0, INT_MAX
},
164 { -1, "", (int64_t)0L, HN_DIVISOR_1000
, INT_MAX
},
166 /* Negative scale values are not handled well
167 by the existing library routine - should report as error */
168 /* all should return errors with new code, fail assertion with old */
170 { -1, "", (int64_t)1L, 0, -1 },
171 { -1, "", (int64_t)1L, HN_DIVISOR_1000
, -1 },
172 { -1, "", (int64_t)1L, 0, -1000 },
173 { -1, "", (int64_t)1L, HN_DIVISOR_1000
, -1000 },
175 /* __INT_MIN doesn't print properly, skipped. */
177 { -1, "", (int64_t)1L, 0, -__INT_MAX
},
178 { -1, "", (int64_t)1L, HN_DIVISOR_1000
, -__INT_MAX
},
181 /* tests for scale == 0, without autoscale */
182 /* tests 100-114 test scale 0 with 1000 divisor - print first N digits */
183 { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000
, 0 },
184 { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000
, 0 },
185 { 3, "10 ", (int64_t)10L, HN_DIVISOR_1000
, 0 },
186 { 3, "0 M", (int64_t)150L, HN_DIVISOR_1000
, HN_NOSPACE
},
187 { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000
, HN_NOSPACE
},
188 { 3, "0 M", (int64_t)999L, HN_DIVISOR_1000
, HN_NOSPACE
},
189 { 4, "150", (int64_t)150L, HN_DIVISOR_1000
, 0 },
190 { 4, "500", (int64_t)500L, HN_DIVISOR_1000
, 0 },
191 { 4, "999", (int64_t)999L, HN_DIVISOR_1000
, 0 },
192 { 5, "100", (int64_t)1000L, HN_DIVISOR_1000
, 0 },
193 { 5, "150", (int64_t)1500L, HN_DIVISOR_1000
, 0 },
194 { 7, "500", (int64_t)500*1000L, HN_DIVISOR_1000
, 0 },
195 { 8, "150", (int64_t)1500*1000L, HN_DIVISOR_1000
, 0 },
196 { 10, "500", (int64_t)500*1000*1000L, HN_DIVISOR_1000
, 0 },
197 { 11, "150", (int64_t)1500*1000*1000L, HN_DIVISOR_1000
, 0 },
199 /* tests 115-126 test scale 0 with 1024 divisor - print first N digits */
200 { 2, "0 ", (int64_t)0L, 0, 0 },
201 { 2, "1 ", (int64_t)1L, 0, 0 },
202 { 3, "10 ", (int64_t)10L, 0, 0 },
203 { 4, "150", (int64_t)150L, 0, 0 },
204 { 4, "500", (int64_t)500L, 0, 0 },
205 { 4, "999", (int64_t)999L, 0, 0 },
206 { 5, "100", (int64_t)1000L, 0, 0 },
207 { 5, "150", (int64_t)1500L, 0, 0 },
208 { 7, "500", (int64_t)500*1000L, 0, 0 },
209 { 8, "150", (int64_t)1500*1000L, 0, 0 },
210 { 10, "500", (int64_t)500*1000*1000L, 0, 0 },
211 { 11, "150", (int64_t)1500*1000*1000L, 0, 0 },
213 /* Test boundary cases for very large positive/negative number formatting */
214 /* Explicit scale, divisor 1024 */
216 /* XXX = requires length 5 (buflen 6) for some cases*/
217 /* KLUDGE - test loop below will bump length 5 up to 5 */
218 { 3, "8 E", INT64_MAX
, 0, 6 },
219 { 4, "-8 E", -INT64_MAX
, 0, 6 },
220 { 3, "0 E", (int64_t)92*1024*1024*1024*1024*1024L, 0, 6 },
221 { 3, "0 E", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 6 },
222 { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, 0, 6 },
223 { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 6 },
224 { 3, "0 E", (int64_t)81*1024*1024*1024*1024*1024L, 0, 6 },
225 { 3, "0 E", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 6 },
226 { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, 5 },
227 { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 5 },
228 { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, 5 },
229 { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 5 },
230 { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, 5 },
231 { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 5 },
233 /* Explicit scale, divisor 1000 */
234 { 3, "9 E", INT64_MAX
, HN_DIVISOR_1000
, 6 },
235 { 4, "-9 E", -INT64_MAX
, HN_DIVISOR_1000
, 6 },
236 { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 6 },
237 { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 6 },
238 { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 6 },
239 { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 6 },
240 { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 5 },
241 { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 5 },
242 { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 5 },
243 { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 5 },
245 /* Autoscale, divisor 1024 */
246 { 3, "8 E", INT64_MAX
, 0, HN_AUTOSCALE
},
247 { 4, "-8 E", -INT64_MAX
, 0, HN_AUTOSCALE
},
248 { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
249 { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
250 { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
251 { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
252 { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
253 { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE
},
254 /* Autoscale, divisor 1000 */
255 { 3, "9 E", INT64_MAX
, HN_DIVISOR_1000
, HN_AUTOSCALE
},
256 { 4, "-9 E", -INT64_MAX
, HN_DIVISOR_1000
, HN_AUTOSCALE
},
257 { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
258 { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
259 { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
260 { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
262 /* 0 scale, divisor 1024 */
263 { 12, "skdj", INT64_MAX
, 0, 0 },
264 { 21, "-9223", -INT64_MAX
, 0, 0 },
265 { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, 0, 0 },
266 { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 0 },
267 { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, 0, 0 },
268 { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 0 },
269 { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, 0, 0 },
270 { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 0 },
272 /* 0 scale, divisor 1000 */
273 /* XXX - why does this fail? */
274 { -1, "", INT64_MAX
, HN_DIVISOR_1000
, 0 },
275 { 21, "-9223", -INT64_MAX
, HN_DIVISOR_1000
, 0 },
276 { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 0 },
277 { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 0 },
278 { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 0 },
279 { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 0 },
280 /* Expected to pass */
281 { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 0 },
282 { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000
, 0 },
286 /* Need to implement tests for GETSCALE */
287 /* { ?, "", (int64_t)0L, HN_DIVISOR_1000, HN_GETSCALE },
290 /* Tests for HN_DECIMAL */
291 /* Positive, Autoscale */
292 { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
293 { 5, "994 k", (int64_t)994*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
294 { 5, "995 k", (int64_t)995*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
295 { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
296 { 5, "1.0 M", (int64_t)1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
297 { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
298 { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
299 { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
300 { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
301 { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
302 { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
303 { 5, "994 M", (int64_t)994*1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
304 { 5, "995 M", (int64_t)995*1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
305 { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
307 { 5, "500 K", (int64_t)500*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
308 { 5, "994 K", (int64_t)994*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
309 { 5, "995 K", (int64_t)995*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
310 { 5, "999 K", (int64_t)999*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
311 { 5, "1.0 M", (int64_t)1000*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
312 { 5, "1.0 M", (int64_t)1018*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
313 { 5, "1.0 M", (int64_t)1019*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
314 { 5, "1.5 M", (int64_t)1536*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
315 { 5, "1.9 M", (int64_t)1996*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
316 { 5, "2.0 M", (int64_t)1997*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
317 { 5, "2.0 M", (int64_t)2047*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
318 { 5, "2.0 M", (int64_t)2048*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
319 { 5, "2.0 M", (int64_t)2099*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
320 { 5, "2.1 M", (int64_t)2100*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
321 { 5, "9.9 M", (int64_t)10188*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
322 /* XXX - shouldn't the following two be "10. M"? */
323 { 4, "10 M", (int64_t)10189*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
324 { 4, "10 M", (int64_t)10240*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
325 { 5, "500 M", (int64_t)500*1024*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
326 { 5, "994 M", (int64_t)994*1024*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
327 { 5, "995 M", (int64_t)995*1024*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
328 { 5, "999 M", (int64_t)999*1024*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
329 { 5, "1.0 G", (int64_t)1000*1024*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
330 { 5, "1.0 G", (int64_t)1023*1024*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
332 /* Negative, Autoscale - should pass */
333 { 6, "-1.5 ", -(int64_t)1500*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
334 { 6, "-1.9 ", -(int64_t)1949*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
335 { 6, "-9.9 ", -(int64_t)9949*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
337 { 6, "-1.5 ", -(int64_t)1536*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
338 { 6, "-1.9 ", -(int64_t)1949*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
339 { 6, "-9.7 ", -(int64_t)9949*1024L, HN_DECIMAL
, HN_AUTOSCALE
},
341 /* Positive/negative, at maximum scale */
342 { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
343 { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
344 { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, HN_AUTOSCALE
},
345 { 5, "9.2 E", INT64_MAX
, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
346 /* Negatives work with latest rev only: */
347 { 6, "-9.2 ", -INT64_MAX
, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
348 { 6, "-8.9 ", -(int64_t)8949*1000*1000*1000*1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, HN_AUTOSCALE
},
350 { 5, "8.0 E", INT64_MAX
, HN_DECIMAL
, HN_AUTOSCALE
},
351 { 5, "7.9 E", INT64_MAX
-(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL
, HN_AUTOSCALE
},
352 { 6, "-8.0 ", -INT64_MAX
, HN_DECIMAL
, HN_AUTOSCALE
},
353 { 6, "-7.9 ", -INT64_MAX
+(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL
, HN_AUTOSCALE
},
355 /* Positive, Fixed scales */
356 { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 1 },
357 { 5, "0.5 M", (int64_t)500*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
358 { 5, "949 k", (int64_t)949*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 1 },
359 { 5, "0.9 M", (int64_t)949*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
360 { 5, "950 k", (int64_t)950*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 1 },
361 { 5, "1.0 M", (int64_t)950*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
362 { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 1 },
363 { 5, "1.0 M", (int64_t)999*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
364 { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
365 { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
366 { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
367 { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
368 { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
369 { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
370 { 5, "0.5 G", (int64_t)500*1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 3 },
371 { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 2 },
372 { 5, "1.0 G", (int64_t)999*1000*1000L, HN_DECIMAL
|HN_DIVISOR_1000
, 3 },
373 /* Positive/negative, at maximum scale */
374 { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, 5 },
375 { 5, "1.0 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, 6 },
376 { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, 6 },
377 { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000
, 6 },
378 { 5, "9.2 E", INT64_MAX
, HN_DECIMAL
|HN_DIVISOR_1000
, 6 },
380 /* HN_DECIMAL + binary + fixed scale cases not completed */
381 { 5, "512 K", (int64_t)512*1024L, HN_DECIMAL
, 1 },
382 { 5, "0.5 M", (int64_t)512*1024L, HN_DECIMAL
, 2 },
384 /* Negative, Fixed scales */
385 /* Not yet added, but should work with latest rev */
390 /* Command line options usage */
392 usage(char * progname
) {
393 printf("%s: tests libutil humanize_number function\n", progname
);
394 printf("Usage: %s [-nE] [-l num] [-v]\n\n", progname
);
395 printf("Options:\n");
396 printf("\t-l num\tSet max length for result; buflen = num + 1\n");
397 printf("\t\t (NOTE: does not change expected result strings.)\n");
398 printf("\t-n\tInclude negative scale tests, which cause older libutil\n");
399 printf("\t\t version of function to coredump with assertion failure\n");
400 printf("\t-E\tInclude numbers > 1/2 Exa[byte] which currently fail\n");
401 printf("\t-v\tVerbose - always print summary results\n");
402 printf("\t-h, -?\tShow options\n");
405 /* Parse command line options */
407 read_options(int argc
, char * const argv
[], size_t *bufLength
,
408 int *includeNegativeScale
, int *includeExabytes
, int *verbose
) {
412 while ((ch
= getopt(argc
, argv
, "nEh?vl:")) != -1) {
417 break; /* UNREACHABLE */
422 break; /* UNREACHABLE */
424 sscanf(optarg
, "%zu", &temp
);
425 *bufLength
= temp
+ 1;
428 *includeNegativeScale
= 1;
431 *includeExabytes
= 1;
444 { HN_AUTOSCALE
, "HN_AUTOSCALE" },
445 { HN_GETSCALE
, "HN_GETSCALE" },
446 { HN_DIVISOR_1000
, "HN_DIVISOR_1000"},
448 { HN_DECIMAL
, "HN_DECIMAL"},
451 static const char *separator
= "|";
453 /* Format flags parameter for meaningful display */
455 str_flags(int hn_flags
, char *noFlags
) {
459 result
= malloc(MAX_STR_FLAGS_RESULT
);
462 for (i
= 0; i
< sizeof flags
/ sizeof *flags
; i
++) {
463 if (hn_flags
& flags
[i
].value
) {
465 strlcat(result
, separator
,
466 MAX_STR_FLAGS_RESULT
);
467 strlcat(result
, flags
[i
].name
, MAX_STR_FLAGS_RESULT
);
471 if (strlen(result
) == 0)
472 strlcat(result
, noFlags
, MAX_STR_FLAGS_RESULT
);
477 /* Format scale parameter for meaningful display */
479 str_scale(int scale
) {
482 if (scale
== HN_AUTOSCALE
|| scale
== HN_GETSCALE
)
483 return str_flags(scale
, "");
485 result
= malloc(MAX_INT_STR_DIGITS
);
487 snprintf(result
, MAX_INT_STR_DIGITS
, "%d", scale
);
492 testskipped(size_t i
)
495 printf("ok %zu # skip - not turned on\n", i
);
499 main(int argc
, char * const argv
[])
502 char *flag_str
, *scale_str
;
503 size_t buflen
, errcnt
, i
, skipped
, tested
;
506 int includeExabyteTests
;
511 includeExabyteTests
= 0;
514 read_options(argc
, argv
, &buflen
, &includeNegScale
,
515 &includeExabyteTests
, &verbose
);
517 buf
= malloc(buflen
);
523 printf("Warning: buffer size %zu != 4, expect some results to differ.\n", buflen
);
525 printf("1..%zu\n", nitems(test_args
));
526 for (i
= 0; i
< nitems(test_args
); i
++) {
528 if (test_args
[i
].num
== INT64_MAX
&& buflen
== 4) {
529 /* Start final tests which require buffer of 6 */
532 buf
= malloc(buflen
);
534 printf("Buffer length increased to %zu\n",
538 if (test_args
[i
].scale
< 0 && ! includeNegScale
) {
543 if (test_args
[i
].num
>= halfExabyte
&& ! includeExabyteTests
) {
549 r
= humanize_number(buf
, buflen
, test_args
[i
].num
, "",
550 test_args
[i
].scale
, test_args
[i
].flags
);
551 flag_str
= str_flags(test_args
[i
].flags
, "[no flags]");
552 scale_str
= str_scale(test_args
[i
].scale
);
554 if (r
!= test_args
[i
].retval
) {
556 printf("wrong return value on index %zu, "
557 "buflen: %zu, got: %d + \"%s\", "
558 "expected %d + \"%s\"; num = %jd, "
559 "scale = %s, flags= %s.\n",
560 i
, buflen
, r
, buf
, test_args
[i
].retval
,
562 (intmax_t)test_args
[i
].num
,
563 scale_str
, flag_str
);
565 printf("not ok %zu # return %d != %d\n",
566 i
+ 1, r
, test_args
[i
].retval
);
568 } else if (strcmp(buf
, test_args
[i
].res
) != 0) {
570 printf("result mismatch on index %zu, got: "
571 "\"%s\", expected \"%s\"; num = %jd, "
572 "scale = %s, flags= %s.\n",
573 i
, buf
, test_args
[i
].res
,
574 (intmax_t)test_args
[i
].num
,
575 scale_str
, flag_str
);
577 printf("not ok %zu # buf \"%s\" != \"%s\"\n",
578 i
+ 1, buf
, test_args
[i
].res
);
582 printf("successful result on index %zu, "
583 "returned %d, got: \"%s\"; num = %jd, "
584 "scale = %s, flags= %s.\n",
586 (intmax_t)test_args
[i
].num
,
587 scale_str
, flag_str
);
589 printf("ok %zu\n", i
+ 1);
595 printf("total errors: %zu/%zu tests, %zu skipped\n", errcnt
,