fmt_test.c revision 1.13
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
17static int fmt_test(void);
18static int scan_test(void);
19
20static void print_errno(int e);
21static int assert_int(int testnum, int checknum, int expect, int result);
22static int assert_errno(int testnum, int checknum, int expect, int result);
23static int assert_llong(int testnum, int checknum, long long expect, long long result);
24static int assert_str(int testnum, int checknum, char * expect, char * result);
25
26extern char *__progname;
27static 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
35int
36main(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
74static 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
121static int
122fmt_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
155struct {					/* 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
194static void
195print_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 */
206static void
207print(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
217static int
218scan_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
244static int
245assert_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
254static int
255assert_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
268static int
269assert_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
278static int
279assert_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