]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Fix test_waitcondition.py race by converting to mox.
authorSteve Baker <sbaker@redhat.com>
Mon, 24 Sep 2012 23:46:08 +0000 (11:46 +1200)
committerSteve Baker <sbaker@redhat.com>
Mon, 24 Sep 2012 23:46:08 +0000 (11:46 +1200)
Eventlet calls and metadata state changes are now
mocked, so there are no sleeps, and in theory no
chance of races.

Change-Id: I05fee73a8cefafe1f2bb5a4ca65c585933497475

heat/engine/wait_condition.py
heat/tests/test_waitcondition.py

index 73512130d63eeae27e83e792b520e53b15d970ae..179a467f84201f2b78e6f76474ed95c5f9238e0f 100644 (file)
@@ -14,7 +14,6 @@
 #    under the License.
 
 import eventlet
-import json
 
 from heat.common import exception
 from heat.engine import resources
@@ -80,23 +79,26 @@ class WaitCondition(resources.Resource):
             self.resource_id = handle_url.split('/')[-1]
         return self.resource_id
 
+    def _get_status_reason(self, handle):
+        return (handle.metadata.get('Status', WAITING),
+                handle.metadata.get('Reason', 'Reason not provided'))
+
+    def _create_timeout(self):
+        return eventlet.Timeout(self.timeout)
+
     def handle_create(self):
         tmo = None
         try:
             # keep polling our Metadata to see if the cfn-signal has written
             # it yet. The execution here is limited by timeout.
-            with eventlet.Timeout(self.timeout) as tmo:
+            with self._create_timeout() as tmo:
                 handle = self.stack[self._get_handle_resource_id()]
 
-                status = WAITING
-                reason = ''
+                (status, reason) = (WAITING, '')
                 sleep_time = 1
 
                 while status == WAITING:
-                    meta = handle.metadata
-                    status = meta.get('Status', WAITING)
-                    reason = meta.get('Reason', 'Reason not provided')
-                    logger.debug('got %s' % json.dumps(meta))
+                    (status, reason) = self._get_status_reason(handle)
                     if status == WAITING:
                         logger.debug('Waiting for the Metadata[Status]')
                         eventlet.sleep(sleep_time)
@@ -107,8 +109,7 @@ class WaitCondition(resources.Resource):
                 # not my timeout
                 raise
             else:
-                status = TIMEDOUT
-                reason = 'Timed out waiting for instance'
+                (status, reason) = (TIMEDOUT, 'Timed out waiting for instance')
 
         if status != SUCCESS:
             raise exception.Error(reason)
index 15f2421a7cc2b1e4c5d37cd22b30d5d0f127c8a5..5307f214ed44c241843edb62018f45b6529d8632 100644 (file)
 #    under the License.
 
 
-from datetime import datetime
-import eventlet
 import json
 import logging
-import os
+import mox
 import sys
 
+import eventlet
 import nose
 import unittest
 from nose.plugins.attrib import attr
-from nose import with_setup
 
 import heat.db as db_api
 from heat.engine import parser
+from heat.engine import wait_condition as wc
 from heat.common import context
 
 logger = logging.getLogger('test_waitcondition')
@@ -56,7 +55,15 @@ test_template_waitcondition = '''
 @attr(speed='slow')
 class stacksTest(unittest.TestCase):
     def setUp(self):
-        self.greenpool = eventlet.GreenPool()
+        self.m = mox.Mox()
+        self.m.StubOutWithMock(wc.WaitCondition,
+                               '_get_status_reason')
+        self.m.StubOutWithMock(wc.WaitCondition,
+                               '_create_timeout')
+        self.m.StubOutWithMock(eventlet, 'sleep')
+
+    def tearDown(self):
+        self.m.UnsetStubs()
 
     def create_stack(self, stack_name, temp, params):
         template = parser.Template(temp)
@@ -68,33 +75,62 @@ class stacksTest(unittest.TestCase):
         return stack
 
     def test_post_success_to_handle(self):
-        params = {}
+
         t = json.loads(test_template_waitcondition)
-        stack = self.create_stack('test_stack', t, params)
+        stack = self.create_stack('test_stack', t, {})
 
-        self.greenpool.spawn_n(stack.create)
-        eventlet.sleep(1)
-        self.assertEqual(stack.resources['WaitForTheHandle'].state,
-                         'IN_PROGRESS')
+        wc.WaitCondition._create_timeout().AndReturn(eventlet.Timeout(5))
+        wc.WaitCondition._get_status_reason(
+                         mox.IgnoreArg()).AndReturn(('WAITING', ''))
+        eventlet.sleep(1).AndReturn(None)
+        wc.WaitCondition._get_status_reason(
+                         mox.IgnoreArg()).AndReturn(('WAITING', ''))
+        eventlet.sleep(1).AndReturn(None)
+        wc.WaitCondition._get_status_reason(
+                         mox.IgnoreArg()).AndReturn(('SUCCESS', 'woot toot'))
+
+        self.m.ReplayAll()
+
+        stack.create()
+
+        resource = stack.resources['WaitForTheHandle']
+        self.assertEqual(resource.state,
+                         'CREATE_COMPLETE')
 
         r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
                                                   stack.id)
         self.assertEqual(r.name, 'WaitHandle')
 
-        metadata = {"Status": "SUCCESS",
-                    "Reason": "woot toot",
-                    "Data": "Application has completed configuration.",
-                    "UniqueId": "00000"}
+        self.m.VerifyAll()
 
-        r.update_and_save({'rsrc_metadata': metadata})
+    def test_timeout(self):
 
-        eventlet.sleep(2)
+        t = json.loads(test_template_waitcondition)
+        stack = self.create_stack('test_stack', t, {})
 
-        logger.debug('state %s' % stack.resources['WaitForTheHandle'].state)
-        self.assertEqual(stack.resources['WaitForTheHandle'].state,
-                         'CREATE_COMPLETE')
+        tmo = eventlet.Timeout(6)
+        wc.WaitCondition._create_timeout().AndReturn(tmo)
+        wc.WaitCondition._get_status_reason(
+                         mox.IgnoreArg()).AndReturn(('WAITING', ''))
+        eventlet.sleep(1).AndReturn(None)
+        wc.WaitCondition._get_status_reason(
+                         mox.IgnoreArg()).AndReturn(('WAITING', ''))
+        eventlet.sleep(1).AndRaise(tmo)
+
+        self.m.ReplayAll()
+
+        stack.create()
+
+        resource = stack.resources['WaitForTheHandle']
+
+        self.assertEqual(resource.state,
+                         'CREATE_FAILED')
+        self.assertEqual(wc.WaitCondition.UPDATE_REPLACE,
+                  resource.handle_update())
+
+        stack.delete()
 
-        self.greenpool.waitall()
+        self.m.VerifyAll()
 
     # allows testing of the test directly
     if __name__ == '__main__':