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