Mercurial > hg > octave-lojdl > gnulib-hg
changeset 14677:fa93679417c1
fclose: add some tests
POSIX requires that fclose() on seekable input streams rewind back
to the next byte not actually given to the application. Glibc fails
this test. See:
http://sourceware.org/bugzilla/show_bug.cgi?id=3746
http://sourceware.org/bugzilla/show_bug.cgi?id=12724
Likewise for FreeBSD.
Cygwin 1.7.9 and Solaris 10 pass, however.
* modules/fclose-tests: New test module.
* tests/test-fclose.c: New file.
Signed-off-by: Eric Blake <eblake@redhat.com>
author | Eric Blake <eblake@redhat.com> |
---|---|
date | Mon, 02 May 2011 13:38:23 -0600 |
parents | ead32d10a3f0 |
children | 68c96ae4be1a |
files | ChangeLog doc/posix-functions/fclose.texi modules/fclose-tests tests/test-fclose.c |
diffstat | 4 files changed, 109 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2011-05-02 Eric Blake <eblake@redhat.com> + fclose: add some tests + * modules/fclose-tests: New test module. + * tests/test-fclose.c: New file. + * doc/posix-functions/fclose.texi (fclose): Document the bug. + fclose: reduced dependencies * modules/fclose (Depends-on): Switch from fflush/fseeko to simpler lseek.
--- a/doc/posix-functions/fclose.texi +++ b/doc/posix-functions/fclose.texi @@ -17,6 +17,10 @@ Portability problems not fixed by Gnulib: @itemize @item +On some platforms, this function fails to set the file position of a +seekable input stream to the byte after the last one actually read: +glibc 2.13, FreeBSD. +@item On Windows platforms (excluding Cygwin), this function does not set @code{errno} upon failure. @end itemize
new file mode 100644 --- /dev/null +++ b/modules/fclose-tests @@ -0,0 +1,10 @@ +Files: +tests/test-fclose.c + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-fclose +check_PROGRAMS += test-fclose
new file mode 100644 --- /dev/null +++ b/tests/test-fclose.c @@ -0,0 +1,90 @@ +/* Test of fclose module. + Copyright (C) 2011 Free Software Foundation, Inc. + + 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, 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, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Eric Blake. */ + +#include <config.h> + +#include <stdio.h> + +#include "signature.h" +SIGNATURE_CHECK (fclose, int, (FILE *)); + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "macros.h" + +#define BASE "test-fclose.t" + +int +main (int argc, char **argv) +{ + const char buf[] = "hello world"; + int fd; + int fd2; + FILE *f; + + /* Prepare a seekable file. */ + fd = open (BASE, O_RDWR | O_CREAT | O_TRUNC, 0600); + ASSERT (0 <= fd); + ASSERT (write (fd, buf, sizeof buf) == sizeof buf); + ASSERT (lseek (fd, 1, SEEK_SET) == 1); + + /* Create an output stream visiting the file; when it is closed, all + other file descriptors visiting the file must see the new file + position. */ + fd2 = dup (fd); + ASSERT (0 <= fd2); + f = fdopen (fd2, "w"); + ASSERT (f); + ASSERT (fputc (buf[1], f) == buf[1]); + ASSERT (fclose (f) == 0); + errno = 0; + ASSERT (lseek (fd2, 0, SEEK_CUR) == -1); + ASSERT (errno == EBADF); + ASSERT (lseek (fd, 0, SEEK_CUR) == 2); + + /* Likewise for an input stream. */ + fd2 = dup (fd); + ASSERT (0 <= fd2); + f = fdopen (fd2, "r"); + ASSERT (f); + ASSERT (fgetc (f) == buf[2]); + ASSERT (fclose (f) == 0); + errno = 0; + ASSERT (lseek (fd2, 0, SEEK_CUR) == -1); + ASSERT (errno == EBADF); + ASSERT (lseek (fd, 0, SEEK_CUR) == 3); + + /* Test that fclose() sets errno if someone else closes the stream + fd behind the back of stdio. */ + f = fdopen (fd, "w+"); + ASSERT (f); + ASSERT (close (fd) == 0); + errno = 0; + ASSERT (fclose (f) == EOF); + ASSERT (errno == EBADF); + + /* Clean up. */ + ASSERT (remove (BASE) == 0); + + return 0; +}