aboutsummaryrefslogtreecommitdiff
path: root/bpkg/system-package-manager-debian.test.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'bpkg/system-package-manager-debian.test.cxx')
-rw-r--r--bpkg/system-package-manager-debian.test.cxx386
1 files changed, 386 insertions, 0 deletions
diff --git a/bpkg/system-package-manager-debian.test.cxx b/bpkg/system-package-manager-debian.test.cxx
new file mode 100644
index 0000000..c85b231
--- /dev/null
+++ b/bpkg/system-package-manager-debian.test.cxx
@@ -0,0 +1,386 @@
+// file : bpkg/system-package-manager-debian.test.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#include <bpkg/system-package-manager-debian.hxx>
+
+#include <map>
+#include <iostream>
+
+#include <bpkg/types.hxx>
+#include <bpkg/utility.hxx>
+
+#undef NDEBUG
+#include <cassert>
+
+#include <bpkg/system-package-manager.test.hxx>
+
+using namespace std;
+
+namespace bpkg
+{
+ using package_status = system_package_status_debian;
+ using package_policy = package_status::package_policy;
+
+ using butl::manifest_parser;
+ using butl::manifest_parsing;
+
+ // Usage: args[0] <command> ...
+ //
+ // Where <command> is one of:
+ //
+ // apt-cache-policy <pkg>... result comes from stdin
+ //
+ // apt-cache-show <pkg> <ver> result comes from stdin
+ //
+ // parse-name-value <pkg> debian-name value from stdin
+ //
+ // main-from-dev <dev-pkg> <dev-ver> depends comes from stdin
+ //
+ // map-package [<build-metadata>] manifest comes from stdin
+ //
+ // build <query-pkg>... [--install [--no-fetch] <install-pkg>...]
+ //
+ // The stdin of the build command is used to read the simulation description
+ // which consists of lines in the following forms (blanks are ignored):
+ //
+ // manifest: <query-pkg> <file>
+ //
+ // Available package manifest for one of <query-pkg>. If none is
+ // specified, then a stub is automatically added.
+ //
+ // apt-cache-policy[-{fetched,installed}]: <sys-pkg>... <file>
+ //
+ // Values for simulation::apt_cache_policy_*. If <file> is the special `!`
+ // value, then make the entry empty.
+ //
+ // apt-cache-show[-fetched]: <sys-pkg> <sys-ver> <file>
+ //
+ // Values for simulation::apt_cache_show_*. If <file> is the special `!`
+ // value, then make the entry empty.
+ //
+ // apt-get-update-fail: true
+ // apt-get-install-fail: true
+ //
+ // Values for simulation::apt_get_{update,install}_fail_.
+ //
+ int
+ main (int argc, char* argv[])
+ try
+ {
+ assert (argc >= 2); // <command>
+
+ string cmd (argv[1]);
+
+ // @@ TODO: add option to customize? Maybe option before command?
+ //
+ os_release osr {"debian", {}, "10", "", "Debian", "", ""};
+
+ if (cmd == "apt-cache-policy")
+ {
+ assert (argc >= 3); // <pkg>...
+
+ strings key;
+ vector<package_policy> pps;
+ for (int i (2); i != argc; ++i)
+ {
+ key.push_back (argv[i]);
+ pps.push_back (package_policy (argv[i]));
+ }
+
+ system_package_manager_debian::simulation s;
+ s.apt_cache_policy_.emplace (move (key), path ("-"));
+
+ system_package_manager_debian m (move (osr),
+ host_triplet,
+ "" /* arch */,
+ nullopt /* progress */,
+ nullopt /* fetch_timeout */,
+ false /* install */,
+ false /* fetch */,
+ false /* yes */,
+ "sudo");
+ m.simulate_ = &s;
+
+ m.apt_cache_policy (pps);
+
+ for (const package_policy& pp: pps)
+ {
+ cout << pp.name << " '"
+ << pp.installed_version << "' '"
+ << pp.candidate_version << "'\n";
+ }
+ }
+ else if (cmd == "apt-cache-show")
+ {
+ assert (argc == 4); // <pkg> <ver>
+
+ pair<string, string> key (argv[2], argv[3]);
+
+ system_package_manager_debian::simulation s;
+ s.apt_cache_show_.emplace (key, path ("-"));
+
+ system_package_manager_debian m (move (osr),
+ host_triplet,
+ "" /* arch */,
+ nullopt /* progress */,
+ nullopt /* fetch_timeout */,
+ false /* install */,
+ false /* fetch */,
+ false /* yes */,
+ "sudo");
+ m.simulate_ = &s;
+
+ cout << m.apt_cache_show (key.first, key.second) << '\n';
+ }
+ else if (cmd == "parse-name-value")
+ {
+ assert (argc == 3); // <pkg>
+
+ package_name pn (argv[2]);
+ string pt (package_manifest::effective_type (nullopt, pn));
+
+ string v;
+ getline (cin, v);
+
+ package_status s (
+ system_package_manager_debian::parse_name_value (pt, v, false, false));
+
+ if (!s.main.empty ()) cout << "main: " << s.main << '\n';
+ if (!s.dev.empty ()) cout << "dev: " << s.dev << '\n';
+ if (!s.doc.empty ()) cout << "doc: " << s.doc << '\n';
+ if (!s.dbg.empty ()) cout << "dbg: " << s.dbg << '\n';
+ if (!s.common.empty ()) cout << "common: " << s.common << '\n';
+ if (!s.extras.empty ())
+ {
+ cout << "extras:";
+ for (const string& e: s.extras)
+ cout << ' ' << e;
+ cout << '\n';
+ }
+ }
+ else if (cmd == "main-from-dev")
+ {
+ assert (argc == 4); // <dev-pkg> <dev-ver>
+
+ string n (argv[2]);
+ string v (argv[3]);
+ string d;
+ getline (cin, d);
+
+ cout << system_package_manager_debian::main_from_dev (n, v, d) << '\n';
+ }
+ else if (cmd == "map-package")
+ {
+ assert (argc >= 2 && argc <= 3); // [<build-metadata>]
+
+ optional<string> bm;
+ if (argc > 2)
+ bm = argv[2];
+
+ available_packages aps;
+ aps.push_back (make_available_from_manifest ("", "-"));
+
+ const package_name& n (aps.front ().first->id.name);
+ const version& v (aps.front ().first->version);
+
+ system_package_manager_debian m (move (osr),
+ host_triplet,
+ "" /* arch */,
+ nullopt /* progress */,
+ nullptr /* options */);
+
+ package_status s (m.map_package (n, v, aps, bm));
+
+ cout << "version: " << s.system_version << '\n'
+ << "main: " << s.main << '\n';
+ if (!s.dev.empty ()) cout << "dev: " << s.dev << '\n';
+ if (!s.doc.empty ()) cout << "doc: " << s.doc << '\n';
+ if (!s.dbg.empty ()) cout << "dbg: " << s.dbg << '\n';
+ if (!s.common.empty ()) cout << "common: " << s.common << '\n';
+ }
+ else if (cmd == "build")
+ {
+ assert (argc >= 3); // <query-pkg>...
+
+ strings qps;
+ map<string, available_packages> aps;
+
+ // Parse <query-pkg>...
+ //
+ int argi (2);
+ for (; argi != argc; ++argi)
+ {
+ string a (argv[argi]);
+
+ if (a.compare (0, 2, "--") == 0)
+ break;
+
+ aps.emplace (a, available_packages {});
+ qps.push_back (move (a));
+ }
+
+ // Parse --install [--no-fetch]
+ //
+ bool install (false);
+ bool fetch (true);
+
+ for (; argi != argc; ++argi)
+ {
+ string a (argv[argi]);
+
+ if (a == "--install") install = true;
+ else if (a == "--no-fetch") fetch = false;
+ else break;
+ }
+
+ // Parse the description.
+ //
+ system_package_manager_debian::simulation s;
+
+ for (string l; !eof (getline (cin, l)); )
+ {
+ if (l.empty ())
+ continue;
+
+ size_t p (l.find (':')); assert (p != string::npos);
+ string k (l, 0, p);
+
+ if (k == "manifest")
+ {
+ size_t q (l.rfind (' ')); assert (q != string::npos);
+ string n (l, p + 2, q - p - 2); trim (n);
+ string f (l, q + 1); trim (f);
+
+ auto i (aps.find (n));
+ if (i == aps.end ())
+ fail << "unknown package " << n << " in '" << l << "'";
+
+ i->second.push_back (make_available_from_manifest (n, f));
+ }
+ else if (
+ map<strings, path>* policy =
+ k == "apt-cache-policy" ? &s.apt_cache_policy_ :
+ k == "apt-cache-policy-fetched" ? &s.apt_cache_policy_fetched_ :
+ k == "apt-cache-policy-installed" ? &s.apt_cache_policy_installed_ :
+ nullptr)
+ {
+ size_t q (l.rfind (' ')); assert (q != string::npos);
+ string n (l, p + 2, q - p - 2); trim (n);
+ string f (l, q + 1); trim (f);
+
+ strings ns;
+ for (size_t b (0), e (0); next_word (n, b, e); )
+ ns.push_back (string (n, b, e - b));
+
+ if (f == "!")
+ f.clear ();
+
+ policy->emplace (move (ns), path (move (f)));
+ }
+ else if (map<pair<string, string>, path>* show =
+ k == "apt-cache-show" ? &s.apt_cache_show_ :
+ k == "apt-cache-show-fetched" ? &s.apt_cache_show_fetched_ :
+ nullptr)
+ {
+ size_t q (l.rfind (' ')); assert (q != string::npos);
+ string n (l, p + 2, q - p - 2); trim (n);
+ string f (l, q + 1); trim (f);
+
+ q = n.find (' '); assert (q != string::npos);
+ pair<string, string> nv (string (n, 0, q), string (n, q + 1));
+ trim (nv.second);
+
+ if (f == "!")
+ f.clear ();
+
+ show->emplace (move (nv), path (move (f)));
+ }
+ else if (k == "apt-get-update-fail")
+ {
+ s.apt_get_update_fail_ = true;
+ }
+ else if (k == "apt-get-install-fail")
+ {
+ s.apt_get_install_fail_ = true;
+ }
+ else
+ fail << "unknown keyword '" << k << "' in simulation description";
+ }
+
+ // Fallback to stubs and sort in the version descending order.
+ //
+ for (pair<const string, available_packages>& p: aps)
+ {
+ if (p.second.empty ())
+ p.second.push_back (make_available_stub (p.first));
+
+ sort_available (p.second);
+ }
+
+ system_package_manager_debian m (move (osr),
+ host_triplet,
+ "" /* arch */,
+ nullopt /* progress */,
+ nullopt /* fetch_timeout */,
+ install,
+ fetch,
+ false /* yes */,
+ "sudo");
+ m.simulate_ = &s;
+
+ // Query each package.
+ //
+ for (const string& n: qps)
+ {
+ package_name pn (n);
+
+ const system_package_status* s (*m.status (pn, &aps[n]));
+
+ assert (*m.status (pn, nullptr) == s); // Test caching.
+
+ if (s == nullptr)
+ fail << "no installed " << (install ? "or available " : "")
+ << "system package for " << pn;
+
+ cout << pn << ' ' << s->version
+ << " (" << s->system_name << ' ' << s->system_version << ") ";
+
+ switch (s->status)
+ {
+ case package_status::installed: cout << "installed"; break;
+ case package_status::partially_installed: cout << "part installed"; break;
+ case package_status::not_installed: cout << "not installed"; break;
+ }
+
+ cout << '\n';
+ }
+
+ // Install if requested.
+ //
+ if (install)
+ {
+ assert (argi != argc); // <install-pkg>...
+
+ vector<package_name> ips;
+ for (; argi != argc; ++argi)
+ ips.push_back (package_name (argv[argi]));
+
+ m.install (ips);
+ }
+ }
+ else
+ fail << "unknown command '" << cmd << "'";
+
+ return 0;
+ }
+ catch (const failed&)
+ {
+ return 1;
+ }
+}
+
+int
+main (int argc, char* argv[])
+{
+ return bpkg::main (argc, argv);
+}