aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-10-26 13:38:27 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-11-04 09:26:35 +0200
commit616690fd06d1c5d05de97b88119dd8d328522df0 (patch)
treea7e212f33d30efb598464571b23531621064e5c9
parent8fabd86e687ef9455f1b31abbe0b44876afdecab (diff)
Implement support for testscript scopes
-rw-r--r--build2/test/script/lexer.cxx2
-rw-r--r--build2/test/script/parser.cxx51
-rw-r--r--tests/test/script/integration/testscript28
-rw-r--r--unit-tests/test/script/lexer/first-token.test12
-rw-r--r--unit-tests/test/script/lexer/second-token.test2
-rw-r--r--unit-tests/test/script/parser/scope.test71
6 files changed, 133 insertions, 33 deletions
diff --git a/build2/test/script/lexer.cxx b/build2/test/script/lexer.cxx
index 7442973..98d52e7 100644
--- a/build2/test/script/lexer.cxx
+++ b/build2/test/script/lexer.cxx
@@ -331,7 +331,7 @@ namespace build2
}
}
- // Plus/minus and left/right curly braces
+ // Plus/minus and left/right curly braces.
//
if (m == lexer_mode::first_token)
{
diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx
index 85a77ce..25d3636 100644
--- a/build2/test/script/parser.cxx
+++ b/build2/test/script/parser.cxx
@@ -105,27 +105,45 @@ namespace build2
}
case type::lcbrace:
{
- // @@ Nested scope. Get newlines after open/close.
+ // Nested scope.
+ //
+ next (t, tt); // Get '{'.
+
+ if (next (t, tt) != type::newline)
+ fail (t) << "expected newline after '{'";
+
+ // Push group. Use line number as the scope id.
+ //
+ group* og (group_);
+ unique_ptr<group> p (
+ group_ = new group (to_string (ll.line), *og));
+ og->scopes.push_back (move (p));
+
+ group_->start_loc_ = ll;
+ token e (pre_parse_scope_body ());
+ group_->end_loc_ = get_location (e);
- assert (false);
+ // Pop group.
+ //
+ group_ = og;
- /*
- group_->start_loc_ = get_location (t);
+ if (e.type != type::rcbrace)
+ fail (e) << "expected '}' at the end of the scope";
// Check that we don't expect more lines.
//
if (lines_ != nullptr)
- fail (t) << "expected another line after semicolon";
+ fail (e) << "expected another line after semicolon";
- group_->end_loc_ = get_location (t);
- */
+ if (next (t, tt) != type::newline)
+ fail (t) << "expected newline after '}'";
continue;
}
case type::plus:
case type::minus:
{
- // This is a setup/teardown command.
+ // Setup/teardown command.
//
lt = (tt == type::plus ? line_type::setup : line_type::tdown);
@@ -136,7 +154,7 @@ namespace build2
}
default:
{
- // This is either a test command or a variable assignment.
+ // Either a test command or a variable assignment.
//
replay_save (); // Start saving tokens from the current one.
next (t, tt);
@@ -297,12 +315,14 @@ namespace build2
void parser::
parse_scope_body ()
{
- auto play = [this] (lines& ls) // Note: destructive to lines.
+ size_t li (0);
+
+ auto play = [&li, this] (lines& ls) // Note: destructive to lines.
{
token t;
type tt;
- for (size_t i (0), li (0), n (ls.size ()); i != n; ++i)
+ for (size_t i (0), n (ls.size ()); i != n; ++i)
{
line& l (ls[i]);
@@ -322,9 +342,14 @@ namespace build2
}
case line_type::setup:
case line_type::tdown:
+ {
+ parse_command_line (t, tt, l.type, ++li);
+ break;
+ }
case line_type::test:
{
// We use the 0 index to signal that this is the only command.
+ // Note that we only do this for test commands.
//
if (li == 0)
{
@@ -794,7 +819,7 @@ namespace build2
next (t, tt);
if (tt != type::word || t.quoted)
- fail (l) << "here-document end marker expected";
+ fail (l) << "expected here-document end marker";
hd.push_back (here_doc {nullptr, move (t.value), nn});
break;
@@ -1082,7 +1107,7 @@ namespace build2
catch (const exception&) {} // Fall through.
if (es > 255)
- fail (t) << "exit status expected instead of '" << ns << "'" <<
+ fail (t) << "expected exit status instead of '" << ns << "'" <<
info << "exit status is an unsigned integer less than 256";
}
diff --git a/tests/test/script/integration/testscript b/tests/test/script/integration/testscript
index e98a25c..a9c29a7 100644
--- a/tests/test/script/integration/testscript
+++ b/tests/test/script/integration/testscript
@@ -14,28 +14,32 @@ test.arguments = test
#EOI
+cp $src_base/bootstrap.build build/
-# @@ TODO: redo as scope.
-#
-touch testscript foo.test bar.test;
-$* <<EOI 2>>EOE != 0;
-./: test{testscript foo}
+{
+ +touch testscript foo.test bar.test
+
+ $* <<EOI 2>>EOE != 0
+./: test{../testscript ../foo}
EOI
error: both 'testscript' and other names specified for dir{./}
info: while testing dir{./}
EOE
-$* <<EOI 2>>EOE != 0;
-./: test{foo testscript}
+
+ $* <<EOI 2>>EOE != 0
+./: test{../foo ../testscript}
EOI
error: both 'testscript' and other names specified for dir{./}
info: while testing dir{./}
EOE
-$* <<EOI 2>>EOE;
-./: test{foo bar}
+
+ $* <<EOI 2>>EOE
+./: test{../foo ../bar}
EOI
-test dir{./} with test{foo}
-test dir{./} with test{bar}
+test dir{./} with ../test{foo}
+test dir{./} with ../test{bar}
EOE
-rm -f testscript foo.test bar.test
+
+ -rm -f testscript foo.test bar.test
+}
# work-dir-not-empty-begin
#
diff --git a/unit-tests/test/script/lexer/first-token.test b/unit-tests/test/script/lexer/first-token.test
index fb75c8b..a433362 100644
--- a/unit-tests/test/script/lexer/first-token.test
+++ b/unit-tests/test/script/lexer/first-token.test
@@ -2,11 +2,21 @@
#
test.arguments += first-token
-$* <";" >>EOO # semi-only
+$* <";" >>EOO # semi
;
<newline>
EOO
+$* <"{" >>EOO # lcbrace
+{
+<newline>
+EOO
+
+$* <"}" >>EOO # rcbrace
+}
+<newline>
+EOO
+
$* <"+foo" >>EOO # setup
+
'foo'
diff --git a/unit-tests/test/script/lexer/second-token.test b/unit-tests/test/script/lexer/second-token.test
index cc044dd..058dc65 100644
--- a/unit-tests/test/script/lexer/second-token.test
+++ b/unit-tests/test/script/lexer/second-token.test
@@ -2,7 +2,7 @@
#
test.arguments += second-token
-$* <";" >>EOO # semi-only
+$* <";" >>EOO # semi
;
<newline>
EOO
diff --git a/unit-tests/test/script/parser/scope.test b/unit-tests/test/script/parser/scope.test
index 4e358f3..593dbb2 100644
--- a/unit-tests/test/script/parser/scope.test
+++ b/unit-tests/test/script/parser/scope.test
@@ -12,7 +12,68 @@ wd += foo;
wd += 1;
$* foo.test <'cmd $~' >"cmd $wd" # wd
-$* -s <<EOI >>EOO # compound-2
+$* -s <<EOI >>EOO # group-empty
+{
+}
+EOI
+{
+ {
+ }
+}
+EOO
+
+$* -s <<EOI >>EOO # group
+{
+ cmd1
+ cmd2
+}
+EOI
+{
+ {
+ {
+ cmd1
+ }
+ {
+ cmd2
+ }
+ }
+}
+EOO
+
+$* <:"{x" 2>>EOE != 0 # expected-newline-lcbrace
+testscript:1:2: error: expected newline after '{'
+EOE
+
+$* <"{" 2>>EOE != 0 # expected-rcbrace
+testscript:2:1: error: expected '}' at the end of the scope
+EOE
+
+$* <<EOI 2>>EOE != 0 # expected-line-rcbrace
+{
+ cmd;
+}
+EOI
+testscript:3:1: error: expected another line after semicolon
+EOE
+
+$* <<:EOI 2>>EOE != 0 # expected-newline-rcbrace
+{
+}
+EOI
+testscript:2:2: error: expected newline after '}'
+EOE
+
+$* -s <<EOI >>EOO # test-1
+cmd1
+EOI
+{
+ {
+ cmd1
+ }
+}
+EOO
+
+$* -s <<EOI >>EOO # test-2
cmd1;
cmd2
EOI
@@ -24,7 +85,7 @@ EOI
}
EOO
-$* -s <<EOI >>EOO # compound-3
+$* -s <<EOI >>EOO # test-3
cmd1;
cmd2;
cmd3
@@ -38,7 +99,7 @@ EOI
}
EOO
-$* -s <<EOI >>EOO # compound-var
+$* -s <<EOI >>EOO # test-var
cmd1;
x = abc;
cmd2 \$x
@@ -51,7 +112,7 @@ EOI
}
EOO
-$* -s <<EOI >>EOO # compound-var-first
+$* -s <<EOI >>EOO # test-var-first
x = abc;
cmd \$x
EOI
@@ -83,7 +144,7 @@ testscript:3:1: error: test after teardown
testscript:2:1: info: last teardown line appears here
EOE
-$* <<EOI 2>>EOE != 0 # expected-line
+$* <<EOI 2>>EOE != 0 # expected-line-eof
cmd;
EOI
testscript:2:1: error: expected another line after semicolon