From 868ecf7b2660747f7628df2b3a17a8d68b0325eb Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 28 Feb 2020 19:50:30 +0330 Subject: [PATCH] [draw] Add fuzzer runner --- test/fuzzing/Makefile.am | 3 + test/fuzzing/run-draw-fuzzer-tests.py | 107 ++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100755 test/fuzzing/run-draw-fuzzer-tests.py diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am index 4f0a0f68a..00d9c2288 100644 --- a/test/fuzzing/Makefile.am +++ b/test/fuzzing/Makefile.am @@ -19,6 +19,7 @@ EXTRA_DIST += \ README \ run-shape-fuzzer-tests.py \ run-subset-fuzzer-tests.py \ + run-draw-fuzzer-tests.py \ CMakeLists.txt \ fonts \ $(NULL) @@ -27,6 +28,7 @@ check_PROGRAMS = \ hb-shape-fuzzer \ hb-subset-fuzzer \ hb-set-fuzzer \ + hb-draw-fuzzer \ $(NULL) AM_CPPFLAGS = \ @@ -77,6 +79,7 @@ hb_draw_fuzzer_DEPENDENCIES = $(top_builddir)/src/libharfbuzz.la check: EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" LIBTOOL="$(LIBTOOL)" $(srcdir)/run-shape-fuzzer-tests.py EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" LIBTOOL="$(LIBTOOL)" $(srcdir)/run-subset-fuzzer-tests.py + EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" LIBTOOL="$(LIBTOOL)" $(srcdir)/run-draw-fuzzer-tests.py check-valgrind: $(AM_V_at)RUN_VALGRIND=1 $(MAKE) $(AM_MAKEFLGS) check diff --git a/test/fuzzing/run-draw-fuzzer-tests.py b/test/fuzzing/run-draw-fuzzer-tests.py new file mode 100755 index 000000000..4085649a4 --- /dev/null +++ b/test/fuzzing/run-draw-fuzzer-tests.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 + +import sys, os, subprocess, tempfile, threading + + +def which (program): + # https://stackoverflow.com/a/377028 + def is_exe (fpath): + return os.path.isfile (fpath) and os.access (fpath, os.X_OK) + + fpath, _ = os.path.split (program) + if fpath: + if is_exe (program): + return program + else: + for path in os.environ["PATH"].split (os.pathsep): + exe_file = os.path.join (path, program) + if is_exe (exe_file): + return exe_file + + return None + + +def cmd (command): + # https://stackoverflow.com/a/4408409 + # https://stackoverflow.com/a/10012262 + with tempfile.TemporaryFile () as tempf: + p = subprocess.Popen (command, stderr=tempf) + is_killed = {'value': False} + + def timeout (p, is_killed): + is_killed['value'] = True + p.kill () + timeout_seconds = int (os.environ.get ("HB_TEST_SHAPE_FUZZER_TIMEOUT", "2")) + timer = threading.Timer (timeout_seconds, timeout, [p, is_killed]) + + try: + timer.start() + p.wait () + tempf.seek (0) + text = tempf.read () + + #TODO: Detect debug mode with a better way + is_debug_mode = b"SANITIZE" in text + + text = "" if is_debug_mode else text.decode ("utf-8").strip () + returncode = p.returncode + finally: + timer.cancel() + + if is_killed['value']: + text = 'error: timeout, ' + text + returncode = 1 + + return text, returncode + + +srcdir = os.environ.get ("srcdir", ".") +EXEEXT = os.environ.get ("EXEEXT", "") +top_builddir = os.environ.get ("top_builddir", ".") +hb_draw_fuzzer = os.path.join (top_builddir, "hb-draw-fuzzer" + EXEEXT) + +if not os.path.exists (hb_draw_fuzzer): + if len (sys.argv) == 1 or not os.path.exists (sys.argv[1]): + print ("""Failed to find hb-draw-fuzzer binary automatically, +please provide it as the first argument to the tool""") + sys.exit (1) + + hb_draw_fuzzer = sys.argv[1] + +print ('hb_draw_fuzzer:', hb_draw_fuzzer) +fails = 0 + +libtool = os.environ.get ('LIBTOOL') +valgrind = None +if os.environ.get ('RUN_VALGRIND', ''): + valgrind = which ('valgrind') + if valgrind is None: + print ("""Valgrind requested but not found.""") + sys.exit (1) + if libtool is None: + print ("""Valgrind support is currently autotools only and needs libtool but not found.""") + + +parent_path = os.path.join (srcdir, "fonts") +for file in os.listdir (parent_path): + if "draw" not in file: continue + path = os.path.join (parent_path, file) + + if valgrind: + text, returncode = cmd (libtool.split(' ') + ['--mode=execute', valgrind + ' --leak-check=full --error-exitcode=1', '--', hb_draw_fuzzer, path]) + else: + text, returncode = cmd ([hb_draw_fuzzer, path]) + if 'error' in text: + returncode = 1 + + if (not valgrind or returncode) and text.strip (): + print (text) + + if returncode != 0: + print ('failure on %s' % file) + fails = fails + 1 + + +if fails: + print ("%i draw fuzzer related tests failed." % fails) + sys.exit (1)