Prevent tests from using utils.execute()

This change modifies the base test class so that it mocks out
utils.execute() and similar functions and forces an exception if it
gets called. If utils.execute() is mocked by the test case then it
will work. What this does is prevent un-mocked access to
utils.execute() / processutils.execute() and similar subprocess
library functions.

Inspired by Julian Edwards' patch to ironic-python-agent

Change-Id: Id3a8e6c5fce44a1f5f6f936d2a35e0660adbf086
This commit is contained in:
John L. Villalovos 2017-05-16 16:43:00 -07:00
parent f84bee7faa
commit 5dc756e8bf

View File

@ -23,12 +23,16 @@ inline callbacks.
import copy import copy
import os import os
import subprocess
import sys import sys
import tempfile import tempfile
import eventlet import eventlet
eventlet.monkey_patch(os=False) eventlet.monkey_patch(os=False)
import fixtures import fixtures
from ironic_lib import utils
import mock
from oslo_concurrency import processutils
from oslo_config import fixture as config_fixture from oslo_config import fixture as config_fixture
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
@ -73,6 +77,9 @@ class TestingException(Exception):
class TestCase(testtools.TestCase): class TestCase(testtools.TestCase):
"""Test case base class for all unit tests.""" """Test case base class for all unit tests."""
# By default block execution of utils.execute() and related functions.
block_execute = True
def setUp(self): def setUp(self):
"""Run before each test method to initialize test environment.""" """Run before each test method to initialize test environment."""
super(TestCase, self).setUp() super(TestCase, self).setUp()
@ -117,6 +124,23 @@ class TestCase(testtools.TestCase):
for factory in driver_factory._INTERFACE_LOADERS.values(): for factory in driver_factory._INTERFACE_LOADERS.values():
factory._extension_manager = None factory._extension_manager = None
# Block access to utils.execute() and related functions.
# NOTE(bigjools): Not using a decorator on tests because I don't
# want to force every test method to accept a new arg. Instead, they
# can override or examine this self._exec_patch Mock as needed.
if self.block_execute:
self._exec_patch = mock.Mock()
self._exec_patch.side_effect = Exception(
"Don't call ironic_lib.utils.execute() / "
"processutils.execute() or similar functions in tests!")
self.patch(processutils, 'execute', self._exec_patch)
self.patch(subprocess, 'Popen', self._exec_patch)
self.patch(subprocess, 'call', self._exec_patch)
self.patch(subprocess, 'check_call', self._exec_patch)
self.patch(subprocess, 'check_output', self._exec_patch)
self.patch(utils, 'execute', self._exec_patch)
def _set_config(self): def _set_config(self):
self.cfg_fixture = self.useFixture(config_fixture.Config(CONF)) self.cfg_fixture = self.useFixture(config_fixture.Config(CONF))
self.config(use_stderr=False, self.config(use_stderr=False,