1*cd62a92dSRobert Mustacchi /*
2*cd62a92dSRobert Mustacchi  * Copyright (c) 2009 Philip Guenther
3*cd62a92dSRobert Mustacchi  * All rights reserved.
4*cd62a92dSRobert Mustacchi  *
5*cd62a92dSRobert Mustacchi  * Redistribution and use in source and binary forms, with or without
6*cd62a92dSRobert Mustacchi  * modification, are permitted provided that the following conditions
7*cd62a92dSRobert Mustacchi  * are met:
8*cd62a92dSRobert Mustacchi  *
9*cd62a92dSRobert Mustacchi  *    - Redistributions of source code must retain the above copyright
10*cd62a92dSRobert Mustacchi  *      notice, this list of conditions and the following disclaimer.
11*cd62a92dSRobert Mustacchi  *    - Redistributions in binary form must reproduce the above
12*cd62a92dSRobert Mustacchi  *      copyright notice, this list of conditions and the following
13*cd62a92dSRobert Mustacchi  *      disclaimer in the documentation and/or other materials provided
14*cd62a92dSRobert Mustacchi  *      with the distribution.
15*cd62a92dSRobert Mustacchi  *
16*cd62a92dSRobert Mustacchi  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17*cd62a92dSRobert Mustacchi  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18*cd62a92dSRobert Mustacchi  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19*cd62a92dSRobert Mustacchi  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20*cd62a92dSRobert Mustacchi  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21*cd62a92dSRobert Mustacchi  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22*cd62a92dSRobert Mustacchi  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23*cd62a92dSRobert Mustacchi  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24*cd62a92dSRobert Mustacchi  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*cd62a92dSRobert Mustacchi  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26*cd62a92dSRobert Mustacchi  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*cd62a92dSRobert Mustacchi  * POSSIBILITY OF SUCH DAMAGE.
28*cd62a92dSRobert Mustacchi  */
29*cd62a92dSRobert Mustacchi 
30*cd62a92dSRobert Mustacchi /*
31*cd62a92dSRobert Mustacchi  * Test whether the various stdio functions set the stream orientation
32*cd62a92dSRobert Mustacchi  * ("width") as they should
33*cd62a92dSRobert Mustacchi  */
34*cd62a92dSRobert Mustacchi 
35*cd62a92dSRobert Mustacchi #include <sys/types.h>
36*cd62a92dSRobert Mustacchi #include <err.h>
37*cd62a92dSRobert Mustacchi #include <stddef.h>
38*cd62a92dSRobert Mustacchi #include <stdio.h>
39*cd62a92dSRobert Mustacchi #include <stdlib.h>
40*cd62a92dSRobert Mustacchi #include <string.h>
41*cd62a92dSRobert Mustacchi #include <unistd.h>
42*cd62a92dSRobert Mustacchi #include <wchar.h>
43*cd62a92dSRobert Mustacchi 
44*cd62a92dSRobert Mustacchi char filename[] = "/tmp/fwide.XXXXXXXXXX";
45*cd62a92dSRobert Mustacchi 
46*cd62a92dSRobert Mustacchi FILE *dup_stdout = NULL;
47*cd62a92dSRobert Mustacchi int failures = 0;
48*cd62a92dSRobert Mustacchi 
49*cd62a92dSRobert Mustacchi void
fail(int line,int r,char const * expect,char const * test)50*cd62a92dSRobert Mustacchi fail(int line, int r, char const *expect, char const *test)
51*cd62a92dSRobert Mustacchi {
52*cd62a92dSRobert Mustacchi 	failures++;
53*cd62a92dSRobert Mustacchi 	fprintf(dup_stdout,
54*cd62a92dSRobert Mustacchi 		"FAIL: %d: fwide returned %d, expected %s 0 after %s\n",
55*cd62a92dSRobert Mustacchi 		line, r, expect, test);
56*cd62a92dSRobert Mustacchi }
57*cd62a92dSRobert Mustacchi 
58*cd62a92dSRobert Mustacchi FILE *
setup(int line)59*cd62a92dSRobert Mustacchi setup(int line)
60*cd62a92dSRobert Mustacchi {
61*cd62a92dSRobert Mustacchi 	FILE	*f;
62*cd62a92dSRobert Mustacchi 	int	r;
63*cd62a92dSRobert Mustacchi 
64*cd62a92dSRobert Mustacchi 	if ((f = fopen(filename, "r+")) == NULL)
65*cd62a92dSRobert Mustacchi 		err(2, "fopen");
66*cd62a92dSRobert Mustacchi 	if ((r = fwide(f, 0)) != 0)
67*cd62a92dSRobert Mustacchi 		fail(line, r, "==", "fopen");
68*cd62a92dSRobert Mustacchi 	return (f);
69*cd62a92dSRobert Mustacchi }
70*cd62a92dSRobert Mustacchi 
71*cd62a92dSRobert Mustacchi FILE *
setup_std(FILE * std,int line)72*cd62a92dSRobert Mustacchi setup_std(FILE *std, int line)
73*cd62a92dSRobert Mustacchi {
74*cd62a92dSRobert Mustacchi 	int	r;
75*cd62a92dSRobert Mustacchi 
76*cd62a92dSRobert Mustacchi 	if (freopen(filename, "r+", std) == NULL)
77*cd62a92dSRobert Mustacchi 		err(2, "freopen");
78*cd62a92dSRobert Mustacchi 	if ((r = fwide(std, 0)) != 0)
79*cd62a92dSRobert Mustacchi 		fail(line, r, "==", "freopen");
80*cd62a92dSRobert Mustacchi 	return (std);
81*cd62a92dSRobert Mustacchi }
82*cd62a92dSRobert Mustacchi 
83*cd62a92dSRobert Mustacchi #define TEST_(x, op)						\
84*cd62a92dSRobert Mustacchi 	do {							\
85*cd62a92dSRobert Mustacchi 		f = setup(__LINE__);				\
86*cd62a92dSRobert Mustacchi 		x;						\
87*cd62a92dSRobert Mustacchi 		if (!((r = fwide(f, 0)) op 0))			\
88*cd62a92dSRobert Mustacchi 			fail(__LINE__, r, #op, #x);		\
89*cd62a92dSRobert Mustacchi 		fclose(f);					\
90*cd62a92dSRobert Mustacchi 	} while (0)
91*cd62a92dSRobert Mustacchi 
92*cd62a92dSRobert Mustacchi #define TEST_STD_(std, x, op)					\
93*cd62a92dSRobert Mustacchi 	do {							\
94*cd62a92dSRobert Mustacchi 		f = setup_std(std, __LINE__);			\
95*cd62a92dSRobert Mustacchi 		x;						\
96*cd62a92dSRobert Mustacchi 		if (!((r = fwide(f, 0)) op 0))			\
97*cd62a92dSRobert Mustacchi 			fail(__LINE__, r, #op, #x);		\
98*cd62a92dSRobert Mustacchi 	} while (0)
99*cd62a92dSRobert Mustacchi 
100*cd62a92dSRobert Mustacchi #define TEST_UNCHANGED(x)		TEST_(x, ==)
101*cd62a92dSRobert Mustacchi #define TEST_NARROW(x)			TEST_(x, <)
102*cd62a92dSRobert Mustacchi #define TEST_WIDE(x)			TEST_(x, >)
103*cd62a92dSRobert Mustacchi #define TEST_UNCHANGED_STD(std, x)	TEST_STD_(std, x, ==)
104*cd62a92dSRobert Mustacchi #define TEST_NARROW_STD(std, x)		TEST_STD_(std, x, <)
105*cd62a92dSRobert Mustacchi #define TEST_WIDE_STD(std, x)		TEST_STD_(std, x, >)
106*cd62a92dSRobert Mustacchi 
107*cd62a92dSRobert Mustacchi int
main(int argc,char * argv[])108*cd62a92dSRobert Mustacchi main(int argc, char *argv[])
109*cd62a92dSRobert Mustacchi {
110*cd62a92dSRobert Mustacchi 	char	buffer[BUFSIZ];
111*cd62a92dSRobert Mustacchi 	wchar_t	wbuffer[BUFSIZ];
112*cd62a92dSRobert Mustacchi 	char	*buf;
113*cd62a92dSRobert Mustacchi 	wchar_t	*wbuf;
114*cd62a92dSRobert Mustacchi 	FILE	*f;
115*cd62a92dSRobert Mustacchi 	fpos_t	pos;
116*cd62a92dSRobert Mustacchi 	size_t	size;
117*cd62a92dSRobert Mustacchi 	int	fd, r;
118*cd62a92dSRobert Mustacchi 	char	c;
119*cd62a92dSRobert Mustacchi 	wchar_t	wc;
120*cd62a92dSRobert Mustacchi 
121*cd62a92dSRobert Mustacchi 	if ((fd = dup(1)) == -1)
122*cd62a92dSRobert Mustacchi 		err(2, "dup");
123*cd62a92dSRobert Mustacchi 	if ((dup_stdout = fdopen(fd, "w")) == NULL)
124*cd62a92dSRobert Mustacchi 		err(2, "fdopen");
125*cd62a92dSRobert Mustacchi 	if ((fd = mkstemp(filename)) == -1)
126*cd62a92dSRobert Mustacchi 		err(2, "mkstemp");
127*cd62a92dSRobert Mustacchi 	if (write(fd, "0123456789\n\n", 12) != 12 || close(fd))
128*cd62a92dSRobert Mustacchi 		err(2, "write + close");
129*cd62a92dSRobert Mustacchi 
130*cd62a92dSRobert Mustacchi 	/* status */
131*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fwide(f, 0));
132*cd62a92dSRobert Mustacchi 	TEST_NARROW(fwide(f, -1));
133*cd62a92dSRobert Mustacchi 	TEST_WIDE(fwide(f, 1));
134*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(feof(f));
135*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(ferror(f));
136*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fileno(f));
137*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(clearerr(f));
138*cd62a92dSRobert Mustacchi 
139*cd62a92dSRobert Mustacchi 	/* flush and purge */
140*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fflush(f));
141*cd62a92dSRobert Mustacchi 
142*cd62a92dSRobert Mustacchi 	/* positioning */
143*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fgetpos(f, &pos));
144*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fgetpos(f, &pos); fsetpos(f, &pos));
145*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(ftell(f));
146*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(ftello(f));
147*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fseek(f, 1, SEEK_CUR));
148*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fseek(f, 1, SEEK_SET));
149*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fseek(f, 1, SEEK_END));
150*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fseeko(f, 1, SEEK_CUR));
151*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fseeko(f, 1, SEEK_SET));
152*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(fseeko(f, 1, SEEK_END));
153*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(rewind(f));
154*cd62a92dSRobert Mustacchi 
155*cd62a92dSRobert Mustacchi 	/* buffering */
156*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setbuf(f, NULL));
157*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setbuf(f, buffer));
158*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setvbuf(f, buffer, _IONBF, BUFSIZ));
159*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setvbuf(f, buffer, _IOLBF, BUFSIZ));
160*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setvbuf(f, buffer, _IOFBF, BUFSIZ));
161*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setvbuf(f, NULL, _IONBF, 0));
162*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setvbuf(f, NULL, _IOLBF, 0));
163*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setvbuf(f, NULL, _IOFBF, 0));
164*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setbuffer(f, NULL, 0));
165*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setbuffer(f, buffer, BUFSIZ));
166*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(setlinebuf(f));
167*cd62a92dSRobert Mustacchi 
168*cd62a92dSRobert Mustacchi 	/* locking */
169*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(flockfile(f);funlockfile(f));
170*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED(ftrylockfile(f);funlockfile(f));
171*cd62a92dSRobert Mustacchi 
172*cd62a92dSRobert Mustacchi 	/* input */
173*cd62a92dSRobert Mustacchi 	TEST_NARROW(getc(f));
174*cd62a92dSRobert Mustacchi 	TEST_NARROW(getc_unlocked(f));
175*cd62a92dSRobert Mustacchi 	TEST_NARROW(fgetc(f));
176*cd62a92dSRobert Mustacchi 	TEST_NARROW(c = fgetc(f); ungetc(c, f));
177*cd62a92dSRobert Mustacchi 	TEST_NARROW(fgets(buffer, BUFSIZ, f));
178*cd62a92dSRobert Mustacchi 	TEST_NARROW(fscanf(f, "%s\n", buffer));
179*cd62a92dSRobert Mustacchi 
180*cd62a92dSRobert Mustacchi 	/* output */
181*cd62a92dSRobert Mustacchi 	TEST_NARROW(putc('c', f));
182*cd62a92dSRobert Mustacchi 	TEST_NARROW(putc_unlocked('c', f));
183*cd62a92dSRobert Mustacchi 	TEST_NARROW(fputc('c', f));
184*cd62a92dSRobert Mustacchi 	TEST_NARROW(fputs("foo", f));
185*cd62a92dSRobert Mustacchi 	TEST_NARROW(fprintf(f, "%s\n", "foo"));
186*cd62a92dSRobert Mustacchi 
187*cd62a92dSRobert Mustacchi 	/* input from stdin */
188*cd62a92dSRobert Mustacchi 	TEST_NARROW_STD(stdin, getchar());
189*cd62a92dSRobert Mustacchi 	TEST_NARROW_STD(stdin, getchar_unlocked());
190*cd62a92dSRobert Mustacchi 	TEST_NARROW_STD(stdin, scanf("%s\n", buffer));
191*cd62a92dSRobert Mustacchi 
192*cd62a92dSRobert Mustacchi 	/* output to stdout */
193*cd62a92dSRobert Mustacchi 	TEST_NARROW_STD(stdout, putchar('c'));
194*cd62a92dSRobert Mustacchi 	TEST_NARROW_STD(stdout, putchar_unlocked('c'));
195*cd62a92dSRobert Mustacchi 	TEST_NARROW_STD(stdout, puts("foo"));
196*cd62a92dSRobert Mustacchi 	TEST_NARROW_STD(stdout, printf("foo"));
197*cd62a92dSRobert Mustacchi 
198*cd62a92dSRobert Mustacchi 	/* word-size ops */
199*cd62a92dSRobert Mustacchi 	/*
200*cd62a92dSRobert Mustacchi 	 * fread and fwrite are specified as being implemented in
201*cd62a92dSRobert Mustacchi 	 * terms of fgetc() and fputc() and therefore must set the
202*cd62a92dSRobert Mustacchi 	 * stream orientation to narrow.
203*cd62a92dSRobert Mustacchi 	 */
204*cd62a92dSRobert Mustacchi 	TEST_NARROW(fread(buffer, 4, BUFSIZ / 4, f));
205*cd62a92dSRobert Mustacchi 	TEST_NARROW(fwrite(buffer, 4, BUFSIZ / 4, f));
206*cd62a92dSRobert Mustacchi 
207*cd62a92dSRobert Mustacchi 	/*
208*cd62a92dSRobert Mustacchi 	 * getw() and putw() aren't specified anywhere but logically
209*cd62a92dSRobert Mustacchi 	 * should behave the same as fread/fwrite.  Not all OSes agree:
210*cd62a92dSRobert Mustacchi 	 * Solaris 10 has them not changing the orientation.
211*cd62a92dSRobert Mustacchi 	 */
212*cd62a92dSRobert Mustacchi 	TEST_NARROW(getw(f));
213*cd62a92dSRobert Mustacchi 	TEST_NARROW(putw(1234, f));
214*cd62a92dSRobert Mustacchi 
215*cd62a92dSRobert Mustacchi 
216*cd62a92dSRobert Mustacchi 	/* WIDE CHAR TIME! */
217*cd62a92dSRobert Mustacchi 
218*cd62a92dSRobert Mustacchi 	/* input */
219*cd62a92dSRobert Mustacchi 	TEST_WIDE(getwc(f));
220*cd62a92dSRobert Mustacchi 	TEST_WIDE(fgetwc(f));
221*cd62a92dSRobert Mustacchi 	TEST_WIDE(wc = fgetwc(f); ungetwc(wc, f));
222*cd62a92dSRobert Mustacchi 	TEST_WIDE(fgetws(wbuffer, BUFSIZ, f));
223*cd62a92dSRobert Mustacchi 	TEST_WIDE(fwscanf(f, L"%s\n", wbuffer));
224*cd62a92dSRobert Mustacchi 
225*cd62a92dSRobert Mustacchi 	/* output */
226*cd62a92dSRobert Mustacchi 	TEST_WIDE(putwc(L'c', f));
227*cd62a92dSRobert Mustacchi 	TEST_WIDE(fputwc(L'c', f));
228*cd62a92dSRobert Mustacchi 	TEST_WIDE(fputws(L"foo", f));
229*cd62a92dSRobert Mustacchi 	TEST_WIDE(fwprintf(f, L"%s\n", L"foo"));
230*cd62a92dSRobert Mustacchi 
231*cd62a92dSRobert Mustacchi 	/* input from stdin */
232*cd62a92dSRobert Mustacchi 	TEST_WIDE_STD(stdin, getwchar());
233*cd62a92dSRobert Mustacchi 	TEST_WIDE_STD(stdin, wscanf(L"%s\n", wbuffer));
234*cd62a92dSRobert Mustacchi 
235*cd62a92dSRobert Mustacchi 	/* output to stdout */
236*cd62a92dSRobert Mustacchi 	TEST_WIDE_STD(stdout, putwchar(L'c'));
237*cd62a92dSRobert Mustacchi 	TEST_WIDE_STD(stdout, wprintf(L"foo"));
238*cd62a92dSRobert Mustacchi 
239*cd62a92dSRobert Mustacchi 
240*cd62a92dSRobert Mustacchi 	/* memory streams */
241*cd62a92dSRobert Mustacchi 	f = open_memstream(&buf, &size);
242*cd62a92dSRobert Mustacchi 	if (!((r = fwide(f, 0)) < 0))
243*cd62a92dSRobert Mustacchi 		fail(__LINE__, r, "<", "open_memstream()");
244*cd62a92dSRobert Mustacchi 	fclose(f);
245*cd62a92dSRobert Mustacchi 	f = open_wmemstream(&wbuf, &size);
246*cd62a92dSRobert Mustacchi 	if (f != NULL && !((r = fwide(f, 0)) > 0))
247*cd62a92dSRobert Mustacchi 		fail(__LINE__, r, ">", "open_wmemstream()");
248*cd62a92dSRobert Mustacchi 	fclose(f);
249*cd62a92dSRobert Mustacchi 
250*cd62a92dSRobert Mustacchi 
251*cd62a92dSRobert Mustacchi 	/* random stuff? */
252*cd62a92dSRobert Mustacchi 	TEST_UNCHANGED_STD(stderr, perror("foo"));
253*cd62a92dSRobert Mustacchi 
254*cd62a92dSRobert Mustacchi 	remove(filename);
255*cd62a92dSRobert Mustacchi 	if (failures)
256*cd62a92dSRobert Mustacchi 		exit(1);
257*cd62a92dSRobert Mustacchi 	exit(0);
258*cd62a92dSRobert Mustacchi }
259