blob: d529b2c6af417561a76d0b5d2beaa4d38a53477b [file] [log] [blame]
Paul Semel2c1673cc02024-01-31 15:30:491#!/usr/bin/env python3
2#
3# Copyright 2024 The Chromium Authors
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6"""List the fuzzers within a fuzztest and confirm they match what we expect.
7
8Invoked by GN from fuzzer_test.gni.
9"""
10
11import argparse
12import os
13import re
14import subprocess
15import sys
16
Brian Sheedyc0021a862024-08-06 20:53:5617# //build imports.
Paul Semel2c1673cc02024-01-31 15:30:4918sys.path.append(
19 os.path.join(
20 os.path.dirname(os.path.abspath(__file__)),
21 os.pardir,
22 os.pardir,
23 'build',
Ben Pasteneb5c67262024-05-15 21:24:0124 ))
Paul Semel2c1673cc02024-01-31 15:30:4925import action_helpers
26
27
28def CreateArgumentParser():
29 """Creates an argparse.ArgumentParser instance."""
30 parser = argparse.ArgumentParser(description='Generate fuzztest fuzzers.')
Ben Pasteneb5c67262024-05-15 21:24:0131 parser.add_argument('--executable',
32 help='Executable to interrogate for present fuzztests.')
Paul Semel2c1673cc02024-01-31 15:30:4933 parser.add_argument(
34 '--output',
35 help='Path to the output file (which will be intentionally blank).',
36 )
Ben Pasteneb5c67262024-05-15 21:24:0137 parser.add_argument('--fuzztests',
38 nargs='+',
39 help='List of fuzztests we expect to find.')
Paul Semel2c1673cc02024-01-31 15:30:4940 return parser
41
42
43def main():
44 parser = CreateArgumentParser()
45 args = parser.parse_args()
46
47 expected_tests = set(args.fuzztests)
48
49 env = os.environ
50 env['ASAN_OPTIONS'] = 'detect_odr_violation=0'
Ben Pasteneb5c67262024-05-15 21:24:0151 process_result = subprocess.run([args.executable, '--list_fuzz_tests=1'],
52 env=env,
53 stdout=subprocess.PIPE,
54 check=False)
Paul Semel2c1673cc02024-01-31 15:30:4955
Adrian Taylordc3507982024-01-31 18:02:3756 if process_result.returncode == 0:
57 test_list = process_result.stdout.decode('utf-8')
Paul Semel2c1673cc02024-01-31 15:30:4958
Adrian Taylor8e94ce52024-10-23 15:24:5559 actual_tests = re.findall('Fuzz test: (.*)', test_list)
60 # Gardeners may disable fuzztests by changing the names of the fuzztest
61 # in code to start with DISABLED_. We don't want gardeners to need to
62 # change gn files correspondingly, so strip such prefixes when checking
63 # that the test lists match.
64 actual_tests = {
65 test.replace('DISABLED_', '').replace('FLAKY_', '')
66 for test in actual_tests
67 }
Paul Semel2c1673cc02024-01-31 15:30:4968
Adrian Taylordc3507982024-01-31 18:02:3769 if expected_tests != actual_tests:
Ben Pasteneb5c67262024-05-15 21:24:0170 print('Unexpected fuzztests found in this binary.\nFuzztest binary: ' +
71 args.executable + '\n' +
72 'Expected fuzztests (as declared by the gn "fuzztests" variable on'
73 ' this target): ' + str(expected_tests) +
74 '\nActual tests (as found in the binary): ' + str(actual_tests) +
75 '\nYou probably need to update the gn variable to match the tests'
76 ' actually in the binary.')
Adrian Taylordc3507982024-01-31 18:02:3777 sys.exit(-1)
Paul Semel2c1673cc02024-01-31 15:30:4978
Adrian Taylordc3507982024-01-31 18:02:3779 # If we couldn't run the fuzztest binary itself, we'll
80 # regard that as fine. This is a best-efforts check that the
81 # gn 'fuzztests' variable is correct, and sometimes fuzzers don't
82 # run on LUCI e.g. due to lack of dependencies.
Paul Semel2c1673cc02024-01-31 15:30:4983
84 with action_helpers.atomic_output(args.output) as output:
85 output.write(''.encode('utf-8'))
86
87
88if __name__ == '__main__':
89 main()