xref: /openbsd-src/regress/lib/libutil/fmt_scaled/fmt_test.c (revision df8f77ad52f129e828e5a0faf8dc866791114c4e)
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