From: Tim Kientzle Date: Sat, 12 Sep 2009 05:24:28 +0000 (-0400) Subject: Refactor hardlink/symlink support in test harness: we now have X-Git-Tag: v2.8.0~353 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26ef8e6ac13f6649f45de4e63dcb1de4f2e09e5d;p=thirdparty%2Flibarchive.git Refactor hardlink/symlink support in test harness: we now have assertIsHardlink() and assertIsNotHardlink(). On the symlink side, I've added a run-time platform probe canSymlink() that tests the local platform the first time it is called and remembers the result. As an experiment, refactor test_basic.c to omit symlinks from the tests if the current platform lacks symlink support. SVN-Revision: 1455 --- diff --git a/cpio/test/main.c b/cpio/test/main.c index 6100eccea..15ee56719 100644 --- a/cpio/test/main.c +++ b/cpio/test/main.c @@ -811,8 +811,8 @@ assertion_text_file_contents(const char *buff, const char *fn) /* Test that two paths point to the same file. */ /* As a side-effect, asserts that both files exist. */ -int -is_file_hardlinks(const char *file, int line, +static int +is_hardlink(const char *file, int line, const char *path1, const char *path2) { #if defined(_WIN32) && !defined(__CYGWIN__) @@ -856,10 +856,10 @@ is_file_hardlinks(const char *file, int line, } int -assertion_file_hardlinks(const char *file, int line, - const char *path1, const char *path2) -{ - if (is_file_hardlinks(file, line, path1, path2)) +assertion_is_hardlink(const char *file, int line, + const char *path1, const char *path2) +{ + if (is_hardlink(file, line, path1, path2)) return (1); failure_start(file, line, "Files %s and %s are not hardlinked", path1, path2); @@ -867,6 +867,18 @@ assertion_file_hardlinks(const char *file, int line, return (0); } +int +assertion_is_not_hardlink(const char *file, int line, + const char *path1, const char *path2) +{ + if (!is_hardlink(file, line, path1, path2)) + return (1); + failure_start(file, line, + "Files %s and %s should not be hardlinked", path1, path2); + failure_finish(NULL); + return (0); +} + /* Verify a/b/mtime of 'pathname'. */ /* If 'recent', verify that it's within last 10 seconds. */ static int @@ -1122,17 +1134,14 @@ assertion_is_reg(const char *file, int line, const char *pathname, int mode) return (1); } -/* Verify that 'pathname' is a symbolic link. If 'contents' is +/* Check whether 'pathname' is a symbolic link. If 'contents' is * non-NULL, verify that the symlink has those contents. */ -int -assertion_is_symlink(const char *file, int line, +static int +is_symlink(const char *file, int line, const char *pathname, const char *contents) { #if defined(_WIN32) && !defined(__CYGWIN__) assertion_count(file, line); - /* TODO: Vista supports symlinks */ - failure_start(file, line, "Symlink %s not supported", pathname); - failure_finish(NULL); return (0); #else char buff[300]; @@ -1148,11 +1157,8 @@ assertion_is_symlink(const char *file, int line, failure_finish(NULL); return (0); } - if (!S_ISLNK(st.st_mode)) { - failure_start(file, line, "%s should be a symlink", pathname); - failure_finish(NULL); + if (!S_ISLNK(st.st_mode)) return (0); - } if (contents == NULL) return (1); linklen = readlink(pathname, buff, sizeof(buff)); @@ -1162,17 +1168,29 @@ assertion_is_symlink(const char *file, int line, return (0); } buff[linklen] = '\0'; - if (strcmp(buff, contents) != 0) { - failure_start(file, line, "Wrong symlink %s", pathname); - logprintf(" Expected: %s\n", contents); - logprintf(" Found: %s\n", buff); - failure_finish(NULL); + if (strcmp(buff, contents) != 0) return (0); - } return (1); #endif } +/* Assert that path is a symlink that (optionally) contains contents. */ +int +assertion_is_symlink(const char *file, int line, + const char *path, const char *contents) +{ + if (is_symlink(file, line, path, contents)) + return (1); + if (contents) + failure_start(file, line, "File %s is not a symlink to %s", + path, contents); + else + failure_start(file, line, "File %s is not a symlink", path); + failure_finish(NULL); + return (0); +} + + /* Create a directory and report any errors. */ int assertion_make_dir(const char *file, int line, const char *dirname, int mode) @@ -1303,6 +1321,32 @@ assertion_umask(const char *file, int line, int mask) * */ +/* + * Check whether platform supports symlinks. This is intended + * for tests to use in deciding whether to bother testing symlink + * support; if the platform doesn't support symlinks, there's no point + * in checking whether the program being tested can create them. + */ +int +canSymlink(void) +{ + /* Remember the test result */ + static int value = 0, tested = 1; + if (tested) + return (value); + + ++tested; + assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, "a"); +#if defined(_WIN32) && !defined(__CYGWIN__) + value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0) + && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0"); +#elif HAVE_SYMLINK + value = (0 == symlink("canSymlink.0", "canSymlink.1")) + && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0"); +#endif + return (value); +} + /* * Sleep as needed; useful for verifying disk timestamp changes by * ensuring that the wall-clock time has actually changed before we diff --git a/cpio/test/test.h b/cpio/test/test.h index 5d89a45c4..e2e83b3ef 100644 --- a/cpio/test/test.h +++ b/cpio/test/test.h @@ -166,8 +166,6 @@ /* Assert that file contents match a string; supports printf-style arguments. */ #define assertFileContents \ assertion_setup(__FILE__, __LINE__);assertion_file_contents -#define assertFileHardlinks(path1, path2) \ - assertion_file_hardlinks(__FILE__, __LINE__, path1, path2) #define assertFileMtime(pathname, sec, nsec) \ assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec) #define assertFileMtimeRecent(pathname) \ @@ -180,6 +178,10 @@ assertion_setup(__FILE__, __LINE__);assertion_text_file_contents #define assertIsDir(pathname, mode) \ assertion_is_dir(__FILE__, __LINE__, pathname, mode) +#define assertIsHardlink(path1, path2) \ + assertion_is_hardlink(__FILE__, __LINE__, path1, path2) +#define assertIsNotHardlink(path1, path2) \ + assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2) #define assertIsReg(pathname, mode) \ assertion_is_reg(__FILE__, __LINE__, pathname, mode) #define assertIsSymlink(pathname, contents) \ @@ -196,11 +198,6 @@ #define assertUmask(mask) \ assertion_umask(__FILE__, __LINE__, mask) -/* - */ -#define isFileHardlinks(path1, path2) \ - is_file_hardlinks(__FILE__, __LINE__, path1, path2) - /* * This would be simple with C99 variadic macros, but I don't want to * require that. Instead, I insert a function call before each @@ -226,13 +223,14 @@ int assertion_file_birthtime(const char *, int, const char *, long, long); int assertion_file_birthtime_recent(const char *, int, const char *); int assertion_file_contents(const void *, int, const char *, ...); int assertion_file_exists(const char *, ...); -int assertion_file_hardlinks(const char *, int, const char *, const char *); int assertion_file_mtime(const char *, int, const char *, long, long); int assertion_file_mtime_recent(const char *, int, const char *); int assertion_file_nlinks(const char *, int, const char *, int); int assertion_file_not_exists(const char *, ...); int assertion_file_size(const char *, int, const char *, long); int assertion_is_dir(const char *, int, const char *, int); +int assertion_is_hardlink(const char *, int, const char *, const char *); +int assertion_is_not_hardlink(const char *, int, const char *, const char *); int assertion_is_reg(const char *, int, const char *, int); int assertion_is_symlink(const char *, int, const char *, const char *); int assertion_make_dir(const char *, int, const char *, int); @@ -244,7 +242,6 @@ int assertion_text_file_contents(const char *buff, const char *f); int assertion_umask(const char *, int, int); void assertion_setup(const char *, int); -int is_file_hardlinks(const char *, int, const char *, const char *); void test_skipping(const char *fmt, ...); /* Like sprintf, then system() */ @@ -253,6 +250,9 @@ int systemf(const char * fmt, ...); /* Delay until time() returns a value after this. */ void sleepUntilAfter(time_t); +/* Return true if this platform can create symlinks. */ +int canSymlink(void); + /* Suck file into string allocated via malloc(). Call free() when done. */ /* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */ char *slurpfile(size_t *, const char *fmt, ...); diff --git a/cpio/test/test_basic.c b/cpio/test/test_basic.c index 65fe82444..b56e80785 100644 --- a/cpio/test/test_basic.c +++ b/cpio/test/test_basic.c @@ -38,12 +38,11 @@ verify_files(void) assertFileNLinks("file", 2); /* Another name for the same file. */ - assertFileHardlinks("linkfile", "file"); + assertIsHardlink("linkfile", "file"); /* Symlink */ -#if !defined(_WIN32) || defined(__CYGWIN__) - assertIsSymlink("symlink", "file"); -#endif + if (canSymlink()) + assertIsSymlink("symlink", "file"); /* Another file with 1 link and different permissions. */ assertIsReg("file2", 0777); @@ -124,6 +123,7 @@ passthrough(const char *target) DEFINE_TEST(test_basic) { FILE *filelist; + const char *msg; assertUmask(0); @@ -141,8 +141,10 @@ DEFINE_TEST(test_basic) fprintf(filelist, "linkfile\n"); /* Symlink to above file. */ - assertMakeSymlink("symlink", "file"); - fprintf(filelist, "symlink\n"); + if (canSymlink()) { + assertMakeSymlink("symlink", "file"); + fprintf(filelist, "symlink\n"); + } /* Another file with different permissions. */ assertMakeFile("file2", 0777, "1234567890"); @@ -157,20 +159,14 @@ DEFINE_TEST(test_basic) assertUmask(022); /* Archive/dearchive with a variety of options. */ - basic_cpio("copy", "", "", "2 blocks\n"); - basic_cpio("copy_odc", "--format=odc", "", "2 blocks\n"); + msg = canSymlink() ? "2 blocks\n" : "1 block\n"; + basic_cpio("copy", "", "", msg); + basic_cpio("copy_odc", "--format=odc", "", msg); basic_cpio("copy_newc", "-H newc", "", "2 blocks\n"); - basic_cpio("copy_cpio", "-H odc", "", "2 blocks\n"); -#if defined(_WIN32) && !defined(__CYGWIN__) - /* - * On Windows, symbolic link does not work. - * Currentry copying file instead. therefore block size is - * different. - */ - basic_cpio("copy_ustar", "-H ustar", "", "10 blocks\n"); -#else - basic_cpio("copy_ustar", "-H ustar", "", "9 blocks\n"); -#endif + basic_cpio("copy_cpio", "-H odc", "", msg); + msg = canSymlink() ? "9 blocks\n" : "8 blocks\n"; + basic_cpio("copy_ustar", "-H ustar", "", msg); + /* Copy in one step using -p */ passthrough("passthrough"); } diff --git a/cpio/test/test_gcpio_compat.c b/cpio/test/test_gcpio_compat.c index 320ca6604..2a98dfc66 100644 --- a/cpio/test/test_gcpio_compat.c +++ b/cpio/test/test_gcpio_compat.c @@ -58,7 +58,7 @@ unpack_test(const char *from, const char *options, const char *se) assertFileNLinks("file", 2); /* Another name for the same file. */ - assertFileHardlinks("linkfile", "file"); + assertIsHardlink("linkfile", "file"); /* Symlink */ assertIsSymlink("symlink", "file"); diff --git a/cpio/test/test_option_l.c b/cpio/test/test_option_l.c index f2cd5bfbf..5c76e688e 100644 --- a/cpio/test/test_option_l.c +++ b/cpio/test/test_option_l.c @@ -38,7 +38,7 @@ DEFINE_TEST(test_option_l) assertEqualInt(r, 0); /* Check that the copy is a true copy and not a link. */ - assert(!isFileHardlinks("f", "copy/f")); + assertIsNotHardlink("f", "copy/f"); /* Copy the file to the "link" dir with the -l option. */ r = systemf("echo f | %s -pld link >link.out 2>link.err", @@ -46,5 +46,5 @@ DEFINE_TEST(test_option_l) assertEqualInt(r, 0); /* Check that this is a link and not a copy. */ - assertFileHardlinks("f", "link/f"); + assertIsHardlink("f", "link/f"); }