1#!/usr/bin/env python 2 3from __future__ import print_function, division, absolute_import 4 5import sys, os, subprocess, tempfile, threading 6 7 8def which(program): 9 # https://stackoverflow.com/a/377028 10 def is_exe(fpath): 11 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 12 13 fpath, _ = os.path.split(program) 14 if fpath: 15 if is_exe(program): 16 return program 17 else: 18 for path in os.environ["PATH"].split(os.pathsep): 19 exe_file = os.path.join(path, program) 20 if is_exe(exe_file): 21 return exe_file 22 23 return None 24 25 26def cmd(command): 27 # https://stackoverflow.com/a/4408409 28 # https://stackoverflow.com/a/10012262 29 with tempfile.TemporaryFile() as tempf: 30 p = subprocess.Popen (command, stderr=tempf) 31 is_killed = {'value': False} 32 33 def timeout(p, is_killed): 34 is_killed['value'] = True 35 p.kill() 36 timer = threading.Timer (2, timeout, [p, is_killed]) 37 38 try: 39 timer.start() 40 p.wait () 41 tempf.seek (0) 42 text = tempf.read().decode ("utf-8").strip () 43 returncode = p.returncode 44 finally: 45 timer.cancel() 46 47 if is_killed['value']: 48 text = 'error: timeout, ' + text 49 returncode = 1 50 51 return text, returncode 52 53 54srcdir = os.environ.get ("srcdir", ".") 55EXEEXT = os.environ.get ("EXEEXT", "") 56top_builddir = os.environ.get ("top_builddir", ".") 57hb_subset_fuzzer = os.path.join (top_builddir, "hb-subset-fuzzer" + EXEEXT) 58 59if not os.path.exists (hb_subset_fuzzer): 60 if len (sys.argv) < 2 or not os.path.exists (sys.argv[1]): 61 print ("""Failed to find hb-subset-fuzzer binary automatically, 62please provide it as the first argument to the tool""") 63 sys.exit (1) 64 65 hb_subset_fuzzer = sys.argv[1] 66 67print ('hb_subset_fuzzer:', hb_subset_fuzzer) 68fails = 0 69 70libtool = os.environ.get('LIBTOOL') 71valgrind = None 72if os.environ.get('RUN_VALGRIND', ''): 73 valgrind = which ('valgrind') 74 if valgrind is None: 75 print ("""Valgrind requested but not found.""") 76 sys.exit (1) 77 if libtool is None: 78 print ("""Valgrind support is currently autotools only and needs libtool but not found.""") 79 80 81def run_dir (parent_path): 82 global fails 83 for file in os.listdir (parent_path): 84 path = os.path.join(parent_path, file) 85 86 print ("running subset fuzzer against %s" % path) 87 if valgrind: 88 text, returncode = cmd (libtool.split(' ') + ['--mode=execute', valgrind + ' --leak-check=full --show-leak-kinds=all --error-exitcode=1', '--', hb_subset_fuzzer, path]) 89 else: 90 text, returncode = cmd ([hb_subset_fuzzer, path]) 91 if 'error' in text: 92 returncode = 1 93 94 if not valgrind and text.strip (): 95 print (text) 96 97 if returncode != 0: 98 print ("failed for %s" % path) 99 fails = fails + 1 100 101 102run_dir (os.path.join (srcdir, "..", "subset", "data", "fonts")) 103# TODO running these tests very slow tests. Fix and re-enable 104#run_dir (os.path.join (srcdir, "fonts")) 105 106if fails: 107 print ("%i subset fuzzer related tests failed." % fails) 108 sys.exit (1) 109