On native Windows, the 'test-stat-time' test works fine the first time I run it, but fails in subsequent runs in the same build directory.
Strangely enough, when you create a file, delete it, create it again (with the same name), then the st_ctime field will contain the time of the first creation. (See log appended below.) Reproduced with Windows 10 on NTFS. As a workaround/fix: Let the stat-time test create files with different names each time. 2017-05-14 Bruno Haible <br...@clisp.org> stat-time tests: Workaround for native Windows. * tests/test-stat-time.c: Include <stdio.h>, <time.h>. (filename_stamp1, filename_testfile, filename_stamp2, filename_stamp3): New variables. (initialize_filenames): New function. (main): Invoke it. (cleanup, prepare_test): Update. diff --git a/tests/test-stat-time.c b/tests/test-stat-time.c index 7b9cebf..25fe6c3 100644 --- a/tests/test-stat-time.c +++ b/tests/test-stat-time.c @@ -22,8 +22,10 @@ #include <fcntl.h> #include <signal.h> +#include <stdio.h> #include <sys/stat.h> #include <unistd.h> +#include <time.h> #include "macros.h" @@ -32,6 +34,25 @@ enum { NFILES = 4 }; +static char filename_stamp1[50]; +static char filename_testfile[50]; +static char filename_stamp2[50]; +static char filename_stamp3[50]; + +/* Use file names that are different at each run. + This is necessary for test_birthtime() to pass on native Windows: + On this platform, the file system apparently remembers the creation time + of a file even after it is removed and created anew. */ +static void +initialize_filenames (void) +{ + long t = (long) time (NULL); + sprintf (filename_stamp1, "t-stt-%ld-stamp1", t); + sprintf (filename_testfile, "t-stt-%ld-testfile", t); + sprintf (filename_stamp2, "t-stt-%ld-stamp2", t); + sprintf (filename_stamp3, "t-stt-%ld-stamp3", t); +} + static int force_unlink (const char *filename) { @@ -45,11 +66,10 @@ static void cleanup (int sig) { /* Remove temporary files. */ - force_unlink ("t-stt-stamp1"); - force_unlink ("t-stt-testfile"); - force_unlink ("t-stt-stamp2"); - force_unlink ("t-stt-renamed"); - force_unlink ("t-stt-stamp3"); + force_unlink (filename_stamp1); + force_unlink (filename_testfile); + force_unlink (filename_stamp2); + force_unlink (filename_stamp3); if (sig != 0) _exit (1); @@ -87,20 +107,20 @@ prepare_test (struct stat *statinfo, struct timespec *modtimes) { int i; - create_file ("t-stt-stamp1"); + create_file (filename_stamp1); nap (); - create_file ("t-stt-testfile"); + create_file (filename_testfile); nap (); - create_file ("t-stt-stamp2"); + create_file (filename_stamp2); nap (); - ASSERT (chmod ("t-stt-testfile", 0400) == 0); + ASSERT (chmod (filename_testfile, 0400) == 0); nap (); - create_file ("t-stt-stamp3"); + create_file (filename_stamp3); - do_stat ("t-stt-stamp1", &statinfo[0]); - do_stat ("t-stt-testfile", &statinfo[1]); - do_stat ("t-stt-stamp2", &statinfo[2]); - do_stat ("t-stt-stamp3", &statinfo[3]); + do_stat (filename_stamp1, &statinfo[0]); + do_stat (filename_testfile, &statinfo[1]); + do_stat (filename_stamp2, &statinfo[2]); + do_stat (filename_stamp3, &statinfo[3]); /* Now use our access functions. */ for (i = 0; i < NFILES; ++i) @@ -160,7 +180,7 @@ test_ctime (const struct stat *statinfo) if (statinfo[0].st_mtime != statinfo[0].st_ctime) return; - /* mtime(stamp2) < ctime(renamed) */ + /* mtime(stamp2) < ctime(testfile) */ ASSERT (statinfo[2].st_mtime < statinfo[1].st_ctime || (statinfo[2].st_mtime == statinfo[1].st_ctime && (get_stat_mtime_ns (&statinfo[2]) @@ -183,11 +203,11 @@ test_birthtime (const struct stat *statinfo, return; } - /* mtime(stamp1) < birthtime(renamed) */ + /* mtime(stamp1) < birthtime(testfile) */ ASSERT (modtimes[0].tv_sec < birthtimes[1].tv_sec || (modtimes[0].tv_sec == birthtimes[1].tv_sec && modtimes[0].tv_nsec < birthtimes[1].tv_nsec)); - /* birthtime(renamed) < mtime(stamp2) */ + /* birthtime(testfile) < mtime(stamp2) */ ASSERT (birthtimes[1].tv_sec < modtimes[2].tv_sec || (birthtimes[1].tv_sec == modtimes[2].tv_sec && birthtimes[1].tv_nsec < modtimes[2].tv_nsec)); @@ -200,6 +220,8 @@ main (void) struct timespec modtimes[NFILES]; struct timespec birthtimes[NFILES]; + initialize_filenames (); + #ifdef SIGHUP signal (SIGHUP, cleanup); #endif =================================== EXPERIMENT ============================== $ gltests/test-stat-time.exe i=0 modtime=1494769524.508897000 birthtime=1494769524.508897000 i=1 modtime=1494769524.509899300 birthtime=1494769524.509899300 i=2 modtime=1494769524.517378100 birthtime=1494769524.517378100 i=3 modtime=1494769524.535423400 birthtime=1494769524.535423400 File t-stt-stamp1: ret=0, st_ctim = 1494769524.508897000 File t-stt-testfile: ret=0, st_ctim = 1494769524.509899300 File t-stt-stamp2: ret=0, st_ctim = 1494769524.517378100 File t-stt-stamp3: ret=0, st_ctim = 1494769524.535423400 $ echo $? 0 $ gltests/test-stat-time.exe File t-stt-stamp1: ret=0, st_ctim = 1494769524.508897000 File t-stt-testfile: ret=0, st_ctim = 1494769524.509899300 File t-stt-stamp2: ret=0, st_ctim = 1494769524.517378100 File t-stt-stamp3: ret=0, st_ctim = 1494769524.535423400 ../../gltests/test-stat-time.c:193: assertion 'modtimes[0].tv_sec < birthtimes[1].tv_sec || (modtimes[0].tv_sec == birthtimes[1].tv_sec && modtimes[0].tv_nsec < birthtimes[1].tv_nsec)' failed This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. i=0 modtime=1494769535.271086600 birthtime=1494769524.508897000 i=1 modtime=1494769535.272055700 birthtime=1494769524.509899300 i=2 modtime=1494769535.275064100 birthtime=1494769524.517378100 i=3 modtime=1494769535.283084700 birthtime=1494769524.535423400 $ rm -f t-stt-* $ gltests/test-stat-time.exe File t-stt-stamp1: ret=0, st_ctim = 1494769524.508897000 File t-stt-testfile: ret=0, st_ctim = 1494769524.509899300 File t-stt-stamp2: ret=0, st_ctim = 1494769524.517378100 File t-stt-stamp3: ret=0, st_ctim = 1494769524.535423400 ../../gltests/test-stat-time.c:193: assertion 'modtimes[0].tv_sec < birthtimes[1].tv_sec || (modtimes[0].tv_sec == birthtimes[1].tv_sec && modtimes[0].tv_nsec < birthtimes[1].tv_nsec)' failed This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. i=0 modtime=1494769595.727543200 birthtime=1494769524.508897000 i=1 modtime=1494769595.728546200 birthtime=1494769524.509899300 i=2 modtime=1494769595.731553900 birthtime=1494769524.517378100 i=3 modtime=1494769595.738220100 birthtime=1494769524.535423400