diff options
Diffstat (limited to 'tests/link/driver.cxx')
-rw-r--r-- | tests/link/driver.cxx | 141 |
1 files changed, 141 insertions, 0 deletions
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); +} |