Index: tools/foozzie/v8_foozzie.py |
diff --git a/tools/foozzie/v8_foozzie.py b/tools/foozzie/v8_foozzie.py |
index 8cfceb04203268b6030610a04fcea3e518521860..86194b9871ee6b477972a8a7bdf20156b60a474a 100755 |
--- a/tools/foozzie/v8_foozzie.py |
+++ b/tools/foozzie/v8_foozzie.py |
@@ -51,7 +51,7 @@ SUPPORTED_ARCHS = ['ia32', 'x64', 'arm', 'arm64'] |
FAILURE_HEADER_TEMPLATE = """# |
# V8 correctness failure |
# V8 correctness configs: %(configs)s |
-# V8 correctness sources: %(sources)s |
+# V8 correctness sources: %(source_key)s |
# V8 correctness suppression: %(suppression)s |
""" |
@@ -69,6 +69,9 @@ FAILURE_TEMPLATE = FAILURE_HEADER_TEMPLATE + """# |
# Difference: |
%(difference)s |
# |
+# Source file: |
+%(source)s |
+# |
### Start of configuration %(first_config_label)s: |
%(first_config_output)s |
### End of configuration %(first_config_label)s |
@@ -79,6 +82,7 @@ FAILURE_TEMPLATE = FAILURE_HEADER_TEMPLATE + """# |
""" |
FUZZ_TEST_RE = re.compile(r'.*fuzz(-\d+\.js)') |
+SOURCE_RE = re.compile(r'print\("v8-foozzie source: (.*)"\);') |
def parse_args(): |
parser = argparse.ArgumentParser() |
@@ -117,14 +121,6 @@ def parse_args(): |
os.path.isfile(options.testcase)), ( |
'Test case %s doesn\'t exist' % options.testcase) |
- # Deduce metadata file name from test case. This also removes |
- # the prefix the test case might get during minimization. |
- suffix = FUZZ_TEST_RE.match(os.path.basename(options.testcase)).group(1) |
- options.meta_data_path = os.path.join( |
- os.path.dirname(options.testcase), 'meta' + suffix) |
- assert os.path.exists(options.meta_data_path), ( |
- 'Metadata %s doesn\'t exist' % options.meta_data_path) |
- |
# Use first d8 as default for second d8. |
options.second_d8 = options.second_d8 or options.first_d8 |
@@ -147,27 +143,26 @@ def parse_args(): |
return options |
-def metadata_bailout(metadata, ignore_fun): |
- """Print failure state and return if ignore_fun matches metadata.""" |
- bug = (ignore_fun(metadata) or '').strip() |
+def get_meta_data(content): |
+ """Extracts original-source-file paths from test case content.""" |
+ sources = [] |
+ for line in content.splitlines(): |
+ match = SOURCE_RE.match(line) |
+ if match: |
+ sources.append(match.group(1)) |
+ return {'sources': sources} |
+ |
+ |
+def content_bailout(content, ignore_fun): |
+ """Print failure state and return if ignore_fun matches content.""" |
+ bug = (ignore_fun(content) or '').strip() |
if bug: |
print FAILURE_HEADER_TEMPLATE % dict( |
- configs='', sources='', suppression=bug) |
+ configs='', source_key='', suppression=bug) |
return True |
return False |
-def test_pattern_bailout(testcase, ignore_fun): |
- """Print failure state and return if ignore_fun matches testcase.""" |
- with open(testcase) as f: |
- bug = (ignore_fun(f.read()) or '').strip() |
- if bug: |
- print FAILURE_HEADER_TEMPLATE % dict( |
- configs='', sources='', suppression=bug) |
- return True |
- return False |
- |
- |
def pass_bailout(output, step_number): |
"""Print info and return if in timeout or crash pass states.""" |
if output.HasTimedOut(): |
@@ -186,7 +181,7 @@ def fail_bailout(output, ignore_by_output_fun): |
bug = (ignore_by_output_fun(output.stdout) or '').strip() |
if bug: |
print FAILURE_HEADER_TEMPLATE % dict( |
- configs='', sources='', suppression=bug) |
+ configs='', source_key='', suppression=bug) |
return True |
return False |
@@ -200,18 +195,15 @@ def main(): |
options.second_arch, options.second_config, |
) |
- # Get metadata. |
- # TODO(machenbach): We probably don't need the metadata file anymore |
- # now that the metadata is printed in the test cases. |
- with open(options.meta_data_path) as f: |
- metadata = json.load(f) |
- |
- if metadata_bailout(metadata, suppress.ignore_by_metadata): |
+ # Static bailout based on test case content or metadata. |
+ with open(options.testcase) as f: |
+ content = f.read() |
+ if content_bailout(get_meta_data(content), suppress.ignore_by_metadata): |
return RETURN_FAIL |
- |
- if test_pattern_bailout(options.testcase, suppress.ignore_by_content): |
+ if content_bailout(content, suppress.ignore_by_content): |
return RETURN_FAIL |
+ # Set up runtime arguments. |
common_flags = FLAGS + ['--random-seed', str(options.random_seed)] |
first_config_flags = common_flags + CONFIGS[options.first_config] |
second_config_flags = common_flags + CONFIGS[options.second_config] |
@@ -243,7 +235,7 @@ def main(): |
if fail_bailout(second_config_output, suppress.ignore_by_output2): |
return RETURN_FAIL |
- difference, source_key = suppress.diff( |
+ difference, source, source_key = suppress.diff( |
first_config_output.stdout, second_config_output.stdout) |
if difference: |
# The first three entries will be parsed by clusterfuzz. Format changes |
@@ -252,7 +244,7 @@ def main(): |
second_config_label = '%s,%s' % (options.second_arch, options.second_config) |
print FAILURE_TEMPLATE % dict( |
configs='%s:%s' % (first_config_label, second_config_label), |
- sources=source_key, |
+ source_key=source_key, |
suppression='', # We can't tie bugs to differences. |
first_config_label=first_config_label, |
second_config_label=second_config_label, |
@@ -260,6 +252,7 @@ def main(): |
second_config_flags=' '.join(second_config_flags), |
first_config_output=first_config_output.stdout, |
second_config_output=second_config_output.stdout, |
+ source=source, |
difference=difference, |
) |
return RETURN_FAIL |
@@ -279,11 +272,11 @@ if __name__ == "__main__": |
# Make sure clusterfuzz reports internal errors and wrong usage. |
# Use one label for all internal and usage errors. |
print FAILURE_HEADER_TEMPLATE % dict( |
- configs='', sources='', suppression='wrong_usage') |
+ configs='', source_key='', suppression='wrong_usage') |
result = RETURN_FAIL |
except Exception as e: |
print FAILURE_HEADER_TEMPLATE % dict( |
- configs='', sources='', suppression='internal_error') |
+ configs='', source_key='', suppression='internal_error') |
print '# Internal error: %s' % e |
traceback.print_exc(file=sys.stdout) |
result = RETURN_FAIL |