aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/link/buildfile2
-rw-r--r--tests/link/driver.cxx91
-rw-r--r--tests/link/testscript79
-rw-r--r--tests/path-entry/driver.cxx29
-rw-r--r--tests/path-entry/testscript21
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"
}