Download .venv/Lib/site-packages/psutil/tests/test_misc.py from DrDavis/PythonProject1: direct link, hf CLI and curl.
- Browser
- Download file 30.5 kB
-
https://huggingface.co/DrDavis/PythonProject1/resolve/main/.venv/Lib/site-packages/psutil/tests/test_misc.py
- Command line
-
hf download hf://DrDavis/PythonProject1/.venv/Lib/site-packages/psutil/tests/test_misc.py
-
curl -L -o test_misc.py https://huggingface.co/DrDavis/PythonProject1/resolve/main/.venv/Lib/site-packages/psutil/tests/test_misc.py
30.5 kB
| #!/usr/bin/env python3 | |
| # Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| """Miscellaneous tests.""" | |
| import collections | |
| import contextlib | |
| import io | |
| import json | |
| import os | |
| import pickle | |
| import socket | |
| import sys | |
| from unittest import mock | |
| import psutil | |
| import psutil.tests | |
| from psutil import WINDOWS | |
| from psutil._common import bcat | |
| from psutil._common import cat | |
| from psutil._common import debug | |
| from psutil._common import isfile_strict | |
| from psutil._common import memoize | |
| from psutil._common import memoize_when_activated | |
| from psutil._common import parse_environ_block | |
| from psutil._common import supports_ipv6 | |
| from psutil._common import wrap_numbers | |
| from psutil.tests import HAS_NET_IO_COUNTERS | |
| from psutil.tests import PsutilTestCase | |
| from psutil.tests import process_namespace | |
| from psutil.tests import pytest | |
| from psutil.tests import reload_module | |
| from psutil.tests import system_namespace | |
| # =================================================================== | |
| # --- Test classes' repr(), str(), ... | |
| # =================================================================== | |
| class TestSpecialMethods(PsutilTestCase): | |
| def test_check_pid_range(self): | |
| with pytest.raises(OverflowError): | |
| psutil._psplatform.cext.check_pid_range(2**128) | |
| with pytest.raises(psutil.NoSuchProcess): | |
| psutil.Process(2**128) | |
| def test_process__repr__(self, func=repr): | |
| p = psutil.Process(self.spawn_testproc().pid) | |
| r = func(p) | |
| assert "psutil.Process" in r | |
| assert f"pid={p.pid}" in r | |
| assert f"name='{p.name()}'" in r.replace("name=u'", "name='") | |
| assert "status=" in r | |
| assert "exitcode=" not in r | |
| p.terminate() | |
| p.wait() | |
| r = func(p) | |
| assert "status='terminated'" in r | |
| assert "exitcode=" in r | |
| with mock.patch.object( | |
| psutil.Process, | |
| "name", | |
| side_effect=psutil.ZombieProcess(os.getpid()), | |
| ): | |
| p = psutil.Process() | |
| r = func(p) | |
| assert f"pid={p.pid}" in r | |
| assert "status='zombie'" in r | |
| assert "name=" not in r | |
| with mock.patch.object( | |
| psutil.Process, | |
| "name", | |
| side_effect=psutil.NoSuchProcess(os.getpid()), | |
| ): | |
| p = psutil.Process() | |
| r = func(p) | |
| assert f"pid={p.pid}" in r | |
| assert "terminated" in r | |
| assert "name=" not in r | |
| with mock.patch.object( | |
| psutil.Process, | |
| "name", | |
| side_effect=psutil.AccessDenied(os.getpid()), | |
| ): | |
| p = psutil.Process() | |
| r = func(p) | |
| assert f"pid={p.pid}" in r | |
| assert "name=" not in r | |
| def test_process__str__(self): | |
| self.test_process__repr__(func=str) | |
| def test_error__repr__(self): | |
| assert repr(psutil.Error()) == "psutil.Error()" | |
| def test_error__str__(self): | |
| assert str(psutil.Error()) == "" | |
| def test_no_such_process__repr__(self): | |
| assert ( | |
| repr(psutil.NoSuchProcess(321)) | |
| == "psutil.NoSuchProcess(pid=321, msg='process no longer exists')" | |
| ) | |
| assert ( | |
| repr(psutil.NoSuchProcess(321, name="name", msg="msg")) | |
| == "psutil.NoSuchProcess(pid=321, name='name', msg='msg')" | |
| ) | |
| def test_no_such_process__str__(self): | |
| assert ( | |
| str(psutil.NoSuchProcess(321)) | |
| == "process no longer exists (pid=321)" | |
| ) | |
| assert ( | |
| str(psutil.NoSuchProcess(321, name="name", msg="msg")) | |
| == "msg (pid=321, name='name')" | |
| ) | |
| def test_zombie_process__repr__(self): | |
| assert ( | |
| repr(psutil.ZombieProcess(321)) | |
| == 'psutil.ZombieProcess(pid=321, msg="PID still ' | |
| 'exists but it\'s a zombie")' | |
| ) | |
| assert ( | |
| repr(psutil.ZombieProcess(321, name="name", ppid=320, msg="foo")) | |
| == "psutil.ZombieProcess(pid=321, ppid=320, name='name'," | |
| " msg='foo')" | |
| ) | |
| def test_zombie_process__str__(self): | |
| assert ( | |
| str(psutil.ZombieProcess(321)) | |
| == "PID still exists but it's a zombie (pid=321)" | |
| ) | |
| assert ( | |
| str(psutil.ZombieProcess(321, name="name", ppid=320, msg="foo")) | |
| == "foo (pid=321, ppid=320, name='name')" | |
| ) | |
| def test_access_denied__repr__(self): | |
| assert repr(psutil.AccessDenied(321)) == "psutil.AccessDenied(pid=321)" | |
| assert ( | |
| repr(psutil.AccessDenied(321, name="name", msg="msg")) | |
| == "psutil.AccessDenied(pid=321, name='name', msg='msg')" | |
| ) | |
| def test_access_denied__str__(self): | |
| assert str(psutil.AccessDenied(321)) == "(pid=321)" | |
| assert ( | |
| str(psutil.AccessDenied(321, name="name", msg="msg")) | |
| == "msg (pid=321, name='name')" | |
| ) | |
| def test_timeout_expired__repr__(self): | |
| assert ( | |
| repr(psutil.TimeoutExpired(5)) | |
| == "psutil.TimeoutExpired(seconds=5, msg='timeout after 5" | |
| " seconds')" | |
| ) | |
| assert ( | |
| repr(psutil.TimeoutExpired(5, pid=321, name="name")) | |
| == "psutil.TimeoutExpired(pid=321, name='name', seconds=5, " | |
| "msg='timeout after 5 seconds')" | |
| ) | |
| def test_timeout_expired__str__(self): | |
| assert str(psutil.TimeoutExpired(5)) == "timeout after 5 seconds" | |
| assert ( | |
| str(psutil.TimeoutExpired(5, pid=321, name="name")) | |
| == "timeout after 5 seconds (pid=321, name='name')" | |
| ) | |
| def test_process__eq__(self): | |
| p1 = psutil.Process() | |
| p2 = psutil.Process() | |
| assert p1 == p2 | |
| p2._ident = (0, 0) | |
| assert p1 != p2 | |
| assert p1 != 'foo' | |
| def test_process__hash__(self): | |
| s = {psutil.Process(), psutil.Process()} | |
| assert len(s) == 1 | |
| # =================================================================== | |
| # --- Misc, generic, corner cases | |
| # =================================================================== | |
| class TestMisc(PsutilTestCase): | |
| def test__all__(self): | |
| dir_psutil = dir(psutil) | |
| for name in dir_psutil: | |
| if name in { | |
| 'debug', | |
| 'tests', | |
| 'test', | |
| 'PermissionError', | |
| 'ProcessLookupError', | |
| }: | |
| 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() | |
| ): | |
| raise self.fail(f"{name!r} not in psutil.__all__") | |
| # Import 'star' will break if __all__ is inconsistent, see: | |
| # https://github.com/giampaolo/psutil/issues/656 | |
| # Can't do `from psutil import *` as it won't work | |
| # so we simply iterate over __all__. | |
| for name in psutil.__all__: | |
| assert name in dir_psutil | |
| def test_version(self): | |
| assert ( | |
| '.'.join([str(x) for x in psutil.version_info]) | |
| == psutil.__version__ | |
| ) | |
| def test_process_as_dict_no_new_names(self): | |
| # See https://github.com/giampaolo/psutil/issues/813 | |
| p = psutil.Process() | |
| p.foo = '1' | |
| assert 'foo' not in p.as_dict() | |
| def test_serialization(self): | |
| def check(ret): | |
| json.loads(json.dumps(ret)) | |
| a = pickle.dumps(ret) | |
| b = pickle.loads(a) | |
| assert ret == b | |
| # --- process APIs | |
| proc = psutil.Process() | |
| check(psutil.Process().as_dict()) | |
| ns = process_namespace(proc) | |
| for fun, name in ns.iter(ns.getters, clear_cache=True): | |
| with self.subTest(proc=proc, name=name): | |
| try: | |
| ret = fun() | |
| except psutil.Error: | |
| pass | |
| else: | |
| check(ret) | |
| # --- system APIs | |
| ns = system_namespace() | |
| for fun, name in ns.iter(ns.getters): | |
| if name in {"win_service_iter", "win_service_get"}: | |
| continue | |
| with self.subTest(name=name): | |
| try: | |
| ret = fun() | |
| except psutil.AccessDenied: | |
| pass | |
| else: | |
| check(ret) | |
| # --- exception classes | |
| b = pickle.loads( | |
| pickle.dumps( | |
| psutil.NoSuchProcess(pid=4567, name='name', msg='msg') | |
| ) | |
| ) | |
| assert isinstance(b, psutil.NoSuchProcess) | |
| assert b.pid == 4567 | |
| assert b.name == 'name' | |
| assert b.msg == 'msg' | |
| b = pickle.loads( | |
| pickle.dumps( | |
| psutil.ZombieProcess(pid=4567, name='name', ppid=42, msg='msg') | |
| ) | |
| ) | |
| assert isinstance(b, psutil.ZombieProcess) | |
| assert b.pid == 4567 | |
| assert b.ppid == 42 | |
| assert b.name == 'name' | |
| assert b.msg == 'msg' | |
| b = pickle.loads( | |
| pickle.dumps(psutil.AccessDenied(pid=123, name='name', msg='msg')) | |
| ) | |
| assert isinstance(b, psutil.AccessDenied) | |
| assert b.pid == 123 | |
| assert b.name == 'name' | |
| assert b.msg == 'msg' | |
| b = pickle.loads( | |
| pickle.dumps( | |
| psutil.TimeoutExpired(seconds=33, pid=4567, name='name') | |
| ) | |
| ) | |
| assert isinstance(b, psutil.TimeoutExpired) | |
| assert b.seconds == 33 | |
| assert b.pid == 4567 | |
| assert b.name == 'name' | |
| def test_ad_on_process_creation(self): | |
| # We are supposed to be able to instantiate Process also in case | |
| # of zombie processes or access denied. | |
| with mock.patch.object( | |
| psutil.Process, '_get_ident', side_effect=psutil.AccessDenied | |
| ) as meth: | |
| psutil.Process() | |
| assert meth.called | |
| with mock.patch.object( | |
| psutil.Process, '_get_ident', side_effect=psutil.ZombieProcess(1) | |
| ) as meth: | |
| psutil.Process() | |
| assert meth.called | |
| with mock.patch.object( | |
| psutil.Process, '_get_ident', side_effect=ValueError | |
| ) as meth: | |
| with pytest.raises(ValueError): | |
| psutil.Process() | |
| assert meth.called | |
| with mock.patch.object( | |
| psutil.Process, '_get_ident', side_effect=psutil.NoSuchProcess(1) | |
| ) as meth: | |
| with self.assertRaises(psutil.NoSuchProcess): | |
| psutil.Process() | |
| assert meth.called | |
| def test_sanity_version_check(self): | |
| # see: https://github.com/giampaolo/psutil/issues/564 | |
| with mock.patch( | |
| "psutil._psplatform.cext.version", return_value="0.0.0" | |
| ): | |
| with pytest.raises(ImportError) as cm: | |
| reload_module(psutil) | |
| assert "version conflict" in str(cm.value).lower() | |
| # =================================================================== | |
| # --- psutil/_common.py utils | |
| # =================================================================== | |
| class TestMemoizeDecorator(PsutilTestCase): | |
| def setUp(self): | |
| self.calls = [] | |
| tearDown = setUp | |
| def run_against(self, obj, expected_retval=None): | |
| # no args | |
| for _ in range(2): | |
| ret = obj() | |
| assert self.calls == [((), {})] | |
| if expected_retval is not None: | |
| assert ret == expected_retval | |
| # with args | |
| for _ in range(2): | |
| ret = obj(1) | |
| assert self.calls == [((), {}), ((1,), {})] | |
| if expected_retval is not None: | |
| assert ret == expected_retval | |
| # with args + kwargs | |
| for _ in range(2): | |
| ret = obj(1, bar=2) | |
| assert self.calls == [((), {}), ((1,), {}), ((1,), {'bar': 2})] | |
| if expected_retval is not None: | |
| assert ret == expected_retval | |
| # clear cache | |
| assert len(self.calls) == 3 | |
| obj.cache_clear() | |
| ret = obj() | |
| if expected_retval is not None: | |
| assert ret == expected_retval | |
| assert len(self.calls) == 4 | |
| # docstring | |
| assert obj.__doc__ == "My docstring." | |
| def test_function(self): | |
| def foo(*args, **kwargs): | |
| """My docstring.""" | |
| baseclass.calls.append((args, kwargs)) | |
| return 22 | |
| baseclass = self | |
| self.run_against(foo, expected_retval=22) | |
| def test_class(self): | |
| class Foo: | |
| """My docstring.""" | |
| def __init__(self, *args, **kwargs): | |
| baseclass.calls.append((args, kwargs)) | |
| def bar(self): | |
| return 22 | |
| baseclass = self | |
| self.run_against(Foo, expected_retval=None) | |
| assert Foo().bar() == 22 | |
| def test_class_singleton(self): | |
| # @memoize can be used against classes to create singletons | |
| class Bar: | |
| def __init__(self, *args, **kwargs): | |
| pass | |
| assert Bar() is Bar() | |
| assert id(Bar()) == id(Bar()) | |
| assert id(Bar(1)) == id(Bar(1)) | |
| assert id(Bar(1, foo=3)) == id(Bar(1, foo=3)) | |
| assert id(Bar(1)) != id(Bar(2)) | |
| def test_staticmethod(self): | |
| class Foo: | |
| def bar(*args, **kwargs): | |
| """My docstring.""" | |
| baseclass.calls.append((args, kwargs)) | |
| return 22 | |
| baseclass = self | |
| self.run_against(Foo().bar, expected_retval=22) | |
| def test_classmethod(self): | |
| class Foo: | |
| def bar(cls, *args, **kwargs): | |
| """My docstring.""" | |
| baseclass.calls.append((args, kwargs)) | |
| return 22 | |
| baseclass = self | |
| self.run_against(Foo().bar, expected_retval=22) | |
| def test_original(self): | |
| # This was the original test before I made it dynamic to test it | |
| # against different types. Keeping it anyway. | |
| def foo(*args, **kwargs): | |
| """Foo docstring.""" | |
| calls.append(None) | |
| return (args, kwargs) | |
| calls = [] | |
| # no args | |
| for _ in range(2): | |
| ret = foo() | |
| expected = ((), {}) | |
| assert ret == expected | |
| assert len(calls) == 1 | |
| # with args | |
| for _ in range(2): | |
| ret = foo(1) | |
| expected = ((1,), {}) | |
| assert ret == expected | |
| assert len(calls) == 2 | |
| # with args + kwargs | |
| for _ in range(2): | |
| ret = foo(1, bar=2) | |
| expected = ((1,), {'bar': 2}) | |
| assert ret == expected | |
| assert len(calls) == 3 | |
| # clear cache | |
| foo.cache_clear() | |
| ret = foo() | |
| expected = ((), {}) | |
| assert ret == expected | |
| assert len(calls) == 4 | |
| # docstring | |
| assert foo.__doc__ == "Foo docstring." | |
| class TestCommonModule(PsutilTestCase): | |
| def test_memoize_when_activated(self): | |
| class Foo: | |
| def foo(self): | |
| calls.append(None) | |
| f = Foo() | |
| calls = [] | |
| f.foo() | |
| f.foo() | |
| assert len(calls) == 2 | |
| # activate | |
| calls = [] | |
| f.foo.cache_activate(f) | |
| f.foo() | |
| f.foo() | |
| assert len(calls) == 1 | |
| # deactivate | |
| calls = [] | |
| f.foo.cache_deactivate(f) | |
| f.foo() | |
| f.foo() | |
| assert len(calls) == 2 | |
| def test_parse_environ_block(self): | |
| def k(s): | |
| return s.upper() if WINDOWS else s | |
| assert parse_environ_block("a=1\0") == {k("a"): "1"} | |
| assert parse_environ_block("a=1\0b=2\0\0") == { | |
| k("a"): "1", | |
| k("b"): "2", | |
| } | |
| assert parse_environ_block("a=1\0b=\0\0") == {k("a"): "1", k("b"): ""} | |
| # ignore everything after \0\0 | |
| assert parse_environ_block("a=1\0b=2\0\0c=3\0") == { | |
| k("a"): "1", | |
| k("b"): "2", | |
| } | |
| # ignore everything that is not an assignment | |
| assert parse_environ_block("xxx\0a=1\0") == {k("a"): "1"} | |
| assert parse_environ_block("a=1\0=b=2\0") == {k("a"): "1"} | |
| # do not fail if the block is incomplete | |
| assert parse_environ_block("a=1\0b=2") == {k("a"): "1"} | |
| def test_supports_ipv6(self): | |
| self.addCleanup(supports_ipv6.cache_clear) | |
| if supports_ipv6(): | |
| with mock.patch('psutil._common.socket') as s: | |
| s.has_ipv6 = False | |
| supports_ipv6.cache_clear() | |
| assert not supports_ipv6() | |
| supports_ipv6.cache_clear() | |
| with mock.patch( | |
| 'psutil._common.socket.socket', side_effect=OSError | |
| ) as s: | |
| assert not supports_ipv6() | |
| assert s.called | |
| supports_ipv6.cache_clear() | |
| with mock.patch( | |
| 'psutil._common.socket.socket', side_effect=socket.gaierror | |
| ) as s: | |
| assert not supports_ipv6() | |
| supports_ipv6.cache_clear() | |
| assert s.called | |
| supports_ipv6.cache_clear() | |
| with mock.patch( | |
| 'psutil._common.socket.socket.bind', | |
| side_effect=socket.gaierror, | |
| ) as s: | |
| assert not supports_ipv6() | |
| supports_ipv6.cache_clear() | |
| assert s.called | |
| else: | |
| with pytest.raises(OSError): | |
| sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) | |
| try: | |
| sock.bind(("::1", 0)) | |
| finally: | |
| sock.close() | |
| def test_isfile_strict(self): | |
| this_file = os.path.abspath(__file__) | |
| assert isfile_strict(this_file) | |
| assert not isfile_strict(os.path.dirname(this_file)) | |
| with mock.patch('psutil._common.os.stat', side_effect=PermissionError): | |
| with pytest.raises(OSError): | |
| isfile_strict(this_file) | |
| with mock.patch( | |
| 'psutil._common.os.stat', side_effect=FileNotFoundError | |
| ): | |
| assert not isfile_strict(this_file) | |
| with mock.patch('psutil._common.stat.S_ISREG', return_value=False): | |
| assert not isfile_strict(this_file) | |
| def test_debug(self): | |
| with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True): | |
| with contextlib.redirect_stderr(io.StringIO()) as f: | |
| debug("hello") | |
| sys.stderr.flush() | |
| msg = f.getvalue() | |
| assert msg.startswith("psutil-debug"), msg | |
| assert "hello" in msg | |
| assert __file__.replace('.pyc', '.py') in msg | |
| # supposed to use repr(exc) | |
| with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True): | |
| with contextlib.redirect_stderr(io.StringIO()) as f: | |
| debug(ValueError("this is an error")) | |
| msg = f.getvalue() | |
| assert "ignoring ValueError" in msg | |
| assert "'this is an error'" in msg | |
| # supposed to use str(exc), because of extra info about file name | |
| with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True): | |
| with contextlib.redirect_stderr(io.StringIO()) as f: | |
| exc = OSError(2, "no such file") | |
| exc.filename = "/foo" | |
| debug(exc) | |
| msg = f.getvalue() | |
| assert "no such file" in msg | |
| assert "/foo" in msg | |
| def test_cat_bcat(self): | |
| testfn = self.get_testfn() | |
| with open(testfn, "w") as f: | |
| f.write("foo") | |
| assert cat(testfn) == "foo" | |
| assert bcat(testfn) == b"foo" | |
| with pytest.raises(FileNotFoundError): | |
| cat(testfn + '-invalid') | |
| with pytest.raises(FileNotFoundError): | |
| bcat(testfn + '-invalid') | |
| assert cat(testfn + '-invalid', fallback="bar") == "bar" | |
| assert bcat(testfn + '-invalid', fallback="bar") == "bar" | |
| # =================================================================== | |
| # --- Tests for wrap_numbers() function. | |
| # =================================================================== | |
| nt = collections.namedtuple('foo', 'a b c') | |
| class TestWrapNumbers(PsutilTestCase): | |
| def setUp(self): | |
| wrap_numbers.cache_clear() | |
| tearDown = setUp | |
| def test_first_call(self): | |
| input = {'disk1': nt(5, 5, 5)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| def test_input_hasnt_changed(self): | |
| input = {'disk1': nt(5, 5, 5)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| assert wrap_numbers(input, 'disk_io') == input | |
| def test_increase_but_no_wrap(self): | |
| input = {'disk1': nt(5, 5, 5)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| input = {'disk1': nt(10, 15, 20)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| input = {'disk1': nt(20, 25, 30)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| input = {'disk1': nt(20, 25, 30)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| def test_wrap(self): | |
| # let's say 100 is the threshold | |
| input = {'disk1': nt(100, 100, 100)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| # first wrap restarts from 10 | |
| input = {'disk1': nt(100, 100, 10)} | |
| assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 110)} | |
| # then it remains the same | |
| input = {'disk1': nt(100, 100, 10)} | |
| assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 110)} | |
| # then it goes up | |
| input = {'disk1': nt(100, 100, 90)} | |
| assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 190)} | |
| # then it wraps again | |
| input = {'disk1': nt(100, 100, 20)} | |
| assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 210)} | |
| # and remains the same | |
| input = {'disk1': nt(100, 100, 20)} | |
| assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 210)} | |
| # now wrap another num | |
| input = {'disk1': nt(50, 100, 20)} | |
| assert wrap_numbers(input, 'disk_io') == {'disk1': nt(150, 100, 210)} | |
| # and again | |
| input = {'disk1': nt(40, 100, 20)} | |
| assert wrap_numbers(input, 'disk_io') == {'disk1': nt(190, 100, 210)} | |
| # keep it the same | |
| input = {'disk1': nt(40, 100, 20)} | |
| assert wrap_numbers(input, 'disk_io') == {'disk1': nt(190, 100, 210)} | |
| def test_changing_keys(self): | |
| # Emulate a case where the second call to disk_io() | |
| # (or whatever) provides a new disk, then the new disk | |
| # disappears on the third call. | |
| input = {'disk1': nt(5, 5, 5)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| input = {'disk1': nt(5, 5, 5), 'disk2': nt(7, 7, 7)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| input = {'disk1': nt(8, 8, 8)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| def test_changing_keys_w_wrap(self): | |
| input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 100)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| # disk 2 wraps | |
| input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 10)} | |
| assert wrap_numbers(input, 'disk_io') == { | |
| 'disk1': nt(50, 50, 50), | |
| 'disk2': nt(100, 100, 110), | |
| } | |
| # disk 2 disappears | |
| input = {'disk1': nt(50, 50, 50)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| # then it appears again; the old wrap is supposed to be | |
| # gone. | |
| input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 100)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| # remains the same | |
| input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 100)} | |
| assert wrap_numbers(input, 'disk_io') == input | |
| # and then wraps again | |
| input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 10)} | |
| assert wrap_numbers(input, 'disk_io') == { | |
| 'disk1': nt(50, 50, 50), | |
| 'disk2': nt(100, 100, 110), | |
| } | |
| def test_real_data(self): | |
| d = { | |
| 'nvme0n1': (300, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048), | |
| 'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8), | |
| 'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28), | |
| 'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348), | |
| } | |
| assert wrap_numbers(d, 'disk_io') == d | |
| assert wrap_numbers(d, 'disk_io') == d | |
| # decrease this ↓ | |
| d = { | |
| 'nvme0n1': (100, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048), | |
| 'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8), | |
| 'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28), | |
| 'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348), | |
| } | |
| out = wrap_numbers(d, 'disk_io') | |
| assert out['nvme0n1'][0] == 400 | |
| # --- cache tests | |
| def test_cache_first_call(self): | |
| input = {'disk1': nt(5, 5, 5)} | |
| wrap_numbers(input, 'disk_io') | |
| cache = wrap_numbers.cache_info() | |
| assert cache[0] == {'disk_io': input} | |
| assert cache[1] == {'disk_io': {}} | |
| assert cache[2] == {'disk_io': {}} | |
| def test_cache_call_twice(self): | |
| input = {'disk1': nt(5, 5, 5)} | |
| wrap_numbers(input, 'disk_io') | |
| input = {'disk1': nt(10, 10, 10)} | |
| wrap_numbers(input, 'disk_io') | |
| cache = wrap_numbers.cache_info() | |
| assert cache[0] == {'disk_io': input} | |
| assert cache[1] == { | |
| 'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0} | |
| } | |
| assert cache[2] == {'disk_io': {}} | |
| def test_cache_wrap(self): | |
| # let's say 100 is the threshold | |
| input = {'disk1': nt(100, 100, 100)} | |
| wrap_numbers(input, 'disk_io') | |
| # first wrap restarts from 10 | |
| input = {'disk1': nt(100, 100, 10)} | |
| wrap_numbers(input, 'disk_io') | |
| cache = wrap_numbers.cache_info() | |
| assert cache[0] == {'disk_io': input} | |
| assert cache[1] == { | |
| 'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 100} | |
| } | |
| assert cache[2] == {'disk_io': {'disk1': {('disk1', 2)}}} | |
| def check_cache_info(): | |
| cache = wrap_numbers.cache_info() | |
| assert cache[1] == { | |
| 'disk_io': { | |
| ('disk1', 0): 0, | |
| ('disk1', 1): 0, | |
| ('disk1', 2): 100, | |
| } | |
| } | |
| assert cache[2] == {'disk_io': {'disk1': {('disk1', 2)}}} | |
| # then it remains the same | |
| input = {'disk1': nt(100, 100, 10)} | |
| wrap_numbers(input, 'disk_io') | |
| cache = wrap_numbers.cache_info() | |
| assert cache[0] == {'disk_io': input} | |
| check_cache_info() | |
| # then it goes up | |
| input = {'disk1': nt(100, 100, 90)} | |
| wrap_numbers(input, 'disk_io') | |
| cache = wrap_numbers.cache_info() | |
| assert cache[0] == {'disk_io': input} | |
| check_cache_info() | |
| # then it wraps again | |
| input = {'disk1': nt(100, 100, 20)} | |
| wrap_numbers(input, 'disk_io') | |
| cache = wrap_numbers.cache_info() | |
| assert cache[0] == {'disk_io': input} | |
| assert cache[1] == { | |
| 'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 190} | |
| } | |
| assert cache[2] == {'disk_io': {'disk1': {('disk1', 2)}}} | |
| def test_cache_changing_keys(self): | |
| input = {'disk1': nt(5, 5, 5)} | |
| wrap_numbers(input, 'disk_io') | |
| input = {'disk1': nt(5, 5, 5), 'disk2': nt(7, 7, 7)} | |
| wrap_numbers(input, 'disk_io') | |
| cache = wrap_numbers.cache_info() | |
| assert cache[0] == {'disk_io': input} | |
| assert cache[1] == { | |
| 'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0} | |
| } | |
| assert cache[2] == {'disk_io': {}} | |
| def test_cache_clear(self): | |
| input = {'disk1': nt(5, 5, 5)} | |
| wrap_numbers(input, 'disk_io') | |
| wrap_numbers(input, 'disk_io') | |
| wrap_numbers.cache_clear('disk_io') | |
| assert wrap_numbers.cache_info() == ({}, {}, {}) | |
| wrap_numbers.cache_clear('disk_io') | |
| wrap_numbers.cache_clear('?!?') | |
| def test_cache_clear_public_apis(self): | |
| if not psutil.disk_io_counters() or not psutil.net_io_counters(): | |
| raise pytest.skip("no disks or NICs available") | |
| psutil.disk_io_counters() | |
| psutil.net_io_counters() | |
| caches = wrap_numbers.cache_info() | |
| for cache in caches: | |
| assert 'psutil.disk_io_counters' in cache | |
| assert 'psutil.net_io_counters' in cache | |
| psutil.disk_io_counters.cache_clear() | |
| caches = wrap_numbers.cache_info() | |
| for cache in caches: | |
| assert 'psutil.net_io_counters' in cache | |
| assert 'psutil.disk_io_counters' not in cache | |
| psutil.net_io_counters.cache_clear() | |
| caches = wrap_numbers.cache_info() | |
| assert caches == ({}, {}, {}) | |