# HG changeset patch # User Eric Blake # Date 1253318791 21600 # Node ID 42d53e82a46064cdaf6a6c26dd87971969809e39 # Parent 73e9ab6e2c9086460a87c51dbe08d74382b84b3d test-fstatat: new test, to expose Solaris 9 bugs Share the stat and lstat tests with fstatat. * tests/test-stat.c (main): Factor guts... * tests/test-stat.h (test_stat_func): ...into new file. * tests/test-lstat.c (main): Factor guts... * tests/test-lstat.h (test_lstat_func): ...into new file. * tests/test-fstatat.c: New file. * modules/stat-tests (Files): Add test-stat.h. * modules/lstat-tests (Files): Add test-lstat.h. (Depends-on): Add stdbool. * modules/openat-tests (Depends-on): Add pathmax. (Files): Add test-lstat.h, test-stat.h, test-fstatat.c. (Makefile.am): Run new test. Signed-off-by: Eric Blake diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2009-09-19 Eric Blake + test-fstatat: new test, to expose Solaris 9 bugs + * tests/test-stat.c (main): Factor guts... + * tests/test-stat.h (test_stat_func): ...into new file. + * tests/test-lstat.c (main): Factor guts... + * tests/test-lstat.h (test_lstat_func): ...into new file. + * tests/test-fstatat.c: New file. + * modules/stat-tests (Files): Add test-stat.h. + * modules/lstat-tests (Files): Add test-lstat.h. + (Depends-on): Add stdbool. + * modules/openat-tests (Depends-on): Add pathmax. + (Files): Add test-lstat.h, test-stat.h, test-fstatat.c. + (Makefile.am): Run new test. + remove: new module, for mingw and Solaris 9 bugs * modules/remove: New file. * lib/remove.c: Likewise. diff --git a/modules/lstat-tests b/modules/lstat-tests --- a/modules/lstat-tests +++ b/modules/lstat-tests @@ -1,9 +1,11 @@ Files: +tests/test-lstat.h tests/test-lstat.c Depends-on: errno same-inode +stdbool configure.ac: AC_CHECK_FUNCS_ONCE([symlink]) diff --git a/modules/openat-tests b/modules/openat-tests --- a/modules/openat-tests +++ b/modules/openat-tests @@ -1,15 +1,20 @@ Files: +tests/test-lstat.h tests/test-rmdir.h +tests/test-stat.h +tests/test-fstatat.c tests/test-openat.c tests/test-unlinkat.c Depends-on: +pathmax configure.ac: AC_CHECK_FUNCS_ONCE([symlink]) Makefile.am: -TESTS += test-openat test-unlinkat -check_PROGRAMS += test-openat test-unlinkat +TESTS += test-fstatat test-openat test-unlinkat +check_PROGRAMS += test-fstatat test-openat test-unlinkat +test_fstatat_LDADD = $(LDADD) @LIBINTL@ test_openat_LDADD = $(LDADD) @LIBINTL@ test_unlinkat_LDADD = $(LDADD) @LIBINTL@ diff --git a/modules/stat-tests b/modules/stat-tests --- a/modules/stat-tests +++ b/modules/stat-tests @@ -1,4 +1,5 @@ Files: +tests/test-stat.h tests/test-stat.c Depends-on: diff --git a/tests/test-fstatat.c b/tests/test-fstatat.c new file mode 100644 --- /dev/null +++ b/tests/test-fstatat.c @@ -0,0 +1,89 @@ +/* Tests of fstatat. + Copyright (C) 2009 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 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 . */ + +/* Written by Eric Blake , 2009. */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "openat.h" +#include "pathmax.h" +#include "same-inode.h" + +#if !HAVE_SYMLINK +# define symlink(a,b) (-1) +#endif + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + +#define BASE "test-fstatat.t" + +#include "test-lstat.h" +#include "test-stat.h" + +static int dfd = AT_FDCWD; + +/* Wrapper around fstatat to test stat behavior. */ +static int +do_stat (char const *name, struct stat *st) +{ + return statat (dfd, name, st); +} + +/* Wrapper around fstatat to test lstat behavior. */ +static int +do_lstat (char const *name, struct stat *st) +{ + return lstatat (dfd, name, st); +} + +int +main () +{ + int result; + ASSERT (test_stat_func (do_stat) == 0); + result = test_lstat_func (do_lstat, false); + dfd = open (".", O_RDONLY); + ASSERT (0 <= dfd); + ASSERT (test_stat_func (do_stat) == 0); + ASSERT (test_lstat_func (do_lstat, false) == result); + ASSERT (close (dfd) == 0); + + /* FIXME - add additional tests of dfd not at current directory. */ + + if (result == 77) + fputs ("skipping test: symlinks not supported on this filesystem\n", + stderr); + return result; +} diff --git a/tests/test-lstat.c b/tests/test-lstat.c --- a/tests/test-lstat.c +++ b/tests/test-lstat.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -46,97 +47,18 @@ #define BASE "test-lstat.t" +#include "test-lstat.h" + +/* Wrapper around lstat, which works even if lstat is a function-like + macro, where test_lstat_func(lstat) would do the wrong thing. */ +static int +do_lstat (char const *name, struct stat *st) +{ + return lstat (name, st); +} + int main () { - struct stat st1; - struct stat st2; - - /* Remove any leftovers from a previous partial run. */ - ASSERT (system ("rm -rf " BASE "*") == 0); - - /* Test for common directories. */ - ASSERT (lstat (".", &st1) == 0); - ASSERT (lstat ("./", &st2) == 0); - ASSERT (SAME_INODE (st1, st2)); - ASSERT (S_ISDIR (st1.st_mode)); - ASSERT (S_ISDIR (st2.st_mode)); - ASSERT (lstat ("/", &st1) == 0); - ASSERT (lstat ("///", &st2) == 0); - ASSERT (SAME_INODE (st1, st2)); - ASSERT (S_ISDIR (st1.st_mode)); - ASSERT (S_ISDIR (st2.st_mode)); - ASSERT (lstat ("..", &st1) == 0); - ASSERT (S_ISDIR (st1.st_mode)); - - /* Test for error conditions. */ - errno = 0; - ASSERT (lstat ("", &st1) == -1); - ASSERT (errno == ENOENT); - errno = 0; - ASSERT (lstat ("nosuch", &st1) == -1); - ASSERT (errno == ENOENT); - errno = 0; - ASSERT (lstat ("nosuch/", &st1) == -1); - ASSERT (errno == ENOENT); - - ASSERT (close (creat (BASE "file", 0600)) == 0); - ASSERT (lstat (BASE "file", &st1) == 0); - ASSERT (S_ISREG (st1.st_mode)); - errno = 0; - ASSERT (lstat (BASE "file/", &st1) == -1); - ASSERT (errno == ENOTDIR); - - /* Now for some symlink tests, where supported. We set up: - link1 -> directory - link2 -> file - link3 -> dangling - link4 -> loop - then test behavior both with and without trailing slash. - */ - if (symlink (".", BASE "link1") != 0) - { - ASSERT (unlink (BASE "file") == 0); - fputs ("skipping test: symlinks not supported on this filesystem\n", - stderr); - return 77; - } - ASSERT (symlink (BASE "file", BASE "link2") == 0); - ASSERT (symlink (BASE "nosuch", BASE "link3") == 0); - ASSERT (symlink (BASE "link4", BASE "link4") == 0); - - ASSERT (lstat (BASE "link1", &st1) == 0); - ASSERT (S_ISLNK (st1.st_mode)); - ASSERT (lstat (BASE "link1/", &st1) == 0); - ASSERT (stat (BASE "link1", &st2) == 0); - ASSERT (S_ISDIR (st1.st_mode)); - ASSERT (S_ISDIR (st2.st_mode)); - ASSERT (SAME_INODE (st1, st2)); - - ASSERT (lstat (BASE "link2", &st1) == 0); - ASSERT (S_ISLNK (st1.st_mode)); - errno = 0; - ASSERT (lstat (BASE "link2/", &st1) == -1); - ASSERT (errno == ENOTDIR); - - ASSERT (lstat (BASE "link3", &st1) == 0); - ASSERT (S_ISLNK (st1.st_mode)); - errno = 0; - ASSERT (lstat (BASE "link3/", &st1) == -1); - ASSERT (errno == ENOENT); - - ASSERT (lstat (BASE "link4", &st1) == 0); - ASSERT (S_ISLNK (st1.st_mode)); - errno = 0; - ASSERT (lstat (BASE "link4/", &st1) == -1); - ASSERT (errno == ELOOP); - - /* Cleanup. */ - ASSERT (unlink (BASE "file") == 0); - ASSERT (unlink (BASE "link1") == 0); - ASSERT (unlink (BASE "link2") == 0); - ASSERT (unlink (BASE "link3") == 0); - ASSERT (unlink (BASE "link4") == 0); - - return 0; + return test_lstat_func (do_lstat, true); } diff --git a/tests/test-lstat.h b/tests/test-lstat.h new file mode 100644 --- /dev/null +++ b/tests/test-lstat.h @@ -0,0 +1,119 @@ +/* Test of lstat() function. + Copyright (C) 2008, 2009 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 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 . */ + +/* Written by Simon Josefsson, 2008; and Eric Blake, 2009. */ + +/* This file is designed to test both lstat(n,buf) and + fstatat(AT_FDCWD,n,buf,AT_SYMLINK_NOFOLLOW). FUNC is the function + to test. Assumes that BASE and ASSERT are already defined, and + that appropriate headers are already included. If PRINT, warn + before skipping symlink tests with status 77. */ + +static int +test_lstat_func (int (*func) (char const *, struct stat *), bool print) +{ + struct stat st1; + struct stat st2; + + /* Remove any leftovers from a previous partial run. */ + ASSERT (system ("rm -rf " BASE "*") == 0); + + /* Test for common directories. */ + ASSERT (func (".", &st1) == 0); + ASSERT (func ("./", &st2) == 0); + ASSERT (SAME_INODE (st1, st2)); + ASSERT (S_ISDIR (st1.st_mode)); + ASSERT (S_ISDIR (st2.st_mode)); + ASSERT (func ("/", &st1) == 0); + ASSERT (func ("///", &st2) == 0); + ASSERT (SAME_INODE (st1, st2)); + ASSERT (S_ISDIR (st1.st_mode)); + ASSERT (S_ISDIR (st2.st_mode)); + ASSERT (func ("..", &st1) == 0); + ASSERT (S_ISDIR (st1.st_mode)); + + /* Test for error conditions. */ + errno = 0; + ASSERT (func ("", &st1) == -1); + ASSERT (errno == ENOENT); + errno = 0; + ASSERT (func ("nosuch", &st1) == -1); + ASSERT (errno == ENOENT); + errno = 0; + ASSERT (func ("nosuch/", &st1) == -1); + ASSERT (errno == ENOENT); + + ASSERT (close (creat (BASE "file", 0600)) == 0); + ASSERT (func (BASE "file", &st1) == 0); + ASSERT (S_ISREG (st1.st_mode)); + errno = 0; + ASSERT (func (BASE "file/", &st1) == -1); + ASSERT (errno == ENOTDIR); + + /* Now for some symlink tests, where supported. We set up: + link1 -> directory + link2 -> file + link3 -> dangling + link4 -> loop + then test behavior both with and without trailing slash. + */ + if (symlink (".", BASE "link1") != 0) + { + ASSERT (unlink (BASE "file") == 0); + if (print) + fputs ("skipping test: symlinks not supported on this filesystem\n", + stderr); + return 77; + } + ASSERT (symlink (BASE "file", BASE "link2") == 0); + ASSERT (symlink (BASE "nosuch", BASE "link3") == 0); + ASSERT (symlink (BASE "link4", BASE "link4") == 0); + + ASSERT (func (BASE "link1", &st1) == 0); + ASSERT (S_ISLNK (st1.st_mode)); + ASSERT (func (BASE "link1/", &st1) == 0); + ASSERT (stat (BASE "link1", &st2) == 0); + ASSERT (S_ISDIR (st1.st_mode)); + ASSERT (S_ISDIR (st2.st_mode)); + ASSERT (SAME_INODE (st1, st2)); + + ASSERT (func (BASE "link2", &st1) == 0); + ASSERT (S_ISLNK (st1.st_mode)); + errno = 0; + ASSERT (func (BASE "link2/", &st1) == -1); + ASSERT (errno == ENOTDIR); + + ASSERT (func (BASE "link3", &st1) == 0); + ASSERT (S_ISLNK (st1.st_mode)); + errno = 0; + ASSERT (func (BASE "link3/", &st1) == -1); + ASSERT (errno == ENOENT); + + ASSERT (func (BASE "link4", &st1) == 0); + ASSERT (S_ISLNK (st1.st_mode)); + errno = 0; + ASSERT (func (BASE "link4/", &st1) == -1); + ASSERT (errno == ELOOP); + + /* Cleanup. */ + ASSERT (unlink (BASE "file") == 0); + ASSERT (unlink (BASE "link1") == 0); + ASSERT (unlink (BASE "link2") == 0); + ASSERT (unlink (BASE "link3") == 0); + ASSERT (unlink (BASE "link4") == 0); + + return 0; +} diff --git a/tests/test-stat.c b/tests/test-stat.c --- a/tests/test-stat.c +++ b/tests/test-stat.c @@ -43,39 +43,18 @@ #define BASE "test-stat.t" +#include "test-stat.h" + +/* Wrapper around stat, which works even if stat is a function-like + macro, where test_stat_func(stat) would do the wrong thing. */ +static int +do_stat (char const *name, struct stat *st) +{ + return stat (name, st); +} + int main () { - struct stat st1; - struct stat st2; - char cwd[PATH_MAX]; - - ASSERT (getcwd (cwd, PATH_MAX) == cwd); - ASSERT (stat (".", &st1) == 0); - ASSERT (stat ("./", &st2) == 0); - ASSERT (SAME_INODE (st1, st2)); - ASSERT (stat (cwd, &st2) == 0); - ASSERT (SAME_INODE (st1, st2)); - ASSERT (stat ("/", &st1) == 0); - ASSERT (stat ("///", &st2) == 0); - ASSERT (SAME_INODE (st1, st2)); - - errno = 0; - ASSERT (stat ("", &st1) == -1); - ASSERT (errno == ENOENT); - errno = 0; - ASSERT (stat ("nosuch", &st1) == -1); - ASSERT (errno == ENOENT); - errno = 0; - ASSERT (stat ("nosuch/", &st1) == -1); - ASSERT (errno == ENOENT); - - ASSERT (close (creat (BASE "file", 0600)) == 0); - ASSERT (stat (BASE "file", &st1) == 0); - errno = 0; - ASSERT (stat (BASE "file/", &st1) == -1); - ASSERT (errno == ENOTDIR); - ASSERT (unlink (BASE "file") == 0); - - return 0; + return test_stat_func (do_stat); } diff --git a/tests/test-stat.h b/tests/test-stat.h new file mode 100644 --- /dev/null +++ b/tests/test-stat.h @@ -0,0 +1,59 @@ +/* Tests of stat. + Copyright (C) 2009 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 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 . */ + +/* Written by Eric Blake , 2009. */ + +/* This file is designed to test both stat(n,buf) and + fstatat(AT_FDCWD,n,buf,0). FUNC is the function to test. Assumes + that BASE and ASSERT are already defined, and that appropriate + headers are already included. */ + +static int +test_stat_func (int (*func) (char const *, struct stat *)) +{ + struct stat st1; + struct stat st2; + char cwd[PATH_MAX]; + + ASSERT (getcwd (cwd, PATH_MAX) == cwd); + ASSERT (func (".", &st1) == 0); + ASSERT (func ("./", &st2) == 0); + ASSERT (SAME_INODE (st1, st2)); + ASSERT (func (cwd, &st2) == 0); + ASSERT (SAME_INODE (st1, st2)); + ASSERT (func ("/", &st1) == 0); + ASSERT (func ("///", &st2) == 0); + ASSERT (SAME_INODE (st1, st2)); + + errno = 0; + ASSERT (func ("", &st1) == -1); + ASSERT (errno == ENOENT); + errno = 0; + ASSERT (func ("nosuch", &st1) == -1); + ASSERT (errno == ENOENT); + errno = 0; + ASSERT (func ("nosuch/", &st1) == -1); + ASSERT (errno == ENOENT); + + ASSERT (close (creat (BASE "file", 0600)) == 0); + ASSERT (func (BASE "file", &st1) == 0); + errno = 0; + ASSERT (func (BASE "file/", &st1) == -1); + ASSERT (errno == ENOTDIR); + ASSERT (unlink (BASE "file") == 0); + + return 0; +}