From a685b825aa87e9806a0ebcbd87bca5c1547b5dff Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sat, 22 Jun 2013 18:21:10 +0200 Subject: [PATCH] tests: Add example_stdio.c and test_stdio.sh. --- .gitignore | 4 + README | 8 ++ tests/Makefile.am | 6 +- tests/example_stdio.c | 140 +++++++++++++++++++++++++++++++++++ tests/example_stdio.expected | 28 +++++++ tests/test_stdio.sh | 23 ++++++ 6 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 tests/example_stdio.c create mode 100644 tests/example_stdio.expected create mode 100755 tests/test_stdio.sh diff --git a/.gitignore b/.gitignore index a279991..9c247c8 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,8 @@ /tests/example_error.o /tests/example_exec /tests/example_exec.o +/tests/example_stdio +/tests/example_stdio.o /tests/example_vfork /tests/example_vfork.o /tests/test_environment.sh.log @@ -47,6 +49,8 @@ /tests/test_redirects.sh.trs /tests/test_simple.sh.log /tests/test_simple.sh.trs +/tests/test_stdio.sh.log +/tests/test_stdio.sh.trs /tests/test_symbols.sh.log /tests/test_symbols.sh.trs /tests/test_vfork.sh.log diff --git a/README b/README index 79a4084..e298a04 100644 --- a/README +++ b/README @@ -137,6 +137,14 @@ doesn't exist it's created. An existing file isn't overwritten, but the warnings are appended at the end. +KNOWN ISSUES +------------ + +- `{fputc,putc,putchar}_unlocked()` are not hooked when writing to stdout + (which might be redirected to stderr). Can't be fixed as the compiler + inlines the code into the program without calling any function. + + BUGS ---- diff --git a/tests/Makefile.am b/tests/Makefile.am index 24f94e0..2863950 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -6,8 +6,9 @@ TESTS = test_environment.sh \ test_exec.sh \ test_noforce.sh \ test_redirects.sh \ - test_simple.sh -check_PROGRAMS = example example_exec + test_simple.sh \ + test_stdio.sh +check_PROGRAMS = example example_exec example_stdio if HAVE_ERR_H TESTS += test_err.sh @@ -36,6 +37,7 @@ dist_check_DATA = example.h \ example_redirects.sh.expected \ example_simple.sh \ example_simple.sh.expected \ + example_stdio.expected \ example_vfork.expected # Used by lib.sh. Can't use "export EGREP" because it doesn't work with BSD's diff --git a/tests/example_stdio.c b/tests/example_stdio.c new file mode 100644 index 0000000..028b3f7 --- /dev/null +++ b/tests/example_stdio.c @@ -0,0 +1,140 @@ +/* + * Test all hooked stdio.h functions. + * + * Copyright (C) 2013 Simon Ruderich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +/* For {fwrite,fputs,fputc}_unlocked(), if available. */ +#define _GNU_SOURCE +#include +#include +#include +#include + +#include "example.h" +#include "../src/compiler.h" + + +/* These are not in POSIX. */ +#ifndef HAVE_FWRITE_UNLOCKED +static size_t fwrite_unlocked(void const *ptr, size_t size, size_t n, FILE *stream) { + return fwrite(ptr, size, n, stream); +} +#endif +#ifndef HAVE_FPUTS_UNLOCKED +static int fputs_unlocked(char const *s, FILE *stream) { + return fputs(s, stream); +} +#endif +#ifndef HAVE_FPUTC_UNLOCKED +static int fputc_unlocked(int c, FILE *stream) { + return fputc(c, stream); +} +#endif + + +static int out; + +static void test_vprintf(char const *format, ...) noinline; +static void test_vfprintf(FILE *stream, char const *format, ...) noinline; +static void NEWLINE(void) noinline; + +static void test_vprintf(char const *format, ...) { + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} +static void test_vfprintf(FILE *stream, char const *format, ...) { + va_list ap; + + va_start(ap, format); + vfprintf(stream, format, ap); + va_end(ap); +} + +static void NEWLINE(void) { + fflush(stdout); + fflush(stderr); + xwrite(out, "\n", 1); +} + + +int main(int argc, char **argv unused) { + /* stdout */ + + out = dup(STDOUT_FILENO); + if (out == -1) { + perror("dup"); + return EXIT_FAILURE; + } + + /* Redirect stdout to stderr so we can test all functions, including those + * not writing to stderr. */ + xdup2(STDERR_FILENO, STDOUT_FILENO); + + /* stdout redirected to stderr. */ + + xwrite(STDOUT_FILENO, "write()", 7); NEWLINE(); + fwrite("fwrite()", 8, 1, stdout); NEWLINE(); + + /* puts(3) */ + fputs("fputs()", stdout); NEWLINE(); + fputc('a', stdout); NEWLINE(); + putc('b', stdout); NEWLINE(); + putchar('c'); NEWLINE(); + puts("puts()"); NEWLINE(); + + /* printf(3) */ + printf("%s [%d]", "printf()", argc); NEWLINE(); + fprintf(stdout, "%s [%d]", "fprintf()", argc); NEWLINE(); + test_vprintf("%s [%d]", "vprintf()", argc); NEWLINE(); + test_vfprintf(stdout, "%s [%d]", "vfprintf()", argc); NEWLINE(); + + /* unlocked_stdio(3) */ + fwrite_unlocked("fwrite_unlocked()", 17, 1, stdout); NEWLINE(); + fputs_unlocked("fputs_unlocked()", stdout); NEWLINE(); + /* FIXME: 'x', 'y' and 'z' are not colored */ + fputc_unlocked('x', stdout); NEWLINE(); + putc_unlocked('y', stdout); NEWLINE(); + putchar_unlocked('z'); NEWLINE(); + + + /* stderr */ + + xwrite(STDERR_FILENO, "write()", 7); NEWLINE(); + fwrite("fwrite()", 8, 1, stderr); NEWLINE(); + + /* puts(3) */ + fputs("fputs()", stderr); NEWLINE(); + fputc('a', stderr); NEWLINE(); + putc('b', stderr); NEWLINE(); + + /* printf(3) */ + fprintf(stderr, "%s [%d]", "fprintf()", argc); NEWLINE(); + test_vfprintf(stderr, "%s [%d]", "vfprintf()", argc); NEWLINE(); + + /* unlocked_stdio(3) */ + fwrite_unlocked("fwrite_unlocked()", 17, 1, stderr); NEWLINE(); + fputs_unlocked("fputs_unlocked()", stderr); NEWLINE(); + fputc_unlocked('x', stderr); NEWLINE(); + putc_unlocked('y', stderr); NEWLINE(); + + return EXIT_SUCCESS; +} diff --git a/tests/example_stdio.expected b/tests/example_stdio.expected new file mode 100644 index 0000000..0ab9883 --- /dev/null +++ b/tests/example_stdio.expected @@ -0,0 +1,28 @@ +>STDERR>write()STDERR>fwrite()STDERR>fputs()STDERR>aSTDERR>bSTDERR>cSTDERR>puts() +STDERR>printf() [1]STDERR>fprintf() [1]STDERR>vprintf() [1]STDERR>vfprintf() [1]STDERR>fwrite_unlocked()STDERR>fputs_unlocked()STDERR>write()STDERR>fwrite()STDERR>fputs()STDERR>aSTDERR>bSTDERR>fprintf() [1]STDERR>vfprintf() [1]STDERR>fwrite_unlocked()STDERR>fputs_unlocked()STDERR>xSTDERR>y. + + +test "x$srcdir" = x && srcdir=. +. "$srcdir/lib.sh" + +test_program example_stdio +test_program_subshell example_stdio -- 2.43.2