summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2016-02-02 07:01:12 +0000
committerGiampaolo Rodola <g.rodola@gmail.com>2016-02-02 07:01:12 +0000
commit9c879e52948e1105e0a9a90854792198be636ebf (patch)
tree7a9991b0c2983563884303b89777bdb50d55e7d5
parente5dd8b6817e344bf04b7b3e2333bbeb562fc7ac6 (diff)
parentcbfe54481327639689587699bd23882cee0ca0f4 (diff)
downloadpsutil-9c879e52948e1105e0a9a90854792198be636ebf.tar.gz
Merge branch 'master' of github.com:giampaolo/psutil
-rw-r--r--.travis.yml1
-rw-r--r--HISTORY.rst7
-rw-r--r--IDEAS7
-rw-r--r--INSTALL.rst15
-rw-r--r--Makefile2
-rw-r--r--README.rst2
-rw-r--r--docs/index.rst30
-rw-r--r--psutil/__init__.py16
-rw-r--r--psutil/_common.py3
-rw-r--r--psutil/_psbsd.py14
-rw-r--r--psutil/_pslinux.py15
-rw-r--r--psutil/_psosx.py3
-rw-r--r--psutil/_pssunos.py6
-rw-r--r--psutil/_psutil_bsd.c11
-rw-r--r--psutil/_psutil_osx.c13
-rw-r--r--psutil/_psutil_sunos.c10
-rw-r--r--psutil/_pswindows.py7
-rw-r--r--psutil/tests/__init__.py9
-rw-r--r--psutil/tests/test_bsd.py41
-rw-r--r--psutil/tests/test_linux.py65
-rw-r--r--psutil/tests/test_process.py16
-rw-r--r--psutil/tests/test_system.py21
22 files changed, 246 insertions, 68 deletions
diff --git a/.travis.yml b/.travis.yml
index 03f19132..17206c58 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,7 @@ matrix:
- python: 3.3
- python: 3.4
- python: 3.5
+ - "pypy"
# XXX - commented because OSX builds are deadly slow
# - language: generic
# os: osx
diff --git a/HISTORY.rst b/HISTORY.rst
index 5ba233b8..b8bdec10 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -7,6 +7,8 @@ Bug tracker at https://github.com/giampaolo/psutil/issues
- #777: [Linux] Process.open_files() on Linux return 3 new fields: position,
mode and flags.
+- #779: Process.cpu_times() returns two new fields, 'children_user' and
+ 'children_system' (always set to 0 on OSX and Windows).
**Bug fixes**
@@ -14,6 +16,9 @@ Bug tracker at https://github.com/giampaolo/psutil/issues
provides it.
- #776: [Linux] Process.cpu_affinity() may erroneously raise NoSuchProcess.
(patch by wxwright)
+- #780: [OSX] psutil does not compile with some gcc versions.
+- #786: net_if_addrs() may report incomplete MAC addresses.
+- #788: [NetBSD] virtual_memory()'s buffers and shared values were set to 0.
4.0.0 - 2016-02-17
@@ -36,6 +41,8 @@ Bug tracker at https://github.com/giampaolo/psutil/issues
**Bug fixes**
+- #685: [Linux] virtual_memory() provides wrong results on systems with a lot
+ of physical memory.
- #704: [Solaris] psutil does not compile on Solaris sparc.
- #734: on Python 3 invalid UTF-8 data is not correctly handled for process
name(), cwd(), exe(), cmdline() and open_files() methods resulting in
diff --git a/IDEAS b/IDEAS
index 2b27c714..06328543 100644
--- a/IDEAS
+++ b/IDEAS
@@ -17,9 +17,9 @@ PLATFORMS
FEATURES
========
-- #782: (UNIX) process num of signals received.
+- (UNIX) process root (different from cwd)
-- (UNIX) process root (different from xwd)
+- #782: (UNIX) process num of signals received.
- (Linux) locked files via /proc/locks:
https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-proc-locks.html
@@ -144,5 +144,6 @@ FEATURES
SIMILAR PROJECTS
================
-- https://github.com/hyperic/sigar (Java)
+- sigar: https://github.com/hyperic/sigar (Java)
- zabbix source code: https://zabbix.org/wiki/Get_Zabbix
+- libstatgrab: http://www.i-scream.org/libstatgrab/
diff --git a/INSTALL.rst b/INSTALL.rst
index fdbc4d6d..2a98e193 100644
--- a/INSTALL.rst
+++ b/INSTALL.rst
@@ -69,13 +69,16 @@ Once done, you can build/install psutil with::
$ python setup.py install
-==================
-Installing on OS X
-==================
+=================
+Installing on OSX
+=================
-OS X installation from source will require gcc which you can obtain as part of
-the 'XcodeTools' installer from Apple. Then you can run the standard distutils
-commands.
+OSX installation from source will require gcc which you can obtain as part of
+the 'XcodeTools' installer from Apple:
+
+https://developer.apple.com/downloads/?name=Xcode
+
+Once you have installed XCode you can run the standard distutils commands.
To build only::
$ python setup.py build
diff --git a/Makefile b/Makefile
index f72611a8..3e6995d6 100644
--- a/Makefile
+++ b/Makefile
@@ -82,7 +82,7 @@ test-by-name: install
# Run specific platform tests only.
test-platform: install
- $(PYTHON) psutil/tests/test_`$(PYTHON) -c 'import psutil; print([x.lower() for x in ("FREEBSD", "LINUX", "NETBSD", "OPENBSD", "OSX", "SUNOS", "WINDOWS") if getattr(psutil, x)][0])'`.py
+ $(PYTHON) psutil/tests/test_`$(PYTHON) -c 'import psutil; print([x.lower() for x in ("LINUX", "BSD", "OSX", "SUNOS", "WINDOWS") if getattr(psutil, x)][0])'`.py
# Same as above but for test_memory_leaks.py script.
test-memleaks-by-name: install
diff --git a/README.rst b/README.rst
index 2a88f934..1559636b 100644
--- a/README.rst
+++ b/README.rst
@@ -226,7 +226,7 @@ Process management
pgids(real=1000, effective=1000, saved=1000)
>>>
>>> p.cpu_times()
- pcputimes(user=1.02, system=0.31)
+ pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1)
>>> p.cpu_percent(interval=1.0)
12.1
>>> p.cpu_affinity()
diff --git a/docs/index.rst b/docs/index.rst
index b6cf4d91..c9066493 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -266,16 +266,22 @@ Disks
.. function:: disk_io_counters(perdisk=False)
Return system-wide disk I/O statistics as a namedtuple including the
- following fields.
+ following fields:
+
- **read_count**: number of reads
- **write_count**: number of writes
- **read_bytes**: number of bytes read
- **write_bytes**: number of bytes written
- - **read_time**: (all except NetBSD and OpenBSD) time spent reading from disk (in milliseconds)
- - **write_time**: (all except NetBSD and OpenBSD) time spent writing to disk (in milliseconds)
- - **busy_time**: (Linux, FreeBSD) time spent doing actual I/Os (in milliseconds)
- - **read_merged_count** (Linux): number of merged reads (see `iostat doc <https://www.kernel.org/doc/Documentation/iostats.txt>`__)
- - **write_merged_count** (Linux): number of merged writes (see `iostats doc <https://www.kernel.org/doc/Documentation/iostats.txt>`__)
+ - **read_time**: (all except NetBSD and OpenBSD) time spent reading from
+ disk (in milliseconds)
+ - **write_time**: (all except NetBSD and OpenBSD) time spent writing to disk
+ (in milliseconds)
+ - **busy_time**: (Linux, FreeBSD) time spent doing actual I/Os (in
+ milliseconds)
+ - **read_merged_count** (Linux): number of merged reads
+ (see `iostat doc <https://www.kernel.org/doc/Documentation/iostats.txt>`__)
+ - **write_merged_count** (Linux): number of merged writes
+ (see `iostats doc <https://www.kernel.org/doc/Documentation/iostats.txt>`__)
If *perdisk* is ``True`` return the same information for every physical disk
installed on the system as a dictionary with partition names as the keys and
@@ -915,14 +921,18 @@ Process class
.. method:: cpu_times()
- Return a tuple whose values are process CPU **user** and **system**
- times which means the amount of time expressed in seconds that a process
- has spent in
- `user / system mode <http://stackoverflow.com/questions/556405/what-do-real-user-and-sys-mean-in-the-output-of-time1>`__.
+ Return a `(user, system, children_user, children_system)` namedtuple
+ representing the accumulated process time, in seconds (see
+ `explanation <http://stackoverflow.com/questions/556405/>`__).
+ On Windows and OSX only *user* and *system* are filled, the others are
+ set to ``0``.
This is similar to
`os.times() <http://docs.python.org//library/os.html#os.times>`__
but can be used for any process PID.
+ .. versionchanged:: 4.1.0 return two extra fields: *children_user* and
+ *children_system*.
+
.. method:: cpu_percent(interval=None)
Return a float representing the process CPU utilization as a percentage.
diff --git a/psutil/__init__.py b/psutil/__init__.py
index 8594e4b9..256783d9 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -960,9 +960,12 @@ class Process(object):
return round(overall_percent, 1)
def cpu_times(self):
- """Return a (user, system) namedtuple representing the
- accumulated process time, in seconds.
- This is the same as os.times() but per-process.
+ """Return a (user, system, children_user, children_system)
+ namedtuple representing the accumulated process time, in
+ seconds.
+ This is similar to os.times() but per-process.
+ On OSX and Windows children_user and children_system are
+ always set to 0.
"""
return self._proc.cpu_times()
@@ -1911,6 +1914,13 @@ def net_if_addrs():
# We re-set the family here so that repr(family)
# will show AF_LINK rather than AF_PACKET
fam = _psplatform.AF_LINK
+ if fam == _psplatform.AF_LINK:
+ # The underlying C function may return an incomplete MAC
+ # address in which case we fill it with null bytes, see:
+ # https://github.com/giampaolo/psutil/issues/786
+ separator = ":" if POSIX else "-"
+ while addr.count(separator) < 5:
+ addr += "%s00" % separator
ret[name].append(_common.snic(fam, addr, mask, broadcast, ptp))
return dict(ret)
diff --git a/psutil/_common.py b/psutil/_common.py
index 51cc1a2c..b146c736 100644
--- a/psutil/_common.py
+++ b/psutil/_common.py
@@ -311,7 +311,8 @@ snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu'])
# --- namedtuples for psutil.Process methods
# psutil.Process.cpu_times()
-pcputimes = namedtuple('pcputimes', ['user', 'system'])
+pcputimes = namedtuple('pcputimes',
+ ['user', 'system', 'children_user', 'children_system'])
# psutil.Process.open_files()
popenfile = namedtuple('popenfile', ['path', 'fd'])
# psutil.Process.threads()
diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py
index b43e052a..4af3bc8e 100644
--- a/psutil/_psbsd.py
+++ b/psutil/_psbsd.py
@@ -100,6 +100,8 @@ scputimes = namedtuple(
'scputimes', ['user', 'nice', 'system', 'idle', 'irq'])
pmem = namedtuple('pmem', ['rss', 'vms', 'text', 'data', 'stack'])
pfullmem = pmem
+pcputimes = namedtuple('pcputimes',
+ ['user', 'system', 'children_user', 'children_system'])
pmmap_grouped = namedtuple(
'pmmap_grouped', 'path rss, private, ref_count, shadow_count')
pmmap_ext = namedtuple(
@@ -124,6 +126,15 @@ def virtual_memory():
"""System virtual memory as a namedtuple."""
mem = cext.virtual_mem()
total, free, active, inactive, wired, cached, buffers, shared = mem
+ if NETBSD:
+ # On NetBSD buffers and shared mem is determined via /proc.
+ # The C ext set them to 0.
+ with open('/proc/meminfo', 'rb') as f:
+ for line in f:
+ if line.startswith("Buffers:"):
+ buffers = int(line.split()[1]) * 1024
+ elif line.startswith("MemShared:"):
+ shared = int(line.split()[1]) * 1024
avail = inactive + cached + free
used = active + wired + cached
percent = usage_percent((total - avail), total, _round=1)
@@ -436,8 +447,7 @@ class Process(object):
@wrap_exceptions
def cpu_times(self):
- user, system = cext.proc_cpu_times(self.pid)
- return _common.pcputimes(user, system)
+ return _common.pcputimes(*cext.proc_cpu_times(self.pid))
@wrap_exceptions
def memory_info(self):
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index 324ff5cb..0b996e70 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -180,13 +180,13 @@ def readlink(path):
def file_flags_to_mode(flags):
- md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
- m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
+ modes_map = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
+ mode = modes_map[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
if flags & os.O_APPEND:
- m = m.replace('w', 'a', 1)
- m = m.replace('w+', 'r+')
+ mode = mode.replace('w', 'a', 1)
+ mode = mode.replace('w+', 'r+')
# possible values: r, w, a, r+, a+
- return m
+ return mode
def get_sector_size():
@@ -251,7 +251,6 @@ popenfile = namedtuple('popenfile',
['path', 'fd', 'position', 'mode', 'flags'])
pmem = namedtuple('pmem', 'rss vms shared text lib data dirty')
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', 'pss', 'swap'))
-
pmmap_grouped = namedtuple(
'pmmap_grouped', ['path', 'rss', 'size', 'pss', 'shared_clean',
'shared_dirty', 'private_clean', 'private_dirty',
@@ -989,7 +988,9 @@ class Process(object):
values = st.split(b' ')
utime = float(values[11]) / CLOCK_TICKS
stime = float(values[12]) / CLOCK_TICKS
- return _common.pcputimes(utime, stime)
+ children_utime = float(values[13]) / CLOCK_TICKS
+ children_stime = float(values[14]) / CLOCK_TICKS
+ return _common.pcputimes(utime, stime, children_utime, children_stime)
@wrap_exceptions
def wait(self, timeout=None):
diff --git a/psutil/_psosx.py b/psutil/_psosx.py
index 5f39589c..b8066775 100644
--- a/psutil/_psosx.py
+++ b/psutil/_psosx.py
@@ -282,7 +282,8 @@ class Process(object):
@wrap_exceptions
def cpu_times(self):
user, system = cext.proc_cpu_times(self.pid)
- return _common.pcputimes(user, system)
+ # Children user/system times are not retrievable (set to 0).
+ return _common.pcputimes(user, system, 0, 0)
@wrap_exceptions
def create_time(self):
diff --git a/psutil/_pssunos.py b/psutil/_pssunos.py
index c0d44b12..06da5aab 100644
--- a/psutil/_pssunos.py
+++ b/psutil/_pssunos.py
@@ -59,6 +59,8 @@ TCP_STATUSES = {
}
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
+pcputimes = namedtuple('pcputimes',
+ ['user', 'system', 'children_user', 'children_system'])
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
pmem = namedtuple('pmem', ['rss', 'vms'])
pfullmem = pmem
@@ -364,8 +366,8 @@ class Process(object):
@wrap_exceptions
def cpu_times(self):
- user, system = cext.proc_cpu_times(self.pid, self._procfs_path)
- return _common.pcputimes(user, system)
+ times = cext.proc_cpu_times(self.pid, self._procfs_path)
+ return _common.pcputimes(*times)
@wrap_exceptions
def terminal(self):
diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c
index db05dc8e..31511abb 100644
--- a/psutil/_psutil_bsd.c
+++ b/psutil/_psutil_bsd.c
@@ -368,7 +368,7 @@ psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) {
static PyObject *
psutil_proc_cpu_times(PyObject *self, PyObject *args) {
long pid;
- double user_t, sys_t;
+ double user_t, sys_t, children_user_t, children_sys_t;
kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
@@ -378,11 +378,18 @@ psutil_proc_cpu_times(PyObject *self, PyObject *args) {
#ifdef __FreeBSD__
user_t = PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_utime);
sys_t = PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_stime);
+ children_user_t = PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_utime);
+ children_sys_t = PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_stime);
#elif defined(__OpenBSD__) || defined(__NetBSD__)
user_t = PSUTIL_KPT2DOUBLE(kp.p_uutime);
sys_t = PSUTIL_KPT2DOUBLE(kp.p_ustime);
+ // OpenBSD and NetBSD provide children user + system times summed
+ // together (no distinction).
+ children_user_t = kp.p_uctime_sec + kp.p_uctime_usec / 1000000.0;
+ children_sys_t = children_user_t;
#endif
- return Py_BuildValue("(dd)", user_t, sys_t);
+ return Py_BuildValue("(dddd)",
+ user_t, sys_t, children_user_t, children_sys_t);
}
diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c
index f76ca0e6..e9a898ac 100644
--- a/psutil/_psutil_osx.c
+++ b/psutil/_psutil_osx.c
@@ -581,11 +581,14 @@ psutil_proc_memory_uss(PyObject *self, PyObject *args) {
mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT;
kern_return_t kr;
vm_size_t page_size;
+ mach_vm_address_t addr = MACH_VM_MIN_ADDRESS;
+ mach_port_t task = MACH_PORT_NULL;
+ vm_region_top_info_data_t info;
+ mach_port_t object_name;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
- mach_port_t task = MACH_PORT_NULL;
err = task_for_pid(mach_task_self(), pid, &task);
if (err != KERN_SUCCESS) {
psutil_raise_ad_or_nsp(pid);
@@ -600,10 +603,7 @@ psutil_proc_memory_uss(PyObject *self, PyObject *args) {
// Roughly based on libtop_update_vm_regions in
// http://www.opensource.apple.com/source/top/top-100.1.2/libtop.c
- for (mach_vm_address_t addr = MACH_VM_MIN_ADDRESS; ; addr += size) {
- vm_region_top_info_data_t info;
- mach_port_t object_name;
-
+ for (addr = 0; ; addr += size) {
kr = mach_vm_region(
task, &addr, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info,
&info_count, &object_name);
@@ -612,7 +612,8 @@ psutil_proc_memory_uss(PyObject *self, PyObject *args) {
break;
}
else if (kr != KERN_SUCCESS) {
- return false;
+ PyErr_Format(PyExc_RuntimeError, "mach_vm_region() failed");
+ return NULL;
}
if (psutil_in_shared_region(addr, cpu_type) &&
diff --git a/psutil/_psutil_sunos.c b/psutil/_psutil_sunos.c
index 7ffee306..9a7067d3 100644
--- a/psutil/_psutil_sunos.c
+++ b/psutil/_psutil_sunos.c
@@ -159,9 +159,13 @@ psutil_proc_cpu_times(PyObject *self, PyObject *args) {
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info)))
return NULL;
// results are more precise than os.times()
- return Py_BuildValue("dd",
- PSUTIL_TV2DOUBLE(info.pr_utime),
- PSUTIL_TV2DOUBLE(info.pr_stime));
+ return Py_BuildValue(
+ "(dddd)",
+ PSUTIL_TV2DOUBLE(info.pr_utime),
+ PSUTIL_TV2DOUBLE(info.pr_stime),
+ PSUTIL_TV2DOUBLE(info.pr_cutime),
+ PSUTIL_TV2DOUBLE(info.pr_cstime)
+ );
}
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index 92472576..25ed2a59 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -448,14 +448,15 @@ class Process(object):
@wrap_exceptions
def cpu_times(self):
try:
- ret = cext.proc_cpu_times(self.pid)
+ user, system = cext.proc_cpu_times(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_SET:
nt = ntpinfo(*cext.proc_info(self.pid))
- ret = (nt.user_time, nt.kernel_time)
+ user, system = (nt.user_time, nt.kernel_time)
else:
raise
- return _common.pcputimes(*ret)
+ # Children user/system times are not retrievable (set to 0).
+ return _common.pcputimes(user, system, 0, 0)
@wrap_exceptions
def suspend(self):
diff --git a/psutil/tests/__init__.py b/psutil/tests/__init__.py
index 7ff5133f..1db2369b 100644
--- a/psutil/tests/__init__.py
+++ b/psutil/tests/__init__.py
@@ -82,6 +82,7 @@ TESTFN = os.path.join(os.getcwd(), "$testfile")
TESTFN_UNICODE = TESTFN + "ƒőő"
TESTFILE_PREFIX = 'psutil-test-suite-'
TOX = os.getenv('TOX') or '' in ('1', 'true')
+PYPY = '__pypy__' in sys.builtin_module_names
if not PY3:
try:
TESTFN_UNICODE = unicode(TESTFN_UNICODE, sys.getfilesystemencoding())
@@ -344,8 +345,10 @@ def reap_children(search_all=False):
_subprocesses_started = set(alive)
-def check_ip_address(addr, family):
- """Attempts to check IP address's validity."""
+def check_net_address(addr, family):
+ """Check a net address validity. Supported families are IPv4,
+ IPv6 and MAC addresses.
+ """
if enum and PY3:
assert isinstance(family, enum.IntEnum), family
if family == AF_INET:
@@ -392,7 +395,7 @@ def check_connection_ntuple(conn):
ip, port = addr
assert isinstance(port, int), port
assert 0 <= port <= 65535, port
- check_ip_address(ip, conn.family)
+ check_net_address(ip, conn.family)
elif conn.family == AF_UNIX:
assert isinstance(addr, (str, None)), addr
else:
diff --git a/psutil/tests/test_bsd.py b/psutil/tests/test_bsd.py
index b77640cf..6d2749ae 100644
--- a/psutil/tests/test_bsd.py
+++ b/psutil/tests/test_bsd.py
@@ -286,7 +286,6 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
# --- OpenBSD
# =====================================================================
-
@unittest.skipUnless(OPENBSD, "not an OpenBSD system")
class OpenBSDSpecificTestCase(unittest.TestCase):
@@ -297,5 +296,45 @@ class OpenBSDSpecificTestCase(unittest.TestCase):
self.assertEqual(sys_bt, psutil_bt)
+# =====================================================================
+# --- NetBSD
+# =====================================================================
+
+@unittest.skipUnless(NETBSD, "not a NetBSD system")
+class NetBSDSpecificTestCase(unittest.TestCase):
+
+ def parse_meminfo(self, look_for):
+ with open('/proc/meminfo', 'rb') as f:
+ for line in f:
+ if line.startswith(look_for):
+ return int(line.split()[1]) * 1024
+ raise ValueError("can't find %s" % look_for)
+
+ # XXX - failing tests
+
+ # def test_vmem_total(self):
+ # self.assertEqual(
+ # psutil.virtual_memory().total, self.parse_meminfo("MemTotal:"))
+
+ # def test_vmem_free(self):
+ # self.assertEqual(
+ # psutil.virtual_memory().buffers, self.parse_meminfo("MemFree:"))
+
+ def test_vmem_buffers(self):
+ self.assertEqual(
+ psutil.virtual_memory().buffers, self.parse_meminfo("Buffers:"))
+
+ def test_vmem_shared(self):
+ self.assertEqual(
+ psutil.virtual_memory().shared, self.parse_meminfo("MemShared:"))
+
+ def test_swapmem_total(self):
+ self.assertEqual(
+ psutil.swap_memory().total, self.parse_meminfo("SwapTotal:"))
+
+ def test_swapmem_free(self):
+ self.assertEqual(
+ psutil.swap_memory().free, self.parse_meminfo("SwapFree:"))
+
if __name__ == '__main__':
run_test_module_by_name(__file__)
diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py
index a9545991..baab1228 100644
--- a/psutil/tests/test_linux.py
+++ b/psutil/tests/test_linux.py
@@ -33,6 +33,7 @@ from psutil.tests import call_until
from psutil.tests import get_kernel_version
from psutil.tests import importlib
from psutil.tests import MEMORY_TOLERANCE
+from psutil.tests import PYPY
from psutil.tests import pyrun
from psutil.tests import reap_children
from psutil.tests import retry_before_failing
@@ -332,6 +333,53 @@ class TestSystemNetwork(unittest.TestCase):
self.assertEqual(addr.address, get_ipv4_address(name))
# TODO: test for AF_INET6 family
+ def test_net_if_stats(self):
+ for name, stats in psutil.net_if_stats().items():
+ try:
+ out = sh("ifconfig %s" % name)
+ except RuntimeError:
+ pass
+ else:
+ self.assertEqual(stats.isup, 'RUNNING' in out)
+ self.assertEqual(stats.mtu,
+ int(re.findall('MTU:(\d+)', out)[0]))
+
+ def test_net_io_counters(self):
+ def ifconfig(nic):
+ ret = {}
+ out = sh("ifconfig %s" % name)
+ ret['packets_recv'] = int(re.findall('RX packets:(\d+)', out)[0])
+ ret['packets_sent'] = int(re.findall('TX packets:(\d+)', out)[0])
+ ret['errin'] = int(re.findall('errors:(\d+)', out)[0])
+ ret['errout'] = int(re.findall('errors:(\d+)', out)[1])
+ ret['dropin'] = int(re.findall('dropped:(\d+)', out)[0])
+ ret['dropout'] = int(re.findall('dropped:(\d+)', out)[1])
+ ret['bytes_recv'] = int(re.findall('RX bytes:(\d+)', out)[0])
+ ret['bytes_sent'] = int(re.findall('TX bytes:(\d+)', out)[0])
+ return ret
+
+ for name, stats in psutil.net_io_counters(pernic=True).items():
+ try:
+ ifconfig_ret = ifconfig(name)
+ except RuntimeError:
+ continue
+ self.assertAlmostEqual(
+ stats.bytes_recv, ifconfig_ret['bytes_recv'], delta=1024)
+ self.assertAlmostEqual(
+ stats.bytes_sent, ifconfig_ret['bytes_sent'], delta=1024)
+ self.assertAlmostEqual(
+ stats.packets_recv, ifconfig_ret['packets_recv'], delta=512)
+ self.assertAlmostEqual(
+ stats.packets_sent, ifconfig_ret['packets_sent'], delta=512)
+ self.assertAlmostEqual(
+ stats.errin, ifconfig_ret['errin'], delta=10)
+ self.assertAlmostEqual(
+ stats.errout, ifconfig_ret['errout'], delta=10)
+ self.assertAlmostEqual(
+ stats.dropin, ifconfig_ret['dropin'], delta=10)
+ self.assertAlmostEqual(
+ stats.dropout, ifconfig_ret['dropout'], delta=10)
+
@unittest.skipUnless(which('ip'), "'ip' utility not available")
@unittest.skipIf(TRAVIS, "skipped on Travis")
def test_net_if_names(self):
@@ -764,13 +812,16 @@ class TestProcess(unittest.TestCase):
time.sleep(.1)
mem = p.memory_full_info()
maps = p.memory_maps(grouped=False)
- self.assertEqual(
- mem.uss, sum([x.private_dirty + x.private_clean for x in maps]))
- self.assertEqual(
- mem.pss, sum([x.pss for x in maps]))
- self.assertEqual(
- mem.swap, sum([x.swap for x in maps]))
-
+ self.assertAlmostEqual(
+ mem.uss, sum([x.private_dirty + x.private_clean for x in maps]),
+ delta=4096)
+ self.assertAlmostEqual(
+ mem.pss, sum([x.pss for x in maps]), delta=4096)
+ self.assertAlmostEqual(
+ mem.swap, sum([x.swap for x in maps]), delta=4096)
+
+ # On PYPY file descriptors are not closed fast enough.
+ @unittest.skipIf(PYPY, "skipped on PYPY")
def test_open_files_mode(self):
def get_test_file():
p = psutil.Process()
diff --git a/psutil/tests/test_process.py b/psutil/tests/test_process.py
index c556caf0..79d28b19 100644
--- a/psutil/tests/test_process.py
+++ b/psutil/tests/test_process.py
@@ -65,6 +65,7 @@ from psutil.tests import get_test_subprocess
from psutil.tests import get_winver
from psutil.tests import GLOBAL_TIMEOUT
from psutil.tests import pyrun
+from psutil.tests import PYPY
from psutil.tests import PYTHON
from psutil.tests import reap_children
from psutil.tests import retry_before_failing
@@ -267,9 +268,11 @@ class TestProcess(unittest.TestCase):
def test_cpu_times(self):
times = psutil.Process().cpu_times()
assert (times.user > 0.0) or (times.system > 0.0), times
+ assert (times.children_user >= 0.0), times
+ assert (times.children_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))
+ for name in times._fields:
+ time.strftime("%H:%M:%S", time.localtime(getattr(times, name)))
# Test Process.cpu_times() against os.times()
# os.times() is broken on Python 2.6
@@ -279,8 +282,8 @@ class TestProcess(unittest.TestCase):
@unittest.skipUnless(sys.version_info > (2, 6, 1) and not OSX,
'os.times() is not reliable on this Python version')
- def test_cpu_times2(self):
- user_time, kernel_time = psutil.Process().cpu_times()
+ def test_cpu_times_2(self):
+ user_time, kernel_time = psutil.Process().cpu_times()[:2]
utime, ktime = os.times()[:2]
# Use os.times()[:2] as base values to compare our results
@@ -423,6 +426,11 @@ class TestProcess(unittest.TestCase):
self.assertGreaterEqual(value, 0)
if name in dir(resource):
self.assertEqual(value, getattr(resource, name))
+ # XXX - On PyPy RLIMIT_INFINITY returned by
+ # resource.getrlimit() is reported as a very big long
+ # number instead of -1. It looks like a bug with PyPy.
+ if PYPY:
+ continue
self.assertEqual(p.rlimit(value), resource.getrlimit(value))
else:
ret = p.rlimit(value)
diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py
index 4f73e181..4cbba7f8 100644
--- a/psutil/tests/test_system.py
+++ b/psutil/tests/test_system.py
@@ -31,7 +31,7 @@ from psutil import WINDOWS
from psutil._compat import long
from psutil.tests import AF_INET6
from psutil.tests import APPVEYOR
-from psutil.tests import check_ip_address
+from psutil.tests import check_net_address
from psutil.tests import DEVNULL
from psutil.tests import enum
from psutil.tests import get_test_subprocess
@@ -568,7 +568,7 @@ class TestSystemAPIs(unittest.TestCase):
# AddressValueError: Only hex digits permitted in
# u'c6f3%lxcbr0' in u'fe80::c8e0:fff:fe54:c6f3%lxcbr0'
if addr.family != AF_INET6:
- check_ip_address(ip, addr.family)
+ check_net_address(ip, addr.family)
# broadcast and ptp addresses are mutually exclusive
if addr.broadcast:
self.assertIsNone(addr.ptp)
@@ -583,6 +583,23 @@ class TestSystemAPIs(unittest.TestCase):
elif WINDOWS:
self.assertEqual(psutil.AF_LINK, -1)
+ def test_net_if_addrs_mac_null_bytes(self):
+ # Simulate that the underlying C function returns an incomplete
+ # MAC address. psutil is supposed to fill it with null bytes.
+ # https://github.com/giampaolo/psutil/issues/786
+ if POSIX:
+ ret = [('em1', psutil.AF_LINK, '06:3d:29', None, None, None)]
+ else:
+ ret = [('em1', -1, '06-3d-29', None, None, None)]
+ with mock.patch('psutil._psplatform.net_if_addrs',
+ return_value=ret) as m:
+ addr = psutil.net_if_addrs()['em1'][0]
+ assert m.called
+ if POSIX:
+ self.assertEqual(addr.address, '06:3d:29:00:00:00')
+ else:
+ self.assertEqual(addr.address, '06-3d-29-00-00-00')
+
@unittest.skipIf(TRAVIS, "EPERM on travis")
def test_net_if_stats(self):
nics = psutil.net_if_stats()