aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/b-info/driver.cxx15
-rw-r--r--tests/base64/driver.cxx69
-rw-r--r--tests/build/root.build12
-rw-r--r--tests/builtin/driver.cxx7
-rw-r--r--tests/builtin/find.testscript276
-rw-r--r--tests/curl/driver.cxx20
-rw-r--r--tests/curl/testscript20
-rw-r--r--tests/dir-iterator/driver.cxx39
-rw-r--r--tests/dir-iterator/testscript30
-rw-r--r--tests/fdstream/driver.cxx84
-rw-r--r--tests/host-os-release/buildfile6
-rw-r--r--tests/host-os-release/driver.cxx58
-rw-r--r--tests/host-os-release/testscript223
-rw-r--r--tests/link/driver.cxx14
-rw-r--r--tests/manifest-parser/driver.cxx65
-rw-r--r--tests/manifest-roundtrip/driver.cxx13
-rw-r--r--tests/manifest-roundtrip/testscript40
-rw-r--r--tests/manifest-serializer/driver.cxx29
-rw-r--r--tests/mventry/testscript10
-rw-r--r--tests/next-word/buildfile6
-rw-r--r--tests/next-word/driver.cxx46
-rw-r--r--tests/odb/buildfile6
l---------tests/odb/driver.cxx1
-rw-r--r--tests/path-entry/testscript10
-rw-r--r--tests/pkg-config/buildfile6
l---------tests/pkg-config/driver.c1
l---------tests/pkg-config/testscript1
-rw-r--r--tests/semantic-version/driver.cxx33
-rw-r--r--tests/standard-version/driver.cxx4
-rw-r--r--tests/target-triplet/driver.cxx8
-rw-r--r--tests/timestamp/driver.cxx6
-rw-r--r--tests/wildcard/driver.cxx57
-rw-r--r--tests/wildcard/testscript6
33 files changed, 1153 insertions, 68 deletions
diff --git a/tests/b-info/driver.cxx b/tests/b-info/driver.cxx
index 6832aaa..5691221 100644
--- a/tests/b-info/driver.cxx
+++ b/tests/b-info/driver.cxx
@@ -49,13 +49,14 @@ try
cout.exceptions (ios::failbit | ios::badbit);
- b_project_info pi (b_info (project,
- true /* ext_mods */,
- 1 /* verb */,
- {} /* cmd_callback */,
- b,
- {} /* search_fallback */,
- {"--no-default-options"}));
+ b_project_info pi (
+ b_info (project,
+ b_info_flags::ext_mods | b_info_flags::subprojects,
+ 1 /* verb */,
+ {} /* cmd_callback */,
+ b,
+ {} /* search_fallback */,
+ {"--no-default-options"}));
cout << "project: " << pi.project << endl
<< "version: " << pi.version << endl
diff --git a/tests/base64/driver.cxx b/tests/base64/driver.cxx
index a37a238..32d5236 100644
--- a/tests/base64/driver.cxx
+++ b/tests/base64/driver.cxx
@@ -13,6 +13,8 @@
using namespace std;
using namespace butl;
+// Test base64 encoding and decoding.
+//
static bool
encode (const string& i, const string& o)
{
@@ -68,9 +70,44 @@ encode (const string& i, const string& o)
return r;
}
+// Test base64url encoding only (decoding not yet implemented).
+//
+static bool
+encode_url (const string& i, const string& o)
+{
+ istringstream is (i);
+ string s (base64url_encode (is));
+ bool r (s == o && is.eof ());
+
+ if (r)
+ {
+ is.seekg (0);
+
+ // VC15 seekg() doesn't clear eofbit.
+ //
+#if defined(_MSC_VER) && _MSC_VER < 1920
+ is.clear ();
+#endif
+
+ assert (!is.eof ());
+
+ ostringstream os;
+ base64url_encode (os, is);
+ r = os.str () == o && is.eof ();
+ }
+
+ if (r)
+ r = base64url_encode (vector<char> (i.begin (), i.end ())) == o;
+
+ return r;
+}
+
+
int
main ()
{
+ // base64
+ //
assert (encode ("", ""));
assert (encode ("B", "Qg=="));
assert (encode ("BX", "Qlg="));
@@ -80,6 +117,19 @@ main ()
assert (encode ("BXzS@#", "Qlh6U0Aj"));
assert (encode ("BXzS@#/", "Qlh6U0AjLw=="));
+ // base64url: no padding in output.
+ //
+ assert (encode_url ("", ""));
+ assert (encode_url ("B", "Qg"));
+ assert (encode_url ("BX", "Qlg"));
+ assert (encode_url ("BXz", "Qlh6"));
+ assert (encode_url ("BXzS", "Qlh6Uw"));
+ assert (encode_url ("BXzS@", "Qlh6U0A"));
+ assert (encode_url ("BXzS@#", "Qlh6U0Aj"));
+ assert (encode_url ("BXzS@#/", "Qlh6U0AjLw"));
+
+ // Multi-line input.
+ //
const char* s (
"class fdstream_base\n"
"{\n"
@@ -91,10 +141,29 @@ main ()
" fdbuf buf_;\n"
"};\n");
+ // base64
+ //
const char* r (
"Y2xhc3MgZmRzdHJlYW1fYmFzZQp7CnByb3RlY3RlZDoKICBmZHN0cmVhbV9iYXNlICgpID0gZGVm\n"
"YXVsdDsKICBmZHN0cmVhbV9iYXNlIChpbnQgZmQpOiBidWZfIChmZCkge30KCnByb3RlY3RlZDoK\n"
"ICBmZGJ1ZiBidWZfOwp9Owo=");
assert (encode (s, r));
+
+ // base64url: no newlines or padding in output.
+ //
+ r =
+"Y2xhc3MgZmRzdHJlYW1fYmFzZQp7CnByb3RlY3RlZDoKICBmZHN0cmVhbV9iYXNlICgpID0gZGVm"
+"YXVsdDsKICBmZHN0cmVhbV9iYXNlIChpbnQgZmQpOiBidWZfIChmZCkge30KCnByb3RlY3RlZDoK"
+"ICBmZGJ1ZiBidWZfOwp9Owo";
+
+ assert (encode_url (s, r));
+
+ // Test 63rd and 64th characters: `>` maps to `+` or `-`; `?` maps to `/` or
+ // `_`.
+ //
+ assert (encode (">>>>>>", "Pj4+Pj4+"));
+ assert (encode_url (">>>>>>", "Pj4-Pj4-"));
+ assert (encode ("??????", "Pz8/Pz8/"));
+ assert (encode_url ("??????", "Pz8_Pz8_"));
}
diff --git a/tests/build/root.build b/tests/build/root.build
index a1e935c..5ce7156 100644
--- a/tests/build/root.build
+++ b/tests/build/root.build
@@ -4,19 +4,27 @@
cxx.std = latest
using cxx
+using c
hxx{*}: extension = hxx
cxx{*}: extension = cxx
if ($cxx.target.system == 'win32-msvc')
- cxx.poptions += -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS
+ cc.poptions += -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS
if ($cxx.class == 'msvc')
- cxx.coptions += /wd4251 /wd4275 /wd4800
+ cc.coptions += /wd4251 /wd4275 /wd4800
elif ($cxx.id == 'gcc')
+{
cxx.coptions += -Wno-maybe-uninitialized -Wno-free-nonheap-object \
-Wno-stringop-overread
+ if ($cxx.version.major >= 13)
+ cxx.coptions += -Wno-dangling-reference
+}
+elif ($cxx.id.type == 'clang' && $cxx.version.major >= 15)
+ cxx.coptions += -Wno-unqualified-std-cast-call
+
# Every exe{} in this subproject is by default a test.
#
exe{*}: test = true
diff --git a/tests/builtin/driver.cxx b/tests/builtin/driver.cxx
index 7a0193f..bdf3fa9 100644
--- a/tests/builtin/driver.cxx
+++ b/tests/builtin/driver.cxx
@@ -28,6 +28,13 @@
using namespace std;
using namespace butl;
+// Disable arguments globbing that may be enabled by default for MinGW runtime
+// (see tests/wildcard/driver.cxx for details).
+//
+#ifdef __MINGW32__
+int _CRT_glob = 0;
+#endif
+
inline ostream&
operator<< (ostream& os, const path& p)
{
diff --git a/tests/builtin/find.testscript b/tests/builtin/find.testscript
new file mode 100644
index 0000000..b09822c
--- /dev/null
+++ b/tests/builtin/find.testscript
@@ -0,0 +1,276 @@
+# file : tests/builtin/find.testscript
+# license : MIT; see accompanying LICENSE file
+
+posix = ($cxx.target.class != 'windows')
+
+test.arguments = "find"
+
+: no-paths
+:
+$* 2>"find: missing start path" == 1
+
+: no-paths-primary
+:
+$* -name foo 2>"find: unknown option '-name'" == 1
+
+: unknown-primary
+:
+$* . -foo 2>"find: unknown primary '-foo'" == 1
+
+
+: no-primary-value
+:
+$* . -name 2>"find: missing value for primary '-name'" == 1
+
+: empty-primary-value
+:
+$* . -type '' 2>"find: empty value for primary '-type'" == 1
+
+: invalid-type-primary
+:
+$* . -type foo 2>"find: invalid value 'foo' for primary '-type'" == 1
+
+: invalid-mindepth-primary
+:
+$* . -mindepth 12a 2>"find: invalid value '12a' for primary '-mindepth'" == 1
+
+: path-not-exists
+:
+{
+ mkdir d;
+ $* x d >'d' 2>"find: 'x' doesn't exists" != 0
+}
+
+: path
+:
+{
+ : relative
+ :
+ {
+ : no-cwd
+ :
+ {
+ mkdir a;
+ touch a/b;
+
+ $* a >>/EOO
+ a
+ a/b
+ EOO
+ }
+
+ : absolute-cwd
+ :
+ : When cross-testing we cannot guarantee that host absolute paths are
+ : recognized by the target process.
+ :
+ if ($test.target == $build.host)
+ {
+ test.options += -d $~/a;
+ mkdir a;
+ touch a/b;
+
+ $* b >'b'
+ }
+
+ : relative-cwd
+ :
+ if ($test.target == $build.host)
+ {
+ test.options += -d a;
+ mkdir a;
+ touch a/b;
+
+ $* b >'b'
+ }
+ }
+
+ : non-normalized
+ :
+ {
+ mkdir a;
+ touch a/b;
+
+ # Note that the path specified on the command line is used unaltered.
+ #
+ s = ($posix ? '/' : '\');
+
+ $* ./a >>"EOO"
+ ./a
+ ./a$(s)b
+ EOO
+ }
+
+ : absolute
+ :
+ {
+ mkdir a;
+ touch a/b;
+
+ $* $~/a >>/"EOO"
+ $~/a
+ $~/a/b
+ EOO
+ }
+
+ : non-existent
+ :
+ {
+ touch a b;
+
+ $* a x b >>EOO 2>"find: 'x' doesn't exists" != 0
+ a
+ b
+ EOO
+ }
+
+ : non-directory
+ :
+ {
+ touch a b c;
+
+ $* a b/ c >>EOO 2>"find: 'b' is not a directory" != 0
+ a
+ c
+ EOO
+ }
+
+ : trailing-slash
+ :
+ {
+ mkdir -p a/b;
+
+ $* a >>/"EOO";
+ a
+ a/b
+ EOO
+
+ $* a/ >>"EOO"
+ a/
+ a/b
+ EOO
+ }
+}
+
+: name-primary
+:
+{
+ : basic
+ :
+ {
+ mkdir a;
+ touch a/ab a/ba;
+
+ $* . -name 'a*' >>/EOO;
+ ./a
+ ./a/ab
+ EOO
+
+ $* . -name 'b*' >>/EOO;
+ ./a/ba
+ EOO
+
+ $* a -name 'a*' >>/EOO
+ a
+ a/ab
+ EOO
+ }
+
+ : empty
+ :
+ {
+ touch a;
+
+ $* . -name ''
+ }
+}
+
+: type-primary
+:
+{
+ : regular
+ :
+ {
+ mkdir -p a/b;
+ touch a/b/c;
+
+ $* a -type f >>/EOO
+ a/b/c
+ EOO
+ }
+
+ : directory
+ :
+ {
+ mkdir -p a/b;
+ touch a/b/c;
+
+ $* a -type d >>/EOO
+ a
+ a/b
+ EOO
+ }
+
+ : symlink
+ :
+ if $posix
+ {
+ mkdir -p a/b;
+ touch a/b/c;
+ ln -s c a/b/d;
+
+ $* a -type l >>/EOO
+ a/b/d
+ EOO
+ }
+}
+
+: mindepth-primary
+:
+{
+ mkdir -p a/b/c;
+
+ $* a -mindepth 0 >>/EOO;
+ a
+ a/b
+ a/b/c
+ EOO
+
+ $* a -mindepth 1 >>/EOO;
+ a/b
+ a/b/c
+ EOO
+
+ $* a -mindepth 2 >>/EOO;
+ a/b/c
+ EOO
+
+ $* a -mindepth 3
+}
+
+: maxdepth-primary
+:
+{
+ mkdir -p a/b/c;
+
+ $* a -maxdepth 0 >>/EOO;
+ a
+ EOO
+
+ $* a -maxdepth 1 >>/EOO;
+ a
+ a/b
+ EOO
+
+ $* a -maxdepth 2 >>/EOO;
+ a
+ a/b
+ a/b/c
+ EOO
+
+ $* a -maxdepth 3 >>/EOO
+ a
+ a/b
+ a/b/c
+ EOO
+}
diff --git a/tests/curl/driver.cxx b/tests/curl/driver.cxx
index 72faf52..856fde3 100644
--- a/tests/curl/driver.cxx
+++ b/tests/curl/driver.cxx
@@ -104,6 +104,26 @@ http ()
c.out.close ();
assert (!c.wait ());
}
+
+ // POST from stream without --fail.
+ //
+ {
+ curl c (p, path ("-"), nullfd, 2,
+ curl::post,
+ curl::flags::no_fail,
+ u + "/bogus");
+
+ c.out << "bogus" << endl;
+ c.out.close ();
+ assert (c.wait ());
+ }
+
+ // POST empty data.
+ //
+ {
+ curl c (p, nullfd, 1, 2, curl::post, u + "/bogus", "--verbose");
+ assert (!c.wait ());
+ }
}
int
diff --git a/tests/curl/testscript b/tests/curl/testscript
index 3da2306..d2056cd 100644
--- a/tests/curl/testscript
+++ b/tests/curl/testscript
@@ -43,14 +43,22 @@ sudo /usr/sbin/in.tftpd \
: http
:
{
- $* 'http' 2>>EOE
+ $* 'http' 2>>~%EOE%
- curl -s -S --fail --location https://build2.org/bogus
- curl: (22) The requested URL returned error: 404 Not Found
+ curl -sS --fail --location https://build2.org/bogus
+ %curl: \(22\) The requested URL returned error: 404( Not Found)?%
- curl -s -S --fail --location https://build2.org
+ curl -sS --fail --location https://build2.org
- curl -s -S --fail --location --data-binary @- https://build2.org/bogus
- curl: (22) The requested URL returned error: 404 Not Found
+ curl -sS --fail --location --data-binary @- https://build2.org/bogus
+ %curl: \(22\) The requested URL returned error: 404( Not Found)?%
+
+ curl -sS --location --data-binary @- https://build2.org/bogus
+
+ curl -sS --fail --location --data-raw "" --verbose https://build2.org/bogus
+ %.*
+ %> POST /bogus HTTP.+%
+ %.*
+ %curl: \(22\) The requested URL returned error: 404( Not Found)?%
EOE
}
diff --git a/tests/dir-iterator/driver.cxx b/tests/dir-iterator/driver.cxx
index 4a2ff53..c9f7218 100644
--- a/tests/dir-iterator/driver.cxx
+++ b/tests/dir-iterator/driver.cxx
@@ -7,6 +7,7 @@
#include <libbutl/path.hxx>
#include <libbutl/path-io.hxx>
#include <libbutl/utility.hxx> // operator<<(ostream, exception)
+#include <libbutl/timestamp.hxx>
#include <libbutl/filesystem.hxx>
#undef NDEBUG
@@ -26,7 +27,7 @@ operator<< (ostream& os, entry_type e)
return os << entry_type_string[static_cast<size_t> (e)];
}
-// Usage: argv[0] [-v] [-i] <dir>
+// Usage: argv[0] [-v] [-i|-d] <dir>
//
// Iterates over a directory filesystem sub-entries, obtains their types and
// target types for symlinks.
@@ -38,6 +39,10 @@ operator<< (ostream& os, entry_type e)
// Ignore dangling symlinks, rather than fail trying to obtain the target
// type.
//
+// -d
+// Detect dangling symlinks, rather than fail trying to obtain the target
+// type.
+//
int
main (int argc, const char* argv[])
{
@@ -45,6 +50,7 @@ main (int argc, const char* argv[])
bool verbose (false);
bool ignore_dangling (false);
+ bool detect_dangling (false);
int i (1);
for (; i != argc; ++i)
@@ -55,6 +61,8 @@ main (int argc, const char* argv[])
verbose = true;
else if (v == "-i")
ignore_dangling = true;
+ else if (v == "-d")
+ detect_dangling = true;
else
break;
}
@@ -65,15 +73,42 @@ main (int argc, const char* argv[])
return 1;
}
+ assert (!ignore_dangling || !detect_dangling);
+
const char* d (argv[i]);
try
{
- for (const dir_entry& de: dir_iterator (dir_path (d), ignore_dangling))
+ for (const dir_entry& de:
+ dir_iterator (dir_path (d),
+ (ignore_dangling ? dir_iterator::ignore_dangling :
+ detect_dangling ? dir_iterator::detect_dangling :
+ dir_iterator::no_follow)))
{
+ timestamp mt (de.mtime ());
+ timestamp at (de.atime ());
+
entry_type lt (de.ltype ());
entry_type t (lt == entry_type::symlink ? de.type () : lt);
+
const path& p (de.path ());
+ path fp (de.base () / p);
+
+ entry_time et (t == entry_type::directory
+ ? dir_time (path_cast<dir_path> (fp))
+ : file_time (fp));
+
+ if (mt != timestamp_unknown)
+ assert (mt == et.modification);
+
+ if (at != timestamp_unknown)
+ assert (mt == et.access);
+
+ if (de.mtime () != timestamp_unknown)
+ assert (de.mtime () == et.modification);
+
+ if (de.atime () != timestamp_unknown)
+ assert (de.atime () == et.access);
if (verbose)
{
diff --git a/tests/dir-iterator/testscript b/tests/dir-iterator/testscript
index 03ed164..9bc5513 100644
--- a/tests/dir-iterator/testscript
+++ b/tests/dir-iterator/testscript
@@ -7,6 +7,8 @@ test.options = -v
:
mkdir a;
touch a/b;
+sleep 1;
+echo "a" >=a/b; # Change modification time.
$* a >"reg b"
: dir
@@ -24,16 +26,16 @@ $* a >"dir b"
if ($test.target == $build.host)
{
+if ($cxx.target.class != 'windows')
- lnf = ^ln -s t wd/l &wd/l
- lnd = $lnf
+ lnf = [cmdline] ^ln -s t wd/l &wd/l
+ lnd = [cmdline] $lnf
else
echo 'yes' >=t
if cmd /C 'mklink l t' >- 2>- &?l && cat l >'yes'
- lnf = cmd /C 'mklink wd\l t' &wd/l >-
- lnd = cmd /C 'mklink /D wd\l t' &wd/l >-
+ lnf = [cmdline] cmd /C 'mklink wd\l t' &wd/l >-
+ lnd = [cmdline] cmd /C 'mklink /D wd\l t' &wd/l >-
end
- jnc = cmd /C 'mklink /J wd\l wd\t' &wd/l >-
+ jnc = [cmdline] cmd /C 'mklink /J wd\l wd\t' &wd/l >-
end
: symlink
@@ -54,6 +56,12 @@ if ($test.target == $build.host)
$* ../wd >- 2>! != 0 : keep
$* -i ../wd >'reg f': skip
+
+ : detect
+ :
+ $* -d ../wd >>~%EOO%
+ %(reg f|sym unk l)%{2}
+ EOO
}
: dir
@@ -71,6 +79,12 @@ if ($test.target == $build.host)
$* ../wd >- 2>! != 0 : keep
$* -i ../wd >'dir d': skip
+
+ : detect
+ :
+ $* -d ../wd >>~%EOO%
+ %(dir d|sym unk l)%{2}
+ EOO
}
}
@@ -89,5 +103,11 @@ if ($test.target == $build.host)
$* ../wd >- 2>! != 0 : keep
$* -i ../wd >'dir d': skip
+
+ : detect
+ :
+ $* -d ../wd >>~%EOO%
+ %(dir d|sym unk l)%{2}
+ EOO
}
}
diff --git a/tests/fdstream/driver.cxx b/tests/fdstream/driver.cxx
index 0b66574..d039b00 100644
--- a/tests/fdstream/driver.cxx
+++ b/tests/fdstream/driver.cxx
@@ -42,7 +42,9 @@ static const string text2 ("12"); // Keep shorter than text1.
// Windows text mode write-translated form of text1.
//
+#ifdef _WIN32
static const string text3 ("ABCDEF\r\nXYZ");
+#endif
static string
from_stream (ifdstream& is)
@@ -568,6 +570,83 @@ main (int argc, const char* argv[])
t.join ();
}
+ // Test (non-blocking) reading with getline_non_blocking().
+ //
+ {
+ const string ln (
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
+
+ string s;
+ for (size_t i (0); i < 300; ++i)
+ {
+ s += ln;
+ s += '\n';
+ }
+
+ const char* args[] = {argv[0], "-c", nullptr};
+
+ auto test_read = [&args, &s, &ln] ()
+ {
+ try
+ {
+ process pr (args, -1, -1);
+ ofdstream os (move (pr.out_fd));
+
+ ifdstream is (move (pr.in_ofd),
+ fdstream_mode::non_blocking,
+ ios_base::badbit);
+
+ os << s;
+ os.close ();
+
+ fdselect_set fds {is.fd ()};
+ fdselect_state& ist (fds[0]);
+
+ string r;
+ for (string l; ist.fd != nullfd; )
+ {
+ if (ist.fd != nullfd && getline_non_blocking (is, l))
+ {
+ if (eof (is))
+ ist.fd = nullfd;
+ else
+ {
+ assert (l == ln);
+
+ r += l;
+ r += '\n';
+
+ l.clear ();
+ }
+
+ continue;
+ }
+
+ ifdselect (fds);
+ }
+
+ is.close ();
+
+ assert (r == s);
+ }
+ catch (const ios::failure&)
+ {
+ assert (false);
+ }
+ catch (const process_error&)
+ {
+ assert (false);
+ }
+ };
+
+ vector<thread> threads;
+ for (size_t i (0); i < 20; ++i)
+ threads.emplace_back (test_read);
+
+ for (thread& t: threads)
+ t.join ();
+ }
+
// Test setting and getting position via the non-standard fdstreambuf
// interface.
//
@@ -886,6 +965,11 @@ main (int argc, const char* argv[])
}
#endif
+
+ // Test fdterm().
+ //
+ assert (!fdterm (fdopen_null ().get ())); // /dev/null is not a terminal.
+
// Compare fdstream and fstream operations performance.
//
duration fwd (0);
diff --git a/tests/host-os-release/buildfile b/tests/host-os-release/buildfile
new file mode 100644
index 0000000..cd277ff
--- /dev/null
+++ b/tests/host-os-release/buildfile
@@ -0,0 +1,6 @@
+# file : tests/host-os-release/buildfile
+# license : MIT; see accompanying LICENSE file
+
+import libs = libbutl%lib{butl}
+
+exe{driver}: {hxx cxx}{*} $libs testscript
diff --git a/tests/host-os-release/driver.cxx b/tests/host-os-release/driver.cxx
new file mode 100644
index 0000000..249cbff
--- /dev/null
+++ b/tests/host-os-release/driver.cxx
@@ -0,0 +1,58 @@
+// file : tests/host-os-release/driver.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#include <libbutl/host-os-release.hxx>
+
+#include <libbutl/path.hxx>
+
+namespace butl
+{
+ LIBBUTL_SYMEXPORT os_release
+ host_os_release_linux (path f = {});
+}
+
+#include <iostream>
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+using namespace butl;
+
+int
+main (int argc, char* argv[])
+{
+ assert (argc >= 2); // <host-target-triplet>
+
+ target_triplet host (argv[1]);
+
+ os_release r;
+ if (host.class_ == "linux")
+ {
+ assert (argc == 3); // <host-target-triplet> <file-path>
+ r = host_os_release_linux (path (argv[2]));
+ }
+ else
+ {
+ assert (argc == 2);
+ if (optional<os_release> o = host_os_release (host))
+ r = move (*o);
+ else
+ {
+ cerr << "unrecognized host os " << host.string () << endl;
+ return 1;
+ }
+ }
+
+ cout << r.name_id << '\n';
+ for (auto b (r.like_ids.begin ()), i (b); i != r.like_ids.end (); ++i)
+ cout << (i != b ? "|" : "") << *i;
+ cout << '\n'
+ << r.version_id << '\n'
+ << r.variant_id << '\n'
+ << r.name << '\n'
+ << r.version_codename << '\n'
+ << r.variant << '\n';
+
+ return 0;
+}
diff --git a/tests/host-os-release/testscript b/tests/host-os-release/testscript
new file mode 100644
index 0000000..a18aa74
--- /dev/null
+++ b/tests/host-os-release/testscript
@@ -0,0 +1,223 @@
+# file : tests/host-os-release/testscript
+# license : MIT; see accompanying LICENSE file
+
+: linux
+:
+$* x86_64-linux-gnu os-release >>EOO
+ linux
+
+
+
+ Linux
+
+
+ EOO
+
+: debian-10
+:
+cat <<EOI >=os-release;
+ PRETTY_NAME="Debian GNU/Linux 10 (buster)"
+ NAME="Debian GNU/Linux"
+ VERSION_ID="10"
+ VERSION="10 (buster)"
+ VERSION_CODENAME=buster
+ ID=debian
+ HOME_URL="https://www.debian.org/"
+ SUPPORT_URL="https://www.debian.org/support"
+ BUG_REPORT_URL="https://bugs.debian.org/"
+ EOI
+$* x86_64-linux-gnu os-release >>EOO
+ debian
+
+ 10
+
+ Debian GNU/Linux
+ buster
+
+ EOO
+
+: debian-testing
+:
+cat <<EOI >=os-release;
+ PRETTY_NAME="Debian GNU/Linux bookworm/sid"
+ NAME="Debian GNU/Linux"
+ ID=debian
+ HOME_URL="https://www.debian.org/"
+ SUPPORT_URL="https://www.debian.org/support"
+ BUG_REPORT_URL="https://bugs.debian.org/"
+ EOI
+$* x86_64-linux-gnu os-release >>EOO
+ debian
+
+
+
+ Debian GNU/Linux
+
+
+ EOO
+
+: ubuntu-20.04
+:
+cat <<EOI >=os-release;
+ NAME="Ubuntu"
+ VERSION="20.04.1 LTS (Focal Fossa)"
+ ID=ubuntu
+ ID_LIKE=debian
+ PRETTY_NAME="Ubuntu 20.04.1 LTS"
+ VERSION_ID="20.04"
+ HOME_URL="https://www.ubuntu.com/"
+ SUPPORT_URL="https://help.ubuntu.com/"
+ BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
+ PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
+ VERSION_CODENAME=focal
+ UBUNTU_CODENAME=focal
+ EOI
+$* x86_64-linux-gnu os-release >>EOO
+ ubuntu
+ debian
+ 20.04
+
+ Ubuntu
+ focal
+
+ EOO
+
+: fedora-35
+:
+cat <<EOI >=os-release;
+ NAME="Fedora Linux"
+ VERSION="35 (Workstation Edition)"
+ ID=fedora
+ VERSION_ID=35
+ VERSION_CODENAME=""
+ PLATFORM_ID="platform:f35"
+ PRETTY_NAME="Fedora Linux 35 (Workstation Edition)"
+ ANSI_COLOR="0;38;2;60;110;180"
+ LOGO=fedora-logo-icon
+ CPE_NAME="cpe:/o:fedoraproject:fedora:35"
+ HOME_URL="https://fedoraproject.org/"
+ DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f35/system-administrators-guide/"
+ SUPPORT_URL="https://ask.fedoraproject.org/"
+ BUG_REPORT_URL="https://bugzilla.redhat.com/"
+ REDHAT_BUGZILLA_PRODUCT="Fedora"
+ REDHAT_BUGZILLA_PRODUCT_VERSION=35
+ REDHAT_SUPPORT_PRODUCT="Fedora"
+ REDHAT_SUPPORT_PRODUCT_VERSION=35
+ PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
+ VARIANT="Workstation Edition"
+ VARIANT_ID=workstation
+ EOI
+$* x86_64-linux-gnu os-release >>EOO
+ fedora
+
+ 35
+ workstation
+ Fedora Linux
+
+ Workstation Edition
+ EOO
+
+: rhel-8.2
+:
+cat <<EOI >=os-release;
+ NAME="Red Hat Enterprise Linux"
+ VERSION="8.2 (Ootpa)"
+ ID="rhel"
+ ID_LIKE="fedora"
+ VERSION_ID="8.2"
+ PLATFORM_ID="platform:el8"
+ PRETTY_NAME="Red Hat Enterprise Linux 8.2 (Ootpa)"
+ ANSI_COLOR="0;31"
+ CPE_NAME="cpe:/o:redhat:enterprise_linux:8.2:GA"
+ HOME_URL="https://www.redhat.com/"
+ BUG_REPORT_URL="https://bugzilla.redhat.com/"
+
+ REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 8"
+ REDHAT_BUGZILLA_PRODUCT_VERSION=8.2
+ REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
+ REDHAT_SUPPORT_PRODUCT_VERSION="8.2"
+ EOI
+$* x86_64-linux-gnu os-release >>EOO
+ rhel
+ fedora
+ 8.2
+
+ Red Hat Enterprise Linux
+
+
+ EOO
+
+: centos-8
+:
+cat <<EOI >=os-release;
+ NAME="CentOS Linux"
+ VERSION="8 (Core)"
+ ID="centos"
+ ID_LIKE="rhel fedora"
+ VERSION_ID="8"
+ PLATFORM_ID="platform:el8"
+ PRETTY_NAME="CentOS Linux 8 (Core)"
+ ANSI_COLOR="0;31"
+ CPE_NAME="cpe:/o:centos:centos:8"
+ HOME_URL="https://www.centos.org/"
+ BUG_REPORT_URL="https://bugs.centos.org/"
+
+ CENTOS_MANTISBT_PROJECT="CentOS-8"
+ CENTOS_MANTISBT_PROJECT_VERSION="8"
+ REDHAT_SUPPORT_PRODUCT="centos"
+ REDHAT_SUPPORT_PRODUCT_VERSION="8"
+ EOI
+$* x86_64-linux-gnu os-release >>EOO
+ centos
+ rhel|fedora
+ 8
+
+ CentOS Linux
+
+
+ EOO
+
+: macos
+:
+if ($build.host.class == 'macos')
+{
+ $* $build.host >>~/EOO/
+ macos
+
+ /[0-9]+(\.[0-9]+(\.[0-9]+)?)?/
+
+ Mac OS
+
+
+ EOO
+}
+
+: freebsd
+:
+if ($build.host.system == 'freebsd')
+{
+ $* $build.host >>~/EOO/
+ freebsd
+
+ /[0-9]+\.[0-9]+/
+
+ FreeBSD
+
+
+ EOO
+}
+
+: windows
+:
+if ($build.host.system == 'windows')
+{
+ $* $build.host >>~/EOO/
+ windows
+
+ /[0-9]+(\.[0-9]+)?/
+
+ Windows
+
+
+ EOO
+}
diff --git a/tests/link/driver.cxx b/tests/link/driver.cxx
index db9c195..b659838 100644
--- a/tests/link/driver.cxx
+++ b/tests/link/driver.cxx
@@ -107,11 +107,11 @@ link_dir (const dir_path& target,
dir_path tp (target.absolute () ? target : link.directory () / target);
set<pair<entry_type, path>> te;
- for (const dir_entry& de: dir_iterator (tp, false /* ignore_dangling */))
+ for (const dir_entry& de: dir_iterator (tp, dir_iterator::no_follow))
te.emplace (de.ltype (), de.path ());
set<pair<entry_type, path>> le;
- for (const dir_entry& de: dir_iterator (link, false /* ignore_dangling */))
+ for (const dir_entry& de: dir_iterator (link, dir_iterator::no_follow))
le.emplace (de.ltype (), de.path ());
return te == le;
@@ -306,7 +306,7 @@ main (int argc, const char* argv[])
assert (pe.first && pe.second.type == entry_type::directory);
}
- for (const dir_entry& de: dir_iterator (td, false /* ignore_dangling */))
+ for (const dir_entry& de: dir_iterator (td, dir_iterator::no_follow))
{
assert (de.path () != path ("dslink") ||
(de.type () == entry_type::directory &&
@@ -368,7 +368,9 @@ main (int argc, const char* argv[])
{
mksymlink (dp / "non-existing", dp / "lnk");
assert (!dir_empty (dp));
- assert (dir_iterator (dp, true /* ignore_dangling */) == dir_iterator ());
+
+ assert (dir_iterator (dp, dir_iterator::ignore_dangling) ==
+ dir_iterator ());
}
catch (const system_error& e)
{
@@ -393,10 +395,10 @@ main (int argc, const char* argv[])
mksymlink (dp / "non-existing", dp / "lnk1", true /* dir */);
assert (!dir_empty (dp));
- assert (dir_iterator (dp, true /* ignore_dangling */) == dir_iterator ());
+ assert (dir_iterator (dp, dir_iterator::ignore_dangling) == dir_iterator ());
mksymlink (tgd, dp / "lnk2", true /* dir */);
- assert (dir_iterator (dp, true /* ignore_dangling */) != dir_iterator ());
+ assert (dir_iterator (dp, dir_iterator::ignore_dangling) != dir_iterator ());
rmdir_r (dp);
assert (dir_exists (tgd));
diff --git a/tests/manifest-parser/driver.cxx b/tests/manifest-parser/driver.cxx
index 6924321..56c614a 100644
--- a/tests/manifest-parser/driver.cxx
+++ b/tests/manifest-parser/driver.cxx
@@ -164,14 +164,18 @@ namespace butl
// Manifest value splitting (into the value/comment pair).
//
+ // Single-line.
+ //
{
- auto p (manifest_parser::split_comment ("value\\; text ; comment text"));
- assert (p.first == "value; text" && p.second == "comment text");
+ auto p (manifest_parser::split_comment (
+ "\\value\\\\\\; text ; comment text"));
+
+ assert (p.first == "\\value\\; text" && p.second == "comment text");
}
{
- auto p (manifest_parser::split_comment ("value"));
- assert (p.first == "value" && p.second == "");
+ auto p (manifest_parser::split_comment ("value\\"));
+ assert (p.first == "value\\" && p.second == "");
}
{
@@ -179,6 +183,59 @@ namespace butl
assert (p.first == "" && p.second == "comment");
}
+ // Multi-line.
+ //
+ {
+ auto p (manifest_parser::split_comment ("value\n;"));
+ assert (p.first == "value" && p.second == "");
+ }
+
+ {
+ auto p (manifest_parser::split_comment ("value\ntext\n"));
+ assert (p.first == "value\ntext\n" && p.second == "");
+ }
+
+ {
+ auto p (manifest_parser::split_comment ("value\ntext\n;"));
+ assert (p.first == "value\ntext" && p.second == "");
+ }
+
+ {
+ auto p (manifest_parser::split_comment ("value\ntext\n;\n"));
+ assert (p.first == "value\ntext" && p.second == "");
+ }
+
+ {
+ auto p (manifest_parser::split_comment ("\n\\\nvalue\ntext\n"
+ ";\n"
+ "\n\n comment\ntext"));
+
+ assert (p.first == "\n\\\nvalue\ntext" && p.second ==
+ "\n\n comment\ntext");
+ }
+
+ {
+ auto p (manifest_parser::split_comment ("\n;\ncomment"));
+ assert (p.first == "" && p.second == "comment");
+ }
+
+ {
+ auto p (manifest_parser::split_comment (";\ncomment"));
+ assert (p.first == "" && p.second == "comment");
+ }
+
+ {
+ auto p (manifest_parser::split_comment (";\n"));
+ assert (p.first == "" && p.second == "");
+ }
+
+ {
+ auto p (manifest_parser::split_comment (
+ "\\;\n\\\\;\n\\\\\\;\n\\\\\\\\;\n\\\\\\\\\\;"));
+
+ assert (p.first == ";\n\\;\n\\;\n\\\\;\n\\\\;" && p.second == "");
+ }
+
// UTF-8.
//
assert (test (":1\n#\xD0\xB0\n\xD0\xB0y\xD0\xB0:\xD0\xB0z\xD0\xB0",
diff --git a/tests/manifest-roundtrip/driver.cxx b/tests/manifest-roundtrip/driver.cxx
index 5dc5862..c63a729 100644
--- a/tests/manifest-roundtrip/driver.cxx
+++ b/tests/manifest-roundtrip/driver.cxx
@@ -22,11 +22,16 @@ using namespace butl;
// -m
// Serialize multi-line manifest values using the v2 form.
//
+// -s
+// Split values into the value/comment pairs and merge them back before
+// printing.
+//
int
main (int argc, const char* argv[])
try
{
bool multiline_v2 (false);
+ bool split (false);
for (int i (1); i != argc; ++i)
{
@@ -34,6 +39,8 @@ try
if (v == "-m")
multiline_v2 = true;
+ else if (v == "-s")
+ split = true;
}
// Read/write in binary mode.
@@ -61,6 +68,12 @@ try
else
eom = false;
+ if (split)
+ {
+ const auto& vc (manifest_parser::split_comment (nv.value));
+ nv.value = manifest_serializer::merge_comment (vc.first, vc.second);
+ }
+
s.next (nv.name, nv.value);
}
}
diff --git a/tests/manifest-roundtrip/testscript b/tests/manifest-roundtrip/testscript
index e0a15cc..a228b0f 100644
--- a/tests/manifest-roundtrip/testscript
+++ b/tests/manifest-roundtrip/testscript
@@ -76,3 +76,43 @@ $* -m <<EOF >>EOF
c:\windows\\
\
EOF
+
+: split-merge-comment
+:
+$* -s <<EOF >>EOF
+ : 1
+ info:\
+ value
+ text
+ \
+ info:\
+ value
+ text
+ ;
+ comment
+ \
+ info:\
+ ;
+ comment
+ text
+ \
+ info:\
+ value
+ \;
+ \\
+ ;
+ comment
+ \
+ info:\
+ value
+ \\;
+ ;
+ comment
+ \
+ info:\
+ value
+ \\\\;
+ ;
+ comment
+ \
+ EOF
diff --git a/tests/manifest-serializer/driver.cxx b/tests/manifest-serializer/driver.cxx
index be3ae25..a003fa4 100644
--- a/tests/manifest-serializer/driver.cxx
+++ b/tests/manifest-serializer/driver.cxx
@@ -251,12 +251,37 @@ main ()
// Manifest value/comment merging.
//
- assert (manifest_serializer::merge_comment ("value; text", "comment") ==
- "value\\; text; comment");
+ // Single-line.
+ //
+ assert (manifest_serializer::merge_comment ("value\\; text", "comment") ==
+ "value\\\\\\; text; comment");
assert (manifest_serializer::merge_comment ("value text", "") ==
"value text");
+ // Multi-line.
+ //
+ assert (manifest_serializer::merge_comment ("value\n;\ntext", "comment") ==
+ "value\n\\;\ntext\n;\ncomment");
+
+ assert (manifest_serializer::merge_comment ("value\n\\;\ntext\n",
+ "comment") ==
+ "value\n\\\\;\ntext\n\n;\ncomment");
+
+ assert (manifest_serializer::merge_comment ("value\n\\\\;\ntext\n",
+ "comment") ==
+ "value\n\\\\\\\\;\ntext\n\n;\ncomment");
+
+
+ assert (manifest_serializer::merge_comment ("value\n\\\ntext", "comment") ==
+ "value\n\\\ntext\n;\ncomment");
+
+ assert (manifest_serializer::merge_comment ("\\", "comment\n") ==
+ "\\\n;\ncomment\n");
+
+ assert (manifest_serializer::merge_comment ("", "comment\ntext") ==
+ ";\ncomment\ntext");
+
// Filtering.
//
assert (test ({{"","1"},{"a","abc"},{"b","bca"},{"c","cab"},{"",""},{"",""}},
diff --git a/tests/mventry/testscript b/tests/mventry/testscript
index 61ef871..f52be79 100644
--- a/tests/mventry/testscript
+++ b/tests/mventry/testscript
@@ -98,16 +98,16 @@
if ($test.target == $build.host)
{
+if ($cxx.target.class != 'windows')
- lnf = ^ln -s t l &l
- lnd = $lnf
+ lnf = [cmdline] ^ln -s t l &l
+ lnd = [cmdline] $lnf
else
echo 'yes' >=t
if cmd /C 'mklink l t' >- 2>- &?l && cat l >'yes'
- lnf = cmd /C 'mklink l t' &l >-
- lnd = cmd /C 'mklink /D l t' &l >-
+ lnf = [cmdline] cmd /C 'mklink l t' &l >-
+ lnd = [cmdline] cmd /C 'mklink /D l t' &l >-
end
- jnc = cmd /C 'mklink /J l t' &l >-
+ jnc = [cmdline] cmd /C 'mklink /J l t' &l >-
end
: symlink
diff --git a/tests/next-word/buildfile b/tests/next-word/buildfile
new file mode 100644
index 0000000..e06cd88
--- /dev/null
+++ b/tests/next-word/buildfile
@@ -0,0 +1,6 @@
+# file : tests/next-word/buildfile
+# license : MIT; see accompanying LICENSE file
+
+import libs = libbutl%lib{butl}
+
+exe{driver}: {hxx cxx}{*} $libs
diff --git a/tests/next-word/driver.cxx b/tests/next-word/driver.cxx
new file mode 100644
index 0000000..4ebe1a5
--- /dev/null
+++ b/tests/next-word/driver.cxx
@@ -0,0 +1,46 @@
+// file : tests/next-word/driver.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#include <vector>
+#include <string>
+//#include <iostream>
+
+#include <libbutl/utility.hxx>
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+using namespace butl;
+
+using strings = vector<string>;
+
+static strings
+parse_lines (const string& s)
+{
+ strings r;
+ for (size_t b (0), e (0), m (0), n (s.size ());
+ next_word (s, n, b, e, m, '\n', '\r'), b != n; )
+ {
+ //cerr << "'" << string (s, b, e - b) << "'" << endl;
+ r.push_back (string (s, b, e - b));
+ }
+ return r;
+}
+
+int
+main ()
+{
+ assert ((parse_lines("") == strings {}));
+ assert ((parse_lines("a") == strings {"a"}));
+ assert ((parse_lines("\n") == strings {"", ""}));
+ assert ((parse_lines("\n\n") == strings {"", "", ""}));
+ assert ((parse_lines("\n\n\n") == strings {"", "", "", ""}));
+ assert ((parse_lines("\na") == strings {"", "a"}));
+ assert ((parse_lines("\n\na") == strings {"", "", "a"}));
+ assert ((parse_lines("a\n") == strings {"a", ""}));
+ assert ((parse_lines("a\n\n") == strings {"a", "", ""}));
+ assert ((parse_lines("a\nb") == strings {"a", "b"}));
+ assert ((parse_lines("a\n\nb") == strings {"a", "", "b"}));
+ assert ((parse_lines("\na\nb\n") == strings {"", "a", "b", ""}));
+}
diff --git a/tests/odb/buildfile b/tests/odb/buildfile
new file mode 100644
index 0000000..c59ab0f
--- /dev/null
+++ b/tests/odb/buildfile
@@ -0,0 +1,6 @@
+# file : tests/odb/buildfile
+# license : MIT; see accompanying LICENSE file
+
+import libs = libbutl%lib{butl-odb}
+
+exe{driver}: {hxx cxx}{*} $libs
diff --git a/tests/odb/driver.cxx b/tests/odb/driver.cxx
new file mode 120000
index 0000000..d880fda
--- /dev/null
+++ b/tests/odb/driver.cxx
@@ -0,0 +1 @@
+../../upstream/odb/libodb-sqlite/tests/basics/driver.cxx \ No newline at end of file
diff --git a/tests/path-entry/testscript b/tests/path-entry/testscript
index 16039fa..3ac363b 100644
--- a/tests/path-entry/testscript
+++ b/tests/path-entry/testscript
@@ -57,16 +57,16 @@
if ($test.target == $build.host)
{
+if ($cxx.target.class != 'windows')
- lnf = ^ln -s t l &l
- lnd = $lnf
+ lnf = [cmdline] ^ln -s t l &l
+ lnd = [cmdline] $lnf
else
echo 'yes' >=t
if cmd /C 'mklink l t' >- 2>- &?l && cat l >'yes'
- lnf = cmd /C 'mklink l t' &l >-
- lnd = cmd /C 'mklink /D l t' &l >-
+ lnf = [cmdline] cmd /C 'mklink l t' &l >-
+ lnd = [cmdline] cmd /C 'mklink /D l t' &l >-
end
- jnc = cmd /C 'mklink /J l t' &l >-
+ jnc = [cmdline] cmd /C 'mklink /J l t' &l >-
end
: symlink
diff --git a/tests/pkg-config/buildfile b/tests/pkg-config/buildfile
new file mode 100644
index 0000000..896b916
--- /dev/null
+++ b/tests/pkg-config/buildfile
@@ -0,0 +1,6 @@
+# file : tests/pkg-config/buildfile
+# license : MIT; see accompanying LICENSE file
+
+import libs = libbutl%lib{butl-pkg-config}
+
+exe{driver}: {h c}{*} $libs testscript
diff --git a/tests/pkg-config/driver.c b/tests/pkg-config/driver.c
new file mode 120000
index 0000000..2e6f14a
--- /dev/null
+++ b/tests/pkg-config/driver.c
@@ -0,0 +1 @@
+../../upstream/libpkg-config/libpkg-config/tests/basic/driver.c \ No newline at end of file
diff --git a/tests/pkg-config/testscript b/tests/pkg-config/testscript
new file mode 120000
index 0000000..628bd41
--- /dev/null
+++ b/tests/pkg-config/testscript
@@ -0,0 +1 @@
+../../upstream/libpkg-config/libpkg-config/tests/basic/testscript \ No newline at end of file
diff --git a/tests/semantic-version/driver.cxx b/tests/semantic-version/driver.cxx
index 2bdd415..3c20a6c 100644
--- a/tests/semantic-version/driver.cxx
+++ b/tests/semantic-version/driver.cxx
@@ -23,7 +23,6 @@ main ()
semver v;
assert (v.major == 0 && v.minor == 0 && v.patch == 0 && v.build.empty ());
}
-
{
semver v (1, 2, 3);
assert (v.major == 1 && v.minor == 2 && v.patch == 3 && v.build.empty ());
@@ -46,17 +45,27 @@ main ()
// String representation.
//
- assert (semver ("1.2") == semver (1, 2, 0));
- assert (semver ("1.2-3") == semver (1, 2, 0, "-3"));
- assert (semver ("1.2.a1", "+-.") == semver (1, 2, 0, ".a1"));
- assert (semver ("1.2.3") == semver (1, 2, 3));
- assert (semver ("1.2.3-4") == semver (1, 2, 3, "-4"));
- assert (semver ("1.2.3+4") == semver (1, 2, 3, "+4"));
- assert (semver ("1.2.3.4", "+-.") == semver (1, 2, 3, ".4"));
- assert (semver ("1.2.3a", "") == semver (1, 2, 3, "a"));
- try {semver v ("1.2.3-4", false); assert (false);} catch (failed) {}
- try {semver v ("1.2.3.4"); assert (false);} catch (failed) {}
- try {semver v ("1.2.3a"); assert (false);} catch (failed) {}
+ assert (semver ("1", semver::allow_omit_minor) == semver (1, 0, 0));
+ assert (semver ("1-2", semver::allow_omit_minor | semver::allow_build) == semver (1, 0, 0, "-2"));
+ assert (semver ("1.2", semver::allow_omit_minor) == semver (1, 2, 0));
+ assert (semver ("1.2+a", semver::allow_omit_minor | semver::allow_build) == semver (1, 2, 0, "+a"));
+ assert (semver ("1.2", semver::allow_omit_patch) == semver (1, 2, 0));
+ assert (semver ("1.2-3", semver::allow_omit_patch | semver::allow_build) == semver (1, 2, 0, "-3"));
+ assert (semver ("1.2.a1", semver::allow_omit_patch | semver::allow_build, ".+-") == semver (1, 2, 0, ".a1"));
+ assert (semver ("1.2.3") == semver (1, 2, 3));
+ assert (semver ("1.2.3-4", semver::allow_build) == semver (1, 2, 3, "-4"));
+ assert (semver ("1.2.3+4", semver::allow_build) == semver (1, 2, 3, "+4"));
+ assert (semver ("1.2.3.4", semver::allow_build, "+-.") == semver (1, 2, 3, ".4"));
+ assert (semver ("1.2.3a", semver::allow_build, "") == semver (1, 2, 3, "a"));
+
+ try {semver v ("1"); assert (false);} catch (failed) {}
+ try {semver v ("1.x.2"); assert (false);} catch (failed) {}
+ try {semver v ("1.2"); assert (false);} catch (failed) {}
+ try {semver v ("1.2.x"); assert (false);} catch (failed) {}
+ try {semver v ("1.2.3-4"); assert (false);} catch (failed) {}
+ try {semver v ("1.2.3.4"); assert (false);} catch (failed) {}
+ try {semver v ("1.2.3a"); assert (false);} catch (failed) {}
+
assert (!parse_semantic_version ("1.2.3.4"));
// Numeric representation.
diff --git a/tests/standard-version/driver.cxx b/tests/standard-version/driver.cxx
index 29cad54..4bddf08 100644
--- a/tests/standard-version/driver.cxx
+++ b/tests/standard-version/driver.cxx
@@ -83,7 +83,7 @@ version (const string& s,
if (v.minor () != 99999)
{
- standard_version_constraint c1 ("~" + s);
+ standard_version_constraint c1 ('~' + s);
standard_version_constraint c2 ('[' + s + ' ' + max_ver ('~') + ')');
assert (c1 == c2);
}
@@ -91,7 +91,7 @@ version (const string& s,
if ((v.major () == 0 && v.minor () != 99999) ||
(v.major () != 0 && v.major () != 99999))
{
- standard_version_constraint c1 ("^" + s);
+ standard_version_constraint c1 ('^' + s);
standard_version_constraint c2 ('[' + s + ' ' + max_ver ('^') + ')');
assert (c1 == c2);
}
diff --git a/tests/target-triplet/driver.cxx b/tests/target-triplet/driver.cxx
index 6dcb77e..8c08a90 100644
--- a/tests/target-triplet/driver.cxx
+++ b/tests/target-triplet/driver.cxx
@@ -74,6 +74,10 @@ main ()
"i686-w64-mingw32",
"i686", "w64", "mingw32", "", "windows"));
+ assert (test ("x86_64-w64-windows-gnu",
+ "x86_64-w64-mingw32",
+ "x86_64", "w64", "mingw32", "", "windows"));
+
assert (test ("i686-lfs-linux-gnu",
"i686-lfs-linux-gnu",
"i686", "lfs", "linux-gnu", "", "linux"));
@@ -82,6 +86,10 @@ main ()
"x86_64-linux-gnu",
"x86_64", "", "linux-gnu", "", "linux"));
+ assert (test ("x86_64-redhat-linux",
+ "x86_64-redhat-linux-gnu",
+ "x86_64", "redhat", "linux-gnu", "", "linux"));
+
assert (test ("x86_64-linux-gnux32",
"x86_64-linux-gnux32",
"x86_64", "", "linux-gnux32", "", "linux"));
diff --git a/tests/timestamp/driver.cxx b/tests/timestamp/driver.cxx
index 11f328a..956b295 100644
--- a/tests/timestamp/driver.cxx
+++ b/tests/timestamp/driver.cxx
@@ -178,15 +178,15 @@ main ()
assert (parse (".384902285 Feb 21 19:31:10 2016",
"%[.N] %b %d %H:%M:%S %Y",
- "." + ns (384902285) + " Feb 21 19:31:10 2016"));
+ '.' + ns (384902285) + " Feb 21 19:31:10 2016"));
assert (parse (".384902285 2016-02-21 19:31:10",
"%[.N] %Y-%m-%d %H:%M:%S",
- "." + ns (384902285) + " 2016-02-21 19:31:10"));
+ '.' + ns (384902285) + " 2016-02-21 19:31:10"));
assert (parse (".3849022852016-02-21 19:31:10",
"%[.N]%Y-%m-%d %H:%M:%S",
- "." + ns (384902285) + "2016-02-21 19:31:10"));
+ '.' + ns (384902285) + "2016-02-21 19:31:10"));
assert (parse ("Feb 1 2016", "%b %e %Y", "Feb 1 2016"));
assert (parse ("Feb 11 2016", "%b %e %Y", "Feb 11 2016"));
diff --git a/tests/wildcard/driver.cxx b/tests/wildcard/driver.cxx
index 9419a79..fee2748 100644
--- a/tests/wildcard/driver.cxx
+++ b/tests/wildcard/driver.cxx
@@ -4,11 +4,14 @@
#include <map>
#include <string>
#include <vector>
-#include <algorithm> // sort()
-#include <exception>
#include <iostream>
+#include <algorithm> // sort()
+#include <exception>
+#include <functional>
+#include <system_error>
#include <libbutl/path.hxx>
+#include <libbutl/path-io.hxx>
#include <libbutl/utility.hxx> // operator<<(ostream, exception)
#include <libbutl/optional.hxx>
#include <libbutl/filesystem.hxx>
@@ -59,8 +62,13 @@ int _CRT_glob = 0;
// through contains only the specified entry. The start directory is used if
// the first pattern component is a self-matching wildcard.
//
+// -d (print|stop)
+// If a inaccessible/dangling link is encountered, then print its path to
+// stderr and, optionally, stop the search. Meaningful in combination with
+// -sd and must follow it, if specified in the command line.
+//
// -i
-// Pass psflags::ignorable_components to the match/search functions.
+// Pass path_match_flags::match_absent to the match/search functions.
// Meaningful in combination with -sd or -sp options and must follow it, if
// specified in the command line.
//
@@ -93,6 +101,9 @@ try
bool sort (true);
path_match_flags flags (path_match_flags::follow_symlinks);
+ bool dangle_stop (false);
+ function<bool (const dir_entry&)> dangle_func;
+
int i (2);
for (; i != argc; ++i)
{
@@ -101,6 +112,34 @@ try
sort = false;
else if (o == "-i")
flags |= path_match_flags::match_absent;
+ else if (o == "-d")
+ {
+ ++i;
+
+ assert (op == "-sd" && i != argc);
+
+ string v (argv[i]);
+
+ if (v == "print")
+ {
+ dangle_func = [] (const dir_entry& de)
+ {
+ cerr << de.base () / de.path () << endl;
+ return true;
+ };
+ }
+ else if (v == "stop")
+ {
+ dangle_func = [&dangle_stop] (const dir_entry& de)
+ {
+ cerr << de.base () / de.path () << endl;
+ dangle_stop = true;
+ return false;
+ };
+ }
+ else
+ assert (false);
+ }
else
break; // End of options.
}
@@ -166,10 +205,13 @@ try
};
if (!entry)
- path_search (pattern, add, start, flags);
+ path_search (pattern, add, start, flags, dangle_func);
else
path_search (pattern, *entry, add, start, flags);
+ if (dangle_stop)
+ return 1;
+
// It the search succeeds, then test search in the directory tree
// represented by each matched path. Otherwise, if the directory tree is
// specified, then make sure that it doesn't match the pattern.
@@ -230,8 +272,13 @@ catch (const invalid_path& e)
cerr << e << ": " << e.path << endl;
return 2;
}
+catch (const system_error& e)
+{
+ cerr << e << endl;
+ return 3;
+}
catch (const exception& e)
{
cerr << e << endl;
- return 2;
+ return 4;
}
diff --git a/tests/wildcard/testscript b/tests/wildcard/testscript
index 5f6a767..baa51aa 100644
--- a/tests/wildcard/testscript
+++ b/tests/wildcard/testscript
@@ -650,12 +650,14 @@
{
mkdir a;
touch --no-cleanup a/b;
- ^ln -s b a/l &a/l;
+ ln -s b a/l &a/l;
rm a/b;
touch a/c;
- $* a/* >/'a/c'
+ $* a/* 2>! == 3;
+ $* -d 'print' a/* >/'a/c' 2>/'a/l';
+ $* -d 'stop' a/* >! 2>/'a/l' == 1
}
}