-
Notifications
You must be signed in to change notification settings - Fork 10
/
testharness-alt.py
executable file
·160 lines (139 loc) · 4.39 KB
/
testharness-alt.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
#!/usr/bin/python3
## Alternative, smaller test harness for Frank
## Craig McLaughlin, modified by Lukas Convent
## See the musings document for details on the proposed specification
## for this harness.
import io
import os
from subprocess import Popen,PIPE,TimeoutExpired
# LC: TODO: Configuration should be parseable
dirs = ["tests/should-pass/", "tests/should-fail/",
"tests/still-todo/", "examples/"]
showSuccesses = False
showSuccessesDetail = False
showFailures = True
showFailuresDetail = True
# marking => number-of-occurrences
stats = dict()
def main():
# Run tests
for d in dirs:
run_tests_in_dir(d)
# Print stats
for marking, count in sorted(stats.items()):
print(marking + ": " + str(count))
def run_tests_in_dir(d):
"""Execute tests in directory d"""
for x in sorted(os.listdir(d)):
x = d+x
## Recursively go through subdirectories
if os.path.isdir(x):
run_tests_in_dir(x+"/")
## Process only *.fk files
elif os.path.isfile(x) and x.endswith(".fk"):
process_file(x)
def process_file(x):
## Parse the file to obtain list of directives
ds = parse_file(x)
if ds:
out = ""
for (k, v, args) in ds:
out += process_directive(x, ds, k, v, args)
if out:
print(x)
print(out)
print("\n\n")
## File -> [Directive]
def parse_file(x):
ds = []
with open(x) as f:
for line in f:
if line.startswith("--"):
parse_line(ds, line[2:])
return ds
def parse_line(ds, line):
line = line.strip()
if line.startswith('#'):
ds.append(parse_directive(line[1:]))
def parse_directive(line):
args = [] ## directive arguments
(key,value),line = parse_pair(line)
parse_args(args,line)
return (key,value,args)
def parse_args(args,line):
line = line.strip()
if line.startswith('~'):
p,line = parse_pair(line[1:])
args.append(p)
def parse_pair(line):
key,value = "",""
x = 0
while x < len(line) and line[x].isalpha():
key += line[x]
x = x + 1
while x < len(line) and line[x] != '~':
value += line[x]
x = x + 1
return (key,value.strip()),line[x:]
def get_flags(ds):
for (k,v,args) in ds:
if k == "flags":
return [z for (x,y) in args for z in ["--" + x,y]]
return []
def process_directive(x,ds,k,v,args):
if k == "return":
flags = get_flags(ds)
p = Popen(["frank"] + flags + [x],stderr=PIPE,stdout=PIPE)
p.wait()
ret = p.returncode
try:
#TODO: LC: Timeout does not work...
(out,err) = p.communicate(timeout=15)
out = (err.decode("utf-8") + out.decode("utf-8")).strip()
except TimeoutExpired:
p.kill()
out = "TIMEOUT"
isSuccess = out == v
# Stats
isRegression = True if os.path.basename(x).startswith('r.') else False
if isRegression:
registerStat("regression", isSuccess)
for d in dirs:
if x.startswith(d):
registerStat(d, isSuccess)
# Output
res = ""
if isSuccess and showSuccesses:
res += "PASS"
if showSuccessesDetail:
res += "\nOutput: " + out
if (not isSuccess) and showFailures:
res += "FAIL"
if showFailuresDetail:
res += "\nExpected: " + v
res += "\nOutput: " + out
if (len(args) > 0):
res += str(args)
return res
else:
return ""
def registerStat(marking, isSuccess):
marking = ("successful " if isSuccess else "failing ") + marking
if (marking) in stats:
stats[marking] += 1
else:
stats[marking] = 1
if __name__ == "__main__":
import sys
import argparse
desc = "Run the test suite for the Frank implementation"
more = "PATH may be a filename or sub-directory \
in which case verbose output is produced for PATH only."
parser = argparse.ArgumentParser(description=desc)
# LC: TODO: parse configuration
parser.add_argument("--verbose", nargs='?', const=True, default=False,
metavar="PATH",
help="Produce verbose output. {0}".format(more))
args = parser.parse_args()
# Invariant: All directories end with a forward slash.
main()