-
Notifications
You must be signed in to change notification settings - Fork 0
/
P5-1.py
216 lines (180 loc) · 6.39 KB
/
P5-1.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/usr/bin/env python
import sys
import math
# INSTRUCTIONS !
# This provided, working code calculates phi coefficients for each code line.
# Make sure that you understand how this works, then modify the traceit
# function to work for function calls instead of lines. It should save the
# function name and the return value of the function for each function call.
# Use the mystery function that can be found at line 155 and the
# test cases at line 180 for this exercise.
# Modify the provided functions to use this information to calculate
# phi values for the function calls as described in the video.
# You should get 3 phi values for each function - one for positive values (1),
# one for 0 values and one for negative values (-1), called "bins" in the video.
# When you have found out which function call and which return value type (bin)
# correlates the most with failure, fill in the following 3 variables,
# Do NOT set these values dynamically.
answer_function = "f3" # One of f1, f2, f3
answer_bin = -1 # One of 1, 0, -1
answer_value = 0.8165 # precision to 4 decimal places.
# The buggy program
def remove_html_markup(s):
tag = False
quote = False
out = ""
for c in s:
if c == '<' and not quote:
tag = True
elif c == '>' and not quote:
tag = False
elif c == '"' or c == "'" and tag:
quote = not quote
elif not tag:
out = out + c
return out
# global variable to keep the coverage data in
coverage = {}
# Tracing function that saves the coverage data
# To track function calls, you will have to check 'if event == "return"', and in
# that case the variable arg will hold the return value of the function,
# and frame.f_code.co_name will hold the function name
def traceit(frame, event, arg):
global coverage
if event == "line":
filename = frame.f_code.co_filename
lineno = frame.f_lineno
if not coverage.has_key(filename):
coverage[filename] = {}
coverage[filename][lineno] = True
return traceit
# Calculate phi coefficient from given values
def phi(n11, n10, n01, n00):
return ((n11 * n00 - n10 * n01) /
math.sqrt((n10 + n11) * (n01 + n00) * (n10 + n00) * (n01 + n11)))
# Print out values of phi, and result of runs for each covered line
def print_tables(tables):
for filename in tables.keys():
lines = open(filename).readlines()
for i in range(23, 40): # lines of the remove_html_markup in this file
if tables[filename].has_key(i + 1):
(n11, n10, n01, n00) = tables[filename][i + 1]
try:
factor = phi(n11, n10, n01, n00)
prefix = "%+.4f%2d%2d%2d%2d" % (factor, n11, n10, n01, n00)
except:
prefix = " %2d%2d%2d%2d" % (n11, n10, n01, n00)
else:
prefix = " "
print prefix, lines[i],
# Run the program with each test case and record
# input, outcome and coverage of lines
def run_tests(inputs):
runs = []
for input in inputs:
global coverage
coverage = {}
sys.settrace(traceit)
result = remove_html_markup(input)
sys.settrace(None)
if result.find('<') == -1:
outcome = "PASS"
else:
outcome = "FAIL"
runs.append((input, outcome, coverage))
return runs
# Create empty tuples for each covered line
def init_tables(runs):
tables = {}
for (input, outcome, coverage) in runs:
for filename, lines in coverage.iteritems():
for line in lines.keys():
if not tables.has_key(filename):
tables[filename] = {}
if not tables[filename].has_key(line):
tables[filename][line] = (0, 0, 0, 0)
return tables
# Compute n11, n10, etc. for each line
def compute_n(tables):
for filename, lines in tables.iteritems():
for line in lines.keys():
(n11, n10, n01, n00) = tables[filename][line]
for (input, outcome, coverage) in runs:
if coverage.has_key(filename) and coverage[filename].has_key(line):
# Covered in this run
if outcome == "FAIL":
n11 += 1 # covered and fails
else:
n10 += 1 # covered and passes
else:
# Not covered in this run
if outcome == "FAIL":
n01 += 1 # uncovered and fails
else:
n00 += 1 # uncovered and passes
tables[filename][line] = (n11, n10, n01, n00)
return tables
# Now compute (and report) phi for each line. The higher the value,
# the more likely the line is the cause of the failures.
# These are the test cases
inputs_line = ['foo',
'<b>foo</b>',
'"<b>foo</b>"',
'"foo"',
"'foo'",
'<em>foo</em>',
'<a href="foo">foo</a>',
'""',
"<p>"]
runs = run_tests(inputs_line)
tables = init_tables(runs)
tables = compute_n(tables)
print_tables(tables)
###### MYSTERY FUNCTION
def mystery(magic):
assert type(magic) == tuple
assert len(magic) == 3
l, s, n = magic
r1 = f1(l)
r2 = f2(s)
r3 = f3(n)
if -1 in [r1, r2, r3]:
return "FAIL"
elif r3 < 0:
return "FAIL"
elif not r1 or not r2:
return "FAIL"
else:
return "PASS"
# These are the input values you should test the mystery function with
inputs = [([1,2],"ab", 10),
([1,2],"ab", 2),
([1,2],"ab", 12),
([1,2],"ab", 21),
("a",1, [1]),
([1],"a", 1),
([1,2],"abcd", 8),
([1,2,3,4,5],"abcde", 8),
([1,2,3,4,5],"abcdefgijkl", 18),
([1,2,3,4,5,6,7],"abcdefghij", 5)]
def f1(ml):
if type(ml) is not list:
return -1
elif len(ml) <6 :
return len(ml)
else:
return 0
def f2(ms):
if type(ms) is not str:
return -1
elif len(ms) <6 :
return len(ms)
else:
return 0
def f3(mn):
if type(mn) is not int:
return -1
if mn > 10:
return -100
else:
return mn