![Thomas Goirand](/assets/img/avatar_default.png)
Previously "repr" was automatically applied to "qs" argument of assertQuerysetEqual() and most horizon unittest behaviors assume it. It was deprecated in Django 3.2 and removed in Django 4.1. We need to specify transform=repr explicitly to use the existing behavior. [1] https://docs.djangoproject.com/en/3.2/topics/testing/tools/#django.test.TransactionTestCase.assertQuerysetEqual Closes-Bug: #2038474 Change-Id: Ie7c7e9a1efc492889639e25509c8e614268c1d26
591 lines
25 KiB
Python
591 lines
25 KiB
Python
# 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.
|
|
|
|
from unittest import mock
|
|
|
|
import django
|
|
from django.conf import settings
|
|
from django.urls import reverse
|
|
from novaclient.v2 import flavors
|
|
|
|
from openstack_dashboard import api
|
|
from openstack_dashboard.dashboards.admin.flavors import constants
|
|
from openstack_dashboard.dashboards.admin.flavors import tables
|
|
from openstack_dashboard.dashboards.admin.flavors import workflows
|
|
from openstack_dashboard.test import helpers as test
|
|
|
|
|
|
class FlavorsViewTests(test.BaseAdminViewTests):
|
|
|
|
@test.create_mocks({api.nova: ('flavor_list_paged',),
|
|
flavors.Flavor: ('get_keys',), })
|
|
def test_index(self):
|
|
self.mock_flavor_list_paged.return_value = (self.flavors.list(),
|
|
False, False)
|
|
self.mock_get_keys.return_value = {}
|
|
|
|
res = self.client.get(reverse(constants.FLAVORS_INDEX_URL))
|
|
self.assertTemplateUsed(res, constants.FLAVORS_TEMPLATE_NAME)
|
|
self.assertCountEqual(res.context['table'].data, self.flavors.list())
|
|
|
|
self.mock_flavor_list_paged.assert_called_once_with(
|
|
test.IsHttpRequest(), None, marker=None, paginate=True,
|
|
sort_dir='asc', sort_key='name', reversed_order=False)
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_get_keys, 4, mock.call())
|
|
|
|
@django.test.utils.override_settings(API_RESULT_PAGE_SIZE=2)
|
|
@test.create_mocks({api.nova: ('flavor_list_paged',),
|
|
flavors.Flavor: ('get_keys',), })
|
|
def test_index_pagination(self):
|
|
flavors_list = self.flavors.list()[:4]
|
|
self.mock_flavor_list_paged.side_effect = [
|
|
(flavors_list, True, True),
|
|
(flavors_list[:2], True, True),
|
|
(flavors_list[2:4], True, True),
|
|
]
|
|
self.mock_get_keys.return_value = {}
|
|
|
|
# get all
|
|
res = self.client.get(reverse(constants.FLAVORS_INDEX_URL))
|
|
self.assertTemplateUsed(res, constants.FLAVORS_TEMPLATE_NAME)
|
|
self.assertCountEqual(res.context['table'].data,
|
|
self.flavors.list()[:5])
|
|
|
|
# get first page with 2 items
|
|
res = self.client.get(reverse(constants.FLAVORS_INDEX_URL))
|
|
self.assertTemplateUsed(res, constants.FLAVORS_TEMPLATE_NAME)
|
|
self.assertCountEqual(res.context['table'].data,
|
|
self.flavors.list()[:2])
|
|
|
|
# get second page (items 2-4)
|
|
params = "=".join([tables.FlavorsTable._meta.pagination_param,
|
|
flavors_list[2].id])
|
|
url = "?".join([reverse(constants.FLAVORS_INDEX_URL), params])
|
|
res = self.client.get(url)
|
|
self.assertCountEqual(res.context['table'].data,
|
|
self.flavors.list()[2:4])
|
|
|
|
self.mock_flavor_list_paged.assert_has_calls([
|
|
mock.call(test.IsHttpRequest(), None,
|
|
marker=None, paginate=True,
|
|
sort_dir='asc', sort_key='name',
|
|
reversed_order=False),
|
|
mock.call(test.IsHttpRequest(), None,
|
|
marker=None, paginate=True,
|
|
sort_dir='asc', sort_key='name',
|
|
reversed_order=False),
|
|
mock.call(test.IsHttpRequest(), None,
|
|
marker=flavors_list[2].id, paginate=True,
|
|
sort_dir='asc', sort_key='name',
|
|
reversed_order=False),
|
|
])
|
|
self.assertEqual(3, self.mock_flavor_list_paged.call_count)
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_get_keys, 8, mock.call())
|
|
|
|
@django.test.utils.override_settings(API_RESULT_PAGE_SIZE=2)
|
|
@test.create_mocks({api.nova: ('flavor_list_paged',),
|
|
flavors.Flavor: ('get_keys',), })
|
|
def test_index_prev_pagination(self):
|
|
flavors_list = self.flavors.list()[:3]
|
|
self.mock_flavor_list_paged.side_effect = [
|
|
(flavors_list, True, False),
|
|
(flavors_list[:2], True, True),
|
|
(flavors_list[2:], True, True),
|
|
(flavors_list[:2], True, True),
|
|
]
|
|
self.mock_get_keys.return_value = {}
|
|
|
|
# get all
|
|
res = self.client.get(reverse(constants.FLAVORS_INDEX_URL))
|
|
self.assertTemplateUsed(res, constants.FLAVORS_TEMPLATE_NAME)
|
|
self.assertCountEqual(res.context['table'].data,
|
|
self.flavors.list()[:3])
|
|
# get first page with 2 items
|
|
res = self.client.get(reverse(constants.FLAVORS_INDEX_URL))
|
|
self.assertEqual(len(res.context['table'].data),
|
|
settings.API_RESULT_PAGE_SIZE)
|
|
self.assertCountEqual(res.context['table'].data,
|
|
self.flavors.list()[:2])
|
|
params = "=".join([tables.FlavorsTable._meta.pagination_param,
|
|
flavors_list[2].id])
|
|
url = "?".join([reverse(constants.FLAVORS_INDEX_URL), params])
|
|
res = self.client.get(url)
|
|
# get second page (item 3)
|
|
self.assertEqual(len(res.context['table'].data), 1)
|
|
self.assertCountEqual(res.context['table'].data,
|
|
self.flavors.list()[2:3])
|
|
|
|
params = "=".join([tables.FlavorsTable._meta.prev_pagination_param,
|
|
flavors_list[2].id])
|
|
url = "?".join([reverse(constants.FLAVORS_INDEX_URL), params])
|
|
res = self.client.get(url)
|
|
# prev back to get first page with 2 items
|
|
self.assertEqual(len(res.context['table'].data),
|
|
settings.API_RESULT_PAGE_SIZE)
|
|
self.assertCountEqual(res.context['table'].data,
|
|
self.flavors.list()[:2])
|
|
|
|
self.mock_flavor_list_paged.assert_has_calls([
|
|
mock.call(test.IsHttpRequest(), None,
|
|
marker=None, paginate=True,
|
|
sort_dir='asc', sort_key='name',
|
|
reversed_order=False),
|
|
mock.call(test.IsHttpRequest(), None,
|
|
marker=None, paginate=True,
|
|
sort_dir='asc', sort_key='name',
|
|
reversed_order=False),
|
|
mock.call(test.IsHttpRequest(), None,
|
|
marker=flavors_list[2].id, paginate=True,
|
|
sort_dir='asc', sort_key='name',
|
|
reversed_order=False),
|
|
mock.call(test.IsHttpRequest(), None,
|
|
marker=flavors_list[2].id, paginate=True,
|
|
sort_dir='asc', sort_key='name',
|
|
reversed_order=True),
|
|
])
|
|
self.assertEqual(4, self.mock_flavor_list_paged.call_count)
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_get_keys, 8, mock.call())
|
|
|
|
@django.test.utils.override_settings(API_RESULT_PAGE_SIZE=1)
|
|
@test.create_mocks({api.nova: ('flavor_list_paged',),
|
|
flavors.Flavor: ('get_keys',), })
|
|
def test_index_form_action_with_pagination(self):
|
|
page_size = settings.API_RESULT_PAGE_SIZE
|
|
flavors_list = self.flavors.list()[:2]
|
|
self.mock_flavor_list_paged.side_effect = [
|
|
(flavors_list[:page_size], False, False),
|
|
(flavors_list[page_size:], False, False),
|
|
]
|
|
self.mock_get_keys.return_value = {}
|
|
|
|
res = self.client.get(reverse(constants.FLAVORS_INDEX_URL))
|
|
self.assertTemplateUsed(res, constants.FLAVORS_TEMPLATE_NAME)
|
|
self.assertEqual(len(res.context['table'].data), page_size)
|
|
|
|
params = "=".join([tables.FlavorsTable._meta.pagination_param,
|
|
flavors_list[page_size - 1].id])
|
|
next_page_url = "?".join([reverse(constants.FLAVORS_INDEX_URL),
|
|
params])
|
|
form_action = 'action="%s"' % next_page_url
|
|
|
|
res = self.client.get(next_page_url)
|
|
self.assertEqual(len(res.context['table'].data), 1)
|
|
self.assertContains(res, form_action, count=1)
|
|
|
|
self.mock_flavor_list_paged.assert_has_calls([
|
|
mock.call(test.IsHttpRequest(), None,
|
|
marker=None, paginate=True,
|
|
sort_dir='asc', sort_key='name',
|
|
reversed_order=False),
|
|
mock.call(test.IsHttpRequest(), None,
|
|
marker=flavors_list[page_size - 1].id,
|
|
paginate=True,
|
|
sort_dir='asc', sort_key='name',
|
|
reversed_order=False),
|
|
])
|
|
self.assertEqual(2, self.mock_flavor_list_paged.call_count)
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_get_keys, 2, mock.call())
|
|
|
|
|
|
class BaseFlavorWorkflowTests(test.BaseAdminViewTests):
|
|
|
|
def _flavor_create_params(self, flavor, id=None):
|
|
eph = getattr(flavor, 'OS-FLV-EXT-DATA:ephemeral')
|
|
flavor_info = {"name": flavor.name,
|
|
"vcpu": flavor.vcpus,
|
|
"memory": flavor.ram,
|
|
"disk": flavor.disk,
|
|
"swap": flavor.swap,
|
|
"rxtx_factor": flavor.rxtx_factor,
|
|
"ephemeral": eph,
|
|
"is_public": flavor.is_public}
|
|
if id:
|
|
flavor_info["flavorid"] = id
|
|
return flavor_info
|
|
|
|
def _get_workflow_data(self, flavor, id=None, access=None):
|
|
eph = getattr(flavor, 'OS-FLV-EXT-DATA:ephemeral')
|
|
flavor_info = {"name": flavor.name,
|
|
"vcpus": flavor.vcpus,
|
|
"memory_mb": flavor.ram,
|
|
"disk_gb": flavor.disk,
|
|
"swap_mb": flavor.swap,
|
|
"rxtx_factor": flavor.rxtx_factor,
|
|
"eph_gb": eph}
|
|
self._get_access_field(flavor_info, access)
|
|
if id:
|
|
flavor_info['flavor_id'] = id
|
|
return flavor_info
|
|
|
|
def _get_access_field(self, flavor_info=None, access=None):
|
|
flavor_info = flavor_info or {}
|
|
if access is not None:
|
|
access_field_name = 'flavor_access_role_member'
|
|
flavor_info[access_field_name] = [p.id for p in access]
|
|
return flavor_info
|
|
|
|
|
|
class CreateFlavorWorkflowTests(BaseFlavorWorkflowTests):
|
|
@test.create_mocks({api.keystone: ('tenant_list',), })
|
|
def test_workflow_get(self):
|
|
projects = self.tenants.list()
|
|
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
|
|
url = reverse(constants.FLAVORS_CREATE_URL)
|
|
res = self.client.get(url)
|
|
self.assertTemplateUsed(res, constants.FLAVORS_CREATE_VIEW_TEMPLATE)
|
|
workflow = res.context['workflow']
|
|
expected_name = workflows.CreateFlavor.name
|
|
self.assertEqual(res.context['workflow'].name, expected_name)
|
|
self.assertQuerysetEqual(
|
|
workflow.steps,
|
|
['<CreateFlavorInfo: createflavorinfoaction>',
|
|
'<CreateFlavorAccess: flavor_access>'],
|
|
transform=repr)
|
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
|
|
|
|
@test.create_mocks({api.keystone: ('tenant_list',),
|
|
api.nova: ('flavor_list',
|
|
'flavor_create',)})
|
|
def test_create_flavor_without_projects_post(self):
|
|
flavor = self.flavors.first()
|
|
projects = self.tenants.list()
|
|
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_list.return_value = []
|
|
self.mock_flavor_create.return_value = flavor
|
|
|
|
workflow_data = self._get_workflow_data(flavor)
|
|
|
|
url = reverse(constants.FLAVORS_CREATE_URL)
|
|
res = self.client.post(url, workflow_data)
|
|
|
|
self.assertNoFormErrors(res)
|
|
self.assertRedirectsNoFollow(res, reverse(constants.FLAVORS_INDEX_URL))
|
|
|
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.mock_flavor_list.assert_called_once_with(test.IsHttpRequest(),
|
|
None)
|
|
params = self._flavor_create_params(flavor, id='auto')
|
|
self.mock_flavor_create.assert_called_once_with(test.IsHttpRequest(),
|
|
**params)
|
|
|
|
@test.create_mocks({api.keystone: ('tenant_list',),
|
|
api.nova: ('flavor_list',
|
|
'flavor_create',
|
|
'add_tenant_to_flavor',)})
|
|
def test_create_flavor_with_projects_post(self):
|
|
flavor = self.flavors.first()
|
|
projects = self.tenants.list()
|
|
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_list.return_value = []
|
|
self.mock_flavor_create.return_value = flavor
|
|
self.mock_add_tenant_to_flavor.return_value = None
|
|
|
|
workflow_data = self._get_workflow_data(flavor, access=projects)
|
|
|
|
url = reverse(constants.FLAVORS_CREATE_URL)
|
|
res = self.client.post(url, workflow_data)
|
|
|
|
self.assertNoFormErrors(res)
|
|
self.assertRedirectsNoFollow(res, reverse(constants.FLAVORS_INDEX_URL))
|
|
|
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.mock_flavor_list.assert_called_once_with(test.IsHttpRequest(),
|
|
None)
|
|
params = self._flavor_create_params(flavor, id='auto')
|
|
params['is_public'] = False
|
|
self.mock_flavor_create.assert_called_once_with(test.IsHttpRequest(),
|
|
**params)
|
|
self.mock_add_tenant_to_flavor.assert_has_calls(
|
|
[mock.call(test.IsHttpRequest(), flavor.id, project.id)
|
|
for project in projects]
|
|
)
|
|
self.assertEqual(len(projects),
|
|
self.mock_add_tenant_to_flavor.call_count)
|
|
|
|
@test.create_mocks({api.keystone: ('tenant_list',),
|
|
api.nova: ('flavor_list',)})
|
|
def test_create_existing_flavor_name_error(self):
|
|
flavor = self.flavors.first()
|
|
projects = self.tenants.list()
|
|
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_list.return_value = self.flavors.list()
|
|
|
|
workflow_data = self._get_workflow_data(flavor)
|
|
|
|
url = reverse(constants.FLAVORS_CREATE_URL)
|
|
res = self.client.post(url, workflow_data)
|
|
|
|
self.assertFormErrors(res)
|
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.mock_flavor_list.assert_called_once_with(test.IsHttpRequest(),
|
|
None)
|
|
|
|
@test.create_mocks({api.keystone: ('tenant_list',),
|
|
api.nova: ('flavor_list',)})
|
|
def test_create_existing_flavor_id_error(self):
|
|
flavor = self.flavors.first()
|
|
projects = self.tenants.list()
|
|
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_list.return_value = self.flavors.list()
|
|
|
|
workflow_data = self._get_workflow_data(flavor)
|
|
# Name is okay.
|
|
workflow_data['name'] = 'newflavorname'
|
|
# Flavor id already exists.
|
|
workflow_data['flavor_id'] = flavor.id
|
|
|
|
url = reverse(constants.FLAVORS_CREATE_URL)
|
|
res = self.client.post(url, workflow_data)
|
|
|
|
self.assertFormErrors(res)
|
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.mock_flavor_list.assert_called_once_with(test.IsHttpRequest(),
|
|
None)
|
|
|
|
@test.create_mocks({api.keystone: ('tenant_list',),
|
|
api.nova: ('flavor_list',
|
|
'flavor_create',
|
|
'add_tenant_to_flavor',)})
|
|
def test_create_flavor_project_update_error(self):
|
|
flavor = self.flavors.first()
|
|
projects = self.tenants.list()
|
|
|
|
# init
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_list.return_value = []
|
|
self.mock_flavor_create.return_value = flavor
|
|
retvals_add_tenant = [None for project in projects]
|
|
retvals_add_tenant[0] = self.exceptions.nova
|
|
self.mock_add_tenant_to_flavor.side_effect = retvals_add_tenant
|
|
|
|
workflow_data = self._get_workflow_data(flavor, access=projects)
|
|
|
|
url = reverse(constants.FLAVORS_CREATE_URL)
|
|
res = self.client.post(url, workflow_data)
|
|
|
|
self.assertNoFormErrors(res)
|
|
self.assertMessageCount(error=1, warning=0)
|
|
self.assertRedirectsNoFollow(res, reverse(constants.FLAVORS_INDEX_URL))
|
|
|
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.mock_flavor_list.assert_called_once_with(test.IsHttpRequest(),
|
|
None)
|
|
params = self._flavor_create_params(flavor, id='auto')
|
|
params['is_public'] = False
|
|
self.mock_flavor_create.assert_called_once_with(test.IsHttpRequest(),
|
|
**params)
|
|
self.mock_add_tenant_to_flavor.assert_has_calls(
|
|
[mock.call(test.IsHttpRequest(), flavor.id, project.id)
|
|
for project in projects]
|
|
)
|
|
self.assertEqual(len(projects),
|
|
self.mock_add_tenant_to_flavor.call_count)
|
|
|
|
@test.create_mocks({api.keystone: ('tenant_list',),
|
|
api.nova: ('flavor_list',)})
|
|
def test_create_flavor_missing_field_error(self):
|
|
flavor = self.flavors.first()
|
|
projects = self.tenants.list()
|
|
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_list.return_value = []
|
|
|
|
workflow_data = self._get_workflow_data(flavor)
|
|
workflow_data["name"] = ""
|
|
|
|
url = reverse(constants.FLAVORS_CREATE_URL)
|
|
res = self.client.post(url, workflow_data)
|
|
|
|
self.assertFormErrors(res)
|
|
self.assertContains(res, "field is required")
|
|
|
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.mock_flavor_list.assert_called_once_with(test.IsHttpRequest(),
|
|
None)
|
|
|
|
@test.create_mocks({api.keystone: ('tenant_list',),
|
|
api.nova: ('flavor_list',)})
|
|
def test_create_flavor_missing_swap_and_ephemeral_fields(self):
|
|
flavor = self.flavors.first()
|
|
projects = self.tenants.list()
|
|
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_list.return_value = self.flavors.list()
|
|
|
|
workflow_data = self._get_workflow_data(flavor)
|
|
# Swap field empty
|
|
del workflow_data['swap_mb']
|
|
# Ephemeral field empty
|
|
del workflow_data['eph_gb']
|
|
|
|
url = reverse(constants.FLAVORS_CREATE_URL)
|
|
res = self.client.post(url, workflow_data)
|
|
|
|
self.assertFormErrors(res)
|
|
|
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.mock_flavor_list.assert_called_once_with(test.IsHttpRequest(),
|
|
None)
|
|
|
|
|
|
class UpdateFlavorWorkflowTests(BaseFlavorWorkflowTests):
|
|
|
|
@test.create_mocks({api.nova: ('flavor_get',
|
|
'flavor_access_list',),
|
|
api.keystone: ('tenant_list',)})
|
|
def test_update_flavor_get(self):
|
|
flavor = self.flavors.list()[2]
|
|
flavor_access = self.flavor_access.list()
|
|
projects = self.tenants.list()
|
|
|
|
self.mock_flavor_get.return_value = flavor
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_access_list.return_value = flavor_access
|
|
|
|
url = reverse(constants.FLAVORS_UPDATE_URL, args=[flavor.id])
|
|
res = self.client.get(url)
|
|
|
|
self.assertTemplateUsed(res, constants.FLAVORS_UPDATE_VIEW_TEMPLATE)
|
|
|
|
workflow = res.context['workflow']
|
|
expected_name = workflows.UpdateFlavor.name
|
|
self.assertEqual(res.context['workflow'].name, expected_name)
|
|
|
|
self.assertQuerysetEqual(
|
|
workflow.steps,
|
|
['<UpdateFlavorAccess: flavor_access>'],
|
|
transform=repr)
|
|
|
|
step = workflow.get_step("flavor_access")
|
|
field_name = step.get_member_field_name('member')
|
|
self.assertEqual(step.action.fields[field_name].initial,
|
|
[fa.tenant_id for fa in flavor_access])
|
|
|
|
self.mock_flavor_get.assert_called_once_with(test.IsHttpRequest(),
|
|
flavor.id)
|
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest())
|
|
self.mock_flavor_access_list.assert_called_once_with(
|
|
test.IsHttpRequest(), flavor.id)
|
|
|
|
@test.create_mocks({api.nova: ('flavor_get',), })
|
|
def test_update_flavor_get_flavor_error(self):
|
|
flavor = self.flavors.first()
|
|
|
|
self.mock_flavor_get.side_effect = self.exceptions.nova
|
|
|
|
url = reverse(constants.FLAVORS_UPDATE_URL, args=[flavor.id])
|
|
res = self.client.get(url)
|
|
|
|
self.assertRedirectsNoFollow(res, reverse(constants.FLAVORS_INDEX_URL))
|
|
self.mock_flavor_get.assert_called_once_with(test.IsHttpRequest(),
|
|
flavor.id)
|
|
|
|
@test.create_mocks({api.keystone: ('tenant_list',),
|
|
api.nova: ('flavor_get',
|
|
'flavor_access_list',
|
|
'remove_tenant_from_flavor',
|
|
'add_tenant_to_flavor')})
|
|
def test_update_flavor_access(self):
|
|
# The third element is private (is_public False)
|
|
flavor = self.flavors.list()[2]
|
|
projects = self.tenants.list()
|
|
flavor_accesses = self.flavor_access.list()
|
|
|
|
self.mock_flavor_get.return_value = flavor
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_access_list.return_value = flavor_accesses
|
|
self.mock_add_tenant_to_flavor.return_value = None
|
|
self.mock_remove_tenant_from_flavor.return_value = None
|
|
|
|
# run get test
|
|
url = reverse(constants.FLAVORS_UPDATE_URL, args=[flavor.id])
|
|
resp = self.client.get(url)
|
|
self.assertEqual(resp.status_code, 200)
|
|
self.assertTemplateUsed(resp, constants.FLAVORS_UPDATE_VIEW_TEMPLATE)
|
|
|
|
# run post test
|
|
data = self._get_access_field(access=projects[1:3])
|
|
resp = self.client.post(url, data)
|
|
self.assertNoFormErrors(resp)
|
|
self.assertMessageCount(success=1, error=0, warning=0)
|
|
self.assertRedirectsNoFollow(resp,
|
|
reverse(constants.FLAVORS_INDEX_URL))
|
|
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_flavor_get, 2,
|
|
mock.call(test.IsHttpRequest(), flavor.id))
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_tenant_list, 2,
|
|
mock.call(test.IsHttpRequest()))
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_flavor_access_list, 2,
|
|
mock.call(test.IsHttpRequest(), flavor.id))
|
|
# NOTE: This test assumes self.tenants.list() and
|
|
# self.flavor_access.list() contains project IDs in a same order.
|
|
# Otherwise, mocking below will fail.
|
|
self.mock_add_tenant_to_flavor.assert_called_once_with(
|
|
test.IsHttpRequest(), flavor.id, projects[2].id)
|
|
self.mock_remove_tenant_from_flavor.assert_called_once_with(
|
|
test.IsHttpRequest(), flavor.id, projects[0].id)
|
|
|
|
@test.create_mocks({api.keystone: ('tenant_list',),
|
|
api.nova: ('flavor_get',
|
|
'flavor_access_list',
|
|
'add_tenant_to_flavor')})
|
|
def test_update_flavor_access_with_error(self):
|
|
# The third element is private (is_public False)
|
|
flavor = self.flavors.list()[2]
|
|
projects = self.tenants.list()
|
|
flavor_projects = [self.tenants.first()]
|
|
|
|
self.mock_flavor_get.return_value = flavor
|
|
self.mock_tenant_list.return_value = [projects, False]
|
|
self.mock_flavor_access_list.return_value = []
|
|
self.mock_add_tenant_to_flavor.side_effect = self.exceptions.nova
|
|
|
|
# run get test
|
|
url = reverse(constants.FLAVORS_UPDATE_URL, args=[flavor.id])
|
|
resp = self.client.get(url)
|
|
self.assertEqual(resp.status_code, 200)
|
|
self.assertTemplateUsed(resp, constants.FLAVORS_UPDATE_VIEW_TEMPLATE)
|
|
|
|
# run post test
|
|
data = self._get_access_field(access=flavor_projects)
|
|
resp = self.client.post(url, data)
|
|
self.assertNoFormErrors(resp)
|
|
self.assertMessageCount(error=1, warning=0)
|
|
self.assertRedirectsNoFollow(resp,
|
|
reverse(constants.FLAVORS_INDEX_URL))
|
|
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_flavor_get, 2,
|
|
mock.call(test.IsHttpRequest(), flavor.id))
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_tenant_list, 2,
|
|
mock.call(test.IsHttpRequest()))
|
|
self.assert_mock_multiple_calls_with_same_arguments(
|
|
self.mock_flavor_access_list, 2,
|
|
mock.call(test.IsHttpRequest(), flavor.id))
|
|
|
|
self.mock_add_tenant_to_flavor.assert_called_once_with(
|
|
test.IsHttpRequest(), flavor.id, flavor_projects[0].id)
|