diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2020-04-25 17:02:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-26 02:02:43 +0200 |
commit | 420c9e82fd3321e3062424846870f3104c1b0eb8 (patch) | |
tree | 92a8c1464f5db815f034a5f2b3c7393c8aa1ddc9 | |
parent | f4cce6862758cc4502553c05cc04bbc5055b2982 (diff) | |
download | psutil-420c9e82fd3321e3062424846870f3104c1b0eb8.tar.gz |
Parallel tests (UNIX) (#1709)
-rwxr-xr-x | .ci/travis/install.sh | 10 | ||||
-rwxr-xr-x | .ci/travis/run.sh | 2 | ||||
-rw-r--r-- | .cirrus.yml | 8 | ||||
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | HISTORY.rst | 4 | ||||
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | docs/DEVGUIDE.rst | 13 | ||||
-rw-r--r-- | psutil/tests/README.rst | 3 | ||||
-rw-r--r-- | psutil/tests/__init__.py | 16 | ||||
-rwxr-xr-x | psutil/tests/runner.py | 298 | ||||
-rwxr-xr-x | psutil/tests/test_aix.py | 4 | ||||
-rwxr-xr-x | psutil/tests/test_bsd.py | 4 | ||||
-rwxr-xr-x | psutil/tests/test_connections.py | 20 | ||||
-rwxr-xr-x | psutil/tests/test_contracts.py | 4 | ||||
-rwxr-xr-x | psutil/tests/test_linux.py | 5 | ||||
-rwxr-xr-x | psutil/tests/test_memory_leaks.py | 4 | ||||
-rwxr-xr-x | psutil/tests/test_misc.py | 4 | ||||
-rwxr-xr-x | psutil/tests/test_osx.py | 4 | ||||
-rwxr-xr-x | psutil/tests/test_posix.py | 4 | ||||
-rwxr-xr-x | psutil/tests/test_process.py | 7 | ||||
-rwxr-xr-x | psutil/tests/test_sunos.py | 4 | ||||
-rwxr-xr-x | psutil/tests/test_system.py | 11 | ||||
-rwxr-xr-x | psutil/tests/test_testutils.py | 2 | ||||
-rwxr-xr-x | psutil/tests/test_unicode.py | 6 | ||||
-rwxr-xr-x | psutil/tests/test_windows.py | 4 |
25 files changed, 315 insertions, 134 deletions
diff --git a/.ci/travis/install.sh b/.ci/travis/install.sh index 1e37c39b..f06e43d5 100755 --- a/.ci/travis/install.sh +++ b/.ci/travis/install.sh @@ -16,10 +16,6 @@ if [[ "$(uname -s)" == 'Darwin' ]]; then fi case "${PYVER}" in - # py26) - # pyenv install 2.6.9 - # pyenv virtualenv 2.6.9 psutil - # ;; py27) pyenv install 2.7.16 pyenv virtualenv 2.7.16 psutil @@ -33,10 +29,8 @@ if [[ "$(uname -s)" == 'Darwin' ]]; then pyenv activate psutil fi -if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]] || [[ $PYVER == 'py26' ]]; then - pip install -U ipaddress unittest2 argparse mock==1.0.1 -elif [[ $TRAVIS_PYTHON_VERSION == '2.7' ]] || [[ $PYVER == 'py27' ]]; then +if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]] || [[ $PYVER == 'py27' ]]; then pip install -U ipaddress mock fi -pip install -U coverage coveralls flake8 setuptools +pip install -U coverage coveralls flake8 setuptools concurrencytest diff --git a/.ci/travis/run.sh b/.ci/travis/run.sh index 879e78a6..562564b0 100755 --- a/.ci/travis/run.sh +++ b/.ci/travis/run.sh @@ -22,7 +22,7 @@ python setup.py develop if [[ $PYVER == '2.7' ]] && [[ "$(uname -s)" != 'Darwin' ]]; then PSUTIL_TESTING=1 python -Wa -m coverage run psutil/tests/runner.py else - PSUTIL_TESTING=1 python -Wa psutil/tests/runner.py + PSUTIL_TESTING=1 python -Wa psutil/tests/runner.py --parallel fi if [ "$PYVER" == "2.7" ] || [ "$PYVER" == "3.6" ]; then diff --git a/.cirrus.yml b/.cirrus.yml index a0b8f1f0..129644c5 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -6,10 +6,10 @@ freebsd_13_py3_task: install_script: - pkg install -y python3 gcc py37-pip script: - - python3 -m pip install --user setuptools + - python3 -m pip install --user setuptools concurrencytest - make clean - make install - - make test + - make test-parallel - make test-memleaks - make print-access-denied - make print-api-speed @@ -22,10 +22,10 @@ freebsd_11_py2_task: install_script: - pkg install -y python gcc py27-pip script: - - python2.7 -m pip install --user setuptools ipaddress mock + - python2.7 -m pip install --user setuptools ipaddress mock concurrencytest - make clean - make install - - make test + - make test-parallel - make test-memleaks - make print-access-denied - make print-api-speed diff --git a/.travis.yml b/.travis.yml index fad35121..d49f2cf1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,6 @@ matrix: env: PYVER=py36 # Linux - python: 2.7 - - python: 3.4 - python: 3.5 - python: 3.6 - python: 3.7 diff --git a/HISTORY.rst b/HISTORY.rst index b906066a..d68e68fc 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -5,6 +5,10 @@ XXXX-XX-XX +**Enhancements** + +- 1729_: parallel tests on UNIX (make test-parallel). + **Bug fixes** - 1726_: [Linux] cpu_freq() parsing should use spaces instead of tabs on ia64. @@ -9,6 +9,7 @@ ARGS = DEPS = \ argparse \ check-manifest \ + concurrencytest \ coverage \ flake8 \ flake8-print \ @@ -112,6 +113,10 @@ test: ## Run all tests. ${MAKE} install $(TEST_PREFIX) $(PYTHON) $(TSCRIPT) +test-parallel: ## Run all tests in parallel. + ${MAKE} install + $(TEST_PREFIX) $(PYTHON) $(TSCRIPT) --parallel + test-process: ## Run process-related API tests. ${MAKE} install $(TEST_PREFIX) $(PYTHON) psutil/tests/test_process.py @@ -154,7 +159,7 @@ test-memleaks: ## Memory leak tests. test-by-name: ## e.g. make test-by-name ARGS=psutil.tests.test_system.TestSystemAPIs ${MAKE} install - @$(TEST_PREFIX) $(PYTHON) -m unittest -v $(ARGS) + @$(TEST_PREFIX) $(PYTHON) $(TSCRIPT) $(ARGS) test-failed: ## Re-run tests which failed on last run ${MAKE} install diff --git a/docs/DEVGUIDE.rst b/docs/DEVGUIDE.rst index 170a40a9..2e8272f0 100644 --- a/docs/DEVGUIDE.rst +++ b/docs/DEVGUIDE.rst @@ -31,12 +31,13 @@ Some useful make commands: .. code-block:: bash - make install # install - make setup-dev-env # install useful dev libs (flake8, unittest2, etc.) - make test # run unit tests - make test-memleaks # run memory leak tests - make test-coverage # run test coverage - make lint # run Python (PEP8) and C linters + make install + make setup-dev-env # install useful dev libs (flake8, unittest2, etc.) + make test # run unit tests + make test-parallel # faster + make test-memleaks + make test-coverage + make lint # Python (PEP8) and C linters There are some differences between ``make`` on UNIX and Windows. For instance, to run a specific Python version. On UNIX: diff --git a/psutil/tests/README.rst b/psutil/tests/README.rst index 9b870d5b..61e066b7 100644 --- a/psutil/tests/README.rst +++ b/psutil/tests/README.rst @@ -10,7 +10,8 @@ Instructions for running tests on psutil:: make setup-dev-env # install missing third-party deps - make test + make test # serial run + make test-parallel # parallel run * To run tests on all supported Python versions install tox (``pip install tox``) then run ``tox`` from within psutil root directory. diff --git a/psutil/tests/__init__.py b/psutil/tests/__init__.py index ec406a27..afd0b98b 100644 --- a/psutil/tests/__init__.py +++ b/psutil/tests/__init__.py @@ -15,6 +15,7 @@ import ctypes import errno import functools import gc +import inspect import os import random import re @@ -799,8 +800,17 @@ class TestCase(unittest.TestCase): # monkey patch default unittest.TestCase -if 'PSUTIL_TESTING' in os.environ: - unittest.TestCase = TestCase +unittest.TestCase = TestCase + + +def serialrun(klass): + """A decorator to mark a TestCase class. When running parallel tests, + class' unit tests will be run serially (1 process). + """ + # assert issubclass(klass, unittest.TestCase), klass + assert inspect.isclass(klass), klass + klass._serialrun = True + return klass @unittest.skipIf(PYPY, "unreliable on PYPY") @@ -1249,5 +1259,5 @@ def cleanup_test_procs(): # modul. With this it will. See: # http://grodola.blogspot.com/ # 2016/02/how-to-always-execute-exit-functions-in-py.html -if POSIX and 'PSUTIL_TESTING' in os.environ: +if POSIX: signal.signal(signal.SIGTERM, lambda sig, frame: sys.exit(sig)) diff --git a/psutil/tests/runner.py b/psutil/tests/runner.py index 7ffbc1cf..bfadc069 100755 --- a/psutil/tests/runner.py +++ b/psutil/tests/runner.py @@ -6,15 +6,19 @@ """ Unit test runner, providing new features on top of unittest module: -- colourized output (error, skip) +- colourized output +- parallel run (UNIX only) - print failures/tracebacks on CTRL+C - re-run failed tests only (make test-failed) """ from __future__ import print_function +import atexit import optparse import os import sys +import textwrap +import time import unittest from unittest import TestResult from unittest import TextTestResult @@ -24,11 +28,18 @@ try: except ImportError: ctypes = None +try: + import concurrencytest # pip install concurrencytest +except ImportError: + concurrencytest = None + import psutil from psutil._common import hilite from psutil._common import print_color from psutil._common import term_supports_colors from psutil.tests import APPVEYOR +from psutil.tests import import_module_by_path +from psutil.tests import reap_children from psutil.tests import safe_rmpath from psutil.tests import TOX @@ -36,6 +47,9 @@ from psutil.tests import TOX HERE = os.path.abspath(os.path.dirname(__file__)) VERBOSITY = 1 if TOX else 2 FAILED_TESTS_FNAME = '.failed-tests.txt' +NWORKERS = psutil.cpu_count() or 1 + +loadTestsFromTestCase = unittest.defaultTestLoader.loadTestsFromTestCase # ===================================================================== @@ -46,8 +60,7 @@ FAILED_TESTS_FNAME = '.failed-tests.txt' class ColouredResult(TextTestResult): def _print_color(self, s, color, bold=False): - file = sys.stderr if color == "red" else sys.stdout - print_color(s, color, bold=bold, file=file) + print_color(s, color, bold=bold, file=self.stream) def addSuccess(self, test): TestResult.addSuccess(self, test) @@ -63,15 +76,15 @@ class ColouredResult(TextTestResult): def addSkip(self, test, reason): TestResult.addSkip(self, test, reason) - self._print_color("skipped: %s" % reason, "brown") + self._print_color("skipped: %s" % reason.strip(), "brown") def printErrorList(self, flavour, errors): flavour = hilite(flavour, "red", bold=flavour == 'ERROR') TextTestResult.printErrorList(self, flavour, errors) -class ColouredRunner(TextTestRunner): - resultclass = ColouredResult if term_supports_colors() else TextTestResult +class ColouredTextRunner(TextTestRunner): + resultclass = ColouredResult def _makeResult(self): # Store result instance so that it can be accessed on @@ -85,81 +98,232 @@ class ColouredRunner(TextTestRunner): # ===================================================================== -def setup_tests(): - if 'PSUTIL_TESTING' not in os.environ: - # This won't work on Windows but set_testing() below will do it. - os.environ['PSUTIL_TESTING'] = '1' - psutil._psplatform.cext.set_testing() +class SuiteLoader: + + testdir = HERE + skip_files = ['test_memory_leaks.py'] + if "WHEELHOUSE_UPLOADER_USERNAME" in os.environ: + skip_files.extend(['test_osx.py', 'test_linux.py', 'test_posix.py']) + + def _get_testmods(self): + return [os.path.join(self.testdir, x) + for x in os.listdir(self.testdir) + if x.startswith('test_') and x.endswith('.py') and + x not in self.skip_files] + + def _iter_testmod_classes(self): + """Iterate over all test files in this directory and return + all TestCase classes in them. + """ + for path in self._get_testmods(): + mod = import_module_by_path(path) + for name in dir(mod): + obj = getattr(mod, name) + if isinstance(obj, type) and \ + issubclass(obj, unittest.TestCase): + yield obj + + def all(self): + suite = unittest.TestSuite() + for obj in self._iter_testmod_classes(): + test = loadTestsFromTestCase(obj) + suite.addTest(test) + return suite + def parallel(self): + serial = unittest.TestSuite() + parallel = unittest.TestSuite() + for obj in self._iter_testmod_classes(): + test = loadTestsFromTestCase(obj) + if getattr(obj, '_serialrun', False): + serial.addTest(test) + else: + parallel.addTest(test) + return (serial, parallel) + + def last_failed(self): + # ...from previously failed test run + suite = unittest.TestSuite() + if not os.path.isfile(FAILED_TESTS_FNAME): + return suite + with open(FAILED_TESTS_FNAME, 'rt') as f: + names = f.read().split() + for n in names: + test = unittest.defaultTestLoader.loadTestsFromName(n) + suite.addTest(test) + return suite -def get_suite(name=None): - suite = unittest.TestSuite() - if name is None: - testmods = [os.path.splitext(x)[0] for x in os.listdir(HERE) - if x.endswith('.py') and x.startswith('test_') and not - x.startswith('test_memory_leaks')] - if "WHEELHOUSE_UPLOADER_USERNAME" in os.environ: - testmods = [x for x in testmods if not x.endswith(( - "osx", "posix", "linux"))] - for tm in testmods: - # ...so that the full test paths are printed on screen - tm = "psutil.tests.%s" % tm - suite.addTest(unittest.defaultTestLoader.loadTestsFromName(tm)) - else: + def from_name(self, name): + suite = unittest.TestSuite() name = os.path.splitext(os.path.basename(name))[0] suite.addTest(unittest.defaultTestLoader.loadTestsFromName(name)) - return suite + return suite -def get_suite_from_failed(): - # ...from previously failed test run - suite = unittest.TestSuite() - if not os.path.isfile(FAILED_TESTS_FNAME): - return suite - with open(FAILED_TESTS_FNAME, 'rt') as f: - names = f.read().split() - for n in names: - suite.addTest(unittest.defaultTestLoader.loadTestsFromName(n)) - return suite - - -def save_failed_tests(result): - if result.wasSuccessful(): - return safe_rmpath(FAILED_TESTS_FNAME) - with open(FAILED_TESTS_FNAME, 'wt') as f: - for t in result.errors + result.failures: - tname = str(t[0]) - unittest.defaultTestLoader.loadTestsFromName(tname) - f.write(tname + '\n') - - -def run(name=None, last_failed=False): - setup_tests() - if APPVEYOR: - runner = TextTestRunner(verbosity=VERBOSITY) - else: - runner = ColouredRunner(verbosity=VERBOSITY) - suite = get_suite_from_failed() if last_failed else get_suite(name) - try: - result = runner.run(suite) - except (KeyboardInterrupt, SystemExit) as err: - print("received %s" % err.__class__.__name__, file=sys.stderr) - runner.result.printErrors() - sys.exit(1) - else: - save_failed_tests(result) - success = result.wasSuccessful() - sys.exit(0 if success else 1) +class Runner: + + def __init__(self): + self.loader = SuiteLoader() + self.failed_tnames = set() + if term_supports_colors() and not APPVEYOR: + self.runner = ColouredTextRunner(verbosity=VERBOSITY) + else: + self.runner = TextTestRunner(verbosity=VERBOSITY) + + def _write_last_failed(self): + if self.failed_tnames: + with open(FAILED_TESTS_FNAME, 'wt') as f: + for tname in self.failed_tnames: + f.write(tname + '\n') + + def _save_result(self, result): + if not result.wasSuccessful(): + for t in result.errors + result.failures: + tname = t[0].id() + self.failed_tnames.add(tname) + + def _run(self, suite): + try: + result = self.runner.run(suite) + except (KeyboardInterrupt, SystemExit): + result = self.runner.result + result.printErrors() + raise sys.exit(1) + else: + self._save_result(result) + return result + + def _finalize(self, success): + if success: + safe_rmpath(FAILED_TESTS_FNAME) + else: + self._write_last_failed() + print_color("FAILED", "red") + sys.exit(1) + + def run(self, suite=None): + """Run tests serially (1 process).""" + if suite is None: + suite = self.loader.all() + result = self._run(suite) + self._finalize(result.wasSuccessful()) + + def run_last_failed(self): + """Run tests which failed in the last run.""" + self.run(self.loader.last_failed()) + + def run_from_name(self, name): + """Run test by name, e.g.: + "test_linux.TestSystemCPUStats.test_ctx_switches" + """ + self.run(self.loader.from_name(name)) + + def _parallelize_suite(self, suite): + def fdopen(*args, **kwds): + stream = orig_fdopen(*args, **kwds) + atexit.register(stream.close) + return stream + + # Monkey patch concurrencytest lib bug (fdopen() stream not closed). + # https://github.com/cgoldberg/concurrencytest/issues/11 + orig_fdopen = os.fdopen + concurrencytest.os.fdopen = fdopen + forker = concurrencytest.fork_for_tests(NWORKERS) + return concurrencytest.ConcurrentTestSuite(suite, forker) + + def run_parallel(self): + """Run tests in parallel.""" + ser_suite, par_suite = self.loader.parallel() + par_suite = self._parallelize_suite(par_suite) + + # run parallel + print("starting parallel tests using %s workers" % NWORKERS) + t = time.time() + par = self._run(par_suite) + par_elapsed = time.time() - t + + # cleanup workers and test subprocesses + orphans = psutil.Process().children() + gone, alive = psutil.wait_procs(orphans, timeout=1) + if alive: + print_color("alive processes %s" % alive, "red") + reap_children() + + # run serial + t = time.time() + ser = self._run(ser_suite) + ser_elapsed = time.time() - t + + # print + par_fails, par_errs, par_skips = map(len, (par.failures, + par.errors, + par.skipped)) + ser_fails, ser_errs, ser_skips = map(len, (ser.failures, + ser.errors, + ser.skipped)) + print("-" * 70) + print(textwrap.dedent(""" + +----------+----------+----------+----------+----------+----------+ + | | total | failures | errors | skipped | time | + +----------+----------+----------+----------+----------+----------+ + | parallel | %3s | %3s | %3s | %3s | %.2fs | + +----------+----------+----------+----------+----------+----------+ + | serial | %3s | %3s | %3s | %3s | %.2fs | + +----------+----------+----------+----------+----------+----------+ + """ % (par.testsRun, par_fails, par_errs, par_skips, par_elapsed, + ser.testsRun, ser_fails, ser_errs, ser_skips, ser_elapsed))) + print("Ran %s tests in %.3fs using %s workers" % ( + par.testsRun + ser.testsRun, par_elapsed + ser_elapsed, NWORKERS)) + ok = par.wasSuccessful() and ser.wasSuccessful() + self._finalize(ok) + + +runner = Runner() +run_from_name = runner.run_from_name + + +def _setup(): + if 'PSUTIL_TESTING' not in os.environ: + # This won't work on Windows but set_testing() below will do it. + os.environ['PSUTIL_TESTING'] = '1' + psutil._psplatform.cext.set_testing() def main(): - usage = "python3 -m psutil.tests [opts]" + _setup() + usage = "python3 -m psutil.tests [opts] [test-name]" parser = optparse.OptionParser(usage=usage, description="run unit tests") parser.add_option("--last-failed", action="store_true", default=False, help="only run last failed tests") + parser.add_option("--parallel", + action="store_true", default=False, + help="run tests in parallel") opts, args = parser.parse_args() - run(last_failed=opts.last_failed) + + if not opts.last_failed: + safe_rmpath(FAILED_TESTS_FNAME) + + # test-by-name + if args: + if len(args) > 1: + parser.print_usage() + return sys.exit(1) + return runner.run_from_name(args[0]) + elif opts.last_failed: + runner.run_last_failed() + elif not opts.parallel: + runner.run() + # parallel + elif concurrencytest is None: + print_color("concurrencytest module is not installed; " + "running serial tests instead", "red") + runner.run() + elif NWORKERS == 1: + print_color("only 1 CPU; running serial tests instead", "red") + runner.run() + else: + runner.run_parallel() if __name__ == '__main__': diff --git a/psutil/tests/test_aix.py b/psutil/tests/test_aix.py index 7171232e..1a769424 100755 --- a/psutil/tests/test_aix.py +++ b/psutil/tests/test_aix.py @@ -117,5 +117,5 @@ class AIXSpecificTestCase(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_bsd.py b/psutil/tests/test_bsd.py index 899875d0..3a948c89 100755 --- a/psutil/tests/test_bsd.py +++ b/psutil/tests/test_bsd.py @@ -561,5 +561,5 @@ class NetBSDTestCase(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_connections.py b/psutil/tests/test_connections.py index 5bd71dc8..f4ddc14e 100755 --- a/psutil/tests/test_connections.py +++ b/psutil/tests/test_connections.py @@ -41,6 +41,7 @@ from psutil.tests import get_testfn from psutil.tests import HAS_CONNECTIONS_UNIX from psutil.tests import pyrun from psutil.tests import reap_children +from psutil.tests import serialrun from psutil.tests import skip_on_access_denied from psutil.tests import SKIP_SYSCONS from psutil.tests import tcp_socketpair @@ -54,7 +55,8 @@ thisproc = psutil.Process() SOCK_SEQPACKET = getattr(socket, "SOCK_SEQPACKET", object()) -class Base(object): +@serialrun +class _ConnTestCase(unittest.TestCase): def setUp(self): if not (NETBSD or FREEBSD): @@ -165,7 +167,7 @@ class Base(object): check_status(conn) -class TestBase(Base, unittest.TestCase): +class TestBasicOperations(_ConnTestCase): @unittest.skipIf(SKIP_SYSCONS, "requires root") def test_system(self): @@ -183,7 +185,8 @@ class TestBase(Base, unittest.TestCase): self.assertRaises(ValueError, psutil.net_connections, kind='???') -class TestUnconnectedSockets(Base, unittest.TestCase): +@serialrun +class TestUnconnectedSockets(_ConnTestCase): """Tests sockets which are open but not connected to anything.""" def get_conn_from_sock(self, sock): @@ -279,7 +282,8 @@ class TestUnconnectedSockets(Base, unittest.TestCase): self.assertEqual(conn.status, psutil.CONN_NONE) -class TestConnectedSocket(Base, unittest.TestCase): +@serialrun +class TestConnectedSocket(_ConnTestCase): """Test socket pairs which are are actually connected to each other. """ @@ -343,7 +347,7 @@ class TestConnectedSocket(Base, unittest.TestCase): client.close() -class TestFilters(Base, unittest.TestCase): +class TestFilters(_ConnTestCase): def test_filters(self): def check(kind, families, types): @@ -543,7 +547,7 @@ class TestFilters(Base, unittest.TestCase): @unittest.skipIf(SKIP_SYSCONS, "requires root") -class TestSystemWideConnections(Base, unittest.TestCase): +class TestSystemWideConnections(_ConnTestCase): """Tests for net_connections().""" def test_it(self): @@ -630,5 +634,5 @@ class TestMisc(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py index 74c429be..69bb0b2f 100755 --- a/psutil/tests/test_contracts.py +++ b/psutil/tests/test_contracts.py @@ -682,5 +682,5 @@ class TestFetchAllProcesses(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py index d529ae7c..4cb3d3af 100755 --- a/psutil/tests/test_linux.py +++ b/psutil/tests/test_linux.py @@ -1643,6 +1643,7 @@ class TestSensorsFans(unittest.TestCase): @unittest.skipIf(not LINUX, "LINUX only") class TestProcess(unittest.TestCase): + @retry_on_failure() def test_memory_full_info(self): testfn = get_testfn() src = textwrap.dedent(""" @@ -2111,5 +2112,5 @@ class TestUtils(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_memory_leaks.py b/psutil/tests/test_memory_leaks.py index 5cfec577..9069b1a3 100755 --- a/psutil/tests/test_memory_leaks.py +++ b/psutil/tests/test_memory_leaks.py @@ -489,5 +489,5 @@ class TestModuleFunctionsLeaks(TestMemoryLeak): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_misc.py b/psutil/tests/test_misc.py index 74a0c427..8ae7ea4d 100755 --- a/psutil/tests/test_misc.py +++ b/psutil/tests/test_misc.py @@ -759,5 +759,5 @@ class TestScripts(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_osx.py b/psutil/tests/test_osx.py index e4e77f93..4df05fa8 100755 --- a/psutil/tests/test_osx.py +++ b/psutil/tests/test_osx.py @@ -290,5 +290,5 @@ class TestSystemAPIs(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_posix.py b/psutil/tests/test_posix.py index d2c4bfb6..14ec880b 100755 --- a/psutil/tests/test_posix.py +++ b/psutil/tests/test_posix.py @@ -449,5 +449,5 @@ class TestSystemAPIs(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_process.py b/psutil/tests/test_process.py index ddb1bbba..8095fc04 100755 --- a/psutil/tests/test_process.py +++ b/psutil/tests/test_process.py @@ -70,6 +70,7 @@ from psutil.tests import wait_for_pid # --- psutil.Process class tests # =================================================================== + class TestProcess(unittest.TestCase): """Tests for psutil.Process class.""" @@ -295,7 +296,7 @@ class TestProcess(unittest.TestCase): @unittest.skipIf(TRAVIS or CIRRUS, 'not reliable on TRAVIS/CIRRUS') def test_terminal(self): terminal = psutil.Process().terminal() - if sys.stdin.isatty() or sys.stdout.isatty(): + if sys.stdout.isatty(): tty = os.path.realpath(sh('tty')) self.assertEqual(terminal, tty) else: @@ -1624,5 +1625,5 @@ class TestPopen(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_sunos.py b/psutil/tests/test_sunos.py index e3beb625..bac1a212 100755 --- a/psutil/tests/test_sunos.py +++ b/psutil/tests/test_sunos.py @@ -41,5 +41,5 @@ class SunOSSpecificTestCase(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py index 73401b3c..f5d9f49e 100755 --- a/psutil/tests/test_system.py +++ b/psutil/tests/test_system.py @@ -194,13 +194,6 @@ class TestProcessAPIs(unittest.TestCase): for pid in pids: self.assertFalse(psutil.pid_exists(pid), msg=pid) - def test_pids(self): - pidslist = psutil.pids() - procslist = [x.pid for x in psutil.process_iter()] - # make sure every pid is unique - self.assertEqual(sorted(set(pidslist)), pidslist) - self.assertEqual(pidslist, procslist) - class TestMiscAPIs(unittest.TestCase): @@ -895,5 +888,5 @@ class TestSensorsAPIs(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_testutils.py b/psutil/tests/test_testutils.py index 55c5d3df..45b2557f 100755 --- a/psutil/tests/test_testutils.py +++ b/psutil/tests/test_testutils.py @@ -43,6 +43,7 @@ from psutil.tests import retry from psutil.tests import retry_on_failure from psutil.tests import safe_mkdir from psutil.tests import safe_rmpath +from psutil.tests import serialrun from psutil.tests import tcp_socketpair from psutil.tests import TestMemoryLeak from psutil.tests import unittest @@ -316,6 +317,7 @@ class TestNetUtils(unittest.TestCase): self.assertGreaterEqual(types[socket.SOCK_DGRAM], 2) +@serialrun class TestMemLeakClass(TestMemoryLeak): def test_times(self): diff --git a/psutil/tests/test_unicode.py b/psutil/tests/test_unicode.py index 6fbaa43f..da6ec96e 100755 --- a/psutil/tests/test_unicode.py +++ b/psutil/tests/test_unicode.py @@ -102,6 +102,7 @@ from psutil.tests import PYPY from psutil.tests import reap_children from psutil.tests import safe_mkdir from psutil.tests import safe_rmpath as _safe_rmpath +from psutil.tests import serialrun from psutil.tests import skip_on_access_denied from psutil.tests import TESTFN_PREFIX from psutil.tests import TRAVIS @@ -154,6 +155,7 @@ def subprocess_supports_unicode(suffix): # =================================================================== +@serialrun class _BaseFSAPIsTests(object): funky_suffix = None @@ -358,5 +360,5 @@ class TestNonFSAPIS(unittest.TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) diff --git a/psutil/tests/test_windows.py b/psutil/tests/test_windows.py index f68885d0..27343ca2 100755 --- a/psutil/tests/test_windows.py +++ b/psutil/tests/test_windows.py @@ -866,5 +866,5 @@ class TestServices(TestCase): if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) + from psutil.tests.runner import run_from_name + run_from_name(__file__) |