From 8091fa5999d2ac5c83e4aaf99a5560dc63dbee4b Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 25 Feb 2022 07:41:36 +0000 Subject: [PATCH] Improves robustness of some tests that were too environment-specific (#2080) Signed-off-by: Steve Dower --- psutil/tests/test_process.py | 28 ++++++++++++++++++++++------ psutil/tests/test_windows.py | 28 ++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/psutil/tests/test_process.py b/psutil/tests/test_process.py index 2a2af93c6..181097e3b 100755 --- a/psutil/tests/test_process.py +++ b/psutil/tests/test_process.py @@ -799,19 +799,29 @@ def test_nice(self): init = p.nice() try: if WINDOWS: - for prio in [psutil.NORMAL_PRIORITY_CLASS, - psutil.IDLE_PRIORITY_CLASS, + # A CI runner may limit our maximum priority, which will break + # this test. Instead, we test in order of increasing priority, + # and match either the expected value or the highest so far. + highest_prio = None + for prio in [psutil.IDLE_PRIORITY_CLASS, psutil.BELOW_NORMAL_PRIORITY_CLASS, - psutil.REALTIME_PRIORITY_CLASS, + psutil.NORMAL_PRIORITY_CLASS, + psutil.ABOVE_NORMAL_PRIORITY_CLASS, psutil.HIGH_PRIORITY_CLASS, - psutil.ABOVE_NORMAL_PRIORITY_CLASS]: + psutil.REALTIME_PRIORITY_CLASS]: with self.subTest(prio=prio): try: p.nice(prio) except psutil.AccessDenied: pass else: - self.assertEqual(p.nice(), prio) + new_prio = p.nice() + if CI_TESTING: + if new_prio == prio or highest_prio is None: + highest_prio = prio + self.assertEqual(new_prio, highest_prio) + else: + self.assertEqual(new_prio, prio) else: try: if hasattr(os, "getpriority"): @@ -846,7 +856,13 @@ def test_username(self): username = p.username() if WINDOWS: domain, username = username.split('\\') - self.assertEqual(username, getpass.getuser()) + getpass_user = getpass.getuser() + if getpass_user.endswith('$'): + # When running as a service account (most likely to be + # NetworkService), these user name calculations don't produce + # the same result, causing the test to fail. + raise unittest.SkipTest('running as service account') + self.assertEqual(username, getpass_user) if 'USERDOMAIN' in os.environ: self.assertEqual(domain, os.environ['USERDOMAIN']) else: diff --git a/psutil/tests/test_windows.py b/psutil/tests/test_windows.py index 55b6bc7b1..7a843bc38 100755 --- a/psutil/tests/test_windows.py +++ b/psutil/tests/test_windows.py @@ -86,13 +86,14 @@ def test_cpu_count_vs_GetSystemInfo(self): def test_cpu_count_logical_vs_wmi(self): w = wmi.WMI() - proc = w.Win32_Processor()[0] - self.assertEqual(psutil.cpu_count(), proc.NumberOfLogicalProcessors) + procs = sum(proc.NumberOfLogicalProcessors + for proc in w.Win32_Processor()) + self.assertEqual(psutil.cpu_count(), procs) def test_cpu_count_cores_vs_wmi(self): w = wmi.WMI() - proc = w.Win32_Processor()[0] - self.assertEqual(psutil.cpu_count(logical=False), proc.NumberOfCores) + cores = sum(proc.NumberOfCores for proc in w.Win32_Processor()) + self.assertEqual(psutil.cpu_count(logical=False), cores) def test_cpu_count_vs_cpu_times(self): self.assertEqual(psutil.cpu_count(), @@ -213,7 +214,7 @@ def test_boot_time(self): wmi_btime_str, "%Y%m%d%H%M%S") psutil_dt = datetime.datetime.fromtimestamp(psutil.boot_time()) diff = abs((wmi_btime_dt - psutil_dt).total_seconds()) - self.assertLessEqual(diff, 3) + self.assertLessEqual(diff, 5) def test_boot_time_fluctuation(self): # https://github.com/giampaolo/psutil/issues/1007 @@ -351,12 +352,23 @@ def test_ctrl_signals(self): p.send_signal, signal.CTRL_BREAK_EVENT) def test_username(self): - self.assertEqual(psutil.Process().username(), - win32api.GetUserNameEx(win32con.NameSamCompatible)) + name = win32api.GetUserNameEx(win32con.NameSamCompatible) + if name.endswith('$'): + # When running as a service account (most likely to be + # NetworkService), these user name calculations don't produce the + # same result, causing the test to fail. + raise unittest.SkipTest('running as service account') + self.assertEqual(psutil.Process().username(), name) def test_cmdline(self): - sys_value = re.sub(' +', ' ', win32api.GetCommandLine()).strip() + sys_value = re.sub('[ ]+', ' ', win32api.GetCommandLine()).strip() psutil_value = ' '.join(psutil.Process().cmdline()) + if sys_value[0] == '"' != psutil_value[0]: + # The PyWin32 command line may retain quotes around argv[0] if they + # were used unnecessarily, while psutil will omit them. So remove + # the first 2 quotes from sys_value if not in psutil_value. + # A path to an executable will not contain quotes, so this is safe. + sys_value = sys_value.replace('"', '', 2) self.assertEqual(sys_value, psutil_value) # XXX - occasional failures