aboutsummaryrefslogtreecommitdiff
path: root/tests/link
diff options
context:
space:
mode:
Diffstat (limited to 'tests/link')
-rw-r--r--tests/link/buildfile7
-rw-r--r--tests/link/driver.cxx141
2 files changed, 148 insertions, 0 deletions
diff --git a/tests/link/buildfile b/tests/link/buildfile
new file mode 100644
index 0000000..860f0fc
--- /dev/null
+++ b/tests/link/buildfile
@@ -0,0 +1,7 @@
+# file : tests/link/buildfile
+# copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
+# license : MIT; see accompanying LICENSE file
+
+exe{driver}: cxx{driver} ../../butl/lib{butl}
+
+include ../../butl/
diff --git a/tests/link/driver.cxx b/tests/link/driver.cxx
new file mode 100644
index 0000000..7ec4ac2
--- /dev/null
+++ b/tests/link/driver.cxx
@@ -0,0 +1,141 @@
+// file : tests/link/driver.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <set>
+#include <cassert>
+#include <fstream>
+#include <utility> // pair
+#include <system_error>
+
+#include <butl/path>
+#include <butl/filesystem>
+
+using namespace std;
+using namespace butl;
+
+static const char text[] = "ABCDEF";
+
+static bool
+link_file (const path& target, const path& link, bool hard, bool check_content)
+{
+ try
+ {
+ if (hard)
+ mkhardlink (target, link);
+ else
+ mksymlink (target, link);
+ }
+ catch (const system_error&)
+ {
+ return false;
+ }
+
+ if (!check_content)
+ return true;
+
+ string s;
+ ifstream ifs;
+ ifs.exceptions (fstream::badbit | fstream::failbit);
+ ifs.open (link.string ());
+ ifs >> s;
+ return s == text;
+}
+
+#ifndef _WIN32
+static bool
+link_dir (
+ const dir_path& target, const dir_path& link, bool hard, bool check_content)
+{
+ try
+ {
+ if (hard)
+ mkhardlink (target, link);
+ else
+ mksymlink (target, link);
+ }
+ catch (const system_error&)
+ {
+ return false;
+ }
+
+ if (!check_content)
+ return true;
+
+ dir_path tp (target.absolute () ? target : link.directory () / target);
+ set<pair<entry_type, path>> te;
+ for (const dir_entry& de: dir_iterator (tp))
+ te.emplace (de.ltype (), de.path ());
+
+ set<pair<entry_type, path>> le;
+ for (const dir_entry& de: dir_iterator (link))
+ le.emplace (de.ltype (), de.path ());
+
+ return te == le;
+}
+#endif
+
+int
+main ()
+{
+ dir_path td (dir_path::temp_directory () / dir_path ("butl-link"));
+
+ // Recreate the temporary directory (that possibly exists from the previous
+ // faulty run) for the test files. Delete the directory only if the test
+ // succeeds to simplify the failure research.
+ //
+ try_rmdir_r (td);
+ assert (try_mkdir (td) == mkdir_status::success);
+
+ // Prepare the target file.
+ //
+ path fn ("target");
+ path fp (td / fn);
+
+ {
+ ofstream ofs;
+ ofs.exceptions (fstream::badbit | fstream::failbit);
+ ofs.open (fp.string ());
+ ofs << text;
+ }
+
+ // Create the file hard link.
+ //
+ assert (link_file (fp, td / path ("hlink"), true, true));
+
+#ifndef _WIN32
+ // Create the file symlink using an absolute path.
+ //
+ assert (link_file (fp, td / path ("slink"), false, true));
+
+ // Create the file symlink using a relative path.
+ //
+ assert (link_file (fn, td / path ("rslink"), false, true));
+
+ // Create the file symlink using an unexistent file path.
+ //
+ assert (link_file (fp / path ("a"), td / path ("sa"), false, false));
+
+ // Prepare the target directory.
+ //
+ dir_path dn ("dir");
+ dir_path dp (td / dn);
+ assert (try_mkdir (dp) == mkdir_status::success);
+ assert (link_file (fp, dp / path ("hlink"), true, true));
+ assert (link_file (fp, dp / path ("slink"), false, true));
+
+ // Create the directory symlink using an absolute path.
+ //
+ assert (link_dir (dp, td / dir_path ("dslink"), false, true));
+
+ // Create the directory symlink using a relative path.
+ //
+ assert (link_dir (dn, td / dir_path ("rdslink"), false, true));
+
+ // Create the directory symlink using an unexistent directory path.
+ //
+ assert (link_dir (dp / dir_path ("a"), td / dir_path ("dsa"), false, false));
+#endif
+
+ rmdir_r (td);
+}