def test_execute_sends_callbacks(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', value='-5.6'), Argument('num2', value='4.3'), Argument('num3', value='10.2') ]) instance = TestAction._make_app_instance() result = {'started_triggered': False, 'result_triggered': False} def callback_is_sent(sender, **kwargs): if isinstance(sender, Action): self.assertIn('event', kwargs) self.assertIn(kwargs['event'], (WalkoffEvent.ActionStarted, WalkoffEvent.ActionExecutionSuccess)) if kwargs['event'] == WalkoffEvent.ActionStarted: result['started_triggered'] = True else: self.assertIn('data', kwargs) data = kwargs['data'] self.assertEqual(data['status'], 'Success') self.assertAlmostEqual(data['result'], 8.9) result['result_triggered'] = True WalkoffEvent.CommonWorkflowSignal.connect(callback_is_sent) action.execute(LocalActionExecutionStrategy(), {}, instance.instance) self.assertTrue(result['started_triggered']) self.assertTrue(result['result_triggered'])
def test_execute_default_return_success(self): action = Action(app_name='HelloWorld', action_name='dummy action', name='helloWorld', arguments=[ Argument('status', value=True), Argument('other', value=True) ]) instance = TestAction._make_app_instance() result = {'started_triggered': False, 'result_triggered': False} def callback_is_sent(sender, **kwargs): if isinstance(sender, Action): self.assertIn('event', kwargs) self.assertIn(kwargs['event'], (WalkoffEvent.ActionStarted, WalkoffEvent.ActionExecutionSuccess)) if kwargs['event'] == WalkoffEvent.ActionStarted: result['started_triggered'] = True else: self.assertIn('data', kwargs) data = kwargs['data'] self.assertEqual(data['status'], 'Success') self.assertEqual(data['result'], None) result['result_triggered'] = True WalkoffEvent.CommonWorkflowSignal.connect(callback_is_sent) action.execute(LocalActionExecutionStrategy(), {}, instance.instance) self.assertTrue(result['started_triggered']) self.assertTrue(result['result_triggered'])
def test_init_with_arguments_with_routing(self): condition = Condition( 'HelloWorld', action_name='mod1_flag2', arguments=[Argument('arg1', reference='action2')]) self.__compare_init(condition, 'HelloWorld', 'mod1_flag2', [], [Argument('arg1', reference="action2")])
def test_validate_parameters_missing_required_without_default(self): parameter_apis = [{ 'name': 'name1', 'type': 'string', 'minLength': 1, 'maxLength': 25, 'enum': ['test', 'test3'] }, { 'name': 'name2', 'type': 'integer', 'minimum': -3, 'maximum': 25 }, { 'name': 'name3', 'type': 'number', 'required': True, 'minimum': -10.5, 'maximum': 30.725 }] arguments = [ Argument('name1', value='test'), Argument('name2', value='5') ] with self.assertRaises(InvalidArgument): validate_parameters(parameter_apis, arguments, self.message)
def test_validate_parameters_missing_without_default(self): parameter_apis = [{ 'name': 'name1', 'type': 'string', 'minLength': 1, 'maxLength': 25, 'enum': ['test', 'test3'] }, { 'name': 'name2', 'type': 'integer', 'minimum': -3, 'maximum': 25 }, { 'name': 'name3', 'type': 'number', 'minimum': -10.5, 'maximum': 30.725 }] arguments = [ Argument('name1', value='test'), Argument('name2', value='5') ] expected = {'name1': 'test', 'name2': 5, 'name3': None} self.assertAlmostEqual( validate_parameters(parameter_apis, arguments, self.message), expected)
def test_execute(self): condition1 = ConditionalExpression( 'and', conditions=[ Condition('HelloWorld', action_name='regMatch', arguments=[Argument('regex', value='(.*)')]) ]) condition2 = ConditionalExpression( 'and', conditions=[ Condition('HelloWorld', action_name='regMatch', arguments=[Argument('regex', value='(.*)')]), Condition('HelloWorld', action_name='regMatch', arguments=[Argument('regex', value='a')]) ]) inputs = [('name1', None, ActionResult('aaaa', 'Success'), True), ('name2', condition1, ActionResult('anyString', 'Success'), True), ('name3', condition2, ActionResult('anyString', 'Success'), True), ('name4', condition2, ActionResult('bbbb', 'Success'), False), ('name4', condition2, ActionResult('aaaa', 'Custom'), False)] for name, condition, input_str, expect_name in inputs: branch = Branch(source_id=1, destination_id=2, condition=condition) if expect_name: expected_name = branch.destination_id self.assertEqual(branch.execute(input_str, {}), expected_name) else: self.assertIsNone(branch.execute(input_str, {}))
def test_validate_parameters_skip_action_references_inputs_non_string( self): parameter_apis = [{ 'name': 'name1', 'type': 'string', 'minLength': 1, 'maxLength': 25, 'enum': ['test', 'test3'] }, { 'name': 'name2', 'type': 'integer', 'minimum': -3, 'maximum': 25 }, { 'name': 'name3', 'type': 'number', 'required': True, 'minimum': -10.5, 'maximum': 30.725 }] arguments = [ Argument('name1', value='test'), Argument('name2', value=5), Argument('name3', reference='action1') ] expected = {'name1': 'test', 'name2': 5} self.assertDictEqual( validate_parameters(parameter_apis, arguments, self.message), expected)
def test_execute_with_accumulator_missing_action_callbacks(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', reference='1'), Argument('num2', reference='action2'), Argument('num3', value='10.2') ]) accumulator = {'1': '-5.6', 'missing': '4.3', '3': '45'} instance = TestAction._make_app_instance() result = {'started_triggered': False, 'result_triggered': False} def callback_is_sent(sender, **kwargs): if isinstance(sender, Action): self.assertIn('event', kwargs) self.assertIn(kwargs['event'], (WalkoffEvent.ActionStarted, WalkoffEvent.ActionArgumentsInvalid)) if kwargs['event'] == WalkoffEvent.ActionStarted: result['started_triggered'] = True else: result['result_triggered'] = True WalkoffEvent.CommonWorkflowSignal.connect(callback_is_sent) action.execute(LocalActionExecutionStrategy(), accumulator, instance.instance) self.assertTrue(result['started_triggered']) self.assertTrue(result['result_triggered'])
def test_init_with_args(self): filter_elem = Transform('HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', value='5.4')]) self.__compare_init(filter_elem, 'HelloWorld', 'mod1_filter2', arguments=[Argument('arg1', value='5.4')])
def test_execute_action_with_valid_arguments_and_transforms_invalid_data(self): transforms = [Transform('HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', value='5')]), Transform('HelloWorld', action_name='Top Transform')] # should go <input = invalid> -> <mod1_filter2 with error = invalid> -> <Top Transform with error = invalid> # -> <mod1_flag2 4+invalid throws error> -> False with self.assertRaises(InvalidArgument): Condition('HelloWorld', action_name='mod1_flag2', arguments=[Argument('arg1', value=4)], transforms=transforms).execute('invalid', {})
def test_get_action_from_reference(self): arg = Argument('test', reference='a') self.assertEqual( arg._get_action_from_reference({ 'a': 1, 'b': 3, 'c': 7 }), 1)
def test_get_value_reference_and_selection(self): arg = Argument('test', reference='a', selection=['a', 0, '1', 'b']) input_ = {'a': [[{'one': 1}, {'three': 3, 'b': 4}], [{'one': 1}, {'two': 2}]], 'b': 15, 'c': 'something'} self.assertEqual(arg.get_value({'a': input_, 'b': 2}), 4)
def test_select(self): arg = Argument('test', reference='some_id', selection=['a', 0, '1', 'b']) input_ = {'a': [[{'one': 1}, {'three': 3, 'b': 4}], [{'one': 1}, {'two': 2}]], 'b': 15, 'c': 'something'} self.assertEqual(arg._select(input_), 4)
def test_init_with_args_with_routing(self): filter_elem = Transform( 'HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', reference="action1")]) self.__compare_init(filter_elem, 'HelloWorld', 'mod1_filter2', arguments=[Argument('arg1', reference="action1")])
def test_select_selection_too_deep(self): arg = Argument('test', reference='some_id', selection=['a', 0, '1', 'b', 10]) input_ = {'a': [[{'one': 1}, {'three': 3, 'b': 4}], [{'one': 1}, {'two': 2}]], 'b': 15, 'c': 'something'} with self.assertRaises(InvalidArgument): arg._select(input_)
def test_get_value_reference_and_bad_selection(self): arg = Argument('test', reference='a', selection=['a', 0, '1', 'invalid']) input_ = {'a': [[{'one': 1}, {'three': 3, 'b': 4}], [{'one': 1}, {'two': 2}]], 'b': 15, 'c': 'something'} with self.assertRaises(InvalidArgument): arg.get_value({'a': input_, 'b': 2})
def test_init_with_arguments_with_conversion(self): action = Action('HelloWorld', 'returnPlusOne', 'returnPlusOne', arguments=[Argument('number', value='-5.6')]) self.__compare_init(action, 'HelloWorld', 'returnPlusOne', 'returnPlusOne', arguments=[Argument('number', value='-5.6')])
def test_init_app_action_only_with_device(self): action = Action('HelloWorld', 'helloWorld', 'helloWorld', device_id=Argument(name='__device__', value="test")) self.__compare_init(action, 'HelloWorld', 'helloWorld', 'helloWorld', device_id=Argument(name='__device__', value="test"))
def test_execute_with_accumulator_missing_action(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', reference='1'), Argument('num2', reference='action2'), Argument('num3', value='10.2') ]) accumulator = {'1': '-5.6', 'missing': '4.3', '3': '45'} instance = AppInstance.create(app_name='HelloWorld', device_name='device1') action.execute(instance.instance, accumulator)
def test_execute_with_accumulator_missing_action(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', reference='1'), Argument('num2', reference='action2'), Argument('num3', value='10.2') ]) accumulator = {'1': '-5.6', 'missing': '4.3', '3': '45'} instance = TestAction._make_app_instance() action.execute(LocalActionExecutionStrategy(), accumulator, instance.instance)
def test_update_value_reference_from_value(self): input_output = { (None, None): (42, None), (43, None): (43, None), (42, None): (42, None), (43, 'a'): (43, None), (None, 'a'): (None, 'a'), (42, 'a'): (None, 'a') } for inputs, outputs in input_output.items(): arg = Argument('test', value=42) arg.update_value_reference(*inputs) self.assertEqual(arg.value, outputs[0]) self.assertEqual(arg.reference, outputs[1])
def test_execute_with_args(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', value='-5.6'), Argument('num2', value='4.3'), Argument('num3', value='10.2') ]) instance = TestAction._make_app_instance() acc = {} result = action.execute(LocalActionExecutionStrategy(), acc, instance.instance) self.assertAlmostEqual(acc[action.id], 8.9) self.assertEqual(result, 'Success')
def test_execute_with_args(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', value='-5.6'), Argument('num2', value='4.3'), Argument('num3', value='10.2') ]) instance = AppInstance.create(app_name='HelloWorld', device_name='device1') result = action.execute(instance.instance, {}) self.assertAlmostEqual(result.result, 8.9) self.assertEqual(result.status, 'Success') self.assertEqual(action._output, result)
def test_execute_with_accumulator_with_extra_actions(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', reference='1'), Argument('num2', reference='action2'), Argument('num3', value='10.2') ]) accumulator = {'1': '-5.6', 'action2': '4.3', '3': '45'} instance = TestAction._make_app_instance() result = action.execute(LocalActionExecutionStrategy(), accumulator, instance.instance) self.assertAlmostEqual(accumulator[action.id], 8.9) self.assertEqual(result, 'Success')
def test_execute_action_with_valid_arguments_and_transforms_valid_data( self): transforms = [ Transform('HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', value='5')]), Transform('HelloWorld', action_name='Top Transform') ] # should go <input = 1> -> <mod1_filter2 = 5+1 = 6> -> <Top Transform 6=6> -> <mod1_flag2 4+6%2==0> -> True self.assertTrue( Condition('HelloWorld', action_name='mod1_flag2', arguments=[Argument('arg1', value=4)], transforms=transforms).execute( LocalActionExecutionStrategy(), '1', {}))
def test_execute_with_complex_args(self): action = Action(app_name='HelloWorld', action_name='Json Sample', name='helloWorld', arguments=[ Argument('json_in', value={ 'a': '-5.6', 'b': { 'a': '4.3', 'b': 5.3 }, 'c': ['1', '2', '3'], 'd': [{ 'a': '', 'b': 3 }, { 'a': '', 'b': -1.5 }, { 'a': '', 'b': -0.5 }] }) ]) instance = TestAction._make_app_instance() acc = {} result = action.execute(LocalActionExecutionStrategy(), acc, instance.instance) self.assertAlmostEqual(acc[action.id], 11.0) self.assertEqual(result, 'Success')
def test_execute_with_args_with_conversion(self): self.assertAlmostEqual( Transform('HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', value='10.3')]).execute(5.4, {}), 15.7)
def __update_arguments_with_data(self, data): arguments = [] for argument in self.arguments: if argument.name != self._data_param_name: arguments.append(argument) arguments.append(Argument(self._data_param_name, value=data)) return arguments
def receive_workflows(self): """Receives requests to execute workflows, and sends them off to worker threads""" logger.info('Starting workflow receiver') box = Box(self.key, self.server_key) while not self.exit: received_message = self.cache.rpop("request_queue") if received_message is not None: try: decrypted_msg = box.decrypt(received_message) except CryptoError: logger.error( 'Worker could not decrypt received workflow message') continue try: message = ExecuteWorkflowMessage() message.ParseFromString(decrypted_msg) except DecodeError: logger.error( 'Workflow could not decode received workflow message') else: start = message.start if hasattr(message, 'start') else None start_arguments = [] if hasattr(message, 'arguments'): for arg in message.arguments: start_arguments.append( Argument(**(MessageToDict( arg, preserving_proto_field_name=True)))) yield message.workflow_id, message.workflow_execution_id, start, start_arguments, message.resume else: yield None raise StopIteration
def __func(): data = request.get_json() workflows_in = set(data['execution_ids']) data_in = data['data_in'] arguments = data['arguments'] if 'arguments' in data else [] workflows_awaiting_data = set( current_app.running_context.executor.get_waiting_workflows()) execution_ids = set.intersection(workflows_in, workflows_awaiting_data) user_id = get_jwt_identity() authorization_not_required, authorized_execution_ids = get_authorized_execution_ids( execution_ids, user_id, get_jwt_claims().get('roles', [])) execution_ids = list(authorized_execution_ids | authorization_not_required) completed_execution_ids = [] arg_objects = [] for arg in arguments: arg_objects.append(Argument(**arg)) for execution_id in execution_ids: if current_app.running_context.executor.resume_trigger_step( execution_id, data_in, arg_objects): completed_execution_ids.append(execution_id) log_action_taken_on_message(user_id, execution_id) return completed_execution_ids, SUCCESS
def test_update_value_reference_from_reference(self): input_output = { (None, None): (None, 'a'), (None, 'b'): (None, 'b'), (None, 'a'): (None, 'a'), (None, ''): (None, 'a'), (42, None): (42, None), (42, 'a'): (42, None), (42, ''): (42, None) } for inputs, outputs in input_output.items(): arg = Argument('test', reference='a', selection=[1, 'a']) arg.update_value_reference(*inputs) self.assertEqual(arg.value, outputs[0]) self.assertEqual(arg.reference, outputs[1]) if outputs[1] is None: self.assertListEqual(arg.selection, [])
def test_select_one_on_dict(self): arg = Argument('test', reference='some_id', selection=['b']) self.assertEqual(arg._select({'a': 1, 'b': 2, 'c': 3}), 2)
def test_select_one_on_list(self): arg = Argument('test', reference='some_id', selection=[1]) self.assertEqual(arg._select(['a', 'b', 'c']), 'b')
def test_select_one_on_list_out_of_range(self): arg = Argument('test', reference='some_id', selection=[10]) with self.assertRaises(InvalidArgument): arg._select(['a', 'b', 'c'])
def test_get_next_selection_str_index_on_list(self): self.assertEqual(Argument._get_next_selection(['a', 1, '2', 'something'], '3'), 'something')
def test_get_next_selection_index_on_list_out_of_bounds(self): with self.assertRaises(IndexError): Argument._get_next_selection(['a', 1, '2', 'something'], 10)
def test_get_next_selection_key_on_value(self): with self.assertRaises(ValueError): Argument._get_next_selection('something', 'a')
def test_get_next_selection_index_on_dict(self): with self.assertRaises(KeyError): Argument._get_next_selection({'a': 1, '2': 'something'}, 3)
def test_get_action_from_reference(self): arg = Argument('test', reference='a') self.assertEqual(arg._get_action_from_reference({'a': 1, 'b': 3, 'c': 7}), 1)
def test_get_action_from_reference_not_in_accumulator(self): arg = Argument('test', reference='a') with self.assertRaises(InvalidArgument): arg._get_action_from_reference({'b': 3, 'c': 7})
def test_select_one_on_dict_key_error(self): arg = Argument('test', reference='some_id', selection=['d']) with self.assertRaises(InvalidArgument): arg._select({'a': 1, 'b': 2, 'c': 3})
def test_get_value_value_only(self): arg = Argument('test', value=42) self.assertEqual(arg.get_value({}), 42)
def test_get_value_value_with_reference(self): arg = Argument('test', value=42, reference='a') self.assertEqual(arg.get_value({'a': 1}), 42)
def test_get_value_reference_only(self): arg = Argument('test', reference='a') self.assertEqual(arg.get_value({'a': 1, 'b': 2}), 1)
def test_get_value_reference_not_found(self): arg = Argument('test', reference='c') with self.assertRaises(InvalidArgument): arg.get_value({'a': 1, 'b': 2})
def test_select_one_on_value(self): arg = Argument('test', reference='some_id', selection=['d']) with self.assertRaises(InvalidArgument): arg._select('some raw value')
def test_get_next_selection_key_on_dict(self): self.assertEqual(Argument._get_next_selection({'a': 1, '2': 'something'}, 'a'), 1)
def test_get_next_selection_key_on_list(self): with self.assertRaises(ValueError): Argument._get_next_selection(['a', 1, '2', 'something'], 'a')
def test_get_action_from_reference_empty_accumulator(self): arg = Argument('test', reference='a') with self.assertRaises(InvalidArgument): arg._get_action_from_reference({})