test-unlinkat: enhance test, to expose Solaris 9 bug
authorEric Blake <ebb9@byu.net>
Fri, 18 Sep 2009 04:16:56 +0000 (22:16 -0600)
committerEric Blake <ebb9@byu.net>
Sat, 19 Sep 2009 19:40:41 +0000 (13:40 -0600)
Share the unlink tests with unlinkat.

* tests/test-unlink.c (main): Factor guts...
* tests/test-unlink.h (test_rmdir_func): ...into new file.
* tests/test-rmdir.h (test_rmdir_func): Add parameter.
* tests/test-rmdir.c (main): Adjust caller.
* tests/test-unlinkat.c (main): Likewise.  Add unlink tests.
(unlinker): New helper function.
(rmdirat): Enhance check.
* modules/rmdir-tests (Depends-on): Add stdbool.
* modules/unlink-tests (Depends-on): Likewise.
(Files): Add test-unlink.h.
* modules/openat-tests (Files): Likewise.
(Depends-on): Add unlinkdir.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
modules/openat-tests
modules/rmdir-tests
modules/unlink-tests
tests/test-rmdir.c
tests/test-rmdir.h
tests/test-unlink.c
tests/test-unlink.h [new file with mode: 0644]
tests/test-unlinkat.c

index 99833ab..3c54062 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2009-09-19  Eric Blake  <ebb9@byu.net>
 
+       test-unlinkat: enhance test, to expose Solaris 9 bug
+       * tests/test-unlink.c (main): Factor guts...
+       * tests/test-unlink.h (test_rmdir_func): ...into new file.
+       * tests/test-rmdir.h (test_rmdir_func): Add parameter.
+       * tests/test-rmdir.c (main): Adjust caller.
+       * tests/test-unlinkat.c (main): Likewise.  Add unlink tests.
+       (unlinker): New helper function.
+       (rmdirat): Enhance check.
+       * modules/rmdir-tests (Depends-on): Add stdbool.
+       * modules/unlink-tests (Depends-on): Likewise.
+       (Files): Add test-unlink.h.
+       * modules/openat-tests (Files): Likewise.
+       (Depends-on): Add unlinkdir.
+
        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.
index 42ae6e8..7134f2c 100644 (file)
@@ -2,12 +2,14 @@ Files:
 tests/test-lstat.h
 tests/test-rmdir.h
 tests/test-stat.h
+tests/test-unlink.h
 tests/test-fstatat.c
 tests/test-openat.c
 tests/test-unlinkat.c
 
 Depends-on:
 pathmax
+unlinkdir
 
 configure.ac:
 AC_CHECK_FUNCS_ONCE([symlink])
index 2a68120..fca8a77 100644 (file)
@@ -3,6 +3,7 @@ tests/test-rmdir.h
 tests/test-rmdir.c
 
 Depends-on:
+stdbool
 
 configure.ac:
 AC_CHECK_FUNCS_ONCE([symlink])
index b527b61..f0930f0 100644 (file)
@@ -1,7 +1,9 @@
 Files:
+tests/test-unlink.h
 tests/test-unlink.c
 
 Depends-on:
+stdbool
 unlinkdir
 
 configure.ac:
index 6d55ea9..d7e4da3 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <fcntl.h>
 #include <errno.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
@@ -49,5 +50,5 @@
 int
 main ()
 {
-  return test_rmdir_func (rmdir);
+  return test_rmdir_func (rmdir, true);
 }
index 2470240..bb7b344 100644 (file)
 /* This file is designed to test both rmdir(n) and
    unlinkat(AT_FDCWD,n,AT_REMOVEDIR).  FUNC is the function to test.
    Assumes that BASE and ASSERT are already defined, and that
-   appropriate headers are already included.  */
+   appropriate headers are already included.  If PRINT, then warn
+   before returning status 77 when symlinks are unsupported.  */
 
 static int
-test_rmdir_func (int (*func) (char const *name))
+test_rmdir_func (int (*func) (char const *name), bool print)
 {
   /* Remove any leftovers from a previous partial run.  */
   ASSERT (system ("rm -rf " BASE "*") == 0);
@@ -78,8 +79,9 @@ test_rmdir_func (int (*func) (char const *name))
      but not enough to penalize POSIX systems with an rpl_rmdir.  */
   if (symlink (BASE "dir", BASE "link") != 0)
     {
-      fputs ("skipping test: symlinks not supported on this filesystem\n",
-             stderr);
+      if (print)
+       fputs ("skipping test: symlinks not supported on this filesystem\n",
+              stderr);
       return 77;
     }
   ASSERT (mkdir (BASE "dir", 0700) == 0);
index 5aaa595..f5df9b6 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <fcntl.h>
 #include <errno.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #define BASE "test-unlink.t"
 
+#include "test-unlink.h"
+
 int
 main ()
 {
-  /* Remove any leftovers from a previous partial run.  */
-  ASSERT (system ("rm -rf " BASE "*") == 0);
-
-  /* Setup.  */
-  ASSERT (mkdir (BASE "dir", 0700) == 0);
-  ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
-
-  /* Basic error conditions.  */
-  errno = 0;
-  ASSERT (unlink ("") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (unlink (BASE "nosuch") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (unlink (BASE "nosuch/") == -1);
-  ASSERT (errno == ENOENT);
-  /* Resulting errno after directories is rather varied across
-     implementations (EPERM, EINVAL, EACCES, EBUSY, EISDIR, ENOTSUP);
-     however, we must be careful to not attempt unlink on a directory
-     unless we know it must fail.  */
-  if (cannot_unlink_dir ())
-    {
-      ASSERT (unlink (".") == -1);
-      ASSERT (unlink ("..") == -1);
-      ASSERT (unlink ("/") == -1);
-      ASSERT (unlink (BASE "dir") == -1);
-      ASSERT (mkdir (BASE "dir1", 0700) == 0);
-      ASSERT (unlink (BASE "dir1") == -1);
-      ASSERT (rmdir (BASE "dir1") == 0);
-    }
-  errno = 0;
-  ASSERT (unlink (BASE "dir/file/") == -1);
-  ASSERT (errno == ENOTDIR);
-
-  /* Test symlink behavior.  Specifying trailing slash will attempt
-     unlink of a directory, so only attempt it if we know it must
-     fail.  */
-  if (symlink (BASE "dir", BASE "link") != 0)
-    {
-      ASSERT (unlink (BASE "dir/file") == 0);
-      ASSERT (rmdir (BASE "dir") == 0);
-      fputs ("skipping test: symlinks not supported on this filesystem\n",
-             stderr);
-      return 77;
-    }
-  if (cannot_unlink_dir ())
-    ASSERT (unlink (BASE "link/") == -1);
-  ASSERT (unlink (BASE "link") == 0);
-  ASSERT (symlink (BASE "dir/file", BASE "link") == 0);
-  /* Order here proves unlink of a symlink does not follow through to
-     the file.  */
-  ASSERT (unlink (BASE "link") == 0);
-  ASSERT (unlink (BASE "dir/file") == 0);
-  ASSERT (rmdir (BASE "dir") == 0);
-
-  return 0;
+  return test_unlink_func (unlink, true);
 }
diff --git a/tests/test-unlink.h b/tests/test-unlink.h
new file mode 100644 (file)
index 0000000..80cce94
--- /dev/null
@@ -0,0 +1,86 @@
+/* Tests of unlink.
+   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 <http://www.gnu.org/licenses/>.  */
+
+/* Written by Eric Blake <ebb9@byu.net>, 2009.  */
+
+/* This file is designed to test both unlink(n) and
+   unlinkat(AT_FDCWD,n,0).  FUNC is the function to test.  Assumes
+   that BASE and ASSERT are already defined, and that appropriate
+   headers are already included.  If PRINT, then warn before returning
+   status 77 when symlinks are unsupported.  */
+
+static int
+test_unlink_func (int (*func) (char const *name), bool print)
+{
+  /* Remove any leftovers from a previous partial run.  */
+  ASSERT (system ("rm -rf " BASE "*") == 0);
+
+  /* Setup.  */
+  ASSERT (mkdir (BASE "dir", 0700) == 0);
+  ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
+
+  /* Basic error conditions.  */
+  errno = 0;
+  ASSERT (func ("") == -1);
+  ASSERT (errno == ENOENT);
+  errno = 0;
+  ASSERT (func (BASE "nosuch") == -1);
+  ASSERT (errno == ENOENT);
+  errno = 0;
+  ASSERT (func (BASE "nosuch/") == -1);
+  ASSERT (errno == ENOENT);
+  /* Resulting errno after directories is rather varied across
+     implementations (EPERM, EINVAL, EACCES, EBUSY, EISDIR, ENOTSUP);
+     however, we must be careful to not attempt unlink on a directory
+     unless we know it must fail.  */
+  if (cannot_unlink_dir ())
+    {
+      ASSERT (func (".") == -1);
+      ASSERT (func ("..") == -1);
+      ASSERT (func ("/") == -1);
+      ASSERT (func (BASE "dir") == -1);
+      ASSERT (mkdir (BASE "dir1", 0700) == 0);
+      ASSERT (func (BASE "dir1") == -1);
+      ASSERT (rmdir (BASE "dir1") == 0);
+    }
+  errno = 0;
+  ASSERT (func (BASE "dir/file/") == -1);
+  ASSERT (errno == ENOTDIR);
+
+  /* Test symlink behavior.  Specifying trailing slash will attempt
+     unlink of a directory, so only attempt it if we know it must
+     fail.  */
+  if (symlink (BASE "dir", BASE "link") != 0)
+    {
+      ASSERT (func (BASE "dir/file") == 0);
+      ASSERT (rmdir (BASE "dir") == 0);
+      if (print)
+       fputs ("skipping test: symlinks not supported on this filesystem\n",
+              stderr);
+      return 77;
+    }
+  if (cannot_unlink_dir ())
+    ASSERT (func (BASE "link/") == -1);
+  ASSERT (func (BASE "link") == 0);
+  ASSERT (symlink (BASE "dir/file", BASE "link") == 0);
+  /* Order here proves unlink of a symlink does not follow through to
+     the file.  */
+  ASSERT (func (BASE "link") == 0);
+  ASSERT (func (BASE "dir/file") == 0);
+  ASSERT (rmdir (BASE "dir") == 0);
+
+  return 0;
+}
index fb87a19..8e0a1cd 100644 (file)
 
 #include <fcntl.h>
 #include <errno.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 
+#include "unlinkdir.h"
+
 #if !HAVE_SYMLINK
 # define symlink(a,b) (-1)
 #endif
 #define BASE "test-unlinkat.t"
 
 #include "test-rmdir.h"
+#include "test-unlink.h"
+
+static int dfd = AT_FDCWD;
 
 /* Wrapper around unlinkat to test rmdir behavior.  */
 static int
 rmdirat (char const *name)
 {
-  return unlinkat (AT_FDCWD, name, AT_REMOVEDIR);
+  return unlinkat (dfd, name, AT_REMOVEDIR);
+}
+
+/* Wrapper around unlinkat to test unlink behavior.  */
+static int
+unlinker (char const *name)
+{
+  return unlinkat (dfd, name, 0);
 }
 
 int
 main ()
 {
-  /* FIXME: Add tests of unlinkat(,0), and of fd instead of AT_FDCWD.  */
-  return test_rmdir_func (rmdirat);
+  /* FIXME: Add tests of fd other than ".".  */
+  int result1;
+  int result2;
+  result1 = test_rmdir_func (rmdirat, false);
+  result2 = test_unlink_func (unlinker, false);
+  ASSERT (result1 == result2);
+  dfd = open (".", O_RDONLY);
+  ASSERT (0 <= dfd);
+  result2 = test_rmdir_func (rmdirat, false);
+  ASSERT (result1 == result2);
+  result2 = test_unlink_func (unlinker, false);
+  ASSERT (result1 == result2);
+  ASSERT (close (dfd) == 0);
+  if (result1 == 77)
+    fputs ("skipping test: symlinks not supported on this filesystem\n",
+          stderr);
+  return result1;
 }