2009-10-16 Eric Blake <ebb9@byu.net>
+ test-stat-time, test-utimens: improve portability
+ * tests/test-stat-time.c (nap): Lengthen delay to 20ms, for
+ ext4 on alpha, and for cygwin.
+ * tests/test-utimens-common.h: New file.
+ (nap): Factor delays into single function.
+ * tests/test-lutimens.h (test_lutimens): Use new header.
+ * tests/test-futimens.h (test_futimens): Likewise.
+ * tests/test-utimens.h (test_utimens): Likewise. Also, force NFS
+ timestamps to occur from same machine, as was done previously for
+ test_utimens.
+ * modules/utimens-tests (Files): Ship new file.
+ * modules/futimens-tests (Files): Likewise.
+ Reported in part by Jim Meyering.
+
sys_stat: sort replacement declarations
* lib/sys_stat.in.h: Sort declarations.
* lib/futimens.c (futimens): Fix typo.
Files:
tests/test-futimens.h
+tests/test-utimens-common.h
tests/test-futimens.c
Depends-on:
tests/test-futimens.h
tests/test-lutimens.h
tests/test-utimens.h
+tests/test-utimens-common.h
tests/test-utimens.c
Depends-on:
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-/* This file assumes that BASE and ASSERT are already defined. */
+#include "test-utimens-common.h"
-#ifndef GL_TEST_UTIMENS
-# define GL_TEST_UTIMENS
-
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "stat-time.h"
-#include "timespec.h"
-#include "utimecmp.h"
-
-enum {
- BILLION = 1000 * 1000 * 1000,
-
- Y2K = 946684800, /* Jan 1, 2000, in seconds since epoch. */
-
- /* Bogus positive and negative tv_nsec values closest to valid
- range, but without colliding with UTIME_NOW or UTIME_OMIT. */
- UTIME_BOGUS_POS = BILLION + ((UTIME_NOW == BILLION || UTIME_OMIT == BILLION)
- ? (1 + (UTIME_NOW == BILLION + 1)
- + (UTIME_OMIT == BILLION + 1))
- : 0),
- UTIME_BOGUS_NEG = -1 - ((UTIME_NOW == -1 || UTIME_OMIT == -1)
- ? (1 + (UTIME_NOW == -2) + (UTIME_OMIT == -2))
- : 0)
-};
-
-#endif /* GL_TEST_UTIMENS */
-
-/* This function is designed to test both gl_futimens(a,NULL,b) and
- futimens(a,b). FUNC is the function to test. If PRINT, warn
- before skipping tests with status 77. */
+/* This file is designed to test both gl_futimens(a,NULL,b) and
+ futimens(a,b). FUNC is the function to test. Assumes that BASE
+ and ASSERT are already defined. If PRINT, warn before skipping
+ tests with status 77. */
static int
test_futimens (int (*func) (int, struct timespec const *),
bool print)
ASSERT (0 <= fd);
/* Sanity check. */
+ ASSERT (fstat (fd, &st1) == 0);
+ nap ();
errno = 0;
result = func (fd, NULL);
if (result == -1 && errno == ENOSYS)
return 77;
}
ASSERT (!result);
- ASSERT (fstat (fd, &st1) == 0);
+ ASSERT (fstat (fd, &st2) == 0);
+ /* If utimens truncates to less resolution than the file system
+ supports, then time can appear to go backwards between now and a
+ follow-up utimens with UTIME_NOW or a NULL timespec. Use
+ UTIMECMP_TRUNCATE_SOURCE to compensate, with st1 as the
+ source. */
+ ASSERT (0 <= utimecmp (BASE "file", &st2, &st1, UTIMECMP_TRUNCATE_SOURCE));
+ {
+ /* On some NFS systems, the 'now' timestamp of creat or a NULL
+ timespec is determined by the server, but the 'now' timestamp
+ determined by gettime() (as is done when using UTIME_NOW) is
+ determined by the client; since the two machines are not
+ necessarily on the same clock, this is another case where time
+ can appear to go backwards. The rest of this test cares about
+ client time, so manually use gettime() to set both times. */
+ struct timespec ts[2];
+ gettime (&ts[0]);
+ ts[1] = ts[0];
+ ASSERT (func (fd, ts) == 0);
+ ASSERT (fstat (fd, &st1) == 0);
+ nap ();
+ }
/* Invalid arguments. */
errno = 0;
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-/* This file assumes that BASE and ASSERT are already defined. */
+#include "test-utimens-common.h"
-#ifndef GL_TEST_UTIMENS
-# define GL_TEST_UTIMENS
-
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "stat-time.h"
-#include "timespec.h"
-#include "utimecmp.h"
-
-enum {
- BILLION = 1000 * 1000 * 1000,
-
- Y2K = 946684800, /* Jan 1, 2000, in seconds since epoch. */
-
- /* Bogus positive and negative tv_nsec values closest to valid
- range, but without colliding with UTIME_NOW or UTIME_OMIT. */
- UTIME_BOGUS_POS = BILLION + ((UTIME_NOW == BILLION || UTIME_OMIT == BILLION)
- ? (1 + (UTIME_NOW == BILLION + 1)
- + (UTIME_OMIT == BILLION + 1))
- : 0),
- UTIME_BOGUS_NEG = -1 - ((UTIME_NOW == -1 || UTIME_OMIT == -1)
- ? (1 + (UTIME_NOW == -2) + (UTIME_OMIT == -2))
- : 0)
-};
-
-#endif /* GL_TEST_UTIMENS */
-
-/* This function is designed to test both lutimens(a,b) and
+/* This file is designed to test both lutimens(a,b) and
utimensat(AT_FDCWD,a,b,AT_SYMLINK_NOFOLLOW). FUNC is the function
- to test. If PRINT, warn before skipping tests with status 77. */
+ to test. Assumes that BASE and ASSERT are already defined. If
+ PRINT, warn before skipping tests with status 77. */
static int
test_lutimens (int (*func) (char const *, struct timespec const *), bool print)
{
}
ASSERT (!result);
ASSERT (lstat (BASE "link", &st1) == 0);
-#if HAVE_USLEEP
- /* On Cygwin, the mere act of lstat changes symlink atime, even
- though POSIX says that only readlink is allowed to do that.
- Sleeping for one millisecond is enough to expose this. Platforms
- without usleep either don't have symlinks, or are immune. */
- usleep (1000);
-#endif
+ /* On cygwin, lstat() changes atime of symlinks, so that lutimens
+ can only effectively modify mtime. */
+ nap ();
ASSERT (lstat (BASE "link", &st2) == 0);
if (st1.st_atime != st2.st_atime
|| get_stat_atime_ns (&st1) != get_stat_atime_ns (&st2))
- atime_supported = false;
+ atime_supported = false;
/* Invalid arguments. */
errno = 0;
static long delay;
if (!delay)
{
- /* Initialize only once, by sleeping for 15 milliseconds (needed
+ /* Initialize only once, by sleeping for 20 milliseconds (needed
since xfs has a quantization of about 10 milliseconds, even
- though it has a granularity of 1 nanosecond). If the seconds
+ though it has a granularity of 1 nanosecond, and since NTFS
+ has a default quantization of 15.25 milliseconds, even though
+ it has a granularity of 100 nanoseconds). If the seconds
differ, repeat the test one more time (in case we crossed a
quantization boundary on a file system with 1 second
resolution). If we can't observe a difference in only the
struct stat st2;
ASSERT (stat ("t-stt-stamp1", &st1) == 0);
ASSERT (force_unlink ("t-stt-stamp1") == 0);
- delay = 15000;
+ delay = 20000;
usleep (delay);
create_file ("t-stt-stamp1");
ASSERT (stat ("t-stt-stamp1", &st2) == 0);
--- /dev/null
+/* Test of file timestamp modification functions.
+ 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 2 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/>. */
+
+/* This file defines some prerequisites useful to utime-related tests. */
+
+#ifndef GL_TEST_UTIMENS_COMMON
+# define GL_TEST_UTIMENS_COMMON
+
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "stat-time.h"
+#include "timespec.h"
+#include "utimecmp.h"
+
+enum {
+ BILLION = 1000 * 1000 * 1000,
+
+ Y2K = 946684800, /* Jan 1, 2000, in seconds since epoch. */
+
+ /* Bogus positive and negative tv_nsec values closest to valid
+ range, but without colliding with UTIME_NOW or UTIME_OMIT. */
+ UTIME_BOGUS_POS = BILLION + ((UTIME_NOW == BILLION || UTIME_OMIT == BILLION)
+ ? (1 + (UTIME_NOW == BILLION + 1)
+ + (UTIME_OMIT == BILLION + 1))
+ : 0),
+ UTIME_BOGUS_NEG = -1 - ((UTIME_NOW == -1 || UTIME_OMIT == -1)
+ ? (1 + (UTIME_NOW == -2) + (UTIME_OMIT == -2))
+ : 0)
+};
+
+/* Sleep long enough to cross a timestamp quantization boundary on
+ most known systems with subsecond timestamp resolution. For
+ example, ext4 has a quantization of 10 milliseconds, but a
+ resolution of 1 nanosecond. Likewise, NTFS has a quantization as
+ slow as 15.25 milliseconds, but a resolution of 100 nanoseconds.
+ This is necessary on systems where creat or utimens with NULL
+ rounds down to the quantization boundary, but where gettime and
+ hence utimensat can inject timestamps between quantization
+ boundaries. By ensuring we cross a boundary, we are less likely to
+ confuse utimecmp for two times that would round to the same
+ quantization boundary but are distinct based on resolution. */
+static void
+nap (void)
+{
+ /* Systems that lack usleep also lack subsecond timestamps. Our
+ usage of utimecmp allows equality, so we don't need to sleep. */
+#if HAVE_USLEEP
+ usleep (20 * 1000); /* 20 milliseconds. */
+#endif
+}
+
+#endif /* GL_TEST_UTIMENS_COMMON */
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-/* This file assumes that BASE and ASSERT are already defined. */
+#include "test-utimens-common.h"
-#ifndef GL_TEST_UTIMENS
-# define GL_TEST_UTIMENS
-
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "stat-time.h"
-#include "timespec.h"
-#include "utimecmp.h"
-
-enum {
- BILLION = 1000 * 1000 * 1000,
-
- Y2K = 946684800, /* Jan 1, 2000, in seconds since epoch. */
-
- /* Bogus positive and negative tv_nsec values closest to valid
- range, but without colliding with UTIME_NOW or UTIME_OMIT. */
- UTIME_BOGUS_POS = BILLION + ((UTIME_NOW == BILLION || UTIME_OMIT == BILLION)
- ? (1 + (UTIME_NOW == BILLION + 1)
- + (UTIME_OMIT == BILLION + 1))
- : 0),
- UTIME_BOGUS_NEG = -1 - ((UTIME_NOW == -1 || UTIME_OMIT == -1)
- ? (1 + (UTIME_NOW == -2) + (UTIME_OMIT == -2))
- : 0)
-};
-
-#endif /* GL_TEST_UTIMENS */
-
-/* This function is designed to test both utimens(a,b) and
- utimensat(AT_FDCWD,a,b,0). FUNC is the function to test. */
+/* This file is designed to test both utimens(a,b) and
+ utimensat(AT_FDCWD,a,b,0). FUNC is the function to test. Assumes
+ that BASE and ASSERT are already defined. */
static int
test_utimens (int (*func) (char const *, struct timespec const *))
{
UTIMECMP_TRUNCATE_SOURCE to compensate, with st1 as the
source. */
ASSERT (stat (BASE "file", &st1) == 0);
+ nap ();
ASSERT (func (BASE "file", NULL) == 0);
ASSERT (stat (BASE "file", &st2) == 0);
ASSERT (0 <= utimecmp (BASE "file", &st2, &st1, UTIMECMP_TRUNCATE_SOURCE));
{
/* On some NFS systems, the 'now' timestamp of creat or a NULL
timespec is determined by the server, but the 'now' timestamp
- determined by gettime() (as is done when using UTIME_OMIT) is
+ determined by gettime() (as is done when using UTIME_NOW) is
determined by the client; since the two machines are not
necessarily on the same clock, this is another case where time
can appear to go backwards. The rest of this test cares about
ts[1] = ts[0];
ASSERT (func (BASE "file", ts) == 0);
ASSERT (stat (BASE "file", &st1) == 0);
+ nap ();
}
/* Invalid arguments. */