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