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