def testSlotAbiEmerge(self): debug = False ebuilds = { "dev-libs/glib-1.2.10": { "SLOT": "1" }, "dev-libs/glib-2.30.2": { "EAPI": "4-slot-abi", "SLOT": "2/2.30" }, "dev-libs/glib-2.32.3": { "EAPI": "4-slot-abi", "SLOT": "2/2.32" }, "dev-libs/dbus-glib-0.98": { "EAPI": "4-slot-abi", "DEPEND": "dev-libs/glib:2=", "RDEPEND": "dev-libs/glib:2=" }, } installed = { "dev-libs/glib-1.2.10": { "EAPI": "4-slot-abi", "SLOT": "1" }, "dev-libs/glib-2.30.2": { "EAPI": "4-slot-abi", "SLOT": "2/2.30" }, "dev-libs/dbus-glib-0.98": { "EAPI": "4-slot-abi", "DEPEND": "dev-libs/glib:2/2.30=", "RDEPEND": "dev-libs/glib:2/2.30=" }, } world = ["dev-libs/glib:1", "dev-libs/dbus-glib"] playground = ResolverPlayground(ebuilds=ebuilds, installed=installed, world=world, debug=debug) settings = playground.settings eprefix = settings["EPREFIX"] eroot = settings["EROOT"] trees = playground.trees portdb = trees[eroot]["porttree"].dbapi vardb = trees[eroot]["vartree"].dbapi portdir = settings["PORTDIR"] var_cache_edb = os.path.join(eprefix, "var", "cache", "edb") user_config_dir = os.path.join(eprefix, USER_CONFIG_PATH) package_mask_path = os.path.join(user_config_dir, "package.mask") portage_python = portage._python_interpreter ebuild_cmd = (portage_python, "-Wd", os.path.join(PORTAGE_BIN_PATH, "ebuild")) emerge_cmd = (portage_python, "-Wd", os.path.join(PORTAGE_BIN_PATH, "emerge")) test_ebuild = portdb.findname("dev-libs/dbus-glib-0.98") self.assertFalse(test_ebuild is None) test_commands = ( emerge_cmd + ( "--oneshot", "dev-libs/glib", ), (lambda: "dev-libs/glib:2/2.32=" in vardb.aux_get( "dev-libs/dbus-glib-0.98", ["RDEPEND"])[0], ), (BASH_BINARY, "-c", "echo %s >> %s" % tuple( map(portage._shell_quote, ( ">=dev-libs/glib-2.32", package_mask_path, )))), emerge_cmd + ( "--oneshot", "dev-libs/glib", ), (lambda: "dev-libs/glib:2/2.30=" in vardb.aux_get( "dev-libs/dbus-glib-0.98", ["RDEPEND"])[0], ), ) distdir = playground.distdir pkgdir = playground.pkgdir fake_bin = os.path.join(eprefix, "bin") portage_tmpdir = os.path.join(eprefix, "var", "tmp", "portage") profile_path = settings.profile_path path = os.environ.get("PATH") if path is not None and not path.strip(): path = None if path is None: path = "" else: path = ":" + path path = fake_bin + path pythonpath = os.environ.get("PYTHONPATH") if pythonpath is not None and not pythonpath.strip(): pythonpath = None if pythonpath is not None and \ pythonpath.split(":")[0] == PORTAGE_PYM_PATH: pass else: if pythonpath is None: pythonpath = "" else: pythonpath = ":" + pythonpath pythonpath = PORTAGE_PYM_PATH + pythonpath env = { "PORTAGE_OVERRIDE_EPREFIX": eprefix, "PATH": path, "PORTAGE_PYTHON": portage_python, "PYTHONPATH": pythonpath, } if "__PORTAGE_TEST_HARDLINK_LOCKS" in os.environ: env["__PORTAGE_TEST_HARDLINK_LOCKS"] = \ os.environ["__PORTAGE_TEST_HARDLINK_LOCKS"] dirs = [ distdir, fake_bin, portage_tmpdir, user_config_dir, var_cache_edb ] true_symlinks = ["chown", "chgrp"] true_binary = find_binary("true") self.assertEqual(true_binary is None, False, "true command not found") try: for d in dirs: ensure_dirs(d) for x in true_symlinks: os.symlink(true_binary, os.path.join(fake_bin, x)) with open(os.path.join(var_cache_edb, "counter"), 'wb') as f: f.write(b"100") # non-empty system set keeps --depclean quiet with open(os.path.join(profile_path, "packages"), 'w') as f: f.write("*dev-libs/token-system-pkg") if debug: # The subprocess inherits both stdout and stderr, for # debugging purposes. stdout = None else: # The subprocess inherits stderr so that any warnings # triggered by python -Wd will be visible. stdout = subprocess.PIPE for i, args in enumerate(test_commands): if hasattr(args[0], '__call__'): self.assertTrue(args[0](), "callable at index %s failed" % (i, )) continue proc = subprocess.Popen(args, env=env, stdout=stdout) if debug: proc.wait() else: output = proc.stdout.readlines() proc.wait() proc.stdout.close() if proc.returncode != os.EX_OK: for line in output: sys.stderr.write(_unicode_decode(line)) self.assertEqual(os.EX_OK, proc.returncode, "emerge failed with args %s" % (args, )) finally: playground.cleanup()
def testCircularJsoncppCmakeBootstrapOrDeps(self): ebuilds = { 'dev-libs/jsoncpp-1.9.2': { 'EAPI': '7', 'BDEPEND': '|| ( dev-util/cmake-bootstrap dev-util/cmake )' }, 'dev-util/cmake-bootstrap-3.16.2': { 'EAPI': '7', }, 'dev-util/cmake-3.16.2': { 'EAPI': '7', 'BDEPEND': '>=dev-libs/jsoncpp-0.6.0_rc2:0=', }, } test_cases = ( # Demonstrate bug 703440. It ignores cmake-bootstrap in order to eliminate redundant packages. # # * Error: circular dependencies: # # (dev-libs/jsoncpp-1.9.2:0/0::test_repo, ebuild scheduled for merge) depends on # (dev-util/cmake-3.16.2:0/0::test_repo, ebuild scheduled for merge) (buildtime) # (dev-libs/jsoncpp-1.9.2:0/0::test_repo, ebuild scheduled for merge) (buildtime_slot_op) ResolverPlaygroundTestCase( ['dev-util/cmake'], options={"--backtrack": 0}, circular_dependency_solutions={}, success=False, ), # Demonstrate that backtracking adjusts || preferences in order to solve bug 703440. ResolverPlaygroundTestCase( ['dev-util/cmake'], mergelist=[ 'dev-util/cmake-bootstrap-3.16.2', 'dev-libs/jsoncpp-1.9.2', 'dev-util/cmake-3.16.2' ], success=True, ), ) playground = ResolverPlayground(ebuilds=ebuilds) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup() test_cases = ( # Demonstrate elimination of cmake-bootstrap via --depclean. ResolverPlaygroundTestCase( [], options={'--depclean': True}, success=True, cleanlist=['dev-util/cmake-bootstrap-3.16.2'], ), ) playground = ResolverPlayground(ebuilds=ebuilds, installed=ebuilds, world=['dev-util/cmake']) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testPackageMaskOrder(self): ebuilds = { "dev-libs/A-1": {}, "dev-libs/B-1": {}, "dev-libs/C-1": {}, "dev-libs/D-1": {}, "dev-libs/E-1": {}, } repo_configs = { "test_repo": { "package.mask": ( "dev-libs/A", "dev-libs/C", ), } } profile = { "package.mask": ( "-dev-libs/A", "dev-libs/B", "-dev-libs/B", "dev-libs/D", ), } user_config = { "package.mask": ( "-dev-libs/C", "-dev-libs/D", "dev-libs/E", ), } test_cases = ( ResolverPlaygroundTestCase(["dev-libs/A"], options={"--autounmask": "n"}, success=False), ResolverPlaygroundTestCase(["dev-libs/B"], success=True, mergelist=["dev-libs/B-1"]), ResolverPlaygroundTestCase(["dev-libs/C"], success=True, mergelist=["dev-libs/C-1"]), ResolverPlaygroundTestCase(["dev-libs/D"], success=True, mergelist=["dev-libs/D-1"]), ResolverPlaygroundTestCase(["dev-libs/E"], options={"--autounmask": "n"}, success=False), ) playground = ResolverPlayground( ebuilds=ebuilds, repo_configs=repo_configs, profile=profile, user_config=user_config, ) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testSyncLocal(self): debug = False skip_reason = self._must_skip() if skip_reason: self.portage_skip = skip_reason self.assertFalse(True, skip_reason) return repos_conf = textwrap.dedent(""" [DEFAULT] %(default_keys)s [test_repo] location = %(EPREFIX)s/var/repositories/test_repo sync-type = %(sync-type)s sync-uri = file:/%(EPREFIX)s/var/repositories/test_repo_sync auto-sync = yes %(repo_extra_keys)s """) profile = { "eapi": ("5", ), "package.use.stable.mask": ("dev-libs/A flag", ) } ebuilds = {"dev-libs/A-0": {}} user_config = {'make.conf': ('FEATURES="metadata-transfer"', )} playground = ResolverPlayground(ebuilds=ebuilds, profile=profile, user_config=user_config, debug=debug) settings = playground.settings eprefix = settings["EPREFIX"] eroot = settings["EROOT"] homedir = os.path.join(eroot, "home") distdir = os.path.join(eprefix, "distdir") repo = settings.repositories["test_repo"] metadata_dir = os.path.join(repo.location, "metadata") cmds = {} for cmd in ("emerge", "emaint"): cmds[cmd] = (portage._python_interpreter, "-b", "-Wd", os.path.join(self.bindir, cmd)) git_binary = find_binary("git") git_cmd = (git_binary, ) committer_name = "Gentoo Dev" committer_email = "*****@*****.**" def repos_set_conf(sync_type, dflt_keys=None, xtra_keys=None): env["PORTAGE_REPOSITORIES"] = repos_conf % {\ "EPREFIX": eprefix, "sync-type": sync_type, "default_keys": "" if dflt_keys is None else dflt_keys, "repo_extra_keys": "" if xtra_keys is None else xtra_keys} def alter_ebuild(): with open( os.path.join(repo.location + "_sync", "dev-libs", "A", "A-0.ebuild"), "a") as f: f.write("\n") os.unlink(os.path.join(metadata_dir, 'timestamp.chk')) sync_cmds = ( (homedir, cmds["emerge"] + ("--sync", )), (homedir, lambda: self.assertTrue( os.path.exists(os.path.join(repo.location, "dev-libs", "A")), "dev-libs/A expected, but missing")), (homedir, cmds["emaint"] + ("sync", "-A")), ) rename_repo = ( (homedir, lambda: os.rename(repo.location, repo.location + "_sync")), ) rsync_opts_repos = ( (homedir, alter_ebuild), (homedir, lambda: repos_set_conf( "rsync", None, "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back"))), (homedir, cmds['emerge'] + ("--sync", )), (homedir, lambda: self.assertTrue(os.path.exists(repo.location + "_back"))), (homedir, lambda: shutil.rmtree(repo.location + "_back")), (homedir, lambda: repos_set_conf("rsync")), ) rsync_opts_repos_default = ( (homedir, alter_ebuild), (homedir, lambda: repos_set_conf( "rsync", "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back"))), (homedir, cmds['emerge'] + ("--sync", )), (homedir, lambda: self.assertTrue(os.path.exists(repo.location + "_back"))), (homedir, lambda: shutil.rmtree(repo.location + "_back")), (homedir, lambda: repos_set_conf("rsync")), ) rsync_opts_repos_default_ovr = ( (homedir, alter_ebuild), (homedir, lambda: repos_set_conf( "rsync", "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back_nowhere"), "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back"))), (homedir, cmds['emerge'] + ("--sync", )), (homedir, lambda: self.assertTrue(os.path.exists(repo.location + "_back"))), (homedir, lambda: shutil.rmtree(repo.location + "_back")), (homedir, lambda: repos_set_conf("rsync")), ) rsync_opts_repos_default_cancel = ( (homedir, alter_ebuild), (homedir, lambda: repos_set_conf( "rsync", "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back_nowhere" ), "sync-rsync-extra-opts = ")), (homedir, cmds['emerge'] + ("--sync", )), (homedir, lambda: self.assertFalse(os.path.exists(repo.location + "_back")) ), (homedir, lambda: repos_set_conf("rsync")), ) delete_sync_repo = ((homedir, lambda: shutil.rmtree(repo.location + "_sync")), ) git_repo_create = ( (repo.location, git_cmd + ( "config", "--global", "user.name", committer_name, )), (repo.location, git_cmd + ( "config", "--global", "user.email", committer_email, )), (repo.location, git_cmd + ("init-db", )), (repo.location, git_cmd + ("add", ".")), (repo.location, git_cmd + ("commit", "-a", "-m", "add whole repo")), ) sync_type_git = ((homedir, lambda: repos_set_conf("git")), ) pythonpath = os.environ.get("PYTHONPATH") if pythonpath is not None and not pythonpath.strip(): pythonpath = None if pythonpath is not None and \ pythonpath.split(":")[0] == PORTAGE_PYM_PATH: pass else: if pythonpath is None: pythonpath = "" else: pythonpath = ":" + pythonpath pythonpath = PORTAGE_PYM_PATH + pythonpath env = { "PORTAGE_OVERRIDE_EPREFIX": eprefix, "DISTDIR": distdir, "GENTOO_COMMITTER_NAME": committer_name, "GENTOO_COMMITTER_EMAIL": committer_email, "HOME": homedir, "PATH": os.environ["PATH"], "PORTAGE_GRPNAME": os.environ["PORTAGE_GRPNAME"], "PORTAGE_USERNAME": os.environ["PORTAGE_USERNAME"], "PYTHONDONTWRITEBYTECODE": os.environ.get("PYTHONDONTWRITEBYTECODE", ""), "PYTHONPATH": pythonpath, } repos_set_conf("rsync") if os.environ.get("SANDBOX_ON") == "1": # avoid problems from nested sandbox instances env["FEATURES"] = "-sandbox -usersandbox" dirs = [homedir, metadata_dir] try: for d in dirs: ensure_dirs(d) timestamp_path = os.path.join(metadata_dir, 'timestamp.chk') with open(timestamp_path, 'w') as f: f.write(time.strftime('%s\n' % TIMESTAMP_FORMAT, time.gmtime())) if debug: # The subprocess inherits both stdout and stderr, for # debugging purposes. stdout = None else: # The subprocess inherits stderr so that any warnings # triggered by python -Wd will be visible. stdout = subprocess.PIPE for cwd, cmd in rename_repo + sync_cmds + \ rsync_opts_repos + rsync_opts_repos_default + \ rsync_opts_repos_default_ovr + rsync_opts_repos_default_cancel + \ delete_sync_repo + git_repo_create + sync_type_git + \ rename_repo + sync_cmds: if hasattr(cmd, '__call__'): cmd() continue abs_cwd = os.path.join(repo.location, cwd) proc = subprocess.Popen(cmd, cwd=abs_cwd, env=env, stdout=stdout) if debug: proc.wait() else: output = proc.stdout.readlines() proc.wait() proc.stdout.close() if proc.returncode != os.EX_OK: for line in output: sys.stderr.write(_unicode_decode(line)) self.assertEqual(os.EX_OK, proc.returncode, "%s failed in %s" % ( cmd, cwd, )) finally: playground.cleanup()
def testSonameAutoUnmask(self): binpkgs = { "dev-libs/icu-49": { "KEYWORDS": "x86", "PROVIDES": "x86_32: libicu.so.49", }, "dev-libs/icu-4.8": { "KEYWORDS": "x86", "PROVIDES": "x86_32: libicu.so.48", }, "dev-libs/libxml2-2.7.8": { "KEYWORDS": "~x86", "DEPEND": "dev-libs/icu", "RDEPEND": "dev-libs/icu", "REQUIRES": "x86_32: libicu.so.49", }, } installed = { "dev-libs/icu-4.8": { "KEYWORDS": "x86", "PROVIDES": "x86_32: libicu.so.48", }, "dev-libs/libxml2-2.7.8": { "KEYWORDS": "~x86", "DEPEND": "dev-libs/icu", "RDEPEND": "dev-libs/icu", "REQUIRES": "x86_32: libicu.so.48", }, } world = ["dev-libs/libxml2"] test_cases = ( ResolverPlaygroundTestCase( ["dev-libs/icu"], options={ "--autounmask": True, "--ignore-soname-deps": "n", "--oneshot": True, "--usepkgonly": True, }, success=False, mergelist=[ "[binary]dev-libs/icu-49", "[binary]dev-libs/libxml2-2.7.8" ], unstable_keywords=["dev-libs/libxml2-2.7.8"], ), ResolverPlaygroundTestCase( ["dev-libs/icu"], options={ "--autounmask": True, "--ignore-soname-deps": "y", "--oneshot": True, "--usepkgonly": True, }, success=True, mergelist=["[binary]dev-libs/icu-49"], ), # Test that dev-libs/icu-49 update is skipped due to # dev-libs/libxml2-2.7.8 being masked by KEYWORDS. Note # that this result is questionable, since the installed # dev-libs/libxml2-2.7.8 instance is also masked! ResolverPlaygroundTestCase( ["@world"], options={ "--autounmask": True, "--deep": True, "--ignore-soname-deps": "n", "--update": True, "--usepkgonly": True, }, success=True, mergelist=[], ), ) playground = ResolverPlayground(binpkgs=binpkgs, installed=installed, world=world, debug=False) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.debug = False playground.cleanup()
def testSonameSlotConflictMassRebuild(self): """ Bug 486580 Before this bug was fixed, emerge would backtrack for each package that needs a rebuild. This could cause it to hit the backtrack limit and not rebuild all needed packages. """ binpkgs = { "app-misc/A-1": { "DEPEND": "app-misc/B", "RDEPEND": "app-misc/B", "REQUIRES": "x86_32: libB-2.so", }, "app-misc/B-1": { "SLOT": "1", "PROVIDES": "x86_32: libB-1.so", }, "app-misc/B-2": { "SLOT": "2", "PROVIDES": "x86_32: libB-2.so", }, } installed = { "app-misc/B-1": { "SLOT": "1", "PROVIDES": "x86_32: libB-1.so", }, } expected_mergelist = ["[binary]app-misc/A-1", "[binary]app-misc/B-2"] for i in range(5): binpkgs["app-misc/C%sC-1" % i] = { "DEPEND": "app-misc/B", "RDEPEND": "app-misc/B", "REQUIRES": "x86_32: libB-2.so", } installed["app-misc/C%sC-1" % i] = { "DEPEND": "app-misc/B", "RDEPEND": "app-misc/B", "REQUIRES": "x86_32: libB-1.so", } for x in ("DEPEND", "RDEPEND"): binpkgs["app-misc/A-1"][x] += " app-misc/C%sC" % i expected_mergelist.append("[binary]app-misc/C%sC-1" % i) test_cases = ( ResolverPlaygroundTestCase( ["app-misc/A"], ignore_mergelist_order=True, all_permutations=True, options={ "--backtrack": 3, "--deep": True, "--ignore-soname-deps": "n", "--update": True, "--usepkgonly": True, }, success=True, mergelist=expected_mergelist, ), ) world = [] playground = ResolverPlayground( binpkgs=binpkgs, installed=installed, world=world, debug=False ) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.debug = False playground.cleanup()
def testImageMagickUpdate(self): ebuilds = { "app-misc/A-1": { "EAPI": "6", "DEPEND": "app-misc/B", "RDEPEND": "app-misc/C", }, "app-misc/B-1": { "EAPI": "6" }, "app-misc/B-2": { "EAPI": "6", }, "app-misc/C-1": { "EAPI": "6", "DEPEND": "app-misc/D", }, "app-misc/C-2": { "EAPI": "6", "DEPEND": "app-misc/D", }, "app-misc/D-1": { "EAPI": "6", }, "app-misc/D-2": { "EAPI": "6", }, } installed = { "app-misc/A-1": { "EAPI": "6", "DEPEND": "app-misc/B", "RDEPEND": "app-misc/C", }, "app-misc/B-1": { "EAPI": "6", }, "app-misc/C-1": { "EAPI": "6", "DEPEND": "app-misc/D", }, "app-misc/D-1": { "EAPI": "6", }, } binpkgs = { "app-misc/A-1": { "EAPI": "6", "DEPEND": "app-misc/B", "RDEPEND": "app-misc/C", }, "app-misc/B-1": { "EAPI": "6", }, "app-misc/B-2": { "EAPI": "6", }, "app-misc/C-1": { "EAPI": "6", "DEPEND": "app-misc/D", }, "app-misc/C-2": { "EAPI": "6", "DEPEND": "app-misc/D", }, "app-misc/D-1": { "EAPI": "6", }, "app-misc/D-2": { "EAPI": "6", }, } world = ("app-misc/A", ) test_cases = ( # Enable --with-bdeps automatically when # --usepkg has not been specified. ResolverPlaygroundTestCase(["@world"], options={ "--update": True, "--deep": True, }, success=True, ambiguous_merge_order=True, mergelist=[ "app-misc/D-2", ("app-misc/B-2", "app-misc/C-2"), ]), # Use --with-bdeps-auto=n to prevent --with-bdeps # from being enabled automatically. ResolverPlaygroundTestCase(["@world"], options={ "--update": True, "--deep": True, "--with-bdeps-auto": "n", }, success=True, mergelist=[ "app-misc/D-2", "app-misc/C-2", ]), # Do not enable --with-bdeps automatically when # --usepkg has been specified, since many users of binary # packages do not want unnecessary build time dependencies # installed. In this case we miss an update to # app-misc/D-2, since DEPEND is not pulled in for # the [binary]app-misc/C-2 update. ResolverPlaygroundTestCase(["@world"], options={ "--update": True, "--deep": True, "--usepkg": True, }, success=True, mergelist=[ "[binary]app-misc/C-2", ]), # Use --with-bdeps=y to pull in build-time dependencies of # binary packages. ResolverPlaygroundTestCase( ["@world"], options={ "--update": True, "--deep": True, "--usepkg": True, "--with-bdeps": "y", }, success=True, ambiguous_merge_order=True, mergelist=[ ( "[binary]app-misc/D-2", "[binary]app-misc/B-2", "[binary]app-misc/C-2", ), ]), # For --depclean, do not remove build-time dependencies by # default. Specify --with-bdeps-auto=n, in order to # demonstrate that it does not affect removal actions. ResolverPlaygroundTestCase( [], options={ "--depclean": True, "--with-bdeps-auto": "n", }, success=True, cleanlist=[], ), # For --depclean, remove build-time dependencies if # --with-bdeps=n has been specified. ResolverPlaygroundTestCase( [], options={ "--depclean": True, "--with-bdeps": "n", }, success=True, ignore_cleanlist_order=True, cleanlist=[ "app-misc/D-1", "app-misc/B-1", ], ), ) playground = ResolverPlayground(debug=False, ebuilds=ebuilds, installed=installed, binpkgs=binpkgs, world=world) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: # Disable debug so that cleanup works. playground.debug = False playground.cleanup()
def testDoebuild(self): """ Invoke portage.doebuild() with the fd_pipes parameter, and check that the expected output appears in the pipe. This functionality is not used by portage internally, but it is supported for API consumers (see bug #475812). """ output_fd = 200 ebuild_body = ['S=${WORKDIR}'] for phase_func in ('pkg_info', 'pkg_nofetch', 'pkg_pretend', 'pkg_setup', 'src_unpack', 'src_prepare', 'src_configure', 'src_compile', 'src_test', 'src_install'): ebuild_body.append(('%s() { echo ${EBUILD_PHASE}' ' 1>&%s; }') % (phase_func, output_fd)) ebuild_body.append('') ebuild_body = '\n'.join(ebuild_body) ebuilds = { 'app-misct/foo-1': { 'EAPI': '5', "MISC_CONTENT": ebuild_body, } } # Override things that may be unavailable, or may have portability # issues when running tests in exotic environments. # prepstrip - bug #447810 (bash read builtin EINTR problem) true_symlinks = ("find", "prepstrip", "sed", "scanelf") true_binary = portage.process.find_binary("true") self.assertEqual(true_binary is None, False, "true command not found") dev_null = open(os.devnull, 'wb') playground = ResolverPlayground(ebuilds=ebuilds) try: QueryCommand._db = playground.trees root_config = playground.trees[playground.eroot]['root_config'] portdb = root_config.trees["porttree"].dbapi settings = portage.config(clone=playground.settings) if "__PORTAGE_TEST_HARDLINK_LOCKS" in os.environ: settings["__PORTAGE_TEST_HARDLINK_LOCKS"] = \ os.environ["__PORTAGE_TEST_HARDLINK_LOCKS"] settings.backup_changes("__PORTAGE_TEST_HARDLINK_LOCKS") settings.features.add("noauto") settings.features.add("test") settings['PORTAGE_PYTHON'] = portage._python_interpreter settings['PORTAGE_QUIET'] = "1" settings['PYTHONDONTWRITEBYTECODE'] = os.environ.get( "PYTHONDONTWRITEBYTECODE", "") fake_bin = os.path.join(settings["EPREFIX"], "bin") portage.util.ensure_dirs(fake_bin) for x in true_symlinks: os.symlink(true_binary, os.path.join(fake_bin, x)) settings["__PORTAGE_TEST_PATH_OVERRIDE"] = fake_bin settings.backup_changes("__PORTAGE_TEST_PATH_OVERRIDE") cpv = 'app-misct/foo-1' metadata = dict( zip(Package.metadata_keys, portdb.aux_get(cpv, Package.metadata_keys))) pkg = Package(built=False, cpv=cpv, installed=False, metadata=metadata, root_config=root_config, type_name='ebuild') settings.setcpv(pkg) ebuildpath = portdb.findname(cpv) self.assertNotEqual(ebuildpath, None) for phase in ('info', 'nofetch', 'pretend', 'setup', 'unpack', 'prepare', 'configure', 'compile', 'test', 'install', 'qmerge', 'clean', 'merge'): pr, pw = os.pipe() producer = DoebuildProcess(doebuild_pargs=(ebuildpath, phase), doebuild_kwargs={ "settings": settings, "mydbapi": portdb, "tree": "porttree", "vartree": root_config.trees["vartree"], "fd_pipes": { 1: dev_null.fileno(), 2: dev_null.fileno(), output_fd: pw, }, "prev_mtimes": {} }) consumer = PipeReader(input_files={"producer": pr}) task_scheduler = TaskScheduler(iter([producer, consumer]), max_jobs=2) try: task_scheduler.start() finally: # PipeReader closes pr os.close(pw) task_scheduler.wait() output = portage._unicode_decode( consumer.getvalue()).rstrip("\n") if task_scheduler.returncode != os.EX_OK: portage.writemsg(output, noiselevel=-1) self.assertEqual(task_scheduler.returncode, os.EX_OK) if phase not in ('clean', 'merge', 'qmerge'): self.assertEqual(phase, output) finally: dev_null.close() playground.cleanup() QueryCommand._db = None
def testMergelistOutput(self): """ This test doesn't check if the output is correct, but makes sure that we don't backtrace somewhere in the output code. """ ebuilds = { "dev-libs/A-1": { "DEPEND": "dev-libs/B dev-libs/C", "IUSE": "+foo", "EAPI": 1 }, "dev-libs/B-1": { "DEPEND": "dev-libs/D", "IUSE": "foo +bar", "EAPI": 1 }, "dev-libs/C-1": { "DEPEND": "dev-libs/E", "IUSE": "foo bar" }, "dev-libs/D-1": { "IUSE": "" }, "dev-libs/E-1": {}, #reinstall for flags "dev-libs/Z-1": { "IUSE": "+foo", "EAPI": 1 }, "dev-libs/Y-1": { "IUSE": "foo", "EAPI": 1 }, "dev-libs/X-1": {}, "dev-libs/W-1": { "IUSE": "+foo", "EAPI": 1 }, } installed = { "dev-libs/Z-1": { "USE": "", "IUSE": "foo" }, "dev-libs/Y-1": { "USE": "foo", "IUSE": "+foo", "EAPI": 1 }, "dev-libs/X-1": { "USE": "foo", "IUSE": "+foo", "EAPI": 1 }, "dev-libs/W-1": {}, } option_cobos = ( (), ("verbose", ), ("tree", ), ( "tree", "unordered-display", ), ("verbose", ), ( "verbose", "tree", ), ( "verbose", "tree", "unordered-display", ), ) test_cases = [] for options in option_cobos: testcase_opts = {} for opt in options: testcase_opts["--" + opt] = True test_cases.append( ResolverPlaygroundTestCase(["dev-libs/A"], options=testcase_opts, success=True, ignore_mergelist_order=True, mergelist=[ "dev-libs/D-1", "dev-libs/E-1", "dev-libs/C-1", "dev-libs/B-1", "dev-libs/A-1" ])) test_cases.append( ResolverPlaygroundTestCase(["dev-libs/Z"], options=testcase_opts, success=True, mergelist=["dev-libs/Z-1"])) test_cases.append( ResolverPlaygroundTestCase(["dev-libs/Y"], options=testcase_opts, success=True, mergelist=["dev-libs/Y-1"])) test_cases.append( ResolverPlaygroundTestCase(["dev-libs/X"], options=testcase_opts, success=True, mergelist=["dev-libs/X-1"])) test_cases.append( ResolverPlaygroundTestCase(["dev-libs/W"], options=testcase_opts, success=True, mergelist=["dev-libs/W-1"])) playground = ResolverPlayground(ebuilds=ebuilds, installed=installed) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testSlotConflictUpdate(self): ebuilds = { "app-text/podofo-0.9.2": { "EAPI": "5", "RDEPEND": "dev-util/boost-build" }, "dev-cpp/libcmis-0.3.1": { "EAPI": "5", "RDEPEND": "dev-libs/boost:=" }, "dev-libs/boost-1.53.0": { "EAPI": "5", "SLOT": "0/1.53", "RDEPEND": "=dev-util/boost-build-1.53.0", }, "dev-libs/boost-1.52.0": { "EAPI": "5", "SLOT": "0/1.52", "RDEPEND": "=dev-util/boost-build-1.52.0", }, "dev-util/boost-build-1.53.0": { "EAPI": "5", "SLOT": "0" }, "dev-util/boost-build-1.52.0": { "EAPI": "5", "SLOT": "0" }, } installed = { "app-text/podofo-0.9.2": { "EAPI": "5", "RDEPEND": "dev-util/boost-build" }, "dev-cpp/libcmis-0.3.1": { "EAPI": "5", "RDEPEND": "dev-libs/boost:0/1.52=" }, "dev-util/boost-build-1.52.0": { "EAPI": "5", "SLOT": "0" }, "dev-libs/boost-1.52.0": { "EAPI": "5", "SLOT": "0/1.52", "RDEPEND": "=dev-util/boost-build-1.52.0", }, } world = ["dev-cpp/libcmis", "dev-libs/boost", "app-text/podofo"] test_cases = ( # In order to avoid a missed update, first mask lower # versions that conflict with higher versions. Note that # this behavior makes SlotConflictMaskUpdateTestCase # fail. ResolverPlaygroundTestCase( ["@world"], all_permutations=True, options={ "--update": True, "--deep": True }, success=True, mergelist=[ "dev-util/boost-build-1.53.0", "dev-libs/boost-1.53.0", "dev-cpp/libcmis-0.3.1", ], ), ) playground = ResolverPlayground(ebuilds=ebuilds, installed=installed, world=world, debug=False) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testSimple(self): debug = False skip_reason = self._must_skip() if skip_reason: self.portage_skip = skip_reason self.assertFalse(True, skip_reason) return copyright_header = """# Copyright 1999-%s Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ """ % time.gmtime().tm_year repo_configs = { "test_repo": { "layout.conf": ("update-changelog = true", ), } } profiles = ( ("x86", "default/linux/x86/test_profile", "stable"), ("x86", "default/linux/x86/test_dev", "dev"), ("x86", "default/linux/x86/test_exp", "exp"), ) profile = { "eapi": ("5", ), "package.use.stable.mask": ("dev-libs/A flag", ) } ebuilds = { "dev-libs/A-0": { "COPYRIGHT_HEADER": copyright_header, "DESCRIPTION": "Desc goes here", "EAPI": "5", "HOMEPAGE": "http://example.com", "IUSE": "flag", "KEYWORDS": "x86", "LICENSE": "GPL-2", "RDEPEND": "flag? ( dev-libs/B[flag] )", }, "dev-libs/A-1": { "COPYRIGHT_HEADER": copyright_header, "DESCRIPTION": "Desc goes here", "EAPI": "4", "HOMEPAGE": "http://example.com", "IUSE": "flag", "KEYWORDS": "~x86", "LICENSE": "GPL-2", "RDEPEND": "flag? ( dev-libs/B[flag] )", }, "dev-libs/B-1": { "COPYRIGHT_HEADER": copyright_header, "DESCRIPTION": "Desc goes here", "EAPI": "4", "HOMEPAGE": "http://example.com", "IUSE": "flag", "KEYWORDS": "~x86", "LICENSE": "GPL-2", }, "dev-libs/C-0": { "COPYRIGHT_HEADER": copyright_header, "DESCRIPTION": "Desc goes here", "EAPI": "4", "HOMEPAGE": "http://example.com", "IUSE": "flag", # must be unstable, since dev-libs/A[flag] is stable masked "KEYWORDS": "~x86", "LICENSE": "GPL-2", "RDEPEND": "flag? ( dev-libs/A[flag] )", }, } licenses = ["GPL-2"] arch_list = ["x86"] metadata_xsd = os.path.join(REPOMAN_BASE_PATH, "cnf/metadata.xsd") metadata_xml_files = ( ( "dev-libs/A", { "flags": "<flag name='flag' restrict='>=dev-libs/A-0'>Description of how USE='flag' affects this package</flag>", }, ), ( "dev-libs/B", { "flags": "<flag name='flag'>Description of how USE='flag' affects this package</flag>", }, ), ( "dev-libs/C", { "flags": "<flag name='flag'>Description of how USE='flag' affects this package</flag>", }, ), ) use_desc = (("flag", "Description of how USE='flag' affects packages"), ) playground = ResolverPlayground(ebuilds=ebuilds, profile=profile, repo_configs=repo_configs, debug=debug) settings = playground.settings eprefix = settings["EPREFIX"] eroot = settings["EROOT"] portdb = playground.trees[playground.eroot]["porttree"].dbapi homedir = os.path.join(eroot, "home") distdir = os.path.join(eprefix, "distdir") test_repo_location = settings.repositories["test_repo"].location profiles_dir = os.path.join(test_repo_location, "profiles") license_dir = os.path.join(test_repo_location, "licenses") repoman_cmd = (portage._python_interpreter, "-b", "-Wd", os.path.join(self.bindir, "repoman")) git_binary = find_binary("git") git_cmd = (git_binary, ) cp_binary = find_binary("cp") self.assertEqual(cp_binary is None, False, "cp command not found") cp_cmd = (cp_binary, ) test_ebuild = portdb.findname("dev-libs/A-1") self.assertFalse(test_ebuild is None) committer_name = "Gentoo Dev" committer_email = "*****@*****.**" git_test = ( ("", repoman_cmd + ("manifest", )), ("", git_cmd + ( "config", "--global", "user.name", committer_name, )), ("", git_cmd + ( "config", "--global", "user.email", committer_email, )), ("", git_cmd + ("init-db", )), ("", git_cmd + ("add", ".")), ("", git_cmd + ("commit", "-a", "-m", "add whole repo")), ("", repoman_cmd + ("full", "-d")), ("", cp_cmd + (test_ebuild, test_ebuild[:-8] + "2.ebuild")), ("", git_cmd + ("add", test_ebuild[:-8] + "2.ebuild")), ("", repoman_cmd + ("commit", "-m", "bump to version 2")), ("", cp_cmd + (test_ebuild, test_ebuild[:-8] + "3.ebuild")), ("", git_cmd + ("add", test_ebuild[:-8] + "3.ebuild")), ("dev-libs", repoman_cmd + ("commit", "-m", "bump to version 3")), ("", cp_cmd + (test_ebuild, test_ebuild[:-8] + "4.ebuild")), ("", git_cmd + ("add", test_ebuild[:-8] + "4.ebuild")), ("dev-libs/A", repoman_cmd + ("commit", "-m", "bump to version 4")), ) pythonpath = os.environ.get("PYTHONPATH") if pythonpath is not None and not pythonpath.strip(): pythonpath = None if pythonpath is not None and \ pythonpath.split(":")[0] == PORTAGE_PYM_PATH: pass else: if pythonpath is None: pythonpath = "" else: pythonpath = ":" + pythonpath pythonpath = PORTAGE_PYM_PATH + pythonpath env = { "PORTAGE_OVERRIDE_EPREFIX": eprefix, "DISTDIR": distdir, "GENTOO_COMMITTER_NAME": committer_name, "GENTOO_COMMITTER_EMAIL": committer_email, "HOME": homedir, "PATH": os.environ["PATH"], "PORTAGE_GRPNAME": os.environ["PORTAGE_GRPNAME"], "PORTAGE_USERNAME": os.environ["PORTAGE_USERNAME"], "PORTAGE_REPOSITORIES": settings.repositories.config_string(), "PYTHONDONTWRITEBYTECODE": os.environ.get("PYTHONDONTWRITEBYTECODE", ""), "PYTHONPATH": pythonpath, } if os.environ.get("SANDBOX_ON") == "1": # avoid problems from nested sandbox instances env["FEATURES"] = "-sandbox -usersandbox" dirs = [homedir, license_dir, profiles_dir, distdir] try: for d in dirs: ensure_dirs(d) with open(os.path.join(test_repo_location, "skel.ChangeLog"), 'w') as f: f.write(copyright_header) with open(os.path.join(profiles_dir, "profiles.desc"), 'w') as f: for x in profiles: f.write("%s %s %s\n" % x) # ResolverPlayground only created the first profile, # so create the remaining ones. for x in profiles[1:]: sub_profile_dir = os.path.join(profiles_dir, x[1]) ensure_dirs(sub_profile_dir) for config_file, lines in profile.items(): file_name = os.path.join(sub_profile_dir, config_file) with open(file_name, "w") as f: for line in lines: f.write("%s\n" % line) for x in licenses: open(os.path.join(license_dir, x), 'wb').close() with open(os.path.join(profiles_dir, "arch.list"), 'w') as f: for x in arch_list: f.write("%s\n" % x) with open(os.path.join(profiles_dir, "use.desc"), 'w') as f: for k, v in use_desc: f.write("%s - %s\n" % (k, v)) for cp, xml_data in metadata_xml_files: with open(os.path.join(test_repo_location, cp, "metadata.xml"), 'w') as f: f.write(playground.metadata_xml_template % xml_data) # Use a symlink to test_repo, in order to trigger bugs # involving canonical vs. non-canonical paths. test_repo_symlink = os.path.join(eroot, "test_repo_symlink") os.symlink(test_repo_location, test_repo_symlink) metadata_xsd_dest = os.path.join( test_repo_location, 'metadata/xml-schema/metadata.xsd') os.makedirs(os.path.dirname(metadata_xsd_dest)) os.symlink(metadata_xsd, metadata_xsd_dest) if debug: # The subprocess inherits both stdout and stderr, for # debugging purposes. stdout = None else: # The subprocess inherits stderr so that any warnings # triggered by python -Wd will be visible. stdout = subprocess.PIPE for cwd in ("", "dev-libs", "dev-libs/A", "dev-libs/B"): abs_cwd = os.path.join(test_repo_symlink, cwd) proc = subprocess.Popen(repoman_cmd + ("full", ), cwd=abs_cwd, env=env, stdout=stdout) if debug: proc.wait() else: output = proc.stdout.readlines() proc.wait() proc.stdout.close() if proc.returncode != os.EX_OK: for line in output: sys.stderr.write(_unicode_decode(line)) self.assertEqual(os.EX_OK, proc.returncode, "repoman failed in %s" % (cwd, )) if git_binary is not None: for cwd, cmd in git_test: abs_cwd = os.path.join(test_repo_symlink, cwd) proc = subprocess.Popen(cmd, cwd=abs_cwd, env=env, stdout=stdout) if debug: proc.wait() else: output = proc.stdout.readlines() proc.wait() proc.stdout.close() if proc.returncode != os.EX_OK: for line in output: sys.stderr.write(_unicode_decode(line)) self.assertEqual(os.EX_OK, proc.returncode, "%s failed in %s" % ( cmd, cwd, )) finally: playground.cleanup()
def testSonameSkipUpdate(self): binpkgs = { "app-misc/A-1": { "RDEPEND": "dev-libs/B", "DEPEND": "dev-libs/B", "REQUIRES": "x86_32: libB.so.1", }, "dev-libs/B-2": { "PROVIDES": "x86_32: libB.so.2", }, "dev-libs/B-1": { "PROVIDES": "x86_32: libB.so.1", }, } installed = { "app-misc/A-1": { "RDEPEND": "dev-libs/B", "DEPEND": "dev-libs/B", "REQUIRES": "x86_32: libB.so.1", }, "dev-libs/B-1": { "PROVIDES": "x86_32: libB.so.1", }, } world = ("app-misc/A", ) test_cases = ( # Test that --ignore-soname-deps allows the upgrade, # even though it will break an soname dependency of # app-misc/A-1. ResolverPlaygroundTestCase( ["@world"], options={ "--deep": True, "--ignore-soname-deps": "y", "--update": True, "--usepkgonly": True, }, success=True, mergelist=[ "[binary]dev-libs/B-2", ], ), # Test that upgrade to B-2 is skipped with --usepkgonly # because it will break an soname dependency that # cannot be satisfied by the available binary packages. ResolverPlaygroundTestCase( ["@world"], options={ "--deep": True, "--ignore-soname-deps": "n", "--update": True, "--usepkgonly": True, }, success=True, mergelist=[], ), ) playground = ResolverPlayground(debug=False, binpkgs=binpkgs, installed=installed, world=world) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: # Disable debug so that cleanup works. playground.debug = False playground.cleanup()
def testOrChoices(self): ebuilds = { "dev-lang/vala-0.20.0": { "EAPI": "5", "SLOT": "0.20" }, "dev-lang/vala-0.18.0": { "EAPI": "5", "SLOT": "0.18" }, #"dev-libs/gobject-introspection-1.36.0" : { # "EAPI": "5", # "RDEPEND" : "!<dev-lang/vala-0.20.0", #}, "dev-libs/gobject-introspection-1.34.0": { "EAPI": "5" }, "sys-apps/systemd-ui-2": { "EAPI": "5", "RDEPEND": "|| ( dev-lang/vala:0.20 dev-lang/vala:0.18 )" }, } installed = { "dev-lang/vala-0.18.0": { "EAPI": "5", "SLOT": "0.18" }, "dev-libs/gobject-introspection-1.34.0": { "EAPI": "5" }, "sys-apps/systemd-ui-2": { "EAPI": "5", "RDEPEND": "|| ( dev-lang/vala:0.20 dev-lang/vala:0.18 )" }, } world = ["dev-libs/gobject-introspection", "sys-apps/systemd-ui"] test_cases = ( # Demonstrate that vala:0.20 update is pulled in, for bug #478188 ResolverPlaygroundTestCase(["@world"], options={ "--update": True, "--deep": True }, success=True, all_permutations=True, mergelist=['dev-lang/vala-0.20.0']), # Verify that vala:0.20 is not pulled in without --deep ResolverPlaygroundTestCase(["@world"], options={"--update": True}, success=True, all_permutations=True, mergelist=[]), # Verify that vala:0.20 is not pulled in without --update ResolverPlaygroundTestCase(["@world"], options={ "--selective": True, "--deep": True }, success=True, all_permutations=True, mergelist=[]), ) playground = ResolverPlayground(ebuilds=ebuilds, installed=installed, world=world) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testSimple(self): debug = False install_something = """ S="${WORKDIR}" pkg_pretend() { einfo "called pkg_pretend for $CATEGORY/$PF" } src_install() { einfo "installing something..." insinto /usr/lib/${P} echo "blah blah blah" > "${T}"/regular-file doins "${T}"/regular-file dosym regular-file /usr/lib/${P}/symlink || die # Test CONFIG_PROTECT insinto /etc newins "${T}"/regular-file ${PN}-${SLOT%/*} # Test code for bug #381629, using a copyright symbol encoded with latin-1. # We use $(printf "\\xa9") rather than $'\\xa9', since printf apparently # works in any case, while $'\\xa9' transforms to \\xef\\xbf\\xbd under # some conditions. TODO: Find out why it transforms to \\xef\\xbf\\xbd when # running tests for Python 3.2 (even though it's bash that is ultimately # responsible for performing the transformation). local latin_1_dir=/usr/lib/${P}/latin-1-$(printf "\\xa9")-directory insinto "${latin_1_dir}" echo "blah blah blah" > "${T}"/latin-1-$(printf "\\xa9")-regular-file || die doins "${T}"/latin-1-$(printf "\\xa9")-regular-file dosym latin-1-$(printf "\\xa9")-regular-file ${latin_1_dir}/latin-1-$(printf "\\xa9")-symlink || die call_has_and_best_version } pkg_config() { einfo "called pkg_config for $CATEGORY/$PF" } pkg_info() { einfo "called pkg_info for $CATEGORY/$PF" } pkg_preinst() { if ! ___eapi_best_version_and_has_version_support_-b_-d_-r; then # The BROOT variable is unset during pkg_* phases for EAPI 7, # therefore best/has_version -b is expected to fail if we attempt # to call it for EAPI 7 here. call_has_and_best_version fi } call_has_and_best_version() { local root_arg if ___eapi_best_version_and_has_version_support_-b_-d_-r; then root_arg="-b" else root_arg="--host-root" fi einfo "called ${EBUILD_PHASE_FUNC} for $CATEGORY/$PF" einfo "EPREFIX=${EPREFIX}" einfo "PORTAGE_OVERRIDE_EPREFIX=${PORTAGE_OVERRIDE_EPREFIX}" einfo "ROOT=${ROOT}" einfo "EROOT=${EROOT}" einfo "SYSROOT=${SYSROOT}" einfo "ESYSROOT=${ESYSROOT}" einfo "BROOT=${BROOT}" # Test that has_version and best_version work correctly with # prefix (involves internal ROOT -> EROOT calculation in order # to support ROOT override via the environment with EAPIs 3 # and later which support prefix). if has_version $CATEGORY/$PN:$SLOT ; then einfo "has_version detects an installed instance of $CATEGORY/$PN:$SLOT" einfo "best_version reports that the installed instance is $(best_version $CATEGORY/$PN:$SLOT)" else einfo "has_version does not detect an installed instance of $CATEGORY/$PN:$SLOT" fi if [[ ${EPREFIX} != ${PORTAGE_OVERRIDE_EPREFIX} ]] ; then if has_version ${root_arg} $CATEGORY/$PN:$SLOT ; then einfo "has_version ${root_arg} detects an installed instance of $CATEGORY/$PN:$SLOT" einfo "best_version ${root_arg} reports that the installed instance is $(best_version ${root_arg} $CATEGORY/$PN:$SLOT)" else einfo "has_version ${root_arg} does not detect an installed instance of $CATEGORY/$PN:$SLOT" fi fi } """ ebuilds = { "dev-libs/A-1": { "EAPI" : "5", "IUSE" : "+flag", "KEYWORDS": "x86", "LICENSE": "GPL-2", "MISC_CONTENT": install_something, "RDEPEND": "flag? ( dev-libs/B[flag] )", }, "dev-libs/B-1": { "EAPI" : "5", "IUSE" : "+flag", "KEYWORDS": "x86", "LICENSE": "GPL-2", "MISC_CONTENT": install_something, }, "dev-libs/C-1": { "EAPI" : "7", "KEYWORDS": "~x86", "RDEPEND": "dev-libs/D[flag]", "MISC_CONTENT": install_something, }, "dev-libs/D-1": { "EAPI" : "7", "KEYWORDS": "~x86", "IUSE" : "flag", "MISC_CONTENT": install_something, }, "virtual/foo-0": { "EAPI" : "5", "KEYWORDS": "x86", "LICENSE": "GPL-2", }, } installed = { "dev-libs/A-1": { "EAPI" : "5", "IUSE" : "+flag", "KEYWORDS": "x86", "LICENSE": "GPL-2", "RDEPEND": "flag? ( dev-libs/B[flag] )", "USE": "flag", }, "dev-libs/B-1": { "EAPI" : "5", "IUSE" : "+flag", "KEYWORDS": "x86", "LICENSE": "GPL-2", "USE": "flag", }, "dev-libs/depclean-me-1": { "EAPI" : "5", "IUSE" : "", "KEYWORDS": "x86", "LICENSE": "GPL-2", "USE": "", }, "app-misc/depclean-me-1": { "EAPI" : "5", "IUSE" : "", "KEYWORDS": "x86", "LICENSE": "GPL-2", "RDEPEND": "dev-libs/depclean-me", "USE": "", }, } metadata_xml_files = ( ( "dev-libs/A", { "flags" : "<flag name='flag'>Description of how USE='flag' affects this package</flag>", }, ), ( "dev-libs/B", { "flags" : "<flag name='flag'>Description of how USE='flag' affects this package</flag>", }, ), ) playground = ResolverPlayground( ebuilds=ebuilds, installed=installed, debug=debug) loop = asyncio._wrap_loop() loop.run_until_complete(asyncio.ensure_future( self._async_test_simple(loop, playground, metadata_xml_files), loop=loop))
def testSonameSlotConflictForgottenChild(self): """ Similar to testSonameSlotConflictMassRebuild above, but this time the rebuilds are scheduled, but the package causing the rebuild (the child) is not installed. """ binpkgs = { "app-misc/A-2": { "DEPEND": "app-misc/B app-misc/C", "RDEPEND": "app-misc/B app-misc/C", "REQUIRES": "x86_32: libB-2.so", }, "app-misc/B-2": { "PROVIDES": "x86_32: libB-2.so", "SLOT": "2", }, "app-misc/C-1": { "DEPEND": "app-misc/B", "RDEPEND": "app-misc/B", "REQUIRES": "x86_32: libB-2.so", }, } installed = { "app-misc/A-1": { "DEPEND": "app-misc/B app-misc/C", "RDEPEND": "app-misc/B app-misc/C", "REQUIRES": "x86_32: libB-1.so", }, "app-misc/B-1": { "PROVIDES": "x86_32: libB-1.so", "SLOT": "1", }, "app-misc/C-1": { "DEPEND": "app-misc/B", "RDEPEND": "app-misc/B", "REQUIRES": "x86_32: libB-1.so", }, } test_cases = ( ResolverPlaygroundTestCase( ["app-misc/A"], options={ "--ignore-soname-deps": "n", "--usepkgonly": True, }, success=True, mergelist=[ "[binary]app-misc/B-2", "[binary]app-misc/A-2", ], ), ResolverPlaygroundTestCase( ["@world"], options={ "--ignore-soname-deps": "n", "--usepkgonly": True, "--update": True, "--deep": True, }, success=True, mergelist=[ "[binary]app-misc/B-2", "[binary]app-misc/C-1", "[binary]app-misc/A-2", ], ), ) world = ["app-misc/A"] playground = ResolverPlayground( binpkgs=binpkgs, installed=installed, world=world, debug=False ) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.debug = False playground.cleanup()
def testProfilePackageSet(self): repo_configs = { "test_repo": { "layout.conf": ("profile-formats = profile-set", ), } } profiles = ( ('default/linux', { "eapi": ("5", ), "packages": ( "*sys-libs/A", "app-misc/A", "app-misc/B", "app-misc/C", ), }), ('default/linux/x86', { "eapi": ("5", ), "packages": ("-app-misc/B", ), "parent": ("..", ) }), ) ebuilds = { "sys-libs/A-1": { "EAPI": "5", }, "app-misc/A-1": { "EAPI": "5", }, "app-misc/B-1": { "EAPI": "5", }, "app-misc/C-1": { "EAPI": "5", }, } installed = { "sys-libs/A-1": { "EAPI": "5", }, "app-misc/A-1": { "EAPI": "5", }, "app-misc/B-1": { "EAPI": "5", }, "app-misc/C-1": { "EAPI": "5", }, } test_cases = ( ResolverPlaygroundTestCase( ["@world"], options={ "--update": True, "--deep": True }, mergelist=[], success=True, ), ResolverPlaygroundTestCase([], options={"--depclean": True}, success=True, cleanlist=["app-misc/B-1"]), ) playground = ResolverPlayground(debug=False, ebuilds=ebuilds, installed=installed, repo_configs=repo_configs) try: repo_dir = (playground.settings.repositories.get_location_for_name( "test_repo")) profile_root = os.path.join(repo_dir, "profiles") for p, data in profiles: prof_path = os.path.join(profile_root, p) ensure_dirs(prof_path) for k, v in data.items(): with io.open(os.path.join(prof_path, k), mode="w", encoding=_encodings["repo.content"]) as f: for line in v: f.write("%s\n" % line) # The config must be reloaded in order to account # for the above profile customizations. playground.reload_config() for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testSonameSlotConflictMixedDependencies(self): """ Bug 487198 For parents with mixed >= and < dependencies, we scheduled reinstalls for the >= atom, but in the end didn't install the child update because of the < atom. """ binpkgs = { "cat/slotted-lib-1": { "PROVIDES": "x86_32: lib1.so", "SLOT": "1", }, "cat/slotted-lib-2": { "PROVIDES": "x86_32: lib2.so", "SLOT": "2", }, "cat/slotted-lib-3": { "PROVIDES": "x86_32: lib3.so", "SLOT": "3", }, "cat/slotted-lib-4": { "PROVIDES": "x86_32: lib4.so", "SLOT": "4", }, "cat/slotted-lib-5": { "PROVIDES": "x86_32: lib5.so", "SLOT": "5", }, "cat/user-1": { "DEPEND": ">=cat/slotted-lib-2 <cat/slotted-lib-4", "RDEPEND": ">=cat/slotted-lib-2 <cat/slotted-lib-4", "REQUIRES": "x86_32: lib3.so", }, } installed = { "cat/slotted-lib-3": { "PROVIDES": "x86_32: lib3.so", "SLOT": "3", }, "cat/user-1": { "DEPEND": ">=cat/slotted-lib-2 <cat/slotted-lib-4", "RDEPEND": ">=cat/slotted-lib-2 <cat/slotted-lib-4", "REQUIRES": "x86_32: lib3.so", }, } test_cases = ( ResolverPlaygroundTestCase( ["cat/user"], options={ "--deep": True, "--ignore-soname-deps": "n", "--update": True, "--usepkgonly": True, }, success=True, mergelist=[], ), ) world = [] playground = ResolverPlayground( binpkgs=binpkgs, installed=installed, world=world, debug=False ) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.debug = False playground.cleanup()
def testDoebuildSpawn(self): ebuild_body = textwrap.dedent(""" pkg_nofetch() { : ; } """) ebuilds = { 'sys-apps/portage-2.1': { 'EAPI': '2', 'IUSE': 'build doc epydoc python3 selinux', 'KEYWORDS': 'x86', 'LICENSE': 'GPL-2', 'RDEPEND': '>=app-shells/bash-3.2_p17 >=dev-lang/python-2.6', 'SLOT': '0', "MISC_CONTENT": ebuild_body, } } playground = ResolverPlayground(ebuilds=ebuilds) try: root_config = playground.trees[playground.eroot]['root_config'] portdb = root_config.trees["porttree"].dbapi settings = config(clone=playground.settings) if "__PORTAGE_TEST_HARDLINK_LOCKS" in os.environ: settings["__PORTAGE_TEST_HARDLINK_LOCKS"] = \ os.environ["__PORTAGE_TEST_HARDLINK_LOCKS"] settings.backup_changes("__PORTAGE_TEST_HARDLINK_LOCKS") cpv = 'sys-apps/portage-2.1' metadata = dict( zip(Package.metadata_keys, portdb.aux_get(cpv, Package.metadata_keys))) pkg = Package(built=False, cpv=cpv, installed=False, metadata=metadata, root_config=root_config, type_name='ebuild') settings.setcpv(pkg) settings['PORTAGE_PYTHON'] = _python_interpreter settings['PORTAGE_BUILDDIR'] = os.path.join( settings['PORTAGE_TMPDIR'], cpv) settings['PYTHONDONTWRITEBYTECODE'] = os.environ.get( 'PYTHONDONTWRITEBYTECODE', '') settings['HOME'] = os.path.join(settings['PORTAGE_BUILDDIR'], 'homedir') settings['T'] = os.path.join(settings['PORTAGE_BUILDDIR'], 'temp') for x in ('PORTAGE_BUILDDIR', 'HOME', 'T'): os.makedirs(settings[x]) # Create a fake environment, to pretend as if the ebuild # has been sourced already. open(os.path.join(settings['T'], 'environment'), 'wb').close() scheduler = SchedulerInterface(global_event_loop()) for phase in ('_internal_test', ): # Test EbuildSpawnProcess by calling doebuild.spawn() with # returnpid=False. This case is no longer used by portage # internals since EbuildPhase is used instead and that passes # returnpid=True to doebuild.spawn(). rval = doebuild_spawn("%s %s" % (_shell_quote( os.path.join(settings["PORTAGE_BIN_PATH"], os.path.basename(EBUILD_SH_BINARY))), phase), settings, free=1) self.assertEqual(rval, os.EX_OK) ebuild_phase = EbuildPhase(background=False, phase=phase, scheduler=scheduler, settings=settings) scheduler.run_until_complete(ebuild_phase.async_start()) ebuild_phase.wait() self.assertEqual(ebuild_phase.returncode, os.EX_OK) ebuild_phase = MiscFunctionsProcess(background=False, commands=['success_hooks'], scheduler=scheduler, settings=settings) scheduler.run_until_complete(ebuild_phase.async_start()) ebuild_phase.wait() self.assertEqual(ebuild_phase.returncode, os.EX_OK) spawn_nofetch(portdb, portdb.findname(cpv), settings=settings) finally: playground.cleanup()
def testSyncLocal(self): debug = False skip_reason = self._must_skip() if skip_reason: self.portage_skip = skip_reason self.assertFalse(True, skip_reason) return repos_conf = textwrap.dedent(""" [DEFAULT] %(default_keys)s [test_repo] location = %(EPREFIX)s/var/repositories/test_repo sync-type = %(sync-type)s sync-depth = %(sync-depth)s sync-uri = file://%(EPREFIX)s/var/repositories/test_repo_sync sync-rcu = %(sync-rcu)s sync-rcu-store-dir = %(EPREFIX)s/var/repositories/test_repo_rcu_storedir auto-sync = %(auto-sync)s %(repo_extra_keys)s """) profile = { "eapi": ("5", ), "package.use.stable.mask": ("dev-libs/A flag", ) } ebuilds = {"dev-libs/A-0": {}} user_config = {'make.conf': ('FEATURES="metadata-transfer"', )} playground = ResolverPlayground(ebuilds=ebuilds, profile=profile, user_config=user_config, debug=debug) settings = playground.settings eprefix = settings["EPREFIX"] eroot = settings["EROOT"] homedir = os.path.join(eroot, "home") distdir = os.path.join(eprefix, "distdir") repo = settings.repositories["test_repo"] metadata_dir = os.path.join(repo.location, "metadata") rcu_store_dir = os.path.join( eprefix, 'var/repositories/test_repo_rcu_storedir') cmds = {} for cmd in ("emerge", "emaint"): for bindir in (self.bindir, self.sbindir): path = os.path.join(bindir, cmd) if os.path.exists(path): cmds[cmd] = (portage._python_interpreter, "-b", "-Wd", path) break else: raise AssertionError('%s binary not found in %s or %s' % (cmd, self.bindir, self.sbindir)) git_binary = find_binary("git") git_cmd = (git_binary, ) hg_binary = find_binary("hg") hg_cmd = (hg_binary, ) committer_name = "Gentoo Dev" committer_email = "*****@*****.**" def repos_set_conf(sync_type, dflt_keys=None, xtra_keys=None, auto_sync="yes", sync_rcu=False, sync_depth=None): env["PORTAGE_REPOSITORIES"] = repos_conf % {\ "EPREFIX": eprefix, "sync-type": sync_type, "sync-depth": 0 if sync_depth is None else sync_depth, "sync-rcu": "yes" if sync_rcu else "no", "auto-sync": auto_sync, "default_keys": "" if dflt_keys is None else dflt_keys, "repo_extra_keys": "" if xtra_keys is None else xtra_keys} def alter_ebuild(): with open( os.path.join(repo.location + "_sync", "dev-libs", "A", "A-0.ebuild"), "a") as f: f.write("\n") bump_timestamp() def bump_timestamp(): bump_timestamp.timestamp += datetime.timedelta(seconds=1) with open( os.path.join(repo.location + '_sync', 'metadata', 'timestamp.chk'), 'w') as f: f.write( bump_timestamp.timestamp.strftime( '%s\n' % TIMESTAMP_FORMAT, )) bump_timestamp.timestamp = datetime.datetime.utcnow() bump_timestamp_cmds = ((homedir, bump_timestamp), ) sync_cmds = ( (homedir, cmds["emerge"] + ("--sync", )), (homedir, lambda: self.assertTrue( os.path.exists(os.path.join(repo.location, "dev-libs", "A")), "dev-libs/A expected, but missing")), (homedir, cmds["emaint"] + ("sync", "-A")), ) sync_cmds_auto_sync = ( (homedir, lambda: repos_set_conf("rsync", auto_sync="no")), (homedir, cmds["emerge"] + ("--sync", )), (homedir, lambda: self.assertFalse( os.path.exists(os.path.join(repo.location, "dev-libs", "A")), "dev-libs/A found, expected missing")), (homedir, lambda: repos_set_conf("rsync", auto_sync="yes")), ) rename_repo = ( (homedir, lambda: os.rename(repo.location, repo.location + "_sync")), ) rsync_opts_repos = ( (homedir, alter_ebuild), (homedir, lambda: repos_set_conf( "rsync", None, "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back"))), (homedir, cmds['emerge'] + ("--sync", )), (homedir, lambda: self.assertTrue(os.path.exists(repo.location + "_back"))), (homedir, lambda: shutil.rmtree(repo.location + "_back")), (homedir, lambda: repos_set_conf("rsync")), ) rsync_opts_repos_default = ( (homedir, alter_ebuild), (homedir, lambda: repos_set_conf( "rsync", "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back"))), (homedir, cmds['emerge'] + ("--sync", )), (homedir, lambda: self.assertTrue(os.path.exists(repo.location + "_back"))), (homedir, lambda: shutil.rmtree(repo.location + "_back")), (homedir, lambda: repos_set_conf("rsync")), ) rsync_opts_repos_default_ovr = ( (homedir, alter_ebuild), (homedir, lambda: repos_set_conf( "rsync", "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back_nowhere"), "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back"))), (homedir, cmds['emerge'] + ("--sync", )), (homedir, lambda: self.assertTrue(os.path.exists(repo.location + "_back"))), (homedir, lambda: shutil.rmtree(repo.location + "_back")), (homedir, lambda: repos_set_conf("rsync")), ) rsync_opts_repos_default_cancel = ( (homedir, alter_ebuild), (homedir, lambda: repos_set_conf( "rsync", "sync-rsync-extra-opts = --backup --backup-dir=%s" % _shell_quote(repo.location + "_back_nowhere" ), "sync-rsync-extra-opts = ")), (homedir, cmds['emerge'] + ("--sync", )), (homedir, lambda: self.assertFalse(os.path.exists(repo.location + "_back")) ), (homedir, lambda: repos_set_conf("rsync")), ) delete_repo_location = ( (homedir, lambda: shutil.rmtree(repo.user_location)), (homedir, lambda: os.mkdir(repo.user_location)), ) delete_rcu_store_dir = ((homedir, lambda: shutil.rmtree(rcu_store_dir)), ) revert_rcu_layout = ( (homedir, lambda: os.rename(repo.user_location, repo.user_location + '.bak') ), (homedir, lambda: os.rename(os.path.realpath(repo.user_location + '.bak'), repo.user_location)), (homedir, lambda: os.unlink(repo.user_location + '.bak')), (homedir, lambda: shutil.rmtree(repo.user_location + '_rcu_storedir')), ) upstream_git_commit = ( ( repo.location + "_sync", git_cmd + ('commit', '--allow-empty', '-m', 'test empty commit'), ), ( repo.location + "_sync", git_cmd + ('commit', '--allow-empty', '-m', 'test empty commit 2'), ), ) delete_sync_repo = ((homedir, lambda: shutil.rmtree(repo.location + "_sync")), ) git_repo_create = ( (repo.location, git_cmd + ( "config", "--global", "user.name", committer_name, )), (repo.location, git_cmd + ( "config", "--global", "user.email", committer_email, )), (repo.location, git_cmd + ("init-db", )), (repo.location, git_cmd + ("add", ".")), (repo.location, git_cmd + ("commit", "-a", "-m", "add whole repo")), ) sync_type_git = ((homedir, lambda: repos_set_conf("git")), ) sync_type_git_shallow = (( homedir, lambda: repos_set_conf("git", sync_depth=1)), ) sync_rsync_rcu = ((homedir, lambda: repos_set_conf("rsync", sync_rcu=True)), ) delete_git_dir = ( (homedir, lambda: shutil.rmtree(os.path.join(repo.location, ".git"))), ) def hg_init_global_config(): with open(os.path.join(homedir, ".hgrc"), "wt") as f: f.write("[ui]\nusername = {} <{}>\n".format( committer_name, committer_email)) hg_repo_create = ( (repo.location, hg_init_global_config), (repo.location, hg_cmd + ("init", )), (repo.location, hg_cmd + ("add", ".")), (repo.location, hg_cmd + ("commit", "-A", "-m", "add whole repo")), ) sync_type_mercurial = ((homedir, lambda: repos_set_conf("mercurial")), ) def append_newline(path): with open(path, "at") as f: f.write("\n") upstream_hg_commit = ( ( repo.location + "_sync", lambda: append_newline( os.path.join(repo.location + "_sync", "metadata/layout.conf")), ), ( repo.location + "_sync", hg_cmd + ("commit", "metadata/layout.conf", "-m", "test empty commit"), ), ( repo.location + "_sync", lambda: append_newline( os.path.join(repo.location + "_sync", "metadata/layout.conf")), ), ( repo.location + "_sync", hg_cmd + ("commit", "metadata/layout.conf", "-m", "test empty commit 2"), ), ) if hg_binary is None: mercurial_tests = () else: mercurial_tests = (delete_sync_repo + delete_git_dir + hg_repo_create + sync_type_mercurial + rename_repo + sync_cmds + upstream_hg_commit + sync_cmds) pythonpath = os.environ.get("PYTHONPATH") if pythonpath is not None and not pythonpath.strip(): pythonpath = None if pythonpath is not None and \ pythonpath.split(":")[0] == PORTAGE_PYM_PATH: pass else: if pythonpath is None: pythonpath = "" else: pythonpath = ":" + pythonpath pythonpath = PORTAGE_PYM_PATH + pythonpath env = { "PORTAGE_OVERRIDE_EPREFIX": eprefix, "DISTDIR": distdir, "GENTOO_COMMITTER_NAME": committer_name, "GENTOO_COMMITTER_EMAIL": committer_email, "HOME": homedir, "PATH": os.environ["PATH"], "PORTAGE_GRPNAME": os.environ["PORTAGE_GRPNAME"], "PORTAGE_USERNAME": os.environ["PORTAGE_USERNAME"], "PYTHONDONTWRITEBYTECODE": os.environ.get("PYTHONDONTWRITEBYTECODE", ""), "PYTHONPATH": pythonpath, } repos_set_conf("rsync") if os.environ.get("SANDBOX_ON") == "1": # avoid problems from nested sandbox instances env["FEATURES"] = "-sandbox -usersandbox" dirs = [homedir, metadata_dir] try: for d in dirs: ensure_dirs(d) timestamp_path = os.path.join(metadata_dir, 'timestamp.chk') with open(timestamp_path, 'w') as f: f.write( bump_timestamp.timestamp.strftime( '%s\n' % TIMESTAMP_FORMAT, )) if debug: # The subprocess inherits both stdout and stderr, for # debugging purposes. stdout = None else: # The subprocess inherits stderr so that any warnings # triggered by python -Wd will be visible. stdout = subprocess.PIPE for cwd, cmd in rename_repo + sync_cmds_auto_sync + sync_cmds + \ rsync_opts_repos + rsync_opts_repos_default + \ rsync_opts_repos_default_ovr + rsync_opts_repos_default_cancel + \ bump_timestamp_cmds + sync_rsync_rcu + sync_cmds + delete_rcu_store_dir + \ sync_cmds + revert_rcu_layout + \ delete_repo_location + sync_cmds + sync_cmds + \ bump_timestamp_cmds + sync_cmds + revert_rcu_layout + \ delete_sync_repo + git_repo_create + sync_type_git + \ rename_repo + sync_cmds + upstream_git_commit + sync_cmds + \ sync_type_git_shallow + upstream_git_commit + sync_cmds + mercurial_tests: if hasattr(cmd, '__call__'): cmd() continue abs_cwd = os.path.join(repo.location, cwd) proc = subprocess.Popen(cmd, cwd=abs_cwd, env=env, stdout=stdout) if debug: proc.wait() else: output = proc.stdout.readlines() proc.wait() proc.stdout.close() if proc.returncode != os.EX_OK: for line in output: sys.stderr.write(_unicode_decode(line)) self.assertEqual(os.EX_OK, proc.returncode, "%s failed in %s" % ( cmd, cwd, )) finally: playground.cleanup()
def testResolverDepth(self): profile = { "package.mask": ( # Mask an installed package (for which an update is # available) in order to test for bug 712298, where # --update caused --deep=<depth> to be violated for # such a package. "<dev-libs/B-2", ), } ebuilds = { "dev-libs/A-1": { "RDEPEND": "dev-libs/B" }, "dev-libs/A-2": { "RDEPEND": "dev-libs/B" }, "dev-libs/B-1": { "RDEPEND": "dev-libs/C" }, "dev-libs/B-2": { "RDEPEND": "dev-libs/C" }, "dev-libs/C-1": {}, "dev-libs/C-2": {}, "virtual/libusb-0": { "EAPI": "2", "SLOT": "0", "RDEPEND": "|| ( >=dev-libs/libusb-0.1.12-r1:0 dev-libs/libusb-compat >=sys-freebsd/freebsd-lib-8.0[usb] )" }, "virtual/libusb-1": { "EAPI": "2", "SLOT": "1", "RDEPEND": ">=dev-libs/libusb-1.0.4:1" }, "dev-libs/libusb-0.1.13": {}, "dev-libs/libusb-1.0.5": { "SLOT": "1" }, "dev-libs/libusb-compat-1": {}, "sys-freebsd/freebsd-lib-8": { "IUSE": "+usb" }, "sys-fs/udev-164": { "EAPI": "1", "RDEPEND": "virtual/libusb:0" }, "virtual/jre-1.5.0": { "SLOT": "1.5", "RDEPEND": "|| ( =dev-java/sun-jre-bin-1.5.0* =virtual/jdk-1.5.0* )" }, "virtual/jre-1.5.0-r1": { "SLOT": "1.5", "RDEPEND": "|| ( =dev-java/sun-jre-bin-1.5.0* =virtual/jdk-1.5.0* )" }, "virtual/jre-1.6.0": { "SLOT": "1.6", "RDEPEND": "|| ( =dev-java/sun-jre-bin-1.6.0* =virtual/jdk-1.6.0* )" }, "virtual/jre-1.6.0-r1": { "SLOT": "1.6", "RDEPEND": "|| ( =dev-java/sun-jre-bin-1.6.0* =virtual/jdk-1.6.0* )" }, "virtual/jdk-1.5.0": { "SLOT": "1.5", "RDEPEND": "|| ( =dev-java/sun-jdk-1.5.0* dev-java/gcj-jdk )" }, "virtual/jdk-1.5.0-r1": { "SLOT": "1.5", "RDEPEND": "|| ( =dev-java/sun-jdk-1.5.0* dev-java/gcj-jdk )" }, "virtual/jdk-1.6.0": { "SLOT": "1.6", "RDEPEND": "|| ( =dev-java/icedtea-6* =dev-java/sun-jdk-1.6.0* )" }, "virtual/jdk-1.6.0-r1": { "SLOT": "1.6", "RDEPEND": "|| ( =dev-java/icedtea-6* =dev-java/sun-jdk-1.6.0* )" }, "dev-java/gcj-jdk-4.5": {}, "dev-java/gcj-jdk-4.5-r1": {}, "dev-java/icedtea-6.1": {}, "dev-java/icedtea-6.1-r1": {}, "dev-java/sun-jdk-1.5": { "SLOT": "1.5" }, "dev-java/sun-jdk-1.6": { "SLOT": "1.6" }, "dev-java/sun-jre-bin-1.5": { "SLOT": "1.5" }, "dev-java/sun-jre-bin-1.6": { "SLOT": "1.6" }, "dev-java/ant-core-1.8": { "DEPEND": ">=virtual/jdk-1.4" }, "dev-db/hsqldb-1.8": { "RDEPEND": ">=virtual/jre-1.6" }, } installed = { "dev-libs/A-1": { "RDEPEND": "dev-libs/B" }, "dev-libs/B-1": { "RDEPEND": "dev-libs/C" }, "dev-libs/C-1": {}, "virtual/jre-1.5.0": { "SLOT": "1.5", "RDEPEND": "|| ( =virtual/jdk-1.5.0* =dev-java/sun-jre-bin-1.5.0* )" }, "virtual/jre-1.6.0": { "SLOT": "1.6", "RDEPEND": "|| ( =virtual/jdk-1.6.0* =dev-java/sun-jre-bin-1.6.0* )" }, "virtual/jdk-1.5.0": { "SLOT": "1.5", "RDEPEND": "|| ( =dev-java/sun-jdk-1.5.0* dev-java/gcj-jdk )" }, "virtual/jdk-1.6.0": { "SLOT": "1.6", "RDEPEND": "|| ( =dev-java/icedtea-6* =dev-java/sun-jdk-1.6.0* )" }, "dev-java/gcj-jdk-4.5": {}, "dev-java/icedtea-6.1": {}, "virtual/libusb-0": { "EAPI": "2", "SLOT": "0", "RDEPEND": "|| ( >=dev-libs/libusb-0.1.12-r1:0 dev-libs/libusb-compat >=sys-freebsd/freebsd-lib-8.0[usb] )" }, } world = ["dev-libs/A"] test_cases = ( # Test for bug 712298, where --update caused --deep=<depth> # to be violated for dependencies that were masked. In this # case, the installed dev-libs/B-1 dependency is masked. ResolverPlaygroundTestCase(["dev-libs/A"], options={ "--update": True, "--deep": 0 }, success=True, mergelist=["dev-libs/A-2"]), ResolverPlaygroundTestCase( ["dev-libs/A"], options={ "--update": True, "--deep": 1 }, success=True, mergelist=["dev-libs/B-2", "dev-libs/A-2"]), ResolverPlaygroundTestCase( ["dev-libs/A"], options={ "--update": True, "--deep": 2 }, success=True, mergelist=["dev-libs/C-2", "dev-libs/B-2", "dev-libs/A-2"]), ResolverPlaygroundTestCase( ["@world"], options={ "--update": True, "--deep": True }, success=True, mergelist=["dev-libs/C-2", "dev-libs/B-2", "dev-libs/A-2"]), ResolverPlaygroundTestCase( ["@world"], options={"--emptytree": True}, success=True, mergelist=["dev-libs/C-2", "dev-libs/B-2", "dev-libs/A-2"]), ResolverPlaygroundTestCase(["@world"], options={ "--selective": True, "--deep": True }, success=True, mergelist=[]), ResolverPlaygroundTestCase(["dev-libs/A"], options={"--deep": 2}, success=True, mergelist=["dev-libs/A-2"]), ResolverPlaygroundTestCase(["virtual/jre"], options={}, success=True, mergelist=['virtual/jre-1.6.0-r1']), ResolverPlaygroundTestCase(["virtual/jre"], options={"--deep": True}, success=True, mergelist=['virtual/jre-1.6.0-r1']), # Test bug #141118, where we avoid pulling in # redundant deps, satisfying nested virtuals # as efficiently as possible. ResolverPlaygroundTestCase(["virtual/jre"], options={ "--selective": True, "--deep": True }, success=True, mergelist=[]), # Test bug #150361, where depgraph._greedy_slots() # is triggered by --update with AtomArg. ResolverPlaygroundTestCase(["virtual/jre"], options={"--update": True}, success=True, ambiguous_merge_order=True, mergelist=[('virtual/jre-1.6.0-r1', 'virtual/jre-1.5.0-r1')]), # Recursively traversed virtual dependencies, and their # direct dependencies, are considered to have the same # depth as direct dependencies. ResolverPlaygroundTestCase( ["virtual/jre"], options={ "--update": True, "--deep": 1 }, success=True, ambiguous_merge_order=True, merge_order_assertions=(('dev-java/icedtea-6.1-r1', 'virtual/jdk-1.6.0-r1'), ('virtual/jdk-1.6.0-r1', 'virtual/jre-1.6.0-r1'), ('dev-java/gcj-jdk-4.5-r1', 'virtual/jdk-1.5.0-r1'), ('virtual/jdk-1.5.0-r1', 'virtual/jre-1.5.0-r1')), mergelist=[ ('dev-java/icedtea-6.1-r1', 'dev-java/gcj-jdk-4.5-r1', 'virtual/jdk-1.6.0-r1', 'virtual/jdk-1.5.0-r1', 'virtual/jre-1.6.0-r1', 'virtual/jre-1.5.0-r1') ]), ResolverPlaygroundTestCase(["virtual/jre:1.5"], options={"--update": True}, success=True, mergelist=['virtual/jre-1.5.0-r1']), ResolverPlaygroundTestCase(["virtual/jre:1.6"], options={"--update": True}, success=True, mergelist=['virtual/jre-1.6.0-r1']), # Test that we don't pull in any unnecessary updates # when --update is not specified, even though we # specified --deep. ResolverPlaygroundTestCase(["dev-java/ant-core"], options={"--deep": True}, success=True, mergelist=["dev-java/ant-core-1.8"]), ResolverPlaygroundTestCase(["dev-java/ant-core"], options={"--update": True}, success=True, mergelist=["dev-java/ant-core-1.8"]), # Recursively traversed virtual dependencies, and their # direct dependencies, are considered to have the same # depth as direct dependencies. ResolverPlaygroundTestCase(["dev-java/ant-core"], options={ "--update": True, "--deep": 1 }, success=True, mergelist=[ 'dev-java/icedtea-6.1-r1', 'virtual/jdk-1.6.0-r1', 'dev-java/ant-core-1.8' ]), ResolverPlaygroundTestCase(["dev-db/hsqldb"], options={"--deep": True}, success=True, mergelist=["dev-db/hsqldb-1.8"]), # Don't traverse deps of an installed package with --deep=0, # even if it's a virtual. ResolverPlaygroundTestCase(["virtual/libusb:0"], options={ "--selective": True, "--deep": 0 }, success=True, mergelist=[]), # Satisfy unsatisfied dep of installed package with --deep=1. ResolverPlaygroundTestCase(["virtual/libusb:0"], options={ "--selective": True, "--deep": 1 }, success=True, mergelist=['dev-libs/libusb-0.1.13']), # Pull in direct dep of virtual, even with --deep=0. ResolverPlaygroundTestCase( ["sys-fs/udev"], options={"--deep": 0}, success=True, mergelist=['dev-libs/libusb-0.1.13', 'sys-fs/udev-164']), # Test --nodeps with direct virtual deps. ResolverPlaygroundTestCase(["sys-fs/udev"], options={"--nodeps": True}, success=True, mergelist=["sys-fs/udev-164"]), # Test that --nodeps overrides --deep. ResolverPlaygroundTestCase(["sys-fs/udev"], options={ "--nodeps": True, "--deep": True }, success=True, mergelist=["sys-fs/udev-164"]), # Test that --nodeps overrides --emptytree. ResolverPlaygroundTestCase(["sys-fs/udev"], options={ "--nodeps": True, "--emptytree": True }, success=True, mergelist=["sys-fs/udev-164"]), # Test --emptytree with virtuals. ResolverPlaygroundTestCase(["sys-fs/udev"], options={"--emptytree": True}, success=True, mergelist=[ 'dev-libs/libusb-0.1.13', 'virtual/libusb-0', 'sys-fs/udev-164' ]), ) playground = ResolverPlayground(ebuilds=ebuilds, installed=installed, profile=profile, world=world) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testLicenseManager(self): user_config = { "package.license": ( "dev-libs/* TEST", "dev-libs/A -TEST2", "=dev-libs/A-2 TEST3 @TEST", "*/* @EULA TEST2", "=dev-libs/C-1 *", "=dev-libs/C-2 -*", ), } playground = ResolverPlayground(user_config=user_config) try: portage.util.noiselimit = -2 license_group_locations = (os.path.join(playground.portdir, "profiles"), ) pkg_license = os.path.join(playground.eroot, "etc", "portage") lic_man = LicenseManager(license_group_locations, pkg_license) self.assertEqual(lic_man._accept_license_str, None) self.assertEqual(lic_man._accept_license, None) self.assertEqual(lic_man._license_groups, {"EULA": ["TEST"]}) self.assertEqual(lic_man._undef_lic_groups, set(["TEST"])) self.assertEqual(lic_man.extract_global_changes(), "TEST TEST2") self.assertEqual(lic_man.extract_global_changes(), "") lic_man.set_accept_license_str("TEST TEST2") self.assertEqual(lic_man._getPkgAcceptLicense("dev-libs/B-1", "0"), ["TEST", "TEST2", "TEST"]) self.assertEqual(lic_man._getPkgAcceptLicense("dev-libs/A-1", "0"), ["TEST", "TEST2", "TEST", "-TEST2"]) self.assertEqual( lic_man._getPkgAcceptLicense("dev-libs/A-2", "0"), ["TEST", "TEST2", "TEST", "-TEST2", "TEST3", "@TEST"]) self.assertEqual( lic_man.get_prunned_accept_license("dev-libs/B-1", [], "TEST", "0"), "TEST") self.assertEqual( lic_man.get_prunned_accept_license("dev-libs/A-1", [], "-TEST2", "0"), "") self.assertEqual( lic_man.get_prunned_accept_license("dev-libs/A-2", [], "|| ( TEST TEST2 )", "0"), "TEST") self.assertEqual( lic_man.get_prunned_accept_license("dev-libs/C-1", [], "TEST5", "0"), "TEST5") self.assertEqual( lic_man.get_prunned_accept_license("dev-libs/C-2", [], "TEST2", "0"), "") self.assertEqual( lic_man.getMissingLicenses("dev-libs/B-1", [], "TEST", "0"), []) self.assertEqual( lic_man.getMissingLicenses("dev-libs/A-1", [], "-TEST2", "0"), ["-TEST2"]) self.assertEqual( lic_man.getMissingLicenses("dev-libs/A-2", [], "|| ( TEST TEST2 )", "0"), []) self.assertEqual( lic_man.getMissingLicenses("dev-libs/A-3", [], "|| ( TEST2 || ( TEST3 TEST4 ) )", "0"), ["TEST2", "TEST3", "TEST4"]) self.assertEqual( lic_man.getMissingLicenses("dev-libs/C-1", [], "TEST5", "0"), []) self.assertEqual( lic_man.getMissingLicenses("dev-libs/C-2", [], "TEST2", "0"), ["TEST2"]) self.assertEqual( lic_man.getMissingLicenses("dev-libs/D-1", [], "", "0"), []) finally: portage.util.noiselimit = 0 playground.cleanup()
def testDisjunctiveDependOrderTestCase(self): ebuilds = { 'virtual/jre-1.8': { 'EAPI': '6', 'SLOT' : '1.8', 'RDEPEND' : '|| ( dev-java/oracle-jre-bin:1.8 virtual/jdk:1.8 )', }, 'virtual/jdk-1.8': { 'EAPI': '6', 'SLOT' : '1.8', 'RDEPEND' : '|| ( dev-java/icedtea:8 dev-java/oracle-jdk-bin:1.8 )', }, 'dev-java/icedtea-3.6': { 'SLOT' : '8', }, 'dev-java/oracle-jdk-bin-1.8': { 'SLOT' : '1.8', }, 'dev-java/oracle-jre-bin-1.8': { 'SLOT' : '1.8', }, 'dev-db/hsqldb-1.8' : { 'DEPEND' : 'virtual/jdk', 'RDEPEND' : 'virtual/jre', }, } binpkgs = { 'dev-db/hsqldb-1.8' : { 'DEPEND' : 'virtual/jdk', 'RDEPEND' : 'virtual/jre', }, } test_cases = ( # Test bug 639346, where a redundant jre implementation # was pulled in because DEPEND was evaluated after # RDEPEND. ResolverPlaygroundTestCase( ['dev-db/hsqldb'], success=True, mergelist=[ 'dev-java/icedtea-3.6', 'virtual/jdk-1.8', 'virtual/jre-1.8', 'dev-db/hsqldb-1.8', ], ), # The jdk is not needed with --usepkg, so the jre should # be preferred in this case. ResolverPlaygroundTestCase( ['dev-db/hsqldb'], options = { '--usepkg': True }, success=True, mergelist=[ 'dev-java/oracle-jre-bin-1.8', 'virtual/jre-1.8', '[binary]dev-db/hsqldb-1.8', ], ), ) playground = ResolverPlayground(debug=False, binpkgs=binpkgs, ebuilds=ebuilds) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.debug = False playground.cleanup()
def testSimple(self): debug = False install_something = """ S="${WORKDIR}" pkg_pretend() { einfo "called pkg_pretend for $CATEGORY/$PF" } src_install() { einfo "installing something..." insinto /usr/lib/${P} echo "blah blah blah" > "${T}"/regular-file doins "${T}"/regular-file dosym regular-file /usr/lib/${P}/symlink || die # Test CONFIG_PROTECT insinto /etc newins "${T}"/regular-file ${PN}-${SLOT%/*} # Test code for bug #381629, using a copyright symbol encoded with latin-1. # We use $(printf "\\xa9") rather than $'\\xa9', since printf apparently # works in any case, while $'\\xa9' transforms to \\xef\\xbf\\xbd under # some conditions. TODO: Find out why it transforms to \\xef\\xbf\\xbd when # running tests for Python 3.2 (even though it's bash that is ultimately # responsible for performing the transformation). local latin_1_dir=/usr/lib/${P}/latin-1-$(printf "\\xa9")-directory insinto "${latin_1_dir}" echo "blah blah blah" > "${T}"/latin-1-$(printf "\\xa9")-regular-file || die doins "${T}"/latin-1-$(printf "\\xa9")-regular-file dosym latin-1-$(printf "\\xa9")-regular-file ${latin_1_dir}/latin-1-$(printf "\\xa9")-symlink || die } pkg_config() { einfo "called pkg_config for $CATEGORY/$PF" } pkg_info() { einfo "called pkg_info for $CATEGORY/$PF" } pkg_preinst() { einfo "called pkg_preinst for $CATEGORY/$PF" # Test that has_version and best_version work correctly with # prefix (involves internal ROOT -> EROOT calculation in order # to support ROOT override via the environment with EAPIs 3 # and later which support prefix). if has_version $CATEGORY/$PN:$SLOT ; then einfo "has_version detects an installed instance of $CATEGORY/$PN:$SLOT" einfo "best_version reports that the installed instance is $(best_version $CATEGORY/$PN:$SLOT)" else einfo "has_version does not detect an installed instance of $CATEGORY/$PN:$SLOT" fi if [[ ${EPREFIX} != ${PORTAGE_OVERRIDE_EPREFIX} ]] ; then if has_version --host-root $CATEGORY/$PN:$SLOT ; then einfo "has_version --host-root detects an installed instance of $CATEGORY/$PN:$SLOT" einfo "best_version --host-root reports that the installed instance is $(best_version $CATEGORY/$PN:$SLOT)" else einfo "has_version --host-root does not detect an installed instance of $CATEGORY/$PN:$SLOT" fi fi } """ ebuilds = { "dev-libs/A-1": { "EAPI": "5", "IUSE": "+flag", "KEYWORDS": "x86", "LICENSE": "GPL-2", "MISC_CONTENT": install_something, "RDEPEND": "flag? ( dev-libs/B[flag] )", }, "dev-libs/B-1": { "EAPI": "5", "IUSE": "+flag", "KEYWORDS": "x86", "LICENSE": "GPL-2", "MISC_CONTENT": install_something, }, "dev-libs/C-1": { "EAPI": "6", "KEYWORDS": "~x86", "RDEPEND": "dev-libs/D[flag]", }, "dev-libs/D-1": { "EAPI": "6", "KEYWORDS": "~x86", "IUSE": "flag", }, "virtual/foo-0": { "EAPI": "5", "KEYWORDS": "x86", "LICENSE": "GPL-2", }, } installed = { "dev-libs/A-1": { "EAPI": "5", "IUSE": "+flag", "KEYWORDS": "x86", "LICENSE": "GPL-2", "RDEPEND": "flag? ( dev-libs/B[flag] )", "USE": "flag", }, "dev-libs/B-1": { "EAPI": "5", "IUSE": "+flag", "KEYWORDS": "x86", "LICENSE": "GPL-2", "USE": "flag", }, "dev-libs/depclean-me-1": { "EAPI": "5", "IUSE": "", "KEYWORDS": "x86", "LICENSE": "GPL-2", "USE": "", }, "app-misc/depclean-me-1": { "EAPI": "5", "IUSE": "", "KEYWORDS": "x86", "LICENSE": "GPL-2", "RDEPEND": "dev-libs/depclean-me", "USE": "", }, } metadata_xml_files = ( ( "dev-libs/A", { "flags": "<flag name='flag'>Description of how USE='flag' affects this package</flag>", }, ), ( "dev-libs/B", { "flags": "<flag name='flag'>Description of how USE='flag' affects this package</flag>", }, ), ) playground = ResolverPlayground(ebuilds=ebuilds, installed=installed, debug=debug) settings = playground.settings eprefix = settings["EPREFIX"] eroot = settings["EROOT"] trees = playground.trees portdb = trees[eroot]["porttree"].dbapi test_repo_location = settings.repositories["test_repo"].location var_cache_edb = os.path.join(eprefix, "var", "cache", "edb") cachedir = os.path.join(var_cache_edb, "dep") cachedir_pregen = os.path.join(test_repo_location, "metadata", "md5-cache") portage_python = portage._python_interpreter dispatch_conf_cmd = (portage_python, "-b", "-Wd", os.path.join(self.sbindir, "dispatch-conf")) ebuild_cmd = (portage_python, "-b", "-Wd", os.path.join(self.bindir, "ebuild")) egencache_cmd = (portage_python, "-b", "-Wd", os.path.join(self.bindir, "egencache"), "--repo", "test_repo", "--repositories-configuration", settings.repositories.config_string()) emerge_cmd = (portage_python, "-b", "-Wd", os.path.join(self.bindir, "emerge")) emaint_cmd = (portage_python, "-b", "-Wd", os.path.join(self.sbindir, "emaint")) env_update_cmd = (portage_python, "-b", "-Wd", os.path.join(self.sbindir, "env-update")) etc_update_cmd = (BASH_BINARY, os.path.join(self.sbindir, "etc-update")) fixpackages_cmd = (portage_python, "-b", "-Wd", os.path.join(self.sbindir, "fixpackages")) portageq_cmd = (portage_python, "-b", "-Wd", os.path.join(self.bindir, "portageq")) quickpkg_cmd = (portage_python, "-b", "-Wd", os.path.join(self.bindir, "quickpkg")) regenworld_cmd = (portage_python, "-b", "-Wd", os.path.join(self.sbindir, "regenworld")) rm_binary = find_binary("rm") self.assertEqual(rm_binary is None, False, "rm command not found") rm_cmd = (rm_binary, ) egencache_extra_args = [] if self._have_python_xml(): egencache_extra_args.append("--update-use-local-desc") test_ebuild = portdb.findname("dev-libs/A-1") self.assertFalse(test_ebuild is None) cross_prefix = os.path.join(eprefix, "cross_prefix") cross_root = os.path.join(eprefix, "cross_root") cross_eroot = os.path.join(cross_root, eprefix.lstrip(os.sep)) test_commands = ( env_update_cmd, portageq_cmd + ("envvar", "-v", "CONFIG_PROTECT", "EROOT", "PORTAGE_CONFIGROOT", "PORTAGE_TMPDIR", "USERLAND"), etc_update_cmd, dispatch_conf_cmd, emerge_cmd + ("--version",), emerge_cmd + ("--info",), emerge_cmd + ("--info", "--verbose"), emerge_cmd + ("--list-sets",), emerge_cmd + ("--check-news",), rm_cmd + ("-rf", cachedir), rm_cmd + ("-rf", cachedir_pregen), emerge_cmd + ("--regen",), rm_cmd + ("-rf", cachedir), ({"FEATURES" : "metadata-transfer"},) + \ emerge_cmd + ("--regen",), rm_cmd + ("-rf", cachedir), ({"FEATURES" : "metadata-transfer"},) + \ emerge_cmd + ("--regen",), rm_cmd + ("-rf", cachedir), egencache_cmd + ("--update",) + tuple(egencache_extra_args), ({"FEATURES" : "metadata-transfer"},) + \ emerge_cmd + ("--metadata",), rm_cmd + ("-rf", cachedir), ({"FEATURES" : "metadata-transfer"},) + \ emerge_cmd + ("--metadata",), emerge_cmd + ("--metadata",), rm_cmd + ("-rf", cachedir), emerge_cmd + ("--oneshot", "virtual/foo"), lambda: self.assertFalse(os.path.exists( os.path.join(pkgdir, "virtual", "foo-0.tbz2"))), ({"FEATURES" : "unmerge-backup"},) + \ emerge_cmd + ("--unmerge", "virtual/foo"), lambda: self.assertTrue(os.path.exists( os.path.join(pkgdir, "virtual", "foo-0.tbz2"))), emerge_cmd + ("--pretend", "dev-libs/A"), ebuild_cmd + (test_ebuild, "manifest", "clean", "package", "merge"), emerge_cmd + ("--pretend", "--tree", "--complete-graph", "dev-libs/A"), emerge_cmd + ("-p", "dev-libs/B"), emerge_cmd + ("-p", "--newrepo", "dev-libs/B"), emerge_cmd + ("-B", "dev-libs/B",), emerge_cmd + ("--oneshot", "--usepkg", "dev-libs/B",), # trigger clean prior to pkg_pretend as in bug #390711 ebuild_cmd + (test_ebuild, "unpack"), emerge_cmd + ("--oneshot", "dev-libs/A",), emerge_cmd + ("--noreplace", "dev-libs/A",), emerge_cmd + ("--config", "dev-libs/A",), emerge_cmd + ("--info", "dev-libs/A", "dev-libs/B"), emerge_cmd + ("--pretend", "--depclean", "--verbose", "dev-libs/B"), emerge_cmd + ("--pretend", "--depclean",), emerge_cmd + ("--depclean",), quickpkg_cmd + ("--include-config", "y", "dev-libs/A",), # Test bug #523684, where a file renamed or removed by the # admin forces replacement files to be merged with config # protection. lambda: self.assertEqual(0, len(list(find_updated_config_files(eroot, shlex_split(settings["CONFIG_PROTECT"]))))), lambda: os.unlink(os.path.join(eprefix, "etc", "A-0")), emerge_cmd + ("--usepkgonly", "dev-libs/A"), lambda: self.assertEqual(1, len(list(find_updated_config_files(eroot, shlex_split(settings["CONFIG_PROTECT"]))))), emaint_cmd + ("--check", "all"), emaint_cmd + ("--fix", "all"), fixpackages_cmd, regenworld_cmd, portageq_cmd + ("match", eroot, "dev-libs/A"), portageq_cmd + ("best_visible", eroot, "dev-libs/A"), portageq_cmd + ("best_visible", eroot, "binary", "dev-libs/A"), portageq_cmd + ("contents", eroot, "dev-libs/A-1"), portageq_cmd + ("metadata", eroot, "ebuild", "dev-libs/A-1", "EAPI", "IUSE", "RDEPEND"), portageq_cmd + ("metadata", eroot, "binary", "dev-libs/A-1", "EAPI", "USE", "RDEPEND"), portageq_cmd + ("metadata", eroot, "installed", "dev-libs/A-1", "EAPI", "USE", "RDEPEND"), portageq_cmd + ("owners", eroot, eroot + "usr"), emerge_cmd + ("-p", eroot + "usr"), emerge_cmd + ("-p", "--unmerge", "-q", eroot + "usr"), emerge_cmd + ("--unmerge", "--quiet", "dev-libs/A"), emerge_cmd + ("-C", "--quiet", "dev-libs/B"), emerge_cmd + ("--autounmask-continue", "dev-libs/C",), # Verify that the above --autounmask-continue command caused # USE=flag to be applied correctly to dev-libs/D. portageq_cmd + ("match", eroot, "dev-libs/D[flag]"), # Test cross-prefix usage, including chpathtool for binpkgs. ({"EPREFIX" : cross_prefix},) + \ emerge_cmd + ("--usepkgonly", "dev-libs/A"), ({"EPREFIX" : cross_prefix},) + \ portageq_cmd + ("has_version", cross_prefix, "dev-libs/A"), ({"EPREFIX" : cross_prefix},) + \ portageq_cmd + ("has_version", cross_prefix, "dev-libs/B"), ({"EPREFIX" : cross_prefix},) + \ emerge_cmd + ("-C", "--quiet", "dev-libs/B"), ({"EPREFIX" : cross_prefix},) + \ emerge_cmd + ("-C", "--quiet", "dev-libs/A"), ({"EPREFIX" : cross_prefix},) + \ emerge_cmd + ("dev-libs/A",), ({"EPREFIX" : cross_prefix},) + \ portageq_cmd + ("has_version", cross_prefix, "dev-libs/A"), ({"EPREFIX" : cross_prefix},) + \ portageq_cmd + ("has_version", cross_prefix, "dev-libs/B"), # Test ROOT support ({"ROOT": cross_root},) + emerge_cmd + ("dev-libs/B",), portageq_cmd + ("has_version", cross_eroot, "dev-libs/B"), ) distdir = playground.distdir pkgdir = playground.pkgdir fake_bin = os.path.join(eprefix, "bin") portage_tmpdir = os.path.join(eprefix, "var", "tmp", "portage") profile_path = settings.profile_path user_config_dir = os.path.join(os.sep, eprefix, USER_CONFIG_PATH) path = os.environ.get("PATH") if path is not None and not path.strip(): path = None if path is None: path = "" else: path = ":" + path path = fake_bin + path pythonpath = os.environ.get("PYTHONPATH") if pythonpath is not None and not pythonpath.strip(): pythonpath = None if pythonpath is not None and \ pythonpath.split(":")[0] == PORTAGE_PYM_PATH: pass else: if pythonpath is None: pythonpath = "" else: pythonpath = ":" + pythonpath pythonpath = PORTAGE_PYM_PATH + pythonpath env = { "PORTAGE_OVERRIDE_EPREFIX": eprefix, "CLEAN_DELAY": "0", "DISTDIR": distdir, "EMERGE_WARNING_DELAY": "0", "INFODIR": "", "INFOPATH": "", "PATH": path, "PKGDIR": pkgdir, "PORTAGE_INST_GID": str(portage.data.portage_gid), "PORTAGE_INST_UID": str(portage.data.portage_uid), "PORTAGE_PYTHON": portage_python, "PORTAGE_REPOSITORIES": settings.repositories.config_string(), "PORTAGE_TMPDIR": portage_tmpdir, "PORT_LOGDIR": portage_tmpdir, "PYTHONDONTWRITEBYTECODE": os.environ.get("PYTHONDONTWRITEBYTECODE", ""), "PYTHONPATH": pythonpath, "__PORTAGE_TEST_PATH_OVERRIDE": fake_bin, } if "__PORTAGE_TEST_HARDLINK_LOCKS" in os.environ: env["__PORTAGE_TEST_HARDLINK_LOCKS"] = \ os.environ["__PORTAGE_TEST_HARDLINK_LOCKS"] updates_dir = os.path.join(test_repo_location, "profiles", "updates") dirs = [ cachedir, cachedir_pregen, cross_eroot, cross_prefix, distdir, fake_bin, portage_tmpdir, updates_dir, user_config_dir, var_cache_edb ] etc_symlinks = ("dispatch-conf.conf", "etc-update.conf") # Override things that may be unavailable, or may have portability # issues when running tests in exotic environments. # prepstrip - bug #447810 (bash read builtin EINTR problem) true_symlinks = ["find", "prepstrip", "sed", "scanelf"] true_binary = find_binary("true") self.assertEqual(true_binary is None, False, "true command not found") try: for d in dirs: ensure_dirs(d) for x in true_symlinks: os.symlink(true_binary, os.path.join(fake_bin, x)) for x in etc_symlinks: os.symlink(os.path.join(self.cnf_etc_path, x), os.path.join(eprefix, "etc", x)) with open(os.path.join(var_cache_edb, "counter"), 'wb') as f: f.write(b"100") # non-empty system set keeps --depclean quiet with open(os.path.join(profile_path, "packages"), 'w') as f: f.write("*dev-libs/token-system-pkg") for cp, xml_data in metadata_xml_files: with open(os.path.join(test_repo_location, cp, "metadata.xml"), 'w') as f: f.write(playground.metadata_xml_template % xml_data) with open(os.path.join(updates_dir, "1Q-2010"), 'w') as f: f.write(""" slotmove =app-doc/pms-3 2 3 move dev-util/git dev-vcs/git """) if debug: # The subprocess inherits both stdout and stderr, for # debugging purposes. stdout = None else: # The subprocess inherits stderr so that any warnings # triggered by python -Wd will be visible. stdout = subprocess.PIPE for args in test_commands: if hasattr(args, '__call__'): args() continue if isinstance(args[0], dict): local_env = env.copy() local_env.update(args[0]) args = args[1:] else: local_env = env proc = subprocess.Popen(args, env=local_env, stdout=stdout) if debug: proc.wait() else: output = proc.stdout.readlines() proc.wait() proc.stdout.close() if proc.returncode != os.EX_OK: for line in output: sys.stderr.write(_unicode_decode(line)) self.assertEqual(os.EX_OK, proc.returncode, "emerge failed with args %s" % (args, )) finally: playground.cleanup()
def testSubSlot(self): ebuilds = { "dev-libs/icu-4.8": { "EAPI": "4-slot-abi", "SLOT": "0/48" }, "dev-libs/libxml2-2.7.8": { "EAPI": "4-slot-abi", "DEPEND": "dev-libs/icu:=", "RDEPEND": "dev-libs/icu:=" }, } binpkgs = { "dev-libs/icu-49": { "EAPI": "4-slot-abi", "SLOT": "0/49" }, "dev-libs/icu-4.8": { "EAPI": "4-slot-abi", "SLOT": "0/48" }, "dev-libs/libxml2-2.7.8": { "EAPI": "4-slot-abi", "DEPEND": "dev-libs/icu:0/49=", "RDEPEND": "dev-libs/icu:0/49=" }, } installed = { "dev-libs/icu-49": { "EAPI": "4-slot-abi", "SLOT": "0/49" }, "dev-libs/libxml2-2.7.8": { "EAPI": "4-slot-abi", "DEPEND": "dev-libs/icu:0/49=", "RDEPEND": "dev-libs/icu:0/49=" }, } world = ["dev-libs/libxml2"] test_cases = ( ResolverPlaygroundTestCase( ["dev-libs/icu"], options={"--oneshot": True}, success=True, mergelist=["dev-libs/icu-4.8", "dev-libs/libxml2-2.7.8"]), ResolverPlaygroundTestCase(["dev-libs/icu"], options={ "--oneshot": True, "--ignore-built-slot-operator-deps": "y" }, success=True, mergelist=["dev-libs/icu-4.8"]), ResolverPlaygroundTestCase(["dev-libs/icu"], options={ "--oneshot": True, "--usepkg": True }, success=True, mergelist=[ "[binary]dev-libs/icu-4.8", "dev-libs/libxml2-2.7.8" ]), ResolverPlaygroundTestCase(["dev-libs/icu"], options={ "--oneshot": True, "--usepkgonly": True }, success=True, mergelist=["[binary]dev-libs/icu-49"]), ResolverPlaygroundTestCase( ["@world"], options={ "--update": True, "--deep": True }, success=True, mergelist=["dev-libs/icu-4.8", "dev-libs/libxml2-2.7.8"]), ResolverPlaygroundTestCase( ["@world"], options={ "--update": True, "--deep": True, "--ignore-built-slot-operator-deps": "y" }, success=True, mergelist=["dev-libs/icu-4.8"]), ResolverPlaygroundTestCase(["@world"], options={ "--update": True, "--deep": True, "--usepkg": True }, success=True, mergelist=[ "[binary]dev-libs/icu-4.8", "dev-libs/libxml2-2.7.8" ]), ResolverPlaygroundTestCase(["@world"], options={ "--update": True, "--deep": True, "--usepkgonly": True }, success=True, mergelist=[]), ) playground = ResolverPlayground(ebuilds=ebuilds, binpkgs=binpkgs, installed=installed, world=world, debug=False) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testSlotConflictUpdateVirt(self): ebuilds = { "dev-db/mysql-connector-c-6.1.11-r2": { "EAPI": "7", "SLOT": "0/18" }, "dev-db/mysql-connector-c-8.0.17-r3": { "EAPI": "7", "SLOT": "0/21" }, "virtual/libmysqlclient-18-r1": { "EAPI": "7", "SLOT": "0/18", "RDEPEND": "dev-db/mysql-connector-c:0/18", }, "virtual/libmysqlclient-21": { "EAPI": "7", "SLOT": "0/21", "RDEPEND": "dev-db/mysql-connector-c:0/21", }, "dev-perl/DBD-mysql-4.44.0": { "EAPI": "7", "RDEPEND": "virtual/libmysqlclient:=", }, } installed = { "dev-db/mysql-connector-c-6.1.11-r2": { "EAPI": "7", "SLOT": "0/18" }, "virtual/libmysqlclient-18-r1": { "EAPI": "7", "SLOT": "0/18", "RDEPEND": "dev-db/mysql-connector-c:0/18", }, "dev-perl/DBD-mysql-4.44.0": { "EAPI": "7", "RDEPEND": "virtual/libmysqlclient:0/18=", }, } world = ["dev-db/mysql-connector-c", "dev-perl/DBD-mysql"] test_cases = ( # In order to avoid missed updates for bug 692746, consider # masking a package matched by all parent atoms. ResolverPlaygroundTestCase( ["@world"], options={ "--update": True, "--deep": True }, success=True, mergelist=[ "dev-db/mysql-connector-c-8.0.17-r3", "virtual/libmysqlclient-21", "dev-perl/DBD-mysql-4.44.0", ], ), ) playground = ResolverPlayground(ebuilds=ebuilds, installed=installed, world=world, debug=False) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.debug = False playground.cleanup()
def testWholeSlotSubSlotMix(self): ebuilds = { "dev-libs/glib-1.2.10": { "SLOT": "1" }, "dev-libs/glib-2.30.2": { "EAPI": "4-slot-abi", "SLOT": "2/2.30" }, "dev-libs/dbus-glib-0.98": { "EAPI": "4-slot-abi", "DEPEND": "dev-libs/glib:2=", "RDEPEND": "dev-libs/glib:2=" }, } binpkgs = { "dev-libs/glib-1.2.10": { "SLOT": "1" }, "dev-libs/glib-2.30.2": { "EAPI": "4-slot-abi", "SLOT": "2/2.30" }, "dev-libs/glib-2.32.3": { "EAPI": "4-slot-abi", "SLOT": "2/2.32" }, "dev-libs/dbus-glib-0.98": { "EAPI": "4-slot-abi", "DEPEND": "dev-libs/glib:2/2.32=", "RDEPEND": "dev-libs/glib:2/2.32=" }, } installed = { "dev-libs/glib-1.2.10": { "EAPI": "4-slot-abi", "SLOT": "1" }, "dev-libs/glib-2.32.3": { "EAPI": "4-slot-abi", "SLOT": "2/2.32" }, "dev-libs/dbus-glib-0.98": { "EAPI": "4-slot-abi", "DEPEND": "dev-libs/glib:2/2.32=", "RDEPEND": "dev-libs/glib:2/2.32=" }, } world = ["dev-libs/glib:1", "dev-libs/dbus-glib"] test_cases = ( ResolverPlaygroundTestCase( ["dev-libs/glib"], options={"--oneshot": True}, success=True, mergelist=["dev-libs/glib-2.30.2", "dev-libs/dbus-glib-0.98"]), ResolverPlaygroundTestCase(["dev-libs/glib"], options={ "--oneshot": True, "--ignore-built-slot-operator-deps": "y" }, success=True, mergelist=["dev-libs/glib-2.30.2"]), ResolverPlaygroundTestCase(["dev-libs/glib"], options={ "--oneshot": True, "--usepkg": True }, success=True, mergelist=[ "[binary]dev-libs/glib-2.30.2", "dev-libs/dbus-glib-0.98" ]), ResolverPlaygroundTestCase( ["dev-libs/glib"], options={ "--oneshot": True, "--usepkgonly": True }, success=True, mergelist=["[binary]dev-libs/glib-2.32.3"]), ResolverPlaygroundTestCase( ["@world"], options={ "--update": True, "--deep": True }, success=True, mergelist=["dev-libs/glib-2.30.2", "dev-libs/dbus-glib-0.98"]), ResolverPlaygroundTestCase( ["@world"], options={ "--update": True, "--deep": True, "--ignore-built-slot-operator-deps": "y" }, success=True, mergelist=["dev-libs/glib-2.30.2"]), ResolverPlaygroundTestCase(["@world"], options={ "--update": True, "--deep": True, "--usepkg": True }, success=True, mergelist=[ "[binary]dev-libs/glib-2.30.2", "dev-libs/dbus-glib-0.98" ]), ResolverPlaygroundTestCase(["@world"], options={ "--update": True, "--deep": True, "--usepkgonly": True }, success=True, mergelist=[]), ) playground = ResolverPlayground(ebuilds=ebuilds, binpkgs=binpkgs, installed=installed, world=world, debug=False) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testMoveSlotEnt(self): ebuilds = { "dev-libs/A-2::dont_apply_updates": { "EAPI": "5", "SLOT": "0/2.30", }, "dev-libs/B-2::dont_apply_updates": { "SLOT": "0", }, "dev-libs/C-2.1::dont_apply_updates": { "EAPI": "5", "SLOT": "0/2.1", }, } installed = { "dev-libs/A-1::test_repo": { "EAPI": "5", "SLOT": "0/2.30", }, "dev-libs/B-1::test_repo": { "SLOT": "0", }, "dev-libs/C-1::test_repo": { "EAPI": "5", "SLOT": "0/1", }, } binpkgs = { "dev-libs/A-1::test_repo": { "EAPI": "5", "SLOT": "0/2.30", }, "dev-libs/A-2::dont_apply_updates": { "EAPI": "5", "SLOT": "0/2.30", }, "dev-libs/B-1::test_repo": { "SLOT": "0", }, "dev-libs/B-2::dont_apply_updates": { "SLOT": "0", }, "dev-libs/C-1::test_repo": { "EAPI": "5", "SLOT": "0/1", }, "dev-libs/C-2.1::dont_apply_updates": { "EAPI": "5", "SLOT": "0/2.1", }, } updates = textwrap.dedent( """ slotmove dev-libs/A 0 2 slotmove dev-libs/B 0 1 slotmove dev-libs/C 0 1 """ ) playground = ResolverPlayground( binpkgs=binpkgs, ebuilds=ebuilds, installed=installed ) settings = playground.settings trees = playground.trees eroot = settings["EROOT"] test_repo_location = settings.repositories["test_repo"].location portdb = trees[eroot]["porttree"].dbapi vardb = trees[eroot]["vartree"].dbapi bindb = trees[eroot]["bintree"].dbapi updates_dir = os.path.join(test_repo_location, "profiles", "updates") try: ensure_dirs(updates_dir) with open(os.path.join(updates_dir, "1Q-2010"), "w") as f: f.write(updates) # Create an empty updates directory, so that this # repo doesn't inherit updates from the main repo. ensure_dirs( os.path.join( portdb.getRepositoryPath("dont_apply_updates"), "profiles", "updates", ) ) global_noiselimit = portage.util.noiselimit portage.util.noiselimit = -2 try: _do_global_updates(trees, {}) finally: portage.util.noiselimit = global_noiselimit # Workaround for cache validation not working # correctly when filesystem has timestamp precision # of 1 second. vardb._clear_cache() # 0/2.30 -> 2/2.30 self.assertEqual("2/2.30", vardb.aux_get("dev-libs/A-1", ["SLOT"])[0]) self.assertEqual("2/2.30", bindb.aux_get("dev-libs/A-1", ["SLOT"])[0]) # 0 -> 1 self.assertEqual("1", vardb.aux_get("dev-libs/B-1", ["SLOT"])[0]) self.assertEqual("1", bindb.aux_get("dev-libs/B-1", ["SLOT"])[0]) # 0/1 -> 1 (equivalent to 1/1) self.assertEqual("1", vardb.aux_get("dev-libs/C-1", ["SLOT"])[0]) self.assertEqual("1", bindb.aux_get("dev-libs/C-1", ["SLOT"])[0]) # dont_apply_updates self.assertEqual("0/2.30", bindb.aux_get("dev-libs/A-2", ["SLOT"])[0]) self.assertEqual("0", bindb.aux_get("dev-libs/B-2", ["SLOT"])[0]) self.assertEqual("0/2.1", bindb.aux_get("dev-libs/C-2.1", ["SLOT"])[0]) finally: playground.cleanup()
def testSonameSlotConflictReinstall(self): binpkgs = { "app-misc/A-1": { "PROVIDES": "x86_32: libA-1.so", }, "app-misc/A-2": { "PROVIDES": "x86_32: libA-2.so", }, "app-misc/B-0": { "DEPEND": "app-misc/A", "RDEPEND": "app-misc/A", "REQUIRES": "x86_32: libA-2.so", }, "app-misc/C-0": { "EAPI": "5", "DEPEND": "<app-misc/A-2", "RDEPEND": "<app-misc/A-2", }, "app-misc/D-1": { "PROVIDES": "x86_32: libD-1.so", }, "app-misc/D-2": { "PROVIDES": "x86_32: libD-2.so", }, "app-misc/E-0": { "DEPEND": "app-misc/D", "RDEPEND": "app-misc/D", "REQUIRES": "x86_32: libD-2.so", }, } installed = { "app-misc/A-1": { "PROVIDES": "x86_32: libA-1.so", }, "app-misc/B-0": { "DEPEND": "app-misc/A", "RDEPEND": "app-misc/A", "REQUIRES": "x86_32: libA-1.so", }, "app-misc/C-0": {"DEPEND": "<app-misc/A-2", "RDEPEND": "<app-misc/A-2"}, "app-misc/D-1": { "PROVIDES": "x86_32: libD-1.so", }, "app-misc/E-0": { "DEPEND": "app-misc/D", "RDEPEND": "app-misc/D", "REQUIRES": "x86_32: libD-1.so", }, } world = ["app-misc/B", "app-misc/C", "app-misc/E"] test_cases = ( # Test bug #439688, where a slot conflict prevents an # upgrade and we don't want to trigger unnecessary rebuilds. ResolverPlaygroundTestCase( ["@world"], options={ "--deep": True, "--ignore-soname-deps": "n", "--update": True, "--usepkgonly": True, "--backtrack": 10, }, success=True, mergelist=["[binary]app-misc/D-2", "[binary]app-misc/E-0"], ), ) playground = ResolverPlayground( binpkgs=binpkgs, installed=installed, world=world, debug=False ) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.debug = False playground.cleanup()
def testManifest(self): distfiles = { "B-2.tar.bz2": b"binary\0content", "C-2.zip": b"binary\0content", "C-2.tar.bz2": b"binary\0content", } ebuilds = { "dev-libs/A-1::old_repo": {}, "dev-libs/A-2::new_repo": {}, "dev-libs/B-2::new_repo": { "SRC_URI": "B-2.tar.bz2" }, "dev-libs/C-2::new_repo": { "SRC_URI": "C-2.zip C-2.tar.bz2" }, } repo_configs = { "new_repo": { "layout.conf": ( "profile-formats = pms", "thin-manifests = true", "manifest-hashes = SHA256 SHA512 WHIRLPOOL", "manifest-required-hashes = SHA512", "# use implicit masters", ), } } test_cases = ( ResolverPlaygroundTestCase(["=dev-libs/A-1"], mergelist=["dev-libs/A-1"], success=True), ResolverPlaygroundTestCase(["=dev-libs/A-2"], mergelist=["dev-libs/A-2"], success=True), ) playground = ResolverPlayground(ebuilds=ebuilds, repo_configs=repo_configs, distfiles=distfiles) settings = playground.settings new_repo_config = settings.repositories["new_repo"] old_repo_config = settings.repositories["old_repo"] self.assertTrue( len(new_repo_config.masters) > 0, "new_repo has no default master") self.assertEqual( new_repo_config.masters[0].location, playground.settings.repositories["test_repo"].location, "new_repo default master is not test_repo", ) self.assertEqual(new_repo_config.thin_manifest, True, "new_repo_config.thin_manifest != True") new_manifest_file = os.path.join(new_repo_config.location, "dev-libs", "A", "Manifest") self.assertNotExists(new_manifest_file) new_manifest_file = os.path.join(new_repo_config.location, "dev-libs", "B", "Manifest") f = open(new_manifest_file) self.assertEqual(len(list(f)), 1) f.close() new_manifest_file = os.path.join(new_repo_config.location, "dev-libs", "C", "Manifest") f = open(new_manifest_file) self.assertEqual(len(list(f)), 2) f.close() old_manifest_file = os.path.join(old_repo_config.location, "dev-libs", "A", "Manifest") f = open(old_manifest_file) self.assertEqual(len(list(f)), 1) f.close() try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()
def testSlotOperatorReverseDeps(self): ebuilds = { "media-libs/mesa-11.2.2" : { "EAPI": "6", "SLOT": "0", "RDEPEND": ">=sys-devel/llvm-3.6.0:=" }, "sys-devel/clang-3.7.1-r100" : { "EAPI": "6", "SLOT": "0/3.7", "RDEPEND": "~sys-devel/llvm-3.7.1" }, "sys-devel/clang-3.8.0-r100" : { "EAPI": "6", "SLOT": "0/3.8", "RDEPEND": "~sys-devel/llvm-3.8.0" }, "sys-devel/llvm-3.7.1-r2" : { "EAPI": "6", "SLOT": "0/3.7.1", "PDEPEND": "=sys-devel/clang-3.7.1-r100" }, "sys-devel/llvm-3.8.0-r2" : { "EAPI": "6", "SLOT": "0/3.8.0", "PDEPEND": "=sys-devel/clang-3.8.0-r100" }, } installed = { "media-libs/mesa-11.2.2" : { "EAPI": "6", "SLOT": "0", "RDEPEND": ">=sys-devel/llvm-3.6.0:0/3.7.1=" }, "sys-devel/clang-3.7.1-r100" : { "EAPI": "6", "SLOT": "0/3.7", "RDEPEND": "~sys-devel/llvm-3.7.1" }, "sys-devel/llvm-3.7.1-r2" : { "EAPI": "6", "SLOT": "0/3.7.1", "PDEPEND": "=sys-devel/clang-3.7.1-r100" }, } world = ["media-libs/mesa"] test_cases = ( # Test bug #584626, where an llvm update is missed due to # the check_reverse_dependencies function seeing that # updating llvm will break a dependency of the installed # version of clang (though a clang update is available). ResolverPlaygroundTestCase( ["@world"], options = {"--update": True, "--deep": True}, success = True, mergelist = [ 'sys-devel/llvm-3.8.0-r2', 'sys-devel/clang-3.8.0-r100', 'media-libs/mesa-11.2.2', ], ), ResolverPlaygroundTestCase( ["@world"], options = { "--update": True, "--deep": True, "--ignore-built-slot-operator-deps": "y", }, success = True, mergelist = [ 'sys-devel/llvm-3.8.0-r2', 'sys-devel/clang-3.8.0-r100', ], ), ) playground = ResolverPlayground(ebuilds=ebuilds, installed=installed, world=world, debug=False) try: for test_case in test_cases: playground.run_TestCase(test_case) self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup()