aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2018-07-17 21:50:45 +0200
committerZac Medico <zmedico@gentoo.org>2018-07-18 16:19:11 -0700
commitbc0fa8d3795ed7e40aaa00f579bb2977897bce25 (patch)
tree2a62c721ee8dec47ddb564254e1cbd967577d1f0 /lib/portage/tests/emerge
parentEventLoop: raise TypeError for unexpected call_* keyword args (diff)
downloadportage-bc0fa8d3795ed7e40aaa00f579bb2977897bce25.tar.gz
portage-bc0fa8d3795ed7e40aaa00f579bb2977897bce25.tar.bz2
portage-bc0fa8d3795ed7e40aaa00f579bb2977897bce25.zip
Rename pym→lib, for better distutils-r1 interoperability
Closes: https://github.com/gentoo/portage/pull/343
Diffstat (limited to 'lib/portage/tests/emerge')
-rw-r--r--lib/portage/tests/emerge/__init__.py2
-rw-r--r--lib/portage/tests/emerge/__test__.py0
-rw-r--r--lib/portage/tests/emerge/test_config_protect.py293
-rw-r--r--lib/portage/tests/emerge/test_emerge_blocker_file_collision.py168
-rw-r--r--lib/portage/tests/emerge/test_emerge_slot_abi.py179
-rw-r--r--lib/portage/tests/emerge/test_global_updates.py41
-rw-r--r--lib/portage/tests/emerge/test_simple.py505
7 files changed, 1188 insertions, 0 deletions
diff --git a/lib/portage/tests/emerge/__init__.py b/lib/portage/tests/emerge/__init__.py
new file mode 100644
index 000000000..532918b6a
--- /dev/null
+++ b/lib/portage/tests/emerge/__init__.py
@@ -0,0 +1,2 @@
+# Copyright 2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
diff --git a/lib/portage/tests/emerge/__test__.py b/lib/portage/tests/emerge/__test__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/lib/portage/tests/emerge/__test__.py
diff --git a/lib/portage/tests/emerge/test_config_protect.py b/lib/portage/tests/emerge/test_config_protect.py
new file mode 100644
index 000000000..06ab059ee
--- /dev/null
+++ b/lib/portage/tests/emerge/test_config_protect.py
@@ -0,0 +1,293 @@
+# Copyright 2014-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from __future__ import unicode_literals
+
+import io
+from functools import partial
+import shutil
+import stat
+import subprocess
+import sys
+import time
+
+import portage
+from portage import os
+from portage import _encodings, _unicode_decode
+from portage.const import BASH_BINARY, PORTAGE_PYM_PATH
+from portage.process import find_binary
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import ResolverPlayground
+from portage.util import (ensure_dirs, find_updated_config_files,
+ shlex_split)
+
+class ConfigProtectTestCase(TestCase):
+
+ def testConfigProtect(self):
+ """
+ Demonstrates many different scenarios. For example:
+
+ * regular file replaces regular file
+ * regular file replaces symlink
+ * regular file replaces directory
+ * symlink replaces symlink
+ * symlink replaces regular file
+ * symlink replaces directory
+ * directory replaces regular file
+ * directory replaces symlink
+ """
+
+ debug = False
+
+ content_A_1 = """
+S="${WORKDIR}"
+
+src_install() {
+ insinto /etc/A
+ keepdir /etc/A/dir_a
+ keepdir /etc/A/symlink_replaces_dir
+ keepdir /etc/A/regular_replaces_dir
+ echo regular_a_1 > "${T}"/regular_a
+ doins "${T}"/regular_a
+ echo regular_b_1 > "${T}"/regular_b
+ doins "${T}"/regular_b
+ dosym regular_a /etc/A/regular_replaces_symlink
+ dosym regular_b /etc/A/symlink_replaces_symlink
+ echo regular_replaces_regular_1 > \
+ "${T}"/regular_replaces_regular
+ doins "${T}"/regular_replaces_regular
+ echo symlink_replaces_regular > \
+ "${T}"/symlink_replaces_regular
+ doins "${T}"/symlink_replaces_regular
+}
+
+"""
+
+ content_A_2 = """
+S="${WORKDIR}"
+
+src_install() {
+ insinto /etc/A
+ keepdir /etc/A/dir_a
+ dosym dir_a /etc/A/symlink_replaces_dir
+ echo regular_replaces_dir > "${T}"/regular_replaces_dir
+ doins "${T}"/regular_replaces_dir
+ echo regular_a_2 > "${T}"/regular_a
+ doins "${T}"/regular_a
+ echo regular_b_2 > "${T}"/regular_b
+ doins "${T}"/regular_b
+ echo regular_replaces_symlink > \
+ "${T}"/regular_replaces_symlink
+ doins "${T}"/regular_replaces_symlink
+ dosym regular_b /etc/A/symlink_replaces_symlink
+ echo regular_replaces_regular_2 > \
+ "${T}"/regular_replaces_regular
+ doins "${T}"/regular_replaces_regular
+ dosym regular_a /etc/A/symlink_replaces_regular
+}
+
+"""
+
+ ebuilds = {
+ "dev-libs/A-1": {
+ "EAPI" : "5",
+ "IUSE" : "+flag",
+ "KEYWORDS": "x86",
+ "LICENSE": "GPL-2",
+ "MISC_CONTENT": content_A_1,
+ },
+ "dev-libs/A-2": {
+ "EAPI" : "5",
+ "IUSE" : "+flag",
+ "KEYWORDS": "x86",
+ "LICENSE": "GPL-2",
+ "MISC_CONTENT": content_A_2,
+ },
+ }
+
+ playground = ResolverPlayground(
+ ebuilds=ebuilds, debug=debug)
+ settings = playground.settings
+ eprefix = settings["EPREFIX"]
+ eroot = settings["EROOT"]
+ var_cache_edb = os.path.join(eprefix, "var", "cache", "edb")
+
+ portage_python = portage._python_interpreter
+ dispatch_conf_cmd = (portage_python, "-b", "-Wd",
+ os.path.join(self.sbindir, "dispatch-conf"))
+ emerge_cmd = (portage_python, "-b", "-Wd",
+ os.path.join(self.bindir, "emerge"))
+ etc_update_cmd = (BASH_BINARY,
+ os.path.join(self.sbindir, "etc-update"))
+ etc_update_auto = etc_update_cmd + ("--automode", "-5",)
+
+ config_protect = "/etc"
+
+ def modify_files(dir_path):
+ for name in os.listdir(dir_path):
+ path = os.path.join(dir_path, name)
+ st = os.lstat(path)
+ if stat.S_ISREG(st.st_mode):
+ with io.open(path, mode='a',
+ encoding=_encodings["stdio"]) as f:
+ f.write("modified at %d\n" % time.time())
+ elif stat.S_ISLNK(st.st_mode):
+ old_dest = os.readlink(path)
+ os.unlink(path)
+ os.symlink(old_dest +
+ " modified at %d" % time.time(), path)
+
+ def updated_config_files(count):
+ self.assertEqual(count,
+ sum(len(x[1]) for x in find_updated_config_files(eroot,
+ shlex_split(config_protect))))
+
+ test_commands = (
+ etc_update_cmd,
+ dispatch_conf_cmd,
+ emerge_cmd + ("-1", "=dev-libs/A-1"),
+ partial(updated_config_files, 0),
+ emerge_cmd + ("-1", "=dev-libs/A-2"),
+ partial(updated_config_files, 2),
+ etc_update_auto,
+ partial(updated_config_files, 0),
+ emerge_cmd + ("-1", "=dev-libs/A-2"),
+ partial(updated_config_files, 0),
+ # Test bug #523684, where a file renamed or removed by the
+ # admin forces replacement files to be merged with config
+ # protection.
+ partial(shutil.rmtree,
+ os.path.join(eprefix, "etc", "A")),
+ emerge_cmd + ("-1", "=dev-libs/A-2"),
+ partial(updated_config_files, 8),
+ etc_update_auto,
+ partial(updated_config_files, 0),
+ # Modify some config files, and verify that it triggers
+ # config protection.
+ partial(modify_files,
+ os.path.join(eroot, "etc", "A")),
+ emerge_cmd + ("-1", "=dev-libs/A-2"),
+ partial(updated_config_files, 6),
+ etc_update_auto,
+ partial(updated_config_files, 0),
+ # Modify some config files, downgrade to A-1, and verify
+ # that config protection works properly when the file
+ # types are changing.
+ partial(modify_files,
+ os.path.join(eroot, "etc", "A")),
+ emerge_cmd + ("-1", "--noconfmem", "=dev-libs/A-1"),
+ partial(updated_config_files, 6),
+ etc_update_auto,
+ partial(updated_config_files, 0),
+ )
+
+ distdir = playground.distdir
+ fake_bin = os.path.join(eprefix, "bin")
+ portage_tmpdir = os.path.join(eprefix, "var", "tmp", "portage")
+
+ 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",
+ "CONFIG_PROTECT": config_protect,
+ "DISTDIR" : distdir,
+ "EMERGE_DEFAULT_OPTS": "-v",
+ "EMERGE_WARNING_DELAY" : "0",
+ "INFODIR" : "",
+ "INFOPATH" : "",
+ "PATH" : path,
+ "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,
+ "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"]
+
+ dirs = [distdir, fake_bin, portage_tmpdir,
+ 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 = ["prepstrip", "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")
+
+ 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()
diff --git a/lib/portage/tests/emerge/test_emerge_blocker_file_collision.py b/lib/portage/tests/emerge/test_emerge_blocker_file_collision.py
new file mode 100644
index 000000000..10d09d843
--- /dev/null
+++ b/lib/portage/tests/emerge/test_emerge_blocker_file_collision.py
@@ -0,0 +1,168 @@
+# Copyright 2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import subprocess
+import sys
+
+import portage
+from portage import os
+from portage import _unicode_decode
+from portage.const import PORTAGE_PYM_PATH, USER_CONFIG_PATH
+from portage.process import find_binary
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import ResolverPlayground
+from portage.util import ensure_dirs
+
+class BlockerFileCollisionEmergeTestCase(TestCase):
+
+ def testBlockerFileCollision(self):
+
+ debug = False
+
+ install_something = """
+S="${WORKDIR}"
+
+src_install() {
+ einfo "installing something..."
+ insinto /usr/lib
+ echo "${PN}" > "${T}/file-collision"
+ doins "${T}/file-collision"
+}
+"""
+
+ ebuilds = {
+ "dev-libs/A-1" : {
+ "EAPI": "6",
+ "MISC_CONTENT": install_something,
+ "RDEPEND": "!dev-libs/B",
+ },
+ "dev-libs/B-1" : {
+ "EAPI": "6",
+ "MISC_CONTENT": install_something,
+ "RDEPEND": "!dev-libs/A",
+ },
+ }
+
+ playground = ResolverPlayground(ebuilds=ebuilds, debug=debug)
+ settings = playground.settings
+ eprefix = settings["EPREFIX"]
+ eroot = settings["EROOT"]
+ var_cache_edb = os.path.join(eprefix, "var", "cache", "edb")
+ user_config_dir = os.path.join(eprefix, USER_CONFIG_PATH)
+
+ portage_python = portage._python_interpreter
+ emerge_cmd = (portage_python, "-b", "-Wd",
+ os.path.join(self.bindir, "emerge"))
+
+ file_collision = os.path.join(eroot, 'usr/lib/file-collision')
+
+ test_commands = (
+ emerge_cmd + ("--oneshot", "dev-libs/A",),
+ (lambda: portage.util.grablines(file_collision) == ["A\n"],),
+ emerge_cmd + ("--oneshot", "dev-libs/B",),
+ (lambda: portage.util.grablines(file_collision) == ["B\n"],),
+ emerge_cmd + ("--oneshot", "dev-libs/A",),
+ (lambda: portage.util.grablines(file_collision) == ["A\n"],),
+ ({"FEATURES":"parallel-install"},) + emerge_cmd + ("--oneshot", "dev-libs/B",),
+ (lambda: portage.util.grablines(file_collision) == ["B\n"],),
+ ({"FEATURES":"parallel-install"},) + emerge_cmd + ("-Cq", "dev-libs/B",),
+ (lambda: not os.path.exists(file_collision),),
+ )
+
+ 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,
+ "PORTAGE_REPOSITORIES" : settings.repositories.config_string(),
+ "PYTHONDONTWRITEBYTECODE" : os.environ.get("PYTHONDONTWRITEBYTECODE", ""),
+ "PYTHONPATH" : pythonpath,
+ }
+
+ if "__PORTAGE_TEST_HARDLINK_LOCKS" in os.environ:
+ env["__PORTAGE_TEST_HARDLINK_LOCKS"] = \
+ os.environ["__PORTAGE_TEST_HARDLINK_LOCKS"]
+
+ dirs = [playground.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
+
+ 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.debug = False
+ playground.cleanup()
diff --git a/lib/portage/tests/emerge/test_emerge_slot_abi.py b/lib/portage/tests/emerge/test_emerge_slot_abi.py
new file mode 100644
index 000000000..200699396
--- /dev/null
+++ b/lib/portage/tests/emerge/test_emerge_slot_abi.py
@@ -0,0 +1,179 @@
+# Copyright 2012-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import subprocess
+import sys
+
+import portage
+from portage import os
+from portage import _unicode_decode
+from portage.const import (BASH_BINARY, PORTAGE_PYM_PATH, USER_CONFIG_PATH)
+from portage.process import find_binary
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import ResolverPlayground
+from portage.util import ensure_dirs
+
+class SlotAbiEmergeTestCase(TestCase):
+
+ 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
+ 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, "-b", "-Wd",
+ os.path.join(self.bindir, "ebuild"))
+ emerge_cmd = (portage_python, "-b", "-Wd",
+ os.path.join(self.bindir, "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,
+ "PORTAGE_REPOSITORIES" : settings.repositories.config_string(),
+ "PYTHONDONTWRITEBYTECODE" : os.environ.get("PYTHONDONTWRITEBYTECODE", ""),
+ "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()
diff --git a/lib/portage/tests/emerge/test_global_updates.py b/lib/portage/tests/emerge/test_global_updates.py
new file mode 100644
index 000000000..eb5431059
--- /dev/null
+++ b/lib/portage/tests/emerge/test_global_updates.py
@@ -0,0 +1,41 @@
+# Copyright 2011-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from portage.tests import TestCase
+from portage.update import parse_updates
+from portage.dep import Atom
+
+class ParseUpdatesTestCase(TestCase):
+
+ def testParseUpdates(self):
+ test_cases = (
+ (
+ """
+slotmove invalid_atom 0 3
+slotmove !=invalid/blocker-3* 0 3
+slotmove =valid/atom-3* 0 3 invalid_extra_token
+slotmove =valid/atom-3* 0 3
+slotmove =valid/atom-3* 0 3/3.1
+slotmove =valid/atom-3* 0/0 3
+move valid/atom1 valid/atom2 invalid_extra_token
+move valid/atom1 invalid_atom2
+move invalid_atom1 valid/atom2
+move !invalid/blocker1 valid/atom2
+move valid/atom1 !invalid/blocker2
+move =invalid/operator-1* valid/atom2
+move valid/atom1 =invalid/operator-2*
+move valid/atom1 valid/atom2
+""",
+ [
+ ['slotmove', Atom('=valid/atom-3*'), '0', '3'],
+ ['move', Atom('valid/atom1'), Atom('valid/atom2')],
+ ],
+ 12,
+ ),
+
+ )
+
+ for input_content, expected_output, expected_error_count in test_cases:
+ output_data, errors = parse_updates(input_content)
+ self.assertEqual(output_data, expected_output)
+ self.assertEqual(len(errors), expected_error_count)
diff --git a/lib/portage/tests/emerge/test_simple.py b/lib/portage/tests/emerge/test_simple.py
new file mode 100644
index 000000000..b1402ddd5
--- /dev/null
+++ b/lib/portage/tests/emerge/test_simple.py
@@ -0,0 +1,505 @@
+# Copyright 2011-2018 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import subprocess
+import sys
+
+import portage
+from portage import os
+from portage import _unicode_decode
+from portage.const import (BASH_BINARY, PORTAGE_BASE_PATH,
+ PORTAGE_PYM_PATH, USER_CONFIG_PATH)
+from portage.process import find_binary
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import ResolverPlayground
+from portage.util import (ensure_dirs, find_updated_config_files,
+ shlex_split)
+
+class SimpleEmergeTestCase(TestCase):
+
+ def _have_python_xml(self):
+ try:
+ __import__("xml.etree.ElementTree")
+ __import__("xml.parsers.expat").parsers.expat.ExpatError
+ except (AttributeError, ImportError):
+ return False
+ return True
+
+ 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)
+ 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"),
+
+ # If EMERGE_DEFAULT_OPTS contains --autounmask=n, then --autounmask
+ # must be specified with --autounmask-continue.
+ ({"EMERGE_DEFAULT_OPTS" : "--autounmask=n"},) + \
+ emerge_cmd + ("--autounmask", "--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.
+ # EAPI 7
+ ({"EPREFIX" : cross_prefix},) + \
+ emerge_cmd + ("dev-libs/C",),
+ ({"EPREFIX" : cross_prefix},) + \
+ portageq_cmd + ("has_version", cross_prefix, "dev-libs/C"),
+ ({"EPREFIX" : cross_prefix},) + \
+ portageq_cmd + ("has_version", cross_prefix, "dev-libs/D"),
+ ({"ROOT": cross_root},) + emerge_cmd + ("dev-libs/D",),
+ portageq_cmd + ("has_version", cross_eroot, "dev-libs/D"),
+ # EAPI 5
+ ({"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()