1 /* $NetBSD: t_humanize_number.c,v 1.8 2012/03/18 07:14:08 jruoho Exp $ */
4 * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
42 const char *ho_suffix
;
45 int ho_retval
; /* expected return value */
46 const char *ho_retstr
; /* expected string in buffer */
49 * Rev. 1.6 produces "10.0".
51 { 5, 10737418236ULL * 1024, "",
52 HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
, 3, "10T" },
55 HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
, 3, "10M" },
56 { 5, 10500000, "", /* just for reference */
57 HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
, 3, "10M" },
60 * Trailing space. Rev. 1.7 produces "1 ".
62 { 5, 1, "", 0, HN_NOSPACE
, 1, "1" },
64 { 5, 1, "", 0, 0, 2, "1 " }, /* just for reference */
65 { 5, 1, "", 0, HN_B
, 3, "1 B" }, /* and more ... */
66 { 5, 1, "", 0, HN_DECIMAL
, 2, "1 " },
67 { 5, 1, "", 0, HN_NOSPACE
| HN_B
, 2, "1B" },
68 { 5, 1, "", 0, HN_B
| HN_DECIMAL
, 3, "1 B" },
69 { 5, 1, "", 0, HN_NOSPACE
| HN_B
| HN_DECIMAL
, 2, "1B" },
72 * Space and HN_B. Rev. 1.7 produces "1B".
74 { 5, 1, "", HN_AUTOSCALE
, HN_B
, 3, "1 B" },
75 { 5, 1000, "", /* just for reference */
76 HN_AUTOSCALE
, HN_B
, 3, "1 K" },
79 * Truncated output. Rev. 1.7 produces "1.0 K".
81 { 6, 1000, "A", HN_AUTOSCALE
, HN_DECIMAL
, -1, "" },
84 * Failure case reported by Greg Troxel <gdt@NetBSD.org>.
85 * Rev. 1.11 incorrectly returns 5 with filling the buffer
89 HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
, 4, "1.0G" },
90 /* Similar case it prints 1000 where it shouldn't */
92 HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
, 4, "1.0M" },
94 HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
, 4, "1.0M" },
102 const struct hnflags scale_flags
[] = {
103 { HN_GETSCALE
, "HN_GETSCALE" },
104 { HN_AUTOSCALE
, "HN_AUTOSCALE" },
106 const struct hnflags normal_flags
[] = {
107 { HN_DECIMAL
, "HN_DECIMAL" },
108 { HN_NOSPACE
, "HN_NOSPACE" },
110 { HN_DIVISOR_1000
, "HN_DIVISOR_1000" },
113 const char *formatflags(char *, size_t, const struct hnflags
*, size_t, int);
115 void w_printf(const char *, ...) __printflike(1, 2);
116 int main(int, char *[]);
119 formatflags(char *buf
, size_t buflen
, const struct hnflags
*hfs
,
120 size_t hfslen
, int flags
)
122 const struct hnflags
*hf
;
124 ssize_t len
= buflen
;
125 unsigned int i
, found
;
129 snprintf(buf
, buflen
, "0");
132 for (i
= found
= 0; i
< hfslen
&& flags
& ~found
; i
++) {
134 if (flags
& hf
->hf_flags
) {
135 found
|= hf
->hf_flags
;
136 n
= snprintf(p
, len
, "|%s", hf
->hf_name
);
140 /* Print `flags' as number */
150 snprintf(p
, len
, "|0x%x", flags
);
151 return (*buf
== '|' ? buf
+ 1 : buf
);
154 static int col
, bol
= 1;
159 fprintf(stderr
, "\n");
165 w_printf(const char *fmt
, ...)
173 n
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
174 if (n
>= (int)sizeof(buf
)) {
182 fprintf(stderr
, "\n "), col
= 4;
184 fprintf(stderr
, " "), col
++;
186 fprintf(stderr
, "%s", buf
);
191 vfprintf(stderr
, fmt
, ap
);
197 ATF_TC(humanize_number_basic
);
198 ATF_TC_HEAD(humanize_number_basic
, tc
)
201 atf_tc_set_md_var(tc
, "descr", "Test humanize_number(3)");
204 ATF_TC_BODY(humanize_number_basic
, tc
)
207 const struct hnopts
*ho
;
213 for (i
= 0; i
< __arraycount(hnopts
); i
++) {
215 if (buflen
< ho
->ho_len
) {
217 buf
= realloc(buf
, buflen
);
219 atf_tc_fail("realloc(..., %zu) failed", buflen
);
222 rv
= humanize_number(buf
, ho
->ho_len
, ho
->ho_num
,
223 ho
->ho_suffix
, ho
->ho_scale
, ho
->ho_flags
);
225 if (rv
== ho
->ho_retval
&&
226 (rv
== -1 || strcmp(buf
, ho
->ho_retstr
) == 0))
229 w_printf("humanize_number(\"%s\", %zu, %" PRId64
",",
230 ho
->ho_retstr
, ho
->ho_len
, ho
->ho_num
);
231 w_printf("\"%s\",", ho
->ho_suffix
);
232 w_printf("%s,", formatflags(fbuf
, sizeof(fbuf
), scale_flags
,
233 sizeof(scale_flags
) / sizeof(scale_flags
[0]),
235 w_printf("%s)", formatflags(fbuf
, sizeof(fbuf
), normal_flags
,
236 sizeof(normal_flags
) / sizeof(normal_flags
[0]),
238 w_printf("= %d,", ho
->ho_retval
);
240 w_printf("%d/[%s]", rv
, rv
== -1 ? "" : buf
);
242 atf_tc_fail_nonfatal("Failed for table entry %d", i
);
246 ATF_TC(humanize_number_big
);
247 ATF_TC_HEAD(humanize_number_big
, tc
)
250 atf_tc_set_md_var(tc
, "descr", "Test humanize "
251 "big numbers (PR lib/44097)");
254 ATF_TC_BODY(humanize_number_big
, tc
)
262 (void)memset(buf
, 0, sizeof(buf
));
264 rv
= humanize_number(buf
, 10, 10000, "", HN_AUTOSCALE
, HN_NOSPACE
);
266 ATF_REQUIRE(rv
!= -1);
267 ATF_CHECK_STREQ(buf
, "10000");
270 * A bogus value with large number.
272 (void)memset(buf
, 0, sizeof(buf
));
274 rv
= humanize_number(buf
, 10, INT64_MAX
, "", HN_AUTOSCALE
, HN_NOSPACE
);
276 ATF_REQUIRE(rv
!= -1);
277 ATF_REQUIRE(strcmp(buf
, "0") != 0);
280 * Large buffer with HN_AUTOSCALE. Entirely bogus.
282 (void)memset(buf
, 0, sizeof(buf
));
284 rv
= humanize_number(buf
, sizeof(buf
), 10000, "",
285 HN_AUTOSCALE
, HN_NOSPACE
);
287 ATF_REQUIRE(rv
!= -1);
288 ATF_REQUIRE(strcmp(buf
, "0%d%s%d%s%s%s") != 0);
293 * The man page says that len must be at least 4.
294 * 3 works, but anything less that will not. This
295 * is because baselen starts with 2 for positive
298 (void)memset(buf
, 0, sizeof(buf
));
300 rv
= humanize_number(buf
, 3, 1, "", HN_AUTOSCALE
, HN_NOSPACE
);
302 ATF_REQUIRE(rv
!= -1);
308 ATF_TP_ADD_TC(tp
, humanize_number_basic
);
309 ATF_TP_ADD_TC(tp
, humanize_number_big
);
311 return atf_no_error();