v8/tools/clusterfuzz/v8_foozzie_test.py
Michael Achenbach 47608ce626 [foozzie] Add sanity checks to avoid bug flooding
This lets foozzie call d8 with sanity output before doing the actual
correctness comparisons. This will make clusterfuzz dedupe cases on
the difference found in the sanity checks.

Also adding missing OWNERS file.

NOTRY=true

Bug: chromium:933076
Change-Id: I4229183726064cc0ad76da8fe432e1dbb601a7ba
Reviewed-on: https://chromium-review.googlesource.com/c/1491221
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Sergiy Belozorov <sergiyb@chromium.org>
Reviewed-by: Tamer Tas <tmrts@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59938}
2019-02-28 11:27:32 +00:00

157 lines
4.4 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright 2016 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import subprocess
import sys
import unittest
import v8_foozzie
import v8_fuzz_config
import v8_suppressions
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
FOOZZIE = os.path.join(BASE_DIR, 'v8_foozzie.py')
TEST_DATA = os.path.join(BASE_DIR, 'testdata')
class ConfigTest(unittest.TestCase):
def testExperiments(self):
"""Test that probabilities add up to 100 and that all config names exist.
"""
EXPERIMENTS = v8_fuzz_config.FOOZZIE_EXPERIMENTS
CONFIGS = v8_foozzie.CONFIGS
assert sum(x[0] for x in EXPERIMENTS) == 100
assert all(map(lambda x: x[1] in CONFIGS, EXPERIMENTS))
assert all(map(lambda x: x[2] in CONFIGS, EXPERIMENTS))
assert all(map(lambda x: x[3].endswith('d8'), EXPERIMENTS))
def testConfig(self):
"""Smoke test how to choose experiments.
When experiment distribution changes this test might change, too.
"""
class Rng(object):
def random(self):
return 0.5
self.assertEqual(
[
'--first-config=ignition',
'--second-config=ignition_turbo',
'--second-d8=d8',
],
v8_fuzz_config.Config('foo', Rng()).choose_foozzie_flags(),
)
class UnitTest(unittest.TestCase):
def testDiff(self):
# TODO(machenbach): Mock out suppression configuration.
suppress = v8_suppressions.get_suppression(
'x64', 'ignition', 'x64', 'ignition_turbo')
one = ''
two = ''
diff = None, None
self.assertEquals(diff, suppress.diff(one, two))
one = 'a \n b\nc();'
two = 'a \n b\nc();'
diff = None, None
self.assertEquals(diff, suppress.diff(one, two))
# Ignore line before caret, caret position and error message.
one = """
undefined
weird stuff
^
somefile.js: TypeError: undefined is not a function
undefined
"""
two = """
undefined
other weird stuff
^
somefile.js: TypeError: baz is not a function
undefined
"""
diff = None, None
self.assertEquals(diff, suppress.diff(one, two))
one = """
Still equal
Extra line
"""
two = """
Still equal
"""
diff = '- Extra line', None
self.assertEquals(diff, suppress.diff(one, two))
one = """
Still equal
"""
two = """
Still equal
Extra line
"""
diff = '+ Extra line', None
self.assertEquals(diff, suppress.diff(one, two))
one = """
undefined
somefile.js: TypeError: undefined is not a constructor
"""
two = """
undefined
otherfile.js: TypeError: undefined is not a constructor
"""
diff = """- somefile.js: TypeError: undefined is not a constructor
+ otherfile.js: TypeError: undefined is not a constructor""", None
self.assertEquals(diff, suppress.diff(one, two))
def cut_verbose_output(stdout):
# This removes first lines containing d8 commands.
return '\n'.join(stdout.split('\n')[4:])
def run_foozzie(first_d8, second_d8, *extra_flags):
return subprocess.check_output([
sys.executable, FOOZZIE,
'--random-seed', '12345',
'--first-d8', os.path.join(TEST_DATA, first_d8),
'--second-d8', os.path.join(TEST_DATA, second_d8),
'--first-config', 'ignition',
'--second-config', 'ignition_turbo',
os.path.join(TEST_DATA, 'fuzz-123.js'),
] + list(extra_flags))
class SystemTest(unittest.TestCase):
def testSyntaxErrorDiffPass(self):
stdout = run_foozzie('test_d8_1.py', 'test_d8_2.py', '--skip-sanity-checks')
self.assertEquals('# V8 correctness - pass\n', cut_verbose_output(stdout))
def testDifferentOutputFail(self):
with open(os.path.join(TEST_DATA, 'failure_output.txt')) as f:
expected_output = f.read()
with self.assertRaises(subprocess.CalledProcessError) as ctx:
run_foozzie('test_d8_1.py', 'test_d8_3.py', '--skip-sanity-checks')
e = ctx.exception
self.assertEquals(v8_foozzie.RETURN_FAIL, e.returncode)
self.assertEquals(expected_output, cut_verbose_output(e.output))
def testSanityCheck(self):
with open(os.path.join(TEST_DATA, 'sanity_check_output.txt')) as f:
expected_output = f.read()
with self.assertRaises(subprocess.CalledProcessError) as ctx:
run_foozzie('test_d8_1.py', 'test_d8_3.py')
e = ctx.exception
self.assertEquals(v8_foozzie.RETURN_FAIL, e.returncode)
self.assertEquals(expected_output, e.output)
if __name__ == '__main__':
unittest.main()