aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/test/script/parser.cxx23
-rw-r--r--build2/test/script/runner.cxx102
-rw-r--r--build2/test/script/script4
-rw-r--r--unit-tests/test/script/lexer/script-line.test2
4 files changed, 118 insertions, 13 deletions
diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx
index 626bc38..b670956 100644
--- a/build2/test/script/parser.cxx
+++ b/build2/test/script/parser.cxx
@@ -172,8 +172,7 @@ namespace build2
pending p (pending::program);
// Ordered sequence of here-document redirects that we can expect to
- // see after the command line. We temporarily store the end marker
- // as the redirect's value.
+ // see after the command line.
//
vector<reference_wrapper<redirect>> hd;
@@ -182,6 +181,12 @@ namespace build2
//
auto add_word = [&ts, &p, &hd, this] (string&& w, const location& l)
{
+ auto add_heredoc = [&w, &hd] (redirect& r)
+ {
+ hd.push_back (r);
+ r.end_marker = move (w);
+ };
+
switch (p)
{
case pending::none: ts.arguments.push_back (move (w)); break;
@@ -200,13 +205,11 @@ namespace build2
}
break;
}
- case pending::in_document: hd.push_back (ts.in); // Fall through.
- case pending::in_string: ts.in.value = move (w); break;
-
- case pending::out_document: hd.push_back (ts.out); // Fall through.
+ case pending::in_document: add_heredoc (ts.in); break;
+ case pending::in_string: ts.in.value = move (w); break;
+ case pending::out_document: add_heredoc (ts.out); break;
case pending::out_string: ts.out.value = move (w); break;
-
- case pending::err_document: hd.push_back (ts.err); // Fall through.
+ case pending::err_document: add_heredoc (ts.err); break;
case pending::err_string: ts.err.value = move (w); break;
}
@@ -541,9 +544,7 @@ namespace build2
mode (lexer_mode::here_line);
next (t, tt);
- // The end marker is temporarily stored as the redirect's value.
- //
- r.value = parse_here_document (t, tt, r.value);
+ r.value = parse_here_document (t, tt, r.end_marker);
expire_mode ();
}
diff --git a/build2/test/script/runner.cxx b/build2/test/script/runner.cxx
index a17b9bf..c4778bf 100644
--- a/build2/test/script/runner.cxx
+++ b/build2/test/script/runner.cxx
@@ -12,11 +12,111 @@ namespace build2
{
namespace script
{
+ static ostream&
+ operator<< (ostream& o, const test& t)
+ {
+ auto print_string = [&o] (const string& s)
+ {
+ // Quote if empty or contains spaces.
+ //
+ if (s.empty () || s.find (' ') != string::npos)
+ o << '"' << s << '"';
+ else
+ o << s;
+ };
+
+ auto print_redirect = [&o, &print_string] (const redirect& r,
+ const char* prefix)
+ {
+ o << ' ' << prefix;
+
+ size_t n (string::traits_type::length (prefix));
+ assert (n > 0);
+
+ switch (r.type)
+ {
+ case redirect_type::null: o << '!'; break;
+ case redirect_type::here_string: print_string (r.value); break;
+ case redirect_type::here_document:
+ {
+ o << prefix[n - 1]; // Add another '>' or '<'.
+ print_string (r.end_marker);
+ break;
+ }
+ default: assert (false);
+ }
+ };
+
+ auto print_heredoc = [&o] (const redirect& r)
+ {
+ // Here-document value always ends with a newline.
+ //
+ o << endl << r.value << r.end_marker;
+ };
+
+ print_string (t.program.string ());
+
+ for (const auto& a: t.arguments)
+ {
+ o << ' ';
+ print_string (a);
+ }
+
+ if (t.in.type != redirect_type::none)
+ print_redirect (t.in, "<");
+
+ if (t.out.type != redirect_type::none)
+ print_redirect (t.out, ">");
+
+ if (t.err.type != redirect_type::none)
+ print_redirect (t.err, "2>");
+
+ if (t.exit.comparison != exit_comparison::eq || t.exit.status != 0)
+ o << (t.exit.comparison == exit_comparison::eq ? " == " : " != ")
+ << (int)t.exit.status;
+
+ if (t.in.type == redirect_type::here_document)
+ print_heredoc (t.in);
+
+ if (t.out.type == redirect_type::here_document)
+ print_heredoc (t.out);
+
+ if (t.err.type == redirect_type::here_document)
+ print_heredoc (t.err);
+
+ return o;
+ }
+
+ static void
+ print_test (diag_record& r, const test& t)
+ {
+ // @@ No indentation performed for here-documents. If to fix then
+ // probably need to do on diag_record level in a way similar to
+ // butl::pager approach.
+ //
+ r << t;
+ }
+
+ static void
+ print_test (const test& t)
+ {
+ diag_record r (text);
+ print_test (r, t);
+ }
+
void concurrent_runner::
run (const test& t)
{
// @@ TODO
- text << "run " << t.program.string ();
+
+ // @@ When running multiple threads will need to synchronize printing
+ // the diagnostics so it don't overlap for concurrent tests.
+ // Alternatively we can not bother with that and expect a user to
+ // re-run test operation in the single-thread mode.
+ //
+
+ if (verb >= 3)
+ print_test (t);
}
}
}
diff --git a/build2/test/script/script b/build2/test/script/script
index 9fb2a28..8f918fc 100644
--- a/build2/test/script/script
+++ b/build2/test/script/script
@@ -32,6 +32,10 @@ namespace build2
{
redirect_type type = redirect_type::none;
string value;
+
+ // Meaningul for here-documents only. Used for diagnostics.
+ //
+ string end_marker;
};
struct command
diff --git a/unit-tests/test/script/lexer/script-line.test b/unit-tests/test/script/lexer/script-line.test
index ff67801..692161b 100644
--- a/unit-tests/test/script/lexer/script-line.test
+++ b/unit-tests/test/script/lexer/script-line.test
@@ -1,6 +1,6 @@
foo != 0
a=aaa
-foo bar <"bbb $a ccc" >ddd 2>>EOE
+foo bar <"bbb $a ccc" >ddd 2>>EOE == 2
eee
EOE
foo