diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-10-24 14:55:06 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-11-04 09:26:35 +0200 |
commit | aa79de0b9a1e214e923139c25b02b5313a6305a9 (patch) | |
tree | 3104cdb7f0d4008c443df43beaf70aebeb8e7ec4 | |
parent | 0f7ecf29943c9d8112fff923d93eeadb99a816f3 (diff) |
Implement creation/cleanup of testscript root working directory
-rw-r--r-- | build2/test/rule.cxx | 97 | ||||
-rw-r--r-- | build2/test/script/runner.cxx | 2 | ||||
-rw-r--r-- | build2/test/script/script | 4 | ||||
-rw-r--r-- | build2/test/script/script.cxx | 21 | ||||
-rw-r--r-- | unit-tests/test/script/parser/driver.cxx | 2 | ||||
-rw-r--r-- | unit-tests/test/script/parser/scope.test | 4 |
6 files changed, 94 insertions, 36 deletions
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 <build2/scope> #include <build2/target> #include <build2/algorithm> +#include <build2/filesystem> #include <build2/diagnostics> #include <build2/test/target> @@ -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<bool> 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<testscript> ()) + if (testscript* ts = pt->is_a<testscript> ()) { - 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-<target-name> for + // other targets. + // + dir_path wd (t.out_dir ()); + + if (t.is_a<dir> ()) + 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<testscript> ()) + 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; diff --git a/build2/test/script/runner.cxx b/build2/test/script/runner.cxx index 7377528..55c3ffe 100644 --- a/build2/test/script/runner.cxx +++ b/build2/test/script/runner.cxx @@ -254,7 +254,7 @@ namespace build2 path r (sp.wd_path / path (nm)); if (ci > 0) - r += "-" + to_string (ci); + r += "-" + to_string (ci + 1); // Start from first line. return r; }; diff --git a/build2/test/script/script b/build2/test/script/script index 44ec7c5..f1a3f50 100644 --- a/build2/test/script/script +++ b/build2/test/script/script @@ -217,7 +217,9 @@ namespace build2 class script: public script_base, public group { public: - script (target& test_target, testscript& script_target); + script (target& test_target, + testscript& script_target, + const dir_path& root_wd); public: target& test_target; // Target we are testing. diff --git a/build2/test/script/script.cxx b/build2/test/script/script.cxx index 6602518..4dd47c5 100644 --- a/build2/test/script/script.cxx +++ b/build2/test/script/script.cxx @@ -159,19 +159,14 @@ namespace build2 } script:: - script (target& tt, testscript& st) + script (target& tt, testscript& st, const dir_path& rwd) : group (script_id (st.path ())), test_target (tt), script_target (st) { // Set the script working dir ($~) to $out_base/test/<id> (id_path - // for root is just the id). + // for root is just the id which is empty if st is 'testscript'). // - { - auto& wd (const_cast<dir_path&> (wd_path)); - wd = tt.out_dir (); - wd /= "test"; - wd /= id_path.string (); - } + const_cast<dir_path&> (wd_path) = dir_path (rwd) /= id_path.string (); // Unless we have the test variable set on the test or script target, // set it at the script level to the test target's path. @@ -180,14 +175,14 @@ namespace build2 { value& v (assign (test_var)); - // If this is a path-based target, then we use the path. If this - // is a directory (alias) target, then we use the directory path. - // Otherwise, we leave it NULL expecting the testscript to set it - // to something appropriate, if used. + // If this is a path-based target, then we use the path. If this is + // an alias target (e.g., dir{}), then we use the directory path. + // Otherwise, we leave it NULL expecting the testscript to set it to + // something appropriate, if used. // if (auto* p = tt.is_a<path_target> ()) v = p->path (); - else if (tt.is_a<dir> ()) + else if (tt.is_a<alias> ()) v = path (tt.dir.string ()); // Strip trailing slash. } diff --git a/unit-tests/test/script/parser/driver.cxx b/unit-tests/test/script/parser/driver.cxx index 09fd6f5..4fd0489 100644 --- a/unit-tests/test/script/parser/driver.cxx +++ b/unit-tests/test/script/parser/driver.cxx @@ -120,7 +120,7 @@ namespace build2 // Parse and run. // - script s (tt, st); + script s (tt, st, dir_path (work) /= "test-driver"); print_runner r (scope); parser p; diff --git a/unit-tests/test/script/parser/scope.test b/unit-tests/test/script/parser/scope.test index 7749b3d..4e358f3 100644 --- a/unit-tests/test/script/parser/scope.test +++ b/unit-tests/test/script/parser/scope.test @@ -2,12 +2,12 @@ $* testscript <'cmd $@' >"cmd 1" # id-testscript $* foo.test <'cmd $@' >"cmd foo/1" # id wd = [dir_path] $~; -wd += test; +wd += test-driver; wd += 1; $* testscript <'cmd $~' >"cmd $wd" # wd-testscript wd = [dir_path] $~; -wd += test; +wd += test-driver; wd += foo; wd += 1; $* foo.test <'cmd $~' >"cmd $wd" # wd |