From df5112eb7c29eb1c2bda53d6f401dd62dddc67c7 Mon Sep 17 00:00:00 2001 From: mayeut Date: Sat, 27 Apr 2024 09:10:00 +0200 Subject: [PATCH] feat: add tests for linux aarch64 wheel Signed-off-by: mayeut --- psutil/tests/__init__.py | 7 ++++++- psutil/tests/test_contracts.py | 2 ++ psutil/tests/test_linux.py | 5 ++++- psutil/tests/test_memleaks.py | 9 +++++++++ psutil/tests/test_misc.py | 5 +++++ psutil/tests/test_posix.py | 7 ++++++- psutil/tests/test_process.py | 24 +++++++++++++++++++----- psutil/tests/test_process_all.py | 4 ++++ psutil/tests/test_system.py | 3 +++ pyproject.toml | 3 +-- 10 files changed, 59 insertions(+), 10 deletions(-) diff --git a/psutil/tests/__init__.py b/psutil/tests/__init__.py index e47a44cd6..dccb9e4b2 100644 --- a/psutil/tests/__init__.py +++ b/psutil/tests/__init__.py @@ -87,7 +87,7 @@ "HAS_IONICE", "HAS_MEMORY_MAPS", "HAS_PROC_CPU_NUM", "HAS_RLIMIT", "HAS_SENSORS_BATTERY", "HAS_BATTERY", "HAS_SENSORS_FANS", "HAS_SENSORS_TEMPERATURES", "HAS_NET_CONNECTIONS_UNIX", "MACOS_11PLUS", - "MACOS_12PLUS", "COVERAGE", 'AARCH64', + "MACOS_12PLUS", "COVERAGE", 'AARCH64', "QEMU_USER", # subprocesses 'pyrun', 'terminate', 'reap_children', 'spawn_testproc', 'spawn_zombie', 'spawn_children_pair', @@ -128,6 +128,11 @@ GITHUB_ACTIONS = 'GITHUB_ACTIONS' in os.environ or 'CIBUILDWHEEL' in os.environ CI_TESTING = APPVEYOR or GITHUB_ACTIONS COVERAGE = 'COVERAGE_RUN' in os.environ +if LINUX and GITHUB_ACTIONS: + with open('/proc/1/cmdline') as f: + QEMU_USER = "/bin/qemu-" in f.read() +else: + QEMU_USER = False # are we a 64 bit process? IS_64BIT = sys.maxsize > 2**32 AARCH64 = platform.machine() == "aarch64" diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py index e768e7d52..a5469ac8a 100755 --- a/psutil/tests/test_contracts.py +++ b/psutil/tests/test_contracts.py @@ -30,6 +30,7 @@ from psutil.tests import HAS_SENSORS_FANS from psutil.tests import HAS_SENSORS_TEMPERATURES from psutil.tests import PYPY +from psutil.tests import QEMU_USER from psutil.tests import SKIP_SYSCONS from psutil.tests import PsutilTestCase from psutil.tests import create_sockets @@ -277,6 +278,7 @@ def test_net_if_addrs(self): self.assertIsInstance(addr.netmask, (str, type(None))) self.assertIsInstance(addr.broadcast, (str, type(None))) + @unittest.skipIf(QEMU_USER, 'QEMU user not supported') def test_net_if_stats(self): # Duplicate of test_system.py. Keep it anyway. for ifname, info in psutil.net_if_stats().items(): diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py index 9fb48805a..d8faac968 100755 --- a/psutil/tests/test_linux.py +++ b/psutil/tests/test_linux.py @@ -36,6 +36,7 @@ from psutil.tests import HAS_GETLOADAVG from psutil.tests import HAS_RLIMIT from psutil.tests import PYPY +from psutil.tests import QEMU_USER from psutil.tests import TOLERANCE_DISK_USAGE from psutil.tests import TOLERANCE_SYS_MEM from psutil.tests import PsutilTestCase @@ -1051,6 +1052,7 @@ def test_ips(self): @unittest.skipIf(not LINUX, "LINUX only") +@unittest.skipIf(QEMU_USER, "QEMU user not supported") class TestSystemNetIfStats(PsutilTestCase): @unittest.skipIf(not which("ifconfig"), "ifconfig utility not available") def test_against_ifconfig(self): @@ -1610,7 +1612,7 @@ def test_issue_687(self): with ThreadTask(): p = psutil.Process() threads = p.threads() - self.assertEqual(len(threads), 2) + self.assertEqual(len(threads), 3 if QEMU_USER else 2) tid = sorted(threads, key=lambda x: x.id)[1].id self.assertNotEqual(p.pid, tid) pt = psutil.Process(tid) @@ -2290,6 +2292,7 @@ def test_name(self): value = self.read_status_file("Name:") self.assertEqual(self.proc.name(), value) + @unittest.skipIf(QEMU_USER, "QEMU user not supported") def test_status(self): value = self.read_status_file("State:") value = value[value.find('(') + 1 : value.rfind(')')] diff --git a/psutil/tests/test_memleaks.py b/psutil/tests/test_memleaks.py index 8232b18ad..6506497c9 100755 --- a/psutil/tests/test_memleaks.py +++ b/psutil/tests/test_memleaks.py @@ -19,6 +19,7 @@ import functools import os import platform +import sys import unittest import psutil @@ -43,6 +44,7 @@ from psutil.tests import HAS_SENSORS_BATTERY from psutil.tests import HAS_SENSORS_FANS from psutil.tests import HAS_SENSORS_TEMPERATURES +from psutil.tests import QEMU_USER from psutil.tests import TestMemoryLeak from psutil.tests import create_sockets from psutil.tests import get_testfn @@ -398,6 +400,7 @@ def test_disk_usage(self): times = FEW_TIMES if POSIX else self.times self.execute(lambda: psutil.disk_usage('.'), times=times) + @unittest.skipIf(QEMU_USER, "QEMU user not supported") def test_disk_partitions(self): self.execute(psutil.disk_partitions) @@ -435,6 +438,7 @@ def test_net_if_addrs(self): tolerance = 80 * 1024 if WINDOWS else self.tolerance self.execute(psutil.net_if_addrs, tolerance=tolerance) + @unittest.skipIf(QEMU_USER, "QEMU user not supported") def test_net_if_stats(self): self.execute(psutil.net_if_stats) @@ -491,6 +495,11 @@ def test_win_service_get_description(self): if __name__ == '__main__': + from psutil.tests.runner import cprint from psutil.tests.runner import run_from_name + if QEMU_USER: + cprint("skipping %s tests under QEMU_USER" % __file__, "brown") + sys.exit(0) + run_from_name(__file__) diff --git a/psutil/tests/test_misc.py b/psutil/tests/test_misc.py index 59416592e..5c05d1764 100755 --- a/psutil/tests/test_misc.py +++ b/psutil/tests/test_misc.py @@ -43,6 +43,7 @@ from psutil.tests import HAS_SENSORS_TEMPERATURES from psutil.tests import PYTHON_EXE from psutil.tests import PYTHON_EXE_ENV +from psutil.tests import QEMU_USER from psutil.tests import SCRIPTS_DIR from psutil.tests import PsutilTestCase from psutil.tests import mock @@ -288,6 +289,9 @@ def check(ret): for fun, name in ns.iter(ns.getters): if name in {"win_service_iter", "win_service_get"}: continue + if QEMU_USER and name == "net_if_stats": + # OSError: [Errno 38] ioctl(SIOCETHTOOL) not implemented + continue with self.subTest(name=name): try: ret = fun() @@ -1008,6 +1012,7 @@ def test_pstree(self): def test_netstat(self): self.assert_stdout('netstat.py') + @unittest.skipIf(QEMU_USER, 'QEMU user not supported') def test_ifconfig(self): self.assert_stdout('ifconfig.py') diff --git a/psutil/tests/test_posix.py b/psutil/tests/test_posix.py index 5203c2707..941f0fac1 100755 --- a/psutil/tests/test_posix.py +++ b/psutil/tests/test_posix.py @@ -25,6 +25,7 @@ from psutil import SUNOS from psutil.tests import HAS_NET_IO_COUNTERS from psutil.tests import PYTHON_EXE +from psutil.tests import QEMU_USER from psutil.tests import PsutilTestCase from psutil.tests import mock from psutil.tests import retry_on_failure @@ -102,7 +103,11 @@ def ps_name(pid): field = "command" if SUNOS: field = "comm" - return ps(field, pid).split()[0] + command = ps(field, pid).split() + if QEMU_USER: + assert "/bin/qemu-" in command[0] + return command[1] + return command[0] def ps_args(pid): diff --git a/psutil/tests/test_process.py b/psutil/tests/test_process.py index 1ee5393c2..363474c78 100755 --- a/psutil/tests/test_process.py +++ b/psutil/tests/test_process.py @@ -54,6 +54,7 @@ from psutil.tests import PYPY from psutil.tests import PYTHON_EXE from psutil.tests import PYTHON_EXE_ENV +from psutil.tests import QEMU_USER from psutil.tests import PsutilTestCase from psutil.tests import ThreadTask from psutil.tests import call_until @@ -253,6 +254,7 @@ def test_cpu_percent_numcpus_none(self): psutil.Process().cpu_percent() assert m.called + @unittest.skipIf(QEMU_USER, "QEMU user not supported") def test_cpu_times(self): times = psutil.Process().cpu_times() assert times.user >= 0.0, times @@ -265,6 +267,7 @@ def test_cpu_times(self): for name in times._fields: time.strftime("%H:%M:%S", time.localtime(getattr(times, name))) + @unittest.skipIf(QEMU_USER, "QEMU user not supported") def test_cpu_times_2(self): user_time, kernel_time = psutil.Process().cpu_times()[:2] utime, ktime = os.times()[:2] @@ -633,6 +636,8 @@ def test_memory_maps(self): for nt in maps: if not nt.path.startswith('['): + if QEMU_USER and "/bin/qemu-" in nt.path: + continue assert os.path.isabs(nt.path), nt.path if POSIX: try: @@ -698,6 +703,7 @@ def test_is_running(self): assert not p.is_running() assert not p.is_running() + @unittest.skipIf(QEMU_USER, "QEMU user not supported") def test_exe(self): p = self.spawn_psproc() exe = p.exe() @@ -754,6 +760,9 @@ def test_cmdline(self): ' '.join(p.cmdline()[1:]), ' '.join(cmdline[1:]) ) return + if QEMU_USER: + self.assertEqual(' '.join(p.cmdline()[2:]), ' '.join(cmdline)) + return self.assertEqual(' '.join(p.cmdline()), ' '.join(cmdline)) @unittest.skipIf(PYPY, "broken on PYPY") @@ -771,13 +780,14 @@ def test_long_cmdline(self): self.assertEqual(p.cmdline(), cmdline) except psutil.ZombieProcess: raise unittest.SkipTest("OPENBSD: process turned into zombie") - elif NETBSD: + elif QEMU_USER: + self.assertEqual(p.cmdline()[2:], cmdline) + else: ret = p.cmdline() - if ret == []: + if NETBSD and ret == []: # https://github.com/giampaolo/psutil/issues/2250 raise unittest.SkipTest("OPENBSD: returned EBUSY") - - self.assertEqual(p.cmdline(), cmdline) + self.assertEqual(ret, cmdline) def test_name(self): p = self.spawn_psproc() @@ -785,7 +795,8 @@ def test_name(self): pyexe = os.path.basename(os.path.realpath(sys.executable)).lower() assert pyexe.startswith(name), (pyexe, name) - @unittest.skipIf(PYPY, "unreliable on PYPY") + @unittest.skipIf(PYPY or QEMU_USER, "unreliable on PYPY") + @unittest.skipIf(QEMU_USER, "unreliable on QEMU user") def test_long_name(self): pyexe = create_py_exe(self.get_testfn(suffix="0123456789" * 2)) cmdline = [ @@ -816,6 +827,7 @@ def test_long_name(self): @unittest.skipIf(SUNOS, "broken on SUNOS") @unittest.skipIf(AIX, "broken on AIX") @unittest.skipIf(PYPY, "broken on PYPY") + @unittest.skipIf(QEMU_USER, "broken on QEMU user") def test_prog_w_funky_name(self): # Test that name(), exe() and cmdline() correctly handle programs # with funky chars such as spaces and ")", see: @@ -922,6 +934,7 @@ def cleanup(init): except psutil.AccessDenied: pass + @unittest.skipIf(QEMU_USER, "QEMU user not supported") def test_status(self): p = psutil.Process() self.assertEqual(p.status(), psutil.STATUS_RUNNING) @@ -1149,6 +1162,7 @@ def test_parent_multi(self): self.assertEqual(grandchild.parent(), child) self.assertEqual(child.parent(), parent) + @unittest.skipIf(QEMU_USER, "QEMU user not supported") @retry_on_failure() def test_parents(self): parent = psutil.Process() diff --git a/psutil/tests/test_process_all.py b/psutil/tests/test_process_all.py index d1f476bb5..48833a105 100755 --- a/psutil/tests/test_process_all.py +++ b/psutil/tests/test_process_all.py @@ -32,6 +32,7 @@ from psutil._compat import long from psutil._compat import unicode from psutil.tests import CI_TESTING +from psutil.tests import QEMU_USER from psutil.tests import VALID_PROC_STATUSES from psutil.tests import PsutilTestCase from psutil.tests import check_connection_ntuple @@ -235,6 +236,9 @@ def username(self, ret, info): def status(self, ret, info): self.assertIsInstance(ret, str) assert ret, ret + if QEMU_USER: + # status does not work under qemu user + return self.assertNotEqual(ret, '?') # XXX self.assertIn(ret, VALID_PROC_STATUSES) diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py index 554fbffb2..e228f6d32 100755 --- a/psutil/tests/test_system.py +++ b/psutil/tests/test_system.py @@ -48,6 +48,7 @@ from psutil.tests import IS_64BIT from psutil.tests import MACOS_12PLUS from psutil.tests import PYPY +from psutil.tests import QEMU_USER from psutil.tests import UNICODE_SUFFIX from psutil.tests import PsutilTestCase from psutil.tests import check_net_address @@ -806,6 +807,7 @@ def test_net_io_counters_no_nics(self): self.assertEqual(psutil.net_io_counters(pernic=True), {}) assert m.called + @unittest.skipIf(QEMU_USER, 'QEMU user not supported') def test_net_if_addrs(self): nics = psutil.net_if_addrs() assert nics, nics @@ -893,6 +895,7 @@ def test_net_if_addrs_mac_null_bytes(self): else: self.assertEqual(addr.address, '06-3d-29-00-00-00') + @unittest.skipIf(QEMU_USER, 'QEMU user not supported') def test_net_if_stats(self): nics = psutil.net_if_stats() assert nics, nics diff --git a/pyproject.toml b/pyproject.toml index b4d858d01..ba13f2829 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -207,10 +207,9 @@ trailing_comma_inline_array = true skip = [ "*-musllinux*", "cp313-win*", # pywin32 is not available on cp313 yet + "cp3{7,8,9,10,11,12}-*linux_{aarch64,ppc64le,s390x}", # Only test cp36/cp313 on qemu tested architectures "pp*", ] -# Will avoid testing on emulated architectures -test-skip = "*-*linux_{aarch64,ppc64le,s390x}" test-command = [ "env PYTHONWARNINGS=always PYTHONUNBUFFERED=1 PSUTIL_DEBUG=1 PSUTIL_SCRIPTS_DIR={project}/scripts python {project}/psutil/tests/runner.py", "env PYTHONWARNINGS=always PYTHONUNBUFFERED=1 PSUTIL_DEBUG=1 PSUTIL_SCRIPTS_DIR={project}/scripts python {project}/psutil/tests/test_memleaks.py",