xref: /aosp_15_r20/external/harfbuzz_ng/test/fuzzing/run-shape-fuzzer-tests.py (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*2d1272b8SAndroid Build Coastguard Worker
3*2d1272b8SAndroid Build Coastguard Workerimport sys, os, subprocess, tempfile, shutil
4*2d1272b8SAndroid Build Coastguard Worker
5*2d1272b8SAndroid Build Coastguard Worker
6*2d1272b8SAndroid Build Coastguard Workerdef cmd (command):
7*2d1272b8SAndroid Build Coastguard Worker	# https://stackoverflow.com/a/4408409 as we might have huge output sometimes
8*2d1272b8SAndroid Build Coastguard Worker	with tempfile.TemporaryFile () as tempf:
9*2d1272b8SAndroid Build Coastguard Worker		p = subprocess.Popen (command, stderr=tempf)
10*2d1272b8SAndroid Build Coastguard Worker
11*2d1272b8SAndroid Build Coastguard Worker		try:
12*2d1272b8SAndroid Build Coastguard Worker			p.wait ()
13*2d1272b8SAndroid Build Coastguard Worker			tempf.seek (0)
14*2d1272b8SAndroid Build Coastguard Worker			text = tempf.read ()
15*2d1272b8SAndroid Build Coastguard Worker
16*2d1272b8SAndroid Build Coastguard Worker			#TODO: Detect debug mode with a better way
17*2d1272b8SAndroid Build Coastguard Worker			is_debug_mode = b"SANITIZE" in text
18*2d1272b8SAndroid Build Coastguard Worker
19*2d1272b8SAndroid Build Coastguard Worker			return ("" if is_debug_mode else text.decode ("utf-8").strip ()), p.returncode
20*2d1272b8SAndroid Build Coastguard Worker		except subprocess.TimeoutExpired:
21*2d1272b8SAndroid Build Coastguard Worker			return 'error: timeout, ' + ' '.join (command), 1
22*2d1272b8SAndroid Build Coastguard Worker
23*2d1272b8SAndroid Build Coastguard Worker
24*2d1272b8SAndroid Build Coastguard Workersrcdir = os.getenv ("srcdir", ".")
25*2d1272b8SAndroid Build Coastguard WorkerEXEEXT = os.getenv ("EXEEXT", "")
26*2d1272b8SAndroid Build Coastguard Workertop_builddir = os.getenv ("top_builddir", ".")
27*2d1272b8SAndroid Build Coastguard Workerhb_shape_fuzzer = os.path.join (top_builddir, "hb-shape-fuzzer" + EXEEXT)
28*2d1272b8SAndroid Build Coastguard Worker
29*2d1272b8SAndroid Build Coastguard Workerif not os.path.exists (hb_shape_fuzzer):
30*2d1272b8SAndroid Build Coastguard Worker	if len (sys.argv) == 1 or not os.path.exists (sys.argv[1]):
31*2d1272b8SAndroid Build Coastguard Worker		sys.exit ("""Failed to find hb-shape-fuzzer binary automatically,
32*2d1272b8SAndroid Build Coastguard Workerplease provide it as the first argument to the tool""")
33*2d1272b8SAndroid Build Coastguard Worker
34*2d1272b8SAndroid Build Coastguard Worker	hb_shape_fuzzer = sys.argv[1]
35*2d1272b8SAndroid Build Coastguard Worker
36*2d1272b8SAndroid Build Coastguard Workerprint ('hb_shape_fuzzer:', hb_shape_fuzzer)
37*2d1272b8SAndroid Build Coastguard Workerfails = 0
38*2d1272b8SAndroid Build Coastguard Worker
39*2d1272b8SAndroid Build Coastguard Workervalgrind = None
40*2d1272b8SAndroid Build Coastguard Workerif os.getenv ('RUN_VALGRIND', ''):
41*2d1272b8SAndroid Build Coastguard Worker	valgrind = shutil.which ('valgrind')
42*2d1272b8SAndroid Build Coastguard Worker	if valgrind is None:
43*2d1272b8SAndroid Build Coastguard Worker		sys.exit ("""Valgrind requested but not found.""")
44*2d1272b8SAndroid Build Coastguard Worker
45*2d1272b8SAndroid Build Coastguard Workerparent_path = os.path.join (srcdir, "fonts")
46*2d1272b8SAndroid Build Coastguard Workerfor file in os.listdir (parent_path):
47*2d1272b8SAndroid Build Coastguard Worker	path = os.path.join (parent_path, file)
48*2d1272b8SAndroid Build Coastguard Worker
49*2d1272b8SAndroid Build Coastguard Worker	if valgrind:
50*2d1272b8SAndroid Build Coastguard Worker		text, returncode = cmd ([valgrind, '--leak-check=full', '--error-exitcode=1', hb_shape_fuzzer, path])
51*2d1272b8SAndroid Build Coastguard Worker	else:
52*2d1272b8SAndroid Build Coastguard Worker		text, returncode = cmd ([hb_shape_fuzzer, path])
53*2d1272b8SAndroid Build Coastguard Worker		if 'error' in text:
54*2d1272b8SAndroid Build Coastguard Worker			returncode = 1
55*2d1272b8SAndroid Build Coastguard Worker
56*2d1272b8SAndroid Build Coastguard Worker	if (not valgrind or returncode) and text.strip ():
57*2d1272b8SAndroid Build Coastguard Worker		print (text)
58*2d1272b8SAndroid Build Coastguard Worker
59*2d1272b8SAndroid Build Coastguard Worker	if returncode != 0:
60*2d1272b8SAndroid Build Coastguard Worker		print ('failure on %s' % file)
61*2d1272b8SAndroid Build Coastguard Worker		fails = fails + 1
62*2d1272b8SAndroid Build Coastguard Worker
63*2d1272b8SAndroid Build Coastguard Worker
64*2d1272b8SAndroid Build Coastguard Workerif fails:
65*2d1272b8SAndroid Build Coastguard Worker	sys.exit ("%d shape fuzzer related tests failed." % fails)
66