def _processVisit(self, node, loop_name): if self.loop_counter > self.loop_target: self.is_mutating = False if self.is_mutating: self.loop_counter += 1 if self.loop_counter == self.loop_target: self.has_mutation = True start_lineno = node.lineno body_lineno = node.body[0].lineno line = self.source_lines[node.lineno + self.lineno_modifier - 1] if node.lineno == body_lineno: # For those loop-statements with body on the same line end_lineno = node.lineno + 1 body_indentation = self.indentation(line) + ' ' if isinstance(node.body[0], ast.Pass): node.body.pop(0) else: end_lineno = body_lineno body_indentation = self.indentation(self.source_lines[body_lineno + self.lineno_modifier - 1]) if isinstance(node.body[0], ast.Pass): n = node.body.pop(0) end_lineno += 1 node.body.insert(0, ast.parse('if mutest_statement_reached() % 2 == 0: continue')) new_lines = [ ] if loop_name == 'for': new_lines.append(self.indentation(line) + 'for ' + codegen.to_source(node.target) + ' in ' + codegen.to_source(node.iter) + ':\n') else: new_lines.append(self.indentation(line) + 'while ' + codegen.to_source(node.test) + ':\n') new_lines.append(body_indentation + 'if mutest_statement_reached() % 2 == 0: continue\n') if node.lineno == body_lineno: for n in node.body[1:]: # The first line "if mutest_statement_reached() % 2 == 0: continue" is already inserted new_lines.append(body_indentation + codegen.to_source(n) + '\n') indent = None for i in range(start_lineno, end_lineno): indent = self.comment_line(i + self.lineno_modifier, indent) self.source_lines[end_lineno-1+self.lineno_modifier:end_lineno-1+self.lineno_modifier] = new_lines self.lineno_modifier += len(new_lines) self.generic_visit(node) return node
def visit_If(self, node): if self.if_counter > self.if_target: self.is_mutating = False if self.is_mutating: self.if_counter += 1 if len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If): self.ifelse_set.add(node.orelse[0]) if self.if_counter == self.if_target: new_test = ast.UnaryOp(op=ast.Not(), operand=node.test) new_node = ast.copy_location( ast.If( test=ast.BoolOp(op=ast.Or(), values=[self.prepare_mutest_reached_node(), new_test]), body=node.body, orelse=node.orelse, ), node, ) self.has_mutation = True is_elif = node in self.ifelse_set if node.lineno == node.body[0].lineno: # For those if-statements with body on the same line line = self.source_lines[node.lineno + self.lineno_modifier - 1] new_line = ( self.indentation(line) + ("elif " if is_elif else "if ") + codegen.to_source(new_test) + ": " ) child_nodes = node.body[:] while child_nodes: n = child_nodes.pop(0) new_line = new_line + codegen.to_source(n) + ("; " if child_nodes else "") new_line = new_line + "\n" self.comment_line(node.lineno + self.lineno_modifier) self.source_lines.insert(node.lineno + self.lineno_modifier, new_line) self.lineno_modifier += 1 else: end_lineno = node.body[0].lineno for start_lineno in range(end_lineno - 1, 0, -1): m = (self.IFELSE_PAT if is_elif else self.IF_PAT).search( self.source_lines[start_lineno + self.lineno_modifier - 1] + " " ) if m: break # Standard if-statements with body on separate lines, or testing conditions over multiple lines indent = None for i in range(start_lineno, end_lineno): indent = self.comment_line(i + self.lineno_modifier, indent) line = self.source_lines[node.lineno + self.lineno_modifier - 1] new_line = ( self.indentation(line) + ("elif " if is_elif else "if ") + codegen.to_source(new_test) + ":\n" ) self.source_lines.insert(end_lineno + self.lineno_modifier - 1, new_line) self.lineno_modifier += 1 self.generic_visit(new_node) return new_node self.generic_visit(node) return node
def _f(): source_filename = os.path.join(os.path.dirname(__file__), 'depfiles', test_name + '.py') with open(source_filename, 'r') as source_fh: source_lines = source_fh.readlines() test_func_name, lineno = source_lines[0][1:].strip().split(':') test_func_lineno = int(lineno) buf = StringIO(codegen.to_source(ast.parse(''.join(source_lines)))) orig_ast_lines = buf.readlines() buf.close() diffs_filename = os.path.join(os.path.dirname(__file__), 'depfiles', test_name + '.diffs') diffs_list, _diff = [ ], [ ] with open(diffs_filename, 'r') as diff_fh: while True: line = diff_fh.readline() if not line: break line = line.rstrip() if line[:2] == '##': if _diff: diffs_list.append(_diff) _diff = [ ] elif line: _diff.append(line) if _diff: diffs_list.append(_diff) del _diff asts_filename = os.path.join(os.path.dirname(__file__), 'depfiles', test_name + '.asts') asts_list, _ast = [ ], [ ] with open(asts_filename, 'r') as ast_fh: while True: line = ast_fh.readline() if not line: break line = line.rstrip() if line[:2] == '##': if _ast: asts_list.append(_ast) _ast = [ ] elif line: _ast.append(line) if _ast: asts_list.append(_ast) del _ast mutator = mutator_klass() for asts, diff, result in itertools.izip_longest(asts_list, diffs_list, mutator.mutate(source_filename, test_func_name, test_func_lineno), fillvalue = None): if not result: print 'Failed. Missing diff results' print '===========================' print 'Expecting diff' print '\n'.join(diff) assert False test_id, mutated_lines, mutated_ast = result mutated_diff = filter(lambda s: s and s[0] in ( '+', '-' ) and s != '---' and s != '+++', map(lambda s: s.rstrip(), difflib.unified_diff(source_lines, mutated_lines))) if not diff: print test_id, 'has failed. No corresponding diff found' print '===========================' print 'Result diff' print '\n'.join(mutated_diff) assert False if list(difflib.unified_diff(diff, mutated_diff)): print print test_id, 'has failed to match diff' print '===========================' print 'Expecting diff' print '\n'.join(diff) print 'Result diff' print '\n'.join(mutated_diff) print assert False buf = StringIO(codegen.to_source(mutated_ast)) mutated_lines = buf.readlines() buf.close() mutated_asts = filter(lambda s: s and s[0] in ( '+', '-' ) and s != '---' and s != '+++', map(lambda s: s.rstrip(), difflib.unified_diff(orig_ast_lines, mutated_lines))) if not asts: print test_id, 'has failed. No corresponding ast found' print '===========================' print 'Result ast' print '\n'.join(mutated_asts) assert False if list(difflib.unified_diff(asts, mutated_asts)): print print test_id, 'has failed to match ast' print '===========================' print 'Expecting ast' print '\n'.join(asts) print 'Result ast' print '\n'.join(mutated_asts) print assert False
def _f(): source_filename = os.path.join(os.path.dirname(__file__), "depfiles", test_name + ".py") with open(source_filename, "r") as source_fh: source_lines = source_fh.readlines() test_func_name, lineno = source_lines[0][1:].strip().split(":") test_func_lineno = int(lineno) buf = StringIO(codegen.to_source(ast.parse("".join(source_lines)))) orig_ast_lines = buf.readlines() buf.close() diffs_filename = os.path.join(os.path.dirname(__file__), "depfiles", test_name + ".diffs") diffs_list, _diff = [], [] with open(diffs_filename, "r") as diff_fh: while True: line = diff_fh.readline() if not line: break line = line.rstrip() if line[:2] == "##": if _diff: diffs_list.append(_diff) _diff = [] elif line: _diff.append(line) if _diff: diffs_list.append(_diff) del _diff asts_filename = os.path.join(os.path.dirname(__file__), "depfiles", test_name + ".asts") asts_list, _ast = [], [] with open(asts_filename, "r") as ast_fh: while True: line = ast_fh.readline() if not line: break line = line.rstrip() if line[:2] == "##": if _ast: asts_list.append(_ast) _ast = [] elif line: _ast.append(line) if _ast: asts_list.append(_ast) del _ast mutator = mutator_klass() for asts, diff, result in itertools.izip_longest( asts_list, diffs_list, mutator.mutate(source_filename, test_func_name, test_func_lineno), fillvalue=None ): if not result: print "Failed. Missing diff results" print "===========================" print "Expecting diff" print "\n".join(diff) assert False test_id, mutated_lines, mutated_ast = result mutated_diff = filter( lambda s: s and s[0] in ("+", "-") and s != "---" and s != "+++", map(lambda s: s.rstrip(), difflib.unified_diff(source_lines, mutated_lines)), ) if not diff: print test_id, "has failed. No corresponding diff found" print "===========================" print "Result diff" print "\n".join(mutated_diff) assert False if list(difflib.unified_diff(diff, mutated_diff)): print print test_id, "has failed to match diff" print "===========================" print "Expecting diff" print "\n".join(diff) print "Result diff" print "\n".join(mutated_diff) print assert False buf = StringIO(codegen.to_source(mutated_ast)) mutated_lines = buf.readlines() buf.close() mutated_asts = filter( lambda s: s and s[0] in ("+", "-") and s != "---" and s != "+++", map(lambda s: s.rstrip(), difflib.unified_diff(orig_ast_lines, mutated_lines)), ) if not asts: print test_id, "has failed. No corresponding ast found" print "===========================" print "Result ast" print "\n".join(mutated_asts) assert False if list(difflib.unified_diff(asts, mutated_asts)): print print test_id, "has failed to match ast" print "===========================" print "Expecting ast" print "\n".join(asts) print "Result ast" print "\n".join(mutated_asts) print assert False
def _processVisit(self, node, loop_name): if self.loop_counter > self.loop_target: self.is_mutating = False if self.is_mutating: self.loop_counter += 1 if self.loop_counter == self.loop_target: self.has_mutation = True start_lineno = node.lineno body_lineno = node.body[0].lineno line = self.source_lines[node.lineno + self.lineno_modifier - 1] if node.lineno == body_lineno: # For those loop-statements with body on the same line end_lineno = node.lineno + 1 body_indentation = self.indentation(line) + ' ' if isinstance(node.body[0], ast.Pass): node.body.pop(0) else: end_lineno = body_lineno body_indentation = self.indentation( self.source_lines[body_lineno + self.lineno_modifier - 1]) if isinstance(node.body[0], ast.Pass): n = node.body.pop(0) end_lineno += 1 node.body.insert( 0, ast.parse( 'if mutest_statement_reached() % 2 == 0: continue')) new_lines = [] if loop_name == 'for': new_lines.append( self.indentation(line) + 'for ' + codegen.to_source(node.target) + ' in ' + codegen.to_source(node.iter) + ':\n') else: new_lines.append( self.indentation(line) + 'while ' + codegen.to_source(node.test) + ':\n') new_lines.append( body_indentation + 'if mutest_statement_reached() % 2 == 0: continue\n') if node.lineno == body_lineno: for n in node.body[ 1:]: # The first line "if mutest_statement_reached() % 2 == 0: continue" is already inserted new_lines.append(body_indentation + codegen.to_source(n) + '\n') indent = None for i in range(start_lineno, end_lineno): indent = self.comment_line(i + self.lineno_modifier, indent) self.source_lines[end_lineno - 1 + self.lineno_modifier:end_lineno - 1 + self.lineno_modifier] = new_lines self.lineno_modifier += len(new_lines) self.generic_visit(node) return node
def visit_If(self, node): if self.if_counter > self.if_target: self.is_mutating = False if self.is_mutating: self.if_counter += 1 if len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If): self.ifelse_set.add(node.orelse[0]) if self.if_counter == self.if_target: new_test = ast.UnaryOp(op=ast.Not(), operand=node.test) new_node = ast.copy_location( ast.If(test=ast.BoolOp( op=ast.Or(), values=[self.prepare_mutest_reached_node(), new_test]), body=node.body, orelse=node.orelse), node) self.has_mutation = True is_elif = node in self.ifelse_set if node.lineno == node.body[0].lineno: # For those if-statements with body on the same line line = self.source_lines[node.lineno + self.lineno_modifier - 1] new_line = self.indentation(line) + ( 'elif ' if is_elif else 'if ') + codegen.to_source(new_test) + ': ' child_nodes = node.body[:] while child_nodes: n = child_nodes.pop(0) new_line = new_line + codegen.to_source(n) + ( '; ' if child_nodes else '') new_line = new_line + '\n' self.comment_line(node.lineno + self.lineno_modifier) self.source_lines.insert( node.lineno + self.lineno_modifier, new_line) self.lineno_modifier += 1 else: end_lineno = node.body[0].lineno for start_lineno in range(end_lineno - 1, 0, -1): m = (self.IFELSE_PAT if is_elif else self.IF_PAT).search(self.source_lines[ start_lineno + self.lineno_modifier - 1] + ' ') if m: break # Standard if-statements with body on separate lines, or testing conditions over multiple lines indent = None for i in range(start_lineno, end_lineno): indent = self.comment_line(i + self.lineno_modifier, indent) line = self.source_lines[node.lineno + self.lineno_modifier - 1] new_line = self.indentation(line) + ( 'elif ' if is_elif else 'if ') + codegen.to_source(new_test) + ':\n' self.source_lines.insert( end_lineno + self.lineno_modifier - 1, new_line) self.lineno_modifier += 1 self.generic_visit(new_node) return new_node self.generic_visit(node) return node