1 #!/usr/bin/env python 2 3 from __future__ import print_function, division, absolute_import 4 5 import sys, os, subprocess, tempfile, threading 6 7 8 def 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 26 def 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 54 srcdir = os.environ.get ("srcdir", ".") 55 EXEEXT = os.environ.get ("EXEEXT", "") 56 top_builddir = os.environ.get ("top_builddir", ".") 57 hb_shape_fuzzer = os.path.join (top_builddir, "hb-shape-fuzzer" + EXEEXT) 58 59 if not os.path.exists (hb_shape_fuzzer): 60 if len (sys.argv) == 1 or not os.path.exists (sys.argv[1]): 61 print ("""Failed to find hb-shape-fuzzer binary automatically, 62 please provide it as the first argument to the tool""") 63 sys.exit (1) 64 65 hb_shape_fuzzer = sys.argv[1] 66 67 print ('hb_shape_fuzzer:', hb_shape_fuzzer) 68 fails = 0 69 70 valgrind = None 71 if os.environ.get('RUN_VALGRIND', ''): 72 valgrind = which ('valgrind') 73 74 parent_path = os.path.join (srcdir, "fonts") 75 for file in os.listdir (parent_path): 76 path = os.path.join(parent_path, file) 77 78 text, returncode = cmd ([hb_shape_fuzzer, path]) 79 if text.strip (): 80 print (text) 81 82 failed = False 83 if returncode != 0 or 'error' in text: 84 print ('failure on %s' % file) 85 failed = True 86 87 if valgrind: 88 text, returncode = cmd ([valgrind, '--error-exitcode=1', hb_shape_fuzzer, path]) 89 if returncode: 90 print (text) 91 print ('failure on %s' % file) 92 failed = True 93 94 if failed: 95 fails = fails + 1 96 97 if fails: 98 print ("%i shape fuzzer related tests failed." % fails) 99 sys.exit (1) 100