-
Notifications
You must be signed in to change notification settings - Fork 0
/
program.py
102 lines (86 loc) · 3.38 KB
/
program.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import random
import subprocess
import timeit
from Cython.Compiler.TreeFragment import *
from Cython.Compiler.Visitor import *
from Cython.Compiler.Main import *
from Cython.Compiler.Pipeline import *
from Cython.CodeWriter import *
from Cython.Compiler.AnalysedTreeTransforms import *
from Cython.Compiler.ParseTreeTransforms import *
from Cython.Compiler.Symtab import *
from black import out
import utilities.cython_tree as cy
from utilities.cython_visitor import MyVisitor, NodeVisitor
import time
import importlib
class Program:
file_path = ""
def __init__(self, file_path, test_path):
self.file_path = file_path
self.test_path = test_path
self.contents = cy.file_to_ast(self.file_path)
self.modification_points = cy.get_modification_points(self.contents)
def get_modified_contents(self, patch):
modification_points = copy.deepcopy(self.modification_points)
new_contents = copy.deepcopy(self.contents)
edits = patch.edit_list
for edit in edits:
edit.apply(new_contents, modification_points)
return new_contents
def apply(self, patch):
"""
This method applies the patch to the target program.
It does not directly modify the source code of the original program,
but modifies the copied program within the temporary directory.
"""
new_contents = self.get_modified_contents(patch)
self.write_to_tmp_dir(new_contents)
return new_contents
def evaluate_patch(self, patch):
result_type = ["compilation_fail",
"bug_found", "wrong_value"]
result = {"status": None, "value": None}
# apply & run
self.apply(patch)
output = self.exec_cmd().strip()
print(output)
if output in result_type:
result["status"] = output
return result
result["status"] = "success"
result["value"] = output
return result
def load_contents(self):
self.contents = {}
self.modification_points = dict()
for file_name in self.target_files:
self.contents[file_name] = cy.get_contents(file_name)
self.modification_points[file_name] = cy.get_modification_points(
self.contents[file_name])
def exec_cmd(self):
process = subprocess.Popen(['python', self.test_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, universal_newlines=True)
stdout, stderr = process.communicate()
return stdout
def dump(self, content, name):
writer = CodeWriter()
writer.visit(content[name])
source = "\n".join(writer.result.lines)
return source
def random_target(self):
"""
:param str target_file: The modification point is chosen within target_file
:return: The **index** of modification point
:rtype: int
"""
candidates = self.modification_points
return random.randrange(len(candidates))
def write_to_tmp_dir(cls, contents):
with open("output/temp.pyx", 'w') as tmp_file:
tmp_file.write(cy.ast_to_source(contents))
def write_result(self, patch):
contents = self.get_modified_contents(patch)
with open("output/result.pyx", 'w') as result_file:
result_file.write(cy.ast_to_source(contents))