* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/tests/simple/, repoman/pym/repoman/tests/, repoman/
@ 2016-05-14 18:12 Brian Dolbec
0 siblings, 0 replies; 2+ messages in thread
From: Brian Dolbec @ 2016-05-14 18:12 UTC (permalink / raw
To: gentoo-commits
commit: 0aac71f5ed2eff3ad0a3cf9114c8e54b61269d4b
Author: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat May 14 18:11:17 2016 +0000
Commit: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Sat May 14 18:11:17 2016 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=0aac71f5
repoman: Copy portage runtests file, edit & make them operational
Make copies of files as needed.
Edit the files for the appropriate namespaces.
Add in the parent portage python directory for it to import from.
repoman/pym/repoman/tests/__init__.py | 353 +++++++++++++++++++++++-
repoman/pym/repoman/tests/runTests.py | 9 +-
repoman/pym/repoman/tests/simple/__test__.py | 1 +
repoman/pym/repoman/tests/simple/test_simple.py | 7 +-
repoman/runtests | 180 ++++++++++++
5 files changed, 545 insertions(+), 5 deletions(-)
diff --git a/repoman/pym/repoman/tests/__init__.py b/repoman/pym/repoman/tests/__init__.py
index 532918b..7243e7a 100644
--- a/repoman/pym/repoman/tests/__init__.py
+++ b/repoman/pym/repoman/tests/__init__.py
@@ -1,2 +1,353 @@
-# Copyright 2011 Gentoo Foundation
+# 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 = os.path.join(PORTAGE_BASE_PATH, 'repoman/bin')
+ 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(("repoman", "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:
+ try:
+ self.setUp()
+ except SystemExit:
+ raise
+ except KeyboardInterrupt:
+ raise
+ except:
+ result.addError(self, sys.exc_info())
+ return
+
+ ok = False
+ try:
+ 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?')]
diff --git a/repoman/pym/repoman/tests/runTests.py b/repoman/pym/repoman/tests/runTests.py
index 9c45276..882911c 100644
--- a/repoman/pym/repoman/tests/runTests.py
+++ b/repoman/pym/repoman/tests/runTests.py
@@ -29,7 +29,12 @@ 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__)))))
+repoman_pym = osp.dirname(osp.dirname(osp.dirname(osp.realpath(__file__))))
+sys.path.insert(0, repoman_pym)
+
+# Add in the parent portage python modules
+portage_pym = osp.dirname(osp.dirname(repoman_pym))+'/pym'
+sys.path.insert(0, portage_pym)
import portage
portage._internal_caller = True
@@ -41,7 +46,7 @@ portage._disable_legacy_globals()
if os.environ.get('NOCOLOR') in ('yes', 'true'):
portage.output.nocolor()
-import portage.tests as tests
+import repoman.tests as tests
from portage.const import PORTAGE_BIN_PATH
path = os.environ.get("PATH", "").split(":")
path = [x for x in path if x]
diff --git a/repoman/pym/repoman/tests/simple/__test__.py b/repoman/pym/repoman/tests/simple/__test__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/repoman/pym/repoman/tests/simple/__test__.py
@@ -0,0 +1 @@
+
diff --git a/repoman/pym/repoman/tests/simple/test_simple.py b/repoman/pym/repoman/tests/simple/test_simple.py
index 6a79761..ae5194f 100644
--- a/repoman/pym/repoman/tests/simple/test_simple.py
+++ b/repoman/pym/repoman/tests/simple/test_simple.py
@@ -10,10 +10,13 @@ from portage import os
from portage import _unicode_decode
from portage.const import PORTAGE_BASE_PATH, 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
from repoman.copyrights import update_copyright_year
+from repoman.tests import TestCase
+
+REPOMAN_BASE_PATH = os.path.join(PORTAGE_BASE_PATH, 'repoman')
+
class SimpleRepomanTestCase(TestCase):
@@ -128,7 +131,7 @@ class SimpleRepomanTestCase(TestCase):
}
licenses = ["GPL-2"]
arch_list = ["x86"]
- metadata_xsd = os.path.join(PORTAGE_BASE_PATH, "cnf/metadata.xsd")
+ metadata_xsd = os.path.join(REPOMAN_BASE_PATH, "cnf/metadata.xsd")
metadata_xml_files = (
(
"dev-libs/A",
diff --git a/repoman/runtests b/repoman/runtests
new file mode 100755
index 0000000..bad83dc
--- /dev/null
+++ b/repoman/runtests
@@ -0,0 +1,180 @@
+#!/usr/bin/python
+# Copyright 2010-2015 Gentoo Foundation
+# 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.
+"""
+
+from __future__ import print_function
+
+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 = [
+ '2.7',
+ '3.3',
+ '3.4',
+]
+# The rest are just "nice to have".
+PYTHON_NICE_VERSIONS = [
+ 'pypy',
+ '3.5',
+]
+
+EPREFIX = os.environ.get('PORTAGE_OVERRIDE_EPREFIX', '/')
+
+
+class Colors(object):
+ """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('$NOCOLORS is invalid: %s' % nocolors)
+ else:
+ if colorize in self._COLORS_YES:
+ colorize = True
+ elif colorize in self._COLORS_NO:
+ colorize = False
+ else:
+ raise ValueError('--colors is invalid: %s' % 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 pym/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='repoman.runtests.')
+ os.environ['TMPDIR'] = tempdir
+
+ # Actually test those versions now.
+ statuses = []
+ for ver in pyversions:
+ prog = get_python_executable(ver)
+ cmd = [prog, '-b', '-Wd', 'pym/repoman/tests/runTests.py'] + args
+ if os.access(prog, os.X_OK):
+ print('%sTesting with Python %s...%s' %
+ (colors.GOOD, ver, colors.NORMAL))
+ statuses.append((ver, subprocess.call(cmd)))
+ elif not ignore_missing:
+ print('%sCould not find requested Python %s%s' %
+ (colors.BAD, ver, colors.NORMAL))
+ statuses.append((ver, 1))
+ else:
+ print('%sSkip Python %s...%s' %
+ (colors.WARN, ver, colors.NORMAL))
+ print()
+ finally:
+ if tempdir is not None:
+ if opts.keep_temp:
+ print('Temporary directory left behind:\n%s' % 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('%s\n|%s' % (header, '-' * (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)
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/tests/simple/, repoman/pym/repoman/tests/, repoman/
@ 2016-05-14 18:33 Brian Dolbec
0 siblings, 0 replies; 2+ messages in thread
From: Brian Dolbec @ 2016-05-14 18:33 UTC (permalink / raw
To: gentoo-commits
commit: 50f3664b855b4ea70860fbea1827a68cd0da127a
Author: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat May 14 18:11:17 2016 +0000
Commit: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Sat May 14 18:29:40 2016 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=50f3664b
repoman: Copy portage runtests file, edit & make them operational
Make copies of files as needed.
Edit the files for the appropriate namespaces.
Add in the parent portage python directory for it to import from.
repoman/pym/repoman/tests/__init__.py | 353 +++++++++++++++++++++++-
repoman/pym/repoman/tests/runTests.py | 9 +-
repoman/pym/repoman/tests/simple/__test__.py | 1 +
repoman/pym/repoman/tests/simple/test_simple.py | 7 +-
repoman/runtests | 180 ++++++++++++
5 files changed, 545 insertions(+), 5 deletions(-)
diff --git a/repoman/pym/repoman/tests/__init__.py b/repoman/pym/repoman/tests/__init__.py
index 532918b..7243e7a 100644
--- a/repoman/pym/repoman/tests/__init__.py
+++ b/repoman/pym/repoman/tests/__init__.py
@@ -1,2 +1,353 @@
-# Copyright 2011 Gentoo Foundation
+# 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 = os.path.join(PORTAGE_BASE_PATH, 'repoman/bin')
+ 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(("repoman", "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:
+ try:
+ self.setUp()
+ except SystemExit:
+ raise
+ except KeyboardInterrupt:
+ raise
+ except:
+ result.addError(self, sys.exc_info())
+ return
+
+ ok = False
+ try:
+ 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?')]
diff --git a/repoman/pym/repoman/tests/runTests.py b/repoman/pym/repoman/tests/runTests.py
index 9c45276..882911c 100644
--- a/repoman/pym/repoman/tests/runTests.py
+++ b/repoman/pym/repoman/tests/runTests.py
@@ -29,7 +29,12 @@ 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__)))))
+repoman_pym = osp.dirname(osp.dirname(osp.dirname(osp.realpath(__file__))))
+sys.path.insert(0, repoman_pym)
+
+# Add in the parent portage python modules
+portage_pym = osp.dirname(osp.dirname(repoman_pym))+'/pym'
+sys.path.insert(0, portage_pym)
import portage
portage._internal_caller = True
@@ -41,7 +46,7 @@ portage._disable_legacy_globals()
if os.environ.get('NOCOLOR') in ('yes', 'true'):
portage.output.nocolor()
-import portage.tests as tests
+import repoman.tests as tests
from portage.const import PORTAGE_BIN_PATH
path = os.environ.get("PATH", "").split(":")
path = [x for x in path if x]
diff --git a/repoman/pym/repoman/tests/simple/__test__.py b/repoman/pym/repoman/tests/simple/__test__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/repoman/pym/repoman/tests/simple/__test__.py
@@ -0,0 +1 @@
+
diff --git a/repoman/pym/repoman/tests/simple/test_simple.py b/repoman/pym/repoman/tests/simple/test_simple.py
index 6a79761..ae5194f 100644
--- a/repoman/pym/repoman/tests/simple/test_simple.py
+++ b/repoman/pym/repoman/tests/simple/test_simple.py
@@ -10,10 +10,13 @@ from portage import os
from portage import _unicode_decode
from portage.const import PORTAGE_BASE_PATH, 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
from repoman.copyrights import update_copyright_year
+from repoman.tests import TestCase
+
+REPOMAN_BASE_PATH = os.path.join(PORTAGE_BASE_PATH, 'repoman')
+
class SimpleRepomanTestCase(TestCase):
@@ -128,7 +131,7 @@ class SimpleRepomanTestCase(TestCase):
}
licenses = ["GPL-2"]
arch_list = ["x86"]
- metadata_xsd = os.path.join(PORTAGE_BASE_PATH, "cnf/metadata.xsd")
+ metadata_xsd = os.path.join(REPOMAN_BASE_PATH, "cnf/metadata.xsd")
metadata_xml_files = (
(
"dev-libs/A",
diff --git a/repoman/runtests b/repoman/runtests
new file mode 100755
index 0000000..bad83dc
--- /dev/null
+++ b/repoman/runtests
@@ -0,0 +1,180 @@
+#!/usr/bin/python
+# Copyright 2010-2015 Gentoo Foundation
+# 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.
+"""
+
+from __future__ import print_function
+
+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 = [
+ '2.7',
+ '3.3',
+ '3.4',
+]
+# The rest are just "nice to have".
+PYTHON_NICE_VERSIONS = [
+ 'pypy',
+ '3.5',
+]
+
+EPREFIX = os.environ.get('PORTAGE_OVERRIDE_EPREFIX', '/')
+
+
+class Colors(object):
+ """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('$NOCOLORS is invalid: %s' % nocolors)
+ else:
+ if colorize in self._COLORS_YES:
+ colorize = True
+ elif colorize in self._COLORS_NO:
+ colorize = False
+ else:
+ raise ValueError('--colors is invalid: %s' % 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 pym/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='repoman.runtests.')
+ os.environ['TMPDIR'] = tempdir
+
+ # Actually test those versions now.
+ statuses = []
+ for ver in pyversions:
+ prog = get_python_executable(ver)
+ cmd = [prog, '-b', '-Wd', 'pym/repoman/tests/runTests.py'] + args
+ if os.access(prog, os.X_OK):
+ print('%sTesting with Python %s...%s' %
+ (colors.GOOD, ver, colors.NORMAL))
+ statuses.append((ver, subprocess.call(cmd)))
+ elif not ignore_missing:
+ print('%sCould not find requested Python %s%s' %
+ (colors.BAD, ver, colors.NORMAL))
+ statuses.append((ver, 1))
+ else:
+ print('%sSkip Python %s...%s' %
+ (colors.WARN, ver, colors.NORMAL))
+ print()
+ finally:
+ if tempdir is not None:
+ if opts.keep_temp:
+ print('Temporary directory left behind:\n%s' % 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('%s\n|%s' % (header, '-' * (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)
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-05-14 18:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-14 18:12 [gentoo-commits] proj/portage:repoman commit in: repoman/pym/repoman/tests/simple/, repoman/pym/repoman/tests/, repoman/ Brian Dolbec
-- strict thread matches above, loose matches on Subject: below --
2016-05-14 18:33 Brian Dolbec
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox