Merge "Prevent tests from using utils.execute()"

This commit is contained in:
Jenkins 2017-05-25 21:48:54 +00:00 committed by Gerrit Code Review
commit 9b62156880
7 changed files with 92 additions and 28 deletions

60
ironic_lib/tests/base.py Normal file
View File

@ -0,0 +1,60 @@
# Copyright 2017 Cisco Systems, Inc
#
# 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
#
# http://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.
"""Common utilities and classes across all unit tests."""
import subprocess
import mock
from oslo_concurrency import processutils
from oslotest import base as test_base
from ironic_lib import utils
class IronicLibTestCase(test_base.BaseTestCase):
"""Test case base class for all unit tests except callers of utils.execute.
This test class prevents calls to the utils.execute() /
processutils.execute() and similar functions.
"""
block_execute = True
def setUp(self):
super(IronicLibTestCase, self).setUp()
"""Add a blanket ban on running external processes via utils.execute().
`self` will create a property called _exec_patch which is the Mock that
replaces utils.execute.
If the mock is called, an exception is raised to warn the tester.
"""
# 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)

View File

@ -16,15 +16,15 @@
import eventlet
import mock
from oslotest import base as test_base
from testtools.matchers import HasLength
from ironic_lib import disk_partitioner
from ironic_lib import exception
from ironic_lib.tests import base
from ironic_lib import utils
class DiskPartitionerTestCase(test_base.BaseTestCase):
class DiskPartitionerTestCase(base.IronicLibTestCase):
def test_add_partition(self):
dp = disk_partitioner.DiskPartitioner('/dev/fake')

View File

@ -25,19 +25,19 @@ from oslo_config import cfg
from oslo_serialization import base64
from oslo_service import loopingcall
from oslo_utils import imageutils
from oslotest import base as test_base
import requests
from ironic_lib import disk_partitioner
from ironic_lib import disk_utils
from ironic_lib import exception
from ironic_lib.tests import base
from ironic_lib import utils
CONF = cfg.CONF
@mock.patch.object(utils, 'execute', autospec=True)
class ListPartitionsTestCase(test_base.BaseTestCase):
class ListPartitionsTestCase(base.IronicLibTestCase):
def test_correct(self, execute_mock):
output = """
@ -72,7 +72,7 @@ BYT;
@mock.patch.object(disk_partitioner.DiskPartitioner, 'commit', lambda _: None)
class WorkOnDiskTestCase(test_base.BaseTestCase):
class WorkOnDiskTestCase(base.IronicLibTestCase):
def setUp(self):
super(WorkOnDiskTestCase, self).setUp()
@ -294,7 +294,7 @@ class WorkOnDiskTestCase(test_base.BaseTestCase):
@mock.patch.object(utils, 'execute', autospec=True)
class MakePartitionsTestCase(test_base.BaseTestCase):
class MakePartitionsTestCase(base.IronicLibTestCase):
def setUp(self):
super(MakePartitionsTestCase, self).setUp()
@ -443,7 +443,7 @@ class MakePartitionsTestCase(test_base.BaseTestCase):
@mock.patch.object(utils, 'execute', autospec=True)
class DestroyMetaDataTestCase(test_base.BaseTestCase):
class DestroyMetaDataTestCase(base.IronicLibTestCase):
def setUp(self):
super(DestroyMetaDataTestCase, self).setUp()
@ -485,7 +485,7 @@ class DestroyMetaDataTestCase(test_base.BaseTestCase):
@mock.patch.object(utils, 'execute', autospec=True)
class GetDeviceBlockSizeTestCase(test_base.BaseTestCase):
class GetDeviceBlockSizeTestCase(base.IronicLibTestCase):
def setUp(self):
super(GetDeviceBlockSizeTestCase, self).setUp()
@ -503,7 +503,7 @@ class GetDeviceBlockSizeTestCase(test_base.BaseTestCase):
@mock.patch.object(disk_utils, 'dd', autospec=True)
@mock.patch.object(disk_utils, 'qemu_img_info', autospec=True)
@mock.patch.object(disk_utils, 'convert_image', autospec=True)
class PopulateImageTestCase(test_base.BaseTestCase):
class PopulateImageTestCase(base.IronicLibTestCase):
def setUp(self):
super(PopulateImageTestCase, self).setUp()
@ -537,7 +537,7 @@ def _looping_call_done(*args, **kwargs):
@mock.patch.object(utils, 'mkfs', lambda fs, path, label=None: None)
# NOTE(dtantsur): destroy_disk_metadata resets file size, disabling it
@mock.patch.object(disk_utils, 'destroy_disk_metadata', lambda *_: None)
class RealFilePartitioningTestCase(test_base.BaseTestCase):
class RealFilePartitioningTestCase(base.IronicLibTestCase):
"""This test applies some real-world partitioning scenario to a file.
This test covers the whole partitioning, mocking everything not possible
@ -545,6 +545,9 @@ class RealFilePartitioningTestCase(test_base.BaseTestCase):
and also conducts integration testing of DiskPartitioner.
"""
# Allow calls to utils.execute() and related functions
block_execute = False
def setUp(self):
super(RealFilePartitioningTestCase, self).setUp()
# NOTE(dtantsur): no parted utility on gate-ironic-python26
@ -608,7 +611,7 @@ class RealFilePartitioningTestCase(test_base.BaseTestCase):
@mock.patch.object(shutil, 'copyfileobj', autospec=True)
@mock.patch.object(requests, 'get', autospec=True)
class GetConfigdriveTestCase(test_base.BaseTestCase):
class GetConfigdriveTestCase(base.IronicLibTestCase):
@mock.patch.object(gzip, 'GzipFile', autospec=True)
def test_get_configdrive(self, mock_gzip, mock_requests, mock_copy):
@ -664,7 +667,7 @@ class GetConfigdriveTestCase(test_base.BaseTestCase):
@mock.patch('time.sleep', lambda sec: None)
class OtherFunctionTestCase(test_base.BaseTestCase):
class OtherFunctionTestCase(base.IronicLibTestCase):
@mock.patch.object(os, 'stat', autospec=True)
@mock.patch.object(stat, 'S_ISBLK', autospec=True)
@ -772,7 +775,7 @@ class OtherFunctionTestCase(test_base.BaseTestCase):
@mock.patch.object(utils, 'execute', autospec=True)
class WholeDiskPartitionTestCases(test_base.BaseTestCase):
class WholeDiskPartitionTestCases(base.IronicLibTestCase):
def setUp(self):
super(WholeDiskPartitionTestCases, self).setUp()
@ -947,7 +950,7 @@ or continue with the current setting?
self.assertEqual(1, mock_log.call_count)
class WholeDiskConfigDriveTestCases(test_base.BaseTestCase):
class WholeDiskConfigDriveTestCases(base.IronicLibTestCase):
def setUp(self):
super(WholeDiskConfigDriveTestCases, self).setUp()

View File

@ -16,9 +16,9 @@
import types
import mock
from oslotest import base as test_base
from ironic_lib import metrics as metricslib
from ironic_lib.tests import base
class MockedMetricLogger(metricslib.MetricLogger):
@ -27,7 +27,7 @@ class MockedMetricLogger(metricslib.MetricLogger):
_timer = mock.Mock(spec_set=types.FunctionType)
class TestMetricLogger(test_base.BaseTestCase):
class TestMetricLogger(base.IronicLibTestCase):
def setUp(self):
super(TestMetricLogger, self).setUp()
self.ml = MockedMetricLogger('prefix', '.')

View File

@ -16,9 +16,9 @@
import socket
import mock
from oslotest import base as test_base
from ironic_lib import metrics_statsd
from ironic_lib.tests import base
def connect(family=None, type=None, proto=None):
@ -26,7 +26,7 @@ def connect(family=None, type=None, proto=None):
pass
class TestStatsdMetricLogger(test_base.BaseTestCase):
class TestStatsdMetricLogger(base.IronicLibTestCase):
def setUp(self):
super(TestStatsdMetricLogger, self).setUp()
self.ml = metrics_statsd.StatsdMetricLogger('prefix', '.', 'test-host',

View File

@ -13,19 +13,18 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslotest import base as test_base
from oslo_config import cfg
from ironic_lib import exception
from ironic_lib import metrics as metricslib
from ironic_lib import metrics_statsd
from ironic_lib import metrics_utils
from ironic_lib.tests import base
CONF = cfg.CONF
class TestGetLogger(test_base.BaseTestCase):
class TestGetLogger(base.IronicLibTestCase):
def setUp(self):
super(TestGetLogger, self).setUp()

View File

@ -21,15 +21,15 @@ import os.path
import mock
from oslo_concurrency import processutils
from oslo_config import cfg
from oslotest import base as test_base
from ironic_lib import exception
from ironic_lib.tests import base
from ironic_lib import utils
CONF = cfg.CONF
class BareMetalUtilsTestCase(test_base.BaseTestCase):
class BareMetalUtilsTestCase(base.IronicLibTestCase):
def test_unlink(self):
with mock.patch.object(os, "unlink", autospec=True) as unlink_mock:
@ -44,7 +44,9 @@ class BareMetalUtilsTestCase(test_base.BaseTestCase):
unlink_mock.assert_called_once_with("/fake/path")
class ExecuteTestCase(test_base.BaseTestCase):
class ExecuteTestCase(base.IronicLibTestCase):
# Allow calls to utils.execute() and related functions
block_execute = False
@mock.patch.object(processutils, 'execute', autospec=True)
@mock.patch.object(os.environ, 'copy', return_value={}, autospec=True)
@ -126,7 +128,7 @@ class ExecuteTestCase(test_base.BaseTestCase):
self._test_execute_with_log_stdout(log_stdout=False)
class MkfsTestCase(test_base.BaseTestCase):
class MkfsTestCase(base.IronicLibTestCase):
@mock.patch.object(utils, 'execute', autospec=True)
def test_mkfs(self, execute_mock):
@ -177,7 +179,7 @@ class MkfsTestCase(test_base.BaseTestCase):
'ext4', '/my/block/dev', 'ext4-vol')
class IsHttpUrlTestCase(test_base.BaseTestCase):
class IsHttpUrlTestCase(base.IronicLibTestCase):
def test_is_http_url(self):
self.assertTrue(utils.is_http_url('http://127.0.0.1'))
@ -188,7 +190,7 @@ class IsHttpUrlTestCase(test_base.BaseTestCase):
self.assertFalse(utils.is_http_url('11111111'))
class ParseRootDeviceTestCase(test_base.BaseTestCase):
class ParseRootDeviceTestCase(base.IronicLibTestCase):
def test_parse_root_device_hints_without_operators(self):
root_device = {
@ -391,7 +393,7 @@ class ParseRootDeviceTestCase(test_base.BaseTestCase):
ValueError, utils._normalize_hint_expression, '', 'size')
class MatchRootDeviceTestCase(test_base.BaseTestCase):
class MatchRootDeviceTestCase(base.IronicLibTestCase):
def setUp(self):
super(MatchRootDeviceTestCase, self).setUp()