b9a1fab7a0
Use `requests` library instead of `urllib2` & `httplib` Main profit from `requests` library: - `requests` is HTTP for Humans; - `requests` is well documented[1]; - `requests` can save downloaded files by parts, so usage of memory is less(useful when downloading big data, for example - some images) - `requests` has same name as in Python 2x and Python 3x Use `inspect.getmembers`[2][3] for discovery of each function for section generator. Profit : decrease lines of code Add checks for existence of subnet in 'network' section. Move function `_write_config`[4] from class `Tempest`[5] to `TempestConf`. Reason: this function not related to verifier for Tempest. Fix message for exception when user doesn't have admin role. Move name of section into kwargs to each section function. Profit: less string objects with section names [1] - http://docs.python-requests.org/en/latest/ [2] - https://docs.python.org/2/library/inspect.html#types-and-members [3] - https://docs.python.org/3.3/library/inspect.html#types-and-members [4] - http://git.io/E1zPOQ [5] - http://git.io/8Ru-Yw Change-Id: I8307ec33dd93ef055450f58d7cd55bf6b200f249
201 lines
8.2 KiB
Python
201 lines
8.2 KiB
Python
# Copyright 2014: Mirantis Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
|
|
import os
|
|
|
|
import mock
|
|
|
|
from rally.openstack.common import jsonutils
|
|
from rally.verification.verifiers.tempest import subunit2json
|
|
from rally.verification.verifiers.tempest import tempest
|
|
from tests import test
|
|
|
|
|
|
TEMPEST_PATH = 'rally.verification.verifiers.tempest'
|
|
|
|
|
|
class TempestTestCase(test.TestCase):
|
|
|
|
def setUp(self):
|
|
super(TempestTestCase, self).setUp()
|
|
self.verifier = tempest.Tempest('fake_deploy_id',
|
|
verification=mock.MagicMock())
|
|
|
|
self.verifier.tempest_path = '/tmp'
|
|
self.verifier.config_file = '/tmp/tempest.conf'
|
|
self.verifier.log_file_raw = '/tmp/subunit.stream'
|
|
self.regex = None
|
|
|
|
@mock.patch('os.path.exists')
|
|
def test_is_installed(self, mock_exists):
|
|
mock_exists.return_value = True
|
|
|
|
result = self.verifier.is_installed()
|
|
|
|
mock_exists.assert_called_once_with(
|
|
os.path.join(self.verifier.tempest_path, '.venv'))
|
|
self.assertTrue(result)
|
|
|
|
@mock.patch('rally.verification.verifiers.tempest.tempest.subprocess')
|
|
def test__clone(self, mock_sp):
|
|
self.verifier._clone()
|
|
mock_sp.check_call.assert_called_once_with(
|
|
['git', 'clone', 'https://github.com/openstack/tempest',
|
|
tempest.Tempest.tempest_base_path])
|
|
|
|
@mock.patch(TEMPEST_PATH + '.tempest.Tempest._initialize_testr')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.Tempest._install_venv')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.subprocess')
|
|
@mock.patch('os.path.exists')
|
|
@mock.patch('shutil.copytree')
|
|
def test_install(
|
|
self, mock_copytree, mock_exists, mock_sp, mock_venv, mock_testr):
|
|
mock_exists.side_effect = (False, True, False)
|
|
# simulate tempest is clonned but is not installed for current deploy
|
|
|
|
self.verifier.install()
|
|
mock_copytree.assert_called_once_with(
|
|
tempest.Tempest.tempest_base_path,
|
|
self.verifier.tempest_path)
|
|
mock_sp.check_call.assert_called_once_with(
|
|
'git checkout master; git remote update; git pull',
|
|
cwd=os.path.join(self.verifier.tempest_path, 'tempest'),
|
|
shell=True)
|
|
|
|
@mock.patch('rally.verification.verifiers.tempest.tempest.shutil')
|
|
@mock.patch('os.path.exists')
|
|
def test_uninstall(self, mock_exists, mock_shutil):
|
|
mock_exists.return_value = True
|
|
self.verifier.uninstall()
|
|
mock_shutil.rmtree.assert_called_once_with(self.verifier.tempest_path)
|
|
|
|
@mock.patch(TEMPEST_PATH + '.tempest.Tempest.env')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.subprocess')
|
|
def test_run(self, mock_sp, mock_env):
|
|
self.verifier.run('tempest.api.image')
|
|
fake_call = (
|
|
'%(venv)s testr run --parallel --subunit tempest.api.image '
|
|
'| tee %(tempest_path)s/subunit.stream '
|
|
'| %(venv)s subunit-2to1 '
|
|
'| %(venv)s %(tempest_path)s/tools/colorizer.py' % {
|
|
'venv': self.verifier.venv_wrapper,
|
|
'tempest_path': self.verifier.tempest_path})
|
|
mock_sp.check_call.assert_called_once_with(
|
|
fake_call, env=mock_env, cwd=self.verifier.tempest_path,
|
|
shell=True)
|
|
|
|
@mock.patch(TEMPEST_PATH + '.tempest.os.remove')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.Tempest.discover_tests')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.Tempest._initialize_testr')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.Tempest.run')
|
|
@mock.patch(TEMPEST_PATH + '.config.TempestConf')
|
|
@mock.patch('rally.db.deployment_get')
|
|
@mock.patch('rally.osclients.Clients')
|
|
@mock.patch('rally.objects.endpoint.Endpoint')
|
|
def test_verify(self, mock_endpoint, mock_osclients, mock_get, mock_conf,
|
|
mock_run, mock_testr_init, mock_discover, mock_os):
|
|
self.verifier.verify("smoke", None)
|
|
mock_conf().generate.assert_called_once_with(self.verifier.config_file)
|
|
mock_run.assert_called_once_with("smoke")
|
|
|
|
@mock.patch('os.environ')
|
|
def test__generate_env(self, mock_env):
|
|
expected_env = {'PATH': '/some/path'}
|
|
mock_env.copy.return_value = expected_env.copy()
|
|
expected_env.update({
|
|
'TEMPEST_CONFIG': 'tempest.conf',
|
|
'TEMPEST_CONFIG_DIR': self.verifier.tempest_path,
|
|
'OS_TEST_PATH': os.path.join(self.verifier.tempest_path,
|
|
'tempest/test_discover')})
|
|
self.assertIsNone(self.verifier._env)
|
|
self.verifier._generate_env()
|
|
self.assertEqual(expected_env, self.verifier._env)
|
|
|
|
@mock.patch('os.path.isdir')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.subprocess')
|
|
def test__venv_install_when_venv_exists(self, mock_sp, mock_isdir):
|
|
mock_isdir.return_value = True
|
|
self.verifier._install_venv()
|
|
|
|
mock_isdir.assert_called_once_with(
|
|
os.path.join(self.verifier.tempest_path, '.venv'))
|
|
self.assertFalse(mock_sp.called)
|
|
|
|
@mock.patch('os.path.isdir')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.subprocess.check_call')
|
|
def test__venv_install_when_venv_not_exist(self, mock_sp, mock_isdir):
|
|
mock_isdir.return_value = False
|
|
self.verifier._install_venv()
|
|
|
|
mock_isdir.assert_called_once_with(
|
|
os.path.join(self.verifier.tempest_path, '.venv'))
|
|
mock_sp.assert_has_calls([
|
|
mock.call('python ./tools/install_venv.py', shell=True,
|
|
cwd=self.verifier.tempest_path),
|
|
mock.call('%s python setup.py install' %
|
|
self.verifier.venv_wrapper, shell=True,
|
|
cwd=self.verifier.tempest_path)])
|
|
|
|
@mock.patch('os.path.isdir')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.subprocess')
|
|
def test__initialize_testr_when_testr_already_initialized(
|
|
self, mock_sp, mock_isdir):
|
|
mock_isdir.return_value = True
|
|
self.verifier._initialize_testr()
|
|
|
|
mock_isdir.assert_called_once_with(
|
|
os.path.join(self.verifier.tempest_path, '.testrepository'))
|
|
self.assertFalse(mock_sp.called)
|
|
|
|
@mock.patch('os.path.isdir')
|
|
@mock.patch(TEMPEST_PATH + '.tempest.subprocess.check_call')
|
|
def test__initialize_testr_when_testr_not_initialized(
|
|
self, mock_sp, mock_isdir):
|
|
mock_isdir.return_value = False
|
|
self.verifier._initialize_testr()
|
|
|
|
mock_isdir.assert_called_once_with(
|
|
os.path.join(self.verifier.tempest_path, '.testrepository'))
|
|
mock_sp.assert_called_once_with(
|
|
'%s testr init' % self.verifier.venv_wrapper, shell=True,
|
|
cwd=self.verifier.tempest_path)
|
|
|
|
@mock.patch('xml.dom.minidom.parse')
|
|
@mock.patch('os.path.isfile')
|
|
def test__save_results_without_log_file(self, mock_isfile, mock_parse):
|
|
mock_isfile.return_value = False
|
|
|
|
self.verifier._save_results()
|
|
|
|
mock_isfile.assert_called_once_with(self.verifier.log_file_raw)
|
|
self.assertEqual(0, mock_parse.call_count)
|
|
|
|
@mock.patch('os.path.isfile')
|
|
def test__save_results_with_log_file(self, mock_isfile):
|
|
with mock.patch.object(subunit2json, 'main') as mock_main:
|
|
mock_isfile.return_value = True
|
|
data = {'total': True, 'test_cases': True}
|
|
mock_main.return_value = jsonutils.dumps(data)
|
|
self.verifier.log_file_raw = os.path.join(
|
|
os.path.dirname(__file__),
|
|
'subunit.stream')
|
|
self.verifier._save_results()
|
|
mock_isfile.assert_called_once_with(self.verifier.log_file_raw)
|
|
mock_main.assert_called_once_with(
|
|
self.verifier.log_file_raw)
|
|
|
|
self.assertEqual(
|
|
1, self.verifier.verification.finish_verification.call_count)
|