Beispiel #1
0
 def _parse_expression(self, expression: Any) -> Node:
     if isinstance(expression, UVLParser.TermContext):
         return Node(expression.WORD().getText())
     if isinstance(expression, UVLParser.ParenthesisExpContext):
         return self._parse_expression(expression.getChild(1))
     if isinstance(expression, UVLParser.NotExpContext):
         return Node(ASTOperation.NOT,
                     self._parse_expression(expression.getChild(1)))
     # Binary operation type:
     left = self._parse_expression(expression.getChild(0))
     right = self._parse_expression(expression.getChild(2))
     if isinstance(expression, UVLParser.AndExpContext):
         return Node(ASTOperation.AND, left, right)
     if isinstance(expression, UVLParser.OrExpContext):
         return Node(ASTOperation.OR, left, right)
     if isinstance(expression, UVLParser.LogicalExpContext):
         logic_op_type = {
             UVLParser.EquivExpContext: ASTOperation.EQUIVALENCE,
             UVLParser.ImpliesExpContext: ASTOperation.IMPLIES,
             UVLParser.RequiresExpContext: ASTOperation.REQUIRES,
             UVLParser.ExcludesExpContext: ASTOperation.EXCLUDES
         }
         logic_op = logic_op_type.get(type(expression.logical_operator()))
         if logic_op is None:
             raise Exception(
                 f'Constraint expression not supported by UVL reader: '
                 f'{expression.logical_operator().getText()}')
         return Node(logic_op, left, right)
     raise Exception(f'Constraint expression not supported by UVL reader: '
                     f'{expression.getText()}')
Beispiel #2
0
    def build_ast_node(self, expression: AFMParser.ExpressionContext,
                       prefix: str) -> Node:
        if isinstance(expression, AFMParser.AtomContext):
            if expression.variable() is not None:
                var_name = prefix + expression.variable().getText()
            if expression.number() is not None:
                var_name = expression.number().getText()
            result = Node(var_name)

        binary_operation_types = [
            AFMParser.LogicalExpContext, AFMParser.OrExpContext,
            AFMParser.AndExpContext, AFMParser.RelationalExpContext,
            AFMParser.ArithmeticExpContext
        ]
        binary_operations_map = {
            'REQUIRES': ASTOperation.REQUIRES,
            'EXCLUDES': ASTOperation.EXCLUDES,
            'OR': ASTOperation.OR,
            'AND': ASTOperation.AND,
            'IFF': ASTOperation.EQUIVALENCE
        }

        if expression.__class__ in binary_operation_types:
            binary_operation = expression.getChild(1).getText()
            ast_operation = binary_operations_map.get(binary_operation)

            # TODO: provide support for arithmetic and relational operations.
            if ast_operation is None:
                raise Exception(
                    f'Constraints not supported in AFM Reader: {binary_operation}.'
                )
            result = Node(ast_operation)
            result.left = self.build_ast_node(expression.expression()[0],
                                              prefix)
            result.right = self.build_ast_node(expression.expression()[1],
                                               prefix)

        if isinstance(expression, AFMParser.NotExpContext):
            result = Node(ASTOperation.NOT)
            result.right = self.build_ast_node(expression.expression(), prefix)

        if isinstance(expression, AFMParser.ParenthesisExpContext):
            result = self.build_ast_node(expression.expression(), prefix)

        if result is None:
            raise Exception(
                f'Constraint not support in AFM Reader: {expression}, {prefix}'
            )

        return result
def test_refinement_df_alternative_excludes() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)
    feature_4 = Feature("D", None, None, True)
    feature_5 = Feature("E", None, None, False)

    relation_1 = Relation(feature_1, [feature_2], 1, 1)
    relation_2 = Relation(feature_1, [feature_3], 0, 1)

    feature_1.add_relation(relation_1)
    feature_1.add_relation(relation_2)

    relation_3 = Relation(feature_3, [feature_4, feature_5], 1, 1)

    feature_3.add_relation(relation_3)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("B")
    node_1.right = Node("D")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    model = FeatureModel(feature_1, [ctc_1])
    path = normalize_path(
        "refinement/df-alternative-excludes/df-alternative-excludes")
    run(path, model)
def test_error_guessing_dead_features_case_1() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)
    feature_4 = Feature("D", None, None, False)
    feature_5 = Feature("E", None, None, True)

    relation_1 = Relation(feature_1, [feature_2], 1, 1)
    relation_2 = Relation(feature_1, [feature_3], 1, 1)

    feature_1.add_relation(relation_1)
    feature_1.add_relation(relation_2)

    relation_3 = Relation(feature_3, [feature_4, feature_5], 1, 1)

    feature_3.add_relation(relation_3)

    node_1 = Node(ASTOperation.EXCLUDES)
    node_1.left = Node("D")
    node_1.right = Node("B")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    model = FeatureModel(feature_1, [ctc_1])
    path = normalize_path("error-guessing/dead-features/case1/df-case1")
    run(path, model)
def test_error_guessing_false_optional_features_case_3() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, False)
    feature_4 = Feature("D", None, None, False)
    feature_5 = Feature("E", None, None, True)

    relation_1 = Relation(feature_1, [feature_2], 1, 1)
    relation_2 = Relation(feature_1, [feature_3], 0, 1)

    feature_1.add_relation(relation_1)
    feature_1.add_relation(relation_2)

    relation_3 = Relation(feature_3, [feature_4, feature_5], 1, 2)

    feature_3.add_relation(relation_3)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("B")
    node_1.right = Node("D")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    model = FeatureModel(feature_1, [ctc_1])
    path = normalize_path(
        "error-guessing/false-optional-features/case3/fof-case3")
    run(path, model)
Beispiel #6
0
def _get_ctc_info(ast_node: Node) -> dict[str, Any]:
    ctc_info: dict[str, Any] = {}
    if ast_node.is_term():
        ctc_info['type'] = 'FeatureTerm'
        ctc_info['operands'] = [ast_node.data]
    else:
        ctc_info['type'] = GlencoeWriter.CTC_TYPES[ast_node.data]
        operands = []
        left = _get_ctc_info(ast_node.left)
        operands.append(left)
        if ast_node.right is not None:
            right = _get_ctc_info(ast_node.right)
            operands.append(right)
        ctc_info['operands'] = operands
    return ctc_info
Beispiel #7
0
    def recursive_constraint_read(self, node: Node) -> str:

        data = node.data
        if node.is_op():
            data = data.value.upper()

        if node.left and node.right:
            result = self.recursive_constraint_read(
                node.left) + data + self.recursive_constraint_read(node.right)
        elif not node.left and node.right:
            result = data + self.recursive_constraint_read(node.right)
        elif node.left and not node.right:
            result = self.recursive_constraint_read(node.left) + node.data
        else:
            result = " " + data + " "

        return result
def test_error_guessing_core_features_case_2() -> None:
    feature_1 = Feature("A", None, None, False)
    feature_2 = Feature("B", None, None, False)

    relation_1 = Relation(feature_1, [feature_2], 0, 1)

    feature_1.add_relation(relation_1)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("A")
    node_1.right = Node("B")
    ast_1 = AST(node_1)

    ctc_1 = Constraint("ctc_1", ast_1)

    model = FeatureModel(feature_1, [ctc_1])
    path = normalize_path("error-guessing/core-features/case2/cf-case2")
    run(path, model)
def test_error_guessing_dead_features_case_6() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, False)
    feature_3 = Feature("C", None, None, True)

    relation_1 = Relation(feature_1, [feature_2, feature_3], 1, 1)

    feature_1.add_relation(relation_1)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("B")
    node_1.right = Node("C")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    model = FeatureModel(feature_1, [ctc_1])
    path = normalize_path("error-guessing/dead-features/case6/df-case6")
    run(path, model)
Beispiel #10
0
def test_relationships_alternative_requires() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)

    relation_1 = Relation(feature_1, [feature_2, feature_3], 1, 1)

    feature_1.add_relation(relation_1)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("B")
    node_1.right = Node("C")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    model = FeatureModel(feature_1, [ctc_1])
    path = normalize_path(
        "relationships/alternative-requires/alternative-requires")
    run(path, model)
Beispiel #11
0
def test_relationships_or_excludes() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)

    relation_1 = Relation(feature_1, [feature_2, feature_3], 1, 2)

    feature_1.add_relation(relation_1)

    node_1 = Node(ASTOperation.EXCLUDES)
    node_1.left = Node("B")
    node_1.right = Node("C")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    model = FeatureModel(feature_1, [ctc_1])
    path = normalize_path(
        "relationships/or-excludes/or-excludes")
    run(path, model)
Beispiel #12
0
def test_error_guessing_redundancies_case_1() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)

    relation_1 = Relation(feature_1, [feature_2], 0, 1)
    relation_2 = Relation(feature_1, [feature_3], 1, 1)

    feature_1.add_relation(relation_1)
    feature_1.add_relation(relation_2)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("B")
    node_1.right = Node("C")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    model = FeatureModel(feature_1, [ctc_1])
    path = normalize_path(
        "error-guessing/redundancies/case1/r-case1")
    run(path, model)
Beispiel #13
0
def test_relationships_allrelationships() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)
    feature_4 = Feature("D", None, None, True)
    feature_5 = Feature("E", None, None, True)
    feature_6 = Feature("F", None, None, True)
    feature_7 = Feature("G", None, None, True)

    relation_1 = Relation(feature_1, [feature_2], 1, 1)
    relation_2 = Relation(feature_1, [feature_3], 0, 1)

    feature_1.add_relation(relation_1)
    feature_1.add_relation(relation_2)

    relation_3 = Relation(feature_2, [feature_4, feature_5], 1, 1)

    feature_2.add_relation(relation_3)

    relation_4 = Relation(feature_3, [feature_6, feature_7], 1, 2)

    feature_3.add_relation(relation_4)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("E")
    node_1.right = Node("F")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    node_2 = Node(ASTOperation.EXCLUDES)
    node_2.left = Node("D")
    node_2.right = Node("G")
    ast_2 = AST(node_2)
    ctc_2 = Constraint("ctc_2", ast_2)

    model = FeatureModel(feature_1, [ctc_1, ctc_2])
    path = normalize_path(
        "relationships/allrelationships/allrelationships")
    run(path, model)
Beispiel #14
0
def test_refinement_or_no_alternative() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)
    feature_4 = Feature("D", None, None, True)
    feature_5 = Feature("E", None, None, False)

    relation_1 = Relation(feature_1, [feature_2], 1, 1)
    relation_2 = Relation(feature_1, [feature_5], 1, 1)

    feature_1.add_relation(relation_1)
    feature_1.add_relation(relation_2)

    relation_3 = Relation(feature_2, [feature_3, feature_4], 1, 2)

    feature_2.add_relation(relation_3)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("E")
    node_1.right = Node("D")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    node_2 = Node(ASTOperation.REQUIRES)
    node_2.left = Node("E")
    node_2.right = Node("C")
    ast_2 = AST(node_2)
    ctc_2 = Constraint("ctc_2", ast_2)

    model = FeatureModel(feature_1, [ctc_1, ctc_2])
    path = normalize_path(
        "refinement/or-noAlternative/or-noAlternative")
    run(path, model)
Beispiel #15
0
    def _parse_rule(self, rule: Element) -> AST:
        """Return the representation of the constraint (rule) in the AST syntax."""
        if rule.tag == FeatureIDEReader.TAG_VAR:
            node = Node(rule.text)
        elif rule.tag == FeatureIDEReader.TAG_NOT:
            node = Node(ASTOperation.NOT)
            node.left = self._parse_rule(rule[0]).root
        elif rule.tag == FeatureIDEReader.TAG_IMP:
            node = Node(ASTOperation.IMPLIES)
            node.left = self._parse_rule(rule[0]).root
            node.right = self._parse_rule(rule[1]).root
        elif rule.tag == FeatureIDEReader.TAG_EQ:
            node = Node(ASTOperation.AND)
            node.left = Node(ASTOperation.IMPLIES)
            node.left.left = self._parse_rule(rule[0]).root
            node.left.right = self._parse_rule(rule[1]).root
            node.right = Node(ASTOperation.IMPLIES)
            node.right.left = self._parse_rule(rule[1]).root
            node.right.right = self._parse_rule(rule[0]).root

        elif rule.tag == FeatureIDEReader.TAG_DISJ:
            if len(rule) > 1:
                node = Node(ASTOperation.OR)
                node.left = self._parse_rule(rule[0]).root
                node.right = self._parse_rule(rule[1]).root

            else:
                node = self._parse_rule(rule[0]).root

        elif rule.tag == FeatureIDEReader.TAG_CONJ:
            if len(rule) > 1:
                node = Node(ASTOperation.AND)
                node.left = self._parse_rule(rule[0]).root
                node.right = self._parse_rule(rule[1]).root
            else:
                node = self._parse_rule(rule[0]).root
        return AST(node)
Beispiel #16
0
def test_refinement_alternative_odd_children() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)
    feature_4 = Feature("D", None, None, True)
    feature_5 = Feature("E", None, None, True)
    feature_6 = Feature("F", None, None, True)
    feature_7 = Feature("G", None, None, True)
    feature_8 = Feature("H", None, None, True)

    relation_1 = Relation(feature_1, [feature_2], 1, 1)
    relation_2 = Relation(feature_1, [feature_8], 1, 1)

    feature_1.add_relation(relation_1)
    feature_1.add_relation(relation_2)

    relation_3 = Relation(
        feature_2, [feature_3, feature_4, feature_5, feature_6, feature_7], 1, 1)

    feature_2.add_relation(relation_3)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("H")
    node_1.right = Node("G")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    node_2 = Node(ASTOperation.REQUIRES)
    node_2.left = Node("H")
    node_2.right = Node("E")
    ast_2 = AST(node_2)
    ctc_2 = Constraint("ctc_2", ast_2)

    model = FeatureModel(feature_1, [ctc_1, ctc_2])
    path = normalize_path(
        "refinement/alternative-oddChildren/alternative-oddChildren")
    run(path, model)
Beispiel #17
0
def test_refinement_alternative_no_parent_last_child() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)
    feature_4 = Feature("D", None, None, True)
    feature_5 = Feature("E", None, None, True)

    relation_1 = Relation(feature_1, [feature_2], 0, 1)
    relation_2 = Relation(feature_1, [feature_5], 1, 1)

    feature_1.add_relation(relation_1)
    feature_1.add_relation(relation_2)

    relation_3 = Relation(feature_2, [feature_3, feature_4], 1, 1)

    feature_2.add_relation(relation_3)

    node_1 = Node(ASTOperation.EXCLUDES)
    node_1.left = Node("E")
    node_1.right = Node("B")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    node_2 = Node(ASTOperation.REQUIRES)
    node_2.left = Node("E")
    node_2.right = Node("D")
    ast_2 = AST(node_2)
    ctc_2 = Constraint("ctc_2", ast_2)

    model = FeatureModel(feature_1, [ctc_1, ctc_2])
    path = normalize_path(
        "refinement/alternative-noParentLastChild/alternative-noParentLastChild")
    run(path, model)
Beispiel #18
0
def test_relationships_requires_excludes() -> None:
    feature_1 = Feature("A", None, None, True)
    feature_2 = Feature("B", None, None, True)
    feature_3 = Feature("C", None, None, True)

    relation_1 = Relation(feature_1, [feature_2], 0, 1)
    relation_2 = Relation(feature_1, [feature_3], 0, 1)

    feature_1.add_relation(relation_1)
    feature_1.add_relation(relation_2)

    node_1 = Node(ASTOperation.REQUIRES)
    node_1.left = Node("B")
    node_1.right = Node("C")
    ast_1 = AST(node_1)
    ctc_1 = Constraint("ctc_1", ast_1)

    node_2 = Node(ASTOperation.EXCLUDES)
    node_2.left = Node("B")
    node_2.right = Node("C")
    ast_2 = AST(node_2)
    ctc_2 = Constraint("ctc_1", ast_2)

    model = FeatureModel(feature_1, [ctc_1, ctc_2])
    path = normalize_path(
        "relationships/requires-excludes/requires-excludes")
    run(path, model)