176 lines
6.9 KiB
Python
176 lines
6.9 KiB
Python
# Copyright 2012 OpenStack Foundation
|
|
# 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 mock
|
|
from neutron_lib.api import converters
|
|
from neutron_lib import constants
|
|
from neutron_lib import exceptions as n_exc
|
|
from oslo_utils import uuidutils
|
|
import webob.exc
|
|
|
|
from neutron.api.v2 import attributes
|
|
from neutron import context
|
|
from neutron.tests import base
|
|
|
|
|
|
class TestResDict(base.BaseTestCase):
|
|
class _MyException(Exception):
|
|
pass
|
|
_EXC_CLS = _MyException
|
|
|
|
def _test_fill_default_value(self, attr_info, expected, res_dict):
|
|
attributes.fill_default_value(attr_info, res_dict)
|
|
self.assertEqual(expected, res_dict)
|
|
|
|
def test_fill_default_value(self):
|
|
attr_info = {
|
|
'key': {
|
|
'allow_post': True,
|
|
'default': constants.ATTR_NOT_SPECIFIED,
|
|
},
|
|
}
|
|
self._test_fill_default_value(attr_info, {'key': 'X'}, {'key': 'X'})
|
|
self._test_fill_default_value(
|
|
attr_info, {'key': constants.ATTR_NOT_SPECIFIED}, {})
|
|
|
|
attr_info = {
|
|
'key': {
|
|
'allow_post': True,
|
|
},
|
|
}
|
|
self._test_fill_default_value(attr_info, {'key': 'X'}, {'key': 'X'})
|
|
self.assertRaises(ValueError, self._test_fill_default_value,
|
|
attr_info, {'key': 'X'}, {})
|
|
self.assertRaises(self._EXC_CLS, attributes.fill_default_value,
|
|
attr_info, {}, self._EXC_CLS)
|
|
attr_info = {
|
|
'key': {
|
|
'allow_post': False,
|
|
},
|
|
}
|
|
self.assertRaises(ValueError, self._test_fill_default_value,
|
|
attr_info, {'key': 'X'}, {'key': 'X'})
|
|
self._test_fill_default_value(attr_info, {}, {})
|
|
self.assertRaises(self._EXC_CLS, attributes.fill_default_value,
|
|
attr_info, {'key': 'X'}, self._EXC_CLS)
|
|
|
|
def _test_convert_value(self, attr_info, expected, res_dict):
|
|
attributes.convert_value(attr_info, res_dict)
|
|
self.assertEqual(expected, res_dict)
|
|
|
|
def test_convert_value(self):
|
|
attr_info = {
|
|
'key': {
|
|
},
|
|
}
|
|
self._test_convert_value(attr_info,
|
|
{'key': constants.ATTR_NOT_SPECIFIED},
|
|
{'key': constants.ATTR_NOT_SPECIFIED})
|
|
self._test_convert_value(attr_info, {'key': 'X'}, {'key': 'X'})
|
|
self._test_convert_value(attr_info,
|
|
{'other_key': 'X'}, {'other_key': 'X'})
|
|
|
|
attr_info = {
|
|
'key': {
|
|
'convert_to': converters.convert_to_int,
|
|
},
|
|
}
|
|
self._test_convert_value(attr_info,
|
|
{'key': constants.ATTR_NOT_SPECIFIED},
|
|
{'key': constants.ATTR_NOT_SPECIFIED})
|
|
self._test_convert_value(attr_info, {'key': 1}, {'key': '1'})
|
|
self._test_convert_value(attr_info, {'key': 1}, {'key': 1})
|
|
self.assertRaises(n_exc.InvalidInput, self._test_convert_value,
|
|
attr_info, {'key': 1}, {'key': 'a'})
|
|
|
|
attr_info = {
|
|
'key': {
|
|
'validate': {'type:uuid': None},
|
|
},
|
|
}
|
|
self._test_convert_value(attr_info,
|
|
{'key': constants.ATTR_NOT_SPECIFIED},
|
|
{'key': constants.ATTR_NOT_SPECIFIED})
|
|
uuid_str = '01234567-1234-1234-1234-1234567890ab'
|
|
self._test_convert_value(attr_info,
|
|
{'key': uuid_str}, {'key': uuid_str})
|
|
self.assertRaises(ValueError, self._test_convert_value,
|
|
attr_info, {'key': 1}, {'key': 1})
|
|
self.assertRaises(self._EXC_CLS, attributes.convert_value,
|
|
attr_info, {'key': 1}, self._EXC_CLS)
|
|
|
|
def test_populate_tenant_id(self):
|
|
tenant_id_1 = uuidutils.generate_uuid()
|
|
tenant_id_2 = uuidutils.generate_uuid()
|
|
# apart from the admin, nobody can create a res on behalf of another
|
|
# tenant
|
|
ctx = context.Context(user_id=None, tenant_id=tenant_id_1)
|
|
res_dict = {'tenant_id': tenant_id_2}
|
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
|
attributes.populate_tenant_id,
|
|
ctx, res_dict, None, None)
|
|
ctx.is_admin = True
|
|
self.assertIsNone(attributes.populate_tenant_id(ctx, res_dict,
|
|
None, None))
|
|
|
|
# for each create request, the tenant_id should be added to the
|
|
# req body
|
|
res_dict2 = {}
|
|
attributes.populate_tenant_id(ctx, res_dict2, None, True)
|
|
self.assertEqual(
|
|
{'tenant_id': ctx.tenant_id, 'project_id': ctx.tenant_id},
|
|
res_dict2)
|
|
|
|
# if the tenant_id is mandatory for the resource and not specified
|
|
# in the request nor in the context, an exception should be raised
|
|
res_dict3 = {}
|
|
attr_info = {'tenant_id': {'allow_post': True}, }
|
|
ctx.tenant_id = None
|
|
self.assertRaises(webob.exc.HTTPBadRequest,
|
|
attributes.populate_tenant_id,
|
|
ctx, res_dict3, attr_info, True)
|
|
|
|
|
|
class TestHelpers(base.DietTestCase):
|
|
|
|
def _verify_port_attributes(self, attrs):
|
|
for test_attribute in ('id', 'name', 'mac_address', 'network_id',
|
|
'tenant_id', 'fixed_ips', 'status'):
|
|
self.assertIn(test_attribute, attrs)
|
|
|
|
def test_get_collection_info(self):
|
|
attrs = attributes.get_collection_info('ports')
|
|
self._verify_port_attributes(attrs)
|
|
|
|
def test_get_collection_info_missing(self):
|
|
self.assertFalse(attributes.get_collection_info('meh'))
|
|
|
|
def test_get_resource_info(self):
|
|
attributes.REVERSED_PLURALS.pop('port', None)
|
|
attrs = attributes.get_resource_info('port')
|
|
self._verify_port_attributes(attrs)
|
|
# verify side effect
|
|
self.assertIn('port', attributes.REVERSED_PLURALS)
|
|
|
|
def test_get_resource_info_missing(self):
|
|
self.assertFalse(attributes.get_resource_info('meh'))
|
|
|
|
def test_get_resource_info_cached(self):
|
|
with mock.patch('neutron.api.v2.attributes.PLURALS') as mock_plurals:
|
|
attributes.REVERSED_PLURALS['port'] = 'ports'
|
|
attrs = attributes.get_resource_info('port')
|
|
self._verify_port_attributes(attrs)
|
|
self.assertEqual(0, mock_plurals.items.call_count)
|