diff options
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | LICENSE | 2 | ||||
-rw-r--r-- | build/root.build | 9 | ||||
-rw-r--r-- | libbbot/build-target-config.cxx (renamed from libbbot/build-config.cxx) | 60 | ||||
-rw-r--r-- | libbbot/build-target-config.hxx (renamed from libbbot/build-config.hxx) | 29 | ||||
-rw-r--r-- | libbbot/manifest.cxx | 499 | ||||
-rw-r--r-- | libbbot/manifest.hxx | 241 | ||||
-rw-r--r-- | manifest | 12 | ||||
-rw-r--r-- | tests/build/root.build | 9 | ||||
-rw-r--r-- | tests/buildtab/driver.cxx | 12 | ||||
-rw-r--r-- | tests/buildtab/testscript | 22 | ||||
-rw-r--r-- | tests/manifest/driver.cxx | 10 | ||||
-rw-r--r-- | tests/manifest/machine-header.testscript | 18 | ||||
-rw-r--r-- | tests/manifest/result-request.testscript | 31 | ||||
-rw-r--r-- | tests/manifest/result.testscript | 31 | ||||
-rw-r--r-- | tests/manifest/task-request.testscript | 80 | ||||
-rw-r--r-- | tests/manifest/task-response.testscript | 59 | ||||
-rw-r--r-- | tests/manifest/task.testscript | 224 |
18 files changed, 1156 insertions, 198 deletions
@@ -5,10 +5,16 @@ *.d *.t *.i +*.i.* *.ii +*.ii.* *.o *.obj +*.gcm +*.pcm +*.ifc *.so +*.dylib *.dll *.a *.lib @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2014-2020 the build2 authors (see the AUTHORS file). +Copyright (c) 2014-2024 the build2 authors (see the AUTHORS file). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/build/root.build b/build/root.build index ad3f3a7..c9ab5dc 100644 --- a/build/root.build +++ b/build/root.build @@ -15,3 +15,12 @@ if ($cxx.target.system == 'win32-msvc') if ($cxx.class == 'msvc') cxx.coptions += /wd4251 /wd4275 /wd4800 +elif ($cxx.id == 'gcc') +{ + cxx.coptions += -Wno-maybe-uninitialized -Wno-free-nonheap-object # libbutl + + if ($cxx.version.major >= 13) + cxx.coptions += -Wno-dangling-reference +} +elif ($cxx.id.type == 'clang' && $cxx.version.major >= 15) + cxx.coptions += -Wno-unqualified-std-cast-call diff --git a/libbbot/build-config.cxx b/libbbot/build-target-config.cxx index ff365e3..9e04a17 100644 --- a/libbbot/build-config.cxx +++ b/libbbot/build-target-config.cxx @@ -1,7 +1,7 @@ -// file : libbbot/build-config.cxx -*- C++ -*- +// file : libbbot/build-target-config.cxx -*- C++ -*- // license : MIT; see accompanying LICENSE file -#include <libbbot/build-config.hxx> +#include <libbbot/build-target-config.hxx> #include <map> #include <string> @@ -9,10 +9,10 @@ #include <utility> // move(), make_pair() #include <stdexcept> // invalid_argument -#include <libbutl/path.mxx> -#include <libbutl/fdstream.mxx> -#include <libbutl/tab-parser.mxx> -#include <libbutl/string-parser.mxx> +#include <libbutl/path.hxx> +#include <libbutl/fdstream.hxx> +#include <libbutl/tab-parser.hxx> +#include <libbutl/string-parser.hxx> #include <libbpkg/manifest.hxx> // build_class_term::validate_name() @@ -23,10 +23,10 @@ using namespace butl; namespace bbot { - LIBBBOT_EXPORT build_configs + LIBBBOT_EXPORT build_target_configs parse_buildtab (istream& is, const string& name) { - build_configs r; + build_target_configs r; tab_parser parser (is, name); r.classes.push_back ("all"); @@ -56,33 +56,26 @@ namespace bbot d); }; - build_config config; + build_target_config config; config.machine_pattern = move (tl[i++].value); // If the machine pattern is a single dash character, then this is a // placeholder entry. The only thing we are interested about it is the // class inheritance information. Note that while all other information - // is discarded, the configuration name and target must be present (can - // also be dashes), so the classes field can be determined and parsed. + // is discarded, the target configuration name and target must be + // present (can also be dashes), so the classes field can be determined + // and parsed. // bool placeholder (config.machine_pattern == "-"); - // Configuration name, target[/environment] and classes fields are the - // required ones. + // Target configuration name, target[/environment] and classes fields + // are the required ones. // if (i == n) - bad_line ("no configuration name found"); + bad_line ("no target configuration name found"); config.name = move (tl[i].value); - // Make sure the name is unique. - // - for (const auto& c: r) - { - if (c.name == config.name) - bad_line ("duplicate configuration name"); - } - if (++i == n) bad_line ("no target found"); @@ -116,6 +109,14 @@ namespace bbot bad_line (e.what ()); } + // Make sure the name/target combination is unique. + // + for (const auto& c: r) + { + if (c.name == config.name && c.target == config.target) + bad_line ("duplicate target configuration name/target"); + } + if (++i == n) bad_line ("no classes found"); @@ -189,9 +190,9 @@ namespace bbot r.classes.push_back (c); } else if (j->second != base && !base.empty ()) - throw invalid_argument ("'" + c + "' new base '" + base + + throw invalid_argument ('\'' + c + "' new base '" + base + "' does not match existing '" + - j->second + "'"); + j->second + '\''); if (!placeholder) config.classes.emplace_back (move (c)); @@ -221,7 +222,7 @@ namespace bbot task_manifest::validate_regex (re); config.warning_regexes.emplace_back (move (re)); } - else // Configuration option or variable. + else // Target configuration option or variable. config.args.emplace_back (move (v)); } } @@ -230,13 +231,14 @@ namespace bbot bad_line (e.what ()); } - // Save the configuration. + // Save the target configuration. // r.emplace_back (move (config)); } // Erase entries for baseless classes (we were collecting them to make - // sure that the class inheritance is consistent across configurations). + // sure that the class inheritance is consistent across target + // configurations). // for (auto i (r.class_inheritance_map.begin ()); i != r.class_inheritance_map.end (); ) @@ -250,11 +252,11 @@ namespace bbot return r; } - build_configs + build_target_configs parse_buildtab (const path& p) { ifdstream ifs (p); - build_configs r (parse_buildtab (ifs, p.string ())); + build_target_configs r (parse_buildtab (ifs, p.string ())); ifs.close (); // Throws on failure. return r; diff --git a/libbbot/build-config.hxx b/libbbot/build-target-config.hxx index 3541388..27b555c 100644 --- a/libbbot/build-config.hxx +++ b/libbbot/build-target-config.hxx @@ -1,4 +1,4 @@ -// file : libbbot/build-config.hxx -*- C++ -*- +// file : libbbot/build-target-config.hxx -*- C++ -*- // license : MIT; see accompanying LICENSE file #ifndef LIBBBOT_BUILD_CONFIG_HXX @@ -9,20 +9,20 @@ #include <vector> #include <iosfwd> -#include <libbutl/path.mxx> -#include <libbutl/optional.mxx> -#include <libbutl/tab-parser.mxx> -#include <libbutl/target-triplet.mxx> +#include <libbutl/path.hxx> +#include <libbutl/optional.hxx> +#include <libbutl/tab-parser.hxx> +#include <libbutl/target-triplet.hxx> #include <libbbot/export.hxx> #include <libbbot/version.hxx> namespace bbot { - // Build configuration matching specific machine names. Used by bbot + // Build target configuration matching specific machine names. Used by bbot // controllers. // - struct build_config + struct build_target_config { std::string machine_pattern; // Machine name pattern. std::string name; // Configuration name. @@ -36,10 +36,10 @@ namespace bbot std::vector<std::string> warning_regexes; }; - struct build_configs: std::vector<build_config> + struct build_target_configs: std::vector<build_target_config> { - // List of all configuration class names. Starts with the all and default - // classes. The rest follows in the same order as in the buildtab. + // List of all target configuration class names. Starts with the all and + // default classes. The rest follows in the same order as in the buildtab. // std::vector<std::string> classes; @@ -53,14 +53,17 @@ namespace bbot // // buildtab consists of lines in the following format: // - // <machine-pattern> <config> <target>[/<environment>] <classes> [<config-arg>]* [<warning-regex>]* + // <machine-pattern> <target-config> <target>[/<environment>] <classes> [<tgt-config-arg>]* [<warning-regex>]* + // + // Note that each <target-config>/<target> pair is expected to be unique in + // the buildtab. // using butl::tab_parsing; - LIBBBOT_EXPORT build_configs + LIBBBOT_EXPORT build_target_configs parse_buildtab (std::istream&, const std::string& name); - LIBBBOT_EXPORT build_configs + LIBBBOT_EXPORT build_target_configs parse_buildtab (const butl::path&); } diff --git a/libbbot/manifest.cxx b/libbbot/manifest.cxx index c01a84b..45a4668 100644 --- a/libbbot/manifest.cxx +++ b/libbbot/manifest.cxx @@ -7,20 +7,23 @@ #include <vector> #include <string> #include <cctype> // isxdigit() +#include <limits> // numeric_limits #include <cassert> #include <sstream> #include <cstddef> // size_t #include <utility> // move() #include <cstdint> // uint64_t +#include <cstdlib> // strtoull() +#include <algorithm> // find_if() #include <stdexcept> // invalid_argument -#include <libbutl/regex.mxx> -#include <libbutl/base64.mxx> -#include <libbutl/utility.mxx> // digit() -#include <libbutl/tab-parser.mxx> -#include <libbutl/string-parser.mxx> -#include <libbutl/manifest-parser.mxx> -#include <libbutl/manifest-serializer.mxx> +#include <libbutl/regex.hxx> +#include <libbutl/base64.hxx> +#include <libbutl/utility.hxx> // digit() +#include <libbutl/tab-parser.hxx> +#include <libbutl/string-parser.hxx> +#include <libbutl/manifest-parser.hxx> +#include <libbutl/manifest-serializer.hxx> using namespace std; using namespace butl; @@ -36,6 +39,29 @@ namespace bbot using butl::optional; + // machine_role + // + string + to_string (machine_role r) + { + switch (r) + { + case machine_role::build: return "build"; + case machine_role::auxiliary: return "auxiliary"; + } + + assert (false); + return string (); + } + + machine_role + to_machine_role (const string& s) + { + if (s == "build") return machine_role::build; + else if (s == "auxiliary") return machine_role::auxiliary; + else throw invalid_argument ("invalid machine role '" + s + '\''); + } + // result_status // string @@ -43,11 +69,13 @@ namespace bbot { switch (s) { - case result_status::success: return "success"; - case result_status::warning: return "warning"; - case result_status::error: return "error"; - case result_status::abort: return "abort"; - case result_status::abnormal: return "abnormal"; + case result_status::skip: return "skip"; + case result_status::success: return "success"; + case result_status::warning: return "warning"; + case result_status::error: return "error"; + case result_status::abort: return "abort"; + case result_status::abnormal: return "abnormal"; + case result_status::interrupt: return "interrupt"; } assert (false); @@ -57,12 +85,39 @@ namespace bbot result_status to_result_status (const string& s) { - if (s == "success") return result_status::success; - else if (s == "warning") return result_status::warning; - else if (s == "error") return result_status::error; - else if (s == "abort") return result_status::abort; - else if (s == "abnormal") return result_status::abnormal; - else throw invalid_argument ("invalid result status '" + s + "'"); + if (s == "skip") return result_status::skip; + else if (s == "success") return result_status::success; + else if (s == "warning") return result_status::warning; + else if (s == "error") return result_status::error; + else if (s == "abort") return result_status::abort; + else if (s == "abnormal") return result_status::abnormal; + else if (s == "interrupt") return result_status::interrupt; + else throw invalid_argument ("invalid result status '" + s + '\''); + } + + // interactive_mode + // + string + to_string (interactive_mode m) + { + switch (m) + { + case interactive_mode::false_: return "false"; + case interactive_mode::true_: return "true"; + case interactive_mode::both: return "both"; + } + + assert (false); + return string (); + } + + interactive_mode + to_interactive_mode (const string& s) + { + if (s == "false") return interactive_mode::false_; + else if (s == "true") return interactive_mode::true_; + else if (s == "both") return interactive_mode::both; + else throw invalid_argument ("invalid interactive mode '" + s + '\''); } // Utility functions @@ -104,6 +159,29 @@ namespace bbot return true; } + // Return nullopt if the string is not a valid 64-bit unsigned integer. + // + static optional<uint64_t> + parse_uint64 (const string& s) + { + if (!s.empty () && s[0] != '-' && s[0] != '+') // strtoull() allows these. + { + const char* b (s.c_str ()); + char* e (nullptr); + errno = 0; // We must clear it according to POSIX. + uint64_t v (strtoull (b, &e, 10)); // Can't throw. + + if (errno != ERANGE && + e == b + s.size () && + v <= numeric_limits<uint64_t>::max ()) + { + return static_cast<uint64_t> (v); + } + } + + return nullopt; + } + // machine_header_manifest // machine_header_manifest:: @@ -177,6 +255,42 @@ namespace bbot summary = move (v); } + else if (n == "role") + { + if (role) + bad_name ("machine role redefinition"); + + try + { + role = to_machine_role (v); + } + catch (const invalid_argument& e) + { + bad_value (e.what ()); + } + } + else if (n == "ram-minimum") + { + if (ram_minimum) + bad_name ("machine minimum RAM redefinition"); + + ram_minimum = parse_uint64 (v); + + if (!ram_minimum || *ram_minimum == 0) + bad_value ( + "machine minimum RAM should be non-zero 64-bit unsigned integer"); + } + else if (n == "ram-maximum") + { + if (ram_maximum) + bad_name ("machine maximum RAM redefinition"); + + ram_maximum = parse_uint64 (v); + + if (!ram_maximum || *ram_maximum == 0) + bad_value ( + "machine maximum RAM should be non-zero 64-bit unsigned integer"); + } else { switch (m) @@ -217,6 +331,21 @@ namespace bbot s.next ("name", name); s.next ("summary", summary); + if (role) + s.next ("role", to_string (*role)); + + if (ram_minimum) + { + assert (*ram_minimum != 0); + s.next ("ram-minimum", std::to_string (*ram_minimum)); + } + + if (ram_maximum) + { + assert (*ram_maximum != 0); + s.next ("ram-maximum", std::to_string (*ram_maximum)); + } + if (end_of_manifest) s.next ("", ""); // End of manifest. } @@ -246,6 +375,11 @@ namespace bbot if (nv.value != "1") bad_value ("unsupported format version"); + // Cache the interactive login manifest value and validate whether it's + // allowed later, after the interactive mode is parsed. + // + optional<name_value> interactive_login_nv; + // Parse the task request manifest. // for (nv = p.next (); !nv.empty (); nv = p.next ()) @@ -288,6 +422,31 @@ namespace bbot e.what ()); } } + else if (n == "interactive-mode") + { + if (interactive_mode) + bad_name ("task request interactive mode redefinition"); + + try + { + interactive_mode = to_interactive_mode (v); + } + catch (const invalid_argument&) + { + bad_value ( + string ("invalid task request interactive mode '" + v + '\'')); + } + } + else if (n == "interactive-login") + { + if (interactive_login_nv) + bad_name ("task request interactive login redefinition"); + + if (v.empty ()) + bad_value ("empty task request interactive login"); + + interactive_login_nv = move (nv); + } else if (n == "fingerprint") { if (fingerprint) @@ -298,6 +457,17 @@ namespace bbot fingerprint = move (v); } + else if (n == "auxiliary-ram") + { + if (auxiliary_ram) + bad_name ("auxiliary machines RAM limit redefinition"); + + auxiliary_ram = parse_uint64 (v); + + if (!auxiliary_ram) + bad_value ( + "auxiliary machines RAM limit should be 64-bit unsigned integer"); + } else if (!iu) bad_name ("unknown name '" + n + "' in task request manifest"); } @@ -313,6 +483,22 @@ namespace bbot if (toolchain_version.empty ()) bad_value ("no task request toolchain version specified"); + if (effective_interactive_mode () != interactive_mode_type::false_) + { + if (!interactive_login_nv) + bad_value ("no task request interactive login specified"); + + interactive_login = move (interactive_login_nv->value); + } + else if (interactive_login_nv) + { + // Restore as bad_name() uses its line/column. + // + nv = move (*interactive_login_nv); + + bad_name ("interactive login specified for non-interactive mode"); + } + // Parse machine header manifests. // for (nv = p.next (); !nv.empty (); nv = p.next ()) @@ -338,9 +524,18 @@ namespace bbot s.next ("toolchain-name", toolchain_name); s.next ("toolchain-version", toolchain_version.string ()); + if (interactive_mode) + s.next ("interactive-mode", to_string (*interactive_mode)); + + if (interactive_login) + s.next ("interactive-login", *interactive_login); + if (fingerprint) s.next ("fingerprint", *fingerprint); + if (auxiliary_ram) + s.next ("auxiliary-ram", std::to_string (*auxiliary_ram)); + s.next ("", ""); // End of manifest. for (const machine_header_manifest& m: machines) @@ -451,6 +646,11 @@ namespace bbot optional<name_value> repo_url; optional<repository_type> repo_type; + // We will also cache the requires values to parse them later, after the + // package name is parsed. + // + vector<name_value> reqs; + for (nv = p.next (); !nv.empty (); nv = p.next ()) { string& n (nv.name); @@ -511,7 +711,7 @@ namespace bbot } catch (const invalid_argument&) { - bad_value ("invalid task repository type '" + v + "'"); + bad_value ("invalid task repository type '" + v + '\''); } } else if (n == "trust") @@ -521,37 +721,31 @@ namespace bbot trust.emplace_back (move (v)); } - else if (n == "test-exclude") + else if (n == "requires") + { + reqs.push_back (move (nv)); + } + else if (n == "tests" || n == "examples" || n == "benchmarks") { - size_t p (v.find ('/')); - if (p == string::npos) - bad_value ("invalid test exclusion package: '/' is expected"); - - package_name pn; - try { - pn = package_name (string (v, 0, p)); + tests.push_back (test_dependency (move (v), + to_test_dependency_type (n))); } catch (const invalid_argument& e) { - bad_value (string ("invalid test exclusion package name: ") + - e.what ()); + bad_value (e.what ()); } + } + else if (n == "dependency-checksum") + { + if (dependency_checksum) + bad_name ("task dependency checksum redefinition"); - bpkg::version pv; - - try - { - pv = bpkg::version (string (v, p + 1)); - } - catch (const invalid_argument& e) - { - bad_value (string ("invalid test exclusion package version: ") + - e.what ()); - } + if (v.empty ()) + bad_value ("empty task dependency checksum"); - test_exclusions.push_back (package {move (pn), move (pv)}); + dependency_checksum = move (v); } else if (n == "machine") { @@ -563,6 +757,26 @@ namespace bbot machine = move (v); } + else if (n == "auxiliary-machine" || + (n.size () > 18 && n.compare (0, 18, "auxiliary-machine-") == 0)) + { + if (v.empty ()) + bad_value ("empty task auxiliary machine name"); + + auxiliary_machine m {move (v), + n.size () > 18 ? string (n, 18) : string ()}; + + if (find_if (auxiliary_machines.begin (), auxiliary_machines.end (), + [&m] (const auxiliary_machine& am) + { + return am.environment_name == m.environment_name; + }) != auxiliary_machines.end ()) + { + bad_name ("task auxiliary machine environment redefinition"); + } + + auxiliary_machines.push_back (move (m)); + } else if (n == "target") { if (!target.empty ()) @@ -587,15 +801,45 @@ namespace bbot environment = move (v); } - else if (n == "config") + else if (n == "auxiliary-environment") { - if (!config.empty ()) - bad_name ("task configuration redefinition"); + if (auxiliary_environment) + bad_name ("task auxiliary environment redefinition"); - config = parse_tab (v, [](const string&){}, "configuration"); + if (v.empty ()) + bad_value ("empty task auxiliary environment"); - if (config.empty ()) - bad_value ("empty task configuration"); + auxiliary_environment = move (v); + } + else if (n == "config" || // @@ TMP Until toolchain 0.16.0 is released. + n == "target-config") + { + if (!target_config.empty ()) + bad_name ("task target configuration redefinition"); + + target_config = parse_tab (v, [](const string&){}, "configuration"); + + if (target_config.empty ()) + bad_value ("empty task target configuration"); + } + else if (n == "package-config") + { + if (!package_config.empty ()) + bad_name ("task package configuration redefinition"); + + package_config = move (v); + } + else if (n == "host") + { + if (host) + bad_name ("task host value redefinition"); + + if (v == "true") + host = true; + else if (v == "false") + host = false; + else + bad_value ("invalid task host value '" + v + '\''); } else if (n == "warning-regex") { @@ -607,6 +851,26 @@ namespace bbot if (warning_regex.empty ()) bad_value ("empty task warning regex"); } + else if (n == "interactive") + { + if (interactive) + bad_name ("task interactive value redefinition"); + + if (v.empty ()) + bad_value ("empty task interactive value"); + + interactive = move (v); + } + else if (n == "worker-checksum") + { + if (worker_checksum) + bad_name ("task worker checksum redefinition"); + + if (v.empty ()) + bad_value ("empty task worker checksum"); + + worker_checksum = move (v); + } else if (!iu) bad_name ("unknown name '" + n + "' in task manifest"); } @@ -642,6 +906,18 @@ namespace bbot nv = move (*repo_url); // Restore as bad_value() uses its line/column. bad_value (string ("invalid task repository URL: ") + e.what ()); } + + // Parse the requirements. + // + for (const name_value& r: reqs) + { + requirements.push_back ( + requirement_alternatives (r.value, + name, + p.name (), + r.value_line, + r.value_column)); + } } void task_manifest:: @@ -672,15 +948,31 @@ namespace bbot for (const string& v: trust) s.next ("trust", v); - for (const package& te: test_exclusions) - s.next ("test-exclude", te.name.string () + '/' + te.version.string ()); + for (const requirement_alternatives& r: requirements) + s.next ("requires", r.string ()); + + for (const test_dependency& t: tests) + s.next (to_string (t.type), t.string ()); + + if (dependency_checksum) + s.next ("dependency-checksum", *dependency_checksum); s.next ("machine", machine); + + for (const auxiliary_machine& am: auxiliary_machines) + s.next ((!am.environment_name.empty () + ? "auxiliary-machine-" + am.environment_name + : "auxiliary-machine"), + am.name); + s.next ("target", target.string ()); if (environment) s.next ("environment", *environment); + if (auxiliary_environment) + s.next ("auxiliary-environment", *auxiliary_environment); + // Serialize an optional value of the strings type as a space-separated // string list. // @@ -701,16 +993,35 @@ namespace bbot } }; - serialize_list ("config", config); + // @@ TMP Always use 'target-config' name and always serialize + // package_config after toolchain 0.16.0 is released. + // + if (!package_config.empty ()) + { + serialize_list ("target-config", target_config); + s.next ("package-config", package_config); + } + else + serialize_list ("config", target_config); + + if (host) + s.next ("host", *host ? "true" : "false"); + serialize_list ("warning-regex", warning_regex); + if (interactive) + s.next ("interactive", *interactive); + + if (worker_checksum) + s.next ("worker-checksum", *worker_checksum); + s.next ("", ""); // End of manifest. } strings task_manifest:: - unquoted_config () const + unquoted_target_config () const { - return string_parser::unquote (config); + return string_parser::unquote (target_config); } strings task_manifest:: @@ -798,6 +1109,33 @@ namespace bbot result_url = move (v); } + else if (n.size () > 11 && + n.compare (n.size () - 11, 11, "-upload-url") == 0) + { + n.resize (n.size () - 11); + + if (find_if (upload_urls.begin (), upload_urls.end (), + [&n] (const upload_url& u) {return u.type == n;}) != + upload_urls.end ()) + { + bad_name ("task response upload url redefinition"); + } + + if (v.empty ()) + bad_value ("empty task response upload url"); + + upload_urls.emplace_back (move (v), move (n)); + } + else if (n == "agent-checksum") + { + if (agent_checksum) + bad_name ("task response agent checksum redefinition"); + + if (v.empty ()) + bad_value ("empty task response agent checksum"); + + agent_checksum = move (v); + } else if (!iu) bad_name ("unknown name '" + n + "' in task response manifest"); } @@ -825,10 +1163,16 @@ namespace bbot if (result_url) bad_value ("unexpected task response result url"); + + if (!upload_urls.empty ()) + bad_value ("unexpected task response upload url"); + + if (agent_checksum) + bad_value ("unexpected task response agent checksum"); } - // If session is not empty then the task manifest must follow, otherwise it - // shouldn't. + // If session is not empty then the task manifest must follow, otherwise + // it shouldn't. // nv = p.next (); @@ -864,6 +1208,12 @@ namespace bbot if (result_url) s.next ("result-url", *result_url); + for (const upload_url& u: upload_urls) + s.next (u.type + "-upload-url", u.url); + + if (agent_checksum) + s.next ("agent-checksum", *agent_checksum); + s.next ("", ""); // End of manifest. if (task) @@ -1030,6 +1380,26 @@ namespace bbot // results[nlog++].log = move (v); } + else if (n == "worker-checksum") + { + if (worker_checksum) + bad_name ("result worker checksum redefinition"); + + if (v.empty ()) + bad_value ("empty result worker checksum"); + + worker_checksum = move (v); + } + else if (n == "dependency-checksum") + { + if (dependency_checksum) + bad_name ("result dependency checksum redefinition"); + + if (v.empty ()) + bad_value ("empty result dependency checksum"); + + dependency_checksum = move (v); + } else if (!iu) bad_name ("unknown name '" + n + "' in result manifest"); } @@ -1086,6 +1456,12 @@ namespace bbot for (const auto& r: results) s.next (r.operation + "-log", r.log); + if (worker_checksum) + s.next ("worker-checksum", *worker_checksum); + + if (dependency_checksum) + s.next ("dependency-checksum", *dependency_checksum); + s.next ("", ""); // End of manifest. } @@ -1148,6 +1524,16 @@ namespace bbot bad_value ("invalid result request challenge"); } } + else if (n == "agent-checksum") + { + if (!agent_checksum.empty ()) + bad_name ("result request agent checksum redefinition"); + + if (v.empty ()) + bad_value ("empty result request agent checksum"); + + agent_checksum = move (v); + } else if (!iu) bad_name ("unknown name '" + n + "' in result request manifest"); } @@ -1157,6 +1543,9 @@ namespace bbot if (session.empty ()) bad_value ("no result request session specified"); + if (agent_checksum.empty ()) + bad_value ("no result request agent checksum specified"); + nv = p.next (); if (nv.empty ()) bad_value ("result manifest expected"); @@ -1183,6 +1572,8 @@ namespace bbot if (challenge) s.next ("challenge", base64_encode (*challenge)); + s.next ("agent-checksum", agent_checksum); + s.next ("", ""); // End of manifest. result.serialize (s); diff --git a/libbbot/manifest.hxx b/libbbot/manifest.hxx index daee743..909d47d 100644 --- a/libbbot/manifest.hxx +++ b/libbbot/manifest.hxx @@ -6,12 +6,13 @@ #include <string> #include <vector> +#include <cstdint> // uint*_t #include <ostream> -#include <libbutl/optional.mxx> -#include <libbutl/small-vector.mxx> -#include <libbutl/target-triplet.mxx> -#include <libbutl/standard-version.mxx> +#include <libbutl/optional.hxx> +#include <libbutl/small-vector.hxx> +#include <libbutl/target-triplet.hxx> +#include <libbutl/standard-version.hxx> #include <libbutl/manifest-forward.hxx> #include <libbpkg/manifest.hxx> // version, repository_location @@ -24,15 +25,57 @@ namespace bbot { using strings = std::vector<std::string>; + // The machine's role. + // + enum class machine_role: std::uint8_t + { + build, + auxiliary + }; + + LIBBBOT_EXPORT std::string + to_string (machine_role); + + LIBBBOT_EXPORT machine_role + to_machine_role (const std::string&); // May throw invalid_argument. + + inline std::ostream& + operator<< (std::ostream& os, machine_role r) + { + return os << to_string (r); + } + class LIBBBOT_EXPORT machine_header_manifest { public: std::string id; std::string name; std::string summary; + butl::optional<machine_role> role; + butl::optional<std::uint64_t> ram_minimum; // In KiB, non-zero. + butl::optional<std::uint64_t> ram_maximum; // In KiB, non-zero. - machine_header_manifest (std::string i, std::string n, std::string s) - : id (std::move (i)), name (std::move (n)), summary (std::move (s)) {} + // Return the effective machine role. If the role is not explicitly + // specified, then the build role is assumed. + // + machine_role + effective_role () const noexcept + { + return role ? *role : machine_role::build; + } + + machine_header_manifest (std::string i, + std::string n, + std::string s, + butl::optional<machine_role> r, + butl::optional<std::uint64_t> rmn, + butl::optional<std::uint64_t> rmx) + : id (std::move (i)), + name (std::move (n)), + summary (std::move (s)), + role (r), + ram_minimum (rmn), + ram_maximum (rmx) {} public: machine_header_manifest () = default; // VC export. @@ -62,14 +105,40 @@ namespace bbot using machine_header_manifests = std::vector<machine_header_manifest>; + // Agent's capability to perform (non-)interactive builds. + // + enum class interactive_mode: std::uint8_t + { + false_, + true_, + both + }; + + LIBBBOT_EXPORT std::string + to_string (interactive_mode); + + LIBBBOT_EXPORT interactive_mode + to_interactive_mode (const std::string&); // May throw invalid_argument. + + inline std::ostream& + operator<< (std::ostream& os, interactive_mode m) + { + return os << to_string (m); + } + class LIBBBOT_EXPORT task_request_manifest { public: + using interactive_mode_type = bbot::interactive_mode; + std::string agent; std::string toolchain_name; butl::standard_version toolchain_version; + butl::optional<interactive_mode_type> interactive_mode; + butl::optional<std::string> interactive_login; + // Agent's public key SHA256 fingerprint. // // @@ How the fingerpring for openssl public key will be produced? Seems @@ -80,18 +149,37 @@ namespace bbot // butl::optional<std::string> fingerprint; + butl::optional<std::uint64_t> auxiliary_ram; // In KiB. + machine_header_manifests machines; - task_request_manifest (std::string a, - std::string n, - butl::standard_version v, - butl::optional<std::string> f, - machine_header_manifests m) - : agent (std::move (a)), - toolchain_name (std::move (n)), - toolchain_version (std::move (v)), - fingerprint (std::move (f)), - machines (std::move (m)) {} + // Return the effective interactive build mode. If the mode is not + // explicitly specified, then false is assumed. + // + interactive_mode_type + effective_interactive_mode () const noexcept + { + return interactive_mode + ? *interactive_mode + : interactive_mode_type::false_; + } + + task_request_manifest (std::string ag, + std::string tn, + butl::standard_version tv, + butl::optional<interactive_mode_type> im, + butl::optional<std::string> il, + butl::optional<std::string> fp, + butl::optional<std::uint64_t> ar, + machine_header_manifests ms) + : agent (std::move (ag)), + toolchain_name (std::move (tn)), + toolchain_version (std::move (tv)), + interactive_mode (std::move (im)), + interactive_login (std::move (il)), + fingerprint (std::move (fp)), + auxiliary_ram (ar), + machines (std::move (ms)) {} public: task_request_manifest () = default; // VC export. @@ -108,6 +196,14 @@ namespace bbot bpkg::version version; }; + // Note: corresponds to build_auxiliary in the package manifest. + // + struct auxiliary_machine + { + std::string name; + std::string environment_name; + }; + class LIBBBOT_EXPORT task_manifest { public: @@ -123,22 +219,53 @@ namespace bbot // strings trust; - // Separate tests, examples, and benchmarks packages that should be - // excluded from building together with the primary package. + // The subset of the build task-relevant package manifest values (see + // bpkg::package_manifest for their semantics). // - butl::small_vector<package, 1> test_exclusions; + std::vector<bpkg::requirement_alternatives> requirements; + butl::small_vector<bpkg::test_dependency, 1> tests; + + butl::optional<std::string> dependency_checksum; std::string machine; // Build machine to use for building the package. + // The list of build auxiliary machines. + // + // Note that all entries in this list must have distinct environment names + // (with empty name being one of the possibilities). + // + // Also note that some auxiliary machines can potentially be used by the + // main package and some by the test packages. It is such package author's + // responsibility to make sure that the environment names specified in + // multiple package manifests do not clash. It is bbot controller's + // responsibility to verify that there is no clash, aborting the task if + // there is. + // + std::vector<auxiliary_machine> auxiliary_machines; + butl::target_triplet target; // Build target. butl::optional<std::string> environment; // Build environment name. + // The environment variables describing the auxiliary machines. + // + butl::optional<std::string> auxiliary_environment; + // Build system configuration variables (in addition to build environment // configuration variables). + // // Note: could be quoted. // - strings config; + strings target_config; + + // Whitespace separated list of potentially double/single-quoted package + // configuration arguments for bpkg-pkg-build command. + // + std::string package_config; + + // If true, then this configuration is self-hosted. + // + butl::optional<bool> host; // Regular expressions for detecting warnings in the operation result logs // (in addition to the default list of expressions). @@ -146,8 +273,12 @@ namespace bbot // strings warning_regex; + butl::optional<std::string> interactive; // Interactive build breakpoint. + + butl::optional<std::string> worker_checksum; + strings - unquoted_config () const; + unquoted_target_config () const; strings unquoted_warning_regex () const; @@ -156,22 +287,38 @@ namespace bbot bpkg::version vr, bpkg::repository_location rl, strings tr, - butl::small_vector<package, 1> te, + std::vector<bpkg::requirement_alternatives> ra, + butl::small_vector<bpkg::test_dependency, 1> ts, + butl::optional<std::string> dc, std::string mn, + std::vector<auxiliary_machine> ams, butl::target_triplet tg, butl::optional<std::string> en, - strings cf, - strings wr) + butl::optional<std::string> ae, + strings tc, + std::string pc, + butl::optional<bool> ht, + strings wr, + butl::optional<std::string> ir, + butl::optional<std::string> wc) : name (std::move (nm)), version (std::move (vr)), repository (std::move (rl)), trust (std::move (tr)), - test_exclusions (std::move (te)), + requirements (std::move (ra)), + tests (std::move (ts)), + dependency_checksum (std::move (dc)), machine (std::move (mn)), + auxiliary_machines (std::move (ams)), target (std::move (tg)), environment (std::move (en)), - config (std::move (cf)), - warning_regex (std::move (wr)){} + auxiliary_environment (std::move (ae)), + target_config (std::move (tc)), + package_config (std::move (pc)), + host (std::move (ht)), + warning_regex (std::move (wr)), + interactive (std::move (ir)), + worker_checksum (std::move (wc)) {} public: task_manifest () = default; // VC export. @@ -190,6 +337,16 @@ namespace bbot validate_regex (const std::string&); }; + class upload_url + { + public: + std::string url; + std::string type; + + upload_url (std::string u, std::string t) + : url (std::move (u)), type (std::move (t)) {} + }; + class LIBBBOT_EXPORT task_response_manifest { public: @@ -197,19 +354,28 @@ namespace bbot // std::string session; - // Challenge, result url and task are absent if session is empty. + // Challenge, result url, and task are absent and upload urls list is + // empty if session is empty. // butl::optional<std::string> challenge; butl::optional<std::string> result_url; + std::vector<upload_url> upload_urls; // <type>-upload-url: <url> + + butl::optional<std::string> agent_checksum; + butl::optional<task_manifest> task; task_response_manifest (std::string s, butl::optional<std::string> c, butl::optional<std::string> u, + std::vector<upload_url> uus, + butl::optional<std::string> ac, butl::optional<task_manifest> t) : session (std::move (s)), challenge (std::move (c)), result_url (std::move (u)), + upload_urls (std::move (uus)), + agent_checksum (std::move (ac)), task (std::move (t)) {} public: @@ -229,11 +395,13 @@ namespace bbot // indicate whether one "overrides" the other in the "merge" operator| // (see below). // + skip, success, warning, error, abort, - abnormal + abnormal, + interrupt }; LIBBBOT_EXPORT std::string @@ -292,14 +460,21 @@ namespace bbot // operation_results results; + butl::optional<std::string> worker_checksum; + butl::optional<std::string> dependency_checksum; + result_manifest (bpkg::package_name n, bpkg::version v, result_status s, - operation_results r) + operation_results r, + butl::optional<std::string> wc, + butl::optional<std::string> dc) : name (std::move (n)), version (std::move (v)), status (s), - results (std::move (r)) {} + results (std::move (r)), + worker_checksum (std::move (wc)), + dependency_checksum (std::move (dc)) {} public: result_manifest () = default; // VC export. @@ -321,13 +496,17 @@ namespace bbot // butl::optional<std::vector<char>> challenge; + std::string agent_checksum; + result_manifest result; result_request_manifest (std::string s, butl::optional<std::vector<char>> c, + std::string ac, result_manifest r) : session (std::move (s)), challenge (std::move (c)), + agent_checksum (std::move (ac)), result (std::move (r)) {} public: @@ -1,6 +1,6 @@ : 1 name: libbbot -version: 0.13.0 +version: 0.17.0-a.0.z project: build2 summary: build2 build bot utility library license: MIT @@ -13,9 +13,9 @@ doc-url: https://build2.org/doc.xhtml src-url: https://git.build2.org/cgit/libbbot/tree/ email: users@build2.org build-warning-email: builds@build2.org -builds: all +builds: all : &host requires: c++14 -depends: * build2 >= 0.13.0 -depends: * bpkg >= 0.13.0 -depends: libbutl ^0.13.0 -depends: libbpkg ^0.13.0 +depends: * build2 >= 0.16.0- +depends: * bpkg >= 0.16.0- +depends: libbutl [0.17.0-a.0.1 0.17.0-a.1) +depends: libbpkg [0.17.0-a.0.1 0.17.0-a.1) diff --git a/tests/build/root.build b/tests/build/root.build index bb274d3..f97c101 100644 --- a/tests/build/root.build +++ b/tests/build/root.build @@ -13,6 +13,15 @@ if ($cxx.target.system == 'win32-msvc') if ($cxx.class == 'msvc') cxx.coptions += /wd4251 /wd4275 /wd4800 +elif ($cxx.id == 'gcc') +{ + cxx.coptions += -Wno-maybe-uninitialized -Wno-free-nonheap-object # libbutl + + if ($cxx.version.major >= 13) + cxx.coptions += -Wno-dangling-reference +} +elif ($cxx.id.type == 'clang' && $cxx.version.major >= 15) + cxx.coptions += -Wno-unqualified-std-cast-call # Every exe{} in this subproject is by default a test. # diff --git a/tests/buildtab/driver.cxx b/tests/buildtab/driver.cxx index 13d0d71..1ea4331 100644 --- a/tests/buildtab/driver.cxx +++ b/tests/buildtab/driver.cxx @@ -2,12 +2,14 @@ // license : MIT; see accompanying LICENSE file #include <ios> // ios::failbit, ios::badbit -#include <cassert> #include <iostream> -#include <libbutl/utility.mxx> // operator<<(ostream,exception) +#include <libbutl/utility.hxx> // operator<<(ostream,exception) + +#include <libbbot/build-target-config.hxx> -#include <libbbot/build-config.hxx> +#undef NDEBUG +#include <cassert> using namespace std; using namespace butl; @@ -25,9 +27,9 @@ try cin.exceptions (ios::failbit | ios::badbit); cout.exceptions (ios::failbit | ios::badbit); - const build_configs& configs (parse_buildtab (cin, "cin")); + const build_target_configs& configs (parse_buildtab (cin, "cin")); - for (const build_config& c: configs) + for (const build_target_config& c: configs) { cout << c.machine_pattern << ' ' << c.name << ' ' << c.target; diff --git a/tests/buildtab/testscript b/tests/buildtab/testscript index c9b5389..6c8b054 100644 --- a/tests/buildtab/testscript +++ b/tests/buildtab/testscript @@ -6,11 +6,13 @@ : Roundtrip buildtab. : { - : all-fileds-combinations + : all-fields-combinations : $* <<EOI >>EOO - windows*-vc_14* windows-vc_14-32 i686-microsoft-win32-msvc14.0 all - windows*-vc_14* windows-vc_14-32-debug i686-microsoft-win32-msvc14.0 "" config.cc.coptions=/Z7 config.cc.loptions=/DEBUG ~"warning C4\d{3}: " + windows*-vc_14* windows-vc_14 i686-microsoft-win32-msvc14.0 all + windows*-vc_14* windows-vc_14-debug i686-microsoft-win32-msvc14.0 "" config.cc.coptions=/Z7 config.cc.loptions=/DEBUG ~"warning C4\d{3}: " + + windows*-vc_14* windows-vc_14 x86_64-microsoft-win32-msvc14.0 all linux_debian_8*-gcc_4.9 linux_debian_8-gcc_4.9 x86_64-linux-gnu "all default linux gcc gcc-4+:gcc-3+" - - - gcc-5+:gcc-4+ @@ -21,8 +23,9 @@ windows_10*-clang_9.0_msvc_16.3 windows_10-clang_9.0_msvc_16.3_lld x86_64-microsoft-win32-msvc14.2/lld "all default windows clang" EOI - windows*-vc_14* windows-vc_14-32 i686-microsoft-win32-msvc14.0 all - windows*-vc_14* windows-vc_14-32-debug i686-microsoft-win32-msvc14.0 "" config.cc.coptions=/Z7 config.cc.loptions=/DEBUG ~"warning C4\d{3}: " + windows*-vc_14* windows-vc_14 i686-microsoft-win32-msvc14.0 all + windows*-vc_14* windows-vc_14-debug i686-microsoft-win32-msvc14.0 "" config.cc.coptions=/Z7 config.cc.loptions=/DEBUG ~"warning C4\d{3}: " + windows*-vc_14* windows-vc_14 x86_64-microsoft-win32-msvc14.0 all linux_debian_8*-gcc_4.9 linux_debian_8-gcc_4.9 x86_64-linux-gnu "all default linux gcc gcc-4+:gcc-3+" linux_debian_9*-gcc_7.3 linux_debian_9-gcc_7.3 x86_64-linux-gnu "all default linux gcc gcc-7+:gcc-6+" linux_debian_9*-gcc_7.3 linux_debian_9-gcc_7.3-O3 x86_64-linux-gnu "all default linux gcc optimized gcc-7+:gcc-6+" config.cc.coptions=-O3 @@ -52,14 +55,15 @@ $* <<EOI 2>>EOE == 1 windows*-vc_14* EOI - cin:1:16: error: no configuration name found + cin:1:16: error: no target configuration name found EOE : dup : - $* <<EOI 2>'cin:2:17: error: duplicate configuration name' == 1 - windows*-vc_14* windows-vc_14-32 i686-microsoft-win32-msvc14.0 default - windows*-vc_14* windows-vc_14-32 i686-microsoft-win32-msvc14.0 default + $* <<EOI 2>'cin:3:31: error: duplicate target configuration name/target' == 1 + windows*-vc_14* windows-vc_14 i686-microsoft-win32-msvc14.0 default + windows*-vc_14* windows-vc_14 x86_64-microsoft-win32-msvc14.0 default + windows*-vc_14* windows-vc_14 i686-microsoft-win32-msvc14.0 default EOI } diff --git a/tests/manifest/driver.cxx b/tests/manifest/driver.cxx index 821aa63..9c0fcf9 100644 --- a/tests/manifest/driver.cxx +++ b/tests/manifest/driver.cxx @@ -3,15 +3,17 @@ #include <ios> // ios_base::failbit, ios_base::badbit #include <string> -#include <cassert> #include <iostream> -#include <libbutl/utility.mxx> // operator<<(ostream,exception) -#include <libbutl/manifest-parser.mxx> -#include <libbutl/manifest-serializer.mxx> +#include <libbutl/utility.hxx> // operator<<(ostream,exception) +#include <libbutl/manifest-parser.hxx> +#include <libbutl/manifest-serializer.hxx> #include <libbbot/manifest.hxx> +#undef NDEBUG +#include <cassert> + using namespace std; using namespace butl; using namespace bbot; diff --git a/tests/manifest/machine-header.testscript b/tests/manifest/machine-header.testscript index 84295d2..559a107 100644 --- a/tests/manifest/machine-header.testscript +++ b/tests/manifest/machine-header.testscript @@ -13,6 +13,8 @@ test.options += -m id: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 name: windows_10-msvc_14 summary: Windows 10 build 1607 with VC 14 update 3 + role: build + ram-minimum: 4194304 EOF } @@ -52,6 +54,22 @@ EOI summary: Windows summary: Windows EOI + + : ram-maximum + : + $* <<EOI 2>'stdin:3:1: error: machine maximum RAM redefinition' == 1 + : 1 + ram-maximum: 4194304 + ram-maximum: 4194304 + EOI + + : role + : + $* <<EOI 2>'stdin:3:1: error: machine role redefinition' == 1 + : 1 + role: build + role: auxiliary + EOI } : empty diff --git a/tests/manifest/result-request.testscript b/tests/manifest/result-request.testscript index e2c4a94..6d0e5b1 100644 --- a/tests/manifest/result-request.testscript +++ b/tests/manifest/result-request.testscript @@ -14,10 +14,12 @@ test.options += -rq : 1 session: abcd challenge: YQo= + agent-checksum: 1 : name: libfoo version: 1.0 status: error + worker-checksum: 1 EOF : no-challenge @@ -25,10 +27,12 @@ test.options += -rq $* <<EOF >>EOF : 1 session: abcd + agent-checksum: 1 : name: libfoo version: 1.0 status: error + worker-checksum: 1 EOF } @@ -51,6 +55,14 @@ test.options += -rq challenge: YQo= challenge: YQo= EOI + + : agent-checksum + : + $* <<EOI 2>'stdin:3:1: error: result request agent checksum redefinition' == 1 + : 1 + agent-checksum: 1 + agent-checksum: 1 + EOI } : invalid @@ -76,6 +88,13 @@ test.options += -rq : 1 challenge: EOI + + : empty-agent-checksum + : + $* <<EOI 2>'stdin:2:16: error: empty result request agent checksum' == 1 + : 1 + agent-checksum: + EOI } : unknown-name @@ -95,11 +114,21 @@ EOI challenge: YQo= EOI + + : agent-checksum + : + $* <<EOI 2>'stdin:4:1: error: no result request agent checksum specified' == 1 + : 1 + session: abc + challenge: YQo= + EOI + : result : - $* <<EOI 2>'stdin:4:1: error: result manifest expected' == 1 + $* <<EOI 2>'stdin:5:1: error: result manifest expected' == 1 : 1 session: abc challenge: YQo= + agent-checksum: 1 EOI } diff --git a/tests/manifest/result.testscript b/tests/manifest/result.testscript index c530170..b48a691 100644 --- a/tests/manifest/result.testscript +++ b/tests/manifest/result.testscript @@ -18,18 +18,20 @@ test.options += -r configure-status: success update-status: warning test-status: error - configure-log: \ + configure-log:\ conf line 1 conf line 2 \ - update-log: \ + update-log:\ update line 1 update line 2 \ - test-log: \ + test-log:\ test line 1 test line 2 \ + worker-checksum: 1 + dependency-checksum: 12345 EOF : update-error @@ -41,14 +43,16 @@ test.options += -r status: error configure-status: warning update-status: error - configure-log: \ + configure-log:\ conf line 1 conf line 2 \ - update-log: \ + update-log:\ update line 1 update line 2 \ + worker-checksum: 1 + dependency-checksum: 12345 EOF : early-abort @@ -106,12 +110,20 @@ test.options += -r configure-log: configured configure-log: configured EOI + + : worker-checksum + : + $* <<EOI 2>'stdin:3:1: error: result worker checksum redefinition' == 1 + : 1 + worker-checksum: 1 + worker-checksum: 1 + EOI } : invalid : { - : name-empty + : empty-name : $* <<EOI 2>'stdin:2:6: error: invalid result package name: length is less than two characters' == 1 : 1 @@ -181,6 +193,13 @@ test.options += -r update-log: log EOI } + + : empty-worker-checksum + : + $* <<EOI 2>'stdin:2:17: error: empty result worker checksum' == 1 + : 1 + worker-checksum: + EOI } : unknown-name diff --git a/tests/manifest/task-request.testscript b/tests/manifest/task-request.testscript index 4b797f6..79f3982 100644 --- a/tests/manifest/task-request.testscript +++ b/tests/manifest/task-request.testscript @@ -15,7 +15,10 @@ test.options += -tq agent: upsa toolchain-name: queue toolchain-version: 0.5.0 + interactive-mode: both + interactive-login: 10.5.0.1:5901 fingerprint: 1105fb394ee870adb154b7abfbbae5755df7dcef6c81db34e8d1b68d2653734e + auxiliary-ram: 41943040 : id: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 name: windows_10-msvc_14 @@ -70,6 +73,14 @@ test.options += -tq fingerprint: 1105fb394ee870adb154b7abfbbae5755df7dcef6c81db34e8d1b68d2653734e fingerprint: 1105fb394ee870adb154b7abfbbae5755df7dcef6c81db34e8d1b68d2653734e EOI + + : auxiliary-ram + : + $* <<EOI 2>'stdin:3:1: error: auxiliary machines RAM limit redefinition' == 1 + : 1 + auxiliary-ram: 41943040 + auxiliary-ram: 41943040 + EOI } : empty @@ -88,6 +99,13 @@ test.options += -tq : 1 toolchain-name: EOI + + : auxiliary-ram + : + $* <<EOI 2>'stdin:2:15: error: auxiliary machines RAM limit should be 64-bit unsigned integer' == 1 + : 1 + auxiliary-ram: + EOI } : invalid-toolchain-version @@ -124,3 +142,65 @@ toolchain-name: queue toolchain-version: 0.5.0 fingerprint: 1105fb394ee870adb154b7abfbbae5755df7dcef6c81db34e8d1b68d2653734e EOI + +: interactive +: +{ + : redefinition + : + { + : mode + : + $* <<EOI 2>'stdin:3:1: error: task request interactive mode redefinition' == 1 + : 1 + interactive-mode: true + interactive-mode: both + EOI + + : login + : + $* <<EOI 2>'stdin:3:1: error: task request interactive login redefinition' == 1 + : 1 + interactive-login: 10.5.0.1:5901 + interactive-login: 10.5.0.1:5901 + EOI + } + + : invalid + : + { + : mode + : + $* <<EOI 2>"stdin:2:19: error: invalid task request interactive mode 'on'" == 1 + : 1 + interactive-mode: on + EOI + + : login + : + $* <<EOI 2>'stdin:2:19: error: empty task request interactive login' == 1 + : 1 + interactive-login: + EOI + } + + : no-login + : + $* <<EOI 2>'stdin:6:1: error: no task request interactive login specified' == 1 + : 1 + agent: upsa + toolchain-name: queue + toolchain-version: 0.5.0 + interactive-mode: both + EOI + + : unexpected-login + : + $* <<EOI 2>'stdin:5:1: error: interactive login specified for non-interactive mode' == 1 + : 1 + agent: upsa + toolchain-name: queue + toolchain-version: 0.5.0 + interactive-login: 10.5.0.1:5901 + EOI +} diff --git a/tests/manifest/task-response.testscript b/tests/manifest/task-response.testscript index e7dbdb9..7615127 100644 --- a/tests/manifest/task-response.testscript +++ b/tests/manifest/task-response.testscript @@ -18,6 +18,8 @@ test.options += -ts session: abcd challenge: cc6585375ef81898cc60791b11852e3d2ed9ebb82ebb0874010fe0e6f9ebdb73 result-url: https://cppget.org/?build-result + bindist-upload-url: https://cppget.org/?upload=bindist + agent-checksum: 1 : name: libfoo version: 1.0 @@ -26,7 +28,7 @@ test.options += -ts target: x86_64-microsoft-win32-msvc14.0 EOF - : no-challenge + : no-optional : $* <<EOF >>EOF : 1 @@ -75,6 +77,23 @@ test.options += -ts result-url: https://cppget.org/?build-result result-url: https://cppget.org/?build-result EOI + + : upload-url + : + $* <<EOI 2>'stdin:4:1: error: task response upload url redefinition' == 1 + : 1 + bindist-upload-url: https://cppget.org/?upload=bindist + other-upload-url: https://cppget.org/?upload=other + bindist-upload-url: https://cppget.org/?upload=bindist + EOI + + : agent-checksum + : + $* <<EOI 2>'stdin:3:1: error: task response agent checksum redefinition' == 1 + : 1 + agent-checksum: 1 + agent-checksum: 1 + EOI } : invalid @@ -118,6 +137,44 @@ test.options += -ts EOI } + : upload-url + : + { + : empty + : + $* <<EOI 2>'stdin:2:20: error: empty task response upload url' == 1 + : 1 + bindist-upload-url: + EOI + + : redundant + : + $* <<EOI 2>'stdin:4:1: error: unexpected task response upload url' == 1 + : 1 + session: + bindist-upload-url: https://cppget.org/?upload=bindist + EOI + } + + : agent-checksum + : + { + : empty + : + $* <<EOI 2>'stdin:2:16: error: empty task response agent checksum' == 1 + : 1 + agent-checksum: + EOI + + : redundant + : + $* <<EOI 2>'stdin:4:1: error: unexpected task response agent checksum' == 1 + : 1 + session: + agent-checksum: 1 + EOI + } + : task-unexpected : $* <<EOI 2>'stdin:3:1: error: single task response manifest expected' == 1 diff --git a/tests/manifest/task.testscript b/tests/manifest/task.testscript index 65ecd29..8320f59 100644 --- a/tests/manifest/task.testscript +++ b/tests/manifest/task.testscript @@ -12,18 +12,53 @@ test.options += -t : $* <<EOF >>EOF : 1 - name: libfoo + name: foo + version: 1.0 + repository-url: http://pkg.example.org/1/math + trust: AB:0D:3F:C1:B0:13:E4:0E:AD:4A:08:06:AE:F3:85:DB:E2:27:5F:83:11:47:A2:7\ + 8:64:3C:73:60:F8:66:3A:A4 + requires: host + tests: foo-tests + examples: foo-examples + dependency-checksum: 12345 + machine: windows_10-msvc_14 + auxiliary-machine-pgsql: x86_64-linux_debian_12-postgresql_16 + auxiliary-machine: x86_64-linux_debian_12-mysql* + target: x86_64-microsoft-win32-msvc14.0 + environment: lld + auxiliary-environment:\ + PGSQL_DATABASE_HOST=192.168.0.1 + PGSQL_DATABASE_PORT=1245 + \ + target-config: config.cc.coptions=/Z7 config.cc.loptions=/DEBUG + package-config: config.foo.network=true + warning-regex: '^warning: ' '^.+: warning: ' + interactive: error + worker-checksum: 1 + EOF + + # @@ TMP Remove when toolchain 0.16.0 is released. + # + : no-package-config + : + $* <<EOF >>EOF + : 1 + name: foo version: 1.0 repository-url: http://pkg.example.org/1/math trust: AB:0D:3F:C1:B0:13:E4:0E:AD:4A:08:06:AE:F3:85:DB:E2:27:5F:83:11:47:A2:7\ 8:64:3C:73:60:F8:66:3A:A4 - test-exclude: libfoo-tests/1.0 - test-exclude: libfoo-examples/1.0 + requires: host + tests: foo-tests + examples: foo-examples + dependency-checksum: 12345 machine: windows_10-msvc_14 target: x86_64-microsoft-win32-msvc14.0 environment: lld config: config.cc.coptions=/Z7 config.cc.loptions=/DEBUG warning-regex: '^warning: ' '^.+: warning: ' + interactive: error + worker-checksum: 1 EOF : no-config-regex-environment @@ -67,6 +102,53 @@ test.options += -t target: x86_64-microsoft-win32-msvc14.0 EOO + : requires + : + { + $* <<EOF >>EOF + : 1 + name: foo + version: 1.0 + repository-url: http://pkg.example.org/1/math + requires: {c++ >= 14 windows} + requires: host + machine: windows + target: x86_64-microsoft-win32-msvc14.0 + EOF + } + + : requires-invalid + : + { + $* <<EOI 2>>EOE != 0 + : 1 + name: foo + version: 1.0 + repository-url: http://pkg.example.org/1/math + requires: {c++ >= 14 windows + machine: windows + target: x86_64-microsoft-win32-msvc14.0 + EOI + stdin:5:29: error: requirement or '}' expected + EOE + } + + : tests + : + { + $* <<EOF >>EOF + : 1 + name: libfoo + version: 1.0 + repository-url: http://pkg.example.org/1/math + tests: libfoo-tests + examples: libfoo-examples == 1.2.3 + benchmarks: libfoo-benchmarks ~1.2.0 + machine: windows + target: x86_64-microsoft-win32-msvc14.0 + EOF + } + : config : { @@ -95,6 +177,34 @@ test.options += -t EOF } + : host + : + { + : true + : + $* <<EOF >>EOF + : 1 + name: libfoo + version: 1.0 + repository-url: http://pkg.example.org/1/math + machine: windows + target: x86_64-microsoft-win32-msvc14.0 + host: true + EOF + + : false + : + $* <<EOF >>EOF + : 1 + name: libfoo + version: 1.0 + repository-url: http://pkg.example.org/1/math + machine: windows + target: x86_64-microsoft-win32-msvc14.0 + host: false + EOF + } + : trust-yes : $* <<EOF >>EOF @@ -144,6 +254,14 @@ test.options += -t machine: windows_10-msvc_14 EOI + : auxiliary-machine + : + $* <<EOI 2>'stdin:3:1: error: task auxiliary machine environment redefinition' == 1 + : 1 + auxiliary-machine-pgsql: x86_64-linux_debian_12-postgresql_16 + auxiliary-machine-pgsql: x86_64-linux_debian_12-postgresql_14 + EOI + : target : $* <<EOI 2>'stdin:3:1: error: task target redefinition' == 1 @@ -152,14 +270,38 @@ test.options += -t target: x86_64-microsoft-win32-msvc14.0 EOI + : auxiliary-environment + : + $* <<EOI 2>'stdin:7:1: error: task auxiliary environment redefinition' == 1 + : 1 + auxiliary-environment: + \ + PGSQL_DATABASE_HOST=192.168.0.1 + PGSQL_DATABASE_PORT=1245 + \ + auxiliary-environment: + \ + PGSQL_DATABASE_HOST=192.168.0.1 + PGSQL_DATABASE_PORT=1245 + \ + EOI + : config : - $* <<EOI 2>'stdin:3:1: error: task configuration redefinition' == 1 + $* <<EOI 2>'stdin:3:1: error: task target configuration redefinition' == 1 : 1 config: config.cc.coptions=/Z7 config: config.cc.loptions=/DEBUG EOI + : host + : + $* <<EOI 2>'stdin:3:1: error: task host value redefinition' == 1 + : 1 + host: true + host: false + EOI + : warning-regex : $* <<EOI 2>'stdin:3:1: error: task warning regex redefinition' == 1 @@ -167,6 +309,22 @@ test.options += -t warning-regex: '^warning: ' warning-regex: '^.+: warning: ' EOI + + : interactive + : + $* <<EOI 2>'stdin:3:1: error: task interactive value redefinition' == 1 + : 1 + interactive: error + interactive: warning + EOI + + : worker-checksum + : + $* <<EOI 2>'stdin:3:1: error: task worker checksum redefinition' == 1 + : 1 + worker-checksum: 1 + worker-checksum: 1 + EOI } : invalid @@ -224,37 +382,6 @@ test.options += -t EOE } - : test-exclude - : - { - : invalid-name - : - $* <<EOI 2>>EOE == 1 - : 1 - test-exclude: 0ibfoo-tests/1.0 - EOI - stdin:2:15: error: invalid test exclusion package name: illegal first character (must be alphabetic) - EOE - - : no-version - : - $* <<EOI 2>>EOE == 1 - : 1 - test-exclude: libfoo-tests - EOI - stdin:2:15: error: invalid test exclusion package: '/' is expected - EOE - - : invalid-version - : - $* <<EOI 2>>EOE == 1 - : 1 - test-exclude: libfoo-tests/+1 - EOI - stdin:2:15: error: invalid test exclusion package version: unexpected end - EOE - } - : machine-empty : $* <<EOI 2>'stdin:2:9: error: empty task machine' == 1 @@ -269,12 +396,12 @@ test.options += -t target: EOI - : config + : target-config : { : empty : - $* <<EOI 2>'stdin:2:8: error: empty task configuration' == 1 + $* <<EOI 2>'stdin:2:8: error: empty task target configuration' == 1 : 1 config: EOI @@ -293,13 +420,20 @@ test.options += -t : $* <<EOI 2>'stdin:3:7: error: invalid task configuration: unterminated quoted string' == 1 : 1 - config: \ + config:\ 'abc=x \ EOI } } + : host + : + $* <<EOI 2>"stdin:2:7: error: invalid task host value 'yes'" == 1 + : 1 + host: yes + EOI + : warning-regex : { @@ -326,6 +460,20 @@ test.options += -t : 1 trust: abc EOI + + : interactive + : + $* <<EOI 2>'stdin:2:13: error: empty task interactive value' == 1 + : 1 + interactive: + EOI + + : worker-checksum + : + $* <<EOI 2>'stdin:2:17: error: empty task worker checksum' == 1 + : 1 + worker-checksum: + EOI } : unknown-name |