def test_accumulated_risk_with_error(self):
        workflow = Workflow(name='workflow')
        workflow._execution_uid = 'some_uid'
        step1 = Step(name="step_one", app='HelloWorld', action='Buggy', risk=1)
        step2 = Step(name="step_two", app='HelloWorld', action='Buggy', risk=2)
        step3 = Step(name="step_three",
                     app='HelloWorld',
                     action='Buggy',
                     risk=3.5)
        workflow.steps = {
            'step_one': step1,
            'step_two': step2,
            'step_three': step3
        }
        workflow._total_risk = 6.5

        instance = AppInstance.create(app_name='HelloWorld',
                                      device_name='test_device_name')

        workflow._Workflow__execute_step(workflow.steps["step_one"], instance)
        self.assertAlmostEqual(workflow.accumulated_risk, 1.0 / 6.5)
        workflow._Workflow__execute_step(workflow.steps["step_two"], instance)
        self.assertAlmostEqual(workflow.accumulated_risk,
                               (1.0 / 6.5) + (2.0 / 6.5))
        workflow._Workflow__execute_step(workflow.steps["step_three"],
                                         instance)
        self.assertAlmostEqual(workflow.accumulated_risk, 1.0)
예제 #2
0
    def test_execute_with_accumulator_missing_step_callbacks(self):
        step = Step(app='HelloWorld',
                    action='Add Three',
                    inputs={
                        'num1': '@1',
                        'num2': '@step2',
                        'num3': '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}

        @callbacks.data_sent.connect
        def callback_is_sent(sender, **kwargs):
            if isinstance(sender, Step):
                self.assertIs(sender, step)
                self.assertIn('callback_name', kwargs)
                self.assertIn(kwargs['callback_name'],
                              ('Step Started', 'Step Input Invalid'))
                self.assertIn('object_type', kwargs)
                self.assertEqual(kwargs['object_type'], 'Step')
                if kwargs['callback_name'] == 'Step Started':
                    result['started_triggered'] = True
                else:
                    result['result_triggered'] = True

        with self.assertRaises(InvalidInput):
            step.execute(instance.instance, accumulator)

        self.assertTrue(result['started_triggered'])
        self.assertTrue(result['result_triggered'])
예제 #3
0
 def test_execute_with_complex_inputs(self):
     step = Step(app='HelloWorld',
                 action='Json Sample',
                 inputs={
                     'json_in': {
                         '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 = step.execute(instance.instance, {})
     self.assertAlmostEqual(result.result, 11.0)
     self.assertEqual(result.status, 'Success')
     self.assertEqual(step._output, result)
예제 #4
0
 def test_execute_action_which_raises_exception(self):
     from tests.testapps.HelloWorld.exceptions import CustomException
     step = Step(app='HelloWorld', action='Buggy')
     instance = AppInstance.create(app_name='HelloWorld',
                                   device_name='device1')
     with self.assertRaises(CustomException):
         step.execute(instance.instance, {})
예제 #5
0
 def test_execute_no_args(self):
     step = Step(app='HelloWorld', action='helloWorld')
     instance = AppInstance.create(app_name='HelloWorld',
                                   device_name='device1')
     self.assertEqual(step.execute(instance.instance, {}),
                      ActionResult({'message': 'HELLO WORLD'}, 'Success'))
     self.assertEqual(step._output,
                      ActionResult({'message': 'HELLO WORLD'}, 'Success'))
예제 #6
0
 def test_execute_global_action(self):
     step = Step(app='HelloWorld',
                 action='global2',
                 inputs={'arg1': 'something'})
     instance = AppInstance.create(app_name='HelloWorld', device_name='')
     result = step.execute(instance.instance, {})
     self.assertAlmostEqual(result.result, 'something')
     self.assertEqual(result.status, 'Success')
     self.assertEqual(step._output, result)
예제 #7
0
 def test_set_input_invalid_format(self):
     step = Step(app='HelloWorld',
                 action='Add Three',
                 inputs={
                     'num1': '-5.6',
                     'num2': '4.3',
                     'num3': '10.2'
                 })
     with self.assertRaises(InvalidInput):
         step.set_input({'num1': '-5.62', 'num2': '5', 'num3': 'invalid'})
예제 #8
0
 def test_execute_with_accumulator_missing_step(self):
     step = Step(app='HelloWorld',
                 action='Add Three',
                 inputs={
                     'num1': '@1',
                     'num2': '@step2',
                     'num3': '10.2'
                 })
     accumulator = {'1': '-5.6', 'missing': '4.3', '3': '45'}
     instance = AppInstance.create(app_name='HelloWorld',
                                   device_name='device1')
     with self.assertRaises(InvalidInput):
         step.execute(instance.instance, accumulator)
예제 #9
0
 def test_execute_with_args(self):
     step = Step(app='HelloWorld',
                 action='Add Three',
                 inputs={
                     'num1': '-5.6',
                     'num2': '4.3',
                     'num3': '10.2'
                 })
     instance = AppInstance.create(app_name='HelloWorld',
                                   device_name='device1')
     result = step.execute(instance.instance, {})
     self.assertAlmostEqual(result.result, 8.9)
     self.assertEqual(result.status, 'Success')
     self.assertEqual(step._output, result)
예제 #10
0
 def test_set_input_valid(self):
     step = Step(app='HelloWorld',
                 action='Add Three',
                 inputs={
                     'num1': '-5.6',
                     'num2': '4.3',
                     'num3': '10.2'
                 })
     step.set_input({'num1': '-5.62', 'num2': '5', 'num3': '42.42'})
     self.assertDictEqual(step.inputs, {
         'num1': -5.62,
         'num2': 5.,
         'num3': 42.42
     })
예제 #11
0
 def test_execute_with_accumulator_with_conversion(self):
     step = Step(app='HelloWorld',
                 action='Add Three',
                 inputs={
                     'num1': '@1',
                     'num2': '@step2',
                     'num3': '10.2'
                 })
     accumulator = {'1': '-5.6', 'step2': '4.3'}
     instance = AppInstance.create(app_name='HelloWorld',
                                   device_name='device1')
     result = step.execute(instance.instance, accumulator)
     self.assertAlmostEqual(result.result, 8.9)
     self.assertEqual(result.status, 'Success')
     self.assertEqual(step._output, result)
예제 #12
0
    def test_save_workflow_new_start_step(self):
        initial_workflow = flask_server.running_context.controller.get_workflow(
            'test', 'helloWorldWorkflow')
        workflow_name = initial_workflow.name
        initial_steps = [
            step.read() for step in initial_workflow.steps.values()
        ]
        initial_steps[0]['position']['x'] = 0.0
        initial_steps[0]['position']['y'] = 0.0
        added_step = Step(name='new_id',
                          app='HelloWorld',
                          action='pause',
                          inputs={
                              'seconds': 5
                          },
                          position={
                              'x': 0,
                              'y': 0
                          }).read()

        initial_steps.append(added_step)
        data = {"steps": initial_steps, "start": "new_start"}
        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')

        resulting_workflow = flask_server.running_context.controller.get_workflow(
            'test', workflow_name)
        self.assertEqual(resulting_workflow.start, "new_start")
예제 #13
0
    def test_save_workflow_invalid_input_format(self):
        initial_workflow = flask_server.running_context.controller.get_workflow(
            'test', 'helloWorldWorkflow')
        workflow_name = initial_workflow.name
        initial_steps = [
            step.read() for step in initial_workflow.steps.values()
        ]
        initial_steps[0]['position']['x'] = 0.0
        initial_steps[0]['position']['y'] = 0.0
        added_step = Step(name='new_id',
                          app='HelloWorld',
                          action='pause',
                          inputs={
                              'seconds': 5
                          },
                          position={
                              'x': 0,
                              'y': 0
                          }).read()
        added_step['inputs'][0]['value'] = 'aaaa'

        initial_steps.append(added_step)
        data = {"steps": initial_steps}
        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)
예제 #14
0
 def test_init_with_risk(self):
     step = Step('HelloWorld', 'helloWorld', risk=42)
     self.__compare_init(step,
                         '',
                         'helloWorld',
                         'HelloWorld',
                         '', {},
                         risk=42)
예제 #15
0
 def test_init_with_uid(self):
     step = Step('HelloWorld', 'helloWorld', uid='test')
     self.__compare_init(step,
                         '',
                         'helloWorld',
                         'HelloWorld',
                         '', {},
                         uid='test')
예제 #16
0
 def test_init_with_next_steps(self):
     next_steps = [NextStep(name=i) for i in range(3)]
     step = Step('HelloWorld', 'helloWorld', next_steps=next_steps)
     self.__compare_init(step,
                         '',
                         'helloWorld',
                         'HelloWorld',
                         '', {},
                         next_steps=list(range(3)))
예제 #17
0
 def test_init_with_position(self):
     step = Step('HelloWorld', 'helloWorld', position={'x': 13, 'y': 42})
     self.__compare_init(step,
                         '',
                         'helloWorld',
                         'HelloWorld',
                         '', {},
                         position={
                             'x': 13,
                             'y': 42
                         })
예제 #18
0
 def test_init_with_flags(self):
     triggers = [
         Flag(action='regMatch', args={'regex': '(.*)'}),
         Flag(action='regMatch', args={'regex': 'a'})
     ]
     step = Step('HelloWorld', 'helloWorld', triggers=triggers)
     self.__compare_init(step,
                         '',
                         'helloWorld',
                         'HelloWorld',
                         '', {},
                         triggers=['regMatch', 'regMatch'])
예제 #19
0
 def test_init_templated(self):
     step = Step('HelloWorld',
                 'helloWorld',
                 templated=True,
                 raw_representation={'a': 42})
     self.__compare_init(step,
                         '',
                         'helloWorld',
                         'HelloWorld',
                         '', {},
                         templated=True,
                         raw_representation={'a': 42})
예제 #20
0
 def test_execute_generates_uid(self):
     step = Step(app='HelloWorld', action='helloWorld')
     original_execution_uid = step.get_execution_uid()
     instance = AppInstance.create(app_name='HelloWorld',
                                   device_name='device1')
     step.execute(instance.instance, {})
     self.assertNotEqual(step.get_execution_uid(), original_execution_uid)
예제 #21
0
    def test_get_next_step(self):
        flag = Flag(action='regMatch', args={'regex': 'aaa'})
        next_step = NextStep(name='next', flags=[flag], status='Success')
        step = Step('HelloWorld', 'helloWorld', next_steps=[next_step])
        step._output = ActionResult(result='aaa', status='Success')

        result = {'triggered': False}

        @callbacks.data_sent.connect
        def validate_sent_data(sender, **kwargs):
            if isinstance(sender, Step):
                self.assertIs(sender, step)
                self.assertIn('callback_name', kwargs)
                self.assertEqual(kwargs['callback_name'],
                                 'Conditionals Executed')
                self.assertIn('object_type', kwargs)
                self.assertEqual(kwargs['object_type'], 'Step')
                result['triggered'] = True

        self.assertEqual(step.get_next_step({}), 'next')
        self.assertEqual(step._next_up, 'next')
        self.assertTrue(result['triggered'])
예제 #22
0
    def test_execute_action_which_raises_exception_sends_callbacks(self):
        from tests.testapps.HelloWorld.exceptions import CustomException
        step = Step(app='HelloWorld', action='Buggy')
        instance = AppInstance.create(app_name='HelloWorld',
                                      device_name='device1')

        result = {'started_triggered': False}

        @callbacks.data_sent.connect
        def callback_is_sent(sender, **kwargs):
            if isinstance(sender, Step):
                self.assertIs(sender, step)
                self.assertIn('callback_name', kwargs)
                self.assertEqual(kwargs['callback_name'], 'Step Started')
                self.assertIn('object_type', kwargs)
                self.assertEqual(kwargs['object_type'], 'Step')
                result['started_triggered'] = True

        with self.assertRaises(CustomException):
            step.execute(instance.instance, {})

        self.assertTrue(result['started_triggered'])
예제 #23
0
 def test_init_with_widgets(self):
     widget_tuples = [('aaa', 'bbb'), ('ccc', 'ddd'), ('eee', 'fff')]
     widgets = [{
         'app': widget[0],
         'name': widget[1]
     } for widget in widget_tuples]
     step = Step('HelloWorld', 'helloWorld', widgets=widgets)
     self.__compare_init(step,
                         '',
                         'helloWorld',
                         'HelloWorld',
                         '', {},
                         widgets=widget_tuples)
예제 #24
0
    def test_execute_event(self):
        step = Step(app='HelloWorld',
                    action='Sample Event',
                    inputs={'arg1': 1})
        instance = AppInstance.create(app_name='HelloWorld',
                                      device_name='device1')

        import time
        from tests.testapps.HelloWorld.events import event1
        import threading

        def sender():
            time.sleep(0.1)
            event1.trigger(3)

        thread = threading.Thread(target=sender)
        start = time.time()
        thread.start()
        result = step.execute(instance.instance, {})
        end = time.time()
        thread.join()
        self.assertEqual(result, ActionResult(4, 'Success'))
        self.assertGreater((end - start), 0.1)
예제 #25
0
    def test_execute_sends_callbacks(self):
        step = Step(app='HelloWorld',
                    action='Add Three',
                    inputs={
                        'num1': '-5.6',
                        'num2': '4.3',
                        'num3': '10.2'
                    })
        instance = AppInstance.create(app_name='HelloWorld',
                                      device_name='device1')

        result = {'started_triggered': False, 'result_triggered': False}

        @callbacks.data_sent.connect
        def callback_is_sent(sender, **kwargs):
            if isinstance(sender, Step):
                self.assertIs(sender, step)
                self.assertIn('callback_name', kwargs)
                self.assertIn(kwargs['callback_name'],
                              ('Step Started', 'Function Execution Success'))
                self.assertIn('object_type', kwargs)
                self.assertEqual(kwargs['object_type'], 'Step')
                if kwargs['callback_name'] == 'Step Started':
                    result['started_triggered'] = True
                else:
                    self.assertIn('data', kwargs)
                    data = json.loads(kwargs['data'])
                    self.assertIn('result', data)
                    data = data['result']
                    self.assertEqual(data['status'], 'Success')
                    self.assertAlmostEqual(data['result'], 8.9)
                    result['result_triggered'] = True

        step.execute(instance.instance, {})
        self.assertTrue(result['started_triggered'])
        self.assertTrue(result['result_triggered'])
예제 #26
0
 def create_step(self, name='', action='', app='', device='', arg_input=None, next_steps=None, risk=0):
     """Creates a new Step object and adds it to the Workflow's list of Steps.
     
     Args:
         name (str, optional): The name of the Step object. Defaults to an empty string.
         action (str, optional): The name of the action associated with a Step. Defaults to an empty string.
         app (str, optional): The name of the app associated with the Step. Defaults to an empty string.
         device (str, optional): The name of the device associated with the app associated with the Step. Defaults
             to an empty string.
         arg_input (dict, optional): A dictionary of Argument objects that are input to the step execution. Defaults
             to None.
         next_steps (list[NextStep], optional): A list of NextStep objects for the Step object. Defaults to None.
         risk (int, optional): The risk associated with the Step. Defaults to 0.
         
     """
     arg_input = arg_input if arg_input is not None else {}
     next_steps = next_steps if next_steps is not None else []
     self.steps[name] = Step(name=name, action=action, app=app, device=device, inputs=arg_input,
                             next_steps=next_steps, risk=risk)
     self._total_risk += risk
     logger.info('Step added to workflow {0}. Step: {1}'.format(self.name, self.steps[name].read()))
예제 #27
0
    def test_execute_with_triggers(self):
        triggers = [Flag(action='regMatch', args={'regex': 'aaa'})]
        step = Step(app='HelloWorld', action='helloWorld', triggers=triggers)
        instance = AppInstance.create(app_name='HelloWorld',
                                      device_name='device1')
        step.send_data_to_trigger({"data_in": {"data": 'aaa'}})

        result = {'triggered': False}

        @callbacks.data_sent.connect
        def callback_is_sent(sender, **kwargs):
            if kwargs['callback_name'] == "Trigger Step Taken":
                result['triggered'] = True

        step.execute(instance.instance, {})
        self.assertTrue(result['triggered'])
예제 #28
0
    def update_from_json(self, json_in):
        """Reconstruct a Workflow object based on JSON data.

           Args:
               json_in (JSON dict): The JSON data to be parsed and reconstructed into a Workflow object.
        """

        # backup_steps = deepcopy(self.steps)
        backup_steps = self.strip_async_result(with_deepcopy=True)
        self.steps = {}
        if 'name' in json_in:
            self.name = json_in['name']
        uid = json_in['uid'] if 'uid' in json_in else uuid.uuid4().hex
        try:
            if 'start' in json_in and json_in['start']:
                self.start = json_in['start']
            self.steps = {}
            self.uid = uid
            for step_json in json_in['steps']:
                step = Step.create(step_json)
                self.steps[step_json['name']] = step
        except (UnknownApp, UnknownAppAction, InvalidInput):
            self.reload_async_result(backup_steps, with_deepcopy=True)
            raise
예제 #29
0
    def test_execute_multiple_triggers(self):
        triggers = [Flag(action='regMatch', args={'regex': 'aaa'})]
        step = Step(app='HelloWorld', action='helloWorld', triggers=triggers)
        instance = AppInstance.create(app_name='HelloWorld',
                                      device_name='device1')
        step.send_data_to_trigger({"data_in": {"data": 'a'}})

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

        @callbacks.data_sent.connect
        def callback_is_sent(sender, **kwargs):
            if kwargs['callback_name'] == "Trigger Step Taken":
                trigger_taken['triggered'] += 1
            elif kwargs['callback_name'] == "Trigger Step Not Taken":
                step.send_data_to_trigger({"data_in": {"data": 'aaa'}})
                trigger_not_taken['triggered'] += 1

        step.execute(instance.instance, {})
        self.assertEqual(trigger_taken['triggered'], 1)
        self.assertEqual(trigger_not_taken['triggered'], 1)
예제 #30
0
 def test_init_with_name(self):
     step = Step('HelloWorld', 'helloWorld', name='test')
     self.__compare_init(step, 'test', 'helloWorld', 'HelloWorld', '', {})