aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Le Cuirot <chewi@gentoo.org>2023-07-21 21:36:31 +0100
committerSam James <sam@gentoo.org>2023-08-02 07:31:20 +0100
commitf3b90592994c418286b10d883b4aee9a104f5e75 (patch)
tree773d70d2932a1db333e8dbc32b592deca23c1dc0
parentPatch Meson in GitHub CI to fix pypy-3.9 detection (diff)
downloadportage-f3b90592.tar.gz
portage-f3b90592.tar.bz2
portage-f3b90592.zip
Drop custom test runner bits in favour of pytest
Signed-off-by: James Le Cuirot <chewi@gentoo.org> Signed-off-by: Sam James <sam@gentoo.org>
-rw-r--r--.builds/lint.yml2
-rw-r--r--.github/workflows/lint.yml2
-rw-r--r--DEVELOPING2
-rw-r--r--TEST-NOTES2
-rw-r--r--lib/portage/tests/__init__.py269
-rw-r--r--lib/portage/tests/conftest.py27
-rw-r--r--lib/portage/tests/dep/meson.build10
-rw-r--r--lib/portage/tests/dep/test_atom.py (renamed from lib/portage/tests/dep/testAtom.py)0
-rw-r--r--lib/portage/tests/dep/test_check_required_use.py (renamed from lib/portage/tests/dep/testCheckRequiredUse.py)0
-rw-r--r--lib/portage/tests/dep/test_extended_atom_dict.py (renamed from lib/portage/tests/dep/testExtendedAtomDict.py)0
-rw-r--r--lib/portage/tests/dep/test_extract_affecting_use.py (renamed from lib/portage/tests/dep/testExtractAffectingUSE.py)0
-rw-r--r--lib/portage/tests/dep/test_standalone.py (renamed from lib/portage/tests/dep/testStandalone.py)0
-rw-r--r--lib/portage/tests/glsa/test_security_set.py16
-rw-r--r--lib/portage/tests/meson.build1
-rw-r--r--lib/portage/tests/process/test_poll.py1
-rw-r--r--lib/portage/tests/process/test_unshare_net.py13
-rw-r--r--lib/portage/tests/resolver/test_autounmask_multilib_use.py2
-rw-r--r--lib/portage/tests/resolver/test_autounmask_use_slot_conflict.py2
-rw-r--r--lib/portage/tests/resolver/test_or_choices.py2
-rw-r--r--lib/portage/tests/runTests.py79
-rw-r--r--lib/portage/tests/sets/base/meson.build4
-rw-r--r--lib/portage/tests/sets/base/test_internal_package_set.py (renamed from lib/portage/tests/sets/base/testInternalPackageSet.py)0
-rw-r--r--lib/portage/tests/sets/base/test_variable_set.py (renamed from lib/portage/tests/sets/base/testVariableSet.py)0
-rw-r--r--lib/portage/tests/sets/files/meson.build4
-rw-r--r--lib/portage/tests/sets/files/test_config_file_set.py (renamed from lib/portage/tests/sets/files/testConfigFileSet.py)0
-rw-r--r--lib/portage/tests/sets/files/test_static_file_set.py (renamed from lib/portage/tests/sets/files/testStaticFileSet.py)0
-rw-r--r--lib/portage/tests/sets/shell/meson.build2
-rw-r--r--lib/portage/tests/sets/shell/test_shell.py (renamed from lib/portage/tests/sets/shell/testShell.py)0
-rw-r--r--lib/portage/tests/sync/test_sync_local.py13
-rw-r--r--lib/portage/tests/util/file_copy/test_copyfile.py11
-rw-r--r--lib/portage/tests/util/futures/test_iter_completed.py12
-rw-r--r--meson.build4
-rwxr-xr-xruntests184
-rw-r--r--tox.ini2
34 files changed, 49 insertions, 617 deletions
diff --git a/.builds/lint.yml b/.builds/lint.yml
index 847552aac..e7aad2114 100644
--- a/.builds/lint.yml
+++ b/.builds/lint.yml
@@ -25,7 +25,7 @@ tasks:
- black: |
source .venv/bin/activate
cd portage
- STRAGGLERS="$(find bin runtests -type f -not -name '*.py' -not -name '*.sh' | \
+ STRAGGLERS="$(find bin -type f -not -name '*.py' -not -name '*.sh' | \
xargs grep -l '#!/usr/bin/env python' | \
tr '\n' ' ')"
time black --check --diff --color . $STRAGGLERS
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index f2af40957..69b9578d4 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -11,7 +11,7 @@ jobs:
id: stragglers
run: |
echo "::set-output name=missed::$(
- find bin runtests -type f -not -name '*.py' -not -name '*.sh' | \
+ find bin -type f -not -name '*.py' -not -name '*.sh' | \
xargs grep -l '#!/usr/bin/env python' | tr $'\n' ' ')"
- uses: psf/black@stable
with:
diff --git a/DEVELOPING b/DEVELOPING
index a49afff83..8302f9aa1 100644
--- a/DEVELOPING
+++ b/DEVELOPING
@@ -223,7 +223,7 @@ and commit.
- meson setup -Dmodules-only=true build
- meson test -C build --verbose
Use meson setup's --native-file to override the Python version. See
- PYTHON_SUPPORTED_VERSIONS in runtests.
+ Python versions listed in tox.ini.
4. Version bump the ebuild locally (don't push) and verify it can re-install itself:
emerge --oneshot sys-apps/portage
diff --git a/TEST-NOTES b/TEST-NOTES
index 8be5f9cf3..8a1b981bb 100644
--- a/TEST-NOTES
+++ b/TEST-NOTES
@@ -42,4 +42,4 @@ functionality. You should raise portage.tests.SkipException in that case.
emerge
------
-The emerge namespace currently has 0 tests (and no runner)
+The emerge namespace currently has 0 tests
diff --git a/lib/portage/tests/__init__.py b/lib/portage/tests/__init__.py
index d8e0cc78f..ef5985298 100644
--- a/lib/portage/tests/__init__.py
+++ b/lib/portage/tests/__init__.py
@@ -1,5 +1,5 @@
# tests/__init__.py -- Portage Unit Test functionality
-# Copyright 2006-2021 Gentoo Authors
+# Copyright 2006-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
import argparse
@@ -64,175 +64,6 @@ def cnf_sbindir():
return os.path.join(portage.const.EPREFIX or "/", "usr", "sbin")
-def main():
- suite = unittest.TestSuite()
- basedir = Path(__file__).resolve().parent
-
- argv0 = Path(sys.argv[0])
-
- usage = f"usage: {argv0.name} [options] [tests to run]"
- parser = argparse.ArgumentParser(usage=usage)
- parser.add_argument(
- "-l", "--list", help="list all tests", action="store_true", dest="list_tests"
- )
- parser.add_argument("tests", nargs="*", type=Path)
- options = parser.parse_args(args=sys.argv)
-
- if (
- no_color(os.environ)
- or os.environ.get("TERM") == "dumb"
- or not sys.stdout.isatty()
- ):
- portage.output.nocolor()
-
- if options.list_tests:
- testdir = argv0.parent
- for mydir in getTestDirs(basedir):
- testsubdir = mydir.name
- for name in getTestNames(mydir):
- print(f"{testdir}/{testsubdir}/{name}.py")
- return os.EX_OK
-
- if len(options.tests) > 1:
- suite.addTests(getTestFromCommandLine(options.tests[1:], basedir))
- else:
- for mydir in getTestDirs(basedir):
- suite.addTests(getTests(mydir, basedir))
-
- result = TextTestRunner(verbosity=2).run(suite)
- if not result.wasSuccessful():
- return 1
- return os.EX_OK
-
-
-def my_import(name):
- mod = __import__(name)
- components = name.split(".")
- for comp in components[1:]:
- mod = getattr(mod, comp)
- return mod
-
-
-def getTestFromCommandLine(args, base_path):
- result = []
- for arg in args:
- realpath = arg.resolve()
- path = realpath.parent
- f = realpath.relative_to(path)
-
- if not f.name.startswith("test") or not f.suffix == ".py":
- raise Exception(f"Invalid argument: '{arg}'")
-
- mymodule = f.stem
- result.extend(getTestsFromFiles(path, base_path, [mymodule]))
- return result
-
-
-def getTestDirs(base_path):
- TEST_FILE = "__test__.py"
- testDirs = []
-
- # the os.walk help mentions relative paths as being quirky
- # I was tired of adding dirs to the list, so now we add __test__.py
- # to each dir we want tested.
- for testFile in base_path.rglob(TEST_FILE):
- testDirs.append(testFile.parent)
-
- testDirs.sort()
- return testDirs
-
-
-def getTestNames(path):
- files = path.glob("*")
- files = [f.stem for f in files if f.name.startswith("test") and f.suffix == ".py"]
- files.sort()
- return files
-
-
-def getTestsFromFiles(path, base_path, files):
- parent_path = path.relative_to(base_path)
- parent_module = ".".join(("portage", "tests") + parent_path.parts)
- result = []
- for mymodule in files:
- # Make the trailing / a . for module importing
- modname = ".".join((parent_module, mymodule))
- mod = my_import(modname)
- result.append(unittest.TestLoader().loadTestsFromModule(mod))
- return result
-
-
-def getTests(path, base_path):
- """
-
- path is the path to a given subdir ( 'portage/' for example)
- This does a simple filter on files in that dir to give us modules
- to import
-
- """
- return getTestsFromFiles(path, base_path, getTestNames(path))
-
-
-class TextTestResult(_TextTestResult):
- """
- We need a subclass of unittest.runner.TextTestResult to handle tests with TODO
-
- This just adds an addTodo method that can be used to add tests
- that are marked TODO; these can be displayed later
- by the test runner.
- """
-
- def __init__(self, stream, descriptions, verbosity):
- super().__init__(stream, descriptions, verbosity)
- self.todoed = []
- self.portage_skipped = []
-
- def addSuccess(self, test):
- super(_TextTestResult, self).addSuccess(test)
- if self.showAll:
- self.stream.writeln(colorize("GOOD", "ok"))
- elif self.dots:
- self.stream.write(colorize("GOOD", "."))
- self.stream.flush()
-
- def addError(self, test, err):
- super(_TextTestResult, self).addError(test, err)
- if self.showAll:
- self.stream.writeln(colorize("BAD", "ERROR"))
- elif self.dots:
- self.stream.write(colorize("HILITE", "E"))
- self.stream.flush()
-
- def addFailure(self, test, err):
- super(_TextTestResult, self).addFailure(test, err)
- if self.showAll:
- self.stream.writeln(colorize("BAD", "FAIL"))
- elif self.dots:
- self.stream.write(colorize("BAD", "F"))
- self.stream.flush()
-
- def addTodo(self, test, info):
- self.todoed.append((test, info))
- if self.showAll:
- self.stream.writeln(colorize("BRACKET", "TODO"))
- elif self.dots:
- self.stream.write(colorize("BRACKET", "."))
-
- def addPortageSkip(self, test, info):
- self.portage_skipped.append((test, info))
- if self.showAll:
- self.stream.writeln(colorize("WARN", "SKIP"))
- elif self.dots:
- self.stream.write(colorize("WARN", "."))
-
- def printErrors(self):
- if self.dots or self.showAll:
- self.stream.writeln()
- self.printErrorList("ERROR", self.errors)
- self.printErrorList("FAIL", self.failures)
- self.printErrorList("TODO", self.todoed)
- self.printErrorList("SKIP", self.portage_skipped)
-
-
class TestCase(unittest.TestCase):
"""
We need a way to mark a unit test as "ok to fail"
@@ -243,69 +74,11 @@ class TestCase(unittest.TestCase):
def __init__(self, *pargs, **kwargs):
unittest.TestCase.__init__(self, *pargs, **kwargs)
- self.todo = False
- self.portage_skip = None
self.cnf_path = cnf_path
self.cnf_etc_path = cnf_etc_path
self.bindir = cnf_bindir
self.sbindir = cnf_sbindir
- def defaultTestResult(self):
- return TextTestResult()
-
- def run(self, result=None):
- if result is None:
- result = self.defaultTestResult()
- result.startTest(self)
- testMethod = getattr(self, self._testMethodName)
- try:
- ok = False
- try:
- try:
- self.setUp()
- except KeyboardInterrupt:
- raise
- except unittest.SkipTest:
- raise
- except Exception:
- result.addError(self, sys.exc_info())
- return
-
- testMethod()
- ok = True
- except unittest.SkipTest as e:
- result.addPortageSkip(self, f"{testMethod}: SKIP: {str(e)}")
- except self.failureException:
- if self.portage_skip is not None:
- if self.portage_skip is True:
- result.addPortageSkip(self, f"{testMethod}: SKIP")
- else:
- result.addPortageSkip(
- self, f"{testMethod}: SKIP: {self.portage_skip}"
- )
- elif self.todo:
- result.addTodo(self, f"{testMethod}: TODO")
- else:
- result.addFailure(self, sys.exc_info())
- except (KeyboardInterrupt, SystemExit):
- raise
- except:
- result.addError(self, sys.exc_info())
-
- try:
- self.tearDown()
- except SystemExit:
- raise
- except KeyboardInterrupt:
- raise
- except:
- result.addError(self, sys.exc_info())
- ok = False
- if ok:
- result.addSuccess(self)
- finally:
- result.stopTest(self)
-
def assertRaisesMsg(self, msg, excClass, callableObj, *args, **kwargs):
"""Fail unless an exception of class excClass is thrown
by callableObj when invoked with arguments args and keyword
@@ -332,46 +105,6 @@ class TestCase(unittest.TestCase):
raise self.failureException(f"path exists when it should not: {path}")
-class TextTestRunner(unittest.TextTestRunner):
- """
- We subclass unittest.TextTestRunner to output SKIP for tests that fail but are skippable
- """
-
- def _makeResult(self):
- return TextTestResult(self.stream, self.descriptions, self.verbosity)
-
- def run(self, test):
- """
- Run the given test case or test suite.
- """
- result = self._makeResult()
- startTime = time.time()
- test(result)
- stopTime = time.time()
- timeTaken = stopTime - startTime
- result.printErrors()
- self.stream.writeln(result.separator2)
- run = result.testsRun
- self.stream.writeln(
- "Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", timeTaken)
- )
- self.stream.writeln()
- if not result.wasSuccessful():
- self.stream.write(colorize("BAD", "FAILED") + " (")
- failed = len(result.failures)
- errored = len(result.errors)
- if failed:
- self.stream.write("failures=%d" % failed)
- if errored:
- if failed:
- self.stream.write(", ")
- self.stream.write("errors=%d" % errored)
- self.stream.writeln(")")
- else:
- self.stream.writeln(colorize("GOOD", "OK"))
- return result
-
-
test_cps = ["sys-apps/portage", "virtual/portage"]
test_versions = ["1.0", "1.0-r1", "2.3_p4", "1.0_alpha57"]
test_slots = [None, "1", "gentoo-sources-2.6.17", "spankywashere"]
diff --git a/lib/portage/tests/conftest.py b/lib/portage/tests/conftest.py
index 88fc72b15..76bdaa381 100644
--- a/lib/portage/tests/conftest.py
+++ b/lib/portage/tests/conftest.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# runTests.py -- Portage Unit Test Functionality
# Copyright 2006-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
@@ -64,22 +63,24 @@ def prepare_environment():
path.insert(0, PORTAGE_BIN_PATH)
os.environ["PATH"] = ":".join(path)
- # Copy GPG test keys to temporary directory
- gpg_path = tempfile.mkdtemp(prefix="gpg_")
+ try:
+ # Copy GPG test keys to temporary directory
+ gpg_path = tempfile.mkdtemp(prefix="gpg_")
- shutil.copytree(
- os.path.join(os.path.dirname(os.path.realpath(__file__)), ".gnupg"),
- gpg_path,
- dirs_exist_ok=True,
- )
+ shutil.copytree(
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), ".gnupg"),
+ gpg_path,
+ dirs_exist_ok=True,
+ )
- os.chmod(gpg_path, 0o700)
- os.environ["PORTAGE_GNUPGHOME"] = gpg_path
+ os.chmod(gpg_path, 0o700)
+ os.environ["PORTAGE_GNUPGHOME"] = gpg_path
- yield
+ yield
- global_event_loop().close()
- shutil.rmtree(gpg_path, ignore_errors=True)
+ finally:
+ global_event_loop().close()
+ shutil.rmtree(gpg_path, ignore_errors=True)
# if __name__ == "__main__":
diff --git a/lib/portage/tests/dep/meson.build b/lib/portage/tests/dep/meson.build
index f96018917..848f5aade 100644
--- a/lib/portage/tests/dep/meson.build
+++ b/lib/portage/tests/dep/meson.build
@@ -1,10 +1,10 @@
py.install_sources(
[
- 'testAtom.py',
- 'testCheckRequiredUse.py',
- 'testExtendedAtomDict.py',
- 'testExtractAffectingUSE.py',
- 'testStandalone.py',
+ 'test_atom.py',
+ 'test_check_required_use.py',
+ 'test_extended_atom_dict.py',
+ 'test_extract_affecting_use.py',
+ 'test_standalone.py',
'test_best_match_to_list.py',
'test_dep_getcpv.py',
'test_dep_getrepo.py',
diff --git a/lib/portage/tests/dep/testAtom.py b/lib/portage/tests/dep/test_atom.py
index b7d8bee8b..b7d8bee8b 100644
--- a/lib/portage/tests/dep/testAtom.py
+++ b/lib/portage/tests/dep/test_atom.py
diff --git a/lib/portage/tests/dep/testCheckRequiredUse.py b/lib/portage/tests/dep/test_check_required_use.py
index cbb1a608a..cbb1a608a 100644
--- a/lib/portage/tests/dep/testCheckRequiredUse.py
+++ b/lib/portage/tests/dep/test_check_required_use.py
diff --git a/lib/portage/tests/dep/testExtendedAtomDict.py b/lib/portage/tests/dep/test_extended_atom_dict.py
index 7c177b927..7c177b927 100644
--- a/lib/portage/tests/dep/testExtendedAtomDict.py
+++ b/lib/portage/tests/dep/test_extended_atom_dict.py
diff --git a/lib/portage/tests/dep/testExtractAffectingUSE.py b/lib/portage/tests/dep/test_extract_affecting_use.py
index 8c93ad973..8c93ad973 100644
--- a/lib/portage/tests/dep/testExtractAffectingUSE.py
+++ b/lib/portage/tests/dep/test_extract_affecting_use.py
diff --git a/lib/portage/tests/dep/testStandalone.py b/lib/portage/tests/dep/test_standalone.py
index 3b6cb12d7..3b6cb12d7 100644
--- a/lib/portage/tests/dep/testStandalone.py
+++ b/lib/portage/tests/dep/test_standalone.py
diff --git a/lib/portage/tests/glsa/test_security_set.py b/lib/portage/tests/glsa/test_security_set.py
index 867a7cd4f..a0ba1e5b4 100644
--- a/lib/portage/tests/glsa/test_security_set.py
+++ b/lib/portage/tests/glsa/test_security_set.py
@@ -1,4 +1,4 @@
-# Copyright 2013-2022 Gentoo Authors
+# Copyright 2013-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
@@ -64,7 +64,7 @@ class SecuritySetTestCase(TestCase):
__import__("xml.etree.ElementTree")
__import__("xml.parsers.expat").parsers.expat.ExpatError
except (AttributeError, ImportError):
- return "python is missing xml support"
+ self.skipTest("python is missing xml support")
def write_glsa_test_case(self, glsa_dir, glsa):
with open(
@@ -75,11 +75,7 @@ class SecuritySetTestCase(TestCase):
f.write(self.glsa_template % glsa)
def testSecuritySet(self):
- skip_reason = self._must_skip()
- if skip_reason:
- self.portage_skip = skip_reason
- self.assertFalse(True, skip_reason)
- return
+ self._must_skip()
ebuilds = {
"cat/A-vulnerable-2.2": {"KEYWORDS": "x86"},
@@ -159,11 +155,7 @@ class SecuritySetTestCase(TestCase):
# testing the format parsing with a bit more flexibility (no
# need to keep inventing packages).
- skip_reason = self._must_skip()
- if skip_reason:
- self.portage_skip = skip_reason
- self.assertFalse(True, skip_reason)
- return
+ self._must_skip()
ebuilds = {
"cat/A-vulnerable-2.2": {"KEYWORDS": "x86"},
diff --git a/lib/portage/tests/meson.build b/lib/portage/tests/meson.build
index 86e8e71ce..e8f204b51 100644
--- a/lib/portage/tests/meson.build
+++ b/lib/portage/tests/meson.build
@@ -1,7 +1,6 @@
py.install_sources(
[
'conftest.py',
- 'runTests.py',
'__init__.py',
],
subdir : 'portage/tests',
diff --git a/lib/portage/tests/process/test_poll.py b/lib/portage/tests/process/test_poll.py
index 371dd1906..65a9ca1bf 100644
--- a/lib/portage/tests/process/test_poll.py
+++ b/lib/portage/tests/process/test_poll.py
@@ -121,4 +121,3 @@ class PipeReaderArrayTestCase(PipeReaderTestCase):
super().__init__(*args, **kwargs)
# https://bugs.python.org/issue5380
# https://bugs.pypy.org/issue956
- self.todo = True
diff --git a/lib/portage/tests/process/test_unshare_net.py b/lib/portage/tests/process/test_unshare_net.py
index e17357f4d..dabf15585 100644
--- a/lib/portage/tests/process/test_unshare_net.py
+++ b/lib/portage/tests/process/test_unshare_net.py
@@ -33,19 +33,6 @@ class UnshareNetTestCase(TestCase):
)
@pytest.mark.skipif(platform.system() != "Linux", reason="not Linux")
def testUnshareNet(self):
- AM_I_UNDER_PYTEST = "PYTEST_CURRENT_TEST" in os.environ
- if not AM_I_UNDER_PYTEST:
- if platform.system() != "Linux":
- self.skipTest("not Linux")
- if portage.process.find_binary("ping") is None:
- self.skipTest("ping not found")
-
- errno_value = portage.process._unshare_validate(CLONE_NEWNET)
- if errno_value != 0:
- self.skipTest(
- f"Unable to unshare: {errno.errorcode.get(errno_value, '?')}"
- )
-
env = os.environ.copy()
env["IPV6"] = "1" if portage.process._has_ipv6() else ""
self.assertEqual(
diff --git a/lib/portage/tests/resolver/test_autounmask_multilib_use.py b/lib/portage/tests/resolver/test_autounmask_multilib_use.py
index 3abbebbd5..2d3da85c5 100644
--- a/lib/portage/tests/resolver/test_autounmask_multilib_use.py
+++ b/lib/portage/tests/resolver/test_autounmask_multilib_use.py
@@ -13,8 +13,6 @@ from portage.tests.resolver.ResolverPlayground import (
class AutounmaskMultilibUseTestCase(TestCase):
@pytest.mark.xfail()
def testAutounmaskMultilibUse(self):
- self.todo = True
-
ebuilds = {
"x11-proto/xextproto-7.2.1-r1": {
"EAPI": "5",
diff --git a/lib/portage/tests/resolver/test_autounmask_use_slot_conflict.py b/lib/portage/tests/resolver/test_autounmask_use_slot_conflict.py
index 2db1396bc..a0b8c4ae7 100644
--- a/lib/portage/tests/resolver/test_autounmask_use_slot_conflict.py
+++ b/lib/portage/tests/resolver/test_autounmask_use_slot_conflict.py
@@ -13,8 +13,6 @@ from portage.tests.resolver.ResolverPlayground import (
class AutounmaskUseSlotConflictTestCase(TestCase):
@pytest.mark.xfail()
def testAutounmaskUseSlotConflict(self):
- self.todo = True
-
ebuilds = {
"sci-libs/K-1": {"IUSE": "+foo", "EAPI": 1},
"sci-libs/L-1": {"DEPEND": "sci-libs/K[-foo]", "EAPI": 2},
diff --git a/lib/portage/tests/resolver/test_or_choices.py b/lib/portage/tests/resolver/test_or_choices.py
index 33707c71a..4258a1ab5 100644
--- a/lib/portage/tests/resolver/test_or_choices.py
+++ b/lib/portage/tests/resolver/test_or_choices.py
@@ -649,8 +649,6 @@ class OrChoicesLibpostprocTestCase(TestCase):
# compatible with any available media-video/ffmpeg slot. In order to
# solve this test case, some fancy backtracking (like for bug 382421)
# will be required.
- self.todo = True
-
ebuilds = {
"media-video/ffmpeg-0.10": {"EAPI": "5", "SLOT": "0.10"},
"media-video/ffmpeg-1.2.2": {"EAPI": "5", "SLOT": "0"},
diff --git a/lib/portage/tests/runTests.py b/lib/portage/tests/runTests.py
deleted file mode 100644
index 36ea3a791..000000000
--- a/lib/portage/tests/runTests.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env python
-# runTests.py -- Portage Unit Test Functionality
-# Copyright 2006-2022 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-import grp
-import os
-import os.path as osp
-import pwd
-import signal
-import tempfile
-import shutil
-import sys
-
-
-def debug_signal(signum, frame):
- import pdb
-
- pdb.set_trace()
-
-
-signal.signal(signal.SIGUSR1, debug_signal)
-
-# Pretend that the current user's uid/gid are the 'portage' uid/gid,
-# so things go smoothly regardless of the current user and global
-# user/group configuration.
-os.environ["PORTAGE_USERNAME"] = pwd.getpwuid(os.getuid()).pw_name
-os.environ["PORTAGE_GRPNAME"] = grp.getgrgid(os.getgid()).gr_name
-
-# Insert our parent dir so we can do shiny import "tests"
-# This line courtesy of Marienz and Pkgcore ;)
-sys.path.insert(0, osp.dirname(osp.dirname(osp.dirname(osp.realpath(__file__)))))
-
-import portage
-
-portage._internal_caller = True
-
-# Ensure that we don't instantiate portage.settings, so that tests should
-# work the same regardless of global configuration file state/existence.
-portage._disable_legacy_globals()
-
-if portage.util.no_color(os.environ):
- portage.output.nocolor()
-
-import portage.tests as tests
-from portage.util._eventloop.global_event_loop import global_event_loop
-from portage.const import PORTAGE_BIN_PATH
-
-path = os.environ.get("PATH", "").split(":")
-path = [x for x in path if x]
-
-insert_bin_path = True
-try:
- insert_bin_path = not path or not os.path.samefile(path[0], PORTAGE_BIN_PATH)
-except OSError:
- pass
-
-if insert_bin_path:
- path.insert(0, PORTAGE_BIN_PATH)
- os.environ["PATH"] = ":".join(path)
-
-# Copy GPG test keys to temporary directory
-gpg_path = tempfile.mkdtemp(prefix="gpg_")
-
-shutil.copytree(
- os.path.join(os.path.dirname(os.path.realpath(__file__)), ".gnupg"),
- gpg_path,
- dirs_exist_ok=True,
-)
-
-os.chmod(gpg_path, 0o700)
-os.environ["PORTAGE_GNUPGHOME"] = gpg_path
-
-if __name__ == "__main__":
- try:
- sys.exit(tests.main())
- finally:
- global_event_loop().close()
- shutil.rmtree(gpg_path, ignore_errors=True)
diff --git a/lib/portage/tests/sets/base/meson.build b/lib/portage/tests/sets/base/meson.build
index ba15a8213..6c59b11ee 100644
--- a/lib/portage/tests/sets/base/meson.build
+++ b/lib/portage/tests/sets/base/meson.build
@@ -1,7 +1,7 @@
py.install_sources(
[
- 'testInternalPackageSet.py',
- 'testVariableSet.py',
+ 'test_internal_package_set.py',
+ 'test_variable_set.py',
'__init__.py',
'__test__.py',
],
diff --git a/lib/portage/tests/sets/base/testInternalPackageSet.py b/lib/portage/tests/sets/base/test_internal_package_set.py
index 77934cab2..77934cab2 100644
--- a/lib/portage/tests/sets/base/testInternalPackageSet.py
+++ b/lib/portage/tests/sets/base/test_internal_package_set.py
diff --git a/lib/portage/tests/sets/base/testVariableSet.py b/lib/portage/tests/sets/base/test_variable_set.py
index 506104667..506104667 100644
--- a/lib/portage/tests/sets/base/testVariableSet.py
+++ b/lib/portage/tests/sets/base/test_variable_set.py
diff --git a/lib/portage/tests/sets/files/meson.build b/lib/portage/tests/sets/files/meson.build
index 0ac7449db..d4550f4ee 100644
--- a/lib/portage/tests/sets/files/meson.build
+++ b/lib/portage/tests/sets/files/meson.build
@@ -1,7 +1,7 @@
py.install_sources(
[
- 'testConfigFileSet.py',
- 'testStaticFileSet.py',
+ 'test_config_file_set.py',
+ 'test_static_file_set.py',
'__init__.py',
'__test__.py',
],
diff --git a/lib/portage/tests/sets/files/testConfigFileSet.py b/lib/portage/tests/sets/files/test_config_file_set.py
index 81419df4a..81419df4a 100644
--- a/lib/portage/tests/sets/files/testConfigFileSet.py
+++ b/lib/portage/tests/sets/files/test_config_file_set.py
diff --git a/lib/portage/tests/sets/files/testStaticFileSet.py b/lib/portage/tests/sets/files/test_static_file_set.py
index a4e6c29c2..a4e6c29c2 100644
--- a/lib/portage/tests/sets/files/testStaticFileSet.py
+++ b/lib/portage/tests/sets/files/test_static_file_set.py
diff --git a/lib/portage/tests/sets/shell/meson.build b/lib/portage/tests/sets/shell/meson.build
index 6044f3ebe..55a41a6e0 100644
--- a/lib/portage/tests/sets/shell/meson.build
+++ b/lib/portage/tests/sets/shell/meson.build
@@ -1,6 +1,6 @@
py.install_sources(
[
- 'testShell.py',
+ 'test_shell.py',
'__init__.py',
'__test__.py',
],
diff --git a/lib/portage/tests/sets/shell/testShell.py b/lib/portage/tests/sets/shell/test_shell.py
index f30b72a8b..f30b72a8b 100644
--- a/lib/portage/tests/sets/shell/testShell.py
+++ b/lib/portage/tests/sets/shell/test_shell.py
diff --git a/lib/portage/tests/sync/test_sync_local.py b/lib/portage/tests/sync/test_sync_local.py
index c400c9bba..a8a71cd4b 100644
--- a/lib/portage/tests/sync/test_sync_local.py
+++ b/lib/portage/tests/sync/test_sync_local.py
@@ -1,4 +1,4 @@
-# Copyright 2014-2021 Gentoo Authors
+# Copyright 2014-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
import datetime
@@ -23,18 +23,13 @@ class SyncLocalTestCase(TestCase):
def _must_skip(self):
if find_binary("rsync") is None:
- return "rsync: command not found"
+ self.skipTest("rsync: command not found")
if find_binary("git") is None:
- return "git: command not found"
+ self.skipTest("git: command not found")
def testSyncLocal(self):
debug = False
-
- skip_reason = self._must_skip()
- if skip_reason:
- self.portage_skip = skip_reason
- self.assertFalse(True, skip_reason)
- return
+ self._must_skip()
repos_conf = textwrap.dedent(
"""
diff --git a/lib/portage/tests/util/file_copy/test_copyfile.py b/lib/portage/tests/util/file_copy/test_copyfile.py
index 22c3982f0..e91a47bed 100644
--- a/lib/portage/tests/util/file_copy/test_copyfile.py
+++ b/lib/portage/tests/util/file_copy/test_copyfile.py
@@ -56,15 +56,8 @@ class CopyFileSparseTestCase(TestCase):
self.assertEqual(perform_md5(src_path), perform_md5(dest_path))
# This last part of the test is expected to fail when sparse
- # copy is not implemented, so set the todo flag in order
- # to tolerate failures. Or mark it xfail:
-
- AM_I_UNDER_PYTEST = "PYTEST_CURRENT_TEST" in os.environ
-
- if AM_I_UNDER_PYTEST:
- pytest.xfail(reason="sparse copy is not implemented")
- else:
- self.todo = True
+ # copy is not implemented, so mark it xfail:
+ pytest.xfail(reason="sparse copy is not implemented")
# If sparse blocks were preserved, then both files should
# consume the same number of blocks.
diff --git a/lib/portage/tests/util/futures/test_iter_completed.py b/lib/portage/tests/util/futures/test_iter_completed.py
index 8955546ee..bda900505 100644
--- a/lib/portage/tests/util/futures/test_iter_completed.py
+++ b/lib/portage/tests/util/futures/test_iter_completed.py
@@ -1,7 +1,10 @@
-# Copyright 2018 Gentoo Foundation
+# Copyright 2023 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
import time
+
+import pytest
+
from portage.tests import TestCase
from portage.util._async.ForkProcess import ForkProcess
from portage.util._eventloop.global_event_loop import global_event_loop
@@ -28,11 +31,10 @@ class SleepProcess(ForkProcess):
class IterCompletedTestCase(TestCase):
+ # Mark this as todo, since we don't want to fail if heavy system load causes
+ # the tasks to finish in an unexpected order.
+ @pytest.mark.xfail(strict=False)
def testIterCompleted(self):
- # Mark this as todo, since we don't want to fail if heavy system
- # load causes the tasks to finish in an unexpected order.
- self.todo = True
-
loop = global_event_loop()
tasks = [
SleepProcess(seconds=0.200),
diff --git a/meson.build b/meson.build
index db812eeaf..3d2a053b5 100644
--- a/meson.build
+++ b/meson.build
@@ -95,9 +95,9 @@ if get_option('native-extensions')
endif
test(
- 'python',
+ 'pytest',
py,
- args : ['-bWd', meson.current_source_dir() / 'lib' / 'portage' / 'tests' / 'runTests.py'],
+ args : ['-m', 'pytest', '--rootdir', meson.current_source_dir(), meson.current_source_dir()],
timeout : 0
)
diff --git a/runtests b/runtests
deleted file mode 100755
index 1701190b4..000000000
--- a/runtests
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2010-2023 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-#
-# Note: We don't want to import portage modules directly because we do things
-# like run the testsuite through multiple versions of python.
-
-"""Helper script to run portage unittests against different python versions.
-
-Note: Any additional arguments will be passed down directly to the underlying
-unittest runner. This lets you select specific tests to execute.
-"""
-
-import argparse
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-
-
-# These are the versions we fully support and require to pass tests.
-PYTHON_SUPPORTED_VERSIONS = ["3.9", "3.10", "3.11"]
-# The rest are just "nice to have".
-PYTHON_NICE_VERSIONS = ["pypy3", "3.12"]
-
-EPREFIX = os.environ.get("PORTAGE_OVERRIDE_EPREFIX", "/")
-
-
-class Colors:
- """Simple object holding color constants."""
-
- _COLORS_YES = ("y", "yes", "true")
- _COLORS_NO = ("n", "no", "false")
-
- WARN = GOOD = BAD = NORMAL = ""
-
- def __init__(self, colorize=None):
- if colorize is None:
- nocolors = os.environ.get("NOCOLOR", "false")
- # Ugh, look away, for here we invert the world!
- if nocolors in self._COLORS_YES:
- colorize = False
- elif nocolors in self._COLORS_NO:
- colorize = True
- else:
- raise ValueError(f"$NOCOLORS is invalid: {nocolors}")
- else:
- if colorize in self._COLORS_YES:
- colorize = True
- elif colorize in self._COLORS_NO:
- colorize = False
- else:
- raise ValueError(f"--colors is invalid: {colorize}")
-
- if colorize:
- self.WARN = "\033[1;33m"
- self.GOOD = "\033[1;32m"
- self.BAD = "\033[1;31m"
- self.NORMAL = "\033[0m"
-
-
-def get_python_executable(ver):
- """Find the right python executable for |ver|"""
- if ver in ("pypy", "pypy3"):
- prog = ver
- else:
- prog = "python" + ver
- return os.path.join(EPREFIX, "usr", "bin", prog)
-
-
-def get_parser():
- """Return a argument parser for this module"""
- epilog = """Examples:
-List all the available unittests.
-$ %(prog)s --list
-
-Run against specific versions of python.
-$ %(prog)s --python-versions '2.7 3.3'
-
-Run just one unittest.
-$ %(prog)s lib/portage/tests/xpak/test_decodeint.py
-"""
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog=epilog,
- )
- parser.add_argument(
- "--keep-temp",
- default=False,
- action="store_true",
- help="Do not delete the temporary directory when exiting",
- )
- parser.add_argument(
- "--color",
- type=str,
- default=None,
- help="Whether to use colorized output (default is auto)",
- )
- parser.add_argument(
- "--python-versions",
- action="append",
- help="Versions of python to test (default is test available)",
- )
- return parser
-
-
-def main(argv):
- parser = get_parser()
- opts, args = parser.parse_known_args(argv)
- colors = Colors(colorize=opts.color)
-
- # Figure out all the versions we want to test.
- if opts.python_versions is None:
- ignore_missing = True
- pyversions = PYTHON_SUPPORTED_VERSIONS + PYTHON_NICE_VERSIONS
- else:
- ignore_missing = False
- pyversions = []
- for ver in opts.python_versions:
- if ver == "supported":
- pyversions.extend(PYTHON_SUPPORTED_VERSIONS)
- else:
- pyversions.extend(ver.split())
-
- tempdir = None
- try:
- # Set up a single tempdir for all the tests to use.
- # This way we know the tests won't leak things on us.
- tempdir = tempfile.mkdtemp(prefix="portage.runtests.")
- os.environ["TMPDIR"] = tempdir
-
- # Actually test those versions now.
- statuses = []
- for ver in pyversions:
- prog = get_python_executable(ver)
- cmd = [prog, "-b", "-Wd", "lib/portage/tests/runTests.py"] + args
- if os.access(prog, os.X_OK):
- print(f"{colors.GOOD}Testing with Python {ver}...{colors.NORMAL}")
- statuses.append((ver, subprocess.call(cmd)))
- elif not ignore_missing:
- print(
- f"{colors.BAD}Could not find requested Python {ver}{colors.NORMAL}"
- )
- statuses.append((ver, 1))
- else:
- print(f"{colors.WARN}Skip Python {ver}...{colors.NORMAL}")
- print()
- finally:
- if tempdir is not None:
- if opts.keep_temp:
- print(f"Temporary directory left behind:\n{tempdir}")
- else:
- # Nuke our tempdir and anything that might be under it.
- shutil.rmtree(tempdir, True)
-
- # Then summarize it all.
- print("\nSummary:\n")
- width = 10
- header = "| %-*s | %s" % (width, "Version", "Status")
- print(f"{header}\n|{'-' * (len(header) - 1)}")
- exit_status = 0
- for ver, status in statuses:
- exit_status += status
- if status:
- color = colors.BAD
- msg = "FAIL"
- else:
- color = colors.GOOD
- msg = "PASS"
- print(
- "| %s%-*s%s | %s%s%s"
- % (color, width, ver, colors.NORMAL, color, msg, colors.NORMAL)
- )
- exit(exit_status)
-
-
-if __name__ == "__main__":
- try:
- main(sys.argv[1:])
- except KeyboardInterrupt:
- print("interrupted ...", file=sys.stderr)
- exit(1)
diff --git a/tox.ini b/tox.ini
index 6a52a8a0a..6778dd00f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -28,4 +28,4 @@ allowlist_externals =
./run-pylint
commands =
pylint: ./run-pylint
- test: python -bWd lib/portage/tests/runTests.py
+ test: pytest