Improve unit tests to succeed without hash tweak
PYTHONHASHSEED was set to 0 to disable hash randomization, because some tests assertions were order sensitive. This commit is to improve the assertions, so the PYTHONHASHSEED hack in tox.ini is not needed. Change-Id: I4ff09d202af818d27321e8e83718e82d0c48e3d2 Closes-Bug: 1348818
This commit is contained in:
parent
87e625e20c
commit
b070ed0286
|
@ -17,6 +17,7 @@ import json
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
import mox
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
|
@ -1229,11 +1230,11 @@ class LoadBalancerTest(common.HeatTestCase):
|
||||||
template['Resources'][lb_name]['Properties']['metadata'] = {
|
template['Resources'][lb_name]['Properties']['metadata'] = {
|
||||||
'a': 1, 'b': 2}
|
'a': 1, 'b': 2}
|
||||||
expected_body = copy.deepcopy(self.expected_body)
|
expected_body = copy.deepcopy(self.expected_body)
|
||||||
expected_body['metadata'] = [{'key': 'a', 'value': 1},
|
expected_body['metadata'] = mox.SameElementsAs(
|
||||||
{'key': 'b', 'value': 2}]
|
[{'key': 'a', 'value': 1},
|
||||||
rsrc, fake_loadbalancer = self._mock_loadbalancer(template,
|
{'key': 'b', 'value': 2}])
|
||||||
self.lb_name,
|
rsrc, fake_loadbalancer = self._mock_loadbalancer(
|
||||||
expected_body)
|
template, self.lb_name, expected_body)
|
||||||
|
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
scheduler.TaskRunner(rsrc.create)()
|
scheduler.TaskRunner(rsrc.create)()
|
||||||
|
|
|
@ -24,12 +24,13 @@ from heat.api.aws import ec2token
|
||||||
from heat.api.aws import exception
|
from heat.api.aws import exception
|
||||||
from heat.common import wsgi
|
from heat.common import wsgi
|
||||||
from heat.tests import common
|
from heat.tests import common
|
||||||
|
from heat.tests import utils
|
||||||
|
|
||||||
|
|
||||||
class Ec2TokenTest(common.HeatTestCase):
|
class Ec2TokenTest(common.HeatTestCase):
|
||||||
'''
|
"""
|
||||||
Tests the Ec2Token middleware
|
Tests the Ec2Token middleware
|
||||||
'''
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(Ec2TokenTest, self).setUp()
|
super(Ec2TokenTest, self).setUp()
|
||||||
|
@ -253,8 +254,9 @@ class Ec2TokenTest(common.HeatTestCase):
|
||||||
"path": "/v1",
|
"path": "/v1",
|
||||||
"body_hash": body_hash}})
|
"body_hash": body_hash}})
|
||||||
req_headers = {'Content-Type': 'application/json'}
|
req_headers = {'Content-Type': 'application/json'}
|
||||||
requests.post(req_url, data=req_creds, verify=verify, cert=cert,
|
requests.post(
|
||||||
headers=req_headers).AndReturn(DummyHTTPResponse())
|
req_url, data=utils.JsonEquals(req_creds), verify=verify,
|
||||||
|
cert=cert, headers=req_headers).AndReturn(DummyHTTPResponse())
|
||||||
|
|
||||||
def test_call_ok(self):
|
def test_call_ok(self):
|
||||||
dummy_conf = {'auth_uri': 'http://123:5000/v2.0'}
|
dummy_conf = {'auth_uri': 'http://123:5000/v2.0'}
|
||||||
|
|
|
@ -33,10 +33,10 @@ policy_path = os.path.dirname(os.path.realpath(__file__)) + "/../../policy/"
|
||||||
|
|
||||||
|
|
||||||
class CfnStackControllerTest(common.HeatTestCase):
|
class CfnStackControllerTest(common.HeatTestCase):
|
||||||
'''
|
"""
|
||||||
Tests the API class which acts as the WSGI controller,
|
Tests the API class which acts as the WSGI controller,
|
||||||
the endpoint processing API requests after they are routed
|
the endpoint processing API requests after they are routed
|
||||||
'''
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(CfnStackControllerTest, self).setUp()
|
super(CfnStackControllerTest, self).setUp()
|
||||||
|
@ -333,7 +333,8 @@ class CfnStackControllerTest(common.HeatTestCase):
|
||||||
'DisableRollback': 'true',
|
'DisableRollback': 'true',
|
||||||
'LastUpdatedTime': u'2012-07-09T09:13:11Z'}]}}}
|
'LastUpdatedTime': u'2012-07-09T09:13:11Z'}]}}}
|
||||||
|
|
||||||
self.assertEqual(expected, response)
|
self.assertEqual(utils.recursive_sort(expected),
|
||||||
|
utils.recursive_sort(response))
|
||||||
|
|
||||||
def test_describe_arn(self):
|
def test_describe_arn(self):
|
||||||
# Format a dummy GET request to pass into the WSGI handler
|
# Format a dummy GET request to pass into the WSGI handler
|
||||||
|
@ -417,7 +418,8 @@ class CfnStackControllerTest(common.HeatTestCase):
|
||||||
'DisableRollback': 'true',
|
'DisableRollback': 'true',
|
||||||
'LastUpdatedTime': u'2012-07-09T09:13:11Z'}]}}}
|
'LastUpdatedTime': u'2012-07-09T09:13:11Z'}]}}}
|
||||||
|
|
||||||
self.assertEqual(expected, response)
|
self.assertEqual(utils.recursive_sort(expected),
|
||||||
|
utils.recursive_sort(response))
|
||||||
|
|
||||||
def test_describe_arn_invalidtenant(self):
|
def test_describe_arn_invalidtenant(self):
|
||||||
# Format a dummy GET request to pass into the WSGI handler
|
# Format a dummy GET request to pass into the WSGI handler
|
||||||
|
@ -481,7 +483,7 @@ class CfnStackControllerTest(common.HeatTestCase):
|
||||||
self.assertIsInstance(result, exception.HeatInvalidParameterValueError)
|
self.assertIsInstance(result, exception.HeatInvalidParameterValueError)
|
||||||
|
|
||||||
def test_get_template_int_body(self):
|
def test_get_template_int_body(self):
|
||||||
'''Test the internal _get_template function.'''
|
"""Test the internal _get_template function."""
|
||||||
params = {'TemplateBody': "abcdef"}
|
params = {'TemplateBody': "abcdef"}
|
||||||
dummy_req = self._dummy_GET_request(params)
|
dummy_req = self._dummy_GET_request(params)
|
||||||
result = self.controller._get_template(dummy_req)
|
result = self.controller._get_template(dummy_req)
|
||||||
|
|
|
@ -73,11 +73,13 @@ class WatchControllerTest(common.HeatTestCase):
|
||||||
|
|
||||||
dims = [{'StackId': u'21617058-781e-4262-97ab-5f9df371ee52',
|
dims = [{'StackId': u'21617058-781e-4262-97ab-5f9df371ee52',
|
||||||
'Foo': 'bar'}]
|
'Foo': 'bar'}]
|
||||||
self.assertEqual([{'Name': 'StackId',
|
self.assertEqual(
|
||||||
|
utils.recursive_sort(
|
||||||
|
[{'Name': 'StackId',
|
||||||
'Value': u'21617058-781e-4262-97ab-5f9df371ee52'},
|
'Value': u'21617058-781e-4262-97ab-5f9df371ee52'},
|
||||||
{'Name': 'Foo', 'Value': 'bar'}],
|
{'Name': 'Foo',
|
||||||
self.controller._reformat_dimensions(dims)
|
'Value': 'bar'}]),
|
||||||
)
|
utils.recursive_sort(self.controller._reformat_dimensions(dims)))
|
||||||
|
|
||||||
def test_enforce_default(self):
|
def test_enforce_default(self):
|
||||||
self.m.ReplayAll()
|
self.m.ReplayAll()
|
||||||
|
@ -301,7 +303,9 @@ class WatchControllerTest(common.HeatTestCase):
|
||||||
'MetricName': u'ServiceFailure3'}]}}}
|
'MetricName': u'ServiceFailure3'}]}}}
|
||||||
|
|
||||||
# First pass no query paramters filtering, should get all three
|
# First pass no query paramters filtering, should get all three
|
||||||
self.assertEqual(expected, self.controller.list_metrics(dummy_req))
|
self.assertEqual(
|
||||||
|
utils.recursive_sort(expected),
|
||||||
|
utils.recursive_sort(self.controller.list_metrics(dummy_req)))
|
||||||
|
|
||||||
def test_list_metrics_filter_name(self):
|
def test_list_metrics_filter_name(self):
|
||||||
|
|
||||||
|
@ -358,7 +362,9 @@ class WatchControllerTest(common.HeatTestCase):
|
||||||
'Value': 1}],
|
'Value': 1}],
|
||||||
'MetricName': u'ServiceFailure'}]}}}
|
'MetricName': u'ServiceFailure'}]}}}
|
||||||
# First pass no query paramters filtering, should get all three
|
# First pass no query paramters filtering, should get all three
|
||||||
self.assertEqual(expected, self.controller.list_metrics(dummy_req))
|
self.assertEqual(
|
||||||
|
utils.recursive_sort(expected),
|
||||||
|
utils.recursive_sort(self.controller.list_metrics(dummy_req)))
|
||||||
|
|
||||||
def test_list_metrics_filter_namespace(self):
|
def test_list_metrics_filter_namespace(self):
|
||||||
|
|
||||||
|
@ -426,7 +432,9 @@ class WatchControllerTest(common.HeatTestCase):
|
||||||
{'Name': u'Value',
|
{'Name': u'Value',
|
||||||
'Value': 1}],
|
'Value': 1}],
|
||||||
'MetricName': u'ServiceFailure2'}]}}}
|
'MetricName': u'ServiceFailure2'}]}}}
|
||||||
self.assertEqual(expected, self.controller.list_metrics(dummy_req))
|
self.assertEqual(
|
||||||
|
utils.recursive_sort(expected),
|
||||||
|
utils.recursive_sort(self.controller.list_metrics(dummy_req)))
|
||||||
|
|
||||||
def test_put_metric_alarm(self):
|
def test_put_metric_alarm(self):
|
||||||
# Not yet implemented, should raise HeatAPINotImplementedError
|
# Not yet implemented, should raise HeatAPINotImplementedError
|
||||||
|
|
|
@ -38,10 +38,12 @@ class TestViewsCommon(common.HeatTestCase):
|
||||||
self.setUpGetCollectionLinks()
|
self.setUpGetCollectionLinks()
|
||||||
links = views_common.get_collection_links(self.request, self.items)
|
links = views_common.get_collection_links(self.request, self.items)
|
||||||
|
|
||||||
expected = 'http://example.com/fake/path?marker=id2&limit=2'
|
expected_params = {'marker': ['id2'], 'limit': ['2']}
|
||||||
next_link = filter(lambda link: link['rel'] == 'next', links).pop()
|
next_link = filter(lambda link: link['rel'] == 'next', links).pop()
|
||||||
self.assertEqual('next', next_link['rel'])
|
self.assertEqual('next', next_link['rel'])
|
||||||
self.assertEqual(expected, next_link['href'])
|
url_path, url_params = next_link['href'].split('?', 1)
|
||||||
|
self.assertEqual(url_path, self.request.path_url)
|
||||||
|
self.assertEqual(expected_params, urlparse.parse_qs(url_params))
|
||||||
|
|
||||||
def test_get_collection_links_doesnt_create_next_if_no_limit(self):
|
def test_get_collection_links_doesnt_create_next_if_no_limit(self):
|
||||||
self.setUpGetCollectionLinks()
|
self.setUpGetCollectionLinks()
|
||||||
|
@ -62,9 +64,12 @@ class TestViewsCommon(common.HeatTestCase):
|
||||||
self.request.params = {'limit': '2', 'marker': 'some_marker'}
|
self.request.params = {'limit': '2', 'marker': 'some_marker'}
|
||||||
links = views_common.get_collection_links(self.request, self.items)
|
links = views_common.get_collection_links(self.request, self.items)
|
||||||
|
|
||||||
expected = 'http://example.com/fake/path?marker=id2&limit=2'
|
expected_params = {'marker': ['id2'], 'limit': ['2']}
|
||||||
next_link = filter(lambda link: link['rel'] == 'next', links).pop()
|
next_link = filter(lambda link: link['rel'] == 'next', links).pop()
|
||||||
self.assertEqual(expected, next_link['href'])
|
self.assertEqual('next', next_link['rel'])
|
||||||
|
url_path, url_params = next_link['href'].split('?', 1)
|
||||||
|
self.assertEqual(url_path, self.request.path_url)
|
||||||
|
self.assertEqual(expected_params, urlparse.parse_qs(url_params))
|
||||||
|
|
||||||
def test_get_collection_links_does_not_overwrite_other_params(self):
|
def test_get_collection_links_does_not_overwrite_other_params(self):
|
||||||
self.setUpGetCollectionLinks()
|
self.setUpGetCollectionLinks()
|
||||||
|
|
|
@ -88,7 +88,8 @@ class LoadBalancerTest(common.HeatTestCase):
|
||||||
lb_defn = s.t.resource_definitions(s)[resource_name]
|
lb_defn = s.t.resource_definitions(s)[resource_name]
|
||||||
rsrc = lb.LoadBalancer(resource_name, lb_defn, s)
|
rsrc = lb.LoadBalancer(resource_name, lb_defn, s)
|
||||||
|
|
||||||
nova.NovaClientPlugin._create = mock.Mock(return_value=self.fc)
|
self.patchobject(nova.NovaClientPlugin, '_create',
|
||||||
|
return_value=self.fc)
|
||||||
|
|
||||||
initial_md = {'AWS::CloudFormation::Init':
|
initial_md = {'AWS::CloudFormation::Init':
|
||||||
{'config':
|
{'config':
|
||||||
|
|
|
@ -198,7 +198,7 @@ class CeilometerAlarmTest(common.HeatTestCase):
|
||||||
if 'matching_metadata' in al:
|
if 'matching_metadata' in al:
|
||||||
del al['matching_metadata']
|
del al['matching_metadata']
|
||||||
if query:
|
if query:
|
||||||
rule['query'] = query
|
rule['query'] = mox.SameElementsAs(query)
|
||||||
al['threshold_rule'] = rule
|
al['threshold_rule'] = rule
|
||||||
al['type'] = 'threshold'
|
al['type'] = 'threshold'
|
||||||
self.m.StubOutWithMock(self.fa.alarms, 'create')
|
self.m.StubOutWithMock(self.fa.alarms, 'create')
|
||||||
|
@ -396,8 +396,9 @@ class CeilometerAlarmTest(common.HeatTestCase):
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_mem_alarm_high_not_correct_string_parameters(self):
|
def test_mem_alarm_high_not_correct_string_parameters(self):
|
||||||
snippet = template_format.parse(not_string_alarm_template)
|
orig_snippet = template_format.parse(not_string_alarm_template)
|
||||||
for p in ('period', 'evaluation_periods'):
|
for p in ('period', 'evaluation_periods'):
|
||||||
|
snippet = copy.deepcopy(orig_snippet)
|
||||||
snippet['Resources']['MEMAlarmHigh']['Properties'][p] = '60a'
|
snippet['Resources']['MEMAlarmHigh']['Properties'][p] = '60a'
|
||||||
stack = utils.parse_stack(snippet)
|
stack = utils.parse_stack(snippet)
|
||||||
|
|
||||||
|
@ -411,8 +412,9 @@ class CeilometerAlarmTest(common.HeatTestCase):
|
||||||
"Value '60a' is not an integer" % p, six.text_type(error))
|
"Value '60a' is not an integer" % p, six.text_type(error))
|
||||||
|
|
||||||
def test_mem_alarm_high_not_integer_parameters(self):
|
def test_mem_alarm_high_not_integer_parameters(self):
|
||||||
snippet = template_format.parse(not_string_alarm_template)
|
orig_snippet = template_format.parse(not_string_alarm_template)
|
||||||
for p in ('period', 'evaluation_periods'):
|
for p in ('period', 'evaluation_periods'):
|
||||||
|
snippet = copy.deepcopy(orig_snippet)
|
||||||
snippet['Resources']['MEMAlarmHigh']['Properties'][p] = [60]
|
snippet['Resources']['MEMAlarmHigh']['Properties'][p] = [60]
|
||||||
stack = utils.parse_stack(snippet)
|
stack = utils.parse_stack(snippet)
|
||||||
|
|
||||||
|
|
|
@ -374,7 +374,12 @@ class NovaClientPluginMetadataTests(NovaClientPluginTestCase):
|
||||||
self.assertEqual(expected, self.nova_plugin.meta_serialize(original))
|
self.assertEqual(expected, self.nova_plugin.meta_serialize(original))
|
||||||
|
|
||||||
def test_serialize_dict(self):
|
def test_serialize_dict(self):
|
||||||
original = {'test_key': {'a': 'b', 'c': 'd'}}
|
original = collections.OrderedDict([
|
||||||
|
('test_key', collections.OrderedDict([
|
||||||
|
('a', 'b'),
|
||||||
|
('c', 'd'),
|
||||||
|
]))
|
||||||
|
])
|
||||||
expected = {'test_key': '{"a": "b", "c": "d"}'}
|
expected = {'test_key': '{"a": "b", "c": "d"}'}
|
||||||
actual = self.nova_plugin.meta_serialize(original)
|
actual = self.nova_plugin.meta_serialize(original)
|
||||||
self.assertEqual(json.loads(expected['test_key']),
|
self.assertEqual(json.loads(expected['test_key']),
|
||||||
|
|
|
@ -85,6 +85,11 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
|
||||||
return self.engine.create_software_config(
|
return self.engine.create_software_config(
|
||||||
self.ctx, group, name, config, inputs, outputs, options)
|
self.ctx, group, name, config, inputs, outputs, options)
|
||||||
|
|
||||||
|
def assert_status_reason(self, expected, actual):
|
||||||
|
expected_dict = dict((i.split(' : ') for i in expected.split(', ')))
|
||||||
|
actual_dict = dict((i.split(' : ') for i in actual.split(', ')))
|
||||||
|
self.assertEqual(expected_dict, actual_dict)
|
||||||
|
|
||||||
def test_list_software_configs(self):
|
def test_list_software_configs(self):
|
||||||
config = self._create_software_config()
|
config = self._create_software_config()
|
||||||
config_id = config['id']
|
config_id = config['id']
|
||||||
|
@ -362,7 +367,7 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
|
||||||
sd = software_deployment_object.SoftwareDeployment.get_by_id(
|
sd = software_deployment_object.SoftwareDeployment.get_by_id(
|
||||||
self.ctx, deployment_id)
|
self.ctx, deployment_id)
|
||||||
self.assertEqual('FAILED', sd.status)
|
self.assertEqual('FAILED', sd.status)
|
||||||
self.assertEqual(
|
self.assert_status_reason(
|
||||||
('deploy_status_code : Deployment exited with non-zero '
|
('deploy_status_code : Deployment exited with non-zero '
|
||||||
'status code: -1'),
|
'status code: -1'),
|
||||||
sd.status_reason)
|
sd.status_reason)
|
||||||
|
@ -394,7 +399,7 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
|
||||||
sd = software_deployment_object.SoftwareDeployment.get_by_id(
|
sd = software_deployment_object.SoftwareDeployment.get_by_id(
|
||||||
self.ctx, deployment_id)
|
self.ctx, deployment_id)
|
||||||
self.assertEqual('FAILED', sd.status)
|
self.assertEqual('FAILED', sd.status)
|
||||||
self.assertEqual(
|
self.assert_status_reason(
|
||||||
('foo : bar, deploy_status_code : Deployment exited with '
|
('foo : bar, deploy_status_code : Deployment exited with '
|
||||||
'non-zero status code: -1'),
|
'non-zero status code: -1'),
|
||||||
sd.status_reason)
|
sd.status_reason)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import collections
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
@ -31,8 +32,9 @@ class GenericResource(resource.Resource):
|
||||||
Dummy resource for use in tests
|
Dummy resource for use in tests
|
||||||
'''
|
'''
|
||||||
properties_schema = {}
|
properties_schema = {}
|
||||||
attributes_schema = {'foo': attributes.Schema('A generic attribute'),
|
attributes_schema = collections.OrderedDict([
|
||||||
'Foo': attributes.Schema('Another generic attribute')}
|
('foo', attributes.Schema('A generic attribute')),
|
||||||
|
('Foo', attributes.Schema('Another generic attribute'))])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_service_available(cls, context):
|
def is_service_available(cls, context):
|
||||||
|
|
|
@ -214,7 +214,8 @@ class HeatWaitConditionTest(common.HeatTestCase):
|
||||||
'status': 'SUCCESS', 'id': '456'}
|
'status': 'SUCCESS', 'id': '456'}
|
||||||
ret = handle.handle_signal(details=test_metadata)
|
ret = handle.handle_signal(details=test_metadata)
|
||||||
wc_att = rsrc.FnGetAtt('data')
|
wc_att = rsrc.FnGetAtt('data')
|
||||||
self.assertEqual(u'{"123": "foo", "456": "dog"}', wc_att)
|
self.assertEqual(json.loads(u'{"123": "foo", "456": "dog"}'),
|
||||||
|
json.loads(wc_att))
|
||||||
self.assertEqual('status:SUCCESS reason:cat', ret)
|
self.assertEqual('status:SUCCESS reason:cat', ret)
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import collections
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import webob
|
import webob
|
||||||
|
@ -37,13 +38,21 @@ class JSONResponseSerializerTest(common.HeatTestCase):
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_to_json_with_more_deep_format(self):
|
def test_to_json_with_more_deep_format(self):
|
||||||
fixture = {"is_public": True, "name": [{"name1": "test"}]}
|
fixture = collections.OrderedDict([
|
||||||
|
('is_public', True),
|
||||||
|
('name', [collections.OrderedDict([
|
||||||
|
('name1', 'test'),
|
||||||
|
])])
|
||||||
|
])
|
||||||
expected = '{"is_public": true, "name": [{"name1": "test"}]}'
|
expected = '{"is_public": true, "name": [{"name1": "test"}]}'
|
||||||
actual = serializers.JSONResponseSerializer().to_json(fixture)
|
actual = serializers.JSONResponseSerializer().to_json(fixture)
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_to_json_with_objects(self):
|
def test_to_json_with_objects(self):
|
||||||
fixture = {"is_public": True, "value": complex(1, 2)}
|
fixture = collections.OrderedDict([
|
||||||
|
('is_public', True),
|
||||||
|
('value', complex(1, 2)),
|
||||||
|
])
|
||||||
expected = '{"is_public": true, "value": "(1+2j)"}'
|
expected = '{"is_public": true, "value": "(1+2j)"}'
|
||||||
actual = serializers.JSONResponseSerializer().to_json(fixture)
|
actual = serializers.JSONResponseSerializer().to_json(fixture)
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
@ -83,8 +92,14 @@ class XMLResponseSerializerTest(common.HeatTestCase):
|
||||||
def test_to_xml_with_more_deep_format(self):
|
def test_to_xml_with_more_deep_format(self):
|
||||||
# Note we expect tree traversal from one root key, which is compatible
|
# Note we expect tree traversal from one root key, which is compatible
|
||||||
# with the AWS format responses we need to serialize
|
# with the AWS format responses we need to serialize
|
||||||
fixture = {"aresponse":
|
fixture = collections.OrderedDict([
|
||||||
{"is_public": True, "name": [{"name1": "test"}]}}
|
('aresponse', collections.OrderedDict([
|
||||||
|
('is_public', True),
|
||||||
|
('name', [collections.OrderedDict([
|
||||||
|
('name1', 'test'),
|
||||||
|
])])
|
||||||
|
]))
|
||||||
|
])
|
||||||
expected = ('<aresponse><is_public>True</is_public>'
|
expected = ('<aresponse><is_public>True</is_public>'
|
||||||
'<name><member><name1>test</name1></member></name>'
|
'<name><member><name1>test</name1></member></name>'
|
||||||
'</aresponse>')
|
'</aresponse>')
|
||||||
|
@ -94,10 +109,13 @@ class XMLResponseSerializerTest(common.HeatTestCase):
|
||||||
def test_to_xml_with_json_only_keys(self):
|
def test_to_xml_with_json_only_keys(self):
|
||||||
# Certain keys are excluded from serialization because CFN
|
# Certain keys are excluded from serialization because CFN
|
||||||
# format demands a json blob in the XML body
|
# format demands a json blob in the XML body
|
||||||
fixture = {"aresponse":
|
fixture = collections.OrderedDict([
|
||||||
{"is_public": True,
|
('aresponse', collections.OrderedDict([
|
||||||
"TemplateBody": {"name1": "test"},
|
('is_public', True),
|
||||||
"Metadata": {"name2": "test2"}}}
|
('TemplateBody', {"name1": "test"}),
|
||||||
|
('Metadata', {"name2": "test2"}),
|
||||||
|
]))
|
||||||
|
])
|
||||||
expected = ('<aresponse><is_public>True</is_public>'
|
expected = ('<aresponse><is_public>True</is_public>'
|
||||||
'<TemplateBody>{"name1": "test"}</TemplateBody>'
|
'<TemplateBody>{"name1": "test"}</TemplateBody>'
|
||||||
'<Metadata>{"name2": "test2"}</Metadata></aresponse>')
|
'<Metadata>{"name2": "test2"}</Metadata></aresponse>')
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
import mox
|
import mox
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
from heat.common import identifier
|
from heat.common import identifier
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
|
@ -286,12 +287,13 @@ class WaitCondMetadataUpdateTest(common.HeatTestCase):
|
||||||
|
|
||||||
update_metadata('456', 'blarg', 'wibble')
|
update_metadata('456', 'blarg', 'wibble')
|
||||||
|
|
||||||
self.assertEqual('{"123": "foo", "456": "blarg"}',
|
self.assertEqual({'123': 'foo', '456': 'blarg'},
|
||||||
watch.FnGetAtt('Data'))
|
jsonutils.loads(watch.FnGetAtt('Data')))
|
||||||
self.assertEqual('{"123": "foo"}',
|
self.assertEqual('{"123": "foo"}',
|
||||||
inst.metadata_get()['test'])
|
inst.metadata_get()['test'])
|
||||||
self.assertEqual('{"123": "foo", "456": "blarg"}',
|
self.assertEqual(
|
||||||
inst.metadata_get(refresh=True)['test'])
|
{'123': 'foo', '456': 'blarg'},
|
||||||
|
jsonutils.loads(inst.metadata_get(refresh=True)['test']))
|
||||||
|
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,9 @@ class ParameterTestCommon(common.HeatTestCase):
|
||||||
|
|
||||||
def test_param_to_str(self):
|
def test_param_to_str(self):
|
||||||
p = new_parameter('p', {'Type': self.p_type}, self.value)
|
p = new_parameter('p', {'Type': self.p_type}, self.value)
|
||||||
|
if self.p_type == 'Json':
|
||||||
|
self.assertEqual(json.loads(self.expected), json.loads(str(p)))
|
||||||
|
else:
|
||||||
self.assertEqual(self.expected, str(p))
|
self.assertEqual(self.expected, str(p))
|
||||||
|
|
||||||
def test_default_no_override(self):
|
def test_default_no_override(self):
|
||||||
|
@ -137,6 +140,9 @@ class ParameterTestCommon(common.HeatTestCase):
|
||||||
'NoEcho': 'false'},
|
'NoEcho': 'false'},
|
||||||
self.value)
|
self.value)
|
||||||
self.assertFalse(p.hidden())
|
self.assertFalse(p.hidden())
|
||||||
|
if self.p_type == 'Json':
|
||||||
|
self.assertEqual(json.loads(self.expected), json.loads(str(p)))
|
||||||
|
else:
|
||||||
self.assertEqual(self.expected, str(p))
|
self.assertEqual(self.expected, str(p))
|
||||||
|
|
||||||
def test_default_empty(self):
|
def test_default_empty(self):
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import collections
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
@ -140,8 +141,13 @@ class ProviderTemplateTest(common.HeatTestCase):
|
||||||
prop_vals = {
|
prop_vals = {
|
||||||
"Foo": "Bar",
|
"Foo": "Bar",
|
||||||
"AList": ["one", "two", "three"],
|
"AList": ["one", "two", "three"],
|
||||||
"MemList": [{"key": "name", "value": "three"},
|
"MemList": [collections.OrderedDict([
|
||||||
{"key": "name", "value": "four"}],
|
('key', 'name'),
|
||||||
|
('value', 'three'),
|
||||||
|
]), collections.OrderedDict([
|
||||||
|
('key', 'name'),
|
||||||
|
('value', 'four'),
|
||||||
|
])],
|
||||||
"ListEmpty": [],
|
"ListEmpty": [],
|
||||||
"ANum": 5,
|
"ANum": 5,
|
||||||
"AMap": map_prop_val,
|
"AMap": map_prop_val,
|
||||||
|
@ -165,7 +171,8 @@ class ProviderTemplateTest(common.HeatTestCase):
|
||||||
'.member.0.value=three,'
|
'.member.0.value=three,'
|
||||||
'.member.1.key=name,'
|
'.member.1.key=name,'
|
||||||
'.member.1.value=four')
|
'.member.1.value=four')
|
||||||
self.assertEqual(mem_exp, converted_params.get("MemList"))
|
self.assertEqual(sorted(mem_exp.split(',')),
|
||||||
|
sorted(converted_params.get("MemList").split(',')))
|
||||||
# verify Number conversion
|
# verify Number conversion
|
||||||
self.assertEqual(5, converted_params.get("ANum"))
|
self.assertEqual(5, converted_params.get("ANum"))
|
||||||
# verify Map conversion
|
# verify Map conversion
|
||||||
|
|
|
@ -17,6 +17,7 @@ import uuid
|
||||||
from keystoneclient import exceptions as kc_exceptions
|
from keystoneclient import exceptions as kc_exceptions
|
||||||
import mox
|
import mox
|
||||||
import six
|
import six
|
||||||
|
from six.moves.urllib import parse as urlparse
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
|
@ -176,19 +177,25 @@ class SignalTest(common.HeatTestCase):
|
||||||
rsrc.created_time = created_time
|
rsrc.created_time = created_time
|
||||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
|
||||||
expected_url = "".join([
|
# url parameters come in unexpected order, so the conversion has to be
|
||||||
|
# done for comparison
|
||||||
|
expected_url_path = "".join([
|
||||||
'http://server.test:8000/v1/signal/',
|
'http://server.test:8000/v1/signal/',
|
||||||
'arn%3Aopenstack%3Aheat%3A%3Atest_tenant%3Astacks%2F',
|
'arn%3Aopenstack%3Aheat%3A%3Atest_tenant%3Astacks%2F',
|
||||||
'test_stack%2FSTACKABCD1234%2Fresources%2F',
|
'test_stack%2FSTACKABCD1234%2Fresources%2F',
|
||||||
'signal_handler?',
|
'signal_handler'])
|
||||||
'Timestamp=2012-11-29T13%3A49%3A37Z&',
|
expected_url_params = {
|
||||||
'SignatureMethod=HmacSHA256&',
|
'Timestamp': ['2012-11-29T13:49:37Z'],
|
||||||
'AWSAccessKeyId=4567&',
|
'SignatureMethod': ['HmacSHA256'],
|
||||||
'SignatureVersion=2&',
|
'AWSAccessKeyId': ['4567'],
|
||||||
'Signature=',
|
'SignatureVersion': ['2'],
|
||||||
'VW4NyvRO4WhQdsQ4rxl5JMUr0AlefHN6OLsRz9oZyls%3D'])
|
'Signature': ['VW4NyvRO4WhQdsQ4rxl5JMUr0AlefHN6OLsRz9oZyls=']}
|
||||||
|
|
||||||
self.assertEqual(expected_url, rsrc.FnGetAtt('AlarmUrl'))
|
url = rsrc.FnGetAtt('AlarmUrl')
|
||||||
|
url_path, url_params = url.split('?', 1)
|
||||||
|
url_params = urlparse.parse_qs(url_params)
|
||||||
|
self.assertEqual(expected_url_path, url_path)
|
||||||
|
self.assertEqual(expected_url_params, url_params)
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_FnGetAtt_Alarm_Url_is_cached(self):
|
def test_FnGetAtt_Alarm_Url_is_cached(self):
|
||||||
|
|
|
@ -17,6 +17,7 @@ import uuid
|
||||||
import mock
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_messaging import exceptions as msg_exceptions
|
from oslo_messaging import exceptions as msg_exceptions
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
import six
|
import six
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
@ -156,11 +157,24 @@ class StackResourceBaseTest(common.HeatTestCase):
|
||||||
|
|
||||||
|
|
||||||
class StackResourceTest(StackResourceBaseTest):
|
class StackResourceTest(StackResourceBaseTest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(StackResourceTest, self).setUp()
|
super(StackResourceTest, self).setUp()
|
||||||
self.templ = template_format.parse(param_template)
|
self.templ = template_format.parse(param_template)
|
||||||
self.simple_template = template_format.parse(simple_template)
|
self.simple_template = template_format.parse(simple_template)
|
||||||
|
|
||||||
|
# to get same json string from a dict for comparison,
|
||||||
|
# make sort_keys True
|
||||||
|
orig_dumps = jsonutils.dumps
|
||||||
|
|
||||||
|
def sorted_dumps(*args, **kwargs):
|
||||||
|
kwargs.setdefault('sort_keys', True)
|
||||||
|
return orig_dumps(*args, **kwargs)
|
||||||
|
patched_dumps = mock.patch(
|
||||||
|
'oslo_serialization.jsonutils.dumps', sorted_dumps)
|
||||||
|
patched_dumps.start()
|
||||||
|
self.addCleanup(lambda: patched_dumps.stop())
|
||||||
|
|
||||||
def test_child_template_defaults_to_not_implemented(self):
|
def test_child_template_defaults_to_not_implemented(self):
|
||||||
self.assertRaises(NotImplementedError,
|
self.assertRaises(NotImplementedError,
|
||||||
self.parent_resource.child_template)
|
self.parent_resource.child_template)
|
||||||
|
@ -188,8 +202,8 @@ class StackResourceTest(StackResourceBaseTest):
|
||||||
sig1, sig2 = self.parent_resource.implementation_signature()
|
sig1, sig2 = self.parent_resource.implementation_signature()
|
||||||
self.assertEqual('7b0eaabb5b82b9e90804d42e0bb739035588cb797'
|
self.assertEqual('7b0eaabb5b82b9e90804d42e0bb739035588cb797'
|
||||||
'82427770646686ca2235028', sig1)
|
'82427770646686ca2235028', sig1)
|
||||||
self.assertEqual('5a58b34cc3dd7f4e11fa35b63daad7b6b3aaa1744'
|
self.assertEqual('8fa647d036b8f36909386e1e1004539dfae7a8e88'
|
||||||
'19eb1c42b75d102bdda5fc9', sig2)
|
'c24aac0d85399e881421301', sig2)
|
||||||
self.parent_stack.t.files["foo"] = "bar"
|
self.parent_stack.t.files["foo"] = "bar"
|
||||||
sig1a, sig2a = self.parent_resource.implementation_signature()
|
sig1a, sig2a = self.parent_resource.implementation_signature()
|
||||||
self.assertEqual(sig1, sig1a)
|
self.assertEqual(sig1, sig1a)
|
||||||
|
|
|
@ -15,8 +15,10 @@ import random
|
||||||
import string
|
import string
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
import mox
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_db import options
|
from oslo_db import options
|
||||||
|
from oslo_serialization import jsonutils
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from heat.common import context
|
from heat.common import context
|
||||||
|
@ -143,3 +145,32 @@ class PhysName(object):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self._physname
|
return self._physname
|
||||||
|
|
||||||
|
|
||||||
|
def recursive_sort(obj):
|
||||||
|
"""Recursively sort list in iterables for comparison."""
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
for v in obj.values():
|
||||||
|
recursive_sort(v)
|
||||||
|
elif isinstance(obj, list):
|
||||||
|
obj.sort()
|
||||||
|
for i in obj:
|
||||||
|
recursive_sort(i)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
class JsonEquals(mox.Comparator):
|
||||||
|
"""Comparison class used to check if two json strings equal.
|
||||||
|
|
||||||
|
If a dict is dumped to json, the order is undecided, so load the string
|
||||||
|
back to an object for comparison
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, other_json):
|
||||||
|
self.other_json = other_json
|
||||||
|
|
||||||
|
def equals(self, rhs):
|
||||||
|
return jsonutils.loads(self.other_json) == jsonutils.loads(rhs)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<equals to json '%s'>" % self.other_json
|
||||||
|
|
3
tox.ini
3
tox.ini
|
@ -4,10 +4,7 @@ minversion = 1.6
|
||||||
skipsdist = True
|
skipsdist = True
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
# Note the hash seed is set to 0 until heat can be tested with a
|
|
||||||
# random hash seed successfully.
|
|
||||||
setenv = VIRTUAL_ENV={envdir}
|
setenv = VIRTUAL_ENV={envdir}
|
||||||
PYTHONHASHSEED=0
|
|
||||||
usedevelop = True
|
usedevelop = True
|
||||||
install_command = pip install {opts} {packages}
|
install_command = pip install {opts} {packages}
|
||||||
deps = -r{toxinidir}/requirements.txt
|
deps = -r{toxinidir}/requirements.txt
|
||||||
|
|
Loading…
Reference in New Issue