2012-09-19 22:20:16 +04:00
|
|
|
#!/usr/bin/env python
|
2014-12-23 21:45:15 +03:00
|
|
|
# -*- coding: utf-8 -*-
|
2013-05-10 02:39:30 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
|
2012-09-19 22:20:16 +04:00
|
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
|
|
# found in the LICENSE file.
|
|
|
|
|
|
|
|
"""
|
2014-12-23 21:45:15 +03:00
|
|
|
psutil test suite. Run it with:
|
|
|
|
$ make test
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
If you're on Python < 2.7 unittest2 module must be installed first:
|
|
|
|
https://pypi.python.org/pypi/unittest2
|
2012-09-19 22:20:16 +04:00
|
|
|
"""
|
|
|
|
|
|
|
|
from __future__ import division
|
2014-12-23 21:45:15 +03:00
|
|
|
|
|
|
|
import atexit
|
|
|
|
import datetime
|
|
|
|
import errno
|
2012-09-19 22:20:16 +04:00
|
|
|
import os
|
2014-12-23 21:45:15 +03:00
|
|
|
import pickle
|
|
|
|
import re
|
|
|
|
import select
|
|
|
|
import shutil
|
|
|
|
import signal
|
|
|
|
import socket
|
|
|
|
import stat
|
2012-09-19 22:20:16 +04:00
|
|
|
import subprocess
|
2014-12-23 21:45:15 +03:00
|
|
|
import sys
|
|
|
|
import tempfile
|
|
|
|
import textwrap
|
|
|
|
import threading
|
2012-09-19 22:20:16 +04:00
|
|
|
import time
|
|
|
|
import traceback
|
2014-12-23 21:45:15 +03:00
|
|
|
import types
|
2012-09-19 22:20:16 +04:00
|
|
|
import warnings
|
2014-12-23 21:45:15 +03:00
|
|
|
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
|
2013-08-23 10:36:57 +04:00
|
|
|
try:
|
|
|
|
import ast # python >= 2.6
|
|
|
|
except ImportError:
|
|
|
|
ast = None
|
2014-12-23 21:45:15 +03:00
|
|
|
try:
|
|
|
|
import json # python >= 2.6
|
|
|
|
except ImportError:
|
|
|
|
json = None
|
|
|
|
|
|
|
|
if sys.version_info < (2, 7):
|
|
|
|
import unittest2 as unittest # https://pypi.python.org/pypi/unittest2
|
|
|
|
else:
|
|
|
|
import unittest
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
import psutil
|
2014-12-23 21:45:15 +03:00
|
|
|
from psutil._compat import PY3, callable, long, wraps, unicode
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
# ===================================================================
|
|
|
|
# --- Constants
|
|
|
|
# ===================================================================
|
|
|
|
|
|
|
|
# conf for retry_before_failing() decorator
|
|
|
|
NO_RETRIES = 10
|
|
|
|
# bytes tolerance for OS memory related tests
|
|
|
|
TOLERANCE = 500 * 1024 # 500KB
|
2014-12-23 21:45:15 +03:00
|
|
|
# the timeout used in functions which have to wait
|
|
|
|
GLOBAL_TIMEOUT = 3
|
2013-08-23 10:36:57 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
AF_INET6 = getattr(socket, "AF_INET6")
|
|
|
|
AF_UNIX = getattr(socket, "AF_UNIX", None)
|
2012-09-19 22:20:16 +04:00
|
|
|
PYTHON = os.path.realpath(sys.executable)
|
|
|
|
DEVNULL = open(os.devnull, 'r+')
|
|
|
|
TESTFN = os.path.join(os.getcwd(), "$testfile")
|
2014-12-23 21:45:15 +03:00
|
|
|
TESTFN_UNICODE = TESTFN + "ƒőő"
|
|
|
|
TESTFILE_PREFIX = 'psutil-test-suite-'
|
|
|
|
if not PY3:
|
|
|
|
try:
|
|
|
|
TESTFN_UNICODE = unicode(TESTFN_UNICODE, sys.getfilesystemencoding())
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
TESTFN_UNICODE = TESTFN + "???"
|
|
|
|
|
|
|
|
EXAMPLES_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
|
|
|
'..', 'examples'))
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
POSIX = os.name == 'posix'
|
2014-12-23 21:45:15 +03:00
|
|
|
WINDOWS = os.name == 'nt'
|
|
|
|
if WINDOWS:
|
|
|
|
WIN_VISTA = (6, 0, 0)
|
2012-09-19 22:20:16 +04:00
|
|
|
LINUX = sys.platform.startswith("linux")
|
|
|
|
OSX = sys.platform.startswith("darwin")
|
|
|
|
BSD = sys.platform.startswith("freebsd")
|
2013-08-23 10:36:57 +04:00
|
|
|
SUNOS = sys.platform.startswith("sunos")
|
2014-12-23 21:45:15 +03:00
|
|
|
VALID_PROC_STATUSES = [getattr(psutil, x) for x in dir(psutil)
|
|
|
|
if x.startswith('STATUS_')]
|
|
|
|
# whether we're running this test suite on Travis (https://travis-ci.org/)
|
|
|
|
TRAVIS = bool(os.environ.get('TRAVIS'))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
# ===================================================================
|
|
|
|
# --- Utility functions
|
|
|
|
# ===================================================================
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def cleanup():
|
|
|
|
reap_children(search_all=True)
|
|
|
|
safe_remove(TESTFN)
|
|
|
|
try:
|
|
|
|
safe_rmdir(TESTFN_UNICODE)
|
|
|
|
except UnicodeEncodeError:
|
|
|
|
pass
|
|
|
|
for path in _testfiles:
|
|
|
|
safe_remove(path)
|
|
|
|
|
|
|
|
atexit.register(cleanup)
|
|
|
|
atexit.register(lambda: DEVNULL.close())
|
|
|
|
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
_subprocesses_started = set()
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
|
|
|
def get_test_subprocess(cmd=None, stdout=DEVNULL, stderr=DEVNULL,
|
|
|
|
stdin=DEVNULL, wait=False):
|
2012-09-19 22:20:16 +04:00
|
|
|
"""Return a subprocess.Popen object to use in tests.
|
|
|
|
By default stdout and stderr are redirected to /dev/null and the
|
|
|
|
python interpreter is used as test process.
|
|
|
|
If 'wait' is True attemps to make sure the process is in a
|
|
|
|
reasonably initialized state.
|
|
|
|
"""
|
|
|
|
if cmd is None:
|
|
|
|
pyline = ""
|
|
|
|
if wait:
|
2013-05-10 02:39:30 +04:00
|
|
|
pyline += "open(r'%s', 'w'); " % TESTFN
|
2013-08-23 10:36:57 +04:00
|
|
|
pyline += "import time; time.sleep(2);"
|
2012-09-19 22:20:16 +04:00
|
|
|
cmd_ = [PYTHON, "-c", pyline]
|
|
|
|
else:
|
|
|
|
cmd_ = cmd
|
|
|
|
sproc = subprocess.Popen(cmd_, stdout=stdout, stderr=stderr, stdin=stdin)
|
|
|
|
if wait:
|
|
|
|
if cmd is None:
|
|
|
|
stop_at = time.time() + 3
|
2013-05-10 02:39:30 +04:00
|
|
|
while stop_at > time.time():
|
2012-09-19 22:20:16 +04:00
|
|
|
if os.path.exists(TESTFN):
|
|
|
|
break
|
|
|
|
time.sleep(0.001)
|
|
|
|
else:
|
|
|
|
warn("couldn't make sure test file was actually created")
|
|
|
|
else:
|
|
|
|
wait_for_pid(sproc.pid)
|
2014-12-23 21:45:15 +03:00
|
|
|
_subprocesses_started.add(psutil.Process(sproc.pid))
|
2012-09-19 22:20:16 +04:00
|
|
|
return sproc
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
|
|
|
_testfiles = []
|
|
|
|
|
|
|
|
|
|
|
|
def pyrun(src):
|
|
|
|
"""Run python code 'src' in a separate interpreter.
|
|
|
|
Return interpreter subprocess.
|
|
|
|
"""
|
|
|
|
if PY3:
|
|
|
|
src = bytes(src, 'ascii')
|
|
|
|
# could have used NamedTemporaryFile(delete=False) but it's
|
|
|
|
# >= 2.6 only
|
|
|
|
fd, path = tempfile.mkstemp(prefix=TESTFILE_PREFIX)
|
|
|
|
_testfiles.append(path)
|
|
|
|
f = open(path, 'wb')
|
|
|
|
try:
|
|
|
|
f.write(src)
|
|
|
|
f.flush()
|
|
|
|
subp = get_test_subprocess([PYTHON, f.name], stdout=None, stderr=None)
|
|
|
|
wait_for_pid(subp.pid)
|
|
|
|
return subp
|
|
|
|
finally:
|
|
|
|
os.close(fd)
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
def warn(msg):
|
2012-09-19 22:20:16 +04:00
|
|
|
"""Raise a warning msg."""
|
2013-08-23 10:36:57 +04:00
|
|
|
warnings.warn(msg, UserWarning)
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def sh(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE):
|
|
|
|
"""run cmd in a subprocess and return its output.
|
|
|
|
raises RuntimeError on error.
|
|
|
|
"""
|
|
|
|
p = subprocess.Popen(cmdline, shell=True, stdout=stdout, stderr=stderr)
|
|
|
|
stdout, stderr = p.communicate()
|
|
|
|
if p.returncode != 0:
|
|
|
|
raise RuntimeError(stderr)
|
|
|
|
if stderr:
|
|
|
|
warn(stderr)
|
|
|
|
if PY3:
|
|
|
|
stdout = str(stdout, sys.stdout.encoding)
|
|
|
|
return stdout.strip()
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
def which(program):
|
|
|
|
"""Same as UNIX which command. Return None on command not found."""
|
|
|
|
def is_exe(fpath):
|
|
|
|
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
|
|
|
|
|
|
|
fpath, fname = os.path.split(program)
|
|
|
|
if fpath:
|
|
|
|
if is_exe(program):
|
|
|
|
return program
|
|
|
|
else:
|
|
|
|
for path in os.environ["PATH"].split(os.pathsep):
|
|
|
|
exe_file = os.path.join(path, program)
|
|
|
|
if is_exe(exe_file):
|
|
|
|
return exe_file
|
|
|
|
return None
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
|
|
|
if POSIX:
|
|
|
|
def get_kernel_version():
|
|
|
|
"""Return a tuple such as (2, 6, 36)."""
|
|
|
|
s = ""
|
|
|
|
uname = os.uname()[2]
|
|
|
|
for c in uname:
|
|
|
|
if c.isdigit() or c == '.':
|
|
|
|
s += c
|
|
|
|
else:
|
|
|
|
break
|
|
|
|
if not s:
|
|
|
|
raise ValueError("can't parse %r" % uname)
|
|
|
|
minor = 0
|
|
|
|
micro = 0
|
|
|
|
nums = s.split('.')
|
|
|
|
major = int(nums[0])
|
|
|
|
if len(nums) >= 2:
|
|
|
|
minor = int(nums[1])
|
|
|
|
if len(nums) >= 3:
|
|
|
|
micro = int(nums[2])
|
|
|
|
return (major, minor, micro)
|
|
|
|
|
|
|
|
|
|
|
|
if LINUX:
|
|
|
|
RLIMIT_SUPPORT = get_kernel_version() >= (2, 6, 36)
|
|
|
|
else:
|
|
|
|
RLIMIT_SUPPORT = False
|
|
|
|
|
|
|
|
|
|
|
|
def wait_for_pid(pid, timeout=GLOBAL_TIMEOUT):
|
2012-09-19 22:20:16 +04:00
|
|
|
"""Wait for pid to show up in the process list then return.
|
|
|
|
Used in the test suite to give time the sub process to initialize.
|
|
|
|
"""
|
|
|
|
raise_at = time.time() + timeout
|
|
|
|
while 1:
|
2014-12-23 21:45:15 +03:00
|
|
|
if pid in psutil.pids():
|
2012-09-19 22:20:16 +04:00
|
|
|
# give it one more iteration to allow full initialization
|
|
|
|
time.sleep(0.01)
|
|
|
|
return
|
|
|
|
time.sleep(0.0001)
|
|
|
|
if time.time() >= raise_at:
|
|
|
|
raise RuntimeError("Timed out")
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
def reap_children(search_all=False):
|
|
|
|
"""Kill any subprocess started by this test suite and ensure that
|
|
|
|
no zombies stick around to hog resources and create problems when
|
|
|
|
looking for refleaks.
|
|
|
|
"""
|
2014-12-23 21:45:15 +03:00
|
|
|
global _subprocesses_started
|
|
|
|
procs = _subprocesses_started.copy()
|
2012-09-19 22:20:16 +04:00
|
|
|
if search_all:
|
2014-12-23 21:45:15 +03:00
|
|
|
this_process = psutil.Process()
|
|
|
|
for p in this_process.children(recursive=True):
|
|
|
|
procs.add(p)
|
|
|
|
for p in procs:
|
2012-09-19 22:20:16 +04:00
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.terminate()
|
2012-09-19 22:20:16 +04:00
|
|
|
except psutil.NoSuchProcess:
|
|
|
|
pass
|
2014-12-23 21:45:15 +03:00
|
|
|
gone, alive = psutil.wait_procs(procs, timeout=GLOBAL_TIMEOUT)
|
|
|
|
for p in alive:
|
|
|
|
warn("couldn't terminate process %s" % p)
|
|
|
|
try:
|
|
|
|
p.kill()
|
|
|
|
except psutil.NoSuchProcess:
|
|
|
|
pass
|
|
|
|
_, alive = psutil.wait_procs(alive, timeout=GLOBAL_TIMEOUT)
|
|
|
|
if alive:
|
|
|
|
warn("couldn't not kill processes %s" % str(alive))
|
|
|
|
_subprocesses_started = set(alive)
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def check_ip_address(addr, family):
|
|
|
|
"""Attempts to check IP address's validity."""
|
|
|
|
if not addr:
|
|
|
|
return
|
2014-12-23 21:45:15 +03:00
|
|
|
if family in (AF_INET, AF_INET6):
|
|
|
|
assert isinstance(addr, tuple), addr
|
|
|
|
ip, port = addr
|
|
|
|
assert isinstance(port, int), port
|
|
|
|
if family == AF_INET:
|
|
|
|
ip = list(map(int, ip.split('.')))
|
|
|
|
assert len(ip) == 4, ip
|
|
|
|
for num in ip:
|
|
|
|
assert 0 <= num <= 255, ip
|
|
|
|
assert 0 <= port <= 65535, port
|
|
|
|
elif family == AF_UNIX:
|
|
|
|
assert isinstance(addr, (str, None)), addr
|
|
|
|
else:
|
|
|
|
raise ValueError("unknown family %r", family)
|
|
|
|
|
|
|
|
|
|
|
|
def check_connection(conn):
|
|
|
|
"""Check validity of a connection namedtuple."""
|
|
|
|
valid_conn_states = [getattr(psutil, x) for x in dir(psutil) if
|
|
|
|
x.startswith('CONN_')]
|
|
|
|
|
|
|
|
assert conn.type in (SOCK_STREAM, SOCK_DGRAM), repr(conn.type)
|
|
|
|
assert conn.family in (AF_INET, AF_INET6, AF_UNIX), repr(conn.family)
|
|
|
|
assert conn.status in valid_conn_states, conn.status
|
|
|
|
check_ip_address(conn.laddr, conn.family)
|
|
|
|
check_ip_address(conn.raddr, conn.family)
|
|
|
|
|
|
|
|
if conn.family in (AF_INET, AF_INET6):
|
|
|
|
# actually try to bind the local socket; ignore IPv6
|
|
|
|
# sockets as their address might be represented as
|
|
|
|
# an IPv4-mapped-address (e.g. "::127.0.0.1")
|
|
|
|
# and that's rejected by bind()
|
|
|
|
if conn.family == AF_INET:
|
|
|
|
s = socket.socket(conn.family, conn.type)
|
|
|
|
try:
|
|
|
|
s.bind((conn.laddr[0], 0))
|
|
|
|
except socket.error:
|
|
|
|
err = sys.exc_info()[1]
|
|
|
|
if err.errno != errno.EADDRNOTAVAIL:
|
|
|
|
raise
|
|
|
|
s.close()
|
|
|
|
elif conn.family == AF_UNIX:
|
|
|
|
assert not conn.raddr, repr(conn.raddr)
|
|
|
|
assert conn.status == psutil.CONN_NONE, conn.status
|
|
|
|
|
|
|
|
if getattr(conn, 'fd', -1) != -1:
|
|
|
|
assert conn.fd > 0, conn
|
|
|
|
if hasattr(socket, 'fromfd') and not WINDOWS:
|
|
|
|
dupsock = None
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
dupsock = socket.fromfd(conn.fd, conn.family, conn.type)
|
|
|
|
except (socket.error, OSError):
|
|
|
|
err = sys.exc_info()[1]
|
|
|
|
if err.args[0] != errno.EBADF:
|
|
|
|
raise
|
|
|
|
else:
|
|
|
|
# python >= 2.5
|
|
|
|
if hasattr(dupsock, "family"):
|
|
|
|
assert dupsock.family == conn.family
|
|
|
|
assert dupsock.type == conn.type
|
|
|
|
finally:
|
|
|
|
if dupsock is not None:
|
|
|
|
dupsock.close()
|
|
|
|
|
|
|
|
|
|
|
|
def safe_remove(file):
|
|
|
|
"Convenience function for removing temporary test files"
|
|
|
|
try:
|
|
|
|
os.remove(file)
|
|
|
|
except OSError:
|
|
|
|
err = sys.exc_info()[1]
|
|
|
|
if err.errno != errno.ENOENT:
|
|
|
|
# file is being used by another process
|
|
|
|
if WINDOWS and isinstance(err, WindowsError) and err.errno == 13:
|
|
|
|
return
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
def safe_rmdir(dir):
|
|
|
|
"Convenience function for removing temporary test directories"
|
2012-09-19 22:20:16 +04:00
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
os.rmdir(dir)
|
2012-09-19 22:20:16 +04:00
|
|
|
except OSError:
|
2013-05-10 02:39:30 +04:00
|
|
|
err = sys.exc_info()[1]
|
2014-12-23 21:45:15 +03:00
|
|
|
if err.errno != errno.ENOENT:
|
2013-05-10 02:39:30 +04:00
|
|
|
raise
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
|
|
|
def call_until(fun, expr, timeout=GLOBAL_TIMEOUT):
|
2012-09-19 22:20:16 +04:00
|
|
|
"""Keep calling function for timeout secs and exit if eval()
|
|
|
|
expression is True.
|
|
|
|
"""
|
|
|
|
stop_at = time.time() + timeout
|
|
|
|
while time.time() < stop_at:
|
|
|
|
ret = fun()
|
|
|
|
if eval(expr):
|
|
|
|
return ret
|
|
|
|
time.sleep(0.001)
|
|
|
|
raise RuntimeError('timed out (ret=%r)' % ret)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
def retry_before_failing(ntimes=None):
|
|
|
|
"""Decorator which runs a test function and retries N times before
|
|
|
|
actually failing.
|
2012-09-19 22:20:16 +04:00
|
|
|
"""
|
2013-08-23 10:36:57 +04:00
|
|
|
def decorator(fun):
|
|
|
|
@wraps(fun)
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
for x in range(ntimes or NO_RETRIES):
|
|
|
|
try:
|
|
|
|
return fun(*args, **kwargs)
|
|
|
|
except AssertionError:
|
2014-12-23 21:45:15 +03:00
|
|
|
pass
|
2013-08-23 10:36:57 +04:00
|
|
|
raise
|
|
|
|
return wrapper
|
|
|
|
return decorator
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
2013-05-10 02:39:30 +04:00
|
|
|
def skip_on_access_denied(only_if=None):
|
2012-09-19 22:20:16 +04:00
|
|
|
"""Decorator to Ignore AccessDenied exceptions."""
|
2013-05-10 02:39:30 +04:00
|
|
|
def decorator(fun):
|
|
|
|
@wraps(fun)
|
|
|
|
def wrapper(*args, **kwargs):
|
2012-09-19 22:20:16 +04:00
|
|
|
try:
|
2013-05-10 02:39:30 +04:00
|
|
|
return fun(*args, **kwargs)
|
2012-09-19 22:20:16 +04:00
|
|
|
except psutil.AccessDenied:
|
2013-05-10 02:39:30 +04:00
|
|
|
if only_if is not None:
|
|
|
|
if not only_if:
|
|
|
|
raise
|
2013-08-23 10:36:57 +04:00
|
|
|
msg = "%r was skipped because it raised AccessDenied" \
|
|
|
|
% fun.__name__
|
|
|
|
self = args[0]
|
2014-12-23 21:45:15 +03:00
|
|
|
self.skip(msg)
|
2013-05-10 02:39:30 +04:00
|
|
|
return wrapper
|
|
|
|
return decorator
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
def skip_on_not_implemented(only_if=None):
|
|
|
|
"""Decorator to Ignore NotImplementedError exceptions."""
|
|
|
|
def decorator(fun):
|
|
|
|
@wraps(fun)
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
try:
|
|
|
|
return fun(*args, **kwargs)
|
|
|
|
except NotImplementedError:
|
|
|
|
if only_if is not None:
|
|
|
|
if not only_if:
|
|
|
|
raise
|
|
|
|
msg = "%r was skipped because it raised NotImplementedError" \
|
|
|
|
% fun.__name__
|
|
|
|
self = args[0]
|
2014-12-23 21:45:15 +03:00
|
|
|
self.skip(msg)
|
2013-08-23 10:36:57 +04:00
|
|
|
return wrapper
|
|
|
|
return decorator
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
def supports_ipv6():
|
|
|
|
"""Return True if IPv6 is supported on this platform."""
|
|
|
|
if not socket.has_ipv6 or not hasattr(socket, "AF_INET6"):
|
|
|
|
return False
|
|
|
|
sock = None
|
|
|
|
try:
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
sock = socket.socket(AF_INET6, SOCK_STREAM)
|
2012-09-19 22:20:16 +04:00
|
|
|
sock.bind(("::1", 0))
|
|
|
|
except (socket.error, socket.gaierror):
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
finally:
|
|
|
|
if sock is not None:
|
|
|
|
sock.close()
|
|
|
|
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
if WINDOWS:
|
|
|
|
def get_winver():
|
|
|
|
wv = sys.getwindowsversion()
|
|
|
|
if hasattr(wv, 'service_pack_major'): # python >= 2.7
|
|
|
|
sp = wv.service_pack_major or 0
|
|
|
|
else:
|
|
|
|
r = re.search("\s\d$", wv[4])
|
|
|
|
if r:
|
|
|
|
sp = int(r.group(0))
|
|
|
|
else:
|
|
|
|
sp = 0
|
|
|
|
return (wv[0], wv[1], sp)
|
|
|
|
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
class ThreadTask(threading.Thread):
|
|
|
|
"""A thread object used for running process thread tests."""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
threading.Thread.__init__(self)
|
|
|
|
self._running = False
|
|
|
|
self._interval = None
|
|
|
|
self._flag = threading.Event()
|
|
|
|
|
|
|
|
def __repr__(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
name = self.__class__.__name__
|
2012-09-19 22:20:16 +04:00
|
|
|
return '<%s running=%s at %#x>' % (name, self._running, id(self))
|
|
|
|
|
|
|
|
def start(self, interval=0.001):
|
|
|
|
"""Start thread and keep it running until an explicit
|
|
|
|
stop() request. Polls for shutdown every 'timeout' seconds.
|
|
|
|
"""
|
|
|
|
if self._running:
|
|
|
|
raise ValueError("already started")
|
|
|
|
self._interval = interval
|
|
|
|
threading.Thread.start(self)
|
|
|
|
self._flag.wait()
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
self._running = True
|
|
|
|
self._flag.set()
|
|
|
|
while self._running:
|
|
|
|
time.sleep(self._interval)
|
|
|
|
|
|
|
|
def stop(self):
|
|
|
|
"""Stop thread execution and and waits until it is stopped."""
|
|
|
|
if not self._running:
|
|
|
|
raise ValueError("already stopped")
|
|
|
|
self._running = False
|
|
|
|
self.join()
|
|
|
|
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
# python 2.4
|
|
|
|
if not hasattr(subprocess.Popen, 'terminate'):
|
|
|
|
subprocess.Popen.terminate = \
|
|
|
|
lambda self: psutil.Process(self.pid).terminate()
|
2013-08-23 10:36:57 +04:00
|
|
|
|
|
|
|
|
|
|
|
# ===================================================================
|
|
|
|
# --- System-related API tests
|
|
|
|
# ===================================================================
|
|
|
|
|
|
|
|
class TestSystemAPIs(unittest.TestCase):
|
|
|
|
"""Tests for system-related APIs."""
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
safe_remove(TESTFN)
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
reap_children()
|
|
|
|
|
|
|
|
def test_process_iter(self):
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIn(os.getpid(), [x.pid for x in psutil.process_iter()])
|
2012-09-19 22:20:16 +04:00
|
|
|
sproc = get_test_subprocess()
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIn(sproc.pid, [x.pid for x in psutil.process_iter()])
|
2012-09-19 22:20:16 +04:00
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
p.kill()
|
|
|
|
p.wait()
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertNotIn(sproc.pid, [x.pid for x in psutil.process_iter()])
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_wait_procs(self):
|
|
|
|
l = []
|
|
|
|
callback = lambda p: l.append(p.pid)
|
|
|
|
|
|
|
|
sproc1 = get_test_subprocess()
|
|
|
|
sproc2 = get_test_subprocess()
|
|
|
|
sproc3 = get_test_subprocess()
|
|
|
|
procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)]
|
|
|
|
self.assertRaises(ValueError, psutil.wait_procs, procs, timeout=-1)
|
|
|
|
t = time.time()
|
|
|
|
gone, alive = psutil.wait_procs(procs, timeout=0.01, callback=callback)
|
|
|
|
|
|
|
|
self.assertLess(time.time() - t, 0.5)
|
|
|
|
self.assertEqual(gone, [])
|
|
|
|
self.assertEqual(len(alive), 3)
|
|
|
|
self.assertEqual(l, [])
|
|
|
|
for p in alive:
|
|
|
|
self.assertFalse(hasattr(p, 'returncode'))
|
|
|
|
|
|
|
|
sproc3.terminate()
|
|
|
|
gone, alive = psutil.wait_procs(procs, timeout=0.03, callback=callback)
|
|
|
|
self.assertEqual(len(gone), 1)
|
|
|
|
self.assertEqual(len(alive), 2)
|
|
|
|
self.assertIn(sproc3.pid, [x.pid for x in gone])
|
|
|
|
if POSIX:
|
|
|
|
self.assertEqual(gone.pop().returncode, signal.SIGTERM)
|
2013-05-10 02:39:30 +04:00
|
|
|
else:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(gone.pop().returncode, 1)
|
|
|
|
self.assertEqual(l, [sproc3.pid])
|
|
|
|
for p in alive:
|
|
|
|
self.assertFalse(hasattr(p, 'returncode'))
|
|
|
|
|
|
|
|
sproc1.terminate()
|
|
|
|
sproc2.terminate()
|
|
|
|
gone, alive = psutil.wait_procs(procs, timeout=0.03, callback=callback)
|
|
|
|
self.assertEqual(len(gone), 3)
|
|
|
|
self.assertEqual(len(alive), 0)
|
|
|
|
self.assertEqual(set(l), set([sproc1.pid, sproc2.pid, sproc3.pid]))
|
|
|
|
for p in gone:
|
|
|
|
self.assertTrue(hasattr(p, 'returncode'))
|
|
|
|
|
|
|
|
def test_wait_procs_no_timeout(self):
|
|
|
|
sproc1 = get_test_subprocess()
|
|
|
|
sproc2 = get_test_subprocess()
|
|
|
|
sproc3 = get_test_subprocess()
|
|
|
|
procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)]
|
|
|
|
for p in procs:
|
|
|
|
p.terminate()
|
|
|
|
gone, alive = psutil.wait_procs(procs)
|
|
|
|
|
|
|
|
def test_boot_time(self):
|
|
|
|
bt = psutil.boot_time()
|
|
|
|
self.assertIsInstance(bt, float)
|
|
|
|
self.assertGreater(bt, 0)
|
|
|
|
self.assertLess(bt, time.time())
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@unittest.skipUnless(POSIX, 'posix only')
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_PAGESIZE(self):
|
|
|
|
# pagesize is used internally to perform different calculations
|
|
|
|
# and it's determined by using SC_PAGE_SIZE; make sure
|
|
|
|
# getpagesize() returns the same value.
|
|
|
|
import resource
|
|
|
|
self.assertEqual(os.sysconf("SC_PAGE_SIZE"), resource.getpagesize())
|
|
|
|
|
|
|
|
def test_deprecated_apis(self):
|
2013-08-23 10:36:57 +04:00
|
|
|
s = socket.socket()
|
|
|
|
s.bind(('localhost', 0))
|
|
|
|
s.listen(1)
|
2012-09-19 22:20:16 +04:00
|
|
|
warnings.filterwarnings("error")
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
2012-09-19 22:20:16 +04:00
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
# system APIs
|
|
|
|
self.assertRaises(DeprecationWarning, getattr, psutil, 'NUM_CPUS')
|
|
|
|
self.assertRaises(DeprecationWarning, getattr, psutil, 'BOOT_TIME')
|
|
|
|
self.assertRaises(DeprecationWarning, getattr, psutil,
|
|
|
|
'TOTAL_PHYMEM')
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.get_pid_list)
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.get_users)
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertRaises(DeprecationWarning, psutil.virtmem_usage)
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.used_phymem)
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.avail_phymem)
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.total_virtmem)
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.used_virtmem)
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.avail_virtmem)
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.phymem_usage)
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.get_process_list)
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertRaises(DeprecationWarning, psutil.network_io_counters)
|
2012-09-19 22:20:16 +04:00
|
|
|
if LINUX:
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.phymem_buffers)
|
|
|
|
self.assertRaises(DeprecationWarning, psutil.cached_phymem)
|
2014-12-23 21:45:15 +03:00
|
|
|
|
|
|
|
# Process class
|
|
|
|
names = dir(psutil.Process)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_children)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_connections)
|
|
|
|
if 'cpu_affinity' in names:
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_cpu_affinity)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_cpu_percent)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_cpu_times)
|
|
|
|
self.assertRaises(DeprecationWarning, p.getcwd)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_ext_memory_info)
|
|
|
|
if 'io_counters' in names:
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_io_counters)
|
|
|
|
if 'ionice' in names:
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_ionice)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_memory_info)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_memory_maps)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_memory_percent)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_nice)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_num_ctx_switches)
|
|
|
|
if 'num_fds' in names:
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_num_fds)
|
|
|
|
if 'num_handles' in names:
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_num_handles)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_num_threads)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_open_files)
|
|
|
|
if 'rlimit' in names:
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_rlimit)
|
|
|
|
self.assertRaises(DeprecationWarning, p.get_threads)
|
|
|
|
# ...just to be extra sure:
|
|
|
|
for name in names:
|
|
|
|
if name.startswith('get'):
|
|
|
|
meth = getattr(p, name)
|
|
|
|
try:
|
|
|
|
self.assertRaises(DeprecationWarning, meth)
|
|
|
|
except AssertionError:
|
|
|
|
self.fail("%s did not raise DeprecationWarning" % name)
|
|
|
|
|
|
|
|
# named tuples
|
|
|
|
ret = call_until(p.connections, "len(ret) != 0")
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertRaises(DeprecationWarning,
|
|
|
|
getattr, ret[0], 'local_address')
|
|
|
|
self.assertRaises(DeprecationWarning,
|
|
|
|
getattr, ret[0], 'remote_address')
|
2012-09-19 22:20:16 +04:00
|
|
|
finally:
|
2013-08-23 10:36:57 +04:00
|
|
|
s.close()
|
2012-09-19 22:20:16 +04:00
|
|
|
warnings.resetwarnings()
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
# check value against new APIs
|
|
|
|
warnings.filterwarnings("ignore")
|
|
|
|
try:
|
|
|
|
self.assertEqual(psutil.get_pid_list(), psutil.pids())
|
|
|
|
self.assertEqual(psutil.NUM_CPUS, psutil.cpu_count())
|
|
|
|
self.assertEqual(psutil.BOOT_TIME, psutil.boot_time())
|
|
|
|
self.assertEqual(psutil.TOTAL_PHYMEM,
|
|
|
|
psutil.virtual_memory().total)
|
|
|
|
finally:
|
|
|
|
warnings.resetwarnings()
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_deprecated_apis_retval(self):
|
|
|
|
warnings.filterwarnings("ignore")
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(psutil.total_virtmem(),
|
|
|
|
psutil.swap_memory().total)
|
2012-09-19 22:20:16 +04:00
|
|
|
finally:
|
|
|
|
warnings.resetwarnings()
|
|
|
|
|
|
|
|
def test_virtual_memory(self):
|
|
|
|
mem = psutil.virtual_memory()
|
|
|
|
assert mem.total > 0, mem
|
|
|
|
assert mem.available > 0, mem
|
|
|
|
assert 0 <= mem.percent <= 100, mem
|
|
|
|
assert mem.used > 0, mem
|
|
|
|
assert mem.free >= 0, mem
|
|
|
|
for name in mem._fields:
|
2014-12-23 21:45:15 +03:00
|
|
|
value = getattr(mem, name)
|
|
|
|
if name != 'percent':
|
|
|
|
self.assertIsInstance(value, (int, long))
|
2012-09-19 22:20:16 +04:00
|
|
|
if name != 'total':
|
|
|
|
if not value >= 0:
|
|
|
|
self.fail("%r < 0 (%s)" % (name, value))
|
|
|
|
if value > mem.total:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.fail("%r > total (total=%s, %s=%s)"
|
2012-09-19 22:20:16 +04:00
|
|
|
% (name, mem.total, name, value))
|
|
|
|
|
|
|
|
def test_swap_memory(self):
|
|
|
|
mem = psutil.swap_memory()
|
2013-08-23 10:36:57 +04:00
|
|
|
assert mem.total >= 0, mem
|
2012-09-19 22:20:16 +04:00
|
|
|
assert mem.used >= 0, mem
|
2014-12-23 21:45:15 +03:00
|
|
|
if mem.total > 0:
|
|
|
|
# likely a system with no swap partition
|
|
|
|
assert mem.free > 0, mem
|
|
|
|
else:
|
|
|
|
assert mem.free == 0, mem
|
2012-09-19 22:20:16 +04:00
|
|
|
assert 0 <= mem.percent <= 100, mem
|
|
|
|
assert mem.sin >= 0, mem
|
|
|
|
assert mem.sout >= 0, mem
|
|
|
|
|
|
|
|
def test_pid_exists(self):
|
|
|
|
sproc = get_test_subprocess(wait=True)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertTrue(psutil.pid_exists(sproc.pid))
|
2012-09-19 22:20:16 +04:00
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
p.kill()
|
|
|
|
p.wait()
|
|
|
|
self.assertFalse(psutil.pid_exists(sproc.pid))
|
|
|
|
self.assertFalse(psutil.pid_exists(-1))
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(psutil.pid_exists(0), 0 in psutil.pids())
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_pid_exists_2(self):
|
|
|
|
reap_children()
|
2014-12-23 21:45:15 +03:00
|
|
|
pids = psutil.pids()
|
2012-09-19 22:20:16 +04:00
|
|
|
for pid in pids:
|
|
|
|
try:
|
|
|
|
assert psutil.pid_exists(pid)
|
|
|
|
except AssertionError:
|
|
|
|
# in case the process disappeared in meantime fail only
|
2014-12-23 21:45:15 +03:00
|
|
|
# if it is no longer in psutil.pids()
|
2012-09-19 22:20:16 +04:00
|
|
|
time.sleep(.1)
|
2014-12-23 21:45:15 +03:00
|
|
|
if pid in psutil.pids():
|
2012-09-19 22:20:16 +04:00
|
|
|
self.fail(pid)
|
|
|
|
pids = range(max(pids) + 5000, max(pids) + 6000)
|
|
|
|
for pid in pids:
|
|
|
|
self.assertFalse(psutil.pid_exists(pid))
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_pids(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
plist = [x.pid for x in psutil.process_iter()]
|
2014-12-23 21:45:15 +03:00
|
|
|
pidlist = psutil.pids()
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(plist.sort(), pidlist.sort())
|
|
|
|
# make sure every pid is unique
|
|
|
|
self.assertEqual(len(pidlist), len(set(pidlist)))
|
|
|
|
|
|
|
|
def test_test(self):
|
|
|
|
# test for psutil.test() function
|
|
|
|
stdout = sys.stdout
|
|
|
|
sys.stdout = DEVNULL
|
|
|
|
try:
|
|
|
|
psutil.test()
|
|
|
|
finally:
|
|
|
|
sys.stdout = stdout
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_cpu_count(self):
|
|
|
|
logical = psutil.cpu_count()
|
|
|
|
self.assertEqual(logical, len(psutil.cpu_times(percpu=True)))
|
|
|
|
self.assertGreaterEqual(logical, 1)
|
|
|
|
#
|
|
|
|
physical = psutil.cpu_count(logical=False)
|
|
|
|
self.assertGreaterEqual(physical, 1)
|
|
|
|
self.assertGreaterEqual(logical, physical)
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_sys_cpu_times(self):
|
|
|
|
total = 0
|
|
|
|
times = psutil.cpu_times()
|
|
|
|
sum(times)
|
|
|
|
for cp_time in times:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIsInstance(cp_time, float)
|
|
|
|
self.assertGreaterEqual(cp_time, 0.0)
|
2012-09-19 22:20:16 +04:00
|
|
|
total += cp_time
|
|
|
|
self.assertEqual(total, sum(times))
|
|
|
|
str(times)
|
2014-12-23 21:45:15 +03:00
|
|
|
if not WINDOWS:
|
|
|
|
# CPU times are always supposed to increase over time or
|
|
|
|
# remain the same but never go backwards, see:
|
|
|
|
# https://github.com/giampaolo/psutil/issues/392
|
|
|
|
last = psutil.cpu_times()
|
|
|
|
for x in range(100):
|
|
|
|
new = psutil.cpu_times()
|
|
|
|
for field in new._fields:
|
|
|
|
new_t = getattr(new, field)
|
|
|
|
last_t = getattr(last, field)
|
|
|
|
self.assertGreaterEqual(new_t, last_t,
|
|
|
|
msg="%s %s" % (new_t, last_t))
|
|
|
|
last = new
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_sys_cpu_times2(self):
|
|
|
|
t1 = sum(psutil.cpu_times())
|
|
|
|
time.sleep(0.1)
|
|
|
|
t2 = sum(psutil.cpu_times())
|
|
|
|
difference = t2 - t1
|
|
|
|
if not difference >= 0.05:
|
|
|
|
self.fail("difference %s" % difference)
|
|
|
|
|
|
|
|
def test_sys_per_cpu_times(self):
|
|
|
|
for times in psutil.cpu_times(percpu=True):
|
|
|
|
total = 0
|
|
|
|
sum(times)
|
|
|
|
for cp_time in times:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIsInstance(cp_time, float)
|
|
|
|
self.assertGreaterEqual(cp_time, 0.0)
|
2012-09-19 22:20:16 +04:00
|
|
|
total += cp_time
|
|
|
|
self.assertEqual(total, sum(times))
|
|
|
|
str(times)
|
2013-05-10 02:39:30 +04:00
|
|
|
self.assertEqual(len(psutil.cpu_times(percpu=True)[0]),
|
|
|
|
len(psutil.cpu_times(percpu=False)))
|
2014-12-23 21:45:15 +03:00
|
|
|
if not WINDOWS:
|
|
|
|
# CPU times are always supposed to increase over time or
|
|
|
|
# remain the same but never go backwards, see:
|
|
|
|
# https://github.com/giampaolo/psutil/issues/392
|
|
|
|
last = psutil.cpu_times(percpu=True)
|
|
|
|
for x in range(100):
|
|
|
|
new = psutil.cpu_times(percpu=True)
|
|
|
|
for index in range(len(new)):
|
|
|
|
newcpu = new[index]
|
|
|
|
lastcpu = last[index]
|
|
|
|
for field in newcpu._fields:
|
|
|
|
new_t = getattr(newcpu, field)
|
|
|
|
last_t = getattr(lastcpu, field)
|
|
|
|
self.assertGreaterEqual(
|
|
|
|
new_t, last_t, msg="%s %s" % (lastcpu, newcpu))
|
|
|
|
last = new
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_sys_per_cpu_times2(self):
|
|
|
|
tot1 = psutil.cpu_times(percpu=True)
|
|
|
|
stop_at = time.time() + 0.1
|
|
|
|
while 1:
|
|
|
|
if time.time() >= stop_at:
|
|
|
|
break
|
|
|
|
tot2 = psutil.cpu_times(percpu=True)
|
|
|
|
for t1, t2 in zip(tot1, tot2):
|
|
|
|
t1, t2 = sum(t1), sum(t2)
|
|
|
|
difference = t2 - t1
|
|
|
|
if difference >= 0.05:
|
|
|
|
return
|
|
|
|
self.fail()
|
|
|
|
|
2013-05-10 02:39:30 +04:00
|
|
|
def _test_cpu_percent(self, percent):
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIsInstance(percent, float)
|
|
|
|
self.assertGreaterEqual(percent, 0.0)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertLessEqual(percent, 100.0 * psutil.cpu_count())
|
2013-05-10 02:39:30 +04:00
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_sys_cpu_percent(self):
|
|
|
|
psutil.cpu_percent(interval=0.001)
|
|
|
|
for x in range(1000):
|
2013-05-10 02:39:30 +04:00
|
|
|
self._test_cpu_percent(psutil.cpu_percent(interval=None))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_sys_per_cpu_percent(self):
|
2013-05-10 02:39:30 +04:00
|
|
|
self.assertEqual(len(psutil.cpu_percent(interval=0.001, percpu=True)),
|
2014-12-23 21:45:15 +03:00
|
|
|
psutil.cpu_count())
|
2012-09-19 22:20:16 +04:00
|
|
|
for x in range(1000):
|
|
|
|
percents = psutil.cpu_percent(interval=None, percpu=True)
|
|
|
|
for percent in percents:
|
2013-05-10 02:39:30 +04:00
|
|
|
self._test_cpu_percent(percent)
|
|
|
|
|
|
|
|
def test_sys_cpu_times_percent(self):
|
|
|
|
psutil.cpu_times_percent(interval=0.001)
|
|
|
|
for x in range(1000):
|
|
|
|
cpu = psutil.cpu_times_percent(interval=None)
|
|
|
|
for percent in cpu:
|
|
|
|
self._test_cpu_percent(percent)
|
|
|
|
self._test_cpu_percent(sum(cpu))
|
|
|
|
|
|
|
|
def test_sys_per_cpu_times_percent(self):
|
|
|
|
self.assertEqual(len(psutil.cpu_times_percent(interval=0.001,
|
|
|
|
percpu=True)),
|
2014-12-23 21:45:15 +03:00
|
|
|
psutil.cpu_count())
|
2013-05-10 02:39:30 +04:00
|
|
|
for x in range(1000):
|
|
|
|
cpus = psutil.cpu_times_percent(interval=None, percpu=True)
|
|
|
|
for cpu in cpus:
|
|
|
|
for percent in cpu:
|
|
|
|
self._test_cpu_percent(percent)
|
|
|
|
self._test_cpu_percent(sum(cpu))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@unittest.skipIf(POSIX and not hasattr(os, 'statvfs'),
|
|
|
|
"os.statvfs() function not available on this platform")
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_disk_usage(self):
|
|
|
|
usage = psutil.disk_usage(os.getcwd())
|
|
|
|
assert usage.total > 0, usage
|
|
|
|
assert usage.used > 0, usage
|
|
|
|
assert usage.free > 0, usage
|
|
|
|
assert usage.total > usage.used, usage
|
|
|
|
assert usage.total > usage.free, usage
|
|
|
|
assert 0 <= usage.percent <= 100, usage.percent
|
2014-12-23 21:45:15 +03:00
|
|
|
if hasattr(shutil, 'disk_usage'):
|
|
|
|
# py >= 3.3, see: http://bugs.python.org/issue12442
|
|
|
|
shutil_usage = shutil.disk_usage(os.getcwd())
|
|
|
|
tolerance = 5 * 1024 * 1024 # 5MB
|
|
|
|
self.assertEqual(usage.total, shutil_usage.total)
|
|
|
|
self.assertAlmostEqual(usage.free, shutil_usage.free,
|
|
|
|
delta=tolerance)
|
|
|
|
self.assertAlmostEqual(usage.used, shutil_usage.used,
|
|
|
|
delta=tolerance)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
# if path does not exist OSError ENOENT is expected across
|
|
|
|
# all platforms
|
|
|
|
fname = tempfile.mktemp()
|
|
|
|
try:
|
|
|
|
psutil.disk_usage(fname)
|
|
|
|
except OSError:
|
|
|
|
err = sys.exc_info()[1]
|
|
|
|
if err.args[0] != errno.ENOENT:
|
|
|
|
raise
|
|
|
|
else:
|
|
|
|
self.fail("OSError not raised")
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@unittest.skipIf(POSIX and not hasattr(os, 'statvfs'),
|
|
|
|
"os.statvfs() function not available on this platform")
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_disk_usage_unicode(self):
|
|
|
|
# see: https://github.com/giampaolo/psutil/issues/416
|
|
|
|
# XXX this test is not really reliable as it always fails on
|
|
|
|
# Python 3.X (2.X is fine)
|
|
|
|
try:
|
|
|
|
safe_rmdir(TESTFN_UNICODE)
|
|
|
|
os.mkdir(TESTFN_UNICODE)
|
|
|
|
psutil.disk_usage(TESTFN_UNICODE)
|
|
|
|
safe_rmdir(TESTFN_UNICODE)
|
|
|
|
except UnicodeEncodeError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
@unittest.skipIf(POSIX and not hasattr(os, 'statvfs'),
|
|
|
|
"os.statvfs() function not available on this platform")
|
|
|
|
@unittest.skipIf(LINUX and TRAVIS, "unknown failure on travis")
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_disk_partitions(self):
|
2013-08-23 10:36:57 +04:00
|
|
|
# all = False
|
2014-12-23 21:45:15 +03:00
|
|
|
ls = psutil.disk_partitions(all=False)
|
|
|
|
# on travis we get:
|
|
|
|
# self.assertEqual(p.cpu_affinity(), [n])
|
|
|
|
# AssertionError: Lists differ: [0, 1, 2, 3, 4, 5, 6, 7,... != [0]
|
|
|
|
self.assertTrue(ls, msg=ls)
|
|
|
|
for disk in ls:
|
2013-05-10 02:39:30 +04:00
|
|
|
if WINDOWS and 'cdrom' in disk.opts:
|
|
|
|
continue
|
2013-08-23 10:36:57 +04:00
|
|
|
if not POSIX:
|
|
|
|
assert os.path.exists(disk.device), disk
|
|
|
|
else:
|
|
|
|
# we cannot make any assumption about this, see:
|
|
|
|
# http://goo.gl/p9c43
|
|
|
|
disk.device
|
|
|
|
if SUNOS:
|
|
|
|
# on solaris apparently mount points can also be files
|
|
|
|
assert os.path.exists(disk.mountpoint), disk
|
|
|
|
else:
|
|
|
|
assert os.path.isdir(disk.mountpoint), disk
|
2012-09-19 22:20:16 +04:00
|
|
|
assert disk.fstype, disk
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIsInstance(disk.opts, str)
|
|
|
|
|
|
|
|
# all = True
|
2014-12-23 21:45:15 +03:00
|
|
|
ls = psutil.disk_partitions(all=True)
|
|
|
|
self.assertTrue(ls, msg=ls)
|
2012-09-19 22:20:16 +04:00
|
|
|
for disk in psutil.disk_partitions(all=True):
|
|
|
|
if not WINDOWS:
|
|
|
|
try:
|
|
|
|
os.stat(disk.mountpoint)
|
|
|
|
except OSError:
|
2014-12-23 21:45:15 +03:00
|
|
|
# http://mail.python.org/pipermail/python-dev/
|
|
|
|
# 2012-June/120787.html
|
2012-09-19 22:20:16 +04:00
|
|
|
err = sys.exc_info()[1]
|
|
|
|
if err.errno not in (errno.EPERM, errno.EACCES):
|
|
|
|
raise
|
|
|
|
else:
|
2013-08-23 10:36:57 +04:00
|
|
|
if SUNOS:
|
|
|
|
# on solaris apparently mount points can also be files
|
|
|
|
assert os.path.exists(disk.mountpoint), disk
|
|
|
|
else:
|
|
|
|
assert os.path.isdir(disk.mountpoint), disk
|
|
|
|
self.assertIsInstance(disk.fstype, str)
|
|
|
|
self.assertIsInstance(disk.opts, str)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def find_mount_point(path):
|
|
|
|
path = os.path.abspath(path)
|
|
|
|
while not os.path.ismount(path):
|
|
|
|
path = os.path.dirname(path)
|
|
|
|
return path
|
|
|
|
|
|
|
|
mount = find_mount_point(__file__)
|
|
|
|
mounts = [x.mountpoint for x in psutil.disk_partitions(all=True)]
|
|
|
|
self.assertIn(mount, mounts)
|
|
|
|
psutil.disk_usage(mount)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_net_connections(self):
|
|
|
|
def check(cons, families, types_):
|
|
|
|
for conn in cons:
|
|
|
|
self.assertIn(conn.family, families, msg=conn)
|
|
|
|
if conn.family != getattr(socket, 'AF_UNIX', object()):
|
|
|
|
self.assertIn(conn.type, types_, msg=conn)
|
|
|
|
|
|
|
|
from psutil._common import conn_tmap
|
|
|
|
for kind, groups in conn_tmap.items():
|
|
|
|
if SUNOS and kind == 'unix':
|
|
|
|
continue
|
|
|
|
families, types_ = groups
|
|
|
|
cons = psutil.net_connections(kind)
|
|
|
|
check(cons, families, types_)
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
def test_net_io_counters(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
def check_ntuple(nt):
|
|
|
|
self.assertEqual(nt[0], nt.bytes_sent)
|
|
|
|
self.assertEqual(nt[1], nt.bytes_recv)
|
|
|
|
self.assertEqual(nt[2], nt.packets_sent)
|
|
|
|
self.assertEqual(nt[3], nt.packets_recv)
|
|
|
|
self.assertEqual(nt[4], nt.errin)
|
|
|
|
self.assertEqual(nt[5], nt.errout)
|
|
|
|
self.assertEqual(nt[6], nt.dropin)
|
|
|
|
self.assertEqual(nt[7], nt.dropout)
|
|
|
|
assert nt.bytes_sent >= 0, nt
|
|
|
|
assert nt.bytes_recv >= 0, nt
|
|
|
|
assert nt.packets_sent >= 0, nt
|
|
|
|
assert nt.packets_recv >= 0, nt
|
|
|
|
assert nt.errin >= 0, nt
|
|
|
|
assert nt.errout >= 0, nt
|
|
|
|
assert nt.dropin >= 0, nt
|
|
|
|
assert nt.dropout >= 0, nt
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
ret = psutil.net_io_counters(pernic=False)
|
2012-09-19 22:20:16 +04:00
|
|
|
check_ntuple(ret)
|
2013-08-23 10:36:57 +04:00
|
|
|
ret = psutil.net_io_counters(pernic=True)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertNotEqual(ret, [])
|
2012-09-19 22:20:16 +04:00
|
|
|
for key in ret:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertTrue(key)
|
2012-09-19 22:20:16 +04:00
|
|
|
check_ntuple(ret[key])
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
@unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'),
|
|
|
|
'/proc/diskstats not available on this linux version')
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_disk_io_counters(self):
|
|
|
|
def check_ntuple(nt):
|
|
|
|
self.assertEqual(nt[0], nt.read_count)
|
|
|
|
self.assertEqual(nt[1], nt.write_count)
|
|
|
|
self.assertEqual(nt[2], nt.read_bytes)
|
|
|
|
self.assertEqual(nt[3], nt.write_bytes)
|
|
|
|
self.assertEqual(nt[4], nt.read_time)
|
|
|
|
self.assertEqual(nt[5], nt.write_time)
|
|
|
|
assert nt.read_count >= 0, nt
|
|
|
|
assert nt.write_count >= 0, nt
|
|
|
|
assert nt.read_bytes >= 0, nt
|
|
|
|
assert nt.write_bytes >= 0, nt
|
|
|
|
assert nt.read_time >= 0, nt
|
|
|
|
assert nt.write_time >= 0, nt
|
|
|
|
|
|
|
|
ret = psutil.disk_io_counters(perdisk=False)
|
|
|
|
check_ntuple(ret)
|
|
|
|
ret = psutil.disk_io_counters(perdisk=True)
|
2013-05-10 02:39:30 +04:00
|
|
|
# make sure there are no duplicates
|
|
|
|
self.assertEqual(len(ret), len(set(ret)))
|
2012-09-19 22:20:16 +04:00
|
|
|
for key in ret:
|
|
|
|
assert key, key
|
|
|
|
check_ntuple(ret[key])
|
2013-05-10 02:39:30 +04:00
|
|
|
if LINUX and key[-1].isdigit():
|
|
|
|
# if 'sda1' is listed 'sda' shouldn't, see:
|
2014-12-23 21:45:15 +03:00
|
|
|
# https://github.com/giampaolo/psutil/issues/338
|
2013-05-10 02:39:30 +04:00
|
|
|
while key[-1].isdigit():
|
|
|
|
key = key[:-1]
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertNotIn(key, ret.keys())
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_users(self):
|
|
|
|
users = psutil.users()
|
|
|
|
self.assertNotEqual(users, [])
|
2012-09-19 22:20:16 +04:00
|
|
|
for user in users:
|
|
|
|
assert user.name, user
|
|
|
|
user.terminal
|
|
|
|
user.host
|
|
|
|
assert user.started > 0.0, user
|
|
|
|
datetime.datetime.fromtimestamp(user.started)
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
|
|
|
|
# ===================================================================
|
|
|
|
# --- psutil.Process class tests
|
|
|
|
# ===================================================================
|
|
|
|
|
|
|
|
class TestProcess(unittest.TestCase):
|
|
|
|
"""Tests for psutil.Process class."""
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
safe_remove(TESTFN)
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
reap_children()
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_pid(self):
|
|
|
|
self.assertEqual(psutil.Process().pid, os.getpid())
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
self.assertEqual(psutil.Process(sproc.pid).pid, sproc.pid)
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_kill(self):
|
|
|
|
sproc = get_test_subprocess(wait=True)
|
|
|
|
test_pid = sproc.pid
|
|
|
|
p = psutil.Process(test_pid)
|
|
|
|
p.kill()
|
|
|
|
p.wait()
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertFalse(psutil.pid_exists(test_pid))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_terminate(self):
|
|
|
|
sproc = get_test_subprocess(wait=True)
|
|
|
|
test_pid = sproc.pid
|
|
|
|
p = psutil.Process(test_pid)
|
|
|
|
p.terminate()
|
|
|
|
p.wait()
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertFalse(psutil.pid_exists(test_pid))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_send_signal(self):
|
|
|
|
if POSIX:
|
|
|
|
sig = signal.SIGKILL
|
|
|
|
else:
|
|
|
|
sig = signal.SIGTERM
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
test_pid = sproc.pid
|
|
|
|
p = psutil.Process(test_pid)
|
|
|
|
p.send_signal(sig)
|
|
|
|
p.wait()
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertFalse(psutil.pid_exists(test_pid))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_wait(self):
|
|
|
|
# check exit code signal
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
p.kill()
|
|
|
|
code = p.wait()
|
2014-12-23 21:45:15 +03:00
|
|
|
if POSIX:
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(code, signal.SIGKILL)
|
|
|
|
else:
|
|
|
|
self.assertEqual(code, 0)
|
|
|
|
self.assertFalse(p.is_running())
|
|
|
|
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
p.terminate()
|
|
|
|
code = p.wait()
|
2014-12-23 21:45:15 +03:00
|
|
|
if POSIX:
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(code, signal.SIGTERM)
|
|
|
|
else:
|
|
|
|
self.assertEqual(code, 0)
|
|
|
|
self.assertFalse(p.is_running())
|
|
|
|
|
|
|
|
# check sys.exit() code
|
|
|
|
code = "import time, sys; time.sleep(0.01); sys.exit(5);"
|
|
|
|
sproc = get_test_subprocess([PYTHON, "-c", code])
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
self.assertEqual(p.wait(), 5)
|
|
|
|
self.assertFalse(p.is_running())
|
|
|
|
|
|
|
|
# Test wait() issued twice.
|
|
|
|
# It is not supposed to raise NSP when the process is gone.
|
|
|
|
# On UNIX this should return None, on Windows it should keep
|
|
|
|
# returning the exit code.
|
|
|
|
sproc = get_test_subprocess([PYTHON, "-c", code])
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
self.assertEqual(p.wait(), 5)
|
|
|
|
self.assertIn(p.wait(), (5, None))
|
|
|
|
|
|
|
|
# test timeout
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
2014-12-23 21:45:15 +03:00
|
|
|
p.name()
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertRaises(psutil.TimeoutExpired, p.wait, 0.01)
|
|
|
|
|
|
|
|
# timeout < 0 not allowed
|
|
|
|
self.assertRaises(ValueError, p.wait, -1)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
# XXX why is this skipped on Windows?
|
|
|
|
@unittest.skipUnless(POSIX, 'skipped on Windows')
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_wait_non_children(self):
|
|
|
|
# test wait() against processes which are not our children
|
|
|
|
code = "import sys;"
|
|
|
|
code += "from subprocess import Popen, PIPE;"
|
2014-12-23 21:45:15 +03:00
|
|
|
code += "cmd = ['%s', '-c', 'import time; time.sleep(2)'];" % PYTHON
|
2012-09-19 22:20:16 +04:00
|
|
|
code += "sp = Popen(cmd, stdout=PIPE);"
|
|
|
|
code += "sys.stdout.write(str(sp.pid));"
|
2014-12-23 21:45:15 +03:00
|
|
|
sproc = get_test_subprocess([PYTHON, "-c", code],
|
|
|
|
stdout=subprocess.PIPE)
|
2012-09-19 22:20:16 +04:00
|
|
|
grandson_pid = int(sproc.stdout.read())
|
|
|
|
grandson_proc = psutil.Process(grandson_pid)
|
|
|
|
try:
|
|
|
|
self.assertRaises(psutil.TimeoutExpired, grandson_proc.wait, 0.01)
|
|
|
|
grandson_proc.kill()
|
|
|
|
ret = grandson_proc.wait()
|
|
|
|
self.assertEqual(ret, None)
|
|
|
|
finally:
|
|
|
|
if grandson_proc.is_running():
|
|
|
|
grandson_proc.kill()
|
|
|
|
grandson_proc.wait()
|
|
|
|
|
|
|
|
def test_wait_timeout_0(self):
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
self.assertRaises(psutil.TimeoutExpired, p.wait, 0)
|
|
|
|
p.kill()
|
|
|
|
stop_at = time.time() + 2
|
|
|
|
while 1:
|
|
|
|
try:
|
|
|
|
code = p.wait(0)
|
|
|
|
except psutil.TimeoutExpired:
|
|
|
|
if time.time() >= stop_at:
|
|
|
|
raise
|
|
|
|
else:
|
|
|
|
break
|
2014-12-23 21:45:15 +03:00
|
|
|
if POSIX:
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(code, signal.SIGKILL)
|
|
|
|
else:
|
|
|
|
self.assertEqual(code, 0)
|
|
|
|
self.assertFalse(p.is_running())
|
|
|
|
|
|
|
|
def test_cpu_percent(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
p.cpu_percent(interval=0.001)
|
|
|
|
p.cpu_percent(interval=0.001)
|
2012-09-19 22:20:16 +04:00
|
|
|
for x in range(100):
|
2014-12-23 21:45:15 +03:00
|
|
|
percent = p.cpu_percent(interval=None)
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIsInstance(percent, float)
|
|
|
|
self.assertGreaterEqual(percent, 0.0)
|
2014-12-23 21:45:15 +03:00
|
|
|
if not POSIX:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertLessEqual(percent, 100.0)
|
2012-09-19 22:20:16 +04:00
|
|
|
else:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertGreaterEqual(percent, 0.0)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_cpu_times(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
times = psutil.Process().cpu_times()
|
2012-09-19 22:20:16 +04:00
|
|
|
assert (times.user > 0.0) or (times.system > 0.0), times
|
|
|
|
# make sure returned values can be pretty printed with strftime
|
|
|
|
time.strftime("%H:%M:%S", time.localtime(times.user))
|
|
|
|
time.strftime("%H:%M:%S", time.localtime(times.system))
|
|
|
|
|
|
|
|
# Test Process.cpu_times() against os.times()
|
|
|
|
# os.times() is broken on Python 2.6
|
|
|
|
# http://bugs.python.org/issue1040026
|
|
|
|
# XXX fails on OSX: not sure if it's for os.times(). We should
|
|
|
|
# try this with Python 2.7 and re-enable the test.
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@unittest.skipUnless(sys.version_info > (2, 6, 1) and not OSX,
|
|
|
|
'os.times() is not reliable on this Python version')
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_cpu_times2(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
user_time, kernel_time = psutil.Process().cpu_times()
|
2012-09-19 22:20:16 +04:00
|
|
|
utime, ktime = os.times()[:2]
|
|
|
|
|
|
|
|
# Use os.times()[:2] as base values to compare our results
|
|
|
|
# using a tolerance of +/- 0.1 seconds.
|
|
|
|
# It will fail if the difference between the values is > 0.1s.
|
|
|
|
if (max([user_time, utime]) - min([user_time, utime])) > 0.1:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.fail("expected: %s, found: %s" % (utime, user_time))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
if (max([kernel_time, ktime]) - min([kernel_time, ktime])) > 0.1:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.fail("expected: %s, found: %s" % (ktime, kernel_time))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_create_time(self):
|
|
|
|
sproc = get_test_subprocess(wait=True)
|
|
|
|
now = time.time()
|
|
|
|
p = psutil.Process(sproc.pid)
|
2014-12-23 21:45:15 +03:00
|
|
|
create_time = p.create_time()
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
# Use time.time() as base value to compare our result using a
|
|
|
|
# tolerance of +/- 1 second.
|
|
|
|
# It will fail if the difference between the values is > 2s.
|
|
|
|
difference = abs(create_time - now)
|
|
|
|
if difference > 2:
|
|
|
|
self.fail("expected: %s, found: %s, difference: %s"
|
|
|
|
% (now, create_time, difference))
|
|
|
|
|
|
|
|
# make sure returned value can be pretty printed with strftime
|
2014-12-23 21:45:15 +03:00
|
|
|
time.strftime("%Y %m %d %H:%M:%S", time.localtime(p.create_time()))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
@unittest.skipIf(WINDOWS, 'Windows only')
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_terminal(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
terminal = psutil.Process().terminal()
|
2013-08-23 10:36:57 +04:00
|
|
|
if sys.stdin.isatty():
|
|
|
|
self.assertEqual(terminal, sh('tty'))
|
|
|
|
else:
|
|
|
|
assert terminal, repr(terminal)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
@unittest.skipUnless(LINUX or BSD or WINDOWS,
|
|
|
|
'not available on this platform')
|
2013-08-23 10:36:57 +04:00
|
|
|
@skip_on_not_implemented(only_if=LINUX)
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_io_counters(self):
|
|
|
|
p = psutil.Process()
|
2012-09-19 22:20:16 +04:00
|
|
|
# test reads
|
2014-12-23 21:45:15 +03:00
|
|
|
io1 = p.io_counters()
|
2012-09-19 22:20:16 +04:00
|
|
|
f = open(PYTHON, 'rb')
|
|
|
|
f.read()
|
|
|
|
f.close()
|
2014-12-23 21:45:15 +03:00
|
|
|
io2 = p.io_counters()
|
2012-09-19 22:20:16 +04:00
|
|
|
if not BSD:
|
|
|
|
assert io2.read_count > io1.read_count, (io1, io2)
|
|
|
|
self.assertEqual(io2.write_count, io1.write_count)
|
|
|
|
assert io2.read_bytes >= io1.read_bytes, (io1, io2)
|
|
|
|
assert io2.write_bytes >= io1.write_bytes, (io1, io2)
|
|
|
|
# test writes
|
2014-12-23 21:45:15 +03:00
|
|
|
io1 = p.io_counters()
|
|
|
|
f = tempfile.TemporaryFile(prefix=TESTFILE_PREFIX)
|
2012-09-19 22:20:16 +04:00
|
|
|
if PY3:
|
|
|
|
f.write(bytes("x" * 1000000, 'ascii'))
|
|
|
|
else:
|
|
|
|
f.write("x" * 1000000)
|
|
|
|
f.close()
|
2014-12-23 21:45:15 +03:00
|
|
|
io2 = p.io_counters()
|
2012-09-19 22:20:16 +04:00
|
|
|
assert io2.write_count >= io1.write_count, (io1, io2)
|
|
|
|
assert io2.write_bytes >= io1.write_bytes, (io1, io2)
|
|
|
|
assert io2.read_count >= io1.read_count, (io1, io2)
|
|
|
|
assert io2.read_bytes >= io1.read_bytes, (io1, io2)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
@unittest.skipUnless(LINUX or (WINDOWS and get_winver() >= WIN_VISTA),
|
2013-08-23 10:36:57 +04:00
|
|
|
'Linux and Windows Vista only')
|
2014-12-23 21:45:15 +03:00
|
|
|
@unittest.skipIf(LINUX and TRAVIS, "unknown failure on travis")
|
|
|
|
def test_ionice(self):
|
2013-05-10 02:39:30 +04:00
|
|
|
if LINUX:
|
|
|
|
from psutil import (IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT,
|
|
|
|
IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE)
|
|
|
|
self.assertEqual(IOPRIO_CLASS_NONE, 0)
|
|
|
|
self.assertEqual(IOPRIO_CLASS_RT, 1)
|
|
|
|
self.assertEqual(IOPRIO_CLASS_BE, 2)
|
|
|
|
self.assertEqual(IOPRIO_CLASS_IDLE, 3)
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
2013-05-10 02:39:30 +04:00
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.ionice(2)
|
|
|
|
ioclass, value = p.ionice()
|
2013-05-10 02:39:30 +04:00
|
|
|
self.assertEqual(ioclass, 2)
|
|
|
|
self.assertEqual(value, 4)
|
|
|
|
#
|
2014-12-23 21:45:15 +03:00
|
|
|
p.ionice(3)
|
|
|
|
ioclass, value = p.ionice()
|
2013-05-10 02:39:30 +04:00
|
|
|
self.assertEqual(ioclass, 3)
|
|
|
|
self.assertEqual(value, 0)
|
|
|
|
#
|
2014-12-23 21:45:15 +03:00
|
|
|
p.ionice(2, 0)
|
|
|
|
ioclass, value = p.ionice()
|
2013-05-10 02:39:30 +04:00
|
|
|
self.assertEqual(ioclass, 2)
|
|
|
|
self.assertEqual(value, 0)
|
2014-12-23 21:45:15 +03:00
|
|
|
p.ionice(2, 7)
|
|
|
|
ioclass, value = p.ionice()
|
2013-05-10 02:39:30 +04:00
|
|
|
self.assertEqual(ioclass, 2)
|
|
|
|
self.assertEqual(value, 7)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertRaises(ValueError, p.ionice, 2, 10)
|
2013-05-10 02:39:30 +04:00
|
|
|
finally:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.ionice(IOPRIO_CLASS_NONE)
|
2013-05-10 02:39:30 +04:00
|
|
|
else:
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
original = p.ionice()
|
2013-05-10 02:39:30 +04:00
|
|
|
try:
|
|
|
|
value = 0 # very low
|
|
|
|
if original == value:
|
|
|
|
value = 1 # low
|
2014-12-23 21:45:15 +03:00
|
|
|
p.ionice(value)
|
|
|
|
self.assertEqual(p.ionice(), value)
|
2013-05-10 02:39:30 +04:00
|
|
|
finally:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.ionice(original)
|
2012-09-19 22:20:16 +04:00
|
|
|
#
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertRaises(ValueError, p.ionice, 3)
|
|
|
|
self.assertRaises(TypeError, p.ionice, 2, 1)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
@unittest.skipUnless(LINUX and RLIMIT_SUPPORT,
|
|
|
|
"only available on Linux >= 2.6.36")
|
|
|
|
def test_rlimit_get(self):
|
|
|
|
import resource
|
|
|
|
p = psutil.Process(os.getpid())
|
|
|
|
names = [x for x in dir(psutil) if x.startswith('RLIMIT')]
|
|
|
|
assert names
|
|
|
|
for name in names:
|
|
|
|
value = getattr(psutil, name)
|
|
|
|
self.assertGreaterEqual(value, 0)
|
|
|
|
if name in dir(resource):
|
|
|
|
self.assertEqual(value, getattr(resource, name))
|
|
|
|
self.assertEqual(p.rlimit(value),
|
|
|
|
resource.getrlimit(value))
|
|
|
|
else:
|
|
|
|
ret = p.rlimit(value)
|
|
|
|
self.assertEqual(len(ret), 2)
|
|
|
|
self.assertGreaterEqual(ret[0], -1)
|
|
|
|
self.assertGreaterEqual(ret[1], -1)
|
|
|
|
|
|
|
|
@unittest.skipUnless(LINUX and RLIMIT_SUPPORT,
|
|
|
|
"only available on Linux >= 2.6.36")
|
|
|
|
def test_rlimit_set(self):
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
p.rlimit(psutil.RLIMIT_NOFILE, (5, 5))
|
|
|
|
self.assertEqual(p.rlimit(psutil.RLIMIT_NOFILE), (5, 5))
|
|
|
|
|
|
|
|
def test_num_threads(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
# on certain platforms such as Linux we might test for exact
|
|
|
|
# thread number, since we always have with 1 thread per process,
|
|
|
|
# but this does not apply across all platforms (OSX, Windows)
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
step1 = p.num_threads()
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
thread = ThreadTask()
|
|
|
|
thread.start()
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
step2 = p.num_threads()
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(step2, step1 + 1)
|
|
|
|
thread.stop()
|
|
|
|
finally:
|
|
|
|
if thread._running:
|
|
|
|
thread.stop()
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@unittest.skipUnless(WINDOWS, 'Windows only')
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_num_handles(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
# a better test is done later into test/_windows.py
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
self.assertGreater(p.num_handles(), 0)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_threads(self):
|
|
|
|
p = psutil.Process()
|
|
|
|
step1 = p.threads()
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
thread = ThreadTask()
|
|
|
|
thread.start()
|
|
|
|
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
step2 = p.threads()
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(len(step2), len(step1) + 1)
|
|
|
|
# on Linux, first thread id is supposed to be this process
|
|
|
|
if LINUX:
|
|
|
|
self.assertEqual(step2[0].id, os.getpid())
|
|
|
|
athread = step2[0]
|
|
|
|
# test named tuple
|
|
|
|
self.assertEqual(athread.id, athread[0])
|
|
|
|
self.assertEqual(athread.user_time, athread[1])
|
|
|
|
self.assertEqual(athread.system_time, athread[2])
|
|
|
|
# test num threads
|
|
|
|
thread.stop()
|
|
|
|
finally:
|
|
|
|
if thread._running:
|
|
|
|
thread.stop()
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_memory_info(self):
|
|
|
|
p = psutil.Process()
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
# step 1 - get a base value to compare our results
|
2014-12-23 21:45:15 +03:00
|
|
|
rss1, vms1 = p.memory_info()
|
|
|
|
percent1 = p.memory_percent()
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertGreater(rss1, 0)
|
|
|
|
self.assertGreater(vms1, 0)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
# step 2 - allocate some memory
|
|
|
|
memarr = [None] * 1500000
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
rss2, vms2 = p.memory_info()
|
|
|
|
percent2 = p.memory_percent()
|
2012-09-19 22:20:16 +04:00
|
|
|
# make sure that the memory usage bumped up
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertGreater(rss2, rss1)
|
|
|
|
self.assertGreaterEqual(vms2, vms1) # vms might be equal
|
|
|
|
self.assertGreater(percent2, percent1)
|
2012-09-19 22:20:16 +04:00
|
|
|
del memarr
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
# def test_memory_info_ex(self):
|
|
|
|
# # tested later in fetch all test suite
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_memory_maps(self):
|
|
|
|
p = psutil.Process()
|
|
|
|
maps = p.memory_maps()
|
2012-09-19 22:20:16 +04:00
|
|
|
paths = [x for x in maps]
|
|
|
|
self.assertEqual(len(paths), len(set(paths)))
|
2014-12-23 21:45:15 +03:00
|
|
|
ext_maps = p.memory_maps(grouped=False)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
for nt in maps:
|
|
|
|
if not nt.path.startswith('['):
|
|
|
|
assert os.path.isabs(nt.path), nt.path
|
|
|
|
if POSIX:
|
|
|
|
assert os.path.exists(nt.path), nt.path
|
|
|
|
else:
|
|
|
|
# XXX - On Windows we have this strange behavior with
|
|
|
|
# 64 bit dlls: they are visible via explorer but cannot
|
|
|
|
# be accessed via os.stat() (wtf?).
|
|
|
|
if '64' not in os.path.basename(nt.path):
|
|
|
|
assert os.path.exists(nt.path), nt.path
|
|
|
|
for nt in ext_maps:
|
|
|
|
for fname in nt._fields:
|
|
|
|
value = getattr(nt, fname)
|
|
|
|
if fname == 'path':
|
|
|
|
continue
|
|
|
|
elif fname in ('addr', 'perms'):
|
|
|
|
assert value, value
|
|
|
|
else:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIsInstance(value, (int, long))
|
2012-09-19 22:20:16 +04:00
|
|
|
assert value >= 0, value
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_memory_percent(self):
|
|
|
|
p = psutil.Process()
|
|
|
|
self.assertGreater(p.memory_percent(), 0.0)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_is_running(self):
|
|
|
|
sproc = get_test_subprocess(wait=True)
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
assert p.is_running()
|
|
|
|
assert p.is_running()
|
|
|
|
p.kill()
|
|
|
|
p.wait()
|
|
|
|
assert not p.is_running()
|
|
|
|
assert not p.is_running()
|
|
|
|
|
|
|
|
def test_exe(self):
|
|
|
|
sproc = get_test_subprocess(wait=True)
|
2014-12-23 21:45:15 +03:00
|
|
|
exe = psutil.Process(sproc.pid).exe()
|
2012-09-19 22:20:16 +04:00
|
|
|
try:
|
|
|
|
self.assertEqual(exe, PYTHON)
|
|
|
|
except AssertionError:
|
2013-05-10 02:39:30 +04:00
|
|
|
if WINDOWS and len(exe) == len(PYTHON):
|
|
|
|
# on Windows we don't care about case sensitivity
|
|
|
|
self.assertEqual(exe.lower(), PYTHON.lower())
|
|
|
|
else:
|
|
|
|
# certain platforms such as BSD are more accurate returning:
|
|
|
|
# "/usr/local/bin/python2.7"
|
|
|
|
# ...instead of:
|
|
|
|
# "/usr/local/bin/python"
|
|
|
|
# We do not want to consider this difference in accuracy
|
|
|
|
# an error.
|
|
|
|
ver = "%s.%s" % (sys.version_info[0], sys.version_info[1])
|
|
|
|
self.assertEqual(exe.replace(ver, ''), PYTHON.replace(ver, ''))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_cmdline(self):
|
2013-08-23 10:36:57 +04:00
|
|
|
cmdline = [PYTHON, "-c", "import time; time.sleep(2)"]
|
|
|
|
sproc = get_test_subprocess(cmdline, wait=True)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(' '.join(psutil.Process(sproc.pid).cmdline()),
|
2013-08-23 10:36:57 +04:00
|
|
|
' '.join(cmdline))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_name(self):
|
|
|
|
sproc = get_test_subprocess(PYTHON, wait=True)
|
2014-12-23 21:45:15 +03:00
|
|
|
name = psutil.Process(sproc.pid).name().lower()
|
2012-09-19 22:20:16 +04:00
|
|
|
pyexe = os.path.basename(os.path.realpath(sys.executable)).lower()
|
2013-05-10 02:39:30 +04:00
|
|
|
assert pyexe.startswith(name), (pyexe, name)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@unittest.skipUnless(POSIX, 'posix only')
|
|
|
|
def test_uids(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
real, effective, saved = p.uids()
|
2013-08-23 10:36:57 +04:00
|
|
|
# os.getuid() refers to "real" uid
|
|
|
|
self.assertEqual(real, os.getuid())
|
|
|
|
# os.geteuid() refers to "effective" uid
|
|
|
|
self.assertEqual(effective, os.geteuid())
|
|
|
|
# no such thing as os.getsuid() ("saved" uid), but starting
|
|
|
|
# from python 2.7 we have os.getresuid()[2]
|
|
|
|
if hasattr(os, "getresuid"):
|
|
|
|
self.assertEqual(saved, os.getresuid()[2])
|
|
|
|
|
|
|
|
@unittest.skipUnless(POSIX, 'posix only')
|
|
|
|
def test_gids(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
real, effective, saved = p.gids()
|
2013-08-23 10:36:57 +04:00
|
|
|
# os.getuid() refers to "real" uid
|
|
|
|
self.assertEqual(real, os.getgid())
|
|
|
|
# os.geteuid() refers to "effective" uid
|
|
|
|
self.assertEqual(effective, os.getegid())
|
|
|
|
# no such thing as os.getsuid() ("saved" uid), but starting
|
|
|
|
# from python 2.7 we have os.getresgid()[2]
|
|
|
|
if hasattr(os, "getresuid"):
|
|
|
|
self.assertEqual(saved, os.getresgid()[2])
|
|
|
|
|
|
|
|
def test_nice(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
self.assertRaises(TypeError, p.nice, "str")
|
|
|
|
if WINDOWS:
|
2013-08-23 10:36:57 +04:00
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.nice(), psutil.NORMAL_PRIORITY_CLASS)
|
|
|
|
p.nice(psutil.HIGH_PRIORITY_CLASS)
|
|
|
|
self.assertEqual(p.nice(), psutil.HIGH_PRIORITY_CLASS)
|
|
|
|
p.nice(psutil.NORMAL_PRIORITY_CLASS)
|
|
|
|
self.assertEqual(p.nice(), psutil.NORMAL_PRIORITY_CLASS)
|
2013-08-23 10:36:57 +04:00
|
|
|
finally:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.nice(psutil.NORMAL_PRIORITY_CLASS)
|
2013-08-23 10:36:57 +04:00
|
|
|
else:
|
2012-09-19 22:20:16 +04:00
|
|
|
try:
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
first_nice = p.nice()
|
|
|
|
p.nice(1)
|
|
|
|
self.assertEqual(p.nice(), 1)
|
|
|
|
# going back to previous nice value raises
|
|
|
|
# AccessDenied on OSX
|
2012-09-19 22:20:16 +04:00
|
|
|
if not OSX:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.nice(0)
|
|
|
|
self.assertEqual(p.nice(), 0)
|
2012-09-19 22:20:16 +04:00
|
|
|
except psutil.AccessDenied:
|
|
|
|
pass
|
|
|
|
finally:
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.nice(first_nice)
|
2012-09-19 22:20:16 +04:00
|
|
|
except psutil.AccessDenied:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def test_status(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
self.assertEqual(p.status(), psutil.STATUS_RUNNING)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_username(self):
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
if POSIX:
|
|
|
|
import pwd
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.username(), pwd.getpwuid(os.getuid()).pw_name)
|
2013-08-23 10:36:57 +04:00
|
|
|
elif WINDOWS and 'USERNAME' in os.environ:
|
2012-09-19 22:20:16 +04:00
|
|
|
expected_username = os.environ['USERNAME']
|
|
|
|
expected_domain = os.environ['USERDOMAIN']
|
2014-12-23 21:45:15 +03:00
|
|
|
domain, username = p.username().split('\\')
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(domain, expected_domain)
|
|
|
|
self.assertEqual(username, expected_username)
|
|
|
|
else:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.username()
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_cwd(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
sproc = get_test_subprocess(wait=True)
|
|
|
|
p = psutil.Process(sproc.pid)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.cwd(), os.getcwd())
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_cwd_2(self):
|
2013-08-23 10:36:57 +04:00
|
|
|
cmd = [PYTHON, "-c", "import os, time; os.chdir('..'); time.sleep(2)"]
|
2012-09-19 22:20:16 +04:00
|
|
|
sproc = get_test_subprocess(cmd, wait=True)
|
|
|
|
p = psutil.Process(sproc.pid)
|
2014-12-23 21:45:15 +03:00
|
|
|
call_until(p.cwd, "ret == os.path.dirname(os.getcwd())")
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
@unittest.skipUnless(WINDOWS or LINUX, 'not available on this platform')
|
|
|
|
@unittest.skipIf(LINUX and TRAVIS, "unknown failure on travis")
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_cpu_affinity(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
initial = p.cpu_affinity()
|
|
|
|
if hasattr(os, "sched_getaffinity"):
|
|
|
|
self.assertEqual(initial, list(os.sched_getaffinity(p.pid)))
|
2012-09-19 22:20:16 +04:00
|
|
|
all_cpus = list(range(len(psutil.cpu_percent(percpu=True))))
|
2014-12-23 21:45:15 +03:00
|
|
|
# setting on travis doesn't seem to work (always return all
|
|
|
|
# CPUs on get):
|
|
|
|
# AssertionError: Lists differ: [0, 1, 2, 3, 4, 5, 6, ... != [0]
|
2012-09-19 22:20:16 +04:00
|
|
|
for n in all_cpus:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.cpu_affinity([n])
|
|
|
|
self.assertEqual(p.cpu_affinity(), [n])
|
|
|
|
if hasattr(os, "sched_getaffinity"):
|
|
|
|
self.assertEqual(p.cpu_affinity(),
|
|
|
|
list(os.sched_getaffinity(p.pid)))
|
2012-09-19 22:20:16 +04:00
|
|
|
#
|
2014-12-23 21:45:15 +03:00
|
|
|
p.cpu_affinity(all_cpus)
|
|
|
|
self.assertEqual(p.cpu_affinity(), all_cpus)
|
|
|
|
if hasattr(os, "sched_getaffinity"):
|
|
|
|
self.assertEqual(p.cpu_affinity(),
|
|
|
|
list(os.sched_getaffinity(p.pid)))
|
2012-09-19 22:20:16 +04:00
|
|
|
#
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertRaises(TypeError, p.cpu_affinity, 1)
|
|
|
|
p.cpu_affinity(initial)
|
2012-09-19 22:20:16 +04:00
|
|
|
invalid_cpu = [len(psutil.cpu_times(percpu=True)) + 10]
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertRaises(ValueError, p.cpu_affinity, invalid_cpu)
|
|
|
|
self.assertRaises(ValueError, p.cpu_affinity, range(10000, 11000))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_open_files(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
# current process
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
files = p.open_files()
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertFalse(TESTFN in files)
|
|
|
|
f = open(TESTFN, 'w')
|
2014-12-23 21:45:15 +03:00
|
|
|
call_until(p.open_files, "len(ret) != %i" % len(files))
|
|
|
|
filenames = [x.path for x in p.open_files()]
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertIn(TESTFN, filenames)
|
|
|
|
f.close()
|
|
|
|
for file in filenames:
|
|
|
|
assert os.path.isfile(file), file
|
|
|
|
|
|
|
|
# another process
|
2013-08-23 10:36:57 +04:00
|
|
|
cmdline = "import time; f = open(r'%s', 'r'); time.sleep(2);" % TESTFN
|
2012-09-19 22:20:16 +04:00
|
|
|
sproc = get_test_subprocess([PYTHON, "-c", cmdline], wait=True)
|
|
|
|
p = psutil.Process(sproc.pid)
|
2014-12-23 21:45:15 +03:00
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
for x in range(100):
|
2014-12-23 21:45:15 +03:00
|
|
|
filenames = [x.path for x in p.open_files()]
|
2012-09-19 22:20:16 +04:00
|
|
|
if TESTFN in filenames:
|
|
|
|
break
|
|
|
|
time.sleep(.01)
|
|
|
|
else:
|
|
|
|
self.assertIn(TESTFN, filenames)
|
|
|
|
for file in filenames:
|
|
|
|
assert os.path.isfile(file), file
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_open_files2(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
# test fd and path fields
|
|
|
|
fileobj = open(TESTFN, 'w')
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
for path, fd in p.open_files():
|
2012-09-19 22:20:16 +04:00
|
|
|
if path == fileobj.name or fd == fileobj.fileno():
|
|
|
|
break
|
|
|
|
else:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.fail("no file found; files=%s" % repr(p.open_files()))
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(path, fileobj.name)
|
|
|
|
if WINDOWS:
|
|
|
|
self.assertEqual(fd, -1)
|
|
|
|
else:
|
|
|
|
self.assertEqual(fd, fileobj.fileno())
|
|
|
|
# test positions
|
2014-12-23 21:45:15 +03:00
|
|
|
ntuple = p.open_files()[0]
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(ntuple[0], ntuple.path)
|
|
|
|
self.assertEqual(ntuple[1], ntuple.fd)
|
|
|
|
# test file is gone
|
|
|
|
fileobj.close()
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertTrue(fileobj.name not in p.open_files())
|
|
|
|
|
|
|
|
def compare_proc_sys_cons(self, pid, proc_cons):
|
|
|
|
from psutil._common import pconn
|
|
|
|
sys_cons = []
|
|
|
|
for c in psutil.net_connections(kind='all'):
|
|
|
|
if c.pid == pid:
|
|
|
|
sys_cons.append(pconn(*c[:-1]))
|
|
|
|
if BSD:
|
|
|
|
# on BSD all fds are set to -1
|
|
|
|
proc_cons = [pconn(*[-1] + list(x[1:])) for x in proc_cons]
|
|
|
|
self.assertEqual(sorted(proc_cons), sorted(sys_cons))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
def test_connection_constants(self):
|
|
|
|
ints = []
|
|
|
|
strs = []
|
|
|
|
for name in dir(psutil):
|
|
|
|
if name.startswith('CONN_'):
|
|
|
|
num = getattr(psutil, name)
|
|
|
|
str_ = str(num)
|
|
|
|
assert str_.isupper(), str_
|
|
|
|
assert str_ not in strs, str_
|
|
|
|
assert num not in ints, num
|
|
|
|
ints.append(num)
|
|
|
|
strs.append(str_)
|
|
|
|
if SUNOS:
|
|
|
|
psutil.CONN_IDLE
|
|
|
|
psutil.CONN_BOUND
|
|
|
|
if WINDOWS:
|
|
|
|
psutil.CONN_DELETE_TCB
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_connections(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
arg = "import socket, time;" \
|
|
|
|
"s = socket.socket();" \
|
|
|
|
"s.bind(('127.0.0.1', 0));" \
|
|
|
|
"s.listen(1);" \
|
|
|
|
"conn, addr = s.accept();" \
|
2013-08-23 10:36:57 +04:00
|
|
|
"time.sleep(2);"
|
2012-09-19 22:20:16 +04:00
|
|
|
sproc = get_test_subprocess([PYTHON, "-c", arg])
|
|
|
|
p = psutil.Process(sproc.pid)
|
2014-12-23 21:45:15 +03:00
|
|
|
cons = call_until(p.connections, "len(ret) != 0")
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(len(cons), 1)
|
|
|
|
con = cons[0]
|
2014-12-23 21:45:15 +03:00
|
|
|
check_connection(con)
|
|
|
|
self.assertEqual(con.family, AF_INET)
|
|
|
|
self.assertEqual(con.type, SOCK_STREAM)
|
|
|
|
self.assertEqual(con.status, psutil.CONN_LISTEN, con.status)
|
|
|
|
self.assertEqual(con.laddr[0], '127.0.0.1')
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertEqual(con.raddr, ())
|
2012-09-19 22:20:16 +04:00
|
|
|
# test positions
|
|
|
|
self.assertEqual(con[0], con.fd)
|
|
|
|
self.assertEqual(con[1], con.family)
|
|
|
|
self.assertEqual(con[2], con.type)
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertEqual(con[3], con.laddr)
|
|
|
|
self.assertEqual(con[4], con.raddr)
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(con[5], con.status)
|
|
|
|
# test kind arg
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertRaises(ValueError, p.connections, 'foo')
|
|
|
|
# compare against system-wide connections
|
|
|
|
self.compare_proc_sys_cons(p.pid, cons)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@unittest.skipUnless(supports_ipv6(), 'IPv6 is not supported')
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_connections_ipv6(self):
|
|
|
|
s = socket.socket(AF_INET6, SOCK_STREAM)
|
|
|
|
self.addCleanup(s.close)
|
2012-09-19 22:20:16 +04:00
|
|
|
s.bind(('::1', 0))
|
|
|
|
s.listen(1)
|
2014-12-23 21:45:15 +03:00
|
|
|
cons = psutil.Process().connections()
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertEqual(len(cons), 1)
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertEqual(cons[0].laddr[0], '::1')
|
2014-12-23 21:45:15 +03:00
|
|
|
self.compare_proc_sys_cons(os.getpid(), cons)
|
|
|
|
|
|
|
|
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'),
|
|
|
|
'AF_UNIX is not supported')
|
|
|
|
def test_connections_unix(self):
|
|
|
|
def check(type):
|
|
|
|
safe_remove(TESTFN)
|
|
|
|
sock = socket.socket(AF_UNIX, type)
|
|
|
|
try:
|
|
|
|
sock.bind(TESTFN)
|
|
|
|
cons = psutil.Process().connections(kind='unix')
|
|
|
|
conn = cons[0]
|
|
|
|
check_connection(conn)
|
|
|
|
if conn.fd != -1: # != sunos and windows
|
|
|
|
self.assertEqual(conn.fd, sock.fileno())
|
|
|
|
self.assertEqual(conn.family, AF_UNIX)
|
|
|
|
self.assertEqual(conn.type, type)
|
|
|
|
self.assertEqual(conn.laddr, TESTFN)
|
|
|
|
if not SUNOS:
|
|
|
|
# XXX Solaris can't retrieve system-wide UNIX
|
|
|
|
# sockets.
|
|
|
|
self.compare_proc_sys_cons(os.getpid(), cons)
|
|
|
|
finally:
|
|
|
|
sock.close()
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
check(SOCK_STREAM)
|
|
|
|
check(SOCK_DGRAM)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@unittest.skipUnless(hasattr(socket, "fromfd"),
|
|
|
|
'socket.fromfd() is not availble')
|
|
|
|
@unittest.skipIf(WINDOWS or SUNOS,
|
2014-12-23 21:45:15 +03:00
|
|
|
'connection fd not available on this platform')
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_connection_fromfd(self):
|
|
|
|
sock = socket.socket()
|
|
|
|
sock.bind(('localhost', 0))
|
|
|
|
sock.listen(1)
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
for conn in p.connections():
|
2012-09-19 22:20:16 +04:00
|
|
|
if conn.fd == sock.fileno():
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
sock.close()
|
|
|
|
self.fail("couldn't find socket fd")
|
|
|
|
dupsock = socket.fromfd(conn.fd, conn.family, conn.type)
|
|
|
|
try:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertEqual(dupsock.getsockname(), conn.laddr)
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertNotEqual(sock.fileno(), dupsock.fileno())
|
|
|
|
finally:
|
|
|
|
sock.close()
|
|
|
|
dupsock.close()
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_connections_all(self):
|
|
|
|
tcp_template = textwrap.dedent("""
|
|
|
|
import socket
|
|
|
|
s = socket.socket($family, socket.SOCK_STREAM)
|
|
|
|
s.bind(('$addr', 0))
|
|
|
|
s.listen(1)
|
|
|
|
conn, addr = s.accept()
|
|
|
|
""")
|
|
|
|
|
|
|
|
udp_template = textwrap.dedent("""
|
|
|
|
import socket, time
|
|
|
|
s = socket.socket($family, socket.SOCK_DGRAM)
|
|
|
|
s.bind(('$addr', 0))
|
|
|
|
time.sleep(2)
|
|
|
|
""")
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
from string import Template
|
2014-12-23 21:45:15 +03:00
|
|
|
tcp4_template = Template(tcp_template).substitute(
|
|
|
|
family=int(AF_INET), addr="127.0.0.1")
|
|
|
|
udp4_template = Template(udp_template).substitute(
|
|
|
|
family=int(AF_INET), addr="127.0.0.1")
|
|
|
|
tcp6_template = Template(tcp_template).substitute(
|
|
|
|
family=int(AF_INET6), addr="::1")
|
|
|
|
udp6_template = Template(udp_template).substitute(
|
|
|
|
family=int(AF_INET6), addr="::1")
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
# launch various subprocess instantiating a socket of various
|
|
|
|
# families and types to enrich psutil results
|
2014-12-23 21:45:15 +03:00
|
|
|
tcp4_proc = pyrun(tcp4_template)
|
|
|
|
udp4_proc = pyrun(udp4_template)
|
2012-09-19 22:20:16 +04:00
|
|
|
if supports_ipv6():
|
2014-12-23 21:45:15 +03:00
|
|
|
tcp6_proc = pyrun(tcp6_template)
|
|
|
|
udp6_proc = pyrun(udp6_template)
|
2012-09-19 22:20:16 +04:00
|
|
|
else:
|
|
|
|
tcp6_proc = None
|
|
|
|
udp6_proc = None
|
|
|
|
|
|
|
|
# check matches against subprocesses just created
|
|
|
|
all_kinds = ("all", "inet", "inet4", "inet6", "tcp", "tcp4", "tcp6",
|
|
|
|
"udp", "udp4", "udp6")
|
2014-12-23 21:45:15 +03:00
|
|
|
|
|
|
|
def check_conn(proc, conn, family, type, laddr, raddr, status, kinds):
|
|
|
|
self.assertEqual(conn.family, family)
|
|
|
|
self.assertEqual(conn.type, type)
|
|
|
|
self.assertIn(conn.laddr[0], laddr)
|
|
|
|
self.assertEqual(conn.raddr, raddr)
|
|
|
|
self.assertEqual(conn.status, status)
|
|
|
|
for kind in all_kinds:
|
|
|
|
cons = proc.connections(kind=kind)
|
|
|
|
if kind in kinds:
|
|
|
|
self.assertNotEqual(cons, [])
|
|
|
|
else:
|
|
|
|
self.assertEqual(cons, [])
|
|
|
|
|
|
|
|
for p in psutil.Process().children():
|
|
|
|
cons = p.connections()
|
|
|
|
for conn in cons:
|
2012-09-19 22:20:16 +04:00
|
|
|
# TCP v4
|
|
|
|
if p.pid == tcp4_proc.pid:
|
2014-12-23 21:45:15 +03:00
|
|
|
check_conn(p, conn, AF_INET, SOCK_STREAM, "127.0.0.1", (),
|
|
|
|
psutil.CONN_LISTEN,
|
|
|
|
("all", "inet", "inet4", "tcp", "tcp4"))
|
2012-09-19 22:20:16 +04:00
|
|
|
# UDP v4
|
|
|
|
elif p.pid == udp4_proc.pid:
|
2014-12-23 21:45:15 +03:00
|
|
|
check_conn(p, conn, AF_INET, SOCK_DGRAM, "127.0.0.1", (),
|
|
|
|
psutil.CONN_NONE,
|
|
|
|
("all", "inet", "inet4", "udp", "udp4"))
|
2012-09-19 22:20:16 +04:00
|
|
|
# TCP v6
|
|
|
|
elif p.pid == getattr(tcp6_proc, "pid", None):
|
2014-12-23 21:45:15 +03:00
|
|
|
check_conn(p, conn, AF_INET6, SOCK_STREAM, ("::", "::1"),
|
|
|
|
(), psutil.CONN_LISTEN,
|
|
|
|
("all", "inet", "inet6", "tcp", "tcp6"))
|
2012-09-19 22:20:16 +04:00
|
|
|
# UDP v6
|
|
|
|
elif p.pid == getattr(udp6_proc, "pid", None):
|
2014-12-23 21:45:15 +03:00
|
|
|
check_conn(p, conn, AF_INET6, SOCK_DGRAM, ("::", "::1"),
|
|
|
|
(), psutil.CONN_NONE,
|
|
|
|
("all", "inet", "inet6", "udp", "udp6"))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@unittest.skipUnless(POSIX, 'posix only')
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_num_fds(self):
|
|
|
|
p = psutil.Process()
|
|
|
|
start = p.num_fds()
|
2012-09-19 22:20:16 +04:00
|
|
|
file = open(TESTFN, 'w')
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.num_fds(), start + 1)
|
2012-09-19 22:20:16 +04:00
|
|
|
sock = socket.socket()
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.num_fds(), start + 2)
|
2012-09-19 22:20:16 +04:00
|
|
|
file.close()
|
|
|
|
sock.close()
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.num_fds(), start)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
@skip_on_not_implemented(only_if=LINUX)
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_num_ctx_switches(self):
|
|
|
|
p = psutil.Process()
|
|
|
|
before = sum(p.num_ctx_switches())
|
2013-05-10 02:39:30 +04:00
|
|
|
for x in range(500000):
|
2014-12-23 21:45:15 +03:00
|
|
|
after = sum(p.num_ctx_switches())
|
2012-09-19 22:20:16 +04:00
|
|
|
if after > before:
|
|
|
|
return
|
|
|
|
self.fail("num ctx switches still the same after 50.000 iterations")
|
|
|
|
|
|
|
|
def test_parent_ppid(self):
|
|
|
|
this_parent = os.getpid()
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.ppid(), this_parent)
|
|
|
|
self.assertEqual(p.parent().pid, this_parent)
|
2012-09-19 22:20:16 +04:00
|
|
|
# no other process is supposed to have us as parent
|
|
|
|
for p in psutil.process_iter():
|
|
|
|
if p.pid == sproc.pid:
|
|
|
|
continue
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertTrue(p.ppid() != this_parent)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_children(self):
|
|
|
|
p = psutil.Process()
|
|
|
|
self.assertEqual(p.children(), [])
|
|
|
|
self.assertEqual(p.children(recursive=True), [])
|
2012-09-19 22:20:16 +04:00
|
|
|
sproc = get_test_subprocess()
|
2014-12-23 21:45:15 +03:00
|
|
|
children1 = p.children()
|
|
|
|
children2 = p.children(recursive=True)
|
2012-09-19 22:20:16 +04:00
|
|
|
for children in (children1, children2):
|
|
|
|
self.assertEqual(len(children), 1)
|
|
|
|
self.assertEqual(children[0].pid, sproc.pid)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(children[0].ppid(), os.getpid())
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_children_recursive(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
# here we create a subprocess which creates another one as in:
|
|
|
|
# A (parent) -> B (child) -> C (grandchild)
|
2014-12-23 21:45:15 +03:00
|
|
|
s = "import subprocess, os, sys, time;"
|
2012-09-19 22:20:16 +04:00
|
|
|
s += "PYTHON = os.path.realpath(sys.executable);"
|
2013-08-23 10:36:57 +04:00
|
|
|
s += "cmd = [PYTHON, '-c', 'import time; time.sleep(2);'];"
|
2012-09-19 22:20:16 +04:00
|
|
|
s += "subprocess.Popen(cmd);"
|
2013-08-23 10:36:57 +04:00
|
|
|
s += "time.sleep(2);"
|
2012-09-19 22:20:16 +04:00
|
|
|
get_test_subprocess(cmd=[PYTHON, "-c", s])
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
|
|
|
self.assertEqual(len(p.children(recursive=False)), 1)
|
2012-09-19 22:20:16 +04:00
|
|
|
# give the grandchild some time to start
|
|
|
|
stop_at = time.time() + 1.5
|
|
|
|
while time.time() < stop_at:
|
2014-12-23 21:45:15 +03:00
|
|
|
children = p.children(recursive=True)
|
2012-09-19 22:20:16 +04:00
|
|
|
if len(children) > 1:
|
|
|
|
break
|
|
|
|
self.assertEqual(len(children), 2)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(children[0].ppid(), os.getpid())
|
|
|
|
self.assertEqual(children[1].ppid(), children[0].pid)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_children_duplicates(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
# find the process which has the highest number of children
|
|
|
|
from psutil._compat import defaultdict
|
|
|
|
table = defaultdict(int)
|
|
|
|
for p in psutil.process_iter():
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
table[p.ppid()] += 1
|
2012-09-19 22:20:16 +04:00
|
|
|
except psutil.Error:
|
|
|
|
pass
|
|
|
|
# this is the one, now let's make sure there are no duplicates
|
2013-05-10 02:39:30 +04:00
|
|
|
pid = sorted(table.items(), key=lambda x: x[1])[-1][0]
|
2012-09-19 22:20:16 +04:00
|
|
|
p = psutil.Process(pid)
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
c = p.children(recursive=True)
|
2012-09-19 22:20:16 +04:00
|
|
|
except psutil.AccessDenied: # windows
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
self.assertEqual(len(c), len(set(c)))
|
|
|
|
|
|
|
|
def test_suspend_resume(self):
|
|
|
|
sproc = get_test_subprocess(wait=True)
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
p.suspend()
|
|
|
|
for x in range(100):
|
2014-12-23 21:45:15 +03:00
|
|
|
if p.status() == psutil.STATUS_STOPPED:
|
2012-09-19 22:20:16 +04:00
|
|
|
break
|
|
|
|
time.sleep(0.01)
|
|
|
|
p.resume()
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertNotEqual(p.status(), psutil.STATUS_STOPPED)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_invalid_pid(self):
|
|
|
|
self.assertRaises(TypeError, psutil.Process, "1")
|
2013-05-10 02:39:30 +04:00
|
|
|
self.assertRaises(ValueError, psutil.Process, -1)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_as_dict(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
p = psutil.Process()
|
2012-09-19 22:20:16 +04:00
|
|
|
d = p.as_dict(attrs=['exe', 'name'])
|
|
|
|
self.assertEqual(sorted(d.keys()), ['exe', 'name'])
|
2014-12-23 21:45:15 +03:00
|
|
|
|
|
|
|
p = psutil.Process(min(psutil.pids()))
|
|
|
|
d = p.as_dict(attrs=['connections'], ad_value='foo')
|
2012-09-19 22:20:16 +04:00
|
|
|
if not isinstance(d['connections'], list):
|
|
|
|
self.assertEqual(d['connections'], 'foo')
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_halfway_terminated_process(self):
|
2012-09-19 22:20:16 +04:00
|
|
|
# Test that NoSuchProcess exception gets raised in case the
|
|
|
|
# process dies after we create the Process object.
|
|
|
|
# Example:
|
|
|
|
# >>> proc = Process(1234)
|
2014-12-23 21:45:15 +03:00
|
|
|
# >>> time.sleep(2) # time-consuming task, process dies in meantime
|
|
|
|
# >>> proc.name()
|
2012-09-19 22:20:16 +04:00
|
|
|
# Refers to Issue #15
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
p.kill()
|
|
|
|
p.wait()
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
excluded_names = ['pid', 'is_running', 'wait', 'create_time']
|
|
|
|
if LINUX and not RLIMIT_SUPPORT:
|
|
|
|
excluded_names.append('rlimit')
|
2012-09-19 22:20:16 +04:00
|
|
|
for name in dir(p):
|
2014-12-23 21:45:15 +03:00
|
|
|
if (name.startswith('_')
|
|
|
|
or name.startswith('get') # deprecated APIs
|
|
|
|
or name.startswith('set') # deprecated APIs
|
|
|
|
or name in excluded_names):
|
2012-09-19 22:20:16 +04:00
|
|
|
continue
|
|
|
|
try:
|
|
|
|
meth = getattr(p, name)
|
2014-12-23 21:45:15 +03:00
|
|
|
# get/set methods
|
|
|
|
if name == 'nice':
|
|
|
|
if POSIX:
|
|
|
|
meth(1)
|
|
|
|
else:
|
|
|
|
meth(psutil.NORMAL_PRIORITY_CLASS)
|
|
|
|
elif name == 'ionice':
|
|
|
|
meth()
|
|
|
|
meth(2)
|
|
|
|
elif name == 'rlimit':
|
|
|
|
meth(psutil.RLIMIT_NOFILE)
|
|
|
|
meth(psutil.RLIMIT_NOFILE, (5, 5))
|
|
|
|
elif name == 'cpu_affinity':
|
|
|
|
meth()
|
|
|
|
meth([0])
|
|
|
|
elif name == 'send_signal':
|
|
|
|
meth(signal.SIGTERM)
|
|
|
|
else:
|
2012-09-19 22:20:16 +04:00
|
|
|
meth()
|
|
|
|
except psutil.NoSuchProcess:
|
|
|
|
pass
|
2013-08-23 10:36:57 +04:00
|
|
|
except NotImplementedError:
|
|
|
|
pass
|
2012-09-19 22:20:16 +04:00
|
|
|
else:
|
|
|
|
self.fail("NoSuchProcess exception not raised for %r" % name)
|
|
|
|
|
|
|
|
self.assertFalse(p.is_running())
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
@unittest.skipUnless(POSIX, 'posix only')
|
|
|
|
def test_zombie_process(self):
|
|
|
|
# Note: in this test we'll be creating two sub processes.
|
|
|
|
# Both of them are supposed to be freed / killed by
|
|
|
|
# reap_children() as they are attributable to 'us'
|
|
|
|
# (os.getpid()) via children(recursive=True).
|
|
|
|
src = textwrap.dedent("""\
|
|
|
|
import os, sys, time, socket
|
|
|
|
child_pid = os.fork()
|
|
|
|
if child_pid > 0:
|
|
|
|
time.sleep(3000)
|
|
|
|
else:
|
|
|
|
# this is the zombie process
|
|
|
|
s = socket.socket(socket.AF_UNIX)
|
|
|
|
s.connect('%s')
|
|
|
|
if sys.version_info < (3, ):
|
|
|
|
pid = str(os.getpid())
|
|
|
|
else:
|
|
|
|
pid = bytes(str(os.getpid()), 'ascii')
|
|
|
|
s.sendall(pid)
|
|
|
|
s.close()
|
|
|
|
""" % TESTFN)
|
|
|
|
sock = None
|
|
|
|
try:
|
|
|
|
sock = socket.socket(socket.AF_UNIX)
|
|
|
|
sock.settimeout(GLOBAL_TIMEOUT)
|
|
|
|
sock.bind(TESTFN)
|
|
|
|
sock.listen(1)
|
|
|
|
pyrun(src)
|
|
|
|
conn, _ = sock.accept()
|
|
|
|
select.select([conn.fileno()], [], [], GLOBAL_TIMEOUT)
|
|
|
|
zpid = int(conn.recv(1024))
|
|
|
|
zproc = psutil.Process(zpid)
|
|
|
|
# Make sure we can re-instantiate the process after its
|
|
|
|
# status changed to zombie and at least be able to
|
|
|
|
# query its status.
|
|
|
|
# XXX should we also assume ppid should be querable?
|
|
|
|
call_until(lambda: zproc.status(), "ret == psutil.STATUS_ZOMBIE")
|
|
|
|
self.assertTrue(psutil.pid_exists(zpid))
|
|
|
|
zproc = psutil.Process(zpid)
|
|
|
|
descendants = [x.pid for x in psutil.Process().children(
|
|
|
|
recursive=True)]
|
|
|
|
self.assertIn(zpid, descendants)
|
|
|
|
finally:
|
|
|
|
if sock is not None:
|
|
|
|
sock.close()
|
|
|
|
reap_children(search_all=True)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_pid_0(self):
|
|
|
|
# Process(0) is supposed to work on all platforms except Linux
|
2014-12-23 21:45:15 +03:00
|
|
|
if 0 not in psutil.pids():
|
|
|
|
self.assertRaises(psutil.NoSuchProcess, psutil.Process, 0)
|
|
|
|
return
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
p = psutil.Process(0)
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertTrue(p.name())
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
if POSIX:
|
2013-08-23 10:36:57 +04:00
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.uids().real, 0)
|
|
|
|
self.assertEqual(p.gids().real, 0)
|
2013-08-23 10:36:57 +04:00
|
|
|
except psutil.AccessDenied:
|
|
|
|
pass
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertIn(p.ppid(), (0, 1))
|
|
|
|
# self.assertEqual(p.exe(), "")
|
|
|
|
p.cmdline()
|
2012-09-19 22:20:16 +04:00
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.num_threads()
|
2012-09-19 22:20:16 +04:00
|
|
|
except psutil.AccessDenied:
|
|
|
|
pass
|
|
|
|
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.memory_info()
|
2012-09-19 22:20:16 +04:00
|
|
|
except psutil.AccessDenied:
|
|
|
|
pass
|
|
|
|
|
|
|
|
# username property
|
2013-08-23 10:36:57 +04:00
|
|
|
try:
|
|
|
|
if POSIX:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.username(), 'root')
|
2013-08-23 10:36:57 +04:00
|
|
|
elif WINDOWS:
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(p.username(), 'NT AUTHORITY\\SYSTEM')
|
2013-08-23 10:36:57 +04:00
|
|
|
else:
|
2014-12-23 21:45:15 +03:00
|
|
|
p.username()
|
2013-08-23 10:36:57 +04:00
|
|
|
except psutil.AccessDenied:
|
|
|
|
pass
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertIn(0, psutil.pids())
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertTrue(psutil.pid_exists(0))
|
|
|
|
|
|
|
|
def test_Popen(self):
|
|
|
|
# Popen class test
|
|
|
|
# XXX this test causes a ResourceWarning on Python 3 because
|
|
|
|
# psutil.__subproc instance doesn't get propertly freed.
|
|
|
|
# Not sure what to do though.
|
2013-08-23 10:36:57 +04:00
|
|
|
cmd = [PYTHON, "-c", "import time; time.sleep(2);"]
|
2014-12-23 21:45:15 +03:00
|
|
|
proc = psutil.Popen(cmd, stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.PIPE)
|
2012-09-19 22:20:16 +04:00
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
proc.name()
|
2012-09-19 22:20:16 +04:00
|
|
|
proc.stdin
|
|
|
|
self.assertTrue(hasattr(proc, 'name'))
|
|
|
|
self.assertTrue(hasattr(proc, 'stdin'))
|
|
|
|
self.assertRaises(AttributeError, getattr, proc, 'foo')
|
|
|
|
finally:
|
|
|
|
proc.kill()
|
|
|
|
proc.wait()
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertIsNotNone(proc.returncode)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
# ===================================================================
|
|
|
|
# --- Featch all processes test
|
|
|
|
# ===================================================================
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
class TestFetchAllProcesses(unittest.TestCase):
|
2014-12-23 21:45:15 +03:00
|
|
|
"""Test which iterates over all running processes and performs
|
|
|
|
some sanity checks against Process API's returned values.
|
|
|
|
"""
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
if POSIX:
|
|
|
|
import pwd
|
|
|
|
pall = pwd.getpwall()
|
|
|
|
self._uids = set([x.pw_uid for x in pall])
|
|
|
|
self._usernames = set([x.pw_name for x in pall])
|
|
|
|
|
|
|
|
def test_fetch_all(self):
|
|
|
|
valid_procs = 0
|
2014-12-23 21:45:15 +03:00
|
|
|
excluded_names = set([
|
|
|
|
'send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait',
|
|
|
|
'as_dict', 'cpu_percent', 'parent', 'children', 'pid'])
|
|
|
|
if LINUX and not RLIMIT_SUPPORT:
|
|
|
|
excluded_names.add('rlimit')
|
2012-09-19 22:20:16 +04:00
|
|
|
attrs = []
|
|
|
|
for name in dir(psutil.Process):
|
|
|
|
if name.startswith("_"):
|
|
|
|
continue
|
2014-12-23 21:45:15 +03:00
|
|
|
if name.startswith("get"):
|
|
|
|
# deprecated APIs
|
|
|
|
continue
|
2012-09-19 22:20:16 +04:00
|
|
|
if name.startswith("set_"):
|
|
|
|
continue
|
|
|
|
if name in excluded_names:
|
|
|
|
continue
|
|
|
|
attrs.append(name)
|
|
|
|
|
2013-05-10 02:39:30 +04:00
|
|
|
default = object()
|
|
|
|
failures = []
|
|
|
|
for name in attrs:
|
|
|
|
for p in psutil.process_iter():
|
|
|
|
ret = default
|
2012-09-19 22:20:16 +04:00
|
|
|
try:
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
args = ()
|
2012-09-19 22:20:16 +04:00
|
|
|
attr = getattr(p, name, None)
|
|
|
|
if attr is not None and callable(attr):
|
2014-12-23 21:45:15 +03:00
|
|
|
if name == 'rlimit':
|
|
|
|
args = (psutil.RLIMIT_NOFILE,)
|
|
|
|
ret = attr(*args)
|
2012-09-19 22:20:16 +04:00
|
|
|
else:
|
|
|
|
ret = attr
|
|
|
|
valid_procs += 1
|
2013-08-23 10:36:57 +04:00
|
|
|
except NotImplementedError:
|
2014-12-23 21:45:15 +03:00
|
|
|
msg = "%r was skipped because not implemented" % (
|
|
|
|
self.__class__.__name__ + '.test_' + name)
|
|
|
|
warn(msg)
|
2012-09-19 22:20:16 +04:00
|
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
|
|
err = sys.exc_info()[1]
|
|
|
|
self.assertEqual(err.pid, p.pid)
|
|
|
|
if err.name:
|
|
|
|
# make sure exception's name attr is set
|
|
|
|
# with the actual process name
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertEqual(err.name, p.name())
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertTrue(str(err))
|
|
|
|
self.assertTrue(err.msg)
|
|
|
|
else:
|
|
|
|
if ret not in (0, 0.0, [], None, ''):
|
|
|
|
assert ret, ret
|
|
|
|
meth = getattr(self, name)
|
|
|
|
meth(ret)
|
|
|
|
except Exception:
|
|
|
|
err = sys.exc_info()[1]
|
2013-05-10 02:39:30 +04:00
|
|
|
s = '\n' + '=' * 70 + '\n'
|
|
|
|
s += "FAIL: test_%s (proc=%s" % (name, p)
|
|
|
|
if ret != default:
|
|
|
|
s += ", ret=%s)" % repr(ret)
|
|
|
|
s += ')\n'
|
|
|
|
s += '-' * 70
|
|
|
|
s += "\n%s" % traceback.format_exc()
|
2014-12-23 21:45:15 +03:00
|
|
|
s = "\n".join((" " * 4) + i for i in s.splitlines())
|
2013-05-10 02:39:30 +04:00
|
|
|
failures.append(s)
|
|
|
|
break
|
|
|
|
|
|
|
|
if failures:
|
|
|
|
self.fail(''.join(failures))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
# we should always have a non-empty list, not including PID 0 etc.
|
|
|
|
# special cases.
|
|
|
|
self.assertTrue(valid_procs > 0)
|
|
|
|
|
|
|
|
def cmdline(self, ret):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def exe(self, ret):
|
|
|
|
if not ret:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertEqual(ret, '')
|
2012-09-19 22:20:16 +04:00
|
|
|
else:
|
|
|
|
assert os.path.isabs(ret), ret
|
|
|
|
# Note: os.stat() may return False even if the file is there
|
|
|
|
# hence we skip the test, see:
|
|
|
|
# http://stackoverflow.com/questions/3112546/os-path-exists-lies
|
2014-12-23 21:45:15 +03:00
|
|
|
if POSIX and os.path.isfile(ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
if hasattr(os, 'access') and hasattr(os, "X_OK"):
|
2013-05-10 02:39:30 +04:00
|
|
|
# XXX may fail on OSX
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertTrue(os.access(ret, os.X_OK))
|
|
|
|
|
|
|
|
def ppid(self, ret):
|
|
|
|
self.assertTrue(ret >= 0)
|
|
|
|
|
|
|
|
def name(self, ret):
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertIsInstance(ret, (str, unicode))
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertTrue(ret)
|
|
|
|
|
|
|
|
def create_time(self, ret):
|
|
|
|
self.assertTrue(ret > 0)
|
2013-08-23 10:36:57 +04:00
|
|
|
# this can't be taken for granted on all platforms
|
2014-12-23 21:45:15 +03:00
|
|
|
# self.assertGreaterEqual(ret, psutil.boot_time())
|
2012-09-19 22:20:16 +04:00
|
|
|
# make sure returned value can be pretty printed
|
|
|
|
# with strftime
|
|
|
|
time.strftime("%Y %m %d %H:%M:%S", time.localtime(ret))
|
|
|
|
|
|
|
|
def uids(self, ret):
|
|
|
|
for uid in ret:
|
|
|
|
self.assertTrue(uid >= 0)
|
|
|
|
self.assertIn(uid, self._uids)
|
|
|
|
|
|
|
|
def gids(self, ret):
|
|
|
|
# note: testing all gids as above seems not to be reliable for
|
|
|
|
# gid == 30 (nodoby); not sure why.
|
|
|
|
for gid in ret:
|
|
|
|
self.assertTrue(gid >= 0)
|
2014-12-23 21:45:15 +03:00
|
|
|
# self.assertIn(uid, self.gids
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def username(self, ret):
|
|
|
|
self.assertTrue(ret)
|
2014-12-23 21:45:15 +03:00
|
|
|
if POSIX:
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertIn(ret, self._usernames)
|
|
|
|
|
|
|
|
def status(self, ret):
|
2014-12-23 21:45:15 +03:00
|
|
|
self.assertTrue(ret != "")
|
|
|
|
self.assertTrue(ret != '?')
|
|
|
|
self.assertIn(ret, VALID_PROC_STATUSES)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def io_counters(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
for field in ret:
|
|
|
|
if field != -1:
|
|
|
|
self.assertTrue(field >= 0)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def ionice(self, ret):
|
2013-05-10 02:39:30 +04:00
|
|
|
if LINUX:
|
|
|
|
self.assertTrue(ret.ioclass >= 0)
|
|
|
|
self.assertTrue(ret.value >= 0)
|
|
|
|
else:
|
|
|
|
self.assertTrue(ret >= 0)
|
|
|
|
self.assertIn(ret, (0, 1, 2))
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def num_threads(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertTrue(ret >= 1)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def threads(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
for t in ret:
|
|
|
|
self.assertTrue(t.id >= 0)
|
|
|
|
self.assertTrue(t.user_time >= 0)
|
|
|
|
self.assertTrue(t.system_time >= 0)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def cpu_times(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertTrue(ret.user >= 0)
|
|
|
|
self.assertTrue(ret.system >= 0)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def memory_info(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertTrue(ret.rss >= 0)
|
|
|
|
self.assertTrue(ret.vms >= 0)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def memory_info_ex(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
for name in ret._fields:
|
|
|
|
self.assertTrue(getattr(ret, name) >= 0)
|
|
|
|
if POSIX and ret.vms != 0:
|
|
|
|
# VMS is always supposed to be the highest
|
|
|
|
for name in ret._fields:
|
|
|
|
if name != 'vms':
|
|
|
|
value = getattr(ret, name)
|
|
|
|
assert ret.vms > value, ret
|
|
|
|
elif WINDOWS:
|
|
|
|
assert ret.peak_wset >= ret.wset, ret
|
|
|
|
assert ret.peak_paged_pool >= ret.paged_pool, ret
|
|
|
|
assert ret.peak_nonpaged_pool >= ret.nonpaged_pool, ret
|
|
|
|
assert ret.peak_pagefile >= ret.pagefile, ret
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def open_files(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
for f in ret:
|
|
|
|
if WINDOWS:
|
|
|
|
assert f.fd == -1, f
|
|
|
|
else:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIsInstance(f.fd, int)
|
2012-09-19 22:20:16 +04:00
|
|
|
assert os.path.isabs(f.path), f
|
|
|
|
assert os.path.isfile(f.path), f
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def num_fds(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertTrue(ret >= 0)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def connections(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
for conn in ret:
|
2014-12-23 21:45:15 +03:00
|
|
|
check_connection(conn)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def cwd(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
if ret is not None: # BSD may return None
|
|
|
|
assert os.path.isabs(ret), ret
|
|
|
|
try:
|
|
|
|
st = os.stat(ret)
|
|
|
|
except OSError:
|
|
|
|
err = sys.exc_info()[1]
|
|
|
|
# directory has been removed in mean time
|
|
|
|
if err.errno != errno.ENOENT:
|
|
|
|
raise
|
|
|
|
else:
|
|
|
|
self.assertTrue(stat.S_ISDIR(st.st_mode))
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def memory_percent(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
assert 0 <= ret <= 100, ret
|
|
|
|
|
|
|
|
def is_running(self, ret):
|
|
|
|
self.assertTrue(ret)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def cpu_affinity(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
assert ret != [], ret
|
|
|
|
|
|
|
|
def terminal(self, ret):
|
|
|
|
if ret is not None:
|
|
|
|
assert os.path.isabs(ret), ret
|
|
|
|
assert os.path.exists(ret), ret
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def memory_maps(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
for nt in ret:
|
|
|
|
for fname in nt._fields:
|
|
|
|
value = getattr(nt, fname)
|
|
|
|
if fname == 'path':
|
|
|
|
if not value.startswith('['):
|
|
|
|
assert os.path.isabs(nt.path), nt.path
|
2014-12-23 21:45:15 +03:00
|
|
|
# commented as on Linux we might get
|
|
|
|
# '/foo/bar (deleted)'
|
|
|
|
# assert os.path.exists(nt.path), nt.path
|
2012-09-19 22:20:16 +04:00
|
|
|
elif fname in ('addr', 'perms'):
|
|
|
|
self.assertTrue(value)
|
|
|
|
else:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertIsInstance(value, (int, long))
|
2012-09-19 22:20:16 +04:00
|
|
|
assert value >= 0, value
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def num_handles(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
if WINDOWS:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertGreaterEqual(ret, 0)
|
2012-09-19 22:20:16 +04:00
|
|
|
else:
|
2013-08-23 10:36:57 +04:00
|
|
|
self.assertGreaterEqual(ret, 0)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def nice(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
if POSIX:
|
|
|
|
assert -20 <= ret <= 20, ret
|
|
|
|
else:
|
|
|
|
priorities = [getattr(psutil, x) for x in dir(psutil)
|
|
|
|
if x.endswith('_PRIORITY_CLASS')]
|
|
|
|
self.assertIn(ret, priorities)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def num_ctx_switches(self, ret):
|
2012-09-19 22:20:16 +04:00
|
|
|
self.assertTrue(ret.voluntary >= 0)
|
|
|
|
self.assertTrue(ret.involuntary >= 0)
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def rlimit(self, ret):
|
|
|
|
self.assertEqual(len(ret), 2)
|
|
|
|
self.assertGreaterEqual(ret[0], -1)
|
|
|
|
self.assertGreaterEqual(ret[1], -1)
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
|
|
|
|
# ===================================================================
|
|
|
|
# --- Limited user tests
|
|
|
|
# ===================================================================
|
|
|
|
|
|
|
|
if hasattr(os, 'getuid') and os.getuid() == 0:
|
2014-12-23 21:45:15 +03:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
class LimitedUserTestCase(TestProcess):
|
2012-09-19 22:20:16 +04:00
|
|
|
"""Repeat the previous tests by using a limited user.
|
|
|
|
Executed only on UNIX and only if the user who run the test script
|
|
|
|
is root.
|
|
|
|
"""
|
|
|
|
# the uid/gid the test suite runs under
|
|
|
|
PROCESS_UID = os.getuid()
|
|
|
|
PROCESS_GID = os.getgid()
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
2013-08-23 10:36:57 +04:00
|
|
|
TestProcess.__init__(self, *args, **kwargs)
|
2012-09-19 22:20:16 +04:00
|
|
|
# re-define all existent test methods in order to
|
|
|
|
# ignore AccessDenied exceptions
|
|
|
|
for attr in [x for x in dir(self) if x.startswith('test')]:
|
|
|
|
meth = getattr(self, attr)
|
2014-12-23 21:45:15 +03:00
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_(self):
|
|
|
|
try:
|
|
|
|
meth()
|
|
|
|
except psutil.AccessDenied:
|
|
|
|
pass
|
|
|
|
setattr(self, attr, types.MethodType(test_, self))
|
|
|
|
|
|
|
|
def setUp(self):
|
2014-12-23 21:45:15 +03:00
|
|
|
safe_remove(TESTFN)
|
2012-09-19 22:20:16 +04:00
|
|
|
os.setegid(1000)
|
|
|
|
os.seteuid(1000)
|
2013-08-23 10:36:57 +04:00
|
|
|
TestProcess.setUp(self)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
os.setegid(self.PROCESS_UID)
|
|
|
|
os.seteuid(self.PROCESS_GID)
|
2013-08-23 10:36:57 +04:00
|
|
|
TestProcess.tearDown(self)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
def test_nice(self):
|
|
|
|
try:
|
2014-12-23 21:45:15 +03:00
|
|
|
psutil.Process().nice(-1)
|
2012-09-19 22:20:16 +04:00
|
|
|
except psutil.AccessDenied:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
self.fail("exception not raised")
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_zombie_process(self):
|
|
|
|
# causes problems if test test suite is run as root
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
|
|
|
|
class LimitedUserTestCase(unittest.TestCase):
|
|
|
|
def test_it(self):
|
|
|
|
unittest.skip("super user privileges are required")
|
|
|
|
|
|
|
|
|
|
|
|
# ===================================================================
|
|
|
|
# --- Misc tests
|
|
|
|
# ===================================================================
|
|
|
|
|
|
|
|
class TestMisc(unittest.TestCase):
|
|
|
|
"""Misc / generic tests."""
|
|
|
|
|
|
|
|
def test__str__(self):
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
self.assertIn(str(sproc.pid), str(p))
|
|
|
|
# python shows up as 'Python' in cmdline on OS X so
|
|
|
|
# test fails on OS X
|
|
|
|
if not OSX:
|
|
|
|
self.assertIn(os.path.basename(PYTHON), str(p))
|
|
|
|
sproc = get_test_subprocess()
|
|
|
|
p = psutil.Process(sproc.pid)
|
|
|
|
p.kill()
|
|
|
|
p.wait()
|
|
|
|
self.assertIn(str(sproc.pid), str(p))
|
|
|
|
self.assertIn("terminated", str(p))
|
|
|
|
|
|
|
|
def test__eq__(self):
|
|
|
|
p1 = psutil.Process()
|
|
|
|
p2 = psutil.Process()
|
|
|
|
self.assertEqual(p1, p2)
|
|
|
|
p2._ident = (0, 0)
|
|
|
|
self.assertNotEqual(p1, p2)
|
|
|
|
self.assertNotEqual(p1, 'foo')
|
|
|
|
|
|
|
|
def test__hash__(self):
|
|
|
|
s = set([psutil.Process(), psutil.Process()])
|
|
|
|
self.assertEqual(len(s), 1)
|
|
|
|
|
|
|
|
def test__all__(self):
|
|
|
|
for name in dir(psutil):
|
|
|
|
if name in ('callable', 'defaultdict', 'error', 'namedtuple',
|
|
|
|
'long', 'test', 'NUM_CPUS', 'BOOT_TIME',
|
|
|
|
'TOTAL_PHYMEM'):
|
|
|
|
continue
|
|
|
|
if not name.startswith('_'):
|
|
|
|
try:
|
|
|
|
__import__(name)
|
|
|
|
except ImportError:
|
|
|
|
if name not in psutil.__all__:
|
|
|
|
fun = getattr(psutil, name)
|
|
|
|
if fun is None:
|
|
|
|
continue
|
|
|
|
if (fun.__doc__ is not None and
|
|
|
|
'deprecated' not in fun.__doc__.lower()):
|
|
|
|
self.fail('%r not in psutil.__all__' % name)
|
|
|
|
|
|
|
|
def test_memoize(self):
|
|
|
|
from psutil._common import memoize
|
|
|
|
|
|
|
|
@memoize
|
|
|
|
def foo(*args, **kwargs):
|
|
|
|
"foo docstring"
|
|
|
|
calls.append(None)
|
|
|
|
return (args, kwargs)
|
|
|
|
|
|
|
|
calls = []
|
|
|
|
# no args
|
|
|
|
for x in range(2):
|
|
|
|
ret = foo()
|
|
|
|
expected = ((), {})
|
|
|
|
self.assertEqual(ret, expected)
|
|
|
|
self.assertEqual(len(calls), 1)
|
|
|
|
# with args
|
|
|
|
for x in range(2):
|
|
|
|
ret = foo(1)
|
|
|
|
expected = ((1, ), {})
|
|
|
|
self.assertEqual(ret, expected)
|
|
|
|
self.assertEqual(len(calls), 2)
|
|
|
|
# with args + kwargs
|
|
|
|
for x in range(2):
|
|
|
|
ret = foo(1, bar=2)
|
|
|
|
expected = ((1, ), {'bar': 2})
|
|
|
|
self.assertEqual(ret, expected)
|
|
|
|
self.assertEqual(len(calls), 3)
|
|
|
|
# clear cache
|
|
|
|
foo.cache_clear()
|
|
|
|
ret = foo()
|
|
|
|
expected = ((), {})
|
|
|
|
self.assertEqual(ret, expected)
|
|
|
|
self.assertEqual(len(calls), 4)
|
|
|
|
# docstring
|
|
|
|
self.assertEqual(foo.__doc__, "foo docstring")
|
|
|
|
|
|
|
|
def test_serialization(self):
|
|
|
|
def check(ret):
|
|
|
|
if json is not None:
|
|
|
|
json.loads(json.dumps(ret))
|
|
|
|
a = pickle.dumps(ret)
|
|
|
|
b = pickle.loads(a)
|
|
|
|
self.assertEqual(ret, b)
|
|
|
|
|
|
|
|
check(psutil.Process().as_dict())
|
|
|
|
check(psutil.virtual_memory())
|
|
|
|
check(psutil.swap_memory())
|
|
|
|
check(psutil.cpu_times())
|
|
|
|
check(psutil.cpu_times_percent(interval=0))
|
|
|
|
check(psutil.net_io_counters())
|
|
|
|
if LINUX and not os.path.exists('/proc/diskstats'):
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
check(psutil.disk_io_counters())
|
|
|
|
check(psutil.disk_partitions())
|
|
|
|
check(psutil.disk_usage(os.getcwd()))
|
|
|
|
check(psutil.users())
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
# ===================================================================
|
|
|
|
# --- Example script tests
|
|
|
|
# ===================================================================
|
|
|
|
|
|
|
|
class TestExampleScripts(unittest.TestCase):
|
|
|
|
"""Tests for scripts in the examples directory."""
|
|
|
|
|
|
|
|
def assert_stdout(self, exe, args=None):
|
|
|
|
exe = os.path.join(EXAMPLES_DIR, exe)
|
|
|
|
if args:
|
|
|
|
exe = exe + ' ' + args
|
|
|
|
try:
|
|
|
|
out = sh(sys.executable + ' ' + exe).strip()
|
|
|
|
except RuntimeError:
|
|
|
|
err = sys.exc_info()[1]
|
|
|
|
if 'AccessDenied' in str(err):
|
|
|
|
return str(err)
|
|
|
|
else:
|
|
|
|
raise
|
|
|
|
assert out, out
|
|
|
|
return out
|
|
|
|
|
|
|
|
def assert_syntax(self, exe, args=None):
|
|
|
|
exe = os.path.join(EXAMPLES_DIR, exe)
|
|
|
|
f = open(exe, 'r')
|
|
|
|
try:
|
|
|
|
src = f.read()
|
|
|
|
finally:
|
|
|
|
f.close()
|
|
|
|
ast.parse(src)
|
|
|
|
|
|
|
|
def test_check_presence(self):
|
|
|
|
# make sure all example scripts have a test method defined
|
|
|
|
meths = dir(self)
|
|
|
|
for name in os.listdir(EXAMPLES_DIR):
|
|
|
|
if name.endswith('.py'):
|
|
|
|
if 'test_' + os.path.splitext(name)[0] not in meths:
|
2014-12-23 21:45:15 +03:00
|
|
|
# self.assert_stdout(name)
|
|
|
|
self.fail('no test defined for %r script'
|
2013-08-23 10:36:57 +04:00
|
|
|
% os.path.join(EXAMPLES_DIR, name))
|
|
|
|
|
|
|
|
def test_disk_usage(self):
|
|
|
|
self.assert_stdout('disk_usage.py')
|
|
|
|
|
|
|
|
def test_free(self):
|
|
|
|
self.assert_stdout('free.py')
|
|
|
|
|
|
|
|
def test_meminfo(self):
|
|
|
|
self.assert_stdout('meminfo.py')
|
|
|
|
|
|
|
|
def test_process_detail(self):
|
|
|
|
self.assert_stdout('process_detail.py')
|
|
|
|
|
|
|
|
def test_who(self):
|
|
|
|
self.assert_stdout('who.py')
|
|
|
|
|
2014-12-23 21:45:15 +03:00
|
|
|
def test_ps(self):
|
|
|
|
self.assert_stdout('ps.py')
|
|
|
|
|
2013-08-23 10:36:57 +04:00
|
|
|
def test_netstat(self):
|
|
|
|
self.assert_stdout('netstat.py')
|
|
|
|
|
|
|
|
def test_pmap(self):
|
|
|
|
self.assert_stdout('pmap.py', args=str(os.getpid()))
|
|
|
|
|
|
|
|
@unittest.skipIf(ast is None,
|
|
|
|
'ast module not available on this python version')
|
|
|
|
def test_killall(self):
|
|
|
|
self.assert_syntax('killall.py')
|
|
|
|
|
|
|
|
@unittest.skipIf(ast is None,
|
|
|
|
'ast module not available on this python version')
|
|
|
|
def test_nettop(self):
|
|
|
|
self.assert_syntax('nettop.py')
|
|
|
|
|
|
|
|
@unittest.skipIf(ast is None,
|
|
|
|
'ast module not available on this python version')
|
|
|
|
def test_top(self):
|
|
|
|
self.assert_syntax('top.py')
|
|
|
|
|
|
|
|
@unittest.skipIf(ast is None,
|
|
|
|
'ast module not available on this python version')
|
|
|
|
def test_iotop(self):
|
|
|
|
self.assert_syntax('iotop.py')
|
|
|
|
|
|
|
|
|
2012-09-19 22:20:16 +04:00
|
|
|
def test_main():
|
|
|
|
tests = []
|
|
|
|
test_suite = unittest.TestSuite()
|
2013-08-23 10:36:57 +04:00
|
|
|
tests.append(TestSystemAPIs)
|
|
|
|
tests.append(TestProcess)
|
2012-09-19 22:20:16 +04:00
|
|
|
tests.append(TestFetchAllProcesses)
|
2014-12-23 21:45:15 +03:00
|
|
|
tests.append(TestMisc)
|
|
|
|
tests.append(TestExampleScripts)
|
|
|
|
tests.append(LimitedUserTestCase)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
if POSIX:
|
|
|
|
from _posix import PosixSpecificTestCase
|
|
|
|
tests.append(PosixSpecificTestCase)
|
|
|
|
|
|
|
|
# import the specific platform test suite
|
2014-12-23 21:45:15 +03:00
|
|
|
stc = None
|
2012-09-19 22:20:16 +04:00
|
|
|
if LINUX:
|
|
|
|
from _linux import LinuxSpecificTestCase as stc
|
|
|
|
elif WINDOWS:
|
|
|
|
from _windows import WindowsSpecificTestCase as stc
|
|
|
|
from _windows import TestDualProcessImplementation
|
|
|
|
tests.append(TestDualProcessImplementation)
|
|
|
|
elif OSX:
|
|
|
|
from _osx import OSXSpecificTestCase as stc
|
|
|
|
elif BSD:
|
|
|
|
from _bsd import BSDSpecificTestCase as stc
|
2013-08-23 10:36:57 +04:00
|
|
|
elif SUNOS:
|
|
|
|
from _sunos import SunOSSpecificTestCase as stc
|
2014-12-23 21:45:15 +03:00
|
|
|
if stc is not None:
|
|
|
|
tests.append(stc)
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
for test_class in tests:
|
|
|
|
test_suite.addTest(unittest.makeSuite(test_class))
|
2013-08-23 10:36:57 +04:00
|
|
|
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
|
|
|
|
return result.wasSuccessful()
|
2012-09-19 22:20:16 +04:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2013-08-23 10:36:57 +04:00
|
|
|
if not test_main():
|
|
|
|
sys.exit(1)
|