# Copyright 2023 The Pigweed Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of # the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under # the License. """Tests for pw_cli.process.""" import unittest import sys import textwrap from pw_cli import process import psutil # type: ignore # This timeout must be long enough to wait for the subprocess output, but # fast enough that the test doesn't take terribly long in the success case. FAST_TIMEOUT_SECONDS = 0.5 KILL_SIGNALS = set({-9, 137}) PYTHON = sys.executable class RunTest(unittest.TestCase): """Tests for process.run.""" def test_returns_output(self) -> None: echo_str = 'foobar' print_str = f'print("{echo_str}")' result = process.run(PYTHON, '-c', print_str) self.assertEqual(result.output, b'foobar\n') def test_timeout_kills_process(self) -> None: sleep_100_seconds = 'import time; time.sleep(100)' result = process.run( PYTHON, '-c', sleep_100_seconds, timeout=FAST_TIMEOUT_SECONDS ) self.assertIn(result.returncode, KILL_SIGNALS) def test_timeout_kills_subprocess(self) -> None: # Spawn a subprocess which prints its pid and then waits for 100 # seconds. sleep_in_subprocess = textwrap.dedent( f""" import subprocess import time child = subprocess.Popen( ['{PYTHON}', '-c', 'import time; print("booh"); time.sleep(100)'] ) print(child.pid, flush=True) time.sleep(100) """ ) result = process.run( PYTHON, '-c', sleep_in_subprocess, timeout=FAST_TIMEOUT_SECONDS ) self.assertIn(result.returncode, KILL_SIGNALS) # The first line of the output is the PID of the child sleep process. child_pid_str, sep, remainder = result.output.partition(b'\n') del sep, remainder child_pid = int(child_pid_str) self.assertFalse(psutil.pid_exists(child_pid)) if __name__ == '__main__': unittest.main()