1 /* $OpenBSD: orientation_test.c,v 1.5 2014/04/22 02:29:52 lteo 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 46 char filename[] = "/tmp/fwide.XXXXXXXXXX"; 47 48 FILE *dup_stdout = NULL; 49 int failures = 0; 50 51 void 52 fail(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 60 FILE * 61 setup(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 73 FILE * 74 setup_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 109 int 110 main(int argc, char *argv[]) 111 { 112 char buffer[BUFSIZ]; 113 wchar_t wbuffer[BUFSIZ]; 114 char *buf; 115 wchar_t *wbuf; 116 FILE *f; 117 off_t off; 118 fpos_t pos; 119 size_t size; 120 int fd, r; 121 char c; 122 wchar_t wc; 123 124 if ((fd = dup(1)) == -1) 125 err(2, "dup"); 126 if ((dup_stdout = fdopen(fd, "w")) == NULL) 127 err(2, "fdopen"); 128 if ((fd = mkstemp(filename)) == -1) 129 err(2, "mkstemp"); 130 if (write(fd, "0123456789\n\n", 12) != 12 || close(fd)) 131 err(2, "write + close"); 132 133 /* status */ 134 TEST_UNCHANGED(fwide(f, 0)); 135 TEST_NARROW(fwide(f, -1)); 136 TEST_WIDE(fwide(f, 1)); 137 TEST_UNCHANGED(feof(f)); 138 TEST_UNCHANGED(ferror(f)); 139 TEST_UNCHANGED(fileno(f)); 140 TEST_UNCHANGED(clearerr(f)); 141 142 /* flush and purge */ 143 TEST_UNCHANGED(fflush(f)); 144 TEST_UNCHANGED(fpurge(f)); 145 146 /* positioning */ 147 TEST_UNCHANGED(fgetpos(f, &pos)); 148 TEST_UNCHANGED(fgetpos(f, &pos); fsetpos(f, &pos)); 149 TEST_UNCHANGED(ftell(f)); 150 TEST_UNCHANGED(ftello(f)); 151 TEST_UNCHANGED(fseek(f, 1, SEEK_CUR)); 152 TEST_UNCHANGED(fseek(f, 1, SEEK_SET)); 153 TEST_UNCHANGED(fseek(f, 1, SEEK_END)); 154 TEST_UNCHANGED(fseeko(f, 1, SEEK_CUR)); 155 TEST_UNCHANGED(fseeko(f, 1, SEEK_SET)); 156 TEST_UNCHANGED(fseeko(f, 1, SEEK_END)); 157 TEST_UNCHANGED(rewind(f)); 158 159 /* buffering */ 160 TEST_UNCHANGED(setbuf(f, NULL)); 161 TEST_UNCHANGED(setbuf(f, buffer)); 162 TEST_UNCHANGED(setvbuf(f, buffer, _IONBF, BUFSIZ)); 163 TEST_UNCHANGED(setvbuf(f, buffer, _IOLBF, BUFSIZ)); 164 TEST_UNCHANGED(setvbuf(f, buffer, _IOFBF, BUFSIZ)); 165 TEST_UNCHANGED(setvbuf(f, NULL, _IONBF, 0)); 166 TEST_UNCHANGED(setvbuf(f, NULL, _IOLBF, 0)); 167 TEST_UNCHANGED(setvbuf(f, NULL, _IOFBF, 0)); 168 TEST_UNCHANGED(setbuffer(f, NULL, 0)); 169 TEST_UNCHANGED(setbuffer(f, buffer, BUFSIZ)); 170 TEST_UNCHANGED(setlinebuf(f)); 171 172 /* locking */ 173 TEST_UNCHANGED(flockfile(f);funlockfile(f)); 174 TEST_UNCHANGED(ftrylockfile(f);funlockfile(f)); 175 176 /* input */ 177 TEST_NARROW(getc(f)); 178 TEST_NARROW(getc_unlocked(f)); 179 TEST_NARROW(fgetc(f)); 180 TEST_NARROW(c = fgetc(f); ungetc(c, f)); 181 TEST_NARROW(fgets(buffer, BUFSIZ, f)); 182 TEST_NARROW(fscanf(f, "%s\n", buffer)); 183 TEST_NARROW(fgetln(f, &size)); 184 185 /* output */ 186 TEST_NARROW(putc('c', f)); 187 TEST_NARROW(putc_unlocked('c', f)); 188 TEST_NARROW(fputc('c', f)); 189 TEST_NARROW(fputs("foo", f)); 190 TEST_NARROW(fprintf(f, "%s\n", "foo")); 191 192 /* input from stdin */ 193 TEST_NARROW_STD(stdin, getchar()); 194 TEST_NARROW_STD(stdin, getchar_unlocked()); 195 TEST_NARROW_STD(stdin, scanf("%s\n", buffer)); 196 197 /* output to stdout */ 198 TEST_NARROW_STD(stdout, putchar('c')); 199 TEST_NARROW_STD(stdout, putchar_unlocked('c')); 200 TEST_NARROW_STD(stdout, puts("foo")); 201 TEST_NARROW_STD(stdout, printf("foo")); 202 203 /* word-size ops */ 204 /* 205 * fread and fwrite are specified as being implemented in 206 * terms of fgetc() and fputc() and therefore must set the 207 * stream orientation to narrow. 208 */ 209 TEST_NARROW(fread(buffer, 4, BUFSIZ / 4, f)); 210 TEST_NARROW(fwrite(buffer, 4, BUFSIZ / 4, f)); 211 212 /* 213 * getw() and putw() aren't specified anywhere but logically 214 * should behave the same as fread/fwrite. Not all OSes agree: 215 * Solaris 10 has them not changing the orientation. 216 */ 217 TEST_NARROW(getw(f)); 218 TEST_NARROW(putw(1234, f)); 219 220 221 /* WIDE CHAR TIME! */ 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 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 TEST_WIDE(fwprintf(f, L"%s\n", L"foo")); 235 236 /* input from stdin */ 237 TEST_WIDE_STD(stdin, getwchar()); 238 TEST_WIDE_STD(stdin, wscanf(L"%s\n", wbuffer)); 239 240 /* output to stdout */ 241 TEST_WIDE_STD(stdout, putwchar(L'c')); 242 TEST_WIDE_STD(stdout, wprintf(L"foo")); 243 244 245 /* memory streams */ 246 f = open_memstream(&buf, &size); 247 if (!((r = fwide(f, 0)) < 0)) 248 fail(__LINE__, r, "<", "open_memstream()"); 249 fclose(f); 250 f = open_wmemstream(&wbuf, &size); 251 if (!((r = fwide(f, 0)) > 0)) 252 fail(__LINE__, r, ">", "open_wmemstream()"); 253 fclose(f); 254 255 256 /* random stuff? */ 257 TEST_UNCHANGED_STD(stderr, perror("foo")); 258 259 remove(filename); 260 if (failures) 261 exit(1); 262 exit(0); 263 } 264 265