Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Unified Diff: tools/generate-runtime-tests.py

Issue 548383002: Delete generated runtime tests (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/check-name-clashes.py ('k') | tools/presubmit.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/generate-runtime-tests.py
diff --git a/tools/generate-runtime-tests.py b/tools/generate-runtime-tests.py
index 6cda22277b8924391f2d2e94c4b98e4290244236..e4489303270dbae94d66d075e9dc2dc9f5d759e9 100755
--- a/tools/generate-runtime-tests.py
+++ b/tools/generate-runtime-tests.py
@@ -3,879 +3,32 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import itertools
import js2c
-import multiprocessing
-import optparse
import os
-import random
import re
-import shutil
-import signal
-import string
-import subprocess
import sys
-import time
FILENAME = "src/runtime.cc"
-HEADERFILENAME = "src/runtime.h"
FUNCTION = re.compile("^RUNTIME_FUNCTION\(Runtime_(\w+)")
-ARGSLENGTH = re.compile(".*DCHECK\(.*args\.length\(\) == (\d+)\);")
FUNCTIONEND = "}\n"
MACRO = re.compile(r"^#define ([^ ]+)\(([^)]*)\) *([^\\]*)\\?\n$")
FIRST_WORD = re.compile("^\s*(.*?)[\s({\[]")
-WORKSPACE = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), ".."))
-BASEPATH = os.path.join(WORKSPACE, "test", "mjsunit", "runtime-gen")
-THIS_SCRIPT = os.path.relpath(sys.argv[0])
-
# Expand these macros, they define further runtime functions.
EXPAND_MACROS = [
"BUFFER_VIEW_GETTER",
"DATA_VIEW_GETTER",
"DATA_VIEW_SETTER",
+ "ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION",
+ "FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION",
"RUNTIME_UNARY_MATH",
+ "TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION",
]
-# TODO(jkummerow): We could also whitelist the following macros, but the
-# functions they define are so trivial that it's unclear how much benefit
-# that would provide:
-# ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
-# FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
-# TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
-
-# Counts of functions in each detection state. These are used to assert
-# that the parser doesn't bit-rot. Change the values as needed when you add,
-# remove or change runtime functions, but make sure we don't lose our ability
-# to parse them!
-EXPECTED_FUNCTION_COUNT = 431
-EXPECTED_FUZZABLE_COUNT = 330
-EXPECTED_CCTEST_COUNT = 7
-EXPECTED_UNKNOWN_COUNT = 17
-EXPECTED_BUILTINS_COUNT = 806
-
-
-# Don't call these at all.
-BLACKLISTED = [
- "Abort", # Kills the process.
- "AbortJS", # Kills the process.
- "CompileForOnStackReplacement", # Riddled with DCHECK.
- "IS_VAR", # Not implemented in the runtime.
- "ListNatives", # Not available in Release mode.
- "SetAllocationTimeout", # Too slow for fuzzing.
- "SystemBreak", # Kills (int3) the process.
-
- # These are weird. They violate some invariants when called after
- # bootstrapping.
- "DisableAccessChecks",
- "EnableAccessChecks",
-
- # The current LiveEdit implementation relies on and messes with internals
- # in ways that makes it fundamentally unfuzzable :-(
- "DebugGetLoadedScripts",
- "DebugSetScriptSource",
- "LiveEditFindSharedFunctionInfosForScript",
- "LiveEditFunctionSourceUpdated",
- "LiveEditGatherCompileInfo",
- "LiveEditPatchFunctionPositions",
- "LiveEditReplaceFunctionCode",
- "LiveEditReplaceRefToNestedFunction",
- "LiveEditReplaceScript",
- "LiveEditRestartFrame",
- "SetScriptBreakPoint",
-
- # TODO(jkummerow): Fix these and un-blacklist them!
- "CreateDateTimeFormat",
- "CreateNumberFormat",
-
- # TODO(danno): Fix these internal function that are only callable form stubs
- # and un-blacklist them!
- "NumberToString",
- "RxegExpConstructResult",
- "RegExpExec",
- "StringAdd",
- "SubString",
- "StringCompare",
- "StringCharCodeAt",
- "GetFromCache",
-
- # Compilation
- "CompileUnoptimized",
- "CompileOptimized",
- "TryInstallOptimizedCode",
- "NotifyDeoptimized",
- "NotifyStubFailure",
-
- # Utilities
- "AllocateInNewSpace",
- "AllocateInTargetSpace",
- "AllocateHeapNumber",
- "LoadMutableDouble",
- "NumberToSmi",
- "NumberToStringSkipCache",
-
- "FunctionBindArguments",
- "NewSloppyArguments",
- "NewStrictArguments",
-
- # Harmony
- "CreateJSGeneratorObject",
- "SuspendJSGeneratorObject",
- "ResumeJSGeneratorObject",
- "ThrowGeneratorStateError",
-
- # Arrays
- "ArrayConstructor",
- "InternalArrayConstructor",
- "NormalizeElements",
-
- # Literals
- "MaterializeRegExpLiteral",
- "CreateObjectLiteral",
- "CreateArrayLiteral",
- "CreateArrayLiteralStubBailout",
-
- # Statements
- "NewClosure",
- "NewClosureFromStubFailure",
- "NewObject",
- "NewObjectWithAllocationSite",
- "FinalizeInstanceSize",
- "Throw",
- "ReThrow",
- "ThrowReferenceError",
- "ThrowNotDateError",
- "StackGuard",
- "Interrupt",
- "PromoteScheduledException",
-
- # Contexts
- "NewGlobalContext",
- "NewFunctionContext",
- "PushWithContext",
- "PushCatchContext",
- "PushBlockContext",
- "PushModuleContext",
- "DeleteLookupSlot",
- "LoadLookupSlot",
- "LoadLookupSlotNoReferenceError",
- "StoreLookupSlot",
-
- # Declarations
- "DeclareGlobals",
- "DeclareModules",
- "DeclareContextSlot",
- "InitializeConstGlobal",
- "InitializeConstContextSlot",
-
- # Eval
- "ResolvePossiblyDirectEval",
-
- # Maths
- "MathPowSlow",
- "MathPowRT",
-
- # Internal
- "InternalSetPrototype",
-]
-
-
-# These will always throw.
-THROWS = [
- "CheckExecutionState", # Needs to hit a break point.
- "CheckIsBootstrapping", # Needs to be bootstrapping.
- "DebugEvaluate", # Needs to hit a break point.
- "DebugEvaluateGlobal", # Needs to hit a break point.
- "DebugIndexedInterceptorElementValue", # Needs an indexed interceptor.
- "DebugNamedInterceptorPropertyValue", # Needs a named interceptor.
- "DebugSetScriptSource", # Checks compilation state of script.
- "GetAllScopesDetails", # Needs to hit a break point.
- "GetFrameCount", # Needs to hit a break point.
- "GetFrameDetails", # Needs to hit a break point.
- "GetRootNaN", # Needs to be bootstrapping.
- "GetScopeCount", # Needs to hit a break point.
- "GetScopeDetails", # Needs to hit a break point.
- "GetStepInPositions", # Needs to hit a break point.
- "GetTemplateField", # Needs a {Function,Object}TemplateInfo.
- "GetThreadCount", # Needs to hit a break point.
- "GetThreadDetails", # Needs to hit a break point.
- "IsAccessAllowedForObserver", # Needs access-check-required object.
- "UnblockConcurrentRecompilation" # Needs --block-concurrent-recompilation.
-]
-
-
-# Definitions used in CUSTOM_KNOWN_GOOD_INPUT below.
-_BREAK_ITERATOR = (
- "%GetImplFromInitializedIntlObject(new Intl.v8BreakIterator())")
-_COLLATOR = "%GetImplFromInitializedIntlObject(new Intl.Collator('en-US'))"
-_DATETIME_FORMAT = (
- "%GetImplFromInitializedIntlObject(new Intl.DateTimeFormat('en-US'))")
-_NUMBER_FORMAT = (
- "%GetImplFromInitializedIntlObject(new Intl.NumberFormat('en-US'))")
-
-
-# Custom definitions for function input that does not throw.
-# Format: "FunctionName": ["arg0", "arg1", ..., argslength].
-# None means "fall back to autodetected value".
-CUSTOM_KNOWN_GOOD_INPUT = {
- "AddNamedProperty": [None, "\"bla\"", None, None, None],
- "AddPropertyForTemplate": [None, 10, None, None, None],
- "Apply": ["function() {}", None, None, None, None, None],
- "ArrayBufferSliceImpl": [None, None, 0, None],
- "ArrayConcat": ["[1, 'a']", None],
- "BreakIteratorAdoptText": [_BREAK_ITERATOR, None, None],
- "BreakIteratorBreakType": [_BREAK_ITERATOR, None],
- "BreakIteratorCurrent": [_BREAK_ITERATOR, None],
- "BreakIteratorFirst": [_BREAK_ITERATOR, None],
- "BreakIteratorNext": [_BREAK_ITERATOR, None],
- "CompileString": [None, "false", None],
- "CreateBreakIterator": ["'en-US'", "{type: 'string'}", None, None],
- "CreateJSFunctionProxy": [None, "function() {}", None, None, None],
- "CreatePrivateSymbol": ["\"foo\"", None],
- "CreatePrivateOwnSymbol": ["\"foo\"", None],
- "CreateSymbol": ["\"foo\"", None],
- "DateParseString": [None, "new Array(8)", None],
- "DefineAccessorPropertyUnchecked": [None, None, "function() {}",
- "function() {}", 2, None],
- "FunctionBindArguments": [None, None, "undefined", None, None],
- "GetBreakLocations": [None, 0, None],
- "GetDefaultReceiver": ["function() {}", None],
- "GetImplFromInitializedIntlObject": ["new Intl.NumberFormat('en-US')", None],
- "InternalCompare": [_COLLATOR, None, None, None],
- "InternalDateFormat": [_DATETIME_FORMAT, None, None],
- "InternalDateParse": [_DATETIME_FORMAT, None, None],
- "InternalNumberFormat": [_NUMBER_FORMAT, None, None],
- "InternalNumberParse": [_NUMBER_FORMAT, None, None],
- "IsSloppyModeFunction": ["function() {}", None],
- "LoadMutableDouble": ["{foo: 1.2}", None, None],
- "NewObjectFromBound": ["(function() {}).bind({})", None],
- "NumberToRadixString": [None, "2", None],
- "ParseJson": ["\"{}\"", 1],
- "RegExpExecMultiple": [None, None, "['a']", "['a']", None],
- "DefineApiAccessorProperty": [None, None, "undefined", "undefined", None, None],
- "SetIteratorInitialize": [None, None, "2", None],
- "SetDebugEventListener": ["undefined", None, None],
- "SetFunctionBreakPoint": [None, 218, None, None],
- "StringBuilderConcat": ["[1, 2, 3]", 3, None, None],
- "StringBuilderJoin": ["['a', 'b']", 4, None, None],
- "StringMatch": [None, None, "['a', 'b']", None],
- "StringNormalize": [None, 2, None],
- "StringReplaceGlobalRegExpWithString": [None, None, None, "['a']", None],
- "TypedArrayInitialize": [None, 6, "new ArrayBuffer(8)", None, 4, None],
- "TypedArrayInitializeFromArrayLike": [None, 6, None, None, None],
- "TypedArraySetFastCases": [None, None, "0", None],
- "FunctionIsArrow": ["() => null", None],
-}
-
-
-# Types of arguments that cannot be generated in a JavaScript testcase.
-NON_JS_TYPES = [
- "Code", "Context", "FixedArray", "FunctionTemplateInfo",
- "JSFunctionResultCache", "JSMessageObject", "Map", "ScopeInfo",
- "SharedFunctionInfo"]
-
-
-class Generator(object):
-
- def RandomVariable(self, varname, vartype, simple):
- if simple:
- return self._Variable(varname, self.GENERATORS[vartype][0])
- return self.GENERATORS[vartype][1](self, varname,
- self.DEFAULT_RECURSION_BUDGET)
-
- @staticmethod
- def IsTypeSupported(typename):
- return typename in Generator.GENERATORS
-
- USUAL_SUSPECT_PROPERTIES = ["size", "length", "byteLength", "__proto__",
- "prototype", "0", "1", "-1"]
- DEFAULT_RECURSION_BUDGET = 2
- PROXY_TRAPS = """{
- getOwnPropertyDescriptor: function(name) {
- return {value: function() {}, configurable: true, writable: true,
- enumerable: true};
- },
- getPropertyDescriptor: function(name) {
- return {value: function() {}, configurable: true, writable: true,
- enumerable: true};
- },
- getOwnPropertyNames: function() { return []; },
- getPropertyNames: function() { return []; },
- defineProperty: function(name, descriptor) {},
- delete: function(name) { return true; },
- fix: function() {}
- }"""
-
- def _Variable(self, name, value, fallback=None):
- args = { "name": name, "value": value, "fallback": fallback }
- if fallback:
- wrapper = "try { %%s } catch(e) { var %(name)s = %(fallback)s; }" % args
- else:
- wrapper = "%s"
- return [wrapper % ("var %(name)s = %(value)s;" % args)]
-
- def _Boolean(self, name, recursion_budget):
- return self._Variable(name, random.choice(["true", "false"]))
-
- def _Oddball(self, name, recursion_budget):
- return self._Variable(name,
- random.choice(["true", "false", "undefined", "null"]))
-
- def _StrictMode(self, name, recursion_budget):
- return self._Variable(name, random.choice([0, 1]))
-
- def _Int32(self, name, recursion_budget=0):
- die = random.random()
- if die < 0.5:
- value = random.choice([-3, -1, 0, 1, 2, 10, 515, 0x3fffffff, 0x7fffffff,
- 0x40000000, -0x40000000, -0x80000000])
- elif die < 0.75:
- value = random.randint(-1000, 1000)
- else:
- value = random.randint(-0x80000000, 0x7fffffff)
- return self._Variable(name, value)
-
- def _Uint32(self, name, recursion_budget=0):
- die = random.random()
- if die < 0.5:
- value = random.choice([0, 1, 2, 3, 4, 8, 0x3fffffff, 0x40000000,
- 0x7fffffff, 0xffffffff])
- elif die < 0.75:
- value = random.randint(0, 1000)
- else:
- value = random.randint(0, 0xffffffff)
- return self._Variable(name, value)
-
- def _Smi(self, name, recursion_budget):
- die = random.random()
- if die < 0.5:
- value = random.choice([-5, -1, 0, 1, 2, 3, 0x3fffffff, -0x40000000])
- elif die < 0.75:
- value = random.randint(-1000, 1000)
- else:
- value = random.randint(-0x40000000, 0x3fffffff)
- return self._Variable(name, value)
-
- def _Number(self, name, recursion_budget):
- die = random.random()
- if die < 0.5:
- return self._Smi(name, recursion_budget)
- elif die < 0.6:
- value = random.choice(["Infinity", "-Infinity", "NaN", "-0",
- "1.7976931348623157e+308", # Max value.
- "2.2250738585072014e-308", # Min value.
- "4.9406564584124654e-324"]) # Min subnormal.
- else:
- value = random.lognormvariate(0, 15)
- return self._Variable(name, value)
-
- def _RawRandomString(self, minlength=0, maxlength=100,
- alphabet=string.ascii_letters):
- length = random.randint(minlength, maxlength)
- result = ""
- for i in xrange(length):
- result += random.choice(alphabet)
- return result
-
- def _SeqString(self, name, recursion_budget):
- s1 = self._RawRandomString(1, 5)
- s2 = self._RawRandomString(1, 5)
- # 'foo' + 'bar'
- return self._Variable(name, "\"%s\" + \"%s\"" % (s1, s2))
-
- def _SeqTwoByteString(self, name):
- s1 = self._RawRandomString(1, 5)
- s2 = self._RawRandomString(1, 5)
- # 'foo' + unicode + 'bar'
- return self._Variable(name, "\"%s\" + \"\\2082\" + \"%s\"" % (s1, s2))
-
- def _SlicedString(self, name):
- s = self._RawRandomString(20, 30)
- # 'ffoo12345678901234567890'.substr(1)
- return self._Variable(name, "\"%s\".substr(1)" % s)
-
- def _ConsString(self, name):
- s1 = self._RawRandomString(8, 15)
- s2 = self._RawRandomString(8, 15)
- # 'foo12345' + (function() { return 'bar12345';})()
- return self._Variable(name,
- "\"%s\" + (function() { return \"%s\";})()" % (s1, s2))
-
- def _InternalizedString(self, name):
- return self._Variable(name, "\"%s\"" % self._RawRandomString(0, 20))
-
- def _String(self, name, recursion_budget):
- die = random.random()
- if die < 0.5:
- string = random.choice(self.USUAL_SUSPECT_PROPERTIES)
- return self._Variable(name, "\"%s\"" % string)
- elif die < 0.6:
- number_name = name + "_number"
- result = self._Number(number_name, recursion_budget)
- return result + self._Variable(name, "\"\" + %s" % number_name)
- elif die < 0.7:
- return self._SeqString(name, recursion_budget)
- elif die < 0.8:
- return self._ConsString(name)
- elif die < 0.9:
- return self._InternalizedString(name)
- else:
- return self._SlicedString(name)
-
- def _Symbol(self, name, recursion_budget):
- raw_string_name = name + "_1"
- result = self._String(raw_string_name, recursion_budget)
- return result + self._Variable(name, "Symbol(%s)" % raw_string_name)
-
- def _Name(self, name, recursion_budget):
- if random.random() < 0.2:
- return self._Symbol(name, recursion_budget)
- return self._String(name, recursion_budget)
-
- def _JSValue(self, name, recursion_budget):
- die = random.random()
- raw_name = name + "_1"
- if die < 0.33:
- result = self._String(raw_name, recursion_budget)
- return result + self._Variable(name, "new String(%s)" % raw_name)
- elif die < 0.66:
- result = self._Boolean(raw_name, recursion_budget)
- return result + self._Variable(name, "new Boolean(%s)" % raw_name)
- else:
- result = self._Number(raw_name, recursion_budget)
- return result + self._Variable(name, "new Number(%s)" % raw_name)
-
- def _RawRandomPropertyName(self):
- if random.random() < 0.5:
- return random.choice(self.USUAL_SUSPECT_PROPERTIES)
- return self._RawRandomString(0, 10)
-
- def _AddProperties(self, name, result, recursion_budget):
- propcount = random.randint(0, 3)
- propname = None
- for i in range(propcount):
- die = random.random()
- if die < 0.5:
- propname = "%s_prop%d" % (name, i)
- result += self._Name(propname, recursion_budget - 1)
- else:
- propname = "\"%s\"" % self._RawRandomPropertyName()
- propvalue_name = "%s_val%d" % (name, i)
- result += self._Object(propvalue_name, recursion_budget - 1)
- result.append("try { %s[%s] = %s; } catch (e) {}" %
- (name, propname, propvalue_name))
- if random.random() < 0.2 and propname:
- # Force the object to slow mode.
- result.append("delete %s[%s];" % (name, propname))
-
- def _RandomElementIndex(self, element_name, result):
- if random.random() < 0.5:
- return random.randint(-1000, 1000)
- result += self._Smi(element_name, 0)
- return element_name
-
- def _AddElements(self, name, result, recursion_budget):
- elementcount = random.randint(0, 3)
- for i in range(elementcount):
- element_name = "%s_idx%d" % (name, i)
- index = self._RandomElementIndex(element_name, result)
- value_name = "%s_elt%d" % (name, i)
- result += self._Object(value_name, recursion_budget - 1)
- result.append("try { %s[%s] = %s; } catch(e) {}" %
- (name, index, value_name))
-
- def _AddAccessors(self, name, result, recursion_budget):
- accessorcount = random.randint(0, 3)
- for i in range(accessorcount):
- propname = self._RawRandomPropertyName()
- what = random.choice(["get", "set"])
- function_name = "%s_access%d" % (name, i)
- result += self._PlainFunction(function_name, recursion_budget - 1)
- result.append("try { Object.defineProperty(%s, \"%s\", {%s: %s}); } "
- "catch (e) {}" % (name, propname, what, function_name))
-
- def _PlainArray(self, name, recursion_budget):
- die = random.random()
- if die < 0.5:
- literal = random.choice(["[]", "[1, 2]", "[1.5, 2.5]",
- "['a', 'b', 1, true]"])
- return self._Variable(name, literal)
- else:
- new = random.choice(["", "new "])
- length = random.randint(0, 101000)
- return self._Variable(name, "%sArray(%d)" % (new, length))
-
- def _PlainObject(self, name, recursion_budget):
- die = random.random()
- if die < 0.67:
- literal_propcount = random.randint(0, 3)
- properties = []
- result = []
- for i in range(literal_propcount):
- propname = self._RawRandomPropertyName()
- propvalue_name = "%s_lit%d" % (name, i)
- result += self._Object(propvalue_name, recursion_budget - 1)
- properties.append("\"%s\": %s" % (propname, propvalue_name))
- return result + self._Variable(name, "{%s}" % ", ".join(properties))
- else:
- return self._Variable(name, "new Object()")
-
- def _JSArray(self, name, recursion_budget):
- result = self._PlainArray(name, recursion_budget)
- self._AddAccessors(name, result, recursion_budget)
- self._AddProperties(name, result, recursion_budget)
- self._AddElements(name, result, recursion_budget)
- return result
-
- def _RawRandomBufferLength(self):
- if random.random() < 0.2:
- return random.choice([0, 1, 8, 0x40000000, 0x80000000])
- return random.randint(0, 1000)
-
- def _JSArrayBuffer(self, name, recursion_budget):
- length = self._RawRandomBufferLength()
- return self._Variable(name, "new ArrayBuffer(%d)" % length)
-
- def _JSDataView(self, name, recursion_budget):
- buffer_name = name + "_buffer"
- result = self._JSArrayBuffer(buffer_name, recursion_budget)
- args = [buffer_name]
- die = random.random()
- if die < 0.67:
- offset = self._RawRandomBufferLength()
- args.append("%d" % offset)
- if die < 0.33:
- length = self._RawRandomBufferLength()
- args.append("%d" % length)
- result += self._Variable(name, "new DataView(%s)" % ", ".join(args),
- fallback="new DataView(new ArrayBuffer(8))")
- return result
-
- def _JSDate(self, name, recursion_budget):
- die = random.random()
- if die < 0.25:
- return self._Variable(name, "new Date()")
- elif die < 0.5:
- ms_name = name + "_ms"
- result = self._Number(ms_name, recursion_budget)
- return result + self._Variable(name, "new Date(%s)" % ms_name)
- elif die < 0.75:
- str_name = name + "_str"
- month = random.choice(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
- "Aug", "Sep", "Oct", "Nov", "Dec"])
- day = random.randint(1, 28)
- year = random.randint(1900, 2100)
- hour = random.randint(0, 23)
- minute = random.randint(0, 59)
- second = random.randint(0, 59)
- str_value = ("\"%s %s, %s %s:%s:%s\"" %
- (month, day, year, hour, minute, second))
- result = self._Variable(str_name, str_value)
- return result + self._Variable(name, "new Date(%s)" % str_name)
- else:
- components = tuple(map(lambda x: "%s_%s" % (name, x),
- ["y", "m", "d", "h", "min", "s", "ms"]))
- return ([j for i in map(self._Int32, components) for j in i] +
- self._Variable(name, "new Date(%s)" % ", ".join(components)))
-
- def _PlainFunction(self, name, recursion_budget):
- result_name = "result"
- body = ["function() {"]
- body += self._Object(result_name, recursion_budget - 1)
- body.append("return result;\n}")
- return self._Variable(name, "%s" % "\n".join(body))
-
- def _JSFunction(self, name, recursion_budget):
- result = self._PlainFunction(name, recursion_budget)
- self._AddAccessors(name, result, recursion_budget)
- self._AddProperties(name, result, recursion_budget)
- self._AddElements(name, result, recursion_budget)
- return result
-
- def _JSFunctionProxy(self, name, recursion_budget):
- # TODO(jkummerow): Revisit this as the Proxy implementation evolves.
- return self._Variable(name, "Proxy.createFunction(%s, function() {})" %
- self.PROXY_TRAPS)
-
- def _JSGeneratorObject(self, name, recursion_budget):
- # TODO(jkummerow): Be more creative here?
- return self._Variable(name, "(function*() { yield 1; })()")
-
- def _JSMap(self, name, recursion_budget, weak=""):
- result = self._Variable(name, "new %sMap()" % weak)
- num_entries = random.randint(0, 3)
- for i in range(num_entries):
- key_name = "%s_k%d" % (name, i)
- value_name = "%s_v%d" % (name, i)
- if weak:
- result += self._JSObject(key_name, recursion_budget - 1)
- else:
- result += self._Object(key_name, recursion_budget - 1)
- result += self._Object(value_name, recursion_budget - 1)
- result.append("%s.set(%s, %s)" % (name, key_name, value_name))
- return result
-
- def _JSMapIterator(self, name, recursion_budget):
- map_name = name + "_map"
- result = self._JSMap(map_name, recursion_budget)
- iterator_type = random.choice(['keys', 'values', 'entries'])
- return (result + self._Variable(name, "%s.%s()" %
- (map_name, iterator_type)))
-
- def _JSProxy(self, name, recursion_budget):
- # TODO(jkummerow): Revisit this as the Proxy implementation evolves.
- return self._Variable(name, "Proxy.create(%s)" % self.PROXY_TRAPS)
-
- def _JSRegExp(self, name, recursion_budget):
- flags = random.choice(["", "g", "i", "m", "gi"])
- string = "a(b|c)*a" # TODO(jkummerow): Be more creative here?
- ctor = random.choice(["/%s/%s", "new RegExp(\"%s\", \"%s\")"])
- return self._Variable(name, ctor % (string, flags))
-
- def _JSSet(self, name, recursion_budget, weak=""):
- result = self._Variable(name, "new %sSet()" % weak)
- num_entries = random.randint(0, 3)
- for i in range(num_entries):
- element_name = "%s_e%d" % (name, i)
- if weak:
- result += self._JSObject(element_name, recursion_budget - 1)
- else:
- result += self._Object(element_name, recursion_budget - 1)
- result.append("%s.add(%s)" % (name, element_name))
- return result
-
- def _JSSetIterator(self, name, recursion_budget):
- set_name = name + "_set"
- result = self._JSSet(set_name, recursion_budget)
- iterator_type = random.choice(['values', 'entries'])
- return (result + self._Variable(name, "%s.%s()" %
- (set_name, iterator_type)))
-
- def _JSTypedArray(self, name, recursion_budget):
- arraytype = random.choice(["Int8", "Int16", "Int32", "Uint8", "Uint16",
- "Uint32", "Float32", "Float64", "Uint8Clamped"])
- ctor_type = random.randint(0, 3)
- if ctor_type == 0:
- length = random.randint(0, 1000)
- return self._Variable(name, "new %sArray(%d)" % (arraytype, length),
- fallback="new %sArray(8)" % arraytype)
- elif ctor_type == 1:
- input_name = name + "_typedarray"
- result = self._JSTypedArray(input_name, recursion_budget - 1)
- return (result +
- self._Variable(name, "new %sArray(%s)" % (arraytype, input_name),
- fallback="new %sArray(8)" % arraytype))
- elif ctor_type == 2:
- arraylike_name = name + "_arraylike"
- result = self._JSObject(arraylike_name, recursion_budget - 1)
- length = random.randint(0, 1000)
- result.append("try { %s.length = %d; } catch(e) {}" %
- (arraylike_name, length))
- return (result +
- self._Variable(name,
- "new %sArray(%s)" % (arraytype, arraylike_name),
- fallback="new %sArray(8)" % arraytype))
- else:
- die = random.random()
- buffer_name = name + "_buffer"
- args = [buffer_name]
- result = self._JSArrayBuffer(buffer_name, recursion_budget)
- if die < 0.67:
- offset_name = name + "_offset"
- args.append(offset_name)
- result += self._Int32(offset_name)
- if die < 0.33:
- length_name = name + "_length"
- args.append(length_name)
- result += self._Int32(length_name)
- return (result +
- self._Variable(name,
- "new %sArray(%s)" % (arraytype, ", ".join(args)),
- fallback="new %sArray(8)" % arraytype))
-
- def _JSArrayBufferView(self, name, recursion_budget):
- if random.random() < 0.4:
- return self._JSDataView(name, recursion_budget)
- else:
- return self._JSTypedArray(name, recursion_budget)
-
- def _JSWeakCollection(self, name, recursion_budget):
- ctor = random.choice([self._JSMap, self._JSSet])
- return ctor(name, recursion_budget, weak="Weak")
-
- def _PropertyDetails(self, name, recursion_budget):
- # TODO(jkummerow): Be more clever here?
- return self._Int32(name)
-
- def _JSObject(self, name, recursion_budget):
- die = random.random()
- if die < 0.4:
- function = random.choice([self._PlainObject, self._PlainArray,
- self._PlainFunction])
- elif die < 0.5:
- return self._Variable(name, "this") # Global object.
- else:
- function = random.choice([self._JSArrayBuffer, self._JSDataView,
- self._JSDate, self._JSFunctionProxy,
- self._JSGeneratorObject, self._JSMap,
- self._JSMapIterator, self._JSRegExp,
- self._JSSet, self._JSSetIterator,
- self._JSTypedArray, self._JSValue,
- self._JSWeakCollection])
- result = function(name, recursion_budget)
- self._AddAccessors(name, result, recursion_budget)
- self._AddProperties(name, result, recursion_budget)
- self._AddElements(name, result, recursion_budget)
- return result
-
- def _JSReceiver(self, name, recursion_budget):
- if random.random() < 0.9: return self._JSObject(name, recursion_budget)
- return self._JSProxy(name, recursion_budget)
-
- def _HeapObject(self, name, recursion_budget):
- die = random.random()
- if die < 0.9: return self._JSReceiver(name, recursion_budget)
- elif die < 0.95: return self._Oddball(name, recursion_budget)
- else: return self._Name(name, recursion_budget)
-
- def _Object(self, name, recursion_budget):
- if recursion_budget <= 0:
- function = random.choice([self._Oddball, self._Number, self._Name,
- self._JSValue, self._JSRegExp])
- return function(name, recursion_budget)
- if random.random() < 0.2:
- return self._Smi(name, recursion_budget)
- return self._HeapObject(name, recursion_budget)
-
- GENERATORS = {
- "Boolean": ["true", _Boolean],
- "HeapObject": ["new Object()", _HeapObject],
- "Int32": ["32", _Int32],
- "JSArray": ["new Array()", _JSArray],
- "JSArrayBuffer": ["new ArrayBuffer(8)", _JSArrayBuffer],
- "JSArrayBufferView": ["new Int32Array(2)", _JSArrayBufferView],
- "JSDataView": ["new DataView(new ArrayBuffer(24))", _JSDataView],
- "JSDate": ["new Date()", _JSDate],
- "JSFunction": ["function() {}", _JSFunction],
- "JSFunctionProxy": ["Proxy.createFunction({}, function() {})",
- _JSFunctionProxy],
- "JSGeneratorObject": ["(function*(){ yield 1; })()", _JSGeneratorObject],
- "JSMap": ["new Map()", _JSMap],
- "JSMapIterator": ["new Map().entries()", _JSMapIterator],
- "JSObject": ["new Object()", _JSObject],
- "JSProxy": ["Proxy.create({})", _JSProxy],
- "JSReceiver": ["new Object()", _JSReceiver],
- "JSRegExp": ["/ab/g", _JSRegExp],
- "JSSet": ["new Set()", _JSSet],
- "JSSetIterator": ["new Set().values()", _JSSetIterator],
- "JSTypedArray": ["new Int32Array(2)", _JSTypedArray],
- "JSValue": ["new String('foo')", _JSValue],
- "JSWeakCollection": ["new WeakMap()", _JSWeakCollection],
- "Name": ["\"name\"", _Name],
- "Number": ["1.5", _Number],
- "Object": ["new Object()", _Object],
- "PropertyDetails": ["513", _PropertyDetails],
- "SeqOneByteString": ["\"seq 1-byte\"", _SeqString],
- "SeqString": ["\"seqstring\"", _SeqString],
- "SeqTwoByteString": ["\"seq \\u2082-byte\"", _SeqTwoByteString],
- "Smi": ["1", _Smi],
- "StrictMode": ["1", _StrictMode],
- "String": ["\"foo\"", _String],
- "Symbol": ["Symbol(\"symbol\")", _Symbol],
- "Uint32": ["32", _Uint32],
- }
-
-
-class ArgParser(object):
- def __init__(self, regex, ctor):
- self.regex = regex
- self.ArgCtor = ctor
-
-
-class Arg(object):
- def __init__(self, typename, varname, index):
- self.type = typename
- self.name = "_%s" % varname
- self.index = index
class Function(object):
def __init__(self, match):
self.name = match.group(1)
- self.argslength = -1
- self.args = {}
- self.inline = ""
-
- handle_arg_parser = ArgParser(
- re.compile("^\s*CONVERT_ARG_HANDLE_CHECKED\((\w+), (\w+), (\d+)\)"),
- lambda match: Arg(match.group(1), match.group(2), int(match.group(3))))
-
- plain_arg_parser = ArgParser(
- re.compile("^\s*CONVERT_ARG_CHECKED\((\w+), (\w+), (\d+)\)"),
- lambda match: Arg(match.group(1), match.group(2), int(match.group(3))))
-
- number_handle_arg_parser = ArgParser(
- re.compile("^\s*CONVERT_NUMBER_ARG_HANDLE_CHECKED\((\w+), (\d+)\)"),
- lambda match: Arg("Number", match.group(1), int(match.group(2))))
-
- smi_arg_parser = ArgParser(
- re.compile("^\s*CONVERT_SMI_ARG_CHECKED\((\w+), (\d+)\)"),
- lambda match: Arg("Smi", match.group(1), int(match.group(2))))
-
- double_arg_parser = ArgParser(
- re.compile("^\s*CONVERT_DOUBLE_ARG_CHECKED\((\w+), (\d+)\)"),
- lambda match: Arg("Number", match.group(1), int(match.group(2))))
-
- number_arg_parser = ArgParser(
- re.compile(
- "^\s*CONVERT_NUMBER_CHECKED\(\w+, (\w+), (\w+), args\[(\d+)\]\)"),
- lambda match: Arg(match.group(2), match.group(1), int(match.group(3))))
-
- strict_mode_arg_parser = ArgParser(
- re.compile("^\s*CONVERT_STRICT_MODE_ARG_CHECKED\((\w+), (\d+)\)"),
- lambda match: Arg("StrictMode", match.group(1), int(match.group(2))))
-
- boolean_arg_parser = ArgParser(
- re.compile("^\s*CONVERT_BOOLEAN_ARG_CHECKED\((\w+), (\d+)\)"),
- lambda match: Arg("Boolean", match.group(1), int(match.group(2))))
-
- property_details_parser = ArgParser(
- re.compile("^\s*CONVERT_PROPERTY_DETAILS_CHECKED\((\w+), (\d+)\)"),
- lambda match: Arg("PropertyDetails", match.group(1), int(match.group(2))))
-
- arg_parsers = [handle_arg_parser, plain_arg_parser, number_handle_arg_parser,
- smi_arg_parser,
- double_arg_parser, number_arg_parser, strict_mode_arg_parser,
- boolean_arg_parser, property_details_parser]
-
- def SetArgsLength(self, match):
- self.argslength = int(match.group(1))
-
- def TryParseArg(self, line):
- for parser in Function.arg_parsers:
- match = parser.regex.match(line)
- if match:
- arg = parser.ArgCtor(match)
- self.args[arg.index] = arg
- return True
- return False
-
- def Filename(self):
- return "%s.js" % self.name.lower()
-
- def __str__(self):
- s = [self.name, "("]
- argcount = self.argslength
- if argcount < 0:
- print("WARNING: unknown argslength for function %s" % self.name)
- if self.args:
- argcount = max([self.args[i].index + 1 for i in self.args])
- else:
- argcount = 0
- for i in range(argcount):
- if i > 0: s.append(", ")
- s.append(self.args[i].type if i in self.args else "<unknown>")
- s.append(")")
- return "".join(s)
class Macro(object):
@@ -917,26 +70,6 @@ class Macro(object):
return result
-# Parses HEADERFILENAME to find out which runtime functions are "inline".
-def FindInlineRuntimeFunctions():
- inline_functions = []
- with open(HEADERFILENAME, "r") as f:
- inline_list = "#define INLINE_FUNCTION_LIST(F) \\\n"
- inline_function = re.compile(r"^\s*F\((\w+), \d+, \d+\)\s*\\?")
- mode = "SEARCHING"
- for line in f:
- if mode == "ACTIVE":
- match = inline_function.match(line)
- if match:
- inline_functions.append(match.group(1))
- if not line.endswith("\\\n"):
- mode = "SEARCHING"
- elif mode == "SEARCHING":
- if line == inline_list:
- mode = "ACTIVE"
- return inline_functions
-
-
def ReadFileAndExpandMacros(filename):
found_macros = {}
expanded_lines = []
@@ -976,7 +109,6 @@ def ReadFileAndExpandMacros(filename):
# Detects runtime functions by parsing FILENAME.
def FindRuntimeFunctions():
- inline_functions = FindInlineRuntimeFunctions()
functions = []
expanded_lines = ReadFileAndExpandMacros(FILENAME)
function = None
@@ -998,19 +130,9 @@ def FindRuntimeFunctions():
match = FUNCTION.match(line)
if match:
function = Function(match)
- if function.name in inline_functions:
- function.inline = "_"
continue
if function is None: continue
- match = ARGSLENGTH.match(line)
- if match:
- function.SetArgsLength(match)
- continue
-
- if function.TryParseArg(line):
- continue
-
if line == FUNCTIONEND:
if function is not None:
functions.append(function)
@@ -1018,34 +140,19 @@ def FindRuntimeFunctions():
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():
+def FindJSNatives():
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 = []
+ natives = []
regexp = re.compile("^function (\w+)\s*\((.*?)\) {")
matches = 0
for filename in fileslist:
@@ -1067,351 +174,28 @@ def FindJSBuiltins():
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.
- js_fuzzable_functions = []
- # We have enough information to fuzz these, but they need inputs that
- # cannot be created or passed around in JavaScript.
- cctest_fuzzable_functions = []
- # This script does not have enough information about these.
- unknown_functions = []
-
- types = {}
- for f in functions:
- if f.name in BLACKLISTED:
- continue
- decision = js_fuzzable_functions
- custom = CUSTOM_KNOWN_GOOD_INPUT.get(f.name, None)
- if f.argslength < 0:
- # Unknown length -> give up unless there's a custom definition.
- if custom and custom[-1] is not None:
- f.argslength = custom[-1]
- assert len(custom) == f.argslength + 1, \
- ("%s: last custom definition must be argslength" % f.name)
- else:
- decision = unknown_functions
- else:
- if custom:
- # Any custom definitions must match the known argslength.
- assert len(custom) == f.argslength + 1, \
- ("%s should have %d custom definitions but has %d" %
- (f.name, f.argslength + 1, len(custom)))
- for i in range(f.argslength):
- if custom and custom[i] is not None:
- # All good, there's a custom definition.
- pass
- elif not i in f.args:
- # No custom definition and no parse result -> give up.
- decision = unknown_functions
- else:
- t = f.args[i].type
- if t in NON_JS_TYPES:
- decision = cctest_fuzzable_functions
- else:
- assert Generator.IsTypeSupported(t), \
- ("type generator not found for %s, function: %s" % (t, f))
- decision.append(f)
- return (js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions)
-
-
-def _GetKnownGoodArgs(function, generator):
- custom_input = CUSTOM_KNOWN_GOOD_INPUT.get(function.name, None)
- definitions = []
- argslist = []
- for i in range(function.argslength):
- if custom_input and custom_input[i] is not None:
- name = "arg%d" % i
- definitions.append("var %s = %s;" % (name, custom_input[i]))
- else:
- arg = function.args[i]
- name = arg.name
- definitions += generator.RandomVariable(name, arg.type, simple=True)
- argslist.append(name)
- return (definitions, argslist)
-
-
-def _GenerateTestcase(function, definitions, argslist, throws):
- s = ["// Copyright 2014 the V8 project authors. All rights reserved.",
- "// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY",
- "// Flags: --allow-natives-syntax --harmony --harmony-proxies"
- ] + definitions
- call = "%%%s%s(%s);" % (function.inline, function.name, ", ".join(argslist))
- if throws:
- s.append("try {")
- s.append(call);
- s.append("} catch(e) {}")
- else:
- s.append(call)
- testcase = "\n".join(s)
- return testcase
-
-
-def GenerateJSTestcaseForFunction(function):
- gen = Generator()
- (definitions, argslist) = _GetKnownGoodArgs(function, gen)
- testcase = _GenerateTestcase(function, definitions, argslist,
- function.name in THROWS)
- path = os.path.join(BASEPATH, function.Filename())
- with open(path, "w") as f:
- f.write("%s\n" % testcase)
-
-
-def GenerateTestcases(functions):
- shutil.rmtree(BASEPATH) # Re-generate everything.
- os.makedirs(BASEPATH)
- for f in functions:
- GenerateJSTestcaseForFunction(f)
-
-
-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
- save_file_index = 0
- while os.path.exists(_SaveFileName(options.save_path, process_id,
- save_file_index)):
- save_file_index += 1
-
- targets = FUZZ_TARGET_LISTS[options.fuzz_target]()
- try:
- for i in range(options.num_tests):
- if stop_running.is_set(): break
- function = None
- while function is None or function.argslength == 0:
- function = random.choice(targets)
- args = []
- definitions = []
- gen = Generator()
- for i in range(function.argslength):
- arg = function.args[i]
- argname = "arg%d%s" % (i, arg.name)
- args.append(argname)
- definitions += gen.RandomVariable(argname, arg.type, simple=False)
- testcase = _GenerateTestcase(function, definitions, args, True)
- with open(test_file_name, "w") as f:
- f.write("%s\n" % testcase)
- with open("/dev/null", "w") as devnull:
- with open(stderr_file_name, "w") as stderr:
- process = subprocess.Popen(
- [options.binary, "--allow-natives-syntax", "--harmony",
- "--harmony-proxies", "--enable-slow-asserts", test_file_name],
- stdout=devnull, stderr=stderr)
- end_time = time.time() + options.timeout
- timed_out = False
- exit_code = None
- sleep_time = INITIAL_SLEEP_TIME
- while exit_code is None:
- if time.time() >= end_time:
- # Kill the process and wait for it to exit.
- os.kill(process.pid, signal.SIGTERM)
- exit_code = process.wait()
- timed_out = True
- else:
- exit_code = process.poll()
- time.sleep(sleep_time)
- sleep_time = sleep_time * SLEEP_TIME_FACTOR
- if sleep_time > MAX_SLEEP_TIME:
- sleep_time = MAX_SLEEP_TIME
- if exit_code != 0 and not timed_out:
- oom = False
- with open(stderr_file_name, "r") as stderr:
- for line in stderr:
- if line.strip() == "# Allocation failed - process out of memory":
- oom = True
- break
- if oom: continue
- save_name = _SaveFileName(options.save_path, process_id,
- save_file_index)
- shutil.copyfile(test_file_name, save_name)
- save_file_index += 1
- except KeyboardInterrupt:
- stop_running.set()
- finally:
- 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():
- usage = """Usage: %%prog [options] ACTION
-
-where ACTION can be:
-
-info Print diagnostic info.
-check Check that runtime functions can be parsed as expected, and that
- test cases exist.
-generate Parse source code for runtime functions, and auto-generate
- test cases for them. Warning: this will nuke and re-create
- %(path)s.
-fuzz Generate fuzz tests, run them, save those that crashed (see options).
-""" % {"path": os.path.relpath(BASEPATH)}
-
- 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)")
- o.add_option("--save-path", default="~/runtime_fuzz_output",
- help="Path to directory where failing tests will be stored"
- " (default: %default)")
- o.add_option("--timeout", default=20, type="int",
- help="Timeout for each fuzz test (in seconds, default:"
- "%default)")
- 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
+ natives.append(Builtin(match))
+ return natives
def Main():
- parser = BuildOptionParser()
- (options, args) = parser.parse_args()
-
- if not ProcessOptions(options, args):
- parser.print_help()
- return 1
- action = args[0]
-
functions = FindRuntimeFunctions()
- (js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions) = \
- ClassifyFunctions(functions)
- builtins = FindJSBuiltins()
-
- if action == "test":
- print("put your temporary debugging code here")
- return 0
-
- if action == "info":
- print("%d functions total; js_fuzzable_functions: %d, "
- "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)
- return 0
-
- if action == "check":
- errors = 0
-
- def CheckCount(actual, expected, description):
- if len(actual) != expected:
- print("Expected to detect %d %s, but found %d." % (
- expected, description, len(actual)))
- print("If this change is intentional, please update the expectations"
- " at the top of %s." % THIS_SCRIPT)
- return 1
- return 0
-
- errors += CheckCount(functions, EXPECTED_FUNCTION_COUNT,
- "functions in total")
- errors += CheckCount(js_fuzzable_functions, EXPECTED_FUZZABLE_COUNT,
- "JavaScript-fuzzable functions")
- errors += CheckCount(cctest_fuzzable_functions, EXPECTED_CCTEST_COUNT,
- "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
- for f in functions:
- if not os.path.isfile(os.path.join(BASEPATH, f.Filename())):
- print("Missing testcase for %s, please run '%s generate'" %
- (f.name, THIS_SCRIPT))
- errors += 1
- files = filter(lambda filename: not filename.startswith("."),
- os.listdir(BASEPATH))
- if (len(files) != len(functions)):
- unexpected_files = set(files) - set([f.Filename() for f in functions])
- for f in unexpected_files:
- print("Unexpected testcase: %s" % os.path.join(BASEPATH, f))
- errors += 1
- print("Run '%s generate' to automatically clean these up."
- % THIS_SCRIPT)
- return errors
-
- 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.")
- return 0
+ natives = FindJSNatives()
+ errors = 0
+ runtime_map = {}
+ for f in functions:
+ runtime_map[f.name] = 1
+ for b in natives:
+ if b.name in runtime_map:
+ print("JS_Native/Runtime_Function name clash: %s" % b.name)
+ errors += 1
- if action == "generate":
- GenerateTestcases(js_fuzzable_functions)
- return 0
+ if errors > 0:
+ return 1
+ print("Runtime/Natives name clashes: checked %d/%d functions, all good." %
+ (len(functions), len(natives)))
+ return 0
- if action == "fuzz":
- processes = []
- if not os.path.isdir(options.save_path):
- os.makedirs(options.save_path)
- stop_running = multiprocessing.Event()
- for i in range(multiprocessing.cpu_count()):
- args = (i, options, stop_running)
- p = multiprocessing.Process(target=RunFuzzer, args=args)
- p.start()
- processes.append(p)
- try:
- for i in range(len(processes)):
- processes[i].join()
- except KeyboardInterrupt:
- stop_running.set()
- for i in range(len(processes)):
- processes[i].join()
- return 0
if __name__ == "__main__":
sys.exit(Main())
« no previous file with comments | « tools/check-name-clashes.py ('k') | tools/presubmit.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698