diff --git a/heat/tests/test_signal.py b/heat/tests/test_signal.py index 5c8775665..fd7194be8 100644 --- a/heat/tests/test_signal.py +++ b/heat/tests/test_signal.py @@ -12,17 +12,18 @@ # under the License. import datetime -import uuid from keystoneclient import exceptions as kc_exceptions -import mox +import mock import six from six.moves.urllib import parse as urlparse from heat.common import exception from heat.common import template_format +from heat.engine.clients.os.heat_plugin import HeatClientPlugin +from heat.engine.clients.os.swift import SwiftClientPlugin from heat.engine import scheduler -from heat.engine import stack as parser +from heat.engine import stack as stk from heat.engine import template from heat.objects import resource_data as resource_data_object from heat.tests import common @@ -31,7 +32,7 @@ from heat.tests import generic_resource from heat.tests import utils -test_cfn_template_signal = ''' +TEMPLATE_CFN_SIGNAL = ''' { "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "Just a test.", @@ -44,7 +45,7 @@ test_cfn_template_signal = ''' } ''' -test_heat_template_signal = ''' +TEMPLATE_HEAT_TEMPLATE_SIGNAL = ''' { "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "Just a test.", @@ -57,7 +58,7 @@ test_heat_template_signal = ''' } ''' -test_swift_template_signal = ''' +TEMPLATE_SWIFT_SIGNAL = ''' { "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "Just a test.", @@ -70,7 +71,7 @@ test_swift_template_signal = ''' } ''' -test_zaqar_template_signal = ''' +TEMPLATE_ZAQAR_SIGNAL = ''' { "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "Just a test.", @@ -86,67 +87,54 @@ test_zaqar_template_signal = ''' class SignalTest(common.HeatTestCase): - def setUp(self): - super(SignalTest, self).setUp() - self.stack_id = 'STACKABCD1234' + @staticmethod + def _create_stack(template_string, stack_name=None, + stack_id=None): + stack_name = stack_name or utils.random_name() + stack_id = stack_id or utils.random_name() - def tearDown(self): - super(SignalTest, self).tearDown() - - def create_stack(self, templ=test_cfn_template_signal, - stack_name='test_stack', stub=True): - tpl = template.Template(template_format.parse(templ)) + tpl = template.Template(template_format.parse(template_string)) ctx = utils.dummy_context() ctx.tenant_id = 'test_tenant' - stack = parser.Stack(ctx, stack_name, tpl, - disable_rollback=True) - - # Stub out the stack ID so we have a known value - with utils.UUIDStub(self.stack_id): + stack = stk.Stack(ctx, stack_name, tpl, disable_rollback=True) + with utils.UUIDStub(stack_id): stack.store() - if stub: - self.stub_keystoneclient() - + stack.create() return stack def test_resource_data(self): - self.stub_keystoneclient( - access='anaccesskey', - secret='verysecret', - credential_id='mycredential') - self.stack = self.create_stack(stack_name='resource_data_test', - stub=False) - self.m.ReplayAll() + # Setup + self.stub_keystoneclient(access='anaccesskey', secret='verysecret', + credential_id='mycredential') + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) - self.stack.create() - - rsrc = self.stack['signal_handler'] + rsrc = stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) rsrc._create_keypair() - # Ensure the resource data has been stored correctly + # Test rs_data = resource_data_object.ResourceData.get_all(rsrc) + + # Verify self.assertEqual('mycredential', rs_data.get('credential_id')) self.assertEqual('anaccesskey', rs_data.get('access_key')) self.assertEqual('verysecret', rs_data.get('secret_key')) self.assertEqual('1234', rs_data.get('user_id')) self.assertEqual(rsrc.resource_id, rs_data.get('user_id')) self.assertEqual(4, len(list(six.iterkeys(rs_data)))) - self.m.VerifyAll() def test_get_user_id(self): - self.stack = self.create_stack(stack_name='resource_data_test', - stub=False) + # Setup self.stub_keystoneclient(access='anaccesskey', secret='verysecret') - self.m.ReplayAll() + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) + rsrc = stack['signal_handler'] - self.stack.create() - - rsrc = self.stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) - # Ensure the resource data has been stored correctly + # Test rs_data = resource_data_object.ResourceData.get_all(rsrc) + + # Verify self.assertEqual('1234', rs_data.get('user_id')) self.assertEqual('1234', rsrc.resource_id) self.assertEqual('1234', rsrc._get_user_id()) @@ -158,215 +146,252 @@ class SignalTest(common.HeatTestCase): exception.NotFound, resource_data_object.ResourceData.get_val, rsrc, 'user_id') self.assertEqual('1234', rsrc._get_user_id()) - self.m.VerifyAll() - def test_FnGetAtt_Alarm_Url(self): - self.stack = self.create_stack() - self.m.StubOutWithMock(self.stack.clients.client_plugin('heat'), - 'get_heat_cfn_url') + @mock.patch.object(HeatClientPlugin, 'get_heat_cfn_url') + def test_FnGetAtt_alarm_url(self, mock_get): + # Setup + stack_id = stack_name = 'FnGetAtt-alarm-url' + stack = self._create_stack(TEMPLATE_CFN_SIGNAL, + stack_name=stack_name, + stack_id=stack_id) - self.stack.clients.client_plugin('heat').get_heat_cfn_url().AndReturn( - 'http://server.test:8000/v1') + mock_get.return_value = 'http://server.test:8000/v1' - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['signal_handler'] + rsrc = stack['signal_handler'] created_time = datetime.datetime(2012, 11, 29, 13, 49, 37) rsrc.created_time = created_time + self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test + url = rsrc.FnGetAtt('AlarmUrl') + + # Verify # 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/', 'arn%3Aopenstack%3Aheat%3A%3Atest_tenant%3Astacks%2F', - 'test_stack%2FSTACKABCD1234%2Fresources%2F', + 'FnGetAtt-alarm-url%2FFnGetAtt-alarm-url%2Fresources%2F', 'signal_handler']) expected_url_params = { 'Timestamp': ['2012-11-29T13:49:37Z'], 'SignatureMethod': ['HmacSHA256'], 'AWSAccessKeyId': ['4567'], 'SignatureVersion': ['2'], - 'Signature': ['VW4NyvRO4WhQdsQ4rxl5JMUr0AlefHN6OLsRz9oZyls=']} + 'Signature': ['JWGilkQ4gHS+Y4+zhL41xSAC7+cUCwDsaIxq9xPYPKE=']} - 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() - def test_FnGetAtt_Alarm_Url_is_cached(self): - self.stack = self.create_stack() + mock_get.assert_called_once_with() - self.m.ReplayAll() - self.stack.create() + @mock.patch.object(stk.Stack, 'cache_data_resource_attribute') + @mock.patch.object(stk.Stack, 'has_cache_data') + def test_FnGetAtt_alarm_url_is_cached(self, mock_has, mock_get): + # Setup + mock_has.return_value = False + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) + mock_has.reset_mock() + + # Simulate not caching for the first run, caching afterwards + mock_has.side_effect = [False, True] + mock_get.return_value = 'cached' + rsrc = stack['signal_handler'] - rsrc = self.stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test first_url = rsrc.FnGetAtt('signal') + self.assertTrue('alarm_url' in first_url) + mock_has.assert_called_once_with('signal_handler') + mock_has.reset_mock() # reset the count for the next check + second_url = rsrc.FnGetAtt('signal') - self.assertEqual(first_url, second_url) - self.m.VerifyAll() + mock_has.assert_called_once_with('signal_handler') + self.assertEqual(second_url, 'cached') - def test_FnGetAtt_Heat_Signal(self): - self.stack = self.create_stack(test_heat_template_signal) - self.m.StubOutWithMock(self.stack.clients.client_plugin('heat'), - 'get_heat_url') + @mock.patch.object(HeatClientPlugin, 'get_heat_url') + def test_FnGetAtt_heat_signal(self, mock_get): + # Setup + stack = self._create_stack(TEMPLATE_HEAT_TEMPLATE_SIGNAL) - self.stack.clients.client_plugin('heat').get_heat_url().AndReturn( - 'http://server.test:8004/v1') + mock_get.return_value = 'http://server.test:8004/v1' + rsrc = stack['signal_handler'] - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test signal = rsrc.FnGetAtt('signal') + + # Verify self.assertEqual('http://localhost:5000/v3', signal['auth_url']) self.assertEqual('aprojectid', signal['project_id']) self.assertEqual('1234', signal['user_id']) self.assertIn('username', signal) self.assertIn('password', signal) - self.m.VerifyAll() + mock_get.assert_called_once_with() - def test_FnGetAtt_Heat_Signal_is_cached(self): - self.stack = self.create_stack(test_heat_template_signal) + @mock.patch.object(stk.Stack, 'cache_data_resource_attribute') + @mock.patch.object(stk.Stack, 'has_cache_data') + def test_FnGetAtt_heat_signal_is_cached(self, mock_has, mock_get): + # Setup + mock_has.return_value = False + stack = self._create_stack(TEMPLATE_HEAT_TEMPLATE_SIGNAL) + mock_has.reset_mock() - self.m.ReplayAll() - self.stack.create() + # Simulate not caching for the first run, caching afterwards + mock_has.side_effect = [False, True] + mock_get.return_value = 'cached' + rsrc = stack['signal_handler'] - rsrc = self.stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test first_url = rsrc.FnGetAtt('signal') + self.assertEqual('http://localhost:5000/v3', first_url['auth_url']) + mock_has.assert_called_once_with('signal_handler') + mock_has.reset_mock() # reset the count for the next check + second_url = rsrc.FnGetAtt('signal') - self.assertEqual(first_url, second_url) - self.m.VerifyAll() + mock_has.assert_called_once_with('signal_handler') + self.assertEqual(second_url, 'cached') - def test_FnGetAtt_Zaqar_Signal(self): - self.stack = self.create_stack(test_zaqar_template_signal) + def test_FnGetAtt_zaqar_signal(self): + # Setup + stack = self._create_stack(TEMPLATE_ZAQAR_SIGNAL) + rsrc = stack['signal_handler'] - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test signal = rsrc.FnGetAtt('signal') + + # Verify self.assertEqual('http://localhost:5000/v3', signal['auth_url']) self.assertEqual('aprojectid', signal['project_id']) self.assertEqual('1234', signal['user_id']) self.assertIn('username', signal) self.assertIn('password', signal) self.assertIn('queue_id', signal) - self.m.VerifyAll() - def test_FnGetAtt_Zaqar_Signal_is_cached(self): - self.stack = self.create_stack(test_zaqar_template_signal) + @mock.patch.object(stk.Stack, 'cache_data_resource_attribute') + @mock.patch.object(stk.Stack, 'has_cache_data') + def test_FnGetAtt_zaqar_signal_is_cached(self, mock_has, mock_get): + # Setup + mock_has.return_value = False + stack = self._create_stack(TEMPLATE_ZAQAR_SIGNAL) + mock_has.reset_mock() - self.m.ReplayAll() - self.stack.create() + # Simulate not caching for the first run, caching afterwards + mock_has.side_effect = [False, True] + mock_get.return_value = 'cached' + rsrc = stack['signal_handler'] - rsrc = self.stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test first_url = rsrc.FnGetAtt('signal') + self.assertEqual('http://localhost:5000/v3', first_url['auth_url']) + mock_has.assert_called_once_with('signal_handler') + mock_has.reset_mock() # reset the count for the next check + second_url = rsrc.FnGetAtt('signal') - self.assertEqual(first_url, second_url) - self.m.VerifyAll() + mock_has.assert_called_once_with('signal_handler') + self.assertEqual(second_url, 'cached') - def test_FnGetAtt_Swift_Signal(self): - self.stack = self.create_stack(test_swift_template_signal) - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'put_container') - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'put_object') - self.m.StubOutWithMock(self.stack.clients.client_plugin('swift'), - 'get_temp_url') - - self.stack.clients.client('swift').put_container( - mox.IgnoreArg()).AndReturn(None) - self.stack.clients.client_plugin('swift').get_temp_url( - mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( + @mock.patch('swiftclient.client.Connection.put_container') + @mock.patch('swiftclient.client.Connection.put_object') + @mock.patch.object(SwiftClientPlugin, 'get_temp_url') + def test_FnGetAtt_swift_signal(self, mock_get_url, + mock_put_object, mock_put_container): + # Setup + mock_get_url.return_value = ( 'http://192.0.2.1/v1/AUTH_aprojectid/foo/bar') - self.stack.clients.client('swift').put_object( - mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(None) - - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['signal_handler'] + stack = self._create_stack(TEMPLATE_SWIFT_SIGNAL) + rsrc = stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test + found_url = rsrc.FnGetAtt('AlarmUrl') + + # Verify self.assertEqual('http://192.0.2.1/v1/AUTH_aprojectid/foo/bar', - rsrc.FnGetAtt('AlarmUrl')) - self.m.VerifyAll() + found_url) - def test_FnGetAtt_Swift_Signal_is_cached(self): - self.stack = self.create_stack(test_swift_template_signal) - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'put_container') - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'put_object') - self.m.StubOutWithMock(self.stack.clients.client_plugin('swift'), - 'get_temp_url') + self.assertEqual(1, mock_put_container.call_count) + self.assertEqual(1, mock_put_object.call_count) + self.assertEqual(1, mock_get_url.call_count) - self.stack.clients.client('swift').put_container( - mox.IgnoreArg()).AndReturn(None) - self.stack.clients.client_plugin('swift').get_temp_url( - mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( - 'http://192.0.2.1/v1/AUTH_aprojectid/foo/' + uuid.uuid4().hex) - self.stack.clients.client('swift').put_object( - mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(None) + @mock.patch('swiftclient.client.Connection.put_container') + @mock.patch('swiftclient.client.Connection.put_object') + @mock.patch.object(SwiftClientPlugin, 'get_temp_url') + @mock.patch.object(stk.Stack, 'cache_data_resource_attribute') + @mock.patch.object(stk.Stack, 'has_cache_data') + def test_FnGetAtt_swift_signal_is_cached(self, mock_has, mock_get, + mock_get_url, mock_put_object, + mock_put_container): + # Setup + mock_has.return_value = False + mock_get_url.return_value = ( + 'http://192.0.2.1/v1/AUTH_aprojectid/foo/bar') + stack = self._create_stack(TEMPLATE_SWIFT_SIGNAL) + mock_has.reset_mock() - self.m.ReplayAll() - self.stack.create() + # Simulate not caching for the first run, caching afterwards + mock_has.side_effect = [False, True] + mock_get.return_value = 'cached' - rsrc = self.stack['signal_handler'] + rsrc = stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test first_url = rsrc.FnGetAtt('signal') + self.assertTrue('alarm_url' in first_url) + mock_has.assert_called_once_with('signal_handler') + mock_has.reset_mock() # reset the count for the next check + second_url = rsrc.FnGetAtt('signal') - self.assertEqual(first_url, second_url) - self.m.VerifyAll() + mock_has.assert_called_once_with('signal_handler') + self.assertEqual(second_url, 'cached') - def test_FnGetAtt_delete(self): - self.stack = self.create_stack() - self.m.StubOutWithMock(self.stack.clients.client_plugin('heat'), - 'get_heat_cfn_url') - self.stack.clients.client_plugin('heat').get_heat_cfn_url().AndReturn( - 'http://server.test:8000/v1') - self.stack.clients.client_plugin('heat').get_heat_cfn_url().AndReturn( - 'http://server.test:8000/v1') + # Verify + self.assertEqual(1, mock_put_container.call_count) + self.assertEqual(1, mock_put_object.call_count) + self.assertEqual(1, mock_get_url.call_count) - self.m.ReplayAll() - self.stack.create() + @mock.patch.object(HeatClientPlugin, 'get_heat_cfn_url') + def test_FnGetAtt_delete(self, mock_get): + # Setup + mock_get.return_value = 'http://server.test:8000/v1' + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) - rsrc = self.stack['signal_handler'] + rsrc = stack['signal_handler'] rsrc.resource_id_set('signal') self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) self.assertIn('http://server.test:8000/v1/signal', rsrc.FnGetAtt('AlarmUrl')) + # Test scheduler.TaskRunner(rsrc.delete)() + + # Verify self.assertIn('http://server.test:8000/v1/signal', rsrc.FnGetAtt('AlarmUrl')) - self.m.VerifyAll() + self.assertEqual(2, mock_get.call_count) - def test_FnGetAtt_Heat_Signal_delete(self): - self.stack = self.create_stack(test_heat_template_signal) - self.m.StubOutWithMock(self.stack.clients.client_plugin('heat'), - 'get_heat_url') - self.stack.clients.client_plugin('heat').get_heat_url().AndReturn( - 'http://server.test:8004/v1') - self.stack.clients.client_plugin('heat').get_heat_url().AndReturn( - 'http://server.test:8004/v1') + @mock.patch.object(HeatClientPlugin, 'get_heat_url') + def test_FnGetAtt_heat_signal_delete(self, mock_get): + # Setup + mock_get.return_value = 'http://server.test:8004/v1' + stack = self._create_stack(TEMPLATE_HEAT_TEMPLATE_SIGNAL) + rsrc = stack['signal_handler'] + + self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) def validate_signal(): signal = rsrc.FnGetAtt('signal') @@ -376,88 +401,75 @@ class SignalTest(common.HeatTestCase): self.assertIn('username', signal) self.assertIn('password', signal) - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['signal_handler'] - self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test validate_signal() scheduler.TaskRunner(rsrc.delete)() validate_signal() - self.m.VerifyAll() - def test_FnGetAtt_Swift_Signal_delete(self): - self.stack = self.create_stack(test_swift_template_signal) - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'put_container') - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'put_object') - self.m.StubOutWithMock(self.stack.clients.client_plugin('swift'), - 'get_temp_url') - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'delete_object') - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'delete_container') - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'head_container') - self.m.StubOutWithMock(self.stack.clients.client('swift'), - 'get_container') - self.m.StubOutWithMock(self.stack['signal_handler'], - 'physical_resource_name') + self.assertEqual(2, mock_get.call_count) - self.stack['signal_handler'].physical_resource_name().AndReturn('bar') - self.stack.clients.client('swift').put_container( - mox.IgnoreArg()).AndReturn(None) - self.stack.clients.client_plugin('swift').get_temp_url( - mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( + @mock.patch('swiftclient.client.Connection.delete_container') + @mock.patch('swiftclient.client.Connection.delete_object') + @mock.patch('swiftclient.client.Connection.get_container') + @mock.patch.object(SwiftClientPlugin, 'get_temp_url') + @mock.patch('swiftclient.client.Connection.head_container') + @mock.patch('swiftclient.client.Connection.put_container') + @mock.patch('swiftclient.client.Connection.put_object') + def test_FnGetAtt_swift_signal_delete(self, mock_put_object, + mock_put_container, mock_head, + mock_get_temp, mock_get_container, + mock_delete_object, + mock_delete_container): + # Setup + stack = self._create_stack(TEMPLATE_SWIFT_SIGNAL) + + mock_get_temp.return_value = ( 'http://server.test/v1/AUTH_aprojectid/foo/bar') - self.stack['signal_handler'].physical_resource_name().AndReturn('bar') - self.stack.clients.client('swift').put_object( - mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(None) + mock_get_container.return_value = ({}, [{'name': 'bar'}]) + mock_head.return_value = {'x-container-object-count': 0} - self.stack.clients.client('swift').put_container( - mox.IgnoreArg()).AndReturn(None) - self.stack['signal_handler'].physical_resource_name().AndReturn('bar') - self.stack.clients.client_plugin('swift').get_temp_url( - mox.IgnoreArg(), mox.IgnoreArg()).AndReturn( - 'http://server.test/v1/AUTH_aprojectid/foo/bar') - self.stack.clients.client('swift').put_object( - mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(None) - self.stack.clients.client('swift').get_container( - mox.IgnoreArg()).AndReturn(({}, [{'name': 'bar'}])) - self.stack.clients.client('swift').delete_object( - mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(None) - self.stack.clients.client('swift').head_container( - mox.IgnoreArg()).AndReturn({'x-container-object-count': 0}) - self.stack.clients.client('swift').delete_container( - mox.IgnoreArg()).AndReturn(None) + rsrc = stack['signal_handler'] + mock_name = mock.MagicMock() + mock_name.return_value = 'bar' + rsrc.physical_resource_name = mock_name - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) self.assertEqual('http://server.test/v1/AUTH_aprojectid/foo/bar', rsrc.FnGetAtt('AlarmUrl')) + # Test scheduler.TaskRunner(rsrc.delete)() + + # Verify self.assertEqual('http://server.test/v1/AUTH_aprojectid/foo/bar', rsrc.FnGetAtt('AlarmUrl')) - self.m.VerifyAll() + self.assertEqual(2, mock_put_container.call_count) + self.assertEqual(2, mock_get_temp.call_count) + self.assertEqual(2, mock_put_object.call_count) + self.assertEqual(2, mock_put_container.call_count) + self.assertEqual(1, mock_get_container.call_count) + self.assertEqual(1, mock_delete_object.call_count) + self.assertEqual(1, mock_delete_container.call_count) + self.assertEqual(1, mock_head.call_count) - def test_FnGetAtt_Zaqar_Signal_delete(self): - self.stack = self.create_stack(test_zaqar_template_signal) - rsrc = self.stack['signal_handler'] - self.m.StubOutWithMock(rsrc, '_delete_zaqar_signal_queue') - rsrc._delete_zaqar_signal_queue().AndReturn(None) + def test_FnGetAtt_zaqar_signal_delete(self): + # Setup + stack = self._create_stack(TEMPLATE_ZAQAR_SIGNAL) - self.m.ReplayAll() - self.stack.create() + mock_delete = mock.MagicMock() - self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + rsrc = stack['signal_handler'] + rsrc._delete_zaqar_signal_queue = mock_delete + + stack.create() + + # Test signal = rsrc.FnGetAtt('signal') + + # Verify + self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) self.assertEqual('http://localhost:5000/v3', signal['auth_url']) self.assertEqual('aprojectid', signal['project_id']) self.assertEqual('1234', signal['user_id']) @@ -473,83 +485,69 @@ class SignalTest(common.HeatTestCase): self.assertIn('username', signal) self.assertIn('password', signal) self.assertIn('queue_id', signal) - self.m.VerifyAll() + + mock_delete.assert_called_once_with() def test_delete_not_found(self): - self.stack = self.create_stack(stack_name='test_delete_not_found', - stub=False) - + # Setup class FakeKeystoneClientFail(fakes.FakeKeystoneClient): def delete_stack_user(self, name): raise kc_exceptions.NotFound() self.stub_keystoneclient(fake_client=FakeKeystoneClientFail()) - self.m.ReplayAll() + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) + rsrc = stack['signal_handler'] - self.stack.create() - - rsrc = self.stack['signal_handler'] + # Test self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) - scheduler.TaskRunner(rsrc.delete)() self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state) - self.m.VerifyAll() - - def test_signal(self): + @mock.patch.object(generic_resource.SignalResource, 'handle_signal') + def test_signal(self, mock_handle): + # Setup test_d = {'Data': 'foo', 'Reason': 'bar', 'Status': 'SUCCESS', 'UniqueId': '123'} - self.stack = self.create_stack() + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) + rsrc = stack['signal_handler'] - # to confirm we get a call to handle_signal - self.m.StubOutWithMock(generic_resource.SignalResource, - 'handle_signal') - generic_resource.SignalResource.handle_signal(test_d).AndReturn(None) - - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) self.assertTrue(rsrc.requires_deferred_auth) + # Test rsrc.signal(details=test_d) + mock_handle.assert_called_once_with(test_d) - self.m.VerifyAll() - - def test_signal_no_action(self): + @mock.patch.object(generic_resource.SignalResource, '_add_event') + @mock.patch.object(generic_resource.SignalResource, 'handle_signal') + def test_signal_no_action(self, mock_handle, mock_add): + # Setup test_d = {'Data': 'foo', 'Reason': 'bar', 'Status': 'SUCCESS', 'UniqueId': '123'} - self.stack = self.create_stack() - self.stack.create() + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) - # mock a NoActionRequired from handle_signal() - self.m.StubOutWithMock(generic_resource.SignalResource, - 'handle_signal') - generic_resource.SignalResource.handle_signal(test_d).AndRaise( - exception.NoActionRequired()) + mock_handle.side_effect = exception.NoActionRequired() + rsrc = stack['signal_handler'] - # _add_event should not be called. - self.m.StubOutWithMock(generic_resource.SignalResource, - '_add_event') - - self.m.ReplayAll() - - rsrc = self.stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) self.assertTrue(rsrc.requires_deferred_auth) + # Test + mock_add.reset_mock() # clean up existing calls before test rsrc.signal(details=test_d) + mock_handle.assert_called_once_with(test_d) + mock_add.assert_not_called() - self.m.VerifyAll() + @mock.patch.object(generic_resource.SignalResource, '_add_event') + def test_signal_different_reason_types(self, mock_add): + # Setup + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) - def test_signal_different_reason_types(self): - self.stack = self.create_stack() - self.stack.create() + rsrc = stack['signal_handler'] - rsrc = self.stack['signal_handler'] + # Verify self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) self.assertTrue(rsrc.requires_deferred_auth) @@ -566,116 +564,97 @@ class SignalTest(common.HeatTestCase): none_details = None none_expected = 'No signal details provided' - # to confirm we get a string reason - self.m.StubOutWithMock(generic_resource.SignalResource, - '_add_event') - generic_resource.SignalResource._add_event( - 'SIGNAL', 'COMPLETE', ceilo_expected).AndReturn(None) - generic_resource.SignalResource._add_event( - 'SIGNAL', 'COMPLETE', watch_expected).AndReturn(None) - generic_resource.SignalResource._add_event( - 'SIGNAL', 'COMPLETE', str_expected).AndReturn(None) - generic_resource.SignalResource._add_event( - 'SIGNAL', 'COMPLETE', none_expected).AndReturn(None) - - self.m.ReplayAll() - + # Test for test_d in (ceilo_details, watch_details, str_details, none_details): rsrc.signal(details=test_d) - self.m.VerifyAll() + # Verify + mock_add.assert_any_call('SIGNAL', 'COMPLETE', ceilo_expected) + mock_add.assert_any_call('SIGNAL', 'COMPLETE', watch_expected) + mock_add.assert_any_call('SIGNAL', 'COMPLETE', str_expected) + mock_add.assert_any_call('SIGNAL', 'COMPLETE', none_expected) - def test_signal_plugin_reason(self): - # Ensure if handle_signal returns data, we use it as the reason - self.stack = self.create_stack() - self.stack.create() + @mock.patch.object(generic_resource.SignalResource, 'handle_signal') + @mock.patch.object(generic_resource.SignalResource, '_add_event') + def test_signal_plugin_reason(self, mock_add, mock_handle): + # Setup + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) - rsrc = self.stack['signal_handler'] + rsrc = stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) - self.m.StubOutWithMock(generic_resource.SignalResource, - 'handle_signal') signal_details = {'status': 'COMPLETE'} - ret_expected = "Received COMPLETE signal" - generic_resource.SignalResource.handle_signal( - signal_details).AndReturn(ret_expected) - - self.m.StubOutWithMock(generic_resource.SignalResource, - '_add_event') - generic_resource.SignalResource._add_event( - 'SIGNAL', 'COMPLETE', 'Signal: %s' % ret_expected).AndReturn(None) - self.m.ReplayAll() + ret_expected = 'Received COMPLETE signal' + mock_handle.return_value = ret_expected + # Test rsrc.signal(details=signal_details) - self.m.VerifyAll() + + # Verify + mock_handle.assert_called_once_with(signal_details) + + # Ensure if handle_signal returns data, we use it as the reason + mock_add.assert_any_call('SIGNAL', 'COMPLETE', + 'Signal: %s' % ret_expected) def test_signal_wrong_resource(self): - # assert that we get the correct exception when calling a - # resource.signal() that does not have a handle_signal() - self.stack = self.create_stack() + # Setup + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['resource_X'] + rsrc = stack['resource_X'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + # Test + # assert that we get the correct exception when calling a + # resource.signal() that does not have a handle_signal() err_metadata = {'Data': 'foo', 'Status': 'SUCCESS', 'UniqueId': '123'} self.assertRaises(exception.ResourceActionNotSupported, rsrc.signal, details=err_metadata) - self.m.VerifyAll() + @mock.patch.object(generic_resource.SignalResource, 'handle_signal') + def test_signal_reception_failed_call(self, mock_handle): + # Setup + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) - def _test_signal_not_supported_action(self, action='DELETE'): - self.stack = self.create_stack() + test_d = {'Data': 'foo', 'Reason': 'bar', + 'Status': 'SUCCESS', 'UniqueId': '123'} - self.m.ReplayAll() - self.stack.create() + mock_handle.side_effect = ValueError() - rsrc = self.stack['signal_handler'] + rsrc = stack['signal_handler'] + self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + + # Test + # assert that we get the correct exception from resource.signal() + # when resource.handle_signal() raises an exception. + self.assertRaises(exception.ResourceFailure, + rsrc.signal, details=test_d) + + # Verify + mock_handle.assert_called_once_with(test_d) + + def _run_test_signal_not_supported_action(self, action): + # Setup + stack = self._create_stack(TEMPLATE_CFN_SIGNAL) + + rsrc = stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) - # manually override the action to DELETE rsrc.action = action + # Test err_metadata = {'Data': 'foo', 'Status': 'SUCCESS', 'UniqueId': '123'} msg = 'Signal resource during %s is not supported.' % action exc = self.assertRaises(exception.NotSupported, rsrc.signal, details=err_metadata) self.assertEqual(msg, six.text_type(exc)) - self.m.VerifyAll() def test_signal_in_delete_state(self): # assert that we get the correct exception when calling a # resource.signal() that is in delete action. - self._test_signal_not_supported_action() + self._run_test_signal_not_supported_action('DELETE') def test_signal_in_suspend_state(self): # assert that we get the correct exception when calling a # resource.signal() that is in suspend action. - self._test_signal_not_supported_action(action='SUSPEND') - - def test_signal_reception_failed_call(self): - # assert that we get the correct exception from resource.signal() - # when resource.handle_signal() raises an exception. - self.stack = self.create_stack() - - test_d = {'Data': 'foo', 'Reason': 'bar', - 'Status': 'SUCCESS', 'UniqueId': '123'} - - # to confirm we get a call to handle_signal - self.m.StubOutWithMock(generic_resource.SignalResource, - 'handle_signal') - generic_resource.SignalResource.handle_signal(test_d).AndRaise( - ValueError) - - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['signal_handler'] - self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) - - self.assertRaises(exception.ResourceFailure, - rsrc.signal, details=test_d) - - self.m.VerifyAll() + self._run_test_signal_not_supported_action('SUSPEND')