changeset 11995:5767a52927aa

openat-tests: ensure unlinkat behaves like rmdir * tests/test-rmdir.c (main): Factor guts... * tests/test-rmdir.h (test_rmdir_func): ...into new file. * modules/rmdir-tests (Files): Ship new file. * modules/openat-tests: New test. * tests/test-unlinkat.c: Likewise. Signed-off-by: Eric Blake <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Wed, 16 Sep 2009 13:21:46 -0600
parents 5fc17e46270b
children c64f6d58bbc4
files ChangeLog modules/openat-tests modules/rmdir-tests tests/test-rmdir.c tests/test-rmdir.h tests/test-unlinkat.c
diffstat 6 files changed, 187 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2009-09-16  Eric Blake  <ebb9@byu.net>
 
+	openat-tests: ensure unlinkat behaves like rmdir
+	* tests/test-rmdir.c (main): Factor guts...
+	* tests/test-rmdir.h (test_rmdir_func): ...into new file.
+	* modules/rmdir-tests (Files): Ship new file.
+	* modules/openat-tests: New test.
+	* tests/test-unlinkat.c: Likewise.
+
 	rmdir-errno: mark obsolete, it is unsafe for cross-compilation
 	* modules/rmdir-errno (Status, Notice): Now obsolete.
 
new file mode 100644
--- /dev/null
+++ b/modules/openat-tests
@@ -0,0 +1,13 @@
+Files:
+tests/test-rmdir.h
+tests/test-unlinkat.c
+
+Depends-on:
+
+configure.ac:
+AC_CHECK_FUNCS_ONCE([symlink])
+
+Makefile.am:
+TESTS += test-unlinkat
+check_PROGRAMS += test-unlinkat
+test_unlinkat_LDADD = $(LDADD) @LIBINTL@
--- a/modules/rmdir-tests
+++ b/modules/rmdir-tests
@@ -1,4 +1,5 @@
 Files:
+tests/test-rmdir.h
 tests/test-rmdir.c
 
 Depends-on:
--- a/tests/test-rmdir.c
+++ b/tests/test-rmdir.c
@@ -44,82 +44,10 @@
 
 #define BASE "test-rmdir.t"
 
+#include "test-rmdir.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 (rmdir ("") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (rmdir (BASE "nosuch") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (rmdir (BASE "nosuch/") == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (rmdir (".") == -1);
-  ASSERT (errno == EINVAL || errno == EBUSY);
-  /* Resulting errno after ".." or "/" is too varied to test; it is
-     reasonable to see any of EINVAL, EBUSY, EEXIST, ENOTEMPTY,
-     EACCES, EPERM.  */
-  ASSERT (rmdir ("..") == -1);
-  ASSERT (rmdir ("/") == -1);
-  ASSERT (rmdir ("///") == -1);
-  errno = 0;
-  ASSERT (rmdir (BASE "dir/file/") == -1);
-  ASSERT (errno == ENOTDIR);
-
-  /* Non-empty directory.  */
-  errno = 0;
-  ASSERT (rmdir (BASE "dir") == -1);
-  ASSERT (errno == EEXIST || errno == ENOTEMPTY);
-
-  /* Non-directory.  */
-  errno = 0;
-  ASSERT (rmdir (BASE "dir/file") == -1);
-  ASSERT (errno == ENOTDIR);
-
-  /* Empty directory.  */
-  ASSERT (unlink (BASE "dir/file") == 0);
-  errno = 0;
-  ASSERT (rmdir (BASE "dir/./") == -1);
-  ASSERT (errno == EINVAL || errno == EBUSY);
-  ASSERT (rmdir (BASE "dir") == 0);
-
-  /* Test symlink behavior.  Specifying trailing slash should remove
-     referent directory (POSIX), or cause ENOTDIR failure (Linux), but
-     not touch symlink.  We prefer the Linux behavior for its
-     intuitiveness (especially compared to rmdir("symlink-to-file/")),
-     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);
-      return 77;
-    }
-  ASSERT (mkdir (BASE "dir", 0700) == 0);
-  errno = 0;
-  if (rmdir (BASE "link/") == 0)
-    {
-      struct stat st;
-      errno = 0;
-      ASSERT (stat (BASE "link", &st) == -1);
-      ASSERT (errno == ENOENT);
-    }
-  else
-    {
-      ASSERT (errno == ENOTDIR);
-      ASSERT (rmdir (BASE "dir") == 0);
-    }
-  ASSERT (unlink (BASE "link") == 0);
-
-  return 0;
+  return test_rmdir_func (rmdir);
 }
new file mode 100644
--- /dev/null
+++ b/tests/test-rmdir.h
@@ -0,0 +1,102 @@
+/* Tests of rmdir.
+   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 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.  */
+
+static int
+test_rmdir_func (int (*func) (char const *name))
+{
+  /* 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);
+  errno = 0;
+  ASSERT (func (".") == -1);
+  ASSERT (errno == EINVAL || errno == EBUSY);
+  /* Resulting errno after ".." or "/" is too varied to test; it is
+     reasonable to see any of EINVAL, EBUSY, EEXIST, ENOTEMPTY,
+     EACCES, EPERM.  */
+  ASSERT (func ("..") == -1);
+  ASSERT (func ("/") == -1);
+  ASSERT (func ("///") == -1);
+  errno = 0;
+  ASSERT (func (BASE "dir/file/") == -1);
+  ASSERT (errno == ENOTDIR);
+
+  /* Non-empty directory.  */
+  errno = 0;
+  ASSERT (func (BASE "dir") == -1);
+  ASSERT (errno == EEXIST || errno == ENOTEMPTY);
+
+  /* Non-directory.  */
+  errno = 0;
+  ASSERT (func (BASE "dir/file") == -1);
+  ASSERT (errno == ENOTDIR);
+
+  /* Empty directory.  */
+  ASSERT (unlink (BASE "dir/file") == 0);
+  errno = 0;
+  ASSERT (func (BASE "dir/./") == -1);
+  ASSERT (errno == EINVAL || errno == EBUSY);
+  ASSERT (func (BASE "dir") == 0);
+
+  /* Test symlink behavior.  Specifying trailing slash should remove
+     referent directory (POSIX), or cause ENOTDIR failure (Linux), but
+     not touch symlink.  We prefer the Linux behavior for its
+     intuitiveness (especially compared to rmdir("symlink-to-file/")),
+     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);
+      return 77;
+    }
+  ASSERT (mkdir (BASE "dir", 0700) == 0);
+  errno = 0;
+  if (func (BASE "link/") == 0)
+    {
+      struct stat st;
+      errno = 0;
+      ASSERT (stat (BASE "link", &st) == -1);
+      ASSERT (errno == ENOENT);
+    }
+  else
+    {
+      ASSERT (errno == ENOTDIR);
+      ASSERT (func (BASE "dir") == 0);
+    }
+  ASSERT (unlink (BASE "link") == 0);
+
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/tests/test-unlinkat.c
@@ -0,0 +1,61 @@
+/* Tests of unlinkat.
+   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.  */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.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-unlinkat.t"
+
+#include "test-rmdir.h"
+
+/* Wrapper around unlinkat to test rmdir behavior.  */
+static int
+rmdirat (char const *name)
+{
+  return unlinkat (AT_FDCWD, name, AT_REMOVEDIR);
+}
+
+int
+main ()
+{
+  /* FIXME: Add tests of unlinkat(,0), and of fd instead of AT_FDCWD.  */
+  return test_rmdir_func (rmdirat);
+}