aboutsummaryrefslogtreecommitdiff
path: root/bbot/worker/worker.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bbot/worker/worker.cxx')
-rw-r--r--bbot/worker/worker.cxx145
1 files changed, 117 insertions, 28 deletions
diff --git a/bbot/worker/worker.cxx b/bbot/worker/worker.cxx
index 6a8eda0..fd6232c 100644
--- a/bbot/worker/worker.cxx
+++ b/bbot/worker/worker.cxx
@@ -10,10 +10,12 @@
#include <map>
#include <regex>
-#include <cstring> // strchr()
+#include <cstring> // strchr()
#include <sstream>
#include <iostream>
+#include <algorithm> // find()
+#include <libbutl/b.mxx>
#include <libbutl/pager.mxx>
#include <libbutl/filesystem.mxx>
#include <libbutl/string-parser.mxx>
@@ -210,6 +212,29 @@ static result_status
run_b (tracer& t,
string& log, const regexes& warn_detect,
const V& envvars,
+ const strings& buildspecs, A&&... a)
+{
+ string name ("b");
+ for (const string& s: buildspecs)
+ {
+ if (!name.empty ())
+ name += ' ';
+
+ name += s;
+ }
+
+ return run_cmd (t,
+ log, warn_detect,
+ name,
+ process_env ("b", envvars),
+ "-v", buildspecs, forward<A> (a)...);
+}
+
+template <typename V, typename... A>
+static result_status
+run_b (tracer& t,
+ string& log, const regexes& warn_detect,
+ const V& envvars,
const string& buildspec, A&&... a)
{
return run_cmd (t,
@@ -577,8 +602,33 @@ build (size_t argc, const char* argv[])
rm.status |= r.status;
}
- // Test.
+ // Query the package's build system information with `b info`.
+ //
+ dir_path prj_dir (tm.name.string () + '-' + tm.version.string ());
+ b_project_info prj;
+
+ // Note that `b info` diagnostics will not be copied into any of the build
+ // logs. This seems to be fine, as this is likely to be an infrastructural
+ // problem, given that the project distribution has been successfully
+ // created. It's actually not quite clear which log this diagnostics could
+ // go into.
+ //
+ try
+ {
+ prj = b_info (prj_dir, verb, trace);
+ }
+ catch (const b_error& e)
+ {
+ if (e.normal ())
+ throw failed (); // Assume the build2 process issued diagnostics.
+
+ fail << "unable to query project " << prj_dir << " info: " << e;
+ }
+
+ // Test the package if the test operation is supported by the project.
//
+ if (find (prj.operations.begin (), prj.operations.end (), "test") !=
+ prj.operations.end ())
{
operation_result& r (add_result ("test"));
@@ -587,8 +637,7 @@ build (size_t argc, const char* argv[])
// uncommon for them to expect that tests should run in the project root
// directory.
//
- dir_path d (tm.name.string () + '-' + tm.version.string ());
- dir_path rwd (change_wd (trace, &r.log, d));
+ dir_path rwd (change_wd (trace, &r.log, prj_dir));
// bpkg test <config-args> <env-config-args> <package-name>
//
@@ -624,9 +673,9 @@ build (size_t argc, const char* argv[])
//
// 1. Install the package.
//
- // 2. If the package project has the 'tests' subdirectory that is a
- // subproject, then configure, build and test it out of the source tree
- // against the installed package.
+ // 2. If the package has subprojects that support the test operation, then
+ // configure, build, and test them out of the source tree against the
+ // installed package.
//
// 3. Uninstall the package.
//
@@ -654,15 +703,40 @@ build (size_t argc, const char* argv[])
// Test installed.
//
- // The package tests subdirectory path (may not exist).
+ // Collect the "testable" subprojects.
//
- dir_path tests_dir (tm.name.string () + "-" + tm.version.string ());
- tests_dir /= "tests";
+ dir_paths subprj_dirs;
+ for (const b_project_info::subproject& sp: prj.subprojects)
+ {
+ // Retrieve the subproject information similar to how we've done it for
+ // the package.
+ //
+ dir_path sd (prj_dir / sp.path);
+
+ // Note that `b info` diagnostics will not be logged (see above for
+ // details).
+ //
+ try
+ {
+ b_project_info si (b_info (sd, verb, trace));
+
+ const strings& ops (si.operations);
+ if (find (ops.begin (), ops.end (), "test") != ops.end ())
+ subprj_dirs.push_back (sp.path);
+ }
+ catch (const b_error& e)
+ {
+ if (e.normal ())
+ throw failed (); // Assume the build2 process issued diagnostics.
- // We will consider the tests subdirectory to be a subproject if it
- // contains a build2 bootstrap file.
+ fail << "unable to query subproject " << sd << " info: " << e;
+ }
+ }
+
+ // If there are any "testable" subprojects, then configure them
+ // (sequentially) and test/build in parallel afterwards.
//
- if (file_exists (tests_dir / path ("build/bootstrap.build")))
+ if (!subprj_dirs.empty ())
{
operation_result& r (add_result ("test-installed"));
@@ -714,35 +788,50 @@ build (size_t argc, const char* argv[])
small_vector<string, 1> envvars {move (paths)};
- // b configure(<tests-dir>@<tests-out-dir>) <config-args>
- // <env-config-args>
- //
- // b.test-installed.configure
+ // Configure subprojects and create buildspecs for their testing.
//
- dir_path tests_out_dir (out_dir / dir_path ("tests"));
+ strings test_specs;
+ for (const dir_path& d: subprj_dirs)
+ {
+ // b configure(<subprj-src-dir>@<subprj-out-dir>) <config-args>
+ // <env-config-args>
+ //
+ // b.test-installed.configure
+ //
+ dir_path subprj_src_dir (build_dir / prj_dir / d);
+ dir_path subprj_out_dir (out_dir / d);
+
+ r.status |= run_b (
+ trace, r.log, wre,
+ envvars,
+ "configure(" +
+ subprj_src_dir.representation () + '@' +
+ subprj_out_dir.representation () + ")",
+ step_args (config_args, step_id::b_test_installed_configure),
+ step_args (env_args, step_id::b_test_installed_configure));
+
+ if (!r.status)
+ break;
- r.status |= run_b (
- trace, r.log, wre,
- envvars,
- "configure(" +
- (build_dir / tests_dir).representation () + '@' +
- tests_out_dir.representation () + ")",
- step_args (config_args, step_id::b_test_installed_configure),
- step_args (env_args, step_id::b_test_installed_configure));
+ test_specs.push_back (
+ "test(" + subprj_out_dir.representation () + ')');
+ }
if (!r.status)
break;
rm.status |= r.status;
- // b test(<tests-out-dir>) <config-args> <env-config-args>
+ // Build/test subprojects.
+ //
+ // b test(<subprj-out-dir>)... <config-args> <env-config-args>
//
// b.test-installed.test
//
r.status |= run_b (
trace, r.log, wre,
envvars,
- "test(" + tests_out_dir.representation () + ')',
+ test_specs,
step_args (config_args, step_id::b_test_installed_test),
step_args (env_args, step_id::b_test_installed_test));