def test_second_order_mutation(self): mutator = controller.HighOrderMutator( operators=[operators.ArithmeticOperatorReplacement, operators.AssignmentOperatorReplacement], ) target_ast = utils.create_ast('x += y + z') for number, (mutations, mutant) in enumerate(mutator.mutate(target_ast)): self.assertEqual(number, 0) self.assertEqual('x -= y - z', codegen.to_source(mutant)) self.assertEqual(len(mutations), 2) self.assertEqual(codegen.to_source(target_ast), 'x += y + z')
def test_second_order_mutation(self): mutator = controller.HighOrderMutator( operators=[operators.ArithmeticOperatorReplacement, operators.AssignmentOperatorReplacement], ) target_ast = utils.create_ast('x += y + z') for number, (mutations, mutant) in enumerate(mutator.mutate(target_ast)): if number == 0: self.assertEqual('x -= y - z', codegen.to_source(mutant)) self.assertEqual(len(mutations), 2) else: self.fail() self.assertEqual(codegen.to_source(target_ast), 'x += y + z')
def test_second_order_mutation_with_multiple_visitors(self): mutator = controller.HighOrderMutator( operators=[operators.ConstantReplacement], ) target_ast = utils.create_ast('x = "test"') number = None for number, (mutations, mutant) in enumerate(mutator.mutate(target_ast)): if number == 0: self.assertEqual("x = 'mutpy'", codegen.to_source(mutant)) self.assertEqual(len(mutations), 1) elif number == 1: self.assertEqual("x = ''", codegen.to_source(mutant)) self.assertEqual(len(mutations), 1) self.assertEqual(number, 1) self.assertEqual(codegen.to_source(target_ast), "x = 'test'")
def test_second_order_mutation_with_same_node_as_target(self): mutator = controller.HighOrderMutator( operators=[operators.ArithmeticOperatorDeletion, operators.ArithmeticOperatorReplacement], ) target_ast = utils.create_ast('- a') number = None for number, (mutations, mutant) in enumerate(mutator.mutate(target_ast)): if number == 0: self.assertEqual('a', codegen.to_source(mutant)) self.assertEqual(len(mutations), 1) elif number == 1: self.assertEqual('(+a)', codegen.to_source(mutant)) self.assertEqual(len(mutations), 1) self.assertEqual(number, 1) self.assertEqual(codegen.to_source(target_ast), '(-a)')
def test_second_order_mutation_with_same_node_as_target(self): mutator = controller.HighOrderMutator( operators=[operators.ArithmeticOperatorDeletion, operators.ArithmeticOperatorReplacement], ) target_ast = utils.create_ast('- a') number = None for number, (mutations, mutant) in enumerate(mutator.mutate(target_ast)): if number == 0: self.assertEqual('a', codegen.to_source(mutant)) self.assertEqual(len(mutations), 1) elif number == 1: self.assertEqual('+a', codegen.to_source(mutant)) self.assertEqual(len(mutations), 1) self.assertEqual(number, 1) self.assertEqual(codegen.to_source(target_ast), '-a')
def test_first_order_mutation(self): mutator = controller.FirstOrderMutator( operators=[operators.ArithmeticOperatorReplacement, operators.AssignmentOperatorReplacement], ) target_ast = utils.create_ast('x += y + z') for number, (mutations, mutant) in enumerate(mutator.mutate(target_ast)): self.assertIn(number, [0, 1]) self.assertEqual(len(mutations), 1) if number == 0: self.assertEqual('x += y - z', codegen.to_source(mutant)) elif number == 1: self.assertEqual('x -= y + z', codegen.to_source(mutant)) self.assertEqual(codegen.to_source(target_ast), 'x += y + z')
def assert_mutation(self, original, mutants, lines=None, operator=None, with_coverage=False, with_exec=False): original_ast = utils.create_ast(original) if with_coverage: coverage_injector = coverage.CoverageInjector() coverage_injector.inject(original_ast) else: coverage_injector = None if not operator: operator = self.__class__.op if isinstance(mutants, str): mutants = [mutants] mutants = list(map(codegen.remove_extra_lines, mutants)) module = None if with_exec: module = utils.create_module(original_ast) for mutation, mutatnt in operator.mutate(original_ast, coverage_injector=coverage_injector, module=module): mutant_code = codegen.remove_extra_lines(codegen.to_source(mutatnt)) msg = '\n\nMutant:\n\n' + mutant_code + '\n\nNot found in:' for other_mutant in mutants: msg += '\n\n----------\n\n' + other_mutant self.assertIn(mutant_code, mutants, msg) mutants.remove(mutant_code) self.assert_location(mutatnt) if not lines is None: self.assert_mutation_lineo(mutation.node.lineno, lines) self.assertListEqual(mutants, [], 'did not generate all mutants')
def print_code(self, mutant, number, lineno, o_src, name): def wrap(sr): if isinstance(sr, str): return sr.encode('ascii', 'ignore').decode('ascii') else: return sr #.decode('ascii', 'ignore') mutant_src = codegen.to_source(mutant) hash_object = hashlib.md5(mutant_src.encode()) hsh = hash_object.hexdigest() target = os.getenv('TARGET') or 'T' os.system("mkdir -p ./mutants_%s/%d" % (target, number)) with open('./mutants_%s/%d/%s.py' % (target, number,name), 'w+') as f: f.write(wrap(mutant_src)) with open('./mutants_%s/original.py' % target, 'w+') as f: f.write(wrap(o_src)) mutant_src = codegen.add_line_numbers(mutant_src) o_src = codegen.add_line_numbers(o_src) osrc_lines = o_src.split("\n") src_lines = mutant_src.split("\n") lineno = min(lineno, len(src_lines)) src_lines[lineno - 1] = self.decorate('~' + src_lines[lineno - 1][1:], 'yellow') snippet = src_lines[max(0, lineno - 5):min(len(src_lines), lineno + 5)] snippet += ['-------'] snippet += [osrc_lines[lineno-1]] snippet += ['-------'] try: print("\n{}\n".format('-'*80) + "\n".join([wrap(i) for i in snippet]) + "\n{}".format('-'*80)) except: print(">>>",type(snippet))
def mutate_module(self, target_module, to_mutate, total_duration): target_ast = self.create_target_ast(target_module) target_src = codegen.to_source(target_ast) coverage_injector, coverage_result = self.inject_coverage( target_ast, target_module) if coverage_injector: self.score.update_coverage(*coverage_injector.get_result()) for mutations, mutant_ast in self.mutant_generator.mutate( target_ast, to_mutate, coverage_injector, module=target_module): mutation_number = self.score.all_mutants + 1 if self.mutation_number and self.mutation_number != mutation_number: self.score.inc_incompetent() continue self.notify_mutation(mutation_number, mutations, (target_module.__name__, target_src), mutant_ast) #x self.notify_mutation(mutation_number, mutations, target_module.__name__, mutant_ast) mutant_module = self.create_mutant_module(target_module, mutant_ast) if mutant_module: self.run_tests_with_mutant(total_duration, mutant_module, mutations, coverage_result) else: self.score.inc_incompetent()
def print_code1(self, mutant, number, lineno, name): mutant_src = codegen.to_source(mutant) mutant_src = codegen.add_line_numbers(mutant_src) src_lines = mutant_src.split("\n") lineno = min(lineno, len(src_lines)) src_lines[lineno - 1] = self.decorate('~' + src_lines[lineno - 1][1:], 'yellow') snippet = src_lines[max(0, lineno - 5):min(len(src_lines), lineno + 5)] print("\n{}\n".format('-'*80) + "\n".join(snippet) + "\n{}".format('-'*80))
def print_code(self, mutant, lineno): mutant_src = codegen.to_source(mutant) mutant_src = codegen.add_line_numbers(mutant_src) src_lines = mutant_src.split("\n") lineno = min(lineno, len(src_lines)) src_lines[lineno - 1] = self.decorate('~' + src_lines[lineno - 1][1:], 'yellow') snippet = src_lines[max(0, lineno - 5):min(len(src_lines), lineno + 5)] print("\n{}\n".format('-'*80) + "\n".join(snippet) + "\n{}".format('-'*80))
def end_mutation(self, *args, **kwargs): super().end_mutation(*args, **kwargs) template = self.env.get_template('detail.html') context = { 'mutant_code': codegen.to_source(self.current_mutation['mutant']), } context.update(self.current_mutation) report = template.render(context) file_path = os.path.join(self.dir_name, 'mutants', '{}.html'.format(self.current_mutation['number'])) with open(file_path, 'w') as report_file: report_file.write(report)
def end_mutation(self, *args, **kwargs): super().end_mutation(*args, **kwargs) template = self.env.get_template('detail.html') context = { 'mutant_code': codegen.to_source(self.store_mutant), } context.update(self.current_mutation) with open( os.path.join(self.dir_name, "mutants", "%d.json" % self.current_mutation['number']), 'w') as out_file: json.dump(context, out_file) out_file.closed
def assert_code_equal(self, code): node = utils.create_ast(code) generated = codegen.to_source(node) self.assertMultiLineEqual(code, generated)
def print_code(self, mutant, original): mutant_src = codegen.to_source(mutant) mutant_src = codegen.add_line_numbers(mutant_src) original_src = codegen.to_source(original) original_src = codegen.add_line_numbers(original_src) self._print_diff(mutant_src, original_src)