From f8d6aa9c9ad676a29ff0874b5bf5b9fb898259c7 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Date: Tue, 24 Mar 2015 13:07:37 +0000 Subject: [PATCH] Stop any spawned ProcessMonitor at test cleanup Base test class adds a cleanup fixture to stop any spawned process monitor via unit or functional tests, which otherwise would keep running after the tests already finished, and execution functions go unpatched. Without this patch unit tests will randomly fail when we enable process monitor by default at change: I85fe31bee30714148168a293eea29fa0a37f9701 Co-Authored-By: Maru Newby Change-Id: Ide799a52391b14ff921de25788e8b0f0463fb8f8 --- neutron/agent/linux/external_process.py | 6 ++++- neutron/tests/base.py | 25 +++++++++++++++++++ .../functional/agent/linux/test_keepalived.py | 1 - .../agent/linux/test_process_monitor.py | 1 - 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/neutron/agent/linux/external_process.py b/neutron/agent/linux/external_process.py index 95beddd99df..0dff4efa88a 100644 --- a/neutron/agent/linux/external_process.py +++ b/neutron/agent/linux/external_process.py @@ -199,7 +199,11 @@ class ProcessMonitor(object): self._monitored_processes.pop(service_id, None) def stop(self): - """Stop the process monitoring. """ + """Stop the process monitoring. + + This method will stop the monitoring thread, but no monitored + process will be stopped. + """ self._monitor_processes = False def _spawn_checking_thread(self): diff --git a/neutron/tests/base.py b/neutron/tests/base.py index 6886af9e3cf..d9e61f0613c 100644 --- a/neutron/tests/base.py +++ b/neutron/tests/base.py @@ -27,10 +27,12 @@ import logging as std_logging import os.path import fixtures +import mock from oslo_concurrency.fixture import lockutils from oslo_config import cfg from oslo_messaging import conffixture as messaging_conffixture +from neutron.agent.linux import external_process from neutron.common import config from neutron.common import rpc as n_rpc from neutron import policy @@ -61,6 +63,28 @@ def fake_consume_in_threads(self): bool_from_env = sub_base.bool_from_env +class ProcessMonitorFixture(fixtures.Fixture): + """Test fixture to capture and cleanup any spawn process monitor.""" + def setUp(self): + super(ProcessMonitorFixture, self).setUp() + self.old_callable = ( + external_process.ProcessMonitor._spawn_checking_thread) + p = mock.patch("neutron.agent.linux.external_process.ProcessMonitor." + "_spawn_checking_thread", + new=lambda x: self.record_calls(x)) + p.start() + self.instances = [] + self.addCleanup(self.stop) + + def stop(self): + for instance in self.instances: + instance.stop() + + def record_calls(self, instance): + self.old_callable(instance) + self.instances.append(instance) + + class BaseTestCase(sub_base.SubBaseTestCase): @staticmethod @@ -97,6 +121,7 @@ class BaseTestCase(sub_base.SubBaseTestCase): cfg.CONF.set_override('state_path', self.get_default_temp_dir().path) self.addCleanup(CONF.reset) + self.useFixture(ProcessMonitorFixture()) self.useFixture(fixtures.MonkeyPatch( 'neutron.common.exceptions.NeutronException.use_fatal_exceptions', diff --git a/neutron/tests/functional/agent/linux/test_keepalived.py b/neutron/tests/functional/agent/linux/test_keepalived.py index 9e1060ea07e..f0fe113e61f 100644 --- a/neutron/tests/functional/agent/linux/test_keepalived.py +++ b/neutron/tests/functional/agent/linux/test_keepalived.py @@ -36,7 +36,6 @@ class KeepalivedManagerTestCase(base.BaseTestCase, 'router1', self.expected_config, conf_path=cfg.CONF.state_path, process_monitor=self.process_monitor) self.addCleanup(self.manager.get_process().disable) - self.addCleanup(self.process_monitor.stop) def test_keepalived_spawn(self): self.manager.spawn() diff --git a/neutron/tests/functional/agent/linux/test_process_monitor.py b/neutron/tests/functional/agent/linux/test_process_monitor.py index d202d2e0e3c..1bf50803fc6 100644 --- a/neutron/tests/functional/agent/linux/test_process_monitor.py +++ b/neutron/tests/functional/agent/linux/test_process_monitor.py @@ -34,7 +34,6 @@ class BaseTestProcessMonitor(base.BaseTestCase): self._process_monitor = None self.create_child_processes_manager('respawn') self.addCleanup(self.cleanup_spawned_children) - self.addCleanup(self._process_monitor.stop) def create_child_processes_manager(self, action): cfg.CONF.set_override('check_child_processes_action', action, 'AGENT')