From: Sebastian Luther Date: Thu, 5 Aug 2010 13:47:00 +0000 (+0200) Subject: Tests: Add resolver/test_simple and the resolver test infrastructure X-Git-Tag: v2.2_rc68~396 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=099fc66a93ae7bb8a4f3e5b2caeb08426365b923;p=portage.git Tests: Add resolver/test_simple and the resolver test infrastructure --- diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py new file mode 100644 index 000000000..56cdb5f41 --- /dev/null +++ b/pym/portage/tests/resolver/ResolverPlayground.py @@ -0,0 +1,190 @@ +# Copyright 2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from itertools import chain +import tempfile +import portage +from portage import os +from portage.dbapi.vartree import vartree +from portage.dbapi.porttree import portagetree +from portage.dbapi.bintree import binarytree +from portage.dep import Atom +from portage.package.ebuild.config import config +from portage.sets import load_default_config +from portage.versions import catsplit + +from _emerge.create_depgraph_params import create_depgraph_params +from _emerge.depgraph import backtrack_depgraph +from _emerge.RootConfig import RootConfig + +class ResolverPlayground(object): + """ + This class help to create the necessary files on disk and + the needed settings instances, etc. for the resolver to do + it's work. + """ + + def __init__(self, ebuilds={}, installed={}, profile={}): + """ + ebuilds: cpv -> metadata mapping simulating avaiable ebuilds. + installed: cpv -> metadata mapping simulating installed packages. + If a metadata key is missing, it gets a default value. + profile: settings defined by the profile. + """ + self.root = tempfile.mkdtemp() + os.path.sep + self.portdir = os.path.join(self.root, "usr/portage") + self.vdbdir = os.path.join(self.root, "var/db/pkg") + os.makedirs(self.portdir) + os.makedirs(self.vdbdir) + + self._create_ebuilds(ebuilds) + self._create_installed(installed) + self._create_profile(ebuilds, installed, profile) + + self.settings, self.trees = self._load_config() + + self._create_ebuild_manifests(ebuilds) + + def _create_ebuilds(self, ebuilds): + for cpv in ebuilds: + a = Atom("=" + cpv) + ebuild_dir = os.path.join(self.portdir, a.cp) + ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild") + try: + os.makedirs(ebuild_dir) + except os.error: + pass + + metadata = ebuilds[cpv] + eapi = metadata.get("EAPI", 0) + slot = metadata.get("SLOT", 0) + keywords = metadata.get("KEYWORDS", "x86") + iuse = metadata.get("IUSE", "") + depend = metadata.get("DEPEND", "") + rdepend = metadata.get("RDEPEND", None) + pdepend = metadata.get("PDEPEND", None) + + f = open(ebuild_path, "w") + f.write('EAPI="' + str(eapi) + '"\n') + f.write('SLOT="' + str(slot) + '"\n') + f.write('KEYWORDS="' + str(keywords) + '"\n') + f.write('IUSE="' + str(iuse) + '"\n') + f.write('DEPEND="' + str(depend) + '"\n') + if rdepend is not None: + f.write('RDEPEND="' + str(rdepend) + '"\n') + if rdepend is not None: + f.write('PDEPEND="' + str(pdepend) + '"\n') + f.close() + + def _create_ebuild_manifests(self, ebuilds): + for cpv in ebuilds: + a = Atom("=" + cpv) + ebuild_dir = os.path.join(self.portdir, a.cp) + ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild") + + portage.util.noiselimit = -1 + tmpsettings = config(clone=self.settings) + portdb = self.trees[self.root]["porttree"].dbapi + portage.doebuild(ebuild_path, "digest", self.root, tmpsettings, + tree="porttree", mydbapi=portdb) + portage.util.noiselimit = 0 + + def _create_installed(self, installed): + for cpv in installed: + a = Atom("=" + cpv) + vdb_pkg_dir = os.path.join(self.vdbdir, a.cpv) + try: + os.makedirs(vdb_pkg_dir) + except os.error: + pass + + metadata = installed[cpv] + eapi = metadata.get("EAPI", 0) + slot = metadata.get("SLOT", 0) + keywords = metadata.get("KEYWORDS", "~x86") + iuse = metadata.get("IUSE", "") + use = metadata.get("USE", "") + depend = metadata.get("DEPEND", "") + rdepend = metadata.get("RDEPEND", None) + pdepend = metadata.get("PDEPEND", None) + + def write_key(key, value): + f = open(os.path.join(vdb_pkg_dir, key), "w") + f.write(str(value) + "\n") + f.close() + + write_key("EAPI", eapi) + write_key("SLOT", slot) + write_key("KEYWORDS", keywords) + write_key("IUSE", iuse) + write_key("USE", use) + write_key("DEPEND", depend) + if rdepend is not None: + write_key("RDEPEND", rdepend) + if rdepend is not None: + write_key("PDEPEND", pdepend) + + def _create_profile(self, ebuilds, installed, profile): + #Create $PORTDIR/profiles/categories + categories = set() + for cpv in chain(ebuilds.keys(), installed.keys()): + categories.add(catsplit(cpv)[0]) + + profile_dir = os.path.join(self.portdir, "profiles") + try: + os.makedirs(profile_dir) + except os.error: + pass + + categories_file = os.path.join(profile_dir, "categories") + + f = open(categories_file, "w") + for cat in categories: + f.write(cat + "\n") + f.close() + + #Create $PORTDIR/eclass (we fail to digest the ebuilds if it's not there) + os.makedirs(os.path.join(self.portdir, "eclass")) + + if profile: + #This is meant to allow the consumer to set up his own profile, + #with package.mask and what not. + raise NotImplentedError() + + def _load_config(self): + env = { "PORTDIR": self.portdir, "ROOT": self.root, "ACCEPT_KEYWORDS": "x86"} + settings = config(config_root=self.root, target_root=self.root, local_config=False, env=env) + settings.lock() + + trees = { + self.root: { + "virtuals": settings.getvirtuals(), + "vartree": vartree(self.root, categories=settings.categories, settings=settings), + "porttree": portagetree(self.root, settings=settings), + "bintree": binarytree(self.root, os.path.join(self.root, "usr/portage/packages"), settings=settings) + } + } + + for root, root_trees in trees.items(): + settings = root_trees["vartree"].settings + settings._init_dirs() + setconfig = load_default_config(settings, root_trees) + root_trees["root_config"] = RootConfig(settings, root_trees, setconfig) + + return settings, trees + + def run(self, myfiles, myopts={}, myaction=None): + myopts["--pretend"] = True + myopts["--quiet"] = True + myopts["--root"] = self.root + myopts["--config-root"] = self.root + myparams = create_depgraph_params(myopts, myaction) + success, mydepgraph, favorites = backtrack_depgraph( + self.settings, self.trees, myopts, myparams, myaction, myfiles, None) + + if success: + mergelist = [x.cpv for x in mydepgraph._dynamic_config._serialized_tasks_cache] + return True, mergelist + else: + #TODO: Use mydepgraph.display_problems() to return a useful error message + return False, None diff --git a/pym/portage/tests/resolver/__init__.py b/pym/portage/tests/resolver/__init__.py new file mode 100644 index 000000000..21a391aee --- /dev/null +++ b/pym/portage/tests/resolver/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 diff --git a/pym/portage/tests/resolver/__test__ b/pym/portage/tests/resolver/__test__ new file mode 100644 index 000000000..e69de29bb diff --git a/pym/portage/tests/resolver/test_simple.py b/pym/portage/tests/resolver/test_simple.py new file mode 100644 index 000000000..d178e7fb0 --- /dev/null +++ b/pym/portage/tests/resolver/test_simple.py @@ -0,0 +1,32 @@ +# Copyright 2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.tests import TestCase +from portage.tests.resolver.ResolverPlayground import ResolverPlayground + +class SimpleResolverTestCase(TestCase): + + def testSimple(self): + ebuilds = { + "dev-libs/A-1": {}, + "dev-libs/A-2": { "KEYWORDS": "~x86" }, + "dev-libs/B-1.2": {}, + } + installed = { + "dev-libs/B-1.1": {}, + } + + requests = ( + (["dev-libs/A"], {}, None, True, ["dev-libs/A-1"]), + (["=dev-libs/A-2"], {}, None, False, None), + (["dev-libs/B"], {"--noreplace": True}, None, True, []), + (["dev-libs/B"], {"--update": True}, None, True, ["dev-libs/B-1.2"]), + ) + + playground = ResolverPlayground(ebuilds=ebuilds, installed=installed) + + for atoms, options, action, expected_result, expected_mergelist in requests: + success, mergelist = playground.run(atoms, options, action) + self.assertEqual(success, expected_result) + if success: + self.assertEqual(mergelist, expected_mergelist)