diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/link/buildfile | 2 | ||||
-rw-r--r-- | tests/link/driver.cxx | 91 | ||||
-rw-r--r-- | tests/link/testscript | 79 | ||||
-rw-r--r-- | tests/path-entry/driver.cxx | 29 | ||||
-rw-r--r-- | tests/path-entry/testscript | 21 |
5 files changed, 203 insertions, 19 deletions
diff --git a/tests/link/buildfile b/tests/link/buildfile index 462f60d..9b108b0 100644 --- a/tests/link/buildfile +++ b/tests/link/buildfile @@ -3,4 +3,4 @@ import libs = libbutl%lib{butl} -exe{driver}: {hxx cxx}{*} $libs +exe{driver}: {hxx cxx}{*} $libs testscript diff --git a/tests/link/driver.cxx b/tests/link/driver.cxx index a77df6f..231da4b 100644 --- a/tests/link/driver.cxx +++ b/tests/link/driver.cxx @@ -53,6 +53,12 @@ link_file (const path& target, const path& link, mklink ml, bool check_content) case mklink::hard: mkhardlink (target, link); break; case mklink::any: mkanylink (target, link, true /* copy */); break; } + + pair<bool, entry_stat> es (path_entry (link)); + assert (es.first); + + if (es.second.type == entry_type::symlink && readsymlink (link) != target) + return false; } catch (const system_error&) { @@ -87,6 +93,12 @@ link_dir (const dir_path& target, mkhardlink (target, link); else mksymlink (target, link); + + pair<bool, entry_stat> es (path_entry (link)); + assert (es.first); + + if (es.second.type == entry_type::symlink) + readsymlink (link); // // Check for errors. } catch (const system_error&) { @@ -120,9 +132,86 @@ link_dir (const dir_path& target, return te == le; } +// Usages: +// +// argv[0] +// argv[0] -s <target> <link> +// argv[0] -f <path> +// +// In the first form run the basic symbolic and hard link tests. +// +// In the second form create a symlink. On error print the diagnostics to +// stderr and exit with the one code. +// +// In the third form follow symlinks and print the resulting target path to +// stdout. On error print the diagnostics to stderr and exit with the one +// code. +// int -main () +main (int argc, const char* argv[]) { + bool create_symlink (false); + bool follow_symlinks (false); + + int i (1); + for (; i != argc; ++i) + { + string v (argv[i]); + + if (v == "-s") + create_symlink = true; + else if (v == "-f") + follow_symlinks = true; + else + break; + } + + if (create_symlink) + { + assert (!follow_symlinks); + assert (i + 2 == argc); + + try + { + path t (argv[i]); + path l (argv[i + 1]); + + bool dir (dir_exists (t.relative () ? l.directory () / t : t)); + mksymlink (t, l, dir); + + path lt (readsymlink (l)); + + // The targets may only differ for Windows directory junctions. + // + assert (lt == t || dir); + + return 0; + } + catch (const system_error& e) + { + cerr << "error: " << e << endl; + return 1; + } + } + else if (follow_symlinks) + { + assert (!create_symlink); + assert (i + 1 == argc); + + try + { + cout << try_followsymlink (path (argv[i])).first << endl; + return 0; + } + catch (const system_error& e) + { + cerr << "error: " << e << endl; + return 1; + } + } + else + assert (i == argc); + dir_path td (dir_path::temp_directory () / dir_path ("butl-link")); // Recreate the temporary directory (that possibly exists from the previous diff --git a/tests/link/testscript b/tests/link/testscript new file mode 100644 index 0000000..194b093 --- /dev/null +++ b/tests/link/testscript @@ -0,0 +1,79 @@ +# file : tests/link/testscript +# license : MIT; see accompanying LICENSE file + +: basics +: +$* + +: follow-symlinks +: +: Note that we may not be able to create symlinks on Windows and so test on +: POSIX only. But that'is ok since the follow_symlinks() implementation is not +: platform-specific. +: +if ($cxx.target.class != 'windows') +{ + : not-symlink + : + { + touch f; + $* -f f >f + } + + : not-exists + : + { + $* -f f >f + } + + : single-link + : + { + : absolute + : + { + $* -s $~/f l &l; + $* -f l >/"$~/f" + } + + : relative + : + { + $* -s d/f l &l; + $* -f l >/'d/f' + } + } + + : multiple-links + : + { + : relative-path + : + { + mkdir -p d1/d2; + $* -s ../d3/f d1/d2/l1 &d1/d2/l1; + + $* -f d1/d2/l1 >/'d1/d3/f'; + $* -f ../relative-path/d1/d2/l1 >/'../relative-path/d1/d3/f'; + + mkdir d4; + $* -s ../d1/d2/l1 d4/l2 &d4/l2; + + $* -f d4/l2 >/'d1/d3/f'; + $* -f $~/d4/l2 >/"$~/d1/d3/f" + } + + : absolute-path + : + { + mkdir -p d1/d2; + $* -s ../d3/f d1/d2/l1 &d1/d2/l1; + + mkdir d4; + $* -s $~/d1/d2/l1 d4/l2 &d4/l2; + + $* -f d4/l2 >/"$~/d1/d3/f"; + $* -f $~/d4/l2 >/"$~/d1/d3/f" + } + } +} diff --git a/tests/path-entry/driver.cxx b/tests/path-entry/driver.cxx index 51ac04d..30aae92 100644 --- a/tests/path-entry/driver.cxx +++ b/tests/path-entry/driver.cxx @@ -18,12 +18,14 @@ import std.core; import std.io; #endif import butl.path; +import butl.path-io; import butl.utility; // operator<<(ostream, exception) import butl.optional; import butl.timestamp; import butl.filesystem; #else #include <libbutl/path.mxx> +#include <libbutl/path-io.mxx> #include <libbutl/utility.mxx> #include <libbutl/optional.mxx> #include <libbutl/timestamp.mxx> @@ -36,11 +38,12 @@ using namespace butl; // Usage: argv[0] [-l] [-t] [-p <permissions>] [-m <time>] [-a <time>] <path> // // If path entry exists then optionally modify its meta-information and print -// its type, size (meaningful for the regular file only), permissions, -// modification and access times to STDOUT, one value per line, and exit with +// its type, size (meaningful for the regular file only), target path if the +// specified entry is a symlink and its path otherwise, permissions, +// modification and access times to stdout, one value per line, and exit with // the zero code. Otherwise exit with the one code. Don't follow symlink by -// default. On failure print the error description to STDERR and exit with -// the two code. +// default. On failure print the error description to stderr and exit with the +// two code. // // -l // Follow symlinks. @@ -136,6 +139,10 @@ main (int argc, const char* argv[]) if (!es.first) return 1; + stage = "lstat entry"; + pair<bool, entry_stat> ls (path_entry (p)); + assert (ls.first); + // The entry is a directory with a symlink followed. // bool tdir; @@ -188,7 +195,6 @@ main (int argc, const char* argv[]) } cout << "type: "; - switch (es.second.type) { case entry_type::unknown: cout << "unknown"; break; @@ -197,13 +203,18 @@ main (int argc, const char* argv[]) case entry_type::symlink: cout << "symlink"; break; case entry_type::other: cout << "other"; break; } + cout << endl; + + cout << "size: " << es.second.size << endl + << "target: " + << (ls.second.type == entry_type::symlink + ? readsymlink (p) + : p) << endl; stage = "get permissions"; - cout << endl - << "size: " << es.second.size << endl - << "permissions: " << oct - << static_cast<size_t> (path_permissions (p)) << endl; + cout << "permissions: " + << oct << static_cast<size_t> (path_permissions (p)) << endl; stage = tdir ? "get directory times" : "get file times"; diff --git a/tests/path-entry/testscript b/tests/path-entry/testscript index 0424dff..1d6911f 100644 --- a/tests/path-entry/testscript +++ b/tests/path-entry/testscript @@ -12,10 +12,10 @@ : { cat <:'abc' >=f; - $* f >>~/EOO/ + $* f >>~%EOO% type: regular size: 3 - /.+ + %.+ EOO } @@ -25,9 +25,9 @@ : { mkdir -p d; - $* d >>~/EOO/ + $* d >>~%EOO% type: directory - /.+ + %.+ EOO } @@ -36,10 +36,10 @@ { cat <:'abc' >=f; ln -s f l; - $* -l l >>~/EOO/ + $* -l l >>~%EOO% type: regular size: 3 - /.+ + %.+ EOO } @@ -54,7 +54,7 @@ if ($test.target == $build.host) { +if ($cxx.target.class != 'windows') - lnf = ln -s t l &l + lnf = ^ln -s t l &l lnd = $lnf else echo 'yes' >=t @@ -156,7 +156,12 @@ { mkdir t; $jnc; - $* -p 400 -m '2020-03-05 00:00:00' -a '2020-03-05 00:00:01' t | set ti; + + # Pass the absolute path so the junction's target path matches. + # + $* -p 400 -m '2020-03-05 00:00:00' -a '2020-03-05 00:00:01' $~/t | \ + set ti; + $* -l l >"$ti" } |