Esempio n. 1
0
def test_everything():
    values = {
        'form': {
            'input': "no",
        },
    }

    tree = Condition().parse(
        '!!3<0 || !(form.input == "0" && ("da" != "de"))'
    )
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse(
        '!!3<0 OR !(form.input == "0" AND ("da" != "de"))'
    )
    assert ConditionTransformer(values).transform(tree) is True
Esempio n. 2
0
def test_condition():
    values = {
        'first_form': {
            'param1': 'value1',
        },
        'second_form': {
            'param1': 'value1',
            'param2': 'value2',
        },
    }

    tree = Condition().parse('first_form.param1 == "value1"')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('second_form.param1 == "value1"')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('second_form.param2 == "value2"')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('first_form.param1 != "nonsense"')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('first_form.param1 == "nonsense"')
    assert ConditionTransformer(values).transform(tree) is False

    tree = Condition().parse('first_form.param1 == second_form.param1')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('first_form.param1 == second_form.param2')
    assert ConditionTransformer(values).transform(tree) is False
Esempio n. 3
0
def test_logic_operators():
    values = {
        'set': {
            'A': True,
            'B': False,
        },
    }

    tree = Condition().parse('set.A || set.B')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('set.A && set.B')
    assert ConditionTransformer(values).transform(tree) is False

    tree = Condition().parse('set.A AND set.B')
    assert ConditionTransformer(values).transform(tree) is False

    tree = Condition().parse('set.A OR set.B')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('set.A AND set.B OR set.A')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('set.B OR set.B OR set.A')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('set.A AND set.B AND set.A')
    assert ConditionTransformer(values).transform(tree) is False
Esempio n. 4
0
def test_no():
    values = {
        'set': {
            'A': True,
            'B': False,
        },
    }

    tree = Condition().parse('!set.A')
    assert ConditionTransformer(values).transform(tree) is False

    tree = Condition().parse('set.A && !set.B')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('!set.A && set.B')
    assert ConditionTransformer(values).transform(tree) is False

    tree = Condition().parse('!!0>-2')
    assert ConditionTransformer(values).transform(tree) is True
Esempio n. 5
0
def test_aritmetic_operators():
    values = {
        'set': {
            'A': -1,
            'B': 1,
            'C': 1.0,
            'D': 1.5,
        },
    }

    tree = Condition().parse('set.A < set.B')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('set.A > set.B')
    assert ConditionTransformer(values).transform(tree) is False

    tree = Condition().parse('set.B < set.C')
    assert ConditionTransformer(values).transform(tree) is False

    tree = Condition().parse('set.B <= set.C')
    assert ConditionTransformer(values).transform(tree) is True

    tree = Condition().parse('set.C < set.D')
    assert ConditionTransformer(values).transform(tree) is True
Esempio n. 6
0
    def work(self, config, state, channel, mongo):
        tree = Condition().parse(self.condition)

        try:
            value = ConditionTransformer(state['values']).transform(tree)
        except ValueError as e:
            raise InconsistentState('Could not evaluate condition: {}'.format(
                str(e)))

        return [
            Form.state_json(self.id, [{
                'name': 'condition',
                'state': 'valid',
                'type': 'bool',
                'value': value,
            }])
        ]
Esempio n. 7
0
def test_list():
    tree = Condition().parse('[]')
    assert ConditionTransformer({}).transform(tree) == []

    tree = Condition().parse('["hello",]')
    assert ConditionTransformer({}).transform(tree) == ['hello']

    tree = Condition().parse('[0]')
    assert ConditionTransformer({}).transform(tree) == [0]

    tree = Condition().parse('[1, 2, 3]')
    assert ConditionTransformer({}).transform(tree) == [1, 2, 3]

    tree = Condition().parse('3 IN [1, 2, 3]')
    assert ConditionTransformer({}).transform(tree) is True

    tree = Condition().parse('4 NOT IN [1, 2, 3]')
    assert ConditionTransformer({}).transform(tree) is True

    tree = Condition().parse('4 IN [1, 2, 3]')
    assert ConditionTransformer({}).transform(tree) is False

    tree = Condition().parse('[1, 2, 3] == [1, 2, 3,]')
    assert ConditionTransformer({}).transform(tree) is True
Esempio n. 8
0
def test_constants():
    tree = Condition().parse('TRUE')
    assert ConditionTransformer({}).transform(tree) is True

    tree = Condition().parse('FALSE')
    assert ConditionTransformer({}).transform(tree) is False
Esempio n. 9
0
def _validate_file(filename, verbose=False):
    ids = []
    data_form = ChainMap()
    passed_nodes = []
    variable_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*$')

    class StreamWrapper:
        def __init__(self, filename):
            self.f = open(filename)
            self.lineno = 0

        def read(self, b):
            self.lineno += 1
            return self.f.readline()

    sw = StreamWrapper(filename)

    def check_id(node):
        id_element = node.getAttribute('id')

        if not id_element:
            raise MalformedProcess('{}:{} All nodes must have an id'.format(
                filename, sw.lineno))

        if not variable_re.match(id_element):
            raise MalformedProcess(
                '{}:{} Id must be a valid variable name'.format(
                    filename,
                    sw.lineno,
                ))

        if id_element not in ids:
            ids.append(id_element)
        else:
            raise MalformedProcess("{}:{} Duplicated id: '{}'".format(
                filename,
                sw.lineno,
                id_element,
            ))

    doc = pulldom.parse(sw)

    for event, node in doc:
        if event == pulldom.START_ELEMENT and node.tagName == 'block':
            data_form.maps.append(dict())

        if event == pulldom.END_ELEMENT and node.tagName == 'block':
            data_form.maps.pop()

        if event != pulldom.START_ELEMENT:
            continue

        if node.tagName == 'condition':
            doc.expandNode(node)

            try:
                tree = Condition().parse(get_text(node))
            except GrammarError:
                raise MalformedProcess(
                    '{}:{} Grammar error in condition'.format(
                        filename,
                        sw.lineno,
                    ))
            except ParseError:
                raise MalformedProcess('{}:{} Parse error in condition'.format(
                    filename,
                    sw.lineno,
                ))
            except LexError:
                raise MalformedProcess('{}:{} Lex error in condition'.format(
                    filename, sw.lineno))
            except KeyError as e:
                raise MalformedProcess(
                    '{}:{} variable does not exist: {}'.format(
                        filename,
                        sw.lineno,
                        str(e),
                    ))

            # validate variables used in condition
            for tree in tree.find_data('ref'):
                reference_form, field_form = list(
                    map(lambda x: x.children[0][:], tree.children))

                try:
                    data_form[reference_form][field_form]
                except KeyError:
                    raise MalformedProcess("{}:{} variable used in condition "
                                           "is not defined '{}'".format(
                                               filename,
                                               sw.lineno,
                                               reference_form + '.' +
                                               field_form,
                                           ))

            continue

        if node.tagName not in NODES:
            continue

        # Duplicate ids
        check_id(node)

        if node.tagName == 'if':
            continue

        # Expand and check this node. <if> nodes are not expanded
        doc.expandNode(node)

        # Check auth-filter params
        params = node.getElementsByTagName("param")

        for param in params:
            if param.getAttribute('type') != 'ref':
                continue

            ref_type, ref = get_text(param).split('#')

            if ref_type == 'form':
                reference_form, field_form = ref.split('.')

                try:
                    data_form[reference_form][field_form]
                except KeyError:
                    raise MalformedProcess(
                        "{}:{} Referenced param does not exist '{}'".format(
                            filename,
                            sw.lineno,
                            reference_form + '.' + field_form,
                        ))
            elif ref_type == 'user':
                if ref not in passed_nodes:
                    raise MalformedProcess(
                        '{}:{} Referenced user is never created: {}'.format(
                            filename,
                            sw.lineno,
                            ref,
                        ))

        # Check dependencies
        deps = node.getElementsByTagName("dep")

        for dep in deps:
            form, field = get_text(dep).split('.')

            try:
                data_form[form][field]
            except KeyError:
                raise MalformedProcess(
                    "{}:{} Referenced dependency does not exist '{}'".format(
                        filename,
                        sw.lineno,
                        form + '.' + field,
                    ))

        # fill forms for later usage
        forms = node.getElementsByTagName('form')

        for form in forms:
            form_id = form.getAttribute('id')

            if form_id and not variable_re.match(form_id):
                raise MalformedProcess(
                    '{}:{} Form ids must be valid variable names'.format(
                        filename,
                        sw.lineno,
                    ))

            form_ref = form.getAttribute('ref')

            if form_ref and not variable_re.match(form_ref):
                raise MalformedProcess(
                    '{}:{} Form refs must be valid variable names'.format(
                        filename,
                        sw.lineno,
                    ))

            inputs = form.getElementsByTagName("input")
            array_input = {}

            for inpt in inputs:
                inpt_name = inpt.getAttribute('name')

                if not variable_re.match(inpt_name):
                    raise MalformedProcess(
                        '{}:{} Field names must match [a-zA-Z0-9_]+'.format(
                            filename,
                            sw.lineno,
                        ))

                array_input[inpt_name] = \
                    inpt.getAttribute('default')

            data_form.maps[-1][form_id] = array_input

        # In case of a request node, add its captured values to `data_form`
        # so they can be recognized as valid values
        captures = node.getElementsByTagName('capture')

        for capture in captures:
            capture_id = capture.getAttribute('id')

            if capture_id and not variable_re.match(capture_id):
                raise MalformedProcess(
                    '{}:{} Capture ids must be valid variable names'.format(
                        filename,
                        sw.lineno,
                    ))

            capture_inputs = capture.getElementsByTagName("value")
            array_input = {}

            for inpt in capture_inputs:
                inpt_name = inpt.getAttribute('name')

                if not variable_re.match(inpt_name):
                    raise MalformedProcess(
                        '{}:{} names must be valid variable names'.format(
                            filename,
                            sw.lineno,
                        ))

                array_input[inpt_name] = '1'

            data_form.maps[-1][capture_id] = array_input

        # add this node to the list of revised nodes
        has_auth_filter = len(node.getElementsByTagName('auth-filter')) > 0

        if has_auth_filter:
            passed_nodes.append(node.getAttribute('id'))

    if verbose:
        print('{} seems correct'.format(filename))