aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/b-info/driver.cxx53
-rw-r--r--tests/b-info/testscript4
-rw-r--r--tests/backtrace/driver.cxx24
-rw-r--r--tests/base64/driver.cxx86
-rw-r--r--tests/build/root.build15
-rw-r--r--tests/builtin/buildfile3
-rw-r--r--tests/builtin/driver.cxx184
-rw-r--r--tests/builtin/find.testscript276
-rw-r--r--tests/builtin/sed.testscript55
-rw-r--r--tests/builtin/timeout.testscript30
-rw-r--r--tests/command/driver.cxx32
-rw-r--r--tests/cpfile/driver.cxx23
-rw-r--r--tests/curl/driver.cxx56
-rw-r--r--tests/curl/testscript20
-rw-r--r--tests/default-options/driver.cxx257
-rw-r--r--tests/default-options/testscript308
-rw-r--r--tests/dir-iterator/driver.cxx69
-rw-r--r--tests/dir-iterator/testscript30
-rw-r--r--tests/entry-time/driver.cxx26
-rw-r--r--tests/fdstream/driver.cxx177
-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.cxx43
-rw-r--r--tests/lz4/buildfile6
-rw-r--r--tests/lz4/driver.cxx46
-rw-r--r--tests/lz4/testscript85
-rw-r--r--tests/lz4/truncated-content.lz4bin0 -> 108 bytes
-rw-r--r--tests/lz4/truncated-header12.lz4bin0 -> 12 bytes
-rw-r--r--tests/lz4/truncated-header6.lz41
-rw-r--r--tests/manifest-parser/driver.cxx89
-rw-r--r--tests/manifest-rewriter/driver.cxx48
-rw-r--r--tests/manifest-roundtrip/buildfile3
-rw-r--r--tests/manifest-roundtrip/driver.cxx69
-rw-r--r--tests/manifest-roundtrip/manifest32
-rw-r--r--tests/manifest-roundtrip/testscript118
-rw-r--r--tests/manifest-serializer/driver.cxx84
-rw-r--r--tests/move-only-function/buildfile6
-rw-r--r--tests/move-only-function/driver.cxx149
-rw-r--r--tests/mventry/driver.cxx23
-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/openssl/driver.cxx58
-rw-r--r--tests/optional/driver.cxx20
-rw-r--r--tests/pager/driver.cxx21
-rw-r--r--tests/path-entry/driver.cxx36
-rw-r--r--tests/path-entry/testscript10
-rw-r--r--tests/path/driver.cxx20
-rw-r--r--tests/pkg-config/buildfile6
l---------tests/pkg-config/driver.c1
l---------tests/pkg-config/testscript1
-rw-r--r--tests/prefix-map/driver.cxx21
-rw-r--r--tests/process-run/driver.cxx31
-rw-r--r--tests/process-term/buildfile6
-rw-r--r--tests/process-term/driver.cxx403
-rw-r--r--tests/process-term/testscript4
-rw-r--r--tests/process/driver.cxx105
-rw-r--r--tests/progress/driver.cxx29
-rw-r--r--tests/project-name/driver.cxx25
-rw-r--r--tests/regex/driver.cxx43
-rw-r--r--tests/regex/testscript67
-rw-r--r--tests/semantic-version/driver.cxx50
-rw-r--r--tests/sendmail/driver.cxx34
-rw-r--r--tests/sha1/driver.cxx29
-rw-r--r--tests/sha256/driver.cxx29
-rw-r--r--tests/small-forward-list/driver.cxx21
-rw-r--r--tests/small-list/driver.cxx17
-rw-r--r--tests/small-vector/driver.cxx18
-rw-r--r--tests/standard-version/driver.cxx31
-rw-r--r--tests/strcase/driver.cxx16
-rw-r--r--tests/string-parser/driver.cxx24
-rw-r--r--tests/tab-parser/driver.cxx20
-rw-r--r--tests/target-triplet/driver.cxx75
-rw-r--r--tests/timestamp/driver.cxx23
-rw-r--r--tests/url/driver.cxx81
-rw-r--r--tests/url/testscript252
-rw-r--r--tests/utf8/driver.cxx23
-rw-r--r--tests/uuid/driver.cxx4
-rw-r--r--tests/wildcard/driver.cxx86
-rw-r--r--tests/wildcard/testscript6
83 files changed, 3311 insertions, 1321 deletions
diff --git a/tests/b-info/driver.cxx b/tests/b-info/driver.cxx
index 6a3e0a4..5691221 100644
--- a/tests/b-info/driver.cxx
+++ b/tests/b-info/driver.cxx
@@ -1,28 +1,15 @@
// file : tests/b-info/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.b;
-import butl.path;
-import butl.utility; // operator<<(ostream,exception)
-#else
-#include <libbutl/b.mxx>
-#include <libbutl/path.mxx>
-#include <libbutl/utility.mxx>
-#endif
+
+#include <libbutl/b.hxx>
+#include <libbutl/path.hxx>
+#include <libbutl/utility.hxx> // operator<<(ostream,exception)
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -62,12 +49,14 @@ try
cout.exceptions (ios::failbit | ios::badbit);
- b_project_info pi (b_info (project,
- 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
@@ -109,6 +98,18 @@ try
cout << *i;
}
+ cout << endl
+ << "modules: ";
+
+ for (auto b (pi.modules.begin ()), i (b);
+ i != pi.modules.end ();
+ ++i)
+ {
+ if (i != b)
+ cout << ' ';
+
+ cout << *i;
+ }
cout << endl;
return 0;
diff --git a/tests/b-info/testscript b/tests/b-info/testscript
index c5c3910..1ebf060 100644
--- a/tests/b-info/testscript
+++ b/tests/b-info/testscript
@@ -57,10 +57,11 @@ test.options += -b $recall($build.path)
url:$sp
%src_root: .+/prj/%
%out_root: .+/prj/%
- amalgamation: ../../../../
+ %amalgamation: .*%
subprojects: @subprj/
operations: update clean
meta-operations: perform configure disfigure dist info
+ modules: version config dist
EOO
$* prj/subprj >>/~"%EOO%"
@@ -74,6 +75,7 @@ test.options += -b $recall($build.path)
subprojects:$sp
operations: update clean
meta-operations: perform configure disfigure dist info
+ modules: config dist
EOO
}
diff --git a/tests/backtrace/driver.cxx b/tests/backtrace/driver.cxx
index d998942..ecfa58e 100644
--- a/tests/backtrace/driver.cxx
+++ b/tests/backtrace/driver.cxx
@@ -5,31 +5,17 @@
# include <sys/resource.h> // setrlimit()
#endif
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
#include <exception> // set_terminate(), terminate_handler
#include <system_error>
-#else
-import std.io;
-#endif
-// Other includes.
+#include <libbutl/process.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/backtrace.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-#endif
-import butl.process;
-import butl.fdstream;
-import butl.backtrace;
-#else
-#include <libbutl/process.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/backtrace.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/base64/driver.cxx b/tests/base64/driver.cxx
index c7906f5..32d5236 100644
--- a/tests/base64/driver.cxx
+++ b/tests/base64/driver.cxx
@@ -1,29 +1,20 @@
// file : tests/base64/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <vector>
#include <sstream>
-#endif
-// Other includes.
+#include <libbutl/base64.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.base64;
-#else
-#include <libbutl/base64.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
+// Test base64 encoding and decoding.
+//
static bool
encode (const string& i, const string& o)
{
@@ -79,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="));
@@ -91,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"
@@ -102,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 bb274d3..5ce7156 100644
--- a/tests/build/root.build
+++ b/tests/build/root.build
@@ -4,15 +4,26 @@
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.
#
diff --git a/tests/builtin/buildfile b/tests/builtin/buildfile
index 8341847..8d22fe4 100644
--- a/tests/builtin/buildfile
+++ b/tests/builtin/buildfile
@@ -6,3 +6,6 @@ import libs = libbutl%lib{butl}
./: exe{driver} file{cp-dir/cp-file}
exe{driver}: {hxx cxx}{*} $libs testscript{*}
+
+if ($cxx.target.class != 'windows')
+ cxx.libs += -lpthread
diff --git a/tests/builtin/driver.cxx b/tests/builtin/driver.cxx
index 9fb6d6f..bdf3fa9 100644
--- a/tests/builtin/driver.cxx
+++ b/tests/builtin/driver.cxx
@@ -1,53 +1,60 @@
// file : tests/builtin/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
+#ifdef _WIN32
+# include <libbutl/win32-utility.hxx>
+#endif
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <vector>
+#include <chrono>
#include <utility> // move()
+#include <cstdint> // uint8_t
#include <ostream>
#include <iostream>
+#ifndef _WIN32
+# include <thread> // this_thread::sleep_for()
#endif
-// Other includes.
+#include <libbutl/path.hxx>
+#include <libbutl/utility.hxx> // eof()
+#include <libbutl/builtin.hxx>
+#include <libbutl/optional.hxx>
+#include <libbutl/timestamp.hxx> // to_stream(duration)
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.utility; // eof()
-import butl.builtin;
-import butl.optional;
-import butl.timestamp; // to_stream(duration)
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/utility.mxx>
-#include <libbutl/builtin.mxx>
-#include <libbutl/optional.mxx>
-#include <libbutl/timestamp.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
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)
{
return os << p.representation ();
}
-// Usage: argv[0] [-d <dir>] [-o <opt>] [-c] [-i] <builtin> <builtin-args>
+// Usage: argv[0] [-d <dir>] [-o <opt>] [-c] [-i] [-t <msec>] [-s <sec>]
+// <builtin> <builtin-args>
//
// Execute the builtin and exit with its exit status.
//
-// -d <dir> use as a current working directory
-// -c use callbacks that, in particular, trace calls to stdout
-// -o <opt> additional builtin option recognized by the callback
-// -i read lines from stdin and append them to the builtin arguments
+// -d <dir> use as a current working directory
+// -c use callbacks that, in particular, trace calls to stdout
+// -o <opt> additional builtin option recognized by the callback
+// -i read lines from stdin and append them to the builtin arguments
+// -t <msec> print diag if the builtin didn't complete in <msec> milliseconds
+// -s <sec> sleep <sec> seconds prior to running the builtin
+//
+// Note that the 'roundtrip' builtin name is also recognized and results in
+// running the pseudo-builtin that just roundtrips stdin to stdout.
//
int
main (int argc, char* argv[])
@@ -62,12 +69,25 @@ main (int argc, char* argv[])
dir_path cwd;
string option;
builtin_callbacks callbacks;
+ optional<duration> timeout;
+ optional<chrono::seconds> sec;
string name;
vector<string> args;
auto flag = [] (bool v) {return v ? "true" : "false";};
+ auto num = [] (const string& s)
+ {
+ assert (!s.empty ());
+
+ char* e (nullptr);
+ errno = 0; // We must clear it according to POSIX.
+ uint64_t r (strtoull (s.c_str (), &e, 10)); // Can't throw.
+ assert (errno != ERANGE && e == s.c_str () + s.size ());
+ return r;
+ };
+
// Parse the driver options and arguments.
//
int i (1);
@@ -120,7 +140,23 @@ main (int argc, char* argv[])
);
}
else if (a == "-i")
+ {
in = true;
+ }
+ else if (a == "-t")
+ {
+ ++i;
+
+ assert (i != argc);
+ timeout = chrono::milliseconds (num (argv[i]));
+ }
+ else if (a == "-s")
+ {
+ ++i;
+
+ assert (i != argc);
+ sec = chrono::seconds (num (argv[i]));
+ }
else
break;
}
@@ -142,23 +178,95 @@ main (int argc, char* argv[])
args.push_back (move (s));
}
- // Execute the builtin.
- //
- const builtin_info* bi (builtins.find (name));
+ auto sleep = [&sec] ()
+ {
+ if (sec)
+ {
+ // MINGW GCC 4.9 doesn't implement this_thread so use Win32 Sleep().
+ //
+#ifndef _WIN32
+ this_thread::sleep_for (*sec);
+#else
+ Sleep (static_cast<DWORD> (sec->count () * 1000));
+#endif
+ }
+ };
- if (bi == nullptr)
+ auto wait = [&timeout] (builtin& b)
{
- cerr << "unknown builtin '" << name << "'" << endl;
- return 1;
- }
+ optional<uint8_t> r;
+
+ if (timeout)
+ {
+ r = b.timed_wait (*timeout);
+
+ if (!r)
+ {
+ cerr << "timeout expired" << endl;
- if (bi->function == nullptr)
+ b.wait ();
+ r = 1;
+ }
+ }
+ else
+ r = b.wait ();
+
+ assert (b.try_wait ()); // While at it, test try_wait().
+
+ return *r;
+ };
+
+ // Execute the builtin.
+ //
+ if (name != "roundtrip")
{
- cerr << "external builtin '" << name << "'" << endl;
- return 1;
+ const builtin_info* bi (builtins.find (name));
+
+ if (bi == nullptr)
+ {
+ cerr << "unknown builtin '" << name << "'" << endl;
+ return 1;
+ }
+
+ if (bi->function == nullptr)
+ {
+ cerr << "external builtin '" << name << "'" << endl;
+ return 1;
+ }
+
+ sleep ();
+
+ uint8_t r; // Storage.
+ builtin b (bi->function (r, args, nullfd, nullfd, nullfd, cwd, callbacks));
+ return wait (b);
}
+ else
+ {
+ uint8_t r; // Storage.
- uint8_t r; // Storage.
- builtin b (bi->function (r, args, nullfd, nullfd, nullfd, cwd, callbacks));
- return b.wait ();
+ auto run = [&r, &sleep] ()
+ {
+ // While at it, test that a non-copyable lambda can be used as a
+ // builtin.
+ //
+ auto_fd fd;
+
+ return pseudo_builtin (
+ r,
+ [&sleep, fd = move (fd)] () mutable noexcept
+ {
+ fd.reset ();
+
+ sleep ();
+
+ if (cin.peek () != istream::traits_type::eof ())
+ cout << cin.rdbuf ();
+
+ return 0;
+ });
+ };
+
+ builtin b (run ());
+ return wait (b);
+ }
}
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/builtin/sed.testscript b/tests/builtin/sed.testscript
index ad26483..2ed3088 100644
--- a/tests/builtin/sed.testscript
+++ b/tests/builtin/sed.testscript
@@ -89,16 +89,10 @@ test.options += -c
sed: empty script
EOE
- : multiple
- :
- $* -e 's/a//' -e 's/a//' 2>>EOE != 0
- sed: multiple scripts
- EOE
-
: invalid
:
$* -e 'z' 2>>EOE != 0
- sed: only 's' command supported
+ sed: unknown command in 'z': only 's' command supported
EOE
}
@@ -156,13 +150,13 @@ test.options += -c
: none
:
$* -e 's' 2>>EOE != 0
- sed: no delimiter for 's' command
+ sed: no delimiter for 's' command in 's'
EOE
: invalid
:
$* -e 's\\' 2>>EOE != 0
- sed: invalid delimiter for 's' command
+ sed: invalid delimiter for 's' command in 's\\'
EOE
}
@@ -171,14 +165,14 @@ test.options += -c
{
: unterminated
:
- $* -e 's/foo' 2>>/EOE != 0
- sed: unterminated 's' command regex
+ $* -e 's/foo' 2>>EOE != 0
+ sed: invalid 's' command 's/foo': no delimiter after regex
EOE
: empty
:
$* -e 's///' 2>>EOE != 0
- sed: empty regex in 's' command
+ sed: invalid 's' command 's///': empty regex
EOE
: invalid
@@ -187,20 +181,20 @@ test.options += -c
: regex errors. For example '*' is parsed successfully.
:
$* -e 's/foo[/bar/' 2>>~%EOE% != 0
- %sed: invalid regex.*%
+ %sed: invalid regex 'foo\[' in 's/foo\[/bar/'.*%
EOE
}
: unterminated-replacement
:
- $* -e 's/foo/bar' 2>>/EOE != 0
- sed: unterminated 's' command replacement
+ $* -e 's/foo/bar' 2>>EOE != 0
+ sed: invalid 's' command 's/foo/bar': no delimiter after replacement
EOE
: invalid-flags
:
$* -e 's/foo/bar/a' 2>>EOE != 0
- sed: invalid 's' command flag 'a'
+ sed: invalid 's' command flag 'a' in 's/foo/bar/a'
EOE
}
@@ -314,6 +308,35 @@ test.options += -c
}
}
}
+
+ : multiple
+ :
+ {
+ $* -e 's/b/x/' -e 's/x/y/' -e 's/c/z/' <'abc' >'ayz' : replace-replacement
+
+ : new-cycle
+ :
+ $* -e 's/b/x/p' -e 's/x/y/p' <<EOI >>EOO
+ abc
+ klm
+ dxe
+ EOI
+ axc
+ klm
+ dye
+ EOO
+
+ : quiet
+ :
+ $* -n -e 's/b/x/p' -e 's/x/y/p' <<EOI >>EOO
+ abc
+ klm
+ dxe
+ EOI
+ axc
+ dye
+ EOO
+ }
}
: in-place
diff --git a/tests/builtin/timeout.testscript b/tests/builtin/timeout.testscript
new file mode 100644
index 0000000..b8eddc3
--- /dev/null
+++ b/tests/builtin/timeout.testscript
@@ -0,0 +1,30 @@
+# file : tests/builtin/timeout.testscript
+# license : MIT; see accompanying LICENSE file
+
+: async-builtin
+:
+{
+ : expired
+ :
+ $* -s 5 'cat' <'test' | $* -t 1 'cat' >=f 2>'timeout expired' != 0
+
+ : not-expired
+ :
+ echo 'test' | $* -t 10000 'cat' >!
+}
+
+: pseudo-builtin
+:
+{
+ : expired
+ :
+ $* -s 5 'cat' <'test' | $* -t 1 'roundtrip' >=f 2>'timeout expired' != 0
+
+ : not-expired
+ :
+ echo 'test' | $* -t 10000 'roundtrip' >!
+}
+
+: sync-builtin
+:
+$* -t 1 'mkdir' d &d/
diff --git a/tests/command/driver.cxx b/tests/command/driver.cxx
index 0c070ab..9194c13 100644
--- a/tests/command/driver.cxx
+++ b/tests/command/driver.cxx
@@ -1,38 +1,22 @@
// file : tests/command/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <ios>
#include <string>
#include <vector>
#include <iostream>
#include <stdexcept> // invalid_argument
#include <system_error>
-#endif
-// Other includes.
+#include <libbutl/path.hxx>
+#include <libbutl/path-io.hxx>
+#include <libbutl/process.hxx>
+#include <libbutl/command.hxx>
+#include <libbutl/utility.hxx>
+#include <libbutl/optional.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.path_io;
-import butl.process; // process::print()
-import butl.command;
-import butl.utility;
-import butl.optional;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/path-io.mxx>
-#include <libbutl/process.mxx>
-#include <libbutl/command.mxx>
-#include <libbutl/utility.mxx>
-#include <libbutl/optional.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/cpfile/driver.cxx b/tests/cpfile/driver.cxx
index c613b49..fe01bdd 100644
--- a/tests/cpfile/driver.cxx
+++ b/tests/cpfile/driver.cxx
@@ -1,29 +1,16 @@
// file : tests/cpfile/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <ios>
#include <string>
#include <system_error>
-#endif
-// Other includes.
+#include <libbutl/path.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/filesystem.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.fdstream;
-import butl.filesystem;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/filesystem.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/curl/driver.cxx b/tests/curl/driver.cxx
index 18ed1e6..856fde3 100644
--- a/tests/curl/driver.cxx
+++ b/tests/curl/driver.cxx
@@ -1,35 +1,17 @@
// file : tests/curl/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <iostream>
#include <system_error>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.curl;
-import butl.path;
-import butl.process;
-import butl.utility; // operator<<(ostream, exception)
-import butl.fdstream;
-
-import butl.optional; // @@ MOD Clang should not be necessary.
-import butl.small_vector; // @@ MOD Clang should not be necessary.
-#else
-#include <libbutl/curl.mxx>
-#include <libbutl/path.mxx>
-#include <libbutl/process.mxx>
-#include <libbutl/utility.mxx>
-#include <libbutl/fdstream.mxx>
-#endif
+
+#include <libbutl/curl.hxx>
+#include <libbutl/path.hxx>
+#include <libbutl/process.hxx>
+#include <libbutl/utility.hxx> // operator<<(ostream, exception)
+#include <libbutl/fdstream.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -122,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/default-options/driver.cxx b/tests/default-options/driver.cxx
index c6ac671..766dca8 100644
--- a/tests/default-options/driver.cxx
+++ b/tests/default-options/driver.cxx
@@ -1,62 +1,53 @@
// file : tests/default-options/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
+#include <limits>
#include <string>
#include <vector>
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.path_io;
-import butl.optional;
-import butl.fdstream;
-import butl.default_options;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/path-io.mxx>
-#include <libbutl/utility.mxx> // eof()
-#include <libbutl/optional.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/default-options.mxx>
-#endif
+#include <exception>
+#include <stdexcept> // invalid_argument
+
+#include <libbutl/path.hxx>
+#include <libbutl/path-io.hxx>
+#include <libbutl/utility.hxx> // eof()
+#include <libbutl/optional.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/default-options.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
// Usage: argv[0] [-f <file>] [-d <start-dir>] [-s <sys-dir>] [-h <home-dir>]
-// [-x <extra-dir>] [-e] [-t] <cmd-options>
+// [-x <extra-dir>] [-a] [-e] [-t] <cmd-options>
//
// Parse default options files, merge them with the command line options, and
// print the resulting options to STDOUT one per line. Note that the options
// instance is a vector of arbitrary strings.
//
-// -f
+// -f <file>
// Default options file name. Can be specified multiple times.
//
-// -d
+// -d <start-dir>
// Directory to start the default options files search from. Can be
// specified multiple times, in which case a common start (parent)
// directory is deduced.
//
-// -s
+// -s <sys-dir>
// System directory.
//
-// -h
+// -h <home-dir>
// Home directory.
//
-// -x
+// -x <extra-dir>
// Extra directory.
//
+// -a
+// Default arguments are allowed in the options files.
+//
// -e
// Print the default options entries (rather than the merged options) to
// STDOUT one per line in the following format:
@@ -66,6 +57,12 @@ using namespace butl;
// -t
// Trace the default options files search to STDERR.
//
+// -m <num>
+// Maximum number of arguments globally (SIZE_MAX/2 by default).
+//
+// -l <num>
+// Maximum number of arguments in the options file (1024 by default).
+//
int
main (int argc, const char* argv[])
{
@@ -74,37 +71,111 @@ main (int argc, const char* argv[])
class scanner
{
public:
- scanner (const string& f): ifs_ (f, fdopen_mode::in, ifdstream::badbit) {}
+ scanner (const string& f, const string& option, size_t pos)
+ : option_ (option), start_pos_ (pos) {load (path (f));}
+
+ bool
+ more ()
+ {
+ return i_ < args_.size ();
+ }
- optional<string>
+ string
+ peek ()
+ {
+ assert (more ());
+ return args_[i_];
+ }
+
+ string
next ()
{
- string s;
- return !eof (getline (ifs_, s)) ? optional<string> (move (s)) : nullopt;
+ assert (more ());
+ return args_[i_++];
+ }
+
+ size_t
+ position ()
+ {
+ return start_pos_ + i_;
}
private:
- ifdstream ifs_;
+ void
+ load (const path& f)
+ {
+ ifdstream is (f, fdopen_mode::in, ifdstream::badbit);
+
+ for (string l; !eof (getline (is, l)); )
+ {
+ if (option_ && *option_ == l)
+ {
+ assert (!eof (getline (is, l)));
+
+ // If the path of the file being parsed is not simple and the path
+ // of the file that needs to be loaded is relative, then complete
+ // the latter using the former as a base.
+ //
+ path p (l);
+
+ if (!f.simple () && p.relative ())
+ p = f.directory () / p;
+
+ load (p);
+ }
+ else
+ args_.push_back (move (l));
+ }
+ }
+
+ private:
+ optional<string> option_;
+ vector<string> args_;
+ size_t i_ = 0;
+ size_t start_pos_;
};
enum class unknow_mode
{
+ stop,
fail
};
+ class unknown_argument: public std::exception
+ {
+ public:
+ string argument;
+
+ explicit
+ unknown_argument (string a): argument (move (a)) {}
+ };
+
class options: public vector<string>
{
public:
bool
- parse (scanner& s, unknow_mode, unknow_mode)
+ parse (scanner& s, unknow_mode, unknow_mode m)
{
bool r (false);
- while (optional<string> o = s.next ())
+ while (s.more ())
{
- if (*o == "--no-default-options")
+ string a (s.peek ());
+
+ if (a.compare (0, 2, "--") != 0)
+ {
+ switch (m)
+ {
+ case unknow_mode::stop: return r;
+ case unknow_mode::fail: throw unknown_argument (move (a));
+ }
+ }
+
+ s.next ();
+
+ if (a == "--no-default-options")
no_default_options_ = true;
- push_back (move (*o));
+ push_back (move (a));
r = true;
}
return r;
@@ -132,60 +203,98 @@ main (int argc, const char* argv[])
optional<dir_path> sys_dir;
optional<dir_path> home_dir;
optional<dir_path> extra_dir;
+ bool args (false);
vector<dir_path> dirs;
options cmd_ops;
+ vector<string> cmd_args;
bool print_entries (false);
bool trace (false);
+ size_t arg_max (numeric_limits<size_t>::max () / 2);
+ size_t arg_max_file (1024);
+
+ auto num = [] (const string& s) -> size_t
+ {
+ assert (!s.empty ());
+
+ char* e (nullptr);
+ errno = 0; // We must clear it according to POSIX.
+ uint64_t r (strtoull (s.c_str (), &e, 10)); // Can't throw.
+
+ assert (errno != ERANGE &&
+ e == s.c_str () + s.size () &&
+ r <= numeric_limits<size_t>::max ());
+
+ return static_cast<size_t> (r);
+ };
for (int i (1); i != argc; ++i)
{
- string op (argv[i]);
+ string a (argv[i]);
- if (op == "-f")
+ if (a == "-f")
{
assert (++i != argc);
fs.files.push_back (path (argv[i]));
}
- else if (op == "-d")
+ else if (a == "-d")
{
assert (++i != argc);
dirs.emplace_back (argv[i]);
}
- else if (op == "-s")
+ else if (a == "-s")
{
assert (++i != argc);
sys_dir = dir_path (argv[i]);
}
- else if (op == "-h")
+ else if (a == "-h")
{
assert (++i != argc);
home_dir = dir_path (argv[i]);
}
- else if (op == "-x")
+ else if (a == "-x")
{
assert (++i != argc);
extra_dir = dir_path (argv[i]);
}
- else if (op == "-e")
+ else if (a == "-a")
+ {
+ args = true;
+ }
+ else if (a == "-e")
{
print_entries = true;
}
- else if (op == "-t")
+ else if (a == "-t")
{
trace = true;
}
+ else if (a == "-m")
+ {
+ assert (++i != argc);
+ arg_max = num (argv[i]);
+ }
+ else if (a == "-l")
+ {
+ assert (++i != argc);
+ arg_max_file = num (argv[i]);
+ }
+ else if (a.compare (0, 2, "--") == 0)
+ cmd_ops.push_back (move (a));
else
- cmd_ops.push_back (argv[i]);
+ cmd_args.push_back (move (a));
}
// Deduce a common start directory.
//
- fs.start = default_options_start (home_dir, dirs);
+ fs.start = default_options_start (home_dir, dirs.begin (), dirs.end ());
// Load and print the default options.
//
- default_options<options> def_ops (
- load_default_options<options, scanner, unknow_mode> (
+ default_options<options> def_ops;
+
+ try
+ {
+ def_ops = load_default_options<options, scanner, unknow_mode> (
sys_dir,
home_dir,
extra_dir,
@@ -195,7 +304,23 @@ main (int argc, const char* argv[])
if (trace)
cerr << (overwrite ? "overwriting " : "loading ")
<< (remote ? "remote " : "local ") << f << endl;
- }));
+ },
+ "--options-file",
+ arg_max,
+ arg_max_file,
+ args);
+ }
+ catch (const unknown_argument& e)
+ {
+ cerr << "error: unexpected argument '" << e.argument << "'" << endl;
+ return 1;
+ }
+ catch (const invalid_argument& e)
+ {
+ cerr << "error: unable to load default options files: " << e.what ()
+ << endl;
+ return 1;
+ }
if (print_entries)
{
@@ -211,18 +336,40 @@ main (int argc, const char* argv[])
cout << o;
}
+ if (args)
+ {
+ cout << "|";
+
+ for (const string& a: e.arguments)
+ {
+ if (&a != &e.arguments[0])
+ cout << ' ';
+
+ cout << a;
+ }
+
+ }
+
cout << (e.remote ? ",true" : ",false") << endl;
}
}
// Merge the options and print the result.
//
- options ops (merge_default_options (def_ops, cmd_ops));
-
if (!print_entries)
{
+ options ops (merge_default_options (def_ops, cmd_ops));
+
for (const string& o: ops)
cout << o << endl;
+
+ if (args)
+ {
+ vector<string> as (merge_default_arguments (def_ops, cmd_args));
+
+ for (const string& a: as)
+ cout << a << endl;
+ }
}
return 0;
diff --git a/tests/default-options/testscript b/tests/default-options/testscript
index fa65e62..f071701 100644
--- a/tests/default-options/testscript
+++ b/tests/default-options/testscript
@@ -4,9 +4,9 @@
# Note that when cross-testing the driver may not be able to run the command
# due to the meaningless program path.
#
-+if ($test.target != $build.host)
- exit
-end
+#+if ($test.target != $build.host)
+# exit
+#end
: basic
:
@@ -14,46 +14,47 @@ end
sys_dir = $canonicalize([dir_path] $~/build2)
+mkdir -p $sys_dir/local
- +echo 'sys-foo' >=$sys_dir/foo
- +echo 'sys-bar' >=$sys_dir/bar
- +echo 'sys-local-foo' >=$sys_dir/local/foo
- +echo 'sys-local-bar' >=$sys_dir/local/bar
+ +echo '--sys-foo' >=$sys_dir/foo
+ +echo '--sys-bar' >=$sys_dir/bar
+ +echo '--sys-local-foo' >=$sys_dir/local/foo
+ +echo '--sys-local-bar' >=$sys_dir/local/bar
home_dir = $canonicalize([dir_path] $~/home)
+mkdir -p $home_dir/.build2/local/
- +echo 'home-foo' >=$home_dir/.build2/foo
- +echo 'home-bar' >=$home_dir/.build2/bar
- +echo 'home-local-foo' >=$home_dir/.build2/local/foo
- +echo 'home-local-bar' >=$home_dir/.build2/local/bar
+ +echo '--home-foo' >=$home_dir/.build2/foo
+ +echo '--home-bar' >=$home_dir/.build2/bar
+ +echo '--home-local-foo' >=$home_dir/.build2/local/foo
+ +echo '--home-local-bar' >=$home_dir/.build2/local/bar
work_dir = $home_dir/work
+mkdir -p $work_dir/.build2/local/
d = $work_dir/.build2
- +echo 'work-foo' >=$d/foo
- +echo 'work-bar' >=$d/bar
- +echo 'work-local-foo' >=$d/local/foo
- +echo 'work-local-bar' >=$d/local/bar
+ +echo '--work-foo' >=$d/foo
+ +echo '--work-bar' >=$d/bar
+ +echo '--work-local-foo' >=$d/local/foo
+ +echo '--work-local-bar' >=$d/local/bar
d = $work_dir/project/.build2
+mkdir -p $d/local/
+touch $work_dir/project/.git
- +echo 'project-foo' >=$d/foo
- +echo 'project-bar' >=$d/bar
- +echo 'project-local-foo' >=$d/local/foo
- +echo 'project-local-bar' >=$d/local/bar
+ +echo '--project-foo' >=$d/foo
+ +echo '--project-bar' >=$d/bar
+ +echo '--project-local-foo' >=$d/local/foo
+ +echo '--project-local-bar' >=$d/local/bar
d = $work_dir/project/package/.build2
+mkdir -p $d/local/
- +echo 'package-foo' >=$d/foo
- +echo 'package-bar' >=$d/bar
- +echo 'package-local-foo' >=$d/local/foo
- +echo 'package-local-bar' >=$d/local/bar
+ +echo '--package-foo' >=$d/foo
+ +echo '--package-fox' >+$d/foo
+ +echo '--package-bar' >=$d/bar
+ +echo '--package-local-foo' >=$d/local/foo
+ +echo '--package-local-bar' >=$d/local/bar
+echo '--no-default-options' >=$d/local/baz
@@ -62,26 +63,26 @@ end
: entries
:
$* -e -t -f foo -f bar -d $start_dir -s $sys_dir -h $home_dir >>/~%EOO%d 2>>/~%EOE%d
- %\.+/build2/foo,sys-foo,false%
- %\.+/build2/bar,sys-bar,false%
- %\.+/build2/local/foo,sys-local-foo,false%
- %\.+/build2/local/bar,sys-local-bar,false%
- %\.+/home/.build2/foo,home-foo,false%
- %\.+/home/.build2/bar,home-bar,false%
- %\.+/home/.build2/local/foo,home-local-foo,false%
- %\.+/home/.build2/local/bar,home-local-bar,false%
- %\.+/home/work/.build2/foo,work-foo,false%
- %\.+/home/work/.build2/bar,work-bar,false%
- %\.+/home/work/.build2/local/foo,work-local-foo,false%
- %\.+/home/work/.build2/local/bar,work-local-bar,false%
- %\.+/home/work/project/.build2/foo,project-foo,true%
- %\.+/home/work/project/.build2/bar,project-bar,true%
- %\.+/home/work/project/.build2/local/foo,project-local-foo,true%
- %\.+/home/work/project/.build2/local/bar,project-local-bar,true%
- %\.+/home/work/project/package/.build2/foo,package-foo,true%
- %\.+/home/work/project/package/.build2/bar,package-bar,true%
- %\.+/home/work/project/package/.build2/local/foo,package-local-foo,true%
- %\.+/home/work/project/package/.build2/local/bar,package-local-bar,true%
+ %\.+/build2/foo,--sys-foo,false%
+ %\.+/build2/bar,--sys-bar,false%
+ %\.+/build2/local/foo,--sys-local-foo,false%
+ %\.+/build2/local/bar,--sys-local-bar,false%
+ %\.+/home/.build2/foo,--home-foo,false%
+ %\.+/home/.build2/bar,--home-bar,false%
+ %\.+/home/.build2/local/foo,--home-local-foo,false%
+ %\.+/home/.build2/local/bar,--home-local-bar,false%
+ %\.+/home/work/.build2/foo,--work-foo,false%
+ %\.+/home/work/.build2/bar,--work-bar,false%
+ %\.+/home/work/.build2/local/foo,--work-local-foo,false%
+ %\.+/home/work/.build2/local/bar,--work-local-bar,false%
+ %\.+/home/work/project/.build2/foo,--project-foo,true%
+ %\.+/home/work/project/.build2/bar,--project-bar,true%
+ %\.+/home/work/project/.build2/local/foo,--project-local-foo,true%
+ %\.+/home/work/project/.build2/local/bar,--project-local-bar,true%
+ %\.+/home/work/project/package/.build2/foo,--package-foo --package-fox,true%
+ %\.+/home/work/project/package/.build2/bar,--package-bar,true%
+ %\.+/home/work/project/package/.build2/local/foo,--package-local-foo,true%
+ %\.+/home/work/project/package/.build2/local/bar,--package-local-bar,true%
EOO
%loading local \.+/home/work/project/package/.build2/local/bar%
%loading local \.+/home/work/project/package/.build2/local/foo%
@@ -111,37 +112,38 @@ end
: merged
:
- $* -f foo -f bar -d $start_dir -s $sys_dir -h $home_dir cmd-foo cmd-bar >>EOO
- sys-foo
- sys-bar
- sys-local-foo
- sys-local-bar
- home-foo
- home-bar
- home-local-foo
- home-local-bar
- work-foo
- work-bar
- work-local-foo
- work-local-bar
- project-foo
- project-bar
- project-local-foo
- project-local-bar
- package-foo
- package-bar
- package-local-foo
- package-local-bar
- cmd-foo
- cmd-bar
+ $* -f foo -f bar -d $start_dir -s $sys_dir -h $home_dir --cmd-foo --cmd-bar >>EOO
+ --sys-foo
+ --sys-bar
+ --sys-local-foo
+ --sys-local-bar
+ --home-foo
+ --home-bar
+ --home-local-foo
+ --home-local-bar
+ --work-foo
+ --work-bar
+ --work-local-foo
+ --work-local-bar
+ --project-foo
+ --project-bar
+ --project-local-foo
+ --project-local-bar
+ --package-foo
+ --package-fox
+ --package-bar
+ --package-local-foo
+ --package-local-bar
+ --cmd-foo
+ --cmd-bar
EOO
: no-default-options
:
$* -e -t -f foo -f baz -f bar -d $start_dir -s $sys_dir -h $home_dir >>/~%EOO%d 2>>/~%EOE%d
- %\.+/home/work/project/package/.build2/local/foo,package-local-foo,true%
+ %\.+/home/work/project/package/.build2/local/foo,--package-local-foo,true%
%\.+/home/work/project/package/.build2/local/baz,--no-default-options,true%
- %\.+/home/work/project/package/.build2/local/bar,package-local-bar,true%
+ %\.+/home/work/project/package/.build2/local/bar,--package-local-bar,true%
EOO
%loading local \.+/home/work/project/package/.build2/local/bar%
%loading local \.+/home/work/project/package/.build2/local/baz%
@@ -150,6 +152,67 @@ end
%overwriting remote \.+/home/work/project/package/.build2/local/baz%
%overwriting remote \.+/home/work/project/package/.build2/local/foo%
EOE
+
+ : positions
+ :
+ {
+ : success
+ :
+ $* -f foo -f bar -d $start_dir -m 36 -l 2 >!
+
+ : fail-file
+ :
+ $* -f foo -f bar -d $start_dir -m 36 -l 1 2>>/~%EOE% != 0
+ %error: unable to load default options files: too many options in file .+/package/\.build2/foo%
+ EOE
+
+ : fail-globally
+ :
+ $* -f foo -f bar -d $start_dir -m 100 -l 10 2>>EOE != 0
+ error: unable to load default options files: too many options files
+ EOE
+ }
+}
+
+: args
+:
+{
+ home_dir = $canonicalize([dir_path] $~/home)
+ +mkdir -p $home_dir/.build2
+ +echo '--home' >=$home_dir/.build2/ops
+ +echo 'home' >+$home_dir/.build2/ops
+
+ start_dir = $canonicalize([dir_path] $home_dir/start)
+ +mkdir -p $start_dir/.build2
+ +echo '--start1' >=$start_dir/.build2/ops
+ +echo 'start2' >+$start_dir/.build2/ops
+ +echo '--start3' >+$start_dir/.build2/ops
+ +echo 'start4' >+$start_dir/.build2/ops
+
+ : allowed
+ :
+ $* -a -e -f ops -d $start_dir -h $home_dir >>/~%EOO%d
+ %\.+/home/.build2/ops,--home\|home,false%
+ %\.+/home/start/.build2/ops,--start1 --start3\|start2 start4,false%
+ EOO
+
+ : disallowed
+ :
+ $* -e -f ops -d $start_dir -h $home_dir 2>>EOE != 0
+ error: unexpected argument 'start2'
+ EOE
+
+ : merged
+ :
+ $* -a -f ops -d $start_dir -h $home_dir cmd >>EOO
+ --home
+ --start1
+ --start3
+ home
+ start2
+ start4
+ cmd
+ EOO
}
: common-start
@@ -166,10 +229,10 @@ end
+mkdir -p $work_dir/.build2 $cfg1/.build2 $cfg2/.build2 $cfg3/.build2
- +echo 'work' >=$work_dir/.build2/ops
- +echo 'cfg1' >=$cfg1/.build2/ops
- +echo 'cfg2' >=$cfg2/.build2/ops
- +echo 'cfg3' >=$cfg3/.build2/ops
+ +echo '--work' >=$work_dir/.build2/ops
+ +echo '--cfg1' >=$cfg1/.build2/ops
+ +echo '--cfg2' >=$cfg2/.build2/ops
+ +echo '--cfg3' >=$cfg3/.build2/ops
: exists
:
@@ -177,29 +240,29 @@ end
: single
:
$* -f ops -d $cfg3 -h $home_dir >>EOO
- work
- cfg2
- cfg3
+ --work
+ --cfg2
+ --cfg3
EOO
: same
:
$* -f ops -d $cfg1 -d $cfg1 -h $home_dir >>EOO
- work
- cfg1
+ --work
+ --cfg1
EOO
: adjacent
:
$* -f ops -d $cfg1 -d $cfg2 -h $home_dir >>EOO
- work
+ --work
EOO
: nested
:
$* -f ops -d $cfg2 -d $cfg3 -h $home_dir >>EOO
- work
- cfg2
+ --work
+ --cfg2
EOO
}
@@ -209,7 +272,7 @@ end
: home-reached
:
$* -f ops -d $cfg1 -d $cfg2 -h $work_dir >>EOO
- work
+ --work
EOO
: root-reached
@@ -229,20 +292,20 @@ end
{
home_dir = $canonicalize([dir_path] $~/home);
mkdir -p $home_dir/.build2;
- echo 'home' >=$home_dir/.build2/ops;
+ echo '--home' >=$home_dir/.build2/ops;
extra_dir = $canonicalize([dir_path] $home_dir/extra);
mkdir -p $extra_dir;
- echo 'extra' >=$extra_dir/ops;
+ echo '--extra' >=$extra_dir/ops;
start_dir = $canonicalize([dir_path] $home_dir/start);
mkdir -p $start_dir/.build2;
- echo 'start' >=$start_dir/.build2/ops;
+ echo '--start' >=$start_dir/.build2/ops;
$* -e -f ops -d $start_dir -h $home_dir -x $extra_dir >>/~%EOO%d
- %\.+/home/.build2/ops,home,false%
- %\.+/home/extra/ops,extra,false%
- %\.+/home/start/.build2/ops,start,false%
+ %\.+/home/.build2/ops,--home,false%
+ %\.+/home/extra/ops,--extra,false%
+ %\.+/home/start/.build2/ops,--start,false%
EOO
}
@@ -251,56 +314,89 @@ end
{
home_dir = $canonicalize([dir_path] $~/home);
mkdir -p $home_dir/.build2;
- echo 'home' >=$home_dir/.build2/ops;
+ echo '--home' >=$home_dir/.build2/ops;
d = $home_dir/project/.build2;
mkdir -p $d;
- echo 'project' >=$d/ops;
+ echo '--project' >=$d/ops;
touch $home_dir/project/.git;
d = $home_dir/project/package/.build2;
mkdir -p $d;
- echo 'package' >=$d/ops;
+ echo '--package' >=$d/ops;
extra_dir = $canonicalize([dir_path] $home_dir/project/package/extra1);
mkdir -p $extra_dir;
- echo 'extra1' >=$extra_dir/ops;
+ echo '--extra1' >=$extra_dir/ops;
start_dir = $canonicalize([dir_path] $home_dir/project/package);
$* -e -f ops -d $start_dir -h $home_dir -x $extra_dir >>/~%EOO%d;
- %\.+/home/.build2/ops,home,false%
- %\.+/home/project/.build2/ops,project,true%
- %\.+/home/project/package/.build2/ops,package,true%
- %\.+/home/project/package/extra1/ops,extra1,false%
+ %\.+/home/.build2/ops,--home,false%
+ %\.+/home/project/.build2/ops,--project,true%
+ %\.+/home/project/package/.build2/ops,--package,true%
+ %\.+/home/project/package/extra1/ops,--extra1,false%
EOO
extra_dir = $canonicalize([dir_path] $home_dir/project/package/.build2);
$* -e -f ops -d $start_dir -h $home_dir -x $extra_dir/ >>/~%EOO%d;
- %\.+/home/.build2/ops,home,false%
- %\.+/home/project/.build2/ops,project,true%
- %\.+/home/project/package/.build2/ops,package,false%
+ %\.+/home/.build2/ops,--home,false%
+ %\.+/home/project/.build2/ops,--project,true%
+ %\.+/home/project/package/.build2/ops,--package,false%
EOO
extra_dir = $canonicalize([dir_path] $home_dir/project/extra2);
mkdir -p $extra_dir;
- echo 'extra2' >=$extra_dir/ops;
+ echo '--extra2' >=$extra_dir/ops;
$* -e -f ops -d $start_dir -h $home_dir -x $extra_dir >>/~%EOO%d;
- %\.+/home/.build2/ops,home,false%
- %\.+/home/project/.build2/ops,project,true%
- %\.+/home/project/extra2/ops,extra2,false%
- %\.+/home/project/package/.build2/ops,package,true%
+ %\.+/home/.build2/ops,--home,false%
+ %\.+/home/project/.build2/ops,--project,true%
+ %\.+/home/project/extra2/ops,--extra2,false%
+ %\.+/home/project/package/.build2/ops,--package,true%
EOO
extra_dir = $canonicalize([dir_path] $home_dir/project/.build2);
$* -e -f ops -d $start_dir -h $home_dir -x $extra_dir/ >>/~%EOO%d
- %\.+/home/.build2/ops,home,false%
- %\.+/home/project/.build2/ops,project,false%
- %\.+/home/project/package/.build2/ops,package,true%
+ %\.+/home/.build2/ops,--home,false%
+ %\.+/home/project/.build2/ops,--project,false%
+ %\.+/home/project/package/.build2/ops,--package,true%
EOO
}
}
+
+: options-file
+:
+{
+ d = work/.build2;
+ mkdir -p work/.build2;
+
+ cat <<EOI >=$d/foo;
+ --foo
+ --options-file
+ bar
+ --fox
+ EOI
+
+ cat <<EOI >=$d/bar;
+ --bar
+ --options-file
+ baz
+ --box
+ EOI
+
+ cat <<EOI >=$d/baz;
+ --baz
+ EOI
+
+ $* -d $~/work -f foo >>EOO
+ --foo
+ --bar
+ --baz
+ --box
+ --fox
+ EOO
+}
diff --git a/tests/dir-iterator/driver.cxx b/tests/dir-iterator/driver.cxx
index b73e2e2..c9f7218 100644
--- a/tests/dir-iterator/driver.cxx
+++ b/tests/dir-iterator/driver.cxx
@@ -1,30 +1,17 @@
// file : tests/dir-iterator/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <cstddef> // size_t
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.path_io;
-import butl.utility;
-import butl.filesystem;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/path-io.mxx>
-#include <libbutl/utility.mxx> // operator<<(ostream, exception)
-#include <libbutl/filesystem.mxx>
-#endif
+
+#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
+#include <cassert>
using namespace std;
using namespace butl;
@@ -40,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.
@@ -52,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[])
{
@@ -59,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)
@@ -69,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;
}
@@ -79,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/entry-time/driver.cxx b/tests/entry-time/driver.cxx
index 1e64b0d..c29837d 100644
--- a/tests/entry-time/driver.cxx
+++ b/tests/entry-time/driver.cxx
@@ -1,31 +1,17 @@
// file : tests/entry-time/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <chrono>
#include <iostream>
-#endif
-// Other includes.
+#include <libbutl/path.hxx>
+#include <libbutl/optional.hxx>
+#include <libbutl/timestamp.hxx>
+#include <libbutl/filesystem.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.filesystem;
-
-import butl.optional; // @@ MOD Clang should not be necessary.
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/optional.mxx>
-#include <libbutl/timestamp.mxx>
-#include <libbutl/filesystem.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/fdstream/driver.cxx b/tests/fdstream/driver.cxx
index 3215e02..d039b00 100644
--- a/tests/fdstream/driver.cxx
+++ b/tests/fdstream/driver.cxx
@@ -5,9 +5,6 @@
# include <libbutl/win32-utility.hxx>
#endif
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#ifndef _WIN32
# include <chrono>
#endif
@@ -15,38 +12,28 @@
#include <ios>
#include <string>
#include <vector>
-#include <thread>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <utility> // move()
#include <iostream>
#include <exception>
-#endif
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#ifndef _WIN32
-import std.threading;
-#endif
-#endif
-import butl.path;
-import butl.process;
-import butl.fdstream;
-import butl.timestamp;
-import butl.filesystem;
+#ifndef LIBBUTL_MINGW_STDTHREAD
+# include <thread>
#else
-#include <libbutl/path.mxx>
-#include <libbutl/process.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/timestamp.mxx>
-#include <libbutl/filesystem.mxx>
+# include <libbutl/mingw-thread.hxx>
#endif
+#include <libbutl/path.hxx>
+#include <libbutl/process.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/timestamp.hxx>
+#include <libbutl/filesystem.hxx>
+
+#undef NDEBUG
+#include <cassert>
+
using namespace std;
using namespace butl;
@@ -55,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)
@@ -133,6 +122,12 @@ read_time (const path& p, const T& s, size_t n)
int
main (int argc, const char* argv[])
{
+#ifndef LIBBUTL_MINGW_STDTHREAD
+ using std::thread;
+#else
+ using mingw_stdthread::thread;
+#endif
+
bool v (false);
bool child (false);
@@ -470,12 +465,12 @@ main (int argc, const char* argv[])
//
{
string s;
- for (size_t i (0); i < 100; ++i)
+ for (size_t i (0); i < 300; ++i)
s += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n";
const char* args[] = {argv[0], "-c", nullptr};
- auto test_read = [&args, &s] ()
+ auto test_read = [&args, &s] (bool timeout)
{
try
{
@@ -491,11 +486,29 @@ main (int argc, const char* argv[])
string r;
char buf[300];
+ bool timedout (false);
while (!is.eof ())
{
- pair<size_t, size_t> nd (fdselect (rds, wds));
-
- assert (nd.first == 1 && nd.second == 0 && rds[0].ready);
+ if (timeout)
+ {
+ pair<size_t, size_t> nd (
+ fdselect (rds, wds, chrono::milliseconds (3)));
+
+ assert (((nd.first == 0 && !rds[0].ready) ||
+ (nd.first == 1 && rds[0].ready)) &&
+ nd.second == 0);
+
+ if (nd.first == 0)
+ {
+ timedout = true;
+ continue;
+ }
+ }
+ else
+ {
+ pair<size_t, size_t> nd (fdselect (rds, wds));
+ assert (nd.first == 1 && nd.second == 0 && rds[0].ready);
+ }
for (streamsize n; (n = is.readsome (buf, sizeof (buf))) != 0; )
r.append (buf, static_cast<size_t> (n));
@@ -504,6 +517,10 @@ main (int argc, const char* argv[])
is.close ();
assert (r == s);
+
+ // If timeout is used, then it most likely timedout, at least once.
+ //
+ assert (timedout == timeout);
}
catch (const ios::failure&)
{
@@ -517,7 +534,10 @@ main (int argc, const char* argv[])
vector<thread> threads;
for (size_t i (0); i < 10; ++i)
- threads.emplace_back (test_read);
+ {
+ threads.emplace_back ([&test_read] {test_read (true /* timeout */);});
+ threads.emplace_back ([&test_read] {test_read (false /* timeout */);});
+ }
// While the threads are busy, let's test the skip/non_blocking modes
// combination.
@@ -550,7 +570,85 @@ main (int argc, const char* argv[])
t.join ();
}
- // Test setting and getting position via the non-standard fdbuf interface.
+ // 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.
//
// Seek for read.
//
@@ -559,7 +657,7 @@ main (int argc, const char* argv[])
ifdstream is (f);
- fdbuf* buf (dynamic_cast<fdbuf*> (is.rdbuf ()));
+ fdstreambuf* buf (dynamic_cast<fdstreambuf*> (is.rdbuf ()));
assert (buf != nullptr);
char c;
@@ -602,7 +700,7 @@ main (int argc, const char* argv[])
{
ifdstream is (f, fdopen_mode::in | fdopen_mode::out);
- fdbuf* buf (dynamic_cast<fdbuf*> (is.rdbuf ()));
+ fdstreambuf* buf (dynamic_cast<fdstreambuf*> (is.rdbuf ()));
assert (buf != nullptr);
// Read till the end of the fragment.
@@ -660,7 +758,7 @@ main (int argc, const char* argv[])
assert (static_cast<streamoff> (is.tellg ()) == 8);
- const fdbuf* buf (dynamic_cast<const fdbuf*> (is.rdbuf ()));
+ const fdstreambuf* buf (dynamic_cast<const fdstreambuf*> (is.rdbuf ()));
assert (buf != nullptr && buf->tellg () == 8);
assert (from_stream (is) == "89");
@@ -679,7 +777,7 @@ main (int argc, const char* argv[])
assert (static_cast<streamoff> (os.tellp ()) == 2);
- const fdbuf* buf (dynamic_cast<const fdbuf*> (os.rdbuf ()));
+ const fdstreambuf* buf (dynamic_cast<const fdstreambuf*> (os.rdbuf ()));
assert (buf != nullptr && buf->tellp () == 2);
os.close ();
@@ -732,7 +830,7 @@ main (int argc, const char* argv[])
assert (static_cast<streamoff> (is.tellg ()) == 8);
- const fdbuf* buf (dynamic_cast<const fdbuf*> (is.rdbuf ()));
+ const fdstreambuf* buf (dynamic_cast<const fdstreambuf*> (is.rdbuf ()));
assert (buf != nullptr && buf->tellp () == 8);
assert (from_stream (is) == "6789");
@@ -867,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 231da4b..b659838 100644
--- a/tests/link/driver.cxx
+++ b/tests/link/driver.cxx
@@ -1,34 +1,19 @@
// file : tests/link/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <set>
#include <utility> // pair
#include <iostream> // cerr
#include <system_error>
-#endif
-// Other includes.
+#include <libbutl/path.hxx>
+#include <libbutl/path-io.hxx>
+#include <libbutl/utility.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/filesystem.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.path_io;
-import butl.utility;
-import butl.fdstream;
-import butl.filesystem;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/path-io.mxx>
-#include <libbutl/utility.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/filesystem.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -122,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;
@@ -321,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 &&
@@ -383,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)
{
@@ -408,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/lz4/buildfile b/tests/lz4/buildfile
new file mode 100644
index 0000000..1f9a244
--- /dev/null
+++ b/tests/lz4/buildfile
@@ -0,0 +1,6 @@
+# file : tests/lz4/buildfile
+# license : MIT; see accompanying LICENSE file
+
+import libs = libbutl%lib{butl}
+
+exe{driver}: {hxx cxx}{*} $libs testscript file{*.lz4}
diff --git a/tests/lz4/driver.cxx b/tests/lz4/driver.cxx
new file mode 100644
index 0000000..8139c34
--- /dev/null
+++ b/tests/lz4/driver.cxx
@@ -0,0 +1,46 @@
+// file : tests/lz4/driver.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#include <iostream>
+#include <exception>
+
+#include <libbutl/lz4.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/filesystem.hxx> // entry_stat, path_entry()
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+using namespace butl;
+
+// Usage: argv[0] [-c|-d] <input-file> <output-file>
+//
+int
+main (int argc, const char* argv[])
+try
+{
+ assert (argc == 4);
+
+ ifdstream ifs (argv[2], fdopen_mode::binary, ifdstream::badbit);
+ ofdstream ofs (argv[3], fdopen_mode::binary);
+
+ if (argv[1][1] == 'c')
+ {
+ lz4::compress (ofs, ifs,
+ 1 /* compression_level */,
+ 4 /* block_size_id (64KB) */,
+ fdstat (ifs.fd ()).size);
+ }
+ else
+ {
+ lz4::decompress (ofs, ifs);
+ }
+
+ ofs.close ();
+}
+catch (const std::exception& e)
+{
+ cerr << e.what () << endl;
+ return 1;
+}
diff --git a/tests/lz4/testscript b/tests/lz4/testscript
new file mode 100644
index 0000000..b064cff
--- /dev/null
+++ b/tests/lz4/testscript
@@ -0,0 +1,85 @@
+# file : tests/lz4/testscript
+# license : MIT; see accompanying LICENSE file
+
++touch zero
++cat <:'1' >=one
++cat <'The quick brown fox jumps over the lazy dog.' >=small
++cat <<EOI >=1kb
+The quick brown fox jumps over the lazy dog. The quick brown fox jumps over
+the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox
+jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
+quick brown fox jumps over the lazy dog. The quick brown fox jumps over the
+lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox
+jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
+quick brown fox jumps over the lazy dog. The quick brown fox jumps over the
+lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox
+jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
+quick brown fox jumps over the lazy dog. The quick brown fox jumps over the
+lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox
+jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
+quick brown fox jumps over the lazy dog. The quick brown fox jumps over the
+lazy dog. The quick brown fox jumps over th
+EOI
++cat 1kb 1kb 1kb 1kb 1kb 1kb 1kb 1kb >=8kb
++cat 8kb 8kb 8kb 8kb 8kb 8kb 8kb 8kb >=64kb
++cat 64kb 64kb 64kb 64kb 64kb 64kb 64kb 64kb >=512kb
+
+: rt-zero
+:
+$* -c ../zero zero.lz4 &zero.lz4;
+$* -d zero.lz4 zero &zero;
+diff ../zero zero
+
+: rt-one
+:
+$* -c ../one one.lz4 &one.lz4;
+$* -d one.lz4 one &one;
+diff ../one one
+
+: rt-small
+:
+$* -c ../small small.lz4 &small.lz4;
+$* -d small.lz4 small &small;
+diff ../small small
+
+: rt-1kb
+:
+$* -c ../1kb 1kb.lz4 &1kb.lz4;
+$* -d 1kb.lz4 1kb &1kb;
+diff ../1kb 1kb
+
+: rt-8kb
+:
+$* -c ../8kb 8kb.lz4 &8kb.lz4;
+$* -d 8kb.lz4 8kb &8kb;
+diff ../8kb 8kb
+
+: rt-64kb
+:
+$* -c ../64kb 64kb.lz4 &64kb.lz4;
+$* -d 64kb.lz4 64kb &64kb;
+diff ../64kb 64kb
+
+: rt-512kb
+:
+$* -c ../512kb 512kb.lz4 &512kb.lz4;
+$* -d 512kb.lz4 512kb &512kb;
+diff ../512kb 512kb
+
+: truncated-header6
+:
+$* -d $src_base/truncated-header6.lz4 out &out 2>>EOE !=0
+incomplete LZ4 frame header
+EOE
+
+: truncated-header12
+:
+$* -d $src_base/truncated-header12.lz4 out &out 2>>EOE !=0
+incomplete LZ4 frame header
+EOE
+
+: truncated-content
+:
+$* -d $src_base/truncated-content.lz4 out &out 2>>EOE !=0
+incomplete LZ4 compressed content
+EOE
diff --git a/tests/lz4/truncated-content.lz4 b/tests/lz4/truncated-content.lz4
new file mode 100644
index 0000000..2a9a39d
--- /dev/null
+++ b/tests/lz4/truncated-content.lz4
Binary files differ
diff --git a/tests/lz4/truncated-header12.lz4 b/tests/lz4/truncated-header12.lz4
new file mode 100644
index 0000000..101088e
--- /dev/null
+++ b/tests/lz4/truncated-header12.lz4
Binary files differ
diff --git a/tests/lz4/truncated-header6.lz4 b/tests/lz4/truncated-header6.lz4
new file mode 100644
index 0000000..a00e998
--- /dev/null
+++ b/tests/lz4/truncated-header6.lz4
@@ -0,0 +1 @@
+"Ml@ \ No newline at end of file
diff --git a/tests/manifest-parser/driver.cxx b/tests/manifest-parser/driver.cxx
index a34f2b7..56c614a 100644
--- a/tests/manifest-parser/driver.cxx
+++ b/tests/manifest-parser/driver.cxx
@@ -1,29 +1,17 @@
// file : tests/manifest-parser/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <vector>
#include <string>
#include <utility> // pair, move()
#include <sstream>
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.optional;
-import butl.manifest_parser;
-#else
-#include <libbutl/optional.mxx>
-#include <libbutl/manifest-parser.mxx>
-#endif
+
+#include <libbutl/optional.hxx>
+#include <libbutl/manifest-parser.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
@@ -176,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 == "");
}
{
@@ -191,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-rewriter/driver.cxx b/tests/manifest-rewriter/driver.cxx
index ec73d81..3b1dfe9 100644
--- a/tests/manifest-rewriter/driver.cxx
+++ b/tests/manifest-rewriter/driver.cxx
@@ -1,36 +1,21 @@
// file : tests/manifest-rewriter/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <vector>
#include <string>
#include <cstdint> // uint64_t
#include <utility> // move()
#include <iostream>
#include <exception>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.optional;
-import butl.fdstream;
-import butl.manifest_parser;
-import butl.manifest_rewriter;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/optional.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/manifest-parser.mxx>
-#include <libbutl/manifest-rewriter.mxx>
-#endif
+
+#include <libbutl/path.hxx>
+#include <libbutl/optional.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/manifest-parser.hxx>
+#include <libbutl/manifest-rewriter.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
@@ -82,17 +67,26 @@ namespace butl
{{"a", "xyz"}, edit_cmd {"x", "y", "c"}, {"e", "123"}}) ==
":1\na: xyz\nc:d\nx: y\ne: 123");
- assert (edit (":1\na: b", {{"a", "xy\nz"}}) == ":1\na: \\\nxy\nz\n\\");
+ assert (edit (":1\na: b", {{"a", "xy\nz"}}) == ":1\na:\\\nxy\nz\n\\");
+
+ assert (edit (":1\na:\\\nxy\nz\n\\\nb: c", {{"a", "ab\ncd\ne"}}) ==
+ ":1\na:\\\nab\ncd\ne\n\\\nb: c");
+
+ assert (edit (":1\na: \\\nxy\nz\n\\\nb: c", {{"a", "ab\ncd\ne"}}) ==
+ ":1\na:\\\nab\ncd\ne\n\\\nb: c");
+
+ assert (edit (":1\na:\n\\\nxy\nz\n\\\nb: c", {{"a", "ab\ncd\ne"}}) ==
+ ":1\na:\\\nab\ncd\ne\n\\\nb: c");
assert (edit (":1\n", {{"a", "b", ""}}) == ":1\na: b\n");
assert (edit (":1\n abc: b",
{{"abc", "xyz"}}) ==
- ":1\n abc: \\\nxyz\n\\");
+ ":1\n abc:\\\nxyz\n\\");
assert (edit (":1\n a\xD0\xB0g : b",
{{"a\xD0\xB0g", "xyz"}}) ==
- ":1\n a\xD0\xB0g : \\\nxyz\n\\");
+ ":1\n a\xD0\xB0g :\\\nxyz\n\\");
// Test editing of manifests that contains CR characters.
//
diff --git a/tests/manifest-roundtrip/buildfile b/tests/manifest-roundtrip/buildfile
index 8056f64..7ddcc1f 100644
--- a/tests/manifest-roundtrip/buildfile
+++ b/tests/manifest-roundtrip/buildfile
@@ -3,5 +3,4 @@
import libs = libbutl%lib{butl}
-exe{driver}: {hxx cxx}{*} $libs
-exe{driver}: manifest: test.roundtrip = true
+exe{driver}: {hxx cxx}{*} $libs testscript
diff --git a/tests/manifest-roundtrip/driver.cxx b/tests/manifest-roundtrip/driver.cxx
index 53b688e..c63a729 100644
--- a/tests/manifest-roundtrip/driver.cxx
+++ b/tests/manifest-roundtrip/driver.cxx
@@ -1,45 +1,60 @@
// file : tests/manifest-roundtrip/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.utility; // operator<<(ostream, exception)
-import butl.fdstream;
-import butl.manifest_parser;
-import butl.manifest_serializer;
-#else
-#include <libbutl/utility.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/manifest-parser.mxx>
-#include <libbutl/manifest-serializer.mxx>
-#endif
+
+#include <libbutl/utility.hxx> // operator<<(ostream, exception)
+#include <libbutl/fdstream.hxx>
+#include <libbutl/manifest-parser.hxx>
+#include <libbutl/manifest-serializer.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
+// Usage: argv[0] [-m]
+//
+// Round-trip a manifest reading it from stdin and printing to stdout.
+//
+// -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 ()
+main (int argc, const char* argv[])
try
{
+ bool multiline_v2 (false);
+ bool split (false);
+
+ for (int i (1); i != argc; ++i)
+ {
+ string v (argv[i]);
+
+ if (v == "-m")
+ multiline_v2 = true;
+ else if (v == "-s")
+ split = true;
+ }
+
// Read/write in binary mode.
//
stdin_fdmode (fdstream_mode::binary);
stdout_fdmode (fdstream_mode::binary);
manifest_parser p (cin, "stdin");
- manifest_serializer s (cout, "stdout");
+
+ manifest_serializer s (cout,
+ "stdout",
+ false /* long_lines */,
+ {} /* filter */,
+ multiline_v2);
for (bool eom (true), eos (false); !eos; )
{
@@ -53,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/manifest b/tests/manifest-roundtrip/manifest
deleted file mode 100644
index 23c2730..0000000
--- a/tests/manifest-roundtrip/manifest
+++ /dev/null
@@ -1,32 +0,0 @@
-: 1
-name: libbpkg
-version: 1.0.1
-summary: build2 package manager library
-license: MIT
-tags: c++, package, manager, bpkg
-description: A very very very very very very very very very very very very\
- very very very very very very very very very very very very very very very\
- very very long description.
-changes: \
-1.0.1
- - Fixed a very very very very very very very very very very very very very\
- very annoying bug.
-1.0.0
- - Firts public release
- - Lots of really cool features
-\
-url: http://www.codesynthesis.com/projects/libstudxml/
-email: build-users@codesynthesis.com; Public mailing list, posts by\
- non-members are allowed but moderated.
-package-email: boris@codesynthesis.com; Direct email to the author.
-depends: libbutl
-depends: * build2
-depends: ?* bpkg
-requires: ?* linux | windows
-requires: c++11
-:
-path: c:\windows\\
-path: \
-
-c:\windows\\
-\
diff --git a/tests/manifest-roundtrip/testscript b/tests/manifest-roundtrip/testscript
new file mode 100644
index 0000000..a228b0f
--- /dev/null
+++ b/tests/manifest-roundtrip/testscript
@@ -0,0 +1,118 @@
+# file : tests/manifest-roundtrip/testscript
+# license : MIT; see accompanying LICENSE file
+
+: basics
+:
+$* <<EOF >>EOF
+ : 1
+ name: libbpkg
+ version: 1.0.1
+ summary: build2 package manager library
+ license: MIT
+ tags: c++, package, manager, bpkg
+ description: A very very very very very very very very very very very very\
+ very very very very very very very very very very very very very very very\
+ very very long description.
+ changes:\
+ 1.0.1
+ - Fixed a very very very very very very very very very very very very very\
+ very annoying bug.
+ 1.0.0
+ - Firts public release
+ - Lots of really cool features
+ \
+ url: http://www.codesynthesis.com/projects/libstudxml/
+ email: build-users@codesynthesis.com; Public mailing list, posts by\
+ non-members are allowed but moderated.
+ package-email: boris@codesynthesis.com; Direct email to the author.
+ depends: libbutl
+ depends: * build2
+ depends: * bpkg
+ requires: * linux ? ($linux) | windows ? ($windows)
+ requires: c++11
+ :
+ path: c:\windows\\
+ path:\
+
+ c:\windows\\
+ \
+ EOF
+
+: multiline-v2
+:
+$* -m <<EOF >>EOF
+ : 1
+ name: libbpkg
+ version: 1.0.1
+ summary: build2 package manager library
+ license: MIT
+ tags: c++, package, manager, bpkg
+ description: A very very very very very very very very very very very very\
+ very very very very very very very very very very very very very very very\
+ very very long description.
+ changes:
+ \
+ 1.0.1
+ - Fixed a very very very very very very very very very very very very very\
+ very annoying bug.
+ 1.0.0
+ - Firts public release
+ - Lots of really cool features
+ \
+ url: http://www.codesynthesis.com/projects/libstudxml/
+ email: build-users@codesynthesis.com; Public mailing list, posts by\
+ non-members are allowed but moderated.
+ package-email: boris@codesynthesis.com; Direct email to the author.
+ depends: libbutl
+ depends: * build2
+ depends: * bpkg
+ requires: * linux ? ($linux) | windows ? ($windows)
+ requires: c++11
+ :
+ path: c:\windows\\
+ path:
+ \
+
+ 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 c818b4a..a003fa4 100644
--- a/tests/manifest-serializer/driver.cxx
+++ b/tests/manifest-serializer/driver.cxx
@@ -1,27 +1,16 @@
// file : tests/manifest-serializer/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <vector>
#include <string>
#include <utility> // pair
#include <sstream>
#include <iostream>
-#endif
-// Other includes.
+#include <libbutl/manifest-serializer.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.manifest_serializer;
-#else
-#include <libbutl/manifest-serializer.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -200,21 +189,21 @@ main ()
//
string n ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
assert (test ({{"","1"},{n,"x"},{"",""},{"",""}},
- ": 1\n" + n + ": \\\nx\n\\\n"));
+ ": 1\n" + n + ":\\\nx\n\\\n"));
assert (test ({{"","1"},{"a","\n"},{"",""},{"",""}},
- ": 1\na: \\\n\n\n\\\n"));
+ ": 1\na:\\\n\n\n\\\n"));
assert (test ({{"","1"},{"a","\n\n"},{"",""},{"",""}},
- ": 1\na: \\\n\n\n\n\\\n"));
+ ": 1\na:\\\n\n\n\n\\\n"));
assert (test ({{"","1"},{"a","\nx\n"},{"",""},{"",""}},
- ": 1\na: \\\n\nx\n\n\\\n"));
+ ": 1\na:\\\n\nx\n\n\\\n"));
assert (test ({{"","1"},{"a","x\ny\nz"},{"",""},{"",""}},
- ": 1\na: \\\nx\ny\nz\n\\\n"));
+ ": 1\na:\\\nx\ny\nz\n\\\n"));
assert (test ({{"","1"},{"a"," x"},{"",""},{"",""}},
- ": 1\na: \\\n x\n\\\n"));
+ ": 1\na:\\\n x\n\\\n"));
assert (test ({{"","1"},{"a","x "},{"",""},{"",""}},
- ": 1\na: \\\nx \n\\\n"));
+ ": 1\na:\\\nx \n\\\n"));
assert (test ({{"","1"},{"a"," x "},{"",""},{"",""}},
- ": 1\na: \\\n x \n\\\n"));
+ ": 1\na:\\\n x \n\\\n"));
// The long lines mode.
//
@@ -223,51 +212,76 @@ main ()
true /* long_lines */));
assert (test ({{"","1"},{"a", " abc\n" + l1 + "\ndef"},{"",""},{"",""}},
- ": 1\na: \\\n abc\n" + l1 + "\ndef\n\\\n",
+ ": 1\na:\\\n abc\n" + l1 + "\ndef\n\\\n",
true /* long_lines */));
assert (test ({{"","1"},{n,l1},{"",""},{"",""}},
- ": 1\n" + n + ": \\\n" + l1 + "\n\\\n",
+ ": 1\n" + n + ":\\\n" + l1 + "\n\\\n",
true /* long_lines */));
// Carriage return character.
//
assert (test ({{"","1"},{"a","x\ry"},{"",""},{"",""}},
- ": 1\na: \\\nx\ny\n\\\n"));
+ ": 1\na:\\\nx\ny\n\\\n"));
assert (test ({{"","1"},{"a","x\r"},{"",""},{"",""}},
- ": 1\na: \\\nx\n\n\\\n"));
+ ": 1\na:\\\nx\n\n\\\n"));
assert (test ({{"","1"},{"a","x\r\ny"},{"",""},{"",""}},
- ": 1\na: \\\nx\ny\n\\\n"));
+ ": 1\na:\\\nx\ny\n\\\n"));
assert (test ({{"","1"},{"a","x\r\n"},{"",""},{"",""}},
- ": 1\na: \\\nx\n\n\\\n"));
+ ": 1\na:\\\nx\n\n\\\n"));
// Extra three x's are for the leading name part ("a: ") that we
// don't have.
//
assert (test ({{"","1"},{"a","\nxxx" + l1},{"",""},{"",""}},
- ": 1\na: \\\n\nxxx" + e1 + "\n\\\n"));
+ ": 1\na:\\\n\nxxx" + e1 + "\n\\\n"));
assert (test ({{"","1"},{"a","\nxxx" + l2},{"",""},{"",""}},
- ": 1\na: \\\n\nxxx" + e2 + "\n\\\n"));
+ ": 1\na:\\\n\nxxx" + e2 + "\n\\\n"));
assert (test ({{"","1"},{"a","\nxxx" + l3},{"",""},{"",""}},
- ": 1\na: \\\n\nxxx" + e3 + "\n\\\n"));
+ ": 1\na:\\\n\nxxx" + e3 + "\n\\\n"));
assert (test ({{"","1"},{"a","\nxxx" + l4},{"",""},{"",""}},
- ": 1\na: \\\n\nxxx" + e4 + "\n\\\n"));
+ ": 1\na:\\\n\nxxx" + e4 + "\n\\\n"));
// Backslash escaping (simple and multi-line).
//
assert (test ({{"","1"},{"a","c:\\"},{"",""},{"",""}},
": 1\na: c:\\\\\n"));
assert (test ({{"","1"},{"a","c:\\\nd:\\"},{"",""},{"",""}},
- ": 1\na: \\\nc:\\\\\nd:\\\\\n\\\n"));
+ ": 1\na:\\\nc:\\\\\nd:\\\\\n\\\n"));
// 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/move-only-function/buildfile b/tests/move-only-function/buildfile
new file mode 100644
index 0000000..9012fd6
--- /dev/null
+++ b/tests/move-only-function/buildfile
@@ -0,0 +1,6 @@
+# file : tests/move-only-function/buildfile
+# license : MIT; see accompanying LICENSE file
+
+import libs = libbutl%lib{butl}
+
+exe{driver}: {hxx cxx}{*} $libs
diff --git a/tests/move-only-function/driver.cxx b/tests/move-only-function/driver.cxx
new file mode 100644
index 0000000..b94d674
--- /dev/null
+++ b/tests/move-only-function/driver.cxx
@@ -0,0 +1,149 @@
+// file : tests/move-only-function/driver.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#include <memory> // unique_ptr
+#include <utility> // move()
+
+#include <libbutl/move-only-function.hxx>
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+
+static int
+func (int v)
+{
+ return v + 1;
+}
+
+struct functor
+{
+ int i;
+
+ int
+ operator() (int v)
+ {
+ return v + i;
+ }
+};
+
+int
+main ()
+{
+ using butl::move_only_function_ex;
+
+ // Attempt to copy-construct or copy-assign should not compile.
+ // Also check non-collable.
+ //
+#if 0
+ {
+ using ft = move_only_function_ex<int (int)>;
+ ft f;
+ ft f2 (f);
+ ft f3; f3 = f;
+ ft f4 (123);
+ }
+#endif
+
+ // NULL.
+ //
+ {
+ using ft = move_only_function_ex<int (int)>;
+
+ ft f1;
+ assert (!f1);
+
+ ft f2 (nullptr);
+ assert (f2 == nullptr);
+
+ f1 = func;
+ assert (f1 != nullptr);
+ f1 = nullptr;
+ assert (!f1);
+
+ int (*f) (int) = nullptr;
+ f2 = f;
+ assert (!f2);
+ }
+
+ // Function.
+ //
+ {
+ using ft = move_only_function_ex<int (int)>;
+
+ ft f (func);
+
+ assert (f (1) == 2);
+
+ ft f1 (move (f));
+ assert (!f);
+ assert (f1 (1) == 2);
+
+ f = &func;
+
+ assert (f (1) == 2);
+
+ assert (f.target<int (*) (int)> () != nullptr);
+ assert (f1.target<int (*) (int)> () != nullptr);
+ }
+
+ // Functor.
+ //
+ {
+ using ft = move_only_function_ex<int (int)>;
+
+ ft f (functor {1});
+
+ assert (f (1) == 2);
+
+ ft f1 (move (f));
+ assert (!f);
+ assert (f1 (1) == 2);
+
+ f = functor {2};
+
+ assert (f (1) == 3);
+
+ assert (ft (functor {1}).target<functor> () != nullptr);
+ }
+
+ // Lambda.
+ //
+ {
+ using ft = move_only_function_ex<int (int)>;
+
+ ft f ([p = unique_ptr<int> (new int (1))] (int v)
+ {
+ return *p + v;
+ });
+
+ assert (f (1) == 2);
+
+ ft f1 (move (f));
+ assert (!f);
+ assert (f1 (1) == 2);
+
+ f = ([p = unique_ptr<int> (new int (2))] (int v)
+ {
+ return *p + v;
+ });
+
+ assert (f (1) == 3);
+ }
+
+ // Void result.
+ //
+ {
+ using ft = move_only_function_ex<void (int)>;
+
+ ft f ([] (int v)
+ {
+ assert (v == 1);
+ });
+
+ f (1);
+ ft f1 (move (f));
+ f1 (1);
+ }
+}
diff --git a/tests/mventry/driver.cxx b/tests/mventry/driver.cxx
index cb1c348..e895ad6 100644
--- a/tests/mventry/driver.cxx
+++ b/tests/mventry/driver.cxx
@@ -1,28 +1,15 @@
// file : tests/mventry/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <iostream>
#include <system_error>
-#endif
-// Other includes.
+#include <libbutl/path.hxx>
+#include <libbutl/utility.hxx> // operator<<(ostream, exception)
+#include <libbutl/filesystem.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.utility; // operator<<(ostream, exception)
-import butl.filesystem;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/utility.mxx>
-#include <libbutl/filesystem.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
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/openssl/driver.cxx b/tests/openssl/driver.cxx
index d245a3a..55f91dd 100644
--- a/tests/openssl/driver.cxx
+++ b/tests/openssl/driver.cxx
@@ -1,36 +1,18 @@
// file : tests/openssl/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <vector>
#include <iostream>
#include <iterator>
#include <system_error>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.utility; // operator<<(ostream, exception)
-import butl.openssl;
-import butl.process;
-import butl.fdstream; // nullfd
-
-import butl.optional; // @@ MOD Clang should not be necessary.
-import butl.small_vector; // @@ MOD Clang should not be necessary.
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/utility.mxx>
-#include <libbutl/openssl.mxx>
-#include <libbutl/fdstream.mxx>
-#endif
+
+#include <libbutl/path.hxx>
+#include <libbutl/utility.hxx> // operator<<(ostream, exception)
+#include <libbutl/openssl.hxx>
+#include <libbutl/fdstream.hxx> // nullfd
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -41,12 +23,28 @@ int
main (int, const char* argv[])
try
{
- openssl os (nullfd, path ("-"), 2, path ("openssl"), "rand", 128);
+ using butl::optional;
+
+ // Test openssl rand command.
+ //
+ {
+ openssl os (nullfd, path ("-"), 2, path ("openssl"), "rand", 128);
+
+ vector<char> r (os.in.read_binary ());
+ os.in.close ();
+
+ assert (os.wait () && r.size () == 128);
+ }
+
+ // Test openssl info retrieval.
+ //
+ {
+ optional<openssl_info> v (openssl::info (2, path ("openssl")));
- vector<char> r (os.in.read_binary ());
- os.in.close ();
+ assert (v);
+ }
- return os.wait () && r.size () == 128 ? 0 : 1;
+ return 0;
}
catch (const system_error& e)
{
diff --git a/tests/optional/driver.cxx b/tests/optional/driver.cxx
index 5d72f08..da09cf5 100644
--- a/tests/optional/driver.cxx
+++ b/tests/optional/driver.cxx
@@ -1,23 +1,13 @@
// file : tests/optional/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <vector>
#include <utility> // move()
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-#endif
-import butl.optional;
-#else
-#include <libbutl/optional.mxx>
-#endif
+
+#include <libbutl/optional.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
diff --git a/tests/pager/driver.cxx b/tests/pager/driver.cxx
index ca3c3b9..c807ed0 100644
--- a/tests/pager/driver.cxx
+++ b/tests/pager/driver.cxx
@@ -1,28 +1,17 @@
// file : tests/pager/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <ios> // ios_base::failure
#include <vector>
#include <string>
#include <utility> // move()
#include <sstream>
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.pager;
-#else
-#include <libbutl/pager.mxx>
-#endif
+
+#include <libbutl/pager.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/path-entry/driver.cxx b/tests/path-entry/driver.cxx
index 30aae92..d9ea2be 100644
--- a/tests/path-entry/driver.cxx
+++ b/tests/path-entry/driver.cxx
@@ -1,36 +1,20 @@
// file : tests/path-entry/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
#include <stdexcept> // invalid_argument
#include <system_error>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-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>
-#include <libbutl/filesystem.mxx>
-#endif
+
+#include <libbutl/path.hxx>
+#include <libbutl/path-io.hxx>
+#include <libbutl/utility.hxx> // operator<<(ostream, exception)
+#include <libbutl/optional.hxx>
+#include <libbutl/timestamp.hxx>
+#include <libbutl/filesystem.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
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/path/driver.cxx b/tests/path/driver.cxx
index b855e34..3124c13 100644
--- a/tests/path/driver.cxx
+++ b/tests/path/driver.cxx
@@ -1,27 +1,15 @@
// file : tests/path/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <sstream>
#include <iostream>
#include <type_traits>
-#endif
-// Other includes.
+#include <libbutl/path.hxx>
+//#include <libbutl/path-io.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-//import butl.path_io;
-#else
-#include <libbutl/path.mxx>
-//#include <libbutl/path-io.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
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/prefix-map/driver.cxx b/tests/prefix-map/driver.cxx
index e0da9ea..8ed35ea 100644
--- a/tests/prefix-map/driver.cxx
+++ b/tests/prefix-map/driver.cxx
@@ -1,24 +1,13 @@
// file : tests/prefix-map/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.prefix_map;
-#else
-#include <libbutl/prefix-map.mxx>
-#endif
+
+#include <libbutl/prefix-map.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/process-run/driver.cxx b/tests/process-run/driver.cxx
index 94b6e00..032f890 100644
--- a/tests/process-run/driver.cxx
+++ b/tests/process-run/driver.cxx
@@ -1,31 +1,16 @@
// file : tests/process-run/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.process;
-import butl.optional; // @@ MOD Clang shouldn't be needed.
-import butl.fdstream;
-import butl.small_vector;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/process.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/small-vector.mxx>
-#endif
+
+#include <libbutl/path.hxx>
+#include <libbutl/process.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/small-vector.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/process-term/buildfile b/tests/process-term/buildfile
new file mode 100644
index 0000000..e710179
--- /dev/null
+++ b/tests/process-term/buildfile
@@ -0,0 +1,6 @@
+# file : tests/process-term/buildfile
+# license : MIT; see accompanying LICENSE file
+
+import libs = libbutl%lib{butl}
+
+exe{driver}: {hxx cxx}{*} $libs testscript
diff --git a/tests/process-term/driver.cxx b/tests/process-term/driver.cxx
new file mode 100644
index 0000000..799757c
--- /dev/null
+++ b/tests/process-term/driver.cxx
@@ -0,0 +1,403 @@
+// file : tests/process-term/driver.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#ifndef _WIN32
+# include <time.h>
+# include <signal.h>
+# include <unistd.h>
+# include <sys/types.h>
+#else
+# include <libbutl/win32-utility.hxx>
+#endif
+
+#include <string>
+#include <cerrno> // ERANGE
+#include <utility> // move()
+#include <cstdlib> // atexit(), exit(), strtoull()
+#include <cstring> // memset()
+#include <cstdint> // uint64_t
+#include <iostream>
+#ifndef _WIN32
+# include <chrono>
+#endif
+
+#include <libbutl/process.hxx>
+#include <libbutl/optional.hxx>
+#include <libbutl/fdstream.hxx>
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+using namespace butl;
+
+void
+atexit_func ()
+{
+ cout << "exiting";
+}
+
+#ifndef _WIN32
+
+volatile sig_atomic_t term_sig = 0;
+
+static void
+term (int sig)
+{
+ term_sig = sig;
+}
+#endif
+
+// Usages:
+//
+// argv[0]
+// argv[0] -s <sec> [-t (ignore|exit|default)] [-e] [-c <num>]
+//
+// In the first form run some basic process termination tests, running its
+// child in the second form.
+//
+// In the second form optionally register the SIGTERM signal handler
+// (POSIX-only) and the atexit function, then sleep for the requested number
+// of seconds and exit with the specified status.
+//
+// -s <sec>
+// Sleep for the specified timeout.
+//
+// -t (ignore|exit|default)
+// Register the SIGTERM signal handler. If the signal is received than
+// either ignore it, interrupt the sleep and exit, or call the default
+// handler.
+//
+// -e
+// Register the function with atexit() that prints the 'exiting' string to
+// stdout.
+//
+// -c <num>
+// Exit with the specified status (zero by default).
+//
+int
+main (int argc, const char* argv[])
+{
+ using butl::optional;
+
+ auto num = [] (const string& s)
+ {
+ assert (!s.empty ());
+
+ char* e (nullptr);
+ errno = 0; // We must clear it according to POSIX.
+ uint64_t r (strtoull (s.c_str (), &e, 10)); // Can't throw.
+ assert (errno != ERANGE && e == s.c_str () + s.size ());
+
+ return r;
+ };
+
+ int ec (0);
+ optional<uint64_t> sec;
+
+#ifndef _WIN32
+ enum class sig_action
+ {
+ ignore,
+ exit,
+ default_
+ };
+
+ optional<sig_action> term_action;
+
+ struct sigaction def_handler;
+#endif
+
+ for (int i (1); i != argc; ++i)
+ {
+ string o (argv[i]);
+
+ if (o == "-s")
+ {
+ assert (++i != argc);
+ sec = num (argv[i]);
+ }
+ else if (o == "-c")
+ {
+ assert (++i != argc);
+ ec = static_cast<int> (num (argv[i]));
+ }
+ else if (o == "-e")
+ {
+ assert (atexit (atexit_func) == 0);
+ }
+ else if (o == "-t")
+ {
+ assert (++i != argc);
+
+#ifndef _WIN32
+ string v (argv[i]);
+
+ if (v == "ignore")
+ term_action = sig_action::ignore;
+ else if (v == "exit")
+ term_action = sig_action::exit;
+ else if (v == "default")
+ term_action = sig_action::default_;
+ else
+ assert (false);
+
+ struct sigaction action;
+ memset (&action, 0, sizeof (action));
+ action.sa_handler = term;
+ assert (sigaction (SIGTERM, &action, &def_handler) == 0);
+#endif
+ }
+ else
+ assert (false);
+ }
+
+#ifndef _WIN32
+ auto sleep = [&term_action, &def_handler] (uint64_t sec)
+ {
+ // Wait until timeout expires or SIGTERM is received and is not ignored.
+ //
+ for (timespec tm {static_cast<time_t> (sec), 0};
+ nanosleep (&tm, &tm) == -1; )
+ {
+ assert (term_action && errno == EINTR && term_sig == SIGTERM);
+
+ if (*term_action == sig_action::ignore)
+ continue;
+
+ if (*term_action == sig_action::default_)
+ {
+ assert (sigaction (term_sig, &def_handler, nullptr) == 0);
+ kill (getpid (), term_sig);
+ }
+
+ break;
+ }
+ };
+#else
+ auto sleep = [] (uint64_t sec)
+ {
+ Sleep (static_cast<DWORD> (sec) * 1000);
+ };
+#endif
+
+ // Child process.
+ //
+ if (sec)
+ {
+ if (*sec != 0)
+ sleep (*sec);
+
+ return ec;
+ }
+
+ // Main process.
+ //
+
+ // Return true if the child process has written the specified string to
+ // stdout, represented by the reading end of the specified pipe.
+ //
+ auto test_out = [] (fdpipe&& pipe, const char* out)
+ {
+ pipe.out.close ();
+
+ ifdstream is (move (pipe.in));
+ bool r (is.read_text () == out);
+ is.close ();
+ return r;
+ };
+
+#ifndef _WIN32
+ // Terminate a process with the default SIGTERM handler.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2, argv[0], "-s", 60, "-e"));
+
+ sleep (3); // Give the child some time to initialize.
+ p.term ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (!p.exit->normal ());
+ assert (p.exit->signal () == SIGTERM);
+ }
+
+ // Terminate a process that exits on SIGTERM. Make sure it exits normally
+ // and atexit function is called.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2,
+ argv[0], "-s", 60, "-t", "exit", "-e", "-c", 5));
+
+ sleep (3); // Give the child some time to initialize.
+ p.term ();
+
+ assert (test_out (move (pipe), "exiting"));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (p.exit->normal ());
+ assert (p.exit->code () == 5);
+ }
+
+ // Terminate a process that calls the default handler on SIGTERM.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (
+ process_start (0, pipe, 2,
+ argv[0], "-s", 60, "-t", "default", "-e", "-c", 5));
+
+ sleep (3); // Give the child some time to initialize.
+ p.term ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (!p.exit->normal ());
+ assert (p.exit->signal () == SIGTERM);
+ }
+
+ // Terminate and then kill still running process.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2,
+ argv[0], "-s", 60, "-t", "ignore", "-e"));
+
+ sleep (3); // Give the child some time to initialize.
+ p.term ();
+
+ assert (!p.timed_wait (chrono::seconds (1)));
+
+ p.kill ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (!p.exit->normal ());
+ assert (p.exit->signal () == SIGKILL);
+ }
+
+ // Terminate an already terminated process.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2, argv[0], "-s", 0, "-c", 5));
+
+ sleep (4); // Give the child some time to terminate.
+ p.term ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (p.exit->normal ());
+ assert (p.exit->code () == 5);
+ }
+
+ // Terminate a process being terminated.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2, argv[0], "-s", 60));
+
+ p.term ();
+ p.term ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (!p.exit->normal ());
+ }
+
+ // Kill a process being terminated.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2, argv[0], "-s", 60));
+
+ p.term ();
+ p.kill ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (!p.exit->normal ());
+ assert (p.exit->signal () == SIGTERM || p.exit->signal () == SIGKILL);
+ }
+
+ // Kill a process being killed.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2, argv[0], "-s", 60));
+
+ p.kill ();
+ p.kill ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (!p.exit->normal ());
+ }
+#endif
+
+ // Terminate and wait a process.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2, argv[0], "-s", 60, "-e"));
+
+ sleep (3); // Give the child some time to initialize.
+ p.term ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (!p.exit->normal ());
+ }
+
+ // Kill and wait a process.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2, argv[0], "-s", 60, "-e"));
+
+ sleep (3); // Give the child some time to initialize.
+ p.kill ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (!p.exit->normal ());
+ }
+
+ // Kill a terminated process.
+ //
+ {
+ fdpipe pipe (fdopen_pipe ());
+ process p (process_start (0, pipe, 2, argv[0], "-s", 0, "-c", 5));
+
+ sleep (4); // Give the child some time to terminate.
+ p.kill ();
+
+ assert (test_out (move (pipe), ""));
+
+ assert (!p.wait ());
+ assert (p.exit);
+ assert (p.exit->normal ());
+ assert (p.exit->code () == 5);
+ }
+}
diff --git a/tests/process-term/testscript b/tests/process-term/testscript
new file mode 100644
index 0000000..f61899c
--- /dev/null
+++ b/tests/process-term/testscript
@@ -0,0 +1,4 @@
+# file : tests/process-term/testscript
+# license : MIT; see accompanying LICENSE file
+
+$*
diff --git a/tests/process/driver.cxx b/tests/process/driver.cxx
index 3be4154..1ee5710 100644
--- a/tests/process/driver.cxx
+++ b/tests/process/driver.cxx
@@ -1,44 +1,29 @@
// file : tests/process/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <ios>
#include <string>
#include <vector>
+#include <chrono>
#include <sstream>
#include <iterator> // istreambuf_iterator, ostream_iterator
#include <algorithm> // copy()
#include <iostream>
-#endif
-// Other includes.
+#include <libbutl/path.hxx>
+#include <libbutl/utility.hxx> // setenv(), getenv()
+#include <libbutl/process.hxx>
+#include <libbutl/process-io.hxx>
+#include <libbutl/optional.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/timestamp.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.utility; // setenv(), getenv()
-import butl.process;
-import butl.optional;
-import butl.fdstream;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/utility.mxx>
-#include <libbutl/process.mxx>
-#include <libbutl/process-io.mxx>
-#include <libbutl/optional.mxx>
-#include <libbutl/fdstream.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
-static const char* envvars[] = {"ABC=1", "DEF", nullptr};
-
using cstrings = vector<const char*>;
bool
@@ -91,18 +76,16 @@ exec (const path& p,
if (bin)
args.push_back ("-b");
+ const char* evars[] = {
+ "PAR1", "PAR2=2P", "PAR6=66", "PAR7", // Override the process variables.
+ "THR1", "THR2=2T", // Override the thread variables.
+ "CHD1", // Unset a non-existing variable.
+ "CHD2=C2", // Add the new variable.
+ nullptr};
+
if (env)
- {
args.push_back ("-e");
- // Here we set the environment variables for the current process to make
- // sure that the child process will not see the variable that is requested
- // to be unset, and will see the other one unaffected.
- //
- setenv ("DEF", "2");
- setenv ("XYZ", "3");
- }
-
if (cwd != nullptr)
args.push_back (cwd);
@@ -120,7 +103,7 @@ exec (const path& p,
out ? -1 : -2,
err ? (out ? 1 : -1) : -2,
cwd,
- env ? envvars : nullptr);
+ env ? evars : nullptr);
try
{
@@ -154,18 +137,21 @@ exec (const path& p,
process pr3 (args.data (),
-1, -1, -2,
cwd,
- env ? envvars : nullptr);
+ env ? evars : nullptr);
process pr2 (args.data (),
pr, bin_mode (move (pr3.out_fd)).get (), -2,
cwd,
- env ? envvars : nullptr);
+ env ? evars : nullptr);
ifdstream is (bin_mode (move (pr3.in_ofd)));
o = is.read_binary ();
- r = pr2.wait () && r;
- r = pr3.wait () && r;
+ // While at it, make sure that the process::timed_wait() template
+ // function overloads can be properly instantiated/linked.
+ //
+ r = pr2.timed_wait (duration::max ()) && r;
+ r = pr3.timed_wait (chrono::milliseconds::max ()) && r;
}
else
{
@@ -323,12 +309,23 @@ main (int argc, const char* argv[])
if (env)
{
- // Check that the ABC variable is set, the DEF is unset and the XYZ is
- // left unchanged.
+ // Check that the variables are (un)set as expected.
//
- if (getenv ("ABC") != optional<string> ("1") ||
- getenv ("DEF") ||
- getenv ("XYZ") != optional<string> ("3"))
+ if (getenv ("PAR1") ||
+ getenv ("PAR2") != optional<string> ("2P") ||
+ getenv ("PAR3") != optional<string> ("P3") ||
+ getenv ("PAR4") ||
+ getenv ("PAR5") != optional<string> ("5P") ||
+ getenv ("PAR6") != optional<string> ("66") ||
+ getenv ("PAR7") ||
+
+ getenv ("THR1") ||
+ getenv ("THR2") != optional<string> ("2T") ||
+ getenv ("THR3") != optional<string> ("T3") ||
+ getenv ("THR4") ||
+
+ getenv ("CHD1") ||
+ getenv ("CHD2") != optional<string> ("C2"))
return 1;
}
@@ -358,6 +355,26 @@ main (int argc, const char* argv[])
return 0;
}
+ // Here we set the process and thread environment variables to make sure
+ // that the child process will not see the variables that are requested to
+ // be unset, will see change for the variables that are requested to be set,
+ // and will see the other ones unaffected.
+ //
+ setenv ("PAR1", "P1");
+ setenv ("PAR2", "P2");
+ setenv ("PAR3", "P3");
+ setenv ("PAR4", "P4");
+ setenv ("PAR5", "P5");
+ setenv ("PAR6", "P6");
+ setenv ("PAR7", "P7");
+
+ const char* tevars[] = {
+ "THR1=T1", "THR2=T2", "THR3=T3", "THR4",
+ "PAR4", "PAR5=5P", "PAR6", "PAR7=7P", // Override the process variables.
+ nullptr};
+
+ auto_thread_env ate (tevars);
+
dir_path owd (dir_path::current_directory ());
// Test processes created as "already terminated".
diff --git a/tests/progress/driver.cxx b/tests/progress/driver.cxx
index 2a0b647..f1a257c 100644
--- a/tests/progress/driver.cxx
+++ b/tests/progress/driver.cxx
@@ -8,38 +8,19 @@
# include <io.h> //_write()
#endif
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <cstddef> // size_t
#include <iostream>
#ifndef _WIN32
# include <thread> // this_thread::sleep_for()
#endif
-#endif
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#ifndef _WIN32
-import std.threading;
-#endif
-#endif
-import butl.process;
-import butl.fdstream;
-import butl.diagnostics;
+#include <libbutl/process.hxx>
+#include <libbutl/fdstream.hxx> // fdopen_null(), stderr_fd()
+#include <libbutl/diagnostics.hxx>
-import butl.optional; // @@ MOD Clang should not be necessary.
-import butl.small_vector; // @@ MOD Clang should not be necessary.
-#else
-#include <libbutl/process.mxx>
-#include <libbutl/fdstream.mxx> // fdopen_null(), stderr_fd()
-#include <libbutl/diagnostics.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/project-name/driver.cxx b/tests/project-name/driver.cxx
index 02b3ae3..ac1c898 100644
--- a/tests/project-name/driver.cxx
+++ b/tests/project-name/driver.cxx
@@ -1,28 +1,17 @@
// file : tests/project-name/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <ios> // ios::*bit
#include <string>
#include <iostream>
#include <stdexcept> // invalid_argument
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.utility; // operator<<(ostream,exception), eof(), *case()
-import butl.project_name;
-#else
-#include <libbutl/utility.mxx>
-#include <libbutl/project-name.mxx>
-#endif
+
+#include <libbutl/utility.hxx> // operator<<(ostream,exception), eof(),
+ // *case()
+#include <libbutl/project-name.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/regex/driver.cxx b/tests/regex/driver.cxx
index f78a100..f8363e1 100644
--- a/tests/regex/driver.cxx
+++ b/tests/regex/driver.cxx
@@ -1,33 +1,23 @@
// file : tests/regex/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
+#include <regex>
#include <string>
+#include <utility> // pair
#include <iostream>
+#include <stdexcept> // invalid_argument
#include <exception>
-#endif
-// Other includes.
+#include <libbutl/regex.hxx>
+#include <libbutl/utility.hxx> // operator<<(ostream, exception)
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-import std.regex; // @@ MOD TODO: shouldn't be necessary (re-export).
-#endif
-import butl.regex;
-import butl.utility; // operator<<(ostream, exception)
-#else
-#include <libbutl/regex.mxx>
-#include <libbutl/utility.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
-// Usage: argv[0] [-ffo] [-fnc] [-m] <string> <regex> <format>
+// Usage: argv[0] [-ffo] [-fnc] [-m] <string> "/<regex>/<format>/"
//
// Perform substitution of matched substrings with formatted replacement
// strings using regex_replace_*() functions. If the string matches the regex
@@ -66,11 +56,13 @@ try
break;
}
- assert (i + 3 == argc);
+ assert (i + 2 == argc);
+
+ string s (argv[i++]);
+ pair<regex, string> rf (regex_replace_parse (argv[i]));
- string s (argv[i++]);
- regex re (argv[i++]);
- string fmt (argv[i]);
+ const regex& re (rf.first);
+ const string& fmt (rf.second);
auto r (match
? regex_replace_match (s, re, fmt)
@@ -86,8 +78,13 @@ catch (const regex_error& e)
cerr << "invalid regex" << e << endl; // Print sanitized.
return 2;
}
-catch (const exception& e)
+catch (const invalid_argument& e)
{
cerr << e << endl;
return 2;
}
+catch (const exception&)
+{
+ assert (false);
+ return 2;
+}
diff --git a/tests/regex/testscript b/tests/regex/testscript
index fbee1d6..93ad4b6 100644
--- a/tests/regex/testscript
+++ b/tests/regex/testscript
@@ -4,38 +4,38 @@
: replace-search
:
{
- $* abcbd b x >axcxd : all
- $* -ffo abcbd b x >axcbd : first-only
- $* -fnc abcbd b x >xx : no-copy
+ $* abcbd /b/x/ >axcxd : all
+ $* -ffo abcbd /b/x/ >axcbd : first-only
+ $* -fnc abcbd /b/x/ >xx : no-copy
: ecma-escape
:
{
- $* xay a '$b' >'x$by' : none
- $* xay a '$' >'x$y' : none-term
- $* xay a '$$' >'x$y' : self
- $* xay a 'b$&c' >'xbacy' : match
- $* xay a 'b$`c' >'xbxcy' : match-precede
- $* xay a "b\\\$'c" >'xbycy' : match-follow
+ $* xay '/a/$b/' >'x$by' : none
+ $* xay '/a/$/' >'x$y' : none-term
+ $* xay '/a/$$/' >'x$y' : self
+ $* xay '/a/b$&c/' >'xbacy' : match
+ $* xay '/a/b$`c/' >'xbxcy' : match-precede
+ $* xay "/a/b\\\$'c/" >'xbycy' : match-follow
: capture
:
{
- $* abcdefghij '(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)' '$1$10' >aj : matched
- $* a '(a)|(b)' '$1$2$3' >a : unmatched
+ $* abcdefghij '/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)/$1$10/' >aj : matched
+ $* a '/(a)|(b)/$1$2$3/' >a : unmatched
}
}
: perl-escape
:
{
- $* xay a '\b' >'xby' : none
- $* xay a '\' >'xy' : none-term
- $* xay a '\\' >'x\y' : self
+ $* xay '/a/\b/' >'xby' : none
+ $* xay '/a/\/' >'xy' : none-term
+ $* xay '/a/\\/' >'x\y' : self
: newline
:
- $* xay a '\n' >>EOO
+ $* xay '/a/\n/' >>EOO
x
y
EOO
@@ -43,25 +43,25 @@
: capture
:
{
- $* abcdefghij '(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)' '\1\10' >aa0 : matched
- $* a '(a)|(b)' '\1\2\3' >a : unmatched
+ $* abcdefghij '/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)/\1\10/' >aa0 : matched
+ $* a '/(a)|(b)/\1\2\3/' >a : unmatched
}
: upper
:
{
- $* xay a '\U' >xy : none
- $* xay a '\Uvz' >xVZy : repl
- $* xay a '\Uv\Ez' >xVzy : end
- $* aa a 'v\Uz' >vZvZ : locality
- $* xay '(a)' '\U\1' >xAy : capt
- $* x-y '(a?)-' '\U\1z' >xZy : capt-empty
- $* xay a '\uvz' >xVzy : once
+ $* xay '/a/\U/' >xy : none
+ $* xay '/a/\Uvz/' >xVZy : repl
+ $* xay '/a/\Uv\Ez/' >xVzy : end
+ $* aa '/a/v\Uz/' >vZvZ : locality
+ $* xay '/(a)/\U\1/' >xAy : capt
+ $* x-y '/(a?)-/\U\1z/' >xZy : capt-empty
+ $* xay '/a/\uvz/' >xVzy : once
}
: lower
:
- $* xay a '\lVZ' >xvZy
+ $* xay '/a/\lVZ/' >xvZy
}
}
@@ -70,6 +70,19 @@
{
test.options += -m
- $* abc 'a(b)c' 'x\1y' >xby : match
- $* abcd 'a(b)c' 'x\1yd' == 1 : no-match
+ $* abc '/a(b)c/x\1y/' >xby : match
+ $* abcd '/a(b)c/x\1yd/' == 1 : no-match
+}
+
+: invalid-regex-fmt
+:
+{
+ test.arguments += '' # Note: we will fail before the matching.
+
+ $* '' 2> 'no leading delimiter' != 0 : no-leading-delim
+ $* '/a' 2> 'no delimiter after regex' != 0 : no-mid-delim
+ $* '//' 2> 'empty regex' != 0 : no-regex
+ $* '/a[b/c/' 2>~'/invalid regex.*/' != 0 : regex
+ $* '/a/b' 2> 'no delimiter after replacement' != 0 : no-trailing-delim
+ $* '/a/b/s' 2> 'junk after trailing delimiter' != 0 : junk
}
diff --git a/tests/semantic-version/driver.cxx b/tests/semantic-version/driver.cxx
index 032cb14..3c20a6c 100644
--- a/tests/semantic-version/driver.cxx
+++ b/tests/semantic-version/driver.cxx
@@ -1,23 +1,12 @@
// file : tests/semantic-version/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <iostream>
-#endif
-// Other includes.
+#include <libbutl/semantic-version.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.semantic_version;
-#else
-#include <libbutl/semantic-version.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -34,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 ());
@@ -57,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/sendmail/driver.cxx b/tests/sendmail/driver.cxx
index e73940b..3b97202 100644
--- a/tests/sendmail/driver.cxx
+++ b/tests/sendmail/driver.cxx
@@ -1,34 +1,16 @@
// file : tests/sendmail/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <iostream>
#include <system_error>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.process;
-import butl.utility; // operator<<(ostream, exception)
-import butl.sendmail;
-import butl.fdstream;
-
-import butl.optional; // @@ MOD Clang should not be necessary.
-import butl.small_vector; // @@ MOD Clang should not be necessary.
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/process.mxx>
-#include <libbutl/utility.mxx>
-#include <libbutl/sendmail.mxx>
-#endif
+
+#include <libbutl/path.hxx>
+#include <libbutl/process.hxx>
+#include <libbutl/utility.hxx> // operator<<(ostream, exception)
+#include <libbutl/sendmail.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/sha1/driver.cxx b/tests/sha1/driver.cxx
index 2b58113..1e8e254 100644
--- a/tests/sha1/driver.cxx
+++ b/tests/sha1/driver.cxx
@@ -1,29 +1,16 @@
// file : tests/sha1/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <cstddef> // size_t
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-#endif
-import butl.sha1;
-import butl.path;
-import butl.fdstream;
-import butl.filesystem;
-#else
-#include <libbutl/sha1.mxx>
-#include <libbutl/path.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/filesystem.mxx> // auto_rmfile
-#endif
+
+#include <libbutl/sha1.hxx>
+#include <libbutl/path.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/filesystem.hxx> // auto_rmfile
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/sha256/driver.cxx b/tests/sha256/driver.cxx
index 2946755..30dfa49 100644
--- a/tests/sha256/driver.cxx
+++ b/tests/sha256/driver.cxx
@@ -1,29 +1,16 @@
// file : tests/sha256/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <cstddef> // size_t
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-#endif
-import butl.path;
-import butl.sha256;
-import butl.fdstream;
-import butl.filesystem;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/sha256.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/filesystem.mxx> // auto_rmfile
-#endif
+
+#include <libbutl/path.hxx>
+#include <libbutl/sha256.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/filesystem.hxx> // auto_rmfile
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/small-forward-list/driver.cxx b/tests/small-forward-list/driver.cxx
index 670fff1..1cfea77 100644
--- a/tests/small-forward-list/driver.cxx
+++ b/tests/small-forward-list/driver.cxx
@@ -1,24 +1,13 @@
// file : tests/small-forward-list/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.small_forward_list;
-#else
-#include <libbutl/small-forward-list.mxx>
-#endif
+
+#include <libbutl/small-forward-list.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/small-list/driver.cxx b/tests/small-list/driver.cxx
index 9674402..8e2fb6e 100644
--- a/tests/small-list/driver.cxx
+++ b/tests/small-list/driver.cxx
@@ -1,24 +1,13 @@
// file : tests/small-list/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
-#endif
-// Other includes.
+#include <libbutl/small-list.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.small_list;
-#else
-#include <libbutl/small-list.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/small-vector/driver.cxx b/tests/small-vector/driver.cxx
index d79a03b..cc012fc 100644
--- a/tests/small-vector/driver.cxx
+++ b/tests/small-vector/driver.cxx
@@ -1,24 +1,13 @@
// file : tests/small-vector/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
-#endif
-// Other includes.
+#include <libbutl/small-vector.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.small_vector;
-#else
-#include <libbutl/small-vector.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -111,6 +100,7 @@ main ()
s1.emplace_back ("abc");
vector s2 (move (s1));
assert (s2[0] == "abc" && s2.capacity () == 2 && small (s2));
+ assert (s1.empty ()); // The source vector must be empty now.
}
{
diff --git a/tests/standard-version/driver.cxx b/tests/standard-version/driver.cxx
index 4b985e1..4bddf08 100644
--- a/tests/standard-version/driver.cxx
+++ b/tests/standard-version/driver.cxx
@@ -1,31 +1,18 @@
// file : tests/standard-version/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <ios> // ios::failbit, ios::badbit
#include <string>
#include <cstdint> // uint*_t
#include <iostream>
#include <stdexcept> // invalid_argument
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.utility; // operator<<(ostream,exception), eof()
-import butl.optional;
-import butl.standard_version;
-#else
-#include <libbutl/utility.mxx>
-#include <libbutl/optional.mxx>
-#include <libbutl/standard-version.mxx>
-#endif
+
+#include <libbutl/utility.hxx> // operator<<(ostream,exception), eof()
+#include <libbutl/optional.hxx>
+#include <libbutl/standard-version.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -96,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);
}
@@ -104,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/strcase/driver.cxx b/tests/strcase/driver.cxx
index f9ea3b6..8e964a6 100644
--- a/tests/strcase/driver.cxx
+++ b/tests/strcase/driver.cxx
@@ -1,22 +1,12 @@
// file : tests/strcase/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
-#endif
-// Other includes.
+#include <libbutl/utility.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-#endif
-import butl.utility;
-#else
-#include <libbutl/utility.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/string-parser/driver.cxx b/tests/string-parser/driver.cxx
index 4e4984e..8cba912 100644
--- a/tests/string-parser/driver.cxx
+++ b/tests/string-parser/driver.cxx
@@ -1,27 +1,15 @@
// file : tests/string-parser/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <vector>
#include <iostream>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.utility; // operator<<(ostream,exception)
-import butl.string_parser;
-#else
-#include <libbutl/utility.mxx>
-#include <libbutl/string-parser.mxx>
-#endif
+
+#include <libbutl/utility.hxx> // operator<<(ostream,exception)
+#include <libbutl/string-parser.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl::string_parser;
diff --git a/tests/tab-parser/driver.cxx b/tests/tab-parser/driver.cxx
index 5a527cf..99c19d9 100644
--- a/tests/tab-parser/driver.cxx
+++ b/tests/tab-parser/driver.cxx
@@ -1,26 +1,14 @@
// file : tests/tab-parser/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
-#endif
-// Other includes.
+#include <libbutl/utility.hxx> // operator<<(ostream,exception)
+#include <libbutl/tab-parser.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.utility; // operator<<(ostream,exception)
-import butl.tab_parser;
-#else
-#include <libbutl/utility.mxx>
-#include <libbutl/tab-parser.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/target-triplet/driver.cxx b/tests/target-triplet/driver.cxx
index 0bb305e..8c08a90 100644
--- a/tests/target-triplet/driver.cxx
+++ b/tests/target-triplet/driver.cxx
@@ -1,25 +1,14 @@
// file : tests/target-triplet/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <iostream>
#include <stdexcept> // invalid_argument
-#endif
-// Other includes.
+#include <libbutl/target-triplet.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.target_triplet;
-#else
-#include <libbutl/target-triplet.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -61,6 +50,14 @@ main ()
"arm-eabi",
"arm", "", "eabi", ""));
+ assert (test ("arm-unknown-none-eabi",
+ "arm-none-eabi",
+ "arm", "", "none-eabi", ""));
+
+ assert (test ("arm-none",
+ "arm-none",
+ "arm", "", "none", ""));
+
assert (test ("arm-none-linux-gnueabi",
"arm-linux-gnueabi",
"arm", "", "linux-gnueabi", "", "linux"));
@@ -77,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"));
@@ -85,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"));
@@ -93,15 +98,41 @@ main ()
"x86_64-netbsd",
"x86_64", "", "netbsd", "", "bsd"));
- // Removal of none-.
- //
- assert (test ("arm-none",
- "arm-none",
- "arm", "", "none", ""));
+ assert (test ("aarch64-unknown-nto-qnx7.0.0",
+ "aarch64-nto-qnx7.0.0",
+ "aarch64", "", "nto-qnx", "7.0.0", "other"));
- assert (test ("arm-unknown-none-eabi",
- "arm-eabi",
- "arm", "", "eabi", ""));
+ assert (test ("aarch64-nto-qnx7.0.0",
+ "aarch64-nto-qnx7.0.0",
+ "aarch64", "", "nto-qnx", "7.0.0", "other"));
+
+ assert (test ("wasm32-emscripten",
+ "wasm32-emscripten",
+ "wasm32", "", "emscripten", "", "other"));
+
+ assert (test ("arm64-apple-darwin20.1.0",
+ "aarch64-apple-darwin20.1.0",
+ "aarch64", "apple", "darwin", "20.1.0", "macos"));
+
+ assert (test ("arm64-apple-ios14.4",
+ "aarch64-apple-ios14.4",
+ "aarch64", "apple", "ios", "14.4", "ios"));
+
+ assert (test ("arm64-apple-ios",
+ "aarch64-apple-ios",
+ "aarch64", "apple", "ios", "", "ios"));
+
+ assert (test ("arm64-apple-ios14.4-simulator",
+ "aarch64-apple-ios14.4-simulator",
+ "aarch64", "apple", "ios-simulator", "14.4", "ios"));
+
+ assert (test ("arm64-apple-ios-simulator",
+ "aarch64-apple-ios-simulator",
+ "aarch64", "apple", "ios-simulator", "", "ios"));
+
+ assert (test ("x86_64-apple-ios14.4-macabi",
+ "x86_64-apple-ios14.4-macabi",
+ "x86_64", "apple", "ios-macabi", "14.4", "ios"));
// Version extraction.
//
diff --git a/tests/timestamp/driver.cxx b/tests/timestamp/driver.cxx
index 6283798..956b295 100644
--- a/tests/timestamp/driver.cxx
+++ b/tests/timestamp/driver.cxx
@@ -3,28 +3,17 @@
#include <time.h> // tzset() (POSIX), _tzset() (Windows)
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <chrono>
#include <locale>
#include <clocale>
#include <sstream>
#include <iomanip>
#include <system_error>
-#endif
-// Other includes.
+#include <libbutl/timestamp.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.timestamp;
-#else
-#include <libbutl/timestamp.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -189,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/url/driver.cxx b/tests/url/driver.cxx
index 5f787bd..869eed5 100644
--- a/tests/url/driver.cxx
+++ b/tests/url/driver.cxx
@@ -1,29 +1,17 @@
// file : tests/url/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
#include <utility> // move()
#include <iostream>
#include <iterator> // back_inserter
#include <stdexcept> // invalid_argument
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.url;
-import butl.utility; // operator<<(ostream, exception)
-#else
-#include <libbutl/url.mxx>
-#include <libbutl/utility.mxx>
-#endif
+
+#include <libbutl/url.hxx>
+#include <libbutl/utility.hxx> // operator<<(ostream, exception)
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -151,7 +139,7 @@ namespace butl
// Usages:
//
// argv[0]
-// argv[0] [-c|-s|-w] <url>
+// argv[0] [-c|-s|-w] [-n] <url>
//
// Perform some basic tests if no URL is provided. Otherwise round-trip the URL
// to STDOUT. URL must contain only ASCII characters. Exit with zero code on
@@ -159,7 +147,7 @@ namespace butl
// to STDERR.
//
// -c
-// Print the URL components one per line. Print the special '[null]' string
+// Print the URL components one per line. Print the special '<null>' string
// for an absent components. This is the default option if URL is provided.
//
// -s
@@ -169,6 +157,9 @@ namespace butl
// Same as above, but use the custom wstring-based url_traits
// implementation for the basic_url template.
//
+// -n
+// Normalize the URL.
+//
int
main (int argc, const char* argv[])
try
@@ -186,6 +177,8 @@ try
comp
} mode (print_mode::comp);
+ bool norm (false);
+
int i (1);
for (; i != argc; ++i)
{
@@ -196,6 +189,8 @@ try
mode = print_mode::wstr;
else if (o == "-c")
mode = print_mode::comp;
+ else if (o == "-n")
+ norm = true;
else
break; // End of options.
}
@@ -209,16 +204,18 @@ try
assert (u0.empty ());
wurl u1 (scheme::http,
- wurl_authority {wstring (), wurl_host (L"[123]"), 0},
+ wurl_authority {wstring (), wurl_host (L"[::123]"), 0},
wstring (L"login"),
wstring (L"q="),
wstring (L"f"));
+ u1.normalize ();
+
assert (!u1.empty ());
assert (u1 != u0);
wurl u2 (scheme::http,
- wurl_host (L"123", url_host_kind::ipv6),
+ wurl_host (L"::123", url_host_kind::ipv6),
wstring (L"login"),
wstring (L"q="),
wstring (L"f"));
@@ -226,16 +223,18 @@ try
assert (u2 == u1);
wurl u3 (scheme::http,
- wurl_host (L"123", url_host_kind::ipv6),
+ wurl_host (L"::123", url_host_kind::ipv6),
0,
wstring (L"login"),
wstring (L"q="),
wstring (L"f"));
+ u3.normalize ();
+
assert (u3 == u2);
wurl u4 (scheme::http,
- L"[123]",
+ L"[::123]",
wstring (L"login"),
wstring (L"q="),
wstring (L"f"));
@@ -243,7 +242,7 @@ try
assert (u4 == u3);
wurl u5 (scheme::http,
- L"[123]",
+ L"[::123]",
0,
wstring (L"login"),
wstring (L"q="),
@@ -323,16 +322,31 @@ try
{
case print_mode::str:
{
- cout << (*ua != '\0' ? url (ua) : url ()) << endl;
+ url u;
+ if (*ua != '\0')
+ u = url (ua);
+
+ if (norm)
+ u.normalize ();
+
+ cout << u << endl;
break;
}
case print_mode::wstr:
{
+ wurl u;
+
// Convert ASCII string to wstring.
//
wstring s (ua, ua + strlen (ua));
- wcout << (!s.empty () ? wurl (s) : wurl ()) << endl;
+ if (!s.empty ())
+ u = wurl (s);
+
+ if (norm)
+ u.normalize ();
+
+ wcout << u << endl;
break;
}
case print_mode::comp:
@@ -345,6 +359,9 @@ try
if (!s.empty ())
u = wurl (s);
+ if (norm)
+ u.normalize ();
+
if (!u.empty ())
{
wstring s;
@@ -357,7 +374,7 @@ try
false) << endl;
}
else
- wcout << L"[null]" << endl;
+ wcout << L"<null>" << endl;
if (u.authority)
{
@@ -368,11 +385,11 @@ try
<< " " << kinds[static_cast<size_t> (a.host.kind)] << endl;
}
else
- wcout << L"[null]" << endl;
+ wcout << L"<null>" << endl;
- wcout << (u.path ? *u.path : L"[null]") << endl
- << (u.query ? *u.query : L"[null]") << endl
- << (u.fragment ? *u.fragment : L"[null]") << endl;
+ wcout << (u.path ? *u.path : L"<null>") << endl
+ << (u.query ? *u.query : L"<null>") << endl
+ << (u.fragment ? *u.fragment : L"<null>") << endl;
break;
}
}
diff --git a/tests/url/testscript b/tests/url/testscript
index 94f63ff..52c5005 100644
--- a/tests/url/testscript
+++ b/tests/url/testscript
@@ -21,11 +21,11 @@ $*
: empty-url
:
$* '' >>EOO
- [null]
- [null]
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
+ <null>
+ <null>
EOO
: no-id
@@ -43,19 +43,19 @@ $*
$* 'http://build2.org' >>EOO
http
@build2.org:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
: deduced
:
$* 'c:/a' >>EOO
file
- [null]
+ <null>
c:/a
- [null]
- [null]
+ <null>
+ <null>
EOO
$* ':/a' 2>'no scheme' != 0 : none
@@ -70,10 +70,10 @@ $*
:
$* 'file:/tmp/a' >>EOO
file
- [null]
+ <null>
tmp/a
- [null]
- [null]
+ <null>
+ <null>
EOO
: empty
@@ -82,8 +82,8 @@ $*
file
@:0 name
tmp/a
- [null]
- [null]
+ <null>
+ <null>
EOO
: query
@@ -91,9 +91,9 @@ $*
$* 'http://localhost?q' >>EOO
http
@localhost:0 name
- [null]
+ <null>
q
- [null]
+ <null>
EOO
: fragment
@@ -101,8 +101,8 @@ $*
$* 'http://localhost#master' >>EOO
http
@localhost:0 name
- [null]
- [null]
+ <null>
+ <null>
master
EOO
@@ -111,9 +111,9 @@ $*
$* 'http://localhost' >>EOO
http
@localhost:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
: user
@@ -124,9 +124,9 @@ $*
$* 'http://admin@localhost' >>EOO
http
admin@localhost:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
: empty
@@ -134,9 +134,9 @@ $*
$* 'http://@localhost' >>EOO
http
@localhost:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
}
@@ -148,26 +148,97 @@ $*
{
: port
:
- $* 'http://[1:23]:443' >>EOO
+ $* 'http://[1:2:3:4:5:6:7:8]:443' >>EOO
http
- @1:23:443 ipv6
- [null]
- [null]
- [null]
+ @1:2:3:4:5:6:7:8:443 ipv6
+ <null>
+ <null>
+ <null>
EOO
: no-port
:
- $* 'http://[1:23]' >>EOO
+ $* 'http://[1:2:3:4:5:6:7:abcd]' >>EOO
http
- @1:23:0 ipv6
- [null]
- [null]
- [null]
+ @1:2:3:4:5:6:7:abcd:0 ipv6
+ <null>
+ <null>
+ <null>
+ EOO
+
+ : squashed2-begin
+ :
+ $* 'http://[::3:4:5:6:7:8]' >>EOO
+ http
+ @::3:4:5:6:7:8:0 ipv6
+ <null>
+ <null>
+ <null>
+ EOO
+
+ : squashed3-end
+ :
+ $* 'http://[1:2:3:4:5::]' >>EOO
+ http
+ @1:2:3:4:5:::0 ipv6
+ <null>
+ <null>
+ <null>
+ EOO
+
+ : squashed4-middle
+ :
+ $* 'http://[1:2::7:8]' >>EOO
+ http
+ @1:2::7:8:0 ipv6
+ <null>
+ <null>
+ <null>
+ EOO
+
+ : squashed-all
+ :
+ $* 'http://[::]' >>EOO
+ http
+ @:::0 ipv6
+ <null>
+ <null>
+ <null>
EOO
$* 'http://[123' 2>'invalid IPv6 address' != 0 : missed-bracket
$* 'http://[123] :80' 2>'invalid IPv6 address' != 0 : extra-char
+
+ $* 'http://[]' 2>'invalid IPv6 address' != 0 : empty
+ $* 'http://[1:2]' 2>'invalid IPv6 address' != 0 : too-short
+ $* 'http://[1:2:3:4:5:6:7:8:9]' 2>'invalid IPv6 address' != 0 : too-long1
+ $* 'http://[::2:3:4:5:6:7:8:9]' 2>'invalid IPv6 address' != 0 : too-long2
+ $* 'http://[::3:4::7:8:9]' 2>'invalid IPv6 address' != 0 : several-squashes
+ $* 'http://[1:2:3:4::6:7:8:9]' 2>'invalid IPv6 address' != 0 : squash-one-hextet
+ $* 'http://[12345:2:3:4:5:6:7:8:9]' 2>'invalid IPv6 address' != 0 : long-hextet
+ $* 'http://[123z:2:3:4:5:6:7:8:9]' 2>'invalid IPv6 address' != 0 : not-hex
+
+ : normalize
+ :
+ {
+ test.options += -n -s
+
+ $* 'http://[::01:0:002:00:0003]' >'http://[::1:0:2:0:3]' : strip-zeros
+ $* 'http://[::ABC]' >'http://[::abc]' : lower-case
+
+ $* 'http://[::]' >'http://[::]' : squash-all
+ $* 'http://[::1]' >'http://[::1]' : squash-left
+ $* 'http://[1::]' >'http://[1::]' : squash-right
+ $* 'http://[1::2]' >'http://[1::2]' : squash-middle
+
+ $* 'http://[1::0:2:0:0:3]' >'http://[1::2:0:0:3]' : squash-longest1
+ $* 'http://[::0:2:0:0:3]' >'http://[::2:0:0:3]' : squash-longest2
+ $* 'http://[::0:2:0:0:0:0]' >'http://[0:0:0:2::]' : squash-longest3
+ $* 'http://[0:0:1::2:3:4]' >'http://[::1:0:0:2:3:4]' : squash-first
+ $* 'http://[0:0:2:0:0:0::]' >'http://[0:0:2::]' : squash-trailing
+
+ $* 'http://[::1:2:3:4:5:6:7]' >'http://[0:1:2:3:4:5:6:7]' : expand-zero
+ }
}
: ipv4
@@ -178,9 +249,9 @@ $*
$* 'http://0.10.200.255' >>EOO
http
@0.10.200.255:0 ipv4
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
: long
@@ -188,9 +259,9 @@ $*
$* 'http://0.10.200.255.30' >>EOO
http
@0.10.200.255.30:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
: short
@@ -198,9 +269,9 @@ $*
$* 'http://0.10.200' >>EOO
http
@0.10.200:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
: missed
@@ -208,9 +279,9 @@ $*
$* 'http://0.10..200' >>EOO
http
@0.10..200:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
: out-of-range
@@ -218,10 +289,18 @@ $*
$* 'http://0.10.200.256' >>EOO
http
@0.10.200.256:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
+
+ : normalize
+ :
+ {
+ test.options += -n -s
+
+ $* 'http://0.010.000.00' >'http://0.10.0.0' : strip-zeros
+ }
}
: name
@@ -232,9 +311,9 @@ $*
$* 'https://www.b2.org' >>EOO
https
@www.b2.org:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
: encoded
@@ -245,9 +324,9 @@ $*
$* 'https://www.%62%32.org' >>EOO
https
@www.b2.org:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
$* 'https://www.%62%3.org' 2>'invalid URL-encoding' != 0 : short
@@ -256,6 +335,15 @@ $*
}
$* 'https://www.b|2.org' 2>'invalid host name' != 0 : invalid-char
+
+ : normalize
+ :
+ {
+ test.options += -n
+
+ $* -s 'http://Build2.org' >'http://build2.org' : lower-case-char
+ $* -w 'http://Build2.org' >'http://build2.org' : lower-case-wchar
+ }
}
$* 'http://admin@:80?q=' 2>'no host' != 0: no-host
@@ -269,9 +357,9 @@ $*
$* 'http://build2.org:443' >>EOO
http
@build2.org:443 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
$* 'http://build2.org:-433' 2>'invalid port' != 0 : invalid-char
@@ -288,9 +376,9 @@ $*
$* 'http://b2.org' >>EOO
http
@b2.org:0 name
- [null]
- [null]
- [null]
+ <null>
+ <null>
+ <null>
EOO
: empty
@@ -299,8 +387,8 @@ $*
http
@b2.org:0 name
- [null]
- [null]
+ <null>
+ <null>
EOO
: non-empty
@@ -309,8 +397,8 @@ $*
http
@b2.org:0 name
s/q
- [null]
- [null]
+ <null>
+ <null>
EOO
: encoded
@@ -319,8 +407,8 @@ $*
http
@b2.org:0 name
o/s
- [null]
- [null]
+ <null>
+ <null>
EOO
$* 'http:a/b/c' 2>'rootless path' != 0 : rootless-path
@@ -335,10 +423,10 @@ $*
:
$* 'pkcs11:token=sign;object=SIGN%20key' >>EOO
pkcs11
- [null]
+ <null>
token=sign;object=SIGN key
- [null]
- [null]
+ <null>
+ <null>
EOO
}
@@ -352,7 +440,7 @@ $*
@b2.org:0 name
a
x=foo&y=bar
- [null]
+ <null>
EOO
: fragment
@@ -372,8 +460,8 @@ $*
$* 'http://b2.org#foo' >>EOO
http
@b2.org:0 name
- [null]
- [null]
+ <null>
+ <null>
foo
EOO
}
@@ -389,10 +477,10 @@ $*
: host
:
{
- $* 'file:///a' >'file:///a' : empty
- $* 'http://1.1.1.1' >'http://1.1.1.1' : ipv4
- $* 'https://[1:2:3]' >'https://[1:2:3]' : ipv6
- $* 'file://a%d1%84' >'file://a%D1%84' : name
+ $* 'file:///a' >'file:///a' : empty
+ $* 'https://[1:2:3:4:5:6:7:8]' >'https://[1:2:3:4:5:6:7:8]' : ipv6
+ $* 'http://1.1.1.1' >'http://1.1.1.1' : ipv4
+ $* 'file://a%d1%84' >'file://a%D1%84' : name
}
$* 'http://admin@localhost' >'http://admin@localhost' : user
diff --git a/tests/utf8/driver.cxx b/tests/utf8/driver.cxx
index f35e65e..ccc2870 100644
--- a/tests/utf8/driver.cxx
+++ b/tests/utf8/driver.cxx
@@ -1,24 +1,13 @@
// file : tests/utf8/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <string>
-#endif
-
-// Other includes.
-
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-#endif
-import butl.utf8;
-import butl.utility;
-#else
-#include <libbutl/utf8.mxx>
-#include <libbutl/utility.mxx>
-#endif
+
+#include <libbutl/utf8.hxx>
+#include <libbutl/utility.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
diff --git a/tests/uuid/driver.cxx b/tests/uuid/driver.cxx
index d8dae23..63e5bc7 100644
--- a/tests/uuid/driver.cxx
+++ b/tests/uuid/driver.cxx
@@ -5,13 +5,15 @@
# include <rpc.h> // GUID
#endif
-#include <cassert>
#include <sstream>
#include <iostream>
#include <libbutl/uuid.hxx>
#include <libbutl/uuid-io.hxx>
+#undef NDEBUG
+#include <cassert>
+
using namespace std;
using namespace butl;
diff --git a/tests/wildcard/driver.cxx b/tests/wildcard/driver.cxx
index 00a317a..fee2748 100644
--- a/tests/wildcard/driver.cxx
+++ b/tests/wildcard/driver.cxx
@@ -1,36 +1,24 @@
// file : tests/wildcard/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#include <cassert>
-
-#ifndef __cpp_lib_modules_ts
#include <map>
#include <string>
#include <vector>
-#include <algorithm> // sort()
-#include <exception>
#include <iostream>
-#endif
+#include <algorithm> // sort()
+#include <exception>
+#include <functional>
+#include <system_error>
-// Other includes.
+#include <libbutl/path.hxx>
+#include <libbutl/path-io.hxx>
+#include <libbutl/utility.hxx> // operator<<(ostream, exception)
+#include <libbutl/optional.hxx>
+#include <libbutl/filesystem.hxx>
+#include <libbutl/path-pattern.hxx>
-#ifdef __cpp_modules_ts
-#ifdef __cpp_lib_modules_ts
-import std.core;
-import std.io;
-#endif
-import butl.path;
-import butl.utility; // operator<<(ostream, exception)
-import butl.optional;
-import butl.filesystem;
-import butl.path_pattern;
-#else
-#include <libbutl/path.mxx>
-#include <libbutl/utility.mxx>
-#include <libbutl/optional.mxx>
-#include <libbutl/filesystem.mxx>
-#include <libbutl/path-pattern.mxx>
-#endif
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -74,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.
//
@@ -108,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)
{
@@ -116,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.
}
@@ -181,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.
@@ -245,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
}
}