/* 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__)
}
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);
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
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];
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));
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)
*
*/
+/*
+ * 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
/* 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) \
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) \
#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
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);
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() */
/* 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, ...);
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);
DEFINE_TEST(test_basic)
{
FILE *filelist;
+ const char *msg;
assertUmask(0);
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");
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");
}
assertFileNLinks("file", 2);
/* Another name for the same file. */
- assertFileHardlinks("linkfile", "file");
+ assertIsHardlink("linkfile", "file");
/* Symlink */
assertIsSymlink("symlink", "file");
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",
assertEqualInt(r, 0);
/* Check that this is a link and not a copy. */
- assertFileHardlinks("f", "link/f");
+ assertIsHardlink("f", "link/f");
}