1 /* $OpenBSD: fmt_test.c,v 1.13 2017/03/15 04:31:41 dtucker Exp $ */ 2 3 /* 4 * Combined tests for fmt_scaled and scan_scaled. 5 * Ian Darwin, January 2001. Public domain. 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <sys/types.h> 12 #include <errno.h> 13 #include <unistd.h> 14 15 #include <util.h> 16 17 static int fmt_test(void); 18 static int scan_test(void); 19 20 static void print_errno(int e); 21 static int assert_int(int testnum, int checknum, int expect, int result); 22 static int assert_errno(int testnum, int checknum, int expect, int result); 23 static int assert_llong(int testnum, int checknum, long long expect, long long result); 24 static int assert_str(int testnum, int checknum, char * expect, char * result); 25 26 extern char *__progname; 27 static int verbose = 0; 28 29 __dead static void usage(int stat) 30 { 31 fprintf(stderr, "usage: %s [-v]\n", __progname); 32 exit(stat); 33 } 34 35 int 36 main(int argc, char **argv) 37 { 38 extern char *optarg; 39 extern int optind; 40 int i, ch; 41 42 while ((ch = getopt(argc, argv, "hv")) != -1) { 43 switch (ch) { 44 case 'v': 45 verbose = 1; 46 break; 47 case 'h': 48 usage(0); 49 case '?': 50 default: 51 usage(1); 52 } 53 } 54 argc -= optind; 55 argv += optind; 56 57 if (verbose) 58 printf("Starting fmt_test\n"); 59 i = fmt_test(); 60 if (verbose) 61 printf("Starting scan_test\n"); 62 i += scan_test(); 63 if (i) { 64 printf("*** %d errors in libutil/fmt_scaled tests ***\n", i); 65 } else { 66 if (verbose) 67 printf("Tests done; no unexpected errors\n"); 68 } 69 return i; 70 } 71 72 /************** tests for fmt_scaled *******************/ 73 74 static struct { /* the test cases */ 75 long long input; 76 char *expect; 77 int err; 78 } ddata[] = { 79 { 0, "0B", 0 }, 80 { 1, "1B", 0 }, 81 { -1, "-1B", 0 }, 82 { 100, "100B", 0}, 83 { -100, "-100B", 0}, 84 { 999, "999B", 0 }, 85 { 1000, "1000B", 0 }, 86 { 1023, "1023B", 0 }, 87 { -1023, "-1023B", 0 }, 88 { 1024, "1.0K", 0 }, 89 { 1025, "1.0K", 0 }, 90 { 1234, "1.2K", 0 }, 91 { -1234, "-1.2K", 0 }, 92 { 1484, "1.4K", 0 }, /* rounding boundary, down */ 93 { 1485, "1.5K", 0 }, /* rounding boundary, up */ 94 { -1484, "-1.4K", 0 }, /* rounding boundary, down */ 95 { -1485, "-1.5K", 0 }, /* rounding boundary, up */ 96 { 1536, "1.5K", 0 }, 97 { 1786, "1.7K", 0 }, 98 { 1800, "1.8K", 0 }, 99 { 2000, "2.0K", 0 }, 100 { 123456, "121K", 0 }, 101 { 578318, "565K", 0 }, 102 { 902948, "882K", 0 }, 103 { 1048576, "1.0M", 0}, 104 { 1048628, "1.0M", 0}, 105 { 1049447, "1.0M", 0}, 106 { -102400, "-100K", 0}, 107 { -103423, "-101K", 0 }, 108 { 7299072, "7.0M", 0 }, 109 { 409478144L, "391M", 0 }, 110 { -409478144L, "-391M", 0 }, 111 { 999999999L, "954M", 0 }, 112 { 1499999999L, "1.4G", 0 }, 113 { 12475423744LL, "11.6G", 0}, 114 { 1LL<<61, "2.0E", 0 }, 115 { 1LL<<62, "4.0E", 0 }, 116 { 1LL<<63, "", ERANGE }, 117 { 1099512676352LL, "1.0T", 0} 118 }; 119 # define DDATA_LENGTH (sizeof ddata/sizeof *ddata) 120 121 static int 122 fmt_test(void) 123 { 124 unsigned int i, e, errs = 0; 125 int ret; 126 char buf[FMT_SCALED_STRSIZE]; 127 128 for (i = 0; i < DDATA_LENGTH; i++) { 129 strlcpy(buf, "UNSET", FMT_SCALED_STRSIZE); 130 errno = 0; 131 ret = fmt_scaled(ddata[i].input, buf); 132 e = errno; 133 if (verbose) { 134 printf("%lld --> %s (%d)", ddata[i].input, buf, ret); 135 if (ret == -1) 136 print_errno(e); 137 printf("\n"); 138 } 139 if (ret == -1) 140 errs += assert_int(i, 1, ret, ddata[i].err == 0 ? 0 : -1); 141 if (ddata[i].err) 142 errs += assert_errno(i, 2, ddata[i].err, e); 143 else 144 errs += assert_str(i, 3, ddata[i].expect, buf); 145 } 146 147 return errs; 148 } 149 150 /************** tests for scan_scaled *******************/ 151 152 153 #define IMPROBABLE (-42) 154 155 struct { /* the test cases */ 156 char *input; 157 long long result; 158 int err; 159 } sdata[] = { 160 { "0", 0, 0 }, 161 { "123", 123, 0 }, 162 { "1k", 1024, 0 }, /* lower case */ 163 { "100.944", 100, 0 }, /* should --> 100 (truncates fraction) */ 164 { "10099", 10099LL, 0 }, 165 { "1M", 1048576LL, 0 }, 166 { "1.1M", 1153433LL, 0 }, /* fractions */ 167 { "1.111111111111111111M", 1165084LL, 0 }, /* fractions */ 168 { "1.55M", 1625292LL, 0 }, /* fractions */ 169 { "1.9M", 1992294LL, 0 }, /* fractions */ 170 { "-2K", -2048LL, 0 }, /* negatives */ 171 { "-2.2K", -2252LL, 0 }, /* neg with fract */ 172 { "4.5k", 4608, 0 }, 173 { "4.5555555555555555K", 4664, 0 }, 174 { "4.5555555555555555555K", 4664, 0 }, /* handle enough digits? */ 175 { "4.555555555555555555555555555555K", 4664, 0 }, /* ignores extra digits? */ 176 { "1G", 1073741824LL, 0 }, 177 { "G", 0, 0 }, /* should == 0G? */ 178 { "1234567890", 1234567890LL, 0 }, /* should work */ 179 { "1.5E", 1729382256910270464LL, 0 }, /* big */ 180 { "32948093840918378473209480483092", 0, ERANGE }, /* too big */ 181 { "1.5Q", 0, EINVAL }, /* invalid multiplier */ 182 { "1ab", 0, EINVAL }, /* ditto */ 183 { "3&", 0, EINVAL }, /* ditto */ 184 { "5.0e3", 0, EINVAL }, /* digits after */ 185 { "5.0E3", 0, EINVAL }, /* ditto */ 186 { "1..0", 0, EINVAL }, /* bad format */ 187 { "", 0, 0 }, /* boundary */ 188 { "--1", -1, EINVAL }, 189 { "++42", -1, EINVAL }, 190 /* { "9223372036854775808", -9223372036854775808LL, 0 }, */ /* XXX */ 191 }; 192 # define SDATA_LENGTH (sizeof sdata/sizeof *sdata) 193 194 static void 195 print_errno(int e) 196 { 197 switch(e) { 198 case EINVAL: printf("EINVAL"); break; 199 case EDOM: printf("EDOM"); break; 200 case ERANGE: printf("ERANGE"); break; 201 default: printf("errno %d", e); 202 } 203 } 204 205 /** Print one result */ 206 static void 207 print(char *input, long long result, int ret, int e) 208 { 209 printf("\"%40s\" --> %lld (%d)", input, result, ret); 210 if (ret == -1) { 211 printf(" -- "); 212 print_errno(e); 213 } 214 printf("\n"); 215 } 216 217 static int 218 scan_test(void) 219 { 220 unsigned int i, errs = 0, e; 221 int ret; 222 long long result; 223 224 for (i = 0; i < SDATA_LENGTH; i++) { 225 result = IMPROBABLE; 226 errno = 0; 227 /* printf("Calling scan_scaled(%s, ...)\n", sdata[i].input); */ 228 ret = scan_scaled(sdata[i].input, &result); 229 e = errno; /* protect across printfs &c. */ 230 if (verbose) 231 print(sdata[i].input, result, ret, e); 232 if (ret == -1) 233 errs += assert_int(i, 1, ret, sdata[i].err == 0 ? 0 : -1); 234 if (sdata[i].err) 235 errs += assert_errno(i, 2, sdata[i].err, e); 236 else 237 errs += assert_llong(i, 3, sdata[i].result, result); 238 } 239 return errs; 240 } 241 242 /************** common testing stuff *******************/ 243 244 static int 245 assert_int(int testnum, int check, int expect, int result) 246 { 247 if (expect == result) 248 return 0; 249 printf("** FAILURE: test %d check %d, expect %d, result %d **\n", 250 testnum, check, expect, result); 251 return 1; 252 } 253 254 static int 255 assert_errno(int testnum, int check, int expect, int result) 256 { 257 if (expect == result) 258 return 0; 259 printf("** FAILURE: test %d check %d, expect ", 260 testnum, check); 261 print_errno(expect); 262 printf(", got "); 263 print_errno(result); 264 printf(" **\n"); 265 return 1; 266 } 267 268 static int 269 assert_llong(int testnum, int check, long long expect, long long result) 270 { 271 if (expect == result) 272 return 0; 273 printf("** FAILURE: test %d check %d, expect %lld, result %lld **\n", 274 testnum, check, expect, result); 275 return 1; 276 } 277 278 static int 279 assert_str(int testnum, int check, char * expect, char * result) 280 { 281 if (strcmp(expect, result) == 0) 282 return 0; 283 printf("** FAILURE: test %d check %d, expect %s, result %s **\n", 284 testnum, check, expect, result); 285 return 1; 286 } 287