forked from cuter-testing/cuter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcuter
executable file
·131 lines (118 loc) · 5.41 KB
/
cuter
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, argparse, os
import subprocess as subp
def main():
parser = argparse.ArgumentParser(description="Run the CutEr tool.")
# Add positional arguments.
parser.add_argument("module", metavar="M", help="the module")
parser.add_argument("fun", metavar="F", help="the function")
parser.add_argument("args", metavar="'[A1,...,An]'", help="the arguments of the MFA given as a list")
# Add optional arguments
parser.add_argument("-pa", nargs='+', default=[], metavar="Dir", help="preppends each Dir to Erlang's code path")
parser.add_argument("-pz", nargs='+', default=[], metavar="Dir", help="appends each Dir to Erlang's code path")
parser.add_argument("-d", "--depth", metavar="D", type=int, default=25, help="the depth limit D of the search")
parser.add_argument("-p", "--pollers", metavar="N", type=int, default=1,
help="use N pollers (default: %(default)s)")
parser.add_argument("-s", "--solvers", metavar="N", type=int, default=1,
help="use N solvers (default: %(default)s)")
parser.add_argument("-w", metavar="P",
help="the path P of the file with the whitelisted MFAs. Write one line for each MFA, ending with a dot")
parser.add_argument("-v", "--verbose", action='store_true', help="request a verbose execution")
parser.add_argument("-r", "--recompile", action='store_true', help="recompile the module under test")
parser.add_argument("-c", "--coverage", action='store_true', help="calculate the coverage achieved")
parser.add_argument("--fully-verbose", action='store_true', help="request a fully verbose execution (for debugging)")
parser.add_argument("--disable-pmatch", action='store_true', help="disable the pattern matching compilation")
parser.add_argument("--sorted-errors", action='store_true', help="report the erroneous inputs in a sorted order")
parser.add_argument("--suppress-unsupported", action='store_true', help="suppresses the reporting of unsupported MFAs")
parser.add_argument("--no-type-normalization", action='store_true', help="disable the normalization specifications & types")
parser.add_argument("--z3py", action='store_true', help="use the z3py solver backend")
# Parse the arguments
args = parser.parse_args()
# The directories that will be appended to the code path.
paths = "".join([
"-pa " + " ".join(args.pa) if len(args.pa) > 0 else "",
"-pz " + " ".join(args.pz) if len(args.pz) > 0 else ""
])
# First, recompile the module, if requested.
if args.recompile:
if compileModule(args.module, paths, True) == 1:
sys.exit(1)
# Export ERL_LIBS.
erl_libs = os.getenv("ERL_LIBS")
if erl_libs != None:
os.environ["ERL_LIBS"] = getDirectory() + ":" + erl_libs
else:
os.environ["ERL_LIBS"] = getDirectory()
# Check if the module exists in the code path.
cmd = "erl -noshell {} -eval \"erlang:display(code:which({})),halt()\"".format(paths, args.module)
p = subp.Popen(cmd, shell=True, stdin=subp.PIPE, stdout=subp.PIPE, stderr=subp.STDOUT, close_fds=True)
out, err = p.communicate()
if err:
print "Error in searching for {}: {} ...".format(args.module, err)
sys.exit(1)
out = out.strip().strip("\"")
# If the module is non_existing try to compile it.
if out == "non_existing":
if compileModule(args.module, paths) == 1:
sys.exit(1)
elif len(out) < 4 or out[-4:] != "beam":
print "Module {} is {} ...".format(args.module, out)
sys.exit(1)
# We only get here if the module is either compiled, or found in the code path.
# Now set CutEr's runtime options.
opts = []
opts.append("{{number_of_pollers, {}}}".format(args.pollers))
opts.append("{{number_of_solvers, {}}}".format(args.solvers))
if args.verbose:
opts.append("verbose_execution_info")
if args.coverage:
opts.append("coverage")
if args.fully_verbose:
opts.append("fully_verbose_execution_info")
if args.disable_pmatch:
opts.append("disable_pmatch")
if args.sorted_errors:
opts.append("sorted_errors")
if args.suppress_unsupported:
opts.append("suppress_unsupported")
if args.no_type_normalization:
opts.append("no_type_normalization")
if args.w != None:
opts.append("{{whitelist, '{}'}}".format(args.w))
if args.z3py:
opts.append("z3py")
strOpts = ",".join(opts)
# Run CutEr
cmd = "erl -noshell {} -eval \"cuter:run({}, {}, {}, {}, [{}])\" -s init stop".format(
paths, args.module, args.fun, args.args, args.depth, strOpts)
sys.exit(subp.call(cmd, shell=True))
def getDirectory():
return os.path.dirname(os.path.realpath(__file__))
def compileModule(module, paths, again = False):
"""
Tries to compile the module.
It expects that the erl file is located in the current working directory.
"""
exists = os.path.isfile(module + ".beam")
if again or not exists:
erl = module + ".erl"
if not os.path.isfile(erl):
print "Cannot locate {} ... ".format(erl)
return 1
print "\033[00;34mCompiling {} ...\033[00m".format(erl),
if len(paths) > 0:
pathParts = paths.split(" ")
cmdParts = ["erlc"] + pathParts + ["+debug_info", erl]
else:
cmdParts = ["erlc", "+debug_info", erl]
p = subp.Popen(cmdParts, stdout=subp.PIPE, stderr=subp.PIPE)
out, err = p.communicate()
print "\033[01;32mok\033[00m" if p.returncode == 0 else "ERROR"
return p.returncode, "\n".join([out.strip(), err.strip()]).strip()
return 0
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
sys.exit(1)