aboutsummaryrefslogtreecommitdiff
path: root/build2/test
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-10-24 18:00:05 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-11-04 09:26:35 +0200
commit79a83d6dd0f312a5e390f5627f68cc96c4427d33 (patch)
treef66a0a33ea9d18bf1e85d7c4503fc923028edc80 /build2/test
parent2c0a2b0d688b4450c72cde12ecedaa3fc3c9662a (diff)
Add support for setup/teardown commands
Diffstat (limited to 'build2/test')
-rw-r--r--build2/test/script/lexer3
-rw-r--r--build2/test/script/lexer.cxx57
-rw-r--r--build2/test/script/parser2
-rw-r--r--build2/test/script/parser.cxx64
-rw-r--r--build2/test/script/script2
-rw-r--r--build2/test/script/token3
-rw-r--r--build2/test/script/token.cxx3
7 files changed, 105 insertions, 29 deletions
diff --git a/build2/test/script/lexer b/build2/test/script/lexer
index 80e6036..53b88be 100644
--- a/build2/test/script/lexer
+++ b/build2/test/script/lexer
@@ -25,7 +25,8 @@ namespace build2
enum
{
script_line = base_type::value_next,
- assign_line, // Auto-expires at the end of the token.
+ first_token, // Auto-expires at the end of the token.
+ second_token, // Auto-expires at the end of the token.
variable_line, // Auto-expires at the end of the line.
command_line,
here_line
diff --git a/build2/test/script/lexer.cxx b/build2/test/script/lexer.cxx
index ea906a1..7ced2b9 100644
--- a/build2/test/script/lexer.cxx
+++ b/build2/test/script/lexer.cxx
@@ -30,14 +30,31 @@ namespace build2
s2 = " == ";
break;
}
- case lexer_mode::assign_line:
+ case lexer_mode::first_token:
{
- // As script_line but with variable assignments.
+ // First token on the script line. Like script_line but recognizes
+ // leading plus/minus and variable assignments as separators.
+ //
+ // Note that to recognize only leading plus/minus we shouldn't add
+ // them to the separator strings.
//
s1 = ";=+!|&<> $(#\t\n";
s2 = " == ";
break;
}
+ case lexer_mode::second_token:
+ {
+ // Second token on the script line. Like script_line but
+ // recognizes leading variable assignments.
+ //
+ // Note that to recognize only leading assignments we shouldn't
+ // add them to the separator strings (so this is identical to
+ // script_line).
+ //
+ s1 = ";=!|&<> $(#\t\n";
+ s2 = " == ";
+ break;
+ }
case lexer_mode::variable_line:
{
// Like value except we recognize ';' and don't recognize '{'.
@@ -87,7 +104,8 @@ namespace build2
switch (state_.top ().mode)
{
case lexer_mode::script_line:
- case lexer_mode::assign_line:
+ case lexer_mode::first_token:
+ case lexer_mode::second_token:
case lexer_mode::variable_line:
case lexer_mode::command_line:
case lexer_mode::here_line: r = next_line (); break;
@@ -116,13 +134,13 @@ namespace build2
if (eos (c))
return make_token (type::eos);
- state st (state_.top ()); // Make copy (see assign_line).
+ state st (state_.top ()); // Make copy (see first/second_token).
lexer_mode m (st.mode);
- // Expire the assign mode at the end of the token. Do it early in case
+ // Expire certain modes at the end of the token. Do it early in case
// we push any new mode (e.g., double quote).
//
- if (m == lexer_mode::assign_line)
+ if (m == lexer_mode::first_token || m == lexer_mode::second_token)
state_.pop ();
// NOTE: remember to update mode() if adding new special characters.
@@ -161,8 +179,9 @@ namespace build2
// Line separators.
//
- if (m == lexer_mode::script_line ||
- m == lexer_mode::assign_line ||
+ if (m == lexer_mode::script_line ||
+ m == lexer_mode::first_token ||
+ m == lexer_mode::second_token ||
m == lexer_mode::variable_line)
{
switch (c)
@@ -173,7 +192,9 @@ namespace build2
// Command line operator/separators.
//
- if (m == lexer_mode::script_line || m == lexer_mode::assign_line)
+ if (m == lexer_mode::script_line ||
+ m == lexer_mode::first_token ||
+ m == lexer_mode::second_token)
{
switch (c)
{
@@ -193,8 +214,9 @@ namespace build2
// Command operators/separators.
//
- if (m == lexer_mode::script_line ||
- m == lexer_mode::assign_line ||
+ if (m == lexer_mode::script_line ||
+ m == lexer_mode::first_token ||
+ m == lexer_mode::second_token ||
m == lexer_mode::command_line)
{
switch (c)
@@ -291,9 +313,20 @@ namespace build2
}
}
+ // Plus/minus.
+ //
+ if (m == lexer_mode::first_token)
+ {
+ switch (c)
+ {
+ case '+': return make_token (type::plus);
+ case '-': return make_token (type::minus);
+ }
+ }
+
// Variable assignment (=, +=, =+).
//
- if (m == lexer_mode::assign_line)
+ if (m == lexer_mode::second_token)
{
switch (c)
{
diff --git a/build2/test/script/parser b/build2/test/script/parser
index ef65c1a..2e8a9b1 100644
--- a/build2/test/script/parser
+++ b/build2/test/script/parser
@@ -64,7 +64,7 @@ namespace build2
parse_variable_line (token&, token_type&);
bool
- parse_test_line (token&, token_type&, size_t);
+ parse_command_line (token&, token_type&, size_t);
command_exit
parse_command_exit (token&, token_type&);
diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx
index 2e5e9df..f8b414f 100644
--- a/build2/test/script/parser.cxx
+++ b/build2/test/script/parser.cxx
@@ -72,10 +72,9 @@ namespace build2
//
replay_save ();
- // We need to start lexing each line in the assign mode in order to
- // recognize assignment operators as separators.
+ // Start lexing each line recognizing leading plus/minus.
//
- mode (lexer_mode::assign_line);
+ mode (lexer_mode::first_token);
next (t, tt);
if (group_->start_loc_.empty ())
@@ -111,11 +110,36 @@ namespace build2
// semicolon and we should add this one to the same place.
//
if (lines_ != nullptr)
+ {
+ switch (lt.first)
+ {
+ case line_type::setup: fail (ll) << "setup command in test";
+ case line_type::tdown: fail (ll) << "teardown command in test";
+ default: break;
+ }
+
ls = lines_;
+ }
else
{
switch (lt.first)
{
+ case line_type::setup:
+ {
+ if (!group_->scopes.empty ())
+ fail (ll) << "setup command after tests";
+
+ if (!group_->tdown_.empty ())
+ fail (ll) << "setup command after teardown";
+
+ ls = &group_->setup_;
+ break;
+ }
+ case line_type::tdown:
+ {
+ ls = &group_->tdown_;
+ break;
+ }
case line_type::variable:
{
// If there is a semicolon after the variable then we assume
@@ -142,10 +166,10 @@ namespace build2
// This will detect things like variable assignments between
// tests.
//
- // @@ Can the teardown line be from a different file?
- //
if (!group_->tdown_.empty ())
{
+ // @@ Can the teardown line be from a different file?
+ //
location tl (
get_location (
group_->tdown_.back ().tokens.front ().token));
@@ -249,11 +273,11 @@ namespace build2
//
if (tt == type::word && !t.quoted)
{
- // Switch recognition of variable assignments for one more token.
- // This is safe to do because we know we cannot be in the quoted
- // mode (since the current token is not quoted).
+ // Switch recognition of leading variable assignments for the next
+ // token. This is safe to do because we know we cannot be in the
+ // quoted mode (since the current token is not quoted).
//
- mode (lexer_mode::assign_line);
+ mode (lexer_mode::second_token);
type p (peek ());
if (p == type::assign || p == type::prepend || p == type::append)
@@ -263,7 +287,14 @@ namespace build2
}
}
- return make_pair (line_type::test, parse_test_line (t, tt, 0));
+ line_type lt (tt == type::plus ? line_type::setup :
+ tt == type::minus ? line_type::tdown :
+ line_type::test);
+
+ if (lt != line_type::test)
+ next (t, tt);
+
+ return make_pair (lt, parse_command_line (t, tt, 0));
}
void parser::
@@ -272,7 +303,10 @@ namespace build2
switch (lt)
{
case line_type::variable: parse_variable_line (t, tt); break;
- case line_type::test: parse_test_line (t, tt, li); break;
+
+ case line_type::setup:
+ case line_type::tdown: next (t, tt); // Skip plus/minus fallthrough.
+ case line_type::test: parse_command_line (t, tt, li); break;
}
}
@@ -363,7 +397,7 @@ namespace build2
}
bool parser::
- parse_test_line (token& t, type& tt, size_t li)
+ parse_command_line (token& t, type& tt, size_t li)
{
command c;
@@ -941,9 +975,11 @@ namespace build2
break;
}
- // Expand the line.
+ // Expand the line (can be blank).
//
- names ns (parse_names (t, tt, false, "here-document line", nullptr));
+ names ns (tt != type::newline
+ ? parse_names (t, tt, false, "here-document line", nullptr)
+ : names ());
if (!pre_parse_)
{
diff --git a/build2/test/script/script b/build2/test/script/script
index 8b6c3c0..2dbf7ce 100644
--- a/build2/test/script/script
+++ b/build2/test/script/script
@@ -26,7 +26,7 @@ namespace build2
// Pre-parse representation.
//
- enum class line_type {variable, test};
+ enum class line_type {variable, setup, tdown, test};
struct line
{
diff --git a/build2/test/script/token b/build2/test/script/token
index 1d4f2e4..f9352d2 100644
--- a/build2/test/script/token
+++ b/build2/test/script/token
@@ -26,6 +26,9 @@ namespace build2
semi = base_type::value_next, // ;
+ plus, // +
+ minus, // -
+
pipe, // |
clean, // &
log_and, // &&
diff --git a/build2/test/script/token.cxx b/build2/test/script/token.cxx
index 2e86e29..549fe13 100644
--- a/build2/test/script/token.cxx
+++ b/build2/test/script/token.cxx
@@ -23,6 +23,9 @@ namespace build2
{
case token_type::semi: os << q << ';' << q; break;
+ case token_type::plus: os << q << '+' << q; break;
+ case token_type::minus: os << q << '-' << q; break;
+
case token_type::pipe: os << q << '|' << q; break;
case token_type::clean: os << q << '&' << q; break;
case token_type::log_and: os << q << "&&" << q; break;