summaryrefslogtreecommitdiff
path: root/regress
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2009-11-21 09:56:11 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2009-11-21 09:56:11 +0000
commit4a5ec79456e38963414e8beeac718365148030bf (patch)
tree8870f4ab6e22a9fdbe1de3e5d0f1d24678474c2a /regress
parent93496f056d8dfeaa109df6a8ec9654829d415493 (diff)
Add a (hopefully) comprehensive regression test of how stdio functions
affect stream orientation
Diffstat (limited to 'regress')
-rw-r--r--regress/lib/libc/Makefile4
-rw-r--r--regress/lib/libc/orientation/Makefile10
-rw-r--r--regress/lib/libc/orientation/orientation_test.c252
3 files changed, 264 insertions, 2 deletions
diff --git a/regress/lib/libc/Makefile b/regress/lib/libc/Makefile
index b210b7df719..3c24e3f6341 100644
--- a/regress/lib/libc/Makefile
+++ b/regress/lib/libc/Makefile
@@ -1,10 +1,10 @@
-# $OpenBSD: Makefile,v 1.29 2009/11/19 08:06:06 guenther Exp $
+# $OpenBSD: Makefile,v 1.30 2009/11/21 09:56:10 guenther Exp $
SUBDIR+= _setjmp alloca atexit basename cxa-atexit db dirname fnmatch
SUBDIR+= fpclassify getaddrinfo getcap getopt_long glob hsearch longjmp
SUBDIR+= locale malloc netdb popen printf regex setjmp setjmp-signal
SUBDIR+= sigreturn sigsetjmp sprintf strerror strtod strtonum telldir time vis
-SUBDIR+= stdio_threading
+SUBDIR+= orientation stdio_threading
.if (${MACHINE_ARCH} != "vax")
SUBDIR+= ieeefp
diff --git a/regress/lib/libc/orientation/Makefile b/regress/lib/libc/orientation/Makefile
new file mode 100644
index 00000000000..b116a04b0f7
--- /dev/null
+++ b/regress/lib/libc/orientation/Makefile
@@ -0,0 +1,10 @@
+# $OpenBSD: Makefile,v 1.1 2009/11/21 09:56:10 guenther Exp $
+
+NOMAN=
+PROG=orientation_test
+CPPFLAGS+=-I${.CURDIR}/../../../../lib/libc
+
+run-regress-atexit_test: ${PROG}
+ ./${PROG}
+
+.include <bsd.regress.mk>
diff --git a/regress/lib/libc/orientation/orientation_test.c b/regress/lib/libc/orientation/orientation_test.c
new file mode 100644
index 00000000000..4af6a3407b3
--- /dev/null
+++ b/regress/lib/libc/orientation/orientation_test.c
@@ -0,0 +1,252 @@
+/* $OpenBSD: orientation_test.c,v 1.1 2009/11/21 09:56:10 guenther Exp $ */
+
+/*
+ * Copyright (c) 2009 Philip Guenther
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Test whether the various stdio functions set the stream orientation
+ * ("width") as they should
+ */
+
+#include <sys/types.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+char filename[] = "/tmp/fwide.XXXXXXXXXX";
+
+FILE *dup_stdout = NULL;
+int failures = 0;
+
+void
+fail(int line, int r, char const *expect, char const *test)
+{
+ failures++;
+ fprintf(dup_stdout,
+ "FAIL: %d: fwide returned %d, expected %s 0 after %s\n",
+ line, r, expect, test);
+}
+
+FILE *
+setup(int line)
+{
+ FILE *f;
+ int r;
+
+ if ((f = fopen(filename, "r+")) == NULL)
+ err(2, "fopen");
+ if ((r = fwide(f, 0)) != 0)
+ fail(line, r, "==", "fopen");
+ return (f);
+}
+
+FILE *
+setup_std(FILE *std, int line)
+{
+ int r;
+
+ if (freopen(filename, "r+", std) == NULL)
+ err(2, "freopen");
+ if ((r = fwide(std, 0)) != 0)
+ fail(line, r, "==", "freopen");
+ return (std);
+}
+
+#define TEST_(x, op) \
+ do { \
+ f = setup(__LINE__); \
+ x; \
+ if (!((r = fwide(f, 0)) op 0)) \
+ fail(__LINE__, r, #op, #x); \
+ fclose(f); \
+ } while (0)
+
+#define TEST_STD_(std, x, op) \
+ do { \
+ f = setup_std(std, __LINE__); \
+ x; \
+ if (!((r = fwide(f, 0)) op 0)) \
+ fail(__LINE__, r, #op, #x); \
+ } while (0)
+
+#define TEST_UNCHANGED(x) TEST_(x, ==)
+#define TEST_NARROW(x) TEST_(x, <)
+#define TEST_WIDE(x) TEST_(x, >)
+#define TEST_UNCHANGED_STD(std, x) TEST_STD_(std, x, ==)
+#define TEST_NARROW_STD(std, x) TEST_STD_(std, x, <)
+#define TEST_WIDE_STD(std, x) TEST_STD_(std, x, >)
+
+int
+main(int argc, char *argv[])
+{
+ char buffer[BUFSIZ];
+ wchar_t wbuffer[BUFSIZ];
+ FILE *f;
+ off_t off;
+ fpos_t pos;
+ size_t size;
+ int fd, r;
+ char c;
+ wchar_t wc;
+
+ if ((fd = dup(1)) == -1)
+ err(2, "dup");
+ if ((dup_stdout = fdopen(fd, "w")) == NULL)
+ err(2, "fdopen");
+ if ((fd = mkstemp(filename)) == -1)
+ err(2, "mkstemp");
+ if (write(fd, "0123456789\n\n", 12) != 12 || close(fd))
+ err(2, "write + close");
+
+ /* status */
+ TEST_UNCHANGED(fwide(f, 0));
+ TEST_NARROW(fwide(f, -1));
+ TEST_WIDE(fwide(f, 1));
+ TEST_UNCHANGED(feof(f));
+ TEST_UNCHANGED(ferror(f));
+ TEST_UNCHANGED(fileno(f));
+ TEST_UNCHANGED(clearerr(f));
+
+ /* flush and purge */
+ TEST_UNCHANGED(fflush(f));
+ TEST_UNCHANGED(fpurge(f));
+
+ /* positioning */
+ TEST_UNCHANGED(fgetpos(f, &pos));
+ TEST_UNCHANGED(fgetpos(f, &pos); fsetpos(f, &pos));
+ TEST_UNCHANGED(ftell(f));
+ TEST_UNCHANGED(ftello(f));
+ TEST_UNCHANGED(fseek(f, 1, SEEK_CUR));
+ TEST_UNCHANGED(fseek(f, 1, SEEK_SET));
+ TEST_UNCHANGED(fseek(f, 1, SEEK_END));
+ TEST_UNCHANGED(fseeko(f, 1, SEEK_CUR));
+ TEST_UNCHANGED(fseeko(f, 1, SEEK_SET));
+ TEST_UNCHANGED(fseeko(f, 1, SEEK_END));
+ TEST_UNCHANGED(rewind(f));
+
+ /* buffering */
+ TEST_UNCHANGED(setbuf(f, NULL));
+ TEST_UNCHANGED(setbuf(f, buffer));
+ TEST_UNCHANGED(setvbuf(f, buffer, _IONBF, BUFSIZ));
+ TEST_UNCHANGED(setvbuf(f, buffer, _IOLBF, BUFSIZ));
+ TEST_UNCHANGED(setvbuf(f, buffer, _IOFBF, BUFSIZ));
+ TEST_UNCHANGED(setvbuf(f, NULL, _IONBF, 0));
+ TEST_UNCHANGED(setvbuf(f, NULL, _IOLBF, 0));
+ TEST_UNCHANGED(setvbuf(f, NULL, _IOFBF, 0));
+ TEST_UNCHANGED(setbuffer(f, NULL, 0));
+ TEST_UNCHANGED(setbuffer(f, buffer, BUFSIZ));
+ TEST_UNCHANGED(setlinebuf(f));
+
+ /* locking */
+ TEST_UNCHANGED(flockfile(f);funlockfile(f));
+ TEST_UNCHANGED(ftrylockfile(f);funlockfile(f));
+
+ /* input */
+ TEST_NARROW(getc(f));
+ TEST_NARROW(getc_unlocked(f));
+ TEST_NARROW(fgetc(f));
+ TEST_NARROW(c = fgetc(f); ungetc(c, f));
+ TEST_NARROW(fgets(buffer, BUFSIZ, f));
+ TEST_NARROW(fscanf(f, "%s\n", buffer));
+ TEST_NARROW(fgetln(f, &size));
+
+ /* output */
+ TEST_NARROW(putc('c', f));
+ TEST_NARROW(putc_unlocked('c', f));
+ TEST_NARROW(fputc('c', f));
+ TEST_NARROW(fputs("foo", f));
+ TEST_NARROW(fprintf(f, "%s\n", "foo"));
+
+ /* input from stdin */
+ TEST_NARROW_STD(stdin, getchar());
+ TEST_NARROW_STD(stdin, getchar_unlocked());
+ TEST_NARROW_STD(stdin, gets(buffer));
+ TEST_NARROW_STD(stdin, scanf("%s\n", buffer));
+
+ /* output to stdout */
+ TEST_NARROW_STD(stdout, putchar('c'));
+ TEST_NARROW_STD(stdout, putchar_unlocked('c'));
+ TEST_NARROW_STD(stdout, puts("foo"));
+ TEST_NARROW_STD(stdout, printf("foo"));
+
+ /* word-size ops */
+ /*
+ * fread and fwrite are specified as being implemented in
+ * terms of fgetc() and fputc() and therefore must set the
+ * stream orientation to narrow.
+ */
+ TEST_NARROW(fread(buffer, 4, BUFSIZ / 4, f));
+ TEST_NARROW(fwrite(buffer, 4, BUFSIZ / 4, f));
+
+ /*
+ * getw() and putw() aren't specified anywhere but logically
+ * should behave the same as fread/fwrite. Not all OSes agree:
+ * Solaris 10 has them not changing the orientation.
+ */
+ TEST_NARROW(getw(f));
+ TEST_NARROW(putw(1234, f));
+
+
+ /* WIDE CHAR TIME! */
+ /* the four functions prefixed with "//X" are unimplemented */
+
+ /* input */
+ TEST_WIDE(getwc(f));
+ TEST_WIDE(fgetwc(f));
+ TEST_WIDE(wc = fgetwc(f); ungetwc(wc, f));
+ TEST_WIDE(fgetws(wbuffer, BUFSIZ, f));
+//X TEST_WIDE(fwscanf(f, L"%s\n", wbuffer));
+
+ /* output */
+ TEST_WIDE(putwc(L'c', f));
+ TEST_WIDE(fputwc(L'c', f));
+ TEST_WIDE(fputws(L"foo", f));
+//X TEST_WIDE(fwprintf(f, L"%s\n", L"foo"));
+
+ /* input from stdin */
+ TEST_WIDE_STD(stdin, getwchar());
+//X TEST_WIDE_STD(stdin, wscanf(L"%s\n", wbuffer));
+
+ /* output to stdout */
+ TEST_WIDE_STD(stdout, putwchar(L'c'));
+//X TEST_WIDE_STD(stdout, wprintf(L"foo"));
+
+
+ TEST_UNCHANGED_STD(stderr, perror("foo"));
+
+ remove(filename);
+ if (failures)
+ exit(1);
+ exit(0);
+}
+