1 /* $OpenBSD: orientation_test.c,v 1.2 2011/04/29 15:26:30 stsp 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 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 two 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 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 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 253