def test_error_guessing_dead_features_case_8() -> 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], 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.EXCLUDES) 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.REQUIRES) 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("error-guessing/dead-features/case8/df-case8") run(path, model)
def test_error_guessing_redundancies_case_2() -> 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) relation_1 = Relation(feature_1, [feature_2], 0, 1) relation_2 = Relation(feature_1, [feature_3], 1, 1) relation_3 = Relation(feature_1, [feature_4], 1, 1) feature_1.add_relation(relation_1) feature_1.add_relation(relation_2) feature_1.add_relation(relation_3) node_1 = Node(ASTOperation.REQUIRES) node_1.left = Node("C") 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("D") node_2.right = Node("B") ast_2 = AST(node_2) ctc_2 = Constraint("ctc_2", ast_2) model = FeatureModel(feature_1, [ctc_1, ctc_2]) path = normalize_path( "error-guessing/redundancies/case2/r-case2") run(path, model)
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)
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)
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)
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 parse_ctc(self, element: ElementTree.Element) -> Constraint: origin: Optional[Feature] = None destination: Optional[Feature] = None name = element.attrib.get('name') ctc_type = element.tag.casefold() el_feature = element.attrib.get('feature') if el_feature in self.name_feature: origin = self.name_feature[el_feature] el_exclude = element.attrib.get('excludes') el_require = element.attrib.get('requires') if ctc_type == 'excludes' and el_exclude in self.name_feature: destination = self.name_feature[el_exclude] operator_type = ASTOperation.EXCLUDES elif ctc_type == 'requires' and el_require in self.name_feature: destination = self.name_feature[el_require] operator_type = ASTOperation.REQUIRES if origin is None or destination is None: raise Exception('origin or destination not found') return Constraint( name, AST.create_simple_binary_operation(operator_type, origin.name, destination.name))
def _parse_constraints(self, constraints_node: list[Any]) -> list[Constraint]: constraints: list[Constraint] = [] for i, constraint_node in enumerate(constraints_node, 1): ast_root_node = self._parse_expression(constraint_node) constraints.append(Constraint(f'CTC{i}', AST(ast_root_node))) return constraints
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_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)
def read_expression(self, expression: AFMParser.ExpressionContext, prefix: str) -> None: root_node = self.build_ast_node(expression, prefix) ast = AST(root_node) cst = Constraint(expression.getText(), ast) if self.model is None: raise TypeError('self.model is None, expected FeatureModel type') self.model.ctcs.append(cst)
def add_excludes(self, feature1, feature2) -> None: ctc = Constraint("MEx-" + str(self.ctc_counter[1]), AST(feature1.name + " excludes " + feature2.name)) self.ctc_counter[1] += 1 self.fm.ctcs.append(ctc) updated_products = [product for product in self.products] for product in self.products: if feature1.name in product and feature2.name in product: updated_products.remove(product) self.products = updated_products
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)
def parse_ctc(self, element) -> Constraint: name = element.attrib.get('name') ctc_type = element.tag.casefold() origin = self.name_feature[element.attrib.get('feature')] if ctc_type == 'excludes': destination = self.name_feature[element.attrib.get('excludes')] elif ctc_type == 'requires': destination = self.name_feature[element.attrib.get('requires')] #return Constraint(name,origin,destination,ctc_type) return Constraint(name, AST(f'{origin.name} {ctc_type} {destination.name}'))
def parse_ctc(self, ctc: str) -> Constraint: ctc = (ctc.replace('AND', 'and') .replace('OR', 'or') .replace('NOT', 'not') .replace('IMPLIES', 'implies') .replace('REQUIRES', 'requires') .replace('EXCLUDES', 'excludes')) self.ctc_counter += 1 constraint = Constraint( 'Ctc-' + str(self.ctc_counter), AST(ctc) ) return constraint
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)
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 add_requires(self, feature1, feature2) -> None: ctc = Constraint("MRe-" + str(self.ctc_counter[0]), AST(feature1.name + " requires " + feature2.name)) self.fm.ctcs.append(ctc) self.ctc_counter[0] += 1 cores = [feature.name for feature in self.fm.get_features()] for product in self.products: cores = [feature for feature in product if feature in cores] updated_products = [product for product in self.products] for product in self.products: if feature2.name in cores: break if feature1.name in product and feature2.name not in product: updated_products.remove(product) self.products = updated_products
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)
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)
def test_error_guessing_core_features_case_6() -> 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], 1, 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.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("error-guessing/core-features/case6/cf-case6") run(path, model)
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)