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/__init__.py
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/__init__.py')
-rw-r--r--lib/portage/tests/__init__.py353
1 files changed, 353 insertions, 0 deletions
diff --git a/lib/portage/tests/__init__.py b/lib/portage/tests/__init__.py
new file mode 100644
index 000000000..e149b5c0c
--- /dev/null
+++ b/lib/portage/tests/__init__.py
@@ -0,0 +1,353 @@
+# tests/__init__.py -- Portage Unit Test functionality
+# Copyright 2006-2013 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from __future__ import print_function
+
+import argparse
+import sys
+import time
+import unittest
+
+try:
+ from unittest.runner import _TextTestResult # new in python-2.7
+except ImportError:
+ from unittest import _TextTestResult
+
+try:
+ # They added the skip framework to python-2.7.
+ # Drop this once we drop python-2.6 support.
+ unittest_skip_shims = False
+ import unittest.SkipTest as SkipTest # new in python-2.7
+except ImportError:
+ unittest_skip_shims = True
+
+import portage
+from portage import os
+from portage import _encodings
+from portage import _unicode_decode
+from portage.const import (EPREFIX, GLOBAL_CONFIG_PATH, PORTAGE_BASE_PATH,
+ PORTAGE_BIN_PATH)
+
+
+if portage._not_installed:
+ cnf_path = os.path.join(PORTAGE_BASE_PATH, 'cnf')
+ cnf_etc_path = cnf_path
+ cnf_bindir = PORTAGE_BIN_PATH
+ cnf_sbindir = cnf_bindir
+else:
+ cnf_path = os.path.join(EPREFIX or '/', GLOBAL_CONFIG_PATH)
+ cnf_etc_path = os.path.join(EPREFIX or '/', 'etc')
+ cnf_eprefix = EPREFIX
+ cnf_bindir = os.path.join(EPREFIX or '/', 'usr', 'bin')
+ cnf_sbindir = os.path.join(EPREFIX or '/', 'usr', 'sbin')
+
+
+def main():
+ suite = unittest.TestSuite()
+ basedir = os.path.dirname(os.path.realpath(__file__))
+
+ usage = "usage: %s [options] [tests to run]" % os.path.basename(sys.argv[0])
+ parser = argparse.ArgumentParser(usage=usage)
+ parser.add_argument("-l", "--list", help="list all tests",
+ action="store_true", dest="list_tests")
+ options, args = parser.parse_known_args(args=sys.argv)
+
+ if (os.environ.get('NOCOLOR') in ('yes', 'true') or
+ os.environ.get('TERM') == 'dumb' or
+ not sys.stdout.isatty()):
+ portage.output.nocolor()
+
+ if options.list_tests:
+ testdir = os.path.dirname(sys.argv[0])
+ for mydir in getTestDirs(basedir):
+ testsubdir = os.path.basename(mydir)
+ for name in getTestNames(mydir):
+ print("%s/%s/%s.py" % (testdir, testsubdir, name))
+ return os.EX_OK
+
+ if len(args) > 1:
+ suite.addTests(getTestFromCommandLine(args[1:], basedir))
+ else:
+ for mydir in getTestDirs(basedir):
+ suite.addTests(getTests(os.path.join(basedir, 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 = os.path.realpath(arg)
+ path = os.path.dirname(realpath)
+ f = realpath[len(path)+1:]
+
+ if not f.startswith("test") or not f.endswith(".py"):
+ raise Exception("Invalid argument: '%s'" % arg)
+
+ mymodule = f[:-3]
+ result.extend(getTestsFromFiles(path, base_path, [mymodule]))
+ return result
+
+def getTestDirs(base_path):
+ TEST_FILE = b'__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 root, dirs, files in os.walk(base_path):
+ try:
+ root = _unicode_decode(root,
+ encoding=_encodings['fs'], errors='strict')
+ except UnicodeDecodeError:
+ continue
+
+ if TEST_FILE in files:
+ testDirs.append(root)
+
+ testDirs.sort()
+ return testDirs
+
+def getTestNames(path):
+ files = os.listdir(path)
+ files = [f[:-3] for f in files if f.startswith("test") and f.endswith(".py")]
+ files.sort()
+ return files
+
+def getTestsFromFiles(path, base_path, files):
+ parent_path = path[len(base_path)+1:]
+ parent_module = ".".join(("portage", "tests", parent_path))
+ parent_module = parent_module.replace('/', '.')
+ 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._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(TextTestResult, self).__init__(stream, descriptions, verbosity)
+ self.todoed = []
+ self.portage_skipped = []
+
+ def addTodo(self, test, info):
+ self.todoed.append((test, info))
+ if self.showAll:
+ self.stream.writeln("TODO")
+ elif self.dots:
+ self.stream.write(".")
+
+ def addPortageSkip(self, test, info):
+ self.portage_skipped.append((test, info))
+ if self.showAll:
+ self.stream.writeln("SKIP")
+ elif self.dots:
+ self.stream.write(".")
+
+ 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"
+ This way someone can add a broken test and mark it as failed
+ and then fix the code later. This may not be a great approach
+ (broken code!!??!11oneone) but it does happen at times.
+ """
+
+ 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 SkipTest:
+ raise
+ except Exception:
+ result.addError(self, sys.exc_info())
+ return
+
+ testMethod()
+ ok = True
+ except SkipTest as e:
+ result.addPortageSkip(self, "%s: SKIP: %s" %
+ (testMethod, str(e)))
+ except self.failureException:
+ if self.portage_skip is not None:
+ if self.portage_skip is True:
+ result.addPortageSkip(self, "%s: SKIP" % testMethod)
+ else:
+ result.addPortageSkip(self, "%s: SKIP: %s" %
+ (testMethod, self.portage_skip))
+ elif self.todo:
+ result.addTodo(self, "%s: TODO" % testMethod)
+ 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
+ arguments kwargs. If a different type of exception is
+ thrown, it will not be caught, and the test case will be
+ deemed to have suffered an error, exactly as for an
+ unexpected exception.
+ """
+ try:
+ callableObj(*args, **kwargs)
+ except excClass:
+ return
+ else:
+ if hasattr(excClass, '__name__'): excName = excClass.__name__
+ else: excName = str(excClass)
+ raise self.failureException("%s not raised: %s" % (excName, msg))
+
+ def assertExists(self, path):
+ """Make sure |path| exists"""
+ if not os.path.exists(path):
+ msg = ['path is missing: %s' % (path,)]
+ while path != '/':
+ path = os.path.dirname(path)
+ if not path:
+ # If we're given something like "foo", abort once we get to "".
+ break
+ result = os.path.exists(path)
+ msg.append('\tos.path.exists(%s): %s' % (path, result))
+ if result:
+ msg.append('\tcontents: %r' % os.listdir(path))
+ break
+ raise self.failureException('\n'.join(msg))
+
+ def assertNotExists(self, path):
+ """Make sure |path| does not exist"""
+ if os.path.exists(path):
+ raise self.failureException('path exists when it should not: %s' % path)
+
+if unittest_skip_shims:
+ # Shim code for <python-2.7.
+ class SkipTest(Exception):
+ """unittest.SkipTest shim for <python-2.7"""
+
+ def skipTest(self, reason):
+ raise SkipTest(reason)
+ setattr(TestCase, 'skipTest', skipTest)
+
+ def assertIn(self, member, container, msg=None):
+ self.assertTrue(member in container, msg=msg)
+ setattr(TestCase, 'assertIn', assertIn)
+
+ def assertNotIn(self, member, container, msg=None):
+ self.assertFalse(member in container, msg=msg)
+ setattr(TestCase, 'assertNotIn', assertNotIn)
+
+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("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("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']
+test_usedeps = ['foo', '-bar', ('foo', 'bar'),
+ ('foo', '-bar'), ('foo?', '!bar?')]