Add builtin detector to generate-runtime-tests.py

R=dslomov@chromium.org

Review URL: https://codereview.chromium.org/283403002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21342 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 43c170eb
......@@ -1886,6 +1886,9 @@ function RunMicrotasksJS() {
}
function EnqueueMicrotask(fn) {
if (!IS_FUNCTION(fn)) {
throw new $TypeError('Can only enqueue functions');
}
var microtaskState = %GetMicrotaskState();
if (IS_UNDEFINED(microtaskState.queue) || IS_NULL(microtaskState.queue)) {
microtaskState.queue = new InternalArray;
......
......@@ -4,6 +4,7 @@
# found in the LICENSE file.
import itertools
import js2c
import multiprocessing
import optparse
import os
......@@ -50,6 +51,7 @@ EXPECTED_FUNCTION_COUNT = 362
EXPECTED_FUZZABLE_COUNT = 329
EXPECTED_CCTEST_COUNT = 6
EXPECTED_UNKNOWN_COUNT = 5
EXPECTED_BUILTINS_COUNT = 827
# Don't call these at all.
......@@ -298,10 +300,6 @@ class Generator(object):
return self._Variable(name,
"\"%s\" + (function() { return \"%s\";})()" % (s1, s2))
def _ExternalString(self, name):
# Needs --expose-externalize-string.
return None
def _InternalizedString(self, name):
return self._Variable(name, "\"%s\"" % self._RawRandomString(0, 20))
......@@ -918,6 +916,60 @@ def FindRuntimeFunctions():
function = None
return functions
# Hack: This must have the same fields as class Function above, because the
# two are used polymorphically in RunFuzzer(). We could use inheritance...
class Builtin(object):
def __init__(self, match):
self.name = match.group(1)
args = match.group(2)
self.argslength = 0 if args == "" else args.count(",") + 1
self.inline = ""
self.args = {}
if self.argslength > 0:
args = args.split(",")
for i in range(len(args)):
# a = args[i].strip() # TODO: filter out /* comments */ first.
a = ""
self.args[i] = Arg("Object", a, i)
def __str__(self):
return "%s(%d)" % (self.name, self.argslength)
def FindJSBuiltins():
PATH = "src"
fileslist = []
for (root, dirs, files) in os.walk(PATH):
for f in files:
if f.endswith(".js"):
fileslist.append(os.path.join(root, f))
builtins = []
regexp = re.compile("^function (\w+)\s*\((.*?)\) {")
matches = 0
for filename in fileslist:
with open(filename, "r") as f:
file_contents = f.read()
file_contents = js2c.ExpandInlineMacros(file_contents)
lines = file_contents.split("\n")
partial_line = ""
for line in lines:
if line.startswith("function") and not '{' in line:
partial_line += line.rstrip()
continue
if partial_line:
partial_line += " " + line.strip()
if '{' in line:
line = partial_line
partial_line = ""
else:
continue
match = regexp.match(line)
if match:
builtins.append(Builtin(match))
return builtins
# Classifies runtime functions.
def ClassifyFunctions(functions):
# Can be fuzzed with a JavaScript testcase.
......@@ -1018,7 +1070,23 @@ def _SaveFileName(save_path, process_id, save_file_index):
return "%s/fuzz_%d_%d.js" % (save_path, process_id, save_file_index)
def _GetFuzzableRuntimeFunctions():
functions = FindRuntimeFunctions()
(js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions) = \
ClassifyFunctions(functions)
return js_fuzzable_functions
FUZZ_TARGET_LISTS = {
"runtime": _GetFuzzableRuntimeFunctions,
"builtins": FindJSBuiltins,
}
def RunFuzzer(process_id, options, stop_running):
MAX_SLEEP_TIME = 0.1
INITIAL_SLEEP_TIME = 0.001
SLEEP_TIME_FACTOR = 1.25
base_file_name = "/dev/shm/runtime_fuzz_%d" % process_id
test_file_name = "%s.js" % base_file_name
stderr_file_name = "%s.out" % base_file_name
......@@ -1026,19 +1094,14 @@ def RunFuzzer(process_id, options, stop_running):
while os.path.exists(_SaveFileName(options.save_path, process_id,
save_file_index)):
save_file_index += 1
MAX_SLEEP_TIME = 0.1
INITIAL_SLEEP_TIME = 0.001
SLEEP_TIME_FACTOR = 1.5
functions = FindRuntimeFunctions()
(js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions) = \
ClassifyFunctions(functions)
targets = FUZZ_TARGET_LISTS[options.fuzz_target]()
try:
for i in range(options.num_tests):
if stop_running.is_set(): break
function = random.choice(js_fuzzable_functions) # TODO: others too
if function.argslength == 0: continue
function = None
while function is None or function.argslength == 0:
function = random.choice(targets)
args = []
definitions = []
gen = Generator()
......@@ -1086,11 +1149,11 @@ def RunFuzzer(process_id, options, stop_running):
save_file_index += 1
except KeyboardInterrupt:
stop_running.set()
except Exception, e:
print e
finally:
os.remove(test_file_name)
os.remove(stderr_file_name)
if os.path.exists(test_file_name):
os.remove(test_file_name)
if os.path.exists(stderr_file_name):
os.remove(stderr_file_name)
def BuildOptionParser():
......@@ -1110,6 +1173,9 @@ fuzz Generate fuzz tests, run them, save those that crashed (see options).
o = optparse.OptionParser(usage=usage)
o.add_option("--binary", default="out/x64.debug/d8",
help="d8 binary used for running fuzz tests (default: %default)")
o.add_option("--fuzz-target", default="runtime",
help="Set of functions targeted by fuzzing. Allowed values: "
"%s (default: %%default)" % ", ".join(FUZZ_TARGET_LISTS))
o.add_option("-n", "--num-tests", default=1000, type="int",
help="Number of fuzz tests to generate per worker process"
" (default: %default)")
......@@ -1122,12 +1188,21 @@ fuzz Generate fuzz tests, run them, save those that crashed (see options).
return o
def ProcessOptions(options, args):
options.save_path = os.path.expanduser(options.save_path)
if options.fuzz_target not in FUZZ_TARGET_LISTS:
print("Invalid fuzz target: %s" % options.fuzz_target)
return False
if len(args) != 1 or args[0] == "help":
return False
return True
def Main():
parser = BuildOptionParser()
(options, args) = parser.parse_args()
options.save_path = os.path.expanduser(options.save_path)
if len(args) != 1 or args[0] == "help":
if not ProcessOptions(options, args):
parser.print_help()
return 1
action = args[0]
......@@ -1135,14 +1210,10 @@ def Main():
functions = FindRuntimeFunctions()
(js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions) = \
ClassifyFunctions(functions)
builtins = FindJSBuiltins()
if action == "test":
gen = Generator()
vartype = "JSTypedArray"
print("simple: %s" % gen.RandomVariable("x", vartype, True))
for i in range(10):
print("----")
print("%s" % "\n".join(gen.RandomVariable("x", vartype, False)))
print("put your temporary debugging code here")
return 0
if action == "info":
......@@ -1150,6 +1221,7 @@ def Main():
"cctest_fuzzable_functions: %d, unknown_functions: %d"
% (len(functions), len(js_fuzzable_functions),
len(cctest_fuzzable_functions), len(unknown_functions)))
print("%d JavaScript builtins" % len(builtins))
print("unknown functions:")
for f in unknown_functions:
print(f)
......@@ -1175,6 +1247,8 @@ def Main():
"cctest-fuzzable functions")
errors += CheckCount(unknown_functions, EXPECTED_UNKNOWN_COUNT,
"functions with incomplete type information")
errors += CheckCount(builtins, EXPECTED_BUILTINS_COUNT,
"JavaScript builtins")
def CheckTestcasesExisting(functions):
errors = 0
......@@ -1196,6 +1270,19 @@ def Main():
errors += CheckTestcasesExisting(js_fuzzable_functions)
def CheckNameClashes(runtime_functions, builtins):
errors = 0
runtime_map = {}
for f in runtime_functions:
runtime_map[f.name] = 1
for b in builtins:
if b.name in runtime_map:
print("Builtin/Runtime_Function name clash: %s" % b.name)
errors += 1
return errors
errors += CheckNameClashes(functions, builtins)
if errors > 0:
return 1
print("Generated runtime tests: all good.")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment