aboutsummaryrefslogtreecommitdiff
path: root/build2/test
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-02-15 03:55:15 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-03-02 14:03:34 +0200
commitb37f1aa6398065be806e6605a023189685669885 (patch)
treeb9b32091e3d70a31852302b24c99ecb62465464a /build2/test
parenta64b2ae2099346471ead988d5f2d383d55a9bf89 (diff)
Implement parallel match
Diffstat (limited to 'build2/test')
-rw-r--r--build2/test/rule6
-rw-r--r--build2/test/rule.cxx50
-rw-r--r--build2/test/script/parser.cxx37
-rw-r--r--build2/test/script/script.cxx10
4 files changed, 49 insertions, 54 deletions
diff --git a/build2/test/rule b/build2/test/rule
index da55173..7de2e24 100644
--- a/build2/test/rule
+++ b/build2/test/rule
@@ -21,7 +21,7 @@ namespace build2
{
public:
virtual match_result
- match (slock&, action, target&, const string&) const override;
+ match (action, target&, const string&) const override;
target_state
perform_script (action, const target&) const;
@@ -31,7 +31,7 @@ namespace build2
{
public:
virtual recipe
- apply (slock&, action, target&) const override;
+ apply (action, target&) const override;
static target_state
perform_test (action, const target&);
@@ -41,7 +41,7 @@ namespace build2
{
public:
virtual recipe
- apply (slock&, action, target&) const override;
+ apply (action, target&) const override;
target_state
perform_test (action, const target&) const;
diff --git a/build2/test/rule.cxx b/build2/test/rule.cxx
index eac9203..06ffc9f 100644
--- a/build2/test/rule.cxx
+++ b/build2/test/rule.cxx
@@ -35,7 +35,7 @@ namespace build2
"insufficient space");
match_result rule_common::
- match (slock& ml, action a, target& t, const string&) const
+ match (action a, target& t, const string&) const
{
// The (admittedly twisted) logic of this rule tries to achieve the
// following: If the target is testable, then we want both first update
@@ -63,7 +63,7 @@ namespace build2
// If we have any prerequisites of the test{} type, then this is the
// testscript case.
//
- for (prerequisite_member p: group_prerequisite_members (ml, a, t))
+ for (prerequisite_member p: group_prerequisite_members (a, t))
{
if (p.is_a<testscript> ())
{
@@ -155,7 +155,7 @@ namespace build2
}
recipe alias_rule::
- apply (slock& ml, action a, target& t) const
+ apply (action a, target& t) const
{
match_data md (move (t.data<match_data> ()));
t.clear_data (); // In case delegated-to rule also uses aux storage.
@@ -171,7 +171,7 @@ namespace build2
// standard alias rule.
//
if (a.operation () == update_id)
- return match_delegate (ml, a, t, *this).first;
+ return match_delegate (a, t, *this).first;
// For the test operation we have to implement our own search and match
// because we need to ignore prerequisites that are outside of our
@@ -181,7 +181,7 @@ namespace build2
// not ours seems right. Note that we still want to make sure they are
// up to date (via the above delegate) since our tests might use them.
//
- search_and_match_prerequisites (ml, a, t, t.root_scope ());
+ match_prerequisites (a, t, t.root_scope ());
// If not a test then also redirect to the alias rule.
//
@@ -191,7 +191,7 @@ namespace build2
}
recipe rule::
- apply (slock& ml, action a, target& t) const
+ apply (action a, target& t) const
{
tracer trace ("test::rule::apply");
@@ -208,11 +208,11 @@ namespace build2
if (md.script)
{
if (a.operation () == update_id)
- return match_delegate (ml, a, t, *this).first;
+ return match_delegate (a, t, *this).first;
// Collect all the testscript targets in prerequisite_targets.
//
- for (prerequisite_member p: group_prerequisite_members (ml, a, t))
+ for (prerequisite_member p: group_prerequisite_members (a, t))
{
if (p.is_a<testscript> ())
t.prerequisite_targets.push_back (&p.search ());
@@ -277,10 +277,10 @@ namespace build2
// @@ OUT: what if this is a @-qualified pair or names?
//
- target* it (in != nullptr ? &search (*in, bs) : nullptr);
- target* ot (on != nullptr
- ? in == on ? it : &search (*on, bs)
- : nullptr);
+ const target* it (in != nullptr ? &search (*in, bs) : nullptr);
+ const target* ot (on != nullptr
+ ? in == on ? it : &search (*on, bs)
+ : nullptr);
if (a.operation () == update_id)
{
@@ -289,26 +289,16 @@ namespace build2
//
if (it != nullptr)
{
- build2::match (ml, a, *it);
-
- if (it->unchanged ()) //@@ TM?
- {
- unmatch (a, *it);
+ if (build2::match (a, *it, unmatch::unchanged))
it = nullptr;
- }
}
if (ot != nullptr)
{
if (in != on)
{
- build2::match (ml, a, *ot);
-
- if (ot->unchanged ()) //@@ MT?
- {
- unmatch (a, *ot);
+ if (build2::match (a, *ot, unmatch::unchanged))
ot = nullptr;
- }
}
else
ot = it;
@@ -318,7 +308,7 @@ namespace build2
// been found if we signalled that we do not match from match()
// above.
//
- recipe d (match_delegate (ml, a, t, *this).first);
+ recipe d (match_delegate (a, t, *this).first);
// If we have no input/output that needs updating, then simply
// redirect to it.
@@ -636,8 +626,9 @@ namespace build2
if (pts.size () != 0 && pts[0] != nullptr)
{
const file& it (pts[0]->as<file> ());
- assert (!it.path ().empty ()); // Should have been assigned by update.
- args.push_back (it.path ().string ().c_str ());
+ const path& ip (it.path ());
+ assert (!ip.empty ()); // Should have been assigned by update.
+ args.push_back (ip.string ().c_str ());
}
// Maybe arguments then?
//
@@ -656,7 +647,8 @@ namespace build2
if (pts.size () != 0 && pts[1] != nullptr)
{
const file& ot (pts[1]->as<file> ());
- assert (!ot.path ().empty ()); // Should have been assigned by update.
+ const path& op (ot.path ());
+ assert (!op.empty ()); // Should have been assigned by update.
dpp = run_search (dp, true);
@@ -668,7 +660,7 @@ namespace build2
if (cast<target_triplet> (tt["test.target"]).class_ == "windows")
args.push_back ("--strip-trailing-cr");
- args.push_back (ot.path ().string ().c_str ());
+ args.push_back (op.string ().c_str ());
args.push_back ("-");
args.push_back (nullptr);
}
diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx
index 2ea42b5..4e6759f 100644
--- a/build2/test/script/parser.cxx
+++ b/build2/test/script/parser.cxx
@@ -6,8 +6,7 @@
#include <sstream>
-#include <build2/context> // keep_going
-#include <build2/scheduler>
+#include <build2/context> // sched, keep_going
#include <build2/test/script/lexer>
#include <build2/test/script/runner>
@@ -2838,16 +2837,14 @@ namespace build2
{
exec_lines (g->setup_.begin (), g->setup_.end (), li, false);
- scheduler::atomic_count task_count (0);
+ atomic_count task_count (0);
+ wait_guard wg (task_count);
// Start asynchronous execution of inner scopes keeping track of how
// many we have handled.
//
- auto i (g->scopes.begin ());
- for (auto e (g->scopes.end ()); i != e; ++i)
+ for (unique_ptr<scope>& chain: g->scopes)
{
- unique_ptr<scope>& chain (*i);
-
// Check if this scope is ignored (e.g., via config.test).
//
if (!runner_->test (*chain))
@@ -2932,12 +2929,18 @@ namespace build2
// exec_scope_body ();
// scope_ = os;
+ // Pass our diagnostics stack (this is safe since we are going
+ // to wait for completion before unwinding the diag stack).
+ //
// If the scope was executed synchronously, check the status and
// bail out if we weren't asked to keep going.
//
if (!sched.async (task_count,
- [] (scope& s, script& scr, runner& r)
+ [] (scope& s, script& scr, runner& r,
+ const diag_frame* ds)
{
+ diag_frame df (ds);
+
try
{
parser p;
@@ -2951,24 +2954,24 @@ namespace build2
},
ref (*chain),
ref (*script_),
- ref (*runner_)))
+ ref (*runner_),
+ diag_frame::stack))
{
+ // Bail out if the scope has failed and we weren't instructed
+ // to keep going.
+ //
if (chain->state == scope_state::failed && !keep_going)
- {
- ++i;
- break;
- }
+ throw failed ();
}
}
}
- sched.wait (task_count);
+
+ wg.wait ();
// Re-examine the scopes we have executed collecting their state.
//
- for (auto j (g->scopes.begin ()); j != i; ++j)
+ for (const unique_ptr<scope>& chain: g->scopes)
{
- const unique_ptr<scope>& chain (*j);
-
if (chain == nullptr)
continue;
diff --git a/build2/test/script/script.cxx b/build2/test/script/script.cxx
index 0586377..c2b13ca 100644
--- a/build2/test/script/script.cxx
+++ b/build2/test/script/script.cxx
@@ -567,17 +567,17 @@ namespace build2
//
if (t != nullptr)
{
- if (auto* p = t->is_a<path_target> ())
+ if (auto* pt = t->is_a<path_target> ())
{
// Do some sanity checks: the target better be up-to-date with
// an assigned path.
//
- if (p->path ().empty ())
- fail << "target " << *p << " specified in the test variable "
+ v = pt->path ();
+
+ if (v.empty ())
+ fail << "target " << *pt << " specified in the test variable "
<< "is out of date" <<
info << "consider specifying it as a prerequisite of " << tt;
-
- v = p->path ();
}
else if (t->is_a<alias> ())
v = path (t->dir);