summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-04-26 02:05:25 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2020-04-26 02:05:25 +0200
commit7cd0dd250fcb57874d81c954196bfba4bd3d406d (patch)
treecf10dff1b73f8af69de43646b9d468a13a60a432
parent6e2aa0d80f5c8301c27551f65181ffc7e2cb5d8c (diff)
parent420c9e82fd3321e3062424846870f3104c1b0eb8 (diff)
downloadpsutil-reap-children.tar.gz
Merge branch 'master' into devreap-children
-rwxr-xr-x.ci/travis/install.sh10
-rwxr-xr-x.ci/travis/run.sh2
-rw-r--r--.cirrus.yml8
-rw-r--r--.travis.yml1
-rw-r--r--HISTORY.rst4
-rw-r--r--Makefile7
-rw-r--r--docs/DEVGUIDE.rst13
-rw-r--r--psutil/tests/README.rst3
-rw-r--r--psutil/tests/__init__.py16
-rwxr-xr-xpsutil/tests/runner.py298
-rwxr-xr-xpsutil/tests/test_aix.py4
-rwxr-xr-xpsutil/tests/test_bsd.py4
-rwxr-xr-xpsutil/tests/test_connections.py20
-rwxr-xr-xpsutil/tests/test_contracts.py4
-rwxr-xr-xpsutil/tests/test_linux.py5
-rwxr-xr-xpsutil/tests/test_memory_leaks.py4
-rwxr-xr-xpsutil/tests/test_misc.py4
-rwxr-xr-xpsutil/tests/test_osx.py4
-rwxr-xr-xpsutil/tests/test_posix.py4
-rwxr-xr-xpsutil/tests/test_process.py7
-rwxr-xr-xpsutil/tests/test_sunos.py4
-rwxr-xr-xpsutil/tests/test_system.py11
-rwxr-xr-xpsutil/tests/test_testutils.py2
-rwxr-xr-xpsutil/tests/test_unicode.py6
-rwxr-xr-xpsutil/tests/test_windows.py4
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.
diff --git a/Makefile b/Makefile
index fbd7ffcc..76420bc7 100644
--- a/Makefile
+++ b/Makefile
@@ -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 cc409161..5d64cce9 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 9a80106c..889526ad 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 4b348775..d25eb877 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 30fadd2b..ea957c17 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 c4008b9d..f7862843 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__)