
This brings in a couple of new checks which must be addressed, many of which involve a rather large amount of changes, so these are ignored for now. A series of follow-up changes will resolved these. 'pycodestyle' is added as a dependency rather than it being pulled in transitively. This is necessary since we're using it in tests. Change-Id: I35c654bd39f343417e0a1124263ff31dcd0b05c9 Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
476 lines
16 KiB
Python
476 lines
16 KiB
Python
# Copyright 2015 HPE, 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 copy
|
|
|
|
import mock
|
|
import testtools
|
|
|
|
from nova import test
|
|
from nova.tests.functional import api_samples_test_base
|
|
|
|
|
|
class TestCompareResult(test.NoDBTestCase):
|
|
"""Provide test coverage for result comparison logic in functional tests.
|
|
|
|
_compare_result two types of comparisons, template data and sample
|
|
data.
|
|
|
|
Template data means the response is checked against a regex that is
|
|
referenced by the template name. The template name is specified in
|
|
the format %(name)
|
|
|
|
Sample data is a normal value comparison.
|
|
"""
|
|
|
|
def getApiSampleTestBaseHelper(self):
|
|
"""Build an instance without running any unwanted test methods"""
|
|
|
|
# NOTE(auggy): TestCase takes a "test" method name to run in __init__
|
|
# calling this way prevents additional test methods from running
|
|
ast_instance = api_samples_test_base.ApiSampleTestBase('setUp')
|
|
|
|
# required by ApiSampleTestBase
|
|
ast_instance.api_major_version = 'v2'
|
|
ast_instance._use_project_id = 'True'
|
|
|
|
# automagically create magic methods usually handled by test classes
|
|
ast_instance.compute = mock.MagicMock()
|
|
|
|
ast_instance.subs = ast_instance._get_regexes()
|
|
|
|
return ast_instance
|
|
|
|
def setUp(self):
|
|
super(TestCompareResult, self).setUp()
|
|
self.ast = self.getApiSampleTestBaseHelper()
|
|
|
|
def test_bare_strings_match(self):
|
|
"""compare 2 bare strings that match"""
|
|
sample_data = u'foo'
|
|
response_data = u'foo'
|
|
result = self.ast._compare_result(
|
|
expected=sample_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
# NOTE(auggy): _compare_result will not return a matched value in the
|
|
# case of bare strings. If they don't match it will throw an exception,
|
|
# otherwise it returns "None".
|
|
self.assertEqual(
|
|
expected=None,
|
|
observed=result,
|
|
message='Check _compare_result of 2 bare strings')
|
|
|
|
def test_bare_strings_no_match(self):
|
|
"""check 2 bare strings that don't match"""
|
|
sample_data = u'foo'
|
|
response_data = u'bar'
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=sample_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
def test_template_strings_match(self):
|
|
"""compare 2 template strings (contain %) that match"""
|
|
template_data = u'%(id)s'
|
|
response_data = u'858f295a-8543-45fa-804a-08f8356d616d'
|
|
result = self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
self.assertEqual(
|
|
expected=response_data,
|
|
observed=result,
|
|
message='Check _compare_result of 2 template strings')
|
|
|
|
def test_template_strings_no_match(self):
|
|
"""check 2 template strings (contain %) that don't match"""
|
|
template_data = u'%(id)s'
|
|
response_data = u'$58f295a-8543-45fa-804a-08f8356d616d'
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
# TODO(auggy): _compare_result needs a consistent return value
|
|
# In some cases it returns the value if it matched, in others it returns
|
|
# None. In all cases, it throws an exception if there's no match.
|
|
def test_bare_int_match(self):
|
|
"""check 2 bare ints that match"""
|
|
sample_data = 42
|
|
response_data = 42
|
|
result = self.ast._compare_result(
|
|
expected=sample_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
self.assertEqual(
|
|
expected=None,
|
|
observed=result,
|
|
message='Check _compare_result of 2 bare ints')
|
|
|
|
def test_bare_int_no_match(self):
|
|
"""check 2 bare ints that don't match"""
|
|
sample_data = 42
|
|
response_data = 43
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=sample_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
# TODO(auggy): _compare_result needs a consistent return value
|
|
def test_template_int_match(self):
|
|
"""check template int against string containing digits"""
|
|
template_data = u'%(int)s'
|
|
response_data = u'42'
|
|
|
|
result = self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
self.assertEqual(
|
|
expected=None,
|
|
observed=result,
|
|
message='Check _compare_result of template ints')
|
|
|
|
def test_template_int_no_match(self):
|
|
"""check template int against a string containing no digits"""
|
|
template_data = u'%(int)s'
|
|
response_data = u'foo'
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
def test_template_int_value(self):
|
|
"""check an int value of a template int throws exception"""
|
|
|
|
# template_data = u'%(int_test)'
|
|
# response_data = 42
|
|
|
|
# use an int instead of a string as the subs value
|
|
local_subs = copy.deepcopy(self.ast.subs)
|
|
local_subs.update({'int_test': 42})
|
|
|
|
with testtools.ExpectedException(TypeError):
|
|
self.ast.subs = local_subs
|
|
|
|
# TODO(auggy): _compare_result needs a consistent return value
|
|
def test_dict_match(self):
|
|
"""check 2 matching dictionaries"""
|
|
template_data = {
|
|
u'server': {
|
|
u'id': u'%(id)s',
|
|
u'adminPass': u'%(password)s'
|
|
}
|
|
}
|
|
response_data = {
|
|
u'server': {
|
|
u'id': u'858f295a-8543-45fa-804a-08f8356d616d',
|
|
u'adminPass': u'4ZQ3bb6WYbC2'}
|
|
}
|
|
|
|
result = self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
self.assertEqual(
|
|
expected=u'858f295a-8543-45fa-804a-08f8356d616d',
|
|
observed=result,
|
|
message='Check _compare_result of 2 dictionaries')
|
|
|
|
def test_dict_no_match_value(self):
|
|
"""check 2 dictionaries where one has a different value"""
|
|
sample_data = {
|
|
u'server': {
|
|
u'id': u'858f295a-8543-45fa-804a-08f8356d616d',
|
|
u'adminPass': u'foo'
|
|
}
|
|
}
|
|
response_data = {
|
|
u'server': {
|
|
u'id': u'858f295a-8543-45fa-804a-08f8356d616d',
|
|
u'adminPass': u'4ZQ3bb6WYbC2'}
|
|
}
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=sample_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
def test_dict_no_match_extra_key(self):
|
|
"""check 2 dictionaries where one has an extra key"""
|
|
template_data = {
|
|
u'server': {
|
|
u'id': u'%(id)s',
|
|
u'adminPass': u'%(password)s',
|
|
u'foo': u'foo'
|
|
}
|
|
}
|
|
response_data = {
|
|
u'server': {
|
|
u'id': u'858f295a-8543-45fa-804a-08f8356d616d',
|
|
u'adminPass': u'4ZQ3bb6WYbC2'}
|
|
}
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
def test_dict_result_type_mismatch(self):
|
|
"""check expected is a dictionary and result is not a dictionary"""
|
|
|
|
template_data = {
|
|
u'server': {
|
|
u'id': u'%(id)s',
|
|
u'adminPass': u'%(password)s',
|
|
}
|
|
}
|
|
response_data = u'foo'
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
# TODO(auggy): _compare_result needs a consistent return value
|
|
def test_list_match(self):
|
|
"""check 2 matching lists"""
|
|
template_data = {
|
|
u'links':
|
|
[
|
|
{
|
|
u'href': u'%(versioned_compute_endpoint)s/server/%(uuid)s',
|
|
u'rel': u'self'
|
|
},
|
|
{
|
|
u'href': u'%(compute_endpoint)s/servers/%(uuid)s',
|
|
u'rel': u'bookmark'
|
|
}
|
|
]
|
|
}
|
|
response_data = {
|
|
u'links':
|
|
[
|
|
{
|
|
u'href':
|
|
(u'http://openstack.example.com/v2/%s/server/'
|
|
'858f295a-8543-45fa-804a-08f8356d616d' %
|
|
api_samples_test_base.PROJECT_ID
|
|
),
|
|
u'rel': u'self'
|
|
},
|
|
{
|
|
u'href':
|
|
(u'http://openstack.example.com/%s/servers/'
|
|
'858f295a-8543-45fa-804a-08f8356d616d' %
|
|
api_samples_test_base.PROJECT_ID
|
|
),
|
|
u'rel': u'bookmark'
|
|
}
|
|
]
|
|
}
|
|
|
|
result = self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
self.assertEqual(
|
|
expected=None,
|
|
observed=result,
|
|
message='Check _compare_result of 2 lists')
|
|
|
|
def test_list_match_extra_item_result(self):
|
|
"""check extra list items in result """
|
|
template_data = {
|
|
u'links':
|
|
[
|
|
{
|
|
u'href': u'%(versioned_compute_endpoint)s/server/%(uuid)s',
|
|
u'rel': u'self'
|
|
},
|
|
{
|
|
u'href': u'%(compute_endpoint)s/servers/%(uuid)s',
|
|
u'rel': u'bookmark'
|
|
}
|
|
]
|
|
}
|
|
response_data = {
|
|
u'links':
|
|
[
|
|
{
|
|
u'href':
|
|
(u'http://openstack.example.com/v2/openstack/server/'
|
|
'858f295a-8543-45fa-804a-08f8356d616d'),
|
|
u'rel': u'self'
|
|
},
|
|
{
|
|
u'href':
|
|
(u'http://openstack.example.com/openstack/servers/'
|
|
'858f295a-8543-45fa-804a-08f8356d616d'),
|
|
u'rel': u'bookmark'
|
|
},
|
|
u'foo'
|
|
]
|
|
}
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
def test_list_match_extra_item_template(self):
|
|
"""check extra list items in template """
|
|
template_data = {
|
|
u'links':
|
|
[
|
|
{
|
|
u'href': u'%(versioned_compute_endpoint)s/server/%(uuid)s',
|
|
u'rel': u'self'
|
|
},
|
|
{
|
|
u'href': u'%(compute_endpoint)s/servers/%(uuid)s',
|
|
u'rel': u'bookmark'
|
|
},
|
|
u'foo' # extra field
|
|
]
|
|
}
|
|
response_data = {
|
|
u'links':
|
|
[
|
|
{
|
|
u'href':
|
|
(u'http://openstack.example.com/v2/openstack/server/'
|
|
'858f295a-8543-45fa-804a-08f8356d616d'),
|
|
u'rel': u'self'
|
|
},
|
|
{
|
|
u'href':
|
|
(u'http://openstack.example.com/openstack/servers/'
|
|
'858f295a-8543-45fa-804a-08f8356d616d'),
|
|
u'rel': u'bookmark'
|
|
}
|
|
]
|
|
}
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
def test_list_no_match(self):
|
|
"""check 2 matching lists"""
|
|
template_data = {
|
|
u'things':
|
|
[
|
|
{
|
|
u'foo': u'bar',
|
|
u'baz': 0
|
|
},
|
|
{
|
|
u'foo': u'zod',
|
|
u'baz': 1
|
|
}
|
|
]
|
|
}
|
|
response_data = {
|
|
u'things':
|
|
[
|
|
{
|
|
u'foo': u'bar',
|
|
u'baz': u'0'
|
|
},
|
|
{
|
|
u'foo': u'zod',
|
|
u'baz': 1
|
|
}
|
|
]
|
|
}
|
|
|
|
# TODO(auggy): This error returns "extra list items"
|
|
# it should show the item/s in the list that didn't match
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
def test_none_match(self):
|
|
"""check that None matches"""
|
|
sample_data = None
|
|
response_data = None
|
|
result = self.ast._compare_result(
|
|
expected=sample_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
# NOTE(auggy): _compare_result will not return a matched value in the
|
|
# case of bare strings. If they don't match it will throw an exception,
|
|
# otherwise it returns "None".
|
|
self.assertEqual(
|
|
expected=None,
|
|
observed=result,
|
|
message='Check _compare_result of None')
|
|
|
|
def test_none_no_match(self):
|
|
"""check expected none and non-None response don't match"""
|
|
sample_data = None
|
|
response_data = u'bar'
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=sample_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
def test_none_result_no_match(self):
|
|
"""check result none and expected non-None response don't match"""
|
|
sample_data = u'foo'
|
|
response_data = None
|
|
|
|
with testtools.ExpectedException(api_samples_test_base.NoMatch):
|
|
self.ast._compare_result(
|
|
expected=sample_data,
|
|
result=response_data,
|
|
result_str="Test")
|
|
|
|
def test_template_no_subs_key(self):
|
|
"""check an int value of a template int throws exception"""
|
|
template_data = u'%(foo)'
|
|
response_data = 'bar'
|
|
|
|
with testtools.ExpectedException(KeyError):
|
|
self.ast._compare_result(
|
|
expected=template_data,
|
|
result=response_data,
|
|
result_str="Test")
|