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