Example #1
0
class SpawnTests(unittest.TestCase):

    def setUp(self):
        super(SpawnTests, self).setUp()
        filename = 'test-TaskQueueFSMTests.yaml'
        setUpByFilename(self, filename)
        self.machineName = getMachineNameByFilename(filename)
        self.mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
        # dispatch initial event to get context in correct state
        self.taskName = 'foo'
        self.obj = {TASK_NAME_PARAM: self.taskName}
        self.context.dispatch(FSM.PSEUDO_INIT, self.obj)
        # but now flush the task queue to remove the event that we just dispatched;
        # we're only interested in testing spawn tasks
        self.mockQueue.purge()
        
    def tearDown(self):
        super(SpawnTests, self).tearDown()
        restore()
        
    def getTask(self, num):
        """ Retrieves a queued task from mock queue. """
        return self.mockQueue.tasks[num][0]
    
    def test_spawnWithNoContextDoesNotQueueAnything(self):
        self.context.spawn(self.machineName, None, _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 0)
        
    def test_spawnWithOneContextQueuesOne(self):
        self.context.spawn(self.machineName, {'a': '1'}, _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 1)
        
    def test_spawnWithTwoContextsQueuesTwo(self):
        self.context.spawn(self.machineName, [{'a': '1'}, {'b': '2'}], _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 2)
        
    def test_spawnUsesCorrectUrl(self):
        self.context.spawn(self.machineName, [{'a': '1'}, {'b': '2'}], _currentConfig=self.currentConfig)
        self.assertTrue(self.getTask(0).url.startswith('/fantasm/fsm/%s/' % self.machineName))
        self.assertTrue(self.getTask(1).url.startswith('/fantasm/fsm/%s/' % self.machineName))
        
    def test_contextAreIncludedInTasks(self):
        self.context.spawn(self.machineName, [{'a': '1'}, {'b': '2'}], _currentConfig=self.currentConfig,
                           method='GET')
        self.assertTrue('a=1' in self.getTask(0).url)
        self.assertTrue('b=2' in self.getTask(1).url)

    def test_countdownIsIncludedInTask(self):
        # having trouble mocking Task, so I'll dip into a private attribute right on task
        import time
        self.context.spawn(self.machineName, {'a': '1'}, countdown=20, _currentConfig=self.currentConfig)
        self.assertTrue(time.time()+20 - getattr(self.mockQueue.tasks[0][0], '_Task__eta_posix') < 0.01)
        
    def test_spawnIsIdempotent(self):
        self.context.spawn(self.machineName, {'a': '1'}, _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 1)
        self.context.spawn(self.machineName, {'a': '1'}, _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 1)
Example #2
0
    def setUp(self):
        super(TaskQueueFSMRetryTests, self).setUp()
        filename = 'test-TaskQueueFSMRetryTests.yaml'
        machineName = getMachineNameByFilename(filename)
        self.factory = getFSMFactoryByFilename(filename)
        self.context = self.factory.createFSMInstance(machineName)

        self.mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
        self.loggingDouble = getLoggingDouble()

        # drive the machine to ready
        self.initEvent = self.context.initialize()
        self.mockQueue.purge()  # clear the initialization task
Example #3
0
 def setUp(self):
     super(SpawnTests, self).setUp()
     filename = 'test-TaskQueueFSMTests.yaml'
     setUpByFilename(self, filename)
     self.machineName = getMachineNameByFilename(filename)
     self.mockQueue = TaskQueueDouble()
     mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
     # dispatch initial event to get context in correct state
     self.taskName = 'foo'
     self.obj = {TASK_NAME_PARAM: self.taskName}
     self.context.dispatch(FSM.PSEUDO_INIT, self.obj)
     # but now flush the task queue to remove the event that we just dispatched;
     # we're only interested in testing spawn tasks
     self.mockQueue.purge()
Example #4
0
 def setUp(self):
     super(StartStateMachineTests, self).setUp()
     filename = 'test-TaskQueueFSMTests.yaml'
     setUpByFilename(self, filename)
     self.machineName = getMachineNameByFilename(filename)
     self.mockQueue = TaskQueueDouble()
     mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
Example #5
0
    def test_finalStateDispatchWithEventEmitsNoEventAsTask(self):
        mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=mockQueue.add, tracker=None)

        self.context.currentState = self.stateNormal
        self.context.dispatch('next-event', {})

        self.assertEquals(len(mockQueue.tasks), 0)
Example #6
0
    def test_instanceNameIsPropagated(self):
        mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=mockQueue.add, tracker=None)

        event = self.context.initialize()
        self.context.dispatch(event, {})

        self.assertEquals(len(mockQueue.tasks), 2)
        (task, transactional) = mockQueue.tasks[0]
        self.assertTaskUrlHasInstanceName(task, self.context.instanceName)
Example #7
0
 def setUp(self):
     super(FSMContextTests, self).setUp()
     filename = 'test-FSMContextTests.yaml'
     setUpByFilename(self, filename)
     self.machineName = getMachineNameByFilename(filename)
     self.mockQueue = TaskQueueDouble()
     mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
     # dispatch initial event to get context in correct state
     self.taskName = 'foo'
     self.obj = {TASK_NAME_PARAM: self.taskName}
     self.context.dispatch(FSM.PSEUDO_INIT, self.obj)
Example #8
0
    def test_normalStateDispatchWithEventRespectsCountdown(self):
        import time
        mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=mockQueue.add, tracker=None)

        self.context.currentState = self.stateInitial
        self.context.dispatch('next-event', {})

        (task, transactional) = mockQueue.tasks[0]
        self.assertTrue(
            time.time() + 20 - getattr(task, '_Task__eta_posix') < 0.01)
Example #9
0
    def test_normalStateDispatchWithEventEmitsEventAsTask(self):
        mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=mockQueue.add, tracker=None)

        self.context.currentState = self.stateInitial
        self.context.dispatch('next-event', {})

        self.assertEquals(len(mockQueue.tasks), 1)
        (task, transactional) = mockQueue.tasks[0]
        # state-normal is the state we're transitioning FROM
        self.assertTaskUrlHasStateAndEvent(task, 'state-normal', 'next-event')
Example #10
0
 def setUp(self):
     super(DatastoreFSMContinuationBaseTests, self).setUp()
     setUpByFilename(self,
                     self.FILENAME,
                     instanceName='instanceName',
                     machineName=self.MACHINE_NAME)
     self.mockQueue = TaskQueueDouble()
     mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
     self.loggingDouble = getLoggingDouble()
     self.modelKeys = []
     for i in range(10):
         modelKey = TestModel().put()
         self.modelKeys.append(modelKey)
Example #11
0
    def test_initialDispatchEmitsEventAsTask(self):
        mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=mockQueue.add, tracker=None)

        event = self.context.initialize()
        self.assertEquals(len(mockQueue.tasks), 1)

        self.context.dispatch(event, {})

        self.assertEquals(len(mockQueue.tasks), 2)
        (task, transactional) = mockQueue.tasks[1]

        # state-initial is the state we're transitioning FROM
        self.assertTaskUrlHasStateAndEvent(task, 'state-initial', 'next-event')
Example #12
0
 def setUp(self):
     super(SpawnTests, self).setUp()
     filename = 'test-TaskQueueFSMTests.yaml'
     setUpByFilename(self, filename)
     self.machineName = getMachineNameByFilename(filename)
     self.mockQueue = TaskQueueDouble()
     mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
     # dispatch initial event to get context in correct state
     self.taskName = 'foo'
     self.obj = {TASK_NAME_PARAM: self.taskName}
     self.context.dispatch(FSM.PSEUDO_INIT, self.obj)
     # but now flush the task queue to remove the event that we just dispatched;
     # we're only interested in testing spawn tasks
     self.mockQueue.purge()
Example #13
0
 def setUp(self):
     super(TaskQueueFSMRetryTests, self).setUp()
     filename = 'test-TaskQueueFSMRetryTests.yaml'
     machineName = getMachineNameByFilename(filename)
     self.factory = getFSMFactoryByFilename(filename)
     self.context = self.factory.createFSMInstance(machineName)
     
     self.mockQueue = TaskQueueDouble()
     mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
     self.loggingDouble = getLoggingDouble()
     
     # drive the machine to ready
     self.initEvent = self.context.initialize()
     self.mockQueue.purge() # clear the initialization task
Example #14
0
    def test_taskQueueOnQueueSpecifiedAtTransitionLevel(self):
        mockQueue = TaskQueueDouble()
        mock(name='Queue.__init__',
             returns_func=mockQueue.__init__,
             tracker=None)
        mock(name='Queue.add', returns_func=mockQueue.add, tracker=None)

        self.transNormalToFinal.queueName = 'fantasm-queue'  # should be this one (dest state)
        self.transInitialToNormal.queueName = 'barfoo'
        self.context.queueName = 'foobar'

        self.context.currentState = self.stateInitial
        self.context.dispatch('next-event', {})

        self.assertEquals(mockQueue.name, 'fantasm-queue')
Example #15
0
class TaskQueueFSMRetryTests(AppEngineTestCase):
    def setUp(self):
        super(TaskQueueFSMRetryTests, self).setUp()
        filename = 'test-TaskQueueFSMRetryTests.yaml'
        machineName = getMachineNameByFilename(filename)
        self.factory = getFSMFactoryByFilename(filename)
        self.context = self.factory.createFSMInstance(machineName)

        self.mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
        self.loggingDouble = getLoggingDouble()

        # drive the machine to ready
        self.initEvent = self.context.initialize()
        self.mockQueue.purge()  # clear the initialization task

    def tearDown(self):
        super(TaskQueueFSMRetryTests, self).tearDown()
        restore()

    def test_taskRetryLimitAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok1'

        mock(name='CountExecuteCalls.execute',
             returns_func=execute,
             tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.task_retry_limit, 1)

    def test_minBackoffSecondsAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok2'

        mock(name='CountExecuteCalls.execute',
             returns_func=execute,
             tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.min_backoff_seconds, 2)

    def test_maxBackoffSecondsAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok3'

        mock(name='CountExecuteCalls.execute',
             returns_func=execute,
             tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.max_backoff_seconds, 3)

    def test_taskAgeLimitAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok4'

        mock(name='CountExecuteCalls.execute',
             returns_func=execute,
             tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.task_age_limit, 4)

    def test_maxDoublingsAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok5'

        mock(name='CountExecuteCalls.execute',
             returns_func=execute,
             tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.max_doublings, 5)
Example #16
0
class TaskQueueFSMRetryTests(AppEngineTestCase):
    
    def setUp(self):
        super(TaskQueueFSMRetryTests, self).setUp()
        filename = 'test-TaskQueueFSMRetryTests.yaml'
        machineName = getMachineNameByFilename(filename)
        self.factory = getFSMFactoryByFilename(filename)
        self.context = self.factory.createFSMInstance(machineName)
        
        self.mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
        self.loggingDouble = getLoggingDouble()
        
        # drive the machine to ready
        self.initEvent = self.context.initialize()
        self.mockQueue.purge() # clear the initialization task
        
    def tearDown(self):
        super(TaskQueueFSMRetryTests, self).tearDown()
        restore()
        
    def test_taskRetryLimitAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok1'            
        mock(name='CountExecuteCalls.execute', returns_func=execute, tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.task_retry_limit, 1)
        
    def test_minBackoffSecondsAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok2'            
        mock(name='CountExecuteCalls.execute', returns_func=execute, tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.min_backoff_seconds, 2)
        
    def test_maxBackoffSecondsAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok3'            
        mock(name='CountExecuteCalls.execute', returns_func=execute, tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.max_backoff_seconds, 3)
        
    def test_taskAgeLimitAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok4'            
        mock(name='CountExecuteCalls.execute', returns_func=execute, tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.task_age_limit, 4)
        
    def test_maxDoublingsAddedToQueuedTask(self):
        def execute(context, obj):
            return 'ok5'            
        mock(name='CountExecuteCalls.execute', returns_func=execute, tracker=None)
        self.context.dispatch(self.initEvent, TemporaryStateObject())
        self.assertEquals(len(self.mockQueue.tasks), 1)
        task = self.mockQueue.tasks[0][0]
        self.assertEquals(task.retry_options.max_doublings, 5)
Example #17
0
class SpawnTests(unittest.TestCase):
    def setUp(self):
        super(SpawnTests, self).setUp()
        filename = 'test-TaskQueueFSMTests.yaml'
        setUpByFilename(self, filename)
        self.machineName = getMachineNameByFilename(filename)
        self.mockQueue = TaskQueueDouble()
        mock(name='Queue.add', returns_func=self.mockQueue.add, tracker=None)
        # dispatch initial event to get context in correct state
        self.taskName = 'foo'
        self.obj = {TASK_NAME_PARAM: self.taskName}
        self.context.dispatch(FSM.PSEUDO_INIT, self.obj)
        # but now flush the task queue to remove the event that we just dispatched;
        # we're only interested in testing spawn tasks
        self.mockQueue.purge()

    def tearDown(self):
        super(SpawnTests, self).tearDown()
        restore()

    def getTask(self, num):
        """ Retrieves a queued task from mock queue. """
        return self.mockQueue.tasks[num][0]

    def test_spawnWithNoContextDoesNotQueueAnything(self):
        self.context.spawn(self.machineName,
                           None,
                           _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 0)

    def test_spawnWithOneContextQueuesOne(self):
        self.context.spawn(self.machineName, {'a': '1'},
                           _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 1)

    def test_spawnWithTwoContextsQueuesTwo(self):
        self.context.spawn(self.machineName, [{
            'a': '1'
        }, {
            'b': '2'
        }],
                           _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 2)

    def test_spawnUsesCorrectUrl(self):
        self.context.spawn(self.machineName, [{
            'a': '1'
        }, {
            'b': '2'
        }],
                           _currentConfig=self.currentConfig)
        self.assertTrue(
            self.getTask(0).url.startswith('/fantasm/fsm/%s/' %
                                           self.machineName))
        self.assertTrue(
            self.getTask(1).url.startswith('/fantasm/fsm/%s/' %
                                           self.machineName))

    def test_contextAreIncludedInTasks(self):
        self.context.spawn(self.machineName, [{
            'a': '1'
        }, {
            'b': '2'
        }],
                           _currentConfig=self.currentConfig,
                           method='GET')
        self.assertTrue('a=1' in self.getTask(0).url)
        self.assertTrue('b=2' in self.getTask(1).url)

    def test_countdownIsIncludedInTask(self):
        # having trouble mocking Task, so I'll dip into a private attribute right on task
        import time
        self.context.spawn(self.machineName, {'a': '1'},
                           countdown=20,
                           _currentConfig=self.currentConfig)
        self.assertTrue(
            time.time() + 20 -
            getattr(self.mockQueue.tasks[0][0], '_Task__eta_posix') < 0.01)

    def test_spawnIsIdempotent(self):
        self.context.spawn(self.machineName, {'a': '1'},
                           _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 1)
        self.context.spawn(self.machineName, {'a': '1'},
                           _currentConfig=self.currentConfig)
        self.assertEquals(len(self.mockQueue.tasks), 1)