From aa79de0b9a1e214e923139c25b02b5313a6305a9 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 24 Oct 2016 14:55:06 +0200 Subject: Implement creation/cleanup of testscript root working directory --- build2/test/rule.cxx | 97 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 18 deletions(-) (limited to 'build2/test/rule.cxx') diff --git a/build2/test/rule.cxx b/build2/test/rule.cxx index 188cc90..36b92f2 100644 --- a/build2/test/rule.cxx +++ b/build2/test/rule.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -354,33 +355,93 @@ namespace build2 target_state rule:: perform_script (action, target& t) { + // Figure out whether the testscript file is called 'testscript', in + // which case it should be the only one. + // + optional one; for (target* pt: t.prerequisite_targets) { // In case we are using the alias rule's list (see above). // - if (testscript* st = pt->is_a ()) + if (testscript* ts = pt->is_a ()) { - const path& sp (st->path ()); - assert (!sp.empty ()); // Should have been assigned by update. + bool r (ts->name == "testscript"); - if (verb) - text << "test " << t << " with " << *st; + if ((r && one) || (!r && one && *one)) + fail << "both 'testscript' and other names specified for " << t; - try - { - script::script s (t, *st); - script::concurrent_runner r; + one = r; + } + } - ifdstream ifs (sp); - script::parser p; - p.pre_parse (ifs, sp, s); - p.parse (sp, s, r); - } - catch (const io_error& e) - { - fail << "unable to read testscript " << sp << ": " << e.what (); - } + assert (one); // We should have a testscript or we wouldn't be here. + + // Calculate root working directory. It is in the out_base of the target + // and is called just test for dir{} targets and test- for + // other targets. + // + dir_path wd (t.out_dir ()); + + if (t.is_a ()) + wd /= "test"; + else + wd /= "test-" + t.name; + + // If this is a (potentially) multi-testscript test, then create (and + // cleanup) the root directory. If this is just 'testscript', then the + // root directory is used directly as test's working directory and it's + // the runner's responsibility to create and clean it up. + // + if (!*one) + { + if (!exists (wd)) + mkdir (wd, 2); + else if (!empty (wd)) + fail << "working directory " << wd << " is not empty at the " + << "beginning of the test"; + } + + // Run all the testscripts. + // + auto run = [&t, &wd] (testscript& ts) + { + if (verb) + text << "test " << t << " with " << ts; + + const path& sp (ts.path ()); + assert (!sp.empty ()); // Should have been assigned by update. + + try + { + script::script s (t, ts, wd); + script::concurrent_runner r; + + ifdstream ifs (sp); + script::parser p; + p.pre_parse (ifs, sp, s); + p.parse (sp, s, r); + } + catch (const io_error& e) + { + fail << "unable to read testscript " << sp << ": " << e.what (); } + }; + + for (target* pt: t.prerequisite_targets) + { + if (testscript* ts = pt->is_a ()) + run (*ts); + } + + // Cleanup. + // + if (!*one) + { + if (!empty (wd)) + fail << "working directory " << wd << " is not empty at the " + << "end of the test"; + + rmdir (wd, 2); } return target_state::changed; -- cgit v1.1