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() { ...@@ -1886,6 +1886,9 @@ function RunMicrotasksJS() {
} }
function EnqueueMicrotask(fn) { function EnqueueMicrotask(fn) {
if (!IS_FUNCTION(fn)) {
throw new $TypeError('Can only enqueue functions');
}
var microtaskState = %GetMicrotaskState(); var microtaskState = %GetMicrotaskState();
if (IS_UNDEFINED(microtaskState.queue) || IS_NULL(microtaskState.queue)) { if (IS_UNDEFINED(microtaskState.queue) || IS_NULL(microtaskState.queue)) {
microtaskState.queue = new InternalArray; microtaskState.queue = new InternalArray;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# found in the LICENSE file. # found in the LICENSE file.
import itertools import itertools
import js2c
import multiprocessing import multiprocessing
import optparse import optparse
import os import os
...@@ -50,6 +51,7 @@ EXPECTED_FUNCTION_COUNT = 362 ...@@ -50,6 +51,7 @@ EXPECTED_FUNCTION_COUNT = 362
EXPECTED_FUZZABLE_COUNT = 329 EXPECTED_FUZZABLE_COUNT = 329
EXPECTED_CCTEST_COUNT = 6 EXPECTED_CCTEST_COUNT = 6
EXPECTED_UNKNOWN_COUNT = 5 EXPECTED_UNKNOWN_COUNT = 5
EXPECTED_BUILTINS_COUNT = 827
# Don't call these at all. # Don't call these at all.
...@@ -298,10 +300,6 @@ class Generator(object): ...@@ -298,10 +300,6 @@ class Generator(object):
return self._Variable(name, return self._Variable(name,
"\"%s\" + (function() { return \"%s\";})()" % (s1, s2)) "\"%s\" + (function() { return \"%s\";})()" % (s1, s2))
def _ExternalString(self, name):
# Needs --expose-externalize-string.
return None
def _InternalizedString(self, name): def _InternalizedString(self, name):
return self._Variable(name, "\"%s\"" % self._RawRandomString(0, 20)) return self._Variable(name, "\"%s\"" % self._RawRandomString(0, 20))
...@@ -918,6 +916,60 @@ def FindRuntimeFunctions(): ...@@ -918,6 +916,60 @@ def FindRuntimeFunctions():
function = None function = None
return functions 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. # Classifies runtime functions.
def ClassifyFunctions(functions): def ClassifyFunctions(functions):
# Can be fuzzed with a JavaScript testcase. # Can be fuzzed with a JavaScript testcase.
...@@ -1018,7 +1070,23 @@ def _SaveFileName(save_path, process_id, save_file_index): ...@@ -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) 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): 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 base_file_name = "/dev/shm/runtime_fuzz_%d" % process_id
test_file_name = "%s.js" % base_file_name test_file_name = "%s.js" % base_file_name
stderr_file_name = "%s.out" % base_file_name stderr_file_name = "%s.out" % base_file_name
...@@ -1026,19 +1094,14 @@ def RunFuzzer(process_id, options, stop_running): ...@@ -1026,19 +1094,14 @@ def RunFuzzer(process_id, options, stop_running):
while os.path.exists(_SaveFileName(options.save_path, process_id, while os.path.exists(_SaveFileName(options.save_path, process_id,
save_file_index)): save_file_index)):
save_file_index += 1 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: try:
for i in range(options.num_tests): for i in range(options.num_tests):
if stop_running.is_set(): break if stop_running.is_set(): break
function = random.choice(js_fuzzable_functions) # TODO: others too function = None
if function.argslength == 0: continue while function is None or function.argslength == 0:
function = random.choice(targets)
args = [] args = []
definitions = [] definitions = []
gen = Generator() gen = Generator()
...@@ -1086,11 +1149,11 @@ def RunFuzzer(process_id, options, stop_running): ...@@ -1086,11 +1149,11 @@ def RunFuzzer(process_id, options, stop_running):
save_file_index += 1 save_file_index += 1
except KeyboardInterrupt: except KeyboardInterrupt:
stop_running.set() stop_running.set()
except Exception, e:
print e
finally: finally:
os.remove(test_file_name) if os.path.exists(test_file_name):
os.remove(stderr_file_name) os.remove(test_file_name)
if os.path.exists(stderr_file_name):
os.remove(stderr_file_name)
def BuildOptionParser(): def BuildOptionParser():
...@@ -1110,6 +1173,9 @@ fuzz Generate fuzz tests, run them, save those that crashed (see options). ...@@ -1110,6 +1173,9 @@ fuzz Generate fuzz tests, run them, save those that crashed (see options).
o = optparse.OptionParser(usage=usage) o = optparse.OptionParser(usage=usage)
o.add_option("--binary", default="out/x64.debug/d8", o.add_option("--binary", default="out/x64.debug/d8",
help="d8 binary used for running fuzz tests (default: %default)") 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", o.add_option("-n", "--num-tests", default=1000, type="int",
help="Number of fuzz tests to generate per worker process" help="Number of fuzz tests to generate per worker process"
" (default: %default)") " (default: %default)")
...@@ -1122,12 +1188,21 @@ fuzz Generate fuzz tests, run them, save those that crashed (see options). ...@@ -1122,12 +1188,21 @@ fuzz Generate fuzz tests, run them, save those that crashed (see options).
return o 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(): def Main():
parser = BuildOptionParser() parser = BuildOptionParser()
(options, args) = parser.parse_args() (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() parser.print_help()
return 1 return 1
action = args[0] action = args[0]
...@@ -1135,14 +1210,10 @@ def Main(): ...@@ -1135,14 +1210,10 @@ def Main():
functions = FindRuntimeFunctions() functions = FindRuntimeFunctions()
(js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions) = \ (js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions) = \
ClassifyFunctions(functions) ClassifyFunctions(functions)
builtins = FindJSBuiltins()
if action == "test": if action == "test":
gen = Generator() print("put your temporary debugging code here")
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)))
return 0 return 0
if action == "info": if action == "info":
...@@ -1150,6 +1221,7 @@ def Main(): ...@@ -1150,6 +1221,7 @@ def Main():
"cctest_fuzzable_functions: %d, unknown_functions: %d" "cctest_fuzzable_functions: %d, unknown_functions: %d"
% (len(functions), len(js_fuzzable_functions), % (len(functions), len(js_fuzzable_functions),
len(cctest_fuzzable_functions), len(unknown_functions))) len(cctest_fuzzable_functions), len(unknown_functions)))
print("%d JavaScript builtins" % len(builtins))
print("unknown functions:") print("unknown functions:")
for f in unknown_functions: for f in unknown_functions:
print(f) print(f)
...@@ -1175,6 +1247,8 @@ def Main(): ...@@ -1175,6 +1247,8 @@ def Main():
"cctest-fuzzable functions") "cctest-fuzzable functions")
errors += CheckCount(unknown_functions, EXPECTED_UNKNOWN_COUNT, errors += CheckCount(unknown_functions, EXPECTED_UNKNOWN_COUNT,
"functions with incomplete type information") "functions with incomplete type information")
errors += CheckCount(builtins, EXPECTED_BUILTINS_COUNT,
"JavaScript builtins")
def CheckTestcasesExisting(functions): def CheckTestcasesExisting(functions):
errors = 0 errors = 0
...@@ -1196,6 +1270,19 @@ def Main(): ...@@ -1196,6 +1270,19 @@ def Main():
errors += CheckTestcasesExisting(js_fuzzable_functions) 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: if errors > 0:
return 1 return 1
print("Generated runtime tests: all good.") 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