xref: /aosp_15_r20/external/cronet/testing/libfuzzer/confirm_fuzztests.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6777b538SAndroid Build Coastguard Worker#
3*6777b538SAndroid Build Coastguard Worker# Copyright 2024 The Chromium Authors
4*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
5*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
6*6777b538SAndroid Build Coastguard Worker"""List the fuzzers within a fuzztest and confirm they match what we expect.
7*6777b538SAndroid Build Coastguard Worker
8*6777b538SAndroid Build Coastguard WorkerInvoked by GN from fuzzer_test.gni.
9*6777b538SAndroid Build Coastguard Worker"""
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Workerimport argparse
12*6777b538SAndroid Build Coastguard Workerimport os
13*6777b538SAndroid Build Coastguard Workerimport re
14*6777b538SAndroid Build Coastguard Workerimport subprocess
15*6777b538SAndroid Build Coastguard Workerimport sys
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker# Set up path to be able to import action_helpers
18*6777b538SAndroid Build Coastguard Workersys.path.append(
19*6777b538SAndroid Build Coastguard Worker    os.path.join(
20*6777b538SAndroid Build Coastguard Worker        os.path.dirname(os.path.abspath(__file__)),
21*6777b538SAndroid Build Coastguard Worker        os.pardir,
22*6777b538SAndroid Build Coastguard Worker        os.pardir,
23*6777b538SAndroid Build Coastguard Worker        'build',
24*6777b538SAndroid Build Coastguard Worker    )
25*6777b538SAndroid Build Coastguard Worker)
26*6777b538SAndroid Build Coastguard Workerimport action_helpers
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Workerdef CreateArgumentParser():
30*6777b538SAndroid Build Coastguard Worker  """Creates an argparse.ArgumentParser instance."""
31*6777b538SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(description='Generate fuzztest fuzzers.')
32*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
33*6777b538SAndroid Build Coastguard Worker      '--executable', help='Executable to interrogate for present fuzztests.'
34*6777b538SAndroid Build Coastguard Worker  )
35*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
36*6777b538SAndroid Build Coastguard Worker      '--output',
37*6777b538SAndroid Build Coastguard Worker      help='Path to the output file (which will be intentionally blank).',
38*6777b538SAndroid Build Coastguard Worker  )
39*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
40*6777b538SAndroid Build Coastguard Worker      '--fuzztests', nargs='+', help='List of fuzztests we expect to find.'
41*6777b538SAndroid Build Coastguard Worker  )
42*6777b538SAndroid Build Coastguard Worker  return parser
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker
45*6777b538SAndroid Build Coastguard Workerdef main():
46*6777b538SAndroid Build Coastguard Worker  parser = CreateArgumentParser()
47*6777b538SAndroid Build Coastguard Worker  args = parser.parse_args()
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker  expected_tests = set(args.fuzztests)
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker  env = os.environ
52*6777b538SAndroid Build Coastguard Worker  env['ASAN_OPTIONS'] = 'detect_odr_violation=0'
53*6777b538SAndroid Build Coastguard Worker  process_result = subprocess.run(
54*6777b538SAndroid Build Coastguard Worker      [args.executable, '--list_fuzz_tests'],
55*6777b538SAndroid Build Coastguard Worker      env=env, stdout=subprocess.PIPE, check=False
56*6777b538SAndroid Build Coastguard Worker  )
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker  if process_result.returncode == 0:
59*6777b538SAndroid Build Coastguard Worker    test_list = process_result.stdout.decode('utf-8')
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker    actual_tests = set(re.findall('Fuzz test: (.*)', test_list))
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker    if expected_tests != actual_tests:
64*6777b538SAndroid Build Coastguard Worker      print(
65*6777b538SAndroid Build Coastguard Worker          'Unexpected fuzztests found in this binary.\nFuzztest binary: '
66*6777b538SAndroid Build Coastguard Worker          + args.executable
67*6777b538SAndroid Build Coastguard Worker          + '\n'
68*6777b538SAndroid Build Coastguard Worker          + 'Expected fuzztests (as declared by the gn "fuzztests" variable on'
69*6777b538SAndroid Build Coastguard Worker          ' this target): '
70*6777b538SAndroid Build Coastguard Worker          + str(expected_tests)
71*6777b538SAndroid Build Coastguard Worker          + '\nActual tests (as found in the binary): '
72*6777b538SAndroid Build Coastguard Worker          + str(actual_tests)
73*6777b538SAndroid Build Coastguard Worker          + '\nYou probably need to update the gn variable to match the tests'
74*6777b538SAndroid Build Coastguard Worker          ' actually in the binary.'
75*6777b538SAndroid Build Coastguard Worker      )
76*6777b538SAndroid Build Coastguard Worker      sys.exit(-1)
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker  # If we couldn't run the fuzztest binary itself, we'll
79*6777b538SAndroid Build Coastguard Worker  # regard that as fine. This is a best-efforts check that the
80*6777b538SAndroid Build Coastguard Worker  # gn 'fuzztests' variable is correct, and sometimes fuzzers don't
81*6777b538SAndroid Build Coastguard Worker  # run on LUCI e.g. due to lack of dependencies.
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker  with action_helpers.atomic_output(args.output) as output:
84*6777b538SAndroid Build Coastguard Worker    output.write(''.encode('utf-8'))
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__':
88*6777b538SAndroid Build Coastguard Worker  main()
89