From: jkummerow@chromium.org Date: Fri, 16 May 2014 13:23:32 +0000 (+0000) Subject: Add builtin detector to generate-runtime-tests.py X-Git-Tag: upstream/4.7.83~9101 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5843a3359c7ad6599e1d4fe061f21b8796bd85fb;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/v8natives.js b/src/v8natives.js index 46dfab4..2e76162 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -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; diff --git a/tools/generate-runtime-tests.py b/tools/generate-runtime-tests.py index 8770aa2..429271a 100755 --- a/tools/generate-runtime-tests.py +++ b/tools/generate-runtime-tests.py @@ -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.")