
All strings are considered as unicode string from Python 3. This patch drops the explicit unicode literal (u'...') appearances from the unicode strings. Change-Id: I2985c088d25201edcb0f31fa4a1223a9c840e050
438 lines
18 KiB
Python
438 lines
18 KiB
Python
# Copyright 2015 Tesora 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.
|
|
|
|
import logging
|
|
from unittest import mock
|
|
|
|
from django.urls import reverse
|
|
from oslo_serialization import jsonutils
|
|
|
|
from trove_dashboard import api
|
|
from trove_dashboard.content.database_configurations \
|
|
import config_param_manager
|
|
from trove_dashboard.test import helpers as test
|
|
|
|
INDEX_URL = reverse('horizon:project:database_configurations:index')
|
|
CREATE_URL = reverse('horizon:project:database_configurations:create')
|
|
DETAIL_URL = 'horizon:project:database_configurations:detail'
|
|
ADD_URL = 'horizon:project:database_configurations:add'
|
|
|
|
|
|
class DatabaseConfigurationsTests(test.TestCase):
|
|
@test.create_mocks({api.trove: ('configuration_list',)})
|
|
def test_index(self):
|
|
self.mock_configuration_list.return_value = (
|
|
self.database_configurations.list())
|
|
res = self.client.get(INDEX_URL)
|
|
self.mock_configuration_list.assert_called_once_with(
|
|
test.IsHttpRequest())
|
|
self.assertTemplateUsed(res,
|
|
'project/database_configurations/index.html')
|
|
|
|
@test.create_mocks({api.trove: ('configuration_list',)})
|
|
def test_index_exception(self):
|
|
self.mock_configuration_list.side_effect = self.exceptions.trove
|
|
res = self.client.get(INDEX_URL)
|
|
self.mock_configuration_list.assert_called_once_with(
|
|
test.IsHttpRequest())
|
|
self.assertTemplateUsed(
|
|
res, 'project/database_configurations/index.html')
|
|
self.assertEqual(res.status_code, 200)
|
|
self.assertMessageCount(res, error=1)
|
|
|
|
@test.create_mocks({
|
|
api.trove: ('datastore_list', 'datastore_version_list')})
|
|
def test_create_configuration(self):
|
|
self.mock_datastore_list.return_value = self.datastores.list()
|
|
self.mock_datastore_version_list.return_value = (
|
|
self.datastore_versions.list())
|
|
res = self.client.get(CREATE_URL)
|
|
self.mock_datastore_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_datastore_version_list, 4,
|
|
mock.call(test.IsHttpRequest(), test.IsA(str)))
|
|
self.assertTemplateUsed(res,
|
|
'project/database_configurations/create.html')
|
|
|
|
@test.create_mocks({api.trove: ('datastore_list',)})
|
|
def test_create_configuration_exception_on_datastore(self):
|
|
self.mock_datastore_list.side_effect = self.exceptions.trove
|
|
toSuppress = ["trove_dashboard.content."
|
|
"database_configurations.forms", ]
|
|
|
|
# Suppress expected log messages in the test output
|
|
loggers = []
|
|
for cls in toSuppress:
|
|
logger = logging.getLogger(cls)
|
|
loggers.append((logger, logger.getEffectiveLevel()))
|
|
logger.setLevel(logging.CRITICAL)
|
|
|
|
try:
|
|
res = self.client.get(CREATE_URL)
|
|
self.mock_datastore_list.assert_called_once_with(
|
|
test.IsHttpRequest())
|
|
self.assertEqual(res.status_code, 302)
|
|
|
|
finally:
|
|
# Restore the previous log levels
|
|
for (log, level) in loggers:
|
|
log.setLevel(level)
|
|
|
|
@test.create_mocks({
|
|
api.trove: ('datastore_list', 'datastore_version_list',
|
|
'configuration_create')})
|
|
def _test_create_test_configuration(self, config_description=''):
|
|
self.mock_datastore_list.return_value = self.datastores.list()
|
|
self.mock_datastore_version_list.return_value = (
|
|
self.datastore_versions.list())
|
|
|
|
self.mock_configuration_create.return_value = (
|
|
self.database_configurations.first())
|
|
|
|
name = 'config1'
|
|
values = "{}"
|
|
ds = self._get_test_datastore('mysql')
|
|
dsv = self._get_test_datastore_version(ds.id, '5.5')
|
|
config_datastore = ds.name
|
|
config_datastore_version = dsv.name
|
|
|
|
post = {
|
|
'method': 'CreateConfigurationForm',
|
|
'name': name,
|
|
'description': config_description,
|
|
'datastore': (config_datastore + ',' + config_datastore_version)}
|
|
|
|
res = self.client.post(CREATE_URL, post)
|
|
self.mock_datastore_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_datastore_version_list, 4,
|
|
mock.call(test.IsHttpRequest(), test.IsA(str)))
|
|
self.mock_configuration_create.assert_called_once_with(
|
|
test.IsHttpRequest(),
|
|
name,
|
|
values,
|
|
description=config_description,
|
|
datastore=config_datastore,
|
|
datastore_version=config_datastore_version)
|
|
self.assertNoFormErrors(res)
|
|
self.assertMessageCount(success=1)
|
|
|
|
def test_create_test_configuration(self):
|
|
self._test_create_test_configuration('description of config1')
|
|
|
|
def test_create_test_configuration_with_no_description(self):
|
|
self._test_create_test_configuration()
|
|
|
|
@test.create_mocks({
|
|
api.trove: ('datastore_list', 'datastore_version_list',
|
|
'configuration_create')})
|
|
def test_create_test_configuration_exception(self):
|
|
self.mock_datastore_list.return_value = self.datastores.list()
|
|
self.mock_datastore_version_list.return_value = (
|
|
self.datastore_versions.list())
|
|
|
|
self.mock_configuration_create.side_effect = self.exceptions.trove
|
|
|
|
name = 'config1'
|
|
values = "{}"
|
|
config_description = 'description of config1'
|
|
ds = self._get_test_datastore('mysql')
|
|
dsv = self._get_test_datastore_version(ds.id, '5.5')
|
|
config_datastore = ds.name
|
|
config_datastore_version = dsv.name
|
|
|
|
post = {'method': 'CreateConfigurationForm',
|
|
'name': name,
|
|
'description': config_description,
|
|
'datastore': config_datastore + ',' + config_datastore_version}
|
|
|
|
res = self.client.post(CREATE_URL, post)
|
|
self.mock_datastore_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_datastore_version_list, 4,
|
|
mock.call(test.IsHttpRequest(), test.IsA(str)))
|
|
self.mock_configuration_create.assert_called_once_with(
|
|
test.IsHttpRequest(),
|
|
name,
|
|
values,
|
|
description=config_description,
|
|
datastore=config_datastore,
|
|
datastore_version=config_datastore_version)
|
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
|
|
|
@test.create_mocks({api.trove: ('configuration_get',
|
|
'configuration_instances',)})
|
|
def test_details_tab(self):
|
|
config = self.database_configurations.first()
|
|
self.mock_configuration_get.return_value = config
|
|
details_url = self._get_url_with_arg(DETAIL_URL, config.id)
|
|
url = details_url + '?tab=configuration_details__details'
|
|
res = self.client.get(url)
|
|
self.assertEqual(2, self.mock_configuration_get.call_count)
|
|
self.assertTemplateUsed(res,
|
|
'project/database_configurations/details.html')
|
|
|
|
@test.create_mocks({api.trove: ('configuration_get',)})
|
|
def test_overview_tab_exception(self):
|
|
config = self.database_configurations.first()
|
|
self.mock_configuration_get.side_effect = self.exceptions.trove
|
|
details_url = self._get_url_with_arg(DETAIL_URL, config.id)
|
|
url = details_url + '?tab=configuration_details__overview'
|
|
res = self.client.get(url)
|
|
self.mock_configuration_get.assert_called_once_with(
|
|
test.IsHttpRequest(), config.id)
|
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
|
|
|
@test.create_mocks({
|
|
api.trove: ('configuration_parameters_list',),
|
|
config_param_manager.ConfigParamManager:
|
|
('get_configuration', 'configuration_get',)})
|
|
def test_add_parameter(self):
|
|
config = self.database_configurations.first()
|
|
self.mock_get_configuration.return_value = config
|
|
|
|
self.mock_configuration_get.return_value = config
|
|
ds = self._get_test_datastore('mysql')
|
|
dsv = self._get_test_datastore_version(ds.id, '5.5')
|
|
self.mock_configuration_parameters_list.return_value = (
|
|
self.configuration_parameters.list())
|
|
res = self.client.get(self._get_url_with_arg(ADD_URL, 'id'))
|
|
self.mock_get_configuration.assert_called_once()
|
|
self.mock_configuration_get.assert_called_once_with(
|
|
test.IsHttpRequest())
|
|
self.mock_configuration_parameters_list.assert_called_once_with(
|
|
test.IsHttpRequest(),
|
|
ds.name,
|
|
dsv.name)
|
|
self.assertTemplateUsed(
|
|
res, 'project/database_configurations/add_parameter.html')
|
|
|
|
@test.create_mocks({
|
|
api.trove: ('configuration_parameters_list',),
|
|
config_param_manager.ConfigParamManager:
|
|
('get_configuration', 'configuration_get',)})
|
|
def test_add_parameter_exception_on_parameters(self):
|
|
try:
|
|
config = self.database_configurations.first()
|
|
self.mock_get_configuration.return_value = config
|
|
|
|
self.mock_configuration_get.return_value = config
|
|
|
|
ds = self._get_test_datastore('mysql')
|
|
dsv = self._get_test_datastore_version(ds.id, '5.5')
|
|
self.mock_configuration_parameters_list.side_effect = (
|
|
self.exceptions.trove)
|
|
toSuppress = ["trove_dashboard.content."
|
|
"database_configurations.forms", ]
|
|
|
|
# Suppress expected log messages in the test output
|
|
loggers = []
|
|
for cls in toSuppress:
|
|
logger = logging.getLogger(cls)
|
|
loggers.append((logger, logger.getEffectiveLevel()))
|
|
logger.setLevel(logging.CRITICAL)
|
|
|
|
try:
|
|
res = self.client.get(
|
|
self._get_url_with_arg(ADD_URL, config.id))
|
|
self.mock_get_configuration.assert_called_once()
|
|
self.mock_configuration_get.assert_called_once_with(
|
|
test.IsHttpRequest())
|
|
self.mock_configuration_parameters_list. \
|
|
assert_called_once_with(
|
|
test.IsHttpRequest(),
|
|
ds.name,
|
|
dsv.name
|
|
)
|
|
self.assertEqual(res.status_code, 302)
|
|
|
|
finally:
|
|
# Restore the previous log levels
|
|
for (log, level) in loggers:
|
|
log.setLevel(level)
|
|
finally:
|
|
config_param_manager.delete(config.id)
|
|
|
|
@test.create_mocks(
|
|
{
|
|
api.trove:
|
|
('configuration_parameters_list', 'configuration_update',
|
|
'configuration_get'),
|
|
config_param_manager.ConfigParamManager: ('add_param',)
|
|
}
|
|
)
|
|
def test_add_new_parameter(self):
|
|
config = self.database_configurations.first()
|
|
|
|
try:
|
|
self.mock_configuration_get.return_value = config
|
|
|
|
ds = self._get_test_datastore('mysql')
|
|
dsv = self._get_test_datastore_version(ds.id, '5.5')
|
|
self.mock_configuration_parameters_list.return_value = (
|
|
self.configuration_parameters.list())
|
|
|
|
name = self.configuration_parameters.first().name
|
|
value = 1
|
|
config.values.update({name: value})
|
|
|
|
self.mock_add_param.return_value = value
|
|
|
|
post = {
|
|
'method': 'AddParameterForm',
|
|
'name': name,
|
|
'value': value}
|
|
|
|
res = self.client.post(self._get_url_with_arg(ADD_URL, config.id),
|
|
post)
|
|
|
|
self.assertEqual(2, self.mock_configuration_get.call_count)
|
|
self.mock_configuration_parameters_list.assert_called_once_with(
|
|
test.IsHttpRequest(),
|
|
ds.name,
|
|
dsv.name)
|
|
self.mock_add_param.assert_called_once_with(name, value)
|
|
self.mock_configuration_update.assert_called_once_with(
|
|
test.IsHttpRequest(), config.id,
|
|
jsonutils.dumps(config.values)
|
|
)
|
|
self.assertNoFormErrors(res)
|
|
self.assertMessageCount(success=1)
|
|
finally:
|
|
config_param_manager.delete(config.id)
|
|
|
|
@test.create_mocks({
|
|
api.trove: ('configuration_get', 'configuration_parameters_list',),
|
|
config_param_manager: ('get',)})
|
|
def test_add_parameter_invalid_value(self):
|
|
try:
|
|
config = self.database_configurations.first()
|
|
|
|
# setup the configuration parameter manager
|
|
config_param_mgr = config_param_manager.ConfigParamManager(
|
|
config.id)
|
|
config_param_mgr.configuration = config
|
|
config_param_mgr.original_configuration_values = \
|
|
dict.copy(config.values)
|
|
|
|
self.mock_get.return_value = config_param_mgr
|
|
self.mock_configuration_parameters_list.return_value = (
|
|
self.configuration_parameters.list())
|
|
|
|
name = self.configuration_parameters.first().name
|
|
value = "non-numeric"
|
|
|
|
post = {
|
|
'method': 'AddParameterForm',
|
|
'name': name,
|
|
'value': value}
|
|
|
|
res = self.client.post(self._get_url_with_arg(ADD_URL, config.id),
|
|
post)
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_get, 2,
|
|
mock.call(test.IsHttpRequest(), test.IsA(str)))
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_configuration_parameters_list, 2,
|
|
mock.call(test.IsHttpRequest(), test.IsA(str), test.IsA(str)))
|
|
self.assertFormError(res, "form", 'value',
|
|
['Value must be a number.'])
|
|
finally:
|
|
config_param_manager.delete(config.id)
|
|
|
|
@test.create_mocks({api.trove: ('configuration_instances',),
|
|
config_param_manager: ('get',)})
|
|
def test_instances_tab(self):
|
|
try:
|
|
config = self.database_configurations.first()
|
|
|
|
# setup the configuration parameter manager
|
|
config_param_mgr = config_param_manager.ConfigParamManager(
|
|
config.id)
|
|
config_param_mgr.configuration = config
|
|
config_param_mgr.original_configuration_values = \
|
|
dict.copy(config.values)
|
|
|
|
self.mock_get.return_value = config_param_mgr
|
|
|
|
self.mock_configuration_instances.return_value = (
|
|
self.configuration_instances.list())
|
|
|
|
details_url = self._get_url_with_arg(DETAIL_URL, config.id)
|
|
url = details_url + '?tab=configuration_details__instance'
|
|
|
|
res = self.client.get(url)
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_get, 2, mock.call(test.IsHttpRequest(), config.id))
|
|
self.mock_configuration_instances.assert_called_once_with(
|
|
test.IsHttpRequest(), config.id)
|
|
table_data = res.context['instances_table'].data
|
|
self.assertCountEqual(
|
|
self.configuration_instances.list(), table_data)
|
|
self.assertTemplateUsed(
|
|
res, 'project/database_configurations/details.html')
|
|
finally:
|
|
config_param_manager.delete(config.id)
|
|
|
|
@test.create_mocks({api.trove: ('configuration_instances',),
|
|
config_param_manager: ('get',)})
|
|
def test_instances_tab_exception(self):
|
|
try:
|
|
config = self.database_configurations.first()
|
|
|
|
# setup the configuration parameter manager
|
|
config_param_mgr = config_param_manager.ConfigParamManager(
|
|
config.id)
|
|
config_param_mgr.configuration = config
|
|
config_param_mgr.original_configuration_values = \
|
|
dict.copy(config.values)
|
|
|
|
self.mock_get.return_value = config_param_mgr
|
|
|
|
self.mock_configuration_instances.side_effect = (
|
|
self.exceptions.trove)
|
|
|
|
details_url = self._get_url_with_arg(DETAIL_URL, config.id)
|
|
url = details_url + '?tab=configuration_details__instance'
|
|
|
|
res = self.client.get(url)
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_get, 2, mock.call(test.IsHttpRequest(), config.id))
|
|
self.mock_configuration_instances.assert_called_once_with(
|
|
test.IsHttpRequest(), config.id)
|
|
table_data = res.context['instances_table'].data
|
|
self.assertNotEqual(len(self.configuration_instances.list()),
|
|
len(table_data))
|
|
self.assertTemplateUsed(
|
|
res, 'project/database_configurations/details.html')
|
|
finally:
|
|
config_param_manager.delete(config.id)
|
|
|
|
def _get_url_with_arg(self, url, arg):
|
|
return reverse(url, args=[arg])
|
|
|
|
def _get_test_datastore(self, datastore_name):
|
|
for ds in self.datastores.list():
|
|
if ds.name == datastore_name:
|
|
return ds
|
|
return None
|
|
|
|
def _get_test_datastore_version(self, datastore_id,
|
|
datastore_version_name):
|
|
for dsv in self.datastore_versions.list():
|
|
if (dsv.datastore == datastore_id and
|
|
dsv.name == datastore_version_name):
|
|
return dsv
|
|
return None
|