Example #1
0
class FSMContextMergeJoinTests(AppEngineTestCase):
    
    def setUp(self):
        super(FSMContextMergeJoinTests, self).setUp()
        self.state = State('foo', None, CountExecuteCalls(), None)
        self.state2 = State('foo2', None, CountExecuteCallsWithFork(), None)
        self.state.addTransition(Transition('t1', self.state2, queueName='q'), 'event')
        self.context = FSMContext(self.state, 
                                  currentState=self.state, 
                                  machineName='machineName', 
                                  instanceName='instanceName',
                                  queueName='qq',
                                  obj={TASK_NAME_PARAM: 'taskName'})
        self.context.startingState = self.state
        from google.appengine.api.taskqueue.taskqueue import TaskRetryOptions
        self.context.retryOptions = TaskRetryOptions()
        self.context[INDEX_PARAM] = 1
        self.context[STEPS_PARAM] = 0
        
    def test_mergeJoinDispatch_1_context(self):
        _FantasmFanIn(workIndex='instanceName--foo--event--foo2--step-0-2654435761').put()
        self.assertEqual(1, _FantasmFanIn.all().count())
        contexts = self.context.mergeJoinDispatch('event', {RETRY_COUNT_PARAM: 0})
        self.assertEqual([{'__ix__': 1, '__step__': 0}], contexts)
        self.assertEqual(1, _FantasmFanIn.all().count())
        
    def test_mergeJoinDispatch_1234_contexts(self):
        for i in xrange(1234):
            _FantasmFanIn(workIndex='instanceName--foo--event--foo2--step-0-2654435761').put()
        self.assertEqual(1000, _FantasmFanIn.all().count()) # can't get them all with .count()
        contexts = self.context.mergeJoinDispatch('event', {RETRY_COUNT_PARAM: 0})
        self.assertEqual(1234, len(contexts))
        self.assertEqual(1000, _FantasmFanIn.all().count())
Example #2
0
    def _getState(self, machineConfig, stateConfig):
        """ Returns a State instance based on the machineConfig/stateConfig 
        
        @param machineConfig: a config._MachineConfig instance
        @param stateConfig: a config._StateConfig instance  
        @return: a State instance which is a singleton wrt. the FSM instance
        """

        if machineConfig.name in self.machines and \
           stateConfig.name in self.machines[machineConfig.name][constants.MACHINE_STATES_ATTRIBUTE]:
            return self.machines[machineConfig.name][
                constants.MACHINE_STATES_ATTRIBUTE][stateConfig.name]

        name = stateConfig.name
        entryAction = stateConfig.entry
        doAction = stateConfig.action
        exitAction = stateConfig.exit
        isInitialState = stateConfig.initial
        isFinalState = stateConfig.final
        isContinuation = stateConfig.continuation
        fanInPeriod = stateConfig.fanInPeriod

        return State(name,
                     entryAction,
                     doAction,
                     exitAction,
                     machineName=machineConfig.name,
                     isInitialState=isInitialState,
                     isFinalState=isFinalState,
                     isContinuation=isContinuation,
                     fanInPeriod=fanInPeriod)
Example #3
0
 def setUp(self):
     super(FSMContextMergeJoinTests, self).setUp()
     self.state = State('foo', None, CountExecuteCalls(), None)
     self.state2 = State('foo2', None, CountExecuteCallsWithFork(), None)
     self.state.addTransition(Transition('t1', self.state2, queueName='q'),
                              'event')
     self.context = FSMContext(self.state,
                               currentState=self.state,
                               machineName='machineName',
                               instanceName='instanceName',
                               queueName='qq',
                               obj={TASK_NAME_PARAM: 'taskName'})
     self.context.startingState = self.state
     from google.appengine.api.taskqueue.taskqueue import TaskRetryOptions
     self.context.retryOptions = TaskRetryOptions()
     self.context[INDEX_PARAM] = 1
     self.context[STEPS_PARAM] = 0
Example #4
0
 def setUp(self):
     super(ReadWriteLockTest, self).setUp()
     self.loggingDouble = getLoggingDouble()
     self.state = State('name', None, None, None)
     self.context = FSMContext(self.state, queueName='default')
     self.context.currentState = self.state
     ReadWriteLock._BUSY_WAIT_ITER_SECS = ReadWriteLock.BUSY_WAIT_ITERS
     ReadWriteLock.BUSY_WAIT_ITER_SECS = 0
     ReadWriteLock._BUSY_WAIT_ITERS = ReadWriteLock.BUSY_WAIT_ITERS
     ReadWriteLock.BUSY_WAIT_ITERS = 2
     random.seed(0)  # last step
Example #5
0
class FSMContextMergeJoinTests(AppEngineTestCase):
    def setUp(self):
        super(FSMContextMergeJoinTests, self).setUp()
        self.state = State('foo', None, CountExecuteCalls(), None)
        self.state2 = State('foo2', None, CountExecuteCallsWithFork(), None)
        self.state.addTransition(Transition('t1', self.state2, queueName='q'),
                                 'event')
        self.context = FSMContext(self.state,
                                  currentState=self.state,
                                  machineName='machineName',
                                  instanceName='instanceName',
                                  queueName='qq',
                                  obj={TASK_NAME_PARAM: 'taskName'})
        self.context.startingState = self.state
        from google.appengine.api.taskqueue.taskqueue import TaskRetryOptions
        self.context.retryOptions = TaskRetryOptions()
        self.context[INDEX_PARAM] = 1
        self.context[STEPS_PARAM] = 0

    def test_mergeJoinDispatch_1_context(self):
        _FantasmFanIn(
            workIndex='instanceName--foo--event--foo2--step-0-2654435761').put(
            )
        self.assertEqual(1, _FantasmFanIn.all().count())
        contexts = self.context.mergeJoinDispatch('event',
                                                  {RETRY_COUNT_PARAM: 0})
        self.assertEqual([{'__ix__': 1, '__step__': 0}], contexts)
        self.assertEqual(1, _FantasmFanIn.all().count())

    def test_mergeJoinDispatch_1234_contexts(self):
        for i in xrange(1234):
            _FantasmFanIn(
                workIndex='instanceName--foo--event--foo2--step-0-2654435761'
            ).put()
        self.assertEqual(
            1000,
            _FantasmFanIn.all().count())  # can't get them all with .count()
        contexts = self.context.mergeJoinDispatch('event',
                                                  {RETRY_COUNT_PARAM: 0})
        self.assertEqual(1234, len(contexts))
        self.assertEqual(1000, _FantasmFanIn.all().count())
Example #6
0
 def setUp(self):
     super(FSMContextMergeJoinTests, self).setUp()
     self.state = State('foo', None, CountExecuteCalls(), None)
     self.state2 = State('foo2', None, CountExecuteCallsWithFork(), None)
     self.state.addTransition(Transition('t1', self.state2, queueName='q'), 'event')
     self.context = FSMContext(self.state, 
                               currentState=self.state, 
                               machineName='machineName', 
                               instanceName='instanceName',
                               queueName='qq')
     self.context[INDEX_PARAM] = 1
     self.context[STEPS_PARAM] = 0
Example #7
0
 def setUp(self):
     super(FSMContextMergeJoinTests, self).setUp()
     self.state = State('foo', None, CountExecuteCalls(), None)
     self.state2 = State('foo2', None, CountExecuteCallsWithFork(), None)
     self.state.addTransition(Transition('t1', self.state2, queueName='q'), 'event')
     self.context = FSMContext(self.state, 
                               currentState=self.state, 
                               machineName='machineName', 
                               instanceName='instanceName',
                               queueName='qq',
                               obj={TASK_NAME_PARAM: 'taskName'})
     self.context.startingState = self.state
     from google.appengine.api.taskqueue.taskqueue import TaskRetryOptions
     self.context.retryOptions = TaskRetryOptions()
     self.context[INDEX_PARAM] = 1
     self.context[STEPS_PARAM] = 0
Example #8
0
    def _init(self, currentConfig=None):
        """ Constructs a group of singleton States and Transitions from the machineConfig 
        
        @param currentConfig: a config._Configuration instance (dependency injection). if None, 
            then the factory uses config.currentConfiguration()
        """
        import logging
        logging.info("Initializing FSM factory.")

        self.config = currentConfig or config.currentConfiguration()
        self.machines = {}
        self.pseudoInits, self.pseudoFinals = {}, {}
        for machineConfig in self.config.machines.values():
            self.machines[machineConfig.name] = {
                constants.MACHINE_STATES_ATTRIBUTE: {},
                constants.MACHINE_TRANSITIONS_ATTRIBUTE: {}
            }
            machine = self.machines[machineConfig.name]

            # create a pseudo-init state for each machine that transitions to the initialState
            pseudoInit = State(FSM.PSEUDO_INIT, None, None, None)
            self.pseudoInits[machineConfig.name] = pseudoInit
            self.machines[machineConfig.name][
                constants.MACHINE_STATES_ATTRIBUTE][
                    FSM.PSEUDO_INIT] = pseudoInit

            # create a pseudo-final state for each machine that transitions from the finalState(s)
            pseudoFinal = State(FSM.PSEUDO_FINAL,
                                None,
                                None,
                                None,
                                isFinalState=True)
            self.pseudoFinals[machineConfig.name] = pseudoFinal
            self.machines[machineConfig.name][
                constants.MACHINE_STATES_ATTRIBUTE][
                    FSM.PSEUDO_FINAL] = pseudoFinal

            for stateConfig in machineConfig.states.values():
                state = self._getState(machineConfig, stateConfig)

                # add the transition from pseudo-init to initialState
                if state.isInitialState:
                    transition = Transition(
                        FSM.PSEUDO_INIT,
                        state,
                        retryOptions=self._buildRetryOptions(machineConfig),
                        queueName=machineConfig.queueName)
                    self.pseudoInits[machineConfig.name].addTransition(
                        transition, FSM.PSEUDO_INIT)

                # add the transition from finalState to pseudo-final
                if state.isFinalState:
                    transition = Transition(
                        FSM.PSEUDO_FINAL,
                        pseudoFinal,
                        retryOptions=self._buildRetryOptions(machineConfig),
                        queueName=machineConfig.queueName)
                    state.addTransition(transition, FSM.PSEUDO_FINAL)

                machine[constants.MACHINE_STATES_ATTRIBUTE][
                    stateConfig.name] = state

            for transitionConfig in machineConfig.transitions.values():
                source = machine[constants.MACHINE_STATES_ATTRIBUTE][
                    transitionConfig.fromState.name]
                transition = self._getTransition(machineConfig,
                                                 transitionConfig)
                machine[constants.MACHINE_TRANSITIONS_ATTRIBUTE][
                    transitionConfig.name] = transition
                event = transitionConfig.event
                source.addTransition(transition, event)
Example #9
0
 def test_generatedContextNameIsUnique(self):
     instanceName1 = self.context.instanceName
     state = State('foo', None, CountExecuteCalls(), None)
     context2 = FSMContext({state.name: state}, state, queueName='q')
     instanceName2 = context2.instanceName
     self.assertNotEquals(instanceName1, instanceName2)