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())
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)
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 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
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())
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
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)
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)