1256130Sjmg/*-
2256130Sjmg * Copyright 2012 Clifton Royston
3256130Sjmg * Copyright 2013 John-Mark Gurney
4256130Sjmg * All rights reserved.
5256130Sjmg *
6256130Sjmg * Redistribution and use in source and binary forms, with or without
7256130Sjmg * modification, are permitted provided that the following conditions
8256130Sjmg * are met:
9256130Sjmg * 1. Redistributions of source code must retain the above copyright
10256130Sjmg *    notice, this list of conditions and the following disclaimer.
11256130Sjmg * 2. Redistributions in binary form must reproduce the above copyright
12256130Sjmg *    notice, this list of conditions and the following disclaimer in the
13256130Sjmg *    documentation and/or other materials provided with the distribution.
14256130Sjmg *
15256130Sjmg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16256130Sjmg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17256130Sjmg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18256130Sjmg * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19256130Sjmg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20256130Sjmg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21256130Sjmg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22256130Sjmg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23256130Sjmg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24256130Sjmg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25256130Sjmg * SUCH DAMAGE.
26256130Sjmg *
27256130Sjmg * $FreeBSD$
28256130Sjmg *
29256130Sjmg */
30256130Sjmg
31256130Sjmg#include <sys/types.h>
32256130Sjmg#include <stdlib.h>
33256130Sjmg#include <libutil.h>
34256130Sjmg#include <stdio.h>
35256130Sjmg#include <string.h>
36256130Sjmg#include <inttypes.h>
37256130Sjmg#include <math.h>
38256130Sjmg#include <unistd.h>
39256130Sjmg#include <limits.h>
40256130Sjmg
41256130Sjmgextern char * optarg;
42256130Sjmg
43256130Sjmg#define	MAX_STR_FLAGS_RESULT	80
44256130Sjmg#define MAX_INT_STR_DIGITS	12
45256130Sjmg
46256130Sjmgstatic const int64_t halfExabyte = (int64_t)500*1000*1000*1000*1000*1000L;
47256130Sjmg
48256130Sjmgstatic struct {
49256130Sjmg	int retval;
50256130Sjmg	const char *res;
51256130Sjmg	int64_t num;
52256130Sjmg	int flags;
53256130Sjmg	int scale;
54256130Sjmg} test_args[] = {
55256130Sjmg	/* tests 0-13 test 1000 suffixes */
56256130Sjmg	{ 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, HN_AUTOSCALE },
57256130Sjmg	{ 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, HN_AUTOSCALE },
58256130Sjmg	{ 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
59256130Sjmg	{ 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
60256130Sjmg	{ 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
61256130Sjmg	{ 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
62256130Sjmg	{ 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
63256130Sjmg	{ 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, HN_AUTOSCALE },
64256130Sjmg	{ 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, HN_AUTOSCALE },
65256130Sjmg	{ 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
66256130Sjmg	{ 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
67256130Sjmg	{ 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
68256130Sjmg	{ 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
69256130Sjmg	{ 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
70256130Sjmg
71256130Sjmg	/* tests 14-27 test 1024 suffixes */
72256130Sjmg	{ 2, "0 ", (int64_t)0L, 0, HN_AUTOSCALE },
73256130Sjmg	{ 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE },
74256130Sjmg	{ 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE },
75256130Sjmg	{ 3, "1 G", (int64_t)512*1024*1024L, 0, HN_AUTOSCALE },
76256130Sjmg	{ 3, "1 T", (int64_t)512*1024*1024*1024L, 0, HN_AUTOSCALE },
77256130Sjmg	{ 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
78256130Sjmg	{ 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
79256130Sjmg	{ 2, "1 ", (int64_t)1L, 0, HN_AUTOSCALE },
80256130Sjmg	{ 3, "2 K", (int64_t)1536L, 0, HN_AUTOSCALE },
81256130Sjmg	{ 3, "2 M", (int64_t)1536*1024L, 0, HN_AUTOSCALE },
82256130Sjmg	{ 3, "2 G", (int64_t)1536*1024*1024L, 0, HN_AUTOSCALE },
83256130Sjmg	{ 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, HN_AUTOSCALE },
84256130Sjmg	{ 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
85256130Sjmg	{ 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
86256130Sjmg
87256130Sjmg	/* tests 28-37 test rounding */
88256130Sjmg	{ 3, "0 M", (int64_t)500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE },
89256130Sjmg	{ 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
90256130Sjmg	{ 3, "1 M", (int64_t)1000*1000L + 500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE },
91256130Sjmg	{ 3, "2 M", (int64_t)1000*1000L + 500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
92256130Sjmg	{ 3, "0 K", (int64_t)512L-1, 0, HN_AUTOSCALE },
93256130Sjmg	{ 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE },
94256130Sjmg	{ 3, "0 M", (int64_t)512*1024L-1, 0, HN_AUTOSCALE },
95256130Sjmg	{ 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE },
96256130Sjmg	{ 3, "1 M", (int64_t)1024*1024L + 512*1024L-1, 0, HN_AUTOSCALE },
97256130Sjmg	{ 3, "2 M", (int64_t)1024*1024L + 512*1024L, 0, HN_AUTOSCALE },
98256130Sjmg
99256130Sjmg	/* tests 38-61 test specific scale factors with 1000 divisor */
100256130Sjmg	{ 3, "0 k", (int64_t)0L, HN_DIVISOR_1000, 1 },
101256130Sjmg	{ 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, 1 },
102256130Sjmg	{ 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, 2 },
103256130Sjmg	{ 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, 2 },
104256130Sjmg	{ 3, "0 G", (int64_t)500*1000L, HN_DIVISOR_1000, 3 },
105256130Sjmg	{ 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 3 },
106256130Sjmg	{ 3, "0 T", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 4 },
107256130Sjmg	{ 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 4 },
108256130Sjmg	{ 3, "0 P", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 5 },
109256130Sjmg	{ 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 },
110256130Sjmg	{ 3, "0 E", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
111256130Sjmg	{ 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
112256130Sjmg	{ 3, "0 k", (int64_t)1L, HN_DIVISOR_1000, 1 },
113256130Sjmg	{ 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, 1 },
114256130Sjmg	{ 3, "0 M", (int64_t)1500L, HN_DIVISOR_1000, 2 },
115256130Sjmg	{ 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, 2 },
116256130Sjmg	{ 3, "0 G", (int64_t)1500*1000L, HN_DIVISOR_1000, 3 },
117256130Sjmg	{ 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 3 },
118256130Sjmg	{ 3, "0 T", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 4 },
119256130Sjmg	{ 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 4 },
120256130Sjmg	{ 3, "0 P", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 5 },
121256130Sjmg	{ 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 },
122256130Sjmg	{ 3, "0 E", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
123256130Sjmg	{ 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
124256130Sjmg
125256130Sjmg	/* tests 62-85 test specific scale factors with 1024 divisor */
126256130Sjmg	{ 3, "0 K", (int64_t)0L, 0, 1 },
127256130Sjmg	{ 3, "1 K", (int64_t)512L, 0, 1 },
128256130Sjmg	{ 3, "0 M", (int64_t)512L, 0, 2 },
129256130Sjmg	{ 3, "1 M", (int64_t)512*1024L, 0, 2 },
130256130Sjmg	{ 3, "0 G", (int64_t)512*1024L, 0, 3 },
131256130Sjmg	{ 3, "1 G", (int64_t)512*1024*1024L, 0, 3 },
132256130Sjmg	{ 3, "0 T", (int64_t)512*1024*1024L, 0, 4 },
133256130Sjmg	{ 3, "1 T", (int64_t)512*1024*1024*1024L, 0, 4 },
134256130Sjmg	{ 3, "0 P", (int64_t)512*1024*1024*1024L, 0, 5 },
135256130Sjmg	{ 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, 5 },
136256130Sjmg	{ 3, "0 E", (int64_t)512*1024*1024*1024*1024L, 0, 6 },
137256130Sjmg	{ 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, 6 },
138256130Sjmg	{ 3, "0 K", (int64_t)1L, 0, 1 },
139256130Sjmg	{ 3, "2 K", (int64_t)1536L, 0, 1 },
140256130Sjmg	{ 3, "0 M", (int64_t)1536L, 0, 2 },
141256130Sjmg	{ 3, "2 M", (int64_t)1536*1024L, 0, 2 },
142256130Sjmg	{ 3, "0 G", (int64_t)1536*1024L, 0, 3 },
143256130Sjmg	{ 3, "2 G", (int64_t)1536*1024*1024L, 0, 3 },
144256130Sjmg	{ 3, "0 T", (int64_t)1536*1024*1024L, 0, 4 },
145256130Sjmg	{ 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, 4 },
146256130Sjmg	{ 3, "0 P", (int64_t)1536*1024*1024*1024L, 0, 5 },
147256130Sjmg	{ 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, 5 },
148256130Sjmg	{ 3, "0 E", (int64_t)1536*1024*1024*1024*1024L, 0, 6 },
149256130Sjmg	{ 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, 6 },
150256130Sjmg
151256130Sjmg	/* tests 86-99 test invalid specific scale values of < 0 or >= 7 with
152256130Sjmg	and without HN_DIVISOR_1000 set */
153256130Sjmg	/*  all should return errors with new code; with old, the latter 3
154256130Sjmg	are instead processed as if having AUTOSCALE and/or GETSCALE set */
155256130Sjmg	{ -1, "", (int64_t)1L, 0, 7 },
156256130Sjmg	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, 7 },
157256130Sjmg	{ -1, "", (int64_t)1L, 0, 1000 },
158256130Sjmg	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, 1000 },
159256130Sjmg	{ -1, "", (int64_t)0L, 0, 1000*1000 },
160256130Sjmg	{ -1, "", (int64_t)0L, HN_DIVISOR_1000, 1000*1000 },
161256130Sjmg	{ -1, "", (int64_t)0L, 0, INT_MAX },
162256130Sjmg	{ -1, "", (int64_t)0L, HN_DIVISOR_1000, INT_MAX },
163256130Sjmg
164256130Sjmg	/* Negative scale values are not handled well
165256130Sjmg	 by the existing library routine - should report as error */
166256130Sjmg	/*  all should return errors with new code, fail assertion with old */
167256130Sjmg
168256130Sjmg	{ -1, "", (int64_t)1L, 0, -1 },
169256130Sjmg	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, -1 },
170256130Sjmg	{ -1, "", (int64_t)1L, 0, -1000 },
171256130Sjmg	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, -1000 },
172256130Sjmg
173256130Sjmg	/* __INT_MIN doesn't print properly, skipped. */
174256130Sjmg
175256130Sjmg	{ -1, "", (int64_t)1L, 0, -__INT_MAX },
176256130Sjmg	{ -1, "", (int64_t)1L, HN_DIVISOR_1000, -__INT_MAX },
177256130Sjmg
178256130Sjmg
179256130Sjmg	/* tests for scale == 0, without autoscale */
180256130Sjmg	/* tests 100-114 test scale 0 with 1000 divisor - print first N digits */
181256130Sjmg	{ 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, 0 },
182256130Sjmg	{ 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, 0 },
183256130Sjmg	{ 3, "10 ", (int64_t)10L, HN_DIVISOR_1000, 0 },
184256130Sjmg	{ 3, "0 M", (int64_t)150L, HN_DIVISOR_1000, HN_NOSPACE },
185256130Sjmg	{ 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, HN_NOSPACE },
186256130Sjmg	{ 3, "0 M", (int64_t)999L, HN_DIVISOR_1000, HN_NOSPACE },
187256130Sjmg	{ 4, "150", (int64_t)150L, HN_DIVISOR_1000, 0 },
188256130Sjmg	{ 4, "500", (int64_t)500L, HN_DIVISOR_1000, 0 },
189256130Sjmg	{ 4, "999", (int64_t)999L, HN_DIVISOR_1000, 0 },
190256130Sjmg	{ 5, "100", (int64_t)1000L, HN_DIVISOR_1000, 0 },
191256130Sjmg	{ 5, "150", (int64_t)1500L, HN_DIVISOR_1000, 0 },
192256130Sjmg	{ 7, "500", (int64_t)500*1000L, HN_DIVISOR_1000, 0 },
193256130Sjmg	{ 8, "150", (int64_t)1500*1000L, HN_DIVISOR_1000, 0 },
194256130Sjmg	{ 10, "500", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 0 },
195256130Sjmg	{ 11, "150", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 0 },
196256130Sjmg
197256130Sjmg	/* tests 115-126 test scale 0 with 1024 divisor - print first N digits */
198256130Sjmg	{ 2, "0 ", (int64_t)0L, 0, 0 },
199256130Sjmg	{ 2, "1 ", (int64_t)1L, 0, 0 },
200256130Sjmg	{ 3, "10 ", (int64_t)10L, 0, 0 },
201256130Sjmg	{ 4, "150", (int64_t)150L, 0, 0 },
202256130Sjmg	{ 4, "500", (int64_t)500L, 0, 0 },
203256130Sjmg	{ 4, "999", (int64_t)999L, 0, 0 },
204256130Sjmg	{ 5, "100", (int64_t)1000L, 0, 0 },
205256130Sjmg	{ 5, "150", (int64_t)1500L, 0, 0 },
206256130Sjmg	{ 7, "500", (int64_t)500*1000L, 0, 0 },
207256130Sjmg	{ 8, "150", (int64_t)1500*1000L, 0, 0 },
208256130Sjmg	{ 10, "500", (int64_t)500*1000*1000L, 0, 0 },
209256130Sjmg	{ 11, "150", (int64_t)1500*1000*1000L, 0, 0 },
210256130Sjmg
211256130Sjmg	/* Test boundary cases for very large positive/negative number formatting */
212256130Sjmg	/* Explicit scale, divisor 1024 */
213256130Sjmg
214256130Sjmg	/* XXX = requires length 5 (buflen 6) for some cases*/
215256130Sjmg	/* KLUDGE - test loop below will bump length 5 up to 5 */
216256130Sjmg	{ 3, "8 E",   INT64_MAX, 0, 6 },
217256130Sjmg	{ 4, "-8 E", -INT64_MAX, 0, 6 },
218256130Sjmg	{ 3, "0 E", (int64_t)92*1024*1024*1024*1024*1024L, 0, 6 },
219256130Sjmg	{ 3, "0 E", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 6 },
220256130Sjmg	{ 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, 0, 6 },
221256130Sjmg	{ 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 6 },
222256130Sjmg	{ 3, "0 E", (int64_t)81*1024*1024*1024*1024*1024L, 0, 6 },
223256130Sjmg	{ 3, "0 E", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 6 },
224256130Sjmg	{ 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, 5 },
225256130Sjmg	{ 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 5 },
226256130Sjmg	{ 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, 5 },
227256130Sjmg	{ 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 5 },
228256130Sjmg	{ 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, 5 },
229256130Sjmg	{ 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 5 },
230256130Sjmg
231256130Sjmg	/* Explicit scale, divisor 1000 */
232256130Sjmg	{ 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, 6 },
233256130Sjmg	{ 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000,  6 },
234256130Sjmg	{ 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 },
235256130Sjmg	{ 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 },
236256130Sjmg	{ 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 },
237256130Sjmg	{ 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 },
238256130Sjmg	{ 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 },
239256130Sjmg	{ 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 },
240256130Sjmg	{ 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 },
241256130Sjmg	{ 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 },
242256130Sjmg
243256130Sjmg	/* Autoscale, divisor 1024 */
244256130Sjmg	{ 3, "8 E",   INT64_MAX, 0, HN_AUTOSCALE },
245256130Sjmg	{ 4, "-8 E", -INT64_MAX, 0, HN_AUTOSCALE },
246256130Sjmg	{ 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
247256130Sjmg	{ 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
248256130Sjmg	{ 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
249256130Sjmg	{ 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
250256130Sjmg	{ 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
251256130Sjmg	{ 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
252256130Sjmg	/* Autoscale, divisor 1000 */
253256130Sjmg	{ 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE },
254256130Sjmg	{ 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE },
255256130Sjmg	{ 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE },
256256130Sjmg	{ 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE },
257256130Sjmg	{ 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE },
258256130Sjmg	{ 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, HN_AUTOSCALE },
259256130Sjmg
260256130Sjmg	/* 0 scale, divisor 1024 */
261256130Sjmg	{ 12, "skdj",  INT64_MAX, 0, 0 },
262256130Sjmg	{ 21, "-9223", -INT64_MAX, 0, 0 },
263256130Sjmg	{ 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, 0, 0 },
264256130Sjmg	{ 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 0 },
265256130Sjmg	{ 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, 0, 0 },
266256130Sjmg	{ 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 0 },
267256130Sjmg	{ 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, 0, 0 },
268256130Sjmg	{ 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 0 },
269256130Sjmg
270256130Sjmg	/* 0 scale, divisor 1000 */
271256130Sjmg	/* XXX - why does this fail? */
272256130Sjmg	{ -1, "", INT64_MAX, HN_DIVISOR_1000, 0 },
273256130Sjmg	{ 21, "-9223", -INT64_MAX, HN_DIVISOR_1000,  0 },
274256130Sjmg	{ 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
275256130Sjmg	{ 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
276256130Sjmg	{ 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
277256130Sjmg	{ 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
278256130Sjmg	/* Expected to pass */
279256130Sjmg	{ 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
280256130Sjmg	{ 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  0 },
281256130Sjmg
282256130Sjmg
283256130Sjmg
284256130Sjmg	/* Need to implement tests for GETSCALE */
285256130Sjmg/*	{ ?, "", (int64_t)0L, HN_DIVISOR_1000, HN_GETSCALE },
286256130Sjmg	...
287256130Sjmg*/
288256130Sjmg        /* Tests for HN_DECIMAL */
289256130Sjmg        /* Positive, Autoscale */
290256130Sjmg	{ 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
291256130Sjmg	{ 5, "994 k", (int64_t)994*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
292256130Sjmg	{ 5, "995 k", (int64_t)995*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
293256130Sjmg	{ 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
294256130Sjmg	{ 5, "1.0 M", (int64_t)1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
295256130Sjmg	{ 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
296256130Sjmg	{ 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
297256130Sjmg	{ 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
298256130Sjmg	{ 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
299256130Sjmg	{ 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
300256130Sjmg	{ 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
301256130Sjmg	{ 5, "994 M", (int64_t)994*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
302256130Sjmg	{ 5, "995 M", (int64_t)995*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
303256130Sjmg	{ 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
304256130Sjmg
305256130Sjmg	{ 5, "500 K", (int64_t)500*1024L, HN_DECIMAL, HN_AUTOSCALE },
306256130Sjmg	{ 5, "994 K", (int64_t)994*1024L, HN_DECIMAL, HN_AUTOSCALE },
307256130Sjmg	{ 5, "995 K", (int64_t)995*1024L, HN_DECIMAL, HN_AUTOSCALE },
308256130Sjmg	{ 5, "999 K", (int64_t)999*1024L, HN_DECIMAL, HN_AUTOSCALE },
309256130Sjmg	{ 5, "1.0 M", (int64_t)1000*1024L, HN_DECIMAL, HN_AUTOSCALE },
310256130Sjmg	{ 5, "1.0 M", (int64_t)1018*1024L, HN_DECIMAL, HN_AUTOSCALE },
311256130Sjmg	{ 5, "1.0 M", (int64_t)1019*1024L, HN_DECIMAL, HN_AUTOSCALE },
312256130Sjmg	{ 5, "1.5 M", (int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE },
313256130Sjmg	{ 5, "1.9 M", (int64_t)1996*1024L, HN_DECIMAL, HN_AUTOSCALE },
314256130Sjmg	{ 5, "2.0 M", (int64_t)1997*1024L, HN_DECIMAL, HN_AUTOSCALE },
315256130Sjmg	{ 5, "2.0 M", (int64_t)2047*1024L, HN_DECIMAL, HN_AUTOSCALE },
316256130Sjmg	{ 5, "2.0 M", (int64_t)2048*1024L, HN_DECIMAL, HN_AUTOSCALE },
317256130Sjmg	{ 5, "2.0 M", (int64_t)2099*1024L, HN_DECIMAL, HN_AUTOSCALE },
318256130Sjmg	{ 5, "2.1 M", (int64_t)2100*1024L, HN_DECIMAL, HN_AUTOSCALE },
319256130Sjmg	{ 5, "9.9 M", (int64_t)10188*1024L, HN_DECIMAL, HN_AUTOSCALE },
320256130Sjmg	/* XXX - shouldn't the following two be "10. M"? */
321256130Sjmg	{ 4, "10 M", (int64_t)10189*1024L, HN_DECIMAL, HN_AUTOSCALE },
322256130Sjmg	{ 4, "10 M", (int64_t)10240*1024L, HN_DECIMAL, HN_AUTOSCALE },
323256130Sjmg	{ 5, "500 M", (int64_t)500*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
324256130Sjmg	{ 5, "994 M", (int64_t)994*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
325256130Sjmg	{ 5, "995 M", (int64_t)995*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
326256130Sjmg	{ 5, "999 M", (int64_t)999*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
327256130Sjmg	{ 5, "1.0 G", (int64_t)1000*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
328256130Sjmg	{ 5, "1.0 G", (int64_t)1023*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
329256130Sjmg
330256130Sjmg        /* Negative, Autoscale - should pass */
331256130Sjmg	{ 6, "-1.5 ", -(int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
332256130Sjmg	{ 6, "-1.9 ", -(int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
333256130Sjmg	{ 6, "-9.9 ", -(int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
334256130Sjmg
335256130Sjmg	{ 6, "-1.5 ", -(int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE },
336256130Sjmg	{ 6, "-1.9 ", -(int64_t)1949*1024L, HN_DECIMAL, HN_AUTOSCALE },
337256130Sjmg	{ 6, "-9.7 ", -(int64_t)9949*1024L, HN_DECIMAL, HN_AUTOSCALE },
338256130Sjmg
339256130Sjmg	/* Positive/negative, at maximum scale */
340256130Sjmg	{ 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
341256130Sjmg	{ 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
342256130Sjmg	{ 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
343256130Sjmg	{ 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
344256130Sjmg        /* Negatives work with latest rev only: */
345256130Sjmg	{ 6, "-9.2 ", -INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
346256130Sjmg	{ 6, "-8.9 ", -(int64_t)8949*1000*1000*1000*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
347256130Sjmg
348256130Sjmg	{ 5, "8.0 E",   INT64_MAX, HN_DECIMAL, HN_AUTOSCALE },
349256130Sjmg	{ 5, "7.9 E",   INT64_MAX-(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL, HN_AUTOSCALE },
350256130Sjmg	{ 6, "-8.0 ", -INT64_MAX, HN_DECIMAL, HN_AUTOSCALE },
351256130Sjmg	{ 6, "-7.9 ",   -INT64_MAX+(int64_t)100*1024*1024*1024*1024*1024LL, HN_DECIMAL, HN_AUTOSCALE },
352256130Sjmg
353256130Sjmg	/* Positive, Fixed scales */
354256130Sjmg	{ 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
355256130Sjmg	{ 5, "0.5 M", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
356256130Sjmg	{ 5, "949 k", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
357256130Sjmg	{ 5, "0.9 M", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
358256130Sjmg	{ 5, "950 k", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
359256130Sjmg	{ 5, "1.0 M", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
360256130Sjmg	{ 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
361256130Sjmg	{ 5, "1.0 M", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
362256130Sjmg	{ 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
363256130Sjmg	{ 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
364256130Sjmg	{ 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
365256130Sjmg	{ 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
366256130Sjmg	{ 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
367256130Sjmg	{ 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
368256130Sjmg	{ 5, "0.5 G", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3 },
369256130Sjmg	{ 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
370256130Sjmg	{ 5, "1.0 G", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3 },
371256130Sjmg	/* Positive/negative, at maximum scale */
372256130Sjmg	{ 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 },
373256130Sjmg	{ 5, "1.0 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
374256130Sjmg	{ 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
375256130Sjmg	{ 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
376256130Sjmg	{ 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, 6 },
377256130Sjmg
378256130Sjmg	/* HN_DECIMAL + binary + fixed scale cases not completed */
379256130Sjmg	{ 5, "512 K", (int64_t)512*1024L, HN_DECIMAL, 1 },
380256130Sjmg	{ 5, "0.5 M", (int64_t)512*1024L, HN_DECIMAL, 2 },
381256130Sjmg
382256130Sjmg	/* Negative, Fixed scales */
383256130Sjmg        /* Not yet added, but should work with latest rev */
384256130Sjmg
385256130Sjmg};
386256130Sjmg
387256130Sjmg
388256130Sjmg/* Command line options usage */
389256130Sjmgstatic void
390256130Sjmgusage(char * progname) {
391256130Sjmg	printf("%s: tests libutil humanize_number function\n", progname);
392256130Sjmg	printf("Usage: %s [-nE] [-l num] [-v]\n\n", progname);
393256130Sjmg	printf("Options:\n");
394256130Sjmg	printf("\t-l num\tSet max length for result; buflen = num + 1\n");
395256130Sjmg	printf("\t\t  (NOTE: does not change expected result strings.)\n");
396256130Sjmg	printf("\t-n\tInclude negative scale tests, which cause older libutil\n");
397256130Sjmg	printf("\t\t  version of function to coredump with assertion failure\n");
398256130Sjmg	printf("\t-E\tInclude numbers > 1/2 Exa[byte] which currently fail\n");
399256130Sjmg	printf("\t-v\tVerbose - always print summary results\n");
400256130Sjmg	printf("\t-h, -?\tShow options\n");
401256130Sjmg}
402256130Sjmg
403256130Sjmg/* Parse command line options */
404256130Sjmgstatic void
405256130Sjmgread_options(int argc, char * const argv[], size_t *bufLength,
406256130Sjmg    int *includeNegativeScale, int *includeExabytes, int *verbose) {
407256130Sjmg	int ch;
408256130Sjmg	size_t temp;
409256130Sjmg
410256130Sjmg	while ((ch = getopt(argc, argv, "nEh?vl:")) != -1) {
411256130Sjmg		switch (ch) {
412256130Sjmg			default:
413256130Sjmg				usage(argv[0]);
414256130Sjmg				exit(1);
415256130Sjmg				break;	/* UNREACHABLE */
416256130Sjmg			case 'h' :
417256130Sjmg			case '?' :
418256130Sjmg				usage(argv[0]);
419256130Sjmg				exit(0);
420256130Sjmg				break;	/* UNREACHABLE */
421256130Sjmg			case 'l' :
422256130Sjmg				sscanf(optarg, "%zu", &temp);
423256130Sjmg				*bufLength = temp + 1;
424256130Sjmg				break;
425256130Sjmg			case 'n' :
426256130Sjmg				*includeNegativeScale = 1;
427256130Sjmg				break;
428256130Sjmg			case 'E' :
429256130Sjmg				*includeExabytes = 1;
430256130Sjmg				break;
431256130Sjmg			case 'v' :
432256130Sjmg				*verbose = 1;
433256130Sjmg				break;
434256130Sjmg		}
435256130Sjmg	}
436256130Sjmg}
437256130Sjmg
438256130Sjmgstatic struct {
439256130Sjmg	int value;
440256130Sjmg	const char *name;
441256130Sjmg } flags[] = {
442256130Sjmg	{ HN_AUTOSCALE, "HN_AUTOSCALE" },
443256130Sjmg	{ HN_GETSCALE, "HN_GETSCALE" },
444256130Sjmg	{ HN_DIVISOR_1000, "HN_DIVISOR_1000"},
445256130Sjmg	{ HN_B, "HN_B"},
446256130Sjmg	{ HN_DECIMAL, "HN_DECIMAL"},
447256130Sjmg};
448256130Sjmg
449256130Sjmgstatic const char *separator = "|";
450256130Sjmg
451256130Sjmg/* Format flags parameter for meaningful display */
452256130Sjmgstatic char *
453256130Sjmgstr_flags(int hn_flags, char *noFlags) {
454256130Sjmg	size_t i;
455256130Sjmg	char * result;
456256130Sjmg
457256130Sjmg	result = malloc(MAX_STR_FLAGS_RESULT);
458256130Sjmg	result[0] = '\0';
459256130Sjmg
460256130Sjmg	for (i = 0; i < sizeof flags / sizeof *flags; i++) {
461256130Sjmg		if (hn_flags & flags[i].value) {
462256130Sjmg			if (*result != 0)
463256130Sjmg				strlcat(result, separator,
464256130Sjmg				    MAX_STR_FLAGS_RESULT);
465256130Sjmg			strlcat(result, flags[i].name, MAX_STR_FLAGS_RESULT);
466256130Sjmg		}
467256130Sjmg	}
468256130Sjmg
469256130Sjmg	if (strlen(result) == 0)
470256130Sjmg		strlcat(result, noFlags, MAX_STR_FLAGS_RESULT);
471256130Sjmg	return result;
472256130Sjmg}
473256130Sjmg
474256130Sjmg
475256130Sjmg/* Format scale parameter for meaningful display */
476256130Sjmgstatic char *
477256130Sjmgstr_scale(int scale) {
478256130Sjmg	char *result;
479256130Sjmg
480256130Sjmg	if (scale == HN_AUTOSCALE || scale == HN_GETSCALE)
481256130Sjmg		return str_flags(scale, "");
482256130Sjmg
483256130Sjmg	result = malloc(MAX_INT_STR_DIGITS);
484256130Sjmg	result[0] = '\0';
485256130Sjmg	snprintf(result, MAX_INT_STR_DIGITS, "%d", scale);
486256130Sjmg	return result;
487256130Sjmg}
488256130Sjmg
489256130Sjmgstatic void
490256130Sjmgtestskipped(size_t i)
491256130Sjmg{
492256130Sjmg
493256130Sjmg	printf("ok %lu # skip - not turned on\n", i);
494256130Sjmg}
495256130Sjmg
496256130Sjmgint
497256130Sjmgmain(int argc, char * const argv[])
498256130Sjmg{
499256130Sjmg	char *buf;
500256130Sjmg	char *flag_str, *scale_str;
501256130Sjmg	size_t i;
502256130Sjmg	size_t errcnt, tested, skipped;
503256130Sjmg	int r;
504256130Sjmg	size_t buflen;
505256130Sjmg	int includeNegScale;
506256130Sjmg	int includeExabyteTests;
507256130Sjmg	int verbose;
508256130Sjmg
509256130Sjmg	buflen = 4;
510256130Sjmg	includeNegScale = 0;
511256130Sjmg	includeExabyteTests = 0;
512256130Sjmg	verbose = 0;
513256130Sjmg
514256130Sjmg	read_options(argc, argv, &buflen, &includeNegScale,
515256130Sjmg	    &includeExabyteTests, &verbose);
516256130Sjmg
517256130Sjmg	buf = malloc(buflen);
518256130Sjmg	errcnt = 0;
519256130Sjmg	tested = 0;
520256130Sjmg	skipped = 0;
521256130Sjmg
522256130Sjmg	if (buflen != 4)
523256130Sjmg		printf("Warning: buffer size %zu != 4, expect some results to differ.\n", buflen);
524256130Sjmg
525256130Sjmg	printf("1..%lu\n", sizeof test_args / sizeof *test_args);
526256130Sjmg	for (i = 0; i < sizeof test_args / sizeof *test_args; i++) {
527256130Sjmg		/* KLUDGE */
528256130Sjmg		if (test_args[i].num == INT64_MAX && buflen == 4) {
529256130Sjmg		        /* Start final tests which require buffer of 6 */
530256130Sjmg		        free(buf);
531256130Sjmg		        buflen = 6;
532256130Sjmg                        buf = malloc(buflen);
533256130Sjmg                        if (verbose)
534256130Sjmg                                printf("Buffer length increased to %zu\n",
535256130Sjmg				    buflen);
536256130Sjmg		}
537256130Sjmg
538256130Sjmg		if (test_args[i].scale < 0 && ! includeNegScale) {
539256130Sjmg			skipped++;
540256130Sjmg			testskipped(i);
541256130Sjmg			continue;
542256130Sjmg		}
543256130Sjmg		if (test_args[i].num >= halfExabyte && ! includeExabyteTests) {
544256130Sjmg			skipped++;
545256130Sjmg			testskipped(i);
546256130Sjmg			continue;
547256130Sjmg		}
548256130Sjmg
549256130Sjmg		r = humanize_number(buf, buflen, test_args[i].num, "",
550256130Sjmg		    test_args[i].scale, test_args[i].flags);
551256130Sjmg		flag_str = str_flags(test_args[i].flags, "[no flags]");
552256130Sjmg		scale_str = str_scale(test_args[i].scale);
553256130Sjmg
554256130Sjmg		if (r != test_args[i].retval) {
555256130Sjmg			if (verbose)
556256130Sjmg				printf("wrong return value on index %lu, buflen: %zu, got: %d + \"%s\", expected %d + \"%s\"; num = %" PRId64 ", scale = %s, flags= %s.\n",
557256130Sjmg				    i, buflen, r, buf, test_args[i].retval,
558256130Sjmg				    test_args[i].res, test_args[i].num,
559256130Sjmg				    scale_str, flag_str);
560256130Sjmg			else
561256130Sjmg				printf("not ok %lu # return %d != %d\n", i, r,
562256130Sjmg				    test_args[i].retval);
563256130Sjmg			errcnt++;
564256130Sjmg		} else if (strcmp(buf, test_args[i].res) != 0) {
565256130Sjmg			if (verbose)
566256130Sjmg				printf("result mismatch on index %lu, got: \"%s\", expected \"%s\"; num = %" PRId64 ", scale = %s, flags= %s.\n",
567256130Sjmg				    i, buf, test_args[i].res, test_args[i].num,
568256130Sjmg				    scale_str, flag_str);
569256130Sjmg			else
570256130Sjmg				printf("not ok %lu # buf \"%s\" != \"%s\"\n", i,
571256130Sjmg				    buf, test_args[i].res);
572256130Sjmg			errcnt++;
573256130Sjmg		} else {
574256130Sjmg			if (verbose)
575256130Sjmg				printf("successful result on index %lu, returned %d, got: \"%s\"; num = %" PRId64 ", scale = %s, flags= %s.\n",
576256130Sjmg				    i, r, buf, test_args[i].num, scale_str,
577256130Sjmg				    flag_str);
578256130Sjmg			else
579256130Sjmg				printf("ok %lu\n", i);
580256130Sjmg		}
581256130Sjmg		tested++;
582256130Sjmg	}
583256130Sjmg
584256130Sjmg	if (verbose)
585256130Sjmg		printf("total errors: %lu/%lu tests, %lu skipped\n", errcnt,
586256130Sjmg		    tested, skipped);
587256130Sjmg
588256130Sjmg	if (errcnt)
589256130Sjmg		return 1;
590256130Sjmg
591256130Sjmg	return 0;
592256130Sjmg}
593