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