Esempio n. 1
0
    def test_execute_sends_callbacks(self):
        action = Action(app_name='HelloWorld',
                        action_name='Add Three',
                        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 = {'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(instance.instance, {})
        self.assertTrue(result['started_triggered'])
        self.assertTrue(result['result_triggered'])
Esempio n. 2
0
    def test_execute_default_return_success(self):
        action = Action(app_name='HelloWorld',
                        action_name='dummy action',
                        arguments=[
                            Argument('status', value=True),
                            Argument('other', value=True)
                        ])
        instance = AppInstance.create(app_name='HelloWorld',
                                      device_name='device1')
        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(instance.instance, {})

        self.assertTrue(result['started_triggered'])
        self.assertTrue(result['result_triggered'])
Esempio n. 3
0
 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 = {
         'name1': Argument('name1', value='test'),
         'name2': Argument('name2', value='5')
     }
     with self.assertRaises(InvalidArgument):
         validate_parameters(parameter_apis, arguments, self.message)
Esempio n. 4
0
 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 = {
         'name1': Argument('name1', value='test'),
         'name2': Argument('name2', value=5),
         'name3': Argument('name3', reference='action1')
     }
     expected = {'name1': 'test', 'name2': 5}
     self.assertDictEqual(
         validate_parameters(parameter_apis, arguments, self.message),
         expected)
Esempio n. 5
0
 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")])
Esempio n. 6
0
 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 = {
         'name1': Argument('name1', value='test'),
         'name2': Argument('name2', value='5')
     }
     expected = {'name1': 'test', 'name2': 5, 'name3': None}
     self.assertAlmostEqual(
         validate_parameters(parameter_apis, arguments, self.message),
         expected)
Esempio n. 7
0
    def test_execute_with_accumulator_missing_action_callbacks(self):
        action = Action(app_name='HelloWorld',
                        action_name='Add Three',
                        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')

        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(instance.instance, accumulator)

        self.assertTrue(result['started_triggered'])
        self.assertTrue(result['result_triggered'])
Esempio n. 8
0
    def test_execute(self):
        conditions1 = [
            Condition('HelloWorld',
                      action_name='regMatch',
                      arguments=[Argument('regex', value='(.*)')])
        ]
        conditions2 = [
            Condition('HelloWorld',
                      action_name='regMatch',
                      arguments=[Argument('regex', value='(.*)')]),
            Condition('HelloWorld',
                      action_name='regMatch',
                      arguments=[Argument('regex', value='a')])
        ]

        inputs = [
            ('name1', [], ActionResult('aaaa', 'Success'), True),
            ('name2', conditions1, ActionResult('anyString', 'Success'), True),
            ('name3', conditions2, ActionResult('anyString', 'Success'), True),
            ('name4', conditions2, ActionResult('bbbb', 'Success'), False),
            ('name4', conditions2, ActionResult('aaaa', 'Custom'), False)
        ]

        for name, conditions, input_str, expect_name in inputs:
            branch = Branch(source_uid="1",
                            destination_uid="2",
                            conditions=conditions)
            if expect_name:
                expected_name = branch.destination_uid
                self.assertEqual(branch.execute(input_str, {}), expected_name)
            else:
                self.assertIsNone(branch.execute(input_str, {}))
Esempio n. 9
0
 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)
Esempio n. 10
0
 def test_select(self):
     arg = Argument('test', reference='some_uid', 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)
Esempio n. 11
0
 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')])
Esempio n. 12
0
 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})
Esempio n. 13
0
 def test_init_with_arguments_with_conversion(self):
     action = Action('HelloWorld',
                     'returnPlusOne',
                     arguments=[Argument('number', value='-5.6')])
     self.__compare_init(action,
                         '',
                         'returnPlusOne',
                         'HelloWorld',
                         arguments=[Argument('number', value='-5.6')])
Esempio n. 14
0
 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")])
Esempio n. 15
0
 def test_select_selection_too_deep(self):
     arg = Argument('test', reference='some_uid', 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_)
Esempio n. 16
0
 def test_execute_with_accumulator_missing_action(self):
     action = Action(app_name='HelloWorld',
                     action_name='Add Three',
                     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)
Esempio n. 17
0
 def test_execute_with_args(self):
     action = Action(app_name='HelloWorld',
                     action_name='Add Three',
                     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)
Esempio n. 18
0
 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('1', {}))
Esempio n. 19
0
 def test_init_with_flags(self):
     triggers = [
         Condition('HelloWorld',
                   action_name='regMatch',
                   arguments=[Argument('regex', value='(.*)')]),
         Condition('HelloWorld',
                   action_name='regMatch',
                   arguments=[Argument('regex', value='a')])
     ]
     action = Action('HelloWorld', 'helloWorld', triggers=triggers)
     self.__compare_init(action,
                         '',
                         'helloWorld',
                         'HelloWorld',
                         triggers=['regMatch', 'regMatch'])
Esempio n. 20
0
 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
     self.assertFalse(
         Condition('HelloWorld',
                   action_name='mod1_flag2',
                   arguments=[Argument('arg1', value=4)],
                   transforms=transforms).execute('invalid', {}))
Esempio n. 21
0
 def test_execute_with_accumulator_with_extra_actions(self):
     action = Action(app_name='HelloWorld',
                     action_name='Add Three',
                     arguments=[
                         Argument('num1', reference='1'),
                         Argument('num2', reference='action2'),
                         Argument('num3', value='10.2')
                     ])
     accumulator = {'1': '-5.6', 'action2': '4.3', '3': '45'}
     instance = AppInstance.create(app_name='HelloWorld',
                                   device_name='device1')
     result = action.execute(instance.instance, accumulator)
     self.assertAlmostEqual(result.result, 8.9)
     self.assertEqual(result.status, 'Success')
     self.assertEqual(action._output, result)
Esempio n. 22
0
 def test_execute_action_with_valid_arguments_and_transforms_invalid_data_and_routing(
         self):
     transforms = [
         Transform('HelloWorld',
                   action_name='mod1_filter2',
                   arguments=[Argument('arg1', reference='action1')]),
         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
     accumulator = {'action1': '5', 'action2': 4}
     self.assertFalse(
         Condition('HelloWorld',
                   action_name='mod1_flag2',
                   arguments=[Argument('arg1', value=4)],
                   transforms=transforms).execute('invalid', accumulator))
Esempio n. 23
0
    def execute(self, data_in, accumulator):
        """Executes the transform.

        Args:
            data_in: The input to the condition, the last executed action of the workflow or the input to a trigger.
            accumulator (dict): A record of executed actions and their results. Of form {action_name: result}.

        Returns:
            (obj): The transformed data
        """
        original_data_in = deepcopy(data_in)
        try:
            self.arguments.update({self._data_param_name: Argument(self._data_param_name, value=data_in)})
            args = validate_transform_parameters(self._api, self.arguments, self.action_name, accumulator=accumulator)
            result = self._transform_executable(**args)
            WalkoffEvent.CommonWorkflowSignal.send(self, event=WalkoffEvent.TransformSuccess)
            return result
        except InvalidArgument as e:
            WalkoffEvent.CommonWorkflowSignal.send(self, event=WalkoffEvent.TransformError)
            logger.error('Transform {0} has invalid input {1}. Error: {2}. '
                         'Returning unmodified data'.format(self.action_name, original_data_in, str(e)))
        except Exception as e:
            WalkoffEvent.CommonWorkflowSignal.send(self, event=WalkoffEvent.TransformError)
            logger.error(
                'Transform {0} encountered an error: {1}. Returning unmodified data'.format(self.action_name, str(e)))
        return original_data_in
Esempio n. 24
0
    def test_save_workflow_invalid_app_reload_actions(self):
        initial_workflow = flask_server.running_context.controller.get_workflow('test', 'helloWorldWorkflow')
        workflow_name = initial_workflow.name
        initial_actions = [action.read() for action in initial_workflow.actions.values()]
        actions_unmod = deepcopy(initial_actions)
        initial_actions[0]['position']['x'] = 0.0
        initial_actions[0]['position']['y'] = 0.0
        added_action = Action(name='new_id', app_name='HelloWorld', action_name='pause',
                              arguments=[Argument("seconds", value=5)],
                              position={'x': 0, 'y': 0}).read()
        added_action['app_name'] = 'Invalid'

        initial_actions.append(added_action)
        data = {"actions": initial_actions}
        self.post_with_status_check('/api/playbooks/test/workflows/{0}/save'.format(workflow_name),
                                    data=json.dumps(data),
                                    headers=self.headers,
                                    content_type='application/json',
                                    status_code=INVALID_INPUT_ERROR)

        workflow = flask_server.running_context.controller.get_workflow('test', 'helloWorldWorkflow')
        new_actions = [action.read() for action in workflow.actions.values()]
        for action in actions_unmod:
            action.pop('position')
        for action in new_actions:
            action.pop('position')
            action.pop('event')
        self.assertListEqual(actions_unmod, new_actions)
Esempio n. 25
0
 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)
Esempio n. 26
0
    def receive_data(self):
        """Constantly receives data from the ZMQ socket and handles it accordingly.
        """

        while True:
            if self.thread_exit:
                break
            try:
                message_bytes = self.comm_sock.recv()
            except zmq.ZMQError:
                continue

            message = CommunicationPacket()
            message.ParseFromString(message_bytes)

            if message.type == CommunicationPacket.EXIT:
                break

            workflow = self.__get_workflow_by_execution_uid(message.workflow_execution_uid)
            if workflow:
                if message.type == CommunicationPacket.PAUSE:
                    workflow.pause()
                elif message.type == CommunicationPacket.RESUME:
                    workflow.resume()
                elif message.type == CommunicationPacket.TRIGGER:
                    trigger_data = json.loads(message.data_in)
                    if len(message.arguments) > 0:
                        arguments = []
                        for arg in message.arguments:
                            arguments.append(Argument(**(MessageToDict(arg, preserving_proto_field_name=True))))
                        trigger_data["arguments"] = arguments
                    workflow.send_data_to_action(trigger_data)

        return
Esempio n. 27
0
 def test_execute_with_complex_args(self):
     action = Action(app_name='HelloWorld',
                     action_name='Json Sample',
                     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 = AppInstance.create(app_name='HelloWorld',
                                   device_name='device1')
     result = action.execute(instance.instance, {})
     self.assertAlmostEqual(result.result, 11.0)
     self.assertEqual(result.status, 'Success')
     self.assertEqual(action._output, result)
Esempio n. 28
0
    def test_execute_multiple_triggers(self):
        triggers = [
            Condition('HelloWorld',
                      action_name='regMatch',
                      arguments=[Argument('regex', value='aaa')])
        ]
        action = Action(app_name='HelloWorld',
                        action_name='helloWorld',
                        triggers=triggers)
        instance = AppInstance.create(app_name='HelloWorld',
                                      device_name='device1')
        action.send_data_to_trigger({"data_in": {"data": 'a'}})

        trigger_taken = {'triggered': 0}
        trigger_not_taken = {'triggered': 0}

        def callback_is_sent(sender, **kwargs):
            if kwargs['event'] == WalkoffEvent.TriggerActionTaken:
                trigger_taken['triggered'] += 1
            elif kwargs['event'] == WalkoffEvent.TriggerActionNotTaken:
                action.send_data_to_trigger({"data_in": {"data": 'aaa'}})
                trigger_not_taken['triggered'] += 1

        WalkoffEvent.CommonWorkflowSignal.connect(callback_is_sent)

        action.execute(instance.instance, {})
        self.assertEqual(trigger_taken['triggered'], 1)
        self.assertEqual(trigger_not_taken['triggered'], 1)
Esempio n. 29
0
def recreate_workflow(workflow_json):
    """Recreates a workflow from a JSON to prepare for it to be executed.

    Args:
        workflow_json (JSON dict): The input workflow JSON, with some other fields as well.

    Returns:
        (Workflow object, start_arguments): A tuple containing the reconstructed Workflow object, and the arguments to
            the start action.
    """
    uid = workflow_json['uid']
    del workflow_json['uid']
    execution_uid = workflow_json['execution_uid']
    del workflow_json['execution_uid']
    start = workflow_json['start']

    start_arguments = {}
    if 'start_arguments' in workflow_json:
        start_arguments = [Argument(**arg) for arg in workflow_json['start_arguments']]
        workflow_json.pop("start_arguments")

    workflow = Workflow.create(workflow_json)
    workflow.uid = uid
    workflow.set_execution_uid(execution_uid)
    workflow.start = start

    return workflow, start_arguments
Esempio n. 30
0
 def test_execute_action_with_valid_complex_arguments_valid_data(self):
     self.assertTrue(
         Condition('HelloWorld',
                   action_name='mod1_flag3',
                   arguments=[Argument('arg1', value={
                       'a': '1',
                       'b': '5'
                   })]).execute('some_long_string', {}))