From 5f3f379422053829a406c80b291fcbe37c970075 Mon Sep 17 00:00:00 2001 From: Pavlo Shchelokovskyy Date: Fri, 23 Jan 2015 19:03:23 +0200 Subject: [PATCH] Enable some unit tests back Since split between AWS and OS WaitConidtion/Volume resources unit tests for those resources were not running as they were not discovered. During this time some changes were merged that actually broke some tests (mostly the mocking) so this patch fixes those broken tests too. Some AWS WaitConidtion tests were testing the handle_update method, which has no sense now as it no longer returns a TaskRunner instance. These tests were modified to use the general resource.update method. One test in AWS volumes is modified to use mocked ServerConstraint, which is added to base TestCase as are stubs for other constraints. Another test in AWS volumes was using a dumb monkey-patching instead of proper mock, leading to clashes during concurrent test runs. Change-Id: Ie765eab75de835d5dec94024f1d90197f1723b4d Closes-Bug: #1414083 --- heat/tests/aws/__init__.py | 0 heat/tests/aws/test_volume.py | 6 +- heat/tests/aws/test_waitcondition.py | 117 +++++++-------------- heat/tests/common.py | 5 + heat/tests/openstack/__init__.py | 0 heat/tests/openstack/test_waitcondition.py | 21 ++-- 6 files changed, 57 insertions(+), 92 deletions(-) create mode 100644 heat/tests/aws/__init__.py create mode 100644 heat/tests/openstack/__init__.py diff --git a/heat/tests/aws/__init__.py b/heat/tests/aws/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/heat/tests/aws/test_volume.py b/heat/tests/aws/test_volume.py index fda556c518..6bb7c7d162 100644 --- a/heat/tests/aws/test_volume.py +++ b/heat/tests/aws/test_volume.py @@ -136,6 +136,7 @@ class VolumeTest(vt_base.BaseVolumeTest): cinder.CinderClientPlugin._create().AndReturn( self.cinder_fc) self.stub_ImageConstraint_validate() + self.stub_ServerConstraint_validate() self.stub_VolumeConstraint_validate() vol_name = utils.PhysName(stack_name, 'DataVolume') self.cinder_fc.volumes.create( @@ -641,8 +642,9 @@ class VolumeTest(vt_base.BaseVolumeTest): "range (min: 1, max: None)", six.text_type(error)) def test_volume_attachment_updates_not_supported(self): - nova.NovaClientPlugin.get_server = mock.Mock( - return_value=mock.MagicMock()) + self.m.StubOutWithMock(nova.NovaClientPlugin, 'get_server') + nova.NovaClientPlugin.get_server(mox.IgnoreArg()).AndReturn( + mox.MockAnything()) fv = vt_base.FakeVolume('creating', 'available') fva = vt_base.FakeVolume('attaching', 'in-use') stack_name = 'test_volume_attach_updnotsup_stack' diff --git a/heat/tests/aws/test_waitcondition.py b/heat/tests/aws/test_waitcondition.py index 7b2d25f63d..666ca1e2eb 100644 --- a/heat/tests/aws/test_waitcondition.py +++ b/heat/tests/aws/test_waitcondition.py @@ -14,20 +14,19 @@ import copy import datetime import json -import time import uuid -import mox from oslo.config import cfg +from oslo_utils import timeutils import six +from heat.common import exception from heat.common import identifier from heat.common import template_format from heat.db import api as db_api from heat.engine import environment from heat.engine import parser from heat.engine.resources.aws import wait_condition_handle as aws_wch -from heat.engine.resources import wait_condition as wc from heat.engine import rsrc_defn from heat.engine import scheduler from heat.tests import common @@ -199,23 +198,20 @@ class WaitConditionTest(common.HeatTestCase): self.m.VerifyAll() def test_timeout(self): - st = time.time() - self.stack = self.create_stack() # Avoid the stack create exercising the timeout code at the same time self.m.StubOutWithMock(self.stack, 'timeout_secs') self.stack.timeout_secs().MultipleTimes().AndReturn(None) - self.m.StubOutWithMock(scheduler, 'wallclock') + now = timeutils.utcnow() + fake_clock = [now + datetime.timedelta(0, t) + for t in (0, 0.001, 0.1, 4.1, 5.1)] + timeutils.set_time_override(fake_clock) + self.addCleanup(timeutils.clear_time_override) - scheduler.wallclock().AndReturn(st) - scheduler.wallclock().AndReturn(st + 0.001) - scheduler.wallclock().AndReturn(st + 0.1) - aws_wch.WaitConditionHandle.get_status().AndReturn([]) - scheduler.wallclock().AndReturn(st + 4.1) - aws_wch.WaitConditionHandle.get_status().AndReturn([]) - scheduler.wallclock().AndReturn(st + 5.1) + aws_wch.WaitConditionHandle.get_status( + ).MultipleTimes().AndReturn([]) self.m.ReplayAll() @@ -529,11 +525,6 @@ class WaitConditionUpdateTest(common.HeatTestCase): cfg.CONF.set_default('heat_waitcondition_server_url', 'http://server.test:8000/v1/waitcondition') self.stub_keystoneclient() - scheduler.ENABLE_SLEEP = False - - def tearDown(self): - super(WaitConditionUpdateTest, self).tearDown() - scheduler.ENABLE_SLEEP = True def create_stack(self, tmpl=None): if tmpl is None: @@ -594,34 +585,7 @@ class WaitConditionUpdateTest(common.HeatTestCase): self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state) - def test_handle_update(self): - self.stack = self.create_stack() - self.m.ReplayAll() - self.stack.create() - - rsrc = self.stack['WaitForTheHandle'] - self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) - - self.m.VerifyAll() - self.m.UnsetStubs() - - wait_condition_handle = self.stack['WaitHandle'] - test_metadata = {'Data': 'foo', 'Reason': 'bar', - 'Status': 'SUCCESS', 'UniqueId': '1'} - self._handle_signal(wait_condition_handle, test_metadata, 5) - - prop_diff = {"Count": 5} - props = copy.copy(rsrc.properties.data) - props.update(prop_diff) - update_defn = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(), - props) - updater = rsrc.handle_update(update_defn, {}, prop_diff) - updater.run_to_completion() - - self.assertEqual(5, rsrc.properties['Count']) - self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) - - def test_handle_update_restored_from_db(self): + def test_update_restored_from_db(self): self.stack = self.create_stack() self.m.ReplayAll() self.stack.create() @@ -642,16 +606,17 @@ class WaitConditionUpdateTest(common.HeatTestCase): rsrc = self.stack['WaitForTheHandle'] self._handle_signal(wait_condition_handle, test_metadata, 3) - prop_diff = {"Count": 5} - props = copy.copy(rsrc.properties.data) - props.update(prop_diff) - update_defn = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(), - props) - updater = rsrc.handle_update(update_defn, {}, prop_diff) - updater.run_to_completion() - self.assertEqual(5, rsrc.properties['Count']) - self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + uprops = copy.copy(rsrc.properties.data) + uprops['Count'] = '5' + update_snippet = rsrc_defn.ResourceDefinition(rsrc.name, + rsrc.type(), + uprops) + + updater = scheduler.TaskRunner(rsrc.update, update_snippet) + updater() + + self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state) def _handle_signal(self, rsrc, metadata, times=1): for t in range(times): @@ -661,7 +626,7 @@ class WaitConditionUpdateTest(common.HeatTestCase): (metadata[rsrc.STATUS], metadata[rsrc.REASON]), ret) - def test_handle_update_timeout(self): + def test_update_timeout(self): self.stack = self.create_stack() self.m.ReplayAll() self.stack.create() @@ -672,31 +637,27 @@ class WaitConditionUpdateTest(common.HeatTestCase): self.m.VerifyAll() self.m.UnsetStubs() - st = time.time() + now = timeutils.utcnow() + fake_clock = [now + datetime.timedelta(0, t) + for t in (0, 0.001, 0.1, 4.1, 5.1)] + timeutils.set_time_override(fake_clock) + self.addCleanup(timeutils.clear_time_override) - self.m.StubOutWithMock(scheduler.TaskRunner, '_sleep') - scheduler.TaskRunner._sleep(mox.IgnoreArg()).MultipleTimes().AndReturn( - None) - - self.m.StubOutWithMock(scheduler, 'wallclock') - - scheduler.wallclock().AndReturn(st) - scheduler.wallclock().AndReturn(st + 0.001) - scheduler.wallclock().AndReturn(st + 0.1) - scheduler.wallclock().AndReturn(st + 4.1) - scheduler.wallclock().AndReturn(st + 5.1) + self.m.StubOutWithMock(aws_wch.WaitConditionHandle, 'get_status') + aws_wch.WaitConditionHandle.get_status().MultipleTimes().AndReturn([]) self.m.ReplayAll() - prop_diff = {"Count": 5} - props = copy.copy(rsrc.properties.data) - props.update(prop_diff) - update_defn = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(), - props) - updater = rsrc.handle_update(update_defn, {}, prop_diff) + uprops = copy.copy(rsrc.properties.data) + uprops['Count'] = '5' + update_snippet = rsrc_defn.ResourceDefinition(rsrc.name, + rsrc.type(), + uprops) + + updater = scheduler.TaskRunner(rsrc.update, update_snippet) + ex = self.assertRaises(exception.ResourceFailure, + updater) + self.assertEqual("WaitConditionTimeout: 0 of 5 received", + six.text_type(ex)) self.assertEqual(5, rsrc.properties['Count']) - ex = self.assertRaises(wc.WaitConditionTimeout, - updater.run_to_completion) - self.assertEqual("0 of 5 received", six.text_type(ex)) self.m.VerifyAll() - self.m.UnsetStubs() diff --git a/heat/tests/common.py b/heat/tests/common.py index 0e513a8413..cbc9719cbc 100644 --- a/heat/tests/common.py +++ b/heat/tests/common.py @@ -186,3 +186,8 @@ class HeatTestCase(testscenarios.WithScenarios, self.m.StubOutWithMock(cinder.VolumeTypeConstraint, 'validate') cinder.VolumeTypeConstraint.validate( mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True) + + def stub_ServerConstraint_validate(self): + self.m.StubOutWithMock(nova.ServerConstraint, 'validate') + nova.ServerConstraint.validate( + mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True) diff --git a/heat/tests/openstack/__init__.py b/heat/tests/openstack/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/heat/tests/openstack/test_waitcondition.py b/heat/tests/openstack/test_waitcondition.py index 70cbf931a8..f1df74f905 100644 --- a/heat/tests/openstack/test_waitcondition.py +++ b/heat/tests/openstack/test_waitcondition.py @@ -11,9 +11,10 @@ # License for the specific language governing permissions and limitations # under the License. -import time +import datetime import uuid +from oslo_utils import timeutils import six from heat.common import identifier @@ -24,7 +25,6 @@ from heat.engine import environment from heat.engine import parser from heat.engine import resource from heat.engine.resources.openstack import wait_condition_handle as heat_wch -from heat.engine import scheduler from heat.tests import common from heat.tests import utils @@ -155,23 +155,20 @@ class HeatWaitConditionTest(common.HeatTestCase): self.m.VerifyAll() def test_timeout(self): - st = time.time() - self.stack = self.create_stack() # Avoid the stack create exercising the timeout code at the same time self.m.StubOutWithMock(self.stack, 'timeout_secs') self.stack.timeout_secs().MultipleTimes().AndReturn(None) - self.m.StubOutWithMock(scheduler, 'wallclock') + now = timeutils.utcnow() + fake_clock = [now + datetime.timedelta(0, t) + for t in (0, 0.001, 0.1, 4.1, 5.1)] + timeutils.set_time_override(fake_clock) + self.addCleanup(timeutils.clear_time_override) - scheduler.wallclock().AndReturn(st) - scheduler.wallclock().AndReturn(st + 0.001) - scheduler.wallclock().AndReturn(st + 0.1) - heat_wch.HeatWaitConditionHandle.get_status().AndReturn([]) - scheduler.wallclock().AndReturn(st + 4.1) - heat_wch.HeatWaitConditionHandle.get_status().AndReturn([]) - scheduler.wallclock().AndReturn(st + 5.1) + heat_wch.HeatWaitConditionHandle.get_status( + ).MultipleTimes().AndReturn([]) self.m.ReplayAll()