1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import pathlib
import shutil
import subprocess
import tempfile
import unittest
import sys
class RunAllFuzzersTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
if sys.platform != 'linux':
return
gn_args = ('use_clang_coverage=true '
'dcheck_always_on=true '
'ffmpeg_branding=\"ChromeOS\" '
'is_component_build=true '
'is_debug=false '
'proprietary_codecs=true '
'use_reclient=true '
'use_libfuzzer=true')
cls.testfuzzer1 = 'xml_parser_fuzzer'
cls.testfuzzer2 = 'query_parser_fuzzer'
cls.chromium_src_dir = os.path.join(
os.path.abspath(os.path.dirname(__file__)), "..", "..")
fuzzer_binaries_dir = "out/run_all_fuzzers_test"
pathlib.Path(fuzzer_binaries_dir).mkdir(parents=True, exist_ok=True)
cls.fuzzer_binaries_dir = fuzzer_binaries_dir
cls.fuzzer_corpora_dir = tempfile.mkdtemp()
cls.profdata_outdir = tempfile.mkdtemp()
os.mkdir(os.path.join(cls.fuzzer_corpora_dir, cls.testfuzzer1))
corporadir1 = os.path.join(cls.fuzzer_corpora_dir, cls.testfuzzer1)
os.mkdir(os.path.join(cls.fuzzer_corpora_dir, cls.testfuzzer2))
corporadir2 = os.path.join(cls.fuzzer_corpora_dir, cls.testfuzzer2)
for letter in ["a", "b", "c", "d"]:
f1 = open(os.path.join(corporadir1, letter), "x")
f2 = open(os.path.join(corporadir2, letter), "x")
f1.write(letter)
f2.write(letter)
f1.close()
f2.close()
gn_gen_cmd = ['gn', 'gen', cls.fuzzer_binaries_dir, '--args=%s' % gn_args]
try:
subprocess.check_output(gn_gen_cmd, cwd=cls.chromium_src_dir)
except subprocess.CalledProcessError as e:
print("GN command failed. Error:")
print(e.output)
build_cmd = [
'autoninja', '-C', cls.fuzzer_binaries_dir, cls.testfuzzer1,
cls.testfuzzer2
]
with open("test.log", "wb") as f:
try:
process = subprocess.Popen(build_cmd,
cwd=cls.chromium_src_dir,
stdout=subprocess.PIPE)
for c in iter(lambda: process.stdout.read(1), b''):
f.write(c)
except subprocess.CalledProcessError as e:
print("Build command failed. Error:")
print(e.output)
@classmethod
def tearDownClass(cls):
if sys.platform != 'linux':
return
# ignore_errors allows us to delete the directory even though the directory
# is non-empty. This is what we want, since we created these temporarily,
# only for the purpose of tests.
shutil.rmtree(cls.fuzzer_binaries_dir, ignore_errors=True)
shutil.rmtree(cls.fuzzer_corpora_dir, ignore_errors=True)
shutil.rmtree(cls.profdata_outdir, ignore_errors=True)
def test_wrong_arguments(self):
if sys.platform != 'linux':
return
cmd = [
'python3', 'tools/code_coverage/run_all_fuzzers.py',
'--fuzzer-binaries-dir', self.__class__.fuzzer_binaries_dir,
'--fuzzer-corpora-dir', self.__class__.fuzzer_corpora_dir
]
with self.assertRaises(subprocess.CalledProcessError) as e:
subprocess.check_call(cmd, cwd=self.__class__.chromium_src_dir)
assert ("returned non-zero exit status 2" in str(e.exception))
cmd = [
'python3', 'tools/code_coverage/run_all_fuzzers.py',
'--fuzzer-binaries-dir', self.__class__.fuzzer_binaries_dir,
'--profdata-outdir', self.__class__.profdata_outdir
]
with self.assertRaises(subprocess.CalledProcessError) as e:
subprocess.check_call(cmd, cwd=self.__class__.chromium_src_dir)
assert ("returned non-zero exit status 2" in str(e.exception))
cmd = [
'python3', 'tools/code_coverage/run_all_fuzzers.py',
'--fuzzer-corpora-dir', self.__class__.fuzzer_corpora_dir,
'--profdata-outdir', self.__class__.profdata_outdir
]
with self.assertRaises(subprocess.CalledProcessError) as e:
subprocess.check_call(cmd, cwd=self.__class__.chromium_src_dir)
assert ("returned non-zero exit status 2" in str(e.exception))
def test_all_fuzzers_succeed(self):
if sys.platform != 'linux':
return
cmd = [
'python3', 'tools/code_coverage/run_all_fuzzers.py',
'--fuzzer-binaries-dir', self.__class__.fuzzer_binaries_dir,
'--fuzzer-corpora-dir', self.__class__.fuzzer_corpora_dir,
'--profdata-outdir', self.__class__.profdata_outdir
]
subprocess.check_call(cmd, cwd=self.__class__.chromium_src_dir)
expected_profdata = sorted([
self.__class__.testfuzzer1 + ".profraw",
self.__class__.testfuzzer2 + ".profraw"
])
actual_profdata = sorted(os.listdir(self.__class__.profdata_outdir))
assert (
expected_profdata == actual_profdata
), "Expected " + str(expected_profdata) + " but got " + str(actual_profdata)
if __name__ == '__main__':
unittest.main()
|