# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import psutil
import chrome_helper
LOGGER = logging.getLogger('installer_test')
def VerifyProcessExpectation(expectation_name, expectation, variable_expander):
"""Verifies that a file is present or absent, throwing an AssertionError if
the expectation is not met.
Args:
expectation_name: Path to the process being verified (may contain
variables to be expanded).
expectation: A dictionary with the following key and value:
'running' a boolean indicating whether the process should be
running.
variable_expander: A VariableExpander object.
Raises:
AssertionError: If an expectation is not satisfied.
"""
running_process_paths = [
path for (_, path) in chrome_helper.GetProcessIDAndPathPairs()
]
process_path = variable_expander.Expand(expectation_name)
is_running = process_path in running_process_paths
assert expectation['running'] == is_running, \
('Process %s is running' % process_path) if is_running else \
('Process %s is not running' % process_path)
def CleanProcess(expectation_name, expectation, variable_expander):
"""Terminates processes based on expectations.
Args:
expectation_name: Path to a process's executable.
expectation: A dictionary describing the state of the process:
'running': A boolean False indicating that the process must not be
running.
variable_expander: A VariableExpander object.
Raises:
AssertionError: If an expectation is not satisfied.
WindowsError: If an error occurs while deleting the path.
"""
process_path = variable_expander.Expand(expectation_name)
assert not expectation['running'], (
'Invalid expectation for CleanProcess operation: \'running\' property '
+ 'for %s must not be True' % process_path)
for proc in psutil.process_iter():
try:
if not proc.exe() == process_path:
continue
except psutil.Error:
# Ignore processes for which the path cannot be determined.
# AccessDenied is expected for pid 0, pid 4, and any others that the
# current process does not have access to query.
continue
pid = proc.pid
try:
proc.kill()
LOGGER.info('CleanProcess killed process %s of pid %s' %
(process_path, pid))
except psutil.NoSuchProcess:
LOGGER.info('CleanProcess tried to kill process %s of pid %s, ' %
(process_path, pid) + 'yet it was already gone')