From 992bd75fbeba9294f87c579a579e6db666ae8873 Mon Sep 17 00:00:00 2001 From: Zbynek Winkler Date: Fri, 22 May 2020 15:05:01 +0200 Subject: [PATCH 1/3] test: allow for relative imports in tests --- test.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test.py b/test.py index cb6c81940..1f70dcdff 100755 --- a/test.py +++ b/test.py @@ -2,4 +2,9 @@ if __name__ == "__main__": import unittest - unittest.main(module=None) + import unittest.loader + testLoader = unittest.loader.TestLoader() + from pathlib import Path + top_level_dir = Path(__file__).parent + testLoader._top_level_dir = top_level_dir + unittest.main(module=None, testLoader=testLoader) From 2763a39b7c52b273d6e4e66e94878d03b5ac740c Mon Sep 17 00:00:00 2001 From: Zbynek Winkler Date: Fri, 22 May 2020 15:36:18 +0200 Subject: [PATCH 2/3] subt.launch: add generic process launcher Entry can be added to a config file with driver `subt.launch.Launch` that can be used to launch a generic process when other osgar nodes are started and terminated when other nodes are terminated. --- subt/launch.py | 49 +++++++++++++++++++++++++++++++++++++++++++++ subt/test_launch.py | 32 +++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 subt/launch.py create mode 100644 subt/test_launch.py diff --git a/subt/launch.py b/subt/launch.py new file mode 100644 index 000000000..389664dd9 --- /dev/null +++ b/subt/launch.py @@ -0,0 +1,49 @@ +import logging +import signal +import subprocess + +g_logger = logging.getLogger(__name__) + +class Launch: + def __init__(self, config, bus): + self.bus = bus + self.command = config['command'] + self.shell = config.get('shell', False) + + def start(self): + self.running = subprocess.Popen(self.command, shell=self.shell) + + def request_stop(self): + self.bus.shutdown() + self.running.send_signal(signal.SIGINT) + + def join(self, timeout=None): + try: + self.running.wait(timeout) + except subprocess.TimeoutExpired: + command = self.command if isinstance(self.command, str) else " ".join(self.command) + g_logger.warning(f"'{command}' still running, terminating") + self.running.terminate() + try: + self.running.wait(1) + except subprocess.TimeoutExpired: + g_logger.warning(f"'{command}' ignoring SIGTERM, killing") + self.running.kill() + self.running.wait() + assert self.running.poll() is not None + + +if __name__ == "__main__": + from unittest.mock import MagicMock + test_launch = Launch(config={'command': ['echo', 'hello world!']}, bus=MagicMock()) + test_launch.start() + test_launch.join() + + test_request_stop = Launch(config={'command': ['sleep', '10']}, bus=MagicMock()) + test_request_stop.start() + test_request_stop.request_stop() + test_request_stop.join(0.1) + + test_join = Launch(config={'command': ['sleep', '10']}, bus=MagicMock()) + test_join.start() + test_join.join(0.1) diff --git a/subt/test_launch.py b/subt/test_launch.py new file mode 100644 index 000000000..5c424dbab --- /dev/null +++ b/subt/test_launch.py @@ -0,0 +1,32 @@ +import logging +import unittest +import unittest.mock + +from . import launch + + +class Test(unittest.TestCase): + def test_launch(self): + p = launch.Launch(config={'command': ['true']}, bus=unittest.mock.MagicMock()) + p.start() + p.join() + + def test_request_stop(self): + p = launch.Launch(config={'command': ['sleep', '10']}, bus=unittest.mock.MagicMock()) + p.start() + p.request_stop() + p.join(0.1) + + def test_join(self): + with self.assertLogs(level=logging.WARNING) as log: + p = launch.Launch(config={'command': ['sleep', '10']}, bus=unittest.mock.MagicMock()) + p.start() + p.join(0.1) + self.assertEqual(len(log.records), 1) + + def test_shell(self): + with self.assertLogs(level=logging.WARNING) as log: + p = launch.Launch(config={'command': 'sleep 10', 'shell': True}, bus=unittest.mock.MagicMock()) + p.start() + p.join(0.1) + self.assertEqual(len(log.records), 1) From 9ee6d4c4b397321ac829b0d2eeaf49b01928606b Mon Sep 17 00:00:00 2001 From: Zbynek Winkler Date: Fri, 22 May 2020 16:23:57 +0200 Subject: [PATCH 3/3] subt.launch: send CTRL_C_EVENT on Windows --- subt/launch.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subt/launch.py b/subt/launch.py index 389664dd9..627dd9004 100644 --- a/subt/launch.py +++ b/subt/launch.py @@ -1,4 +1,5 @@ import logging +import platform import signal import subprocess @@ -15,7 +16,8 @@ def start(self): def request_stop(self): self.bus.shutdown() - self.running.send_signal(signal.SIGINT) + signum = signal.CTRL_C_EVENT if platform.system() == "Windows" else signal.SIGINT + self.running.send_signal(signum) def join(self, timeout=None): try: